commit 06de15ce6da45af3924129e1c3a14c2d43f6f210 Author: Minty Cube <90507714+mintycube@users.noreply.github.com> Date: Tue Apr 23 07:34:15 2024 +0500 Initial commit diff --git a/.bashrc b/.bashrc new file mode 100755 index 0000000..a6567ac --- /dev/null +++ b/.bashrc @@ -0,0 +1,36 @@ +# ~/.bashrc +bind "set completion-ignore-case on" # Perform file completion in a case insensitive fashion +bind "set completion-map-case on" # Treat hyphens and underscores as equivalent +bind "set show-all-if-ambiguous on" # Display matches for ambiguous patterns at first tab press +bind "set mark-symlinked-directories on" # Immediately add a trailing slash when autocompleting symlinks to directories + +HISTSIZE=500000 +HISTFILESIZE=100000 +shopt -s histappend # Append to the history file, don't overwrite it +shopt -s cmdhist # Save multi-line commands as one command +PROMPT_COMMAND='history -a' # Record each line as it gets issued +HISTCONTROL="erasedups:ignoreboth" # Avoid duplicate entries +export HISTIGNORE="&:[ ]*:exit:ls:lf:bg:fg:history:clear" # Don't record some commands +HISTTIMEFORMAT='%F %T ' # Use standard ISO 8601 timestamp + +export MANPAGER="nvim +Man!" + +bind Space:magic-space # Typing !! will replace the !! with your last command +bind '"\e[A": history-search-backward' # Enable incremental history search with up/down arrows (also Readline goodness) +bind '"\e[B": history-search-forward' +bind '"\e[C": forward-char' +bind '"\e[D": backward-char' + +shopt -s autocd 2>/dev/null # Prepend cd to directory names automatically +shopt -s dirspell 2>/dev/null # Correct spelling errors during tab-completion +shopt -s cdspell 2>/dev/null # Correct spelling errors in arguments supplied to cd +shopt -s expand_aliases # expand aliases +shopt -s checkwinsize # checks term size when bash regains control + +[ -f "$HOME/.config/shell/shortcutrc" ] && source "$HOME/.config/shell/shortcutrc" # shortcuts +[ -f "$HOME/.config/shell/aliasrc" ] && source "$HOME/.config/shell/aliasrc" # aliases + +PS1='\[\e[34;3m\]\w \[\e[0;32m\] \[\e[0m\]' # prompt with dir in italic + +source "$HOME/.local/src/fzf-tab-completion/bash/fzf-bash-completion.sh" # https://github.com/lincheney/fzf-tab-completion.git +bind -x '"\t": fzf_bash_completion' diff --git a/.config/bat/config b/.config/bat/config new file mode 100644 index 0000000..ecb14b1 --- /dev/null +++ b/.config/bat/config @@ -0,0 +1,27 @@ +# This is `bat`s configuration file. Each line either contains a comment or +# a command-line option that you want to pass to `bat` by default. You can +# run `bat --help` to get a list of all possible configuration options. + +# Specify desired highlighting theme (e.g. "TwoDark"). Run `bat --list-themes` +# for a list of all available themes +--theme="base16" + +--tabs=2 + +# Enable this to use italic text on the terminal. This is not supported on all +# terminal emulators (like tmux, by default): +#--italic-text=always + +# Uncomment the following line to disable automatic paging: +#--paging=never + +# Uncomment the following line if you are using less version >= 551 and want to +# enable mouse scrolling support in `bat` when running inside tmux. This might +# disable text selection, unless you press shift. +#--pager="less --RAW-CONTROL-CHARS --quit-if-one-screen --mouse" + +# Syntax mappings: map a certain filename pattern to a language. +# Example 1: use the C++ syntax for Arduino .ino files +# Example 2: Use ".gitignore"-style highlighting for ".ignore" files +#--map-syntax "*.ino:C++" +#--map-syntax ".ignore:Git Ignore" diff --git a/.config/ctpv/config b/.config/ctpv/config new file mode 100644 index 0000000..d8971bc --- /dev/null +++ b/.config/ctpv/config @@ -0,0 +1,22 @@ +set forcekittyanim + +preview audio audio/* {{ + /usr/bin/vendor_perl/exiftool -- "$f" +}} + +preview lua application/javascript {{ + if exists bat; then + batcmd=bat + elif exists batcat; then + batcmd=batcat + else + exit 127 + fi + "$batcmd" \ + --color always \ + --style plain \ + --paging never \ + --terminal-width "$w" \ + --wrap character \ + -- "$f" +}} diff --git a/.config/dunst/dunstrc b/.config/dunst/dunstrc new file mode 100644 index 0000000..3f74fa9 --- /dev/null +++ b/.config/dunst/dunstrc @@ -0,0 +1,69 @@ +[global] +monitor = 0 +follow = mouse +width = 200 +height = 500 +origin = top-right +offset = 15x15 +corner_radius = 10 +scale = 0 +notification_limit = 0 +progress_bar = true +progress_bar_height = 80 +progress_bar_frame_width = 1 +progress_bar_min_width = 300 +progress_bar_max_width = 300 +indicate_hidden = yes +transparency = 0 +separator_height = 1 +padding = 10 +horizontal_padding = 10 +text_icon_padding = 0 +frame_width = 2 +gap_size = 0 +separator_color = frame +sort = yes +idle_threshold = 120 +font = JetBrainsMono Nerd Font Semibold 9 +line_height = 1 +markup = full +format = %s\n%b +alignment = left +vertical_alignment = center +show_age_threshold = 60 +ellipsize = middle +ignore_newline = no +stack_duplicates = true +hide_duplicate_count = false +show_indicators = yes +enable_recursive_icon_lookup = true +icon_position = left +min_icon_size = 24 +max_icon_size = 48 +sticky_history = yes +history_length = 20 +browser = /usr/bin/xdg-open +always_run_script = true +mouse_left_click = close_current +mouse_middle_click = do_action, close_current +mouse_right_click = close_all +title = Dunst +class = Dunst + +[urgency_low] +timeout = 2 +background = "#1a1b26" +foreground = "#a0caf5" +frame_color = "#7aa2f7" + +[urgency_normal] +timeout = 5 +background = "#1a1b26" +foreground = "#a0caf5" +frame_color = "#7aa2f7" + +[urgency_critical] +timeout = 0 +background = "#1a1b26" +foreground = "#a0caf5" +frame_color = "#f7768e" diff --git a/.config/fontconfig/fonts.conf b/.config/fontconfig/fonts.conf new file mode 100644 index 0000000..d6da074 --- /dev/null +++ b/.config/fontconfig/fonts.conf @@ -0,0 +1,40 @@ + + + + + serif + + Apple Garamond + Joy Pixels + Noto Color Emoji + Symbols Nerd Font + + + + sans-serif + + Lucida Grande + Joy Pixels + Noto Color Emoji + Symbols Nerd Font + + + + sans + + Lucida Grande + Joy Pixels + Noto Color Emoji + Symbols Nerd Font + + + + monospace + + JetBrainsMono Nerd Font + Liberation Mono + Symbols Nerd Font + Braille + + + diff --git a/.config/gtk-2.0/gtkfilechooser.ini b/.config/gtk-2.0/gtkfilechooser.ini new file mode 100644 index 0000000..695931a --- /dev/null +++ b/.config/gtk-2.0/gtkfilechooser.ini @@ -0,0 +1,11 @@ +[Filechooser Settings] +LocationMode=path-bar +ShowHidden=false +ShowSizeColumn=true +GeometryX=209 +GeometryY=51 +GeometryWidth=948 +GeometryHeight=647 +SortColumn=modified +SortOrder=descending +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..88c0b5b --- /dev/null +++ b/.config/gtk-2.0/gtkrc-2.0 @@ -0,0 +1,18 @@ +# DO NOT EDIT! This file will be overwritten by LXAppearance. +# Any customization should be done in ~/.gtkrc-2.0.mine instead. + +gtk-theme-name="siduck-onedark" +gtk-icon-theme-name="Reversal-red-dark" +gtk-font-name="Noto Sans 10" +gtk-cursor-theme-name="Bibata-Modern-Ice" +gtk-cursor-theme-size=24 +gtk-toolbar-style=GTK_TOOLBAR_TEXT +gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR +gtk-button-images=0 +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="rgb" diff --git a/.config/gtk-3.0/settings.ini b/.config/gtk-3.0/settings.ini new file mode 100644 index 0000000..80e7ccb --- /dev/null +++ b/.config/gtk-3.0/settings.ini @@ -0,0 +1,16 @@ +[Settings] +gtk-theme-name=siduck-onedark +gtk-icon-theme-name=Reversal-red-dark +gtk-font-name=Noto Sans 10 +gtk-toolbar-style=GTK_TOOLBAR_TEXT +gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR +gtk-button-images=0 +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=rgb +gtk-cursor-theme-name=Bibata-Modern-Ice +gtk-cursor-theme-size=24 diff --git a/.config/kitty/colors.conf b/.config/kitty/colors.conf new file mode 100644 index 0000000..da7bcac --- /dev/null +++ b/.config/kitty/colors.conf @@ -0,0 +1,19 @@ +background #16161e +foreground #c0caf5 +cursor #c0caf5 +color0 #15161e +color1 #f7768e +color2 #9ece6a +color3 #e0af68 +color4 #7aa2f7 +color5 #bb9af7 +color6 #7dcfff +color7 #a9b1d6 +color8 #414868 +color9 #f7768e +color10 #9ece6a +color11 #e0af68 +color12 #7aa2f7 +color13 #bb9af7 +color14 #7dcfff +color15 #c0caf5 diff --git a/.config/kitty/kitty.conf b/.config/kitty/kitty.conf new file mode 100644 index 0000000..56608ba --- /dev/null +++ b/.config/kitty/kitty.conf @@ -0,0 +1,58 @@ +shell_integration no-cursor +cursor_shape underline +cursor_underline_thickness 2 +cursor_stop_blinking_after 15.0 +allow_remote_control socket-only +listen_on unix:/tmp/kitty + +font_size 10 +font_family JetBrainsMono NF Regular +bold_font JetBrainsMono NF Bold +italic_font JetBrainsMono NF Italic +bold_italic_font Jameel Noori Nastaleeq + +enabled_layouts * +window_border_width 1 +window_margin_width 0 +window_padding_width 10 +active_border_color #282c34 +inactive_border_color #22262d +inactive_text_alpha 1.0 +tab_bar_margin_width 4 +tab_bar_style fade +tab_fade 1 1 1 +symbol_map U+2800-U+28FF Symbola +background_opacity 1 + +enable_audio_bell no +confirm_os_window_close 0 +update_check_interval 0 + +map ctrl+tab next_tab +map ctrl+shift+tab previous_tab +#map ctrl+t new_tab zsh +map ctrl+shift+t new_tab zsh +map ctrl+shift+r new_tab zsh -c 'lfub ~' +map ctrl+shift+w close_tab +map ctrl+shift+l next_layout +map ctrl+shift+f move_tab_forward +map ctrl+shift+b move_tab_backward + +map alt+shift+j increase_font_size +map alt+shift+k decrease_font_size +map ctrl+shift+backspace restore_font_size +map ctrl+shift+f11 toggle_fullscreen + +map alt+y copy_to_clipboard +#map alt+c copy_to_clipboard +#map alt+v paste_from_clipboard +#map ctrl+p paste_from_clipboard +map alt+p paste_from_clipboard + +repaint_delay 6 +input_delay 1 + +copy_on_select yes +strip_trailing_spaces always + +include colors.conf diff --git a/.config/lf/colors b/.config/lf/colors new file mode 100644 index 0000000..239d501 --- /dev/null +++ b/.config/lf/colors @@ -0,0 +1,177 @@ +# 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;33 # 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 49;68 # 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 +*.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 + +# image formats (dircolors defaults) +~/Projects 01;32 diff --git a/.config/lf/icons b/.config/lf/icons new file mode 100644 index 0000000..2e9a9cb --- /dev/null +++ b/.config/lf/icons @@ -0,0 +1,340 @@ +# file types +ln  # LINK +or  # ORPHAN +tw t # STICKY_OTHER_WRITABLE +# ow  # OTHER_WRITABLE +ow  # OTHER_WRITABLE +st t # STICKY +# di  # OTHER_WRITABLE +di  # DIR +pi p # FIFO +so s # SOCK +bd b # BLK +cd c # CHR +su u # SETUID +sg g # SETGID +ex  # EXEC +# fi  # FILE +# fi  # FILE +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  diff --git a/.config/lf/lfrc b/.config/lf/lfrc new file mode 100644 index 0000000..e430908 --- /dev/null +++ b/.config/lf/lfrc @@ -0,0 +1,210 @@ +# Basic vars +set shellopts '-eu' +set ifs "\n" +set scrolloff 8 +set icons +set hidden! +set period 1 +set sortby ext +set hiddenfiles ".*:*.aux:*.log:*.bbl:*.bcf:*.blg:*.run.xml" +set promptfmt "\033[32m \033[35;1m%d\033[0m\033[1m%f\033[0m" +# set cleaner '~/.config/lf/cleaner' +# set previewer '~/.config/lf/scope' +set autoquit true +set cursorpreviewfmt "\033[7m" + +set previewer ctpv +set cleaner ctpvclear +&ctpv -s $id +&ctpvquit $id + +# cmds/functions +cmd open ${{ + case $(file --mime-type "$(readlink -f $f)" -b) in + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) localc $fx ;; + image/vnd.djvu|application/pdf|application/octet-stream|application/postscript) setsid -f zathura $fx >/dev/null 2>&1 ;; + text/html) $EDITOR $fx;; + text/*|application/json|inode/x-empty|application/x-subrip|application/javascript) $EDITOR $fx;; + image/x-xcf) setsid -f gimp $f >/dev/null 2>&1 ;; + image/svg+xml) display -- $f ;; + image/*) rotdir $f | grep -i "\.\(png\|jpg\|jpeg\|gif\|webp\|avif\|tif\|ico\)\(_large\)*$" | + setsid -f nsxiv -aio 2>/dev/null | while read -r file; do + [ -z "$file" ] && continue + lf -remote "send select \"$file\"" + lf -remote "send toggle" + done & + ;; + audio/*|video/x-ms-asf) setsid -f mpv --loop-file --audio-display=no $f ;; + video/*) setsid -f mpv --loop-file $f -quiet >/dev/null 2>&1 ;; + application/pdf|application/vnd.djvu|application/epub*) setsid -f zathura $fx >/dev/null 2>&1 ;; + application/pgp-encrypted) $EDITOR $fx ;; + application/vnd.openxmlformats-officedocument.wordprocessingml.document|application/vnd.oasis.opendocument.text|application/vnd.openxmlformats-officedocument.spreadsheetml.sheet|application/octet-stream|application/vnd.oasis.opendocument.spreadsheet|application/vnd.oasis.opendocument.spreadsheet-template|application/vnd.openxmlformats-officedocument.presentationml.presentation|application/vnd.oasis.opendocument.presentation-template|application/vnd.oasis.opendocument.presentation|application/vnd.ms-powerpoint|application/vnd.oasis.opendocument.graphics|application/vnd.oasis.opendocument.graphics-template|application/vnd.oasis.opendocument.formula|application/vnd.oasis.opendocument.database) setsid -f libreoffice $fx >/dev/null 2>&1 ;; + *) for f in $fx; do setsid -f $OPENER $f >/dev/null 2>&1; done;; + esac +}} + +cmd on-cd &{{ + # display repository status in your prompt + if [ -d .git ] || [ -f .git ]; then + branch=$(git branch --show-current 2>/dev/null) || true + remote=$(git config --get branch.$branch.remote 2>/dev/null) || true + url=$(git remote get-url $remote 2>/dev/null) || true + # "\033[32m \033[35;1m%d\033[0m\033[1m%f\033[0m" + fmt="\033[32m \033[35;1m%d\033[0m\033[1m%f\033[32m  $branch 󰄾 $url\033[0m" + elif [ -d .hg ]; then + hg=$(hg branch 2>/dev/null) || true + fmt="\033[32;1m%u@%h\033[0m:\033[34;1m%w\033[0m\033[33;1m [HG BRANCH:> $hg]\033[0m" + elif [ -d .svn ]; then + svn=$(svn info 2>/dev/null | awk '/^URL: /{print $2}') || true + fmt="\033[32;1m%u@%h\033[0m:\033[34;1m%w\033[0m\033[33;1m [SVN URL:> $svn]\033[0m" + else + fmt="\033[32m \033[35;1m%d\033[0m\033[1m%f\033[0m" + fi + lf -remote "send $id set promptfmt \"$fmt\"" +}} + + +cmd fzf_search ${{ + selected=$(fzf-fd) + if [ -n "$selected" ]; then + lf "$selected" + fi +}} + +cmd fzf_grep ${{ + fzf-grep "$f" +}} + +cmd live_sever ${{ + killall live-server; setsid -f live-server "$f" +}} + +cmd ff $ff "$(echo $*)" + +cmd extract ${{ + clear; tput cup $(($(tput lines)/3)); tput bold + set -f + printf "%s\n\t" "$fx" + printf "extract?[y/N]" + read ans + [ $ans = "y" ] && { + case $fx in + *.tar.bz2) tar xjf $fx ;; + *.tar.gz) tar xzf $fx ;; + *.bz2) bunzip2 $fx ;; + *.rar) unrar e $fx ;; + *.gz) gunzip $fx ;; + *.tar) tar xf $fx ;; + *.tbz2) tar xjf $fx ;; + *.tgz) tar xzf $fx ;; + *.zip) unzip $fx ;; + *.Z) uncompress $fx ;; + *.7z) 7z x $fx ;; + *.tar.xz) tar xf $fx ;; + esac + } +}} + +cmd delete ${{ + clear; tput cup $(($(tput lines)/3)); tput bold + set -f + printf "%s\n\t" "$fx" + printf "delete?[y/N]" + read ans + [ $ans = "y" ] && rm -rf -- $fx +}} + +cmd moveto ${{ + clear; tput cup $(($(tput lines)/3)); tput bold + set -f + clear; echo "Move to where?" + dest="$(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs | fzf | sed 's|~|$HOME|')" && + for x in $fx; do + eval mv -iv \"$x\" \"$dest\" + done && + notify-send "🚚 File(s) moved." "File(s) moved to $dest." +}} + +cmd copyto ${{ + clear; tput cup $(($(tput lines)/3)); tput bold + set -f + clear; echo "Copy to where?" + dest="$(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs | fzf | sed 's|~|$HOME|')" && + for x in $fx; do + eval cp -ivr \"$x\" \"$dest\" + done && + notify-send "📋 File(s) copied." "File(s) copies to $dest." +}} + +cmd setbg "$1" + +cmd bulkrename ${{ + tmpfile_old="$(mktemp)" + tmpfile_new="$(mktemp)" + + [ -n "$fs" ] && fs=$(basename -a $fs) || fs=$(ls) + + echo "$fs" > "$tmpfile_old" + echo "$fs" > "$tmpfile_new" + $EDITOR "$tmpfile_new" + + [ "$(wc -l < "$tmpfile_old")" -eq "$(wc -l < "$tmpfile_new")" ] || { rm -f "$tmpfile_old" "$tmpfile_new"; exit 1; } + + paste "$tmpfile_old" "$tmpfile_new" | while IFS="$(printf '\t')" read -r src dst + do + [ "$src" = "$dst" ] || [ -e "$dst" ] || mv -- "$src" "$dst" + done + + rm -f "$tmpfile_old" "$tmpfile_new" + lf -remote "send $id unselect" +}} + +cmd git_branch ${{ + git branch | fzf | xargs git checkout + pwd_shell=$(pwd | sed 's/\\/\\\\/g;s/"/\\"/g') + lf -remote "send $id updir" + lf -remote "send $id cd \"$pwd_shell\"" +}} +map gb :git_branch +map gp ${{clear; git pull --rebase || true; echo "press ENTER"; read ENTER}} +map gs ${{clear; git status; echo "press ENTER"; read ENTER}} +map gl ${{clear; git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit}} + +# Bindings +map / :fzf_search +map ? :fzf_grep +map S live_server +map J $lf -remote "send $id cd $(sed -e 's/\s*#.*//' -e '/^$/d' -e 's/^\S*\s*//' ${XDG_CONFIG_HOME:-$HOME/.config}/shell/bm-dirs | fzf)" +map gh +map gg top +map D delete +map E extract +map C copyto +map M moveto +map push :ff +map reload +map set hidden! +map shell +map x $$f +map X !$f +map o &mimeopen "$f" +map O $mimeopen --ask "$f" + +map A :rename; cmd-end # at the very end +map c push A # new rename +map I :rename; cmd-home # at the very beginning +map i :rename # before extension +map a :rename; cmd-right # after extension +map B bulkrename +map b $setbg $f + +map down +map up +map V push :!nvim + +map W $setsid -f $TERMINAL >/dev/null 2>&1 + +map Y $printf "%s" "$fx" | xclip -selection clipboard + +# Source Bookmarks +source "~/.config/lf/shortcutrc" diff --git a/.config/lsd/config.yaml b/.config/lsd/config.yaml new file mode 100644 index 0000000..a472966 --- /dev/null +++ b/.config/lsd/config.yaml @@ -0,0 +1,134 @@ +# == Classic == +# This is a shorthand to override some of the options to be backwards compatible +# with `ls`. It affects the "color"->"when", "sorting"->"dir-grouping", "date" +# and "icons"->"when" options. +# Possible values: false, true +classic: false + +# == Blocks == +# This specifies the columns and their order when using the long and the tree +# layout. +# Possible values: permission, user, group, context, size, date, name, inode, links +blocks: + - permission + - date + - name + - size + +# == Color == +# This has various color options. (Will be expanded in the future.) +color: + # When to colorize the output. + # When "classic" is set, this is set to "never". + # Possible values: never, auto, always + when: auto + # How to colorize the output. + # When "classic" is set, this is set to "no-color". + # Possible values: default, + # when specifying , lsd will look up theme file + # XDG Base Directory if relative, e.g. ~/.config/lsd/themes/.yaml, + # The file path if absolute + theme: default + +# == Date == +# This specifies the date format for the date column. The freeform format +# accepts a strftime like string. +# When "classic" is set, this is set to "date". +# Possible values: date, relative, '+' +# `date_format` will be a `strftime` formatted value. e.g. `date: '+%d %b %y %X'` will give you a date like this: 17 Jun 21 20:14:55 +date: '+%b-%d %I:%M %P' + +# == Dereference == +# Whether to dereference symbolic links. +# Possible values: false, true +dereference: false + +# == Display == +# What items to display. Do not specify this for the default behavior. +# Possible values: all, almost-all, directory-only +# display: all + +# == Icons == +icons: + # When to use icons. + # When "classic" is set, this is set to "never". + # Possible values: always, auto, never + when: auto + # Which icon theme to use. + # Possible values: fancy, unicode + theme: fancy + # Separator between icon and the name + # Default to 1 space + separator: " " + +# == Ignore Globs == +# A list of globs to ignore when listing. +# ignore-globs: +# - .git + +# == Indicators == +# Whether to add indicator characters to certain listed files. +# Possible values: false, true +indicators: false + +# == Layout == +# Which layout to use. "oneline" might be a bit confusing here and should be +# called "one-per-line". It might be changed in the future. +# Possible values: grid, tree, oneline +layout: grid + +# == Recursion == +recursion: + # Whether to enable recursion. + # Possible values: false, true + enabled: false + # How deep the recursion should go. This has to be a positive integer. Leave + # it unspecified for (virtually) infinite. + # depth: 3 + +# == Size == +# Specifies the format of the size column. +# Possible values: default, short, bytes +size: default + +# == Permission == +# Specify the format of the permission column +# Possible value: rwx, octal +permission: rwx + +# == Sorting == +sorting: + # Specify what to sort by. + # Possible values: extension, name, time, size, version + column: name + # Whether to reverse the sorting. + # Possible values: false, true + reverse: false + # Whether to group directories together and where. + # When "classic" is set, this is set to "none". + # Possible values: first, last, none + dir-grouping: none + +# == No Symlink == +# Whether to omit showing symlink targets +# Possible values: false, true +no-symlink: false + +# == Total size == +# Whether to display the total size oZf directories. +# Possible values: false, true +total-size: false + +# == Hyperlink == +# Attach hyperlink to filenames +# Possible values: always, auto, never +hyperlink: never + +# == Symlink arrow == +# Specifies how the symlink arrow display, chars in both ascii and utf8 +symlink-arrow: ⇒ + +# == Header == +# Whether to display block headers. +# Possible values: false, true +header: false diff --git a/.config/mpd/mpd.conf b/.config/mpd/mpd.conf new file mode 100644 index 0000000..bf329d6 --- /dev/null +++ b/.config/mpd/mpd.conf @@ -0,0 +1,21 @@ +music_directory "~/Music" +playlist_directory "~/.config/mpd/playlists" + +auto_update "yes" +bind_to_address "127.0.0.1" +restore_paused "yes" +max_output_buffer_size "16384" + +audio_output { + type "pulse" + name "pulse" + #type "alsa" + #name "ALSA" +} + +audio_output { + type "fifo" + name "Visualizer feed" + path "/tmp/mpd.fifo" + format "44100:16:2" +} diff --git a/.config/mpv/input.conf b/.config/mpv/input.conf new file mode 100644 index 0000000..d614b15 --- /dev/null +++ b/.config/mpv/input.conf @@ -0,0 +1,5 @@ +l seek 5 +h seek -5 +j seek -60 +k seek 60 +S cycle sub diff --git a/.config/mpv/mpv.conf b/.config/mpv/mpv.conf new file mode 100644 index 0000000..ecce8a4 --- /dev/null +++ b/.config/mpv/mpv.conf @@ -0,0 +1,22 @@ +# profile=gpu-hq +profile=fast +profile=pseudo-gui +# scale=ewa_lanczossharp + +save-position-on-quit=yes +force-seekable=yes + +autofit-smaller=858x480 # min window size. +osd-font='Lucida Grande' +osd-font-size=18 + +# Using uosc and thumbfast +osc=no +osd-bar=no +border=no + +volume=75 # 75% on startup. +volume-max=100 # max vol to 100%. + +#Youtube videos in 360p or less. +ytdl-format=bestvideo[height<=?360]+bestaudio/best diff --git a/.config/ncmpcpp/bindings b/.config/ncmpcpp/bindings new file mode 100644 index 0000000..a445c2b --- /dev/null +++ b/.config/ncmpcpp/bindings @@ -0,0 +1,475 @@ +############################################################## +## This is the example bindings file. Copy it to ## +## ~/.ncmpcpp/bindings or $XDG_CONFIG_HOME/ncmpcpp/bindings ## +## and set up your preferences ## +############################################################## +# +#def_key "mouse" +# mouse_event +# +#def_key "up" +# scroll_up +# +#def_key "shift-up" +# select_item +# scroll_up +# +#def_key "down" +# scroll_down +# +#def_key "shift-down" +# select_item +# scroll_down +# +#def_key "[" +# scroll_up_album +# +#def_key "]" +# scroll_down_album +# +#def_key "{" +# scroll_up_artist +# +#def_key "}" +# scroll_down_artist +# +#def_key "page_up" +# page_up +# +#def_key "page_down" +# page_down +# +#def_key "home" +# move_home +# +#def_key "end" +# move_end +# +#def_key "insert" +# select_item +# +#def_key "enter" +# enter_directory +# +#def_key "enter" +# toggle_output +# +#def_key "enter" +# run_action +# +#def_key "enter" +# play_item +# +#def_key "space" +# add_item_to_playlist +# +#def_key "space" +# toggle_lyrics_update_on_song_change +# +#def_key "space" +# toggle_visualization_type +# +#def_key "delete" +# delete_playlist_items +# +#def_key "delete" +# delete_browser_items +# +#def_key "delete" +# delete_stored_playlist +# +#def_key "right" +# next_column +# +#def_key "right" +# slave_screen +# +#def_key "right" +# volume_up +# +#def_key "+" +# volume_up +# +#def_key "left" +# previous_column +# +#def_key "left" +# master_screen +# +#def_key "left" +# volume_down +# +#def_key "-" +# volume_down +# +#def_key ":" +# execute_command +# +#def_key "tab" +# next_screen +# +#def_key "shift-tab" +# previous_screen +# +#def_key "f1" +# show_help +# +#def_key "1" +# show_playlist +# +#def_key "2" +# show_browser +# +#def_key "2" +# change_browse_mode +# +#def_key "3" +# show_search_engine +# +#def_key "3" +# reset_search_engine +# +#def_key "4" +# show_media_library +# +#def_key "4" +# toggle_media_library_columns_mode +# +#def_key "5" +# show_playlist_editor +# +#def_key "6" +# show_tag_editor +# +#def_key "7" +# show_outputs +# +#def_key "8" +# show_visualizer +# +#def_key "=" +# show_clock +# +#def_key "@" +# show_server_info +# +#def_key "s" +# stop +# +#def_key "p" +# pause +# +#def_key ">" +# next +# +#def_key "<" +# previous +# +#def_key "ctrl-h" +# jump_to_parent_directory +# +#def_key "ctrl-h" +# replay_song +# +#def_key "backspace" +# jump_to_parent_directory +# +#def_key "backspace" +# replay_song +# +def_key "right" + seek_forward + +def_key "left" + seek_backward + +#def_key "r" +# toggle_repeat +# +#def_key "z" +# toggle_random +# +#def_key "y" +# save_tag_changes +# +#def_key "y" +# start_searching +# +#def_key "y" +# toggle_single +# +#def_key "R" +# toggle_consume +# +#def_key "Y" +# toggle_replay_gain_mode +# +#def_key "T" +# toggle_add_mode +# +#def_key "|" +# toggle_mouse +# +#def_key "#" +# toggle_bitrate_visibility +# +#def_key "Z" +# shuffle +# +#def_key "x" +# toggle_crossfade +# +#def_key "X" +# set_crossfade +# +#def_key "u" +# update_database +# +#def_key "ctrl-s" +# sort_playlist +# +#def_key "ctrl-s" +# toggle_browser_sort_mode +# +#def_key "ctrl-s" +# toggle_media_library_sort_mode +# +#def_key "ctrl-r" +# reverse_playlist +# +#def_key "ctrl-f" +# apply_filter +# +#def_key "ctrl-_" +# select_found_items +# +#def_key "/" +# find +# +#def_key "/" +# find_item_forward +# +#def_key "?" +# find +# +#def_key "?" +# find_item_backward +# +#def_key "." +# next_found_item +# +#def_key "," +# previous_found_item +# +#def_key "w" +# toggle_find_mode +# +#def_key "e" +# edit_song +# +#def_key "e" +# edit_library_tag +# +#def_key "e" +# edit_library_album +# +#def_key "e" +# edit_directory_name +# +#def_key "e" +# edit_playlist_name +# +#def_key "e" +# edit_lyrics +# +#def_key "i" +# show_song_info +# +#def_key "I" +# show_artist_info +# +#def_key "g" +# jump_to_position_in_song +# +#def_key "l" +# show_lyrics +# +#def_key "ctrl-v" +# select_range +# +#def_key "v" +# reverse_selection +# +#def_key "V" +# remove_selection +# +#def_key "B" +# select_album +# +#def_key "a" +# add_selected_items +# +#def_key "c" +# clear_playlist +# +#def_key "c" +# clear_main_playlist +# +#def_key "C" +# crop_playlist +# +#def_key "C" +# crop_main_playlist +# +#def_key "m" +# move_sort_order_up +# +#def_key "m" +# move_selected_items_up +# +#def_key "n" +# move_sort_order_down +# +#def_key "n" +# move_selected_items_down +# +#def_key "M" +# move_selected_items_to +# +#def_key "A" +# add +# +#def_key "S" +# save_playlist +# +#def_key "o" +# jump_to_playing_song +# +#def_key "G" +# jump_to_browser +# +#def_key "G" +# jump_to_playlist_editor +# +#def_key "~" +# jump_to_media_library +# +#def_key "E" +# jump_to_tag_editor +# +#def_key "U" +# toggle_playing_song_centering +# +#def_key "P" +# toggle_display_mode +# +#def_key "\\" +# toggle_interface +# +#def_key "!" +# toggle_separators_between_albums +# +#def_key "L" +# toggle_lyrics_fetcher +# +#def_key "F" +# fetch_lyrics_in_background +# +#def_key "alt-l" +# toggle_fetching_lyrics_in_background +# +#def_key "ctrl-l" +# toggle_screen_lock +# +#def_key "`" +# toggle_library_tag_type +# +#def_key "`" +# refetch_lyrics +# +#def_key "`" +# add_random_items +# +#def_key "ctrl-p" +# set_selected_items_priority +# +#def_key "q" +# quit +# +# +#def_key "f" +# find +#def_key "f" +# find_item_forward + +def_key "+" + show_clock +def_key "=" + volume_up + +def_key "j" + scroll_down +def_key "k" + scroll_up + +def_key "ctrl-u" + page_up +#push_characters "kkkkkkkkkkkkkkk" +def_key "ctrl-d" + page_down +#push_characters "jjjjjjjjjjjjjjj" +def_key "u" + page_up +#push_characters "kkkkkkkkkkkkkkk" +def_key "d" + page_down +#push_characters "jjjjjjjjjjjjjjj" +def_key "h" + previous_column +def_key "l" + next_column + +def_key "." + show_lyrics + +def_key "n" + next_found_item +def_key "N" + previous_found_item + +# not used but bound +def_key "J" + move_sort_order_down +def_key "K" + move_sort_order_up +def_key "h" + jump_to_parent_directory +def_key "l" + enter_directory +def_key "l" + run_action +def_key "l" + play_item +def_key "m" + show_media_library +def_key "m" + toggle_media_library_columns_mode +def_key "t" + show_tag_editor +def_key "v" + show_visualizer +def_key "G" + move_end +def_key "g" + move_home +#jump_to_position_in_song +def_key "U" + update_database +def_key "s" + reset_search_engine +def_key "s" + show_search_engine +def_key "x" + delete_playlist_items +def_key "P" + show_playlist diff --git a/.config/ncmpcpp/config b/.config/ncmpcpp/config new file mode 100644 index 0000000..b55eb31 --- /dev/null +++ b/.config/ncmpcpp/config @@ -0,0 +1,46 @@ +# vim: filetype=conf + +ncmpcpp_directory = "~/.config/ncmpcpp" +lyrics_directory = "~/.local/share/lyrics" +mpd_music_dir = "~/Music" +message_delay_time = "1" +visualizer_type = "spectrum" +visualizer_spectrum_dft_size = 4 +user_interface = "alternative" +startup_screen = "browser" +ignore_leading_the = yes +external_editor = nvim +use_console_editor = yes +execute_on_song_change="pkill -RTMIN+11 dwmblocks" +cyclic_scrolling = "yes" +mouse_support = "yes" +mouse_list_scroll_whole_page = "yes" +lines_scrolled = "1" +playlist_shorten_total_times = "yes" +playlist_display_mode = "classic" +browser_display_mode = "classic" +browser_sort_mode = "mtime" +search_engine_display_mode = "classic" +playlist_editor_display_mode = "classic" +autocenter_mode = "yes" +centered_cursor = "yes" +follow_now_playing_lyrics = "yes" +locked_screen_width_part = "50" +ask_for_locked_screen_width_part = "no" +display_bitrate = "no" +main_window_color = "default" +progressbar_look = "━━ " +progressbar_elapsed_color = "magenta" +header_visibility = "no" +statusbar_visibility = "yes" +titles_visibility = "yes" +enable_window_title = "yes" +clock_display_seconds = no +color1 = "white" +color2 = "blue" +now_playing_prefix = "$b$6 " +now_playing_suffix = "$/b$9" +current_item_prefix = "$b$3 " +song_list_format = "{{%a - %t}|{%f}}{$R%l}" +song_status_format = {%a - %t}|{%f} +song_library_format = {{%a - %t} (%b)}|{%f} diff --git a/.config/networkmanager-dmenu/config.ini b/.config/networkmanager-dmenu/config.ini new file mode 100644 index 0000000..cc27551 --- /dev/null +++ b/.config/networkmanager-dmenu/config.ini @@ -0,0 +1,28 @@ +[dmenu] +dmenu_command = dmenu -i -bw 2 -W 250 -X 1101 -Y 15 -l 15 +# # Note that dmenu_command can contain arguments as well like: +# # `dmenu_command = rofi -dmenu -i -theme nmdm` +# # `dmenu_command = rofi -dmenu -width 30 -i` +# # `dmenu_command = dmenu -i -l 25 -b -nb #909090 -nf #303030` +# rofi_highlight = # (Default: False) use rofi highlighting instead of '==' +rofi_highlight = True +# compact = # (Default: False). Remove extra spacing from display +compact = True +# pinentry = # (Default: None) e.g. `pinentry-gtk` +# wifi_chars = +# wifi_chars = ▂▄▆█ +# list_saved = # (Default: False) list saved connections + +[dmenu_passphrase] +# # Uses the -password flag for Rofi, -x for bemenu. For dmenu, sets -nb and +# # -nf to the same color or uses -P if the dmenu password patch is applied +# # https://tools.suckless.org/dmenu/patches/password/ +obscure = True +# obscure_color = #222222 + +[editor] +# terminal = +# gui_if_available = (Default: True) + +[nmdm] +# rescan_delay = # (seconds to wait after a wifi rescan before redisplaying the results) diff --git a/.config/nvim/.luarc.json b/.config/nvim/.luarc.json new file mode 100644 index 0000000..154c5b3 --- /dev/null +++ b/.config/nvim/.luarc.json @@ -0,0 +1,13 @@ +{ + "runtime.version": "LuaJIT", + "runtime.path": [ + "lua/?.lua", + "lua/?/init.lua" + ], + "diagnostics.globals": ["vim"], + "workspace.checkThirdParty": false, + "workspace.library": [ + "$VIMRUNTIME", + "./lua" + ] +} diff --git a/.config/nvim/README.md b/.config/nvim/README.md new file mode 100644 index 0000000..d606288 --- /dev/null +++ b/.config/nvim/README.md @@ -0,0 +1,3 @@ +# Neovim + +#Features: diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua new file mode 100644 index 0000000..fead070 --- /dev/null +++ b/.config/nvim/init.lua @@ -0,0 +1,7 @@ +vim.g.mapleader = " " +vim.g.maplocalleader = " " + +require("options") +require("manager") +require("autocommands") +require("mappings") diff --git a/.config/nvim/lazy-lock.json b/.config/nvim/lazy-lock.json new file mode 100644 index 0000000..dbc590f --- /dev/null +++ b/.config/nvim/lazy-lock.json @@ -0,0 +1,67 @@ +{ + "Comment.nvim": { "branch": "master", "commit": "0236521ea582747b58869cb72f70ccfa967d2e89" }, + "LuaSnip": { "branch": "master", "commit": "72eea98b1900013e0cb214f29b898c8d91564930" }, + "alpha-nvim": { "branch": "main", "commit": "41283fb402713fc8b327e60907f74e46166f4cfd" }, + "cmp-async-path": { "branch": "main", "commit": "7df7f3721c45aac26b6e0474087538f4681c9c7a" }, + "cmp-buffer": { "branch": "main", "commit": "3022dbc9166796b644a841a02de8dd1cc1d311fa" }, + "cmp-calc": { "branch": "main", "commit": "ce91d14d2e7a8b3f6ad86d85e34d41c1ae6268d9" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "5af77f54de1b16c34b23cba810150689a3a90312" }, + "cmp-spell": { "branch": "master", "commit": "32a0867efa59b43edbb2db67b0871cfad90c9b66" }, + "cmp-vimtex": { "branch": "master", "commit": "613fbfc54d9488252b0b0289d6d1d60242513558" }, + "cmp_luasnip": { "branch": "master", "commit": "05a9ab28b53f71d1aece421ef32fee2cb857a843" }, + "flit.nvim": { "branch": "main", "commit": "56490317983218b09698f8c960c3669958b12b32" }, + "friendly-snippets": { "branch": "main", "commit": "ea068f1becd91bcd4591fceb6420d4335e2e14d3" }, + "fzf-lua": { "branch": "main", "commit": "6860237cbcc6e95d26ffdb22e4fe7a65b2b3e60d" }, + "gitsigns.nvim": { "branch": "main", "commit": "035da036e68e509ed158414416c827d022d914bd" }, + "harpoon": { "branch": "harpoon2", "commit": "0378a6c428a0bed6a2781d459d7943843f374bce" }, + "indent-blankline.nvim": { "branch": "master", "commit": "3d08501caef2329aba5121b753e903904088f7e6" }, + "lazy.nvim": { "branch": "main", "commit": "31ddbea7c10b6920c9077b66c97951ca8682d5c8" }, + "leap.nvim": { "branch": "main", "commit": "626be4c4ec040aeaf6466c9aae17ee0ab09f1a5b" }, + "lf.nvim": { "branch": "master", "commit": "69ab1efcffee6928bf68ac9bd0c016464d9b2c8b" }, + "lsp-zero.nvim": { "branch": "v3.x", "commit": "b93f040edd57888cd6a1e7d9dee47dddc4463f8f" }, + "lspkind.nvim": { "branch": "master", "commit": "1735dd5a5054c1fb7feaf8e8658dbab925f4f0cf" }, + "lualine.nvim": { "branch": "master", "commit": "0a5a66803c7407767b799067986b4dc3036e1983" }, + "luasnip-latex-snippets.nvim": { "branch": "main", "commit": "6b5e24bd30735713b290c8523590197340da3e51" }, + "markdown-preview.nvim": { "branch": "main", "commit": "462ce41af003f5cdadab856f3a42dc27e39b89c8" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "f3658bfc667df6a0340194a015ac2f31c1e675e0" }, + "mason-nvim-dap.nvim": { "branch": "main", "commit": "67210c0e775adec55de9826b038e8b62de554afc" }, + "mason.nvim": { "branch": "main", "commit": "751b1fcbf3d3b783fcf8d48865264a9bcd8f9b10" }, + "mini.ai": { "branch": "main", "commit": "ee9446a17c160aba6a04ff22097389c41872c878" }, + "mini.surround": { "branch": "main", "commit": "d035934958e2605048ee1378ce47cf799f7071d4" }, + "none-ls.nvim": { "branch": "main", "commit": "88821b67e6007041f43b802f58e3d9fa9bfce684" }, + "nvim-autopairs": { "branch": "master", "commit": "4f41e5940bc0443fdbe5f995e2a596847215cd2a" }, + "nvim-cmp": { "branch": "main", "commit": "ce16de5665c766f39c271705b17fff06f7bcb84f" }, + "nvim-colorizer.lua": { "branch": "master", "commit": "85855b38011114929f4058efc97af1059ab3e41d" }, + "nvim-dap": { "branch": "master", "commit": "6ae8a14828b0f3bff1721a35a1dfd604b6a933bb" }, + "nvim-dap-ui": { "branch": "master", "commit": "edfa93f60b189e5952c016eee262d0685d838450" }, + "nvim-dap-virtual-text": { "branch": "master", "commit": "3e8e207513e6ef520894950acd76b79902714103" }, + "nvim-html-css": { "branch": "main", "commit": "c514bd27ad560636ed39dea3e370b3103754e244" }, + "nvim-lspconfig": { "branch": "master", "commit": "ed8b8a15acc441aec669f97d75f2c1f2ac8c8aa5" }, + "nvim-markdown": { "branch": "master", "commit": "75639723c1a3a44366f80cff11383baf0799bcb5" }, + "nvim-nio": { "branch": "master", "commit": "5800f585def265d52f1d8848133217c800bcb25d" }, + "nvim-spectre": { "branch": "master", "commit": "9653847cf2f225648967f6e9363643e327387579" }, + "nvim-treesitter": { "branch": "master", "commit": "1e20226231add3f8fad4e28fd66a68e3ae370b93" }, + "nvim-treesitter-textobjects": { "branch": "master", "commit": "23b820146956b3b681c19e10d3a8bc0cbd9a1d4c" }, + "nvim-ts-autotag": { "branch": "main", "commit": "531f48334c422222aebc888fd36e7d109cb354cd" }, + "nvim-ts-context-commentstring": { "branch": "main", "commit": "a6382f744f584bbf71d0a563af789af7190aabda" }, + "nvim-ufo": { "branch": "main", "commit": "a5390706f510d39951dd581f6d2a972741b3fa26" }, + "nvim-web-devicons": { "branch": "master", "commit": "beb6367ab8496c9e43f22e0252735fdadae1872d" }, + "outline.nvim": { "branch": "main", "commit": "bdfd2da90e9a7686d00e55afa9f772c4b6809413" }, + "persistence.nvim": { "branch": "main", "commit": "4982499c1636eac254b72923ab826ee7827b3084" }, + "plenary.nvim": { "branch": "master", "commit": "8aad4396840be7fc42896e3011751b7609ca4119" }, + "project.nvim": { "branch": "main", "commit": "8c6bad7d22eef1b71144b401c9f74ed01526a4fb" }, + "promise-async": { "branch": "main", "commit": "93540c168c5ed2b030ec3e6c40ab8bbb85e36355" }, + "qalc.nvim": { "branch": "main", "commit": "d3072e5ac8dc1caa4b60f673c53f70c7e06f1367" }, + "refactoring.nvim": { "branch": "master", "commit": "d2786877c91aa409c824f27b4ce8a9f560dda60a" }, + "todo-comments.nvim": { "branch": "main", "commit": "a7e39ae9e74f2c8c6dc4eea6d40c3971ae84752d" }, + "toggleterm.nvim": { "branch": "main", "commit": "dca1c80fb8ec41c97e7c3ef308719d8143fbbb05" }, + "tokyonight.nvim": { "branch": "main", "commit": "9bf9ec53d5e87b025e2404069b71e7ebdc3a13e5" }, + "trouble.nvim": { "branch": "main", "commit": "b9cf677f20bb2faa2dacfa870b084e568dca9572" }, + "undotree": { "branch": "main", "commit": "eab459ab87dd249617b5f7187bb69e614a083047" }, + "vim-be-good": { "branch": "master", "commit": "4fa57b7957715c91326fcead58c1fa898b9b3625" }, + "vim-illuminate": { "branch": "master", "commit": "e522e0dd742a83506db0a72e1ced68c9c130f185" }, + "vim-repeat": { "branch": "master", "commit": "24afe922e6a05891756ecf331f39a1f6743d3d5a" }, + "vimtex": { "branch": "master", "commit": "a1ea8ea08d7b5c1a2adbaed693dd2d1ad0d788ce" }, + "which-key.nvim": { "branch": "main", "commit": "4433e5ec9a507e5097571ed55c02ea9658fb268a" }, + "zen-mode.nvim": { "branch": "main", "commit": "78557d972b4bfbb7488e17b5703d25164ae64e6a" } +} \ No newline at end of file diff --git a/.config/nvim/lua/ascii.lua b/.config/nvim/lua/ascii.lua new file mode 100644 index 0000000..b8674d1 --- /dev/null +++ b/.config/nvim/lua/ascii.lua @@ -0,0 +1,297 @@ +return { + -- great_slash = { + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠠⣀⣠⣶⣶⣶⣿⣿⣿⣟⠟⠉⠁ ⠉⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣵⣶⣿⣿⣿⡿⣟⢿⡝⠙⠀⠤⠤⣤⣤⡶⠂⠀]], + -- [[⠀⠀⠀⠀⢀⠴⣪⣾⣿⣿⣿⣿⣿⢿⡿⠃⢿⢸⣧⡍⠭⣭⣿⡿⠋⠀⠀⠀]], + -- [[⠀⠀⠀⢀⣵⣿⣿⣿⣿⣿⢯⠟⡵⠋ ⢠⢾⣿⣿⣿⡤⣼⢏⣠⣀⠀⠀⠀]], + -- [[⠀⢠⣰⣻⣿⣿⣿⣾⣿⣧⢡⣘⠁⠀⠀⠘⣄⣻⣿⣿⣷⣿⣿⡿⠍⠁⠀⠀]], + -- [[⠀⡇⡿⣿⣿⣿⡿⣿⡻⣿⣜⢄⣶⣤⣀⠀⠀⠀⠈⠛⢻⣟⠫⠉⠀⠀⠀⠀]], + -- [[⠀⠣⡻⣌⡻⠿⣿⣮⣽⣿⣶⣾⣿⣳⠶⠖⠬⠍⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠈⠀⠉⠉⠙⠛⠛⠒⠓⠒⠀⠀⠀⠒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- }, + -- mothwing = { + -- [[⠀⠀⠀⠀⢠⣶⡦⠀⣠⣤⣤⣤⣀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⢸⣿⣧⣾⣿⣣⠄⣹⣿⠟⢆⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠙⣿⣿⣿⣷⣿⣾⣿⣧⣸⡆⠀]], + -- [[⠀⠀⠀⠀⠀⠐⢿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀]], + -- [[⠀⠀⠀⠀⠀⠻⣮⣿⣿⣿⣿⣿⣿⡿⠃⠀⠀]], + -- [[⠀⠀⠀⠀⡠⢞⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀]], + -- [[⠀⠀⡰⣓⣼⡿⡿⢻⣭⣾⣿⢿⢻⡰⠀⠀⠀]], + -- [[⠀⡮⡺⠕⡫⠋⣬⣴⣿⣿⣿⣸⠸⡱⡄⠀⠀]], + -- [[⠸⡰⡝⣨⠕⠊⠀⣿⣿⣿⠏⠏⣶⡕⡇⠀⠀]], + -- [[⠘⠀⡢⠁⠀⠀⠀⠋⠋⠀⠀⢰⡘⠰⠇⠀⠀]], + -- [[ ⠸⠁⠀⠀⠀⠀]], + -- }, + -- radiance = { + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⡇⠀⠠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢇⠀⠃⢀⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⠷⣷⢷⣴⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣧⣅⣂⣧⣾⣷⣇⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⢀⠀⠀⠀⢀⢠⢐⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⠑⢆⣠⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠢⢦⣀⣴⣾⣿⣭⣶⠵⠩⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡛⣘⠿⣿⣷⠶⠿⠦⠴⠠⡀⠀]], + -- [[⠀⠀⢀⣀⣘⣩⣙⣫⣭⣶⡿⣫⣪⣭⢛⠿⣿⣿⡿⠋⣩⣝⢶⣝⡿⣶⣭⣓⡦⢍⠂⠄⠀⠀]], + -- [[⠀⠀⠀⠐⠋⠩⢭⣉⣩⣵⢞⣵⡿⠁⠊⢀⣻⣿⡁⠉⡪⡻⣷⣝⢿⣶⡝⠭⡙⠓⠤⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠈⠉⠉⢉⢉⠠⠟⠉⠂⠀⠀⠠⣭⢩⡤⠀⠁⠰⠈⠙⠷⡈⠙⢆⠀⠆⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠟⠸⢓⠀⠀⠀⠀⠀⠀⠑⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⢠⣸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣾⠸⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- }, + -- suckless = { + -- [[ ]], + -- [[ ]], + -- [[ ]], + -- [[ ]], + -- [[ ▀ ]], + -- [[█▀█▄█▀█▀█▀█]], + -- [[ ]], + -- [[ ]], + -- }, + -- venom = { + -- [[⠀⠀⢰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠀]], + -- [[⠀⠀⣾⣧⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣼⡇⠀]], + -- [[⠀⠀⡏⢿⣿⣿⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣾⣿⣿⡗⠀⠀]], + -- [[⠀⠀⠁⠘⣿⣿⣿⣿⣿⣷⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣿⣿⣿⣿⣿⣿⠁⠀⠀]], + -- [[⠀⠀⠀⠀⢻⣿⣿⣿⣿⣿⣷⣍⠡⠀⠀⠀⠀⠀⠀⢋⣽⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠹⣻⣿⣿⣿⣿⣿⣧⣀⠀⠀⠀⠠⣀⣾⣿⣿⣿⡿⣟⣿⠏⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠈⠹⠜⠋⠟⠿⠉⠀⠀⠀⠀⠀⠑⠻⢿⠙⠩⠫⠛⠁⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⢠⠠⡆⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⡀⢀⠀⠄⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠂⠇⠰⠄⡞⠀⣼⠀⣿⡄⢰⡷⠸⣧⢰⡆⠨⡂⡾⡐⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠈⠈⢧⢹⡇⢿⠀⢿⠇⠈⡇⠨⡟⢸⡇⡿⠡⠁⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠸⡀⢸⠀⠀⠇⢸⠃⡿⠘⠁⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠈⠀⠀⠀⠊⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⢳⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡎⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠘⠧⢢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡆⠏⠁⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠺⣆⢡⢠⠀⡀⢠⢀⡄⡆⣸⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠸⠘⢂⡆⢸⣸⢃⠇⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠋⠎⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- }, + -- symbol = { + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⢂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⠋⠀⠀]], + -- [[⠀⠀⢦⣀⠀⠈⢣⡀⠀⠀⣀⣀⣀⣀⣴⠁⣠⡶⠀⠀⢀⣴⠋⠁⠀⠀⠀]], + -- [[⠀⠀⠀⠙⢷⣄⠈⢿⡞⠛⠉⠉⠉⢹⠃⣠⡞⠀⣠⣴⠟⠀⢀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠙⢣⣀⢡⡶⠞⠛⠛⠣⢦⠝⣠⣾⠟⢁⣤⠔⠃⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠙⠣⠀⢀⣀⣀⣀⣴⣾⠿⠡⠚⠻⣧⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠰⣾⠟⢉⡉⠙⣿⡅⢀⡀⡀⠀⢹⡄⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠈⢀⡀⠻⠟⢀⣿⠃⠘⠶⠃⠀⢸⡇⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⢀⠠⡶⣡⠄⣠⡿⠿⠶⠶⠟⠉⠀⠀⠀⠀⢀⣿⠁⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠘⠂⢡⡾⠋⠀⠀⠀⠀⠀⠀⠀⠱⣤⣠⡾⠃⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠐⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠋⢴⡀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀]], + -- }, + -- scorpion = { + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢤⢠⠠⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣔⡀⠚⠀⠀⠠⠒⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⡟⠁⠀⠀⠀⢀⡋⢙⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⠛⠀⠀⢀⠀⠀⢐⣣⠤⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠒⠁⠢⡄⠀⡈⠀⢐⠧⢀⠇⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢂⠀⠀⠀⣘⢀⠇⣀⡱⢈⡁⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠀⢀⣠⢤⡍⢛⡆⣻⡴⣾⡸⣎⣳⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⣀⣠⣤⣤⣀⡀⣀⣀⡀⠀⢇⣤⣷⣿⣴⣌⣰⡤⡁⢀⡤⠄⠠⡄⠀⠀]], + -- [[⠀⠀⠀⢈⣽⣿⣿⣿⣿⠟⠑⠉⠑⠷⠱⣮⢹⣿⣿⣿⠟⠸⡭⠬⢥⣄⠀⠀⢀⠀⠀]], + -- [[⠀⠀⠔⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⢛⣑⣓⢬⣕⠋⠙⢦⠀⢀⠍⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⢦⡃⠀⠀⡃⠀⢸⠀⠈⠂⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣄⠀⢀⣤⢾⠃⠁⠀⠀⠃⠁⠀⠉⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠐⢄⣀⣀⣠⣴⣿⣿⣿⢣⠞⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⢀⠀⠀⠈⠉⣹⣿⣿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠈⠉⠛⠛⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- }, + -- raven = { + -- [[ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⠀ ]], + -- [[ ⠀⠀⢤⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠠⣢⢃⡶ ]], + -- [[ ⠀⠀⣼⡶⠘⠀⠀⠀⠀⠀⠀⠀⠀⢠⢀⠄⠀⠢⢼⣿⣿⣷⡅ ]], + -- [[ ⠠⠀⣿⣿⢇⡀⠀⠀⠀⠀⠀⠀⡤⠀⢈⢄⡇⣪⣿⣿⣿⢟⡠ ]], + -- [[ ⠀⢸⣿⣿⣟⡐⠁⣀⠀⠀⠀⣠⡤⡨⣳⣿⣿⣿⣿⣿⣿⡿⠃ ]], + -- [[ ⠀⠀⢻⣿⣿⣇⠸⠠⠀⠀⣠⣿⣷⣿⣿⣿⣿⣿⣿⣿⠿⠁⠁ ]], + -- [[ ⠀⠀⠀⠙⠿⣿⣮⣄⣄⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⢏⠹⠄⠃ ]], + -- [[ ⠀⠀⠀⢀⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⠻⠀⠙⠠⠀⠀ ]], + -- [[ ⠀⠀⠀⠈⢤⡟⠻⣿⣿⣿⣿⣿⣿⡿⠿⡻⠳⠁⠀⠁⠀⠀⠀ ]], + -- [[ ⠀⠀⠀⠀⠀⠀⠁⠙⢿⣿⣿⣿⣿⣶⣾⣷⣶⣦⣤⠀⠀⠀⠀ ]], + -- [[ ⠀⠀⠀⠀⠀⢀⣤⡶⡖⠿⣿⣿⣿⣿⡿⠏⠝⠁⠀⠀⠀⠀⠀ ]], + -- [[ ⠀⠀⠀⠀⠀⠈⠀⠡⠔⠀⠈⠙⠙⠑⠂⠀⠀⠀⠀⠀⠀⠀⠀ ]], + -- }, + yggdrasil = { + [[ ⠀⠀⠀⠀⠀⠀⢀⢀⠀⣄⢂⣀⣂⣤⣀⢀⢀⠀⠀⠀⠀⠀⠀ ]], + [[ ⠀⠀⠀⠀⣄⣰⣝⣉⣙⢱⣞⠜⡖⣌⣌⣁⣻⣠⣀⠀⠀⠀⠀ ]], + [[ ⠀⠀⢔⢽⣊⣂⣇⡒⠮⢻⣇⠲⢍⣿⢟⣒⣰⣠⣑⡔⣀⠀⠀ ]], + [[ ⠀⠹⡸⢙⣕⡐⢂⠍⣩⡻⣿⣆⣾⠟⣉⢣⠪⠲⡰⡋⣢⢆⠀ ]], + [[ ⠀⣪⡹⣵⢦⠽⡓⠶⠶⣧⣹⣿⣏⣴⠶⠛⠟⠽⢛⣒⢮⡙⠀ ]], + [[ ⠸⢋⢪⠑⢩⠈⠀⠀⠀⠈⣿⣿⣿⠁⠀⠀⠘⢠⠈⠆⢎⢱⠁ ]], + [[ ⠀⠻⡕⡲⡈⠀⠀⠀⠀⠀⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠆⠄⠁ ]], + [[ ⠀⠀⠀⠇⠀⠀⠀⠀⠀⣰⣿⣿⣿⣤⡀⠀⠀⠀⠀⠌⠘⠀⠀ ]], + [[ ⠀⠀⠀⢱⠒⡶⡶⢖⣫⡿⢻⠿⡟⢿⣍⡱⢖⠶⠒⡆⠀⠀⠀ ]], + [[ ⠀⠀⠀⠀⠁⠬⡃⠴⣇⣴⠏⠖⠙⣦⣸⠦⡼⠣⠉⠀⠀⠀⠀ ]], + [[ ⠀⠀⠀⠀⠀⠀⠈⠁⠑⠢⠧⠭⠼⠵⠋⠊⠁⠀⠀⠀⠀⠀⠀ ]], + }, + -- void_stranger = { + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⣀⣴⣶⣄⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⣴⠋⠁⠈⣿⡟⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⣾⣏⣀⠠⠞⠉⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⣸⣿⠏⠀⠀⠀⠀ ⠀⣀⡀⠀⠀]], + -- [[⠀⢰⣿⣿⠀⠀⠀⠀⡠⠒⠿⣿⣿⣧⠀]], + -- [[⠀⠀⣿⣿⣷⣤⡠⠊⠀⠀⠀⢸⣿⣿⠀]], + -- [[⠀⠀⠈⠛⠋⠁⠀⠀⠀⠀⠀⣼⣿⡇⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⢀⡤⠖⠈⣿⡿⠀⠀]], + -- [[⠀⠀⠀⠀⠀⢀⣾⣿⠀⠀⣰⠗⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠘⠯⢻⠶⠊⠁⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- }, + -- aot = { + -- [[⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⡄⠀⠀]], + -- [[⢰⠒⠒⢻⣿⣶⡒⠒⠒⠒⠒⠒⠒⠒⠒⠒⡲⠊⣰⣓⡒⡆]], + -- [[⢸⢸⢻⣭⡙⢿⣿⣍⡉⠉⡇⡏⠉⠉⣩⠋⢀⣔⠕⢫⡇⡇]], + -- [[⢸⢸⣈⡻⣿⣶⣽⡸⣿⣦⡇⡇⡠⠊⣸⢶⠋⢁⡤⠧⡇⡇]], + -- [[⢸⢸⠻⣿⣶⣝⠛⣿⣮⢻⠟⣏⣠⠞⠁⣼⡶⠋⢀⣴⡇⡇]], + -- [[⢸⢸⣿⣶⣍⠻⠼⣮⡕⢁⡤⢿⢁⡴⠊⣸⣵⠞⠋⢠⡇⡇]], + -- [[⢸⢘⣛⡻⣿⣧⢳⣿⣧⠎⢀⣾⠋⡠⠞⢱⢇⣠⡴⠟⡇⡇]], + -- [[⢸⢸⠹⣿⣷⣎⣉⣻⢁⡔⢁⢿⡏⢀⣤⢾⡟⠁⣀⣎⡇⡇]], + -- [[⢸⢸⠲⣶⣭⡛⠚⢿⢋⡔⢁⣼⠟⢋⣠⣼⠖⠋⢁⠎⡇⡇]], + -- [[⢸⢸⢤⣬⣛⠿⠞⣿⢋⠔⣉⣾⠖⠋⢁⣯⡴⠞⢃⠂⡇⡇]], + -- [[⢸⢸⠀⢙⣻⢿⣧⣾⡵⠚⣉⣯⠶⠛⣹⣧⠤⢮⠁⠀⡇⡇]], + -- [[⠸⣘⠢⣄⠙⠿⢷⡡⠖⣋⣽⠥⠒⣩⣟⣤⣔⣁⡤⠖⣃⠇]], + -- [[⠀⠀⠙⠢⢍⣻⡿⠒⢉⣴⣗⣚⣽⣋⣀⣤⣊⠥⠒⠉⠀⠀]], + -- [[⠀⠀⠀⢀⣔⠥⠒⢮⣙⠾⠀⠷⣚⡭⠞⠉⠛⠦⣀⠀⠀⠀]], + -- [[⠀⠀⠀⠉⠀⠀⠀⠀⠈⠑⠒⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- }, + -- meatboy = { + -- [[⠀⠀⣀⣀⣤⣤⣦⣶⢶⣶⣿⣿⣿⣿⣿⣿⣿⣷⣶⣶⡄⠀⠀⠀⠀⠀]], + -- [[⠀⠀⣿⣿⣿⠿⣿⣿⣾⣿⣿⣿⣿⣿⣿⠟⠛⠛⢿⣿⡇⠀⠀⠀⠀⠀]], + -- [[⠀⠀⣿⡟⠡⠂⠀⢹⣿⣿⣿⣿⣿⣿⡇⠘⠁⠀⠀⣿⡇⠀⢠⣄⠀⠀]], + -- [[⠀⠀⢸⣗⢴⣶⣷⣷⣿⣿⣿⣿⣿⣿⣷⣤⣤⣤⣴⣿⣗⣄⣼⣷⣶⡄]], + -- [[⠀⢀⣾⣿⡅⠐⣶⣦⣶⠀⢰⣶⣴⣦⣦⣶⠴⠀⢠⣿⣿⣿⣿⣼⣿⡇]], + -- [[⢀⣾⣿⣿⣷⣬⡛⠷⣿⣿⣿⣿⣿⣿⣿⠿⠿⣠⣿⣿⣿⣿⣿⠿⠛⠃]], + -- [[⢸⣿⣿⣿⣿⣿⣿⣿⣶⣦⣭⣭⣥⣭⣵⣶⣿⣿⣿⣿⣟⠉⠀⠀⠀⠀]], + -- [[⠀⠙⠇⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⣿⣿⣿⣿⣿⣛⠛⠛⠛⠛⠛⢛⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠿⣿⣿⣿⠿⠿⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⠿⠇⠀⠀⠀⠀⠀]], + -- }, + -- isaac = { + -- [[ ⣀⣤⣴⣶⣶⣶⣶⣶⣶⣤⣄⣀ ]], + -- [[ ⢀⣠⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣄ ]], + -- [[ ⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣆ ]], + -- [[ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧ ]], + -- [[ ⣾⣿⡿⠟⡋⠉⠛⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠛⠉⠉⠙⠻⣿⣿⣇]], + -- [[⢠⣿⡏⢰⣿⣿⡇ ⢸⣿⣿⣿⠿⠿⣿⣿⣿⠁⣾⣿⣷ ⠘⣿⣿]], + -- [[⠸⣿⣇⠈⠉⠉ ⢀⣼⡿⠋ ⠙⢿⣄⠙⠛⠁ ⢠⣿⣿]], + -- [[ ⢿⣿⡇ ⣶⣿⣿⢁⣤⣤⣤⣤⣤⣤ ⣿⣷ ⠈⢹⣿⡟]], + -- [[ ⠈⢿⡗ ⢸⣿⣿⣿⣶⣶⣶⣶⣶⣶⣶⣶⣿⣿ ⢸⡟ ]], + -- [[ ⠳⡀ ⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⠌ ]], + -- [[ ⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣤ ]], + -- [[ ⠉⠙⠻⠿⠿⣿⣿⣿⣿⠿⠿⠛⠉ ]], + -- }, + -- gta = { + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣤⡀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⠟⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠻⣿⣷⣄⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣶⣿⡆⠀⠀⠉⠉⠀⠈⣶⡆⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⢻⣷⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⡿⠟⠀⠀⠀⠀⠀⠀⠀⣸⣿⡄]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣷]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠃⠀⠀⠀⠀⠀⠀⠀⠀⢰⣾⣿⠏]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣧⡔⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠟⠁⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[Ah shit, here we go again.]], + -- }, + -- hydra = { + -- [[ ⣴⣶⣤⡤⠦⣤⣀⣤⠆ ⣈⣭⣭⣿⣶⣿⣦⣼⣆ ]], + -- [[ ⠉⠻⢿⣿⠿⣿⣿⣶⣦⠤⠄⡠⢾⣿⣿⡿⠋⠉⠉⠻⣿⣿⡛⣦ ]], + -- [[ ⠈⢿⣿⣟⠦⠄⣾⣿⣿⣷ ⠻⠿⢿⣿⣧⣄ ]], + -- [[ ⣸⣿⣿⢧⠄⢻⠻⣿⣿⣷⣄⣀ ⣀⡀⠈⠙⠿ ]], + -- [[ ⢀ ⢠⣿⣿⣿⠈ ⣻⣿⣿⣿⣿⣿⣿⣿⣛⣳⣤⣀⣀ ]], + -- [[ ⢠⣧⣶⣥⡤ ⣸⣿⣿⠘ ⢀⣴⣿⣿⡿⠛⣿⣿⣧⠈⢿⠿⠟⠛⠻⠿⠄ ]], + -- [[ ⣰⣿⣿⠛⠻⣿⣿⡦⢹⣿⣷ ⢊⣿⣿⡏ ⢸⣿⣿⡇ ⢀⣠⣄⣾ ]], + -- [[⣠⣿⠿⠛ ⢀⣿⣿⣷⠘⢿⣿⣦⡀ ⢸⢿⣿⣿⣄ ⣸⣿⣿⡇⣪⣿⡿⠿⣿⣷⡄ ]], + -- [[⠙⠃ ⣼⣿⡟ ⠈⠻⣿⣿⣦⣌⡇⠻⣿⣿⣷⣿⣿⣿ ⣿⣿⡇ ⠛⠻⢷⣄]], + -- [[ ⢻⣿⣿⣄ ⠈⠻⣿⣿⣿⣷⣿⣿⣿⣿⣿⡟ ⠫⢿⣿⡆ ⠁]], + -- [[ ⠻⣿⣿⣿⣿⣶⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⡟⢀⣀⣤⣾⡿⠃ ]], + -- }, + -- spider = { + -- [[ ▐ ▌ ▐ ▌ ]], + -- [[ ▐▌ █ █ ▐▌ ]], + -- [[ ▄█ ▀▀▄▌▄▐▄▀▀ █▄ ]], + -- [[ ▐█ ▄█▀▄█████▄▀█▄ █ ]], + -- [[ ▀▀ ▄▄▄█████▄▄▄ ▀▀ ]], + -- [[ ▄█▀ ▄▀███▀▄ ▀█▄ ]], + -- [[ ▄█ ▄▀ ███ ▀▄ █▄ ]], + -- [[▐█ █ ▐█▌ █ █▌]], + -- [[ █ █ ▀ █ █ ]], + -- [[ ▀█ █ █ █▀ ]], + -- [[ █ █ █ █ ]], + -- [[ █ █ █ █ ]], + -- [[ ▌ ▌ ▐ ▐ ]], + -- }, + -- moth = { + -- [[⠀⠀⠀⣀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⢀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣀⣀⣀⣀⠀⠀]], + -- [[⢀⡖⢭⡿⡁⣶⠒⢍⣩⡿⢽⣷⣦⣤⣀⠀⢾⣏⡋⡽⠇⠀⣀⣤⢴⣚⠟⣉⣉⡽⠖⠪⡟⣹⡿⠆]], + -- [[⠈⠙⠵⣫⠵⣐⣏⢒⣲⠿⢷⣛⣹⡽⣿⢻⣾⠿⡛⡧⣷⣛⣷⣯⣿⣲⢶⣾⣚⢇⢁⡼⣿⠟⠋⠀]], + -- [[⠀⠀⠀⠘⠿⣵⣫⠾⣛⣫⢫⠕⠂⠈⠀⢩⣷⠾⢲⢯⣍⠓⠉⠚⠹⣿⣯⣿⣹⣾⣿⠟⠁⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠉⢠⡾⣫⡶⡂⠀⠀⠀⠐⡟⠖⡙⡧⠆⠀⠀⠀⠀⣿⢋⣻⡧⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠘⢾⣕⢕⠰⡀⠀⠀⠀⣯⠩⠏⠇⠐⡀⠀⠀⢠⣇⣰⡿⠃⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠃⠉⠉⠃⠀⠀⢻⣨⡈⠀⠃⠑⠀⠘⠋⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- }, + -- skull = { + -- [[⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⣀⣤⣴⣶⣾⣿⣿⣿⣶⣶⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⢿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀ ]], + -- [[⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣻⣿⣿⣿⡟⠁⠀⠀⠀⠈⢻⣿⣿⣿⠀⠀⠀⠀⠀⠀ ]], + -- [[⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⠛⠛⠛⠛⠛⠛⢛⣿⣮⣿⣿⣿⠀⠀⠀⠀⠀⠀⢈⣿⣿⡟⠀⠀⠀⠀⠀⠀ ]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣧⡀⠀⠀⠀⢀⣼⣿⣿⣿⣿⣿⣧⡀⠀⠀⠀⢀⣼⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣶⣿⣿⣿⣿⠟⠉⠻⣿⣿⣿⣿⣶⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿⡇⣠⣷⡀⢹⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⠋⠛⠋⠛⠙⠛⠙⠛⠙⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- }, + -- morse = { + -- [[ ]], + -- [[ ]], + -- [[ ]], + -- [[ ]], + -- [[ ]], + -- [[ ▄▄ ▄▄ ▄▄ ▄▄ ▄▄ ▄▄ ▄▄ ]], + -- [[ ▄ ▄ ▄ ▄ ▄ ▄ ▄ ]], + -- [[ ]], + -- [[ ]], + -- [[ ]], + -- }, + -- sharp = { + -- [[ ]], + -- [[  ]], + -- [[ ████ ██████ █████ ██ ]], + -- [[ ███████████ █████  ]], + -- [[ █████████ ███████████████████ ███ ███████████ ]], + -- [[ █████████ ███ █████████████ █████ ██████████████ ]], + -- [[ █████████ ██████████ █████████ █████ █████ ████ █████ ]], + -- [[ ███████████ ███ ███ █████████ █████ █████ ████ █████ ]], + -- [[ ██████ █████████████████████ ████ █████ █████ ████ ██████ ]], + -- [[ ]], + -- }, + -- galaxy = { + -- [[ ⠀⠀⢀⣀⣀⡀⠒⠒⠦⣄⡀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⢀⣤⣶⡾⠿⠿⠿⠿⣿⣿⣶⣦⣄⠙⠷⣤⡀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⣠⡾⠛⠉⠀⠀⠀⠀⠀⠀⠀⠈⠙⠻⣿⣷⣄⠘⢿⡄⠀⠀⠀]], + -- [[⠀⢀⡾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠐⠂⠠⢄⡀⠈⢿⣿⣧⠈⢿⡄⠀⠀]], + -- [[⢀⠏⠀⠀⠀⢀⠄⣀⣴⣾⠿⠛⠛⠛⠷⣦⡙⢦⠀⢻⣿⡆⠘⡇⠀⠀]], + -- [[⠀⠀⠀⠀⡐⢁⣴⡿⠋⢀⠠⣠⠤⠒⠲⡜⣧⢸⠄⢸⣿⡇⠀⡇⠀⠀]], + -- [[⠀⠀⠀⡼⠀⣾⡿⠁⣠⢃⡞⢁⢔⣆⠔⣰⠏⡼⠀⣸⣿⠃⢸⠃⠀⠀]], + -- [[⠀⠀⢰⡇⢸⣿⡇⠀⡇⢸⡇⣇⣀⣠⠔⠫⠊⠀⣰⣿⠏⡠⠃⠀⠀⢀]], + -- [[⠀⠀⢸⡇⠸⣿⣷⠀⢳⡈⢿⣦⣀⣀⣀⣠⣴⣾⠟⠁⠀⠀⠀⠀⢀⡎]], + -- [[⠀⠀⠘⣷⠀⢻⣿⣧⠀⠙⠢⠌⢉⣛⠛⠋⠉⠀⠀⠀⠀⠀⠀⣠⠎⠀]], + -- [[⠀⠀⠀⠹⣧⡀⠻⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⡾⠃⠀⠀]], + -- [[⠀⠀⠀⠀⠈⠻⣤⡈⠻⢿⣿⣷⣦⣤⣤⣤⣤⣤⣴⡾⠛⠉⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠈⠙⠶⢤⣈⣉⠛⠛⠛⠛⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀]], + -- [[⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀]], + -- }, +} diff --git a/.config/nvim/lua/autocommands.lua b/.config/nvim/lua/autocommands.lua new file mode 100644 index 0000000..048de0c --- /dev/null +++ b/.config/nvim/lua/autocommands.lua @@ -0,0 +1,115 @@ +-- local vim.api.nvim_create_augroup = vim.api.nvim_create_augroup + +-- [[ Highlight on yank ]] +vim.api.nvim_create_autocmd("TextYankPost", { + callback = function() + vim.highlight.on_yank({ timeout = 100 }) + end, + group = vim.api.nvim_create_augroup("YankHighlight", { clear = true }), + pattern = "*", +}) + +-- [[ Disable Autocommenting on new lines ]] +vim.api.nvim_create_autocmd("BufEnter", { + callback = function() + vim.opt.formatoptions:remove({ "c", "r", "o" }) + end, + group = vim.api.nvim_create_augroup("DisableAutocommenting", { clear = true }), +}) + +-- [[ Update file on Focus ]] +vim.api.nvim_create_autocmd("FocusGained", { + callback = function() + vim.cmd("checktime") + end, + group = vim.api.nvim_create_augroup("UpdateOnFocus", { clear = true }), +}) + +-- [[ Open lf when it's a Directory ]] +vim.api.nvim_create_autocmd("VimEnter", { + callback = function(data) + local directory = vim.fn.isdirectory(data.file) == 1 + if directory then + require("lf").start() + end + end, + group = vim.api.nvim_create_augroup("lf_ifDirectory", { clear = true }), +}) + +-- [[ Remove trailing whitespaces ]] +vim.api.nvim_create_autocmd({ "BufWritePre" }, { + pattern = { "*" }, + callback = function() + local save_cursor = vim.fn.getpos(".") + vim.cmd([[%s/\s\+$//e]]) + vim.cmd([[%s/\n\+\%$//e]]) + vim.fn.setpos(".", save_cursor) + end, + group = vim.api.nvim_create_augroup("RemoveTrailingWhitespaces", { clear = true }), +}) + +-- [[ Restore last cursor position ]] +vim.api.nvim_create_autocmd("BufReadPost", { + pattern = "*", + callback = function() + local line = vim.fn.line "'\"" + if + line > 1 + and line <= vim.fn.line "$" + and vim.bo.filetype ~= "commit" + and vim.fn.index({ "xxd", "gitrebase" }, vim.bo.filetype) == -1 + then + vim.cmd 'normal! g`"zz' + end + end, +}) + +-- [[ Reload xresources on write ]] +vim.api.nvim_create_autocmd({ "BufWritePost" }, { + pattern = vim.fn.resolve(vim.fn.expand("~/.config/x11/xresources")), + callback = function() + -- cmd([[!xrdb % ; killall -USR1 st ; renew-dwm ; notify-send " - xresources reloaded"]]) + vim.cmd([[!xrdb % ; killall -USR1 st ; renew-dwm]]) + end, + group = vim.api.nvim_create_augroup("ReloadXresources", { clear = true }), +}) + +-- [[ Recompile suckless software on write and show notification ]] +local function recompile(path) + vim.api.nvim_create_augroup("RecompileGroup_" .. path, { clear = true }) + vim.api.nvim_create_autocmd({ "BufWritePost" }, { + pattern = vim.fn.resolve(vim.fn.expand(path)), + callback = function() + vim.cmd("!sudo make install; renew-dwm") + end, + }) +end +recompile("~/.config/suckless/dwm/config.h") +recompile("~/.config/suckless/dmenu/config.h") +recompile("~/.config/suckless/st/config.h") +recompile("~/.config/suckless/dwmblocks/config.h") + +--[[ Close nvim if toggleterm or Outline is the last buffer ]] +vim.api.nvim_create_autocmd({ "BufEnter" }, { + pattern = "*", + callback = function() + if + vim.fn.tabpagenr("$") == 1 + and vim.fn.winnr("$") == 1 + and (vim.bo.ft == "toggleterm" or vim.bo.ft == "Outline") + then + vim.cmd("bd! | q") + end + end, + group = vim.api.nvim_create_augroup("CloseLast", { clear = true }), +}) + +-- [[ Autosave ]] +-- vim.api.nvim_create_autocmd({ "FocusLost", "BufLeave", "BufWinLeave", "InsertLeave" }, { +-- callback = function() +-- if vim.bo.filetype ~= "" and vim.bo.buftype == "" then +-- vim.cmd("silent! w") +-- end +-- end, +-- group = vim.api.nvim_create_augroup("AutoSave", { clear = true }), +-- }) diff --git a/.config/nvim/lua/manager.lua b/.config/nvim/lua/manager.lua new file mode 100644 index 0000000..467cd45 --- /dev/null +++ b/.config/nvim/lua/manager.lua @@ -0,0 +1,70 @@ +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.loop.fs_stat(lazypath) then + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", + lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +require("lazy").setup( + { + import = "plugins", + }, + { + defaults = { + lazy = true, + }, + install = { + colorscheme = { "tokyonight", "habamax" }, + }, + change_detection = { + notify = false, + }, + ui = { + border = "rounded", + }, + performance = { + cache = { + enabled = true, + }, + reset_packpath = true, + rtp = { + disabled_plugins = { + "2html_plugin", + "tohtml", + "getscript", + "getscriptPlugin", + "gzip", + "logipat", + "netrw", + "netrwPlugin", + "netrwSettings", + "netrwFileHandlers", + "matchit", + "matchparen", + "tar", + "tarPlugin", + "rrhelper", + "spellfile_plugin", + "vimball", + "vimballPlugin", + "zip", + "zipPlugin", + "tutor", + "rplugin", + "syntax", + "synmenu", + "optwin", + "compiler", + "bugreport", + "ftplugin", + }, + }, + }, + } +) diff --git a/.config/nvim/lua/mappings.lua b/.config/nvim/lua/mappings.lua new file mode 100644 index 0000000..02924ab --- /dev/null +++ b/.config/nvim/lua/mappings.lua @@ -0,0 +1,56 @@ +-- Does not contain plugin specific keybinds +vim.keymap.set("n", "k", "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true }) +vim.keymap.set("n", "j", "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true }) +vim.keymap.set("n", "s", ":%s///gI") +vim.keymap.set("n", "", "h") +vim.keymap.set("n", "", "j") +vim.keymap.set("n", "", "k") +vim.keymap.set("n", "", "l") +vim.keymap.set("n", "", ":vertical resize -2", { silent = true }) +vim.keymap.set("n", "", ":vertical resize +2", { silent = true }) +vim.keymap.set("n", "", ":resize +2", { silent = true }) +vim.keymap.set("n", "", ":resize -2", { silent = true }) +vim.keymap.set("n", "J", "mzJ`z") +vim.keymap.set("n", "", "zz") +vim.keymap.set("n", "", "zz") +vim.keymap.set("n", "n", "nzzzv") +vim.keymap.set("n", "N", "Nzzzv") +vim.keymap.set("n", "cx", "!chmod +x %", { desc = "chmod +x" }) +vim.keymap.set("n", "cp", ':!compiler "%:p"', { desc = "run (C)om[P]iler script" }) +vim.keymap.set("n", "sa", [[:%s/\<\>//gI]], { desc = "Replace All" }) +vim.keymap.set("n", "y", "%yank", { desc = "Yank buffer" }) +vim.keymap.set("n", "", "miA;`i") +vim.keymap.set("n", "q", ":lua vim.diagnostic.open_float()", { noremap = true, silent = true }) +vim.keymap.set("n", "", ":bd", { silent = true }) +vim.keymap.set("n", "", ":vsplit", { silent = true }) +vim.keymap.set("n", "", ":split", { silent = true }) +vim.keymap.set("n", "", ":w") +vim.keymap.set('n', "gl", ':lua vim.diagnostic.open_float()') +vim.keymap.set("n", "cs", ":setlocal spell! spelllang=en_us", { desc = "Spellcheck", silent = true }) + +vim.keymap.set("x", "p", 'p:let @+=@0:let @"=@0', { silent = true }) +vim.keymap.set("x", "K", ":m '<-2gv=gv") +vim.keymap.set("x", "J", ":m '>+1gv=gv") +vim.keymap.set("x", "h", [["ay:!dmenuhandler 'a']]) + +vim.keymap.set("v", "<", "", ">gv^") + +vim.keymap.set("i", "", "viwUea") +vim.keymap.set("i", "", "b~lea") +vim.keymap.set("i", "", "miA;`ii") +vim.keymap.set("i", "", ":m .+1==gi") +vim.keymap.set("i", "", ":m .-2==gi") +vim.keymap.set("i", "", "k") +vim.keymap.set("i", "", "j") +vim.keymap.set("i", "", "h") +vim.keymap.set("i", "", "l") + +vim.keymap.set("t", "", "h") +vim.keymap.set("t", "", "j") +vim.keymap.set("t", "", "k") +vim.keymap.set("t", "", "l") + +vim.keymap.set({ "x", "v", "n" }, ";", ":", { nowait = true }) +vim.keymap.set({ "x", "v", "n" }, "", ":m .+1==") +vim.keymap.set({ "x", "v", "n" }, "", ":m .-2==") diff --git a/.config/nvim/lua/options.lua b/.config/nvim/lua/options.lua new file mode 100644 index 0000000..a115725 --- /dev/null +++ b/.config/nvim/lua/options.lua @@ -0,0 +1,75 @@ +-- indentation +vim.opt.tabstop = 2 +vim.opt.softtabstop = 2 +vim.opt.shiftwidth = 2 +vim.opt.expandtab = true +vim.opt.smartindent = true +vim.opt.breakindent = true +vim.opt.autoindent = true +vim.opt.smarttab = true + +-- search and replace +vim.opt.ignorecase = true +vim.opt.smartcase = true +vim.opt.hlsearch = false +vim.opt.incsearch = true +vim.opt.gdefault = true +vim.opt.showmatch = true +vim.opt.grepformat = "%f:%l:%c:%m" +vim.opt.grepprg = "rg --vimgrep" +vim.opt.inccommand = "nosplit" + +-- user interface +vim.opt.fillchars = { eob = " " } +vim.opt.laststatus = 3 +vim.opt.number = true +vim.opt.numberwidth = 2 +vim.opt.relativenumber = true +vim.opt.ruler = false +vim.opt.wrap = true +vim.opt.termguicolors = true +vim.opt.scrolloff = 4 +vim.opt.sidescrolloff = 4 +vim.opt.signcolumn = "yes" +vim.opt.cursorline = true +vim.opt.cursorlineopt = "both" +vim.opt.conceallevel = 2 +vim.opt.list = false +-- vim.opt.listchars = {eol = "󰌑" } +vim.opt.showmode = false +-- vim.opt.colorcolumn = "80" +vim.opt.winminwidth = 5 + +-- editing +vim.opt.completeopt = { "menu", "menuone", "noselect" } +vim.opt.timeoutlen = 300 +vim.opt.undofile = true +vim.opt.autowrite = true +vim.opt.mouse = "a" +vim.opt.whichwrap:append("<>,[,],h,l") +vim.opt.iskeyword:append("-") + +-- window management +vim.opt.splitbelow = true +vim.opt.splitright = true + +-- clipboard +vim.opt.clipboard = "unnamedplus" + +-- auto change dir +vim.opt.autochdir = true + +-- fold options +vim.opt.foldlevel = 99 +vim.opt.foldlevelstart = 99 +vim.opt.foldenable = true +vim.opt.shortmess = "aoOFCWstTAIcCqFS" + +-- gui options +vim.opt.guifont = "JetBrainsMono NF:h9" + +-- neovide ui +vim.g.neovide_padding_top = 5 +vim.g.neovide_padding_bottom = 0 +vim.g.neovide_padding_right = 10 +vim.g.neovide_padding_left = 10 diff --git a/.config/nvim/lua/plugins/debug.lua b/.config/nvim/lua/plugins/debug.lua new file mode 100644 index 0000000..6602e62 --- /dev/null +++ b/.config/nvim/lua/plugins/debug.lua @@ -0,0 +1,69 @@ +return { + -- dap + dependencies + { + "mfussenegger/nvim-dap", + dependencies = { + { + "rcarriga/nvim-dap-ui", + dependencies = { "nvim-neotest/nvim-nio" }, + --stylua: ignore + keys = { + { "du", function() require("dapui").toggle({}) end, desc = "Dap UI" }, + { "de", function() require("dapui").eval() end, desc = "Eval", mode = { "n", "v" } }, + }, + opts = {}, + config = function(_, opts) + require("dapui").setup(opts) + require("dap").listeners.after.event_initialized["dapui_config"] = function() + require("dapui").open({}) + end + require("dap").listeners.before.event_terminated["dapui_config"] = function() + require("dapui").close({}) + end + require("dap").listeners.before.event_exited["dapui_config"] = function() + require("dapui").close({}) + end + end, + }, + { + "theHamsta/nvim-dap-virtual-text", + opts = {}, + }, + { + "jay-babu/mason-nvim-dap.nvim", + dependencies = "mason.nvim", + cmd = { "DapInstall", "DapUninstall" }, + opts = { + automatic_installation = true, + handlers = {}, + ensure_installed = { + "bash-debug-adapter", + "codelldb", + "debugpy", + "go-debug-adapter", + }, + }, + }, + }, + --stylua: ignore + keys = { + { "dB", function() require("dap").set_breakpoint(vim.fn.input('Breakpoint condition: ')) end, desc = "Breakpoint Condition" }, + { "db", function() require("dap").toggle_breakpoint() end, desc = "Toggle Breakpoint" }, + { "dc", function() require("dap").continue() end, desc = "Continue" }, + { "da", function() require("dap").continue({ before = get_args }) end, desc = "Run with Args" }, + { "dC", function() require("dap").run_to_cursor() end, desc = "Run to Cursor" }, + { "dg", function() require("dap").goto_() end, desc = "Go to Line (No Execute)" }, + { "di", function() require("dap").step_into() end, desc = "Step Into" }, + { "dj", function() require("dap").down() end, desc = "Down" }, + { "dk", function() require("dap").up() end, desc = "Up" }, + { "dl", function() require("dap").run_last() end, desc = "Run Last" }, + { "do", function() require("dap").step_out() end, desc = "Step Out" }, + { "dO", function() require("dap").step_over() end, desc = "Step Over" }, + { "dp", function() require("dap").pause() end, desc = "Pause" }, + { "dr", function() require("dap").repl.toggle() end, desc = "Toggle REPL" }, + { "ds", function() require("dap").session() end, desc = "Session" }, + { "dt", function() require("dap").terminate() end, desc = "Terminate" }, + { "dw", function() require("dap.ui.widgets").hover() end, desc = "Widgets" }, + }, + } +} diff --git a/.config/nvim/lua/plugins/doc.lua b/.config/nvim/lua/plugins/doc.lua new file mode 100644 index 0000000..5843260 --- /dev/null +++ b/.config/nvim/lua/plugins/doc.lua @@ -0,0 +1,77 @@ +return { + -- markdown + { + "ixru/nvim-markdown", + ft = { "markdown" }, + }, + + -- glow preview + { + "0x00-ketsu/markdown-preview.nvim", + keys = { + { "cm", "lua require('markdown-preview')MPToggle", desc = "[M]arkdown preview" }, + }, + opts = {}, + }, + + -- qalc + { + "Apeiros-46B/qalc.nvim", + event = "BufEnter *.qalc", + cmd = { "QalcAttach", "QalcYank" }, + keys = { + { "cqa", "QalcAttach", desc = "Attach Calculator" }, + { "cqy", "QalcYank", desc = "Yank Result" }, + }, + opts = { + cmd_args = {}, -- table + bufname = '', -- string + set_ft = 'config', -- string + attach_extension = '*.qalc', -- string + sign = ' ==> ', -- string + show_sign = true, -- boolean + right_align = true, -- boolean + highlights = { + sign = '@comment', -- sign before result + result = '@string', -- result in virtual text + }, + diagnostics = { -- table + underline = false, + virtual_text = false, + signs = true, + update_in_insert = true, + severity_sort = true, + } + } + }, + + -- vimtex + snippets + { + "lervag/vimtex", + ft = "tex", + dependencies = { + { + "iurimateus/luasnip-latex-snippets.nvim", + dependencies = "L3MON4D3/LuaSnip", + config = function() + require("luasnip-latex-snippets").setup() + -- or setup({ use_treesitter = true }) + require("luasnip").config.setup({ enable_autosnippets = true }) + end, + }, + }, + keys = { + { "cc", "VimtexCompile", desc = "[C]ompile latex" }, + { "co", "VimtexCompileOutput", desc = "Show latex compiler output" }, + }, + config = function() + vim.g.vimtex_view_general_viewer = "zathura" + -- vim.g.vimtex_view_general_options = [[--unique file:@pdf\#src:@line@tex]] + -- vim.g.vimtex_quickfix_enabled = 1 + vim.g.vimtex_syntax_enabled = 1 + vim.g.vimtex_quickfix_mode = 0 + vim.g.vimtex_compiler_method = "tectonic" + -- vim.cmd("call vimtex#init()") + end, + }, +} diff --git a/.config/nvim/lua/plugins/editor.lua b/.config/nvim/lua/plugins/editor.lua new file mode 100644 index 0000000..aef792e --- /dev/null +++ b/.config/nvim/lua/plugins/editor.lua @@ -0,0 +1,539 @@ +return { + -- project management + { + "ahmedkhalf/project.nvim", + event = "VeryLazy", + keys = { + { + "\\p", + function() + local contents = require("project_nvim").get_recent_projects() + local reverse = {} + for i = #contents, 1, -1 do + reverse[#reverse + 1] = contents[i] + end + require("fzf-lua").fzf_exec(reverse, { + actions = { + ["default"] = function(e) + -- vim.cmd.cd(e[1]) + require("fzf-lua").files({ cwd = e[1] }) + end, + ["ctrl-d"] = function(x) + local choice = vim.fn.confirm("Delete '" .. #x .. "' projects? ", "&Yes\n&No", 2) + if choice == 1 then + local history = require("project_nvim.utils.history") + for _, v in ipairs(x) do + history.delete_project(v) + end + end + end, + }, + winopts = { + height = 0.3, + width = 0.5, + }, + }) + end, + desc = "Projects" + }, + }, + config = function() + require("project_nvim").setup { + patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json", "tex" }, + } + end, + }, + + -- harpoon + { + "ThePrimeagen/harpoon", + branch = "harpoon2", + dependencies = { "nvim-lua/plenary.nvim" }, + keys = { + { "a", function() require("harpoon"):list():add() end, desc = "Add to list" }, + { "h", function() require("harpoon").ui:toggle_quick_menu(require("harpoon"):list()) end, desc = "harpoon ui" }, + { "1", function() require("harpoon"):list():select(1) end, desc = "Harpoon Select 1" }, + { "2", function() require("harpoon"):list():select(2) end, desc = "Harpoon Select 2" }, + { "3", function() require("harpoon"):list():select(3) end, desc = "Harpoon Select 3" }, + { "4", function() require("harpoon"):list():select(4) end, desc = "Harpoon Select 4" }, + { "5", function() require("harpoon"):list():select(5) end, desc = "Harpoon Select 5" }, + { "6", function() require("harpoon"):list():select(6) end, desc = "Harpoon Select 6" }, + { "7", function() require("harpoon"):list():select(7) end, desc = "Harpoon Select 7" }, + { "8", function() require("harpoon"):list():select(8) end, desc = "Harpoon Select 8" }, + { "9", function() require("harpoon"):list():select(9) end, desc = "Harpoon Select 9" }, + }, + config = function() + require("harpoon"):setup() + end + }, + + -- vim-be-good game + { + "theprimeagen/vim-be-good", + dependencies = { + "nvim-lua/plenary.nvim" + }, + config = function() + end + }, + + -- todo-comments + { + "folke/todo-comments.nvim", + dependencies = "nvim-lua/plenary.nvim", + cmd = { "TodoTrouble" }, + event = "VeryLazy", + config = true, + -- stylua: ignore + keys = { + { "]t", function() require("todo-comments").jump_next() end, desc = "Next Todo Comment" }, + { "[t", function() require("todo-comments").jump_prev() end, desc = "Previous Todo Comment" }, + { "xt", "TodoTrouble", desc = "Todo (Trouble)" }, + { "xT", "TodoTrouble keywords=TODO,FIX,FIXME", desc = "Todo/Fix/Fixme (Trouble)" }, + -- { "st", "TodoTelescope", desc = "Todo" }, + -- { "sT", "TodoTelescope keywords=TODO,FIX,FIXME", desc = "Todo/Fix/Fixme" }, + }, + }, + + -- trouble + { + "folke/trouble.nvim", + cmd = { "TroubleToggle", "Trouble" }, + opts = { use_diagnostic_signs = true }, + keys = { + { "xx", "TroubleToggle document_diagnostics", desc = "Document Diagnostics (Trouble)" }, + { "xX", "TroubleToggle workspace_diagnostics", desc = "Workspace Diagnostics (Trouble)" }, + { "xL", "TroubleToggle loclist", desc = "Location List (Trouble)" }, + { "xQ", "TroubleToggle quickfix", desc = "Quickfix List (Trouble)" }, + { + "[q", + function() + if require("trouble").is_open() then + require("trouble").previous({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cprev) + if not ok then + vim.notify(err, vim.log.levels.ERROR) + end + end + end, + desc = "Previous Trouble/Quickfix Item", + }, + { + "]q", + function() + if require("trouble").is_open() then + require("trouble").next({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cnext) + if not ok then + vim.notify(err, vim.log.levels.ERROR) + end + end + end, + desc = "Next Trouble/Quickfix Item", + }, + }, + }, + + -- spectre + { + "nvim-pack/nvim-spectre", + build = false, + cmd = "Spectre", + opts = { open_cmd = "noswapfile vnew" }, + -- stylua: ignore + keys = { + { "sr", function() require("spectre").open() end, desc = "Replace in Files (Spectre)" }, + }, + }, + + -- sessions + { + "folke/persistence.nvim", + event = "BufReadPre", + opts = { options = vim.opt.sessionoptions:get() }, + -- stylua: ignore + keys = { + { "qs", function() require("persistence").load() end, desc = "Restore Session" }, + { "ql", function() require("persistence").load({ last = true }) end, desc = "Restore Last Session" }, + { "qd", function() require("persistence").stop() end, desc = "Don't Save Current Session" }, + }, + }, + + -- illuminate + { + "RRethy/vim-illuminate", + event = "VeryLazy", + opts = { + delay = 200, + large_file_cutoff = 2000, + large_file_overrides = { + providers = { "lsp" }, + }, + filetypes_denylist = { + "alpha", + "help", + "lazy", + "mason", + "outline", + "toggleterm", + "fzf", + "lspinfo", + "null-ls-info", + }, + }, + config = function(_, opts) + require("illuminate").configure(opts) + + local function map(key, dir, buffer) + vim.keymap.set("n", key, function() + require("illuminate")["goto_" .. dir .. "_reference"](false) + end, { desc = dir:sub(1, 1):upper() .. dir:sub(2) .. " Reference", buffer = buffer }) + end + + map("]]", "next") + map("[[", "prev") + + -- also set it after loading ftplugins, since a lot overwrite [[ and ]] + vim.api.nvim_create_autocmd("FileType", { + callback = function() + local buffer = vim.api.nvim_get_current_buf() + map("]]", "next", buffer) + map("[[", "prev", buffer) + end, + }) + end, + keys = { + { "]]", desc = "Next Reference" }, + { "[[", desc = "Prev Reference" }, + }, + }, + + -- symbols sidebar + { + "hedyhli/outline.nvim", + lazy = true, + cmd = { "Outline", "OutlineOpen" }, + keys = { + { "cn", "Outline", desc = "Toggle outline" }, + }, + opts = { + outline_window = { + focus_on_open = false, + }, + }, + }, + + -- folds + { + "kevinhwang91/nvim-ufo", + dependencies = "kevinhwang91/promise-async", + event = "VeryLazy", + opts = {}, + }, + + -- comments + { + "numToStr/Comment.nvim", + dependencies = { + { "nvim-treesitter/nvim-treesitter" }, + { + "JoosepAlviste/nvim-ts-context-commentstring", + config = function() + require("ts_context_commentstring").setup({ + enable_autocmd = false, + }) + vim.g.skip_ts_context_commentstring_module = true + end, + }, + }, + config = function() + require("Comment").setup({ + pre_hook = require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook(), + }) + end, + keys = { + { "gcc", mode = "n", desc = "Comment toggle current line" }, + { "gc", mode = { "n", "o" }, desc = "Comment toggle linewise" }, + { "gc", mode = "x", desc = "Comment toggle linewise (visual)" }, + { "gbc", mode = "n", desc = "Comment toggle current block" }, + { "gb", mode = { "n", "o" }, desc = "Comment toggle blockwise" }, + { "gb", mode = "x", desc = "Comment toggle blockwise (visual)" }, + }, + }, + + -- surround + { + "echasnovski/mini.surround", + event = "VeryLazy", + opts = { + mappings = { + add = "gza", -- Add surrounding in Normal and Visual modes + delete = "gzd", -- Delete surrounding + find = "gzf", -- Find surrounding (to the right) + find_left = "gzF", -- Find surrounding (to the left) + highlight = "gzh", -- Highlight surrounding + replace = "gzr", -- Replace surrounding + update_n_lines = "gzn", -- Update `n_lines` + }, + }, + }, + + -- whichkey + { + "folke/which-key.nvim", + event = "VeryLazy", + keys = { "", "", " ", "'", "`", "g", "c", "v", "z", "[", "]", "" }, + cmd = "WhichKey", + opts = {}, + }, + + -- autopairs + { + "windwp/nvim-autopairs", + event = "InsertEnter", + opts = { + ignored_next_char = "[%w%.]", + }, + }, + + -- leap + { + "ggandor/leap.nvim", + enabled = true, + dependencies = { + { + "ggandor/flit.nvim", + enabled = true, + keys = function() + local ret = {} + for _, key in ipairs({ "f", "F", "t", "T" }) do + ret[#ret + 1] = { key, mode = { "n", "x", "o" }, desc = key } + end + return ret + end, + opts = { labeled_modes = "nx" }, + }, + { "tpope/vim-repeat" }, + }, + keys = { + { "s", mode = { "n", "x", "o" }, desc = "Leap Forward to" }, + { "S", mode = { "n", "x", "o" }, desc = "Leap Backward to" }, + { "gs", mode = { "n", "x", "o" }, desc = "Leap from Windows" }, + }, + config = function(_, opts) + local leap = require("leap") + for k, v in pairs(opts) do + leap.opts[k] = v + end + leap.add_default_mappings(true) + vim.keymap.del({ "x", "o" }, "x") + vim.keymap.del({ "x", "o" }, "X") + vim.api.nvim_set_hl(0, "LeapBackdrop", { link = "Comment" }) + vim.api.nvim_set_hl(0, "LeapMatch", { fg = "white", bold = true, nocombine = true }) + vim.api.nvim_set_hl(0, "LeapLabelPrimary", { fg = "#f02077", bold = true, nocombine = true }) + vim.api.nvim_set_hl(0, "LeapLabelSecondary", { fg = "#99ddff", bold = true, nocombine = true }) + end, + }, + + -- colorizer + { + "NvChad/nvim-colorizer.lua", + event = "VeryLazy", + opts = { + user_default_options = { + css = true, + RRGGBBAA = true, + AARRGGBB = true, + names = false, + RGB = false, + }, + }, + }, + + -- file manager + { + "lmburns/lf.nvim", + dependencies = { "nvim-lua/plenary.nvim", "akinsho/toggleterm.nvim" }, + opts = { + winblend = 0, + highlights = { NormalFloat = { guibg = "NONE" } }, + border = "rounded", + escape_quit = true, + }, + keys = { + { "", "lua require('lf').start()", desc = "Lf file manager" }, + }, + }, + + { + "mikavilpas/yazi.nvim", + enabled = false, + dependencies = { + "nvim-lua/plenary.nvim", + }, + event = "VeryLazy", + keys = { + { + "", + function() + require("yazi").yazi() + end, + { desc = "Open the file manager" }, + }, + }, + opts = { + open_for_directories = true, + }, + }, + + -- gitsigns + { + "lewis6991/gitsigns.nvim", + init = function() + -- load gitsigns only when a git file is opened + vim.api.nvim_create_autocmd({ "BufRead" }, { + group = vim.api.nvim_create_augroup("GitSignsLazyLoad", { clear = true }), + callback = function() + vim.fn.system("git -C " .. '"' .. vim.fn.expand("%:p:h") .. '"' .. " rev-parse") + if vim.v.shell_error == 0 then + vim.api.nvim_del_augroup_by_name("GitSignsLazyLoad") + vim.schedule(function() + require("lazy").load({ plugins = { "gitsigns.nvim" } }) + end) + end + end, + }) + end, + opts = { + signs = { + add = { text = "▎" }, + change = { text = "▎" }, + delete = { text = "" }, + topdelete = { text = "" }, + changedelete = { text = "▎" }, + untracked = { text = "▎" }, + }, + on_attach = function(buffer) + local gs = package.loaded.gitsigns + + local function map(mode, l, r, desc) + vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc }) + end + -- stylua: ignore start + map("n", "]h", gs.next_hunk, "Next Hunk") + map("n", "[h", gs.prev_hunk, "Prev Hunk") + map({ "n", "v" }, "ghs", ":Gitsigns stage_hunk", "Stage Hunk") + map({ "n", "v" }, "ghr", ":Gitsigns reset_hunk", "Reset Hunk") + map("n", "ghS", gs.stage_buffer, "Stage Buffer") + map("n", "ghu", gs.undo_stage_hunk, "Undo Stage Hunk") + map("n", "ghR", gs.reset_buffer, "Reset Buffer") + map("n", "ghp", gs.preview_hunk_inline, "Preview Hunk Inline") + map("n", "ghb", function() gs.blame_line({ full = true }) end, "Blame Line") + map("n", "ghd", gs.diffthis, "Diff This") + map("n", "ghD", function() gs.diffthis("~") end, "Diff This ~") + map({ "o", "x" }, "ih", ":Gitsigns select_hunk", "GitSigns Select Hunk") + end, + }, + }, + + -- undotree sidebar + { + "jiaoshijie/undotree", + dependencies = "nvim-lua/plenary.nvim", + config = true, + keys = { -- load the plugin only when using it's keybinding: + { "u", "lua require('undotree').toggle()" }, + }, + }, + + -- terminal + { + "akinsho/toggleterm.nvim", + cmd = { "ToggleTerm" }, + opts = {}, + keys = { + { "t", "ToggleTerm direction=vertical", desc = "Open terminal" }, + { + "gg", + "lua _LAZYGIT_TOGGLE()", + desc = "Toggle Lazy[G]it", + silent = true, + noremap = true, + }, + { + "p", + ":lua RUN_CODE()", + desc = "Run [P]roject", + silent = true, + noremap = true, + }, + }, + config = function() + require("toggleterm").setup({ + size = function(term) + if term.direction == "horizontal" then + return 15 + elseif term.direction == "vertical" then + return vim.o.columns * 0.45 + end + end, + }) + local run_command_table = { + ["cpp"] = "([[ -f Makefile ]] && make all run)", + ["c"] = "gcc -g -Wall % -o %:r && ./%:r", + ["python"] = "python %", + ["lua"] = "lua %", + ["zsh"] = "zsh %", + ["sh"] = "sh %", + -- ["java"] = "cd %:h && javac *.java && java %:t:r", + -- ["asm"] = "nasm -f elf64 % -o %:r.o && ld %:r.o -o %:r && ./%:r && rm %:r.o", + -- ["cpp"] = "g++ -g -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion -Werror -std=c++20 -pedantic-errors % -o %:r && ./%:r", + -- ["rust"] = "rustc % && ./%:r", + -- ["go"] = "go run %", + -- ["javascript"] = "node %", + } + + local extra = 'printf "\\\\n\\\\033[0;33mPress ENTER to continue \\\\033[0m"; read' + local Terminal = require("toggleterm.terminal").Terminal + + function EXPAND_SYMBOL_RESOLVER(cmd) + local mod = string.byte("%") + local space = string.byte(" ") + local col = string.byte(":") + local i = 1 + local expanded_cmd = "" + while i <= #cmd do + if cmd:byte(i) == mod then + local j = i + 1 + while cmd:byte(j) == col and cmd:byte(j + 1) ~= space and j <= #cmd do + j = j + 2 + end + expanded_cmd = expanded_cmd .. vim.fn.expand(string.sub(cmd, i, j - 1)) + i = j + end + expanded_cmd = expanded_cmd .. string.sub(cmd, i, i) + i = i + 1 + end + + return expanded_cmd + end + + function RUN_CODE() + if run_command_table[vim.bo.filetype] then + local expanded_cmd = EXPAND_SYMBOL_RESOLVER(run_command_table[vim.bo.filetype]) + local runcmd = expanded_cmd .. "; " .. extra + local runterm = Terminal:new({ cmd = runcmd, direction = "vertical" }) + runterm:toggle() + else + print("\nFileType not supported\n") + end + end + + function _LAZYGIT_TOGGLE() + Terminal:new({ cmd = "lazygit", hidden = true, direction = "float" }):toggle() + end + end, + }, +} diff --git a/.config/nvim/lua/plugins/fzf.lua b/.config/nvim/lua/plugins/fzf.lua new file mode 100644 index 0000000..1809cc9 --- /dev/null +++ b/.config/nvim/lua/plugins/fzf.lua @@ -0,0 +1,31 @@ +return { + -- fzf + { + "ibhagwan/fzf-lua", + keys = { + { "/", function() require("fzf-lua").buffers() end, desc = "Switch buffers" }, + { "l", function() require("fzf-lua").live_grep_native() end, desc = "Live Grep" }, + { "o", function() require("fzf-lua").oldfiles() end, desc = "Open Recent file" }, + { "b", function() require("fzf-lua").builtin() end, desc = "FZF menu" }, + { "ca", function() require("fzf-lua").lsp_code_actions() end, mode = { "n", "v" }, desc = "LSP Code Actions" }, + { "cd", function() require("fzf-lua").lsp_definitions() end, mode = { "n", "v" }, desc = "LSP Definitions" }, + { "cD", function() require("fzf-lua").lsp_declarations() end, mode = { "n", "v" }, desc = "LSP Declarations" }, + { "cI", function() require("fzf-lua").lsp_implementations() end, mode = { "n", "v" }, desc = "LSP Implementations" }, + { "cr", function() require("fzf-lua").lsp_references() end, mode = { "n", "v" }, desc = "LSP References" }, + { "ce", function() require("fzf-lua").lsp_document_diagnostics() end, desc = "LSP Diagnostics" }, + { "cwe", function() require("fzf-lua").lsp_workspace_diagnostics() end, desc = "LSP Workspace Diagnostics" }, + { "cD", function() require("fzf-lua").lsp_declarations() end, mode = { "n", "v" }, desc = "LSP Declarations" }, + }, + opts = { + previewers = { + builtin = { + extensions = { + ["png"] = { "ueberzug" }, + ["jpg"] = { "ueberzug" }, + }, + ueberzug_scaler = "cover", + } + } + } + } +} diff --git a/.config/nvim/lua/plugins/lsp.lua b/.config/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..6428764 --- /dev/null +++ b/.config/nvim/lua/plugins/lsp.lua @@ -0,0 +1,186 @@ +return { + { + "VonHeikemen/lsp-zero.nvim", + branch = "v3.x", + lazy = true, + config = false, + init = function() + vim.g.lsp_zero_extend_cmp = 0 + vim.g.lsp_zero_extend_lspconfig = 0 + end, + }, + + -- autocompletion + { + "hrsh7th/nvim-cmp", + event = "InsertEnter", + dependencies = { + { "L3MON4D3/LuaSnip" }, + { "hrsh7th/cmp-buffer" }, + { "https://codeberg.org/FelipeLema/cmp-async-path" }, + { "hrsh7th/cmp-nvim-lsp" }, + { "saadparwaiz1/cmp_luasnip" }, + { "rafamadriz/friendly-snippets" }, + { "onsails/lspkind.nvim" }, + { "hrsh7th/cmp-calc" }, + { "f3fora/cmp-spell" }, + { "micangl/cmp-vimtex" }, + { "Jezda1337/nvim-html-css" }, + }, + config = function() + local lsp_zero = require("lsp-zero") + lsp_zero.extend_cmp() + + local cmp = require("cmp") + local cmp_action = lsp_zero.cmp_action() + + -- Lazy load snippets from VSCode + require("luasnip.loaders.from_vscode").lazy_load() + require("luasnip.loaders.from_vscode").lazy_load({ paths = { "./lua/snippets" } }) + + cmp.setup({ + sources = { + { name = "luasnip" }, + { name = "nvim_lsp" }, + { name = "buffer" }, + { name = "async_path" }, + { name = "calc" }, + { name = "html-css" }, + { name = "vimtex" }, + { + name = "spell", + option = { + keep_all_entries = false, + enable_in_context = function() + return true + end, + }, + }, + }, + preselect = "item", + completion = { + completeopt = "menu,menuone,noinsert", + }, + window = { + completion = cmp.config.window.bordered(), + documentation = cmp.config.window.bordered(), + }, + formatting = { + maxwidth = 30, + fields = { "abbr", "kind" }, + format = require("lspkind").cmp_format({ + mode = "symbol_text", + maxwidth = 30, + ellipsis_char = "", + }), + }, + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp_action.luasnip_jump_forward(), + [""] = cmp_action.luasnip_jump_backward(), + [""] = cmp.mapping.confirm({ select = false }), + [""] = cmp_action.luasnip_supertab(), + [""] = cmp_action.luasnip_shift_supertab(), + }), + snippet = { + expand = function(args) + require("luasnip").lsp_expand(args.body) + end, + }, + }) + end, + }, + + -- lsp + { + "neovim/nvim-lspconfig", + cmd = { "LspInfo", "LspInstall", "LspStart" }, + event = { "BufReadPre", "BufNewFile" }, + dependencies = { + { + "williamboman/mason.nvim", + config = true, + }, + { "hrsh7th/cmp-nvim-lsp" }, + { "williamboman/mason-lspconfig.nvim" }, + }, + config = function() + local lsp_zero = require("lsp-zero") + lsp_zero.extend_lspconfig() + + lsp_zero.on_attach(function(client, bufnr) + lsp_zero.default_keymaps({ + buffer = bufnr, + -- exclude = { 'gl', 'K' }, + }) + end) + + lsp_zero.set_sign_icons({ + error = "", + warn = "", + hint = "󰌵", + info = "", + }) + + require("mason-lspconfig").setup({ + ensure_installed = { + "clangd", + "ruff_lsp", + "marksman", + "html", + "cssls", + "lua_ls", + "bashls", + "texlab", + "jsonls", + "eslint", + }, + handlers = { + lsp_zero.default_setup, + lua_ls = function() + require("lspconfig").lua_ls.setup({ + settings = { + Lua = { + workspace = { checkThirdParty = false }, + telemetry = { enable = false }, + }, + }, + }) + end, + clangd = function() + require("lspconfig").clangd.setup({ + capabilities = { offsetEncoding = "utf-16" }, + -- cmd = { + -- "clangd", + -- "--background-index", + -- "--clang-tidy", + -- "--header-insertion=iwyu", + -- "--completion-style=detailed", + -- "--function-arg-placeholders", + -- "--fallback-style=llvm", + -- }, + -- init_options = { + -- usePlaceholders = true, + -- completeUnimported = true, + -- clangdFileStatus = true, + -- }, + }) + end, + -- ltex = function() + -- require("lspconfig").ltex.setup({ + -- settings = { + -- ltex = { + -- language = {"en-US"}, + -- -- dictionary = {":~/.config/nvim/spell/en.utf-8.add"}, + -- disabledRules = { ['en-US'] = { 'MORFOLOGIK_RULE_EN_US' } }, + -- }, + -- }, + -- }) + -- end, + }, + }) + end, + }, +} diff --git a/.config/nvim/lua/plugins/none.lua b/.config/nvim/lua/plugins/none.lua new file mode 100644 index 0000000..c919719 --- /dev/null +++ b/.config/nvim/lua/plugins/none.lua @@ -0,0 +1,45 @@ +return { + +-- formatting and linting + { + "nvimtools/none-ls.nvim", + event = "LspAttach", + opts = function() + local formatting = require("null-ls").builtins.formatting + local lint = require("null-ls").builtins.diagnostics + local code_actions = require("null-ls").builtins.code_actions + -- local actions = require("null-ls").builtins.code_actions + return { + sources = { + -- Linting + lint.cppcheck, -- for c,cpp ( Install manually using pacman ) + lint.proselint, -- for md + lint.stylelint, -- for css + lint.codespell, -- general code spellings + + -- Formatting + formatting.shfmt, -- for sh + formatting.prettier, -- for js, md, html, css`` + + -- Code Actions + code_actions.proselint, + code_actions.gitsigns, + code_actions.refactoring.with({ + filetypes = { + "go", + "javascript", + "lua", + "python", + "typescript", + "c", + "cpp" + } + }), + }, + } + end, + keys = { + { "f", ":lua vim.lsp.buf.format({ timeout_ms = 2000 })", desc = "Format", silent = true }, + }, + } +} diff --git a/.config/nvim/lua/plugins/refactor.lua b/.config/nvim/lua/plugins/refactor.lua new file mode 100644 index 0000000..0fbbd28 --- /dev/null +++ b/.config/nvim/lua/plugins/refactor.lua @@ -0,0 +1,46 @@ +return { + -- refactoring + { + "ThePrimeagen/refactoring.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-treesitter/nvim-treesitter", + }, + event = "LspAttach", + cmd = { "Refactor" }, + config = function() + require("refactoring").setup({ + prompt_func_return_type = { + go = false, + java = false, + + cpp = false, + c = false, + h = false, + hpp = false, + cxx = false, + }, + prompt_func_param_type = { + go = false, + java = false, + + cpp = false, + c = false, + h = false, + hpp = false, + cxx = false, + }, + printf_statements = {}, + print_var_statements = {}, + show_success_message = false, + }) + vim.keymap.set("x", "re", ":Refactor extract ") + vim.keymap.set("x", "rf", ":Refactor extract_to_file ") + vim.keymap.set("x", "rv", ":Refactor extract_var ") + vim.keymap.set({ "n", "x" }, "ri", ":Refactor inline_var") + vim.keymap.set("n", "rI", ":Refactor inline_func") + vim.keymap.set("n", "rb", ":Refactor extract_block") + vim.keymap.set("n", "rbf", ":Refactor extract_block_to_file") + end, + }, +} diff --git a/.config/nvim/lua/plugins/treesitter.lua b/.config/nvim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..0fc8a6e --- /dev/null +++ b/.config/nvim/lua/plugins/treesitter.lua @@ -0,0 +1,105 @@ +return { + -- treesitter + { + "nvim-treesitter/nvim-treesitter", + version = false, + event = { "BufReadPre", "BufNewFile" }, + build = ":TSUpdate", + dependencies = { + "nvim-treesitter/nvim-treesitter-textobjects", + { + "windwp/nvim-ts-autotag", + opts = {}, + }, + }, + config = function() + local treesitter = require("nvim-treesitter.configs") + treesitter.setup({ + highlight = { enable = true, disable = { "latex" } }, + indent = { enable = true }, + ensure_installed = { + "bash", + "html", + "css", + "javascript", + "lua", + "python", + "vim", + "vimdoc", + "yaml", + "json", + "c", + "cpp", + "go", + "rust", + "regex", + "latex", + "bibtex" + }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = "", + node_incremental = "", + scope_incremental = "", + node_decremental = "", + }, + }, + textobjects = { + move = { + enable = true, + goto_next_start = { ["]f"] = "@function.outer", ["]c"] = "@class.outer" }, + goto_next_end = { ["]F"] = "@function.outer", ["]C"] = "@class.outer" }, + goto_previous_start = { ["[f"] = "@function.outer", ["[c"] = "@class.outer" }, + goto_previous_end = { ["[F"] = "@function.outer", ["[C"] = "@class.outer" }, + }, + }, + }) + end, + }, + + -- mini.ai + { + "echasnovski/mini.ai", + -- keys = { + -- { "a", mode = { "x", "o" } }, + -- { "i", mode = { "x", "o" } }, + -- }, + event = "VeryLazy", + opts = function() + local ai = require("mini.ai") + return { + n_lines = 500, + custom_textobjects = { + o = ai.gen_spec.treesitter({ + a = { "@block.outer", "@conditional.outer", "@loop.outer" }, + i = { "@block.inner", "@conditional.inner", "@loop.inner" }, + }, {}), + f = ai.gen_spec.treesitter({ a = "@function.outer", i = "@function.inner" }, {}), + c = ai.gen_spec.treesitter({ a = "@class.outer", i = "@class.inner" }, {}), + t = { "<([%p%w]-)%f[^<%w][^<>]->.-", "^<.->().*()$" }, + d = { "%f[%d]%d+" }, -- digits + e = { -- Word with case + { + "%u[%l%d]+%f[^%l%d]", + "%f[%S][%l%d]+%f[^%l%d]", + "%f[%P][%l%d]+%f[^%l%d]", + "^[%l%d]+%f[^%l%d]", + }, + "^().*()$", + }, + g = function() -- Whole buffer, similar to `gg` and 'G' motion + local from = { line = 1, col = 1 } + local to = { + line = vim.fn.line("$"), + col = math.max(vim.fn.getline("$"):len(), 1), + } + return { from = from, to = to } + end, + u = ai.gen_spec.function_call(), -- u for "Usage" + U = ai.gen_spec.function_call({ name_pattern = "[%w_]" }), -- without dot in function name + }, + } + end, + } +} diff --git a/.config/nvim/lua/plugins/ui.lua b/.config/nvim/lua/plugins/ui.lua new file mode 100644 index 0000000..91bd922 --- /dev/null +++ b/.config/nvim/lua/plugins/ui.lua @@ -0,0 +1,422 @@ +return { + -- colorscheme + { + "folke/tokyonight.nvim", + lazy = false, + priority = 1000, + config = function() + require("tokyonight").setup({ + style = "night", + styles = { + sidebars = "dark", + floats = "dark", + }, + sidebars = { "qf", "help", "Outline" }, + on_colors = function(colors) + colors.bg = "#16161E" + colors.bg_dark = "#0d0d12" + end, + on_highlights = function(hl, colors) + hl.DiagnosticVirtualTextError = { + fg = colors.comment + } + hl.DiagnosticVirtualTextHint = { + fg = colors.comment + } + hl.DiagnosticVirtualTextInfo = { + fg = colors.comment + } + hl.DiagnosticVirtualTextWarn = { + fg = colors.comment + } + end, + }) + vim.cmd.colorscheme("tokyonight") + end, + }, + + -- icons + { + "nvim-tree/nvim-web-devicons", + }, + + -- statusline + { + "nvim-lualine/lualine.nvim", + event = "VeryLazy", + config = function() + local lualine = require("lualine") + local themecolor = require("tokyonight.colors").setup() + local colors = { + bg = "#0d0d12", + fg = themecolor.fg_dark, + yellow = themecolor.yellow, + cyan = themecolor.cyan, + green = themecolor.green, + magenta = themecolor.magenta, + blue = themecolor.blue, + red = themecolor.red, + low = themecolor.terminal_black, + mode = themecolor.terminal_black, + bg2 = "#292e42", + bg3 = "#16161e" + } + local mode_color = { + n = colors.blue, + i = colors.green, + v = colors.magenta, + ["^V"] = colors.magenta, + V = colors.magenta, + c = colors.blue, + no = colors.red, + ic = colors.yellow, + R = colors.red, + Rv = colors.red, + cv = colors.red, + ce = colors.red, + r = colors.blue, + rm = colors.blue, + ["r?"] = colors.blue, + ["!"] = colors.blue, + t = colors.blue, + } + local conditions = { + buffer_not_empty = function() + return vim.fn.empty(vim.fn.expand("%:t")) ~= 1 + end, + hide_in_width = function() + return vim.fn.winwidth(0) > 80 + end, + check_git_workspace = function() + local filepath = vim.fn.expand("%:p:h") + local gitdir = vim.fn.finddir(".git", filepath .. ";") + return gitdir and #gitdir > 0 and #gitdir < #filepath + end, + } + local config = { + options = { + component_separators = "", + section_separators = "", + disabled_filetypes = { "help", "lazy", "mason", "fzf", "lspinfo", "alpha" }, + theme = { + normal = { c = { fg = colors.fg, bg = colors.bg3 } }, + inactive = { c = { fg = colors.fg, bg = colors.bg3 } }, + }, + }, + sections = { + lualine_a = {}, + lualine_b = {}, + lualine_y = {}, + lualine_z = {}, + lualine_c = {}, + lualine_x = {}, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_y = {}, + lualine_z = {}, + lualine_c = {}, + lualine_x = {}, + }, + } + local function ins_left(component) + table.insert(config.sections.lualine_c, component) + end + local function ins_right(component) + table.insert(config.sections.lualine_x, component) + end + ins_left({ + function() + return "" + end, + color = { fg = colors.bg2, bg = colors.bg3 }, + padding = { left = 0, right = 0 }, + }) + ins_left({ + function() + return " " + -- return " " + -- return " " + end, + color = function() + return { fg = mode_color[vim.fn.mode()], bg = colors.bg2 } + end, + padding = { left = 0, right = 0 }, + }) + ins_left({ + function() + return "" + end, + color = { fg = colors.bg2 }, + padding = { left = 0, right = 1 }, + }) + ins_left({ + "buffers", + buffers_color = { + active = { fg = colors.magenta, bg = colors.bg3 }, + inactive = { fg = colors.low, bg = colors.bg3 }, + }, + symbols = { + modified = " ●", + alternate_file = "", + }, + cond = conditions.buffer_not_empty, + color = { fg = colors.magenta, gui = "bold" }, + }) + ins_right({ + function() + if vim.bo.filetype == "txt" or vim.bo.filetype == "markdown" or vim.bo.filetype == "tex" then + if vim.fn.wordcount().visual_words == 1 then + return tostring(vim.fn.wordcount().visual_words) .. " word" + elseif not (vim.fn.wordcount().visual_words == nil) then + return tostring(vim.fn.wordcount().visual_words) .. " words" + else + return tostring(vim.fn.wordcount().words) .. " words" + end + else + return "" + end + end, + color = { fg = colors.low }, + }) + ins_right({ + -- Lsp server name + function() + local msg = "Inactive" + local buf_ft = vim.api.nvim_buf_get_option(0, "filetype") + local clients = vim.lsp.get_active_clients() + if next(clients) == nil then + return msg + end + for _, client in ipairs(clients) do + local filetypes = client.config.filetypes + if filetypes and vim.fn.index(filetypes, buf_ft) ~= -1 then + return client.name + end + end + return msg + end, + icon = " ", + color = { fg = colors.low }, + }) + ins_right({ + "branch", + icon = "", + color = { fg = colors.low, gui = "bold" }, + }) + ins_right({ + "diff", + symbols = { added = " ", modified = " ", removed = " " }, + diff_color = { + added = { fg = colors.low }, + modified = { fg = colors.low }, + removed = { fg = colors.low }, + }, + cond = conditions.hide_in_width, + }) + ins_right({ + "location", + color = function() + return { fg = mode_color[vim.fn.mode()] } + end, + padding = { left = 0, right = 1 }, + }) + ins_right({ + function() + return "" + end, + color = { fg = colors.bg2 }, + padding = { left = 0, right = 0 }, + }) + ins_right({ + "progress", + color = function() + return { fg = mode_color[vim.fn.mode()], bg = colors.bg2, gui = "bold" } + end, + padding = { left = 0, right = 0 }, + }) + ins_right({ + function() + return "" + end, + color = { fg = colors.bg2, bg = colors.bg3 }, + padding = { left = 0, right = 0 }, + }) + lualine.setup(config) + end, + }, + + -- indentation lines + { + "lukas-reineke/indent-blankline.nvim", + main = "ibl", + event = "VeryLazy", + opts = { + -- scope = { enabled = false }, + scope = { enabled = true }, + exclude = { + filetypes = { "help", "lazy", "mason", "outline", "toggleterm", "fzf", "lspinfo" }, + }, + }, + }, + + -- dashboard + { + "goolord/alpha-nvim", + event = "VimEnter", + config = function() + local dashboard = require("alpha.themes.dashboard") + + local create_gradient = function(start, finish, steps) + local r1, g1, b1 = + tonumber("0x" .. start:sub(2, 3)), + tonumber("0x" .. start:sub(4, 5)), + tonumber("0x" .. start:sub(6, 7)) + local r2, g2, b2 = + tonumber("0x" .. finish:sub(2, 3)), + tonumber("0x" .. finish:sub(4, 5)), + tonumber("0x" .. finish:sub(6, 7)) + + local r_step = (r2 - r1) / steps + local g_step = (g2 - g1) / steps + local b_step = (b2 - b1) / steps + + local gradient = {} + for i = 1, steps do + local r = math.floor(r1 + r_step * i) + local g = math.floor(g1 + g_step * i) + local b = math.floor(b1 + b_step * i) + table.insert(gradient, string.format("#%02x%02x%02x", r, g, b)) + end + + return gradient + end + + local function apply_gradient_hl(text) + local gradient = create_gradient("#7aa2f7", "#414868", #text) + + local lines = {} + for i, line in ipairs(text) do + local tbl = { + type = "text", + val = line, + opts = { + hl = "HeaderGradient" .. i, + shrink_margin = false, + position = "center", + }, + } + table.insert(lines, tbl) + + -- create hl group + vim.api.nvim_set_hl(0, "HeaderGradient" .. i, { fg = gradient[i] }) + end + + return { + type = "group", + val = lines, + opts = { position = "center" }, + } + end + + local headers = require("ascii") + + dashboard.section.buttons.val = { + dashboard.button("r", " Recent files", ":lua require('fzf-lua').oldfiles()"), + dashboard.button("e", " New file", ":ene startinsert "), + dashboard.button("p", " Projects", + function() + local contents = require("project_nvim").get_recent_projects() + local reverse = {} + for i = #contents, 1, -1 do + reverse[#reverse + 1] = contents[i] + end + require("fzf-lua").fzf_exec(reverse, { + actions = { + ["default"] = function(e) + -- vim.cmd.cd(e[1]) + require("fzf-lua").files({ cwd = e[1] }) + end, + ["ctrl-d"] = function(x) + local choice = vim.fn.confirm("Delete '" .. #x .. "' projects? ", "&Yes\n&No", 2) + if choice == 1 then + local history = require("project_nvim.utils.history") + for _, v in ipairs(x) do + history.delete_project(v) + end + end + end, + }, + winopts = { + height = 0.3, + width = 0.5, + }, + }) + end), + + dashboard.button("f", " Find file", ":lua require('fzf-lua').files()"), + dashboard.button("t", "󱎸 Find text", ":lua require('fzf-lua').live_grep_native()"), + dashboard.button("s", " Restore Session", ":lua require('persistence').load()"), + dashboard.button("n", "󰠮 Notes", ":lua require('fzf-lua').files({cwd =[[~/notes]]})"), + dashboard.button("c", " Configuration", ":e $MYVIMRC "), + dashboard.button("z", "󰒲 Lazy", ":Lazy"), + dashboard.button("q", " Quit Neovim", ":qa"), + } + dashboard.section.buttons.opts.spacing = 0 + + vim.api.nvim_create_autocmd("User", { + pattern = "LazyVimStarted", + callback = function() + local stats = require("lazy").stats() + local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100) + dashboard.section.footer.val = "󱎫 " .. ms .. " ms" + pcall(vim.cmd.AlphaRedraw) + end, + }) + + local headerKeys = {} + for key, _ in pairs(headers) do + table.insert(headerKeys, key) + end + local randomHeader = headerKeys[math.random(#headerKeys)] + + dashboard.config.layout = { + { type = "padding", val = 3 }, + -- options = randomHeader, raven, yggdrasil, + -- void_stranger, aot, meatboy, isaac, gta, + -- hydra, spider, morse, sharp, galaxy, + apply_gradient_hl(headers[randomHeader]), + { type = "padding", val = 4 }, + dashboard.section.buttons, + { type = "padding", val = 4 }, + dashboard.section.footer, + } + + dashboard.opts.opts.noautocmd = true + require("alpha").setup(dashboard.opts) + end, + }, + + -- zen-mode + { + "folke/zen-mode.nvim", + opts = { + window = { + backdrop = 0, + width = 100, + height = 0.85, + }, + plugins = { + gitsigns = { enabled = false }, + kitty = { + enabled = true, + font = "+2", + }, + }, + }, + keys = { + { "z", ":lua require('zen-mode').toggle()", desc = "[Z]en Mode", silent = true }, + }, + }, +} diff --git a/.config/nvim/lua/snippets/global.json b/.config/nvim/lua/snippets/global.json new file mode 100644 index 0000000..d2c7b31 --- /dev/null +++ b/.config/nvim/lua/snippets/global.json @@ -0,0 +1,34 @@ +{ + "Print Name and Date": { + "prefix": "signature", + "body": ["${0:Author}", "${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}"], + "description": "Signature" + }, + "MIT": { + "prefix": "mitl", + "description": "MIT License", + "body": [ + "The MIT License (MIT)", + "", + "Copyright (c) ${CURRENT_YEAR} ${0:Author}", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and associated documentation files (the \"Software\"), to deal", + "in the Software without restriction, including without limitation the rights", + "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell", + "copies of the Software, and to permit persons to whom the Software is", + "furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all", + "copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,", + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE", + "SOFTWARE." + ] + } +} diff --git a/.config/nvim/lua/snippets/package.json b/.config/nvim/lua/snippets/package.json new file mode 100644 index 0000000..52e7911 --- /dev/null +++ b/.config/nvim/lua/snippets/package.json @@ -0,0 +1,21 @@ +{ + "name": "user snippets", + "engines": { + "vscode": "^1.11.0" + }, + "contributes": { + "snippets": [ + { + "language": [ + "plaintext", + "markdown", + "tex", + "html", + "global", + "all" + ], + "path": "./global.json" + } + ] + } +} diff --git a/.config/shell/aliasrc b/.config/shell/aliasrc new file mode 100644 index 0000000..ddb7538 --- /dev/null +++ b/.config/shell/aliasrc @@ -0,0 +1,50 @@ +#!/bin/sh + +# Use neovim for vim if present. +[ -x "$(command -v nvim)" ] && alias vim="nvim" vimdiff="nvim -d" + +# Use $XINITRC variable if file exists. +[ -f "$XINITRC" ] && alias startx="startx \$XINITRC" + +alias svn="svn --config-dir \"$XDG_CONFIG_HOME\"/subversion" + +# sudo not required for some system commands +for command in mount umount pacman updatedb su shutdown poweroff reboot; do + alias $command="sudo $command" +done +unset command + +alias \ + be="fzf-fd \$HOME/.local/bin | xargs nvim" \ + yy="yazi" \ + ce="fzf-fd \$HOME/.config | xargs nvim" \ + cg="fzf-grep \$HOME/.config" \ + fe="fzf-fd \$(pwd) | xargs nvim" \ + fg="fzf-grep \$(pwd)" \ + cp="cp -iv" \ + mv="mv -iv" \ + rm="rm -vI" \ + ka="killall" \ + g="git" \ + sdn="shutdown -h now" \ + v="\$EDITOR" \ + p="pacman" \ + z="zathura" \ + x="exit" \ + mkd="mkdir -pv" \ + ls="eza --icons --group-directories-first" \ + lss="lsd -lt --total-size --group-directories-first" \ + lsa="eza -a --icons --group-directories-first" \ + lsas="lsd -lAt --total-size --group-directories-first" \ + lst="eza -T --icons" \ + grep="grep --color=auto" \ + diff="diff --color=auto" \ + ccat="highlight --out-format=ansi" \ + ip="ip -color=auto" \ + cat="bat -pp" \ + yt="yt-dlp --embed-metadata -i" \ + yta="yt -x -f bestaudio/best" \ + ffmpeg="ffmpeg -hide_banner" \ + ref="shortcuts >/dev/null; source \${XDG_CONFIG_HOME:-\$HOME/.config}/shell/shortcutrc ; source \${XDG_CONFIG_HOME:-\$HOME/.config}/shell/zshnameddirrc" \ + weath="curl wttr.in | head -n -1 | cat" \ + weath2="curl v2.wttr.in | head -n -1 | cat" diff --git a/.config/shell/vi.zsh b/.config/shell/vi.zsh new file mode 100644 index 0000000..48d5318 --- /dev/null +++ b/.config/shell/vi.zsh @@ -0,0 +1,9 @@ +echo -ne '\e[3 q' # Use underline shape cursor on startup. +preexec() { echo -ne '\e[3 q' ;} # Use underline shape cursor for each new prompt. + +# Edit line in vim with ctrl-e: +autoload edit-command-line; zle -N edit-command-line +bindkey '^e' edit-command-line +bindkey -M vicmd '^[[P' vi-delete-char +bindkey -M vicmd '^e' edit-command-line +bindkey -M visual '^[[P' vi-delete diff --git a/.config/starship.toml b/.config/starship.toml new file mode 100644 index 0000000..c401434 --- /dev/null +++ b/.config/starship.toml @@ -0,0 +1,13 @@ +[git_branch] +symbol = ' ' + +[git_metrics] +disabled = false +added_style = 'bold blue' +format = '[+$added]($added_style)/[-$deleted]($deleted_style) ' + +[gcloud] +disabled = true + +[battery] +disabled = true diff --git a/.config/suckless/dmenu/LICENSE b/.config/suckless/dmenu/LICENSE new file mode 100644 index 0000000..2a64b28 --- /dev/null +++ b/.config/suckless/dmenu/LICENSE @@ -0,0 +1,30 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2008 Sander van Dijk +© 2006-2007 Michał Janeczek +© 2007 Kris Maglione +© 2009 Gottox +© 2009 Markus Schnalke +© 2009 Evan Gates +© 2010-2012 Connor Lane Smith +© 2014-2022 Hiltjo Posthuma +© 2015-2019 Quentin Rameau + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/.config/suckless/dmenu/Makefile b/.config/suckless/dmenu/Makefile new file mode 100644 index 0000000..c7cdf96 --- /dev/null +++ b/.config/suckless/dmenu/Makefile @@ -0,0 +1,58 @@ +# dmenu - dynamic menu +# See LICENSE file for copyright and license details. + +include config.mk + +SRC = drw.c dmenu.c stest.c util.c +OBJ = $(SRC:.c=.o) + +all: dmenu stest + +.c.o: + $(CC) -c $(CFLAGS) $< + +config.h: + cp config.def.h $@ + +$(OBJ): arg.h config.h config.mk drw.h + +dmenu: dmenu.o drw.o util.o + $(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS) + +stest: stest.o + $(CC) -o $@ stest.o $(LDFLAGS) + +clean: + rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz + +dist: clean + mkdir -p dmenu-$(VERSION) + cp LICENSE Makefile README arg.h config.mk dmenu.1\ + drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\ + dmenu-$(VERSION) + tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION) + gzip dmenu-$(VERSION).tar + rm -rf dmenu-$(VERSION) + +install: all + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu + chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path + chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run + chmod 755 $(DESTDIR)$(PREFIX)/bin/stest + mkdir -p $(DESTDIR)$(MANPREFIX)/man1 + sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 + sed "s/VERSION/$(VERSION)/g" < stest.1 > $(DESTDIR)$(MANPREFIX)/man1/stest.1 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stest.1 + +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\ + $(DESTDIR)$(PREFIX)/bin/dmenu_path\ + $(DESTDIR)$(PREFIX)/bin/dmenu_run\ + $(DESTDIR)$(PREFIX)/bin/stest\ + $(DESTDIR)$(MANPREFIX)/man1/dmenu.1\ + $(DESTDIR)$(MANPREFIX)/man1/stest.1 + +.PHONY: all clean dist install uninstall diff --git a/.config/suckless/dmenu/arg.h b/.config/suckless/dmenu/arg.h new file mode 100644 index 0000000..e94e02b --- /dev/null +++ b/.config/suckless/dmenu/arg.h @@ -0,0 +1,49 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][0] == '-'\ + && argv[0][1];\ + argc--, argv++) {\ + char argc_;\ + char **argv_;\ + int brk_;\ + if (argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + for (brk_ = 0, argv[0]++, argv_ = argv;\ + argv[0][0] && !brk_;\ + argv[0]++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][0];\ + switch (argc_) + +#define ARGEND }\ + } + +#define ARGC() argc_ + +#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#endif diff --git a/.config/suckless/dmenu/config.h b/.config/suckless/dmenu/config.h new file mode 100644 index 0000000..5d1cefe --- /dev/null +++ b/.config/suckless/dmenu/config.h @@ -0,0 +1,39 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */ +static int instant = 0; /* -n option; if 1, selects matching item without the need to press enter */ +static int center = 0; /* -c option; if 0, dmenu won't be centered on the screen */ +static int min_width = 680; /* minimum width when centered */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static char *fonts[] = +{ + "JetBrainsMono Nerd Font Semiblod:size=12" +}; +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ + + +static +char *colors[][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, + [SchemeBorder] = { "#000000", "#005577" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 0; +/* -g option; if nonzero, dmenu uses a grid comprised of columns and lines */ +static unsigned int columns = 0; +static unsigned int lineheight = 0; /* -h option; minimum height of a menu line */ +static unsigned int min_lineheight = 8; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; + +/* Size of the window border */ +static unsigned int border_width = 0; diff --git a/.config/suckless/dmenu/config.mk b/.config/suckless/dmenu/config.mk new file mode 100644 index 0000000..29b96ca --- /dev/null +++ b/.config/suckless/dmenu/config.mk @@ -0,0 +1,42 @@ +# dmenu version +VERSION = 5.2 + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 +# OpenBSD (uncomment) +#FREETYPEINC = $(X11INC)/freetype2 +#MANPREFIX = ${PREFIX}/man + +# uncomment on RHEL for strcasecmp +#EXTRAFLAGS=-D_GNU_SOURCE + +# Uncomment this for the alpha patch / ALPHA_PATCH +XRENDER = -lXrender + +# Uncomment for the pango patch / PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + +# includes and libs +INCS = -I$(X11INC) -I$(FREETYPEINC) ${PANGOINC} +LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm $(XRENDER) ${PANGOLIB} + +# flags +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) $(EXTRAFLAGS) +CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) +LDFLAGS = $(LIBS) + +# compiler and linker +CC = cc diff --git a/.config/suckless/dmenu/dmenu.1 b/.config/suckless/dmenu/dmenu.1 new file mode 100644 index 0000000..323f93c --- /dev/null +++ b/.config/suckless/dmenu/dmenu.1 @@ -0,0 +1,194 @@ +.TH DMENU 1 dmenu\-VERSION +.SH NAME +dmenu \- dynamic menu +.SH SYNOPSIS +.B dmenu +.RB [ \-bfiv ] +.RB [ \-l +.IR lines ] +.RB [ \-m +.IR monitor ] +.RB [ \-p +.IR prompt ] +.RB [ \-fn +.IR font ] +.RB [ \-nb +.IR color ] +.RB [ \-nf +.IR color ] +.RB [ \-sb +.IR color ] +.RB [ \-sf +.IR color ] +.RB [ \-w +.IR windowid ] +.P +.BR dmenu_run " ..." +.SH DESCRIPTION +.B dmenu +is a dynamic menu for X, which reads a list of newline\-separated items from +stdin. When the user selects an item and presses Return, their choice is printed +to stdout and dmenu terminates. Entering text will narrow the items to those +matching the tokens in the input. +.P +.B dmenu_run +is a script used by +.IR dwm (1) +which lists programs in the user's $PATH and runs the result in their $SHELL. +.SH OPTIONS +.TP +.B \-b +dmenu appears at the bottom of the screen. +.TP +.B \-f +dmenu grabs the keyboard before reading stdin if not reading from a tty. This +is faster, but will lock up X until stdin reaches end\-of\-file. +.TP +.B \-i +dmenu matches menu items case insensitively. +.TP +.BI \-l " lines" +dmenu lists items vertically, with the given number of lines. +.TP +.BI \-m " monitor" +dmenu is displayed on the monitor number supplied. Monitor numbers are starting +from 0. +.TP +.BI \-p " prompt" +defines the prompt to be displayed to the left of the input field. +.TP +.BI \-fn " font" +defines the font or font set used. +.TP +.BI \-nb " color" +defines the normal background color. +.IR #RGB , +.IR #RRGGBB , +and X color names are supported. +.TP +.BI \-nf " color" +defines the normal foreground color. +.TP +.BI \-sb " color" +defines the selected background color. +.TP +.BI \-sf " color" +defines the selected foreground color. +.TP +.B \-v +prints version information to stdout, then exits. +.TP +.BI \-w " windowid" +embed into windowid. +.SH USAGE +dmenu is completely controlled by the keyboard. Items are selected using the +arrow keys, page up, page down, home, and end. +.TP +.B Tab +Copy the selected item to the input field. +.TP +.B Return +Confirm selection. Prints the selected item to stdout and exits, returning +success. +.TP +.B Ctrl-Return +Confirm selection. Prints the selected item to stdout and continues. +.TP +.B Shift\-Return +Confirm input. Prints the input text to stdout and exits, returning success. +.TP +.B Escape +Exit without selecting an item, returning failure. +.TP +.B Ctrl-Left +Move cursor to the start of the current word +.TP +.B Ctrl-Right +Move cursor to the end of the current word +.TP +.B C\-a +Home +.TP +.B C\-b +Left +.TP +.B C\-c +Escape +.TP +.B C\-d +Delete +.TP +.B C\-e +End +.TP +.B C\-f +Right +.TP +.B C\-g +Escape +.TP +.B C\-h +Backspace +.TP +.B C\-i +Tab +.TP +.B C\-j +Return +.TP +.B C\-J +Shift-Return +.TP +.B C\-k +Delete line right +.TP +.B C\-m +Return +.TP +.B C\-M +Shift-Return +.TP +.B C\-n +Down +.TP +.B C\-p +Up +.TP +.B C\-u +Delete line left +.TP +.B C\-w +Delete word left +.TP +.B C\-y +Paste from primary X selection +.TP +.B C\-Y +Paste from X clipboard +.TP +.B M\-b +Move cursor to the start of the current word +.TP +.B M\-f +Move cursor to the end of the current word +.TP +.B M\-g +Home +.TP +.B M\-G +End +.TP +.B M\-h +Up +.TP +.B M\-j +Page down +.TP +.B M\-k +Page up +.TP +.B M\-l +Down +.SH SEE ALSO +.IR dwm (1), +.IR stest (1) diff --git a/.config/suckless/dmenu/dmenu.c b/.config/suckless/dmenu/dmenu.c new file mode 100644 index 0000000..d559afa --- /dev/null +++ b/.config/suckless/dmenu/dmenu.c @@ -0,0 +1,1041 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef XINERAMA +#include +#endif +#include + +/* Patch incompatibility overrides */ + +#include "drw.h" +#include "util.h" +#include + +/* macros */ +#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ + * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +/* enums */ +enum { + SchemeNorm, + SchemeSel, + SchemeOut, + SchemeBorder, + SchemeLast, +}; /* color schemes */ + +struct item { + char *text; + char *stext; + struct item *left, *right; + int out; + double distance; +}; + +static char text[BUFSIZ] = ""; +static char *embed; +static int bh, mw, mh; +static int dmx = 0, dmy = 0; /* put dmenu at these x and y offsets */ +static unsigned int dmw = 0; /* make dmenu this wide */ +static int inputw = 0, promptw; +static int passwd = 0; +static int lrpad; /* sum of left and right padding */ +static size_t cursor; +static struct item *items = NULL; +static struct item *matches, *matchend; +static struct item *prev, *curr, *next, *sel; +static int mon = -1, screen; + +static Atom clip, utf8; +static Display *dpy; +static Window root, parentwin, win; +static XIC xic; + + +static Drw *drw; +static Clr *scheme[SchemeLast]; + +#include "patch/include.h" + +#include "config.h" + +static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; +static char *(*fstrstr)(const char *, const char *) = strstr; + +static unsigned int +textw_clamp(const char *str, unsigned int n) +{ + unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad; + return MIN(w, n); +} + +static void appenditem(struct item *item, struct item **list, struct item **last); +static void calcoffsets(void); +static void cleanup(void); +static char * cistrstr(const char *s, const char *sub); +static int drawitem(struct item *item, int x, int y, int w); +static void drawmenu(void); +static void grabfocus(void); +static void grabkeyboard(void); +static void match(void); +static void insert(const char *str, ssize_t n); +static size_t nextrune(int inc); +static void movewordedge(int dir); +static void keypress(XKeyEvent *ev); +static void paste(void); +static void readstdin(void); +static void run(void); +static void setup(void); +static void usage(void); + +#include "patch/include.c" + +static void +appenditem(struct item *item, struct item **list, struct item **last) +{ + if (*last) + (*last)->right = item; + else + *list = item; + + item->left = *last; + item->right = NULL; + *last = item; +} + +static void +calcoffsets(void) +{ + int i, n, rpad = 0; + + if (lines > 0) { + if (columns) + n = lines * columns * bh; + else + n = lines * bh; + } else { + n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">") + rpad); + } + /* calculate which items will begin the next page and previous page */ + for (i = 0, next = curr; next; next = next->right) + if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n) + break; + for (i = 0, prev = curr; prev && prev->left; prev = prev->left) + if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n) + break; +} + +static void +cleanup(void) +{ + size_t i; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for (i = 0; i < SchemeLast; i++) + free(scheme[i]); + for (i = 0; items && items[i].text; ++i) + free(items[i].text); + free(items); + drw_free(drw); + XSync(dpy, False); + XCloseDisplay(dpy); +} + +static char * +cistrstr(const char *s, const char *sub) +{ + size_t len; + + for (len = strlen(sub); *s; s++) + if (!strncasecmp(s, sub, len)) + return (char *)s; + return NULL; +} + +static int +drawitem(struct item *item, int x, int y, int w) +{ + int r; + char *text = item->stext; + + + + if (item == sel) + drw_setscheme(drw, scheme[SchemeSel]); + else if (item->out) + drw_setscheme(drw, scheme[SchemeOut]); + else + drw_setscheme(drw, scheme[SchemeNorm]); + + r = drw_text(drw + , x + , y + , w + , bh + , lrpad / 2 + , text + , 0 + ); + return r; +} + +static void +drawmenu(void) +{ + static int curpos, oldcurlen; + int curlen, rcurlen; + struct item *item; + int x = 0, y = 0, w, rpad = 0, itw = 0, stw = 0; + int fh = drw->fonts->h; + char *censort; + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, 0, 0, mw, mh, 1, 1); + + if (prompt && *prompt) { + drw_setscheme(drw, scheme[SchemeSel]); + x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0 + ); + } + /* draw input field */ + w = (lines > 0 || !matches) ? mw - x : inputw; + + w -= lrpad / 2; + x += lrpad / 2; + rcurlen = TEXTW(text + cursor) - lrpad; + curlen = TEXTW(text) - lrpad - rcurlen; + curpos += curlen - oldcurlen; + curpos = MIN(w, MAX(0, curpos)); + curpos = MAX(curpos, w - rcurlen); + curpos = MIN(curpos, curlen); + oldcurlen = curlen; + + drw_setscheme(drw, scheme[SchemeNorm]); + if (passwd) { + censort = ecalloc(1, sizeof(text)); + memset(censort, '.', strlen(text)); + drw_text_align(drw, x, 0, curpos, bh, censort, cursor, AlignR); + drw_text_align(drw, x + curpos, 0, w - curpos, bh, censort + cursor, strlen(censort) - cursor, AlignL); + free(censort); + } else { + drw_text_align(drw, x, 0, curpos, bh, text, cursor, AlignR); + drw_text_align(drw, x + curpos, 0, w - curpos, bh, text + cursor, strlen(text) - cursor, AlignL); + } + drw_rect(drw, x + curpos - 1, 2 + (bh-fh)/2, 2, fh - 4, 1, 0); + + if (lines > 0) { + /* draw grid */ + int i = 0; + for (item = curr; item != next; item = item->right, i++) + if (columns) + drawitem( + item, + 0 + ((i / lines) * (mw / columns)), + y + (((i % lines) + 1) * bh), + mw / columns + ); + else + drawitem(item, 0, y += bh, mw); + } else if (matches) { + /* draw horizontal list */ + x += inputw; + w = TEXTW("<"); + if (curr->left) { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0 + ); + } + x += w; + for (item = curr; item != next; item = item->right) { + stw = TEXTW(">"); + itw = textw_clamp(item->stext, mw - x - stw - rpad); + x = drawitem(item, x, 0, itw); + } + if (next) { + w = TEXTW(">"); + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, mw - w - rpad, 0, w, bh, lrpad / 2 + , ">" + , 0 + ); + } + } + drw_map(drw, win, 0, 0, mw, mh); +} + +static void +grabfocus(void) +{ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; + Window focuswin; + int i, revertwin; + + for (i = 0; i < 100; ++i) { + XGetInputFocus(dpy, &focuswin, &revertwin); + if (focuswin == win) + return; + XSetInputFocus(dpy, win, RevertToParent, CurrentTime); + nanosleep(&ts, NULL); + } + die("cannot grab focus"); +} + +static void +grabkeyboard(void) +{ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; + int i; + + if (embed) + return; + /* try to grab keyboard, we may have to wait for another process to ungrab */ + for (i = 0; i < 1000; i++) { + if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, + GrabModeAsync, CurrentTime) == GrabSuccess) + return; + nanosleep(&ts, NULL); + } + die("cannot grab keyboard"); +} + +static void +match(void) +{ + + if (fuzzy) { + fuzzymatch(); + return; + } + static char **tokv = NULL; + static int tokn = 0; + + char buf[sizeof text], *s; + int i, tokc = 0; + size_t len, textsize; + struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; + + strcpy(buf, text); + /* separate input text into tokens to be matched individually */ + for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) + if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) + die("cannot realloc %zu bytes:", tokn * sizeof *tokv); + len = tokc ? strlen(tokv[0]) : 0; + + matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; + textsize = strlen(text) + 1; + for (item = items; item && item->text; item++) + { + for (i = 0; i < tokc; i++) + if (!fstrstr(item->text, tokv[i])) + break; + if (i != tokc) /* not all tokens match */ + continue; + /* exact matches go first, then prefixes, then substrings */ + if (!tokc || !fstrncmp(text, item->text, textsize)) + appenditem(item, &matches, &matchend); + else if (!fstrncmp(tokv[0], item->text, len)) + appenditem(item, &lprefix, &prefixend); + else + appenditem(item, &lsubstr, &substrend); + } + if (lprefix) { + if (matches) { + matchend->right = lprefix; + lprefix->left = matchend; + } else + matches = lprefix; + matchend = prefixend; + } + if (lsubstr) + { + if (matches) { + matchend->right = lsubstr; + lsubstr->left = matchend; + } else + matches = lsubstr; + matchend = substrend; + } + curr = sel = matches; + + if (instant && matches && matches==matchend && !lsubstr) { + puts(matches->text); + cleanup(); + exit(0); + } + + calcoffsets(); +} + +static void +insert(const char *str, ssize_t n) +{ + if (strlen(text) + n > sizeof text - 1) + return; + + + /* move existing text out of the way, insert new text, and update cursor */ + memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); + if (n > 0) + memcpy(&text[cursor], str, n); + cursor += n; + match(); + +} + +static size_t +nextrune(int inc) +{ + ssize_t n; + + /* return location of next utf8 rune in the given direction (+1 or -1) */ + for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc) + ; + return n; +} + +static void +movewordedge(int dir) +{ + if (dir < 0) { /* move cursor to the start of the word*/ + while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) + cursor = nextrune(-1); + while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) + cursor = nextrune(-1); + } else { /* move cursor to the end of the word */ + while (text[cursor] && strchr(worddelimiters, text[cursor])) + cursor = nextrune(+1); + while (text[cursor] && !strchr(worddelimiters, text[cursor])) + cursor = nextrune(+1); + } +} + +static void +keypress(XKeyEvent *ev) +{ + char buf[64]; + int len; + KeySym ksym = NoSymbol; + Status status; + int i; + struct item *tmpsel; + bool offscreen = false; + + len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); + switch (status) { + default: /* XLookupNone, XBufferOverflow */ + return; + case XLookupChars: /* composed string from input method */ + goto insert; + case XLookupKeySym: + case XLookupBoth: /* a KeySym and a string are returned: use keysym */ + break; + } + + if (ev->state & ControlMask) { + switch(ksym) { + case XK_a: expect("ctrl-a", ev); ksym = XK_Home; break; + case XK_b: expect("ctrl-b", ev); ksym = XK_Left; break; + case XK_c: expect("ctrl-c", ev); ksym = XK_Escape; break; + case XK_d: expect("ctrl-d", ev); ksym = XK_Delete; break; + case XK_e: expect("ctrl-e", ev); ksym = XK_End; break; + case XK_f: expect("ctrl-f", ev); ksym = XK_Right; break; + case XK_g: expect("ctrl-g", ev); ksym = XK_Escape; break; + case XK_h: expect("ctrl-h", ev); ksym = XK_BackSpace; break; + case XK_i: expect("ctrl-i", ev); ksym = XK_Tab; break; + case XK_j: expect("ctrl-j", ev); ksym = XK_Down; break; + case XK_J:/* fallthrough */ + case XK_l: expect("ctrl-l", ev); break; + case XK_m: expect("ctrl-m", ev); /* fallthrough */ + case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break; + case XK_n: expect("ctrl-n", ev); ksym = XK_Down; break; + case XK_p: expect("ctrl-p", ev); ksym = XK_Up; break; + case XK_o: expect("ctrl-o", ev); break; + case XK_q: expect("ctrl-q", ev); break; + case XK_r: expect("ctrl-r", ev); break; + case XK_s: expect("ctrl-s", ev); break; + case XK_t: expect("ctrl-t", ev); break; + case XK_k: expect("ctrl-k", ev); ksym = XK_Up; break; + case XK_u: expect("ctrl-u", ev); /* delete left */ + insert(NULL, 0 - cursor); + break; + case XK_w: expect("ctrl-w", ev); /* delete word */ + while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + break; + case XK_v: + expect("ctrl-v", ev); + case XK_V: + XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + return; + case XK_y: expect("ctrl-y", ev); /* paste selection */ + case XK_Y: + XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + return; + case XK_x: expect("ctrl-x", ev); break; + case XK_z: expect("ctrl-z", ev); break; + case XK_Left: + case XK_KP_Left: + movewordedge(-1); + goto draw; + case XK_Right: + case XK_KP_Right: + movewordedge(+1); + goto draw; + case XK_Return: + case XK_KP_Enter: + break; + case XK_bracketleft: + cleanup(); + exit(1); + default: + return; + } + } else if (ev->state & Mod1Mask) { + switch(ksym) { + case XK_b: + movewordedge(-1); + goto draw; + case XK_f: + movewordedge(+1); + goto draw; + case XK_g: ksym = XK_Home; break; + case XK_G: ksym = XK_End; break; + case XK_h: ksym = XK_Up; break; + case XK_j: ksym = XK_Next; break; + case XK_k: ksym = XK_Prior; break; + case XK_l: ksym = XK_Down; break; + default: + return; + } + } + + switch(ksym) { + default: +insert: + if (!iscntrl((unsigned char)*buf)) + insert(buf, len); + break; + case XK_Delete: + case XK_KP_Delete: + if (text[cursor] == '\0') + return; + cursor = nextrune(+1); + /* fallthrough */ + case XK_BackSpace: + if (cursor == 0) + return; + insert(NULL, nextrune(-1) - cursor); + break; + case XK_End: + case XK_KP_End: + if (text[cursor] != '\0') { + cursor = strlen(text); + break; + } + if (next) { + /* jump to end of list and position items in reverse */ + curr = matchend; + calcoffsets(); + curr = prev; + calcoffsets(); + while (next && (curr = curr->right)) + calcoffsets(); + } + sel = matchend; + break; + case XK_Escape: + cleanup(); + exit(1); + case XK_Home: + case XK_KP_Home: + if (sel == matches) { + cursor = 0; + break; + } + sel = curr = matches; + calcoffsets(); + break; + case XK_Left: + case XK_KP_Left: + if (columns > 1) { + if (!sel) + return; + tmpsel = sel; + for (i = 0; i < lines; i++) { + if (!tmpsel->left || tmpsel->left->right != tmpsel) + return; + if (tmpsel == curr) + offscreen = true; + tmpsel = tmpsel->left; + } + sel = tmpsel; + if (offscreen) { + curr = prev; + calcoffsets(); + } + break; + } + if (cursor > 0 && (!sel || !sel->left || lines > 0)) { + cursor = nextrune(-1); + break; + } + if (lines > 0) + return; + /* fallthrough */ + case XK_Up: + case XK_KP_Up: + if (sel && sel->left && (sel = sel->left)->right == curr) { + curr = prev; + calcoffsets(); + } + break; + case XK_Next: + case XK_KP_Next: + if (!next) + return; + sel = curr = next; + calcoffsets(); + break; + case XK_Prior: + case XK_KP_Prior: + if (!prev) + return; + sel = curr = prev; + calcoffsets(); + break; + case XK_Return: + case XK_KP_Enter: + puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); + if (!(ev->state & ControlMask)) { + cleanup(); + exit(0); + } + if (sel) + sel->out = 1; + break; + case XK_Right: + case XK_KP_Right: + if (columns > 1) { + if (!sel) + return; + tmpsel = sel; + for (i = 0; i < lines; i++) { + if (!tmpsel->right || tmpsel->right->left != tmpsel) + return; + tmpsel = tmpsel->right; + if (tmpsel == next) + offscreen = true; + } + sel = tmpsel; + if (offscreen) { + curr = next; + calcoffsets(); + } + break; + } + if (text[cursor] != '\0') { + cursor = nextrune(+1); + break; + } + if (lines > 0) + return; + /* fallthrough */ + case XK_Down: + case XK_KP_Down: + if (sel && sel->right && (sel = sel->right) == next) { + curr = next; + calcoffsets(); + } + break; + case XK_Tab: + if (!sel) + return; + cursor = strnlen(sel->text, sizeof text - 1); + memcpy(text, sel->text, cursor); + text[cursor] = '\0'; + match(); + break; + } + +draw: + drawmenu(); +} + +static void +paste(void) +{ + char *p, *q; + int di; + unsigned long dl; + Atom da; + + /* we have been given the current selection, now insert it into input */ + if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, + utf8, &da, &di, &dl, &dl, (unsigned char **)&p) + == Success && p) { + insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); + XFree(p); + } + drawmenu(); +} + + +static void +readstdin(void) +{ + char *line = NULL; + char *buf, *p; + + size_t i, linesiz, itemsiz = 0; + ssize_t len; + + if (passwd) { + inputw = lines = 0; + return; + } + + /* read each line from stdin and add it to the item list */ + for (i = 0; (len = getline(&line, &linesiz, stdin)) != -1; i++) { + if (i + 1 >= itemsiz) { + itemsiz += 256; + if (!(items = realloc(items, itemsiz * sizeof(*items)))) + die("cannot realloc %zu bytes:", itemsiz * sizeof(*items)); + } + if (line[len - 1] == '\n') + line[len - 1] = '\0'; + + if (!(items[i].text = strdup(line))) + die("strdup:"); + if (!(buf = strdup(line))) + die("cannot strdup %u bytes:", strlen(line) + 1); + if ((p = strchr(buf, '\t'))) + *p = '\0'; + items[i].stext = buf; + items[i].out = 0; + + } + free(line); + if (items) + items[i].text = NULL; + lines = MIN(lines, i); +} + +static void +run(void) +{ + XEvent ev; + + while (!XNextEvent(dpy, &ev)) { + if (XFilterEvent(&ev, win)) + continue; + switch(ev.type) { + case ButtonPress: + buttonpress(&ev); + break; + case DestroyNotify: + if (ev.xdestroywindow.window != win) + break; + cleanup(); + exit(1); + case Expose: + if (ev.xexpose.count == 0) + drw_map(drw, win, 0, 0, mw, mh); + break; + case FocusIn: + /* regrab focus from parent window */ + if (ev.xfocus.window != win) + grabfocus(); + break; + case KeyPress: + keypress(&ev.xkey); + break; + case SelectionNotify: + if (ev.xselection.property == utf8) + paste(); + break; + case VisibilityNotify: + if (ev.xvisibility.state != VisibilityUnobscured) + XRaiseWindow(dpy, win); + break; + } + } +} + +static void +setup(void) +{ + int x, y, i, j; + unsigned int du; + XSetWindowAttributes swa; + XIM xim; + Window w, dw, *dws; + XWindowAttributes wa; + XClassHint ch = {"dmenu", "dmenu"}; +#ifdef XINERAMA + XineramaScreenInfo *info; + Window pw; + int a, di, n, area = 0; +#endif + /* init appearance */ + for (j = 0; j < SchemeLast; j++) + scheme[j] = drw_scm_create(drw, (const char**)colors[j], 2); + + clip = XInternAtom(dpy, "CLIPBOARD", False); + utf8 = XInternAtom(dpy, "UTF8_STRING", False); + + /* calculate menu geometry */ + bh = drw->fonts->h + 2; + bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */ + lines = MAX(lines, 0); + mh = (lines + 1) * bh; + promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; +#ifdef XINERAMA + i = 0; + if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { + XGetInputFocus(dpy, &w, &di); + if (mon >= 0 && mon < n) + i = mon; + else if (w != root && w != PointerRoot && w != None) { + /* find top-level window containing current input focus */ + do { + if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) + XFree(dws); + } while (w != root && w != pw); + /* find xinerama screen with which the window intersects most */ + if (XGetWindowAttributes(dpy, pw, &wa)) + for (j = 0; j < n; j++) + if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { + area = a; + i = j; + } + } + /* no focused window is on screen, so use pointer location instead */ + if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) + for (i = 0; i < n; i++) + if (INTERSECT(x, y, 1, 1, info[i]) != 0) + break; + + if (center) { + mw = MIN(MAX(max_textw() + promptw, min_width), info[i].width); + x = info[i].x_org + ((info[i].width - mw) / 2); + y = info[i].y_org + ((info[i].height - mh) / 2); + } else { + x = info[i].x_org + dmx; + y = info[i].y_org + (topbar ? dmy : info[i].height - mh - dmy); + mw = (dmw>0 ? dmw : info[i].width); + } + XFree(info); + } else +#endif + { + if (!XGetWindowAttributes(dpy, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + if (center) { + mw = MIN(MAX(max_textw() + promptw, min_width), wa.width); + x = (wa.width - mw) / 2; + y = (wa.height - mh) / 2; + } else { + x = dmx; + y = topbar ? dmy : wa.height - mh - dmy; + mw = (dmw>0 ? dmw : wa.width); + } + } + inputw = mw / 3; /* input width: ~33.33% of monitor width */ + match(); + + /* create menu window */ + swa.override_redirect = True; + swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask + | ButtonPressMask + ; + win = XCreateWindow( + dpy, root, + x, y - (topbar ? 0 : border_width * 2), mw - border_width * 2, mh, border_width, + CopyFromParent, CopyFromParent, CopyFromParent, + CWOverrideRedirect | CWBackPixel | CWEventMask, &swa + ); + if (border_width) + XSetWindowBorder(dpy, win, scheme[SchemeBorder][ColBg].pixel); + XSetClassHint(dpy, win, &ch); + + + /* input methods */ + if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) + die("XOpenIM failed: could not open input device"); + + xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, win, XNFocusWindow, win, NULL); + + + XMapRaised(dpy, win); + if (embed) { + XReparentWindow(dpy, win, parentwin, x, y); + XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask); + if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { + for (i = 0; i < du && dws[i] != win; ++i) + XSelectInput(dpy, dws[i], FocusChangeMask); + XFree(dws); + } + grabfocus(); + } + drw_resize(drw, mw, mh); + drawmenu(); +} + +static void +usage(void) +{ + die("usage: dmenu [-bv" + "c" + "f" + "i" + "n" + "F" + "P" + "] " + "[-g columns] " + "[-l lines] [-p prompt] [-fn font] [-m monitor]" + "\n [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]" + "\n " + " [-ex expectkey]" + " [-bw width]" + "\n " + " [-h height]" + " [-X xoffset] [-Y yoffset] [-W width]" // (arguments made upper case due to conflicts) + "\n"); +} + +int +main(int argc, char *argv[]) +{ + XWindowAttributes wa; + int i; + int fast = 0; + + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("cannot open display"); + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + if (!embed || !(parentwin = strtol(embed, NULL, 0))) + parentwin = root; + if (!XGetWindowAttributes(dpy, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + + drw = drw_create(dpy, screen, root, wa.width, wa.height); + readxresources(); + + for (i = 1; i < argc; i++) { + if (argv[i][0] == '\0') + continue; + + /* these options take no arguments */ + if (!strcmp(argv[i], "-v")) { /* prints version information */ + puts("dmenu-"VERSION); + exit(0); + } else if (!strcmp(argv[i], "-b")) { /* appears at the bottom of the screen */ + topbar = 0; + } else if (!strcmp(argv[i], "-c")) { /* toggles centering of dmenu window on screen */ + center = !center; + } else if (!strcmp(argv[i], "-f")) { /* grabs keyboard before reading stdin */ + fast = 1; + } else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ + fstrncmp = strncasecmp; + fstrstr = cistrstr; + } else if (!strcmp(argv[i], "-n")) { /* instant select only match */ + instant = !instant; + } else if (!strcmp(argv[i], "-F")) { /* disable/enable fuzzy matching, depends on default */ + fuzzy = !fuzzy; + } else if (!strcmp(argv[i], "-P")) { /* is the input a password */ + passwd = 1; + } else if (!strcmp(argv[i], "-ex")) { /* expect key */ + expected = argv[++i]; + } else if (i + 1 == argc) + usage(); + /* these options take one argument */ + else if (!strcmp(argv[i], "-g")) { /* number of columns in grid */ + columns = atoi(argv[++i]); + if (columns && lines == 0) + lines = 1; + } + else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ + lines = atoi(argv[++i]); + else if (!strcmp(argv[i], "-X")) /* window x offset */ + dmx = atoi(argv[++i]); + else if (!strcmp(argv[i], "-Y")) /* window y offset (from bottom up if -b) */ + dmy = atoi(argv[++i]); + else if (!strcmp(argv[i], "-W")) /* make dmenu this wide */ + dmw = atoi(argv[++i]); + else if (!strcmp(argv[i], "-m")) + mon = atoi(argv[++i]); + else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ + prompt = argv[++i]; + else if (!strcmp(argv[i], "-fn")) /* font or font set */ + fonts[0] = argv[++i]; + else if(!strcmp(argv[i], "-h")) { /* minimum height of one menu line */ + lineheight = atoi(argv[++i]); + lineheight = MAX(lineheight, min_lineheight); /* reasonable default in case of value too small/negative */ + } + else if (!strcmp(argv[i], "-nb")) /* normal background color */ + colors[SchemeNorm][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-nf")) /* normal foreground color */ + colors[SchemeNorm][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-sb")) /* selected background color */ + colors[SchemeSel][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ + colors[SchemeSel][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-w")) /* embedding window id */ + embed = argv[++i]; + else if (!strcmp(argv[i], "-bw")) /* border width around dmenu */ + border_width = atoi(argv[++i]); + else { + usage(); + } + } + + if (!drw_fontset_create(drw, (const char**)fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + + lrpad = drw->fonts->h; + + + if (lineheight == -1) + lineheight = drw->fonts->h * 2.5; + +#ifdef __OpenBSD__ + if (pledge("stdio rpath", NULL) == -1) + die("pledge"); +#endif + + if (fast && !isatty(0)) { + grabkeyboard(); + readstdin(); + } else { + readstdin(); + grabkeyboard(); + } + setup(); + run(); + + return 1; /* unreachable */ +} diff --git a/.config/suckless/dmenu/dmenu_path b/.config/suckless/dmenu/dmenu_path new file mode 100755 index 0000000..3a7cda7 --- /dev/null +++ b/.config/suckless/dmenu/dmenu_path @@ -0,0 +1,13 @@ +#!/bin/sh + +cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}" +cache="$cachedir/dmenu_run" + +[ ! -e "$cachedir" ] && mkdir -p "$cachedir" + +IFS=: +if stest -dqr -n "$cache" $PATH; then + stest -flx $PATH | sort -u | tee "$cache" +else + cat "$cache" +fi diff --git a/.config/suckless/dmenu/dmenu_run b/.config/suckless/dmenu/dmenu_run new file mode 100755 index 0000000..e6d1355 --- /dev/null +++ b/.config/suckless/dmenu/dmenu_run @@ -0,0 +1,6 @@ +#!/bin/sh +export _JAVA_AWT_WM_NONREPARENTING=1 +dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & + +# Uncomment for the NAVHISTORY patch (and remove the exec above) +#dmenu_path | dmenu -H "${XDG_CACHE_HOME:-$HOME/.cache/}/dmenu_run.hist" "$@" | ${SHELL:-"/bin/sh"} & \ No newline at end of file diff --git a/.config/suckless/dmenu/drw.c b/.config/suckless/dmenu/drw.c new file mode 100644 index 0000000..4f67d02 --- /dev/null +++ b/.config/suckless/dmenu/drw.c @@ -0,0 +1,455 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" + +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 + +static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + +static long +utf8decodebyte(const char c, size_t *i) +{ + for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) + if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) + return (unsigned char)c & ~utfmask[*i]; + return 0; +} + +static size_t +utf8validate(long *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + return i; +} + +static size_t +utf8decode(const char *c, long *u, size_t clen) +{ + size_t i, j, len, type; + long udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + return len; +} + +Drw * +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +{ + Drw *drw = ecalloc(1, sizeof(Drw)); + + drw->dpy = dpy; + drw->screen = screen; + drw->root = root; + drw->w = w; + drw->h = h; + drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + drw->gc = XCreateGC(dpy, root, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + + return drw; +} + +void +drw_resize(Drw *drw, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + drw->w = w; + drw->h = h; + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); +} + +void +drw_free(Drw *drw) +{ + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); + drw_fontset_free(drw->fonts); + free(drw); +} + +/* This function is an implementation detail. Library users should use + * drw_fontset_create instead. + */ +static Fnt * +xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) +{ + Fnt *font; + XftFont *xfont = NULL; + FcPattern *pattern = NULL; + + if (fontname) { + /* Using the pattern found at font->xfont->pattern does not yield the + * same substitution results as using the pattern returned by + * FcNameParse; using the latter results in the desired fallback + * behaviour whereas the former just results in missing-character + * rectangles being drawn, at least with some fonts. */ + if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { + fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); + return NULL; + } + if (!(pattern = FcNameParse((FcChar8 *) fontname))) { + fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); + XftFontClose(drw->dpy, xfont); + return NULL; + } + } else if (fontpattern) { + if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { + fprintf(stderr, "error, cannot load font from pattern.\n"); + return NULL; + } + } else { + die("no font specified."); + } + + + font = ecalloc(1, sizeof(Fnt)); + font->xfont = xfont; + font->pattern = pattern; + font->h = xfont->ascent + xfont->descent; + font->dpy = drw->dpy; + + return font; +} + +static void +xfont_free(Fnt *font) +{ + if (!font) + return; + if (font->pattern) + FcPatternDestroy(font->pattern); + XftFontClose(font->dpy, font->xfont); + free(font); +} + +Fnt* +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) +{ + Fnt *cur, *ret = NULL; + size_t i; + + if (!drw || !fonts) + return NULL; + + for (i = 1; i <= fontcount; i++) { + if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { + cur->next = ret; + ret = cur; + } + } + return (drw->fonts = ret); +} + +void +drw_fontset_free(Fnt *font) +{ + if (font) { + drw_fontset_free(font->next); + xfont_free(font); + } +} + +void +drw_clr_create(Drw *drw, Clr *dest, const char *clrname) +{ + if (!drw || !dest || !clrname) + return; + + if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen), + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); +} + +/* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ +Clr * +drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +{ + size_t i; + Clr *ret; + + /* need at least two colors for a scheme */ + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) + return NULL; + + for (i = 0; i < clrcount; i++) + drw_clr_create(drw, &ret[i], clrnames[i]); + return ret; +} + +void +drw_setfontset(Drw *drw, Fnt *set) +{ + if (drw) + drw->fonts = set; +} + +void +drw_setscheme(Drw *drw, Clr *scm) +{ + if (drw) + drw->scheme = scm; +} + +void +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) +{ + if (!drw || !drw->scheme) + return; + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); + if (filled) + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + else + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); +} + +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) +{ + int ty, ellipsis_x = 0; + unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1; + XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + int utf8strlen, utf8charlen, render = x || y || w || h; + long utf8codepoint = 0; + const char *utf8str; + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; + XftResult result; + int charexists = 0, overflow = 0; + /* keep track of a couple codepoints for which we have no match. */ + static unsigned int nomatches[128], ellipsis_width; + const char *ellipsis = "..."; + + if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) + return 0; + + if (!render) { + w = invert ? invert : ~invert; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + x += lpad; + w -= lpad; + } + + usedfont = drw->fonts; + if (!ellipsis_width && render) + ellipsis_width = drw_fontset_getwidth(drw, ellipsis); + while (1) { + ew = ellipsis_len = utf8strlen = 0; + utf8str = text; + nextfont = NULL; + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); + if (charexists) { + drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); + if (ew + ellipsis_width <= w) { + /* keep track where the ellipsis still fits */ + ellipsis_x = x + ew; + ellipsis_w = w - ew; + ellipsis_len = utf8strlen; + } + + if (ew + tmpw > w) { + overflow = 1; + /* called from drw_fontset_getwidth_clamp(): + * it wants the width AFTER the overflow + */ + if (!render) + x += tmpw; + else + utf8strlen = ellipsis_len; + } else if (curfont == usedfont) { + utf8strlen += utf8charlen; + text += utf8charlen; + ew += tmpw; + } else { + nextfont = curfont; + } + break; + } + } + + if (overflow || !charexists || nextfont) + break; + else + charexists = 0; + } + + if (utf8strlen) { + if (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], + usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); + } + x += ew; + w -= ew; + } + if (render && overflow && ellipsis_w) + drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, ellipsis, invert); + + if (!*text || overflow) { + break; + } else if (nextfont) { + charexists = 0; + usedfont = nextfont; + } else { + /* Regardless of whether or not a fallback font is found, the + * character must be drawn. */ + charexists = 1; + + hash = (unsigned int)utf8codepoint; + hash = ((hash >> 16) ^ hash) * 0x21F0AAAD; + hash = ((hash >> 15) ^ hash) * 0xD35A2D97; + h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches); + h1 = (hash >> 17) % LENGTH(nomatches); + /* avoid expensive XftFontMatch call when we know we won't find a match */ + if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint) + goto no_match; + + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ + die("the first font in the cache must be loaded from a font string."); + } + + fcpattern = FcPatternDuplicate(drw->fonts->pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; + } else { + xfont_free(usedfont); + nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint; +no_match: + usedfont = drw->fonts; + } + } + } + } + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +} + +void +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); + XSync(drw->dpy, False); +} + +unsigned int +drw_fontset_getwidth(Drw *drw, const char *text) +{ + if (!drw || !drw->fonts || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0); +} + +unsigned int +drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) +{ + unsigned int tmp = 0; + if (drw && drw->fonts && text && n) + tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); + return MIN(n, tmp); +} + +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) +{ + XGlyphInfo ext; + + if (!font || !text) + return; + + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); + if (w) + *w = ext.xOff; + if (h) + *h = font->h; +} + +Cur * +drw_cur_create(Drw *drw, int shape) +{ + Cur *cur; + + if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) + return NULL; + + cur->cursor = XCreateFontCursor(drw->dpy, shape); + + return cur; +} + +void +drw_cur_free(Drw *drw, Cur *cursor) +{ + if (!cursor) + return; + + XFreeCursor(drw->dpy, cursor->cursor); + free(cursor); +} + +#include "patch/scroll.c" diff --git a/.config/suckless/dmenu/drw.h b/.config/suckless/dmenu/drw.h new file mode 100644 index 0000000..b97e268 --- /dev/null +++ b/.config/suckless/dmenu/drw.h @@ -0,0 +1,61 @@ +/* See LICENSE file for copyright and license details. */ + + +typedef struct { + Cursor cursor; +} Cur; + +typedef struct Fnt { + Display *dpy; + unsigned int h; + XftFont *xfont; + FcPattern *pattern; + struct Fnt *next; +} Fnt; + +enum { ColFg, ColBg }; /* Clr scheme index */ +typedef XftColor Clr; + +typedef struct { + unsigned int w, h; + Display *dpy; + int screen; + Window root; + Drawable drawable; + GC gc; + Clr *scheme; + Fnt *fonts; +} Drw; + +/* Drawable abstraction */ +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +void drw_resize(Drw *drw, unsigned int w, unsigned int h); +void drw_free(Drw *drw); + +/* Fnt abstraction */ +Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); +void drw_fontset_free(Fnt* set); +unsigned int drw_fontset_getwidth(Drw *drw, const char *text); +unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); + +/* Colorscheme abstraction */ +void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); +Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); + +/* Cursor abstraction */ +Cur *drw_cur_create(Drw *drw, int shape); +void drw_cur_free(Drw *drw, Cur *cursor); + +/* Drawing context manipulation */ +void drw_setfontset(Drw *drw, Fnt *set); +void drw_setscheme(Drw *drw, Clr *scm); + +/* Drawing functions */ +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); + +/* Map functions */ +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); + +#include "patch/scroll.h" diff --git a/.config/suckless/dmenu/patch/center.c b/.config/suckless/dmenu/patch/center.c new file mode 100644 index 0000000..09b0f9a --- /dev/null +++ b/.config/suckless/dmenu/patch/center.c @@ -0,0 +1,8 @@ +static int +max_textw(void) +{ + int len = 0; + for (struct item *item = items; item && item->text; item++) + len = MAX(TEXTW(item->text), len); + return len; +} diff --git a/.config/suckless/dmenu/patch/fuzzymatch.c b/.config/suckless/dmenu/patch/fuzzymatch.c new file mode 100644 index 0000000..1e5e0f5 --- /dev/null +++ b/.config/suckless/dmenu/patch/fuzzymatch.c @@ -0,0 +1,89 @@ +#include + +int +compare_distance(const void *a, const void *b) +{ + struct item *da = *(struct item **) a; + struct item *db = *(struct item **) b; + + if (!db) + return 1; + if (!da) + return -1; + + return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1; +} + +void +fuzzymatch(void) +{ + /* bang - we have so much memory */ + struct item *it; + struct item **fuzzymatches = NULL; + char c; + int number_of_matches = 0, i, pidx, sidx, eidx; + int text_len = strlen(text), itext_len; + matches = matchend = NULL; + + /* walk through all items */ + for (it = items; it && it->text; it++) { + if (text_len) { + itext_len = strlen(it->text); + pidx = 0; /* pointer */ + sidx = eidx = -1; /* start of match, end of match */ + /* walk through item text */ + for (i = 0; i < itext_len && (c = it->text[i]); i++) { + /* fuzzy match pattern */ + if (!fstrncmp(&text[pidx], &c, 1)) { + if (sidx == -1) + sidx = i; + pidx++; + if (pidx == text_len) { + eidx = i; + break; + } + } + } + /* build list of matches */ + if (eidx != -1) { + /* compute distance */ + /* add penalty if match starts late (log(sidx+2)) + * add penalty for long a match without many matching characters */ + it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len); + /* fprintf(stderr, "distance %s %f\n", it->text, it->distance); */ + appenditem(it, &matches, &matchend); + number_of_matches++; + } + } else { + appenditem(it, &matches, &matchend); + } + } + + if (number_of_matches) { + /* initialize array with matches */ + if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*)))) + die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item*)); + for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) { + fuzzymatches[i] = it; + } + + /* sort matches according to distance */ + qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance); + /* rebuild list of matches */ + matches = matchend = NULL; + for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \ + it->text; i++, it = fuzzymatches[i]) { + appenditem(it, &matches, &matchend); + } + free(fuzzymatches); + } + curr = sel = matches; + + if (instant && matches && matches==matchend) { + puts(matches->text); + cleanup(); + exit(0); + } + + calcoffsets(); +} diff --git a/.config/suckless/dmenu/patch/fzfexpect.c b/.config/suckless/dmenu/patch/fzfexpect.c new file mode 100644 index 0000000..a4ba9d9 --- /dev/null +++ b/.config/suckless/dmenu/patch/fzfexpect.c @@ -0,0 +1,15 @@ +static char *expected; +void +expect(char *expect, XKeyEvent *ignored) +{ + if (sel && expected && strstr(expected, expect)) { + puts(expect); + puts(sel->text); + cleanup(); + exit(1); + } else if (!sel && expected && strstr(expected, expect)){ + puts(expect); + cleanup(); + exit(1); + } +} diff --git a/.config/suckless/dmenu/patch/fzfexpect.h b/.config/suckless/dmenu/patch/fzfexpect.h new file mode 100644 index 0000000..95c1dad --- /dev/null +++ b/.config/suckless/dmenu/patch/fzfexpect.h @@ -0,0 +1 @@ +static void expect(char *expect, XKeyEvent *ev); diff --git a/.config/suckless/dmenu/patch/include.c b/.config/suckless/dmenu/patch/include.c new file mode 100644 index 0000000..4661894 --- /dev/null +++ b/.config/suckless/dmenu/patch/include.c @@ -0,0 +1,5 @@ +#include "center.c" +#include "fuzzymatch.c" +#include "fzfexpect.c" +#include "mousesupport.c" +#include "xresources.c" diff --git a/.config/suckless/dmenu/patch/include.h b/.config/suckless/dmenu/patch/include.h new file mode 100644 index 0000000..a190b82 --- /dev/null +++ b/.config/suckless/dmenu/patch/include.h @@ -0,0 +1 @@ +#include "fzfexpect.h" diff --git a/.config/suckless/dmenu/patch/mousesupport.c b/.config/suckless/dmenu/patch/mousesupport.c new file mode 100644 index 0000000..c8854cd --- /dev/null +++ b/.config/suckless/dmenu/patch/mousesupport.c @@ -0,0 +1,114 @@ +static void +buttonpress(XEvent *e) +{ + struct item *item; + XButtonPressedEvent *ev = &e->xbutton; + int x = 0, y = 0, h = bh, w; + + if (ev->window != win) + return; + + /* right-click: exit */ + if (ev->button == Button3) + exit(1); + + if (prompt && *prompt) + x += promptw; + + /* input field */ + w = (lines > 0 || !matches) ? mw - x : inputw; + + /* left-click on input: clear input, + * NOTE: if there is no left-arrow the space for < is reserved so + * add that to the input width */ + if (ev->button == Button1 && + ((lines <= 0 && ev->x >= 0 && ev->x <= x + w + + ((!prev || !curr->left) ? TEXTW("<") : 0)) || + (lines > 0 && ev->y >= y && ev->y <= y + h))) { + insert(NULL, -cursor); + drawmenu(); + return; + } + /* middle-mouse click: paste selection */ + if (ev->button == Button2) { + XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + drawmenu(); + return; + } + /* scroll up */ + if (ev->button == Button4 && prev) { + sel = curr = prev; + calcoffsets(); + drawmenu(); + return; + } + /* scroll down */ + if (ev->button == Button5 && next) { + sel = curr = next; + calcoffsets(); + drawmenu(); + return; + } + if (ev->button != Button1) + return; + if (ev->state & ~ControlMask) + return; + if (lines > 0) { + /* vertical list: (ctrl)left-click on item */ + w = mw - x; + for (item = curr; item != next; item = item->right) { + y += h; + if (ev->y >= y && ev->y <= (y + h)) { + puts(item->text); + if (!(ev->state & ControlMask)) { + exit(0); + } + sel = item; + if (sel) { + sel->out = 1; + drawmenu(); + } + return; + } + } + } else if (matches) { + /* left-click on left arrow */ + x += inputw; + w = TEXTW("<"); + if (prev && curr->left) { + if (ev->x >= x && ev->x <= x + w) { + sel = curr = prev; + calcoffsets(); + drawmenu(); + return; + } + } + /* horizontal list: (ctrl)left-click on item */ + for (item = curr; item != next; item = item->right) { + x += w; + w = MIN(TEXTW(item->text), mw - x - TEXTW(">")); + if (ev->x >= x && ev->x <= x + w) { + puts(item->text); + if (!(ev->state & ControlMask)) { + exit(0); + } + sel = item; + if (sel) { + sel->out = 1; + drawmenu(); + } + return; + } + } + /* left-click on right arrow */ + w = TEXTW(">"); + x = mw - w; + if (next && ev->x >= x && ev->x <= x + w) { + sel = curr = next; + calcoffsets(); + drawmenu(); + return; + } + } +} diff --git a/.config/suckless/dmenu/patch/scroll.c b/.config/suckless/dmenu/patch/scroll.c new file mode 100644 index 0000000..028090c --- /dev/null +++ b/.config/suckless/dmenu/patch/scroll.c @@ -0,0 +1,168 @@ +int +utf8nextchar(const char *str, int len, int i, int inc) +{ + int n; + + for (n = i + inc; n + inc >= 0 && n + inc <= len + && (str[n] & 0xc0) == 0x80; n += inc) + ; + return n; +} + +int +drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align) +{ + int ty; + unsigned int ew; + XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + size_t len; + int utf8strlen, utf8charlen, render = x || y || w || h; + long utf8codepoint = 0; + const char *utf8str; + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; + XftResult result; + int charexists = 0; + int i, n; + + if (!drw || (render && !drw->scheme) || !text || !drw->fonts || textlen <= 0 + || (align != AlignL && align != AlignR)) + return 0; + + if (!render) { + w = ~w; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + } + + usedfont = drw->fonts; + i = align == AlignL ? 0 : textlen; + x = align == AlignL ? x : x + w; + while (1) { + utf8strlen = 0; + nextfont = NULL; + /* if (align == AlignL) */ + utf8str = text + i; + + while ((align == AlignL && i < textlen) || (align == AlignR && i > 0)) { + if (align == AlignL) { + utf8charlen = utf8decode(text + i, &utf8codepoint, MIN(textlen - i, UTF_SIZ)); + if (!utf8charlen) { + textlen = i; + break; + } + } else { + n = utf8nextchar(text, textlen, i, -1); + utf8charlen = utf8decode(text + n, &utf8codepoint, MIN(textlen - n, UTF_SIZ)); + if (!utf8charlen) { + textlen -= i; + text += i; + i = 0; + break; + } + } + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); + if (charexists) { + if (curfont == usedfont) { + utf8strlen += utf8charlen; + i += align == AlignL ? utf8charlen : -utf8charlen; + } else { + nextfont = curfont; + } + break; + } + } + + if (!charexists || nextfont) + break; + else + charexists = 0; + } + + if (align == AlignR) + utf8str = text + i; + + if (utf8strlen) { + drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); + /* shorten text if necessary */ + if (align == AlignL) { + for (len = utf8strlen; len && ew > w; ) { + len = utf8nextchar(utf8str, len, len, -1); + drw_font_getexts(usedfont, utf8str, len, &ew, NULL); + } + } else { + for (len = utf8strlen; len && ew > w; ) { + n = utf8nextchar(utf8str, len, 0, +1); + utf8str += n; + len -= n; + drw_font_getexts(usedfont, utf8str, len, &ew, NULL); + } + } + + if (len) { + if (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[ColFg], + usedfont->xfont, align == AlignL ? x : x - ew, ty, (XftChar8 *)utf8str, len); + } + x += align == AlignL ? ew : -ew; + w -= ew; + } + if (len < utf8strlen) + break; + } + + if ((align == AlignR && i <= 0) || (align == AlignL && i >= textlen)) { + break; + } else if (nextfont) { + charexists = 0; + usedfont = nextfont; + } else { + /* Regardless of whether or not a fallback font is found, the + * character must be drawn. */ + charexists = 1; + + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ + die("the first font in the cache must be loaded from a font string."); + } + + fcpattern = FcPatternDuplicate(drw->fonts->pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; + } else { + xfont_free(usedfont); + usedfont = drw->fonts; + } + } + } + } + if (d) + XftDrawDestroy(d); + + return x; +} diff --git a/.config/suckless/dmenu/patch/scroll.h b/.config/suckless/dmenu/patch/scroll.h new file mode 100644 index 0000000..2d0c494 --- /dev/null +++ b/.config/suckless/dmenu/patch/scroll.h @@ -0,0 +1,3 @@ +enum { AlignL, AlignR }; + +int drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align); diff --git a/.config/suckless/dmenu/patch/xresources.c b/.config/suckless/dmenu/patch/xresources.c new file mode 100644 index 0000000..38c8f81 --- /dev/null +++ b/.config/suckless/dmenu/patch/xresources.c @@ -0,0 +1,34 @@ +#include + +void +readxresources(void) +{ + XrmInitialize(); + + char* xrm; + if ((xrm = XResourceManagerString(drw->dpy))) { + char *type; + XrmDatabase xdb = XrmGetStringDatabase(xrm); + XrmValue xval; + + if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval)) + fonts[0] = strdup(xval.addr); + else + fonts[0] = strdup(fonts[0]); + if (XrmGetResource(xdb, "dmenu.background", "*", &type, &xval)) + colors[SchemeNorm][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.foreground", "*", &type, &xval)) + colors[SchemeNorm][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.selbackground", "*", &type, &xval)) + colors[SchemeSel][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.selforeground", "*", &type, &xval)) + colors[SchemeSel][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.outbackground", "*", &type, &xval)) + colors[SchemeOut][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.outforeground", "*", &type, &xval)) + colors[SchemeOut][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.bordercolor", "*", &type, &xval)) + colors[SchemeBorder][ColBg] = strdup(xval.addr); + XrmDestroyDatabase(xdb); + } +} diff --git a/.config/suckless/dmenu/stest.1 b/.config/suckless/dmenu/stest.1 new file mode 100644 index 0000000..2667d8a --- /dev/null +++ b/.config/suckless/dmenu/stest.1 @@ -0,0 +1,90 @@ +.TH STEST 1 dmenu\-VERSION +.SH NAME +stest \- filter a list of files by properties +.SH SYNOPSIS +.B stest +.RB [ -abcdefghlpqrsuwx ] +.RB [ -n +.IR file ] +.RB [ -o +.IR file ] +.RI [ file ...] +.SH DESCRIPTION +.B stest +takes a list of files and filters by the files' properties, analogous to +.IR test (1). +Files which pass all tests are printed to stdout. If no files are given, stest +reads files from stdin. +.SH OPTIONS +.TP +.B \-a +Test hidden files. +.TP +.B \-b +Test that files are block specials. +.TP +.B \-c +Test that files are character specials. +.TP +.B \-d +Test that files are directories. +.TP +.B \-e +Test that files exist. +.TP +.B \-f +Test that files are regular files. +.TP +.B \-g +Test that files have their set-group-ID flag set. +.TP +.B \-h +Test that files are symbolic links. +.TP +.B \-l +Test the contents of a directory given as an argument. +.TP +.BI \-n " file" +Test that files are newer than +.IR file . +.TP +.BI \-o " file" +Test that files are older than +.IR file . +.TP +.B \-p +Test that files are named pipes. +.TP +.B \-q +No files are printed, only the exit status is returned. +.TP +.B \-r +Test that files are readable. +.TP +.B \-s +Test that files are not empty. +.TP +.B \-u +Test that files have their set-user-ID flag set. +.TP +.B \-v +Invert the sense of tests, only failing files pass. +.TP +.B \-w +Test that files are writable. +.TP +.B \-x +Test that files are executable. +.SH EXIT STATUS +.TP +.B 0 +At least one file passed all tests. +.TP +.B 1 +No files passed all tests. +.TP +.B 2 +An error occurred. +.SH SEE ALSO +.IR dmenu (1), +.IR test (1) diff --git a/.config/suckless/dmenu/stest.c b/.config/suckless/dmenu/stest.c new file mode 100644 index 0000000..e27d3a5 --- /dev/null +++ b/.config/suckless/dmenu/stest.c @@ -0,0 +1,109 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include +#include +#include +#include +#include +#include + +#include "arg.h" +char *argv0; + +#define FLAG(x) (flag[(x)-'a']) + +static void test(const char *, const char *); +static void usage(void); + +static int match = 0; +static int flag[26]; +static struct stat old, new; + +static void +test(const char *path, const char *name) +{ + struct stat st, ln; + + if ((!stat(path, &st) && (FLAG('a') || name[0] != '.') /* hidden files */ + && (!FLAG('b') || S_ISBLK(st.st_mode)) /* block special */ + && (!FLAG('c') || S_ISCHR(st.st_mode)) /* character special */ + && (!FLAG('d') || S_ISDIR(st.st_mode)) /* directory */ + && (!FLAG('e') || access(path, F_OK) == 0) /* exists */ + && (!FLAG('f') || S_ISREG(st.st_mode)) /* regular file */ + && (!FLAG('g') || st.st_mode & S_ISGID) /* set-group-id flag */ + && (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link */ + && (!FLAG('n') || st.st_mtime > new.st_mtime) /* newer than file */ + && (!FLAG('o') || st.st_mtime < old.st_mtime) /* older than file */ + && (!FLAG('p') || S_ISFIFO(st.st_mode)) /* named pipe */ + && (!FLAG('r') || access(path, R_OK) == 0) /* readable */ + && (!FLAG('s') || st.st_size > 0) /* not empty */ + && (!FLAG('u') || st.st_mode & S_ISUID) /* set-user-id flag */ + && (!FLAG('w') || access(path, W_OK) == 0) /* writable */ + && (!FLAG('x') || access(path, X_OK) == 0)) != FLAG('v')) { /* executable */ + if (FLAG('q')) + exit(0); + match = 1; + puts(name); + } +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [-abcdefghlpqrsuvwx] " + "[-n file] [-o file] [file...]\n", argv0); + exit(2); /* like test(1) return > 1 on error */ +} + +int +main(int argc, char *argv[]) +{ + struct dirent *d; + char path[PATH_MAX], *line = NULL, *file; + size_t linesiz = 0; + ssize_t n; + DIR *dir; + int r; + + ARGBEGIN { + case 'n': /* newer than file */ + case 'o': /* older than file */ + file = EARGF(usage()); + if (!(FLAG(ARGC()) = !stat(file, (ARGC() == 'n' ? &new : &old)))) + perror(file); + break; + default: + /* miscellaneous operators */ + if (strchr("abcdefghlpqrsuvwx", ARGC())) + FLAG(ARGC()) = 1; + else + usage(); /* unknown flag */ + } ARGEND; + + if (!argc) { + /* read list from stdin */ + while ((n = getline(&line, &linesiz, stdin)) > 0) { + if (line[n - 1] == '\n') + line[n - 1] = '\0'; + test(line, line); + } + free(line); + } else { + for (; argc; argc--, argv++) { + if (FLAG('l') && (dir = opendir(*argv))) { + /* test directory contents */ + while ((d = readdir(dir))) { + r = snprintf(path, sizeof path, "%s/%s", + *argv, d->d_name); + if (r >= 0 && (size_t)r < sizeof path) + test(path, d->d_name); + } + closedir(dir); + } else { + test(*argv, *argv); + } + } + } + return match ? 0 : 1; +} diff --git a/.config/suckless/dmenu/util.c b/.config/suckless/dmenu/util.c new file mode 100644 index 0000000..96b82c9 --- /dev/null +++ b/.config/suckless/dmenu/util.c @@ -0,0 +1,36 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "util.h" + +void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(1); +} + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} diff --git a/.config/suckless/dmenu/util.h b/.config/suckless/dmenu/util.h new file mode 100644 index 0000000..2922d77 --- /dev/null +++ b/.config/suckless/dmenu/util.h @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef MAX +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif +#ifndef MIN +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) +#define LENGTH(X) (sizeof (X) / sizeof (X)[0]) + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); diff --git a/.config/suckless/dwm/LICENSE b/.config/suckless/dwm/LICENSE new file mode 100644 index 0000000..995172f --- /dev/null +++ b/.config/suckless/dwm/LICENSE @@ -0,0 +1,38 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2009 Jukka Salmi +© 2006-2007 Sander van Dijk +© 2007-2011 Peter Hartlich +© 2007-2009 Szabolcs Nagy +© 2007-2009 Christof Musik +© 2007-2009 Premysl Hruby +© 2007-2008 Enno Gottox Boland +© 2008 Martin Hurton +© 2008 Neale Pickett +© 2009 Mate Nagy +© 2010-2016 Hiltjo Posthuma +© 2010-2012 Connor Lane Smith +© 2011 Christoph Lohmann <20h@r-36.net> +© 2015-2016 Quentin Rameau +© 2015-2016 Eric Pruitt +© 2016-2017 Markus Teich +© 2020-2022 Chris Down + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/.config/suckless/dwm/Makefile b/.config/suckless/dwm/Makefile new file mode 100644 index 0000000..a166452 --- /dev/null +++ b/.config/suckless/dwm/Makefile @@ -0,0 +1,67 @@ +# dwm - dynamic window manager +# See LICENSE file for copyright and license details. + +include config.mk + +SRC = drw.c dwm.c util.c +OBJ = ${SRC:.c=.o} + +# FreeBSD users, prefix all ifdef, else and endif statements with a . for this to work (e.g. .ifdef) + +ifdef YAJLLIBS +all: dwm dwm-msg +else +all: dwm +endif + +.c.o: + ${CC} -c ${CFLAGS} $< + +${OBJ}: config.h config.mk + +config.h: + cp config.def.h $@ + +dwm: ${OBJ} + ${CC} -o $@ ${OBJ} ${LDFLAGS} + +ifdef YAJLLIBS +dwm-msg: + ${CC} -o $@ patch/ipc/dwm-msg.c ${LDFLAGS} +endif + +clean: + rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz + rm -f dwm-msg + +dist: clean + mkdir -p dwm-${VERSION} + cp -R LICENSE Makefile README config.def.h config.mk\ + dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} + tar -cf dwm-${VERSION}.tar dwm-${VERSION} + gzip dwm-${VERSION}.tar + rm -rf dwm-${VERSION} + +install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f dwm ${DESTDIR}${PREFIX}/bin +ifdef YAJLLIBS + cp -f dwm-msg ${DESTDIR}${PREFIX}/bin +endif + chmod 755 ${DESTDIR}${PREFIX}/bin/dwm +ifdef YAJLLIBS + chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg +endif + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 + mkdir -p ${DESTDIR}${PREFIX}/share/xsessions + test -f ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop || cp -n dwm.desktop ${DESTDIR}${PREFIX}/share/xsessions + chmod 644 ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/dwm\ + ${DESTDIR}${MANPREFIX}/man1/dwm.1\ + ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop + +.PHONY: all clean dist install uninstall diff --git a/.config/suckless/dwm/README.md b/.config/suckless/dwm/README.md new file mode 100644 index 0000000..969beb5 --- /dev/null +++ b/.config/suckless/dwm/README.md @@ -0,0 +1,7 @@ +# dwm - dynamic window manager + +This is my configuration for dwm generated by the awesome [dwm flexipatch](https://github.com/mintycube/dwm-flexipatch) and finalized by [flexipatch-finalizer](). + +## Patches + +The patches used and the accompanying documentation is listed below: diff --git a/.config/suckless/dwm/config.h b/.config/suckless/dwm/config.h new file mode 100644 index 0000000..f1edd26 --- /dev/null +++ b/.config/suckless/dwm/config.h @@ -0,0 +1,275 @@ +/* See LICENSE file for copyright and license details. */ +#include + +static const unsigned int borderpx = 1; /* border pixel of windows */ +static const unsigned int snap = 32; /* snap pixel */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 0; /* 0 means bottom bar */ +static const int statusmon = 'A'; +static const char buttonbar[] = " "; + +/* Indicators: see patch/bar_indicators.h for options */ +static int tagindicatortype = INDICATOR_NONE; +static int tiledindicatortype = INDICATOR_NONE; +static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE; +static int fakefsindicatortype = INDICATOR_PLUS; +static int floatfakefsindicatortype = INDICATOR_PLUS_AND_LARGER_SQUARE; +// static const char *fonts[] = { "JetBrainsMono NF DWM:size=9" }; +static const char *fonts[] = { "CaskaydiaCove NF :pixelsize=12" }; + +static char c000000[] = "#000000"; // placeholder value + +static char normfgcolor[] = "#bbbbbb"; +static char normbgcolor[] = "#222222"; +static char normbordercolor[] = "#444444"; +static char normfloatcolor[] = "#db8fd9"; + +static char selfgcolor[] = "#eeeeee"; +static char selbgcolor[] = "#88c096"; +static char selbordercolor[] = "#88c096"; +static char selfloatcolor[] = "#88c096"; + +static char titlenormfgcolor[] = "#bbbbbb"; +static char titlenormbgcolor[] = "#222222"; +static char titlenormbordercolor[] = "#444444"; +static char titlenormfloatcolor[] = "#db8fd9"; + +static char titleselfgcolor[] = "#eeeeee"; +static char titleselbgcolor[] = "#88c096"; +static char titleselbordercolor[] = "#88c096"; +static char titleselfloatcolor[] = "#88c096"; + +static char tagsnormfgcolor[] = "#bbbbbb"; +static char tagsnormbgcolor[] = "#222222"; +static char tagsnormbordercolor[] = "#444444"; +static char tagsnormfloatcolor[] = "#db8fd9"; + +static char tagsselfgcolor[] = "#eeeeee"; +static char tagsselbgcolor[] = "#88c096"; +static char tagsselbordercolor[] = "#88c096"; +static char tagsselfloatcolor[] = "#88c096"; + +static char hidnormfgcolor[] = "#88c096"; +static char hidselfgcolor[] = "#227799"; +static char hidnormbgcolor[] = "#222222"; +static char hidselbgcolor[] = "#222222"; + +static char urgfgcolor[] = "#bbbbbb"; +static char urgbgcolor[] = "#222222"; +static char urgbordercolor[] = "#ff0000"; +static char urgfloatcolor[] = "#db8fd9"; + +static char *colors[][ColCount] = { + /* fg bg border float */ + [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor }, + [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor }, + [SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor }, + [SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor }, + [SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor }, + [SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor }, + [SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, c000000, c000000 }, + [SchemeHidSel] = { hidselfgcolor, hidselbgcolor, c000000, c000000 }, + [SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor }, +}; + +static const char *const autostart[] = { + // "st", NULL, + "dwmblocks", NULL, + NULL +}; + +const char *spcmd1[] = {"st", "-n", "spterm", "-g", "120x28", NULL }; +const char *spcmd2[] = {"st", "-n", "spcalc", "-g", "120x28", "-e", "qalc", "--color", "--interactive", NULL }; +const char *spcmd3[] = {"qalculate-gtk", NULL }; +const char *spcmd4[] = {"st", "-n", "spmusic", "-g", "100x25", "-e", "ncmpcpp", NULL }; +const char *spcmd5[] = {"st", "-n", "spnotes", "-g", "120x34", "-e", "nvim", NULL }; +static Sp scratchpads[] = { + /* name cmd */ + {"spterm", spcmd1}, + {"spcalc", spcmd2}, + {"spcalcgui", spcmd3}, + {"spmusic", spcmd4}, + {"spnotes", spcmd5}, +}; + +static char *tagicons[][NUMTAGS] = +{ + [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, + [ALTERNATIVE_TAGS] = { "A", "B", "C", "D", "E", "F", "G", "H", "I" }, + [ALT_TAGS_DECORATION] = { "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>" }, +}; + +static const Rule rules[] = { + RULE(.wintype = WTYPE "DIALOG", .isfloating = 1) + RULE(.wintype = WTYPE "UTILITY", .isfloating = 1) + RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1) + RULE(.wintype = WTYPE "SPLASH", .isfloating = 1) + // RULE(.class = "Gimp", .tags = 1 << 4) + // RULE(.class = "Firefox", .tags = 1 << 7) + RULE(.instance = "spterm", .tags = SPTAG(0), .isfloating = 1) + RULE(.instance = "spcalc", .tags = SPTAG(1), .isfloating = 1) + RULE(.class = "Qalculate-gtk", .tags = SPTAG(2), .isfloating = 1) + RULE(.instance = "spmusic", .tags = SPTAG(3), .isfloating = 1) + RULE(.instance = "spnotes", .tags = SPTAG(4), .isfloating = 1) + RULE(.class = "volume-ui", .isfloating = 1) +}; + +static const BarRule barrules[] = { + /* monitor bar alignment widthfunc drawfunc clickfunc hoverfunc name */ + { -1, 0, BAR_ALIGN_LEFT, width_stbutton, draw_stbutton, click_stbutton, NULL, "statusbutton" }, + { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" }, + { -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" }, + { statusmon, 0, BAR_ALIGN_RIGHT, width_status2d, draw_status2d, click_statuscmd, NULL, "status2d" }, +}; + +/* layout(s) */ +static const float mfact = 0.50; +static const int nmaster = 1; +static const int resizehints = 0; +static const int lockfullscreen = 1; + +/* mouse scroll resize */ +static const int scrollsensetivity = 15; +static const int scrollargs[][2] = { + /* width change height change */ + { +scrollsensetivity, 0 }, + { -scrollsensetivity, 0 }, + { 0, +scrollsensetivity }, + { 0, -scrollsensetivity }, +}; + +static const Layout layouts[] = { + { "󰙀", tile }, /* first entry is default */ + { "󰖲", NULL }, + { "󰖯", monocle }, +}; + +/* key definitions */ +#define MODKEY Mod4Mask +#define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + +/* helper for spawning shell commands in the pre dwm-5.0 fashion */ +#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + +#define STATUSBAR "dwmblocks" + +static const char *termcmd[] = { "st", NULL }; +static const char* dmenu_run_cmd[] = { "dmenu_run", "-bw", "2", "-i", "-W", "390", "-X", "961", "-Y", "15", "-l", "15", "-g", "3", NULL }; +static const char* clipmenu_cmd[] = { "clipmenu", "-bw", "2", "-i", "-W", "290", "-X", "1061", "-Y", "15", "-l", "15", NULL }; +static const Key on_empty_keys[] = { +/* modifier key function argument */ + { 0, XK_w, spawn, {.v = (const char*[]){ "firefox", NULL } } }, + { 0, XK_grave, spawn, {.v = (const char*[]){ "dmenunerdsymbols", NULL } } }, + { 0, XK_BackSpace, spawn, {.v = (const char*[]){ "sysact", NULL } } }, + { 0, XK_r, spawn, {.v = (const char*[]){ "st", "-e", "lf", NULL } } }, + { 0, XK_Return, spawn, {.v = (const char*[]){ "st", NULL } } }, + { 0, XK_d, spawn, {.v = dmenu_run_cmd } }, + { 0, XK_a, spawn, {.v = (const char*[]){ "dmenu_hub", NULL } } }, + { 0, XK_space, spawn, {.v = (const char*[]){ "dmenu_web", NULL } } }, + { 0, XK_n, spawn, {.v = (const char*[]){ "st", "-e", "nvim", NULL } } }, +}; + +static const Key keys[] = { + /* modifier key function argument */ + { 0,XF86XK_AudioMute, spawn, SHCMD("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle; pkill -RTMIN+8 dwmblocks") }, + { 0,XF86XK_AudioRaiseVolume, spawn, SHCMD("wpctl set-volume @DEFAULT_AUDIO_SINK@ 0%- && wpctl set-volume @DEFAULT_AUDIO_SINK@ 3%+; pkill -RTMIN+8 dwmblocks") }, + { 0,XF86XK_AudioLowerVolume, spawn, SHCMD("wpctl set-volume @DEFAULT_AUDIO_SINK@ 0%+ && wpctl set-volume @DEFAULT_AUDIO_SINK@ 3%-; pkill -RTMIN+8 dwmblocks") }, + { 0,XF86XK_AudioPrev, spawn, {.v = (const char*[]){ "mpc", "prev", NULL } } }, + { 0,XF86XK_AudioNext, spawn, {.v = (const char*[]){ "mpc", "next", NULL } } }, + { 0,XF86XK_AudioPause, spawn, {.v = (const char*[]){ "mpc", "pause", NULL } } }, + { 0,XF86XK_AudioPlay, spawn, {.v = (const char*[]){ "mpc", "play", NULL } } }, + { 0,XK_F7, spawn, {.v = clipmenu_cmd } }, + { 0,XF86XK_MonBrightnessUp, spawn, {.v = (const char*[]){ "xbacklight", "-inc", "15", NULL } } }, + { 0,XF86XK_MonBrightnessDown, spawn, {.v = (const char*[]){ "xbacklight", "-dec", "15", NULL } } }, + { 0, XK_Print, spawn, {.v = (const char*[]){ "maimpick", NULL } } }, + { MODKEY, XK_Print, spawn, {.v = (const char*[]){ "dmenurecord", NULL } } }, + { MODKEY|ShiftMask, XK_Delete, quit, {0} }, + { MODKEY, XK_Delete, quit, {1} }, + { MODKEY|ControlMask, XK_grave, setscratch, {.ui = 0 } }, + { MODKEY|ShiftMask, XK_grave, removescratch, {.ui = 0 } }, + { MODKEY, XK_0, view, {.ui = ~SPTAGMASK } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~SPTAGMASK } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) + TAGKEYS( XK_4, 3) + TAGKEYS( XK_5, 4) + TAGKEYS( XK_6, 5) + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY, XK_BackSpace, spawn, {.v = (const char*[]){ "sysact", NULL } } }, + { MODKEY|ShiftMask, XK_BackSpace, spawn, {.v = (const char*[]){ "sysact", NULL } } }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY, XK_q, killclient, {0} }, + { MODKEY, XK_w, spawn, {.v = (const char*[]){ "firefox", NULL } } }, + { MODKEY, XK_r, spawn, {.v = (const char*[]){ "st", "-e", "lf", NULL } } }, + { MODKEY|ShiftMask, XK_r, spawn, {.v = (const char*[]){ "thunar", NULL } } }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, // tiled + { MODKEY, XK_y, setlayout, {.v = &layouts[1]} }, // monocle + { MODKEY, XK_u, setlayout, {.v = &layouts[2]} }, // none + { MODKEY, XK_o, incnmaster, {.i = +1 } }, + { MODKEY|ShiftMask, XK_o, incnmaster, {.i = -1 } }, + { MODKEY, XK_a, spawn, {.v = (const char*[]){ "dmenu_hub", NULL } } }, + { MODKEY, XK_d, spawn, {.v = dmenu_run_cmd } }, + { MODKEY, XK_f, togglefakefullscreen, {0} }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY|ShiftMask, XK_apostrophe, togglescratch, {.ui = 2 } }, + { MODKEY, XK_apostrophe, togglescratch, {.ui = 1 } }, + { MODKEY, XK_Return, spawn, {.v = termcmd } }, + { MODKEY|ShiftMask, XK_Return, togglescratch, {.ui = 0 } }, + { MODKEY, XK_m, togglescratch, {.ui = 3 } }, + { MODKEY, XK_comma, togglescratch, {.ui = 4 } }, + { MODKEY, XK_x, transfer, {0} }, + { MODKEY, XK_b, togglebar, {0} }, + { MODKEY|ShiftMask, XK_b, spawn, {.v = (const char*[]){ "dmenu_web", "--add" , NULL } } }, + { MODKEY, XK_n, spawn, {.v = (const char*[]){ "st", "-e", "nvim", NULL } } }, + { MODKEY|ShiftMask, XK_n, spawn, {.v = (const char*[]){ "st", "-e", "newsboat", NULL } } }, + // { MODKEY, XK_m, spawn, {.v = (const char*[]){ "st", "-e", "ncmpcpp", NULL } } }, + { MODKEY, XK_space, spawn, {.v = (const char*[]){ "dmenu_web", NULL } } }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_Left, focusdir, {.i = 0 } }, + { MODKEY, XK_Right, focusdir, {.i = 1 } }, + { MODKEY, XK_Up, focusdir, {.i = 2 } }, + { MODKEY, XK_Down, focusdir, {.i = 3 } }, + { MODKEY|ControlMask, XK_Up, rotatestack, {.i = +1 } }, + { MODKEY|ControlMask, XK_Down, rotatestack, {.i = -1 } }, + { MODKEY|Mod1Mask, XK_Left, shiftboth, { .i = -1 } }, + { MODKEY|Mod1Mask, XK_Right, shiftboth, { .i = +1 } }, + { MODKEY|ControlMask, XK_Left, shiftviewclients, { .i = -1 } }, + { MODKEY|ControlMask, XK_Right, shiftviewclients, { .i = +1 } }, +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static const Button buttons[] = { + /* click event mask button function argument */ + { ClkRootWin, 0, Button1, spawn, SHCMD("dunstctl close-all; killall dmenu") }, + { ClkRootWin, 0, Button3, spawn, SHCMD("dunstctl close-all; pgrep -x 'dmenu' > /dev/null && killall dmenu || dmenu_hub") }, + { ClkButton, 0, Button1, spawn, {.v = dmenu_run_cmd } }, + { ClkButton, 0, Button3, spawn, {.v = (const char*[]){ "dmenu_hub", NULL } } }, + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkStatusText, 0, Button1, sigstatusbar, {.i = 1 } }, + { ClkStatusText, 0, Button2, sigstatusbar, {.i = 2 } }, + { ClkStatusText, 0, Button3, sigstatusbar, {.i = 3 } }, + { ClkStatusText, 0, Button4, sigstatusbar, {.i = 4} }, + { ClkStatusText, 0, Button5, sigstatusbar, {.i = 5} }, + { ClkStatusText, ShiftMask, Button1, sigstatusbar, {.i = 6} }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkClientWin, MODKEY, Button4, resizemousescroll, {.v = &scrollargs[0]} }, + { ClkClientWin, MODKEY, Button5, resizemousescroll, {.v = &scrollargs[1]} }, + { ClkClientWin, MODKEY, Button6, resizemousescroll, {.v = &scrollargs[2]} }, + { ClkClientWin, MODKEY, Button7, resizemousescroll, {.v = &scrollargs[3]} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; diff --git a/.config/suckless/dwm/config.mk b/.config/suckless/dwm/config.mk new file mode 100644 index 0000000..69b8092 --- /dev/null +++ b/.config/suckless/dwm/config.mk @@ -0,0 +1,73 @@ +# dwm version +VERSION = 6.4 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# FreeBSD (uncomment) +#X11INC = /usr/local/include +#X11LIB = /usr/local/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 +# FreeBSD (uncomment) +#FREETYPEINC = /usr/local/include/freetype2 +# OpenBSD (uncomment) +#FREETYPEINC = ${X11INC}/freetype2 +# OpenBSD - Uncomment this for the swallow patch / SWALLOW_PATCH +#KVMLIB = -lkvm + +# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) +XRENDER = -lXrender + +# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH +#MPDCLIENT = -lmpdclient + +# Uncomment for the pango patch / BAR_PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + +# Uncomment for the ipc patch / IPC_PATCH +#YAJLLIBS = -lyajl +#YAJLINC = -I/usr/include/yajl + +# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH +#XEXTLIB = -lXext + +# Uncomment this for the swallow patch / SWALLOW_PATCH +#XCBLIBS = -lX11-xcb -lxcb -lxcb-res + +# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH +#IMLIB2LIBS = -lImlib2 + +# Uncomment for the bidi patch +#BDINC = `pkg-config --cflags fribidi` +#BDLIBS = `pkg-config --libs fribidi` + +# includes and libs +INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} ${BDINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} $(BDLIBS) + +# flags +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS = ${LIBS} + +# Solaris +#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" +#LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/.config/suckless/dwm/drw.c b/.config/suckless/dwm/drw.c new file mode 100644 index 0000000..8e09a26 --- /dev/null +++ b/.config/suckless/dwm/drw.c @@ -0,0 +1,438 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" + + +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 + +static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + + +static long +utf8decodebyte(const char c, size_t *i) +{ + for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) + if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) + return (unsigned char)c & ~utfmask[*i]; + return 0; +} + +static size_t +utf8validate(long *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + return i; +} + +static size_t +utf8decode(const char *c, long *u, size_t clen) +{ + size_t i, j, len, type; + long udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + return len; +} + +Drw * +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +{ + Drw *drw = ecalloc(1, sizeof(Drw)); + + drw->dpy = dpy; + drw->screen = screen; + drw->root = root; + drw->w = w; + drw->h = h; + + drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + drw->gc = XCreateGC(dpy, root, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + + return drw; +} + +void +drw_resize(Drw *drw, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + drw->w = w; + drw->h = h; + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); +} + +void +drw_free(Drw *drw) +{ + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); + drw_fontset_free(drw->fonts); + free(drw); +} + +/* This function is an implementation detail. Library users should use + * drw_fontset_create instead. + */ +static Fnt * +xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) +{ + Fnt *font; + XftFont *xfont = NULL; + FcPattern *pattern = NULL; + + if (fontname) { + /* Using the pattern found at font->xfont->pattern does not yield the + * same substitution results as using the pattern returned by + * FcNameParse; using the latter results in the desired fallback + * behaviour whereas the former just results in missing-character + * rectangles being drawn, at least with some fonts. */ + if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { + fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); + return NULL; + } + if (!(pattern = FcNameParse((FcChar8 *) fontname))) { + fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); + XftFontClose(drw->dpy, xfont); + return NULL; + } + } else if (fontpattern) { + if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { + fprintf(stderr, "error, cannot load font from pattern.\n"); + return NULL; + } + } else { + die("no font specified."); + } + + + font = ecalloc(1, sizeof(Fnt)); + font->xfont = xfont; + font->pattern = pattern; + font->h = xfont->ascent + xfont->descent; + font->dpy = drw->dpy; + + return font; +} + +static void +xfont_free(Fnt *font) +{ + if (!font) + return; + if (font->pattern) + FcPatternDestroy(font->pattern); + XftFontClose(font->dpy, font->xfont); + free(font); +} + +Fnt* +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) +{ + Fnt *cur, *ret = NULL; + size_t i; + + if (!drw || !fonts) + return NULL; + + for (i = 1; i <= fontcount; i++) { + if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { + cur->next = ret; + ret = cur; + } + } + return (drw->fonts = ret); +} + +void +drw_fontset_free(Fnt *font) +{ + if (font) { + drw_fontset_free(font->next); + xfont_free(font); + } +} + +void +drw_clr_create( + Drw *drw, + Clr *dest, + const char *clrname +) { + if (!drw || !dest || !clrname) + return; + + if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen), + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); + + dest->pixel |= 0xff << 24; +} + +/* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ +Clr * +drw_scm_create( + Drw *drw, + char *clrnames[], + size_t clrcount +) { + size_t i; + Clr *ret; + + /* need at least two colors for a scheme */ + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) + return NULL; + + for (i = 0; i < clrcount; i++) + drw_clr_create(drw, &ret[i], clrnames[i]); + return ret; +} + +void +drw_setfontset(Drw *drw, Fnt *set) +{ + if (drw) + drw->fonts = set; +} + +void +drw_setscheme(Drw *drw, Clr *scm) +{ + if (drw) + drw->scheme = scm; +} + + +void +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) +{ + if (!drw || !drw->scheme) + return; + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); + if (filled) + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + else + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); +} + +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) +{ + char buf[1024]; + int ty; + unsigned int ew; + XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + size_t i, len; + int utf8strlen, utf8charlen, render = x || y || w || h; + long utf8codepoint = 0; + const char *utf8str; + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; + XftResult result; + int charexists = 0; + + if (!drw || (render && !drw->scheme) || !text || !drw->fonts) + return 0; + + if (!render) { + w = ~w; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + x += lpad; + w -= lpad; + } + + usedfont = drw->fonts; + while (1) { + utf8strlen = 0; + utf8str = text; + nextfont = NULL; + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); + if (charexists) { + if (curfont == usedfont) { + utf8strlen += utf8charlen; + text += utf8charlen; + } else { + nextfont = curfont; + } + break; + } + } + + if (!charexists || nextfont) + break; + else + charexists = 0; + } + + if (utf8strlen) { + drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); + /* shorten text if necessary */ + for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; drw_font_getexts(usedfont, utf8str, len, &ew, NULL)) + len--; + + if (len) { + memcpy(buf, utf8str, len); + buf[len] = '\0'; + if (len < utf8strlen) + for (i = len; i && i > len - 3; buf[--i] = '.') + ; /* NOP */ + + if (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], + usedfont->xfont, x, ty, (XftChar8 *)buf, len); + } + x += ew; + w -= ew; + } + } + + if (!*text) { + break; + } else if (nextfont) { + charexists = 0; + usedfont = nextfont; + } else { + /* Regardless of whether or not a fallback font is found, the + * character must be drawn. */ + charexists = 1; + + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ + die("the first font in the cache must be loaded from a font string."); + } + + fcpattern = FcPatternDuplicate(drw->fonts->pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; + } else { + xfont_free(usedfont); + usedfont = drw->fonts; + } + } + } + } + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +} + + + +void +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); + XSync(drw->dpy, False); +} + +unsigned int +drw_fontset_getwidth(Drw *drw, const char *text, Bool markup) +{ + if (!drw || !drw->fonts || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup); +} + +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) +{ + XGlyphInfo ext; + + if (!font || !text) + return; + + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); + if (w) + *w = ext.xOff; + if (h) + *h = font->h; +} + +Cur * +drw_cur_create(Drw *drw, int shape) +{ + Cur *cur; + + if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) + return NULL; + + cur->cursor = XCreateFontCursor(drw->dpy, shape); + + return cur; +} + +void +drw_cur_free(Drw *drw, Cur *cursor) +{ + if (!cursor) + return; + + XFreeCursor(drw->dpy, cursor->cursor); + free(cursor); +} + diff --git a/.config/suckless/dwm/drw.h b/.config/suckless/dwm/drw.h new file mode 100644 index 0000000..d1f8cc0 --- /dev/null +++ b/.config/suckless/dwm/drw.h @@ -0,0 +1,67 @@ +/* See LICENSE file for copyright and license details. */ + + +typedef struct { + Cursor cursor; +} Cur; + +typedef struct Fnt { + Display *dpy; + unsigned int h; + XftFont *xfont; + FcPattern *pattern; + struct Fnt *next; +} Fnt; + +enum { ColFg, ColBg, ColBorder, ColFloat, ColCount }; /* Clr scheme index */ +typedef XftColor Clr; + +typedef struct { + unsigned int w, h; + Display *dpy; + int screen; + Window root; + Drawable drawable; + GC gc; + Clr *scheme; + Fnt *fonts; +} Drw; + +/* Drawable abstraction */ +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +void drw_resize(Drw *drw, unsigned int w, unsigned int h); +void drw_free(Drw *drw); + +/* Fnt abstraction */ +Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); +void drw_fontset_free(Fnt* set); +unsigned int drw_fontset_getwidth(Drw *drw, const char *text, Bool markup); + +/* Colorscheme abstraction */ +void drw_clr_create( + Drw *drw, + Clr *dest, + const char *clrname +); +Clr *drw_scm_create( + Drw *drw, + char *clrnames[], + size_t clrcount +); + +/* Cursor abstraction */ +Cur *drw_cur_create(Drw *drw, int shape); +void drw_cur_free(Drw *drw, Cur *cursor); + +/* Drawing context manipulation */ +void drw_setfontset(Drw *drw, Fnt *set); +void drw_setscheme(Drw *drw, Clr *scm); + +/* Drawing functions */ +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup); + +/* Map functions */ +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); + diff --git a/.config/suckless/dwm/dwm.1 b/.config/suckless/dwm/dwm.1 new file mode 100644 index 0000000..ddc8321 --- /dev/null +++ b/.config/suckless/dwm/dwm.1 @@ -0,0 +1,176 @@ +.TH DWM 1 dwm\-VERSION +.SH NAME +dwm \- dynamic window manager +.SH SYNOPSIS +.B dwm +.RB [ \-v ] +.SH DESCRIPTION +dwm is a dynamic window manager for X. It manages windows in tiled, monocle +and floating layouts. Either layout can be applied dynamically, optimising the +environment for the application in use and the task performed. +.P +In tiled layouts windows are managed in a master and stacking area. The master +area on the left contains one window by default, and the stacking area on the +right contains all other windows. The number of master area windows can be +adjusted from zero to an arbitrary number. In monocle layout all windows are +maximised to the screen size. In floating layout windows can be resized and +moved freely. Dialog windows are always managed floating, regardless of the +layout applied. +.P +Windows are grouped by tags. Each window can be tagged with one or multiple +tags. Selecting certain tags displays all windows with these tags. +.P +Each screen contains a small status bar which displays all available tags, the +layout, the title of the focused window, and the text read from the root window +name property, if the screen is focused. A floating window is indicated with an +empty square and a maximised floating window is indicated with a filled square +before the windows title. The selected tags are indicated with a different +color. The tags of the focused window are indicated with a filled square in the +top left corner. The tags which are applied to one or more windows are +indicated with an empty square in the top left corner. +.P +dwm draws a small border around windows to indicate the focus state. +.SH OPTIONS +.TP +.B \-v +prints version information to stderr, then exits. +.SH USAGE +.SS Status bar +.TP +.B X root window name +is read and displayed in the status text area. It can be set with the +.BR xsetroot (1) +command. +.TP +.B Button1 +click on a tag label to display all windows with that tag, click on the layout +label toggles between tiled and floating layout. +.TP +.B Button3 +click on a tag label adds/removes all windows with that tag to/from the view. +.TP +.B Mod1\-Button1 +click on a tag label applies that tag to the focused window. +.TP +.B Mod1\-Button3 +click on a tag label adds/removes that tag to/from the focused window. +.SS Keyboard commands +.TP +.B Mod1\-Shift\-Return +Start +.BR st(1). +.TP +.B Mod1\-p +Spawn +.BR dmenu(1) +for launching other programs. +.TP +.B Mod1\-, +Focus previous screen, if any. +.TP +.B Mod1\-. +Focus next screen, if any. +.TP +.B Mod1\-Shift\-, +Send focused window to previous screen, if any. +.TP +.B Mod1\-Shift\-. +Send focused window to next screen, if any. +.TP +.B Mod1\-b +Toggles bar on and off. +.TP +.B Mod1\-t +Sets tiled layout. +.TP +.B Mod1\-f +Sets floating layout. +.TP +.B Mod1\-m +Sets monocle layout. +.TP +.B Mod1\-space +Toggles between current and previous layout. +.TP +.B Mod1\-j +Focus next window. +.TP +.B Mod1\-k +Focus previous window. +.TP +.B Mod1\-i +Increase number of windows in master area. +.TP +.B Mod1\-d +Decrease number of windows in master area. +.TP +.B Mod1\-l +Increase master area size. +.TP +.B Mod1\-h +Decrease master area size. +.TP +.B Mod1\-Return +Zooms/cycles focused window to/from master area (tiled layouts only). +.TP +.B Mod1\-Shift\-c +Close focused window. +.TP +.B Mod1\-Shift\-space +Toggle focused window between tiled and floating state. +.TP +.B Mod1\-Tab +Toggles to the previously selected tags. +.TP +.B Mod1\-Shift\-[1..n] +Apply nth tag to focused window. +.TP +.B Mod1\-Shift\-0 +Apply all tags to focused window. +.TP +.B Mod1\-Control\-Shift\-[1..n] +Add/remove nth tag to/from focused window. +.TP +.B Mod1\-[1..n] +View all windows with nth tag. +.TP +.B Mod1\-0 +View all windows with any tag. +.TP +.B Mod1\-Control\-[1..n] +Add/remove all windows with nth tag to/from the view. +.TP +.B Mod1\-Shift\-q +Quit dwm. +.SS Mouse commands +.TP +.B Mod1\-Button1 +Move focused window while dragging. Tiled windows will be toggled to the floating state. +.TP +.B Mod1\-Button2 +Toggles focused window between floating and tiled state. +.TP +.B Mod1\-Button3 +Resize focused window while dragging. Tiled windows will be toggled to the floating state. +.SH CUSTOMIZATION +dwm is customized by creating a custom config.h and (re)compiling the source +code. This keeps it fast, secure and simple. +.SH SEE ALSO +.BR dmenu (1), +.BR st (1) +.SH ISSUES +Java applications which use the XToolkit/XAWT backend may draw grey windows +only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early +JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds +are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the +environment variable +.BR AWT_TOOLKIT=MToolkit +(to use the older Motif backend instead) or running +.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D +or +.B wmname LG3D +(to pretend that a non-reparenting window manager is running that the +XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable +.BR _JAVA_AWT_WM_NONREPARENTING=1 . +.SH BUGS +Send all bug reports with a patch to hackers@suckless.org. diff --git a/.config/suckless/dwm/dwm.c b/.config/suckless/dwm/dwm.c new file mode 100644 index 0000000..8218982 --- /dev/null +++ b/.config/suckless/dwm/dwm.c @@ -0,0 +1,2758 @@ +/* See LICENSE file for copyright and license details. + * + * dynamic window manager is designed like any other X client as well. It is + * driven through handling X events. In contrast to other X clients, a window + * manager selects for SubstructureRedirectMask on the root window, to receive + * events about window (dis-)appearance. Only one X connection at a time is + * allowed to select for this event mask. + * + * The event handlers of dwm are organized in an array which is accessed + * whenever a new event has been fetched. This allows event dispatching + * in O(1) time. + * + * Each child of the root window is called a client, except windows which have + * set the override_redirect flag. Clients are organized in a linked client + * list on each monitor, the focus history is remembered through a stack list + * on each monitor. Each client contains a bit array to indicate the tags of a + * client. + * + * Keys and tagging rules are organized as arrays and defined in config.h. + * + * To understand everything else, start reading main(). + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XINERAMA +#include +#endif /* XINERAMA */ +#include + +#include "drw.h" +#include "util.h" + + + +#include + + + +/* macros */ +#define Button6 6 +#define Button7 7 +#define Button8 8 +#define Button9 9 +#define NUMTAGS 9 +#define NUMVIEWHIST NUMTAGS +#define BARRULES 20 +#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define MOUSEMASK (BUTTONMASK|PointerMotionMask) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define WTYPE "_NET_WM_WINDOW_TYPE_" +#define TOTALTAGS (NUMTAGS + LENGTH(scratchpads)) +#define TAGMASK ((1 << TOTALTAGS) - 1) +#define SPTAG(i) ((1 << NUMTAGS) << (i)) +#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << NUMTAGS) +#define TEXTWM(X) (drw_fontset_getwidth(drw, (X), True) + lrpad) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X), False) + lrpad) +#define HIDDEN(C) ((getstate(C->win) == IconicState)) + +/* enums */ +enum { + CurNormal, + CurResize, + CurMove, + CurLast +}; /* cursor */ + +enum { + SchemeNorm, + SchemeSel, + SchemeTitleNorm, + SchemeTitleSel, + SchemeTagsNorm, + SchemeTagsSel, + SchemeHidNorm, + SchemeHidSel, + SchemeUrg, +}; /* color schemes */ + +enum { + NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetClientList, + NetLast +}; /* EWMH atoms */ + +enum { + WMProtocols, + WMDelete, + WMState, + WMTakeFocus, + WMLast +}; /* default atoms */ + +enum { + ClientFields, + ClientTags, + ClientLast +}; /* dwm client atoms */ + +enum { + ClkButton, + ClkTagBar, + ClkLtSymbol, + ClkStatusText, + ClkWinTitle, + ClkClientWin, + ClkRootWin, + ClkLast +}; /* clicks */ + +enum { + BAR_ALIGN_LEFT, + BAR_ALIGN_CENTER, + BAR_ALIGN_RIGHT, + BAR_ALIGN_LEFT_LEFT, + BAR_ALIGN_LEFT_RIGHT, + BAR_ALIGN_LEFT_CENTER, + BAR_ALIGN_NONE, + BAR_ALIGN_RIGHT_LEFT, + BAR_ALIGN_RIGHT_RIGHT, + BAR_ALIGN_RIGHT_CENTER, + BAR_ALIGN_LAST +}; /* bar alignment */ + + +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct Monitor Monitor; +typedef struct Bar Bar; +struct Bar { + Window win; + Monitor *mon; + Bar *next; + int idx; + int showbar; + int topbar; + int external; + int borderpx; + int borderscheme; + int bx, by, bw, bh; /* bar geometry */ + int w[BARRULES]; // width, array length == barrules, then use r index for lookup purposes + int x[BARRULES]; // x position, array length == ^ +}; + +typedef struct { + int x; + int y; + int h; + int w; +} BarArg; + +typedef struct { + int monitor; + int bar; + int alignment; // see bar alignment enum + int (*widthfunc)(Bar *bar, BarArg *a); + int (*drawfunc)(Bar *bar, BarArg *a); + int (*clickfunc)(Bar *bar, Arg *arg, BarArg *a); + int (*hoverfunc)(Bar *bar, BarArg *a, XMotionEvent *ev); + char *name; // for debugging + int x, w; // position, width for internal use +} BarRule; + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + + +typedef struct Client Client; +struct Client { + char name[256]; + float mina, maxa; + int x, y, w, h; + unsigned int idx; + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + int fakefullscreen; + int iscentered; + Client *next; + Client *snext; + Monitor *mon; + Window win; +}; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); +} Layout; + + +typedef struct Pertag Pertag; +struct Monitor { + char ltsymbol[16]; + float mfact; + int nmaster; + int num; + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Bar *bar; + const Layout *lt[2]; + Pertag *pertag; +}; + +typedef struct { + const char *class; + const char *instance; + const char *title; + const char *wintype; + unsigned int tags; + int iscentered; + int isfloating; + int monitor; +} Rule; + +#define RULE(...) { .monitor = -1, __VA_ARGS__ }, + +/* Cross patch compatibility rule macro helper macros */ +#define FLOATING , .isfloating = 1 +#define CENTERED , .iscentered = 1 +#define PERMANENT +#define FAKEFULLSCREEN +#define NOSWALLOW +#define TERMINAL +#define SWITCHTAG + + +/* function declarations */ +static void applyrules(Client *c); +static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +static void arrange(Monitor *m); +static void arrangemon(Monitor *m); +static void attach(Client *c); +static void attachstack(Client *c); +static void buttonpress(XEvent *e); +static void checkotherwm(void); +static void cleanup(void); +static void cleanupmon(Monitor *mon); +static void clientmessage(XEvent *e); +static void configure(Client *c); +static void configurenotify(XEvent *e); +static void configurerequest(XEvent *e); +static Monitor *createmon(void); +static void destroynotify(XEvent *e); +static void detach(Client *c); +static void detachstack(Client *c); +static Monitor *dirtomon(int dir); +static void drawbar(Monitor *m); +static void drawbars(void); +static void drawbarwin(Bar *bar); +static void enternotify(XEvent *e); +static void expose(XEvent *e); +static void focus(Client *c); +static void focusin(XEvent *e); +static void focusmon(const Arg *arg); +static void focusstack(const Arg *arg); +static Atom getatomprop(Client *c, Atom prop, Atom req); +static int getrootptr(int *x, int *y); +static long getstate(Window w); +static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, int focused); +static void grabkeys(void); +static void incnmaster(const Arg *arg); +static void keypress(XEvent *e); +static void killclient(const Arg *arg); +static void manage(Window w, XWindowAttributes *wa); +static void mappingnotify(XEvent *e); +static void maprequest(XEvent *e); +static void motionnotify(XEvent *e); +static void movemouse(const Arg *arg); +static Client *nexttiled(Client *c); +static void pop(Client *c); +static void propertynotify(XEvent *e); +static void quit(const Arg *arg); +static Monitor *recttomon(int x, int y, int w, int h); +static void resize(Client *c, int x, int y, int w, int h, int interact); +static void resizeclient(Client *c, int x, int y, int w, int h); +static void resizemouse(const Arg *arg); +static void restack(Monitor *m); +static void run(void); +static void scan(void); +static int sendevent(Client *c, Atom proto); +static void sendmon(Client *c, Monitor *m); +static void setclientstate(Client *c, long state); +static void setfocus(Client *c); +static void setfullscreen(Client *c, int fullscreen); +static void setlayout(const Arg *arg); +static void setmfact(const Arg *arg); +static void setup(void); +static void seturgent(Client *c, int urg); +static void sigchld(int unused); +static void showhide(Client *c); +static void spawn(const Arg *arg); +static void tag(const Arg *arg); +static void tagmon(const Arg *arg); +static void togglebar(const Arg *arg); +static void togglefloating(const Arg *arg); +static void toggletag(const Arg *arg); +static void toggleview(const Arg *arg); +static void unfocus(Client *c, int setfocus, Client *nextfocus); +static void unmanage(Client *c, int destroyed); +static void unmapnotify(XEvent *e); +static void updatebarpos(Monitor *m); +static void updatebars(void); +static void updateclientlist(void); +static int updategeom(void); +static void updatenumlockmask(void); +static void updatesizehints(Client *c); +static void updatestatus(void); +static void updatetitle(Client *c); +static void updatewmhints(Client *c); +static void view(const Arg *arg); +static Client *wintoclient(Window w); +static Monitor *wintomon(Window w); +static int xerror(Display *dpy, XErrorEvent *ee); +static int xerrordummy(Display *dpy, XErrorEvent *ee); +static int xerrorstart(Display *dpy, XErrorEvent *ee); +static void zoom(const Arg *arg); + +/* bar functions */ + +#include "patch/include.h" + +/* variables */ +static const char broken[] = "broken"; +static char stext[1024]; +static char rawstext[1024]; + +static int screen; +static int sw, sh; /* X display screen geometry width, height */ +static int bh; /* bar geometry */ +static int lrpad; /* sum of left and right padding for text */ +/* Some clients (e.g. alacritty) helpfully send configure requests with a new size or position + * when they detect that they have been moved to another monitor. This can cause visual glitches + * when moving (or resizing) client windows from one monitor to another. This variable is used + * internally to ignore such configure requests while movemouse or resizemouse are being used. */ +static int ignoreconfigurerequests = 0; +static int (*xerrorxlib)(Display *, XErrorEvent *); +static unsigned int numlockmask = 0; +static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [Expose] = expose, + [FocusIn] = focusin, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, + [UnmapNotify] = unmapnotify +}; +static Atom wmatom[WMLast], netatom[NetLast]; +static Atom clientatom[ClientLast]; +static int isempty = 0; +static volatile sig_atomic_t running = 1; +static Cur *cursor[CurLast]; +static Clr **scheme; +static Display *dpy; +static Drw *drw; +static Monitor *mons, *selmon; +static Window root, wmcheckwin; + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +#include "patch/include.c" + +/* compile-time check if all tags fit into an unsigned int bit array. */ +struct NumTags { char limitexceeded[NUMTAGS > 31 ? -1 : 1]; }; + +/* function implementations */ +void +applyrules(Client *c) +{ + const char *class, *instance; + Atom wintype; + unsigned int i; + const Rule *r; + Monitor *m; + XClassHint ch = { NULL, NULL }; + + /* rule matching */ + c->isfloating = 0; + c->tags = 0; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM); + + + for (i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if ((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance)) + && (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False))) + { + c->iscentered = r->iscentered; + c->isfloating = r->isfloating; + c->tags |= r->tags; + if ((r->tags & SPTAGMASK) && r->isfloating) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; + + } + } + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK); +} + +int +applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) +{ + int baseismin; + Monitor *m = c->mon; + + /* set minimum possible */ + *w = MAX(1, *w); + *h = MAX(1, *h); + if (interact) { + if (*x > sw) + *x = sw - WIDTH(c); + if (*y > sh) + *y = sh - HEIGHT(c); + if (*x + *w + 2 * c->bw < 0) + *x = 0; + if (*y + *h + 2 * c->bw < 0) + *y = 0; + } else { + if (*x >= m->wx + m->ww) + *x = m->wx + m->ww - WIDTH(c); + if (*y >= m->wy + m->wh) + *y = m->wy + m->wh - HEIGHT(c); + if (*x + *w + 2 * c->bw <= m->wx) + *x = m->wx; + if (*y + *h + 2 * c->bw <= m->wy) + *y = m->wy; + } + if (*h < bh) + *h = bh; + if (*w < bh) + *w = bh; + if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + if (!c->hintsvalid) + updatesizehints(c); + /* see last two sentences in ICCCM 4.1.2.3 */ + baseismin = c->basew == c->minw && c->baseh == c->minh; + if (!baseismin) { /* temporarily remove base dimensions */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for aspect limits */ + if (c->mina > 0 && c->maxa > 0) { + if (c->maxa < (float)*w / *h) + *w = *h * c->maxa + 0.5; + else if (c->mina < (float)*h / *w) + *h = *w * c->mina + 0.5; + } + if (baseismin) { /* increment calculation requires this */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for increment value */ + if (c->incw) + *w -= *w % c->incw; + if (c->inch) + *h -= *h % c->inch; + /* restore base dimensions */ + *w = MAX(*w + c->basew, c->minw); + *h = MAX(*h + c->baseh, c->minh); + if (c->maxw) + *w = MIN(*w, c->maxw); + if (c->maxh) + *h = MIN(*h, c->maxh); + } + return *x != c->x || *y != c->y || *w != c->w || *h != c->h; +} + +void +arrange(Monitor *m) +{ + if (m) + showhide(m->stack); + else for (m = mons; m; m = m->next) + showhide(m->stack); + if (m) { + arrangemon(m); + restack(m); + } else for (m = mons; m; m = m->next) + arrangemon(m); +} + +void +arrangemon(Monitor *m) +{ + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); +} + +void +attach(Client *c) +{ + c->next = c->mon->clients; + c->mon->clients = c; +} + +void +attachstack(Client *c) +{ + c->snext = c->mon->stack; + c->mon->stack = c; +} + +void +buttonpress(XEvent *e) +{ + int click, i, r; + Arg arg = {0}; + Client *c; + Monitor *m; + Bar *bar; + XButtonPressedEvent *ev = &e->xbutton; + const BarRule *br; + BarArg carg = { 0, 0, 0, 0 }; + click = ClkRootWin; + + + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon + ) { + unfocus(selmon->sel, 1, NULL); + selmon = m; + focus(NULL); + } + + for (bar = selmon->bar; bar; bar = bar->next) { + if (ev->window == bar->win) { + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->clickfunc == NULL) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + if (bar->x[r] <= ev->x && ev->x <= bar->x[r] + bar->w[r]) { + carg.x = ev->x - bar->x[r]; + carg.y = ev->y - bar->borderpx; + carg.w = bar->w[r]; + carg.h = bar->bh - 2 * bar->borderpx; + click = br->clickfunc(bar, &arg, &carg); + if (click < 0) + return; + break; + } + } + break; + } + } + + + if (click == ClkRootWin && (c = wintoclient(ev->window))) { + focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } + + for (i = 0; i < LENGTH(buttons); i++) { + if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) { + buttons[i].func( + ( + click == ClkTagBar + ) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg + ); + } + } +} + +void +checkotherwm(void) +{ + xerrorxlib = XSetErrorHandler(xerrorstart); + /* this causes an error if some other window manager is running */ + XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); + XSync(dpy, False); + XSetErrorHandler(xerror); + XSync(dpy, False); +} + +void +cleanup(void) +{ + Monitor *m; + Layout foo = { "", NULL }; + size_t i; + + + for (m = mons; m; m = m->next) + persistmonitorstate(m); + + /* kill child processes */ + for (i = 0; i < autostart_len; i++) { + if (0 < autostart_pids[i]) { + kill(autostart_pids[i], SIGTERM); + waitpid(autostart_pids[i], NULL, 0); + } + } + + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) + while (m->stack) + unmanage(m->stack, 0); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); + for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for (i = 0; i < LENGTH(colors) + 1; i++) + free(scheme[i]); + free(scheme); + XDestroyWindow(dpy, wmcheckwin); + drw_free(drw); + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + +} + +void +cleanupmon(Monitor *mon) +{ + Monitor *m; + Bar *bar; + + if (mon == mons) + mons = mons->next; + else { + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } + for (bar = mon->bar; bar; bar = mon->bar) { + if (!bar->external) { + XUnmapWindow(dpy, bar->win); + XDestroyWindow(dpy, bar->win); + } + mon->bar = bar->next; + free(bar); + } + free(mon->pertag); + free(mon); +} + +void +clientmessage(XEvent *e) +{ + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + + + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) { + if (c->fakefullscreen == 2 && c->isfullscreen) + c->fakefullscreen = 3; + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ + && !c->isfullscreen + ))); + } + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); + } +} + +void +configure(Client *c) +{ + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.display = dpy; + ce.event = c->win; + ce.window = c->win; + ce.x = c->x; + ce.y = c->y; + ce.width = c->w; + ce.height = c->h; + ce.border_width = c->bw; + ce.above = None; + ce.override_redirect = False; + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); +} + +void +configurenotify(XEvent *e) +{ + Monitor *m; + Bar *bar; + Client *c; + XConfigureEvent *ev = &e->xconfigure; + int dirty; + /* TODO: updategeom handling sucks, needs to be simplified */ + if (ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); + sw = ev->width; + sh = ev->height; + if (updategeom() || dirty) { + drw_resize(drw, sw, sh); + updatebars(); + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) + if (c->isfullscreen && c->fakefullscreen != 1) + resizeclient(c, m->mx, m->my, m->mw, m->mh); + for (bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + } + arrange(NULL); + focus(NULL); + } + } +} + +void +configurerequest(XEvent *e) +{ + Client *c; + Monitor *m; + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + if (ignoreconfigurerequests) + return; + + if ((c = wintoclient(ev->window))) { + if (ev->value_mask & CWBorderWidth) + c->bw = ev->border_width; + else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { + m = c->mon; + if (ev->value_mask & CWX) { + c->oldx = c->x; + c->x = m->mx + ev->x; + } + if (ev->value_mask & CWY) { + c->oldy = c->y; + c->y = m->my + ev->y; + } + if (ev->value_mask & CWWidth) { + c->oldw = c->w; + c->w = ev->width; + } + if (ev->value_mask & CWHeight) { + c->oldh = c->h; + c->h = ev->height; + } + if ((c->x + c->w) > m->mx + m->mw && c->isfloating) + c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ + if ((c->y + c->h) > m->my + m->mh && c->isfloating) + c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ + if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) + configure(c); + if (ISVISIBLE(c)) + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } else + configure(c); + } else { + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); + } + XSync(dpy, False); +} + +Monitor * +createmon(void) +{ + Monitor *m, *mon; + int i, n, mi, max_bars = 2, istopbar = topbar; + + const BarRule *br; + Bar *bar; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + for (mi = 0, mon = mons; mon; mon = mon->next, mi++); // monitor index + m->num = mi; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + + /* Derive the number of bars for this monitor based on bar rules */ + for (n = -1, i = 0; i < LENGTH(barrules); i++) { + br = &barrules[i]; + if (br->monitor == 'A' || br->monitor == -1 || br->monitor == m->num) + n = MAX(br->bar, n); + } + + m->bar = NULL; + for (i = 0; i <= n && i < max_bars; i++) { + bar = ecalloc(1, sizeof(Bar)); + bar->mon = m; + bar->idx = i; + bar->next = m->bar; + bar->topbar = istopbar; + m->bar = bar; + istopbar = !istopbar; + bar->showbar = 1; + bar->external = 0; + bar->borderpx = 0; + bar->bh = bh + bar->borderpx * 2; + bar->borderscheme = SchemeNorm; + } + + + if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); + m->pertag->curtag = 1; + for (i = 0; i <= NUMTAGS; i++) { + + /* init nmaster */ + m->pertag->nmasters[i] = m->nmaster; + + /* init mfacts */ + m->pertag->mfacts[i] = m->mfact; + + + + /* init layouts */ + m->pertag->ltidxs[i][0] = m->lt[0]; + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + + } + + restoremonitorstate(m); + + return m; +} + +void +destroynotify(XEvent *e) +{ + Client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); +} + +void +detach(Client *c) +{ + Client **tc; + c->idx = 0; + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; + c->next = NULL; +} + +void +detachstack(Client *c) +{ + Client **tc, *t; + + for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); + *tc = c->snext; + + if (c == c->mon->sel) { + for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); + c->mon->sel = t; + } + c->snext = NULL; +} + +Monitor * +dirtomon(int dir) +{ + Monitor *m = NULL; + + if (dir > 0) { + if (!(m = selmon->next)) + m = mons; + } else if (selmon == mons) + for (m = mons; m->next; m = m->next); + else + for (m = mons; m->next != selmon; m = m->next); + return m; +} + +void +drawbar(Monitor *m) +{ + Bar *bar; + + if (m->showbar) + for (bar = m->bar; bar; bar = bar->next) + drawbarwin(bar); +} + +void +drawbars(void) +{ + Monitor *m; + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +drawbarwin(Bar *bar) +{ + if (!bar || !bar->win || bar->external) + return; + int r, w, total_drawn = 0; + int rx, lx, rw, lw; // bar size, split between left and right if a center module is added + const BarRule *br; + + if (bar->borderpx) { + XSetForeground(drw->dpy, drw->gc, scheme[bar->borderscheme][ColBorder].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, 0, 0, bar->bw, bar->bh); + } + + BarArg warg = { 0 }; + BarArg darg = { 0 }; + warg.h = bar->bh - 2 * bar->borderpx; + + rw = lw = bar->bw - 2 * bar->borderpx; + rx = lx = bar->borderpx; + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, lx, bar->borderpx, lw, bar->bh - 2 * bar->borderpx, 1, 1); + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || !br->widthfunc || (br->monitor == 'A' && bar->mon != selmon)) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + drw_setscheme(drw, scheme[SchemeNorm]); + warg.w = (br->alignment < BAR_ALIGN_RIGHT_LEFT ? lw : rw); + + w = br->widthfunc(bar, &warg); + w = MIN(warg.w, w); + + if (lw <= 0) { // if left is exhausted then switch to right side, and vice versa + lw = rw; + lx = rx; + } else if (rw <= 0) { + rw = lw; + rx = lx; + } + + switch(br->alignment) { + default: + case BAR_ALIGN_NONE: + case BAR_ALIGN_LEFT_LEFT: + case BAR_ALIGN_LEFT: + bar->x[r] = lx; + if (lx == rx) { + rx += w; + rw -= w; + } + lx += w; + lw -= w; + break; + case BAR_ALIGN_LEFT_RIGHT: + case BAR_ALIGN_RIGHT: + bar->x[r] = lx + lw - w; + if (lx == rx) + rw -= w; + lw -= w; + break; + case BAR_ALIGN_LEFT_CENTER: + case BAR_ALIGN_CENTER: + bar->x[r] = lx + lw / 2 - w / 2; + if (lx == rx) { + rw = rx + rw - bar->x[r] - w; + rx = bar->x[r] + w; + } + lw = bar->x[r] - lx; + break; + case BAR_ALIGN_RIGHT_LEFT: + bar->x[r] = rx; + if (lx == rx) { + lx += w; + lw -= w; + } + rx += w; + rw -= w; + break; + case BAR_ALIGN_RIGHT_RIGHT: + bar->x[r] = rx + rw - w; + if (lx == rx) + lw -= w; + rw -= w; + break; + case BAR_ALIGN_RIGHT_CENTER: + bar->x[r] = rx + rw / 2 - w / 2; + if (lx == rx) { + lw = lx + lw - bar->x[r] + w; + lx = bar->x[r] + w; + } + rw = bar->x[r] - rx; + break; + } + bar->w[r] = w; + darg.x = bar->x[r]; + darg.y = bar->borderpx; + darg.h = bar->bh - 2 * bar->borderpx; + darg.w = bar->w[r]; + if (br->drawfunc) + total_drawn += br->drawfunc(bar, &darg); + } + + if (total_drawn == 0 && bar->showbar) { + bar->showbar = 0; + updatebarpos(bar->mon); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(bar->mon); + } + else if (total_drawn > 0 && !bar->showbar) { + bar->showbar = 1; + updatebarpos(bar->mon); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh); + arrange(bar->mon); + } else + drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh); +} + +void +enternotify(XEvent *e) +{ + Client *c; + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + c = wintoclient(ev->window); + m = c ? c->mon : wintomon(ev->window); + if (m != selmon) { + unfocus(selmon->sel, 1, c); + selmon = m; + } else if (!c || c == selmon->sel) + return; + focus(c); +} + +void +expose(XEvent *e) +{ + Monitor *m; + XExposeEvent *ev = &e->xexpose; + + if (ev->count == 0 && (m = wintomon(ev->window))) { + drawbar(m); + } +} + +void +focus(Client *c) +{ + if (!c || !ISVISIBLE(c)) + c = getpointerclient(); + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + if (selmon->sel && selmon->sel != c) + unfocus(selmon->sel, 0, c); + if (c) { + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); + detachstack(c); + attachstack(c); + grabbuttons(c, 1); + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, selmon->bar && selmon->bar->win ? selmon->bar->win : root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; + drawbars(); + + if ((isempty && selmon->sel) || (!isempty && !selmon->sel)) { + isempty = !isempty; + grabkeys(); + } +} + +/* there are some broken focus acquiring clients needing extra handling */ +void +focusin(XEvent *e) +{ + XFocusChangeEvent *ev = &e->xfocus; + + if (selmon->sel && ev->window != selmon->sel->win) + setfocus(selmon->sel); +} + +void +focusmon(const Arg *arg) +{ + Monitor *m; + + if (!mons->next) + return; + if ((m = dirtomon(arg->i)) == selmon) + return; + unfocus(selmon->sel, 0, NULL); + selmon = m; + focus(NULL); +} + +void +focusstack(const Arg *arg) +{ + Client *c = NULL, *i; + + if (!selmon->sel || (selmon->sel->isfullscreen && !selmon->sel->fakefullscreen)) + return; + if (arg->i > 0) { + for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!c) + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i)) + c = i; + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i)) + c = i; + } + if (c) { + focus(c); + restack(selmon); + } +} + +Atom +getatomprop(Client *c, Atom prop, Atom req) +{ + int di; + unsigned long dl; + unsigned char *p = NULL; + Atom da, atom = None; + + + /* FIXME getatomprop should return the number of items and a pointer to + * the stored data instead of this workaround */ + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; + XFree(p); + } + return atom; +} + +int +getrootptr(int *x, int *y) +{ + int di; + unsigned int dui; + Window dummy; + + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); +} + +long +getstate(Window w) +{ + int format; + long result = -1; + unsigned char *p = NULL; + unsigned long n, extra; + Atom real; + + if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], + &real, &format, &n, &extra, (unsigned char **)&p) != Success) + return -1; + if (n != 0) + result = *p; + XFree(p); + return result; +} + +int +gettextprop(Window w, Atom atom, char *text, unsigned int size) +{ + char **list = NULL; + int n; + XTextProperty name; + + if (!text || size == 0) + return 0; + text[0] = '\0'; + if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) + return 0; + if (name.encoding == XA_STRING) { + strncpy(text, (char *)name.value, size - 1); + } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { + strncpy(text, *list, size - 1); + XFreeStringList(list); + } + text[size - 1] = '\0'; + XFree(name.value); + return 1; +} + +void +grabbuttons(Client *c, int focused) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + if (!focused) + XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin + ) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabButton(dpy, buttons[i].button, + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); + } +} + +void +grabkeys(void) +{ + updatenumlockmask(); + { + unsigned int i, j, k; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + int start, end, skip; + KeySym *syms; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + XDisplayKeycodes(dpy, &start, &end); + syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); + if (!syms) + return; + for (k = start; k <= end; k++) + for (i = 0; i < LENGTH(keys); i++) + /* skip modifier codes, we do that ourselves */ + if (keys[i].keysym == syms[(k - start) * skip]) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, k, + keys[i].mod | modifiers[j], + root, True, + GrabModeAsync, GrabModeAsync); + if (!selmon->sel) + for (k = start; k <= end; k++) + for (i = 0; i < LENGTH(on_empty_keys); i++) + /* skip modifier codes, we do that ourselves */ + if (on_empty_keys[i].keysym == syms[(k - start) * skip]) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, k, + on_empty_keys[i].mod | modifiers[j], + root, True, + GrabModeAsync, GrabModeAsync); + XFree(syms); + } +} + +void +incnmaster(const Arg *arg) +{ + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +#ifdef XINERAMA +static int +isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) +{ + while (n--) + if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org + && unique[n].width == info->width && unique[n].height == info->height) + return 0; + return 1; +} +#endif /* XINERAMA */ + +void +keypress(XEvent *e) +{ + unsigned int i; + int keysyms_return; + KeySym* keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XGetKeyboardMapping(dpy, (KeyCode)ev->keycode, 1, &keysyms_return); + for (i = 0; i < LENGTH(keys); i++) + if (*keysym == keys[i].keysym + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) + keys[i].func(&(keys[i].arg)); + if (!selmon->sel) + for (i = 0; i < LENGTH(on_empty_keys); i++) + if (*keysym == on_empty_keys[i].keysym + && CLEANMASK(on_empty_keys[i].mod) == CLEANMASK(ev->state) + && on_empty_keys[i].func) + on_empty_keys[i].func(&(on_empty_keys[i].arg)); + XFree(keysym); +} + +void +killclient(const Arg *arg) +{ + if (!selmon->sel) + return; + if (!sendevent(selmon->sel, wmatom[WMDelete])) + { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } +} + +void +manage(Window w, XWindowAttributes *wa) +{ + Client *c, *t = NULL; + int settings_restored; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + settings_restored = restoreclientstate(c); + updatetitle(c); + + + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; + c->tags = t->tags; + c->bw = borderpx; + if (c->x == c->mon->wx && c->y == c->mon->wy) + c->iscentered = 1; + } else { + if (!settings_restored) + c->mon = selmon; + if (c->x == c->mon->wx && c->y == c->mon->wy) + c->iscentered = 1; + c->bw = borderpx; + if (!settings_restored) + applyrules(c); + } + + + if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) + c->x = c->mon->wx + c->mon->ww - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) + c->y = c->mon->wy + c->mon->wh - HEIGHT(c); + c->x = MAX(c->x, c->mon->wx); + c->y = MAX(c->y, c->mon->wy); + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + if (c->isfloating) + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); + else + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatesizehints(c); + updatewmhints(c); + + if (c->iscentered) { + c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; + c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; + } + + if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + + if (!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) { + XRaiseWindow(dpy, c->win); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); + } + attachx(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + + setclientstate(c, NormalState); + if (c->mon == selmon) + unfocus(selmon->sel, 0, c); + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); + focus(NULL); + +} + +void +mappingnotify(XEvent *e) +{ + XMappingEvent *ev = &e->xmapping; + + XRefreshKeyboardMapping(ev); + if (ev->request == MappingKeyboard) + grabkeys(); +} + +void +maprequest(XEvent *e) +{ + static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; + + + if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) + return; + if (!wintoclient(ev->window)) + manage(ev->window, &wa); +} + +void +motionnotify(XEvent *e) +{ + static Monitor *mon = NULL; + Monitor *m; + Bar *bar; + XMotionEvent *ev = &e->xmotion; + + if ((bar = wintobar(ev->window))) { + barhover(e, bar); + return; + } + + + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + unfocus(selmon->sel, 1, NULL); + selmon = m; + focus(NULL); + } + mon = m; +} + +void +movemouse(const Arg *arg) +{ + int x, y, ocx, ocy, nx, ny; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen && c->fakefullscreen != 1) /* no support moving fullscreen windows by mouse */ + return; + restack(selmon); + nx = ocx = c->x; + ny = ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; + ignoreconfigurerequests = 1; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + if (abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + nx = selmon->wx + selmon->ww - WIDTH(c); + if (abs(selmon->wy - ny) < snap) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) { + togglefloating(NULL); + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + resize(c, nx, ny, c->w, c->h, 1); + } + break; + } + } while (ev.type != ButtonRelease); + + XUngrabPointer(dpy, CurrentTime); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + if (c->tags & SPTAGMASK) { + c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK); + m->tagset[m->seltags] |= (c->tags & SPTAGMASK); + } + sendmon(c, m); + selmon = m; + focus(NULL); + } + ignoreconfigurerequests = 0; +} + +Client * +nexttiled(Client *c) +{ + for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + return c; +} + +void +pop(Client *c) +{ + detach(c); + attach(c); + focus(c); + arrange(c->mon); +} + +void +propertynotify(XEvent *e) +{ + Client *c; + Window trans; + XPropertyEvent *ev = &e->xproperty; + + + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) { + updatestatus(); + } else if (ev->state == PropertyDelete) { + return; /* ignore */ + } else if ((c = wintoclient(ev->window))) { + switch(ev->atom) { + default: break; + case XA_WM_TRANSIENT_FOR: + if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && + (c->isfloating = (wintoclient(trans)) != NULL)) + arrange(c->mon); + break; + case XA_WM_NORMAL_HINTS: + c->hintsvalid = 0; + break; + case XA_WM_HINTS: + updatewmhints(c); + if (c->isurgent) + drawbars(); + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); + } + } +} + +void +quit(const Arg *arg) +{ + restart = arg->i; + running = 0; +} + +Monitor * +recttomon(int x, int y, int w, int h) +{ + Monitor *m, *r = selmon; + int a, area = 0; + + for (m = mons; m; m = m->next) + if ((a = INTERSECT(x, y, w, h, m)) > area) { + area = a; + r = m; + } + return r; +} + +void +resize(Client *c, int x, int y, int w, int h, int interact) +{ + if (applysizehints(c, &x, &y, &w, &h, interact)) + resizeclient(c, x, y, w, h); +} + +void +resizeclient(Client *c, int x, int y, int w, int h) +{ + XWindowChanges wc; + + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; + if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) + || &monocle == c->mon->lt[c->mon->sellt]->arrange + ) + && (c->fakefullscreen == 1 || !c->isfullscreen) + && !c->isfloating + && c->mon->lt[c->mon->sellt]->arrange) { + c->w = wc.width += c->bw * 2; + c->h = wc.height += c->bw * 2; + wc.border_width = 0; + } + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +} + +void +resizemouse(const Arg *arg) +{ + int ocx, ocy, nw, nh, nx, ny; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen && c->fakefullscreen != 1) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); + nx = ocx = c->x; + ny = ocy = c->y; + nh = c->h; + nw = c->w; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + ignoreconfigurerequests = 1; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) + { + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) { + togglefloating(NULL); + } + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + resize(c, nx, ny, nw, nh, 1); + } + break; + } + } while (ev.type != ButtonRelease); + + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + if (c->tags & SPTAGMASK) { + c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK); + m->tagset[m->seltags] |= (c->tags & SPTAGMASK); + } + sendmon(c, m); + selmon = m; + focus(NULL); + } + ignoreconfigurerequests = 0; +} + +void +restack(Monitor *m) +{ + Client *c, *f = NULL; + XEvent ev; + XWindowChanges wc; + + drawbar(m); + if (!m->sel) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + if (m->bar) { + wc.sibling = m->bar->win; + } else { + for (f = m->stack; f && (f->isfloating || !ISVISIBLE(f)); f = f->snext); // find first tiled stack client + if (f) + wc.sibling = f->win; + } + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c) && c != f) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } + } + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +void +run(void) +{ + XEvent ev; + XSync(dpy, False); + /* main event loop */ + while (running) { + struct pollfd pfd = { + .fd = ConnectionNumber(dpy), + .events = POLLIN, + }; + int pending = XPending(dpy) > 0 || poll(&pfd, 1, -1) > 0; + + if (!running) + break; + if (!pending) + continue; + + XNextEvent(dpy, &ev); + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ + } +} + +void +scan(void) +{ + unsigned int i, num; + Window d1, d2, *wins = NULL; + XWindowAttributes wa; + + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { + for (i = 0; i < num; i++) { + if (!XGetWindowAttributes(dpy, wins[i], &wa) + || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) + continue; + if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + manage(wins[i], &wa); + } + for (i = 0; i < num; i++) { /* now the transients */ + if (!XGetWindowAttributes(dpy, wins[i], &wa)) + continue; + if (XGetTransientForHint(dpy, wins[i], &d1) + && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) + manage(wins[i], &wa); + } + XFree(wins); + } +} + +void +sendmon(Client *c, Monitor *m) +{ + if (c->mon == m) + return; + unfocus(c, 1, NULL); + detach(c); + detachstack(c); + c->mon = m; + if (!(c->tags & SPTAGMASK)) + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); + arrange(NULL); + focus(NULL); +} + +void +setclientstate(Client *c, long state) +{ + long data[] = { state, None }; + + XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, + PropModeReplace, (unsigned char *)data, 2); +} + +int +sendevent(Client *c, Atom proto) +{ + int n; + Atom *protocols; + int exists = 0; + XEvent ev; + + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + + if (exists) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = proto; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + return exists; +} + +void +setfocus(Client *c) +{ + if (!c->neverfocus) { + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } + sendevent(c, wmatom[WMTakeFocus]); +} + +void +setfullscreen(Client *c, int fullscreen) +{ + XEvent ev; + int savestate = 0, restorestate = 0; + + if ((c->fakefullscreen == 0 && fullscreen && !c->isfullscreen) // normal fullscreen + || (c->fakefullscreen == 2 && fullscreen)) // fake fullscreen --> actual fullscreen + savestate = 1; // go actual fullscreen + else if ((c->fakefullscreen == 0 && !fullscreen && c->isfullscreen) // normal fullscreen exit + || (c->fakefullscreen >= 2 && !fullscreen)) // fullscreen exit --> fake fullscreen + restorestate = 1; // go back into tiled + + /* If leaving fullscreen and the window was previously fake fullscreen (2), then restore + * that while staying in fullscreen. The exception to this is if we are in said state, but + * the client itself disables fullscreen (3) then we let the client go out of fullscreen + * while keeping fake fullscreen enabled (as otherwise there will be a mismatch between the + * client and the window manager's perception of the client's fullscreen state). */ + if (c->fakefullscreen == 2 && !fullscreen && c->isfullscreen) { + c->fakefullscreen = 1; + c->isfullscreen = 1; + fullscreen = 1; + } else if (c->fakefullscreen == 3) // client exiting actual fullscreen + c->fakefullscreen = 1; + + if (fullscreen != c->isfullscreen) { // only send property change if necessary + if (fullscreen) + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + else + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + } + + c->isfullscreen = fullscreen; + + /* Some clients, e.g. firefox, will send a client message informing the window manager + * that it is going into fullscreen after receiving the above signal. This has the side + * effect of this function (setfullscreen) sometimes being called twice when toggling + * fullscreen on and off via the window manager as opposed to the application itself. + * To protect against obscure issues where the client settings are stored or restored + * when they are not supposed to we add an additional bit-lock on the old state so that + * settings can only be stored and restored in that precise order. */ + if (savestate && !(c->oldstate & (1 << 1))) { + c->oldbw = c->bw; + c->oldstate = c->isfloating | (1 << 1); + c->bw = 0; + c->isfloating = 1; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } else if (restorestate && (c->oldstate & (1 << 1))) { + c->bw = c->oldbw; + c->isfloating = c->oldstate = c->oldstate & 1; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + restack(c->mon); + } else + resizeclient(c, c->x, c->y, c->w, c->h); + + /* Exception: if the client was in actual fullscreen and we exit out to fake fullscreen + * mode, then the focus would sometimes drift to whichever window is under the mouse cursor + * at the time. To avoid this we ask X for all EnterNotify events and just ignore them. + */ + if (!c->isfullscreen) + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +void +setlayout(const Arg *arg) +{ + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { + selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + } + if (arg && arg->v) + selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); + else + drawbar(selmon); +} + +/* arg > 1.0 will set mfact absolutely */ +void +setmfact(const Arg *arg) +{ + float f; + + if (!arg || !selmon->lt[selmon->sellt]->arrange) + return; + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; + arrange(selmon); +} + +void +setup(void) +{ + int i; + XSetWindowAttributes wa; + Atom utf8string; + /* clean up any zombies immediately */ + sigchld(0); + + signal(SIGHUP, sighup); + signal(SIGTERM, sigterm); + + /* the one line of bloat that would have saved a lot of time for a lot of people */ + putenv("_JAVA_AWT_WM_NONREPARENTING=1"); + + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + drw = drw_create(dpy, screen, root, sw, sh); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + clientatom[ClientFields] = XInternAtom(dpy, "_DWM_CLIENT_FIELDS", False); + clientatom[ClientTags] = XInternAtom(dpy, "_DWM_CLIENT_TAGS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ + scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *)); + scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], ColCount); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], ColCount); + + updatebars(); + updatestatus(); + + /* supporting window for NetWMCheck */ + wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "dwm", 3); + XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + /* EWMH support per view */ + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, + PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); + /* select events */ + wa.cursor = cursor[CurNormal]->cursor; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); + XSelectInput(dpy, root, wa.event_mask); + + + grabkeys(); + focus(NULL); +} + + +void +seturgent(Client *c, int urg) +{ + XWMHints *wmh; + + c->isurgent = urg; + if (!(wmh = XGetWMHints(dpy, c->win))) + return; + wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); + XSetWMHints(dpy, c->win, wmh); + XFree(wmh); +} + +void +showhide(Client *c) +{ + if (!c) + return; + if (ISVISIBLE(c)) { + if ( + (c->tags & SPTAGMASK) && + c->isfloating && + ( + c->x < c->mon->mx || + c->x > c->mon->mx + c->mon->mw || + c->y < c->mon->my || + c->y > c->mon->my + c->mon->mh + ) + ) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) + && !c->isfullscreen + ) + resize(c, c->x, c->y, c->w, c->h, 0); + showhide(c->snext); + } else { + /* hide clients bottom up */ + showhide(c->snext); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); + } +} + +void +sigchld(int unused) +{ + pid_t pid; + + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); + + while (0 < (pid = waitpid(-1, NULL, WNOHANG))) { + pid_t *p, *lim; + + if (!(p = autostart_pids)) + continue; + lim = &p[autostart_len]; + + for (; p < lim; p++) { + if (*p == pid) { + *p = -1; + break; + } + } + } +} + +void +spawn(const Arg *arg) +{ + struct sigaction sa; + + + if (fork() == 0) + { + if (dpy) + close(ConnectionNumber(dpy)); + + setsid(); + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); + + execvp(((char **)arg->v)[0], (char **)arg->v); + die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); + } +} + +void +tag(const Arg *arg) +{ + + if (selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; + arrange(selmon); + focus(NULL); + } +} + +void +tagmon(const Arg *arg) +{ + Client *c = selmon->sel; + Monitor *dest; + if (!c || !mons->next) + return; + dest = dirtomon(arg->i); + sendmon(c, dest); +} + +void +togglebar(const Arg *arg) +{ + Bar *bar; + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); + for (bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(selmon); +} + +void +togglefloating(const Arg *arg) +{ + Client *c = selmon->sel; + if (arg && arg->v) + c = (Client*)arg->v; + if (!c) + return; + if (c->isfullscreen && c->fakefullscreen != 1) /* no support for fullscreen windows */ + return; + c->isfloating = !c->isfloating || c->isfixed; + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + if (c->isfloating) { + resize(c, c->x, c->y, c->w, c->h, 0); + } + arrange(c->mon); + +} + +void +toggletag(const Arg *arg) +{ + unsigned int newtags; + + if (!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; + arrange(selmon); + focus(NULL); + } +} + +void +toggleview(const Arg *arg) +{ + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);; + int i; + + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + + if (newtagset == ~SPTAGMASK) + { + selmon->pertag->curtag = 0; + } + /* test if the user did not select the same tag */ + if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { + for (i = 0; !(newtagset & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + + /* apply settings for this view */ + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + arrange(selmon); + focus(NULL); + } +} + +void +unfocus(Client *c, int setfocus, Client *nextfocus) +{ + if (!c) + return; + grabbuttons(c, 0); + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } +} + +void +unmanage(Client *c, int destroyed) +{ + Monitor *m; + XWindowChanges wc; + + m = c->mon; + + + detach(c); + detachstack(c); + if (!destroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); /* avoid race conditions */ + XSetErrorHandler(xerrordummy); + XSelectInput(dpy, c->win, NoEventMask); + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + + + free(c); + arrange(m); + focus(NULL); + updateclientlist(); +} + +void +unmapnotify(XEvent *e) +{ + Client *c; + XUnmapEvent *ev = &e->xunmap; + + if ((c = wintoclient(ev->window))) { + if (ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, 0); + } +} + +void +updatebars(void) +{ + Bar *bar; + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixmap = ParentRelative, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + for (bar = m->bar; bar; bar = bar->next) { + if (bar->external) + continue; + if (!bar->win) { + bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, bar->win, cursor[CurNormal]->cursor); + XMapRaised(dpy, bar->win); + XSetClassHint(dpy, bar->win, &ch); + } + } + } +} + +void +updatebarpos(Monitor *m) +{ + + m->wx = m->mx; + m->wy = m->my; + m->ww = m->mw; + m->wh = m->mh; + Bar *bar; + int y_pad = 0; + int x_pad = 0; + + + for (bar = m->bar; bar; bar = bar->next) { + bar->bx = m->wx + x_pad; + bar->bw = m->ww - 2 * x_pad; + } + + for (bar = m->bar; bar; bar = bar->next) + if (!m->showbar || !bar->showbar) + bar->by = -bar->bh - y_pad; + + + if (!m->showbar) + return; + for (bar = m->bar; bar; bar = bar->next) { + if (!bar->showbar) + continue; + if (bar->topbar) + m->wy = m->wy + bar->bh + y_pad; + m->wh -= y_pad + bar->bh; + bar->by = (bar->topbar ? m->wy - bar->bh : m->wy + m->wh); + } +} + +void +updateclientlist() +{ + Client *c; + Monitor *m; + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + +} + +int +updategeom(void) +{ + int dirty = 0; + +#ifdef XINERAMA + if (XineramaIsActive(dpy)) { + int i, j, n, nn; + Client *c; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + for (n = 0, m = mons; m; m = m->next, n++); + /* only consider unique geometries as separate screens */ + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); + for (i = 0, j = 0; i < nn; i++) + if (isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); + XFree(info); + nn = j; + /* new monitors if nn > n */ + for (i = n; i < nn; i++) { + for (m = mons; m && m->next; m = m->next); + if (m) + m->next = createmon(); + else + mons = createmon(); + } + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) + { + dirty = 1; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } + /* removed monitors if n > nn */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + dirty = 1; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + if (m == selmon) + selmon = mons; + cleanupmon(m); + } + free(unique); + } else +#endif /* XINERAMA */ + { /* default monitor setup */ + if (!mons) + mons = createmon(); + if (mons->mw != sw || mons->mh != sh) { + dirty = 1; + mons->mw = mons->ww = sw; + mons->mh = mons->wh = sh; + updatebarpos(mons); + } + } + if (dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; +} + +void +updatenumlockmask(void) +{ + unsigned int i, j; + XModifierKeymap *modmap; + + numlockmask = 0; + modmap = XGetModifierMapping(dpy); + for (i = 0; i < 8; i++) + for (j = 0; j < modmap->max_keypermod; j++) + if (modmap->modifiermap[i * modmap->max_keypermod + j] + == XKeysymToKeycode(dpy, XK_Num_Lock)) + numlockmask = (1 << i); + XFreeModifiermap(modmap); +} + +void +updatesizehints(Client *c) +{ + long msize; + XSizeHints size; + + if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) + /* size is uninitialized, ensure that size.flags aren't used */ + size.flags = PSize; + if (size.flags & PBaseSize) { + c->basew = size.base_width; + c->baseh = size.base_height; + } else if (size.flags & PMinSize) { + c->basew = size.min_width; + c->baseh = size.min_height; + } else + c->basew = c->baseh = 0; + if (size.flags & PResizeInc) { + c->incw = size.width_inc; + c->inch = size.height_inc; + } else + c->incw = c->inch = 0; + if (size.flags & PMaxSize) { + c->maxw = size.max_width; + c->maxh = size.max_height; + } else + c->maxw = c->maxh = 0; + if (size.flags & PMinSize) { + c->minw = size.min_width; + c->minh = size.min_height; + } else if (size.flags & PBaseSize) { + c->minw = size.base_width; + c->minh = size.base_height; + } else + c->minw = c->minh = 0; + if (size.flags & PAspect) { + c->mina = (float)size.min_aspect.y / size.min_aspect.x; + c->maxa = (float)size.max_aspect.x / size.max_aspect.y; + } else + c->maxa = c->mina = 0.0; + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); + c->hintsvalid = 1; +} + +void +updatestatus(void) +{ + Monitor *m; + if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) + strcpy(stext, "dwm-"VERSION); + else + copyvalidchars(stext, rawstext); + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +updatetitle(Client *c) +{ + + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) + gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); + if (c->name[0] == '\0') /* hack to mark broken clients */ + strcpy(c->name, broken); + +} + +void +updatewmhints(Client *c) +{ + XWMHints *wmh; + + if ((wmh = XGetWMHints(dpy, c->win))) { + if (c == selmon->sel && wmh->flags & XUrgencyHint) { + wmh->flags &= ~XUrgencyHint; + XSetWMHints(dpy, c->win, wmh); + } else + c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; + if (c->isurgent) { + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColBorder].pixel); + } + if (wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = 0; + XFree(wmh); + } +} + +void +view(const Arg *arg) +{ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + { + view(&((Arg) { .ui = 0 })); + return; + } + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + pertagview(arg); + arrange(selmon); + focus(NULL); +} + +Client * +wintoclient(Window w) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + if (c->win == w) + return c; + return NULL; +} + +Monitor * +wintomon(Window w) +{ + int x, y; + Client *c; + Monitor *m; + Bar *bar; + + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + for (bar = m->bar; bar; bar = bar->next) + if (w == bar->win) + return m; + if ((c = wintoclient(w))) + return c->mon; + return selmon; +} + +/* There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ +int +xerror(Display *dpy, XErrorEvent *ee) +{ + if (ee->error_code == BadWindow + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) + || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) + return 0; + fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", + ee->request_code, ee->error_code); + return xerrorxlib(dpy, ee); /* may call exit */ +} + +int +xerrordummy(Display *dpy, XErrorEvent *ee) +{ + return 0; +} + +/* Startup Error handler to check if another window manager + * is already running. */ +int +xerrorstart(Display *dpy, XErrorEvent *ee) +{ + die("dwm: another window manager is already running"); + return -1; +} + +void +zoom(const Arg *arg) +{ + Client *c = selmon->sel; + if (arg && arg->v) + c = (Client*)arg->v; + if (!c) + return; + + + + if (!c->mon->lt[c->mon->sellt]->arrange || !c || c->isfloating) + return; + + if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) + return; + pop(c); +} + +int +main(int argc, char *argv[]) +{ + if (argc == 2 && !strcmp("-v", argv[1])) + die("dwm-"VERSION); + else if (argc != 1) + die("usage: dwm [-v]"); + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + checkotherwm(); + XrmInitialize(); + loadxrdb(); + autostart_exec(); + setup(); +#ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec", NULL) == -1) + die("pledge"); +#endif /* __OpenBSD__ */ + scan(); + run(); + cleanup(); + XCloseDisplay(dpy); + if (restart) + execvp(argv[0], argv); + return EXIT_SUCCESS; +} + diff --git a/.config/suckless/dwm/dwm.desktop b/.config/suckless/dwm/dwm.desktop new file mode 100644 index 0000000..b0c3354 --- /dev/null +++ b/.config/suckless/dwm/dwm.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Dwm +Comment=Dynamic window manager +Exec=dwm +Icon=dwm +Type=XSession diff --git a/.config/suckless/dwm/dwm.png b/.config/suckless/dwm/dwm.png new file mode 100644 index 0000000..b1f9ba7 Binary files /dev/null and b/.config/suckless/dwm/dwm.png differ diff --git a/.config/suckless/dwm/patch/attachx.c b/.config/suckless/dwm/patch/attachx.c new file mode 100644 index 0000000..83057d6 --- /dev/null +++ b/.config/suckless/dwm/patch/attachx.c @@ -0,0 +1,22 @@ +void +attachx(Client *c) +{ + Client *at; + + if (c->idx > 0) { /* then the client has a designated position in the client list */ + for (at = c->mon->clients; at; at = at->next) { + if (c->idx < at->idx) { + c->next = at; + c->mon->clients = c; + return; + } else if (at->idx <= c->idx && (!at->next || c->idx <= at->next->idx)) { + c->next = at->next; + at->next = c; + return; + } + } + } + + attach(c); // master (default) +} + diff --git a/.config/suckless/dwm/patch/attachx.h b/.config/suckless/dwm/patch/attachx.h new file mode 100644 index 0000000..e522d27 --- /dev/null +++ b/.config/suckless/dwm/patch/attachx.h @@ -0,0 +1,2 @@ +static void attachx(Client *c); + diff --git a/.config/suckless/dwm/patch/bar.c b/.config/suckless/dwm/patch/bar.c new file mode 100644 index 0000000..65e1a69 --- /dev/null +++ b/.config/suckless/dwm/patch/bar.c @@ -0,0 +1,39 @@ +void +barhover(XEvent *e, Bar *bar) +{ + const BarRule *br; + Monitor *m = bar->mon; + XMotionEvent *ev = &e->xmotion; + BarArg barg = { 0, 0, 0, 0 }; + int r; + + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->hoverfunc == NULL) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + if (bar->x[r] > ev->x || ev->x > bar->x[r] + bar->w[r]) + continue; + + barg.x = ev->x - bar->x[r]; + barg.y = ev->y - bar->borderpx; + barg.w = bar->w[r]; + barg.h = bar->bh - 2 * bar->borderpx; + + br->hoverfunc(bar, &barg, ev); + break; + } +} + +Bar * +wintobar(Window win) +{ + Monitor *m; + Bar *bar; + for (m = mons; m; m = m->next) + for (bar = m->bar; bar; bar = bar->next) + if (bar->win == win) + return bar; + return NULL; +} diff --git a/.config/suckless/dwm/patch/bar.h b/.config/suckless/dwm/patch/bar.h new file mode 100644 index 0000000..3e006dc --- /dev/null +++ b/.config/suckless/dwm/patch/bar.h @@ -0,0 +1,2 @@ +static void barhover(XEvent *e, Bar *bar); +static Bar *wintobar(Window win); diff --git a/.config/suckless/dwm/patch/bar_dwmblocks.c b/.config/suckless/dwm/patch/bar_dwmblocks.c new file mode 100644 index 0000000..0a4b097 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_dwmblocks.c @@ -0,0 +1,41 @@ +static int statussig; +pid_t statuspid = -1; + +pid_t +getstatusbarpid() +{ + char buf[32], *str = buf, *c; + FILE *fp; + + if (statuspid > 0) { + snprintf(buf, sizeof(buf), "/proc/%u/cmdline", statuspid); + if ((fp = fopen(buf, "r"))) { + fgets(buf, sizeof(buf), fp); + while ((c = strchr(str, '/'))) + str = c + 1; + fclose(fp); + if (!strcmp(str, STATUSBAR)) + return statuspid; + } + } + if (!(fp = popen("pgrep -o "STATUSBAR, "r"))) + return -1; + fgets(buf, sizeof(buf), fp); + pclose(fp); + return strtol(buf, NULL, 10); +} + +void +sigstatusbar(const Arg *arg) +{ + union sigval sv; + + if (!statussig) + return; + if ((statuspid = getstatusbarpid()) <= 0) + return; + + sv.sival_int = arg->i; + sigqueue(statuspid, SIGRTMIN+statussig, sv); +} + diff --git a/.config/suckless/dwm/patch/bar_dwmblocks.h b/.config/suckless/dwm/patch/bar_dwmblocks.h new file mode 100644 index 0000000..4db9467 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_dwmblocks.h @@ -0,0 +1,3 @@ +static int getstatusbarpid(); +static void sigstatusbar(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/bar_indicators.c b/.config/suckless/dwm/patch/bar_indicators.c new file mode 100644 index 0000000..ad17a39 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_indicators.c @@ -0,0 +1,109 @@ +/* Indicator properties, you can override these in your config.h if you want. */ +#ifndef TAGSINDICATOR +#define TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on +#endif +#ifndef TAGSPX +#define TAGSPX 5 // # pixels for tag grid boxes +#endif +#ifndef TAGSROWS +#define TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3) +#endif + +void +drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type) +{ + int i, boxw, boxs, indn = 0; + if (!(occ & 1 << tag) || type == INDICATOR_NONE) + return; + + boxs = drw->fonts->h / 9; + boxw = drw->fonts->h / 6 + 2; + if (filled == -1) + filled = m == selmon && m->sel && m->sel->tags & 1 << tag; + + switch (type) { + default: + case INDICATOR_TOP_LEFT_SQUARE: + drw_rect(drw, x + boxs, y + boxs, boxw, boxw, filled, invert); + break; + case INDICATOR_TOP_LEFT_LARGER_SQUARE: + drw_rect(drw, x + boxs + 2, y + boxs+1, boxw+1, boxw+1, filled, invert); + break; + case INDICATOR_TOP_BAR: + drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), boxw/2, filled, invert); + break; + case INDICATOR_TOP_BAR_SLIM: + drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), 1, 0, invert); + break; + case INDICATOR_BOTTOM_BAR: + drw_rect(drw, x + boxw, y + h - boxw/2, w - ( 2 * boxw + 1), boxw/2, filled, invert); + break; + case INDICATOR_BOTTOM_BAR_SLIM: + drw_rect(drw, x + boxw, y + h - 1, w - ( 2 * boxw + 1), 1, 0, invert); + break; + case INDICATOR_BOX: + drw_rect(drw, x + boxw, y, w - 2 * boxw, h, 0, invert); + break; + case INDICATOR_BOX_WIDER: + drw_rect(drw, x + boxw/2, y, w - boxw, h, 0, invert); + break; + case INDICATOR_BOX_FULL: + drw_rect(drw, x, y, w - 2, h, 0, invert); + break; + case INDICATOR_CLIENT_DOTS: + for (c = m->clients; c; c = c->next) { + if (c->tags & (1 << tag)) { + drw_rect(drw, x, 1 + (indn * 2), m->sel == c ? 6 : 1, 1, 1, invert); + indn++; + } + if (h <= 1 + (indn * 2)) { + indn = 0; + x += 2; + } + } + break; + case INDICATOR_RIGHT_TAGS: + if (!c) + break; + for (i = 0; i < NUMTAGS; i++) { + drw_rect(drw, + ( x + w - 2 - ((NUMTAGS / TAGSROWS) * TAGSPX) + - (i % (NUMTAGS/TAGSROWS)) + ((i % (NUMTAGS / TAGSROWS)) * TAGSPX) + ), + ( y + 2 + ((i / (NUMTAGS/TAGSROWS)) * TAGSPX) + - ((i / (NUMTAGS/TAGSROWS))) + ), + TAGSPX, TAGSPX, (c->tags >> i) & 1, 0 + ); + } + break; + case INDICATOR_PLUS_AND_LARGER_SQUARE: + boxs += 2; + boxw += 2; + /* falls through */ + case INDICATOR_PLUS_AND_SQUARE: + drw_rect(drw, x + boxs, y + boxs, boxw % 2 ? boxw : boxw + 1, boxw % 2 ? boxw : boxw + 1, filled, invert); + /* falls through */ + case INDICATOR_PLUS: + if (!(boxw % 2)) + boxw += 1; + drw_rect(drw, x + boxs + boxw / 2, y + boxs, 1, boxw, filled, invert); // | + drw_rect(drw, x + boxs, y + boxs + boxw / 2, boxw + 1, 1, filled, invert); // ‒ + break; + } +} + +void +drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert) +{ + if (c->fakefullscreen && c->isfloating) + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatfakefsindicatortype); + else if (c->fakefullscreen) + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, fakefsindicatortype); + else + if (c->isfloating) + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatindicatortype); + else + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, tiledindicatortype); +} + diff --git a/.config/suckless/dwm/patch/bar_indicators.h b/.config/suckless/dwm/patch/bar_indicators.h new file mode 100644 index 0000000..c66e4f0 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_indicators.h @@ -0,0 +1,21 @@ +enum { + INDICATOR_NONE, + INDICATOR_TOP_LEFT_SQUARE, + INDICATOR_TOP_LEFT_LARGER_SQUARE, + INDICATOR_TOP_BAR, + INDICATOR_TOP_BAR_SLIM, + INDICATOR_BOTTOM_BAR, + INDICATOR_BOTTOM_BAR_SLIM, + INDICATOR_BOX, + INDICATOR_BOX_WIDER, + INDICATOR_BOX_FULL, + INDICATOR_CLIENT_DOTS, + INDICATOR_RIGHT_TAGS, + INDICATOR_PLUS, + INDICATOR_PLUS_AND_SQUARE, + INDICATOR_PLUS_AND_LARGER_SQUARE, +}; + +static void drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type); +static void drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert); + diff --git a/.config/suckless/dwm/patch/bar_ltsymbol.c b/.config/suckless/dwm/patch/bar_ltsymbol.c new file mode 100644 index 0000000..1fbd1b8 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_ltsymbol.c @@ -0,0 +1,18 @@ +int +width_ltsymbol(Bar *bar, BarArg *a) +{ + return TEXTW(bar->mon->ltsymbol); +} + +int +draw_ltsymbol(Bar *bar, BarArg *a) +{ + return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, bar->mon->ltsymbol, 0, False); +} + +int +click_ltsymbol(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkLtSymbol; +} + diff --git a/.config/suckless/dwm/patch/bar_ltsymbol.h b/.config/suckless/dwm/patch/bar_ltsymbol.h new file mode 100644 index 0000000..4de5720 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_ltsymbol.h @@ -0,0 +1,4 @@ +static int width_ltsymbol(Bar *bar, BarArg *a); +static int draw_ltsymbol(Bar *bar, BarArg *a); +static int click_ltsymbol(Bar *bar, Arg *arg, BarArg *a); + diff --git a/.config/suckless/dwm/patch/bar_status.c b/.config/suckless/dwm/patch/bar_status.c new file mode 100644 index 0000000..65595e0 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_status.c @@ -0,0 +1,20 @@ +int +width_status(Bar *bar, BarArg *a) +{ + return TEXTWM(stext); +} + + +int +draw_status(Bar *bar, BarArg *a) +{ + return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, stext, 0, True); +} + + +int +click_status(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkStatusText; +} + diff --git a/.config/suckless/dwm/patch/bar_status.h b/.config/suckless/dwm/patch/bar_status.h new file mode 100644 index 0000000..c580597 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_status.h @@ -0,0 +1,4 @@ +static int width_status(Bar *bar, BarArg *a); +static int draw_status(Bar *bar, BarArg *a); +static int click_status(Bar *bar, Arg *arg, BarArg *a); + diff --git a/.config/suckless/dwm/patch/bar_status2d.c b/.config/suckless/dwm/patch/bar_status2d.c new file mode 100644 index 0000000..85d6043 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_status2d.c @@ -0,0 +1,193 @@ +static char termcol0[] = "#000000"; /* black */ +static char termcol1[] = "#ff0000"; /* red */ +static char termcol2[] = "#33ff00"; /* green */ +static char termcol3[] = "#ff0099"; /* yellow */ +static char termcol4[] = "#0066ff"; /* blue */ +static char termcol5[] = "#cc00ff"; /* magenta */ +static char termcol6[] = "#00ffff"; /* cyan */ +static char termcol7[] = "#d0d0d0"; /* white */ +static char termcol8[] = "#808080"; /* black */ +static char termcol9[] = "#ff0000"; /* red */ +static char termcol10[] = "#33ff00"; /* green */ +static char termcol11[] = "#ff0099"; /* yellow */ +static char termcol12[] = "#0066ff"; /* blue */ +static char termcol13[] = "#cc00ff"; /* magenta */ +static char termcol14[] = "#00ffff"; /* cyan */ +static char termcol15[] = "#ffffff"; /* white */ +static char *termcolor[] = { + termcol0, termcol1, termcol2, termcol3, termcol4, termcol5, termcol6, termcol7, + termcol8, termcol9, termcol10, termcol11, termcol12, termcol13, termcol14, termcol15, +}; + +int +width_status2d(Bar *bar, BarArg *a) +{ + int width; + width = status2dtextlength(rawstext); + return width ? width + lrpad : 0; +} + + +int +draw_status2d(Bar *bar, BarArg *a) +{ + return drawstatusbar(a, rawstext); +} + + + +int +drawstatusbar(BarArg *a, char* stext) +{ + int i, w, len; + int x = a->x; + int y = a->y; + short isCode = 0; + char *text; + char *p; + Clr oldbg, oldfg; + len = strlen(stext); + if (!(text = (char*) malloc(sizeof(char)*(len + 1)))) + die("malloc"); + p = text; + copyvalidchars(text, stext); + + x += lrpad / 2; + drw_setscheme(drw, scheme[LENGTH(colors)]); + drw->scheme[ColFg] = scheme[SchemeNorm][ColFg]; + drw->scheme[ColBg] = scheme[SchemeNorm][ColBg]; + + /* process status text */ + i = -1; + while (text[++i]) { + if (text[i] == '^' && !isCode) { + isCode = 1; + + text[i] = '\0'; + w = TEXTWM(text) - lrpad; + drw_text(drw, x, y, w, bh, 0, text, 0, True); + + x += w; + + /* process code */ + while (text[++i] != '^') { + if (text[i] == 'c') { + char buf[8]; + if (i + 7 >= len) { + i += 7; + len = 0; + break; + } + memcpy(buf, (char*)text+i+1, 7); + buf[7] = '\0'; + drw_clr_create(drw, &drw->scheme[ColFg], buf); + i += 7; + } else if (text[i] == 'b') { + char buf[8]; + if (i + 7 >= len) { + i += 7; + len = 0; + break; + } + memcpy(buf, (char*)text+i+1, 7); + buf[7] = '\0'; + drw_clr_create(drw, &drw->scheme[ColBg], buf); + i += 7; + } else if (text[i] == 'C') { + int c = atoi(text + ++i) % 16; + drw_clr_create(drw, &drw->scheme[ColFg], termcolor[c]); + } else if (text[i] == 'B') { + int c = atoi(text + ++i) % 16; + drw_clr_create(drw, &drw->scheme[ColBg], termcolor[c]); + } else if (text[i] == 'd') { + drw->scheme[ColFg] = scheme[SchemeNorm][ColFg]; + drw->scheme[ColBg] = scheme[SchemeNorm][ColBg]; + } else if (text[i] == 'w') { + Clr swp; + swp = drw->scheme[ColFg]; + drw->scheme[ColFg] = drw->scheme[ColBg]; + drw->scheme[ColBg] = swp; + } else if (text[i] == 'v') { + oldfg = drw->scheme[ColFg]; + oldbg = drw->scheme[ColBg]; + } else if (text[i] == 't') { + drw->scheme[ColFg] = oldfg; + drw->scheme[ColBg] = oldbg; + } else if (text[i] == 'r') { + int rx = atoi(text + ++i); + while (text[++i] != ','); + int ry = atoi(text + ++i); + while (text[++i] != ','); + int rw = atoi(text + ++i); + while (text[++i] != ','); + int rh = atoi(text + ++i); + + if (ry < 0) + ry = 0; + if (rx < 0) + rx = 0; + + drw_rect(drw, rx + x, y + ry, rw, rh, 1, 0); + } else if (text[i] == 'f') { + x += atoi(text + ++i); + } + } + + text = text + i + 1; + len -= i + 1; + i = -1; + isCode = 0; + if (len <= 0) + break; + } + } + if (!isCode && len > 0) { + w = TEXTWM(text) - lrpad; + drw_text(drw, x, y, w, bh, 0, text, 0, True); + x += w; + } + free(p); + + drw_setscheme(drw, scheme[SchemeNorm]); + return 1; +} + +int +status2dtextlength(char* stext) +{ + int i, w, len; + short isCode = 0; + char *text; + char *p; + + len = strlen(stext) + 1; + if (!(text = (char*) malloc(sizeof(char)*len))) + die("malloc"); + p = text; + copyvalidchars(text, stext); + + /* compute width of the status text */ + w = 0; + i = -1; + while (text[++i]) { + if (text[i] == '^') { + if (!isCode) { + isCode = 1; + text[i] = '\0'; + w += TEXTWM(text) - lrpad; + text[i] = '^'; + if (text[++i] == 'f') + w += atoi(text + ++i); + } else { + isCode = 0; + text = text + i + 1; + i = -1; + } + } + } + if (!isCode) + w += TEXTWM(text) - lrpad; + free(p); + return w; +} + diff --git a/.config/suckless/dwm/patch/bar_status2d.h b/.config/suckless/dwm/patch/bar_status2d.h new file mode 100644 index 0000000..33cb39b --- /dev/null +++ b/.config/suckless/dwm/patch/bar_status2d.h @@ -0,0 +1,5 @@ +static int width_status2d(Bar *bar, BarArg *a); +static int draw_status2d(Bar *bar, BarArg *a); +static int drawstatusbar(BarArg *a, char *text); +static int status2dtextlength(char *stext); + diff --git a/.config/suckless/dwm/patch/bar_statusbutton.c b/.config/suckless/dwm/patch/bar_statusbutton.c new file mode 100644 index 0000000..5e43fe0 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_statusbutton.c @@ -0,0 +1,18 @@ +int +width_stbutton(Bar *bar, BarArg *a) +{ + return TEXTW(buttonbar); +} + +int +draw_stbutton(Bar *bar, BarArg *a) +{ + return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, buttonbar, 0, False); +} + +int +click_stbutton(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkButton; +} + diff --git a/.config/suckless/dwm/patch/bar_statusbutton.h b/.config/suckless/dwm/patch/bar_statusbutton.h new file mode 100644 index 0000000..ed5beb5 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_statusbutton.h @@ -0,0 +1,4 @@ +static int width_stbutton(Bar *bar, BarArg *a); +static int draw_stbutton(Bar *bar, BarArg *a); +static int click_stbutton(Bar *bar, Arg *arg, BarArg *a); + diff --git a/.config/suckless/dwm/patch/bar_statuscmd.c b/.config/suckless/dwm/patch/bar_statuscmd.c new file mode 100644 index 0000000..706aa19 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_statuscmd.c @@ -0,0 +1,46 @@ + +int +click_statuscmd(Bar *bar, Arg *arg, BarArg *a) +{ + return click_statuscmd_text(arg, a->x, rawstext); +} + + +int +click_statuscmd_text(Arg *arg, int rel_x, char *text) +{ + int i = -1; + int x = 0; + char ch; + statussig = -1; + while (text[++i]) { + if ((unsigned char)text[i] < ' ') { + ch = text[i]; + text[i] = '\0'; + x += status2dtextlength(text); + text[i] = ch; + text += i+1; + i = -1; + if (x >= rel_x && statussig != -1) + break; + statussig = ch; + } + } + if (statussig == -1) + statussig = 0; + return ClkStatusText; +} + +void +copyvalidchars(char *text, char *rawtext) +{ + int i = -1, j = 0; + + while (rawtext[++i]) { + if ((unsigned char)rawtext[i] >= ' ') { + text[j++] = rawtext[i]; + } + } + text[j] = '\0'; +} + diff --git a/.config/suckless/dwm/patch/bar_statuscmd.h b/.config/suckless/dwm/patch/bar_statuscmd.h new file mode 100644 index 0000000..1ec24a6 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_statuscmd.h @@ -0,0 +1,9 @@ +static int click_statuscmd(Bar *bar, Arg *arg, BarArg *a); +static int click_statuscmd_text(Arg *arg, int rel_x, char *text); +static void copyvalidchars(char *text, char *rawtext); + +typedef struct { + const char *cmd; + int id; +} StatusCmd; + diff --git a/.config/suckless/dwm/patch/bar_tagicons.c b/.config/suckless/dwm/patch/bar_tagicons.c new file mode 100644 index 0000000..57d1629 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_tagicons.c @@ -0,0 +1,9 @@ +char * +tagicon(Monitor *m, int tag) +{ + int tagindex = tag + NUMTAGS * m->num; + if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS])) + tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]); + return tagicons[DEFAULT_TAGS][tagindex]; +} + diff --git a/.config/suckless/dwm/patch/bar_tagicons.h b/.config/suckless/dwm/patch/bar_tagicons.h new file mode 100644 index 0000000..16fad2a --- /dev/null +++ b/.config/suckless/dwm/patch/bar_tagicons.h @@ -0,0 +1,8 @@ +enum { + DEFAULT_TAGS, + ALTERNATIVE_TAGS, + ALT_TAGS_DECORATION, +}; + +static char * tagicon(Monitor *m, int tag); + diff --git a/.config/suckless/dwm/patch/bar_tags.c b/.config/suckless/dwm/patch/bar_tags.c new file mode 100644 index 0000000..8aa37b2 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_tags.c @@ -0,0 +1,81 @@ +int +width_tags(Bar *bar, BarArg *a) +{ + int w, i; + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + + for (w = 0, i = 0; i < NUMTAGS; i++) { + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + w += TEXTW(tagicon(bar->mon, i)); + } + return w; +} + +int +draw_tags(Bar *bar, BarArg *a) +{ + int invert; + int w, x = a->x; + unsigned int i, occ = 0, urg = 0; + char *icon; + Client *c; + Monitor *m = bar->mon; + + for (c = m->clients; c; c = c->next) { + occ |= c->tags == 255 ? 0 : c->tags; + if (c->isurgent) + urg |= c->tags; + } + for (i = 0; i < NUMTAGS; i++) { + /* do not draw vacant tags */ + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) + continue; + + icon = tagicon(bar->mon, i); + invert = 0; + w = TEXTW(icon); + drw_setscheme(drw, scheme[ + m->tagset[m->seltags] & 1 << i + ? SchemeTagsSel + : urg & 1 << i + ? SchemeUrg + : SchemeTagsNorm + ]); + drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False); + drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype); + x += w; + } + + return 1; +} + +int +click_tags(Bar *bar, Arg *arg, BarArg *a) +{ + int i = 0, x = 0; + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + + do { + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + x += TEXTW(tagicon(bar->mon, i)); + } while (a->x >= x && ++i < NUMTAGS); + if (i < NUMTAGS) { + arg->ui = 1 << i; + } + return ClkTagBar; +} + +int +hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev) +{ + + return 1; +} diff --git a/.config/suckless/dwm/patch/bar_tags.h b/.config/suckless/dwm/patch/bar_tags.h new file mode 100644 index 0000000..70040d2 --- /dev/null +++ b/.config/suckless/dwm/patch/bar_tags.h @@ -0,0 +1,4 @@ +static int width_tags(Bar *bar, BarArg *a); +static int draw_tags(Bar *bar, BarArg *a); +static int click_tags(Bar *bar, Arg *arg, BarArg *a); +static int hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev); diff --git a/.config/suckless/dwm/patch/cool_autostart.c b/.config/suckless/dwm/patch/cool_autostart.c new file mode 100644 index 0000000..848f5ab --- /dev/null +++ b/.config/suckless/dwm/patch/cool_autostart.c @@ -0,0 +1,37 @@ +/* dwm will keep pid's of processes from autostart array and kill them at quit */ +static pid_t *autostart_pids; +static size_t autostart_len; + +/* execute command from autostart array */ +static void +autostart_exec() +{ + const char *const *p; + struct sigaction sa; + size_t i = 0; + + /* count entries */ + for (p = autostart; *p; autostart_len++, p++) + while (*++p); + + autostart_pids = malloc(autostart_len * sizeof(pid_t)); + for (p = autostart; *p; i++, p++) { + if ((autostart_pids[i] = fork()) == 0) { + setsid(); + + /* Restore SIGCHLD sighandler to default before spawning a program */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); + + execvp(*p, (char *const *)p); + fprintf(stderr, "dwm: execvp %s\n", *p); + perror(" failed"); + _exit(EXIT_FAILURE); + } + /* skip arguments */ + while (*++p); + } +} + diff --git a/.config/suckless/dwm/patch/cool_autostart.h b/.config/suckless/dwm/patch/cool_autostart.h new file mode 100644 index 0000000..5534d99 --- /dev/null +++ b/.config/suckless/dwm/patch/cool_autostart.h @@ -0,0 +1,2 @@ +static void autostart_exec(void); + diff --git a/.config/suckless/dwm/patch/fakefullscreenclient.c b/.config/suckless/dwm/patch/fakefullscreenclient.c new file mode 100644 index 0000000..509211f --- /dev/null +++ b/.config/suckless/dwm/patch/fakefullscreenclient.c @@ -0,0 +1,19 @@ +void +togglefakefullscreen(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + + if (c->fakefullscreen != 1 && c->isfullscreen) { // exit fullscreen --> fake fullscreen + c->fakefullscreen = 2; + setfullscreen(c, 0); + } else if (c->fakefullscreen == 1) { + setfullscreen(c, 0); + c->fakefullscreen = 0; + } else { + c->fakefullscreen = 1; + setfullscreen(c, 1); + } +} + diff --git a/.config/suckless/dwm/patch/fakefullscreenclient.h b/.config/suckless/dwm/patch/fakefullscreenclient.h new file mode 100644 index 0000000..889eed6 --- /dev/null +++ b/.config/suckless/dwm/patch/fakefullscreenclient.h @@ -0,0 +1,2 @@ +static void togglefakefullscreen(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/focusdir.c b/.config/suckless/dwm/patch/focusdir.c new file mode 100644 index 0000000..65798c5 --- /dev/null +++ b/.config/suckless/dwm/patch/focusdir.c @@ -0,0 +1,66 @@ +void +focusdir(const Arg *arg) +{ + Client *s = selmon->sel, *f = NULL, *c, *next; + + if (!s) + return; + + unsigned int score = -1; + unsigned int client_score; + int dist; + int dirweight = 20; + int isfloating = s->isfloating; + + next = s->next; + if (!next) + next = s->mon->clients; + for (c = next; c != s; c = next) { + + next = c->next; + if (!next) + next = s->mon->clients; + + if (!ISVISIBLE(c) || c->isfloating != isfloating) // || HIDDEN(c) + continue; + + switch (arg->i) { + case 0: // left + dist = s->x - c->x - c->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(s->y - c->y); + break; + case 1: // right + dist = c->x - s->x - s->w; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->ww)) + + abs(c->y - s->y); + break; + case 2: // up + dist = s->y - c->y - c->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(s->x - c->x); + break; + default: + case 3: // down + dist = c->y - s->y - s->h; + client_score = + dirweight * MIN(abs(dist), abs(dist + s->mon->wh)) + + abs(c->x - s->x); + break; + } + + if (((arg->i == 0 || arg->i == 2) && client_score <= score) || client_score < score) { + score = client_score; + f = c; + } + } + + if (f && f != s) { + focus(f); + restack(f->mon); + } +} + diff --git a/.config/suckless/dwm/patch/focusdir.h b/.config/suckless/dwm/patch/focusdir.h new file mode 100644 index 0000000..0d82ebf --- /dev/null +++ b/.config/suckless/dwm/patch/focusdir.h @@ -0,0 +1,2 @@ +static void focusdir(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/focusfollowmouse.c b/.config/suckless/dwm/patch/focusfollowmouse.c new file mode 100644 index 0000000..d75a9da --- /dev/null +++ b/.config/suckless/dwm/patch/focusfollowmouse.c @@ -0,0 +1,9 @@ +Client * +getpointerclient(void) +{ + Window dummy, win; + int di; + unsigned int dui; + XQueryPointer(dpy, root, &dummy, &win, &di, &di, &di, &di, &dui); + return wintoclient(win); +} diff --git a/.config/suckless/dwm/patch/focusfollowmouse.h b/.config/suckless/dwm/patch/focusfollowmouse.h new file mode 100644 index 0000000..6b24d5f --- /dev/null +++ b/.config/suckless/dwm/patch/focusfollowmouse.h @@ -0,0 +1 @@ +static Client *getpointerclient(void); diff --git a/.config/suckless/dwm/patch/include.c b/.config/suckless/dwm/patch/include.c new file mode 100644 index 0000000..8679033 --- /dev/null +++ b/.config/suckless/dwm/patch/include.c @@ -0,0 +1,35 @@ +/* Bar functionality */ +#include "bar_indicators.c" +#include "bar_tagicons.c" +#include "bar.c" + +#include "bar_dwmblocks.c" +#include "bar_ltsymbol.c" +#include "bar_status.c" +#include "bar_status2d.c" +#include "bar_statusbutton.c" +#include "bar_statuscmd.c" +#include "bar_tags.c" + +/* Other patches */ +#include "attachx.c" +#include "cool_autostart.c" +#include "fakefullscreenclient.c" +#include "focusdir.c" +#include "focusfollowmouse.c" +#include "pertag.c" +#include "restartsig.c" +#include "rotatestack.c" +#include "scratchpad.c" +#include "shift.c" +#include "shiftboth.c" +#include "shiftviewclients.c" +#include "tapresize.c" +#include "transfer.c" +#include "xrdb.c" +#include "seamless_restart.c" +/* Layouts */ +#include "layout_facts.c" +#include "layout_monocle.c" +#include "layout_tile.c" + diff --git a/.config/suckless/dwm/patch/include.h b/.config/suckless/dwm/patch/include.h new file mode 100644 index 0000000..55d46a8 --- /dev/null +++ b/.config/suckless/dwm/patch/include.h @@ -0,0 +1,34 @@ +/* Bar functionality */ +#include "bar_indicators.h" +#include "bar_tagicons.h" +#include "bar.h" + +#include "bar_dwmblocks.h" +#include "bar_ltsymbol.h" +#include "bar_status.h" +#include "bar_status2d.h" +#include "bar_statusbutton.h" +#include "bar_statuscmd.h" +#include "bar_tags.h" + +/* Other patches */ +#include "attachx.h" +#include "cool_autostart.h" +#include "fakefullscreenclient.h" +#include "focusdir.h" +#include "focusfollowmouse.h" +#include "pertag.h" +#include "restartsig.h" +#include "rotatestack.h" +#include "scratchpad.h" +#include "seamless_restart.h" +#include "shift.h" +#include "shiftboth.h" +#include "shiftviewclients.h" +#include "tapresize.h" +#include "transfer.h" +#include "xrdb.h" +/* Layouts */ +#include "layout_monocle.h" +#include "layout_tile.h" + diff --git a/.config/suckless/dwm/patch/ipc/IPCClient.h b/.config/suckless/dwm/patch/ipc/IPCClient.h new file mode 100644 index 0000000..ee93030 --- /dev/null +++ b/.config/suckless/dwm/patch/ipc/IPCClient.h @@ -0,0 +1,62 @@ +#ifndef IPC_CLIENT_H_ +#define IPC_CLIENT_H_ + +#include +#include +#include + +typedef struct IPCClient IPCClient; +/** + * This structure contains the details of an IPC Client and pointers for a + * linked list + */ +struct IPCClient { + int fd; + int subscriptions; + + char *buffer; + uint32_t buffer_size; + + struct epoll_event event; + IPCClient *next; + IPCClient *prev; +}; + +typedef IPCClient *IPCClientList; + +/** + * Allocate memory for new IPCClient with the specified file descriptor and + * initialize struct. + * + * @param fd File descriptor of IPC client + * + * @return Address to allocated IPCClient struct + */ +IPCClient *ipc_client_new(int fd); + +/** + * Add an IPC Client to the specified list + * + * @param list Address of the list to add the client to + * @param nc Address of the IPCClient + */ +void ipc_list_add_client(IPCClientList *list, IPCClient *nc); + +/** + * Remove an IPCClient from the specified list + * + * @param list Address of the list to remove the client from + * @param c Address of the IPCClient + */ +void ipc_list_remove_client(IPCClientList *list, IPCClient *c); + +/** + * Get an IPCClient from the specified IPCClient list + * + * @param list List to remove the client from + * @param fd File descriptor of the IPCClient + */ +IPCClient *ipc_list_get_client(IPCClientList list, int fd); + +#endif // IPC_CLIENT_H_ + diff --git a/.config/suckless/dwm/patch/ipc/dwm-msg.c b/.config/suckless/dwm/patch/ipc/dwm-msg.c new file mode 100644 index 0000000..ca1e1a4 --- /dev/null +++ b/.config/suckless/dwm/patch/ipc/dwm-msg.c @@ -0,0 +1,549 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPC_MAGIC "DWM-IPC" +// clang-format off +#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' } +// clang-format on +#define IPC_MAGIC_LEN 7 // Not including null char + +#define IPC_EVENT_TAG_CHANGE "tag_change_event" +#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event" +#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event" +#define IPC_EVENT_MONITOR_FOCUS_CHANGE "monitor_focus_change_event" +#define IPC_EVENT_FOCUSED_TITLE_CHANGE "focused_title_change_event" +#define IPC_EVENT_FOCUSED_STATE_CHANGE "focused_state_change_event" + +#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) +#define YINT(num) yajl_gen_integer(gen, num) +#define YDOUBLE(num) yajl_gen_double(gen, num) +#define YBOOL(v) yajl_gen_bool(gen, v) +#define YNULL() yajl_gen_null(gen) +#define YARR(body) \ + { \ + yajl_gen_array_open(gen); \ + body; \ + yajl_gen_array_close(gen); \ + } +#define YMAP(body) \ + { \ + yajl_gen_map_open(gen); \ + body; \ + yajl_gen_map_close(gen); \ + } + +typedef unsigned long Window; + +const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock"; +static int sock_fd = -1; +static unsigned int ignore_reply = 0; + +typedef enum IPCMessageType { + IPC_TYPE_RUN_COMMAND = 0, + IPC_TYPE_GET_MONITORS = 1, + IPC_TYPE_GET_TAGS = 2, + IPC_TYPE_GET_LAYOUTS = 3, + IPC_TYPE_GET_DWM_CLIENT = 4, + IPC_TYPE_SUBSCRIBE = 5, + IPC_TYPE_EVENT = 6 +} IPCMessageType; + +// Every IPC message must begin with this +typedef struct dwm_ipc_header { + uint8_t magic[IPC_MAGIC_LEN]; + uint32_t size; + uint8_t type; +} __attribute((packed)) dwm_ipc_header_t; + +static int +recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply) +{ + uint32_t read_bytes = 0; + const int32_t to_read = sizeof(dwm_ipc_header_t); + char header[to_read]; + char *walk = header; + + // Try to read header + while (read_bytes < to_read) { + ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes); + + if (n == 0) { + if (read_bytes == 0) { + fprintf(stderr, "Unexpectedly reached EOF while reading header."); + fprintf(stderr, + "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", + read_bytes, to_read); + return -2; + } else { + fprintf(stderr, "Unexpectedly reached EOF while reading header."); + fprintf(stderr, + "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", + read_bytes, to_read); + return -3; + } + } else if (n == -1) { + return -1; + } + + read_bytes += n; + } + + // Check if magic string in header matches + if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) { + fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n", + IPC_MAGIC_LEN, walk, IPC_MAGIC); + return -3; + } + + walk += IPC_MAGIC_LEN; + + // Extract reply size + memcpy(reply_size, walk, sizeof(uint32_t)); + walk += sizeof(uint32_t); + + // Extract message type + memcpy(msg_type, walk, sizeof(uint8_t)); + walk += sizeof(uint8_t); + + (*reply) = malloc(*reply_size); + + // Extract payload + read_bytes = 0; + while (read_bytes < *reply_size) { + ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes); + + if (n == 0) { + fprintf(stderr, "Unexpectedly reached EOF while reading payload."); + fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n", + read_bytes, *reply_size); + free(*reply); + return -2; + } else if (n == -1) { + if (errno == EINTR || errno == EAGAIN) continue; + free(*reply); + return -1; + } + + read_bytes += n; + } + + return 0; +} + +static int +read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg) +{ + int ret = -1; + + while (ret != 0) { + ret = recv_message((uint8_t *)msg_type, msg_size, (uint8_t **)msg); + + if (ret < 0) { + // Try again (non-fatal error) + if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue; + + fprintf(stderr, "Error receiving response from socket. "); + fprintf(stderr, "The connection might have been lost.\n"); + exit(2); + } + } + + return 0; +} + +static ssize_t +write_socket(const void *buf, size_t count) +{ + size_t written = 0; + + while (written < count) { + const ssize_t n = + write(sock_fd, ((uint8_t *)buf) + written, count - written); + + if (n == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + continue; + else + return n; + } + written += n; + } + return written; +} + +static void +connect_to_socket() +{ + struct sockaddr_un addr; + + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + + // Initialize struct to 0 + memset(&addr, 0, sizeof(struct sockaddr_un)); + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, DEFAULT_SOCKET_PATH); + + connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)); + + sock_fd = sock; +} + +static int +send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg) +{ + dwm_ipc_header_t header = { + .magic = IPC_MAGIC_ARR, .size = msg_size, .type = msg_type}; + + size_t header_size = sizeof(dwm_ipc_header_t); + size_t total_size = header_size + msg_size; + + uint8_t buffer[total_size]; + + // Copy header to buffer + memcpy(buffer, &header, header_size); + // Copy message to buffer + memcpy(buffer + header_size, msg, header.size); + + write_socket(buffer, total_size); + + return 0; +} + +static int +is_float(const char *s) +{ + size_t len = strlen(s); + int is_dot_used = 0; + int is_minus_used = 0; + + // Floats can only have one decimal point in between or digits + // Optionally, floats can also be below zero (negative) + for (int i = 0; i < len; i++) { + if (isdigit(s[i])) + continue; + else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) { + is_dot_used = 1; + continue; + } else if (!is_minus_used && s[i] == '-' && i == 0) { + is_minus_used = 1; + continue; + } else + return 0; + } + + return 1; +} + +static int +is_unsigned_int(const char *s) +{ + size_t len = strlen(s); + + // Unsigned int can only have digits + for (int i = 0; i < len; i++) { + if (isdigit(s[i])) + continue; + else + return 0; + } + + return 1; +} + +static int +is_signed_int(const char *s) +{ + size_t len = strlen(s); + + // Signed int can only have digits and a negative sign at the start + for (int i = 0; i < len; i++) { + if (isdigit(s[i])) + continue; + else if (i == 0 && s[i] == '-') { + continue; + } else + return 0; + } + + return 1; +} + +static void +flush_socket_reply() +{ + IPCMessageType reply_type; + uint32_t reply_size; + char *reply; + + read_socket(&reply_type, &reply_size, &reply); + + free(reply); +} + +static void +print_socket_reply() +{ + IPCMessageType reply_type; + uint32_t reply_size; + char *reply; + + read_socket(&reply_type, &reply_size, &reply); + + printf("%.*s\n", reply_size, reply); + fflush(stdout); + free(reply); +} + +static int +run_command(const char *name, char *args[], int argc) +{ + const unsigned char *msg; + size_t msg_size; + + yajl_gen gen = yajl_gen_alloc(NULL); + + // Message format: + // { + // "command": "", + // "args": [ ... ] + // } + // clang-format off + YMAP( + YSTR("command"); YSTR(name); + YSTR("args"); YARR( + for (int i = 0; i < argc; i++) { + if (is_signed_int(args[i])) { + long long num = atoll(args[i]); + YINT(num); + } else if (is_float(args[i])) { + float num = atof(args[i]); + YDOUBLE(num); + } else { + YSTR(args[i]); + } + } + ) + ) + // clang-format on + + yajl_gen_get_buf(gen, &msg, &msg_size); + + send_message(IPC_TYPE_RUN_COMMAND, msg_size, (uint8_t *)msg); + + if (!ignore_reply) + print_socket_reply(); + else + flush_socket_reply(); + + yajl_gen_free(gen); + + return 0; +} + +static int +get_monitors() +{ + send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *)""); + print_socket_reply(); + return 0; +} + +static int +get_tags() +{ + send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *)""); + print_socket_reply(); + + return 0; +} + +static int +get_layouts() +{ + send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *)""); + print_socket_reply(); + + return 0; +} + +static int +get_dwm_client(Window win) +{ + const unsigned char *msg; + size_t msg_size; + + yajl_gen gen = yajl_gen_alloc(NULL); + + // Message format: + // { + // "client_window_id": "" + // } + // clang-format off + YMAP( + YSTR("client_window_id"); YINT(win); + ) + // clang-format on + + yajl_gen_get_buf(gen, &msg, &msg_size); + + send_message(IPC_TYPE_GET_DWM_CLIENT, msg_size, (uint8_t *)msg); + + print_socket_reply(); + + yajl_gen_free(gen); + + return 0; +} + +static int +subscribe(const char *event) +{ + const unsigned char *msg; + size_t msg_size; + + yajl_gen gen = yajl_gen_alloc(NULL); + + // Message format: + // { + // "event": "", + // "action": "subscribe" + // } + // clang-format off + YMAP( + YSTR("event"); YSTR(event); + YSTR("action"); YSTR("subscribe"); + ) + // clang-format on + + yajl_gen_get_buf(gen, &msg, &msg_size); + + send_message(IPC_TYPE_SUBSCRIBE, msg_size, (uint8_t *)msg); + + if (!ignore_reply) + print_socket_reply(); + else + flush_socket_reply(); + + yajl_gen_free(gen); + + return 0; +} + +static void +usage_error(const char *prog_name, const char *format, ...) +{ + va_list args; + va_start(args, format); + + fprintf(stderr, "Error: "); + vfprintf(stderr, format, args); + fprintf(stderr, "\nusage: %s [...]\n", prog_name); + fprintf(stderr, "Try '%s help'\n", prog_name); + + va_end(args); + exit(1); +} + +static void +print_usage(const char *name) +{ + printf("usage: %s [options] [...]\n", name); + puts(""); + puts("Commands:"); + puts(" run_command [args...] Run an IPC command"); + puts(""); + puts(" get_monitors Get monitor properties"); + puts(""); + puts(" get_tags Get list of tags"); + puts(""); + puts(" get_layouts Get list of layouts"); + puts(""); + puts(" get_dwm_client Get dwm client proprties"); + puts(""); + puts(" subscribe [events...] Subscribe to specified events"); + puts(" Options: " IPC_EVENT_TAG_CHANGE ","); + puts(" " IPC_EVENT_LAYOUT_CHANGE ","); + puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE ","); + puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE ","); + puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE ","); + puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE); + puts(""); + puts(" help Display this message"); + puts(""); + puts("Options:"); + puts(" --ignore-reply Don't print reply messages from"); + puts(" run_command and subscribe."); + puts(""); +} + +int +main(int argc, char *argv[]) +{ + const char *prog_name = argv[0]; + + connect_to_socket(); + if (sock_fd == -1) { + fprintf(stderr, "Failed to connect to socket\n"); + return 1; + } + + int i = 1; + if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) { + ignore_reply = 1; + i++; + } + + if (i >= argc) usage_error(prog_name, "Expected an argument, got none"); + + if (!argc || strcmp(argv[i], "help") == 0) + print_usage(prog_name); + else if (strcmp(argv[i], "run_command") == 0) { + if (++i >= argc) usage_error(prog_name, "No command specified"); + // Command name + char *command = argv[i]; + // Command arguments are everything after command name + char **command_args = argv + ++i; + // Number of command arguments + int command_argc = argc - i; + run_command(command, command_args, command_argc); + } else if (strcmp(argv[i], "get_monitors") == 0) { + get_monitors(); + } else if (strcmp(argv[i], "get_tags") == 0) { + get_tags(); + } else if (strcmp(argv[i], "get_layouts") == 0) { + get_layouts(); + } else if (strcmp(argv[i], "get_dwm_client") == 0) { + if (++i < argc) { + if (is_unsigned_int(argv[i])) { + Window win = atol(argv[i]); + get_dwm_client(win); + } else + usage_error(prog_name, "Expected unsigned integer argument"); + } else + usage_error(prog_name, "Expected the window id"); + } else if (strcmp(argv[i], "subscribe") == 0) { + if (++i < argc) { + for (int j = i; j < argc; j++) subscribe(argv[j]); + } else + usage_error(prog_name, "Expected event name"); + // Keep listening for events forever + while (1) { + print_socket_reply(); + } + } else + usage_error(prog_name, "Invalid argument '%s'", argv[i]); + + return 0; +} + diff --git a/.config/suckless/dwm/patch/ipc/yajl_dumps.h b/.config/suckless/dwm/patch/ipc/yajl_dumps.h new file mode 100644 index 0000000..bb57a17 --- /dev/null +++ b/.config/suckless/dwm/patch/ipc/yajl_dumps.h @@ -0,0 +1,66 @@ +#ifndef YAJL_DUMPS_H_ +#define YAJL_DUMPS_H_ + +#include +#include + +#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) +#define YINT(num) yajl_gen_integer(gen, num) +#define YDOUBLE(num) yajl_gen_double(gen, num) +#define YBOOL(v) yajl_gen_bool(gen, v) +#define YNULL() yajl_gen_null(gen) +#define YARR(body) \ + { \ + yajl_gen_array_open(gen); \ + body; \ + yajl_gen_array_close(gen); \ + } +#define YMAP(body) \ + { \ + yajl_gen_map_open(gen); \ + body; \ + yajl_gen_map_close(gen); \ + } + +int dump_tag(yajl_gen gen, const char *name, const int tag_mask); + +int dump_tags(yajl_gen gen, int tags_len); + +int dump_client(yajl_gen gen, Client *c); + +int dump_monitor(yajl_gen gen, Monitor *mon, int is_selected); + +int dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon); + +int dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len); + +int dump_tag_state(yajl_gen gen, TagState state); + +int dump_tag_event(yajl_gen gen, int mon_num, TagState old_state, + TagState new_state); + +int dump_client_focus_change_event(yajl_gen gen, Client *old_client, + Client *new_client, int mon_num); + +int dump_layout_change_event(yajl_gen gen, const int mon_num, + const char *old_symbol, const Layout *old_layout, + const char *new_symbol, const Layout *new_layout); + +int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num, + const int new_mon_num); + +int dump_focused_title_change_event(yajl_gen gen, const int mon_num, + const Window client_id, + const char *old_name, const char *new_name); + +int dump_client_state(yajl_gen gen, const ClientState *state); + +int dump_focused_state_change_event(yajl_gen gen, const int mon_num, + const Window client_id, + const ClientState *old_state, + const ClientState *new_state); + +int dump_error_message(yajl_gen gen, const char *reason); + +#endif // YAJL_DUMPS_H_ + diff --git a/.config/suckless/dwm/patch/layout_facts.c b/.config/suckless/dwm/patch/layout_facts.c new file mode 100644 index 0000000..241d344 --- /dev/null +++ b/.config/suckless/dwm/patch/layout_facts.c @@ -0,0 +1,24 @@ +void +getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) +{ + unsigned int n; + float mfacts, sfacts; + int mtotal = 0, stotal = 0; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + mfacts = MIN(n, m->nmaster); + sfacts = n - m->nmaster; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (n < m->nmaster) + mtotal += msize / mfacts; + else + stotal += ssize / sfacts; + + *mf = mfacts; // total factor of master area + *sf = sfacts; // total factor of stack area + *mr = msize - mtotal; // the remainder (rest) of pixels after an even master split + *sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split +} + diff --git a/.config/suckless/dwm/patch/layout_monocle.c b/.config/suckless/dwm/patch/layout_monocle.c new file mode 100644 index 0000000..4018bf3 --- /dev/null +++ b/.config/suckless/dwm/patch/layout_monocle.c @@ -0,0 +1,9 @@ +void +monocle(Monitor *m) +{ + Client *c; + + for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); +} + diff --git a/.config/suckless/dwm/patch/layout_monocle.h b/.config/suckless/dwm/patch/layout_monocle.h new file mode 100644 index 0000000..f32e49f --- /dev/null +++ b/.config/suckless/dwm/patch/layout_monocle.h @@ -0,0 +1,2 @@ +static void monocle(Monitor *m); + diff --git a/.config/suckless/dwm/patch/layout_tile.c b/.config/suckless/dwm/patch/layout_tile.c new file mode 100644 index 0000000..629b321 --- /dev/null +++ b/.config/suckless/dwm/patch/layout_tile.c @@ -0,0 +1,39 @@ +static void +tile(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + + if (n == 0) + return; + + sx = mx = m->wx; + sy = my = m->wy; + sh = mh = m->wh; + sw = mw = m->ww; + + if (m->nmaster && n > m->nmaster) { + sw = mw * (1 - m->mfact); + mw = mw * m->mfact; + sx = mx + mw; + } + + getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + my += HEIGHT(c); + } else { + resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + sy += HEIGHT(c); + } +} + diff --git a/.config/suckless/dwm/patch/layout_tile.h b/.config/suckless/dwm/patch/layout_tile.h new file mode 100644 index 0000000..4aff634 --- /dev/null +++ b/.config/suckless/dwm/patch/layout_tile.h @@ -0,0 +1,2 @@ +static void tile(Monitor *m); + diff --git a/.config/suckless/dwm/patch/pertag.c b/.config/suckless/dwm/patch/pertag.c new file mode 100644 index 0000000..024799e --- /dev/null +++ b/.config/suckless/dwm/patch/pertag.c @@ -0,0 +1,29 @@ +struct Pertag { + unsigned int curtag; /* current tag index */ + int nmasters[NUMTAGS + 1]; /* number of windows in master area */ + const Layout *ltidxs[NUMTAGS + 1][2]; /* matrix of tags and layouts indexes */ + float mfacts[NUMTAGS + 1]; /* mfacts per tag */ + unsigned int sellts[NUMTAGS + 1]; /* selected layouts */ +}; + +void +pertagview(const Arg *arg) +{ + int i; + + if (arg->ui == ~SPTAGMASK) + selmon->pertag->curtag = 0; + else { + for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); + selmon->pertag->curtag = i + 1; + } + + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + + +} + diff --git a/.config/suckless/dwm/patch/pertag.h b/.config/suckless/dwm/patch/pertag.h new file mode 100644 index 0000000..5c53ac9 --- /dev/null +++ b/.config/suckless/dwm/patch/pertag.h @@ -0,0 +1,2 @@ +static void pertagview(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/restartsig.c b/.config/suckless/dwm/patch/restartsig.c new file mode 100644 index 0000000..adb61b5 --- /dev/null +++ b/.config/suckless/dwm/patch/restartsig.c @@ -0,0 +1,16 @@ +static int restart = 0; + +void +sighup(int unused) +{ + Arg a = {.i = 1}; + quit(&a); +} + +void +sigterm(int unused) +{ + Arg a = {.i = 0}; + quit(&a); +} + diff --git a/.config/suckless/dwm/patch/restartsig.h b/.config/suckless/dwm/patch/restartsig.h new file mode 100644 index 0000000..b16975b --- /dev/null +++ b/.config/suckless/dwm/patch/restartsig.h @@ -0,0 +1,3 @@ +static void sighup(int unused); +static void sigterm(int unused); + diff --git a/.config/suckless/dwm/patch/rotatestack.c b/.config/suckless/dwm/patch/rotatestack.c new file mode 100644 index 0000000..41df8b1 --- /dev/null +++ b/.config/suckless/dwm/patch/rotatestack.c @@ -0,0 +1,53 @@ +void +enqueue(Client *c) +{ + Client *l; + for (l = c->mon->clients; l && l->next; l = l->next); + if (l) { + l->next = c; + c->next = NULL; + } +} + +void +enqueuestack(Client *c) +{ + Client *l; + for (l = c->mon->stack; l && l->snext; l = l->snext); + if (l) { + l->snext = c; + c->snext = NULL; + } +} + +void +rotatestack(const Arg *arg) +{ + Client *c = NULL, *f; + + if (!selmon->sel) + return; + f = selmon->sel; + if (arg->i > 0) { + for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next)); + if (c){ + detach(c); + attach(c); + detachstack(c); + attachstack(c); + } + } else { + if ((c = nexttiled(selmon->clients))){ + detach(c); + enqueue(c); + detachstack(c); + enqueuestack(c); + } + } + if (c){ + arrange(selmon); + focus(f); + restack(selmon); + } +} + diff --git a/.config/suckless/dwm/patch/rotatestack.h b/.config/suckless/dwm/patch/rotatestack.h new file mode 100644 index 0000000..ea64e68 --- /dev/null +++ b/.config/suckless/dwm/patch/rotatestack.h @@ -0,0 +1,4 @@ +static void enqueue(Client *c); +static void enqueuestack(Client *c); +static void rotatestack(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/scratchpad.c b/.config/suckless/dwm/patch/scratchpad.c new file mode 100644 index 0000000..013e35f --- /dev/null +++ b/.config/suckless/dwm/patch/scratchpad.c @@ -0,0 +1,77 @@ +void +removescratch(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + unsigned int scratchtag = SPTAG(arg->ui); + c->tags = c->mon->tagset[c->mon->seltags] ^ scratchtag; + arrange(c->mon); +} + +void +setscratch(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + unsigned int scratchtag = SPTAG(arg->ui); + c->tags = scratchtag; + arrange(c->mon); +} + +void +togglescratch(const Arg *arg) +{ + Client *c = NULL, *next = NULL, *found = NULL; + Monitor *mon; + unsigned int scratchtag = SPTAG(arg->ui); + unsigned int newtagset = 0; + int nh = 0, nw = 0; + Arg sparg = {.v = scratchpads[arg->ui].cmd}; + + for (mon = mons; mon; mon = mon->next) { + for (c = mon->clients; c; c = next) { + next = c->next; + if (!(c->tags & scratchtag)) + continue; + + found = c; + + if (HIDDEN(c)) { + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + newtagset = 0; + } else + newtagset = selmon->tagset[selmon->seltags] ^ scratchtag; + + if (c->mon != selmon) { + if (c->mon->tagset[c->mon->seltags] & SPTAGMASK) + c->mon->tagset[c->mon->seltags] ^= scratchtag; + if (c->w > selmon->ww) + nw = selmon->ww - c->bw * 2; + if (c->h > selmon->wh) + nh = selmon->wh - c->bw * 2; + if (nw > 0 || nh > 0) + resizeclient(c, c->x, c->y, nw ? nw : c->w, nh ? nh : c->h); + sendmon(c, selmon); + } + } + } + + if (found) { + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + arrange(selmon); + focus(NULL); + } + if (ISVISIBLE(found)) { + focus(found); + restack(selmon); + } + } else { + selmon->tagset[selmon->seltags] |= scratchtag; + spawn(&sparg); + } +} + diff --git a/.config/suckless/dwm/patch/scratchpad.h b/.config/suckless/dwm/patch/scratchpad.h new file mode 100644 index 0000000..6230266 --- /dev/null +++ b/.config/suckless/dwm/patch/scratchpad.h @@ -0,0 +1,9 @@ +typedef struct { + const char *name; + const void *cmd; +} Sp; + +static void removescratch(const Arg *arg); +static void setscratch(const Arg *arg); +static void togglescratch(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/seamless_restart.c b/.config/suckless/dwm/patch/seamless_restart.c new file mode 100644 index 0000000..febdc32 --- /dev/null +++ b/.config/suckless/dwm/patch/seamless_restart.c @@ -0,0 +1,239 @@ +void +persistmonitorstate(Monitor *m) +{ + Client *c; + unsigned int i; + + setmonitortags(m); + setmonitorfields(m); + + /* Set client atoms */ + for (i = 1, c = m->clients; c; c = c->next, ++i) { + c->idx = i; + persistclientstate(c); + } +} + +int +restoremonitorstate(Monitor *m) +{ + return getmonitortags(m) | getmonitorfields(m); +} + +void +persistclientstate(Client *c) +{ + setclienttags(c); + setclientfields(c); +} + +int +restoreclientstate(Client *c) +{ + return getclienttags(c) + | getclientfields(c) + ; +} + +void setmonitorfields(Monitor *m) +{ + unsigned int i; + char atom[22] = {0}; + Atom monitor_fields; + + sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num); + monitor_fields = XInternAtom(dpy, atom, False); + + /* Perists workspace information in 32 bits laid out like this: + * + * |0|0000|0|0000|0000|0000|0000|0000|000|000 + * | | | | | | | | | |-- nmaster + * | | | | | | | | |-- nstack + * | | | | | | | |-- layout + * | | | | | | |-- flextile LAYOUT (split) + * | | | | | |-- flextile MASTER + * | | | | |-- flextile STACK1 + * | | | |-- flextile STACK2 + * | | |-- flextile mirror layout (indicated by negative layout) + * | | + * | |-- reserved + * |-- showbar + */ + for (i = 0; i <= NUMTAGS; i++) { + uint32_t data[] = { + (m->pertag->nmasters[i] & 0x7) | + (getlayoutindex(m->pertag->ltidxs[i][m->pertag->sellts[i]]) & 0xF) << 6 | + m->showbar << 31 + }; + + XChangeProperty(dpy, root, monitor_fields, XA_CARDINAL, 32, + i ? PropModeAppend : PropModeReplace, (unsigned char *)data, 1); + } +} + +int +getlayoutindex(const Layout *layout) +{ + int i; + + for (i = 0; i < LENGTH(layouts) && &layouts[i] != layout; i++); + if (i == LENGTH(layouts)) + i = 0; + return i; +} + +int +getmonitorfields(Monitor *m) +{ + int di, layout_index; + unsigned int i, restored = 0; + unsigned int tags = m->tagset[m->seltags] << 1; + unsigned long dl, nitems; + unsigned char *p = NULL; + char atom[22] = {0}; + Atom da, state = None; + + sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num); + Atom dwm_monitor = XInternAtom(dpy, atom, False); + if (!dwm_monitor) + return 0; + + for (i = 0; i <= NUMTAGS; i++) { + if (!(XGetWindowProperty(dpy, root, dwm_monitor, i, (NUMTAGS + 1) * sizeof dl, + False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) { + break; + } + + if (!nitems) { + XFree(p); + break; + } + + /* See bit layout in the persistmonitorstate function */ + state = *(Atom *)p; + + m->pertag->nmasters[i] = state & 0x7; + layout_index = (state >> 6) & 0xF; + if (layout_index < LENGTH(layouts)) + m->pertag->ltidxs[i][m->pertag->sellts[i]] = &layouts[layout_index]; + + if (!restored && i && (tags & (1 << i))) { + m->nmaster = m->pertag->nmasters[i]; + m->sellt = m->pertag->sellts[i]; + m->lt[m->sellt] = m->pertag->ltidxs[i][m->sellt]; + m->showbar = (state >> 31) & 0x1; + restored = 1; + } + + XFree(p); + } + + return restored; +} + +void +setmonitortags(Monitor *m) +{ + char atom[22] = {0}; + Atom monitor_tags; + + sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num); + monitor_tags = XInternAtom(dpy, atom, False); + + uint32_t data[] = { m->tagset[m->seltags] }; + XChangeProperty(dpy, root, monitor_tags, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +int +getmonitortags(Monitor *m) +{ + int di; + unsigned long dl, nitems; + unsigned char *p = NULL; + char atom[22] = {0}; + Atom da, monitor_tags = None, tags; + + sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num); + monitor_tags = XInternAtom(dpy, atom, False); + + if (!(XGetWindowProperty(dpy, root, monitor_tags, 0L, sizeof dl, + False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) { + return 0; + } + + if (nitems) { + tags = *(Atom *)p; + m->tagset[m->seltags] = tags & TAGMASK; + } + + XFree(p); + return 1; +} + +void +setclientfields(Client *c) +{ + /* Perists client information in 32 bits laid out like this: + * + * |00000000|00000|0|0|0|0|0|0|0|0|00000000|000 + * | | | | | | | | | | | |-- monitor index + * | | | | | | | | | | |-- client index + * | | | | | | | | | |-- isfloating + * | | | | | | | | |-- ispermanent + * | | | | | | | |-- isterminal + * | | | | | | |-- noswallow + * | | | | | |-- issteam + * | | | | |-- issticky + * | | | |-- fakefullscreen + * | | |-- isfreesize + * | | + * | |-- reserved + * |-- scratchkey (for scratchpads) + */ + uint32_t data[] = { + (c->mon->num & 0x7) + | (c->idx & 0xFF) << 3 + | (c->isfloating & 0x1) << 11 + | (c->fakefullscreen & 0x1) << 17 + }; + XChangeProperty(dpy, c->win, clientatom[ClientFields], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +int +getclientfields(Client *c) +{ + Monitor *m; + Atom fields = getatomprop(c, clientatom[ClientFields], AnyPropertyType); + if (fields == None) + return 0; + + /* See bit layout in the setclientfields function */ + for (m = mons; m; m = m->next) + if (m->num == (fields & 0x7)) { + c->mon = m; + break; + } + c->idx = (fields >> 3) & 0xFF; + c->isfloating = (fields >> 11) & 0x1; + c->fakefullscreen = (fields >> 17) & 0x1; + return 1; +} + +void +setclienttags(Client *c) +{ + uint32_t data[] = { c->tags }; + XChangeProperty(dpy, c->win, clientatom[ClientTags], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); +} + +int +getclienttags(Client *c) +{ + Atom tags = getatomprop(c, clientatom[ClientTags], AnyPropertyType); + if (tags == None) + return 0; + + c->tags = tags & TAGMASK; + return 1; +} + diff --git a/.config/suckless/dwm/patch/seamless_restart.h b/.config/suckless/dwm/patch/seamless_restart.h new file mode 100644 index 0000000..13c5d6d --- /dev/null +++ b/.config/suckless/dwm/patch/seamless_restart.h @@ -0,0 +1,15 @@ +#include + +static void persistmonitorstate(Monitor *m); +static int restoremonitorstate(Monitor *m); +static void persistclientstate(Client *c); +static int restoreclientstate(Client *c); +static void setmonitorfields(Monitor *m); +static int getmonitorfields(Monitor *m); +static void setmonitortags(Monitor *m); +static int getmonitortags(Monitor *m); +static void setclientfields(Client *c); +static int getclientfields(Client *c); +static void setclienttags(Client *c); +static int getclienttags(Client *c); +static int getlayoutindex(const Layout *layout); diff --git a/.config/suckless/dwm/patch/shift.c b/.config/suckless/dwm/patch/shift.c new file mode 100644 index 0000000..eeb4885 --- /dev/null +++ b/.config/suckless/dwm/patch/shift.c @@ -0,0 +1,26 @@ +static Arg +shift(const Arg *arg, int clients) +{ + Arg shifted; + Client *c; + unsigned int tagmask = 0; + + shifted.ui = selmon->tagset[selmon->seltags] & ~SPTAGMASK; + + for (c = selmon->clients; c && clients; c = c->next) { + if (c == selmon->sel) + continue; + if (!(c->tags & SPTAGMASK)) + tagmask |= c->tags; + } + + do { + if (arg->i > 0) // left circular shift + shifted.ui = (shifted.ui << arg->i) | (shifted.ui >> (NUMTAGS - arg->i)); + else // right circular shift + shifted.ui = (shifted.ui >> -arg->i) | (shifted.ui << (NUMTAGS + arg->i)); + shifted.ui &= ~SPTAGMASK; + } while (tagmask && !(shifted.ui & tagmask)); + + return shifted; +} diff --git a/.config/suckless/dwm/patch/shift.h b/.config/suckless/dwm/patch/shift.h new file mode 100644 index 0000000..45f1665 --- /dev/null +++ b/.config/suckless/dwm/patch/shift.h @@ -0,0 +1 @@ +static Arg shift(const Arg *arg, int clients); diff --git a/.config/suckless/dwm/patch/shiftboth.c b/.config/suckless/dwm/patch/shiftboth.c new file mode 100644 index 0000000..d51d4ac --- /dev/null +++ b/.config/suckless/dwm/patch/shiftboth.c @@ -0,0 +1,7 @@ +void +shiftboth(const Arg *arg) +{ + Arg shifted = shift(arg, 0); + tag(&shifted); + view(&shifted); +} diff --git a/.config/suckless/dwm/patch/shiftboth.h b/.config/suckless/dwm/patch/shiftboth.h new file mode 100644 index 0000000..7a9b8c2 --- /dev/null +++ b/.config/suckless/dwm/patch/shiftboth.h @@ -0,0 +1 @@ +static void shiftboth(const Arg *arg); diff --git a/.config/suckless/dwm/patch/shiftviewclients.c b/.config/suckless/dwm/patch/shiftviewclients.c new file mode 100644 index 0000000..7abebb2 --- /dev/null +++ b/.config/suckless/dwm/patch/shiftviewclients.c @@ -0,0 +1,6 @@ +void +shiftviewclients(const Arg *arg) +{ + Arg shifted = shift(arg, 1); + view(&shifted); +} diff --git a/.config/suckless/dwm/patch/shiftviewclients.h b/.config/suckless/dwm/patch/shiftviewclients.h new file mode 100644 index 0000000..2f652cd --- /dev/null +++ b/.config/suckless/dwm/patch/shiftviewclients.h @@ -0,0 +1 @@ +static void shiftviewclients(const Arg *arg); diff --git a/.config/suckless/dwm/patch/tapresize.c b/.config/suckless/dwm/patch/tapresize.c new file mode 100644 index 0000000..d6abf79 --- /dev/null +++ b/.config/suckless/dwm/patch/tapresize.c @@ -0,0 +1,39 @@ +void +resizemousescroll(const Arg *arg) +{ + int nw, nh; + Client *c; + Monitor *m; + XEvent ev; + int dw = *((int*)arg->v + 1); + int dh = *(int*)arg->v; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen && c->fakefullscreen != 1) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + nw = MAX(c->w + dw, 1); + nh = MAX(c->h + dh, 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) + { + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) + togglefloating(NULL); + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, c->x, c->y, nw, nh, 1); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + diff --git a/.config/suckless/dwm/patch/tapresize.h b/.config/suckless/dwm/patch/tapresize.h new file mode 100644 index 0000000..fe6d227 --- /dev/null +++ b/.config/suckless/dwm/patch/tapresize.h @@ -0,0 +1,2 @@ +static void resizemousescroll(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/transfer.c b/.config/suckless/dwm/patch/transfer.c new file mode 100644 index 0000000..ce64319 --- /dev/null +++ b/.config/suckless/dwm/patch/transfer.c @@ -0,0 +1,34 @@ +void +transfer(const Arg *arg) +{ + Client *c, *mtail = selmon->clients, *stail = NULL, *insertafter; + int transfertostack = 0, i, nmasterclients; + + for (i = 0, c = selmon->clients; c; c = c->next) { + if (!ISVISIBLE(c) || c->isfloating) continue; + if (selmon->sel == c) { transfertostack = i < selmon->nmaster && selmon->nmaster != 0; } + if (i < selmon->nmaster) { nmasterclients++; mtail = c; } + stail = c; + i++; + } + if (!selmon->sel || selmon->sel->isfloating || i == 0) { + return; + } else if (transfertostack) { + selmon->nmaster = MIN(i, selmon->nmaster) - 1; + insertafter = stail; + } else { + selmon->nmaster = selmon->nmaster + 1; + insertafter = mtail; + } + if (insertafter != selmon->sel) { + detach(selmon->sel); + if (selmon->nmaster == 1 && !transfertostack) { + attach(selmon->sel); // Head prepend case + } else { + selmon->sel->next = insertafter->next; + insertafter->next = selmon->sel; + } + } + arrange(selmon); +} + diff --git a/.config/suckless/dwm/patch/transfer.h b/.config/suckless/dwm/patch/transfer.h new file mode 100644 index 0000000..e887dae --- /dev/null +++ b/.config/suckless/dwm/patch/transfer.h @@ -0,0 +1,2 @@ +static void transfer(const Arg *arg); + diff --git a/.config/suckless/dwm/patch/xrdb.c b/.config/suckless/dwm/patch/xrdb.c new file mode 100644 index 0000000..55113f7 --- /dev/null +++ b/.config/suckless/dwm/patch/xrdb.c @@ -0,0 +1,87 @@ +void +loadxrdb() +{ + Display *display; + char * resm; + XrmDatabase xrdb; + char *type; + XrmValue value; + + display = XOpenDisplay(NULL); + + if (display != NULL) { + resm = XResourceManagerString(display); + + if (resm != NULL) { + xrdb = XrmGetStringDatabase(resm); + + if (xrdb != NULL) { + XRDB_LOAD_COLOR("dwm.normfgcolor", normfgcolor); + XRDB_LOAD_COLOR("dwm.normbgcolor", normbgcolor); + XRDB_LOAD_COLOR("dwm.normbordercolor", normbordercolor); + XRDB_LOAD_COLOR("dwm.normfloatcolor", normfloatcolor); + XRDB_LOAD_COLOR("dwm.selfgcolor", selfgcolor); + XRDB_LOAD_COLOR("dwm.selbgcolor", selbgcolor); + XRDB_LOAD_COLOR("dwm.selbordercolor", selbordercolor); + XRDB_LOAD_COLOR("dwm.selfloatcolor", selfloatcolor); + XRDB_LOAD_COLOR("dwm.titlenormfgcolor", titlenormfgcolor); + XRDB_LOAD_COLOR("dwm.titlenormbgcolor", titlenormbgcolor); + XRDB_LOAD_COLOR("dwm.titlenormbordercolor", titlenormbordercolor); + XRDB_LOAD_COLOR("dwm.titlenormfloatcolor", titlenormfloatcolor); + XRDB_LOAD_COLOR("dwm.titleselfgcolor", titleselfgcolor); + XRDB_LOAD_COLOR("dwm.titleselbgcolor", titleselbgcolor); + XRDB_LOAD_COLOR("dwm.titleselbordercolor", titleselbordercolor); + XRDB_LOAD_COLOR("dwm.titleselfloatcolor", titleselfloatcolor); + XRDB_LOAD_COLOR("dwm.tagsnormfgcolor", tagsnormfgcolor); + XRDB_LOAD_COLOR("dwm.tagsnormbgcolor", tagsnormbgcolor); + XRDB_LOAD_COLOR("dwm.tagsnormbordercolor", tagsnormbordercolor); + XRDB_LOAD_COLOR("dwm.tagsnormfloatcolor", tagsnormfloatcolor); + XRDB_LOAD_COLOR("dwm.tagsselfgcolor", tagsselfgcolor); + XRDB_LOAD_COLOR("dwm.tagsselbgcolor", tagsselbgcolor); + XRDB_LOAD_COLOR("dwm.tagsselbordercolor", tagsselbordercolor); + XRDB_LOAD_COLOR("dwm.tagsselfloatcolor", tagsselfloatcolor); + XRDB_LOAD_COLOR("dwm.hidnormfgcolor", hidnormfgcolor); + XRDB_LOAD_COLOR("dwm.hidnormbgcolor", hidnormbgcolor); + XRDB_LOAD_COLOR("dwm.hidselfgcolor", hidselfgcolor); + XRDB_LOAD_COLOR("dwm.hidselbgcolor", hidselbgcolor); + XRDB_LOAD_COLOR("dwm.urgfgcolor", urgfgcolor); + XRDB_LOAD_COLOR("dwm.urgbgcolor", urgbgcolor); + XRDB_LOAD_COLOR("dwm.urgbordercolor", urgbordercolor); + XRDB_LOAD_COLOR("dwm.urgfloatcolor", urgfloatcolor); + XRDB_LOAD_COLOR("color0", termcol0); + XRDB_LOAD_COLOR("color1", termcol1); + XRDB_LOAD_COLOR("color2", termcol2); + XRDB_LOAD_COLOR("color3", termcol3); + XRDB_LOAD_COLOR("color4", termcol4); + XRDB_LOAD_COLOR("color5", termcol5); + XRDB_LOAD_COLOR("color6", termcol6); + XRDB_LOAD_COLOR("color7", termcol7); + XRDB_LOAD_COLOR("color8", termcol8); + XRDB_LOAD_COLOR("color9", termcol9); + XRDB_LOAD_COLOR("color10", termcol10); + XRDB_LOAD_COLOR("color11", termcol11); + XRDB_LOAD_COLOR("color12", termcol12); + XRDB_LOAD_COLOR("color13", termcol13); + XRDB_LOAD_COLOR("color14", termcol14); + XRDB_LOAD_COLOR("color15", termcol15); + + XrmDestroyDatabase(xrdb); + } + } + } + + XCloseDisplay(display); +} + +void +xrdb(const Arg *arg) +{ + loadxrdb(); + int i; + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], + ColCount + ); + arrange(NULL); + focus(NULL); +} diff --git a/.config/suckless/dwm/patch/xrdb.h b/.config/suckless/dwm/patch/xrdb.h new file mode 100644 index 0000000..3787bec --- /dev/null +++ b/.config/suckless/dwm/patch/xrdb.h @@ -0,0 +1,22 @@ +#include + +#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ + if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ + int i = 1; \ + for (; i <= 6; i++) { \ + if (value.addr[i] < 48) break; \ + if (value.addr[i] > 57 && value.addr[i] < 65) break; \ + if (value.addr[i] > 70 && value.addr[i] < 97) break; \ + if (value.addr[i] > 102) break; \ + } \ + if (i == 7) { \ + strncpy(V, value.addr, 7); \ + V[7] = '\0'; \ + } \ + } \ + } + +static void loadxrdb(void); +static void xrdb(const Arg *arg); + + diff --git a/.config/suckless/dwm/transient.c b/.config/suckless/dwm/transient.c new file mode 100644 index 0000000..158460f --- /dev/null +++ b/.config/suckless/dwm/transient.c @@ -0,0 +1,43 @@ +/* cc transient.c -o transient -lX11 */ + +#include +#include +#include +#include + +int main(void) { + Display *d; + Window r, f, t = None; + XSizeHints h; + XEvent e; + + d = XOpenDisplay(NULL); + if (!d) + exit(1); + r = DefaultRootWindow(d); + + f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); + h.min_width = h.max_width = h.min_height = h.max_height = 400; + h.flags = PMinSize | PMaxSize; + XSetWMNormalHints(d, f, &h); + XStoreName(d, f, "floating"); + XMapWindow(d, f); + + XSelectInput(d, f, ExposureMask); + while (1) { + XNextEvent(d, &e); + + if (t == None) { + sleep(5); + t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); + XSetTransientForHint(d, t, f); + XStoreName(d, t, "transient"); + XMapWindow(d, t); + XSelectInput(d, t, ExposureMask); + } + } + + XCloseDisplay(d); + exit(0); +} + diff --git a/.config/suckless/dwm/util.c b/.config/suckless/dwm/util.c new file mode 100644 index 0000000..96b82c9 --- /dev/null +++ b/.config/suckless/dwm/util.c @@ -0,0 +1,36 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "util.h" + +void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(1); +} + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} diff --git a/.config/suckless/dwm/util.h b/.config/suckless/dwm/util.h new file mode 100644 index 0000000..1e3cf9a --- /dev/null +++ b/.config/suckless/dwm/util.h @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef MAX +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif +#ifndef MIN +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) + +#ifdef _DEBUG +#define DEBUG(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG(...) +#endif + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); + diff --git a/.config/suckless/dwmblocks/LICENSE b/.config/suckless/dwmblocks/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/.config/suckless/dwmblocks/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/.config/suckless/dwmblocks/Makefile b/.config/suckless/dwmblocks/Makefile new file mode 100644 index 0000000..d7d7455 --- /dev/null +++ b/.config/suckless/dwmblocks/Makefile @@ -0,0 +1,52 @@ +.POSIX: + +BIN := dwmblocks +BUILD_DIR := build +SRC_DIR := src +INC_DIR := include + +VERBOSE := 0 +LIBS := xcb-atom + +PREFIX := /usr/local +CFLAGS := -Ofast -I. -I$(INC_DIR) -std=c99 +CFLAGS += -DBINARY=\"$(BIN)\" -D_POSIX_C_SOURCE=200809L +CFLAGS += -Wall -Wpedantic -Wextra -Wswitch-enum +CFLAGS += $(shell pkg-config --cflags $(LIBS)) +LDLIBS := $(shell pkg-config --libs $(LIBS)) + +SRCS := $(wildcard $(SRC_DIR)/*.c) +OBJS := $(subst $(SRC_DIR)/,$(BUILD_DIR)/,$(SRCS:.c=.o)) + +INSTALL_DIR := $(DESTDIR)$(PREFIX)/bin + +# Prettify output +PRINTF := @printf "%-8s %s\n" +ifeq ($(VERBOSE), 0) + Q := @ +endif + +all: $(BUILD_DIR)/$(BIN) + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c config.h + $Qmkdir -p $(@D) + $(PRINTF) "CC" $@ + $Q$(COMPILE.c) -o $@ $< + +$(BUILD_DIR)/$(BIN): $(OBJS) + $(PRINTF) "LD" $@ + $Q$(LINK.o) $^ $(LDLIBS) -o $@ + +clean: + $(PRINTF) "CLEAN" $(BUILD_DIR) + $Q$(RM) $(BUILD_DIR)/* + +install: $(BUILD_DIR)/$(BIN) + $(PRINTF) "INSTALL" $(INSTALL_DIR)/$(BIN) + $Qinstall -D -m 755 $< $(INSTALL_DIR)/$(BIN) + +uninstall: + $(PRINTF) "RM" $(INSTALL_DIR)/$(BIN) + $Q$(RM) $(INSTALL_DIR)/$(BIN) + +.PHONY: all clean install uninstall diff --git a/.config/suckless/dwmblocks/README.md b/.config/suckless/dwmblocks/README.md new file mode 100644 index 0000000..69b72da --- /dev/null +++ b/.config/suckless/dwmblocks/README.md @@ -0,0 +1,163 @@ +# dwmblocks-async + +A [`dwm`](https://dwm.suckless.org) status bar that has a modular, async +design, so it is always responsive. Imagine `i3blocks`, but for `dwm`. + +![A lean config of dwmblocks-async.](preview.png) + +## Features + +- [Modular](#modifying-the-blocks) +- Lightweight +- [Suckless](https://suckless.org/philosophy) +- Blocks: + - [Clickable](#clickable-blocks) + - Loaded asynchronously + - [Updates can be externally triggered](#signalling-changes) +- Compatible with `i3blocks` scripts + +> Additionally, this build of `dwmblocks` is more optimized and fixes the +> flickering of the status bar when scrolling. + +## Why `dwmblocks`? + +In `dwm`, you have to set the status bar through an infinite loop, like so: + +```sh +while :; do + xsetroot -name "$(date)" + sleep 30 +done +``` + +This is inefficient when running multiple commands that need to be updated at +different frequencies. For example, to display an unread mail count and a clock +in the status bar: + +```sh +while :; do + xsetroot -name "$(mailCount) $(date)" + sleep 60 +done +``` + +Both are executed at the same rate, which is wasteful. Ideally, the mail +counter would be updated every thirty minutes, since there's a limit to the +number of requests I can make using Gmail's APIs (as a free user). + +`dwmblocks` allows you to divide the status bar into multiple blocks, each of +which can be updated at its own interval. This effectively addresses the +previous issue, because the commands in a block are only executed once within +that time frame. + +## Why `dwmblocks-async`? + +The magic of `dwmblocks-async` is in the `async` part. Since vanilla +`dwmblocks` executes the commands of each block sequentially, it leads to +annoying freezes. In cases where one block takes several seconds to execute, +like in the mail and date blocks example from above, the delay is clearly +visible. Fire up a new instance of `dwmblocks` and you'll see! + +With `dwmblocks-async`, the computer executes each block asynchronously +(simultaneously). + +## Installation + +Clone this repository, modify `config.h` appropriately, then compile the +program: + +```sh +git clone https://github.com/UtkarshVerma/dwmblocks-async.git +cd dwmblocks-async +vi config.h +sudo make install +``` + +## Usage + +To set `dwmblocks-async` as your status bar, you need to run it as a background +process on startup. One way is to add the following to `~/.xinitrc`: + +```sh +# The binary of `dwmblocks-async` is named `dwmblocks` +dwmblocks & +``` + +### Modifying the blocks + +You can define your status bar blocks in `config.h`: + +```c +#define BLOCKS(X) \ + ... + X("volume", 0, 5), \ + X("date", 1800, 1), \ + ... +``` + +Each block has the following properties: + +| Property | Description | +| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| Command | The command you wish to execute in your block. | +| Update interval | Time in seconds, after which you want the block to update. If `0`, the block will never be updated. | +| Update signal | Signal to be used for triggering the block. Must be a positive integer. If `0`, a signal won't be set up for the block and it will be unclickable. | + +Apart from defining the blocks, features can be toggled through `config.h`: + +```c +// String used to delimit block outputs in the status. +#define DELIMITER " " + +// Maximum number of Unicode characters that a block can output. +#define MAX_BLOCK_OUTPUT_LENGTH 45 + +// Control whether blocks are clickable. +#define CLICKABLE_BLOCKS 1 + +// Control whether a leading delimiter should be prepended to the status. +#define LEADING_DELIMITER 0 + +// Control whether a trailing delimiter should be appended to the status. +#define TRAILING_DELIMITER 0 +``` + +### Signalling changes + +Most status bars constantly rerun all scripts every few seconds. This is an +option here, but a superior choice is to give your block a signal through which +you can indicate it to update on relevant event, rather than have it rerun +idly. + +For example, the volume block has the update signal `5` by default. I run +`kill -39 $(pidof dwmblocks)` alongside my volume shortcuts in `dwm` to only +update it when relevant. Just add `34` to your signal number! You could also +run `pkill -RTMIN+5 dwmblocks`, but it's slower. + +To refresh all the blocks, run `kill -10 $(pidof dwmblocks)` or +`pkill -SIGUSR1 dwmblocks`. + +> All blocks must have different signal numbers! + +### Clickable blocks + +Like `i3blocks`, this build allows you to build in additional actions into your +scripts in response to click events. You can check out +[my status bar scripts](https://github.com/UtkarshVerma/dotfiles/tree/main/.local/bin/statusbar) +as references for using the `$BLOCK_BUTTON` variable. + +To use this feature, define the `CLICKABLE_BLOCKS` feature macro in your +`config.h`: + +```c +#define CLICKABLE_BLOCKS 1 +``` + +Apart from that, you need `dwm` to be patched with +[statuscmd](https://dwm.suckless.org/patches/statuscmd/). + +## Credits + +This work would not have been possible without +[Luke's build of dwmblocks](https://github.com/LukeSmithxyz/dwmblocks) and +[Daniel Bylinka's statuscmd patch](https://dwm.suckless.org/patches/statuscmd/). diff --git a/.config/suckless/dwmblocks/config.h b/.config/suckless/dwmblocks/config.h new file mode 100644 index 0000000..463df36 --- /dev/null +++ b/.config/suckless/dwmblocks/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_H +#define CONFIG_H + +// String used to delimit block outputs in the status. +#define DELIMITER " ^c#37474f^󰄽 ^d^" +// #define DELIMITER " ^c#37474f^^d^ " + +// Maximum number of Unicode characters that a block can output. +#define MAX_BLOCK_OUTPUT_LENGTH 45 + +// Control whether blocks are clickable. +#define CLICKABLE_BLOCKS 1 + +// Control whether a leading delimiter should be prepended to the status. +#define LEADING_DELIMITER 0 + +// Control whether a trailing delimiter should be appended to the status. +#define TRAILING_DELIMITER 0 + +// Define blocks for the status feed as X(cmd, interval, signal). +#define BLOCKS(X) \ + X("cat /tmp/recordingicon 2>/dev/null", 0, 9) \ + X("sb-internet", 5, 4) \ + X("sb-volume", 0, 8) \ + X("sb-battery", 5, 21) \ + X("sb-clock", 60, 1) \ + X("sb-powerbutton", 0, 17) + +#endif // CONFIG_H diff --git a/.config/suckless/dwmblocks/include/block.h b/.config/suckless/dwmblocks/include/block.h new file mode 100644 index 0000000..f1c9aff --- /dev/null +++ b/.config/suckless/dwmblocks/include/block.h @@ -0,0 +1,29 @@ +#ifndef BLOCK_H +#define BLOCK_H + +#include +#include +#include + +#include "config.h" +#include "util.h" + +typedef struct { + const char *const command; + const unsigned int interval; + const int signal; + + int pipe[PIPE_FD_COUNT]; + char output[MAX_BLOCK_OUTPUT_LENGTH * UTF8_MAX_BYTE_COUNT + 1]; + pid_t fork_pid; +} block; + +block block_new(const char *const command, const unsigned int interval, + const int signal); +int block_init(block *const block); +int block_deinit(block *const block); +int block_execute(block *const block, const uint8_t button); +int block_update(block *const block); +bool block_must_run(const block *const block, const unsigned int time); + +#endif // BLOCK_H diff --git a/.config/suckless/dwmblocks/include/cli.h b/.config/suckless/dwmblocks/include/cli.h new file mode 100644 index 0000000..3d2d5a5 --- /dev/null +++ b/.config/suckless/dwmblocks/include/cli.h @@ -0,0 +1,13 @@ +#ifndef CLI_H +#define CLI_H + +#include + +typedef struct { + bool is_debug_mode; +} cli_arguments; + +int cli_init(cli_arguments* const args, const char* const argv[], + const int argc); + +#endif // CLI_H diff --git a/.config/suckless/dwmblocks/include/main.h b/.config/suckless/dwmblocks/include/main.h new file mode 100644 index 0000000..b37a6b1 --- /dev/null +++ b/.config/suckless/dwmblocks/include/main.h @@ -0,0 +1,16 @@ +#ifndef MAIN_H +#define MAIN_H + +#include + +#include "config.h" +#include "util.h" + +#define REFRESH_SIGNAL SIGUSR1 + +// Utilise C's adjacent string concatenation to count the number of blocks. +#define X(...) "." +enum { BLOCK_COUNT = LEN(BLOCKS(X)) - 1 }; +#undef X + +#endif // MAIN_H diff --git a/.config/suckless/dwmblocks/include/signal-handler.h b/.config/suckless/dwmblocks/include/signal-handler.h new file mode 100644 index 0000000..da2d471 --- /dev/null +++ b/.config/suckless/dwmblocks/include/signal-handler.h @@ -0,0 +1,33 @@ +#ifndef SIGNAL_HANDLER_H +#define SIGNAL_HANDLER_H + +#include + +#include "block.h" +#include "timer.h" + +typedef sigset_t signal_set; +typedef int (*signal_refresh_callback)(block* const blocks, + const unsigned short block_count); +typedef int (*signal_timer_callback)(block* const blocks, + const unsigned short block_code, + timer* const timer); + +typedef struct { + int fd; + const signal_refresh_callback refresh_callback; + const signal_timer_callback timer_callback; + + block* const blocks; + const unsigned short block_count; +} signal_handler; + +signal_handler signal_handler_new( + block* const blocks, const unsigned short block_count, + const signal_refresh_callback refresh_callback, + const signal_timer_callback timer_callback); +int signal_handler_init(signal_handler* const handler); +int signal_handler_deinit(signal_handler* const handler); +int signal_handler_process(signal_handler* const handler, timer* const timer); + +#endif // SIGNAL_HANDLER_H diff --git a/.config/suckless/dwmblocks/include/status.h b/.config/suckless/dwmblocks/include/status.h new file mode 100644 index 0000000..48fb3d8 --- /dev/null +++ b/.config/suckless/dwmblocks/include/status.h @@ -0,0 +1,31 @@ +#ifndef STATUS_H +#define STATUS_H + +#include + +#include "block.h" +#include "config.h" +#include "main.h" +#include "util.h" +#include "x11.h" + +typedef struct { +#define STATUS_LENGTH \ + ((BLOCK_COUNT * (MEMBER_LENGTH(block, output) - 1) + CLICKABLE_BLOCKS) + \ + (BLOCK_COUNT - 1 + LEADING_DELIMITER + TRAILING_DELIMITER) * \ + (LEN(DELIMITER) - 1) + \ + 1) + char current[STATUS_LENGTH]; + char previous[STATUS_LENGTH]; +#undef STATUS_LENGTH + + const block* const blocks; + const unsigned short block_count; +} status; + +status status_new(const block* const blocks, const unsigned short block_count); +bool status_update(status* const status); +int status_write(const status* const status, const bool is_debug_mode, + x11_connection* const connection); + +#endif // STATUS_H diff --git a/.config/suckless/dwmblocks/include/timer.h b/.config/suckless/dwmblocks/include/timer.h new file mode 100644 index 0000000..eccf4a1 --- /dev/null +++ b/.config/suckless/dwmblocks/include/timer.h @@ -0,0 +1,19 @@ +#ifndef TIMER_H +#define TIMER_H + +#include + +#include "block.h" + +#define TIMER_SIGNAL SIGALRM + +typedef struct { + unsigned int time; + const unsigned int tick; + const unsigned int reset_value; +} timer; + +timer timer_new(const block *const blocks, const unsigned short block_count); +int timer_arm(timer *const timer); + +#endif // TIMER_H diff --git a/.config/suckless/dwmblocks/include/util.h b/.config/suckless/dwmblocks/include/util.h new file mode 100644 index 0000000..a3bdcce --- /dev/null +++ b/.config/suckless/dwmblocks/include/util.h @@ -0,0 +1,28 @@ +#ifndef UTIL_H +#define UTIL_H + +#include + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define LEN(arr) (sizeof(arr) / sizeof((arr)[0])) +#define BIT(n) (1 << (n)) + +// NOLINTBEGIN(bugprone-macro-parentheses) +#define MEMBER_SIZE(type, member) sizeof(((type*)NULL)->member) +#define MEMBER_LENGTH(type, member) \ + (MEMBER_SIZE(type, member) / MEMBER_SIZE(type, member[0])) +// NOLINTEND(bugprone-macro-parentheses) + +#define UTF8_MAX_BYTE_COUNT 4 + +enum pipe_fd_index { + READ_END, + WRITE_END, + PIPE_FD_COUNT, +}; + +unsigned int gcd(unsigned int a, unsigned int b); +size_t truncate_utf8_string(char* const buffer, const size_t size, + const size_t char_limit); + +#endif // UTIL_H diff --git a/.config/suckless/dwmblocks/include/watcher.h b/.config/suckless/dwmblocks/include/watcher.h new file mode 100644 index 0000000..ff31809 --- /dev/null +++ b/.config/suckless/dwmblocks/include/watcher.h @@ -0,0 +1,28 @@ +#ifndef WATCHER_H +#define WATCHER_H + +#include +#include + +#include "block.h" +#include "main.h" + +enum watcher_fd_index { + SIGNAL_FD = BLOCK_COUNT, + WATCHER_FD_COUNT, +}; + +typedef struct pollfd watcher_fd; + +typedef struct { + watcher_fd fds[WATCHER_FD_COUNT]; + unsigned short active_blocks[BLOCK_COUNT]; + unsigned short active_block_count; + bool got_signal; +} watcher; + +int watcher_init(watcher *const watcher, const block *const blocks, + const unsigned short block_count, const int signal_fd); +int watcher_poll(watcher *const watcher, const int timeout_ms); + +#endif // WATCHER_H diff --git a/.config/suckless/dwmblocks/include/x11.h b/.config/suckless/dwmblocks/include/x11.h new file mode 100644 index 0000000..6faaced --- /dev/null +++ b/.config/suckless/dwmblocks/include/x11.h @@ -0,0 +1,13 @@ +#ifndef X11_H +#define X11_H + +#include + +typedef xcb_connection_t x11_connection; + +x11_connection* x11_connection_open(void); +void x11_connection_close(x11_connection* const connection); +int x11_set_root_name(x11_connection* const connection, + const char* const name); + +#endif // X11_H diff --git a/.config/suckless/dwmblocks/preview.png b/.config/suckless/dwmblocks/preview.png new file mode 100644 index 0000000..5c00274 Binary files /dev/null and b/.config/suckless/dwmblocks/preview.png differ diff --git a/.config/suckless/dwmblocks/src/block.c b/.config/suckless/dwmblocks/src/block.c new file mode 100644 index 0000000..5020b02 --- /dev/null +++ b/.config/suckless/dwmblocks/src/block.c @@ -0,0 +1,158 @@ +#include "block.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "util.h" + +block block_new(const char *const command, const unsigned int interval, + const int signal) { + block block = { + .command = command, + .interval = interval, + .signal = signal, + + .output = {[0] = '\0'}, + .fork_pid = -1, + }; + + return block; +} + +int block_init(block *const block) { + if (pipe(block->pipe) != 0) { + (void)fprintf(stderr, + "error: could not create a pipe for \"%s\" block\n", + block->command); + return 1; + } + + return 0; +} + +int block_deinit(block *const block) { + int status = close(block->pipe[READ_END]); + status |= close(block->pipe[WRITE_END]); + if (status != 0) { + (void)fprintf(stderr, "error: could not close \"%s\" block's pipe\n", + block->command); + return 1; + } + + return 0; +} + +int block_execute(block *const block, const uint8_t button) { + // Ensure only one child process exists per block at an instance. + if (block->fork_pid != -1) { + return 0; + } + + block->fork_pid = fork(); + if (block->fork_pid == -1) { + (void)fprintf( + stderr, "error: could not create a subprocess for \"%s\" block\n", + block->command); + return 1; + } + + if (block->fork_pid == 0) { + const int write_fd = block->pipe[WRITE_END]; + int status = close(block->pipe[READ_END]); + + if (button != 0) { + char button_str[4]; + (void)snprintf(button_str, LEN(button_str), "%hhu", button); + status |= setenv("BLOCK_BUTTON", button_str, 1); + } + + const char null = '\0'; + if (status != 0) { + (void)write(write_fd, &null, sizeof(null)); + exit(EXIT_FAILURE); + } + + FILE *const file = popen(block->command, "r"); + if (file == NULL) { + (void)write(write_fd, &null, sizeof(null)); + exit(EXIT_FAILURE); + } + + // Ensure null-termination since fgets() will leave buffer untouched on + // no output. + char buffer[LEN(block->output)] = {[0] = null}; + (void)fgets(buffer, LEN(buffer), file); + + // Remove trailing newlines. + const size_t length = strcspn(buffer, "\n"); + buffer[length] = null; + + // Exit if command execution failed or if file could not be closed. + if (pclose(file) != 0) { + (void)write(write_fd, &null, sizeof(null)); + exit(EXIT_FAILURE); + } + + const size_t output_size = + truncate_utf8_string(buffer, LEN(buffer), MAX_BLOCK_OUTPUT_LENGTH); + (void)write(write_fd, buffer, output_size); + + exit(EXIT_SUCCESS); + } + + return 0; +} + +int block_update(block *const block) { + char buffer[LEN(block->output)]; + + const ssize_t bytes_read = + read(block->pipe[READ_END], buffer, LEN(buffer)); + if (bytes_read == -1) { + (void)fprintf(stderr, + "error: could not fetch output of \"%s\" block\n", + block->command); + return 2; + } + + // Collect exit-status of the subprocess to avoid zombification. + int fork_status = 0; + if (waitpid(block->fork_pid, &fork_status, 0) == -1) { + (void)fprintf(stderr, + "error: could not obtain exit status for \"%s\" block\n", + block->command); + return 2; + } + block->fork_pid = -1; + + if (fork_status != 0) { + (void)fprintf(stderr, + "error: \"%s\" block exited with non-zero status\n", + block->command); + return 1; + } + + (void)strncpy(block->output, buffer, LEN(buffer)); + + return 0; +} + +bool block_must_run(const block *const block, const unsigned int time) { + if (time == 0) { + return true; + } + + if (block->interval == 0) { + return false; + } + + return time % block->interval == 0; +} diff --git a/.config/suckless/dwmblocks/src/cli.c b/.config/suckless/dwmblocks/src/cli.c new file mode 100644 index 0000000..1a48863 --- /dev/null +++ b/.config/suckless/dwmblocks/src/cli.c @@ -0,0 +1,30 @@ +#include "cli.h" + +#include +#include +#include + +int cli_init(cli_arguments *const args, const char *const argv[], + const int argc) { + args->is_debug_mode = false; + + int opt = -1; + opterr = 0; // Suppress getopt's built-in invalid opt message + while ((opt = getopt(argc, (char *const *)argv, "dh")) != -1) { + switch (opt) { + case 'd': + args->is_debug_mode = true; + break; + case '?': + (void)fprintf(stderr, "error: unknown option `-%c'\n", optopt); + // fall through + case 'h': + // fall through + default: + (void)fprintf(stderr, "usage: %s [-d]\n", BINARY); + return 1; + } + } + + return 0; +} diff --git a/.config/suckless/dwmblocks/src/main.c b/.config/suckless/dwmblocks/src/main.c new file mode 100644 index 0000000..a858d88 --- /dev/null +++ b/.config/suckless/dwmblocks/src/main.c @@ -0,0 +1,166 @@ +#include "main.h" + +#include +#include + +#include "block.h" +#include "cli.h" +#include "config.h" +#include "signal-handler.h" +#include "status.h" +#include "timer.h" +#include "util.h" +#include "watcher.h" +#include "x11.h" + +static int init_blocks(block *const blocks, const unsigned short block_count) { + for (unsigned short i = 0; i < block_count; ++i) { + block *const block = &blocks[i]; + if (block_init(block) != 0) { + return 1; + } + } + + return 0; +} + +static int deinit_blocks(block *const blocks, + const unsigned short block_count) { + for (unsigned short i = 0; i < block_count; ++i) { + block *const block = &blocks[i]; + if (block_deinit(block) != 0) { + return 1; + } + } + + return 0; +} + +static int execute_blocks(block *const blocks, + const unsigned short block_count, + const unsigned int time) { + for (unsigned short i = 0; i < block_count; ++i) { + block *const block = &blocks[i]; + if (!block_must_run(block, time)) { + continue; + } + + if (block_execute(&blocks[i], 0) != 0) { + return 1; + } + } + + return 0; +} + +static int trigger_event(block *const blocks, const unsigned short block_count, + timer *const timer) { + if (execute_blocks(blocks, block_count, timer->time) != 0) { + return 1; + } + + if (timer_arm(timer) != 0) { + return 1; + } + + return 0; +} + +static int refresh_callback(block *const blocks, + const unsigned short block_count) { + if (execute_blocks(blocks, block_count, 0) != 0) { + return 1; + } + + return 0; +} + +static int event_loop(block *const blocks, const unsigned short block_count, + const bool is_debug_mode, + x11_connection *const connection, + signal_handler *const signal_handler) { + timer timer = timer_new(blocks, block_count); + + // Kickstart the event loop with an initial execution. + if (trigger_event(blocks, block_count, &timer) != 0) { + return 1; + } + + watcher watcher; + if (watcher_init(&watcher, blocks, block_count, signal_handler->fd) != 0) { + return 1; + } + + status status = status_new(blocks, block_count); + bool is_alive = true; + while (is_alive) { + if (watcher_poll(&watcher, -1) != 0) { + return 1; + } + + if (watcher.got_signal) { + is_alive = signal_handler_process(signal_handler, &timer) == 0; + } + + for (unsigned short i = 0; i < watcher.active_block_count; ++i) { + (void)block_update(&blocks[watcher.active_blocks[i]]); + } + + const bool has_status_changed = status_update(&status); + if (has_status_changed && + status_write(&status, is_debug_mode, connection) != 0) { + return 1; + } + } + + return 0; +} + +int main(const int argc, const char *const argv[]) { + cli_arguments cli_args; + if (cli_init(&cli_args, argv, argc) != 0) { + return 1; + } + + x11_connection *const connection = x11_connection_open(); + if (connection == NULL) { + return 1; + } + +#define BLOCK(command, interval, signal) block_new(command, interval, signal), + block blocks[BLOCK_COUNT] = {BLOCKS(BLOCK)}; +#undef BLOCK + const unsigned short block_count = LEN(blocks); + + int status = 0; + if (init_blocks(blocks, block_count) != 0) { + status = 1; + goto x11_close; + } + + signal_handler signal_handler = signal_handler_new( + blocks, block_count, refresh_callback, trigger_event); + if (signal_handler_init(&signal_handler) != 0) { + status = 1; + goto deinit_blocks; + } + + if (event_loop(blocks, block_count, cli_args.is_debug_mode, connection, + &signal_handler) != 0) { + status = 1; + } + + if (signal_handler_deinit(&signal_handler) != 0) { + status = 1; + } + +deinit_blocks: + if (deinit_blocks(blocks, block_count) != 0) { + status = 1; + } + +x11_close: + x11_connection_close(connection); + + return status; +} diff --git a/.config/suckless/dwmblocks/src/signal-handler.c b/.config/suckless/dwmblocks/src/signal-handler.c new file mode 100644 index 0000000..d816dcd --- /dev/null +++ b/.config/suckless/dwmblocks/src/signal-handler.c @@ -0,0 +1,124 @@ +#include "signal-handler.h" + +#include +#include +#include +#include +#include +#include + +#include "block.h" +#include "main.h" +#include "timer.h" + +typedef struct signalfd_siginfo signal_info; + +signal_handler signal_handler_new( + block *const blocks, const unsigned short block_count, + const signal_refresh_callback refresh_callback, + const signal_timer_callback timer_callback) { + signal_handler handler = { + .refresh_callback = refresh_callback, + .timer_callback = timer_callback, + + .blocks = blocks, + .block_count = block_count, + }; + + return handler; +} + +int signal_handler_init(signal_handler *const handler) { + signal_set set; + (void)sigemptyset(&set); + + // Handle user-generated signal for refreshing the status. + (void)sigaddset(&set, REFRESH_SIGNAL); + + // Handle SIGALRM generated by the timer. + (void)sigaddset(&set, TIMER_SIGNAL); + + // Handle termination signals. + (void)sigaddset(&set, SIGINT); + (void)sigaddset(&set, SIGTERM); + + for (unsigned short i = 0; i < handler->block_count; ++i) { + const block *const block = &handler->blocks[i]; + if (block->signal > 0) { + if (sigaddset(&set, SIGRTMIN + block->signal) != 0) { + (void)fprintf( + stderr, + "error: invalid or unsupported signal specified for " + "\"%s\" block\n", + block->command); + return 1; + } + } + } + + // Create a signal file descriptor for epoll to watch. + handler->fd = signalfd(-1, &set, 0); + if (handler->fd == -1) { + (void)fprintf(stderr, + "error: could not create file descriptor for signals\n"); + return 1; + } + + // Block all realtime and handled signals. + for (int i = SIGRTMIN; i <= SIGRTMAX; ++i) { + (void)sigaddset(&set, i); + } + (void)sigprocmask(SIG_BLOCK, &set, NULL); + + return 0; +} + +int signal_handler_deinit(signal_handler *const handler) { + if (close(handler->fd) != 0) { + (void)fprintf(stderr, + "error: could not close signal file descriptor\n"); + return 1; + } + + return 0; +} + +int signal_handler_process(signal_handler *const handler, timer *const timer) { + signal_info info; + const ssize_t bytes_read = read(handler->fd, &info, sizeof(info)); + if (bytes_read == -1) { + (void)fprintf(stderr, "error: could not read info of incoming signal"); + return 1; + } + + const int signal = (int)info.ssi_signo; + switch (signal) { + case TIMER_SIGNAL: + if (handler->timer_callback(handler->blocks, handler->block_count, + timer) != 0) { + return 1; + } + return 0; + case REFRESH_SIGNAL: + if (handler->refresh_callback(handler->blocks, + handler->block_count) != 0) { + return 1; + } + return 0; + case SIGTERM: + // fall through + case SIGINT: + return 1; + } + + for (unsigned short i = 0; i < handler->block_count; ++i) { + block *const block = &handler->blocks[i]; + if (block->signal == signal - SIGRTMIN) { + const uint8_t button = (uint8_t)info.ssi_int; + block_execute(block, button); + break; + } + } + + return 0; +} diff --git a/.config/suckless/dwmblocks/src/status.c b/.config/suckless/dwmblocks/src/status.c new file mode 100644 index 0000000..a3a4794 --- /dev/null +++ b/.config/suckless/dwmblocks/src/status.c @@ -0,0 +1,77 @@ +#include "status.h" + +#include +#include +#include + +#include "block.h" +#include "config.h" +#include "util.h" +#include "x11.h" + +static bool has_status_changed(const status *const status) { + return strcmp(status->current, status->previous) != 0; +} + +status status_new(const block *const blocks, + const unsigned short block_count) { + status status = { + .current = {[0] = '\0'}, + .previous = {[0] = '\0'}, + + .blocks = blocks, + .block_count = block_count, + }; + + return status; +} + +bool status_update(status *const status) { + (void)strncpy(status->previous, status->current, LEN(status->current)); + status->current[0] = '\0'; + + for (unsigned short i = 0; i < status->block_count; ++i) { + const block *const block = &status->blocks[i]; + + if (strlen(block->output) > 0) { +#if LEADING_DELIMITER + (void)strncat(status->current, DELIMITER, LEN(DELIMITER)); +#else + if (status->current[0] != '\0') { + (void)strncat(status->current, DELIMITER, LEN(DELIMITER)); + } +#endif + +#if CLICKABLE_BLOCKS + if (block->signal > 0) { + const char signal[] = {(char)block->signal, '\0'}; + (void)strncat(status->current, signal, LEN(signal)); + } +#endif + + (void)strncat(status->current, block->output, LEN(block->output)); + } + } + +#if TRAILING_DELIMITER + if (status->current[0] != '\0') { + (void)strncat(status->current, DELIMITER, LEN(DELIMITER)); + } +#endif + + return has_status_changed(status); +} + +int status_write(const status *const status, const bool is_debug_mode, + x11_connection *const connection) { + if (is_debug_mode) { + (void)printf("%s\n", status->current); + return 0; + } + + if (x11_set_root_name(connection, status->current) != 0) { + return 1; + } + + return 0; +} diff --git a/.config/suckless/dwmblocks/src/timer.c b/.config/suckless/dwmblocks/src/timer.c new file mode 100644 index 0000000..a9a383c --- /dev/null +++ b/.config/suckless/dwmblocks/src/timer.c @@ -0,0 +1,57 @@ +#include "timer.h" + +#include +#include +#include + +#include "block.h" +#include "util.h" + +static unsigned int compute_tick(const block *const blocks, + const unsigned short block_count) { + unsigned int tick = 0; + + for (unsigned short i = 0; i < block_count; ++i) { + const block *const block = &blocks[i]; + tick = gcd(block->interval, tick); + } + + return tick; +} + +static unsigned int compute_reset_value(const block *const blocks, + const unsigned short block_count) { + unsigned int reset_value = 1; + + for (unsigned short i = 0; i < block_count; ++i) { + const block *const block = &blocks[i]; + reset_value = MAX(block->interval, reset_value); + } + + return reset_value; +} + +timer timer_new(const block *const blocks, const unsigned short block_count) { + timer timer = { + .time = 0, + .tick = compute_tick(blocks, block_count), + .reset_value = compute_reset_value(blocks, block_count), + }; + + return timer; +} + +int timer_arm(timer *const timer) { + errno = 0; + (void)alarm(timer->tick); + + if (errno != 0) { + (void)fprintf(stderr, "error: could not arm timer\n"); + return 1; + } + + // Wrap `time` to the interval [1, reset_value]. + timer->time = (timer->time + timer->tick) % timer->reset_value + 1; + + return 0; +} diff --git a/.config/suckless/dwmblocks/src/util.c b/.config/suckless/dwmblocks/src/util.c new file mode 100644 index 0000000..10485db --- /dev/null +++ b/.config/suckless/dwmblocks/src/util.c @@ -0,0 +1,49 @@ +#include "util.h" + +#define UTF8_MULTIBYTE_BIT BIT(7) + +unsigned int gcd(unsigned int a, unsigned int b) { + while (b > 0) { + const unsigned int temp = a % b; + a = b; + b = temp; + } + + return a; +} + +size_t truncate_utf8_string(char* const buffer, const size_t size, + const size_t char_limit) { + size_t char_count = 0; + size_t i = 0; + while (char_count < char_limit) { + char ch = buffer[i]; + if (ch == '\0') { + break; + } + + unsigned short skip = 1; + + // Multibyte unicode character. + if ((ch & UTF8_MULTIBYTE_BIT) != 0) { + // Skip continuation bytes. + ch <<= 1; + while ((ch & UTF8_MULTIBYTE_BIT) != 0) { + ch <<= 1; + ++skip; + } + } + + // Avoid buffer overflow. + if (i + skip >= size) { + break; + } + + ++char_count; + i += skip; + } + + buffer[i] = '\0'; + + return i + 1; +} diff --git a/.config/suckless/dwmblocks/src/watcher.c b/.config/suckless/dwmblocks/src/watcher.c new file mode 100644 index 0000000..71b6c52 --- /dev/null +++ b/.config/suckless/dwmblocks/src/watcher.c @@ -0,0 +1,69 @@ +#include "watcher.h" + +#include +#include +#include +#include + +#include "block.h" +#include "util.h" + +static bool watcher_fd_is_readable(const watcher_fd* const watcher_fd) { + return (watcher_fd->revents & POLLIN) != 0; +} + +int watcher_init(watcher* const watcher, const block* const blocks, + const unsigned short block_count, const int signal_fd) { + if (signal_fd == -1) { + (void)fprintf( + stderr, + "error: invalid signal file descriptor passed to watcher\n"); + return 1; + } + + watcher_fd* const fd = &watcher->fds[SIGNAL_FD]; + fd->fd = signal_fd; + fd->events = POLLIN; + + for (unsigned short i = 0; i < block_count; ++i) { + const int block_fd = blocks[i].pipe[READ_END]; + if (block_fd == -1) { + (void)fprintf( + stderr, + "error: invalid block file descriptors passed to watcher\n"); + return 1; + } + + watcher_fd* const fd = &watcher->fds[i]; + fd->fd = block_fd; + fd->events = POLLIN; + } + + return 0; +} + +int watcher_poll(watcher* watcher, const int timeout_ms) { + int event_count = poll(watcher->fds, LEN(watcher->fds), timeout_ms); + + // Don't return non-zero status for signal interruptions. + if (event_count == -1 && errno != EINTR) { + (void)fprintf(stderr, "error: watcher could not poll blocks\n"); + return 1; + } + + watcher->got_signal = watcher_fd_is_readable(&watcher->fds[SIGNAL_FD]); + + watcher->active_block_count = event_count - (int)watcher->got_signal; + unsigned short i = 0; + unsigned short j = 0; + while (i < event_count && j < LEN(watcher->active_blocks)) { + if (watcher_fd_is_readable(&watcher->fds[j])) { + watcher->active_blocks[i] = j; + ++i; + } + + ++j; + } + + return 0; +} diff --git a/.config/suckless/dwmblocks/src/x11.c b/.config/suckless/dwmblocks/src/x11.c new file mode 100644 index 0000000..7a310e9 --- /dev/null +++ b/.config/suckless/dwmblocks/src/x11.c @@ -0,0 +1,44 @@ +#include "x11.h" + +#include +#include +#include +#include + +x11_connection *x11_connection_open(void) { + xcb_connection_t *const connection = xcb_connect(NULL, NULL); + if (xcb_connection_has_error(connection)) { + (void)fprintf(stderr, "error: could not connect to X server\n"); + return NULL; + } + + return connection; +} + +void x11_connection_close(xcb_connection_t *const connection) { + xcb_disconnect(connection); +} + +int x11_set_root_name(x11_connection *const connection, const char *name) { + xcb_screen_t *const screen = + xcb_setup_roots_iterator(xcb_get_setup(connection)).data; + const xcb_window_t root_window = screen->root; + + const unsigned short name_format = 8; + const xcb_void_cookie_t cookie = xcb_change_property( + connection, XCB_PROP_MODE_REPLACE, root_window, XCB_ATOM_WM_NAME, + XCB_ATOM_STRING, name_format, strlen(name), name); + + xcb_generic_error_t *error = xcb_request_check(connection, cookie); + if (error != NULL) { + (void)fprintf(stderr, "error: could not set X root name\n"); + return 1; + } + + if (xcb_flush(connection) <= 0) { + (void)fprintf(stderr, "error: could not flush X output buffer\n"); + return 1; + } + + return 0; +} diff --git a/.config/suckless/st/LICENSE b/.config/suckless/st/LICENSE new file mode 100644 index 0000000..3cbf420 --- /dev/null +++ b/.config/suckless/st/LICENSE @@ -0,0 +1,34 @@ +MIT/X Consortium License + +© 2014-2022 Hiltjo Posthuma +© 2018 Devin J. Pohly +© 2014-2017 Quentin Rameau +© 2009-2012 Aurélien APTEL +© 2008-2017 Anselm R Garbe +© 2012-2017 Roberto E. Vargas Caballero +© 2012-2016 Christoph Lohmann <20h at r-36 dot net> +© 2013 Eon S. Jeon +© 2013 Alexander Sedov +© 2013 Mark Edgar +© 2013-2014 Eric Pruitt +© 2013 Michael Forney +© 2013-2014 Markus Teich +© 2014-2015 Laslo Hunhold + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/.config/suckless/st/Makefile b/.config/suckless/st/Makefile new file mode 100644 index 0000000..3dc6258 --- /dev/null +++ b/.config/suckless/st/Makefile @@ -0,0 +1,54 @@ +# st - simple terminal +# See LICENSE file for copyright and license details. +.POSIX: + +include config.mk + +SRC = st.c x.c $(LIGATURES_C) $(SIXEL_C) +OBJ = $(SRC:.c=.o) + +all: st + +config.h: + cp config.def.h config.h + +.c.o: + $(CC) $(STCFLAGS) -c $< + +st.o: config.h st.h win.h +x.o: arg.h config.h st.h win.h $(LIGATURES_H) + +$(OBJ): config.h config.mk + +st: $(OBJ) + $(CC) -o $@ $(OBJ) $(STLDFLAGS) + +clean: + rm -f st $(OBJ) st-$(VERSION).tar.gz + +dist: clean + mkdir -p st-$(VERSION) + cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ + config.def.h st.info st.1 arg.h st.h win.h $(LIGATURES_H) $(SRC)\ + st-$(VERSION) + tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz + rm -rf st-$(VERSION) + +install: st + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f st $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/st + mkdir -p $(DESTDIR)$(MANPREFIX)/man1 + sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 + tic -sx st.info + mkdir -p $(DESTDIR)$(PREFIX)/share/applications # desktop-entry patch + test -f ${DESTDIR}${PREFIX}/share/applications/st.desktop || cp -n st.desktop $(DESTDIR)$(PREFIX)/share/applications # desktop-entry patch + @echo Please see the README file regarding the terminfo entry of st. + +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/st + rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 + rm -f $(DESTDIR)$(PREFIX)/share/applications/st.desktop # desktop-entry patch + +.PHONY: all clean dist install uninstall diff --git a/.config/suckless/st/README.md b/.config/suckless/st/README.md new file mode 100644 index 0000000..748fe9d --- /dev/null +++ b/.config/suckless/st/README.md @@ -0,0 +1,31 @@ +# st - suckless terminal + +This is my configuration for st generated by [st flexipatch](https://github.com/mintycube/dwm-flexipatch) and finalized by [flexipatch finalizer](https://github.com/mintycube/flexipatch-finalizer). + +## Patches + +The patches used and the accompanying documentation is listed below: + +- ALPHA PATCH [link]() +- BLINKING CURSOR PATCH [link]() +- BOLD IS NOT BRIGHT PATCH [link]() +- BOXDRAW PATCH [link]() +- CLIPBOARD PATCH [link]() +- FONT2 PATCH [link]() +- HIDE TERMINAL CURSOR PATCH [link]() +- INVERT PATCH [link]() +- ISO14755 PATCH [link]() +- LIGATURES PATCH [link]() +- NEWTERM PATCH [link]() +- SCROLLBACK PATCH [link]() +- SCROLLBACK MOUSE PATCH [link]() +- SWAPMOUSE PATCH [link]() +- USE XFTFONTMATCH PATCH [link]() +- VISUALBELL PATCH [link]() +- WIDE GLYPHS PATCH [link]() +- WIDE GLYPH SPACING PATCH [link]() +- XRESOURCES PATCH [link]() +- OPENURLONCLICK_PATCH [link]() +- DEFAULT_CURSOR_PATCH [link](url) +- FIXKEYBOARDINPUT_PATCH [link](url) +- OPENCOPIED_PATCH [link](url) diff --git a/.config/suckless/st/arg.h b/.config/suckless/st/arg.h new file mode 100644 index 0000000..a22e019 --- /dev/null +++ b/.config/suckless/st/arg.h @@ -0,0 +1,50 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][0] == '-'\ + && argv[0][1];\ + argc--, argv++) {\ + char argc_;\ + char **argv_;\ + int brk_;\ + if (argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + int i_;\ + for (i_ = 1, brk_ = 0, argv_ = argv;\ + argv[0][i_] && !brk_;\ + i_++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][i_];\ + switch (argc_) + +#define ARGEND }\ + } + +#define ARGC() argc_ + +#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#endif diff --git a/.config/suckless/st/config.h b/.config/suckless/st/config.h new file mode 100644 index 0000000..0792546 --- /dev/null +++ b/.config/suckless/st/config.h @@ -0,0 +1,554 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +static char *font = + "JetBrainsMono Nerd Font:pixelsize=12:antialias=true:autohint=true"; +/* Spare fonts */ +static char *font2[] = { + "Symbols Nerd Font:pixelsize=12:antialias=true:autohint=true", + "NotoColorEmoji:pixelsize=10:antialias=true:autohint=true", + "Unifont:pixelsize=12"}; + +static int borderpx = 10; + +/* + * What program is execed by st depends of these precedence rules: + * 1: program passed with -e + * 2: scroll and/or utmp + * 3: SHELL environment variable + * 4: value of shell in /etc/passwd + * 5: value of shell in config.h + */ +static char *shell = "/bin/sh"; +char *utmp = NULL; +/* scroll program: to enable use a string like "scroll" */ +char *scroll = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +/* identification sequence returned in DA and DECID */ +char *vtiden = "\033[?6c"; + +/* Kerning / character bounding-box multipliers */ +static float cwscale = 1.0; +static float chscale = 1.0; + +/* + * word delimiter string + * + * More advanced example: L" `'\"()[]{}" + */ +wchar_t *worddelimiters = L" "; + +/* selection timeouts (in milliseconds) */ +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +/* alt screens */ +int allowaltscreen = 1; + +/* allow certain non-interactive (insecure) window operations such as: + setting the clipboard text */ +int allowwindowops = 0; + +/* + * draw latency range in ms - from new content/keypress/etc until drawing. + * within this range, st draws when content stops arriving (idle). mostly it's + * near minlatency, but it waits longer for slow updates to avoid partial draw. + * low minlatency will tear/flicker more, as it can "detect" idle too early. + */ +static double minlatency = 8; +static double maxlatency = 33; + +/* + * blinking timeout (set to 0 to disable blinking) for the terminal blinking + * attribute. + */ +static unsigned int blinktimeout = 800; + +/* + * thickness of underline and bar cursors + */ +static unsigned int cursorthickness = 2; + +/* + * 1: render most of the lines/blocks characters without using the font for + * perfect alignment between cells (U2500 - U259F except dashes/diagonals). + * Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored. + * 0: disable (render all U25XX glyphs normally from the font). + */ +const int boxdraw = 1; +const int boxdraw_bold = 0; + +/* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ +const int boxdraw_braille = 1; + +/* + * bell volume. It must be a value between -100 and 100. Use 0 for disabling + * it + */ +static int bellvolume = 0; + +/* default TERM value */ +char *termname = "st-256color"; + +/* + * spaces per tab + * + * When you are changing this value, don't forget to adapt the »it« value in + * the st.info and appropriately install the st.info in the environment where + * you use this st version. + * + * it#$tabspaces, + * + * Secondly make sure your kernel is not expanding tabs. When running `stty + * -a` »tab0« should appear. You can tell the terminal to not expand tabs by + * running following command: + * + * stty tabs + */ +unsigned int tabspaces = 8; + +/* bg opacity */ +float alpha = 1.0; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + /* 8 normal colors */ + "black", "red3", "green3", "yellow3", "blue2", "magenta3", "cyan3", + "gray90", + + /* 8 bright colors */ + "gray50", "red", "green", "yellow", "#5c5cff", "magenta", "cyan", "white", + + [255] = 0, + + /* more colors can be added after 255 to use with DefaultXX */ + "#add8e6", /* 256 -> cursor */ + "#555555", /* 257 -> rev cursor*/ + "#000000", /* 258 -> bg */ + "#e5e5e5", /* 259 -> fg */ +}; + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultbg = 258; +unsigned int defaultfg = 259; +unsigned int defaultcs = 256; +unsigned int defaultrcs = 257; + +/* + * https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81 + * Default style of cursor + * 0: Blinking block + * 1: Blinking block (default) + * 2: Steady block ("â–ˆ") + * 3: Blinking underline + * 4: Steady underline ("_") + * 5: Blinking bar + * 6: Steady bar ("|") + * 7: Blinking st cursor + * 8: Steady st cursor + */ +static unsigned int cursorstyle = 3; +static Rune stcursor = 0x2603; /* snowman (U+2603) */ + +/* + * Default columns and rows numbers + */ + +static unsigned int cols = 80; +static unsigned int rows = 24; + +/* + * Default colour and shape of the mouse cursor + */ +static unsigned int mouseshape = XC_xterm; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; + +/* + * Color used to display font attributes when fontconfig selected a font which + * doesn't match the ones requested. + */ +static unsigned int defaultattr = 11; + +/* + * Xresources preferences to load at startup + */ +ResourcePref resources[] = { + {"font", STRING, &font}, + {"color0", STRING, &colorname[0]}, + {"color1", STRING, &colorname[1]}, + {"color2", STRING, &colorname[2]}, + {"color3", STRING, &colorname[3]}, + {"color4", STRING, &colorname[4]}, + {"color5", STRING, &colorname[5]}, + {"color6", STRING, &colorname[6]}, + {"color7", STRING, &colorname[7]}, + {"color8", STRING, &colorname[8]}, + {"color9", STRING, &colorname[9]}, + {"color10", STRING, &colorname[10]}, + {"color11", STRING, &colorname[11]}, + {"color12", STRING, &colorname[12]}, + {"color13", STRING, &colorname[13]}, + {"color14", STRING, &colorname[14]}, + {"color15", STRING, &colorname[15]}, + {"background", STRING, &colorname[258]}, + {"foreground", STRING, &colorname[259]}, + {"cursorColor", STRING, &colorname[256]}, + {"termname", STRING, &termname}, + {"shell", STRING, &shell}, + {"minlatency", INTEGER, &minlatency}, + {"maxlatency", INTEGER, &maxlatency}, + {"blinktimeout", INTEGER, &blinktimeout}, + {"bellvolume", INTEGER, &bellvolume}, + {"tabspaces", INTEGER, &tabspaces}, + {"borderpx", INTEGER, &borderpx}, + {"cwscale", FLOAT, &cwscale}, + {"chscale", FLOAT, &chscale}, + {"alpha", FLOAT, &alpha}, +}; + +/* + * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forcemousemod = ShiftMask; + +/* + * Internal mouse shortcuts. + * Beware that overloading Button1 will disable the selection. + */ +static MouseShortcut mshortcuts[] = { + /* mask button function argument release + screen */ + {XK_ANY_MOD, Button2, clippaste, {.i = 0}, 1}, + {ShiftMask, Button4, ttysend, {.s = "\033[5;2~"}}, + {ShiftMask, Button5, ttysend, {.s = "\033[6;2~"}}, + {XK_NO_MOD, Button4, kscrollup, {.i = 1}, 0, S_PRI}, + {XK_NO_MOD, Button5, kscrolldown, {.i = 1}, 0, S_PRI}, + {XK_ANY_MOD, Button4, ttysend, {.s = "\031"}, 0, S_ALT}, + {XK_ANY_MOD, Button5, ttysend, {.s = "\005"}, 0, S_ALT}, +}; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (ControlMask | ShiftMask) + +static char *openurlcmd[] = {"/bin/sh", "-c", + "xurls | dmenu -l 10 -w $WINDOWID | xargs -r open", + "externalpipe", NULL}; + +static char *setbgcolorcmd[] = {"/bin/sh", "-c", "printf '\033]11;#008000\007'", + "externalpipein", NULL}; + +static Shortcut shortcuts[] = { + /* mask keysym function argument screen + */ + {XK_ANY_MOD, XK_Break, sendbreak, {.i = 0}}, + {ControlMask, XK_Print, toggleprinter, {.i = 0}}, + {ShiftMask, XK_Print, printscreen, {.i = 0}}, + {XK_ANY_MOD, XK_Print, printsel, {.i = 0}}, + {TERMMOD, XK_Prior, zoom, {.f = +1}}, + {TERMMOD, XK_Next, zoom, {.f = -1}}, + {TERMMOD, XK_Home, zoomreset, {.f = 0}}, + {TERMMOD, XK_C, clipcopy, {.i = 0}}, + {TERMMOD, XK_V, clippaste, {.i = 0}}, + {TERMMOD, XK_O, changealpha, {.f = +0.05}}, + {TERMMOD, XK_P, changealpha, {.f = -0.05}}, + {ShiftMask, XK_Page_Up, kscrollup, {.i = -1}, S_PRI}, + {ShiftMask, XK_Page_Down, kscrolldown, {.i = -1}, S_PRI}, + {TERMMOD, XK_Y, clippaste, {.i = 0}}, + {ShiftMask, XK_Insert, clippaste, {.i = 0}}, + {TERMMOD, XK_Num_Lock, numlock, {.i = 0}}, + {MODKEY, XK_l, copyurl, {.i = 0}}, + {TERMMOD, XK_Return, newterm, {.i = 0}}, + {TERMMOD, XK_I, iso14755, {.i = 0}}, + {TERMMOD, XK_X, invert, {0}}, + {TERMMOD, XK_Up, zoom, {.f = +1}}, + {TERMMOD, XK_Down, zoom, {.f = -1}}, + {TERMMOD, XK_K, zoom, {.f = +1}}, + {TERMMOD, XK_J, zoom, {.f = -1}}, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = {-1}; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask | XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + {XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + {XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + {XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + {XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + {XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + {XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + {XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + {XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + {XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + {XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + {XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + {XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + {XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + {XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + {XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + {XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + {XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + {XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + {XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + {XK_KP_End, ControlMask, "\033[J", -1, 0}, + {XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + {XK_KP_End, ShiftMask, "\033[K", -1, 0}, + {XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + {XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + {XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + {XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + {XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + {XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + {XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + {XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + {XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + {XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + {XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + {XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + {XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + {XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + {XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + {XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + {XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + {XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + {XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + {XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + {XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + {XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + {XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + {XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + {XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + {XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + {XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + {XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + {XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + {XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + {XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + {XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + {XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + {XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + {XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + {XK_Up, ShiftMask | Mod1Mask, "\033[1;4A", 0, 0}, + {XK_Up, ControlMask, "\033[1;5A", 0, 0}, + {XK_Up, ShiftMask | ControlMask, "\033[1;6A", 0, 0}, + {XK_Up, ControlMask | Mod1Mask, "\033[1;7A", 0, 0}, + {XK_Up, ShiftMask | ControlMask | Mod1Mask, "\033[1;8A", 0, 0}, + {XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + {XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + {XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + {XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + {XK_Down, ShiftMask | Mod1Mask, "\033[1;4B", 0, 0}, + {XK_Down, ControlMask, "\033[1;5B", 0, 0}, + {XK_Down, ShiftMask | ControlMask, "\033[1;6B", 0, 0}, + {XK_Down, ControlMask | Mod1Mask, "\033[1;7B", 0, 0}, + {XK_Down, ShiftMask | ControlMask | Mod1Mask, "\033[1;8B", 0, 0}, + {XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + {XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + {XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + {XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + {XK_Left, ShiftMask | Mod1Mask, "\033[1;4D", 0, 0}, + {XK_Left, ControlMask, "\033[1;5D", 0, 0}, + {XK_Left, ShiftMask | ControlMask, "\033[1;6D", 0, 0}, + {XK_Left, ControlMask | Mod1Mask, "\033[1;7D", 0, 0}, + {XK_Left, ShiftMask | ControlMask | Mod1Mask, "\033[1;8D", 0, 0}, + {XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + {XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + {XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + {XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + {XK_Right, ShiftMask | Mod1Mask, "\033[1;4C", 0, 0}, + {XK_Right, ControlMask, "\033[1;5C", 0, 0}, + {XK_Right, ShiftMask | ControlMask, "\033[1;6C", 0, 0}, + {XK_Right, ControlMask | Mod1Mask, "\033[1;7C", 0, 0}, + {XK_Right, ShiftMask | ControlMask | Mod1Mask, "\033[1;8C", 0, 0}, + {XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + {XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + {XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + {XK_Return, Mod1Mask, "\033\r", 0, 0}, + {XK_Return, XK_ANY_MOD, "\r", 0, 0}, + {XK_Insert, ShiftMask, "\033[4l", -1, 0}, + {XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + {XK_Insert, ControlMask, "\033[L", -1, 0}, + {XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + {XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + {XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + {XK_Delete, ControlMask, "\033[M", -1, 0}, + {XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + {XK_Delete, ShiftMask, "\033[2K", -1, 0}, + {XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + {XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + {XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + {XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + {XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + {XK_Home, ShiftMask, "\033[2J", 0, -1}, + {XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + {XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + {XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + {XK_End, ControlMask, "\033[J", -1, 0}, + {XK_End, ControlMask, "\033[1;5F", +1, 0}, + {XK_End, ShiftMask, "\033[K", -1, 0}, + {XK_End, ShiftMask, "\033[1;2F", +1, 0}, + {XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + {XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + {XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + {XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + {XK_Next, ControlMask, "\033[6;5~", 0, 0}, + {XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + {XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + {XK_F1, XK_NO_MOD, "\033OP", 0, 0}, + {XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + {XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + {XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + {XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + {XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + {XK_F2, XK_NO_MOD, "\033OQ", 0, 0}, + {XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + {XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + {XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + {XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + {XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + {XK_F3, XK_NO_MOD, "\033OR", 0, 0}, + {XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + {XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + {XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + {XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + {XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + {XK_F4, XK_NO_MOD, "\033OS", 0, 0}, + {XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + {XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + {XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + {XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + {XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + {XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + {XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + {XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + {XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + {XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + {XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + {XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + {XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + {XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + {XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + {XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + {XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + {XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + {XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + {XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + {XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + {XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + {XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + {XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + {XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + {XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + {XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + {XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + {XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + {XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + {XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + {XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + {XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + {XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + {XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + {XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + {XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + {XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + {XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + {XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + {XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + {XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + {XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + {XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + {XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + {XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + {XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + {XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + {XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + {XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + {XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + {XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + {XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + {XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + {XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + {XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + {XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + {XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + {XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + {XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + {XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + {XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + {XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + {XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + {XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + {XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + {XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; + +/* + * plumb_cmd is run on mouse button 3 click, with argument set to + * current selection and with cwd set to the cwd of the active shell + */ +static char *plumb_cmd = "dmenuhandler"; diff --git a/.config/suckless/st/config.mk b/.config/suckless/st/config.mk new file mode 100644 index 0000000..762b066 --- /dev/null +++ b/.config/suckless/st/config.mk @@ -0,0 +1,53 @@ +# st version +VERSION = 0.9 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +PKG_CONFIG = pkg-config + +# Uncomment this for the alpha patch / ALPHA_PATCH +XRENDER = -lXrender + +# Uncomment this for the themed cursor patch / THEMED_CURSOR_PATCH +#XCURSOR = -lXcursor + +# Uncomment the lines below for the ligatures patch / LIGATURES_PATCH +LIGATURES_C = hb.c +LIGATURES_H = hb.h +LIGATURES_INC = `$(PKG_CONFIG) --cflags harfbuzz` +LIGATURES_LIBS = `$(PKG_CONFIG) --libs harfbuzz` + +# Uncomment this for the SIXEL patch / SIXEL_PATCH +#SIXEL_C = sixel.c sixel_hls.c + +# includes and libs, uncomment harfbuzz for the ligatures patch +INCS = -I$(X11INC) \ + `$(PKG_CONFIG) --cflags fontconfig` \ + `$(PKG_CONFIG) --cflags freetype2` \ + $(LIGATURES_INC) +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft ${XRENDER} ${XCURSOR}\ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` \ + $(LIGATURES_LIBS) + +# flags +STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 +STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) +STLDFLAGS = $(LIBS) $(LDFLAGS) + +# OpenBSD: +#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE +#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ +# `pkg-config --libs fontconfig` \ +# `pkg-config --libs freetype2` +#MANPREFIX = ${PREFIX}/man + +# compiler and linker +# CC = c99 diff --git a/.config/suckless/st/hb.c b/.config/suckless/st/hb.c new file mode 100644 index 0000000..db845e7 --- /dev/null +++ b/.config/suckless/st/hb.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "st.h" +#include "hb.h" + +#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, .start = HB_FEATURE_GLOBAL_START, .end = HB_FEATURE_GLOBAL_END } + +hb_font_t *hbfindfont(XftFont *match); + +typedef struct { + XftFont *match; + hb_font_t *font; +} HbFontMatch; + +static int hbfontslen = 0; +static HbFontMatch *hbfontcache = NULL; + +/* + * Poplulate the array with a list of font features, wrapped in FEATURE macro, + * e. g. + * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g') + */ +hb_feature_t features[] = { 0 }; + +void +hbunloadfonts() +{ + for (int i = 0; i < hbfontslen; i++) { + hb_font_destroy(hbfontcache[i].font); + XftUnlockFace(hbfontcache[i].match); + } + + if (hbfontcache != NULL) { + free(hbfontcache); + hbfontcache = NULL; + } + hbfontslen = 0; +} + +hb_font_t * +hbfindfont(XftFont *match) +{ + for (int i = 0; i < hbfontslen; i++) { + if (hbfontcache[i].match == match) + return hbfontcache[i].font; + } + + /* Font not found in cache, caching it now. */ + hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfontslen + 1)); + FT_Face face = XftLockFace(match); + hb_font_t *font = hb_ft_font_create(face, NULL); + if (font == NULL) + die("Failed to load Harfbuzz font."); + + hbfontcache[hbfontslen].match = match; + hbfontcache[hbfontslen].font = font; + hbfontslen += 1; + + return font; +} + +void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *glyphs, int start, int length) { + Rune rune; + ushort mode = USHRT_MAX; + unsigned int glyph_count; + int i, end = start + length; + + hb_font_t *font = hbfindfont(xfont); + if (font == NULL) + return; + + hb_buffer_t *buffer = hb_buffer_create(); + hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); + + /* Fill buffer with codepoints. */ + for (i = start; i < end; i++) { + rune = glyphs[i].u; + mode = glyphs[i].mode; + if (mode & ATTR_WDUMMY) + rune = 0x0020; + hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1); + } + + /* Shape the segment. */ + hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_feature_t)); + + /* Get new glyph info. */ + hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyph_count); + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer, &glyph_count); + + /** Fill the output. */ + data->buffer = buffer; + data->glyphs = info; + data->positions = pos; + data->count = glyph_count; +} + +void hbcleanup(HbTransformData *data) { + hb_buffer_destroy(data->buffer); + memset(data, 0, sizeof(HbTransformData)); +} diff --git a/.config/suckless/st/hb.h b/.config/suckless/st/hb.h new file mode 100644 index 0000000..3b0ef44 --- /dev/null +++ b/.config/suckless/st/hb.h @@ -0,0 +1,14 @@ +#include +#include +#include + +typedef struct { + hb_buffer_t *buffer; + hb_glyph_info_t *glyphs; + hb_glyph_position_t *positions; + unsigned int count; +} HbTransformData; + +void hbunloadfonts(); +void hbtransform(HbTransformData *, XftFont *, const Glyph *, int, int); +void hbcleanup(HbTransformData *); diff --git a/.config/suckless/st/patch/alpha.c b/.config/suckless/st/patch/alpha.c new file mode 100644 index 0000000..eb71702 --- /dev/null +++ b/.config/suckless/st/patch/alpha.c @@ -0,0 +1,19 @@ +float +clamp(float value, float lower, float upper) { + if (value < lower) + return lower; + if (value > upper) + return upper; + return value; +} + +void +changealpha(const Arg *arg) +{ + if ((alpha > 0 && arg->f < 0) || (alpha < 1 && arg->f > 0)) + alpha += arg->f; + alpha = clamp(alpha, 0.0, 1.0); + xloadcols(); + redraw(); +} + diff --git a/.config/suckless/st/patch/alpha.h b/.config/suckless/st/patch/alpha.h new file mode 100644 index 0000000..8381349 --- /dev/null +++ b/.config/suckless/st/patch/alpha.h @@ -0,0 +1,2 @@ +static float clamp(float value, float lower, float upper); +static void changealpha(const Arg *); diff --git a/.config/suckless/st/patch/boxdraw.c b/.config/suckless/st/patch/boxdraw.c new file mode 100644 index 0000000..ef1e110 --- /dev/null +++ b/.config/suckless/st/patch/boxdraw.c @@ -0,0 +1,192 @@ +/* + * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih + * MIT/X Consortium License + */ + +#include + +/* Rounded non-negative integers division of n / d */ +#define DIV(n, d) (((n) + (d) / 2) / (d)) + +static Display *xdpy; +static Colormap xcmap; +static XftDraw *xd; +static Visual *xvis; + +static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); +static void drawboxlines(int, int, int, int, XftColor *, ushort); + +/* public API */ + +void +boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) +{ + xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; +} + +int +isboxdraw(Rune u) +{ + Rune block = u & ~0xff; + return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) || + (boxdraw_braille && block == 0x2800); +} + +/* the "index" is actually the entire shape data encoded as ushort */ +ushort +boxdrawindex(const Glyph *g) +{ + if (boxdraw_braille && (g->u & ~0xff) == 0x2800) + return BRL | (uint8_t)g->u; + if (boxdraw_bold && (g->mode & ATTR_BOLD)) + return BDB | boxdata[(uint8_t)g->u]; + return boxdata[(uint8_t)g->u]; +} + +void +drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, + const XftGlyphFontSpec *specs, int len) +{ + for ( ; len-- > 0; x += cw, specs++) + drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); +} + +/* implementation */ + +void +drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) +{ + ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ + if (bd & (BDL | BDA)) { + /* lines (light/double/heavy/arcs) */ + drawboxlines(x, y, w, h, fg, bd); + + } else if (cat == BBD) { + /* lower (8-X)/8 block */ + int d = DIV((uint8_t)bd * h, 8); + XftDrawRect(xd, fg, x, y + d, w, h - d); + + } else if (cat == BBU) { + /* upper X/8 block */ + XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); + + } else if (cat == BBL) { + /* left X/8 block */ + XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); + + } else if (cat == BBR) { + /* right (8-X)/8 block */ + int d = DIV((uint8_t)bd * w, 8); + XftDrawRect(xd, fg, x + d, y, w - d, h); + + } else if (cat == BBQ) { + /* Quadrants */ + int w2 = DIV(w, 2), h2 = DIV(h, 2); + if (bd & TL) + XftDrawRect(xd, fg, x, y, w2, h2); + if (bd & TR) + XftDrawRect(xd, fg, x + w2, y, w - w2, h2); + if (bd & BL) + XftDrawRect(xd, fg, x, y + h2, w2, h - h2); + if (bd & BR) + XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); + + } else if (bd & BBS) { + /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ + int d = (uint8_t)bd; + XftColor xfc; + XRenderColor xrc = { .alpha = 0xffff }; + + xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); + xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); + xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); + + XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); + XftDrawRect(xd, &xfc, x, y, w, h); + XftColorFree(xdpy, xvis, xcmap, &xfc); + + } else if (cat == BRL) { + /* braille, each data bit corresponds to one dot at 2x4 grid */ + int w1 = DIV(w, 2); + int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); + + if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); + if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); + if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); + if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); + if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); + if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); + if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); + if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); + + } +} + +void +drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) +{ + /* s: stem thickness. width/8 roughly matches underscore thickness. */ + /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */ + /* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */ + int mwh = MIN(w, h); + int base_s = MAX(1, DIV(mwh, 8)); + int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */ + int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s; + int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2); + /* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */ + /* The base length (per direction till edge) includes this square. */ + + int light = bd & (LL | LU | LR | LD); + int double_ = bd & (DL | DU | DR | DD); + + if (light) { + /* d: additional (negative) length to not-draw the center */ + /* texel - at arcs and avoid drawing inside (some) doubles */ + int arc = bd & BDA; + int multi_light = light & (light - 1); + int multi_double = double_ & (double_ - 1); + /* light crosses double only at DH+LV, DV+LH (ref. shapes) */ + int d = arc || (multi_double && !multi_light) ? -s : 0; + + if (bd & LL) + XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s); + if (bd & LU) + XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d); + if (bd & LR) + XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s); + if (bd & LD) + XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d); + } + + /* double lines - also align with light to form heavy when combined */ + if (double_) { + /* + * going clockwise, for each double-ray: p is additional length + * to the single-ray nearer to the previous direction, and n to + * the next. p and n adjust from the base length to lengths + * which consider other doubles - shorter to avoid intersections + * (p, n), or longer to draw the far-corner texel (n). + */ + int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD; + if (dl) { + int p = dd ? -s : 0, n = du ? -s : dd ? s : 0; + XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s); + XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s); + } + if (du) { + int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0; + XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p); + XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n); + } + if (dr) { + int p = du ? -s : 0, n = dd ? -s : du ? s : 0; + XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s); + XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s); + } + if (dd) { + int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0; + XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p); + XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n); + } + } +} diff --git a/.config/suckless/st/patch/boxdraw.h b/.config/suckless/st/patch/boxdraw.h new file mode 100644 index 0000000..7890500 --- /dev/null +++ b/.config/suckless/st/patch/boxdraw.h @@ -0,0 +1,214 @@ +/* + * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih + * MIT/X Consortium License + */ + +/* + * U+25XX codepoints data + * + * References: + * http://www.unicode.org/charts/PDF/U2500.pdf + * http://www.unicode.org/charts/PDF/U2580.pdf + * + * Test page: + * https://github.com/GNOME/vte/blob/master/doc/boxes.txt + */ + +/* Each shape is encoded as 16-bits. Higher bits are category, lower are data */ +/* Categories (mutually exclusive except BDB): */ +/* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */ +#define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */ +#define BDA (1<<9) /* Box Draw Arc (light) */ + +#define BBD (1<<10) /* Box Block Down (lower) X/8 */ +#define BBL (2<<10) /* Box Block Left X/8 */ +#define BBU (3<<10) /* Box Block Upper X/8 */ +#define BBR (4<<10) /* Box Block Right X/8 */ +#define BBQ (5<<10) /* Box Block Quadrants */ +#define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */ + +#define BBS (1<<14) /* Box Block Shades */ +#define BDB (1<<15) /* Box Draw is Bold */ + +/* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */ +/* Heavy is light+double (literally drawing light+double align to form heavy) */ +#define LL (1<<0) +#define LU (1<<1) +#define LR (1<<2) +#define LD (1<<3) +#define LH (LL+LR) +#define LV (LU+LD) + +#define DL (1<<4) +#define DU (1<<5) +#define DR (1<<6) +#define DD (1<<7) +#define DH (DL+DR) +#define DV (DU+DD) + +#define HL (LL+DL) +#define HU (LU+DU) +#define HR (LR+DR) +#define HD (LD+DD) +#define HH (HL+HR) +#define HV (HU+HD) + +/* (BBQ) Quadrants Top/Bottom x Left/Right */ +#define TL (1<<0) +#define TR (1<<1) +#define BL (1<<2) +#define BR (1<<3) + +/* Data for U+2500 - U+259F except dashes/diagonals */ +static const unsigned short boxdata[256] = { + /* light lines */ + [0x00] = BDL + LH, /* light horizontal */ + [0x02] = BDL + LV, /* light vertical */ + [0x0c] = BDL + LD + LR, /* light down and right */ + [0x10] = BDL + LD + LL, /* light down and left */ + [0x14] = BDL + LU + LR, /* light up and right */ + [0x18] = BDL + LU + LL, /* light up and left */ + [0x1c] = BDL + LV + LR, /* light vertical and right */ + [0x24] = BDL + LV + LL, /* light vertical and left */ + [0x2c] = BDL + LH + LD, /* light horizontal and down */ + [0x34] = BDL + LH + LU, /* light horizontal and up */ + [0x3c] = BDL + LV + LH, /* light vertical and horizontal */ + [0x74] = BDL + LL, /* light left */ + [0x75] = BDL + LU, /* light up */ + [0x76] = BDL + LR, /* light right */ + [0x77] = BDL + LD, /* light down */ + + /* heavy [+light] lines */ + [0x01] = BDL + HH, + [0x03] = BDL + HV, + [0x0d] = BDL + HR + LD, + [0x0e] = BDL + HD + LR, + [0x0f] = BDL + HD + HR, + [0x11] = BDL + HL + LD, + [0x12] = BDL + HD + LL, + [0x13] = BDL + HD + HL, + [0x15] = BDL + HR + LU, + [0x16] = BDL + HU + LR, + [0x17] = BDL + HU + HR, + [0x19] = BDL + HL + LU, + [0x1a] = BDL + HU + LL, + [0x1b] = BDL + HU + HL, + [0x1d] = BDL + HR + LV, + [0x1e] = BDL + HU + LD + LR, + [0x1f] = BDL + HD + LR + LU, + [0x20] = BDL + HV + LR, + [0x21] = BDL + HU + HR + LD, + [0x22] = BDL + HD + HR + LU, + [0x23] = BDL + HV + HR, + [0x25] = BDL + HL + LV, + [0x26] = BDL + HU + LD + LL, + [0x27] = BDL + HD + LU + LL, + [0x28] = BDL + HV + LL, + [0x29] = BDL + HU + HL + LD, + [0x2a] = BDL + HD + HL + LU, + [0x2b] = BDL + HV + HL, + [0x2d] = BDL + HL + LD + LR, + [0x2e] = BDL + HR + LL + LD, + [0x2f] = BDL + HH + LD, + [0x30] = BDL + HD + LH, + [0x31] = BDL + HD + HL + LR, + [0x32] = BDL + HR + HD + LL, + [0x33] = BDL + HH + HD, + [0x35] = BDL + HL + LU + LR, + [0x36] = BDL + HR + LU + LL, + [0x37] = BDL + HH + LU, + [0x38] = BDL + HU + LH, + [0x39] = BDL + HU + HL + LR, + [0x3a] = BDL + HU + HR + LL, + [0x3b] = BDL + HH + HU, + [0x3d] = BDL + HL + LV + LR, + [0x3e] = BDL + HR + LV + LL, + [0x3f] = BDL + HH + LV, + [0x40] = BDL + HU + LH + LD, + [0x41] = BDL + HD + LH + LU, + [0x42] = BDL + HV + LH, + [0x43] = BDL + HU + HL + LD + LR, + [0x44] = BDL + HU + HR + LD + LL, + [0x45] = BDL + HD + HL + LU + LR, + [0x46] = BDL + HD + HR + LU + LL, + [0x47] = BDL + HH + HU + LD, + [0x48] = BDL + HH + HD + LU, + [0x49] = BDL + HV + HL + LR, + [0x4a] = BDL + HV + HR + LL, + [0x4b] = BDL + HV + HH, + [0x78] = BDL + HL, + [0x79] = BDL + HU, + [0x7a] = BDL + HR, + [0x7b] = BDL + HD, + [0x7c] = BDL + HR + LL, + [0x7d] = BDL + HD + LU, + [0x7e] = BDL + HL + LR, + [0x7f] = BDL + HU + LD, + + /* double [+light] lines */ + [0x50] = BDL + DH, + [0x51] = BDL + DV, + [0x52] = BDL + DR + LD, + [0x53] = BDL + DD + LR, + [0x54] = BDL + DR + DD, + [0x55] = BDL + DL + LD, + [0x56] = BDL + DD + LL, + [0x57] = BDL + DL + DD, + [0x58] = BDL + DR + LU, + [0x59] = BDL + DU + LR, + [0x5a] = BDL + DU + DR, + [0x5b] = BDL + DL + LU, + [0x5c] = BDL + DU + LL, + [0x5d] = BDL + DL + DU, + [0x5e] = BDL + DR + LV, + [0x5f] = BDL + DV + LR, + [0x60] = BDL + DV + DR, + [0x61] = BDL + DL + LV, + [0x62] = BDL + DV + LL, + [0x63] = BDL + DV + DL, + [0x64] = BDL + DH + LD, + [0x65] = BDL + DD + LH, + [0x66] = BDL + DD + DH, + [0x67] = BDL + DH + LU, + [0x68] = BDL + DU + LH, + [0x69] = BDL + DH + DU, + [0x6a] = BDL + DH + LV, + [0x6b] = BDL + DV + LH, + [0x6c] = BDL + DH + DV, + + /* (light) arcs */ + [0x6d] = BDA + LD + LR, + [0x6e] = BDA + LD + LL, + [0x6f] = BDA + LU + LL, + [0x70] = BDA + LU + LR, + + /* Lower (Down) X/8 block (data is 8 - X) */ + [0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4, + [0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0, + + /* Left X/8 block (data is X) */ + [0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4, + [0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1, + + /* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */ + [0x80] = BBU + 4, [0x94] = BBU + 1, + [0x90] = BBR + 4, [0x95] = BBR + 7, + + /* Quadrants */ + [0x96] = BBQ + BL, + [0x97] = BBQ + BR, + [0x98] = BBQ + TL, + [0x99] = BBQ + TL + BL + BR, + [0x9a] = BBQ + TL + BR, + [0x9b] = BBQ + TL + TR + BL, + [0x9c] = BBQ + TL + TR + BR, + [0x9d] = BBQ + TR, + [0x9e] = BBQ + BL + TR, + [0x9f] = BBQ + BL + TR + BR, + + /* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */ + [0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3, + + /* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */ + /* U+2571 - U+2573: unsupported (diagonals) */ +}; diff --git a/.config/suckless/st/patch/copyurl.c b/.config/suckless/st/patch/copyurl.c new file mode 100644 index 0000000..a9b29e0 --- /dev/null +++ b/.config/suckless/st/patch/copyurl.c @@ -0,0 +1,118 @@ +void +tsetcolor( int row, int start, int end, uint32_t fg, uint32_t bg ) +{ + int i = start; + for( ; i < end; ++i ) + { + term.line[row][i].fg = fg; + term.line[row][i].bg = bg; + } +} + +char * +findlastany(char *str, const char** find, size_t len) +{ + char* found = NULL; + int i = 0; + for(found = str + strlen(str) - 1; found >= str; --found) { + for(i = 0; i < len; i++) { + if(strncmp(found, find[i], strlen(find[i])) == 0) { + return found; + } + } + } + + return NULL; +} + +/* +** Select and copy the previous url on screen (do nothing if there's no url). +** +** FIXME: doesn't handle urls that span multiple lines; will need to add support +** for multiline "getsel()" first +*/ +void +copyurl(const Arg *arg) { + /* () and [] can appear in urls, but excluding them here will reduce false + * positives when figuring out where a given url ends. + */ + static char URLCHARS[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789-._~:/?#@!$&'*+,;=%"; + + static const char* URLSTRINGS[] = {"http://", "https://"}; + + /* remove highlighting from previous selection if any */ + if(sel.ob.x >= 0 && sel.oe.x >= 0) + tsetcolor(sel.nb.y, sel.ob.x, sel.oe.x + 1, defaultfg, defaultbg); + + int i = 0, + row = 0, /* row of current URL */ + col = 0, /* column of current URL start */ + startrow = 0, /* row of last occurrence */ + colend = 0, /* column of last occurrence */ + passes = 0; /* how many rows have been scanned */ + + char *linestr = calloc(term.col+1, sizeof(Rune)); + char *c = NULL, + *match = NULL; + + row = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.y : term.bot; + LIMIT(row, term.top, term.bot); + startrow = row; + + colend = (sel.ob.x >= 0 && sel.nb.y > 0) ? sel.nb.x : term.col; + LIMIT(colend, 0, term.col); + + /* + ** Scan from (term.bot,term.col) to (0,0) and find + ** next occurrance of a URL + */ + while (passes !=term.bot + 2) { + /* Read in each column of every row until + ** we hit previous occurrence of URL + */ + for (col = 0, i = 0; col < colend; ++col,++i) { + linestr[i] = term.line[row][col].u; + } + linestr[term.col] = '\0'; + + if ((match = findlastany(linestr, URLSTRINGS, + sizeof(URLSTRINGS)/sizeof(URLSTRINGS[0])))) + break; + + if (--row < term.top) + row = term.bot; + + colend = term.col; + passes++; + }; + + if (match) { + /* must happen before trim */ + selclear(); + sel.ob.x = strlen(linestr) - strlen(match); + + /* trim the rest of the line from the url match */ + for (c = match; *c != '\0'; ++c) + if (!strchr(URLCHARS, *c)) { + *c = '\0'; + break; + } + + /* highlight selection by inverting terminal colors */ + tsetcolor(row, sel.ob.x, sel.ob.x + strlen( match ), defaultbg, defaultfg); + + /* select and copy */ + sel.mode = 1; + sel.type = SEL_REGULAR; + sel.oe.x = sel.ob.x + strlen(match)-1; + sel.ob.y = sel.oe.y = row; + selnormalize(); + tsetdirt(sel.nb.y, sel.ne.y); + xsetsel(getsel()); + xclipcopy(); + } + + free(linestr); +} diff --git a/.config/suckless/st/patch/copyurl.h b/.config/suckless/st/patch/copyurl.h new file mode 100644 index 0000000..b87f823 --- /dev/null +++ b/.config/suckless/st/patch/copyurl.h @@ -0,0 +1,3 @@ +void copyurl(const Arg *); +static void tsetcolor(int, int, int, uint32_t, uint32_t); +static char * findlastany(char *, const char**, size_t); diff --git a/.config/suckless/st/patch/font2.c b/.config/suckless/st/patch/font2.c new file mode 100644 index 0000000..d028ea3 --- /dev/null +++ b/.config/suckless/st/patch/font2.c @@ -0,0 +1,96 @@ +int +xloadsparefont(FcPattern *pattern, int flags) +{ + FcPattern *match; + FcResult result; + + match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); + if (!match) { + return 1; + } + + if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) { + FcPatternDestroy(match); + return 1; + } + + frc[frclen].flags = flags; + /* Believe U+0000 glyph will present in each default font */ + frc[frclen].unicodep = 0; + frclen++; + + return 0; +} + +void +xloadsparefonts(void) +{ + FcPattern *pattern; + double fontval; + int fc; + char **fp; + + if (frclen != 0) + die("can't embed spare fonts. cache isn't empty"); + + /* Calculate count of spare fonts */ + fc = sizeof(font2) / sizeof(*font2); + if (fc == 0) + return; + + /* Allocate memory for cache entries. */ + if (frccap < 4 * fc) { + frccap += 4 * fc - frccap; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); + } + + for (fp = font2; fp - font2 < fc; ++fp) { + + if (**fp == '-') + pattern = XftXlfdParse(*fp, False, False); + else + pattern = FcNameParse((FcChar8 *)*fp); + + if (!pattern) + die("can't open spare font %s\n", *fp); + + if (defaultfontsize > 0 && defaultfontsize != usedfontsize) { + if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == + FcResultMatch) { + fontval *= usedfontsize / defaultfontsize; + FcPatternDel(pattern, FC_PIXEL_SIZE); + FcPatternDel(pattern, FC_SIZE); + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); + } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == + FcResultMatch) { + fontval *= usedfontsize / defaultfontsize; + FcPatternDel(pattern, FC_PIXEL_SIZE); + FcPatternDel(pattern, FC_SIZE); + FcPatternAddDouble(pattern, FC_SIZE, fontval); + } + } + + FcPatternAddBool(pattern, FC_SCALABLE, 1); + + + if (xloadsparefont(pattern, FRC_NORMAL)) + die("can't open spare font %s\n", *fp); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); + if (xloadsparefont(pattern, FRC_ITALIC)) + die("can't open spare font %s\n", *fp); + + FcPatternDel(pattern, FC_WEIGHT); + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + if (xloadsparefont(pattern, FRC_ITALICBOLD)) + die("can't open spare font %s\n", *fp); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); + if (xloadsparefont(pattern, FRC_BOLD)) + die("can't open spare font %s\n", *fp); + + FcPatternDestroy(pattern); + } +} diff --git a/.config/suckless/st/patch/font2.h b/.config/suckless/st/patch/font2.h new file mode 100644 index 0000000..69df588 --- /dev/null +++ b/.config/suckless/st/patch/font2.h @@ -0,0 +1,2 @@ +static int xloadsparefont(FcPattern *, int); +static void xloadsparefonts(void); diff --git a/.config/suckless/st/patch/invert.c b/.config/suckless/st/patch/invert.c new file mode 100644 index 0000000..688b45c --- /dev/null +++ b/.config/suckless/st/patch/invert.c @@ -0,0 +1,21 @@ +static int invertcolors = 0; + +void +invert(const Arg *dummy) +{ + invertcolors = !invertcolors; + redraw(); +} + +Color +invertedcolor(Color *clr) +{ + XRenderColor rc; + Color inverted; + rc.red = ~clr->color.red; + rc.green = ~clr->color.green; + rc.blue = ~clr->color.blue; + rc.alpha = clr->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &rc, &inverted); + return inverted; +} diff --git a/.config/suckless/st/patch/invert.h b/.config/suckless/st/patch/invert.h new file mode 100644 index 0000000..60e311d --- /dev/null +++ b/.config/suckless/st/patch/invert.h @@ -0,0 +1 @@ +static void invert(const Arg *); diff --git a/.config/suckless/st/patch/iso14755.c b/.config/suckless/st/patch/iso14755.c new file mode 100644 index 0000000..dbbf2c3 --- /dev/null +++ b/.config/suckless/st/patch/iso14755.c @@ -0,0 +1,21 @@ +void +iso14755(const Arg *arg) +{ + FILE *p; + char *us, *e, codepoint[9], uc[UTF_SIZ]; + unsigned long utf32; + + if (!(p = popen(ISO14755CMD, "r"))) + return; + + us = fgets(codepoint, sizeof(codepoint), p); + pclose(p); + + if (!us || *us == '\0' || *us == '-' || strlen(us) > 7) + return; + if ((utf32 = strtoul(us, &e, 16)) == ULONG_MAX || + (*e != '\n' && *e != '\0')) + return; + + ttywrite(uc, utf8encode(utf32, uc), 1); +} diff --git a/.config/suckless/st/patch/iso14755.h b/.config/suckless/st/patch/iso14755.h new file mode 100644 index 0000000..8647a92 --- /dev/null +++ b/.config/suckless/st/patch/iso14755.h @@ -0,0 +1,6 @@ +#define NUMMAXLEN(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) + +/* constants */ +#define ISO14755CMD "dmenu -w \"$WINDOWID\" -p codepoint: +#endif + +int +subprocwd(char *path) +{ +#if defined(__linux) + if (snprintf(path, PATH_MAX, "/proc/%d/cwd", pid) < 0) + return -1; + return 0; +#elif defined(__OpenBSD__) + size_t sz = PATH_MAX; + int name[3] = {CTL_KERN, KERN_PROC_CWD, pid}; + if (sysctl(name, 3, path, &sz, 0, 0) == -1) + return -1; + return 0; +#endif +} diff --git a/.config/suckless/st/patch/rightclicktoplumb_st.h b/.config/suckless/st/patch/rightclicktoplumb_st.h new file mode 100644 index 0000000..7f8ee04 --- /dev/null +++ b/.config/suckless/st/patch/rightclicktoplumb_st.h @@ -0,0 +1 @@ +int subprocwd(char *); diff --git a/.config/suckless/st/patch/rightclicktoplumb_x.c b/.config/suckless/st/patch/rightclicktoplumb_x.c new file mode 100644 index 0000000..11906f3 --- /dev/null +++ b/.config/suckless/st/patch/rightclicktoplumb_x.c @@ -0,0 +1,24 @@ +#include + +void +plumb(char *sel) { + if (sel == NULL) + return; + char cwd[PATH_MAX]; + pid_t child; + if (subprocwd(cwd) != 0) + return; + + switch(child = fork()) { + case -1: + return; + case 0: + if (chdir(cwd) != 0) + exit(1); + if (execvp(plumb_cmd, (char *const []){plumb_cmd, sel, 0}) == -1) + exit(1); + exit(0); + default: + waitpid(child, NULL, 0); + } +} diff --git a/.config/suckless/st/patch/rightclicktoplumb_x.h b/.config/suckless/st/patch/rightclicktoplumb_x.h new file mode 100644 index 0000000..f77204e --- /dev/null +++ b/.config/suckless/st/patch/rightclicktoplumb_x.h @@ -0,0 +1 @@ +void plumb(char *); diff --git a/.config/suckless/st/patch/scrollback.c b/.config/suckless/st/patch/scrollback.c new file mode 100644 index 0000000..63333eb --- /dev/null +++ b/.config/suckless/st/patch/scrollback.c @@ -0,0 +1,41 @@ +void +kscrolldown(const Arg* a) +{ + int n = a->i; + + if (n < 0) + n = term.row + n; + + if (n > term.scr) + n = term.scr; + + if (term.scr > 0) { + term.scr -= n; + selscroll(0, -n); + tfulldirt(); + } + + +} + +void +kscrollup(const Arg* a) +{ + int n = a->i; + if (n < 0) + n = term.row + n; + + if (term.scr + n > term.histn) + n = term.histn - term.scr; + + if (!n) + return; + + if (term.scr <= HISTSIZE-n) { + term.scr += n; + selscroll(0, n); + tfulldirt(); + } + + +} diff --git a/.config/suckless/st/patch/scrollback.h b/.config/suckless/st/patch/scrollback.h new file mode 100644 index 0000000..a602db2 --- /dev/null +++ b/.config/suckless/st/patch/scrollback.h @@ -0,0 +1,15 @@ +#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ + term.scr + HISTSIZE + 1) % HISTSIZE] : \ + term.line[(y) - term.scr]) + +void kscrolldown(const Arg *); +void kscrollup(const Arg *); + +typedef struct { + uint b; + uint mask; + void (*func)(const Arg *); + const Arg arg; +} MouseKey; + +extern MouseKey mkeys[]; diff --git a/.config/suckless/st/patch/st_include.c b/.config/suckless/st/patch/st_include.c new file mode 100644 index 0000000..20ef1c4 --- /dev/null +++ b/.config/suckless/st/patch/st_include.c @@ -0,0 +1,6 @@ +/* Patches */ +#include "copyurl.c" +#include "iso14755.c" +#include "rightclicktoplumb_st.c" +#include "newterm.c" +#include "scrollback.c" diff --git a/.config/suckless/st/patch/st_include.h b/.config/suckless/st/patch/st_include.h new file mode 100644 index 0000000..2186dce --- /dev/null +++ b/.config/suckless/st/patch/st_include.h @@ -0,0 +1,9 @@ +/* Patches */ +#include "copyurl.h" +#include "iso14755.h" +#include "rightclicktoplumb_st.h" +#include "newterm.h" +#include "scrollback.h" +// #if VIM_BROWSE_PATCH +// #include "normalMode.h" +// #endif diff --git a/.config/suckless/st/patch/utils.h b/.config/suckless/st/patch/utils.h new file mode 100644 index 0000000..6cfca3e --- /dev/null +++ b/.config/suckless/st/patch/utils.h @@ -0,0 +1,23 @@ +/// Dynamic memory-chunk, with (1) datatype size, (2/3) initialized / allocated chunk, (4) content +typedef struct { uint8_t const elSize; uint32_t init, alloc; char* content; } DynamicArray; +#define UTF8_ARRAY {4, 0, 0, NULL} + +static inline int p_alloc(DynamicArray *s, uint32_t amount) { + uint32_t const diff=s->init+s->elSize*amount-s->alloc, nas=s->alloc+max(diff,15)*s->elSize; + if (s->alloc < s->init + s->elSize * amount) { + char* tmp = realloc(s->content, nas); + if (!tmp) return 0; + s->alloc = nas, s->content = tmp; + } + return 1; +} +static inline char *view(DynamicArray * s, uint32_t i) { return s->content + i*s->elSize; } +static inline char *end(DynamicArray *s, uint32_t i) { return s->content +s->init-(i+1)*s->elSize; } +static inline uint32_t getU32(DynamicArray* s, uint32_t i, int b) { return *((uint32_t*) (b ?view(s,i) :end(s,i))); } +static char *expand(DynamicArray *s) { if (!p_alloc(s, 1)) return NULL; s->init += s->elSize; return end(s, 0); } +static inline void pop(DynamicArray* s) { s->init -= s->elSize; } +static inline void empty(DynamicArray* s) { s->init = 0; } +static inline int size(DynamicArray const * s) { return s->init / s->elSize; } +static inline void assign(DynamicArray* s, DynamicArray const *o) { + if (p_alloc(s, size(o))) memcpy(s->content, o->content, (s->init=o->init)); +} diff --git a/.config/suckless/st/patch/x_include.c b/.config/suckless/st/patch/x_include.c new file mode 100644 index 0000000..49ddc07 --- /dev/null +++ b/.config/suckless/st/patch/x_include.c @@ -0,0 +1,7 @@ +/* Patches */ +#include "alpha.c" +#include "boxdraw.c" +#include "font2.c" +#include "invert.c" +#include "rightclicktoplumb_x.c" +#include "xresources.c" diff --git a/.config/suckless/st/patch/x_include.h b/.config/suckless/st/patch/x_include.h new file mode 100644 index 0000000..da7fa49 --- /dev/null +++ b/.config/suckless/st/patch/x_include.h @@ -0,0 +1,7 @@ +/* Patches */ +#include "alpha.h" +#include "boxdraw.h" +#include "font2.h" +#include "invert.h" +#include "rightclicktoplumb_x.h" +#include "xresources.h" diff --git a/.config/suckless/st/patch/xresources.c b/.config/suckless/st/patch/xresources.c new file mode 100644 index 0000000..8926d93 --- /dev/null +++ b/.config/suckless/st/patch/xresources.c @@ -0,0 +1,78 @@ +int +resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) +{ + char **sdst = dst; + int *idst = dst; + float *fdst = dst; + + char fullname[256]; + char fullclass[256]; + char *type; + XrmValue ret; + + snprintf(fullname, sizeof(fullname), "%s.%s", + opt_name ? opt_name : "st", name); + snprintf(fullclass, sizeof(fullclass), "%s.%s", + opt_class ? opt_class : "St", name); + fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0'; + + XrmGetResource(db, fullname, fullclass, &type, &ret); + if (ret.addr == NULL || strncmp("String", type, 64)) + return 1; + + switch (rtype) { + case STRING: + *sdst = ret.addr; + break; + case INTEGER: + *idst = strtoul(ret.addr, NULL, 10); + break; + case FLOAT: + *fdst = strtof(ret.addr, NULL); + break; + } + return 0; +} + +void +config_init(Display *dpy) +{ + char *resm; + XrmDatabase db; + ResourcePref *p; + + XrmInitialize(); + resm = XResourceManagerString(dpy); + if (!resm) + return; + + db = XrmGetStringDatabase(resm); + for (p = resources; p < resources + LEN(resources); p++) + resource_load(db, p->name, p->type, p->dst); +} + +void +reload_config(int sig) +{ + /* Recreate a Display object to have up to date Xresources entries */ + Display *dpy; + if (!(dpy = XOpenDisplay(NULL))) + die("Can't open display\n"); + + config_init(dpy); + xloadcols(); + + /* nearly like zoomabs() */ + xunloadfonts(); + xloadfonts(font, 0); /* font <- config_init() */ + xloadsparefonts(); + cresize(0, 0); + redraw(); + xhints(); + + XCloseDisplay(dpy); + + /* from https://st.suckless.org/patches/xresources-with-reload-signal */ + /* triggers re-render if we're visible */ + ttywrite("\033[O", 3, 1); +} diff --git a/.config/suckless/st/patch/xresources.h b/.config/suckless/st/patch/xresources.h new file mode 100644 index 0000000..c184852 --- /dev/null +++ b/.config/suckless/st/patch/xresources.h @@ -0,0 +1,17 @@ +#include + +/* Xresources preferences */ +enum resource_type { + STRING = 0, + INTEGER = 1, + FLOAT = 2 +}; + +typedef struct { + char *name; + enum resource_type type; + void *dst; +} ResourcePref; + +int resource_load(XrmDatabase, char *, enum resource_type, void *); +void config_init(Display *dpy); diff --git a/.config/suckless/st/st.1 b/.config/suckless/st/st.1 new file mode 100644 index 0000000..39120b4 --- /dev/null +++ b/.config/suckless/st/st.1 @@ -0,0 +1,177 @@ +.TH ST 1 st\-VERSION +.SH NAME +st \- simple terminal +.SH SYNOPSIS +.B st +.RB [ \-aiv ] +.RB [ \-c +.IR class ] +.RB [ \-f +.IR font ] +.RB [ \-g +.IR geometry ] +.RB [ \-n +.IR name ] +.RB [ \-o +.IR iofile ] +.RB [ \-T +.IR title ] +.RB [ \-t +.IR title ] +.RB [ \-l +.IR line ] +.RB [ \-w +.IR windowid ] +.RB [[ \-e ] +.IR command +.RI [ arguments ...]] +.PP +.B st +.RB [ \-aiv ] +.RB [ \-c +.IR class ] +.RB [ \-f +.IR font ] +.RB [ \-g +.IR geometry ] +.RB [ \-n +.IR name ] +.RB [ \-o +.IR iofile ] +.RB [ \-T +.IR title ] +.RB [ \-t +.IR title ] +.RB [ \-w +.IR windowid ] +.RB \-l +.IR line +.RI [ stty_args ...] +.SH DESCRIPTION +.B st +is a simple terminal emulator. +.SH OPTIONS +.TP +.B \-a +disable alternate screens in terminal +.TP +.BI \-c " class" +defines the window class (default $TERM). +.TP +.BI \-f " font" +defines the +.I font +to use when st is run. +.TP +.BI \-g " geometry" +defines the X11 geometry string. +The form is [=][{xX}][{+-}{+-}]. See +.BR XParseGeometry (3) +for further details. +.TP +.B \-i +will fixate the position given with the -g option. +.TP +.BI \-n " name" +defines the window instance name (default $TERM). +.TP +.BI \-o " iofile" +writes all the I/O to +.I iofile. +This feature is useful when recording st sessions. A value of "-" means +standard output. +.TP +.BI \-T " title" +defines the window title (default 'st'). +.TP +.BI \-t " title" +defines the window title (default 'st'). +.TP +.BI \-w " windowid" +embeds st within the window identified by +.I windowid +.TP +.BI \-l " line" +use a tty +.I line +instead of a pseudo terminal. +.I line +should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port +0). +When this flag is given +remaining arguments are used as flags for +.BR stty(1). +By default st initializes the serial line to 8 bits, no parity, 1 stop bit +and a 38400 baud rate. The speed is set by appending it as last argument +(e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are +.BR stty(1) +flags. If you want to set odd parity on 115200 baud use for example 'st -l +/dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for +example 'st -l /dev/ttyS0 cs7 115200'. See +.BR stty(1) +for more arguments and cases. +.TP +.B \-v +prints version information to stderr, then exits. +.TP +.BI \-e " command " [ " arguments " "... ]" +st executes +.I command +instead of the shell. If this is used it +.B must be the last option +on the command line, as in xterm / rxvt. +This option is only intended for compatibility, +and all the remaining arguments are used as a command +even without it. +.SH SHORTCUTS +.TP +.B Break +Send a break in the serial line. +Break key is obtained in PC keyboards +pressing at the same time control and pause. +.TP +.B Ctrl-Print Screen +Toggle if st should print to the +.I iofile. +.TP +.B Shift-Print Screen +Print the full screen to the +.I iofile. +.TP +.B Print Screen +Print the selection to the +.I iofile. +.TP +.B Ctrl-Shift-Page Up +Increase font size. +.TP +.B Ctrl-Shift-Page Down +Decrease font size. +.TP +.B Ctrl-Shift-Home +Reset to default font size. +.TP +.B Ctrl-Shift-y +Paste from primary selection (middle mouse button). +.TP +.B Ctrl-Shift-c +Copy the selected text to the clipboard selection. +.TP +.B Ctrl-Shift-v +Paste from the clipboard selection. +.SH CUSTOMIZATION +.B st +can be customized by creating a custom config.h and (re)compiling the source +code. This keeps it fast, secure and simple. +.SH AUTHORS +See the LICENSE file for the authors. +.SH LICENSE +See the LICENSE file for the terms of redistribution. +.SH SEE ALSO +.BR tabbed (1), +.BR utmp (1), +.BR stty (1), +.BR scroll (1) +.SH BUGS +See the TODO file in the distribution. + diff --git a/.config/suckless/st/st.c b/.config/suckless/st/st.c new file mode 100644 index 0000000..104ef4d --- /dev/null +++ b/.config/suckless/st/st.c @@ -0,0 +1,2783 @@ +/* See LICENSE for license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "st.h" +#include "win.h" + + + + +#if defined(__linux) + #include +#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) + #include +#elif defined(__FreeBSD__) || defined(__DragonFly__) + #include +#endif + +/* Arbitrary sizes */ +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 +#define ESC_BUF_SIZ (128*UTF_SIZ) +#define ESC_ARG_SIZ 16 +#define STR_BUF_SIZ ESC_BUF_SIZ +#define STR_ARG_SIZ ESC_ARG_SIZ + +/* macros */ +#define IS_SET(flag) ((term.mode & (flag)) != 0) +#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) +#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) +#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) + +enum term_mode { + MODE_WRAP = 1 << 0, + MODE_INSERT = 1 << 1, + MODE_ALTSCREEN = 1 << 2, + MODE_CRLF = 1 << 3, + MODE_ECHO = 1 << 4, + MODE_PRINT = 1 << 5, + MODE_UTF8 = 1 << 6, +}; + +enum cursor_movement { + CURSOR_SAVE, + CURSOR_LOAD +}; + +enum cursor_state { + CURSOR_DEFAULT = 0, + CURSOR_WRAPNEXT = 1, + CURSOR_ORIGIN = 2 +}; + +enum charset { + CS_GRAPHIC0, + CS_GRAPHIC1, + CS_UK, + CS_USA, + CS_MULTI, + CS_GER, + CS_FIN +}; + +enum escape_state { + ESC_START = 1, + ESC_CSI = 2, + ESC_STR = 4, /* DCS, OSC, PM, APC */ + ESC_ALTCHARSET = 8, + ESC_STR_END = 16, /* a final string was encountered */ + ESC_TEST = 32, /* Enter in test mode */ + ESC_UTF8 = 64, +}; + +typedef struct { + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; + + int alt; +} Selection; + +/* CSI Escape sequence structs */ +/* ESC '[' [[ [] [;]] []] */ +typedef struct { + char buf[ESC_BUF_SIZ]; /* raw string */ + size_t len; /* raw string length */ + char priv; + int arg[ESC_ARG_SIZ]; + int narg; /* nb of args */ + char mode[2]; +} CSIEscape; + +/* STR Escape sequence structs */ +/* ESC type [[ [] [;]] ] ESC '\' */ +typedef struct { + char type; /* ESC type ... */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ + char *args[STR_ARG_SIZ]; + int narg; /* nb of args */ +} STREscape; + +static void execsh(char *, char **); +static void stty(char **); +static void sigchld(int); +static void ttywriteraw(const char *, size_t); + +static void csidump(void); +static void csihandle(void); +static void csiparse(void); +static void csireset(void); +static void osc4_color_response(int num); +static void osc_color_response(int index, int num); +static int eschandle(uchar); +static void strdump(void); +static void strhandle(void); +static void strparse(void); +static void strreset(void); + +static void tprinter(char *, size_t); +static void tdumpsel(void); +static void tdumpline(int); +static void tdump(void); +static void tclearregion(int, int, int, int); +static void tcursor(int); +static void tdeletechar(int); +static void tdeleteline(int); +static void tinsertblank(int); +static void tinsertblankline(int); +static int tlinelen(int); +static void tmoveto(int, int); +static void tmoveato(int, int); +static void tnewline(int); +static void tputtab(int); +static void tputc(Rune); +static void treset(void); +static void tscrollup(int, int, int); +static void tscrolldown(int, int); +static void tsetattr(const int *, int); +static void tsetchar(Rune, const Glyph *, int, int); +static void tsetdirt(int, int); +static void tsetscroll(int, int); +static void tswapscreen(void); +static void tsetmode(int, int, const int *, int); +static int twrite(const char *, int, int); +static void tcontrolcode(uchar ); +static void tdectest(char ); +static void tdefutf8(char); +static int32_t tdefcolor(const int *, int *, int); +static void tdeftran(char); +static void tstrsequence(uchar); +static void selnormalize(void); +static void selscroll(int, int); +static void selsnap(int *, int *, int); + +static size_t utf8decode(const char *, Rune *, size_t); +static Rune utf8decodebyte(char, size_t *); +static char utf8encodebyte(Rune, size_t); +static size_t utf8validate(Rune *, size_t); + +static char *base64dec(const char *); +static char base64dec_getc(const char **); + +static ssize_t xwrite(int, const char *, size_t); + +/* Globals */ +static Selection sel; +static CSIEscape csiescseq; +static STREscape strescseq; +static int iofd = 1; +static int cmdfd; +static pid_t pid; + +static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + + +#include "patch/st_include.h" + +ssize_t +xwrite(int fd, const char *s, size_t len) +{ + size_t aux = len; + ssize_t r; + + while (len > 0) { + r = write(fd, s, len); + if (r < 0) + return r; + len -= r; + s += r; + } + + return aux; +} + +void * +xmalloc(size_t len) +{ + void *p; + + if (!(p = malloc(len))) + die("malloc: %s\n", strerror(errno)); + + return p; +} + +void * +xrealloc(void *p, size_t len) +{ + if ((p = realloc(p, len)) == NULL) + die("realloc: %s\n", strerror(errno)); + + return p; +} + +char * +xstrdup(const char *s) +{ + char *p; + if ((p = strdup(s)) == NULL) + die("strdup: %s\n", strerror(errno)); + + return p; +} + +size_t +utf8decode(const char *c, Rune *u, size_t clen) +{ + size_t i, j, len, type; + Rune udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type != 0) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + return len; +} + +Rune +utf8decodebyte(char c, size_t *i) +{ + for (*i = 0; *i < LEN(utfmask); ++(*i)) + if (((uchar)c & utfmask[*i]) == utfbyte[*i]) + return (uchar)c & ~utfmask[*i]; + + return 0; +} + +size_t +utf8encode(Rune u, char *c) +{ + size_t len, i; + + len = utf8validate(&u, 0); + if (len > UTF_SIZ) + return 0; + + for (i = len - 1; i != 0; --i) { + c[i] = utf8encodebyte(u, 0); + u >>= 6; + } + c[0] = utf8encodebyte(u, len); + + return len; +} + +char +utf8encodebyte(Rune u, size_t i) +{ + return utfbyte[i] | (u & ~utfmask[i]); +} + +size_t +utf8validate(Rune *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + + return i; +} + +char +base64dec_getc(const char **src) +{ + while (**src && !isprint((unsigned char)**src)) + (*src)++; + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ +} + +char * +base64dec(const char *src) +{ + size_t in_len = strlen(src); + char *result, *dst; + static const char base64_digits[256] = { + [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, + 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + }; + + if (in_len % 4) + in_len += 4 - (in_len % 4); + result = dst = xmalloc(in_len / 4 * 3 + 1); + while (*src) { + int a = base64_digits[(unsigned char) base64dec_getc(&src)]; + int b = base64_digits[(unsigned char) base64dec_getc(&src)]; + int c = base64_digits[(unsigned char) base64dec_getc(&src)]; + int d = base64_digits[(unsigned char) base64dec_getc(&src)]; + + /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ + if (a == -1 || b == -1) + break; + + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (c == -1) + break; + *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); + if (d == -1) + break; + *dst++ = ((c & 0x03) << 6) | d; + } + *dst = '\0'; + return result; +} + +void +selinit(void) +{ + sel.mode = SEL_IDLE; + sel.snap = 0; + sel.ob.x = -1; +} + +int +tlinelen(int y) +{ + int i = term.col; + + if (TLINE(y)[i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && TLINE(y)[i - 1].u == ' ') + --i; + + return i; +} + + +void +selstart(int col, int row, int snap) +{ + selclear(); + sel.mode = SEL_EMPTY; + sel.type = SEL_REGULAR; + sel.alt = IS_SET(MODE_ALTSCREEN); + sel.snap = snap; + sel.oe.x = sel.ob.x = col; + sel.oe.y = sel.ob.y = row; + selnormalize(); + + if (sel.snap != 0) + sel.mode = SEL_READY; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +selextend(int col, int row, int type, int done) +{ + int oldey, oldex, oldsby, oldsey, oldtype; + + if (sel.mode == SEL_IDLE) + return; + if (done && sel.mode == SEL_EMPTY) { + selclear(); + return; + } + + oldey = sel.oe.y; + oldex = sel.oe.x; + oldsby = sel.nb.y; + oldsey = sel.ne.y; + oldtype = sel.type; + + sel.oe.x = col; + sel.oe.y = row; + selnormalize(); + sel.type = type; + + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + + sel.mode = done ? SEL_IDLE : SEL_READY; +} + +void +selnormalize(void) +{ + int i; + + if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { + sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; + sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; + } else { + sel.nb.x = MIN(sel.ob.x, sel.oe.x); + sel.ne.x = MAX(sel.ob.x, sel.oe.x); + } + sel.nb.y = MIN(sel.ob.y, sel.oe.y); + sel.ne.y = MAX(sel.ob.y, sel.oe.y); + + selsnap(&sel.nb.x, &sel.nb.y, -1); + selsnap(&sel.ne.x, &sel.ne.y, +1); + + /* expand selection over line breaks */ + if (sel.type == SEL_RECTANGULAR) + return; + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; +} + +int +selected(int x, int y) +{ + if (sel.mode == SEL_EMPTY || sel.ob.x == -1 || + sel.alt != IS_SET(MODE_ALTSCREEN)) + return 0; + + if (sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) + && BETWEEN(x, sel.nb.x, sel.ne.x); + + return BETWEEN(y, sel.nb.y, sel.ne.y) + && (y != sel.nb.y || x >= sel.nb.x) + && (y != sel.ne.y || x <= sel.ne.x); +} + +void +selsnap(int *x, int *y, int direction) +{ + int newx, newy, xt, yt; + int delim, prevdelim; + const Glyph *gp, *prevgp; + + switch (sel.snap) { + case SNAP_WORD: + /* + * Snap around if the word wraps around at the end or + * beginning of a line. + */ + prevgp = &TLINE(*y)[*x]; + prevdelim = ISDELIM(prevgp->u); + for (;;) { + newx = *x + direction; + newy = *y; + if (!BETWEEN(newx, 0, term.col - 1)) { + newy += direction; + newx = (newx + term.col) % term.col; + if (!BETWEEN(newy, 0, term.row - 1)) + break; + + if (direction > 0) + yt = *y, xt = *x; + else + yt = newy, xt = newx; + if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) + break; + } + + if (newx >= tlinelen(newy)) + break; + + gp = &TLINE(newy)[newx]; + delim = ISDELIM(gp->u); + if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim + || (delim && gp->u != prevgp->u))) + break; + + *x = newx; + *y = newy; + prevgp = gp; + prevdelim = delim; + } + break; + case SNAP_LINE: + /* + * Snap around if the the previous line or the current one + * has set ATTR_WRAP at its end. Then the whole next or + * previous line will be selected. + */ + *x = (direction < 0) ? 0 : term.col - 1; + if (direction < 0) { + for (; *y > 0; *y += direction) { + if (!(TLINE(*y-1)[term.col-1].mode & ATTR_WRAP)) + { + break; + } + } + } else if (direction > 0) { + for (; *y < term.row-1; *y += direction) { + if (!(TLINE(*y)[term.col-1].mode & ATTR_WRAP)) + { + break; + } + } + } + break; + } +} + +char * +getsel(void) +{ + char *str, *ptr; + int y, bufsize, lastx, linelen; + const Glyph *gp, *last; + + if (sel.ob.x == -1) + return NULL; + + bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; + ptr = str = xmalloc(bufsize); + + /* append every set & selected glyph to the selection */ + for (y = sel.nb.y; y <= sel.ne.y; y++) + { + if ((linelen = tlinelen(y)) == 0) { + *ptr++ = '\n'; + continue; + } + + if (sel.type == SEL_RECTANGULAR) { + gp = &TLINE(y)[sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; + } + last = &TLINE(y)[MIN(lastx, linelen-1)]; + while (last >= gp && last->u == ' ') + --last; + + for ( ; gp <= last; ++gp) { + if (gp->mode & ATTR_WDUMMY) + continue; + + ptr += utf8encode(gp->u, ptr); + } + + /* + * Copy and pasting of line endings is inconsistent + * in the inconsistent terminal and GUI world. + * The best solution seems like to produce '\n' when + * something is copied from st and convert '\n' to + * '\r', when something to be pasted is received by + * st. + * FIXME: Fix the computer world. + */ + if ( + (y < sel.ne.y || lastx >= linelen) + && (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) + *ptr++ = '\n'; + } + *ptr = 0; + return str; +} + +void +selclear(void) +{ + if (sel.ob.x == -1) + return; + sel.mode = SEL_IDLE; + sel.ob.x = -1; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +die(const char *errstr, ...) +{ + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); +} + +void +execsh(char *cmd, char **args) +{ + char *sh, *prog, *arg; + const struct passwd *pw; + + errno = 0; + if ((pw = getpwuid(getuid())) == NULL) { + if (errno) + die("getpwuid: %s\n", strerror(errno)); + else + die("who are you?\n"); + } + + if ((sh = getenv("SHELL")) == NULL) + sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; + + if (args) { + prog = args[0]; + arg = NULL; + } else if (scroll) { + prog = scroll; + arg = utmp ? utmp : sh; + } else if (utmp) { + prog = utmp; + arg = NULL; + } else { + prog = sh; + arg = NULL; + } + DEFAULT(args, ((char *[]) {prog, arg, NULL})); + + unsetenv("COLUMNS"); + unsetenv("LINES"); + unsetenv("TERMCAP"); + setenv("LOGNAME", pw->pw_name, 1); + setenv("USER", pw->pw_name, 1); + setenv("SHELL", sh, 1); + setenv("HOME", pw->pw_dir, 1); + setenv("TERM", termname, 1); + setenv("COLORTERM", "truecolor", 1); + + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGALRM, SIG_DFL); + + execvp(prog, args); + _exit(1); +} + +void +sigchld(int a) +{ + int stat; + pid_t p; + + if ((p = waitpid(pid, &stat, WNOHANG)) < 0) + die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); + + if (pid != p) + return; + + + if (WIFEXITED(stat) && WEXITSTATUS(stat)) + die("child exited with status %d\n", WEXITSTATUS(stat)); + else if (WIFSIGNALED(stat)) + die("child terminated due to signal %d\n", WTERMSIG(stat)); + _exit(0); +} + +void +stty(char **args) +{ + char cmd[_POSIX_ARG_MAX], **p, *q, *s; + size_t n, siz; + + if ((n = strlen(stty_args)) > sizeof(cmd)-1) + die("incorrect stty parameters\n"); + memcpy(cmd, stty_args, n); + q = cmd + n; + siz = sizeof(cmd) - n; + for (p = args; p && (s = *p); ++p) { + if ((n = strlen(s)) > siz-1) + die("stty parameter length too long\n"); + *q++ = ' '; + memcpy(q, s, n); + q += n; + siz -= n + 1; + } + *q = '\0'; + if (system(cmd) != 0) + perror("Couldn't call stty"); +} + +int +ttynew(const char *line, char *cmd, const char *out, char **args) +{ + int m, s; + + if (out) { + term.mode |= MODE_PRINT; + iofd = (!strcmp(out, "-")) ? + 1 : open(out, O_WRONLY | O_CREAT, 0666); + if (iofd < 0) { + fprintf(stderr, "Error opening %s:%s\n", + out, strerror(errno)); + } + } + + if (line) { + if ((cmdfd = open(line, O_RDWR)) < 0) + die("open line '%s' failed: %s\n", + line, strerror(errno)); + dup2(cmdfd, 0); + stty(args); + return cmdfd; + } + + /* seems to work fine on linux, openbsd and freebsd */ + if (openpty(&m, &s, NULL, NULL, NULL) < 0) + die("openpty failed: %s\n", strerror(errno)); + + switch (pid = fork()) { + case -1: + die("fork failed: %s\n", strerror(errno)); + break; + case 0: + close(iofd); + close(m); + setsid(); /* create a new process group */ + dup2(s, 0); + dup2(s, 1); + dup2(s, 2); + if (ioctl(s, TIOCSCTTY, NULL) < 0) + die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); + if (s > 2) + close(s); +#ifdef __OpenBSD__ + if (pledge("stdio getpw proc exec", NULL) == -1) + die("pledge\n"); +#endif + execsh(cmd, args); + break; + default: +#ifdef __OpenBSD__ + if (pledge("stdio rpath tty proc ps exec", NULL) == -1) + die("pledge\n"); +#endif + close(s); + cmdfd = m; + signal(SIGCHLD, sigchld); + break; + } + return cmdfd; +} + +size_t +ttyread(void) +{ + static char buf[BUFSIZ]; + static int buflen = 0; + int ret, written; + + /* append read bytes to unprocessed bytes */ + ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); + + switch (ret) { + case 0: + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); + default: + buflen += ret; + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any incomplete UTF-8 byte sequence for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); + return ret; + } +} + +void +ttywrite(const char *s, size_t n, int may_echo) +{ + const char *next; + Arg arg = (Arg) { .i = term.scr }; + + kscrolldown(&arg); + + if (may_echo && IS_SET(MODE_ECHO)) + twrite(s, n, 1); + + if (!IS_SET(MODE_CRLF)) { + ttywriteraw(s, n); + return; + } + + /* This is similar to how the kernel handles ONLCR for ttys */ + while (n > 0) { + if (*s == '\r') { + next = s + 1; + ttywriteraw("\r\n", 2); + } else { + next = memchr(s, '\r', n); + DEFAULT(next, s + n); + ttywriteraw(s, next - s); + } + n -= next - s; + s = next; + } +} + +void +ttywriteraw(const char *s, size_t n) +{ + fd_set wfd, rfd; + ssize_t r; + size_t lim = 256; + + /* + * Remember that we are using a pty, which might be a modem line. + * Writing too much will clog the line. That's why we are doing this + * dance. + * FIXME: Migrate the world to Plan 9. + */ + while (n > 0) { + FD_ZERO(&wfd); + FD_ZERO(&rfd); + FD_SET(cmdfd, &wfd); + FD_SET(cmdfd, &rfd); + + /* Check if we can write. */ + if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + if (FD_ISSET(cmdfd, &wfd)) { + /* + * Only write the bytes written by ttywrite() or the + * default of 256. This seems to be a reasonable value + * for a serial line. Bigger values might clog the I/O. + */ + if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) + goto write_error; + if (r < n) { + /* + * We weren't able to write out everything. + * This means the buffer is getting full + * again. Empty it. + */ + if (n < lim) + lim = ttyread(); + n -= r; + s += r; + } else { + /* All bytes have been written. */ + break; + } + } + if (FD_ISSET(cmdfd, &rfd)) + lim = ttyread(); + } + return; + +write_error: + die("write error on tty: %s\n", strerror(errno)); +} + +void +ttyresize(int tw, int th) +{ + struct winsize w; + + w.ws_row = term.row; + w.ws_col = term.col; + w.ws_xpixel = tw; + w.ws_ypixel = th; + if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) + fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); +} + +void +ttyhangup(void) +{ + /* Send SIGHUP to shell */ + kill(pid, SIGHUP); +} + +int +tattrset(int attr) +{ + int i, j; + + for (i = 0; i < term.row-1; i++) { + for (j = 0; j < term.col-1; j++) { + if (term.line[i][j].mode & attr) + return 1; + } + } + + return 0; +} + +int +tisaltscr(void) +{ + return IS_SET(MODE_ALTSCREEN); +} + +void +tsetdirt(int top, int bot) +{ + int i; + + LIMIT(top, 0, term.row-1); + LIMIT(bot, 0, term.row-1); + + for (i = top; i <= bot; i++) + term.dirty[i] = 1; +} + +void +tsetdirtattr(int attr) +{ + int i, j; + + for (i = 0; i < term.row-1; i++) { + for (j = 0; j < term.col-1; j++) { + if (term.line[i][j].mode & attr) { + tsetdirt(i, i); + break; + } + } + } +} + +void +tfulldirt(void) +{ + tsetdirt(0, term.row-1); +} + +void +tcursor(int mode) +{ + static TCursor c[2]; + int alt = IS_SET(MODE_ALTSCREEN); + + if (mode == CURSOR_SAVE) { + c[alt] = term.c; + } else if (mode == CURSOR_LOAD) { + term.c = c[alt]; + tmoveto(c[alt].x, c[alt].y); + } +} + +void +treset(void) +{ + uint i; + + term.c = (TCursor){{ + .mode = ATTR_NULL, + .fg = defaultfg, + .bg = defaultbg + }, .x = 0, .y = 0, .state = CURSOR_DEFAULT}; + + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + for (i = tabspaces; i < term.col; i += tabspaces) + term.tabs[i] = 1; + term.top = 0; + term.bot = term.row - 1; + term.mode = MODE_WRAP|MODE_UTF8; + memset(term.trantbl, CS_USA, sizeof(term.trantbl)); + term.charset = 0; + + for (i = 0; i < 2; i++) { + tmoveto(0, 0); + tcursor(CURSOR_SAVE); + tclearregion(0, 0, term.maxcol-1, term.row-1); + tswapscreen(); + } +} + +void +tnew(int col, int row) +{ + term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } }; + tresize(col, row); + treset(); +} + +void +tswapscreen(void) +{ + Line *tmp = term.line; + + term.line = term.alt; + term.alt = tmp; + term.mode ^= MODE_ALTSCREEN; + tfulldirt(); +} + +void +tscrolldown(int orig, int n) +{ + + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + tsetdirt(orig, term.bot-n); + tclearregion(0, term.bot-n+1, term.maxcol-1, term.bot); + + for (i = term.bot; i >= orig+n; i--) { + temp = term.line[i]; + term.line[i] = term.line[i-n]; + term.line[i-n] = temp; + } + + + if (term.scr == 0) + selscroll(orig, n); +} + +void +tscrollup(int orig, int n, int copyhist) +{ + + int i; + Line temp; + + LIMIT(n, 0, term.bot-orig+1); + + if (copyhist && !IS_SET(MODE_ALTSCREEN)) { + for (i = 0; i < n; i++) { + term.histi = (term.histi + 1) % HISTSIZE; + temp = term.hist[term.histi]; + term.hist[term.histi] = term.line[orig+i]; + term.line[orig+i] = temp; + } + term.histn = MIN(term.histn + n, HISTSIZE); + + if (term.scr > 0 && term.scr < HISTSIZE) + term.scr = MIN(term.scr + n, HISTSIZE-1); + } + + tclearregion(0, orig, term.maxcol-1, orig+n-1); + tsetdirt(orig+n, term.bot); + + for (i = orig; i <= term.bot-n; i++) { + temp = term.line[i]; + term.line[i] = term.line[i+n]; + term.line[i+n] = temp; + } + + + if (term.scr == 0) + selscroll(orig, -n); +} + +void +selscroll(int orig, int n) +{ + if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) + return; + + if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { + selclear(); + } else if (BETWEEN(sel.nb.y, orig, term.bot)) { + sel.ob.y += n; + sel.oe.y += n; + if (sel.ob.y < term.top || sel.ob.y > term.bot || + sel.oe.y < term.top || sel.oe.y > term.bot) { + selclear(); + } else { + selnormalize(); + } + } +} + +void +tnewline(int first_col) +{ + int y = term.c.y; + + if (y == term.bot) { + tscrollup(term.top, 1, 1); + } else { + y++; + } + tmoveto(first_col ? 0 : term.c.x, y); +} + + +void +csiparse(void) +{ + char *p = csiescseq.buf, *np; + long int v; + + csiescseq.narg = 0; + if (*p == '?') { + csiescseq.priv = 1; + p++; + } + + csiescseq.buf[csiescseq.len] = '\0'; + while (p < csiescseq.buf+csiescseq.len) { + np = NULL; + v = strtol(p, &np, 10); + if (np == p) + v = 0; + if (v == LONG_MAX || v == LONG_MIN) + v = -1; + csiescseq.arg[csiescseq.narg++] = v; + p = np; + if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) + break; + p++; + } + csiescseq.mode[0] = *p++; + csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; +} + +/* for absolute user moves, when decom is set */ +void +tmoveato(int x, int y) +{ + tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); +} + +void +tmoveto(int x, int y) +{ + int miny, maxy; + + if (term.c.state & CURSOR_ORIGIN) { + miny = term.top; + maxy = term.bot; + } else { + miny = 0; + maxy = term.row - 1; + } + term.c.state &= ~CURSOR_WRAPNEXT; + term.c.x = LIMIT(x, 0, term.col-1); + term.c.y = LIMIT(y, miny, maxy); +} + +void +tsetchar(Rune u, const Glyph *attr, int x, int y) +{ + static const char *vt100_0[62] = { /* 0x41 - 0x7e */ + "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ + 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ + 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ + 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ + "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ + "␤", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ + "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ + "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ + }; + + /* + * The table is proudly stolen from rxvt. + */ + if (term.trantbl[term.charset] == CS_GRAPHIC0 && + BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) + utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); + + if (term.line[y][x].mode & ATTR_WIDE) { + if (x+1 < term.col) { + term.line[y][x+1].u = ' '; + term.line[y][x+1].mode &= ~ATTR_WDUMMY; + } + } else if (term.line[y][x].mode & ATTR_WDUMMY) { + term.line[y][x-1].u = ' '; + term.line[y][x-1].mode &= ~ATTR_WIDE; + } + + term.dirty[y] = 1; + term.line[y][x] = *attr; + term.line[y][x].u = u; + + if (isboxdraw(u)) + term.line[y][x].mode |= ATTR_BOXDRAW; +} + +void +tclearregion(int x1, int y1, int x2, int y2) +{ + int x, y, temp; + Glyph *gp; + + if (x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if (y1 > y2) + temp = y1, y1 = y2, y2 = temp; + + LIMIT(x1, 0, term.maxcol-1); + LIMIT(x2, 0, term.maxcol-1); + LIMIT(y1, 0, term.row-1); + LIMIT(y2, 0, term.row-1); + + for (y = y1; y <= y2; y++) { + term.dirty[y] = 1; + for (x = x1; x <= x2; x++) { + gp = &term.line[y][x]; + if (selected(x, y)) + selclear(); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + gp->u = ' '; + } + } +} + +void +tdeletechar(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(term.col-n, term.c.y, term.col-1, term.c.y); +} + +void +tinsertblank(int n) +{ + int dst, src, size; + Glyph *line; + + LIMIT(n, 0, term.col - term.c.x); + + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; + line = term.line[term.c.y]; + + memmove(&line[dst], &line[src], size * sizeof(Glyph)); + tclearregion(src, term.c.y, dst - 1, term.c.y); +} + +void +tinsertblankline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrolldown(term.c.y, n); +} + +void +tdeleteline(int n) +{ + if (BETWEEN(term.c.y, term.top, term.bot)) + tscrollup(term.c.y, n, 0); +} + +int32_t +tdefcolor(const int *attr, int *npar, int l) +{ + int32_t idx = -1; + uint r, g, b; + + switch (attr[*npar + 1]) { + case 2: /* direct color in RGB space */ + if (*npar + 4 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + r = attr[*npar + 2]; + g = attr[*npar + 3]; + b = attr[*npar + 4]; + *npar += 4; + if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) + fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", + r, g, b); + else + idx = TRUECOLOR(r, g, b); + break; + case 5: /* indexed color */ + if (*npar + 2 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + *npar += 2; + if (!BETWEEN(attr[*npar], 0, 255)) + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); + else + idx = attr[*npar]; + break; + case 0: /* implemented defined (only foreground) */ + case 1: /* transparent */ + case 3: /* direct color in CMY space */ + case 4: /* direct color in CMYK space */ + default: + fprintf(stderr, + "erresc(38): gfx attr %d unknown\n", attr[*npar]); + break; + } + + return idx; +} + +void +tsetattr(const int *attr, int l) +{ + int i; + int32_t idx; + + for (i = 0; i < l; i++) { + switch (attr[i]) { + case 0: + term.c.attr.mode &= ~( + ATTR_BOLD | + ATTR_FAINT | + ATTR_ITALIC | + ATTR_UNDERLINE | + ATTR_BLINK | + ATTR_REVERSE | + ATTR_INVISIBLE | + ATTR_STRUCK ); + term.c.attr.fg = defaultfg; + term.c.attr.bg = defaultbg; + break; + case 1: + term.c.attr.mode |= ATTR_BOLD; + break; + case 2: + term.c.attr.mode |= ATTR_FAINT; + break; + case 3: + term.c.attr.mode |= ATTR_ITALIC; + break; + case 4: + term.c.attr.mode |= ATTR_UNDERLINE; + break; + case 5: /* slow blink */ + /* FALLTHROUGH */ + case 6: /* rapid blink */ + term.c.attr.mode |= ATTR_BLINK; + break; + case 7: + term.c.attr.mode |= ATTR_REVERSE; + break; + case 8: + term.c.attr.mode |= ATTR_INVISIBLE; + break; + case 9: + term.c.attr.mode |= ATTR_STRUCK; + break; + case 22: + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); + break; + case 23: + term.c.attr.mode &= ~ATTR_ITALIC; + break; + case 24: + term.c.attr.mode &= ~ATTR_UNDERLINE; + break; + case 25: + term.c.attr.mode &= ~ATTR_BLINK; + break; + case 27: + term.c.attr.mode &= ~ATTR_REVERSE; + break; + case 28: + term.c.attr.mode &= ~ATTR_INVISIBLE; + break; + case 29: + term.c.attr.mode &= ~ATTR_STRUCK; + break; + case 38: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.fg = idx; + break; + case 39: + term.c.attr.fg = defaultfg; + break; + case 48: + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.bg = idx; + break; + case 49: + term.c.attr.bg = defaultbg; + break; + default: + if (BETWEEN(attr[i], 30, 37)) { + term.c.attr.fg = attr[i] - 30; + } else if (BETWEEN(attr[i], 40, 47)) { + term.c.attr.bg = attr[i] - 40; + } else if (BETWEEN(attr[i], 90, 97)) { + term.c.attr.fg = attr[i] - 90 + 8; + } else if (BETWEEN(attr[i], 100, 107)) { + term.c.attr.bg = attr[i] - 100 + 8; + } else { + fprintf(stderr, + "erresc(default): gfx attr %d unknown\n", + attr[i]); + csidump(); + } + break; + } + } +} + +void +tsetscroll(int t, int b) +{ + int temp; + + LIMIT(t, 0, term.row-1); + LIMIT(b, 0, term.row-1); + if (t > b) { + temp = t; + t = b; + b = temp; + } + term.top = t; + term.bot = b; +} + +void +tsetmode(int priv, int set, const int *args, int narg) +{ + int alt; + const int *lim; + + for (lim = args + narg; args < lim; ++args) { + if (priv) { + switch (*args) { + case 1: /* DECCKM -- Cursor key */ + xsetmode(set, MODE_APPCURSOR); + break; + case 5: /* DECSCNM -- Reverse video */ + xsetmode(set, MODE_REVERSE); + break; + case 6: /* DECOM -- Origin */ + MODBIT(term.c.state, set, CURSOR_ORIGIN); + tmoveato(0, 0); + break; + case 7: /* DECAWM -- Auto wrap */ + MODBIT(term.mode, set, MODE_WRAP); + break; + case 0: /* Error (IGNORED) */ + case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ + case 3: /* DECCOLM -- Column (IGNORED) */ + case 4: /* DECSCLM -- Scroll (IGNORED) */ + case 8: /* DECARM -- Auto repeat (IGNORED) */ + case 18: /* DECPFF -- Printer feed (IGNORED) */ + case 19: /* DECPEX -- Printer extent (IGNORED) */ + case 42: /* DECNRCM -- National characters (IGNORED) */ + case 12: /* att610 -- Start blinking cursor (IGNORED) */ + break; + case 25: /* DECTCEM -- Text Cursor Enable Mode */ + xsetmode(!set, MODE_HIDE); + break; + case 9: /* X10 mouse compatibility mode */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEX10); + break; + case 1000: /* 1000: report button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEBTN); + break; + case 1002: /* 1002: report motion on button press */ + xsetpointermotion(0); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMOTION); + break; + case 1003: /* 1003: enable all mouse motions */ + xsetpointermotion(set); + xsetmode(0, MODE_MOUSE); + xsetmode(set, MODE_MOUSEMANY); + break; + case 1004: /* 1004: send focus events to tty */ + xsetmode(set, MODE_FOCUS); + break; + case 1006: /* 1006: extended reporting mode */ + xsetmode(set, MODE_MOUSESGR); + break; + case 1034: + xsetmode(set, MODE_8BIT); + break; + case 1049: /* swap screen & set/restore cursor as xterm */ + if (!allowaltscreen) + break; + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + /* FALLTHROUGH */ + case 47: /* swap screen */ + case 1047: + if (!allowaltscreen) + break; + alt = IS_SET(MODE_ALTSCREEN); + if (alt) { + tclearregion(0, 0, term.maxcol-1, term.row-1); + } + if (set ^ alt) /* set is always 1 or 0 */ + tswapscreen(); + if (*args != 1049) + break; + /* FALLTHROUGH */ + case 1048: + tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); + break; + case 2004: /* 2004: bracketed paste mode */ + xsetmode(set, MODE_BRCKTPASTE); + break; + /* Not implemented mouse modes. See comments there. */ + case 1001: /* mouse highlight mode; can hang the + terminal by design when implemented. */ + case 1005: /* UTF-8 mouse mode; will confuse + applications not supporting UTF-8 + and luit. */ + case 1015: /* urxvt mangled mouse mode; incompatible + and can be mistaken for other control + codes. */ + break; + default: + fprintf(stderr, + "erresc: unknown private set/reset mode %d\n", + *args); + break; + } + } else { + switch (*args) { + case 0: /* Error (IGNORED) */ + break; + case 2: + xsetmode(set, MODE_KBDLOCK); + break; + case 4: /* IRM -- Insertion-replacement */ + MODBIT(term.mode, set, MODE_INSERT); + break; + case 12: /* SRM -- Send/Receive */ + MODBIT(term.mode, !set, MODE_ECHO); + break; + case 20: /* LNM -- Linefeed/new line */ + MODBIT(term.mode, set, MODE_CRLF); + break; + default: + fprintf(stderr, + "erresc: unknown set/reset mode %d\n", + *args); + break; + } + } + } +} + +void +csihandle(void) +{ + char buffer[40]; + int len; + int maxcol = term.maxcol; + + switch (csiescseq.mode[0]) { + default: + unknown: + fprintf(stderr, "erresc: unknown csi "); + csidump(); + /* die(""); */ + break; + case '@': /* ICH -- Insert blank char */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblank(csiescseq.arg[0]); + break; + case 'A': /* CUU -- Cursor Up */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); + break; + case 'B': /* CUD -- Cursor Down */ + case 'e': /* VPR --Cursor Down */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); + break; + case 'i': /* MC -- Media Copy */ + switch (csiescseq.arg[0]) { + case 0: + tdump(); + break; + case 1: + tdumpline(term.c.y); + break; + case 2: + tdumpsel(); + break; + case 4: + term.mode &= ~MODE_PRINT; + break; + case 5: + term.mode |= MODE_PRINT; + break; + } + break; + case 'c': /* DA -- Device Attributes */ + if (csiescseq.arg[0] == 0) + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'b': /* REP -- if last char is printable print it more times */ + DEFAULT(csiescseq.arg[0], 1); + if (term.lastc) + while (csiescseq.arg[0]-- > 0) + tputc(term.lastc); + break; + case 'C': /* CUF -- Cursor Forward */ + case 'a': /* HPR -- Cursor Forward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x+csiescseq.arg[0], term.c.y); + break; + case 'D': /* CUB -- Cursor Backward */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(term.c.x-csiescseq.arg[0], term.c.y); + break; + case 'E': /* CNL -- Cursor Down and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y+csiescseq.arg[0]); + break; + case 'F': /* CPL -- Cursor Up and first col */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(0, term.c.y-csiescseq.arg[0]); + break; + case 'g': /* TBC -- Tabulation clear */ + switch (csiescseq.arg[0]) { + case 0: /* clear current tab stop */ + term.tabs[term.c.x] = 0; + break; + case 3: /* clear all the tabs */ + memset(term.tabs, 0, term.col * sizeof(*term.tabs)); + break; + default: + goto unknown; + } + break; + case 'G': /* CHA -- Move to */ + case '`': /* HPA */ + DEFAULT(csiescseq.arg[0], 1); + tmoveto(csiescseq.arg[0]-1, term.c.y); + break; + case 'H': /* CUP -- Move to */ + case 'f': /* HVP */ + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], 1); + tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); + break; + case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(csiescseq.arg[0]); + break; + case 'J': /* ED -- Clear screen */ + switch (csiescseq.arg[0]) { + case 0: /* below */ + tclearregion(term.c.x, term.c.y, maxcol-1, term.c.y); + if (term.c.y < term.row-1) { + tclearregion(0, term.c.y+1, maxcol-1, + term.row-1); + } + break; + case 1: /* above */ + if (term.c.y > 1) + tclearregion(0, 0, maxcol-1, term.c.y-1); + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* screen */ + if (!IS_SET(MODE_ALTSCREEN)) { + kscrolldown(&((Arg){ .i = term.scr })); + int n, m, bot = term.bot; + term.bot = term.row-1; + for (n = term.row-1; n >= 0; n--) { + for (m = 0; m < maxcol && term.line[n][m].u == ' ' && !term.line[n][m].mode; m++); + if (m < maxcol) { + tscrollup(0, n+1, 1); + break; + } + } + if (n < term.row-1) + tclearregion(0, 0, maxcol-1, term.row-n-2); + term.bot = bot; + break; + } + + tclearregion(0, 0, maxcol-1, term.row-1); + + break; + case 3: /* scrollback */ + if (!IS_SET(MODE_ALTSCREEN)) { + term.scr = 0; + term.histi = 0; + term.histn = 0; + Glyph g=(Glyph){.bg=term.c.attr.bg, .fg=term.c.attr.fg, .u=' ', .mode=0}; + for (int i = 0; i < HISTSIZE; i++) { + for (int j = 0; j < maxcol; j++) + term.hist[i][j] = g; + } + } + break; + default: + goto unknown; + } + break; + case 'K': /* EL -- Clear line */ + switch (csiescseq.arg[0]) { + case 0: /* right */ + tclearregion(term.c.x, term.c.y, maxcol-1, + term.c.y); + break; + case 1: /* left */ + tclearregion(0, term.c.y, term.c.x, term.c.y); + break; + case 2: /* all */ + tclearregion(0, term.c.y, maxcol-1, term.c.y); + break; + } + break; + case 'S': /* SU -- Scroll line up */ + DEFAULT(csiescseq.arg[0], 1); + tscrollup(term.top, csiescseq.arg[0], 0); + break; + case 'T': /* SD -- Scroll line down */ + DEFAULT(csiescseq.arg[0], 1); + tscrolldown(term.top, csiescseq.arg[0]); + break; + case 'L': /* IL -- Insert blank lines */ + DEFAULT(csiescseq.arg[0], 1); + tinsertblankline(csiescseq.arg[0]); + break; + case 'l': /* RM -- Reset Mode */ + tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); + break; + case 'M': /* DL -- Delete lines */ + DEFAULT(csiescseq.arg[0], 1); + tdeleteline(csiescseq.arg[0]); + break; + case 'X': /* ECH -- Erase char */ + DEFAULT(csiescseq.arg[0], 1); + tclearregion(term.c.x, term.c.y, + term.c.x + csiescseq.arg[0] - 1, term.c.y); + break; + case 'P': /* DCH -- Delete char */ + DEFAULT(csiescseq.arg[0], 1); + tdeletechar(csiescseq.arg[0]); + break; + case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ + DEFAULT(csiescseq.arg[0], 1); + tputtab(-csiescseq.arg[0]); + break; + case 'd': /* VPA -- Move to */ + DEFAULT(csiescseq.arg[0], 1); + tmoveato(term.c.x, csiescseq.arg[0]-1); + break; + case 'h': /* SM -- Set terminal mode */ + tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); + break; + case 'm': /* SGR -- Terminal attribute (color) */ + tsetattr(csiescseq.arg, csiescseq.narg); + break; + case 'n': /* DSR -- Device Status Report */ + switch (csiescseq.arg[0]) { + case 5: /* Status Report "OK" `0n` */ + ttywrite("\033[0n", sizeof("\033[0n") - 1, 0); + break; + case 6: /* Report Cursor Position (CPR) ";R" */ + len = snprintf(buffer, sizeof(buffer), "\033[%i;%iR", + term.c.y+1, term.c.x+1); + ttywrite(buffer, len, 0); + break; + default: + goto unknown; + } + break; + case 'r': /* DECSTBM -- Set Scrolling Region */ + if (csiescseq.priv) { + goto unknown; + } else { + DEFAULT(csiescseq.arg[0], 1); + DEFAULT(csiescseq.arg[1], term.row); + tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); + tmoveato(0, 0); + } + break; + case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ + tcursor(CURSOR_SAVE); + break; + case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ + tcursor(CURSOR_LOAD); + break; + case ' ': + switch (csiescseq.mode[1]) { + case 'q': /* DECSCUSR -- Set Cursor Style */ + if (xsetcursor(csiescseq.arg[0])) + goto unknown; + break; + default: + goto unknown; + } + break; + } +} + +void +csidump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC["); + for (i = 0; i < csiescseq.len; i++) { + c = csiescseq.buf[i] & 0xff; + if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + putc('\n', stderr); +} + +void +csireset(void) +{ + memset(&csiescseq, 0, sizeof(csiescseq)); +} + +void +osc4_color_response(int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(num, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + return; + } + + n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +osc_color_response(int index, int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc color %d\n", index); + return; + } + + n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +strhandle(void) +{ + char *p = NULL, *dec; + int j, narg, par; + + term.esc &= ~(ESC_STR_END|ESC_STR); + strparse(); + par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; + + switch (strescseq.type) { + case ']': /* OSC -- Operating System Command */ + switch (par) { + case 0: + if (narg > 1) { + xsettitle(strescseq.args[1]); + xseticontitle(strescseq.args[1]); + } + return; + case 1: + if (narg > 1) + xseticontitle(strescseq.args[1]); + return; + case 2: + if (narg > 1) + xsettitle(strescseq.args[1]); + return; + case 52: + if (narg > 2 && allowwindowops) { + dec = base64dec(strescseq.args[2]); + if (dec) { + xsetsel(dec); + xclipcopy(); + } else { + fprintf(stderr, "erresc: invalid base64\n"); + } + } + return; + case 8: /* Clear Hyperlinks */ + return; + case 10: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultfg, 10); + else if (xsetcolorname(defaultfg, p)) + fprintf(stderr, "erresc: invalid foreground color: %s\n", p); + else + tfulldirt(); + return; + case 11: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultbg, 11); + else if (xsetcolorname(defaultbg, p)) + fprintf(stderr, "erresc: invalid background color: %s\n", p); + else + tfulldirt(); + return; + case 12: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultcs, 12); + else if (xsetcolorname(defaultcs, p)) + fprintf(stderr, "erresc: invalid cursor color: %s\n", p); + else + tfulldirt(); + return; + case 4: /* color set */ + if ((par == 4 && narg < 3) || narg < 2) + break; + p = strescseq.args[((par == 4) ? 2 : 1)]; + /* FALLTHROUGH */ + case 104: /* color reset */ + if (par == 10) + j = defaultfg; + else if (par == 11) + j = defaultbg; + else if (par == 12) + j = defaultcs; + else + j = (narg > 1) ? atoi(strescseq.args[1]) : -1; + + if (p && !strcmp(p, "?")) + osc4_color_response(j); + else if (xsetcolorname(j, p)) { + if (par == 104 && narg <= 1) { + xloadcols(); + return; /* color reset without parameter */ + } + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", + j, p ? p : "(null)"); + } else { + if (j == defaultbg) + xclearwin(); + tfulldirt(); + } + return; + } + break; + case 'k': /* old title set compatibility */ + xsettitle(strescseq.args[0]); + return; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + return; + } + + fprintf(stderr, "erresc: unknown str "); + strdump(); +} + +void +strparse(void) +{ + int c; + char *p = strescseq.buf; + + strescseq.narg = 0; + strescseq.buf[strescseq.len] = '\0'; + + if (*p == '\0') + return; + + while (strescseq.narg < STR_ARG_SIZ) { + strescseq.args[strescseq.narg++] = p; + while ((c = *p) != ';' && c != '\0') + ++p; + if (c == '\0') + return; + *p++ = '\0'; + } +} + +void +strdump(void) +{ + size_t i; + uint c; + + fprintf(stderr, "ESC%c", strescseq.type); + for (i = 0; i < strescseq.len; i++) { + c = strescseq.buf[i] & 0xff; + if (c == '\0') { + putc('\n', stderr); + return; + } else if (isprint(c)) { + putc(c, stderr); + } else if (c == '\n') { + fprintf(stderr, "(\\n)"); + } else if (c == '\r') { + fprintf(stderr, "(\\r)"); + } else if (c == 0x1b) { + fprintf(stderr, "(\\e)"); + } else { + fprintf(stderr, "(%02x)", c); + } + } + fprintf(stderr, "ESC\\\n"); +} + +void +strreset(void) +{ + strescseq = (STREscape){ + .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; +} + +void +sendbreak(const Arg *arg) +{ + if (tcsendbreak(cmdfd, 0)) + perror("Error sending break"); +} + +void +tprinter(char *s, size_t len) +{ + if (iofd != -1 && xwrite(iofd, s, len) < 0) { + perror("Error writing to output file"); + close(iofd); + iofd = -1; + } +} + +void +toggleprinter(const Arg *arg) +{ + term.mode ^= MODE_PRINT; +} + +void +printscreen(const Arg *arg) +{ + tdump(); +} + +void +printsel(const Arg *arg) +{ + tdumpsel(); +} + +void +tdumpsel(void) +{ + char *ptr; + + if ((ptr = getsel())) { + tprinter(ptr, strlen(ptr)); + free(ptr); + } +} + +void +tdumpline(int n) +{ + char buf[UTF_SIZ]; + const Glyph *bp, *end; + + bp = &term.line[n][0]; + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if (bp != end || bp->u != ' ') { + for ( ; bp <= end; ++bp) + tprinter(buf, utf8encode(bp->u, buf)); + } + tprinter("\n", 1); +} + +void +tdump(void) +{ + int i; + + for (i = 0; i < term.row; ++i) + tdumpline(i); +} + +void +tputtab(int n) +{ + uint x = term.c.x; + + if (n > 0) { + while (x < term.col && n--) + for (++x; x < term.col && !term.tabs[x]; ++x) + /* nothing */ ; + } else if (n < 0) { + while (x > 0 && n++) + for (--x; x > 0 && !term.tabs[x]; --x) + /* nothing */ ; + } + term.c.x = LIMIT(x, 0, term.col-1); +} + +void +tdefutf8(char ascii) +{ + if (ascii == 'G') + term.mode |= MODE_UTF8; + else if (ascii == '@') + term.mode &= ~MODE_UTF8; +} + +void +tdeftran(char ascii) +{ + static char cs[] = "0B"; + static int vcs[] = {CS_GRAPHIC0, CS_USA}; + char *p; + + if ((p = strchr(cs, ascii)) == NULL) { + fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); + } else { + term.trantbl[term.icharset] = vcs[p - cs]; + } +} + +void +tdectest(char c) +{ + int x, y; + + if (c == '8') { /* DEC screen alignment test. */ + for (x = 0; x < term.col; ++x) { + for (y = 0; y < term.row; ++y) + tsetchar('E', &term.c.attr, x, y); + } + } +} + +void +tstrsequence(uchar c) +{ + + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; + } + strreset(); + strescseq.type = c; + term.esc |= ESC_STR; +} + +void +tcontrolcode(uchar ascii) +{ + switch (ascii) { + case '\t': /* HT */ + tputtab(1); + return; + case '\b': /* BS */ + tmoveto(term.c.x-1, term.c.y); + return; + case '\r': /* CR */ + tmoveto(0, term.c.y); + return; + case '\f': /* LF */ + case '\v': /* VT */ + case '\n': /* LF */ + /* go to first col if the mode is set */ + tnewline(IS_SET(MODE_CRLF)); + return; + case '\a': /* BEL */ + if (term.esc & ESC_STR_END) { + /* backwards compatibility to xterm */ + strhandle(); + } else { + xbell(); + } + break; + case '\033': /* ESC */ + csireset(); + term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); + term.esc |= ESC_START; + return; + case '\016': /* SO (LS1 -- Locking shift 1) */ + case '\017': /* SI (LS0 -- Locking shift 0) */ + term.charset = 1 - (ascii - '\016'); + return; + case '\032': /* SUB */ + tsetchar('?', &term.c.attr, term.c.x, term.c.y); + /* FALLTHROUGH */ + case '\030': /* CAN */ + csireset(); + break; + case '\005': /* ENQ (IGNORED) */ + case '\000': /* NUL (IGNORED) */ + case '\021': /* XON (IGNORED) */ + case '\023': /* XOFF (IGNORED) */ + case 0177: /* DEL (IGNORED) */ + return; + case 0x80: /* TODO: PAD */ + case 0x81: /* TODO: HOP */ + case 0x82: /* TODO: BPH */ + case 0x83: /* TODO: NBH */ + case 0x84: /* TODO: IND */ + break; + case 0x85: /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 0x86: /* TODO: SSA */ + case 0x87: /* TODO: ESA */ + break; + case 0x88: /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 0x89: /* TODO: HTJ */ + case 0x8a: /* TODO: VTS */ + case 0x8b: /* TODO: PLD */ + case 0x8c: /* TODO: PLU */ + case 0x8d: /* TODO: RI */ + case 0x8e: /* TODO: SS2 */ + case 0x8f: /* TODO: SS3 */ + case 0x91: /* TODO: PU1 */ + case 0x92: /* TODO: PU2 */ + case 0x93: /* TODO: STS */ + case 0x94: /* TODO: CCH */ + case 0x95: /* TODO: MW */ + case 0x96: /* TODO: SPA */ + case 0x97: /* TODO: EPA */ + case 0x98: /* TODO: SOS */ + case 0x99: /* TODO: SGCI */ + break; + case 0x9a: /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 0x9b: /* TODO: CSI */ + case 0x9c: /* TODO: ST */ + break; + case 0x90: /* DCS -- Device Control String */ + case 0x9d: /* OSC -- Operating System Command */ + case 0x9e: /* PM -- Privacy Message */ + case 0x9f: /* APC -- Application Program Command */ + tstrsequence(ascii); + return; + } + /* only CAN, SUB, \a and C1 chars interrupt a sequence */ + term.esc &= ~(ESC_STR_END|ESC_STR); +} + +/* + * returns 1 when the sequence is finished and it hasn't to read + * more characters for this sequence, otherwise 0 + */ +int +eschandle(uchar ascii) +{ + switch (ascii) { + case '[': + term.esc |= ESC_CSI; + return 0; + case '#': + term.esc |= ESC_TEST; + return 0; + case '%': + term.esc |= ESC_UTF8; + return 0; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + case ']': /* OSC -- Operating System Command */ + case 'k': /* old title set compatibility */ + tstrsequence(ascii); + return 0; + case 'n': /* LS2 -- Locking shift 2 */ + case 'o': /* LS3 -- Locking shift 3 */ + term.charset = 2 + (ascii - 'n'); + break; + case '(': /* GZD4 -- set primary charset G0 */ + case ')': /* G1D4 -- set secondary charset G1 */ + case '*': /* G2D4 -- set tertiary charset G2 */ + case '+': /* G3D4 -- set quaternary charset G3 */ + term.icharset = ascii - '('; + term.esc |= ESC_ALTCHARSET; + return 0; + case 'D': /* IND -- Linefeed */ + if (term.c.y == term.bot) { + tscrollup(term.top, 1, 1); + } else { + tmoveto(term.c.x, term.c.y+1); + } + break; + case 'E': /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 'H': /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 'M': /* RI -- Reverse index */ + if (term.c.y == term.top) { + tscrolldown(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y-1); + } + break; + case 'Z': /* DECID -- Identify Terminal */ + ttywrite(vtiden, strlen(vtiden), 0); + break; + case 'c': /* RIS -- Reset to initial state */ + treset(); + resettitle(); + xloadcols(); + xsetmode(0, MODE_HIDE); + if (!IS_SET(MODE_ALTSCREEN)) { + term.scr = 0; + term.histi = 0; + term.histn = 0; + } + break; + case '=': /* DECPAM -- Application keypad */ + xsetmode(1, MODE_APPKEYPAD); + break; + case '>': /* DECPNM -- Normal keypad */ + xsetmode(0, MODE_APPKEYPAD); + break; + case '7': /* DECSC -- Save Cursor */ + tcursor(CURSOR_SAVE); + break; + case '8': /* DECRC -- Restore Cursor */ + tcursor(CURSOR_LOAD); + break; + case '\\': /* ST -- String Terminator */ + if (term.esc & ESC_STR_END) + strhandle(); + break; + default: + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", + (uchar) ascii, isprint(ascii)? ascii:'.'); + break; + } + return 1; +} + +void +tputc(Rune u) +{ + char c[UTF_SIZ]; + int control; + int width, len; + Glyph *gp; + + control = ISCONTROL(u); + if (u < 127 || !IS_SET(MODE_UTF8)) + { + c[0] = u; + width = len = 1; + } else { + len = utf8encode(u, c); + if (!control && (width = wcwidth(u)) == -1) + width = 1; + } + + if (IS_SET(MODE_PRINT)) + tprinter(c, len); + + /* + * STR sequence must be checked before anything else + * because it uses all following characters until it + * receives a ESC, a SUB, a ST or any other C1 control + * character. + */ + if (term.esc & ESC_STR) { + if (u == '\a' || u == 030 || u == 032 || u == 033 || + ISCONTROLC1(u)) { + term.esc &= ~(ESC_START|ESC_STR); + term.esc |= ESC_STR_END; + goto check_control_code; + } + + + if (strescseq.len+len >= strescseq.siz) { + /* + * Here is a bug in terminals. If the user never sends + * some code to stop the str or esc command, then st + * will stop responding. But this is better than + * silently failing with unknown characters. At least + * then users will report back. + * + * In the case users ever get fixed, here is the code: + */ + /* + * term.esc = 0; + * strhandle(); + */ + if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); + } + + memmove(&strescseq.buf[strescseq.len], c, len); + strescseq.len += len; + return; + } + +check_control_code: + /* + * Actions of control codes must be performed as soon they arrive + * because they can be embedded inside a control sequence, and + * they must not cause conflicts with sequences. + */ + if (control) { + /* in UTF-8 mode ignore handling C1 control characters */ + if (IS_SET(MODE_UTF8) && ISCONTROLC1(u)) + return; + tcontrolcode(u); + /* + * control codes are not shown ever + */ + if (!term.esc) + term.lastc = 0; + return; + } else if (term.esc & ESC_START) { + if (term.esc & ESC_CSI) { + csiescseq.buf[csiescseq.len++] = u; + if (BETWEEN(u, 0x40, 0x7E) + || csiescseq.len >= \ + sizeof(csiescseq.buf)-1) { + term.esc = 0; + csiparse(); + csihandle(); + } + return; + } else if (term.esc & ESC_UTF8) { + tdefutf8(u); + } else if (term.esc & ESC_ALTCHARSET) { + tdeftran(u); + } else if (term.esc & ESC_TEST) { + tdectest(u); + } else { + if (!eschandle(u)) + return; + /* sequence already finished */ + } + term.esc = 0; + /* + * All characters which form part of a sequence are not + * printed + */ + return; + } + if (selected(term.c.x, term.c.y)) + selclear(); + + gp = &term.line[term.c.y][term.c.x]; + if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { + gp->mode |= ATTR_WRAP; + tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } + + if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) { + memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); + gp->mode &= ~ATTR_WIDE; + } + + if (term.c.x+width > term.col) { + if (IS_SET(MODE_WRAP)) + tnewline(1); + else + tmoveto(term.col - width, term.c.y); + gp = &term.line[term.c.y][term.c.x]; + } + + tsetchar(u, &term.c.attr, term.c.x, term.c.y); + term.lastc = u; + + if (width == 2) { + gp->mode |= ATTR_WIDE; + if (term.c.x+1 < term.col) { + if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { + gp[2].u = ' '; + gp[2].mode &= ~ATTR_WDUMMY; + } + gp[1].u = '\0'; + gp[1].mode = ATTR_WDUMMY; + } + } + if (term.c.x+width < term.col) { + tmoveto(term.c.x+width, term.c.y); + } else { + term.c.state |= CURSOR_WRAPNEXT; + } +} + +int +twrite(const char *buf, int buflen, int show_ctrl) +{ + int charsize; + Rune u; + int n; + + + for (n = 0; n < buflen; n += charsize) { + if (IS_SET(MODE_UTF8)) + { + /* process a complete utf8 char */ + charsize = utf8decode(buf + n, &u, buflen - n); + if (charsize == 0) + break; + } else { + u = buf[n] & 0xFF; + charsize = 1; + } + if (show_ctrl && ISCONTROL(u)) { + if (u & 0x80) { + u &= 0x7f; + tputc('^'); + tputc('['); + } else if (u != '\n' && u != '\r' && u != '\t') { + u ^= 0x40; + tputc('^'); + } + } + tputc(u); + } + return n; +} + +void +tresize(int col, int row) +{ + int i; + int j; + int tmp = col; + int minrow, mincol; + + if (!term.maxcol) + term.maxcol = term.col; + col = MAX(col, term.maxcol); + minrow = MIN(row, term.row); + mincol = MIN(col, term.maxcol); + int *bp; + TCursor c; + + + if (col < 1 || row < 1) { + fprintf(stderr, + "tresize: error resizing to %dx%d\n", col, row); + return; + } + + + /* + * slide screen to keep cursor where we expect it - + * tscrollup would work here, but we can optimize to + * memmove because we're freeing the earlier lines + */ + for (i = 0; i <= term.c.y - row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + /* ensure that both src and dst are not NULL */ + if (i > 0) { + memmove(term.line, term.line + i, row * sizeof(Line)); + memmove(term.alt, term.alt + i, row * sizeof(Line)); + } + for (i += row; i < term.row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + + /* resize to new height */ + term.line = xrealloc(term.line, row * sizeof(Line)); + term.alt = xrealloc(term.alt, row * sizeof(Line)); + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); + + Glyph gc=(Glyph){.bg=term.c.attr.bg, .fg=term.c.attr.fg, .u=' ', .mode=0}; + for (i = 0; i < HISTSIZE; i++) { + term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); + for (j = mincol; j < col; j++) + term.hist[i][j] = gc; + } + + /* resize each row to new width, zero-pad if needed */ + for (i = 0; i < minrow; i++) { + term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); + term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); + } + + /* allocate any new rows */ + for (/* i = minrow */; i < row; i++) { + term.line[i] = xmalloc(col * sizeof(Glyph)); + term.alt[i] = xmalloc(col * sizeof(Glyph)); + } + if (col > term.maxcol) + { + bp = term.tabs + term.maxcol; + memset(bp, 0, sizeof(*term.tabs) * (col - term.maxcol)); + + while (--bp > term.tabs && !*bp) + /* nothing */ ; + for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) + *bp = 1; + } + /* update terminal size */ + term.col = tmp; + term.maxcol = col; + term.row = row; + /* reset scrolling region */ + tsetscroll(0, row-1); + /* make use of the LIMIT in tmoveto */ + tmoveto(term.c.x, term.c.y); + /* Clearing both screens (it makes dirty all lines) */ + c = term.c; + for (i = 0; i < 2; i++) { + if (mincol < col && 0 < minrow) { + tclearregion(mincol, 0, col - 1, minrow - 1); + } + if (0 < col && minrow < row) { + tclearregion(0, minrow, col - 1, row - 1); + } + tswapscreen(); + tcursor(CURSOR_LOAD); + } + term.c = c; +} + +void +resettitle(void) +{ + xsettitle(NULL); +} + +void +drawregion(int x1, int y1, int x2, int y2) +{ + int y; + + for (y = y1; y < y2; y++) { + if (!term.dirty[y]) + continue; + + term.dirty[y] = 0; + xdrawline(TLINE(y), x1, y, x2); + } +} + +#include "patch/st_include.c" + +void +draw(void) +{ + int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; + + if (!xstartdraw()) + return; + + /* adjust cursor position */ + LIMIT(term.ocx, 0, term.col-1); + LIMIT(term.ocy, 0, term.row-1); + if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) + term.ocx--; + if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) + cx--; + + + drawregion(0, 0, term.col, term.row); + + if (term.scr == 0) + xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], + term.ocx, term.ocy, term.line[term.ocy][term.ocx], + term.line[term.ocy], term.col); + term.ocx = cx; + term.ocy = term.c.y; + xfinishdraw(); + if (ocx != term.ocx || ocy != term.ocy) + xximspot(term.ocx, term.ocy); +} + +void +redraw(void) +{ + tfulldirt(); + draw(); +} diff --git a/.config/suckless/st/st.desktop b/.config/suckless/st/st.desktop new file mode 100644 index 0000000..14a389a --- /dev/null +++ b/.config/suckless/st/st.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=st +Comment=st is a simple terminal implementation for X +Exec=st +Icon=utilities-terminal +Terminal=false +Type=Application +Categories=System;TerminalEmulator; \ No newline at end of file diff --git a/.config/suckless/st/st.h b/.config/suckless/st/st.h new file mode 100644 index 0000000..6766cc9 --- /dev/null +++ b/.config/suckless/st/st.h @@ -0,0 +1,305 @@ +/* See LICENSE for license details. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* macros */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define LEN(a) (sizeof(a) / sizeof(a)[0]) +#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) +#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) +#define DEFAULT(a, b) (a) = (a) ? (a) : (b) +#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) +#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP) & (~ATTR_LIGA)) != ((b).mode & (~ATTR_WRAP) & (~ATTR_LIGA)) || \ + (a).fg != (b).fg || \ + (a).bg != (b).bg) +#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ + (t1.tv_nsec-t2.tv_nsec)/1E6) +#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) + +#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) +#define IS_TRUECOL(x) (1 << 24 & (x)) +#define HISTSIZE 2000 + +enum glyph_attribute { + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, + ATTR_BOXDRAW = 1 << 11, + ATTR_LIGA = 1 << 12, + ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, +}; + + +enum drawing_mode { + DRAW_NONE = 0, + DRAW_BG = 1 << 0, + DRAW_FG = 1 << 1, +}; + +/* Used to control which screen(s) keybindings and mouse shortcuts apply to. */ +enum screen { + S_PRI = -1, /* primary screen */ + S_ALL = 0, /* both primary and alt screen */ + S_ALT = 1 /* alternate screen */ +}; + +enum selection_mode { + SEL_IDLE = 0, + SEL_EMPTY = 1, + SEL_READY = 2 +}; + +enum selection_type { + SEL_REGULAR = 1, + SEL_RECTANGULAR = 2 +}; + +enum selection_snap { + SNAP_WORD = 1, + SNAP_LINE = 2 +}; + +typedef unsigned char uchar; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; + +typedef uint_least32_t Rune; + +typedef XftDraw *Draw; +typedef XftColor Color; +typedef XftGlyphFontSpec GlyphFontSpec; + +#define Glyph Glyph_ +typedef struct { + Rune u; /* character code */ + ushort mode; /* attribute flags */ + uint32_t fg; /* foreground */ + uint32_t bg; /* background */ +} Glyph; + +typedef Glyph *Line; + +typedef struct { + Glyph attr; /* current char attributes */ + int x; + int y; + char state; +} TCursor; + +/* Internal representation of the screen */ +typedef struct { + int row; /* nb row */ + int col; /* nb col */ + int maxcol; + Line *line; /* screen */ + Line *alt; /* alternate screen */ + Line hist[HISTSIZE]; /* history buffer */ + int histi; /* history index */ + int histn; /* number of history entries */ + int scr; /* scroll back */ + int *dirty; /* dirtyness of lines */ + TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int *tabs; + Rune lastc; /* last printed char outside of sequence, 0 if control */ +} Term; + +typedef union { + int i; + uint ui; + float f; + const void *v; + const char *s; +} Arg; + +/* Purely graphic info */ +typedef struct { + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ + int ch; /* char height */ + int cw; /* char width */ + int mode; /* window state/mode flags */ + int cursor; /* cursor style */ +} TermWindow; + +typedef struct { + Display *dpy; + Colormap cmap; + Window win; + Drawable buf; + GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ + Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; + struct { + XIM xim; + XIC xic; + XPoint spot; + XVaNestedList spotlist; + } ime; + Draw draw; + Visual *vis; + XSetWindowAttributes attrs; + /* Here, we use the term *pointer* to differentiate the cursor + * one sees when hovering the mouse over the terminal from, e.g., + * a green rectangle where text would be entered. */ + Cursor vpointer, bpointer; /* visible and hidden pointers */ + int pointerisvisible; + int scr; + int isfixed; /* is fixed geometry? */ + int depth; /* bit depth */ + int l, t; /* left and top offset */ + int gm; /* geometry mask */ +} XWindow; + +typedef struct { + Atom xtarget; + char *primary, *clipboard; + struct timespec tclick1; + struct timespec tclick2; +} XSelection; + +/* types used in config.h */ +typedef struct { + uint mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; + int screen; +} Shortcut; + +typedef struct { + uint mod; + uint button; + void (*func)(const Arg *); + const Arg arg; + uint release; + int screen; +} MouseShortcut; + +typedef struct { + KeySym k; + uint mask; + char *s; + /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ + signed char appkey; /* application keypad */ + signed char appcursor; /* application cursor */ +} Key; + +/* Font structure */ +#define Font Font_ +typedef struct { + int height; + int width; + int ascent; + int descent; + int badslant; + int badweight; + short lbearing; + short rbearing; + XftFont *match; + FcFontSet *set; + FcPattern *pattern; +} Font; + +/* Drawing Context */ +typedef struct { + Color *col; + size_t collen; + Font font, bfont, ifont, ibfont; + GC gc; +} DC; + +void die(const char *, ...); +void redraw(void); +void draw(void); +void drawregion(int, int, int, int); +void tfulldirt(void); + +void printscreen(const Arg *); +void printsel(const Arg *); +void sendbreak(const Arg *); +void toggleprinter(const Arg *); + +int tattrset(int); +int tisaltscr(void); +void tnew(int, int); +void tresize(int, int); +void tsetdirtattr(int); +void ttyhangup(void); +int ttynew(const char *, char *, const char *, char **); +size_t ttyread(void); +void ttyresize(int, int); +void ttywrite(const char *, size_t, int); + +void resettitle(void); + +void selclear(void); +void selinit(void); +void selstart(int, int, int); +void selextend(int, int, int, int); +int selected(int, int); +char *getsel(void); + +size_t utf8encode(Rune, char *); + +void *xmalloc(size_t); +void *xrealloc(void *, size_t); +char *xstrdup(const char *); + +int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); + +int isboxdraw(Rune); +ushort boxdrawindex(const Glyph *); +#ifdef XFT_VERSION +/* only exposed to x.c, otherwise we'll need Xft.h for the types */ +void boxdraw_xinit(Display *, Colormap, XftDraw *, Visual *); +void drawboxes(int, int, int, int, XftColor *, XftColor *, const XftGlyphFontSpec *, int); +#endif // XFT_VERSION + +/* config.h globals */ +extern char *utmp; +extern char *scroll; +extern char *stty_args; +extern char *vtiden; +extern wchar_t *worddelimiters; +extern int allowaltscreen; +extern int allowwindowops; +extern char *termname; +extern unsigned int tabspaces; +extern unsigned int defaultfg; +extern unsigned int defaultbg; +extern unsigned int defaultcs; + +extern const int boxdraw, boxdraw_bold, boxdraw_braille; +extern float alpha; + +extern DC dc; +extern XWindow xw; +extern XSelection xsel; +extern TermWindow win; +extern Term term; diff --git a/.config/suckless/st/st.info b/.config/suckless/st/st.info new file mode 100644 index 0000000..b286fb5 --- /dev/null +++ b/.config/suckless/st/st.info @@ -0,0 +1,252 @@ +st-mono| simpleterm monocolor, +# undercurl patch / UNDERCURL_PATCH + Su, + acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, + am, + bce, + bel=^G, + blink=\E[5m, + bold=\E[1m, + cbt=\E[Z, + cvvis=\E[?25h, + civis=\E[?25l, + clear=\E[H\E[2J, + cnorm=\E[?12l\E[?25h, + colors#2, + cols#80, + cr=^M, + csr=\E[%i%p1%d;%p2%dr, + cub=\E[%p1%dD, + cub1=^H, + cud1=^J, + cud=\E[%p1%dB, + cuf1=\E[C, + cuf=\E[%p1%dC, + cup=\E[%i%p1%d;%p2%dH, + cuu1=\E[A, + cuu=\E[%p1%dA, + dch=\E[%p1%dP, + dch1=\E[P, + dim=\E[2m, + dl=\E[%p1%dM, + dl1=\E[M, + ech=\E[%p1%dX, + ed=\E[J, + el=\E[K, + el1=\E[1K, + enacs=\E)0, + E3=\E[3J, + flash=\E[?5h$<80/>\E[?5l, + fsl=^G, + home=\E[H, + hpa=\E[%i%p1%dG, + hs, + ht=^I, + hts=\EH, + ich=\E[%p1%d@, + il1=\E[L, + il=\E[%p1%dL, + ind=^J, + indn=\E[%p1%dS, + invis=\E[8m, + is2=\E[4l\E>\E[?1034l, + it#8, + kel=\E[1;2F, + ked=\E[1;5F, + ka1=\E[1~, + ka3=\E[5~, + kc1=\E[4~, + kc3=\E[6~, + kbs=\177, + kcbt=\E[Z, + kb2=\EOu, + kcub1=\EOD, + kcud1=\EOB, + kcuf1=\EOC, + kcuu1=\EOA, + kDC=\E[3;2~, + kent=\EOM, + kEND=\E[1;2F, + kIC=\E[2;2~, + kNXT=\E[6;2~, + kPRV=\E[5;2~, + kHOM=\E[1;2H, + kLFT=\E[1;2D, + kRIT=\E[1;2C, + kind=\E[1;2B, + kri=\E[1;2A, + kclr=\E[3;5~, + kdl1=\E[3;2~, + kdch1=\E[3~, + kich1=\E[2~, + kend=\E[4~, + kf1=\EOP, + kf2=\EOQ, + kf3=\EOR, + kf4=\EOS, + kf5=\E[15~, + kf6=\E[17~, + kf7=\E[18~, + kf8=\E[19~, + kf9=\E[20~, + kf10=\E[21~, + kf11=\E[23~, + kf12=\E[24~, + kf13=\E[1;2P, + kf14=\E[1;2Q, + kf15=\E[1;2R, + kf16=\E[1;2S, + kf17=\E[15;2~, + kf18=\E[17;2~, + kf19=\E[18;2~, + kf20=\E[19;2~, + kf21=\E[20;2~, + kf22=\E[21;2~, + kf23=\E[23;2~, + kf24=\E[24;2~, + kf25=\E[1;5P, + kf26=\E[1;5Q, + kf27=\E[1;5R, + kf28=\E[1;5S, + kf29=\E[15;5~, + kf30=\E[17;5~, + kf31=\E[18;5~, + kf32=\E[19;5~, + kf33=\E[20;5~, + kf34=\E[21;5~, + kf35=\E[23;5~, + kf36=\E[24;5~, + kf37=\E[1;6P, + kf38=\E[1;6Q, + kf39=\E[1;6R, + kf40=\E[1;6S, + kf41=\E[15;6~, + kf42=\E[17;6~, + kf43=\E[18;6~, + kf44=\E[19;6~, + kf45=\E[20;6~, + kf46=\E[21;6~, + kf47=\E[23;6~, + kf48=\E[24;6~, + kf49=\E[1;3P, + kf50=\E[1;3Q, + kf51=\E[1;3R, + kf52=\E[1;3S, + kf53=\E[15;3~, + kf54=\E[17;3~, + kf55=\E[18;3~, + kf56=\E[19;3~, + kf57=\E[20;3~, + kf58=\E[21;3~, + kf59=\E[23;3~, + kf60=\E[24;3~, + kf61=\E[1;4P, + kf62=\E[1;4Q, + kf63=\E[1;4R, + khome=\E[1~, + kil1=\E[2;5~, + krmir=\E[2;2~, + knp=\E[6~, + kmous=\E[M, + kpp=\E[5~, + lines#24, + mir, + msgr, + npc, + op=\E[39;49m, + pairs#64, + mc0=\E[i, + mc4=\E[4i, + mc5=\E[5i, + rc=\E8, + rev=\E[7m, + ri=\EM, + rin=\E[%p1%dT, + ritm=\E[23m, + rmacs=\E(B, +# CSI 22, 23 patch / CSI_22_23_PATCH +# rmcup=\E[?1049l, + rmcup=\E[?1049l\E[23;0;0t, + rmir=\E[4l, + rmkx=\E[?1l\E>, + rmso=\E[27m, + rmul=\E[24m, + rs1=\Ec, + rs2=\E[4l\E>\E[?1034l, + sc=\E7, + sitm=\E[3m, + sgr0=\E[0m, + smacs=\E(0, +# CSI 22, 23 patch / CSI_22_23_PATCH +# smcup=\E[?1049h, + smcup=\E[?1049h\E[22;0;0t, + smir=\E[4h, + smkx=\E[?1h\E=, + smso=\E[7m, + smul=\E[4m, + tbc=\E[3g, + tsl=\E]0;, + xenl, + vpa=\E[%i%p1%dd, +# XTerm extensions + rmxx=\E[29m, + smxx=\E[9m, + BE=\E[?2004h, + BD=\E[?2004l, + PS=\E[200~, + PE=\E[201~, +# disabled rep for now: causes some issues with older ncurses versions. +# rep=%p1%c\E[%p2%{1}%-%db, +# tmux extensions, see TERMINFO EXTENSIONS in tmux(1) + Tc, + Ms=\E]52;%p1%s;%p2%s\007, + Se=\E[2 q, + Ss=\E[%p1%d q, +# sync patch / SYNC_PATCH + Sync=\EP=%p1%ds\E\\, + +st| simpleterm, + use=st-mono, + colors#8, + setab=\E[4%p1%dm, + setaf=\E[3%p1%dm, + setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, + setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, + sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, + +st-256color| simpleterm with 256 colors, + use=st, + ccc, + colors#256, + oc=\E]104\007, + pairs#32767, +# Nicked from xterm-256color + initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, + setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, + setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, + +st-meta| simpleterm with meta key, + use=st, + km, + rmm=\E[?1034l, + smm=\E[?1034h, + rs2=\E[4l\E>\E[?1034h, + is2=\E[4l\E>\E[?1034h, + +st-meta-256color| simpleterm with meta key and 256 colors, + use=st-256color, + km, + rmm=\E[?1034l, + smm=\E[?1034h, + rs2=\E[4l\E>\E[?1034h, + is2=\E[4l\E>\E[?1034h, + +st-bs| simpleterm with backspace as backspace, + use=st, + kbs=\010, + kdch1=\177, + +st-bs-256color| simpleterm with backspace as backspace and 256colors, + use=st-256color, + kbs=\010, + kdch1=\177, diff --git a/.config/suckless/st/win.h b/.config/suckless/st/win.h new file mode 100644 index 0000000..b9532a9 --- /dev/null +++ b/.config/suckless/st/win.h @@ -0,0 +1,41 @@ +/* See LICENSE for license details. */ + +enum win_mode { + MODE_VISIBLE = 1 << 0, + MODE_FOCUSED = 1 << 1, + MODE_APPKEYPAD = 1 << 2, + MODE_MOUSEBTN = 1 << 3, + MODE_MOUSEMOTION = 1 << 4, + MODE_REVERSE = 1 << 5, + MODE_KBDLOCK = 1 << 6, + MODE_HIDE = 1 << 7, + MODE_APPCURSOR = 1 << 8, + MODE_MOUSESGR = 1 << 9, + MODE_8BIT = 1 << 10, + MODE_BLINK = 1 << 11, + MODE_FBLINK = 1 << 12, + MODE_FOCUS = 1 << 13, + MODE_MOUSEX10 = 1 << 14, + MODE_MOUSEMANY = 1 << 15, + MODE_BRCKTPASTE = 1 << 16, + MODE_NUMLOCK = 1 << 17, + MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ + |MODE_MOUSEMANY, +}; + +void xbell(void); +void xclipcopy(void); +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int); +void xdrawline(Line, int, int, int); +void xfinishdraw(void); +void xloadcols(void); +int xsetcolorname(int, const char *); +void xseticontitle(char *); +void xsettitle(char *); +int xsetcursor(int); +void xsetmode(int, unsigned int); +void xsetpointermotion(int); +void xsetsel(char *); +int xstartdraw(void); +void xximspot(int, int); +void xclearwin(void); diff --git a/.config/suckless/st/x.c b/.config/suckless/st/x.c new file mode 100644 index 0000000..3e1980d --- /dev/null +++ b/.config/suckless/st/x.c @@ -0,0 +1,2234 @@ +/* See LICENSE for license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *argv0; +#include "arg.h" +#include "st.h" +#include "win.h" +#include "hb.h" + + + +/* X modifiers */ +#define XK_ANY_MOD UINT_MAX +#define XK_NO_MOD 0 +#define XK_SWITCH_MOD (1<<13|1<<14) + +/* function definitions used in config.h */ +static void clipcopy(const Arg *); +static void clippaste(const Arg *); +static void numlock(const Arg *); +static void selpaste(const Arg *); +static void ttysend(const Arg *); +static void zoom(const Arg *); +static void zoomabs(const Arg *); +static void zoomreset(const Arg *); + +#include "patch/st_include.h" +#include "patch/x_include.h" + +/* config.h for applying patches and the configuration. */ +#include "config.h" + + +/* XEMBED messages */ +#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_OUT 5 + +/* macros */ +#define IS_SET(flag) ((win.mode & (flag)) != 0) +#define TRUERED(x) (((x) & 0xff0000) >> 8) +#define TRUEGREEN(x) (((x) & 0xff00)) +#define TRUEBLUE(x) (((x) & 0xff) << 8) + +static inline ushort sixd_to_16bit(int); +static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int); +static void xresetfontsettings(ushort mode, Font **font, int *frcflags); +static void xdrawglyph(Glyph, int, int); +static void xclear(int, int, int, int); +static int xgeommasktogravity(int); +static int ximopen(Display *); +static void ximinstantiate(Display *, XPointer, XPointer); +static void ximdestroy(XIM, XPointer, XPointer); +static int xicdestroy(XIC, XPointer, XPointer); +static void xinit(int, int); +static void cresize(int, int); +static void xresize(int, int); +static void xhints(void); +static int xloadcolor(int, const char *, Color *); +static int xloadfont(Font *, FcPattern *); +static void xloadfonts(const char *, double); +static void xunloadfont(Font *); +static void xunloadfonts(void); +static void xsetenv(void); +static void xseturgency(int); +static int evcol(XEvent *); +static int evrow(XEvent *); + +static void expose(XEvent *); +static void visibility(XEvent *); +static void unmap(XEvent *); +static void kpress(XEvent *); +static void cmessage(XEvent *); +static void resize(XEvent *); +static void focus(XEvent *); +static uint buttonmask(uint); +static void brelease(XEvent *); +static void bpress(XEvent *); +static void bmotion(XEvent *); +static void propnotify(XEvent *); +static void selnotify(XEvent *); +static void selclear_(XEvent *); +static void selrequest(XEvent *); +static void setsel(char *, Time); +static void sigusr1_reload(int sig); +static int mouseaction(XEvent *, uint); +static void mousesel(XEvent *, int); +static void mousereport(XEvent *); +static char *kmap(KeySym, uint); +static int match(uint, uint); + +static void run(void); +static void usage(void); + +static void (*handler[LASTEvent])(XEvent *) = { + [KeyPress] = kpress, + [ClientMessage] = cmessage, + [ConfigureNotify] = resize, + [VisibilityNotify] = visibility, + [UnmapNotify] = unmap, + [Expose] = expose, + [FocusIn] = focus, + [FocusOut] = focus, + [MotionNotify] = bmotion, + [ButtonPress] = bpress, + [ButtonRelease] = brelease, +/* + * Uncomment if you want the selection to disappear when you select something + * different in another window. + */ +/* [SelectionClear] = selclear_, */ + [SelectionNotify] = selnotify, +/* + * PropertyNotify is only turned on when there is some INCR transfer happening + * for the selection retrieval. + */ + [PropertyNotify] = propnotify, + [SelectionRequest] = selrequest, +}; + +/* Globals */ +Term term; +DC dc; +XWindow xw; +XSelection xsel; +TermWindow win; + + +/* Font Ring Cache */ +enum { + FRC_NORMAL, + FRC_ITALIC, + FRC_BOLD, + FRC_ITALICBOLD +}; + +typedef struct { + XftFont *font; + int flags; + Rune unicodep; +} Fontcache; + +/* Fontcache is an array now. A new font will be appended to the array. */ +static Fontcache *frc = NULL; +static int frclen = 0; +static int frccap = 0; +static char *usedfont = NULL; +static double usedfontsize = 0; +static double defaultfontsize = 0; + +static char *opt_alpha = NULL; +static char *opt_class = NULL; +static char **opt_cmd = NULL; +static char *opt_embed = NULL; +static char *opt_font = NULL; +static char *opt_io = NULL; +static char *opt_line = NULL; +static char *opt_name = NULL; +static char *opt_title = NULL; + + +static uint buttons; /* bit field of pressed buttons */ +static int cursorblinks = 0; +static Cursor cursor; +static XColor xmousefg, xmousebg; + +#include "patch/x_include.c" + +void +clipcopy(const Arg *dummy) +{ + Atom clipboard; + + free(xsel.clipboard); + xsel.clipboard = NULL; + + if (xsel.primary != NULL) { + xsel.clipboard = xstrdup(xsel.primary); + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); + } +} + +void +clippaste(const Arg *dummy) +{ + Atom clipboard; + + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, + xw.win, CurrentTime); +} + +void +numlock(const Arg *dummy) +{ + win.mode ^= MODE_NUMLOCK; +} + +void +selpaste(const Arg *dummy) +{ + XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, + xw.win, CurrentTime); +} + +void +ttysend(const Arg *arg) +{ + ttywrite(arg->s, strlen(arg->s), 1); +} + +void +zoom(const Arg *arg) +{ + Arg larg; + + larg.f = usedfontsize + arg->f; + zoomabs(&larg); +} + +void +zoomabs(const Arg *arg) +{ + xunloadfonts(); + xloadfonts(usedfont, arg->f); + xloadsparefonts(); + cresize(0, 0); + redraw(); + xhints(); +} + +void +zoomreset(const Arg *arg) +{ + Arg larg; + + if (defaultfontsize > 0) { + larg.f = defaultfontsize; + zoomabs(&larg); + } +} + +int +evcol(XEvent *e) +{ + int x = e->xbutton.x - borderpx; + LIMIT(x, 0, win.tw - 1); + return x / win.cw; +} + +int +evrow(XEvent *e) +{ + int y = e->xbutton.y - borderpx; + LIMIT(y, 0, win.th - 1); + return y / win.ch; +} + +uint +buttonmask(uint button) +{ + return button == Button1 ? Button1Mask + : button == Button2 ? Button2Mask + : button == Button3 ? Button3Mask + : button == Button4 ? Button4Mask + : button == Button5 ? Button5Mask + : 0; +} + +int +mouseaction(XEvent *e, uint release) +{ + MouseShortcut *ms; + int screen = tisaltscr() ? S_ALT : S_PRI; + + /* ignore Buttonmask for Button - it's set on release */ + uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); + + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { + if (ms->release == release && + ms->button == e->xbutton.button && + (!ms->screen || (ms->screen == screen)) && + (match(ms->mod, state) || /* exact or forced */ + match(ms->mod, state & ~forcemousemod))) { + ms->func(&(ms->arg)); + return 1; + } + } + + return 0; +} + +void +mousesel(XEvent *e, int done) +{ + int type, seltype = SEL_REGULAR; + uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); + + for (type = 1; type < LEN(selmasks); ++type) { + if (match(selmasks[type], state)) { + seltype = type; + break; + } + } + selextend(evcol(e), evrow(e), seltype, done); + if (done) + setsel(getsel(), e->xbutton.time); +} + +void +mousereport(XEvent *e) +{ + int len, btn, code; + int x = evcol(e), y = evrow(e); + int state = e->xbutton.state; + char buf[40]; + static int ox, oy; + + if (e->type == MotionNotify) { + if (x == ox && y == oy) + return; + if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) + return; + /* MODE_MOUSEMOTION: no reporting if no button is pressed */ + if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) + return; + + /* Set btn to lowest-numbered pressed button, or 12 if no + * buttons are pressed. */ + for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) + ; + code = 32; + } else { + btn = e->xbutton.button; + /* Only buttons 1 through 11 can be encoded */ + if (btn < 1 || btn > 11) + return; + if (e->type == ButtonRelease) { + /* MODE_MOUSEX10: no button release reporting */ + if (IS_SET(MODE_MOUSEX10)) + return; + /* Don't send release events for the scroll wheel */ + if (btn == 4 || btn == 5) + return; + } + code = 0; + } + + ox = x; + oy = y; + + /* Encode btn into code. If no button is pressed for a motion event in + * MODE_MOUSEMANY, then encode it as a release. */ + if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) + code += 3; + else if (btn >= 8) + code += 128 + btn - 8; + else if (btn >= 4) + code += 64 + btn - 4; + else + code += btn - 1; + + if (!IS_SET(MODE_MOUSEX10)) { + code += ((state & ShiftMask ) ? 4 : 0) + + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ + + ((state & ControlMask) ? 16 : 0); + } + + if (IS_SET(MODE_MOUSESGR)) { + len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", + code, x+1, y+1, + e->type == ButtonRelease ? 'm' : 'M'); + } else if (x < 223 && y < 223) { + len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", + 32+code, 32+x+1, 32+y+1); + } else { + return; + } + + ttywrite(buf, len, 0); +} + +void +bpress(XEvent *e) +{ + int btn = e->xbutton.button; + struct timespec now; + int snap; + + if (1 <= btn && btn <= 11) + buttons |= 1 << (btn-1); + + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 0)) + return; + + if (btn == Button1) { + /* + * If the user clicks below predefined timeouts specific + * snapping behaviour is exposed. + */ + clock_gettime(CLOCK_MONOTONIC, &now); + if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { + snap = SNAP_LINE; + } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { + snap = SNAP_WORD; + } else { + snap = 0; + } + xsel.tclick2 = xsel.tclick1; + xsel.tclick1 = now; + + selstart(evcol(e), evrow(e), snap); + + } +} + +void +propnotify(XEvent *e) +{ + XPropertyEvent *xpev; + Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + + xpev = &e->xproperty; + if (xpev->state == PropertyNewValue && + (xpev->atom == XA_PRIMARY || + xpev->atom == clipboard)) { + selnotify(e); + } + +} + +void +selnotify(XEvent *e) +{ + ulong nitems, ofs, rem; + int format; + uchar *data, *last, *repl; + Atom type, incratom, property = None; + + incratom = XInternAtom(xw.dpy, "INCR", 0); + + ofs = 0; + if (e->type == SelectionNotify) + property = e->xselection.property; + else if (e->type == PropertyNotify) + property = e->xproperty.atom; + + if (property == None) + return; + + do { + if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, + BUFSIZ/4, False, AnyPropertyType, + &type, &format, &nitems, &rem, + &data)) { + fprintf(stderr, "Clipboard allocation failed\n"); + return; + } + + if (e->type == PropertyNotify && nitems == 0 && rem == 0) + { + /* + * If there is some PropertyNotify with no data, then + * this is the signal of the selection owner that all + * data has been transferred. We won't need to receive + * PropertyNotify events anymore. + */ + MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, + &xw.attrs); + } + + if (type == incratom) { + /* + * Activate the PropertyNotify events so we receive + * when the selection owner does send us the next + * chunk of data. + */ + MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, + &xw.attrs); + + /* + * Deleting the property is the transfer start signal. + */ + XDeleteProperty(xw.dpy, xw.win, (int)property); + continue; + } + + /* + * As seen in getsel: + * Line endings are inconsistent in the terminal and GUI world + * copy and pasting. When receiving some selection data, + * replace all '\n' with '\r'. + * FIXME: Fix the computer world. + */ + repl = data; + last = data + nitems * format / 8; + while ((repl = memchr(repl, '\n', last - repl))) { + *repl++ = '\r'; + } + + if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) + ttywrite("\033[200~", 6, 0); + ttywrite((char *)data, nitems * format / 8, 1); + if (IS_SET(MODE_BRCKTPASTE) && rem == 0) + ttywrite("\033[201~", 6, 0); + XFree(data); + /* number of 32-bit chunks returned */ + ofs += nitems * format / 32; + } while (rem > 0); + + /* + * Deleting the property again tells the selection owner to send the + * next data chunk in the property. + */ + XDeleteProperty(xw.dpy, xw.win, (int)property); +} + +void +xclipcopy(void) +{ + clipcopy(NULL); +} + +void +selclear_(XEvent *e) +{ + selclear(); +} + +void +selrequest(XEvent *e) +{ + XSelectionRequestEvent *xsre; + XSelectionEvent xev; + Atom xa_targets, string, clipboard; + char *seltext; + + xsre = (XSelectionRequestEvent *) e; + xev.type = SelectionNotify; + xev.requestor = xsre->requestor; + xev.selection = xsre->selection; + xev.target = xsre->target; + xev.time = xsre->time; + if (xsre->property == None) + xsre->property = xsre->target; + + /* reject */ + xev.property = None; + + xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); + if (xsre->target == xa_targets) { + /* respond with the supported type */ + string = xsel.xtarget; + XChangeProperty(xsre->display, xsre->requestor, xsre->property, + XA_ATOM, 32, PropModeReplace, + (uchar *) &string, 1); + xev.property = xsre->property; + } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { + /* + * xith XA_STRING non ascii characters may be incorrect in the + * requestor. It is not our problem, use utf8. + */ + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + if (xsre->selection == XA_PRIMARY) { + seltext = xsel.primary; + } else if (xsre->selection == clipboard) { + seltext = xsel.clipboard; + } else { + fprintf(stderr, + "Unhandled clipboard selection 0x%lx\n", + xsre->selection); + return; + } + if (seltext != NULL) { + XChangeProperty(xsre->display, xsre->requestor, + xsre->property, xsre->target, + 8, PropModeReplace, + (uchar *)seltext, strlen(seltext)); + xev.property = xsre->property; + } + } + + /* all done, send a notification to the listener */ + if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) + fprintf(stderr, "Error sending SelectionNotify event\n"); +} + +void +setsel(char *str, Time t) +{ + if (!str) + return; + + free(xsel.primary); + xsel.primary = str; + + XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); + if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) + selclear(); + + clipcopy(NULL); +} + +void +sigusr1_reload(int sig) +{ + reload_config(sig); + signal(SIGUSR1, sigusr1_reload); +} + +void +xsetsel(char *str) +{ + setsel(str, CurrentTime); +} + +void +brelease(XEvent *e) +{ + int btn = e->xbutton.button; + + if (1 <= btn && btn <= 11) + buttons &= ~(1 << (btn-1)); + + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + if (mouseaction(e, 1)) + return; + if (btn == Button1) { + mousesel(e, 1); + } + else if (btn == Button3) + plumb(xsel.primary); +} + +void +bmotion(XEvent *e) +{ + if (!xw.pointerisvisible) { + if (win.mode & MODE_MOUSE) + XUndefineCursor(xw.dpy, xw.win); + else + XDefineCursor(xw.dpy, xw.win, xw.vpointer); + xw.pointerisvisible = 1; + if (!IS_SET(MODE_MOUSEMANY)) + xsetpointermotion(0); + } + + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + mousereport(e); + return; + } + + mousesel(e, 0); +} + +void +cresize(int width, int height) +{ + int col, row; + + if (width != 0) + win.w = width; + if (height != 0) + win.h = height; + + col = (win.w - 2 * borderpx) / win.cw; + row = (win.h - 2 * borderpx) / win.ch; + col = MAX(1, col); + row = MAX(1, row); + + + tresize(col, row); + xresize(col, row); + ttyresize(win.tw, win.th); +} + +void +xresize(int col, int row) +{ + win.tw = col * win.cw; + win.th = row * win.ch; + + XFreePixmap(xw.dpy, xw.buf); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, + xw.depth + ); + XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); + + /* resize to new width */ + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); +} + +ushort +sixd_to_16bit(int x) +{ + return x == 0 ? 0 : 0x3737 + 0x2828 * x; +} + +int +xloadcolor(int i, const char *name, Color *ncolor) +{ + XRenderColor color = { .alpha = 0xffff }; + + if (!name) { + if (BETWEEN(i, 16, 255)) { /* 256 color */ + if (i < 6*6*6+16) { /* same colors as xterm */ + color.red = sixd_to_16bit( ((i-16)/36)%6 ); + color.green = sixd_to_16bit( ((i-16)/6) %6 ); + color.blue = sixd_to_16bit( ((i-16)/1) %6 ); + } else { /* greyscale */ + color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); + color.green = color.blue = color.red; + } + return XftColorAllocValue(xw.dpy, xw.vis, + xw.cmap, &color, ncolor); + } else + name = colorname[i]; + } + + return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); +} + + + +void +xloadcols(void) +{ + int i; + static int loaded; + Color *cp; + + if (loaded) { + for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) + XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); + } else { + dc.collen = MAX(LEN(colorname), 256); + dc.col = xmalloc(dc.collen * sizeof(Color)); + } + + for (i = 0; i < dc.collen; i++) + if (!xloadcolor(i, NULL, &dc.col[i])) { + if (colorname[i]) + die("could not allocate color '%s'\n", colorname[i]); + else + die("could not allocate color %d\n", i); + } + /* set alpha value of bg color */ + if (opt_alpha) + alpha = strtof(opt_alpha, NULL); + dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); + dc.col[defaultbg].pixel &= 0x00FFFFFF; + dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; + loaded = 1; +} + +int +xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) +{ + if (!BETWEEN(x, 0, dc.collen - 1)) + return 1; + + *r = dc.col[x].color.red >> 8; + *g = dc.col[x].color.green >> 8; + *b = dc.col[x].color.blue >> 8; + + return 0; +} + +int +xsetcolorname(int x, const char *name) +{ + Color ncolor; + + if (!BETWEEN(x, 0, dc.collen - 1)) + return 1; + + if (!xloadcolor(x, name, &ncolor)) + return 1; + + XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); + dc.col[x] = ncolor; + + /* set alpha value of bg color */ + if (x == defaultbg) { + if (opt_alpha) + alpha = strtof(opt_alpha, NULL); + dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); + dc.col[defaultbg].pixel &= 0x00FFFFFF; + dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; + } + return 0; +} + +/* + * Absolute coordinates. + */ +void +xclear(int x1, int y1, int x2, int y2) +{ + Color c; + c = dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg]; + if (invertcolors) { + c = invertedcolor(&c); + } + XftDrawRect(xw.draw, &c, x1, y1, x2-x1, y2-y1); +} + +void +xclearwin(void) +{ + xclear(0, 0, win.w, win.h); +} + +void +xhints(void) +{ + XClassHint class = {opt_name ? opt_name : "st", + opt_class ? opt_class : "St"}; + XWMHints wm = {.flags = InputHint, .input = 1}; + XSizeHints *sizeh; + + sizeh = XAllocSizeHints(); + + sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; + sizeh->height = win.h; + sizeh->width = win.w; + sizeh->height_inc = win.ch; + sizeh->width_inc = win.cw; + sizeh->base_height = 2 * borderpx; + sizeh->base_width = 2 * borderpx; + sizeh->min_height = win.ch + 2 * borderpx; + sizeh->min_width = win.cw + 2 * borderpx; + if (xw.isfixed) { + sizeh->flags |= PMaxSize; + sizeh->min_width = sizeh->max_width = win.w; + sizeh->min_height = sizeh->max_height = win.h; + } + if (xw.gm & (XValue|YValue)) { + sizeh->flags |= USPosition | PWinGravity; + sizeh->x = xw.l; + sizeh->y = xw.t; + sizeh->win_gravity = xgeommasktogravity(xw.gm); + } + + XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, + &class); + XFree(sizeh); +} + +int +xgeommasktogravity(int mask) +{ + switch (mask & (XNegative|YNegative)) { + case 0: + return NorthWestGravity; + case XNegative: + return NorthEastGravity; + case YNegative: + return SouthWestGravity; + } + + return SouthEastGravity; +} + +int +ximopen(Display *dpy) +{ + XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; + XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; + + xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); + if (xw.ime.xim == NULL) + return 0; + + if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) + fprintf(stderr, "XSetIMValues: " + "Could not set XNDestroyCallback.\n"); + + xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, + NULL); + + if (xw.ime.xic == NULL) { + xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, + XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, xw.win, + XNDestroyCallback, &icdestroy, + NULL); + } + if (xw.ime.xic == NULL) + fprintf(stderr, "XCreateIC: Could not create input context.\n"); + + return 1; +} + +void +ximinstantiate(Display *dpy, XPointer client, XPointer call) +{ + if (ximopen(dpy)) + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); +} + +void +ximdestroy(XIM xim, XPointer client, XPointer call) +{ + xw.ime.xim = NULL; + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + XFree(xw.ime.spotlist); +} + +int +xicdestroy(XIC xim, XPointer client, XPointer call) +{ + xw.ime.xic = NULL; + return 1; +} + +int +xloadfont(Font *f, FcPattern *pattern) +{ + FcPattern *configured; + FcPattern *match; + FcResult result; + XGlyphInfo extents; + int wantattr, haveattr; + + /* + * Manually configure instead of calling XftMatchFont + * so that we can use the configured pattern for + * "missing glyph" lookups. + */ + configured = FcPatternDuplicate(pattern); + if (!configured) + return 1; + + FcConfigSubstitute(NULL, configured, FcMatchPattern); + XftDefaultSubstitute(xw.dpy, xw.scr, configured); + + match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); + if (!match) { + FcPatternDestroy(configured); + return 1; + } + + if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { + FcPatternDestroy(configured); + FcPatternDestroy(match); + return 1; + } + + if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == + XftResultMatch)) { + /* + * Check if xft was unable to find a font with the appropriate + * slant but gave us one anyway. Try to mitigate. + */ + if ((XftPatternGetInteger(f->match->pattern, "slant", 0, + &haveattr) != XftResultMatch) || haveattr < wantattr) { + f->badslant = 1; + fputs("font slant does not match\n", stderr); + } + } + + if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == + XftResultMatch)) { + if ((XftPatternGetInteger(f->match->pattern, "weight", 0, + &haveattr) != XftResultMatch) || haveattr != wantattr) { + f->badweight = 1; + fputs("font weight does not match\n", stderr); + } + } + + XftTextExtentsUtf8(xw.dpy, f->match, + (const FcChar8 *) ascii_printable, + strlen(ascii_printable), &extents); + + f->set = NULL; + f->pattern = configured; + + f->ascent = f->match->ascent; + f->descent = f->match->descent; + f->lbearing = 0; + f->rbearing = f->match->max_advance_width; + + f->height = f->ascent + f->descent; + f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); + + return 0; +} + +void +xloadfonts(const char *fontstr, double fontsize) +{ + FcPattern *pattern; + double fontval; + + if (fontstr[0] == '-') + pattern = XftXlfdParse(fontstr, False, False); + else + pattern = FcNameParse((const FcChar8 *)fontstr); + + if (!pattern) + die("can't open font %s\n", fontstr); + + if (fontsize > 1) { + FcPatternDel(pattern, FC_PIXEL_SIZE); + FcPatternDel(pattern, FC_SIZE); + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); + usedfontsize = fontsize; + } else { + if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == + FcResultMatch) { + usedfontsize = fontval; + } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == + FcResultMatch) { + usedfontsize = -1; + } else { + /* + * Default font size is 12, if none given. This is to + * have a known usedfontsize value. + */ + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); + usedfontsize = 12; + } + defaultfontsize = usedfontsize; + } + + if (xloadfont(&dc.font, pattern)) + die("can't open font %s\n", fontstr); + + if (usedfontsize < 0) { + FcPatternGetDouble(dc.font.match->pattern, + FC_PIXEL_SIZE, 0, &fontval); + usedfontsize = fontval; + if (fontsize == 0) + defaultfontsize = fontval; + } + + /* Setting character width and height. */ + win.cw = ceilf(dc.font.width * cwscale); + win.ch = ceilf(dc.font.height * chscale); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); + if (xloadfont(&dc.ifont, pattern)) + die("can't open font %s\n", fontstr); + + FcPatternDel(pattern, FC_WEIGHT); + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + if (xloadfont(&dc.ibfont, pattern)) + die("can't open font %s\n", fontstr); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); + if (xloadfont(&dc.bfont, pattern)) + die("can't open font %s\n", fontstr); + + FcPatternDestroy(pattern); +} + +void +xunloadfont(Font *f) +{ + XftFontClose(xw.dpy, f->match); + FcPatternDestroy(f->pattern); + if (f->set) + FcFontSetDestroy(f->set); +} + +void +xunloadfonts(void) +{ + /* Clear Harfbuzz font cache. */ + hbunloadfonts(); + + /* Free the loaded fonts in the font cache. */ + while (frclen > 0) + XftFontClose(xw.dpy, frc[--frclen].font); + + xunloadfont(&dc.font); + xunloadfont(&dc.bfont); + xunloadfont(&dc.ifont); + xunloadfont(&dc.ibfont); +} + +void +xinit(int cols, int rows) +{ + XGCValues gcvalues; + Pixmap blankpm; + Window parent; + pid_t thispid = getpid(); + XWindowAttributes attr; + XVisualInfo vis; + + xw.scr = XDefaultScreen(xw.dpy); + + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { + parent = XRootWindow(xw.dpy, xw.scr); + xw.depth = 32; + } else { + XGetWindowAttributes(xw.dpy, parent, &attr); + xw.depth = attr.depth; + } + + XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); + xw.vis = vis.visual; + + /* font */ + if (!FcInit()) + die("could not init fontconfig.\n"); + + usedfont = (opt_font == NULL)? font : opt_font; + xloadfonts(usedfont, 0); + + /* spare fonts */ + xloadsparefonts(); + + /* colors */ + xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); + xloadcols(); + + /* adjust fixed window geometry */ + win.w = 2 * borderpx + cols * win.cw; + win.h = 2 * borderpx + rows * win.ch; + if (xw.gm & XNegative) + xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; + if (xw.gm & YNegative) + xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; + + /* Events */ + xw.attrs.background_pixel = dc.col[defaultbg].pixel; + xw.attrs.border_pixel = dc.col[defaultbg].pixel; + xw.attrs.bit_gravity = NorthWestGravity; + xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask + | ExposureMask | VisibilityChangeMask | StructureNotifyMask + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask + ; + xw.attrs.colormap = xw.cmap; + + xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, + win.w, win.h, 0, xw.depth, InputOutput, + xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity + | CWEventMask | CWColormap, &xw.attrs); + + memset(&gcvalues, 0, sizeof(gcvalues)); + gcvalues.graphics_exposures = False; + + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); + dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + + /* font spec buffer */ + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); + + /* Xft rendering context */ + xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); + + /* input methods */ + if (!ximopen(xw.dpy)) { + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + } + + /* white cursor, black outline */ + xw.pointerisvisible = 1; + xw.vpointer = XCreateFontCursor(xw.dpy, mouseshape); + XDefineCursor(xw.dpy, xw.win, xw.vpointer); + + if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { + xmousefg.red = 0xffff; + xmousefg.green = 0xffff; + xmousefg.blue = 0xffff; + } + + if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { + xmousebg.red = 0x0000; + xmousebg.green = 0x0000; + xmousebg.blue = 0x0000; + } + + XRecolorCursor(xw.dpy, xw.vpointer, &xmousefg, &xmousebg); + blankpm = XCreateBitmapFromData(xw.dpy, xw.win, &(char){0}, 1, 1); + xw.bpointer = XCreatePixmapCursor(xw.dpy, blankpm, blankpm, + &xmousefg, &xmousebg, 0, 0); + + + xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); + xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); + xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); + xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); + XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); + + + + xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); + XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, + PropModeReplace, (uchar *)&thispid, 1); + + + win.mode = MODE_NUMLOCK; + resettitle(); + xhints(); + XMapWindow(xw.dpy, xw.win); + XSync(xw.dpy, False); + + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); + xsel.primary = NULL; + xsel.clipboard = NULL; + xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); + if (xsel.xtarget == None) + xsel.xtarget = XA_STRING; + + boxdraw_xinit(xw.dpy, xw.cmap, xw.draw, xw.vis); +} + +void +xresetfontsettings(ushort mode, Font **font, int *frcflags) +{ + *font = &dc.font; + if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { + *font = &dc.ibfont; + *frcflags = FRC_ITALICBOLD; + } else if (mode & ATTR_ITALIC) { + *font = &dc.ifont; + *frcflags = FRC_ITALIC; + } else if (mode & ATTR_BOLD) { + *font = &dc.bfont; + *frcflags = FRC_BOLD; + } +} + +int +xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) +{ + float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; + ushort mode, prevmode = USHRT_MAX; + Font *font = &dc.font; + int frcflags = FRC_NORMAL; + float runewidth = win.cw; + Rune rune; + FT_UInt glyphidx; + FcResult fcres; + FcPattern *fcpattern, *fontpattern; + FcFontSet *fcsets[] = { NULL }; + FcCharSet *fccharset; + int i, f, numspecs = 0; + int length = 0, start = 0; + HbTransformData shaped = { 0 }; + + /* Initial values. */ + mode = prevmode = glyphs[0].mode & ~ATTR_WRAP; + xresetfontsettings(mode, &font, &frcflags); + + for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) + { + /* Fetch rune and mode for current glyph. */ + mode = glyphs[i].mode & ~ATTR_WRAP; + + /* Skip dummy wide-character spacing. */ + if (mode & ATTR_WDUMMY) + continue; + + if ( + prevmode != mode + || ATTRCMP(glyphs[start], glyphs[i]) + || selected(x + i, y) != selected(x + start, y) + || i == (len - 1) + ) { + /* Handle 1-character wide segments and end of line */ + length = i - start; + if (i == start) { + length = 1; + } else if (i == (len - 1)) { + length = (i - start + 1); + } + + /* Shape the segment. */ + hbtransform(&shaped, font->match, glyphs, start, length); + for (int code_idx = 0; code_idx < shaped.count; code_idx++) { + rune = glyphs[start + code_idx].u; + runewidth = win.cw * ((glyphs[start + code_idx].mode & ATTR_WIDE) ? 2.0f : 1.0f); + + if (glyphs[start + code_idx].mode & ATTR_WDUMMY) + continue; + + if (glyphs[start + code_idx].mode & ATTR_BOXDRAW) { + /* minor shoehorning: boxdraw uses only this ushort */ + specs[numspecs].font = font->match; + specs[numspecs].glyph = boxdrawindex(&glyphs[start + code_idx]); + specs[numspecs].x = xp; + specs[numspecs].y = yp; + xp += runewidth; + numspecs++; + } else + if (shaped.glyphs[code_idx].codepoint != 0) { + /* If symbol is found, put it into the specs. */ + specs[numspecs].font = font->match; + specs[numspecs].glyph = shaped.glyphs[code_idx].codepoint; + specs[numspecs].x = xp + (short)shaped.positions[code_idx].x_offset; + specs[numspecs].y = yp + (short)shaped.positions[code_idx].y_offset; + xp += runewidth; + numspecs++; + } else { + /* If it's not found, try to fetch it through the font cache. */ + for (f = 0; f < frclen; f++) { + glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); + /* Everything correct. */ + if (glyphidx && frc[f].flags == frcflags) + break; + /* We got a default font for a not found glyph. */ + if (!glyphidx && frc[f].flags == frcflags + && frc[f].unicodep == rune) { + break; + } + } + + /* Nothing was found. Use fontconfig to find matching font. */ + if (f >= frclen) { + if (!font->set) + font->set = FcFontSort(0, font->pattern, 1, 0, &fcres); + fcsets[0] = font->set; + + /* + * Nothing was found in the cache. Now use + * some dozen of Fontconfig calls to get the + * font for one single character. + * + * Xft and fontconfig are design failures. + */ + fcpattern = FcPatternDuplicate(font->pattern); + fccharset = FcCharSetCreate(); + + FcCharSetAddChar(fccharset, rune); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, 1); + + FcConfigSubstitute(0, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + + fontpattern = FcFontSetMatch(0, fcsets, 1, fcpattern, &fcres); + + /* Allocate memory for the new cache entry. */ + if (frclen >= frccap) { + frccap += 16; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); + } + + frc[frclen].font = XftFontOpenPattern(xw.dpy, fontpattern); + if (!frc[frclen].font) + die("XftFontOpenPattern failed seeking fallback font: %s\n", + strerror(errno)); + frc[frclen].flags = frcflags; + frc[frclen].unicodep = rune; + + glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); + + f = frclen; + frclen++; + + FcPatternDestroy(fcpattern); + FcCharSetDestroy(fccharset); + } + + specs[numspecs].font = frc[f].font; + specs[numspecs].glyph = glyphidx; + specs[numspecs].x = (short)xp; + specs[numspecs].y = (short)yp; + xp += runewidth; + numspecs++; + } + } + + /* Cleanup and get ready for next segment. */ + hbcleanup(&shaped); + start = i; + + /* Determine font for glyph if different from previous glyph. */ + if (prevmode != mode) { + prevmode = mode; + xresetfontsettings(mode, &font, &frcflags); + yp = winy + font->ascent; + } + } + } + + return numspecs; +} + + +void +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode) +{ + int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); + int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch; + int width = charlen * win.cw; + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; + XRenderColor colfg, colbg; + XRectangle r; + + /* Fallback on color display for attributes not supported by the font */ + if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { + if (dc.ibfont.badslant || dc.ibfont.badweight) + base.fg = defaultattr; + } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || + (base.mode & ATTR_BOLD && dc.bfont.badweight)) { + base.fg = defaultattr; + } + + if (IS_TRUECOL(base.fg)) { + colfg.alpha = 0xffff; + colfg.red = TRUERED(base.fg); + colfg.green = TRUEGREEN(base.fg); + colfg.blue = TRUEBLUE(base.fg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); + fg = &truefg; + } else { + fg = &dc.col[base.fg]; + } + + if (IS_TRUECOL(base.bg)) { + colbg.alpha = 0xffff; + colbg.green = TRUEGREEN(base.bg); + colbg.red = TRUERED(base.bg); + colbg.blue = TRUEBLUE(base.bg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); + bg = &truebg; + } else { + bg = &dc.col[base.bg]; + } + + + if (IS_SET(MODE_REVERSE)) { + if (fg == &dc.col[defaultfg]) { + fg = &dc.col[defaultbg]; + } else { + colfg.red = ~fg->color.red; + colfg.green = ~fg->color.green; + colfg.blue = ~fg->color.blue; + colfg.alpha = fg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, + &revfg); + fg = &revfg; + } + + if (bg == &dc.col[defaultbg]) { + bg = &dc.col[defaultfg]; + } else { + colbg.red = ~bg->color.red; + colbg.green = ~bg->color.green; + colbg.blue = ~bg->color.blue; + colbg.alpha = bg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, + &revbg); + bg = &revbg; + } + } + + if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { + colfg.red = fg->color.red / 2; + colfg.green = fg->color.green / 2; + colfg.blue = fg->color.blue / 2; + colfg.alpha = fg->color.alpha; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); + fg = &revfg; + } + + if (base.mode & ATTR_REVERSE) { + temp = fg; + fg = bg; + bg = temp; + } + + if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) + fg = bg; + + if (base.mode & ATTR_INVISIBLE) + fg = bg; + + if (invertcolors) { + revfg = invertedcolor(fg); + revbg = invertedcolor(bg); + fg = &revfg; + bg = &revbg; + } + + + if (dmode & DRAW_BG) { + /* Intelligent cleaning up of the borders. */ + if (x == 0) { + xclear(0, (y == 0)? 0 : winy, borderpx, + winy + win.ch + + ((winy + win.ch >= borderpx + win.th)? win.h : 0)); + } + if (winx + width >= borderpx + win.tw) { + xclear(winx + width, (y == 0)? 0 : winy, win.w, + ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); + } + if (y == 0) + xclear(winx, 0, winx + width, borderpx); + if (winy + win.ch >= borderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); + + /* Clean up the region we want to draw to. */ + + + /* Set the clip region because Xft is sometimes dirty. */ + r.x = 0; + r.y = 0; + r.height = win.ch; + r.width = width; + XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); + + /* Fill the background */ + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + } + + if (dmode & DRAW_FG) { + if (base.mode & ATTR_BOXDRAW) { + drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len); + } else { + /* Render the glyphs. */ + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + } + + /* Render underline and strikethrough. */ + if (base.mode & ATTR_UNDERLINE) { + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, + width, 1); + } + + if (base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, + width, 1); + } + } + + + /* Reset clip to none. */ + XftDrawSetClip(xw.draw, 0); +} + +void +xdrawglyph(Glyph g, int x, int y) +{ + int numspecs; + XftGlyphFontSpec spec; + + numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); + xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG); +} + +void +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len) +{ + Color drawcol; + + /* remove the old cursor */ + if (selected(ox, oy)) + og.mode ^= ATTR_REVERSE; + /* Redraw the line where cursor was previously. + * It will restore the ligatures broken by the cursor. */ + xdrawline(line, 0, oy, len); + + if (IS_SET(MODE_HIDE) || !IS_SET(MODE_FOCUSED)) + return; + + /* + * Select the right color for the right mode. + */ + g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE|ATTR_BOXDRAW; + + if (IS_SET(MODE_REVERSE)) { + g.mode |= ATTR_REVERSE; + g.bg = defaultfg; + if (selected(cx, cy)) { + drawcol = dc.col[defaultcs]; + g.fg = defaultrcs; + } else { + drawcol = dc.col[defaultrcs]; + g.fg = defaultcs; + } + } else { + if (selected(cx, cy)) { + g.fg = defaultfg; + g.bg = defaultrcs; + } + else { + g.fg = defaultbg; + g.bg = defaultcs; + } + + drawcol = dc.col[g.bg]; + } + + /* draw the new one */ + if (IS_SET(MODE_FOCUSED)) { + switch (win.cursor) { + case 0: /* Blinking block */ + case 1: /* Blinking block (default) */ + if (IS_SET(MODE_BLINK)) + break; + /* FALLTHROUGH */ + case 2: /* Steady block */ + xdrawglyph(g, cx, cy); + break; + case 3: /* Blinking underline */ + if (IS_SET(MODE_BLINK)) + break; + /* FALLTHROUGH */ + case 4: /* Steady underline */ + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - \ + cursorthickness, + win.cw, cursorthickness); + break; + case 5: /* Blinking bar */ + if (IS_SET(MODE_BLINK)) + break; + /* FALLTHROUGH */ + case 6: /* Steady bar */ + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + cursorthickness, win.ch); + break; + case 7: /* Blinking st cursor */ + if (IS_SET(MODE_BLINK)) + break; + /* FALLTHROUGH */ + case 8: /* Steady st cursor */ + g.u = stcursor; + xdrawglyph(g, cx, cy); + break; + } + } else { + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + win.cw - 1, 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + (cx + 1) * win.cw - 1, + borderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - 1, + win.cw, 1); + } +} + +void +xsetenv(void) +{ + char buf[sizeof(long) * 8 + 1]; + + snprintf(buf, sizeof(buf), "%lu", xw.win); + setenv("WINDOWID", buf, 1); +} + +void +xseticontitle(char *p) +{ + XTextProperty prop; + DEFAULT(p, opt_title); + + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop) != Success) + return; + XSetWMIconName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); + XFree(prop.value); +} + +void +xsettitle(char *p) +{ + XTextProperty prop; + DEFAULT(p, opt_title); + + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop) != Success) + return; + XSetWMName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); + XFree(prop.value); +} + +int +xstartdraw(void) +{ + return IS_SET(MODE_VISIBLE); +} + +void +xdrawline(Line line, int x1, int y1, int x2) +{ + int i, x, ox, numspecs; + int numspecs_cached; + Glyph base, new; + XftGlyphFontSpec *specs; + + numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1); + + /* Draw line in 2 passes: background and foreground. This way wide glyphs + won't get truncated (#223) */ + for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) { + specs = xw.specbuf; + numspecs = numspecs_cached; + i = ox = 0; + for (x = x1; x < x2 && i < numspecs; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); + specs += i; + numspecs -= i; + i = 0; + } + if (i == 0) { + ox = x; + base = new; + } + i++; + } + if (i > 0) + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); + } +} + +void +xfinishdraw(void) +{ + + + XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, win.h, 0, 0); + XSetForeground(xw.dpy, dc.gc, + dc.col[IS_SET(MODE_REVERSE)? + defaultfg : defaultbg].pixel); +} + +void +xximspot(int x, int y) +{ + if (xw.ime.xic == NULL) + return; + + xw.ime.spot.x = borderpx + x * win.cw; + xw.ime.spot.y = borderpx + (y + 1) * win.ch; + + XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); +} + +void +expose(XEvent *ev) +{ + redraw(); +} + +void +visibility(XEvent *ev) +{ + XVisibilityEvent *e = &ev->xvisibility; + + MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); +} + +void +unmap(XEvent *ev) +{ + win.mode &= ~MODE_VISIBLE; +} + +void +xsetpointermotion(int set) +{ + if (!set && !xw.pointerisvisible) + return; + MODBIT(xw.attrs.event_mask, set, PointerMotionMask); + XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); +} + +void +xsetmode(int set, unsigned int flags) +{ + int mode = win.mode; + MODBIT(win.mode, set, flags); + if ((flags & MODE_MOUSE) + && xw.pointerisvisible + ) { + if (win.mode & MODE_MOUSE) + XUndefineCursor(xw.dpy, xw.win); + else + XDefineCursor(xw.dpy, xw.win, xw.vpointer); + } + if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) + redraw(); +} + +int +xsetcursor(int cursor) +{ + if (!BETWEEN(cursor, 0, 8)) /* 7-8: st extensions */ + return 1; + win.cursor = cursor; + cursorblinks = win.cursor == 0 || win.cursor == 1 || + win.cursor == 3 || win.cursor == 5 || + win.cursor == 7; + return 0; +} + +void +xseturgency(int add) +{ + XWMHints *h = XGetWMHints(xw.dpy, xw.win); + + MODBIT(h->flags, add, XUrgencyHint); + XSetWMHints(xw.dpy, xw.win, h); + XFree(h); +} + +void +xbell(void) +{ + if (!(IS_SET(MODE_FOCUSED))) + xseturgency(1); + if (bellvolume) + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); +} + +void +focus(XEvent *ev) +{ + XFocusChangeEvent *e = &ev->xfocus; + + + if (e->mode == NotifyGrab) + return; + + if (ev->type == FocusIn) { + if (xw.ime.xic) + XSetICFocus(xw.ime.xic); + win.mode |= MODE_FOCUSED; + xseturgency(0); + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[I", 3, 0); + } else { + if (xw.ime.xic) + XUnsetICFocus(xw.ime.xic); + win.mode &= ~MODE_FOCUSED; + if (IS_SET(MODE_FOCUS)) + ttywrite("\033[O", 3, 0); + } +} + +int +match(uint mask, uint state) +{ + return mask == XK_ANY_MOD || mask == (state & ~ignoremod); +} + +char* +kmap(KeySym k, uint state) +{ + Key *kp; + int i; + + /* Check for mapped keys out of X11 function keys. */ + for (i = 0; i < LEN(mappedkeys); i++) { + if (mappedkeys[i] == k) + break; + } + if (i == LEN(mappedkeys)) { + if ((k & 0xFFFF) < 0xFD00) + return NULL; + } + + for (kp = key; kp < key + LEN(key); kp++) { + if (kp->k != k) + continue; + + if (!match(kp->mask, state)) + continue; + + if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) + continue; + if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) + continue; + + if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) + continue; + + return kp->s; + } + + return NULL; +} + +void +kpress(XEvent *ev) +{ + XKeyEvent *e = &ev->xkey; + KeySym ksym = NoSymbol; + char buf[64], *customkey; + int len, screen; + Rune c; + Status status; + Shortcut *bp; + + if (xw.pointerisvisible) { + XDefineCursor(xw.dpy, xw.win, xw.bpointer); + xsetpointermotion(1); + xw.pointerisvisible = 0; + } + + if (IS_SET(MODE_KBDLOCK)) + return; + + if (xw.ime.xic) { + len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); + if (status == XBufferOverflow) + return; + } else { + len = XLookupString(e, buf, sizeof buf, &ksym, NULL); + } + + screen = tisaltscr() ? S_ALT : S_PRI; + + /* 1. shortcuts */ + for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { + if (ksym == bp->keysym && match(bp->mod, e->state) && + (!bp->screen || bp->screen == screen)) { + bp->func(&(bp->arg)); + return; + } + } + + /* 2. custom keys from config.h */ + if ((customkey = kmap(ksym, e->state))) { + ttywrite(customkey, strlen(customkey), 1); + return; + } + + /* 3. composed string from input method */ + if (len == 0) + return; + if (len == 1 && e->state & Mod1Mask) { + if (IS_SET(MODE_8BIT)) { + if (*buf < 0177) { + c = *buf | 0x80; + len = utf8encode(c, buf); + } + } else { + buf[1] = buf[0]; + buf[0] = '\033'; + len = 2; + } + } + ttywrite(buf, len, 1); +} + + +void +cmessage(XEvent *e) +{ + /* + * See xembed specs + * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html + */ + if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { + if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { + win.mode |= MODE_FOCUSED; + xseturgency(0); + } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { + win.mode &= ~MODE_FOCUSED; + } + } else if (e->xclient.data.l[0] == xw.wmdeletewin) { + ttyhangup(); + exit(0); + } +} + +void +resize(XEvent *e) +{ + + if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) + return; + + + cresize(e->xconfigure.width, e->xconfigure.height); +} + +void +run(void) +{ + XEvent ev; + int w = win.w, h = win.h; + fd_set rfd; + int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; + struct timespec seltv, *tv, now, lastblink, trigger; + double timeout; + + /* Waiting for window mapping */ + do { + XNextEvent(xw.dpy, &ev); + /* + * This XFilterEvent call is required because of XOpenIM. It + * does filter out the key event and some client message for + * the input method too. + */ + if (XFilterEvent(&ev, None)) + continue; + if (ev.type == ConfigureNotify) { + w = ev.xconfigure.width; + h = ev.xconfigure.height; + } + } while (ev.type != MapNotify); + + ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); + cresize(w, h); + + for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { + FD_ZERO(&rfd); + FD_SET(ttyfd, &rfd); + FD_SET(xfd, &rfd); + + if (XPending(xw.dpy)) + timeout = 0; /* existing events might not set xfd */ + + seltv.tv_sec = timeout / 1E3; + seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); + tv = timeout >= 0 ? &seltv : NULL; + + if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { + if (errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + clock_gettime(CLOCK_MONOTONIC, &now); + + if (FD_ISSET(ttyfd, &rfd)) + ttyread(); + + xev = 0; + while (XPending(xw.dpy)) { + xev = 1; + XNextEvent(xw.dpy, &ev); + if (XFilterEvent(&ev, None)) + continue; + if (handler[ev.type]) + (handler[ev.type])(&ev); + } + + /* + * To reduce flicker and tearing, when new content or event + * triggers drawing, we first wait a bit to ensure we got + * everything, and if nothing new arrives - we draw. + * We start with trying to wait minlatency ms. If more content + * arrives sooner, we retry with shorter and shorter periods, + * and eventually draw even without idle after maxlatency ms. + * Typically this results in low latency while interacting, + * maximum latency intervals during `cat huge.txt`, and perfect + * sync with periodic updates from animations/key-repeats/etc. + */ + if (FD_ISSET(ttyfd, &rfd) || xev) + { + if (!drawing) { + trigger = now; + if (IS_SET(MODE_BLINK)) { + win.mode ^= MODE_BLINK; + } + lastblink = now; + drawing = 1; + } + timeout = (maxlatency - TIMEDIFF(now, trigger)) \ + / maxlatency * minlatency; + if (timeout > 0) + continue; /* we have time, try to find idle */ + } + + + /* idle detected or maxlatency exhausted -> draw */ + timeout = -1; + if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) + { + timeout = blinktimeout - TIMEDIFF(now, lastblink); + if (timeout <= 0) { + if (-timeout > blinktimeout) /* start visible */ + win.mode |= MODE_BLINK; + win.mode ^= MODE_BLINK; + tsetdirtattr(ATTR_BLINK); + lastblink = now; + timeout = blinktimeout; + } + } + + draw(); + XFlush(xw.dpy); + drawing = 0; + } +} + +void +usage(void) +{ + die("usage: %s [-aiv] [-c class]" + " [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid]" + " [[-e] command [args ...]]\n" + " %s [-aiv] [-c class]" + " [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid] -l line" + " [stty_args ...]\n", argv0, argv0); +} + +int +main(int argc, char *argv[]) +{ + xw.l = xw.t = 0; + xw.isfixed = False; + xsetcursor(cursorstyle); + + ARGBEGIN { + case 'a': + allowaltscreen = 0; + break; + case 'A': + opt_alpha = EARGF(usage()); + break; + case 'c': + opt_class = EARGF(usage()); + break; + case 'e': + if (argc > 0) + --argc, ++argv; + goto run; + case 'f': + opt_font = EARGF(usage()); + break; + case 'g': + xw.gm = XParseGeometry(EARGF(usage()), + &xw.l, &xw.t, &cols, &rows); + break; + case 'i': + xw.isfixed = 1; + break; + case 'o': + opt_io = EARGF(usage()); + break; + case 'l': + opt_line = EARGF(usage()); + break; + case 'n': + opt_name = EARGF(usage()); + break; + case 't': + case 'T': + opt_title = EARGF(usage()); + break; + case 'w': + opt_embed = EARGF(usage()); + break; + case 'v': + die("%s " VERSION "\n", argv0); + break; + default: + usage(); + } ARGEND; + +run: + if (argc > 0) /* eat all remaining arguments */ + opt_cmd = argv; + + if (!opt_title) + opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; + + setlocale(LC_CTYPE, ""); + XSetLocaleModifiers(""); + signal(SIGUSR1, sigusr1_reload); + if (!(xw.dpy = XOpenDisplay(NULL))) + die("Can't open display\n"); + + config_init(xw.dpy); + cols = MAX(cols, 1); + rows = MAX(rows, 1); + tnew(cols, rows); + xinit(cols, rows); + xsetenv(); + selinit(); + run(); + + return 0; +} diff --git a/.config/x11/xinitrc b/.config/x11/xinitrc new file mode 100755 index 0000000..c9e5bad --- /dev/null +++ b/.config/x11/xinitrc @@ -0,0 +1,18 @@ +#!/bin/sh + +# xinitrc runs automatically when you run startx. + +# There are some small but important commands that need to be run when we start +# the graphical environment. There is a link to this file in ~/.xprofile +# because that file is run automatically if someone uses a display manager +# (login screen) and so they are needed there. To prevent doubling up commands, +# I source them here with the line below. + +if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/x11/xprofile" ]; then + . "${XDG_CONFIG_HOME:-$HOME/.config}/x11/xprofile" +else + . "$HOME/.xprofile" +fi +# Activate dbus variables +# dbus-update-activation-environment --all +ssh-agent dwm diff --git a/.config/x11/xprofile b/.config/x11/xprofile new file mode 100755 index 0000000..47fa4b0 --- /dev/null +++ b/.config/x11/xprofile @@ -0,0 +1,18 @@ +#!/bin/sh + +# This file runs when a DM logs you into a graphical session. +# If you use startx/xinit like a Chad, this file will also be sourced. + +xrandr --dpi 96 # Set DPI. User may want to use a larger number for larger screens. +setbg & # set the background with the `setbg` script +xrdb "${XDG_CONFIG_HOME:-$HOME/.config}"/x11/xresources & +xrdbpid=$! # Uncomment to use Xresources colors/settings on startup + +autostart="mpd dunst unclutter pipewire remapd clipmenud picom" + +for program in $autostart; do + pidof -sx "$program" || "$program" & +done >/dev/null 2>&1 + +# Ensure that xrdb has finished running before moving on to start the WM/DE. +[ -n "$xrdbpid" ] && wait "$xrdbpid" diff --git a/.config/x11/xrdb/color/ashes b/.config/x11/xrdb/color/ashes new file mode 100644 index 0000000..f003a43 --- /dev/null +++ b/.config/x11/xrdb/color/ashes @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #C7CCD1 +*.background: #1C2023 +*.cursorColor: #C7CCD1 +*.color0: #1C2023 +*.color8: #747C84 +*.color1: #C7AE95 +*.color9: #C7C795 +*.color2: #95C7AE +*.color10: #393F45 +*.color3: #AEC795 +*.color11: #565E65 +*.color4: #AE95C7 +*.color12: #ADB3BA +*.color5: #C795AE +*.color13: #DFE2E5 +*.color6: #95AEC7 +*.color14: #C79595 +*.color7: #C7CCD1 +*.color15: #F3F4F5 diff --git a/.config/x11/xrdb/color/catpuccin b/.config/x11/xrdb/color/catpuccin new file mode 100644 index 0000000..dfbaf3c --- /dev/null +++ b/.config/x11/xrdb/color/catpuccin @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.background: #24273A +*.foreground: #CAD3F5 +*.cursorColor: #B8C0E0 +*.color0: #494D64 +*.color8: #5B6078 +*.color1: #ED8796 +*.color9: #ED8796 +*.color2: #A6DA95 +*.color10: #A6DA95 +*.color3: #EED49F +*.color11: #EED49F +*.color4: #8AADF4 +*.color12: #8AADF4 +*.color5: #F5BDE6 +*.color13: #F5BDE6 +*.color6: #8BD5CA +*.color14: #8BD5CA +*.color7: #B8C0E0 +*.color15: #A5ADCB diff --git a/.config/x11/xrdb/color/cellia b/.config/x11/xrdb/color/cellia new file mode 100644 index 0000000..7d03927 --- /dev/null +++ b/.config/x11/xrdb/color/cellia @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #e0e0e0 +*.background: #343c48 +*.cursorColor: #ea80fc +*.color0: #616161 +*.color8: #757575 +*.color1: #f06292 +*.color9: #f48fb1 +*.color2: #c5e1a5 +*.color10: #dcedc8 +*.color3: #ffe0b2 +*.color11: #fff3e0 +*.color4: #80cbc4 +*.color12: #b2dfdb +*.color5: #ce93d8 +*.color13: #e1bee7 +*.color6: #80deea +*.color14: #b2ebf2 +*.color7: #bdbdbd +*.color15: #e0e0e0 diff --git a/.config/x11/xrdb/color/custom-onedark b/.config/x11/xrdb/color/custom-onedark new file mode 100644 index 0000000..f0eb0b0 --- /dev/null +++ b/.config/x11/xrdb/color/custom-onedark @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #c8ccd4 +*.background: #1e222a +*.cursorColor: #abb2bf +*.color0: #282c34 +*.color8: #545862 +*.color1: #e06c75 +*.color9: #e06c75 +*.color2: #98c379 +*.color10: #98c379 +*.color3: #e5c07b +*.color11: #e5c07b +*.color4: #8fa1b3 +*.color12: #8fa1b3 +*.color5: #c678dd +*.color13: #c678dd +*.color6: #56b6c2 +*.color14: #56b6c2 +*.color7: #abb2bf +*.color15: #c8ccd4 diff --git a/.config/x11/xrdb/color/dracula b/.config/x11/xrdb/color/dracula new file mode 100644 index 0000000..e40a1e6 --- /dev/null +++ b/.config/x11/xrdb/color/dracula @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #f8f8f2 +*.background: #2f343f +*.cursorColor: #b48ead +*.color0: #4b5262 +*.color8: #434a5a +*.color1: #ff5555 +*.color9: #cc4444 +*.color2: #50fa7b +*.color10: #41cc64 +*.color3: #f1fa8c +*.color11: #c5cc72 +*.color4: #bd93f9 +*.color12: #9b78cc +*.color5: #ff79c6 +*.color13: #cc619f +*.color6: #8be9fd +*.color14: #70bccc +*.color7: #e5e9f0 +*.color15: #d1d5dc diff --git a/.config/x11/xrdb/color/duskfox b/.config/x11/xrdb/color/duskfox new file mode 100644 index 0000000..85543a8 --- /dev/null +++ b/.config/x11/xrdb/color/duskfox @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*background: #232136 +*foreground: #e0def4 +*.cursorColor: #e0def4 +*color0: #393552 +*color1: #eb6f92 +*color2: #a3be8c +*color3: #f6c177 +*color4: #569fba +*color5: #c4a7e7 +*color6: #9ccfd8 +*color7: #e0def4 +*color8: #47407d +*color9: #f083a2 +*color10: #b1d196 +*color11: #f9cb8c +*color12: #65b1cd +*color13: #ccb1ed +*color14: #a6dae3 +*color15: #e2e0f7 diff --git a/.config/x11/xrdb/color/eighties b/.config/x11/xrdb/color/eighties new file mode 100644 index 0000000..b369b99 --- /dev/null +++ b/.config/x11/xrdb/color/eighties @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #d3d0c8 +*.background: #2d2d2d +*.cursorColor: #d3d0c8 +*.color0: #2d2d2d +*.color8: #747369 +*.color1: #f2777a +*.color9: #f2777a +*.color2: #99cc99 +*.color10: #99cc99 +*.color3: #ffcc66 +*.color11: #ffcc66 +*.color4: #6699cc +*.color12: #6699cc +*.color5: #cc99cc +*.color13: #cc99cc +*.color6: #66cccc +*.color14: #66cccc +*.color7: #d3d0c8 +*.color15: #f2f0ec diff --git a/.config/x11/xrdb/color/evergarden b/.config/x11/xrdb/color/evergarden new file mode 100644 index 0000000..4a82ef9 --- /dev/null +++ b/.config/x11/xrdb/color/evergarden @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #d3c6aa +*.background: #1c2023 +*.cursorColor: #d3c6aa +*.color0: #272e32 +*.color8: #7a8478 +*.color1: #e67e80 +*.color9: #dbbc7f +*.color2: #b2c98f +*.color10: #b2c98f +*.color3: #dbbc7f +*.color11: #dbbc7f +*.color4: #A2C8C3 +*.color12: #A2C8C3 +*.color5: #D699B6 +*.color13: #D699B6 +*.color6: #88c096 +*.color14: #88c096 +*.color7: #9da9a0 +*.color15: #dde1e6 diff --git a/.config/x11/xrdb/color/gruvbox-material b/.config/x11/xrdb/color/gruvbox-material new file mode 100644 index 0000000..66d8735 --- /dev/null +++ b/.config/x11/xrdb/color/gruvbox-material @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.background: #282828 +*.foreground: #d4be98 +*.cursorColor: #abb2bf +*.color0: #232526 +*.color8: #5a5a5a +*.color1: #bf616a +*.color9: #bf616a +*.color2: #a9b665 +*.color10: #a9b665 +*.color3: #d8a657 +*.color11: #e78a4e +*.color4: #6f8faf +*.color12: #7daea3 +*.color5: #d3869b +*.color13: #d3869b +*.color6: #89b482 +*.color14: #89b482 +*.color7: #8FBCBB +*.color15: #d4be98 diff --git a/.config/x11/xrdb/color/gruvchad b/.config/x11/xrdb/color/gruvchad new file mode 100644 index 0000000..060915f --- /dev/null +++ b/.config/x11/xrdb/color/gruvchad @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.background: #1e2122 +*.foreground: #d4be98 +*.cursorColor: #abb2bf +*.color0: #282b2c +*.color8: #32302f +*.color1: #df736d +*.color9: #d1807b +*.color2: #a8b467 +*.color10: #a5b06b +*.color3: #d28e63 +*.color11: #ccb380 +*.color4: #6d8dad +*.color12: #748faa +*.color5: #d0899d +*.color13: #cb8e9e +*.color6: #8dae88 +*.color14: #89b482 +*.color7: #c0b6a4 +*.color15: #c5b89f diff --git a/.config/x11/xrdb/color/kanagawa b/.config/x11/xrdb/color/kanagawa new file mode 100644 index 0000000..5963e01 --- /dev/null +++ b/.config/x11/xrdb/color/kanagawa @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #dcd7ba +*.background: #1f1f28 +*.cursorColor: #dcd7ba +*.color0: #090618 +*.color8: #727169 +*.color1: #c34043 +*.color9: #e82424 +*.color2: #76946a +*.color10: #98bb6c +*.color3: #c0a36e +*.color11: #e6c384 +*.color4: #7e9cd8 +*.color12: #7fb4ca +*.color5: #957fb8 +*.color13: #938aa9 +*.color6: #6a9589 +*.color14: #7aa89f +*.color7: #c8c093 +*.color15: #dcd7ba diff --git a/.config/x11/xrdb/color/lighthaus b/.config/x11/xrdb/color/lighthaus new file mode 100644 index 0000000..6d0e6d6 --- /dev/null +++ b/.config/x11/xrdb/color/lighthaus @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.background: #161616 +*.foreground: #FFEE79 +*.cursorColor: #FFFF00 +*.color0: #18191E +*.color8: #505050 +*.color1: #cc6666 +*.color9: #cc4444 +*.color2: #44B273 +*.color10: #50C16E +*.color3: #f0c674 +*.color11: #ffcc66 +*.color4: #1D918B +*.color12: #47A8A1 +*.color5: #D16BB7 +*.color13: #D68EB2 +*.color6: #00BFA4 +*.color14: #5AD1AA +*.color7: #CCCCCC +*.color15: #FFFADE diff --git a/.config/x11/xrdb/color/molokai b/.config/x11/xrdb/color/molokai new file mode 100644 index 0000000..cedfb92 --- /dev/null +++ b/.config/x11/xrdb/color/molokai @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.background: #101010 +*.foreground: #d0d0d0 +*.cursorColor: #d0d0d0 +*.color0: #101010 +*.color8: #303030 +*.color1: #960050 +*.color9: #ff0090 +*.color2: #66aa11 +*.color10: #80ff00 +*.color3: #7e40a5 +*.color11: #bb88dd +*.color4: #c47f2c +*.color12: #ffba68 +*.color5: #30309b +*.color13: #5f5fee +*.color6: #3579a8 +*.color14: #4eb4fa +*.color7: #9999aa +*.color15: #d0d0d0 diff --git a/.config/x11/xrdb/color/monokai b/.config/x11/xrdb/color/monokai new file mode 100644 index 0000000..66a27e5 --- /dev/null +++ b/.config/x11/xrdb/color/monokai @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #f8f8f2 +*.background: #272822 +*.cursorColor: #f8f8f2 +*.color0: #272822 +*.color8: #75715e +*.color1: #f92672 +*.color9: #f92672 +*.color2: #a6e22e +*.color10: #a6e22e +*.color3: #f4bf75 +*.color11: #f4bf75 +*.color4: #66d9ef +*.color12: #66d9ef +*.color5: #ae81ff +*.color13: #ae81ff +*.color6: #a1efe4 +*.color14: #a1efe4 +*.color7: #f8f8f2 +*.color15: #f9f8f5 diff --git a/.config/x11/xrdb/color/monokai-pro b/.config/x11/xrdb/color/monokai-pro new file mode 100644 index 0000000..4115ec1 --- /dev/null +++ b/.config/x11/xrdb/color/monokai-pro @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #fcfcfa +*.background: #2d2a2e +*.cursorColor: #f8f8f2 +*.color0: #403e41 +*.color8: #727072 +*.color1: #FF6188 +*.color9: #FF6188 +*.color2: #A9DC76 +*.color10: #A9DC76 +*.color3: #FFD866 +*.color11: #FFD866 +*.color4: #ff8866 +*.color12: #ff8866 +*.color5: #AB9DF2 +*.color13: #AB9DF2 +*.color6: #78DCE8 +*.color14: #78DCE8 +*.color7: #fcfcfa +*.color15: #fcfcfa diff --git a/.config/x11/xrdb/color/nord b/.config/x11/xrdb/color/nord new file mode 100644 index 0000000..a5a630f --- /dev/null +++ b/.config/x11/xrdb/color/nord @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #d8dee8 +*.background: #2f343f +*.cursorColor: #b48ead +*.color0: #4b5262 +*.color8: #434a5a +*.color1: #bf616a +*.color9: #b3555e +*.color2: #a3be8c +*.color10: #93ae7c +*.color3: #ebcb8b +*.color11: #dbbb7b +*.color4: #81a1c1 +*.color12: #7191b1 +*.color5: #b48ead +*.color13: #a6809f +*.color6: #89d0bA +*.color14: #7dbba8 +*.color7: #e5e9f0 +*.color15: #d1d5dc diff --git a/.config/x11/xrdb/color/nordfox b/.config/x11/xrdb/color/nordfox new file mode 100644 index 0000000..55d458f --- /dev/null +++ b/.config/x11/xrdb/color/nordfox @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*background: #2e3440 +*foreground: #cdcecf +*.cursorColor: #cdcecf +*color0: #3b4252 +*color1: #bf616a +*color2: #a3be8c +*color3: #ebcb8b +*color4: #81a1c1 +*color5: #b48ead +*color6: #88c0d0 +*color7: #e5e9f0 +*color8: #465780 +*color9: #d06f79 +*color10: #b1d196 +*color11: #f0d399 +*color12: #8cafd2 +*color13: #c895bf +*color14: #93ccdc +*color15: #e7ecf4 diff --git a/.config/x11/xrdb/color/ocean b/.config/x11/xrdb/color/ocean new file mode 100644 index 0000000..8f0c7bb --- /dev/null +++ b/.config/x11/xrdb/color/ocean @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #c0c5ce +*.background: #2b303b +*.cursorColor: #c0c5ce +*.color0: #2b303b +*.color8: #65737e +*.color1: #bf616a +*.color9: #bf616a +*.color2: #a3be8c +*.color10: #a3be8c +*.color3: #ebcb8b +*.color11: #ebcb8b +*.color4: #8fa1b3 +*.color12: #8fa1b3 +*.color5: #b48ead +*.color13: #b48ead +*.color6: #96b5b4 +*.color14: #96b5b4 +*.color7: #c0c5ce +*.color15: #eff1f5 diff --git a/.config/x11/xrdb/color/oxocarbon b/.config/x11/xrdb/color/oxocarbon new file mode 100644 index 0000000..7d09d68 --- /dev/null +++ b/.config/x11/xrdb/color/oxocarbon @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #dde1e6 +*.background: #161616 +*.cursorColor: #dde1e6 +*.color0: #161616 +*.color8: #37474f +*.color1: #ee5396 +*.color9: #ee5396 +*.color2: #42be65 +*.color10: #42be65 +*.color3: #ffab91 +*.color11: #ffab91 +*.color4: #be95ff +*.color12: #be95ff +*.color5: #78a9ff +*.color13: #33b1ff +*.color6: #3ddbd9 +*.color14: #08bdba +*.color7: #f2f4f8 +*.color15: #a2a9b0 diff --git a/.config/x11/xrdb/color/rhxyn b/.config/x11/xrdb/color/rhxyn new file mode 100644 index 0000000..2e578b1 --- /dev/null +++ b/.config/x11/xrdb/color/rhxyn @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #edeff0 +*.background: #0c0e0f +*.cursorColor: #abb2bf +*.color0: #4c566a +*.color8: #999997 +*.color1: #df5b61 +*.color9: #e8646a +*.color2: #78b892 +*.color10: #81c19b +*.color3: #de8f78 +*.color11: #e79881 +*.color4: #6791c9 +*.color12: #709ad2 +*.color5: #bc83e3 +*.color13: #c58cec +*.color6: #67afc1 +*.color14: #70b8ca +*.color7: #e4e6e7 +*.color15: #f2f4f5 diff --git a/.config/x11/xrdb/color/rosepine b/.config/x11/xrdb/color/rosepine new file mode 100644 index 0000000..366aec3 --- /dev/null +++ b/.config/x11/xrdb/color/rosepine @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #e0def4 +*.background: #191724 +*.cursorColor: #e0def4 +*.color0: #2a273f +*.color8: #393552 +*.color1: #eb6f92 +*.color9: #eb6f92 +*.color2: #f6c177 +*.color10: #f6c177 +*.color3: #ea9a97 +*.color11: #ea9a97 +*.color4: #3e8fb0 +*.color12: #3e8fb0 +*.color5: #c4a7e7 +*.color13: #c4a7e7 +*.color6: #9ccfd8 +*.color14: #9ccfd8 +*.color7: #6e6a86 +*.color15: #908caa diff --git a/.config/x11/xrdb/color/terafox b/.config/x11/xrdb/color/terafox new file mode 100644 index 0000000..80eafab --- /dev/null +++ b/.config/x11/xrdb/color/terafox @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*background: #152528 +*foreground: #e6eaea +*.cursorColor: #e6eaea +*color0: #2f3239 +*color1: #e85c51 +*color2: #7aa4a1 +*color3: #fda47f +*color4: #5a93aa +*color5: #ad5c7c +*color6: #a1cdd8 +*color7: #ebebeb +*color8: #4e5157 +*color9: #eb746b +*color10: #8eb2af +*color11: #fdb292 +*color12: #73a3b7 +*color13: #b97490 +*color14: #afd4de +*color15: #eeeeee diff --git a/.config/x11/xrdb/color/tokyodark b/.config/x11/xrdb/color/tokyodark new file mode 100644 index 0000000..2fde5bc --- /dev/null +++ b/.config/x11/xrdb/color/tokyodark @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.background: #11121D +*.foreground: #A0A8CD +*.cursorColor: #A0A8CD +*.color0: #1d1e29 +*.color8: #4e4f5a +*.color1: #ee6d85 +*.color9: #f3627a +*.color2: #98c379 +*.color10: #98c379 +*.color3: #dfae67 +*.color11: #dfae67 +*.color4: #7199ee +*.color12: #7199ee +*.color5: #a485dd +*.color13: #a485dd +*.color6: #38a89d +*.color14: #38a89d +*.color7: #90A8CD +*.color15: #a2b9c6 diff --git a/.config/x11/xrdb/color/tokyonight b/.config/x11/xrdb/color/tokyonight new file mode 100644 index 0000000..411f19e --- /dev/null +++ b/.config/x11/xrdb/color/tokyonight @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*background: #16161e +*foreground: #c0caf5 +*.cursorColor: #c0caf5 +*color0: #15161e +*color8: #414868 +*.color1: #f7768e +*.color9: #f7768e +*.color2: #9ece6a +*.color10: #9ece6a +*.color3: #e0af68 +*.color11: #e0af68 +*.color4: #7aa2f7 +*.color12: #7aa2f7 +*.color5: #bb9af7 +*.color13: #bb9af7 +*.color6: #7dcfff +*.color14: #7dcfff +*.color7: #a9b1d6 +*.color15: #c0caf5 diff --git a/.config/x11/xrdb/color/tomorrow b/.config/x11/xrdb/color/tomorrow new file mode 100644 index 0000000..72fecc3 --- /dev/null +++ b/.config/x11/xrdb/color/tomorrow @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #c5c8c6 +*.background: #1d1f21 +*.cursorColor: #c5c8c6 +*.color0: #1d1f21 +*.color8: #969896 +*.color1: #cc6666 +*.color9: #cc6666 +*.color2: #b5bd68 +*.color10: #b5bd68 +*.color3: #f0c674 +*.color11: #f0c674 +*.color4: #81a2be +*.color12: #81a2be +*.color5: #b294bb +*.color13: #b294bb +*.color6: #8abeb7 +*.color14: #8abeb7 +*.color7: #c5c8c6 +*.color15: #ffffff diff --git a/.config/x11/xrdb/color/violla b/.config/x11/xrdb/color/violla new file mode 100644 index 0000000..1f76424 --- /dev/null +++ b/.config/x11/xrdb/color/violla @@ -0,0 +1,21 @@ +!! vim: filetype=xdefaults + +*.foreground: #dee3e0 +*.background: #343c48 +*.cursorColor: #ce93d8 +*.color0: #525d70 +*.color8: #59657a +*.color1: #ba5e50 +*.color9: #c46455 +*.color2: #7cb342 +*.color10: #8bc34a +*.color3: #ffb74d +*.color11: #ffc55a +*.color4: #528580 +*.color12: #5a918c +*.color5: #b39ddb +*.color13: #bca5e6 +*.color6: #90caf9 +*.color14: #93d1ff +*.color7: #bdbdbd +*.color15: #e0e0e0 diff --git a/.config/x11/xrdb/dmenu/banana b/.config/x11/xrdb/dmenu/banana new file mode 100644 index 0000000..2345961 --- /dev/null +++ b/.config/x11/xrdb/dmenu/banana @@ -0,0 +1,7 @@ +! vim: filetype=xdefaults + +dmenu.background: #1e222a +dmenu.foreground: #c8ccd4 +dmenu.selbackground: #e5c07b +dmenu.selforeground: #1e222a +dmenu.bordercolor: #e5c07b diff --git a/.config/x11/xrdb/dmenu/evergarden b/.config/x11/xrdb/dmenu/evergarden new file mode 100644 index 0000000..33b6cd4 --- /dev/null +++ b/.config/x11/xrdb/dmenu/evergarden @@ -0,0 +1,7 @@ +!! vim: filetype=xdefaults + +dmenu.foreground: #d3c6aa +dmenu.background: #1c2023 +dmenu.selforeground: #1c2023 +dmenu.selbackground: #88c096 +dmenu.bordercolor: #88c096 diff --git a/.config/x11/xrdb/dmenu/nord b/.config/x11/xrdb/dmenu/nord new file mode 100644 index 0000000..f2a4325 --- /dev/null +++ b/.config/x11/xrdb/dmenu/nord @@ -0,0 +1,7 @@ +!! vim: filetype=xdefaults + +dmenu.foreground: #d8dee8 +dmenu.background: #2f343f +dmenu.selforeground: #d8dee8 +dmenu.selbackground: #bf616a +dmenu.bordercolor: #bf616a diff --git a/.config/x11/xrdb/dmenu/oxocarbon b/.config/x11/xrdb/dmenu/oxocarbon new file mode 100644 index 0000000..2206514 --- /dev/null +++ b/.config/x11/xrdb/dmenu/oxocarbon @@ -0,0 +1,7 @@ +!! vim: filetype=xdefaults + +dmenu.foreground: #dde1e6 +dmenu.background: #161616 +dmenu.selforeground: #161616 +dmenu.selbackground: #be95ff +dmenu.bordercolor: #be95ff diff --git a/.config/x11/xrdb/dmenu/tokyo b/.config/x11/xrdb/dmenu/tokyo new file mode 100644 index 0000000..9aea480 --- /dev/null +++ b/.config/x11/xrdb/dmenu/tokyo @@ -0,0 +1,7 @@ +!! vim: filetype=xdefaults + +dmenu.foreground: #c0caf5 +dmenu.background: #24283b +dmenu.selforeground: #24283b +dmenu.selbackground: #e0af68 +dmenu.bordercolor: #e0af68 diff --git a/.config/x11/xrdb/dmenu/tokyodark b/.config/x11/xrdb/dmenu/tokyodark new file mode 100644 index 0000000..1e4c8ef --- /dev/null +++ b/.config/x11/xrdb/dmenu/tokyodark @@ -0,0 +1,7 @@ +!! vim: filetype=xdefaults + +dmenu.foreground: #a0a8cd +dmenu.background: #11121D +dmenu.selforeground: #11121D +dmenu.selbackground: #dfae67 +dmenu.bordercolor: #dfae67 diff --git a/.config/x11/xrdb/dmenu/tokyonight b/.config/x11/xrdb/dmenu/tokyonight new file mode 100644 index 0000000..8d0952a --- /dev/null +++ b/.config/x11/xrdb/dmenu/tokyonight @@ -0,0 +1,7 @@ +!! vim: filetype=xdefaults + +dmenu.foreground: #c0caf5 +dmenu.background: #1a1b26 +dmenu.selforeground: #1a1b26 +dmenu.selbackground: #7aa2f7 +dmenu.bordercolor: #7aa2f7 diff --git a/.config/x11/xrdb/dmenu/tomorrow b/.config/x11/xrdb/dmenu/tomorrow new file mode 100644 index 0000000..892400a --- /dev/null +++ b/.config/x11/xrdb/dmenu/tomorrow @@ -0,0 +1,7 @@ +!! vim: filetype=xdefaults + +dmenu.foreground: #c5c8c6 +dmenu.background: #1d1f21 +dmenu.selforeground: #c5c8c6 +dmenu.selbackground: #cc6666 +dmenu.bordercolor: #cc6666 diff --git a/.config/x11/xrdb/dwm/evergarden b/.config/x11/xrdb/dwm/evergarden new file mode 100644 index 0000000..ef21f61 --- /dev/null +++ b/.config/x11/xrdb/dwm/evergarden @@ -0,0 +1,15 @@ +! vim: filetype=xdefaults + +dwm.normbordercolor: #262626 +dwm.normbgcolor: #1c2023 +dwm.normfgcolor: #a2a9b0 + +dwm.selbordercolor: #666666 +dwm.selbgcolor: #262626 +dwm.selfgcolor: #a2a9b0 + +dwm.tagsnormfgcolor: #a2a9b0 +dwm.tagsnormbgcolor: #1c2023 + +dwm.tagsselfgcolor: #eeeeee +dwm.tagsselbgcolor: #343E44 diff --git a/.config/x11/xrdb/dwm/oxocarbon b/.config/x11/xrdb/dwm/oxocarbon new file mode 100644 index 0000000..4c2ab42 --- /dev/null +++ b/.config/x11/xrdb/dwm/oxocarbon @@ -0,0 +1,15 @@ +! vim: filetype=xdefaults + +dwm.normbordercolor: #262626 +dwm.normbgcolor: #161616 +dwm.normfgcolor: #a2a9b0 + +dwm.selbordercolor: #666666 +dwm.selbgcolor: #262626 +dwm.selfgcolor: #a2a9b0 + +dwm.tagsnormfgcolor: #a2a9b0 +dwm.tagsnormbgcolor: #161616 + +dwm.tagsselfgcolor: #eeeeee +dwm.tagsselbgcolor: #303030 diff --git a/.config/x11/xrdb/dwm/tokyonight b/.config/x11/xrdb/dwm/tokyonight new file mode 100644 index 0000000..c2d1a0a --- /dev/null +++ b/.config/x11/xrdb/dwm/tokyonight @@ -0,0 +1,15 @@ +! vim: filetype=xdefaults + +dwm.normbordercolor: #15161e +dwm.normbgcolor: #1a1b26 +dwm.normfgcolor: #c0caf5 + +dwm.selbordercolor: #414868 +dwm.selbgcolor: #15161e +dwm.selfgcolor: #c0caf5 + +dwm.tagsnormfgcolor: #c0caf5 +dwm.tagsnormbgcolor: #1a1b26 + +dwm.tagsselfgcolor: #c0caf5 +dwm.tagsselbgcolor: #343E44 diff --git a/.config/x11/xresources b/.config/x11/xresources new file mode 100644 index 0000000..54db41c --- /dev/null +++ b/.config/x11/xresources @@ -0,0 +1,43 @@ +! vim: filetype=xdefaults + +! ▄ ▄ +! ▄▀▄ + +Xcursor.theme: Bibata-Modern-Ice +Xcursor.size: 24 + +! Choices: tokyonight, rosepine, cellia, custom-onedark, ashes +! dracula, eighties, lighthaus, violla,, gruvchad, evergarden, +! gruvbox-material, monokai-pro, nord, ocean, oxocarbon, tomorrow, +! catpuccin, kanagawa, tokyodark, terafox, duskfox, nordfox, rhxyn +#include "xrdb/color/tokyonight" + +! ▄█▀▀█▀ + +! st.font: Berkeley Mono:style=Regular:size=11 +! st.font: MonoLisa:style:Regular:size=10 +! st.font: CaskaydiaCove Nerd Font:style:Regular:size=10 +! st.font: Iosevka NF:style:Regular:size=11 +! st.font: MesloLGS Nerd Font:style:Regular:size=10 +! st.font: Comic Code:style:Regular:size=11 +! st.font: Source Code Pro:style:Regular:size=11 +st.font: JetBrainsMono Nerd Font:style:Medium:size=10 +st.borderpx: 10 +st.alpha: 1.0 +st.tabspaces: 2 +st.cwscale: 1.0 +st.chscale: 1.0 + +! █ +! ███▀█▀██▄█▀█▄█ + +! Choices: tokyo, tokyodark, oxocarbon, nord, tomorrow, banana +#include "xrdb/dmenu/tokyonight" +dmenu.font: JetBrainsMono Nerd Font:style:medium:size=10 +! dmenu.font: CaskaydiaCove Nerd Font:style:Regular:size=10 + +! █ +! ███▄█▄█▀█▀█ + +! Choices: oxocarbon +#include "xrdb/dwm/tokyonight" diff --git a/.config/yazi/flavors/tokyo-night.yazi/LICENSE b/.config/yazi/flavors/tokyo-night.yazi/LICENSE new file mode 100644 index 0000000..9a5124e --- /dev/null +++ b/.config/yazi/flavors/tokyo-night.yazi/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 - sxyazi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/.config/yazi/flavors/tokyo-night.yazi/LICENSE-tmtheme b/.config/yazi/flavors/tokyo-night.yazi/LICENSE-tmtheme new file mode 100644 index 0000000..44b4479 --- /dev/null +++ b/.config/yazi/flavors/tokyo-night.yazi/LICENSE-tmtheme @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Himanshu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/.config/yazi/flavors/tokyo-night.yazi/README.md b/.config/yazi/flavors/tokyo-night.yazi/README.md new file mode 100644 index 0000000..ec2a2e6 --- /dev/null +++ b/.config/yazi/flavors/tokyo-night.yazi/README.md @@ -0,0 +1,37 @@ +
+ Yazi logo +
+ +

+ Tokyo Night Flavor for Yazi +

+ +## 👀 Preview + + + +## 🎨 Installation + +```bash +# Linux/macOS +git clone https://github.com/BennyOe/tokyo-night.yazi.git ~/.config/yazi/flavors/tokyo-night.yazi + +# Windows +git clone https://github.com/BennyOe/tokyo-night.yazi.git %AppData%\yazi\config\flavors\tokyo-night.yazi +``` + +## ⚙️ Usage + +Add the these lines to your `theme.toml` configuration file to use it: + + +```toml +[flavor] +use = "tokyo-night" +``` + +## 📜 License + +The flavor is MIT-licensed, and the included tmTheme is also MIT-licensed. + +Check the [LICENSE](LICENSE) and [LICENSE-tmtheme](LICENSE-tmtheme) file for more details. diff --git a/.config/yazi/flavors/tokyo-night.yazi/flavor.toml b/.config/yazi/flavors/tokyo-night.yazi/flavor.toml new file mode 100644 index 0000000..1b8bd69 --- /dev/null +++ b/.config/yazi/flavors/tokyo-night.yazi/flavor.toml @@ -0,0 +1,167 @@ +# : Manager {{{ + +[manager] +cwd = { fg = "#7aa2f7" } # Blue + +# Hovered +hovered = { reversed = true } +preview_hovered = { underline = true } + +# Find +find_keyword = { fg = "#f7768e", bold = true, italic = true, underline = true } # Red +find_position = { fg = "#bb9af7", bg = "reset", bold = true, italic = true } # Magenta + +# Marker +marker_copied = { fg = "#9ece6a", bg = "#9ece6a" } # Green +marker_cut = { fg = "#e0af68", bg = "#f7768e" } # Red +marker_marked = { fg = "#7aa2f7", bg = "#7dcfff" } # Cyan +marker_selected = { fg = "#e0af68", bg = "#e0af68" } # Yellow + +# Tab +tab_active = { bg = "#282C34", fg = "#7aa2f7" } # Darkened background, Blue text +tab_inactive = {} +tab_width = 1 + +# Count +count_copied = { fg = "#414868", bg = "#9ece6a" } # Darkened black on Green +count_cut = { fg = "#414868", bg = "#e0af68" } # Darkened black on Yellow +count_selected = { fg = "#414868", bg = "#7aa2f7" } # Darkened black on Blue + +# Border +border_symbol = "│" +border_style = { fg = "#414868" } # Darkened black + +# : }}} + + +# : Status {{{ + +[status] +separator_open = "" +separator_close = "" +separator_style = { fg = "#7aa2f7", bg = "#414868" } # Blue on Darkened black + +# Mode +mode_normal = { fg = "#414868", bg = "#7aa2f7", bold = true } # Darkened black on Blue +mode_select = { fg = "#414868", bg = "#9ece6a", bold = true } # Darkened black on Green +mode_unset = { fg = "#414868", bg = "#bb9af7", bold = true } # Darkened black on Magenta + +# Progress +progress_label = { fg = "#a9b1d6", bold = true } # White +progress_normal = { fg = "#7aa2f7", bg = "#414868" } # Blue on Darkened black +progress_error = { fg = "#f7768e", bg = "#414868" } # Red on Darkened black + +# Permissions +permissions_t = { fg = "#7aa2f7" } # Blue +permissions_r = { fg = "#f7768e" } # Red +permissions_w = { fg = "#e0af68" } # Yellow +permissions_x = { fg = "#9ece6a" } # Green +permissions_s = { fg = "#bb9af7" } # Magenta + +# : }}} + + +# : Select {{{ + +[select] +border = { fg = "#7aa2f7" } # Blue +active = { fg = "#bb9af7", bold = true } # Magenta +inactive = {} + +# : }}} + + +# : Input {{{ + +[input] +border = { fg = "#7aa2f7" } # Blue +title = {} +value = {} +selected = { reversed = true } + +# : }}} + + +# : Completion {{{ + +[completion] +border = { fg = "#7aa2f7" } # Blue + +# : }}} + + +# : Tasks {{{ + +[tasks] +border = { fg = "#7aa2f7" } # Blue +title = {} +hovered = { fg = "#bb9af7", underline = true } # Magenta + +# : }}} +# : Which {{{ + +[which] +mask = { bg = "#414868" } # Darkened black +cand = { fg = "#9ece6a" } # Green +rest = { fg = "#a9b1d6" } # White +desc = { fg = "#bb9af7" } # Magenta +separator = "  " +separator_style = { fg = "#626880" } # Darkened gray + +# : }}} + + +# : Help {{{ + +[help] +on = { fg = "#9ece6a" } # Green +run = { fg = "#bb9af7" } # Magenta +hovered = { reversed = true, bold = true } +footer = { fg = "#a9b1d6", bg = "#c6d0f5" } # White on Light gray + +# : }}} + + +# : Notify {{{ + +[notify] +title_info = { fg = "#9ece6a" } # Green +title_warn = { fg = "#f7768e" } # Red +title_error = { fg = "#e0af68" } # Yellow + +# : }}} + + +# : File-specific styles {{{ + +[filetype] + +rules = [ + # Images + { mime = "image/*", fg = "#e0af68" }, # Yellow + + # Media + { mime = "video/*", fg = "#f7768e" }, # Red + { mime = "audio/*", fg = "#f7768e" }, # Red + + # Archives + { mime = "application/zip", fg = "#bb9af7" }, # Magenta + { mime = "application/x-tar", fg = "#bb9af7" }, # Magenta + { mime = "application/x-bzip*", fg = "#bb9af7" }, # Magenta + { mime = "application/x-bzip2", fg = "#bb9af7" }, # Magenta + { mime = "application/x-7z-compressed", fg = "#bb9af7" }, # Magenta + { mime = "application/x-rar", fg = "#bb9af7" }, # Magenta + { mime = "application/x-xz", fg = "#bb9af7" }, # Magenta + + # Documents + { mime = "application/doc", fg = "#9ece6a" }, # Green + { mime = "application/pdf", fg = "#9ece6a" }, # Green + { mime = "application/rtf", fg = "#9ece6a" }, # Green + { mime = "application/vnd.*", fg = "#9ece6a" }, # Green + + # Fallback + { name = "*", fg = "#c6d0f5" }, # Light gray + { name = "*/", fg = "#7aa2f7" } # Blue +] + +# : }}} diff --git a/.config/yazi/flavors/tokyo-night.yazi/tmtheme.xml b/.config/yazi/flavors/tokyo-night.yazi/tmtheme.xml new file mode 100644 index 0000000..21d2163 --- /dev/null +++ b/.config/yazi/flavors/tokyo-night.yazi/tmtheme.xml @@ -0,0 +1,1329 @@ + + + + + author + Kristi Russell (http://github.com/enkia) + colorSpaceName + sRGB + name + Enki-Tokyo-Night + semanticClass + enki.theme.tokyo + settings + + + settings + + activeGuide + #363b54 + background + #1d1f29 + caret + #DBC08A + findHighlight + #ffa300 + findHighlightForeground + #000000 + foreground + #AFBAD4ff + guide + #4f4f5e40 + gutterForeground + #3b415caa + inactiveSelection + #282833 + invisibles + #4f4f5e + lineHighlight + #00000030 + phantomCss + <![CDATA[ html { position: relative; } ]]> + popupCss + <![CDATA[ html { color: #B376B3; background-color: #2b2d3a; padding: 10px; } a { color: #6189BB; line-height: 1.2; text-decoration: none; } .error, .deleted { color: #50B4DC; } .success, .inserted { color: #9DBA72; } .warning, .modified { color: #ffa300; } ]]> + selection + #9D599D40 + selectionBorder + #9D599D + shadow + #00000010 + stackGuide + #4f4f5e60 + tagsOptions + underline + + + + name + Italics - Comments, Storage, Keyword Flow, Vue attributes, Decorators + scope + comment, meta.var.expr storage.type, keyword.control.flow, meta.directive.vue punctuation.separator.key-value.html, meta.directive.vue entity.other.attribute-name.html, tag.decorator.js entity.name.tag.js, tag.decorator.js punctuation.definition.tag.js, storage.modifier + settings + + fontStyle + italic + + + + name + Comment + scope + comment, comment.block.documentation, punctuation.definition.comment + settings + + foreground + #444b6a + + + + name + Comment Doc + scope + comment.block.documentation variable, comment.block.documentation storage, comment.block.documentation punctuation, comment.block.documentation keyword, comment.block.documentation support, comment.block.documentation markup, comment.block.documentation markup.inline.raw.string.markdown, keyword.other.phpdoc.php + settings + + foreground + #7982a9 + + + + name + Number, Boolean, Undefined, Null + scope + variable.other.constant, punctuation.definition.constant, constant.language, constant.numeric, support.constant + settings + + foreground + #ff9e64 + + + + name + String, Symbols, Markup Heading + scope + string, constant.other.symbol, constant.other.key, markup.heading, meta.attribute-selector + settings + + fontStyle + + foreground + #9ece6a + + + + name + Colors + scope + constant.other.color, constant.other.color.rgb-value.hex punctuation.definition.constant + settings + + foreground + #9aa5ce + + + + name + Invalid + scope + invalid, invalid.illegal + settings + + foreground + #ff5370 + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + foreground + #bb9af7 + + + + name + Storage Type + scope + storage.type + settings + + foreground + #bb9af7 + + + + name + Storage - modifier, var, const, let + scope + meta.var.expr storage.type, storage.modifier + settings + + foreground + #9d7cd8 + + + + name + Interpolation + scope + punctuation.definition.template-expression, punctuation.section.embedded + settings + + foreground + #7dcfff + + + + name + Spread + scope + keyword.operator.spread, keyword.operator.rest + settings + + fontStyle + bold + foreground + #f7768e + + + + name + Operator, Misc + scope + keyword.operator, keyword.control.as, keyword.other, keyword.operator.bitwise.shift, punctuation, punctuation.definition.constant.markdown, punctuation.definition.string, punctuation.support.type.property-name, text.html.vue-html meta.tag, punctuation.definition.keyword, punctuation.terminator.rule, punctuation.definition.entity, punctuation.definition.tag, punctuation.separator.inheritance.php, punctuation.definition.tag.html, keyword.other.template, keyword.other.substitution, entity.name.operator, text.html.vue meta.tag.block.any.html, text.html.vue meta.tag.inline.any.html, text.html.vue meta.tag.other.html, text.html.twig meta.tag.inline.any.html, text.html.twig meta.tag.block.any.html, text.html.twig meta.tag.structure.any.html, text.html.twig meta.tag.any.html + settings + + foreground + #89ddff + + + + name + Import, Export, From, Default + scope + keyword.control.import, keyword.control.export, keyword.control.from, keyword.control.default, meta.import keyword.other + settings + + foreground + #7dcfff + + + + name + Keyword + scope + keyword, keyword.control, keyword.other.important + settings + + foreground + #bb9af7 + + + + name + Keyword SQL + scope + keyword.other.DML + settings + + foreground + #7dcfff + + + + name + Keyword Operator Logical, Arrow, Ternary, Comparison + scope + keyword.operator.logical, storage.type.function, keyword.operator.bitwise, keyword.operator.ternary, keyword.operator.comparison, keyword.operator.relational, keyword.operator.or.regexp + settings + + foreground + #bb9af7 + + + + name + Tag + scope + entity.name.tag, entity.name.tag support.class.component, meta.tag + settings + + foreground + #f7768e + + + + name + Tag Punctuation + scope + punctuation.definition.tag, punctuation.definition.tag.html, punctuation.definition.tag.begin.html, punctuation.definition.tag.end.html + settings + + foreground + #ba3c97 + + + + name + Blade + scope + keyword.blade, entity.name.function.blade + settings + + foreground + #7aa2f7 + + + + name + PHP - Embedded Tag + scope + punctuation.section.embedded.begin.php, punctuation.section.embedded.end.php + settings + + foreground + #0db9d7 + + + + name + Smarty - Twig tag - Blade + scope + punctuation.definition.variable.smarty, punctuation.section.embedded.begin.smarty, punctuation.section.embedded.end.smarty, meta.tag.template.value.twig, punctuation.section.tag.twig, meta.tag.expression.twig, punctuation.definition.tag.expression.twig, punctuation.definition.tag.output.twig, variable.parameter.smarty + settings + + foreground + #7DCFFF + + + + name + Smarty - Twig variable - function + scope + variable.other.property.twig, support.function.twig, meta.function-call.twig, keyword.control.twig, keyword.control.smarty, keyword.operator.other.twig, keyword.operator.comparison.twig, support.function.functions.twig, support.function.functions.twig, keyword.operator.assignment.twig, support.function.filters.twig, support.function.built-in.smarty, keyword.operator.smarty, text.blade text.html.blade custom.compiler.blade.php punctuation.section.embedded.php entity.name.tag.block.any.html, text.blade text.html.blade custom.compiler.blade.php punctuation.section.embedded.php constant.other.inline-data.html, text.blade text.html.blade custom.compiler.blade.php support.function constant.other.inline-data.html + settings + + foreground + #0db9d7 + + + + name + Globals - PHP Constants etc + scope + constant.other.php, variable.other.global.safer, variable.other.global.safer punctuation.definition.variable, variable.other.global, variable.other.global punctuation.definition.variable, constant.other + settings + + foreground + #e0af68 + + + + name + Variables + scope + variable, support.variable, string constant.other.placeholder + settings + + foreground + #c0caf5 + + + + name + Object Variable + scope + variable.other.object, support.module.node + settings + + foreground + #c0caf5 + + + + name + Object Key + scope + meta.object-literal.key, meta.group.braces.curly constant.other.object.key.js string.unquoted.label.js, string.alias.graphql, string.unquoted.graphql, string.unquoted.alias.graphql, meta.field.declaration.ts variable.object.property + settings + + foreground + #73daca + + + + name + Object Property + scope + variable.other.property, support.variable.property, support.variable.property.dom, meta.function-call variable.other.object.property, variable.language.prototype, meta.property.object, variable.other.member + settings + + foreground + #7dcfff + + + + name + Object Property + scope + variable.other.object.property + settings + + foreground + #c0caf5 + + + + name + Object Literal Member lvl 3 (Vue Prop Validation) + scope + meta.objectliteral meta.object.member meta.objectliteral meta.object.member meta.objectliteral meta.object.member meta.object-literal.key + settings + + foreground + #41a6b5 + + + + name + C-related Block Level Variables + scope + source.cpp meta.block variable.other + settings + + foreground + #f7768e + + + + name + Other Variable + scope + support.other.variable + settings + + foreground + #f7768e + + + + name + Methods + scope + meta.class-method.js entity.name.function.js, entity.name.method.js, variable.function.constructor, keyword.other.special-method, storage.type.cs + settings + + foreground + #7aa2f7 + + + + name + Function Definition + scope + entity.name.function, meta.function-call, meta.function-call entity.name.function, variable.function, meta.definition.method entity.name.function, meta.object-literal entity.name.function + settings + + foreground + #7aa2f7 + + + + name + Function Argument + scope + variable.parameter.function.language.special, variable.parameter, meta.function.parameters punctuation.definition.variable, meta.function.parameter variable + settings + + foreground + #e0af68 + + + + name + Constant, Tag Attribute + scope + keyword.other.type.php, storage.type.php, constant.character, constant.escape, keyword.other.unit + settings + + foreground + #bb9af7 + + + + name + Variable Definition + scope + meta.definition.variable variable.other.constant, meta.definition.variable variable.other.readwrite, variable.other.declaration + settings + + foreground + #bb9af7 + + + + name + Inherited Class + scope + entity.other.inherited-class + settings + + fontStyle + + foreground + #bb9af7 + + + + name + Class, Support, DOM, etc + scope + support.class, support.type, variable.other.readwrite.alias, support.orther.namespace.use.php, meta.use.php, support.other.namespace.php, support.type.sys-types, support.variable.dom, support.constant.math, support.type.object.module, support.constant.json, entity.name.namespace, meta.import.qualifier, entity.name.class + settings + + foreground + #0db9d7 + + + + name + Class Name + scope + entity.name + settings + + foreground + #c0caf5 + + + + name + Support Function + scope + support.function + settings + + foreground + #0db9d7 + + + + name + CSS Class and Support + scope + source.css support.type.property-name, source.sass support.type.property-name, source.scss support.type.property-name, source.less support.type.property-name, source.stylus support.type.property-name, source.postcss support.type.property-name, support.type.property-name.css, support.type.vendored.property-name, support.type.map.key + settings + + foreground + #7aa2f7 + + + + name + CSS Font + scope + support.constant.font-name, meta.definition.variable + settings + + foreground + #9ece6a + + + + name + CSS Class + scope + entity.other.attribute-name.class, meta.at-rule.mixin.scss entity.name.function.scss + settings + + foreground + #9ece6a + + + + name + CSS ID + scope + entity.other.attribute-name.id + settings + + foreground + #fc7b7b + + + + name + CSS Tag + scope + entity.name.tag.css, entity.name.tag.reference, entity.name.tag.scss + settings + + foreground + #0db9d7 + + + + name + CSS Tag Reference + scope + entity.name.tag.reference + settings + + foreground + #e0af68 + + + + name + CSS Property Separator + scope + meta.property-list punctuation.separator.key-value + settings + + foreground + #9abdf5 + + + + name + CSS Punctuation + scope + meta.property-list, punctuation.definition.entity.css + settings + + foreground + #e0af68 + + + + name + SCSS @ + scope + meta.at-rule.mixin keyword.control.at-rule.mixin, meta.at-rule.include entity.name.function.scss, meta.at-rule.include keyword.control.at-rule.include + settings + + foreground + #bb9af7 + + + + name + SCSS Mixins, Extends, Include Keyword + scope + keyword.control.at-rule.include punctuation.definition.keyword, keyword.control.at-rule.mixin punctuation.definition.keyword, meta.at-rule.include keyword.control.at-rule.include, keyword.control.at-rule.extend punctuation.definition.keyword, meta.at-rule.extend keyword.control.at-rule.extend, entity.other.attribute-name.placeholder.css punctuation.definition.entity.css, meta.at-rule.media keyword.control.at-rule.media, meta.at-rule.mixin keyword.control.at-rule.mixin, meta.at-rule.function keyword.control.at-rule.function, keyword.control punctuation.definition.keyword, meta.at-rule.import.scss entity.other.attribute-name.placeholder.scss punctuation.definition.entity.scss, meta.at-rule.import.scss keyword.control.at-rule.import.scss + settings + + foreground + #9d7cd8 + + + + name + SCSS Include Mixin Argument + scope + meta.property-list meta.at-rule.include + settings + + foreground + #c0caf5 + + + + name + CSS value + scope + support.constant.property-value + settings + + foreground + #ff9e64 + + + + name + Sub-methods + scope + entity.name.module.js, variable.import.parameter.js, variable.other.class.js + settings + + foreground + #c0caf5 + + + + name + Language methods + scope + variable.language + settings + + foreground + #f7768e + + + + name + Variable punctuation + scope + variable.other punctuation.definition.variable + settings + + foreground + #c0caf5 + + + + name + Keyword this with Punctuation, ES7 Bind Operator + scope + source.js constant.other.object.key.js string.unquoted.label.js, variable.language.this punctuation.definition.variable, keyword.other.this + settings + + foreground + #f7768e + + + + name + HTML Attributes + scope + entity.other.attribute-name, text.html.basic entity.other.attribute-name.html, text.html.basic entity.other.attribute-name, text.blade entity.other.attribute-name.class, text.html.smarty entity.other.attribute-name.class + settings + + foreground + #bb9af7 + + + + name + Vue Template attributes + scope + meta.directive.vue punctuation.separator.key-value.html, meta.directive.vue entity.other.attribute-name.html + settings + + foreground + #bb9af7 + + + + name + Vue Template attribute separator + scope + meta.directive.vue punctuation.separator.key-value.html + settings + + foreground + #89ddff + + + + name + CSS IDs + scope + source.sass keyword.control + settings + + foreground + #7aa2f7 + + + + name + CSS psuedo selectors + scope + entity.other.attribute-name.pseudo-class, entity.other.attribute-name.pseudo-element, entity.other.attribute-name.placeholder, meta.property-list meta.property-value + settings + + foreground + #bb9af7 + + + + name + Inserted + scope + markup.inserted + settings + + foreground + #449dab + + + + name + Deleted + scope + markup.deleted + settings + + foreground + #914c54 + + + + name + Changed + scope + markup.changed + settings + + foreground + #6183bb + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #b4f9f8 + + + + name + Regular Expressions - Punctuation + scope + punctuation.definition.group + settings + + foreground + #f7768e + + + + name + Regular Expressions - Character Class + scope + constant.other.character-class.regexp + settings + + foreground + #bb9af7 + + + + name + Regular Expressions - Character Class Set + scope + constant.other.character-class.set.regexp, punctuation.definition.character-class.regexp + settings + + foreground + #e0af68 + + + + name + Regular Expressions - Quantifier + scope + keyword.operator.quantifier.regexp + settings + + foreground + #89ddff + + + + name + Regular Expressions - Backslash + scope + constant.character.escape.backslash + settings + + foreground + #c0caf5 + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #89ddff + + + + name + Decorators + scope + tag.decorator.js entity.name.tag.js, tag.decorator.js punctuation.definition.tag.js + settings + + foreground + #7aa2f7 + + + + name + CSS Units + scope + keyword.other.unit + settings + + foreground + #f7768e + + + + name + JSON Key - Level 0 + scope + source.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #7aa2f7 + + + + name + JSON Key - Level 1 + scope + source.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #0db9d7 + + + + name + JSON Key - Level 2 + scope + source.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #7dcfff + + + + name + JSON Key - Level 3 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #bb9af7 + + + + name + JSON Key - Level 4 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #e0af68 + + + + name + JSON Key - Level 5 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #0db9d7 + + + + name + JSON Key - Level 6 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #73daca + + + + name + JSON Key - Level 7 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json + settings + + foreground + #f7768e + + + + name + JSON Key - Level 8 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json punctuation.definition.string.end.json + settings + + foreground + #9ece6a + + + + name + JSON Key - value + scope + source.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #9ece6a + + + + name + Plain Punctuation + scope + punctuation.definition.list_item.markdown + settings + + foreground + #9abdf5 + + + + name + Block Punctuation + scope + meta.block, meta.brace, punctuation.definition.block, punctuation.definition.use, punctuation.definition.group.shell, punctuation.definition.class, punctuation.definition.begin.bracket, punctuation.definition.end.bracket, punctuation.definition.parameters, punctuation.definition.arguments, punctuation.definition.dictionary, punctuation.definition.array, punctuation.section + settings + + foreground + #9abdf5 + + + + name + Markdown - Plain + scope + meta.jsx.children, meta.embedded.block + settings + + foreground + #c0caf5 + + + + name + HTML text + scope + text.html + settings + + foreground + #9aa5ce + + + + name + Markdown - Markup Raw Inline + scope + text.html.markdown markup.inline.raw.markdown + settings + + foreground + #bb9af7 + + + + name + Markdown - Markup Raw Inline Punctuation + scope + text.html.markdown markup.inline.raw.markdown punctuation.definition.raw.markdown + settings + + foreground + #4E5579 + + + + name + Markdown - Heading 1 + scope + heading.1.markdown entity.name, heading.1.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #89ddff + + + + name + Markdown - Heading 2 + scope + heading.2.markdown entity.name, heading.2.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #61bdf2 + + + + name + Markdown - Heading 3 + scope + heading.3.markdown entity.name, heading.3.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #7aa2f7 + + + + name + Markdown - Heading 4 + scope + heading.4.markdown entity.name, heading.4.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #6d91de + + + + name + Markdown - Heading 5 + scope + heading.5.markdown entity.name, heading.5.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #9aa5ce + + + + name + Markdown - Heading 6 + scope + heading.6.markdown entity.name, heading.6.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #747ca1 + + + + name + Markup - Italic + scope + markup.italic, markup.italic punctuation + settings + + fontStyle + italic + foreground + #c0caf5 + + + + name + Markup - Bold + scope + markup.bold, markup.bold punctuation + settings + + fontStyle + bold + foreground + #c0caf5 + + + + name + Markup - Bold-Italic + scope + markup.bold markup.italic, markup.bold markup.italic punctuation + settings + + fontStyle + bold italic + foreground + #c0caf5 + + + + name + Markup - Underline + scope + markup.underline, markup.underline punctuation + settings + + fontStyle + underline + + + + name + Markdown - Blockquote + scope + markup.quote punctuation.definition.blockquote.markdown + settings + + foreground + #4e5579 + + + + name + Markup - Quote + scope + markup.quote + settings + + fontStyle + italic + + + + name + Markdown - Link + scope + string.other.link, markup.underline.link, constant.other.reference.link.markdown, string.other.link.description.title.markdown + settings + + foreground + #73daca + + + + name + Markdown - Fenced Code Block + scope + markup.fenced_code.block.markdown, markup.inline.raw.string.markdown, variable.language.fenced.markdown + settings + + foreground + #89ddff + + + + name + Markdown - Separator + scope + meta.separator + settings + + fontStyle + bold + foreground + #444b6a + + + + name + Markup - Table + scope + markup.table + settings + + foreground + #c0cefc + + + + name + Token - Info + scope + token.info-token + settings + + foreground + #0db9d7 + + + + name + Token - Warn + scope + token.warn-token + settings + + foreground + #ffdb69 + + + + name + Token - Error + scope + token.error-token + settings + + foreground + #db4b4b + + + + name + Token - Debug + scope + token.debug-token + settings + + foreground + #b267e6 + + + + name + Apache Tag + scope + entity.tag.apacheconf + settings + + foreground + #f7768e + + + + name + Preprocessor + scope + meta.preprocessor + settings + + foreground + #73daca + + + + name + ENV value + scope + source.env + settings + + foreground + #7aa2f7 + + + + uuid + 06f855e3-9fb7-4fb1-b790-aef06065f34e + + diff --git a/.config/yazi/init.lua b/.config/yazi/init.lua new file mode 100644 index 0000000..6013df0 --- /dev/null +++ b/.config/yazi/init.lua @@ -0,0 +1 @@ +require("starship"):setup() diff --git a/.config/yazi/keymap.toml b/.config/yazi/keymap.toml new file mode 100644 index 0000000..88623bc --- /dev/null +++ b/.config/yazi/keymap.toml @@ -0,0 +1,34 @@ +[[manager.prepend_keymap]] +on = [ "l" ] +run = "plugin --sync smart-enter" +desc = "Enter the child directory, or open the file" + +[[manager.prepend_keymap]] +on = [ "k" ] +run = "plugin --sync arrow --args=-1" +desc = "Move cursor up" + +[[manager.prepend_keymap]] +on = [ "j" ] +run = "plugin --sync arrow --args=1" +desc = "Move cursor down" + +[[manager.prepend_keymap]] +on = [ "" ] +run = "plugin --sync arrow --args=-1" +desc = "Move cursor up" + +[[manager.prepend_keymap]] +on = [ "" ] +run = "plugin --sync arrow --args=1" +desc = "Move cursor down" + +[[manager.prepend_keymap]] +on = [ "" ] +run = "plugin --sync smart-enter" +desc = "Enter the child directory, or open the file" + +[[manager.prepend_keymap]] +on = [ "" ] +run = 'shell "$SHELL" --block --confirm' +desc = "Open shell here" diff --git a/.config/yazi/plugins/arrow.yazi/init.lua b/.config/yazi/plugins/arrow.yazi/init.lua new file mode 100644 index 0000000..5e2bec7 --- /dev/null +++ b/.config/yazi/plugins/arrow.yazi/init.lua @@ -0,0 +1,7 @@ +return { + entry = function(_, args) + local current = cx.active.current + local new = (current.cursor + args[1]) % #current.files + ya.manager_emit("arrow", { new - current.cursor }) + end, +} diff --git a/.config/yazi/plugins/smart-enter.yazi/init.lua b/.config/yazi/plugins/smart-enter.yazi/init.lua new file mode 100644 index 0000000..efa1070 --- /dev/null +++ b/.config/yazi/plugins/smart-enter.yazi/init.lua @@ -0,0 +1,6 @@ +return { + entry = function() + local h = cx.active.current.hovered + ya.manager_emit(h and h.cha.is_dir and "enter" or "open", { hovered = true }) + end, +} diff --git a/.config/yazi/plugins/starship.yazi/init.lua b/.config/yazi/plugins/starship.yazi/init.lua new file mode 100644 index 0000000..b59cf04 --- /dev/null +++ b/.config/yazi/plugins/starship.yazi/init.lua @@ -0,0 +1,27 @@ +local save = ya.sync(function(st, cwd, output) + if cx.active.current.cwd == Url(cwd) then + st.output = output + ya.render() + end +end) + +return { + setup = function(st) + Header.cwd = function() + local cwd = cx.active.current.cwd + if st.cwd ~= cwd then + st.cwd = cwd + ya.manager_emit("plugin", { st._name, args = ya.quote(tostring(cwd)) }) + end + + return ui.Line.parse(st.output or "") + end + end, + + entry = function(_, args) + local output = Command("starship"):arg("prompt"):cwd(args[1]):env("STARSHIP_SHELL", ""):output() + if output then + save(args[1], output.stdout:gsub("^%s+", "")) + end + end, +} diff --git a/.config/yazi/theme.toml b/.config/yazi/theme.toml new file mode 100644 index 0000000..a1460bf --- /dev/null +++ b/.config/yazi/theme.toml @@ -0,0 +1,2 @@ +[flavor] +use = "tokyo-night" diff --git a/.config/yazi/yazi.toml b/.config/yazi/yazi.toml new file mode 100644 index 0000000..9f5d644 --- /dev/null +++ b/.config/yazi/yazi.toml @@ -0,0 +1,197 @@ +# A TOML linter such as https://taplo.tamasfe.dev/ can use this schema to validate your config. +# If you encounter any issues, please make an issue at https://github.com/yazi-rs/schemas. +"$schema" = "https://yazi-rs.github.io/schemas/yazi.json" + +[manager] +ratio = [ 2, 3, 4 ] +sort_by = "extension" +sort_sensitive = false +sort_reverse = false +sort_dir_first = true +linemode = "none" +show_hidden = false +show_symlink = true +scrolloff = 5 + +[preview] +tab_size = 2 +max_width = 600 +max_height = 650 +cache_dir = "" +# image_filter = "triangle" +image_filter = "nearest" +image_quality = 70 +sixel_fraction = 15 +ueberzug_scale = 1 +ueberzug_offset = [ 0, 0, 0, 0 ] + +[opener] +edit = [ + { run = '${EDITOR:=vi} "$@"', desc = "$EDITOR", block = true, for = "unix" }, + { run = 'code "%*"', orphan = true, desc = "code", for = "windows" }, + { run = 'code -w "%*"', block = true, desc = "code (block)", for = "windows" }, +] +open = [ + { run = 'xdg-open "$@"', desc = "Open", for = "linux" }, + { run = 'open "$@"', desc = "Open", for = "macos" }, + { run = 'start "" "%1"', orphan = true, desc = "Open", for = "windows" }, +] +reveal = [ + { run = 'open -R "$1"', desc = "Reveal", for = "macos" }, + { run = 'explorer /select, "%1"', orphan = true, desc = "Reveal", for = "windows" }, + { run = '''exiftool "$1"; echo "Press enter to exit"; read _''', block = true, desc = "Show EXIF", for = "unix" }, +] +extract = [ + { run = 'unar "$1"', desc = "Extract here", for = "unix" }, + { run = 'unar "%1"', desc = "Extract here", for = "windows" }, +] +play = [ + { run = 'mpv --loop-file --audio-display=no "$@"', orphan = true, for = "unix" }, + { run = 'mpv "%1"', orphan = true, for = "windows" }, + { run = '''mediainfo "$1"; echo "Press enter to exit"; read _''', block = true, desc = "Show media info", for = "unix" }, +] + +[open] +rules = [ + { name = "*/", use = [ "edit", "open", "reveal" ] }, + + { mime = "text/*", use = [ "edit", "reveal" ] }, + { mime = "image/*", use = [ "open", "reveal" ] }, + { mime = "video/*", use = [ "play", "reveal" ] }, + { mime = "audio/*", use = [ "play", "reveal" ] }, + { mime = "inode/x-empty", use = [ "edit", "reveal" ] }, + + { mime = "application/json", use = [ "edit", "reveal" ] }, + { mime = "*/javascript", use = [ "edit", "reveal" ] }, + + { mime = "application/zip", use = [ "extract", "reveal" ] }, + { mime = "application/gzip", use = [ "extract", "reveal" ] }, + { mime = "application/x-tar", use = [ "extract", "reveal" ] }, + { mime = "application/x-bzip", use = [ "extract", "reveal" ] }, + { mime = "application/x-bzip2", use = [ "extract", "reveal" ] }, + { mime = "application/x-7z-compressed", use = [ "extract", "reveal" ] }, + { mime = "application/x-rar", use = [ "extract", "reveal" ] }, + { mime = "application/xz", use = [ "extract", "reveal" ] }, + + { mime = "*", use = [ "open", "reveal" ] }, +] + +[tasks] +micro_workers = 10 +macro_workers = 25 +bizarre_retry = 5 +image_alloc = 536870912 # 512MB +image_bound = [ 0, 0 ] +suppress_preload = false + +[plugin] + +preloaders = [ + { name = "*", cond = "!mime", run = "mime", multi = true, prio = "high" }, + # Image + { mime = "image/vnd.djvu", run = "noop" }, + { mime = "image/*", run = "image" }, + # Video + { mime = "video/*", run = "video" }, + # PDF + { mime = "application/pdf", run = "pdf" }, +] +previewers = [ + { name = "*/", run = "folder", sync = true }, + # Code + { mime = "text/*", run = "code" }, + { mime = "*/xml", run = "code" }, + { mime = "*/javascript", run = "code" }, + { mime = "*/x-wine-extension-ini", run = "code" }, + # JSON + { mime = "application/json", run = "json" }, + # Image + { mime = "image/vnd.djvu", run = "noop" }, + { mime = "image/*", run = "image" }, + # Video + { mime = "video/*", run = "video" }, + # PDF + { mime = "application/pdf", run = "pdf" }, + # Archive + { mime = "application/zip", run = "archive" }, + { mime = "application/gzip", run = "archive" }, + { mime = "application/x-tar", run = "archive" }, + { mime = "application/x-bzip", run = "archive" }, + { mime = "application/x-bzip2", run = "archive" }, + { mime = "application/x-7z-compressed", run = "archive" }, + { mime = "application/x-rar", run = "archive" }, + { mime = "application/xz", run = "archive" }, + # Fallback + { name = "*", run = "file" }, +] + +[input] +# cd +cd_title = "Change directory:" +cd_origin = "top-center" +cd_offset = [ 0, 2, 50, 3 ] + +# create +create_title = "Create:" +create_origin = "top-center" +create_offset = [ 0, 2, 50, 3 ] + +# rename +rename_title = "Rename:" +rename_origin = "hovered" +rename_offset = [ 0, 1, 50, 3 ] + +# trash +trash_title = "Move {n} selected file{s} to trash? (y/N)" +trash_origin = "top-center" +trash_offset = [ 0, 2, 50, 3 ] + +# delete +delete_title = "Delete {n} selected file{s} permanently? (y/N)" +delete_origin = "top-center" +delete_offset = [ 0, 2, 50, 3 ] + +# filter +filter_title = "Filter:" +filter_origin = "top-center" +filter_offset = [ 0, 2, 50, 3 ] + +# find +find_title = [ "Find next:", "Find previous:" ] +find_origin = "top-center" +find_offset = [ 0, 2, 50, 3 ] + +# search +search_title = "Search via {n}:" +search_origin = "top-center" +search_offset = [ 0, 2, 50, 3 ] + +# shell +shell_title = [ "Shell:", "Shell (block):" ] +shell_origin = "top-center" +shell_offset = [ 0, 2, 50, 3 ] + +# overwrite +overwrite_title = "Overwrite an existing file? (y/N)" +overwrite_origin = "top-center" +overwrite_offset = [ 0, 2, 50, 3 ] + +# quit +quit_title = "{n} task{s} running, sure to quit? (y/N)" +quit_origin = "top-center" +quit_offset = [ 0, 2, 50, 3 ] + +[select] +open_title = "Open with:" +open_origin = "hovered" +open_offset = [ 0, 1, 50, 7 ] + +[which] +sort_by = "none" +sort_sensitive = false +sort_reverse = false + +[log] +enabled = false + +[headsup] diff --git a/.config/zathura/zathurarc b/.config/zathura/zathurarc new file mode 100644 index 0000000..a8006fa --- /dev/null +++ b/.config/zathura/zathurarc @@ -0,0 +1,57 @@ +# vim: filetype=zathurarc + +set notification-error-bg "#ee5396" +set notification-error-fg "#1a1b26" +set notification-warning-bg "#ee5396" +set notification-warning-fg "#1a1b26" +set notification-bg "#ffab91" +set notification-fg "#1a1b26" + +set completion-bg "#1a1b26" +set completion-fg "#42be65" +set completion-group-bg "#1a1b26" +set completion-group-fg "#ffab91" +set completion-highlight-bg "#ffab91" +set completion-highlight-fg "#1a1b26" + +set index-bg "#1a1b26" +set index-fg "#A0A8CD" +set index-active-bg "#1a1b26" +set index-active-fg "#ffab91" + +set inputbar-bg "#1a1b26" +set inputbar-fg "#A0A8CD" +set statusbar-bg "#1a1b26" +set statusbar-fg "#A0A8CD" + +set highlight-color "#ffab91" +set highlight-active-color "#EE6d85" + +set default-bg "#1a1b26" +set default-fg "#A0A8CD" + +set render-loading-fg "#A0A8CD" +set render-loading-bg "#1a1b26" + +set recolor-lightcolor "#1a1b26" +set recolor-darkcolor "#A0A8CD" + +set statusbar-h-padding 0 +set statusbar-v-padding 0 +set page-padding 1 +set selection-clipboard clipboard +set adjust-open width +set recolor false +set recolor-keephue true +set render-loading true + +map u scroll half-up +map d scroll half-down +map D toggle_page_mode +map r reload +map R rotate +map K zoom in +map J zoom out +map i recolor +map p print +map g goto top diff --git a/.config/zsh/.p10k-ascii-8color.zsh b/.config/zsh/.p10k-ascii-8color.zsh new file mode 100644 index 0000000..d6fdd63 --- /dev/null +++ b/.config/zsh/.p10k-ascii-8color.zsh @@ -0,0 +1,1660 @@ +# Generated by Powerlevel10k configuration wizard on 2023-08-24 at 14:36 PKT. +# Based on romkatv/powerlevel10k/config/p10k-lean-8colors.zsh, checksum 63804. +# Wizard options: ascii, lean_8colors, 1 line, compact, concise, transient_prompt, +# instant_prompt=auto-quiet. +# Type `p10k configure` to generate another config. +# +# Config for Powerlevel10k with 8-color lean prompt style. Type `p10k configure` to generate +# your own config based on it. +# +# Tip: Looking for a nice color? Here's a one-liner to print colormap. +# +# for i in {0..255}; do print -Pn "%K{$i} %k%F{$i}${(l:3::0:)i}%f " ${${(M)$((i%6)):#3}:+$'\n'}; done + +# Temporarily change options. +'builtin' 'local' '-a' 'p10k_config_opts' +[[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases') +[[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob') +[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand') +'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' + +() { + emulate -L zsh -o extended_glob + + # Unset all configuration options. This allows you to apply configuration changes without + # restarting zsh. Edit ~/.p10k.zsh and type `source ~/.p10k.zsh`. + unset -m '(POWERLEVEL9K_*|DEFAULT_USER)~POWERLEVEL9K_GITSTATUS_DIR' + + # Zsh >= 5.1 is required. + [[ $ZSH_VERSION == (5.<1->*|<6->.*) ]] || return + + # The list of segments shown on the left. Fill it with the most important segments. + typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=( + # os_icon # os identifier + prompt_char # prompt symbol + ) + + # The list of segments shown on the right. Fill it with less important segments. + # Right prompt on the last prompt line (where you are typing your commands) gets + # automatically hidden when the input line reaches it. Right prompt above the + # last prompt line gets hidden if it would overlap with left prompt. + typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=( + # status # exit code of the last command + command_execution_time # duration of the last command + # background_jobs # presence of background jobs + # direnv # direnv status (https://direnv.net/) + # asdf # asdf version manager (https://github.com/asdf-vm/asdf) + # virtualenv # python virtual environment (https://docs.python.org/3/library/venv.html) + # anaconda # conda environment (https://conda.io/) + # pyenv # python environment (https://github.com/pyenv/pyenv) + # goenv # go environment (https://github.com/syndbg/goenv) + # nodenv # node.js version from nodenv (https://github.com/nodenv/nodenv) + # nvm # node.js version from nvm (https://github.com/nvm-sh/nvm) + # nodeenv # node.js environment (https://github.com/ekalinin/nodeenv) + # node_version # node.js version + # go_version # go version (https://golang.org) + # rust_version # rustc version (https://www.rust-lang.org) + # dotnet_version # .NET version (https://dotnet.microsoft.com) + # php_version # php version (https://www.php.net/) + # laravel_version # laravel php framework version (https://laravel.com/) + # java_version # java version (https://www.java.com/) + # package # name@version from package.json (https://docs.npmjs.com/files/package.json) + # rbenv # ruby version from rbenv (https://github.com/rbenv/rbenv) + # rvm # ruby version from rvm (https://rvm.io) + # fvm # flutter version management (https://github.com/leoafarias/fvm) + # luaenv # lua version from luaenv (https://github.com/cehoffman/luaenv) + # jenv # java version from jenv (https://github.com/jenv/jenv) + # plenv # perl version from plenv (https://github.com/tokuhirom/plenv) + # perlbrew # perl version from perlbrew (https://github.com/gugod/App-perlbrew) + # phpenv # php version from phpenv (https://github.com/phpenv/phpenv) + # scalaenv # scala version from scalaenv (https://github.com/scalaenv/scalaenv) + # haskell_stack # haskell version from stack (https://haskellstack.org/) + # kubecontext # current kubernetes context (https://kubernetes.io/) + # terraform # terraform workspace (https://www.terraform.io) + # terraform_version # terraform version (https://www.terraform.io) + # aws # aws profile (https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) + # aws_eb_env # aws elastic beanstalk environment (https://aws.amazon.com/elasticbeanstalk/) + # azure # azure account name (https://docs.microsoft.com/en-us/cli/azure) + # gcloud # google cloud cli account and project (https://cloud.google.com/) + # google_app_cred # google application credentials (https://cloud.google.com/docs/authentication/production) + # toolbox # toolbox name (https://github.com/containers/toolbox) + # context # user@hostname + # nordvpn # nordvpn connection status, linux only (https://nordvpn.com/) + # ranger # ranger shell (https://github.com/ranger/ranger) + # nnn # nnn shell (https://github.com/jarun/nnn) + # lf # lf shell (https://github.com/gokcehan/lf) + # xplr # xplr shell (https://github.com/sayanarijit/xplr) + # vim_shell # vim shell indicator (:sh) + # midnight_commander # midnight commander shell (https://midnight-commander.org/) + # nix_shell # nix shell (https://nixos.org/nixos/nix-pills/developing-with-nix-shell.html) + # chezmoi_shell # chezmoi shell (https://www.chezmoi.io/) + # vpn_ip # virtual private network indicator + # load # CPU load + # disk_usage # disk usage + # ram # free RAM + # swap # used swap + # todo # todo items (https://github.com/todotxt/todo.txt-cli) + # timewarrior # timewarrior tracking status (https://timewarrior.net/) + # taskwarrior # taskwarrior task count (https://taskwarrior.org/) + # cpu_arch # CPU architecture + # time # current time + # ip # ip address and bandwidth usage for a specified network interface + # public_ip # public IP address + # proxy # system-wide http/https/ftp proxy + # battery # internal battery + # wifi # wifi speed + dir # current directory + vcs # git status + # example # example user-defined segment (see prompt_example function below) + ) + + # Defines character set used by powerlevel10k. It's best to let `p10k configure` set it for you. + typeset -g POWERLEVEL9K_MODE=ascii + # When set to `moderate`, some icons will have an extra space after them. This is meant to avoid + # icon overlap when using non-monospace fonts. When set to `none`, spaces are not added. + typeset -g POWERLEVEL9K_ICON_PADDING=none + + # Basic style options that define the overall look of your prompt. You probably don't want to + # change them. + typeset -g POWERLEVEL9K_BACKGROUND= # transparent background + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_{LEFT,RIGHT}_WHITESPACE= # no surrounding whitespace + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SUBSEGMENT_SEPARATOR=' ' # separate segments with a space + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SEGMENT_SEPARATOR= # no end-of-line symbol + + # When set to true, icons appear before content on both sides of the prompt. When set + # to false, icons go after content. If empty or not set, icons go before content in the left + # prompt and after content in the right prompt. + # + # You can also override it for a specific segment: + # + # POWERLEVEL9K_STATUS_ICON_BEFORE_CONTENT=false + # + # Or for a specific segment in specific state: + # + # POWERLEVEL9K_DIR_NOT_WRITABLE_ICON_BEFORE_CONTENT=false + typeset -g POWERLEVEL9K_ICON_BEFORE_CONTENT=true + + # Add an empty line before each prompt. + typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=false + + # Connect left prompt lines with these symbols. + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX= + typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_PREFIX= + typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX= + # Connect right prompt lines with these symbols. + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_SUFFIX= + typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_SUFFIX= + typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_SUFFIX= + + # The left end of left prompt. + typeset -g POWERLEVEL9K_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL= + # The right end of right prompt. + typeset -g POWERLEVEL9K_RIGHT_PROMPT_LAST_SEGMENT_END_SYMBOL= + + # Ruler, a.k.a. the horizontal line before each prompt. If you set it to true, you'll + # probably want to set POWERLEVEL9K_PROMPT_ADD_NEWLINE=false above and + # POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' ' below. + typeset -g POWERLEVEL9K_SHOW_RULER=false + typeset -g POWERLEVEL9K_RULER_CHAR='-' # reasonable alternative: '·' + typeset -g POWERLEVEL9K_RULER_FOREGROUND=7 + + # Filler between left and right prompt on the first prompt line. You can set it to '·' or '-' + # to make it easier to see the alignment between left and right prompt and to separate prompt + # from command output. It serves the same purpose as ruler (see above) without increasing + # the number of prompt lines. You'll probably want to set POWERLEVEL9K_SHOW_RULER=false + # if using this. You might also like POWERLEVEL9K_PROMPT_ADD_NEWLINE=false for more compact + # prompt. + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' ' + if [[ $POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR != ' ' ]]; then + # The color of the filler. + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_FOREGROUND=7 + # Add a space between the end of left prompt and the filler. + typeset -g POWERLEVEL9K_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL=' ' + # Add a space between the filler and the start of right prompt. + typeset -g POWERLEVEL9K_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL=' ' + # Start filler from the edge of the screen if there are no left segments on the first line. + typeset -g POWERLEVEL9K_EMPTY_LINE_LEFT_PROMPT_FIRST_SEGMENT_END_SYMBOL='%{%}' + # End filler on the edge of the screen if there are no right segments on the first line. + typeset -g POWERLEVEL9K_EMPTY_LINE_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='%{%}' + fi + + #################################[ os_icon: os identifier ]################################## + # OS identifier color. + typeset -g POWERLEVEL9K_OS_ICON_FOREGROUND= + # Custom icon. + # typeset -g POWERLEVEL9K_OS_ICON_CONTENT_EXPANSION='⭐' + + ################################[ prompt_char: prompt symbol ]################################ + # Green prompt symbol if the last command succeeded. + typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=2 + # Red prompt symbol if the last command failed. + typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=1 + # Default prompt symbol. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIINS_CONTENT_EXPANSION='>' + # Prompt symbol in command vi mode. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VICMD_CONTENT_EXPANSION='<' + # Prompt symbol in visual vi mode. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIVIS_CONTENT_EXPANSION='V' + # Prompt symbol in overwrite vi mode. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIOWR_CONTENT_EXPANSION='^' + typeset -g POWERLEVEL9K_PROMPT_CHAR_OVERWRITE_STATE=true + # No line terminator if prompt_char is the last segment. + typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL='' + # No line introducer if prompt_char is the first segment. + typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL= + + ##################################[ dir: current directory ]################################## + # Default current directory color. + typeset -g POWERLEVEL9K_DIR_FOREGROUND=4 + # If directory is too long, shorten some of its segments to the shortest possible unique + # prefix. The shortened directory can be tab-completed to the original. + typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique + # Replace removed segment suffixes with this symbol. + typeset -g POWERLEVEL9K_SHORTEN_DELIMITER= + # Color of the shortened directory segments. + typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND=4 + # Color of the anchor directory segments. Anchor segments are never shortened. The first + # segment is always an anchor. + typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND=4 + # Set to true to display anchor directory segments in bold. + typeset -g POWERLEVEL9K_DIR_ANCHOR_BOLD=false + # Don't shorten directories that contain any of these files. They are anchors. + local anchor_files=( + .bzr + .citc + .git + .hg + .node-version + .python-version + .go-version + .ruby-version + .lua-version + .java-version + .perl-version + .php-version + .tool-version + .shorten_folder_marker + .svn + .terraform + CVS + Cargo.toml + composer.json + go.mod + package.json + stack.yaml + ) + typeset -g POWERLEVEL9K_SHORTEN_FOLDER_MARKER="(${(j:|:)anchor_files})" + # If set to "first" ("last"), remove everything before the first (last) subdirectory that contains + # files matching $POWERLEVEL9K_SHORTEN_FOLDER_MARKER. For example, when the current directory is + # /foo/bar/git_repo/nested_git_repo/baz, prompt will display git_repo/nested_git_repo/baz (first) + # or nested_git_repo/baz (last). This assumes that git_repo and nested_git_repo contain markers + # and other directories don't. + # + # Optionally, "first" and "last" can be followed by ":" where is an integer. + # This moves the truncation point to the right (positive offset) or to the left (negative offset) + # relative to the marker. Plain "first" and "last" are equivalent to "first:0" and "last:0" + # respectively. + typeset -g POWERLEVEL9K_DIR_TRUNCATE_BEFORE_MARKER=false + # Don't shorten this many last directory segments. They are anchors. + typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=1 + # Shorten directory if it's longer than this even if there is space for it. The value can + # be either absolute (e.g., '80') or a percentage of terminal width (e.g, '50%'). If empty, + # directory will be shortened only when prompt doesn't fit or when other parameters demand it + # (see POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS and POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT below). + # If set to `0`, directory will always be shortened to its minimum length. + typeset -g POWERLEVEL9K_DIR_MAX_LENGTH=80 + # When `dir` segment is on the last prompt line, try to shorten it enough to leave at least this + # many columns for typing commands. + typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS=40 + # When `dir` segment is on the last prompt line, try to shorten it enough to leave at least + # COLUMNS * POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT * 0.01 columns for typing commands. + typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT=50 + # If set to true, embed a hyperlink into the directory. Useful for quickly + # opening a directory in the file manager simply by clicking the link. + # Can also be handy when the directory is shortened, as it allows you to see + # the full directory that was used in previous commands. + typeset -g POWERLEVEL9K_DIR_HYPERLINK=false + + # Enable special styling for non-writable directories. See POWERLEVEL9K_LOCK_ICON and + # POWERLEVEL9K_DIR_CLASSES below. + typeset -g POWERLEVEL9K_DIR_SHOW_WRITABLE=v2 + + # Enable special styling for non-writable and non-existent directories. See POWERLEVEL9K_LOCK_ICON + # and POWERLEVEL9K_DIR_CLASSES below. + typeset -g POWERLEVEL9K_DIR_SHOW_WRITABLE=v3 + + # The default icon shown next to non-writable and non-existent directories when + # POWERLEVEL9K_DIR_SHOW_WRITABLE is set to v3. + # typeset -g POWERLEVEL9K_LOCK_ICON='⭐' + + # POWERLEVEL9K_DIR_CLASSES allows you to specify custom icons and colors for different + # directories. It must be an array with 3 * N elements. Each triplet consists of: + # + # 1. A pattern against which the current directory ($PWD) is matched. Matching is done with + # extended_glob option enabled. + # 2. Directory class for the purpose of styling. + # 3. An empty string. + # + # Triplets are tried in order. The first triplet whose pattern matches $PWD wins. + # + # If POWERLEVEL9K_DIR_SHOW_WRITABLE is set to v3, non-writable and non-existent directories + # acquire class suffix _NOT_WRITABLE and NON_EXISTENT respectively. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_DIR_CLASSES=( + # '~/work(|/*)' WORK '' + # '~(|/*)' HOME '' + # '*' DEFAULT '') + # + # Whenever the current directory is ~/work or a subdirectory of ~/work, it gets styled with one + # of the following classes depending on its writability and existence: WORK, WORK_NOT_WRITABLE or + # WORK_NON_EXISTENT. + # + # Simply assigning classes to directories doesn't have any visible effects. It merely gives you an + # option to define custom colors and icons for different directory classes. + # + # # Styling for WORK. + # typeset -g POWERLEVEL9K_DIR_WORK_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_DIR_WORK_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_SHORTENED_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_ANCHOR_FOREGROUND=4 + # + # # Styling for WORK_NOT_WRITABLE. + # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_SHORTENED_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_ANCHOR_FOREGROUND=4# + # + # Styling for WORK_NON_EXISTENT. + # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_SHORTENED_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_ANCHOR_FOREGROUND=4 + # + # If a styling parameter isn't explicitly defined for some class, it falls back to the classless + # parameter. For example, if POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_FOREGROUND is not set, it falls + # back to POWERLEVEL9K_DIR_FOREGROUND. + # + typeset -g POWERLEVEL9K_DIR_CLASSES=() + + # Custom prefix. + # typeset -g POWERLEVEL9K_DIR_PREFIX='%fin ' + + #####################################[ vcs: git status ]###################################### + # Branch icon. Set this parameter to '\UE0A0 ' for the popular Powerline branch icon. + typeset -g POWERLEVEL9K_VCS_BRANCH_ICON= + + # Untracked files icon. It's really a question mark, your font isn't broken. + # Change the value of this parameter to show a different icon. + typeset -g POWERLEVEL9K_VCS_UNTRACKED_ICON='?' + + # Formatter for Git status. + # + # Example output: master wip <42>42 *42 merge ~42 +42 !42 ?42. + # + # You can edit the function to customize how Git status looks. + # + # VCS_STATUS_* parameters are set by gitstatus plugin. See reference: + # https://github.com/romkatv/gitstatus/blob/master/gitstatus.plugin.zsh. + function my_git_formatter() { + emulate -L zsh + + if [[ -n $P9K_CONTENT ]]; then + # If P9K_CONTENT is not empty, use it. It's either "loading" or from vcs_info (not from + # gitstatus plugin). VCS_STATUS_* parameters are not available in this case. + typeset -g my_git_format=$P9K_CONTENT + return + fi + + if (( $1 )); then + # Styling for up-to-date Git status. + local meta='%f' # default foreground + local clean='%2F' # green foreground + local modified='%3F' # yellow foreground + local untracked='%4F' # blue foreground + local conflicted='%1F' # red foreground + else + # Styling for incomplete and stale Git status. + local meta='%f' # default foreground + local clean='%f' # default foreground + local modified='%f' # default foreground + local untracked='%f' # default foreground + local conflicted='%f' # default foreground + fi + + local res + + if [[ -n $VCS_STATUS_LOCAL_BRANCH ]]; then + local branch=${(V)VCS_STATUS_LOCAL_BRANCH} + # If local branch name is at most 32 characters long, show it in full. + # Otherwise show the first 12 .. the last 12. + # Tip: To always show local branch name in full without truncation, delete the next line. + (( $#branch > 32 )) && branch[13,-13]=".." # <-- this line + res+="${clean}${(g::)POWERLEVEL9K_VCS_BRANCH_ICON}${branch//\%/%%}" + fi + + if [[ -n $VCS_STATUS_TAG + # Show tag only if not on a branch. + # Tip: To always show tag, delete the next line. + && -z $VCS_STATUS_LOCAL_BRANCH # <-- this line + ]]; then + local tag=${(V)VCS_STATUS_TAG} + # If tag name is at most 32 characters long, show it in full. + # Otherwise show the first 12 .. the last 12. + # Tip: To always show tag name in full without truncation, delete the next line. + (( $#tag > 32 )) && tag[13,-13]=".." # <-- this line + res+="${meta}#${clean}${tag//\%/%%}" + fi + + # Display the current Git commit if there is no branch and no tag. + # Tip: To always display the current Git commit, delete the next line. + [[ -z $VCS_STATUS_LOCAL_BRANCH && -z $VCS_STATUS_TAG ]] && # <-- this line + res+="${meta}@${clean}${VCS_STATUS_COMMIT[1,8]}" + + # Show tracking branch name if it differs from local branch. + if [[ -n ${VCS_STATUS_REMOTE_BRANCH:#$VCS_STATUS_LOCAL_BRANCH} ]]; then + res+="${meta}:${clean}${(V)VCS_STATUS_REMOTE_BRANCH//\%/%%}" + fi + + # Display "wip" if the latest commit's summary contains "wip" or "WIP". + if [[ $VCS_STATUS_COMMIT_SUMMARY == (|*[^[:alnum:]])(wip|WIP)(|[^[:alnum:]]*) ]]; then + res+=" ${modified}wip" + fi + + # <42 if behind the remote. + (( VCS_STATUS_COMMITS_BEHIND )) && res+=" ${clean}<${VCS_STATUS_COMMITS_BEHIND}" + # >42 if ahead of the remote; no leading space if also behind the remote: <42>42. + (( VCS_STATUS_COMMITS_AHEAD && !VCS_STATUS_COMMITS_BEHIND )) && res+=" " + (( VCS_STATUS_COMMITS_AHEAD )) && res+="${clean}>${VCS_STATUS_COMMITS_AHEAD}" + # <-42 if behind the push remote. + (( VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" ${clean}<-${VCS_STATUS_PUSH_COMMITS_BEHIND}" + (( VCS_STATUS_PUSH_COMMITS_AHEAD && !VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" " + # ->42 if ahead of the push remote; no leading space if also behind: <-42->42. + (( VCS_STATUS_PUSH_COMMITS_AHEAD )) && res+="${clean}->${VCS_STATUS_PUSH_COMMITS_AHEAD}" + # *42 if have stashes. + (( VCS_STATUS_STASHES )) && res+=" ${clean}*${VCS_STATUS_STASHES}" + # 'merge' if the repo is in an unusual state. + [[ -n $VCS_STATUS_ACTION ]] && res+=" ${conflicted}${VCS_STATUS_ACTION}" + # ~42 if have merge conflicts. + (( VCS_STATUS_NUM_CONFLICTED )) && res+=" ${conflicted}~${VCS_STATUS_NUM_CONFLICTED}" + # +42 if have staged changes. + (( VCS_STATUS_NUM_STAGED )) && res+=" ${modified}+${VCS_STATUS_NUM_STAGED}" + # !42 if have unstaged changes. + (( VCS_STATUS_NUM_UNSTAGED )) && res+=" ${modified}!${VCS_STATUS_NUM_UNSTAGED}" + # ?42 if have untracked files. It's really a question mark, your font isn't broken. + # See POWERLEVEL9K_VCS_UNTRACKED_ICON above if you want to use a different icon. + # Remove the next line if you don't want to see untracked files at all. + (( VCS_STATUS_NUM_UNTRACKED )) && res+=" ${untracked}${(g::)POWERLEVEL9K_VCS_UNTRACKED_ICON}${VCS_STATUS_NUM_UNTRACKED}" + # "-" if the number of unstaged files is unknown. This can happen due to + # POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY (see below) being set to a non-negative number lower + # than the number of files in the Git index, or due to bash.showDirtyState being set to false + # in the repository config. The number of staged and untracked files may also be unknown + # in this case. + (( VCS_STATUS_HAS_UNSTAGED == -1 )) && res+=" ${modified}-" + + typeset -g my_git_format=$res + } + functions -M my_git_formatter 2>/dev/null + + # Don't count the number of unstaged, untracked and conflicted files in Git repositories with + # more than this many files in the index. Negative value means infinity. + # + # If you are working in Git repositories with tens of millions of files and seeing performance + # sagging, try setting POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY to a number lower than the output + # of `git ls-files | wc -l`. Alternatively, add `bash.showDirtyState = false` to the repository's + # config: `git config bash.showDirtyState false`. + typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=-1 + + # Don't show Git status in prompt for repositories whose workdir matches this pattern. + # For example, if set to '~', the Git repository at $HOME/.git will be ignored. + # Multiple patterns can be combined with '|': '~(|/foo)|/bar/baz/*'. + typeset -g POWERLEVEL9K_VCS_DISABLED_WORKDIR_PATTERN='~' + + # Disable the default Git status formatting. + typeset -g POWERLEVEL9K_VCS_DISABLE_GITSTATUS_FORMATTING=true + # Install our own Git status formatter. + typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${$((my_git_formatter(1)))+${my_git_format}}' + typeset -g POWERLEVEL9K_VCS_LOADING_CONTENT_EXPANSION='${$((my_git_formatter(0)))+${my_git_format}}' + # Enable counters for staged, unstaged, etc. + typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED,CONFLICTED,COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=-1 + + # Icon color. + typeset -g POWERLEVEL9K_VCS_VISUAL_IDENTIFIER_COLOR=2 + typeset -g POWERLEVEL9K_VCS_LOADING_VISUAL_IDENTIFIER_COLOR= + # Custom icon. + typeset -g POWERLEVEL9K_VCS_VISUAL_IDENTIFIER_EXPANSION= + # Custom prefix. + # typeset -g POWERLEVEL9K_VCS_PREFIX='%fon ' + + # Show status of repositories of these types. You can add svn and/or hg if you are + # using them. If you do, your prompt may become slow even when your current directory + # isn't in an svn or hg repository. + typeset -g POWERLEVEL9K_VCS_BACKENDS=(git) + + # These settings are used for repositories other than Git or when gitstatusd fails and + # Powerlevel10k has to fall back to using vcs_info. + typeset -g POWERLEVEL9K_VCS_CLEAN_FOREGROUND=2 + typeset -g POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND=2 + typeset -g POWERLEVEL9K_VCS_MODIFIED_FOREGROUND=3 + + ##########################[ status: exit code of the last command ]########################### + # Enable OK_PIPE, ERROR_PIPE and ERROR_SIGNAL status states to allow us to enable, disable and + # style them independently from the regular OK and ERROR state. + typeset -g POWERLEVEL9K_STATUS_EXTENDED_STATES=true + + # Status on success. No content, just an icon. No need to show it if prompt_char is enabled as + # it will signify success by turning green. + typeset -g POWERLEVEL9K_STATUS_OK=false + typeset -g POWERLEVEL9K_STATUS_OK_FOREGROUND=2 + typeset -g POWERLEVEL9K_STATUS_OK_VISUAL_IDENTIFIER_EXPANSION='ok' + + # Status when some part of a pipe command fails but the overall exit status is zero. It may look + # like this: 1|0. + typeset -g POWERLEVEL9K_STATUS_OK_PIPE=true + typeset -g POWERLEVEL9K_STATUS_OK_PIPE_FOREGROUND=2 + typeset -g POWERLEVEL9K_STATUS_OK_PIPE_VISUAL_IDENTIFIER_EXPANSION='ok' + + # Status when it's just an error code (e.g., '1'). No need to show it if prompt_char is enabled as + # it will signify error by turning red. + typeset -g POWERLEVEL9K_STATUS_ERROR=false + typeset -g POWERLEVEL9K_STATUS_ERROR_FOREGROUND=1 + typeset -g POWERLEVEL9K_STATUS_ERROR_VISUAL_IDENTIFIER_EXPANSION='err' + + # Status when the last command was terminated by a signal. + typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL=true + typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_FOREGROUND=1 + # Use terse signal names: "INT" instead of "SIGINT(2)". + typeset -g POWERLEVEL9K_STATUS_VERBOSE_SIGNAME=false + typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_VISUAL_IDENTIFIER_EXPANSION= + + # Status when some part of a pipe command fails and the overall exit status is also non-zero. + # It may look like this: 1|0. + typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE=true + typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_FOREGROUND=1 + typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_VISUAL_IDENTIFIER_EXPANSION='err' + + ###################[ command_execution_time: duration of the last command ]################### + # Show duration of the last command if takes at least this many seconds. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=3 + # Show this many fractional digits. Zero means round to seconds. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0 + # Execution time color. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=3 + # Duration format: 1d 2h 3m 4s. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s' + # Custom icon. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_VISUAL_IDENTIFIER_EXPANSION= + # Custom prefix. + # typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PREFIX='%ftook ' + + #######################[ background_jobs: presence of background jobs ]####################### + # Don't show the number of background jobs. + typeset -g POWERLEVEL9K_BACKGROUND_JOBS_VERBOSE=false + # Background jobs color. + typeset -g POWERLEVEL9K_BACKGROUND_JOBS_FOREGROUND=1 + # Custom icon. + # typeset -g POWERLEVEL9K_BACKGROUND_JOBS_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #######################[ direnv: direnv status (https://direnv.net/) ]######################## + # Direnv color. + typeset -g POWERLEVEL9K_DIRENV_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_DIRENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###############[ asdf: asdf version manager (https://github.com/asdf-vm/asdf) ]############### + # Default asdf color. Only used to display tools for which there is no color override (see below). + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_FOREGROUND. + typeset -g POWERLEVEL9K_ASDF_FOREGROUND=6 + + # There are four parameters that can be used to hide asdf tools. Each parameter describes + # conditions under which a tool gets hidden. Parameters can hide tools but not unhide them. If at + # least one parameter decides to hide a tool, that tool gets hidden. If no parameter decides to + # hide a tool, it gets shown. + # + # Special note on the difference between POWERLEVEL9K_ASDF_SOURCES and + # POWERLEVEL9K_ASDF_PROMPT_ALWAYS_SHOW. Consider the effect of the following commands: + # + # asdf local python 3.8.1 + # asdf global python 3.8.1 + # + # After running both commands the current python version is 3.8.1 and its source is "local" as + # it takes precedence over "global". If POWERLEVEL9K_ASDF_PROMPT_ALWAYS_SHOW is set to false, + # it'll hide python version in this case because 3.8.1 is the same as the global version. + # POWERLEVEL9K_ASDF_SOURCES will hide python version only if the value of this parameter doesn't + # contain "local". + + # Hide tool versions that don't come from one of these sources. + # + # Available sources: + # + # - shell `asdf current` says "set by ASDF_${TOOL}_VERSION environment variable" + # - local `asdf current` says "set by /some/not/home/directory/file" + # - global `asdf current` says "set by /home/username/file" + # + # Note: If this parameter is set to (shell local global), it won't hide tools. + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_SOURCES. + typeset -g POWERLEVEL9K_ASDF_SOURCES=(shell local global) + + # If set to false, hide tool versions that are the same as global. + # + # Note: The name of this parameter doesn't reflect its meaning at all. + # Note: If this parameter is set to true, it won't hide tools. + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_PROMPT_ALWAYS_SHOW. + typeset -g POWERLEVEL9K_ASDF_PROMPT_ALWAYS_SHOW=false + + # If set to false, hide tool versions that are equal to "system". + # + # Note: If this parameter is set to true, it won't hide tools. + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_SHOW_SYSTEM. + typeset -g POWERLEVEL9K_ASDF_SHOW_SYSTEM=true + + # If set to non-empty value, hide tools unless there is a file matching the specified file pattern + # in the current directory, or its parent directory, or its grandparent directory, and so on. + # + # Note: If this parameter is set to empty value, it won't hide tools. + # Note: SHOW_ON_UPGLOB isn't specific to asdf. It works with all prompt segments. + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_SHOW_ON_UPGLOB. + # + # Example: Hide nodejs version when there is no package.json and no *.js files in the current + # directory, in `..`, in `../..` and so on. + # + # typeset -g POWERLEVEL9K_ASDF_NODEJS_SHOW_ON_UPGLOB='*.js|package.json' + typeset -g POWERLEVEL9K_ASDF_SHOW_ON_UPGLOB= + + # Ruby version from asdf. + typeset -g POWERLEVEL9K_ASDF_RUBY_FOREGROUND=1 + # typeset -g POWERLEVEL9K_ASDF_RUBY_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_RUBY_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Python version from asdf. + typeset -g POWERLEVEL9K_ASDF_PYTHON_FOREGROUND=6 + # typeset -g POWERLEVEL9K_ASDF_PYTHON_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_PYTHON_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Go version from asdf. + typeset -g POWERLEVEL9K_ASDF_GOLANG_FOREGROUND=6 + # typeset -g POWERLEVEL9K_ASDF_GOLANG_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_GOLANG_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Node.js version from asdf. + typeset -g POWERLEVEL9K_ASDF_NODEJS_FOREGROUND=2 + # typeset -g POWERLEVEL9K_ASDF_NODEJS_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_NODEJS_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Rust version from asdf. + typeset -g POWERLEVEL9K_ASDF_RUST_FOREGROUND=4 + # typeset -g POWERLEVEL9K_ASDF_RUST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_RUST_SHOW_ON_UPGLOB='*.foo|*.bar' + + # .NET Core version from asdf. + typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_FOREGROUND=5 + # typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Flutter version from asdf. + typeset -g POWERLEVEL9K_ASDF_FLUTTER_FOREGROUND=4 + # typeset -g POWERLEVEL9K_ASDF_FLUTTER_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_FLUTTER_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Lua version from asdf. + typeset -g POWERLEVEL9K_ASDF_LUA_FOREGROUND=4 + # typeset -g POWERLEVEL9K_ASDF_LUA_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_LUA_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Java version from asdf. + typeset -g POWERLEVEL9K_ASDF_JAVA_FOREGROUND=4 + # typeset -g POWERLEVEL9K_ASDF_JAVA_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_JAVA_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Perl version from asdf. + typeset -g POWERLEVEL9K_ASDF_PERL_FOREGROUND=6 + # typeset -g POWERLEVEL9K_ASDF_PERL_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_PERL_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Erlang version from asdf. + typeset -g POWERLEVEL9K_ASDF_ERLANG_FOREGROUND=1 + # typeset -g POWERLEVEL9K_ASDF_ERLANG_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_ERLANG_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Elixir version from asdf. + typeset -g POWERLEVEL9K_ASDF_ELIXIR_FOREGROUND=5 + # typeset -g POWERLEVEL9K_ASDF_ELIXIR_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_ELIXIR_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Postgres version from asdf. + typeset -g POWERLEVEL9K_ASDF_POSTGRES_FOREGROUND=6 + # typeset -g POWERLEVEL9K_ASDF_POSTGRES_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_POSTGRES_SHOW_ON_UPGLOB='*.foo|*.bar' + + # PHP version from asdf. + typeset -g POWERLEVEL9K_ASDF_PHP_FOREGROUND=5 + # typeset -g POWERLEVEL9K_ASDF_PHP_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_PHP_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Haskell version from asdf. + typeset -g POWERLEVEL9K_ASDF_HASKELL_FOREGROUND=3 + # typeset -g POWERLEVEL9K_ASDF_HASKELL_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_HASKELL_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Julia version from asdf. + typeset -g POWERLEVEL9K_ASDF_JULIA_FOREGROUND=2 + # typeset -g POWERLEVEL9K_ASDF_JULIA_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_JULIA_SHOW_ON_UPGLOB='*.foo|*.bar' + + ##########[ nordvpn: nordvpn connection status, linux only (https://nordvpn.com/) ]########### + # NordVPN connection indicator color. + typeset -g POWERLEVEL9K_NORDVPN_FOREGROUND=6 + # Hide NordVPN connection indicator when not connected. + typeset -g POWERLEVEL9K_NORDVPN_{DISCONNECTED,CONNECTING,DISCONNECTING}_CONTENT_EXPANSION= + typeset -g POWERLEVEL9K_NORDVPN_{DISCONNECTED,CONNECTING,DISCONNECTING}_VISUAL_IDENTIFIER_EXPANSION= + # Custom icon. + # typeset -g POWERLEVEL9K_NORDVPN_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #################[ ranger: ranger shell (https://github.com/ranger/ranger) ]################## + # Ranger shell color. + typeset -g POWERLEVEL9K_RANGER_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_RANGER_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######################[ nnn: nnn shell (https://github.com/jarun/nnn) ]####################### + # Nnn shell color. + typeset -g POWERLEVEL9K_NNN_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_NNN_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######################[ lf: lf shell (https://github.com/gokcehan/lf) ]####################### + # lf shell color. + typeset -g POWERLEVEL9K_LF_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_LF_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##################[ xplr: xplr shell (https://github.com/sayanarijit/xplr) ]################## + # xplr shell color. + typeset -g POWERLEVEL9K_XPLR_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_XPLR_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########################[ vim_shell: vim shell indicator (:sh) ]########################### + # Vim shell indicator color. + typeset -g POWERLEVEL9K_VIM_SHELL_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_VIM_SHELL_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######[ midnight_commander: midnight commander shell (https://midnight-commander.org/) ]###### + # Midnight Commander shell color. + typeset -g POWERLEVEL9K_MIDNIGHT_COMMANDER_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_MIDNIGHT_COMMANDER_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #[ nix_shell: nix shell (https://nixos.org/nixos/nix-pills/developing-with-nix-shell.html) ]## + # Nix shell color. + typeset -g POWERLEVEL9K_NIX_SHELL_FOREGROUND=4 + + # Display the icon of nix_shell if PATH contains a subdirectory of /nix/store. + # typeset -g POWERLEVEL9K_NIX_SHELL_INFER_FROM_PATH=false + + # Tip: If you want to see just the icon without "pure" and "impure", uncomment the next line. + # typeset -g POWERLEVEL9K_NIX_SHELL_CONTENT_EXPANSION= + + # Custom icon. + # typeset -g POWERLEVEL9K_NIX_SHELL_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##################[ chezmoi_shell: chezmoi shell (https://www.chezmoi.io/) ]################## + # chezmoi shell color. + typeset -g POWERLEVEL9K_CHEZMOI_SHELL_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_CHEZMOI_SHELL_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##################################[ disk_usage: disk usage ]################################## + # Colors for different levels of disk usage. + typeset -g POWERLEVEL9K_DISK_USAGE_NORMAL_FOREGROUND=2 + typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_FOREGROUND=3 + typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_FOREGROUND=1 + # Thresholds for different levels of disk usage (percentage points). + typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_LEVEL=90 + typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_LEVEL=95 + # If set to true, hide disk usage when below $POWERLEVEL9K_DISK_USAGE_WARNING_LEVEL percent. + typeset -g POWERLEVEL9K_DISK_USAGE_ONLY_WARNING=false + # Custom icon. + # typeset -g POWERLEVEL9K_DISK_USAGE_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######################################[ ram: free RAM ]####################################### + # RAM color. + typeset -g POWERLEVEL9K_RAM_FOREGROUND=2 + # Custom icon. + # typeset -g POWERLEVEL9K_RAM_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #####################################[ swap: used swap ]###################################### + # Swap color. + typeset -g POWERLEVEL9K_SWAP_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_SWAP_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######################################[ load: CPU load ]###################################### + # Show average CPU load over this many last minutes. Valid values are 1, 5 and 15. + typeset -g POWERLEVEL9K_LOAD_WHICH=5 + # Load color when load is under 50%. + typeset -g POWERLEVEL9K_LOAD_NORMAL_FOREGROUND=2 + # Load color when load is between 50% and 70%. + typeset -g POWERLEVEL9K_LOAD_WARNING_FOREGROUND=3 + # Load color when load is over 70%. + typeset -g POWERLEVEL9K_LOAD_CRITICAL_FOREGROUND=1 + # Custom icon. + # typeset -g POWERLEVEL9K_LOAD_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################[ todo: todo items (https://github.com/todotxt/todo.txt-cli) ]################ + # Todo color. + typeset -g POWERLEVEL9K_TODO_FOREGROUND=4 + # Hide todo when the total number of tasks is zero. + typeset -g POWERLEVEL9K_TODO_HIDE_ZERO_TOTAL=true + # Hide todo when the number of tasks after filtering is zero. + typeset -g POWERLEVEL9K_TODO_HIDE_ZERO_FILTERED=false + + # Todo format. The following parameters are available within the expansion. + # + # - P9K_TODO_TOTAL_TASK_COUNT The total number of tasks. + # - P9K_TODO_FILTERED_TASK_COUNT The number of tasks after filtering. + # + # These variables correspond to the last line of the output of `todo.sh -p ls`: + # + # TODO: 24 of 42 tasks shown + # + # Here 24 is P9K_TODO_FILTERED_TASK_COUNT and 42 is P9K_TODO_TOTAL_TASK_COUNT. + # + # typeset -g POWERLEVEL9K_TODO_CONTENT_EXPANSION='$P9K_TODO_FILTERED_TASK_COUNT' + + # Custom icon. + # typeset -g POWERLEVEL9K_TODO_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ timewarrior: timewarrior tracking status (https://timewarrior.net/) ]############ + # Timewarrior color. + typeset -g POWERLEVEL9K_TIMEWARRIOR_FOREGROUND=4 + # If the tracked task is longer than 24 characters, truncate and append "..". + # Tip: To always display tasks without truncation, delete the following parameter. + # Tip: To hide task names and display just the icon when time tracking is enabled, set the + # value of the following parameter to "". + typeset -g POWERLEVEL9K_TIMEWARRIOR_CONTENT_EXPANSION='${P9K_CONTENT:0:24}${${P9K_CONTENT:24}:+..}' + + # Custom icon. + # typeset -g POWERLEVEL9K_TIMEWARRIOR_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##############[ taskwarrior: taskwarrior task count (https://taskwarrior.org/) ]############## + # Taskwarrior color. + typeset -g POWERLEVEL9K_TASKWARRIOR_FOREGROUND=6 + + # Taskwarrior segment format. The following parameters are available within the expansion. + # + # - P9K_TASKWARRIOR_PENDING_COUNT The number of pending tasks: `task +PENDING count`. + # - P9K_TASKWARRIOR_OVERDUE_COUNT The number of overdue tasks: `task +OVERDUE count`. + # + # Zero values are represented as empty parameters. + # + # The default format: + # + # '${P9K_TASKWARRIOR_OVERDUE_COUNT:+"!$P9K_TASKWARRIOR_OVERDUE_COUNT/"}$P9K_TASKWARRIOR_PENDING_COUNT' + # + # typeset -g POWERLEVEL9K_TASKWARRIOR_CONTENT_EXPANSION='$P9K_TASKWARRIOR_PENDING_COUNT' + + # Custom icon. + # typeset -g POWERLEVEL9K_TASKWARRIOR_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################################[ cpu_arch: CPU architecture ]################################ + # CPU architecture color. + typeset -g POWERLEVEL9K_CPU_ARCH_FOREGROUND=3 + + # Hide the segment when on a specific CPU architecture. + # typeset -g POWERLEVEL9K_CPU_ARCH_X86_64_CONTENT_EXPANSION= + # typeset -g POWERLEVEL9K_CPU_ARCH_X86_64_VISUAL_IDENTIFIER_EXPANSION= + + # Custom icon. + # typeset -g POWERLEVEL9K_CPU_ARCH_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##################################[ context: user@hostname ]################################## + # Context color when running with privileges. + typeset -g POWERLEVEL9K_CONTEXT_ROOT_FOREGROUND=1 + # Context color in SSH without privileges. + typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_FOREGROUND=7 + # Default context color (no privileges, no SSH). + typeset -g POWERLEVEL9K_CONTEXT_FOREGROUND=7 + + # Context format when running with privileges: bold user@hostname. + typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE='%B%n@%m' + # Context format when in SSH without privileges: user@hostname. + typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_TEMPLATE='%n@%m' + # Default context format (no privileges, no SSH): user@hostname. + typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE='%n@%m' + + # Don't show context unless running with privileges or in SSH. + # Tip: Remove the next line to always show context. + typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_{CONTENT,VISUAL_IDENTIFIER}_EXPANSION= + + # Custom icon. + # typeset -g POWERLEVEL9K_CONTEXT_VISUAL_IDENTIFIER_EXPANSION='⭐' + # Custom prefix. + # typeset -g POWERLEVEL9K_CONTEXT_PREFIX='%fwith ' + + ###[ virtualenv: python virtual environment (https://docs.python.org/3/library/venv.html) ]### + # Python virtual environment color. + typeset -g POWERLEVEL9K_VIRTUALENV_FOREGROUND=6 + # Don't show Python version next to the virtual environment name. + typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_PYTHON_VERSION=false + # If set to "false", won't show virtualenv if pyenv is already shown. + # If set to "if-different", won't show virtualenv if it's the same as pyenv. + typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_WITH_PYENV=false + # Separate environment name from Python version only with a space. + typeset -g POWERLEVEL9K_VIRTUALENV_{LEFT,RIGHT}_DELIMITER= + # Custom icon. + # typeset -g POWERLEVEL9K_VIRTUALENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #####################[ anaconda: conda environment (https://conda.io/) ]###################### + # Anaconda environment color. + typeset -g POWERLEVEL9K_ANACONDA_FOREGROUND=6 + + # Anaconda segment format. The following parameters are available within the expansion. + # + # - CONDA_PREFIX Absolute path to the active Anaconda/Miniconda environment. + # - CONDA_DEFAULT_ENV Name of the active Anaconda/Miniconda environment. + # - CONDA_PROMPT_MODIFIER Configurable prompt modifier (see below). + # - P9K_ANACONDA_PYTHON_VERSION Current python version (python --version). + # + # CONDA_PROMPT_MODIFIER can be configured with the following command: + # + # conda config --set env_prompt '({default_env}) ' + # + # The last argument is a Python format string that can use the following variables: + # + # - prefix The same as CONDA_PREFIX. + # - default_env The same as CONDA_DEFAULT_ENV. + # - name The last segment of CONDA_PREFIX. + # - stacked_env Comma-separated list of names in the environment stack. The first element is + # always the same as default_env. + # + # Note: '({default_env}) ' is the default value of env_prompt. + # + # The default value of POWERLEVEL9K_ANACONDA_CONTENT_EXPANSION expands to $CONDA_PROMPT_MODIFIER + # without the surrounding parentheses, or to the last path component of CONDA_PREFIX if the former + # is empty. + typeset -g POWERLEVEL9K_ANACONDA_CONTENT_EXPANSION='${${${${CONDA_PROMPT_MODIFIER#\(}% }%\)}:-${CONDA_PREFIX:t}}' + + # Custom icon. + # typeset -g POWERLEVEL9K_ANACONDA_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################[ pyenv: python environment (https://github.com/pyenv/pyenv) ]################ + # Pyenv color. + typeset -g POWERLEVEL9K_PYENV_FOREGROUND=6 + # Hide python version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_PYENV_SOURCES=(shell local global) + # If set to false, hide python version if it's the same as global: + # $(pyenv version-name) == $(pyenv global). + typeset -g POWERLEVEL9K_PYENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide python version if it's equal to "system". + typeset -g POWERLEVEL9K_PYENV_SHOW_SYSTEM=true + + # Pyenv segment format. The following parameters are available within the expansion. + # + # - P9K_CONTENT Current pyenv environment (pyenv version-name). + # - P9K_PYENV_PYTHON_VERSION Current python version (python --version). + # + # The default format has the following logic: + # + # 1. Display just "$P9K_CONTENT" if it's equal to "$P9K_PYENV_PYTHON_VERSION" or + # starts with "$P9K_PYENV_PYTHON_VERSION/". + # 2. Otherwise display "$P9K_CONTENT $P9K_PYENV_PYTHON_VERSION". + typeset -g POWERLEVEL9K_PYENV_CONTENT_EXPANSION='${P9K_CONTENT}${${P9K_CONTENT:#$P9K_PYENV_PYTHON_VERSION(|/*)}:+ $P9K_PYENV_PYTHON_VERSION}' + + # Custom icon. + # typeset -g POWERLEVEL9K_PYENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################[ goenv: go environment (https://github.com/syndbg/goenv) ]################ + # Goenv color. + typeset -g POWERLEVEL9K_GOENV_FOREGROUND=6 + # Hide go version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_GOENV_SOURCES=(shell local global) + # If set to false, hide go version if it's the same as global: + # $(goenv version-name) == $(goenv global). + typeset -g POWERLEVEL9K_GOENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide go version if it's equal to "system". + typeset -g POWERLEVEL9K_GOENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_GOENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ nodenv: node.js version from nodenv (https://github.com/nodenv/nodenv) ]########## + # Nodenv color. + typeset -g POWERLEVEL9K_NODENV_FOREGROUND=2 + # Hide node version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_NODENV_SOURCES=(shell local global) + # If set to false, hide node version if it's the same as global: + # $(nodenv version-name) == $(nodenv global). + typeset -g POWERLEVEL9K_NODENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide node version if it's equal to "system". + typeset -g POWERLEVEL9K_NODENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_NODENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##############[ nvm: node.js version from nvm (https://github.com/nvm-sh/nvm) ]############### + # Nvm color. + typeset -g POWERLEVEL9K_NVM_FOREGROUND=2 + # If set to false, hide node version if it's the same as default: + # $(nvm version current) == $(nvm version default). + typeset -g POWERLEVEL9K_NVM_PROMPT_ALWAYS_SHOW=false + # If set to false, hide node version if it's equal to "system". + typeset -g POWERLEVEL9K_NVM_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_NVM_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ############[ nodeenv: node.js environment (https://github.com/ekalinin/nodeenv) ]############ + # Nodeenv color. + typeset -g POWERLEVEL9K_NODEENV_FOREGROUND=2 + # Don't show Node version next to the environment name. + typeset -g POWERLEVEL9K_NODEENV_SHOW_NODE_VERSION=false + # Separate environment name from Node version only with a space. + typeset -g POWERLEVEL9K_NODEENV_{LEFT,RIGHT}_DELIMITER= + # Custom icon. + # typeset -g POWERLEVEL9K_NODEENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##############################[ node_version: node.js version ]############################### + # Node version color. + typeset -g POWERLEVEL9K_NODE_VERSION_FOREGROUND=2 + # Show node version only when in a directory tree containing package.json. + typeset -g POWERLEVEL9K_NODE_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_NODE_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #######################[ go_version: go version (https://golang.org) ]######################## + # Go version color. + typeset -g POWERLEVEL9K_GO_VERSION_FOREGROUND=6 + # Show go version only when in a go project subdirectory. + typeset -g POWERLEVEL9K_GO_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_GO_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #################[ rust_version: rustc version (https://www.rust-lang.org) ]################## + # Rust version color. + typeset -g POWERLEVEL9K_RUST_VERSION_FOREGROUND=4 + # Show rust version only when in a rust project subdirectory. + typeset -g POWERLEVEL9K_RUST_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_RUST_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###############[ dotnet_version: .NET version (https://dotnet.microsoft.com) ]################ + # .NET version color. + typeset -g POWERLEVEL9K_DOTNET_VERSION_FOREGROUND=5 + # Show .NET version only when in a .NET project subdirectory. + typeset -g POWERLEVEL9K_DOTNET_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_DOTNET_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #####################[ php_version: php version (https://www.php.net/) ]###################### + # PHP version color. + typeset -g POWERLEVEL9K_PHP_VERSION_FOREGROUND=5 + # Show PHP version only when in a PHP project subdirectory. + typeset -g POWERLEVEL9K_PHP_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_PHP_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ laravel_version: laravel php framework version (https://laravel.com/) ]########### + # Laravel version color. + typeset -g POWERLEVEL9K_LARAVEL_VERSION_FOREGROUND=1 + # Custom icon. + # typeset -g POWERLEVEL9K_LARAVEL_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ####################[ java_version: java version (https://www.java.com/) ]#################### + # Java version color. + typeset -g POWERLEVEL9K_JAVA_VERSION_FOREGROUND=4 + # Show java version only when in a java project subdirectory. + typeset -g POWERLEVEL9K_JAVA_VERSION_PROJECT_ONLY=true + # Show brief version. + typeset -g POWERLEVEL9K_JAVA_VERSION_FULL=false + # Custom icon. + # typeset -g POWERLEVEL9K_JAVA_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###[ package: name@version from package.json (https://docs.npmjs.com/files/package.json) ]#### + # Package color. + typeset -g POWERLEVEL9K_PACKAGE_FOREGROUND=6 + # Package format. The following parameters are available within the expansion. + # + # - P9K_PACKAGE_NAME The value of `name` field in package.json. + # - P9K_PACKAGE_VERSION The value of `version` field in package.json. + # + # typeset -g POWERLEVEL9K_PACKAGE_CONTENT_EXPANSION='${P9K_PACKAGE_NAME//\%/%%}@${P9K_PACKAGE_VERSION//\%/%%}' + # Custom icon. + # typeset -g POWERLEVEL9K_PACKAGE_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #############[ rbenv: ruby version from rbenv (https://github.com/rbenv/rbenv) ]############## + # Rbenv color. + typeset -g POWERLEVEL9K_RBENV_FOREGROUND=1 + # Hide ruby version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_RBENV_SOURCES=(shell local global) + # If set to false, hide ruby version if it's the same as global: + # $(rbenv version-name) == $(rbenv global). + typeset -g POWERLEVEL9K_RBENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide ruby version if it's equal to "system". + typeset -g POWERLEVEL9K_RBENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_RBENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #######################[ rvm: ruby version from rvm (https://rvm.io) ]######################## + # Rvm color. + typeset -g POWERLEVEL9K_RVM_FOREGROUND=1 + # Don't show @gemset at the end. + typeset -g POWERLEVEL9K_RVM_SHOW_GEMSET=false + # Don't show ruby- at the front. + typeset -g POWERLEVEL9K_RVM_SHOW_PREFIX=false + # Custom icon. + # typeset -g POWERLEVEL9K_RVM_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ fvm: flutter version management (https://github.com/leoafarias/fvm) ]############ + # Fvm color. + typeset -g POWERLEVEL9K_FVM_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_FVM_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ luaenv: lua version from luaenv (https://github.com/cehoffman/luaenv) ]########### + # Lua color. + typeset -g POWERLEVEL9K_LUAENV_FOREGROUND=4 + # Hide lua version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_LUAENV_SOURCES=(shell local global) + # If set to false, hide lua version if it's the same as global: + # $(luaenv version-name) == $(luaenv global). + typeset -g POWERLEVEL9K_LUAENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide lua version if it's equal to "system". + typeset -g POWERLEVEL9K_LUAENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_LUAENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###############[ jenv: java version from jenv (https://github.com/jenv/jenv) ]################ + # Java color. + typeset -g POWERLEVEL9K_JENV_FOREGROUND=4 + # Hide java version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_JENV_SOURCES=(shell local global) + # If set to false, hide java version if it's the same as global: + # $(jenv version-name) == $(jenv global). + typeset -g POWERLEVEL9K_JENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide java version if it's equal to "system". + typeset -g POWERLEVEL9K_JENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_JENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ plenv: perl version from plenv (https://github.com/tokuhirom/plenv) ]############ + # Perl color. + typeset -g POWERLEVEL9K_PLENV_FOREGROUND=6 + # Hide perl version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_PLENV_SOURCES=(shell local global) + # If set to false, hide perl version if it's the same as global: + # $(plenv version-name) == $(plenv global). + typeset -g POWERLEVEL9K_PLENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide perl version if it's equal to "system". + typeset -g POWERLEVEL9K_PLENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_PLENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ perlbrew: perl version from perlbrew (https://github.com/gugod/App-perlbrew) ]############ + # Perlbrew color. + typeset -g POWERLEVEL9K_PERLBREW_FOREGROUND=67 + # Show perlbrew version only when in a perl project subdirectory. + typeset -g POWERLEVEL9K_PERLBREW_PROJECT_ONLY=true + # Don't show "perl-" at the front. + typeset -g POWERLEVEL9K_PERLBREW_SHOW_PREFIX=false + # Custom icon. + # typeset -g POWERLEVEL9K_PERLBREW_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ############[ phpenv: php version from phpenv (https://github.com/phpenv/phpenv) ]############ + # PHP color. + typeset -g POWERLEVEL9K_PHPENV_FOREGROUND=5 + # Hide php version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_PHPENV_SOURCES=(shell local global) + # If set to false, hide php version if it's the same as global: + # $(phpenv version-name) == $(phpenv global). + typeset -g POWERLEVEL9K_PHPENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide php version if it's equal to "system". + typeset -g POWERLEVEL9K_PHPENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_PHPENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #######[ scalaenv: scala version from scalaenv (https://github.com/scalaenv/scalaenv) ]####### + # Scala color. + typeset -g POWERLEVEL9K_SCALAENV_FOREGROUND=1 + # Hide scala version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_SCALAENV_SOURCES=(shell local global) + # If set to false, hide scala version if it's the same as global: + # $(scalaenv version-name) == $(scalaenv global). + typeset -g POWERLEVEL9K_SCALAENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide scala version if it's equal to "system". + typeset -g POWERLEVEL9K_SCALAENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_SCALAENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ haskell_stack: haskell version from stack (https://haskellstack.org/) ]########### + # Haskell color. + typeset -g POWERLEVEL9K_HASKELL_STACK_FOREGROUND=3 + # Hide haskell version if it doesn't come from one of these sources. + # + # shell: version is set by STACK_YAML + # local: version is set by stack.yaml up the directory tree + # global: version is set by the implicit global project (~/.stack/global-project/stack.yaml) + typeset -g POWERLEVEL9K_HASKELL_STACK_SOURCES=(shell local) + # If set to false, hide haskell version if it's the same as in the implicit global project. + typeset -g POWERLEVEL9K_HASKELL_STACK_ALWAYS_SHOW=true + # Custom icon. + # typeset -g POWERLEVEL9K_HASKELL_STACK_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #############[ kubecontext: current kubernetes context (https://kubernetes.io/) ]############# + # Show kubecontext only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show kubecontext. + typeset -g POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm|kubens|kubectx|oc|istioctl|kogito|k9s|helmfile|flux|fluxctl|stern|kubeseal|skaffold|kubent|kubecolor|cmctl|sparkctl' + + # Kubernetes context classes for the purpose of using different colors, icons and expansions with + # different contexts. + # + # POWERLEVEL9K_KUBECONTEXT_CLASSES is an array with even number of elements. The first element + # in each pair defines a pattern against which the current kubernetes context gets matched. + # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) + # that gets matched. If you unset all POWERLEVEL9K_KUBECONTEXT_*CONTENT_EXPANSION parameters, + # you'll see this value in your prompt. The second element of each pair in + # POWERLEVEL9K_KUBECONTEXT_CLASSES defines the context class. Patterns are tried in order. The + # first match wins. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=( + # '*prod*' PROD + # '*test*' TEST + # '*' DEFAULT) + # + # If your current kubernetes context is "deathray-testing/default", its class is TEST + # because "deathray-testing/default" doesn't match the pattern '*prod*' but does match '*test*'. + # + # You can define different colors, icons and content expansions for different classes: + # + # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_FOREGROUND=3 + # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' + typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=( + # '*prod*' PROD # These values are examples that are unlikely + # '*test*' TEST # to match your needs. Customize them as needed. + '*' DEFAULT) + typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_FOREGROUND=5 + # typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # Use POWERLEVEL9K_KUBECONTEXT_CONTENT_EXPANSION to specify the content displayed by kubecontext + # segment. Parameter expansions are very flexible and fast, too. See reference: + # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion. + # + # Within the expansion the following parameters are always available: + # + # - P9K_CONTENT The content that would've been displayed if there was no content + # expansion defined. + # - P9K_KUBECONTEXT_NAME The current context's name. Corresponds to column NAME in the + # output of `kubectl config get-contexts`. + # - P9K_KUBECONTEXT_CLUSTER The current context's cluster. Corresponds to column CLUSTER in the + # output of `kubectl config get-contexts`. + # - P9K_KUBECONTEXT_NAMESPACE The current context's namespace. Corresponds to column NAMESPACE + # in the output of `kubectl config get-contexts`. If there is no + # namespace, the parameter is set to "default". + # - P9K_KUBECONTEXT_USER The current context's user. Corresponds to column AUTHINFO in the + # output of `kubectl config get-contexts`. + # + # If the context points to Google Kubernetes Engine (GKE) or Elastic Kubernetes Service (EKS), + # the following extra parameters are available: + # + # - P9K_KUBECONTEXT_CLOUD_NAME Either "gke" or "eks". + # - P9K_KUBECONTEXT_CLOUD_ACCOUNT Account/project ID. + # - P9K_KUBECONTEXT_CLOUD_ZONE Availability zone. + # - P9K_KUBECONTEXT_CLOUD_CLUSTER Cluster. + # + # P9K_KUBECONTEXT_CLOUD_* parameters are derived from P9K_KUBECONTEXT_CLUSTER. For example, + # if P9K_KUBECONTEXT_CLUSTER is "gke_my-account_us-east1-a_my-cluster-01": + # + # - P9K_KUBECONTEXT_CLOUD_NAME=gke + # - P9K_KUBECONTEXT_CLOUD_ACCOUNT=my-account + # - P9K_KUBECONTEXT_CLOUD_ZONE=us-east1-a + # - P9K_KUBECONTEXT_CLOUD_CLUSTER=my-cluster-01 + # + # If P9K_KUBECONTEXT_CLUSTER is "arn:aws:eks:us-east-1:123456789012:cluster/my-cluster-01": + # + # - P9K_KUBECONTEXT_CLOUD_NAME=eks + # - P9K_KUBECONTEXT_CLOUD_ACCOUNT=123456789012 + # - P9K_KUBECONTEXT_CLOUD_ZONE=us-east-1 + # - P9K_KUBECONTEXT_CLOUD_CLUSTER=my-cluster-01 + typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION= + # Show P9K_KUBECONTEXT_CLOUD_CLUSTER if it's not empty and fall back to P9K_KUBECONTEXT_NAME. + POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${P9K_KUBECONTEXT_CLOUD_CLUSTER:-${P9K_KUBECONTEXT_NAME}}' + # Append the current context's namespace if it's not "default". + POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${${:-/$P9K_KUBECONTEXT_NAMESPACE}:#/default}' + + # Custom prefix. + # typeset -g POWERLEVEL9K_KUBECONTEXT_PREFIX='%fat ' + + ################[ terraform: terraform workspace (https://www.terraform.io) ]################# + # Don't show terraform workspace if it's literally "default". + typeset -g POWERLEVEL9K_TERRAFORM_SHOW_DEFAULT=false + # POWERLEVEL9K_TERRAFORM_CLASSES is an array with even number of elements. The first element + # in each pair defines a pattern against which the current terraform workspace gets matched. + # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) + # that gets matched. If you unset all POWERLEVEL9K_TERRAFORM_*CONTENT_EXPANSION parameters, + # you'll see this value in your prompt. The second element of each pair in + # POWERLEVEL9K_TERRAFORM_CLASSES defines the workspace class. Patterns are tried in order. The + # first match wins. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_TERRAFORM_CLASSES=( + # '*prod*' PROD + # '*test*' TEST + # '*' OTHER) + # + # If your current terraform workspace is "project_test", its class is TEST because "project_test" + # doesn't match the pattern '*prod*' but does match '*test*'. + # + # You can define different colors, icons and content expansions for different classes: + # + # typeset -g POWERLEVEL9K_TERRAFORM_TEST_FOREGROUND=2 + # typeset -g POWERLEVEL9K_TERRAFORM_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_TERRAFORM_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' + typeset -g POWERLEVEL9K_TERRAFORM_CLASSES=( + # '*prod*' PROD # These values are examples that are unlikely + # '*test*' TEST # to match your needs. Customize them as needed. + '*' OTHER) + typeset -g POWERLEVEL9K_TERRAFORM_OTHER_FOREGROUND=4 + # typeset -g POWERLEVEL9K_TERRAFORM_OTHER_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #############[ terraform_version: terraform version (https://www.terraform.io) ]############## + # Terraform version color. + typeset -g POWERLEVEL9K_TERRAFORM_VERSION_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_TERRAFORM_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #[ aws: aws profile (https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) ]# + # Show aws only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show aws. + typeset -g POWERLEVEL9K_AWS_SHOW_ON_COMMAND='aws|awless|terraform|pulumi|terragrunt' + + # POWERLEVEL9K_AWS_CLASSES is an array with even number of elements. The first element + # in each pair defines a pattern against which the current AWS profile gets matched. + # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) + # that gets matched. If you unset all POWERLEVEL9K_AWS_*CONTENT_EXPANSION parameters, + # you'll see this value in your prompt. The second element of each pair in + # POWERLEVEL9K_AWS_CLASSES defines the profile class. Patterns are tried in order. The + # first match wins. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_AWS_CLASSES=( + # '*prod*' PROD + # '*test*' TEST + # '*' DEFAULT) + # + # If your current AWS profile is "company_test", its class is TEST + # because "company_test" doesn't match the pattern '*prod*' but does match '*test*'. + # + # You can define different colors, icons and content expansions for different classes: + # + # typeset -g POWERLEVEL9K_AWS_TEST_FOREGROUND=2 + # typeset -g POWERLEVEL9K_AWS_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_AWS_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' + typeset -g POWERLEVEL9K_AWS_CLASSES=( + # '*prod*' PROD # These values are examples that are unlikely + # '*test*' TEST # to match your needs. Customize them as needed. + '*' DEFAULT) + typeset -g POWERLEVEL9K_AWS_DEFAULT_FOREGROUND=3 + # typeset -g POWERLEVEL9K_AWS_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # AWS segment format. The following parameters are available within the expansion. + # + # - P9K_AWS_PROFILE The name of the current AWS profile. + # - P9K_AWS_REGION The region associated with the current AWS profile. + typeset -g POWERLEVEL9K_AWS_CONTENT_EXPANSION='${P9K_AWS_PROFILE//\%/%%}${P9K_AWS_REGION:+ ${P9K_AWS_REGION//\%/%%}}' + + #[ aws_eb_env: aws elastic beanstalk environment (https://aws.amazon.com/elasticbeanstalk/) ]# + # AWS Elastic Beanstalk environment color. + typeset -g POWERLEVEL9K_AWS_EB_ENV_FOREGROUND=2 + # Custom icon. + # typeset -g POWERLEVEL9K_AWS_EB_ENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ azure: azure account name (https://docs.microsoft.com/en-us/cli/azure) ]########## + # Show azure only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show azure. + typeset -g POWERLEVEL9K_AZURE_SHOW_ON_COMMAND='az|terraform|pulumi|terragrunt' + # Azure account name color. + typeset -g POWERLEVEL9K_AZURE_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_AZURE_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ gcloud: google cloud account and project (https://cloud.google.com/) ]########### + # Show gcloud only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show gcloud. + typeset -g POWERLEVEL9K_GCLOUD_SHOW_ON_COMMAND='gcloud|gcs|gsutil' + # Google cloud color. + typeset -g POWERLEVEL9K_GCLOUD_FOREGROUND=4 + + # Google cloud format. Change the value of POWERLEVEL9K_GCLOUD_PARTIAL_CONTENT_EXPANSION and/or + # POWERLEVEL9K_GCLOUD_COMPLETE_CONTENT_EXPANSION if the default is too verbose or not informative + # enough. You can use the following parameters in the expansions. Each of them corresponds to the + # output of `gcloud` tool. + # + # Parameter | Source + # -------------------------|-------------------------------------------------------------------- + # P9K_GCLOUD_CONFIGURATION | gcloud config configurations list --format='value(name)' + # P9K_GCLOUD_ACCOUNT | gcloud config get-value account + # P9K_GCLOUD_PROJECT_ID | gcloud config get-value project + # P9K_GCLOUD_PROJECT_NAME | gcloud projects describe $P9K_GCLOUD_PROJECT_ID --format='value(name)' + # + # Note: ${VARIABLE//\%/%%} expands to ${VARIABLE} with all occurrences of '%' replaced with '%%'. + # + # Obtaining project name requires sending a request to Google servers. This can take a long time + # and even fail. When project name is unknown, P9K_GCLOUD_PROJECT_NAME is not set and gcloud + # prompt segment is in state PARTIAL. When project name gets known, P9K_GCLOUD_PROJECT_NAME gets + # set and gcloud prompt segment transitions to state COMPLETE. + # + # You can customize the format, icon and colors of gcloud segment separately for states PARTIAL + # and COMPLETE. You can also hide gcloud in state PARTIAL by setting + # POWERLEVEL9K_GCLOUD_PARTIAL_VISUAL_IDENTIFIER_EXPANSION and + # POWERLEVEL9K_GCLOUD_PARTIAL_CONTENT_EXPANSION to empty. + typeset -g POWERLEVEL9K_GCLOUD_PARTIAL_CONTENT_EXPANSION='${P9K_GCLOUD_PROJECT_ID//\%/%%}' + typeset -g POWERLEVEL9K_GCLOUD_COMPLETE_CONTENT_EXPANSION='${P9K_GCLOUD_PROJECT_NAME//\%/%%}' + + # Send a request to Google (by means of `gcloud projects describe ...`) to obtain project name + # this often. Negative value disables periodic polling. In this mode project name is retrieved + # only when the current configuration, account or project id changes. + typeset -g POWERLEVEL9K_GCLOUD_REFRESH_PROJECT_NAME_SECONDS=60 + + # Custom icon. + # typeset -g POWERLEVEL9K_GCLOUD_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #[ google_app_cred: google application credentials (https://cloud.google.com/docs/authentication/production) ]# + # Show google_app_cred only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show google_app_cred. + typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_SHOW_ON_COMMAND='terraform|pulumi|terragrunt' + + # Google application credentials classes for the purpose of using different colors, icons and + # expansions with different credentials. + # + # POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES is an array with even number of elements. The first + # element in each pair defines a pattern against which the current kubernetes context gets + # matched. More specifically, it's P9K_CONTENT prior to the application of context expansion + # (see below) that gets matched. If you unset all POWERLEVEL9K_GOOGLE_APP_CRED_*CONTENT_EXPANSION + # parameters, you'll see this value in your prompt. The second element of each pair in + # POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES defines the context class. Patterns are tried in order. + # The first match wins. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES=( + # '*:*prod*:*' PROD + # '*:*test*:*' TEST + # '*' DEFAULT) + # + # If your current Google application credentials is "service_account deathray-testing x@y.com", + # its class is TEST because it doesn't match the pattern '* *prod* *' but does match '* *test* *'. + # + # You can define different colors, icons and content expansions for different classes: + # + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_TEST_FOREGROUND=3 + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_TEST_CONTENT_EXPANSION='$P9K_GOOGLE_APP_CRED_PROJECT_ID' + typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES=( + # '*:*prod*:*' PROD # These values are examples that are unlikely + # '*:*test*:*' TEST # to match your needs. Customize them as needed. + '*' DEFAULT) + typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_FOREGROUND=5 + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # Use POWERLEVEL9K_GOOGLE_APP_CRED_CONTENT_EXPANSION to specify the content displayed by + # google_app_cred segment. Parameter expansions are very flexible and fast, too. See reference: + # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion. + # + # You can use the following parameters in the expansion. Each of them corresponds to one of the + # fields in the JSON file pointed to by GOOGLE_APPLICATION_CREDENTIALS. + # + # Parameter | JSON key file field + # ---------------------------------+--------------- + # P9K_GOOGLE_APP_CRED_TYPE | type + # P9K_GOOGLE_APP_CRED_PROJECT_ID | project_id + # P9K_GOOGLE_APP_CRED_CLIENT_EMAIL | client_email + # + # Note: ${VARIABLE//\%/%%} expands to ${VARIABLE} with all occurrences of '%' replaced by '%%'. + typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_CONTENT_EXPANSION='${P9K_GOOGLE_APP_CRED_PROJECT_ID//\%/%%}' + + ##############[ toolbox: toolbox name (https://github.com/containers/toolbox) ]############### + # Toolbox color. + typeset -g POWERLEVEL9K_TOOLBOX_FOREGROUND=3 + # Don't display the name of the toolbox if it matches fedora-toolbox-*. + typeset -g POWERLEVEL9K_TOOLBOX_CONTENT_EXPANSION='${P9K_TOOLBOX_NAME:#fedora-toolbox-*}' + # Custom icon. + # typeset -g POWERLEVEL9K_TOOLBOX_VISUAL_IDENTIFIER_EXPANSION='⭐' + # Custom prefix. + # typeset -g POWERLEVEL9K_TOOLBOX_PREFIX='%fin ' + + ###############################[ public_ip: public IP address ]############################### + # Public IP color. + typeset -g POWERLEVEL9K_PUBLIC_IP_FOREGROUND=6 + # Custom icon. + # typeset -g POWERLEVEL9K_PUBLIC_IP_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ########################[ vpn_ip: virtual private network indicator ]######################### + # VPN IP color. + typeset -g POWERLEVEL9K_VPN_IP_FOREGROUND=3 + # When on VPN, show just an icon without the IP address. + # Tip: To display the private IP address when on VPN, remove the next line. + typeset -g POWERLEVEL9K_VPN_IP_CONTENT_EXPANSION= + # Regular expression for the VPN network interface. Run `ifconfig` or `ip -4 a show` while on VPN + # to see the name of the interface. + typeset -g POWERLEVEL9K_VPN_IP_INTERFACE='(gpd|wg|(.*tun)|tailscale)[0-9]*|(zt.*)' + # If set to true, show one segment per matching network interface. If set to false, show only + # one segment corresponding to the first matching network interface. + # Tip: If you set it to true, you'll probably want to unset POWERLEVEL9K_VPN_IP_CONTENT_EXPANSION. + typeset -g POWERLEVEL9K_VPN_IP_SHOW_ALL=false + # Custom icon. + # typeset -g POWERLEVEL9K_VPN_IP_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ ip: ip address and bandwidth usage for a specified network interface ]########### + # IP color. + typeset -g POWERLEVEL9K_IP_FOREGROUND=4 + # The following parameters are accessible within the expansion: + # + # Parameter | Meaning + # ----------------------+------------------------------------------- + # P9K_IP_IP | IP address + # P9K_IP_INTERFACE | network interface + # P9K_IP_RX_BYTES | total number of bytes received + # P9K_IP_TX_BYTES | total number of bytes sent + # P9K_IP_RX_BYTES_DELTA | number of bytes received since last prompt + # P9K_IP_TX_BYTES_DELTA | number of bytes sent since last prompt + # P9K_IP_RX_RATE | receive rate (since last prompt) + # P9K_IP_TX_RATE | send rate (since last prompt) + typeset -g POWERLEVEL9K_IP_CONTENT_EXPANSION='$P9K_IP_IP${P9K_IP_RX_RATE:+ %2F<$P9K_IP_RX_RATE}${P9K_IP_TX_RATE:+ %3F>$P9K_IP_TX_RATE}' + # Show information for the first network interface whose name matches this regular expression. + # Run `ifconfig` or `ip -4 a show` to see the names of all network interfaces. + typeset -g POWERLEVEL9K_IP_INTERFACE='[ew].*' + # Custom icon. + # typeset -g POWERLEVEL9K_IP_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #########################[ proxy: system-wide http/https/ftp proxy ]########################## + # Proxy color. + typeset -g POWERLEVEL9K_PROXY_FOREGROUND=2 + # Custom icon. + # typeset -g POWERLEVEL9K_PROXY_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################################[ battery: internal battery ]################################# + # Show battery in red when it's below this level and not connected to power supply. + typeset -g POWERLEVEL9K_BATTERY_LOW_THRESHOLD=20 + typeset -g POWERLEVEL9K_BATTERY_LOW_FOREGROUND=1 + # Show battery in green when it's charging or fully charged. + typeset -g POWERLEVEL9K_BATTERY_{CHARGING,CHARGED}_FOREGROUND=2 + # Show battery in yellow when it's discharging. + typeset -g POWERLEVEL9K_BATTERY_DISCONNECTED_FOREGROUND=3 + # Battery pictograms going from low to high level of charge. + typeset -g POWERLEVEL9K_BATTERY_STAGES=('battery') + # Don't show the remaining time to charge/discharge. + typeset -g POWERLEVEL9K_BATTERY_VERBOSE=false + + #####################################[ wifi: wifi speed ]##################################### + # WiFi color. + typeset -g POWERLEVEL9K_WIFI_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_WIFI_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # Use different colors and icons depending on signal strength ($P9K_WIFI_BARS). + # + # # Wifi colors and icons for different signal strength levels (low to high). + # typeset -g my_wifi_fg=(4 4 4 4 4) # <-- change these values + # typeset -g my_wifi_icon=('WiFi' 'WiFi' 'WiFi' 'WiFi' 'WiFi') # <-- change these values + # + # typeset -g POWERLEVEL9K_WIFI_CONTENT_EXPANSION='%F{${my_wifi_fg[P9K_WIFI_BARS+1]}}$P9K_WIFI_LAST_TX_RATE Mbps' + # typeset -g POWERLEVEL9K_WIFI_VISUAL_IDENTIFIER_EXPANSION='%F{${my_wifi_fg[P9K_WIFI_BARS+1]}}${my_wifi_icon[P9K_WIFI_BARS+1]}' + # + # The following parameters are accessible within the expansions: + # + # Parameter | Meaning + # ----------------------+--------------- + # P9K_WIFI_SSID | service set identifier, a.k.a. network name + # P9K_WIFI_LINK_AUTH | authentication protocol such as "wpa2-psk" or "none"; empty if unknown + # P9K_WIFI_LAST_TX_RATE | wireless transmit rate in megabits per second + # P9K_WIFI_RSSI | signal strength in dBm, from -120 to 0 + # P9K_WIFI_NOISE | noise in dBm, from -120 to 0 + # P9K_WIFI_BARS | signal strength in bars, from 0 to 4 (derived from P9K_WIFI_RSSI and P9K_WIFI_NOISE) + + ####################################[ time: current time ]#################################### + # Current time color. + typeset -g POWERLEVEL9K_TIME_FOREGROUND=6 + # Format for the current time: 09:51:02. See `man 3 strftime`. + typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}' + # If set to true, time will update when you hit enter. This way prompts for the past + # commands will contain the start times of their commands as opposed to the default + # behavior where they contain the end times of their preceding commands. + typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false + # Custom icon. + typeset -g POWERLEVEL9K_TIME_VISUAL_IDENTIFIER_EXPANSION= + # Custom prefix. + # typeset -g POWERLEVEL9K_TIME_PREFIX='%fat ' + + # Example of a user-defined prompt segment. Function prompt_example will be called on every + # prompt if `example` prompt segment is added to POWERLEVEL9K_LEFT_PROMPT_ELEMENTS or + # POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS. It displays an icon and green text greeting the user. + # + # Type `p10k help segment` for documentation and a more sophisticated example. + function prompt_example() { + p10k segment -f 2 -i '*' -t 'hello, %n' + } + + # User-defined prompt segments may optionally provide an instant_prompt_* function. Its job + # is to generate the prompt segment for display in instant prompt. See + # https://github.com/romkatv/powerlevel10k/blob/master/README.md#instant-prompt. + # + # Powerlevel10k will call instant_prompt_* at the same time as the regular prompt_* function + # and will record all `p10k segment` calls it makes. When displaying instant prompt, Powerlevel10k + # will replay these calls without actually calling instant_prompt_*. It is imperative that + # instant_prompt_* always makes the same `p10k segment` calls regardless of environment. If this + # rule is not observed, the content of instant prompt will be incorrect. + # + # Usually, you should either not define instant_prompt_* or simply call prompt_* from it. If + # instant_prompt_* is not defined for a segment, the segment won't be shown in instant prompt. + function instant_prompt_example() { + # Since prompt_example always makes the same `p10k segment` calls, we can call it from + # instant_prompt_example. This will give us the same `example` prompt segment in the instant + # and regular prompts. + prompt_example + } + + # User-defined prompt segments can be customized the same way as built-in segments. + # typeset -g POWERLEVEL9K_EXAMPLE_FOREGROUND=208 + # typeset -g POWERLEVEL9K_EXAMPLE_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # Transient prompt works similarly to the builtin transient_rprompt option. It trims down prompt + # when accepting a command line. Supported values: + # + # - off: Don't change prompt when accepting a command line. + # - always: Trim down prompt when accepting a command line. + # - same-dir: Trim down prompt when accepting a command line unless this is the first command + # typed after changing current working directory. + typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=always + + # Instant prompt mode. + # + # - off: Disable instant prompt. Choose this if you've tried instant prompt and found + # it incompatible with your zsh configuration files. + # - quiet: Enable instant prompt and don't print warnings when detecting console output + # during zsh initialization. Choose this if you've read and understood + # https://github.com/romkatv/powerlevel10k/blob/master/README.md#instant-prompt. + # - verbose: Enable instant prompt and print a warning when detecting console output during + # zsh initialization. Choose this if you've never tried instant prompt, haven't + # seen the warning, or if you are unsure what this all means. + typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet + + # Hot reload allows you to change POWERLEVEL9K options after Powerlevel10k has been initialized. + # For example, you can type POWERLEVEL9K_BACKGROUND=red and see your prompt turn red. Hot reload + # can slow down prompt by 1-2 milliseconds, so it's better to keep it turned off unless you + # really need it. + typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true + + # If p10k is already loaded, reload configuration. + # This works even with POWERLEVEL9K_DISABLE_HOT_RELOAD=true. + (( ! $+functions[p10k] )) || p10k reload +} + +# Tell `p10k configure` which file it should overwrite. +typeset -g POWERLEVEL9K_CONFIG_FILE=${${(%):-%x}:a} + +(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]} +'builtin' 'unset' 'p10k_config_opts' diff --git a/.config/zsh/.p10k.zsh b/.config/zsh/.p10k.zsh new file mode 100644 index 0000000..4af8e3a --- /dev/null +++ b/.config/zsh/.p10k.zsh @@ -0,0 +1,1713 @@ +# Generated by Powerlevel10k configuration wizard on 2023-11-29 at 06:50 PKT. +# Based on romkatv/powerlevel10k/config/p10k-lean-8colors.zsh, checksum 27973. +# Wizard options: nerdfont-v3 + powerline, large icons, unicode, lean_8colors, 1 line, +# sparse, few icons, concise, transient_prompt, instant_prompt=auto-quiet. +# Type `p10k configure` to generate another config. +# +# Config for Powerlevel10k with 8-color lean prompt style. Type `p10k configure` to generate +# your own config based on it. +# +# Tip: Looking for a nice color? Here's a one-liner to print colormap. +# +# for i in {0..255}; do print -Pn "%K{$i} %k%F{$i}${(l:3::0:)i}%f " ${${(M)$((i%6)):#3}:+$'\n'}; done + +# Temporarily change options. +'builtin' 'local' '-a' 'p10k_config_opts' +[[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases') +[[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob') +[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand') +'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' + +() { + emulate -L zsh -o extended_glob + + # Unset all configuration options. This allows you to apply configuration changes without + # restarting zsh. Edit ~/.p10k.zsh and type `source ~/.p10k.zsh`. + unset -m '(POWERLEVEL9K_*|DEFAULT_USER)~POWERLEVEL9K_GITSTATUS_DIR' + + # Zsh >= 5.1 is required. + [[ $ZSH_VERSION == (5.<1->*|<6->.*) ]] || return + + # The list of segments shown on the left. Fill it with the most important segments. + typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=( + # os_icon # os identifier + + prompt_char # prompt symbol + ) + + # The list of segments shown on the right. Fill it with less important segments. + # Right prompt on the last prompt line (where you are typing your commands) gets + # automatically hidden when the input line reaches it. Right prompt above the + # last prompt line gets hidden if it would overlap with left prompt. + typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=( + # status # exit code of the last command + # command_execution_time # duration of the last command + dir # current directory + background_jobs # presence of background jobs + # direnv # direnv status (https://direnv.net/) + # asdf # asdf version manager (https://github.com/asdf-vm/asdf) + # virtualenv # python virtual environment (https://docs.python.org/3/library/venv.html) + # anaconda # conda environment (https://conda.io/) + pyenv # python environment (https://github.com/pyenv/pyenv) + # goenv # go environment (https://github.com/syndbg/goenv) + # nodenv # node.js version from nodenv (https://github.com/nodenv/nodenv) + # nvm # node.js version from nvm (https://github.com/nvm-sh/nvm) + # nodeenv # node.js environment (https://github.com/ekalinin/nodeenv) + # node_version # node.js version + # go_version # go version (https://golang.org) + # rust_version # rustc version (https://www.rust-lang.org) + # dotnet_version # .NET version (https://dotnet.microsoft.com) + # php_version # php version (https://www.php.net/) + # laravel_version # laravel php framework version (https://laravel.com/) + # java_version # java version (https://www.java.com/) + # package # name@version from package.json (https://docs.npmjs.com/files/package.json) + # rbenv # ruby version from rbenv (https://github.com/rbenv/rbenv) + # rvm # ruby version from rvm (https://rvm.io) + # fvm # flutter version management (https://github.com/leoafarias/fvm) + # luaenv # lua version from luaenv (https://github.com/cehoffman/luaenv) + # jenv # java version from jenv (https://github.com/jenv/jenv) + # plenv # perl version from plenv (https://github.com/tokuhirom/plenv) + # perlbrew # perl version from perlbrew (https://github.com/gugod/App-perlbrew) + # phpenv # php version from phpenv (https://github.com/phpenv/phpenv) + # scalaenv # scala version from scalaenv (https://github.com/scalaenv/scalaenv) + haskell_stack # haskell version from stack (https://haskellstack.org/) + # kubecontext # current kubernetes context (https://kubernetes.io/) + # terraform # terraform workspace (https://www.terraform.io) + # terraform_version # terraform version (https://www.terraform.io) + # aws # aws profile (https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) + # aws_eb_env # aws elastic beanstalk environment (https://aws.amazon.com/elasticbeanstalk/) + # azure # azure account name (https://docs.microsoft.com/en-us/cli/azure) + # gcloud # google cloud cli account and project (https://cloud.google.com/) + # google_app_cred # google application credentials (https://cloud.google.com/docs/authentication/production) + # toolbox # toolbox name (https://github.com/containers/toolbox) + context # user@hostname + # nordvpn # nordvpn connection status, linux only (https://nordvpn.com/) + # ranger # ranger shell (https://github.com/ranger/ranger) + # nnn # nnn shell (https://github.com/jarun/nnn) + lf # lf shell (https://github.com/gokcehan/lf) + # xplr # xplr shell (https://github.com/sayanarijit/xplr) + # vim_shell # vim shell indicator (:sh) + # midnight_commander # midnight commander shell (https://midnight-commander.org/) + # nix_shell # nix shell (https://nixos.org/nixos/nix-pills/developing-with-nix-shell.html) + # chezmoi_shell # chezmoi shell (https://www.chezmoi.io/) + # vi_mode # vi mode (you don't need this if you've enabled prompt_char) + # vpn_ip # virtual private network indicator + # load # CPU load + # disk_usage # disk usage + # ram # free RAM + # swap # used swap + # todo # todo items (https://github.com/todotxt/todo.txt-cli) + # timewarrior # timewarrior tracking status (https://timewarrior.net/) + # taskwarrior # taskwarrior task count (https://taskwarrior.org/) + # cpu_arch # CPU architecture + # time # current time + # ip # ip address and bandwidth usage for a specified network interface + # public_ip # public IP address + # proxy # system-wide http/https/ftp proxy + # battery # internal battery + # wifi # wifi speed + # vcs # git status + # example # example user-defined segment (see prompt_example function below) + ) + + typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true + + + # Defines character set used by powerlevel10k. It's best to let `p10k configure` set it for you. + typeset -g POWERLEVEL9K_MODE=nerdfont-v3 + # When set to `moderate`, some icons will have an extra space after them. This is meant to avoid + # icon overlap when using non-monospace fonts. When set to `none`, spaces are not added. + typeset -g POWERLEVEL9K_ICON_PADDING=moderate + + # Basic style options that define the overall look of your prompt. You probably don't want to + # change them. + typeset -g POWERLEVEL9K_BACKGROUND= # transparent background + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_{LEFT,RIGHT}_WHITESPACE= # no surrounding whitespace + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SUBSEGMENT_SEPARATOR=' ' # separate segments with a space + typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SEGMENT_SEPARATOR= # no end-of-line symbol + + # When set to true, icons appear before content on both sides of the prompt. When set + # to false, icons go after content. If empty or not set, icons go before content in the left + # prompt and after content in the right prompt. + # + # You can also override it for a specific segment: + # + # POWERLEVEL9K_STATUS_ICON_BEFORE_CONTENT=false + # + # Or for a specific segment in specific state: + # + # POWERLEVEL9K_DIR_NOT_WRITABLE_ICON_BEFORE_CONTENT=false + typeset -g POWERLEVEL9K_ICON_BEFORE_CONTENT=true + + # Add an empty line before each prompt. + typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=true + + # Connect left prompt lines with these symbols. + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX= + typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_PREFIX= + typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX= + # Connect right prompt lines with these symbols. + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_SUFFIX= + typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_SUFFIX= + typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_SUFFIX= + + # The left end of left prompt. + typeset -g POWERLEVEL9K_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL= + # The right end of right prompt. + typeset -g POWERLEVEL9K_RIGHT_PROMPT_LAST_SEGMENT_END_SYMBOL= + + # Ruler, a.k.a. the horizontal line before each prompt. If you set it to true, you'll + # probably want to set POWERLEVEL9K_PROMPT_ADD_NEWLINE=false above and + # POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' ' below. + typeset -g POWERLEVEL9K_SHOW_RULER=false + typeset -g POWERLEVEL9K_RULER_CHAR='─' # reasonable alternative: '·' + typeset -g POWERLEVEL9K_RULER_FOREGROUND=7 + + # Filler between left and right prompt on the first prompt line. You can set it to '·' or '─' + # to make it easier to see the alignment between left and right prompt and to separate prompt + # from command output. It serves the same purpose as ruler (see above) without increasing + # the number of prompt lines. You'll probably want to set POWERLEVEL9K_SHOW_RULER=false + # if using this. You might also like POWERLEVEL9K_PROMPT_ADD_NEWLINE=false for more compact + # prompt. + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' ' + if [[ $POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR != ' ' ]]; then + # The color of the filler. + typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_FOREGROUND=7 + # Add a space between the end of left prompt and the filler. + typeset -g POWERLEVEL9K_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL=' ' + # Add a space between the filler and the start of right prompt. + typeset -g POWERLEVEL9K_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL=' ' + # Start filler from the edge of the screen if there are no left segments on the first line. + typeset -g POWERLEVEL9K_EMPTY_LINE_LEFT_PROMPT_FIRST_SEGMENT_END_SYMBOL='%{%}' + # End filler on the edge of the screen if there are no right segments on the first line. + typeset -g POWERLEVEL9K_EMPTY_LINE_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='%{%}' + fi + + #################################[ os_icon: os identifier ]################################## + # OS identifier color. + typeset -g POWERLEVEL9K_OS_ICON_FOREGROUND= + # Custom icon. + # typeset -g POWERLEVEL9K_OS_ICON_CONTENT_EXPANSION='⭐' + + ################################[ prompt_char: prompt symbol ]################################ + # Green prompt symbol if the last command succeeded. + typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=2 + # Red prompt symbol if the last command failed. + typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=1 + # Default prompt symbol. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIINS_CONTENT_EXPANSION=' ' + # Prompt symbol in command vi mode. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VICMD_CONTENT_EXPANSION=' ' + # Prompt symbol in visual vi mode. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIVIS_CONTENT_EXPANSION='V' + # Prompt symbol in overwrite vi mode. + typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIOWR_CONTENT_EXPANSION='▶' + typeset -g POWERLEVEL9K_PROMPT_CHAR_OVERWRITE_STATE=true + # No line terminator if prompt_char is the last segment. + typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL='' + # No line introducer if prompt_char is the first segment. + typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL= + + ##################################[ dir: current directory ]################################## + # Default current directory color. + typeset -g POWERLEVEL9K_DIR_FOREGROUND=4 + # If directory is too long, shorten some of its segments to the shortest possible unique + # prefix. The shortened directory can be tab-completed to the original. + typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique + # Replace removed segment suffixes with this symbol. + typeset -g POWERLEVEL9K_SHORTEN_DELIMITER= + # Color of the shortened directory segments. + typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND=4 + # Color of the anchor directory segments. Anchor segments are never shortened. The first + # segment is always an anchor. + typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND=4 + # Set to true to display anchor directory segments in bold. + typeset -g POWERLEVEL9K_DIR_ANCHOR_BOLD=false + # Don't shorten directories that contain any of these files. They are anchors. + local anchor_files=( + .bzr + .citc + .git + .hg + .node-version + .python-version + .go-version + .ruby-version + .lua-version + .java-version + .perl-version + .php-version + .tool-versions + .shorten_folder_marker + .svn + .terraform + CVS + Cargo.toml + composer.json + go.mod + package.json + stack.yaml + ) + typeset -g POWERLEVEL9K_SHORTEN_FOLDER_MARKER="(${(j:|:)anchor_files})" + # If set to "first" ("last"), remove everything before the first (last) subdirectory that contains + # files matching $POWERLEVEL9K_SHORTEN_FOLDER_MARKER. For example, when the current directory is + # /foo/bar/git_repo/nested_git_repo/baz, prompt will display git_repo/nested_git_repo/baz (first) + # or nested_git_repo/baz (last). This assumes that git_repo and nested_git_repo contain markers + # and other directories don't. + # + # Optionally, "first" and "last" can be followed by ":" where is an integer. + # This moves the truncation point to the right (positive offset) or to the left (negative offset) + # relative to the marker. Plain "first" and "last" are equivalent to "first:0" and "last:0" + # respectively. + typeset -g POWERLEVEL9K_DIR_TRUNCATE_BEFORE_MARKER=false + # Don't shorten this many last directory segments. They are anchors. + typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=1 + # Shorten directory if it's longer than this even if there is space for it. The value can + # be either absolute (e.g., '80') or a percentage of terminal width (e.g, '50%'). If empty, + # directory will be shortened only when prompt doesn't fit or when other parameters demand it + # (see POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS and POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT below). + # If set to `0`, directory will always be shortened to its minimum length. + typeset -g POWERLEVEL9K_DIR_MAX_LENGTH=80 + # When `dir` segment is on the last prompt line, try to shorten it enough to leave at least this + # many columns for typing commands. + typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS=40 + # When `dir` segment is on the last prompt line, try to shorten it enough to leave at least + # COLUMNS * POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT * 0.01 columns for typing commands. + typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT=50 + # If set to true, embed a hyperlink into the directory. Useful for quickly + # opening a directory in the file manager simply by clicking the link. + # Can also be handy when the directory is shortened, as it allows you to see + # the full directory that was used in previous commands. + typeset -g POWERLEVEL9K_DIR_HYPERLINK=false + + # Enable special styling for non-writable directories. See POWERLEVEL9K_LOCK_ICON and + # POWERLEVEL9K_DIR_CLASSES below. + typeset -g POWERLEVEL9K_DIR_SHOW_WRITABLE=v2 + + # Enable special styling for non-writable and non-existent directories. See POWERLEVEL9K_LOCK_ICON + # and POWERLEVEL9K_DIR_CLASSES below. + typeset -g POWERLEVEL9K_DIR_SHOW_WRITABLE=v3 + + # The default icon shown next to non-writable and non-existent directories when + # POWERLEVEL9K_DIR_SHOW_WRITABLE is set to v3. + # typeset -g POWERLEVEL9K_LOCK_ICON='⭐' + + # POWERLEVEL9K_DIR_CLASSES allows you to specify custom icons and colors for different + # directories. It must be an array with 3 * N elements. Each triplet consists of: + # + # 1. A pattern against which the current directory ($PWD) is matched. Matching is done with + # extended_glob option enabled. + # 2. Directory class for the purpose of styling. + # 3. An empty string. + # + # Triplets are tried in order. The first triplet whose pattern matches $PWD wins. + # + # If POWERLEVEL9K_DIR_SHOW_WRITABLE is set to v3, non-writable and non-existent directories + # acquire class suffix _NOT_WRITABLE and NON_EXISTENT respectively. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_DIR_CLASSES=( + # '~/work(|/*)' WORK '' + # '~(|/*)' HOME '' + # '*' DEFAULT '') + # + # Whenever the current directory is ~/work or a subdirectory of ~/work, it gets styled with one + # of the following classes depending on its writability and existence: WORK, WORK_NOT_WRITABLE or + # WORK_NON_EXISTENT. + # + # Simply assigning classes to directories doesn't have any visible effects. It merely gives you an + # option to define custom colors and icons for different directory classes. + # + # # Styling for WORK. + # typeset -g POWERLEVEL9K_DIR_WORK_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_DIR_WORK_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_SHORTENED_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_ANCHOR_FOREGROUND=4 + # + # # Styling for WORK_NOT_WRITABLE. + # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_SHORTENED_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_ANCHOR_FOREGROUND=4# + # + # Styling for WORK_NON_EXISTENT. + # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_SHORTENED_FOREGROUND=4 + # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_ANCHOR_FOREGROUND=4 + # + # If a styling parameter isn't explicitly defined for some class, it falls back to the classless + # parameter. For example, if POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_FOREGROUND is not set, it falls + # back to POWERLEVEL9K_DIR_FOREGROUND. + # + typeset -g POWERLEVEL9K_DIR_CLASSES=() + + # Custom prefix. + # typeset -g POWERLEVEL9K_DIR_PREFIX='%fin ' + + #####################################[ vcs: git status ]###################################### + # Branch icon. Set this parameter to '\UE0A0 ' for the popular Powerline branch icon. + typeset -g POWERLEVEL9K_VCS_BRANCH_ICON= + + # Untracked files icon. It's really a question mark, your font isn't broken. + # Change the value of this parameter to show a different icon. + typeset -g POWERLEVEL9K_VCS_UNTRACKED_ICON='?' + + # Formatter for Git status. + # + # Example output: master wip ⇣42⇡42 *42 merge ~42 +42 !42 ?42. + # + # You can edit the function to customize how Git status looks. + # + # VCS_STATUS_* parameters are set by gitstatus plugin. See reference: + # https://github.com/romkatv/gitstatus/blob/master/gitstatus.plugin.zsh. + function my_git_formatter() { + emulate -L zsh + + if [[ -n $P9K_CONTENT ]]; then + # If P9K_CONTENT is not empty, use it. It's either "loading" or from vcs_info (not from + # gitstatus plugin). VCS_STATUS_* parameters are not available in this case. + typeset -g my_git_format=$P9K_CONTENT + return + fi + + if (( $1 )); then + # Styling for up-to-date Git status. + local meta='%f' # default foreground + local clean='%2F' # green foreground + local modified='%3F' # yellow foreground + local untracked='%4F' # blue foreground + local conflicted='%1F' # red foreground + else + # Styling for incomplete and stale Git status. + local meta='%f' # default foreground + local clean='%f' # default foreground + local modified='%f' # default foreground + local untracked='%f' # default foreground + local conflicted='%f' # default foreground + fi + + local res + + if [[ -n $VCS_STATUS_LOCAL_BRANCH ]]; then + local branch=${(V)VCS_STATUS_LOCAL_BRANCH} + # If local branch name is at most 32 characters long, show it in full. + # Otherwise show the first 12 … the last 12. + # Tip: To always show local branch name in full without truncation, delete the next line. + (( $#branch > 32 )) && branch[13,-13]="…" # <-- this line + res+="${clean}${(g::)POWERLEVEL9K_VCS_BRANCH_ICON}${branch//\%/%%}" + fi + + if [[ -n $VCS_STATUS_TAG + # Show tag only if not on a branch. + # Tip: To always show tag, delete the next line. + && -z $VCS_STATUS_LOCAL_BRANCH # <-- this line + ]]; then + local tag=${(V)VCS_STATUS_TAG} + # If tag name is at most 32 characters long, show it in full. + # Otherwise show the first 12 … the last 12. + # Tip: To always show tag name in full without truncation, delete the next line. + (( $#tag > 32 )) && tag[13,-13]="…" # <-- this line + res+="${meta}#${clean}${tag//\%/%%}" + fi + + # Display the current Git commit if there is no branch and no tag. + # Tip: To always display the current Git commit, delete the next line. + [[ -z $VCS_STATUS_LOCAL_BRANCH && -z $VCS_STATUS_TAG ]] && # <-- this line + res+="${meta}@${clean}${VCS_STATUS_COMMIT[1,8]}" + + # Show tracking branch name if it differs from local branch. + if [[ -n ${VCS_STATUS_REMOTE_BRANCH:#$VCS_STATUS_LOCAL_BRANCH} ]]; then + res+="${meta}:${clean}${(V)VCS_STATUS_REMOTE_BRANCH//\%/%%}" + fi + + # Display "wip" if the latest commit's summary contains "wip" or "WIP". + if [[ $VCS_STATUS_COMMIT_SUMMARY == (|*[^[:alnum:]])(wip|WIP)(|[^[:alnum:]]*) ]]; then + res+=" ${modified}wip" + fi + + if (( VCS_STATUS_COMMITS_AHEAD || VCS_STATUS_COMMITS_BEHIND )); then + # ⇣42 if behind the remote. + (( VCS_STATUS_COMMITS_BEHIND )) && res+=" ${clean}⇣${VCS_STATUS_COMMITS_BEHIND}" + # ⇡42 if ahead of the remote; no leading space if also behind the remote: ⇣42⇡42. + (( VCS_STATUS_COMMITS_AHEAD && !VCS_STATUS_COMMITS_BEHIND )) && res+=" " + (( VCS_STATUS_COMMITS_AHEAD )) && res+="${clean}⇡${VCS_STATUS_COMMITS_AHEAD}" + elif [[ -n $VCS_STATUS_REMOTE_BRANCH ]]; then + # Tip: Uncomment the next line to display '=' if up to date with the remote. + # res+=" ${clean}=" + fi + + # ⇠42 if behind the push remote. + (( VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" ${clean}⇠${VCS_STATUS_PUSH_COMMITS_BEHIND}" + (( VCS_STATUS_PUSH_COMMITS_AHEAD && !VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" " + # ⇢42 if ahead of the push remote; no leading space if also behind: ⇠42⇢42. + (( VCS_STATUS_PUSH_COMMITS_AHEAD )) && res+="${clean}⇢${VCS_STATUS_PUSH_COMMITS_AHEAD}" + # *42 if have stashes. + (( VCS_STATUS_STASHES )) && res+=" ${clean}*${VCS_STATUS_STASHES}" + # 'merge' if the repo is in an unusual state. + [[ -n $VCS_STATUS_ACTION ]] && res+=" ${conflicted}${VCS_STATUS_ACTION}" + # ~42 if have merge conflicts. + (( VCS_STATUS_NUM_CONFLICTED )) && res+=" ${conflicted}~${VCS_STATUS_NUM_CONFLICTED}" + # +42 if have staged changes. + (( VCS_STATUS_NUM_STAGED )) && res+=" ${modified}+${VCS_STATUS_NUM_STAGED}" + # !42 if have unstaged changes. + (( VCS_STATUS_NUM_UNSTAGED )) && res+=" ${modified}!${VCS_STATUS_NUM_UNSTAGED}" + # ?42 if have untracked files. It's really a question mark, your font isn't broken. + # See POWERLEVEL9K_VCS_UNTRACKED_ICON above if you want to use a different icon. + # Remove the next line if you don't want to see untracked files at all. + (( VCS_STATUS_NUM_UNTRACKED )) && res+=" ${untracked}${(g::)POWERLEVEL9K_VCS_UNTRACKED_ICON}${VCS_STATUS_NUM_UNTRACKED}" + # "─" if the number of unstaged files is unknown. This can happen due to + # POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY (see below) being set to a non-negative number lower + # than the number of files in the Git index, or due to bash.showDirtyState being set to false + # in the repository config. The number of staged and untracked files may also be unknown + # in this case. + (( VCS_STATUS_HAS_UNSTAGED == -1 )) && res+=" ${modified}─" + + typeset -g my_git_format=$res + } + functions -M my_git_formatter 2>/dev/null + + # Don't count the number of unstaged, untracked and conflicted files in Git repositories with + # more than this many files in the index. Negative value means infinity. + # + # If you are working in Git repositories with tens of millions of files and seeing performance + # sagging, try setting POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY to a number lower than the output + # of `git ls-files | wc -l`. Alternatively, add `bash.showDirtyState = false` to the repository's + # config: `git config bash.showDirtyState false`. + typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=-1 + + # Don't show Git status in prompt for repositories whose workdir matches this pattern. + # For example, if set to '~', the Git repository at $HOME/.git will be ignored. + # Multiple patterns can be combined with '|': '~(|/foo)|/bar/baz/*'. + typeset -g POWERLEVEL9K_VCS_DISABLED_WORKDIR_PATTERN='~' + + # Disable the default Git status formatting. + typeset -g POWERLEVEL9K_VCS_DISABLE_GITSTATUS_FORMATTING=true + # Install our own Git status formatter. + typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${$((my_git_formatter(1)))+${my_git_format}}' + typeset -g POWERLEVEL9K_VCS_LOADING_CONTENT_EXPANSION='${$((my_git_formatter(0)))+${my_git_format}}' + # Enable counters for staged, unstaged, etc. + typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED,CONFLICTED,COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=-1 + + # Icon color. + typeset -g POWERLEVEL9K_VCS_VISUAL_IDENTIFIER_COLOR=2 + typeset -g POWERLEVEL9K_VCS_LOADING_VISUAL_IDENTIFIER_COLOR= + # Custom icon. + typeset -g POWERLEVEL9K_VCS_VISUAL_IDENTIFIER_EXPANSION= + # Custom prefix. + # typeset -g POWERLEVEL9K_VCS_PREFIX='%fon ' + + # Show status of repositories of these types. You can add svn and/or hg if you are + # using them. If you do, your prompt may become slow even when your current directory + # isn't in an svn or hg repository. + typeset -g POWERLEVEL9K_VCS_BACKENDS=(git) + + # These settings are used for repositories other than Git or when gitstatusd fails and + # Powerlevel10k has to fall back to using vcs_info. + typeset -g POWERLEVEL9K_VCS_CLEAN_FOREGROUND=2 + typeset -g POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND=2 + typeset -g POWERLEVEL9K_VCS_MODIFIED_FOREGROUND=3 + + ##########################[ status: exit code of the last command ]########################### + # Enable OK_PIPE, ERROR_PIPE and ERROR_SIGNAL status states to allow us to enable, disable and + # style them independently from the regular OK and ERROR state. + typeset -g POWERLEVEL9K_STATUS_EXTENDED_STATES=true + + # Status on success. No content, just an icon. No need to show it if prompt_char is enabled as + # it will signify success by turning green. + typeset -g POWERLEVEL9K_STATUS_OK=false + typeset -g POWERLEVEL9K_STATUS_OK_FOREGROUND=2 + typeset -g POWERLEVEL9K_STATUS_OK_VISUAL_IDENTIFIER_EXPANSION='✔' + + # Status when some part of a pipe command fails but the overall exit status is zero. It may look + # like this: 1|0. + typeset -g POWERLEVEL9K_STATUS_OK_PIPE=true + typeset -g POWERLEVEL9K_STATUS_OK_PIPE_FOREGROUND=2 + typeset -g POWERLEVEL9K_STATUS_OK_PIPE_VISUAL_IDENTIFIER_EXPANSION='✔' + + # Status when it's just an error code (e.g., '1'). No need to show it if prompt_char is enabled as + # it will signify error by turning red. + typeset -g POWERLEVEL9K_STATUS_ERROR=false + typeset -g POWERLEVEL9K_STATUS_ERROR_FOREGROUND=1 + typeset -g POWERLEVEL9K_STATUS_ERROR_VISUAL_IDENTIFIER_EXPANSION='✘' + + # Status when the last command was terminated by a signal. + typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL=true + typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_FOREGROUND=1 + # Use terse signal names: "INT" instead of "SIGINT(2)". + typeset -g POWERLEVEL9K_STATUS_VERBOSE_SIGNAME=false + typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_VISUAL_IDENTIFIER_EXPANSION='✘' + + # Status when some part of a pipe command fails and the overall exit status is also non-zero. + # It may look like this: 1|0. + typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE=true + typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_FOREGROUND=1 + typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_VISUAL_IDENTIFIER_EXPANSION='✘' + + ###################[ command_execution_time: duration of the last command ]################### + # Show duration of the last command if takes at least this many seconds. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=3 + # Show this many fractional digits. Zero means round to seconds. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0 + # Execution time color. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=3 + # Duration format: 1d 2h 3m 4s. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s' + # Custom icon. + typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_VISUAL_IDENTIFIER_EXPANSION= + # Custom prefix. + # typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PREFIX='%ftook ' + + #######################[ background_jobs: presence of background jobs ]####################### + # Don't show the number of background jobs. + typeset -g POWERLEVEL9K_BACKGROUND_JOBS_VERBOSE=false + # Background jobs color. + typeset -g POWERLEVEL9K_BACKGROUND_JOBS_FOREGROUND=1 + # Custom icon. + # typeset -g POWERLEVEL9K_BACKGROUND_JOBS_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #######################[ direnv: direnv status (https://direnv.net/) ]######################## + # Direnv color. + typeset -g POWERLEVEL9K_DIRENV_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_DIRENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###############[ asdf: asdf version manager (https://github.com/asdf-vm/asdf) ]############### + # Default asdf color. Only used to display tools for which there is no color override (see below). + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_FOREGROUND. + typeset -g POWERLEVEL9K_ASDF_FOREGROUND=6 + + # There are four parameters that can be used to hide asdf tools. Each parameter describes + # conditions under which a tool gets hidden. Parameters can hide tools but not unhide them. If at + # least one parameter decides to hide a tool, that tool gets hidden. If no parameter decides to + # hide a tool, it gets shown. + # + # Special note on the difference between POWERLEVEL9K_ASDF_SOURCES and + # POWERLEVEL9K_ASDF_PROMPT_ALWAYS_SHOW. Consider the effect of the following commands: + # + # asdf local python 3.8.1 + # asdf global python 3.8.1 + # + # After running both commands the current python version is 3.8.1 and its source is "local" as + # it takes precedence over "global". If POWERLEVEL9K_ASDF_PROMPT_ALWAYS_SHOW is set to false, + # it'll hide python version in this case because 3.8.1 is the same as the global version. + # POWERLEVEL9K_ASDF_SOURCES will hide python version only if the value of this parameter doesn't + # contain "local". + + # Hide tool versions that don't come from one of these sources. + # + # Available sources: + # + # - shell `asdf current` says "set by ASDF_${TOOL}_VERSION environment variable" + # - local `asdf current` says "set by /some/not/home/directory/file" + # - global `asdf current` says "set by /home/username/file" + # + # Note: If this parameter is set to (shell local global), it won't hide tools. + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_SOURCES. + typeset -g POWERLEVEL9K_ASDF_SOURCES=(shell local global) + + # If set to false, hide tool versions that are the same as global. + # + # Note: The name of this parameter doesn't reflect its meaning at all. + # Note: If this parameter is set to true, it won't hide tools. + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_PROMPT_ALWAYS_SHOW. + typeset -g POWERLEVEL9K_ASDF_PROMPT_ALWAYS_SHOW=false + + # If set to false, hide tool versions that are equal to "system". + # + # Note: If this parameter is set to true, it won't hide tools. + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_SHOW_SYSTEM. + typeset -g POWERLEVEL9K_ASDF_SHOW_SYSTEM=true + + # If set to non-empty value, hide tools unless there is a file matching the specified file pattern + # in the current directory, or its parent directory, or its grandparent directory, and so on. + # + # Note: If this parameter is set to empty value, it won't hide tools. + # Note: SHOW_ON_UPGLOB isn't specific to asdf. It works with all prompt segments. + # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_SHOW_ON_UPGLOB. + # + # Example: Hide nodejs version when there is no package.json and no *.js files in the current + # directory, in `..`, in `../..` and so on. + # + # typeset -g POWERLEVEL9K_ASDF_NODEJS_SHOW_ON_UPGLOB='*.js|package.json' + typeset -g POWERLEVEL9K_ASDF_SHOW_ON_UPGLOB= + + # Ruby version from asdf. + typeset -g POWERLEVEL9K_ASDF_RUBY_FOREGROUND=1 + # typeset -g POWERLEVEL9K_ASDF_RUBY_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_RUBY_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Python version from asdf. + typeset -g POWERLEVEL9K_ASDF_PYTHON_FOREGROUND=6 + # typeset -g POWERLEVEL9K_ASDF_PYTHON_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_PYTHON_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Go version from asdf. + typeset -g POWERLEVEL9K_ASDF_GOLANG_FOREGROUND=6 + # typeset -g POWERLEVEL9K_ASDF_GOLANG_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_GOLANG_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Node.js version from asdf. + typeset -g POWERLEVEL9K_ASDF_NODEJS_FOREGROUND=2 + # typeset -g POWERLEVEL9K_ASDF_NODEJS_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_NODEJS_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Rust version from asdf. + typeset -g POWERLEVEL9K_ASDF_RUST_FOREGROUND=4 + # typeset -g POWERLEVEL9K_ASDF_RUST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_RUST_SHOW_ON_UPGLOB='*.foo|*.bar' + + # .NET Core version from asdf. + typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_FOREGROUND=5 + # typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Flutter version from asdf. + typeset -g POWERLEVEL9K_ASDF_FLUTTER_FOREGROUND=4 + # typeset -g POWERLEVEL9K_ASDF_FLUTTER_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_FLUTTER_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Lua version from asdf. + typeset -g POWERLEVEL9K_ASDF_LUA_FOREGROUND=4 + # typeset -g POWERLEVEL9K_ASDF_LUA_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_LUA_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Java version from asdf. + typeset -g POWERLEVEL9K_ASDF_JAVA_FOREGROUND=4 + # typeset -g POWERLEVEL9K_ASDF_JAVA_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_JAVA_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Perl version from asdf. + typeset -g POWERLEVEL9K_ASDF_PERL_FOREGROUND=6 + # typeset -g POWERLEVEL9K_ASDF_PERL_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_PERL_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Erlang version from asdf. + typeset -g POWERLEVEL9K_ASDF_ERLANG_FOREGROUND=1 + # typeset -g POWERLEVEL9K_ASDF_ERLANG_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_ERLANG_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Elixir version from asdf. + typeset -g POWERLEVEL9K_ASDF_ELIXIR_FOREGROUND=5 + # typeset -g POWERLEVEL9K_ASDF_ELIXIR_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_ELIXIR_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Postgres version from asdf. + typeset -g POWERLEVEL9K_ASDF_POSTGRES_FOREGROUND=6 + # typeset -g POWERLEVEL9K_ASDF_POSTGRES_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_POSTGRES_SHOW_ON_UPGLOB='*.foo|*.bar' + + # PHP version from asdf. + typeset -g POWERLEVEL9K_ASDF_PHP_FOREGROUND=5 + # typeset -g POWERLEVEL9K_ASDF_PHP_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_PHP_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Haskell version from asdf. + typeset -g POWERLEVEL9K_ASDF_HASKELL_FOREGROUND=3 + # typeset -g POWERLEVEL9K_ASDF_HASKELL_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_HASKELL_SHOW_ON_UPGLOB='*.foo|*.bar' + + # Julia version from asdf. + typeset -g POWERLEVEL9K_ASDF_JULIA_FOREGROUND=2 + # typeset -g POWERLEVEL9K_ASDF_JULIA_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_ASDF_JULIA_SHOW_ON_UPGLOB='*.foo|*.bar' + + ##########[ nordvpn: nordvpn connection status, linux only (https://nordvpn.com/) ]########### + # NordVPN connection indicator color. + typeset -g POWERLEVEL9K_NORDVPN_FOREGROUND=6 + # Hide NordVPN connection indicator when not connected. + typeset -g POWERLEVEL9K_NORDVPN_{DISCONNECTED,CONNECTING,DISCONNECTING}_CONTENT_EXPANSION= + typeset -g POWERLEVEL9K_NORDVPN_{DISCONNECTED,CONNECTING,DISCONNECTING}_VISUAL_IDENTIFIER_EXPANSION= + # Custom icon. + # typeset -g POWERLEVEL9K_NORDVPN_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #################[ ranger: ranger shell (https://github.com/ranger/ranger) ]################## + # Ranger shell color. + typeset -g POWERLEVEL9K_RANGER_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_RANGER_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######################[ nnn: nnn shell (https://github.com/jarun/nnn) ]####################### + # Nnn shell color. + typeset -g POWERLEVEL9K_NNN_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_NNN_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######################[ lf: lf shell (https://github.com/gokcehan/lf) ]####################### + # lf shell color. + typeset -g POWERLEVEL9K_LF_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_LF_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##################[ xplr: xplr shell (https://github.com/sayanarijit/xplr) ]################## + # xplr shell color. + typeset -g POWERLEVEL9K_XPLR_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_XPLR_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########################[ vim_shell: vim shell indicator (:sh) ]########################### + # Vim shell indicator color. + typeset -g POWERLEVEL9K_VIM_SHELL_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_VIM_SHELL_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######[ midnight_commander: midnight commander shell (https://midnight-commander.org/) ]###### + # Midnight Commander shell color. + typeset -g POWERLEVEL9K_MIDNIGHT_COMMANDER_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_MIDNIGHT_COMMANDER_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #[ nix_shell: nix shell (https://nixos.org/nixos/nix-pills/developing-with-nix-shell.html) ]## + # Nix shell color. + typeset -g POWERLEVEL9K_NIX_SHELL_FOREGROUND=4 + + # Display the icon of nix_shell if PATH contains a subdirectory of /nix/store. + # typeset -g POWERLEVEL9K_NIX_SHELL_INFER_FROM_PATH=false + + # Tip: If you want to see just the icon without "pure" and "impure", uncomment the next line. + # typeset -g POWERLEVEL9K_NIX_SHELL_CONTENT_EXPANSION= + + # Custom icon. + # typeset -g POWERLEVEL9K_NIX_SHELL_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##################[ chezmoi_shell: chezmoi shell (https://www.chezmoi.io/) ]################## + # chezmoi shell color. + typeset -g POWERLEVEL9K_CHEZMOI_SHELL_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_CHEZMOI_SHELL_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##################################[ disk_usage: disk usage ]################################## + # Colors for different levels of disk usage. + typeset -g POWERLEVEL9K_DISK_USAGE_NORMAL_FOREGROUND=2 + typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_FOREGROUND=3 + typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_FOREGROUND=1 + # Thresholds for different levels of disk usage (percentage points). + typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_LEVEL=90 + typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_LEVEL=95 + # If set to true, hide disk usage when below $POWERLEVEL9K_DISK_USAGE_WARNING_LEVEL percent. + typeset -g POWERLEVEL9K_DISK_USAGE_ONLY_WARNING=false + # Custom icon. + # typeset -g POWERLEVEL9K_DISK_USAGE_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######################################[ ram: free RAM ]####################################### + # RAM color. + typeset -g POWERLEVEL9K_RAM_FOREGROUND=2 + # Custom icon. + # typeset -g POWERLEVEL9K_RAM_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #####################################[ swap: used swap ]###################################### + # Swap color. + typeset -g POWERLEVEL9K_SWAP_FOREGROUND=3 + # Custom icon. + # typeset -g POWERLEVEL9K_SWAP_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######################################[ load: CPU load ]###################################### + # Show average CPU load over this many last minutes. Valid values are 1, 5 and 15. + typeset -g POWERLEVEL9K_LOAD_WHICH=5 + # Load color when load is under 50%. + typeset -g POWERLEVEL9K_LOAD_NORMAL_FOREGROUND=2 + # Load color when load is between 50% and 70%. + typeset -g POWERLEVEL9K_LOAD_WARNING_FOREGROUND=3 + # Load color when load is over 70%. + typeset -g POWERLEVEL9K_LOAD_CRITICAL_FOREGROUND=1 + # Custom icon. + # typeset -g POWERLEVEL9K_LOAD_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################[ todo: todo items (https://github.com/todotxt/todo.txt-cli) ]################ + # Todo color. + typeset -g POWERLEVEL9K_TODO_FOREGROUND=4 + # Hide todo when the total number of tasks is zero. + typeset -g POWERLEVEL9K_TODO_HIDE_ZERO_TOTAL=true + # Hide todo when the number of tasks after filtering is zero. + typeset -g POWERLEVEL9K_TODO_HIDE_ZERO_FILTERED=false + + # Todo format. The following parameters are available within the expansion. + # + # - P9K_TODO_TOTAL_TASK_COUNT The total number of tasks. + # - P9K_TODO_FILTERED_TASK_COUNT The number of tasks after filtering. + # + # These variables correspond to the last line of the output of `todo.sh -p ls`: + # + # TODO: 24 of 42 tasks shown + # + # Here 24 is P9K_TODO_FILTERED_TASK_COUNT and 42 is P9K_TODO_TOTAL_TASK_COUNT. + # + # typeset -g POWERLEVEL9K_TODO_CONTENT_EXPANSION='$P9K_TODO_FILTERED_TASK_COUNT' + + # Custom icon. + # typeset -g POWERLEVEL9K_TODO_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ timewarrior: timewarrior tracking status (https://timewarrior.net/) ]############ + # Timewarrior color. + typeset -g POWERLEVEL9K_TIMEWARRIOR_FOREGROUND=4 + # If the tracked task is longer than 24 characters, truncate and append "…". + # Tip: To always display tasks without truncation, delete the following parameter. + # Tip: To hide task names and display just the icon when time tracking is enabled, set the + # value of the following parameter to "". + typeset -g POWERLEVEL9K_TIMEWARRIOR_CONTENT_EXPANSION='${P9K_CONTENT:0:24}${${P9K_CONTENT:24}:+…}' + + # Custom icon. + # typeset -g POWERLEVEL9K_TIMEWARRIOR_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##############[ taskwarrior: taskwarrior task count (https://taskwarrior.org/) ]############## + # Taskwarrior color. + typeset -g POWERLEVEL9K_TASKWARRIOR_FOREGROUND=6 + + # Taskwarrior segment format. The following parameters are available within the expansion. + # + # - P9K_TASKWARRIOR_PENDING_COUNT The number of pending tasks: `task +PENDING count`. + # - P9K_TASKWARRIOR_OVERDUE_COUNT The number of overdue tasks: `task +OVERDUE count`. + # + # Zero values are represented as empty parameters. + # + # The default format: + # + # '${P9K_TASKWARRIOR_OVERDUE_COUNT:+"!$P9K_TASKWARRIOR_OVERDUE_COUNT/"}$P9K_TASKWARRIOR_PENDING_COUNT' + # + # typeset -g POWERLEVEL9K_TASKWARRIOR_CONTENT_EXPANSION='$P9K_TASKWARRIOR_PENDING_COUNT' + + # Custom icon. + # typeset -g POWERLEVEL9K_TASKWARRIOR_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ######[ per_directory_history: Oh My Zsh per-directory-history local/global indicator ]####### + # Color when using local/global history. + typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_FOREGROUND=5 + typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_FOREGROUND=3 + + # Tip: Uncomment the next two lines to hide "local"/"global" text and leave just the icon. + # typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_CONTENT_EXPANSION='' + # typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_CONTENT_EXPANSION='' + + # Custom icon. + # typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################################[ cpu_arch: CPU architecture ]################################ + # CPU architecture color. + typeset -g POWERLEVEL9K_CPU_ARCH_FOREGROUND=3 + + # Hide the segment when on a specific CPU architecture. + # typeset -g POWERLEVEL9K_CPU_ARCH_X86_64_CONTENT_EXPANSION= + # typeset -g POWERLEVEL9K_CPU_ARCH_X86_64_VISUAL_IDENTIFIER_EXPANSION= + + # Custom icon. + # typeset -g POWERLEVEL9K_CPU_ARCH_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##################################[ context: user@hostname ]################################## + # Context color when running with privileges. + typeset -g POWERLEVEL9K_CONTEXT_ROOT_FOREGROUND=1 + # Context color in SSH without privileges. + typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_FOREGROUND=7 + # Default context color (no privileges, no SSH). + typeset -g POWERLEVEL9K_CONTEXT_FOREGROUND=7 + + # Context format when running with privileges: bold user@hostname. + typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE='%B%n@%m' + # Context format when in SSH without privileges: user@hostname. + typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_TEMPLATE='%n@%m' + # Default context format (no privileges, no SSH): user@hostname. + typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE='%n@%m' + + # Don't show context unless running with privileges or in SSH. + # Tip: Remove the next line to always show context. + typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_{CONTENT,VISUAL_IDENTIFIER}_EXPANSION= + + # Custom icon. + # typeset -g POWERLEVEL9K_CONTEXT_VISUAL_IDENTIFIER_EXPANSION='⭐' + # Custom prefix. + # typeset -g POWERLEVEL9K_CONTEXT_PREFIX='%fwith ' + + ###[ virtualenv: python virtual environment (https://docs.python.org/3/library/venv.html) ]### + # Python virtual environment color. + typeset -g POWERLEVEL9K_VIRTUALENV_FOREGROUND=6 + # Don't show Python version next to the virtual environment name. + typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_PYTHON_VERSION=false + # If set to "false", won't show virtualenv if pyenv is already shown. + # If set to "if-different", won't show virtualenv if it's the same as pyenv. + typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_WITH_PYENV=false + # Separate environment name from Python version only with a space. + typeset -g POWERLEVEL9K_VIRTUALENV_{LEFT,RIGHT}_DELIMITER= + # Custom icon. + # typeset -g POWERLEVEL9K_VIRTUALENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #####################[ anaconda: conda environment (https://conda.io/) ]###################### + # Anaconda environment color. + typeset -g POWERLEVEL9K_ANACONDA_FOREGROUND=6 + + # Anaconda segment format. The following parameters are available within the expansion. + # + # - CONDA_PREFIX Absolute path to the active Anaconda/Miniconda environment. + # - CONDA_DEFAULT_ENV Name of the active Anaconda/Miniconda environment. + # - CONDA_PROMPT_MODIFIER Configurable prompt modifier (see below). + # - P9K_ANACONDA_PYTHON_VERSION Current python version (python --version). + # + # CONDA_PROMPT_MODIFIER can be configured with the following command: + # + # conda config --set env_prompt '({default_env}) ' + # + # The last argument is a Python format string that can use the following variables: + # + # - prefix The same as CONDA_PREFIX. + # - default_env The same as CONDA_DEFAULT_ENV. + # - name The last segment of CONDA_PREFIX. + # - stacked_env Comma-separated list of names in the environment stack. The first element is + # always the same as default_env. + # + # Note: '({default_env}) ' is the default value of env_prompt. + # + # The default value of POWERLEVEL9K_ANACONDA_CONTENT_EXPANSION expands to $CONDA_PROMPT_MODIFIER + # without the surrounding parentheses, or to the last path component of CONDA_PREFIX if the former + # is empty. + typeset -g POWERLEVEL9K_ANACONDA_CONTENT_EXPANSION='${${${${CONDA_PROMPT_MODIFIER#\(}% }%\)}:-${CONDA_PREFIX:t}}' + + # Custom icon. + # typeset -g POWERLEVEL9K_ANACONDA_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################[ pyenv: python environment (https://github.com/pyenv/pyenv) ]################ + # Pyenv color. + typeset -g POWERLEVEL9K_PYENV_FOREGROUND=6 + # Hide python version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_PYENV_SOURCES=(shell local global) + # If set to false, hide python version if it's the same as global: + # $(pyenv version-name) == $(pyenv global). + typeset -g POWERLEVEL9K_PYENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide python version if it's equal to "system". + typeset -g POWERLEVEL9K_PYENV_SHOW_SYSTEM=true + + # Pyenv segment format. The following parameters are available within the expansion. + # + # - P9K_CONTENT Current pyenv environment (pyenv version-name). + # - P9K_PYENV_PYTHON_VERSION Current python version (python --version). + # + # The default format has the following logic: + # + # 1. Display just "$P9K_CONTENT" if it's equal to "$P9K_PYENV_PYTHON_VERSION" or + # starts with "$P9K_PYENV_PYTHON_VERSION/". + # 2. Otherwise display "$P9K_CONTENT $P9K_PYENV_PYTHON_VERSION". + typeset -g POWERLEVEL9K_PYENV_CONTENT_EXPANSION='${P9K_CONTENT}${${P9K_CONTENT:#$P9K_PYENV_PYTHON_VERSION(|/*)}:+ $P9K_PYENV_PYTHON_VERSION}' + + # Custom icon. + # typeset -g POWERLEVEL9K_PYENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################[ goenv: go environment (https://github.com/syndbg/goenv) ]################ + # Goenv color. + typeset -g POWERLEVEL9K_GOENV_FOREGROUND=6 + # Hide go version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_GOENV_SOURCES=(shell local global) + # If set to false, hide go version if it's the same as global: + # $(goenv version-name) == $(goenv global). + typeset -g POWERLEVEL9K_GOENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide go version if it's equal to "system". + typeset -g POWERLEVEL9K_GOENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_GOENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ nodenv: node.js version from nodenv (https://github.com/nodenv/nodenv) ]########## + # Nodenv color. + typeset -g POWERLEVEL9K_NODENV_FOREGROUND=2 + # Hide node version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_NODENV_SOURCES=(shell local global) + # If set to false, hide node version if it's the same as global: + # $(nodenv version-name) == $(nodenv global). + typeset -g POWERLEVEL9K_NODENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide node version if it's equal to "system". + typeset -g POWERLEVEL9K_NODENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_NODENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##############[ nvm: node.js version from nvm (https://github.com/nvm-sh/nvm) ]############### + # Nvm color. + typeset -g POWERLEVEL9K_NVM_FOREGROUND=2 + # If set to false, hide node version if it's the same as default: + # $(nvm version current) == $(nvm version default). + typeset -g POWERLEVEL9K_NVM_PROMPT_ALWAYS_SHOW=false + # If set to false, hide node version if it's equal to "system". + typeset -g POWERLEVEL9K_NVM_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_NVM_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ############[ nodeenv: node.js environment (https://github.com/ekalinin/nodeenv) ]############ + # Nodeenv color. + typeset -g POWERLEVEL9K_NODEENV_FOREGROUND=2 + # Don't show Node version next to the environment name. + typeset -g POWERLEVEL9K_NODEENV_SHOW_NODE_VERSION=false + # Separate environment name from Node version only with a space. + typeset -g POWERLEVEL9K_NODEENV_{LEFT,RIGHT}_DELIMITER= + # Custom icon. + # typeset -g POWERLEVEL9K_NODEENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##############################[ node_version: node.js version ]############################### + # Node version color. + typeset -g POWERLEVEL9K_NODE_VERSION_FOREGROUND=2 + # Show node version only when in a directory tree containing package.json. + typeset -g POWERLEVEL9K_NODE_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_NODE_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #######################[ go_version: go version (https://golang.org) ]######################## + # Go version color. + typeset -g POWERLEVEL9K_GO_VERSION_FOREGROUND=6 + # Show go version only when in a go project subdirectory. + typeset -g POWERLEVEL9K_GO_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_GO_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #################[ rust_version: rustc version (https://www.rust-lang.org) ]################## + # Rust version color. + typeset -g POWERLEVEL9K_RUST_VERSION_FOREGROUND=4 + # Show rust version only when in a rust project subdirectory. + typeset -g POWERLEVEL9K_RUST_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_RUST_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###############[ dotnet_version: .NET version (https://dotnet.microsoft.com) ]################ + # .NET version color. + typeset -g POWERLEVEL9K_DOTNET_VERSION_FOREGROUND=5 + # Show .NET version only when in a .NET project subdirectory. + typeset -g POWERLEVEL9K_DOTNET_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_DOTNET_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #####################[ php_version: php version (https://www.php.net/) ]###################### + # PHP version color. + typeset -g POWERLEVEL9K_PHP_VERSION_FOREGROUND=5 + # Show PHP version only when in a PHP project subdirectory. + typeset -g POWERLEVEL9K_PHP_VERSION_PROJECT_ONLY=true + # Custom icon. + # typeset -g POWERLEVEL9K_PHP_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ laravel_version: laravel php framework version (https://laravel.com/) ]########### + # Laravel version color. + typeset -g POWERLEVEL9K_LARAVEL_VERSION_FOREGROUND=1 + # Custom icon. + # typeset -g POWERLEVEL9K_LARAVEL_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ####################[ java_version: java version (https://www.java.com/) ]#################### + # Java version color. + typeset -g POWERLEVEL9K_JAVA_VERSION_FOREGROUND=4 + # Show java version only when in a java project subdirectory. + typeset -g POWERLEVEL9K_JAVA_VERSION_PROJECT_ONLY=true + # Show brief version. + typeset -g POWERLEVEL9K_JAVA_VERSION_FULL=false + # Custom icon. + # typeset -g POWERLEVEL9K_JAVA_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###[ package: name@version from package.json (https://docs.npmjs.com/files/package.json) ]#### + # Package color. + typeset -g POWERLEVEL9K_PACKAGE_FOREGROUND=6 + # Package format. The following parameters are available within the expansion. + # + # - P9K_PACKAGE_NAME The value of `name` field in package.json. + # - P9K_PACKAGE_VERSION The value of `version` field in package.json. + # + # typeset -g POWERLEVEL9K_PACKAGE_CONTENT_EXPANSION='${P9K_PACKAGE_NAME//\%/%%}@${P9K_PACKAGE_VERSION//\%/%%}' + # Custom icon. + # typeset -g POWERLEVEL9K_PACKAGE_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #############[ rbenv: ruby version from rbenv (https://github.com/rbenv/rbenv) ]############## + # Rbenv color. + typeset -g POWERLEVEL9K_RBENV_FOREGROUND=1 + # Hide ruby version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_RBENV_SOURCES=(shell local global) + # If set to false, hide ruby version if it's the same as global: + # $(rbenv version-name) == $(rbenv global). + typeset -g POWERLEVEL9K_RBENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide ruby version if it's equal to "system". + typeset -g POWERLEVEL9K_RBENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_RBENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #######################[ rvm: ruby version from rvm (https://rvm.io) ]######################## + # Rvm color. + typeset -g POWERLEVEL9K_RVM_FOREGROUND=1 + # Don't show @gemset at the end. + typeset -g POWERLEVEL9K_RVM_SHOW_GEMSET=false + # Don't show ruby- at the front. + typeset -g POWERLEVEL9K_RVM_SHOW_PREFIX=false + # Custom icon. + # typeset -g POWERLEVEL9K_RVM_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ fvm: flutter version management (https://github.com/leoafarias/fvm) ]############ + # Fvm color. + typeset -g POWERLEVEL9K_FVM_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_FVM_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ luaenv: lua version from luaenv (https://github.com/cehoffman/luaenv) ]########### + # Lua color. + typeset -g POWERLEVEL9K_LUAENV_FOREGROUND=4 + # Hide lua version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_LUAENV_SOURCES=(shell local global) + # If set to false, hide lua version if it's the same as global: + # $(luaenv version-name) == $(luaenv global). + typeset -g POWERLEVEL9K_LUAENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide lua version if it's equal to "system". + typeset -g POWERLEVEL9K_LUAENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_LUAENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###############[ jenv: java version from jenv (https://github.com/jenv/jenv) ]################ + # Java color. + typeset -g POWERLEVEL9K_JENV_FOREGROUND=4 + # Hide java version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_JENV_SOURCES=(shell local global) + # If set to false, hide java version if it's the same as global: + # $(jenv version-name) == $(jenv global). + typeset -g POWERLEVEL9K_JENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide java version if it's equal to "system". + typeset -g POWERLEVEL9K_JENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_JENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ plenv: perl version from plenv (https://github.com/tokuhirom/plenv) ]############ + # Perl color. + typeset -g POWERLEVEL9K_PLENV_FOREGROUND=6 + # Hide perl version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_PLENV_SOURCES=(shell local global) + # If set to false, hide perl version if it's the same as global: + # $(plenv version-name) == $(plenv global). + typeset -g POWERLEVEL9K_PLENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide perl version if it's equal to "system". + typeset -g POWERLEVEL9K_PLENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_PLENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ perlbrew: perl version from perlbrew (https://github.com/gugod/App-perlbrew) ]############ + # Perlbrew color. + typeset -g POWERLEVEL9K_PERLBREW_FOREGROUND=67 + # Show perlbrew version only when in a perl project subdirectory. + typeset -g POWERLEVEL9K_PERLBREW_PROJECT_ONLY=true + # Don't show "perl-" at the front. + typeset -g POWERLEVEL9K_PERLBREW_SHOW_PREFIX=false + # Custom icon. + # typeset -g POWERLEVEL9K_PERLBREW_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ############[ phpenv: php version from phpenv (https://github.com/phpenv/phpenv) ]############ + # PHP color. + typeset -g POWERLEVEL9K_PHPENV_FOREGROUND=5 + # Hide php version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_PHPENV_SOURCES=(shell local global) + # If set to false, hide php version if it's the same as global: + # $(phpenv version-name) == $(phpenv global). + typeset -g POWERLEVEL9K_PHPENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide php version if it's equal to "system". + typeset -g POWERLEVEL9K_PHPENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_PHPENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #######[ scalaenv: scala version from scalaenv (https://github.com/scalaenv/scalaenv) ]####### + # Scala color. + typeset -g POWERLEVEL9K_SCALAENV_FOREGROUND=1 + # Hide scala version if it doesn't come from one of these sources. + typeset -g POWERLEVEL9K_SCALAENV_SOURCES=(shell local global) + # If set to false, hide scala version if it's the same as global: + # $(scalaenv version-name) == $(scalaenv global). + typeset -g POWERLEVEL9K_SCALAENV_PROMPT_ALWAYS_SHOW=false + # If set to false, hide scala version if it's equal to "system". + typeset -g POWERLEVEL9K_SCALAENV_SHOW_SYSTEM=true + # Custom icon. + # typeset -g POWERLEVEL9K_SCALAENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ haskell_stack: haskell version from stack (https://haskellstack.org/) ]########### + # Haskell color. + typeset -g POWERLEVEL9K_HASKELL_STACK_FOREGROUND=3 + # Hide haskell version if it doesn't come from one of these sources. + # + # shell: version is set by STACK_YAML + # local: version is set by stack.yaml up the directory tree + # global: version is set by the implicit global project (~/.stack/global-project/stack.yaml) + typeset -g POWERLEVEL9K_HASKELL_STACK_SOURCES=(shell local) + # If set to false, hide haskell version if it's the same as in the implicit global project. + typeset -g POWERLEVEL9K_HASKELL_STACK_ALWAYS_SHOW=true + # Custom icon. + # typeset -g POWERLEVEL9K_HASKELL_STACK_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #############[ kubecontext: current kubernetes context (https://kubernetes.io/) ]############# + # Show kubecontext only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show kubecontext. + typeset -g POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm|kubens|kubectx|oc|istioctl|kogito|k9s|helmfile|flux|fluxctl|stern|kubeseal|skaffold|kubent|kubecolor|cmctl|sparkctl' + + # Kubernetes context classes for the purpose of using different colors, icons and expansions with + # different contexts. + # + # POWERLEVEL9K_KUBECONTEXT_CLASSES is an array with even number of elements. The first element + # in each pair defines a pattern against which the current kubernetes context gets matched. + # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) + # that gets matched. If you unset all POWERLEVEL9K_KUBECONTEXT_*CONTENT_EXPANSION parameters, + # you'll see this value in your prompt. The second element of each pair in + # POWERLEVEL9K_KUBECONTEXT_CLASSES defines the context class. Patterns are tried in order. The + # first match wins. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=( + # '*prod*' PROD + # '*test*' TEST + # '*' DEFAULT) + # + # If your current kubernetes context is "deathray-testing/default", its class is TEST + # because "deathray-testing/default" doesn't match the pattern '*prod*' but does match '*test*'. + # + # You can define different colors, icons and content expansions for different classes: + # + # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_FOREGROUND=3 + # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' + typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=( + # '*prod*' PROD # These values are examples that are unlikely + # '*test*' TEST # to match your needs. Customize them as needed. + '*' DEFAULT) + typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_FOREGROUND=5 + # typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # Use POWERLEVEL9K_KUBECONTEXT_CONTENT_EXPANSION to specify the content displayed by kubecontext + # segment. Parameter expansions are very flexible and fast, too. See reference: + # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion. + # + # Within the expansion the following parameters are always available: + # + # - P9K_CONTENT The content that would've been displayed if there was no content + # expansion defined. + # - P9K_KUBECONTEXT_NAME The current context's name. Corresponds to column NAME in the + # output of `kubectl config get-contexts`. + # - P9K_KUBECONTEXT_CLUSTER The current context's cluster. Corresponds to column CLUSTER in the + # output of `kubectl config get-contexts`. + # - P9K_KUBECONTEXT_NAMESPACE The current context's namespace. Corresponds to column NAMESPACE + # in the output of `kubectl config get-contexts`. If there is no + # namespace, the parameter is set to "default". + # - P9K_KUBECONTEXT_USER The current context's user. Corresponds to column AUTHINFO in the + # output of `kubectl config get-contexts`. + # + # If the context points to Google Kubernetes Engine (GKE) or Elastic Kubernetes Service (EKS), + # the following extra parameters are available: + # + # - P9K_KUBECONTEXT_CLOUD_NAME Either "gke" or "eks". + # - P9K_KUBECONTEXT_CLOUD_ACCOUNT Account/project ID. + # - P9K_KUBECONTEXT_CLOUD_ZONE Availability zone. + # - P9K_KUBECONTEXT_CLOUD_CLUSTER Cluster. + # + # P9K_KUBECONTEXT_CLOUD_* parameters are derived from P9K_KUBECONTEXT_CLUSTER. For example, + # if P9K_KUBECONTEXT_CLUSTER is "gke_my-account_us-east1-a_my-cluster-01": + # + # - P9K_KUBECONTEXT_CLOUD_NAME=gke + # - P9K_KUBECONTEXT_CLOUD_ACCOUNT=my-account + # - P9K_KUBECONTEXT_CLOUD_ZONE=us-east1-a + # - P9K_KUBECONTEXT_CLOUD_CLUSTER=my-cluster-01 + # + # If P9K_KUBECONTEXT_CLUSTER is "arn:aws:eks:us-east-1:123456789012:cluster/my-cluster-01": + # + # - P9K_KUBECONTEXT_CLOUD_NAME=eks + # - P9K_KUBECONTEXT_CLOUD_ACCOUNT=123456789012 + # - P9K_KUBECONTEXT_CLOUD_ZONE=us-east-1 + # - P9K_KUBECONTEXT_CLOUD_CLUSTER=my-cluster-01 + typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION= + # Show P9K_KUBECONTEXT_CLOUD_CLUSTER if it's not empty and fall back to P9K_KUBECONTEXT_NAME. + POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${P9K_KUBECONTEXT_CLOUD_CLUSTER:-${P9K_KUBECONTEXT_NAME}}' + # Append the current context's namespace if it's not "default". + POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${${:-/$P9K_KUBECONTEXT_NAMESPACE}:#/default}' + + # Custom prefix. + # typeset -g POWERLEVEL9K_KUBECONTEXT_PREFIX='%fat ' + + ################[ terraform: terraform workspace (https://www.terraform.io) ]################# + # Don't show terraform workspace if it's literally "default". + typeset -g POWERLEVEL9K_TERRAFORM_SHOW_DEFAULT=false + # POWERLEVEL9K_TERRAFORM_CLASSES is an array with even number of elements. The first element + # in each pair defines a pattern against which the current terraform workspace gets matched. + # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) + # that gets matched. If you unset all POWERLEVEL9K_TERRAFORM_*CONTENT_EXPANSION parameters, + # you'll see this value in your prompt. The second element of each pair in + # POWERLEVEL9K_TERRAFORM_CLASSES defines the workspace class. Patterns are tried in order. The + # first match wins. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_TERRAFORM_CLASSES=( + # '*prod*' PROD + # '*test*' TEST + # '*' OTHER) + # + # If your current terraform workspace is "project_test", its class is TEST because "project_test" + # doesn't match the pattern '*prod*' but does match '*test*'. + # + # You can define different colors, icons and content expansions for different classes: + # + # typeset -g POWERLEVEL9K_TERRAFORM_TEST_FOREGROUND=2 + # typeset -g POWERLEVEL9K_TERRAFORM_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_TERRAFORM_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' + typeset -g POWERLEVEL9K_TERRAFORM_CLASSES=( + # '*prod*' PROD # These values are examples that are unlikely + # '*test*' TEST # to match your needs. Customize them as needed. + '*' OTHER) + typeset -g POWERLEVEL9K_TERRAFORM_OTHER_FOREGROUND=4 + # typeset -g POWERLEVEL9K_TERRAFORM_OTHER_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #############[ terraform_version: terraform version (https://www.terraform.io) ]############## + # Terraform version color. + typeset -g POWERLEVEL9K_TERRAFORM_VERSION_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_TERRAFORM_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #[ aws: aws profile (https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) ]# + # Show aws only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show aws. + typeset -g POWERLEVEL9K_AWS_SHOW_ON_COMMAND='aws|awless|terraform|pulumi|terragrunt' + + # POWERLEVEL9K_AWS_CLASSES is an array with even number of elements. The first element + # in each pair defines a pattern against which the current AWS profile gets matched. + # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) + # that gets matched. If you unset all POWERLEVEL9K_AWS_*CONTENT_EXPANSION parameters, + # you'll see this value in your prompt. The second element of each pair in + # POWERLEVEL9K_AWS_CLASSES defines the profile class. Patterns are tried in order. The + # first match wins. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_AWS_CLASSES=( + # '*prod*' PROD + # '*test*' TEST + # '*' DEFAULT) + # + # If your current AWS profile is "company_test", its class is TEST + # because "company_test" doesn't match the pattern '*prod*' but does match '*test*'. + # + # You can define different colors, icons and content expansions for different classes: + # + # typeset -g POWERLEVEL9K_AWS_TEST_FOREGROUND=2 + # typeset -g POWERLEVEL9K_AWS_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_AWS_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' + typeset -g POWERLEVEL9K_AWS_CLASSES=( + # '*prod*' PROD # These values are examples that are unlikely + # '*test*' TEST # to match your needs. Customize them as needed. + '*' DEFAULT) + typeset -g POWERLEVEL9K_AWS_DEFAULT_FOREGROUND=3 + # typeset -g POWERLEVEL9K_AWS_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # AWS segment format. The following parameters are available within the expansion. + # + # - P9K_AWS_PROFILE The name of the current AWS profile. + # - P9K_AWS_REGION The region associated with the current AWS profile. + typeset -g POWERLEVEL9K_AWS_CONTENT_EXPANSION='${P9K_AWS_PROFILE//\%/%%}${P9K_AWS_REGION:+ ${P9K_AWS_REGION//\%/%%}}' + + #[ aws_eb_env: aws elastic beanstalk environment (https://aws.amazon.com/elasticbeanstalk/) ]# + # AWS Elastic Beanstalk environment color. + typeset -g POWERLEVEL9K_AWS_EB_ENV_FOREGROUND=2 + # Custom icon. + # typeset -g POWERLEVEL9K_AWS_EB_ENV_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ azure: azure account name (https://docs.microsoft.com/en-us/cli/azure) ]########## + # Show azure only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show azure. + typeset -g POWERLEVEL9K_AZURE_SHOW_ON_COMMAND='az|terraform|pulumi|terragrunt' + + # POWERLEVEL9K_AZURE_CLASSES is an array with even number of elements. The first element + # in each pair defines a pattern against which the current azure account name gets matched. + # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) + # that gets matched. If you unset all POWERLEVEL9K_AZURE_*CONTENT_EXPANSION parameters, + # you'll see this value in your prompt. The second element of each pair in + # POWERLEVEL9K_AZURE_CLASSES defines the account class. Patterns are tried in order. The + # first match wins. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_AZURE_CLASSES=( + # '*prod*' PROD + # '*test*' TEST + # '*' OTHER) + # + # If your current azure account is "company_test", its class is TEST because "company_test" + # doesn't match the pattern '*prod*' but does match '*test*'. + # + # You can define different colors, icons and content expansions for different classes: + # + # typeset -g POWERLEVEL9K_AZURE_TEST_FOREGROUND=2 + # typeset -g POWERLEVEL9K_AZURE_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_AZURE_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' + typeset -g POWERLEVEL9K_AZURE_CLASSES=( + # '*prod*' PROD # These values are examples that are unlikely + # '*test*' TEST # to match your needs. Customize them as needed. + '*' OTHER) + + # Azure account name color. + typeset -g POWERLEVEL9K_AZURE_OTHER_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_AZURE_OTHER_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ##########[ gcloud: google cloud account and project (https://cloud.google.com/) ]########### + # Show gcloud only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show gcloud. + typeset -g POWERLEVEL9K_GCLOUD_SHOW_ON_COMMAND='gcloud|gcs|gsutil' + # Google cloud color. + typeset -g POWERLEVEL9K_GCLOUD_FOREGROUND=4 + + # Google cloud format. Change the value of POWERLEVEL9K_GCLOUD_PARTIAL_CONTENT_EXPANSION and/or + # POWERLEVEL9K_GCLOUD_COMPLETE_CONTENT_EXPANSION if the default is too verbose or not informative + # enough. You can use the following parameters in the expansions. Each of them corresponds to the + # output of `gcloud` tool. + # + # Parameter | Source + # -------------------------|-------------------------------------------------------------------- + # P9K_GCLOUD_CONFIGURATION | gcloud config configurations list --format='value(name)' + # P9K_GCLOUD_ACCOUNT | gcloud config get-value account + # P9K_GCLOUD_PROJECT_ID | gcloud config get-value project + # P9K_GCLOUD_PROJECT_NAME | gcloud projects describe $P9K_GCLOUD_PROJECT_ID --format='value(name)' + # + # Note: ${VARIABLE//\%/%%} expands to ${VARIABLE} with all occurrences of '%' replaced with '%%'. + # + # Obtaining project name requires sending a request to Google servers. This can take a long time + # and even fail. When project name is unknown, P9K_GCLOUD_PROJECT_NAME is not set and gcloud + # prompt segment is in state PARTIAL. When project name gets known, P9K_GCLOUD_PROJECT_NAME gets + # set and gcloud prompt segment transitions to state COMPLETE. + # + # You can customize the format, icon and colors of gcloud segment separately for states PARTIAL + # and COMPLETE. You can also hide gcloud in state PARTIAL by setting + # POWERLEVEL9K_GCLOUD_PARTIAL_VISUAL_IDENTIFIER_EXPANSION and + # POWERLEVEL9K_GCLOUD_PARTIAL_CONTENT_EXPANSION to empty. + typeset -g POWERLEVEL9K_GCLOUD_PARTIAL_CONTENT_EXPANSION='${P9K_GCLOUD_PROJECT_ID//\%/%%}' + typeset -g POWERLEVEL9K_GCLOUD_COMPLETE_CONTENT_EXPANSION='${P9K_GCLOUD_PROJECT_NAME//\%/%%}' + + # Send a request to Google (by means of `gcloud projects describe ...`) to obtain project name + # this often. Negative value disables periodic polling. In this mode project name is retrieved + # only when the current configuration, account or project id changes. + typeset -g POWERLEVEL9K_GCLOUD_REFRESH_PROJECT_NAME_SECONDS=60 + + # Custom icon. + # typeset -g POWERLEVEL9K_GCLOUD_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #[ google_app_cred: google application credentials (https://cloud.google.com/docs/authentication/production) ]# + # Show google_app_cred only when the command you are typing invokes one of these tools. + # Tip: Remove the next line to always show google_app_cred. + typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_SHOW_ON_COMMAND='terraform|pulumi|terragrunt' + + # Google application credentials classes for the purpose of using different colors, icons and + # expansions with different credentials. + # + # POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES is an array with even number of elements. The first + # element in each pair defines a pattern against which the current kubernetes context gets + # matched. More specifically, it's P9K_CONTENT prior to the application of context expansion + # (see below) that gets matched. If you unset all POWERLEVEL9K_GOOGLE_APP_CRED_*CONTENT_EXPANSION + # parameters, you'll see this value in your prompt. The second element of each pair in + # POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES defines the context class. Patterns are tried in order. + # The first match wins. + # + # For example, given these settings: + # + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES=( + # '*:*prod*:*' PROD + # '*:*test*:*' TEST + # '*' DEFAULT) + # + # If your current Google application credentials is "service_account deathray-testing x@y.com", + # its class is TEST because it doesn't match the pattern '* *prod* *' but does match '* *test* *'. + # + # You can define different colors, icons and content expansions for different classes: + # + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_TEST_FOREGROUND=3 + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_TEST_CONTENT_EXPANSION='$P9K_GOOGLE_APP_CRED_PROJECT_ID' + typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES=( + # '*:*prod*:*' PROD # These values are examples that are unlikely + # '*:*test*:*' TEST # to match your needs. Customize them as needed. + '*' DEFAULT) + typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_FOREGROUND=5 + # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # Use POWERLEVEL9K_GOOGLE_APP_CRED_CONTENT_EXPANSION to specify the content displayed by + # google_app_cred segment. Parameter expansions are very flexible and fast, too. See reference: + # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion. + # + # You can use the following parameters in the expansion. Each of them corresponds to one of the + # fields in the JSON file pointed to by GOOGLE_APPLICATION_CREDENTIALS. + # + # Parameter | JSON key file field + # ---------------------------------+--------------- + # P9K_GOOGLE_APP_CRED_TYPE | type + # P9K_GOOGLE_APP_CRED_PROJECT_ID | project_id + # P9K_GOOGLE_APP_CRED_CLIENT_EMAIL | client_email + # + # Note: ${VARIABLE//\%/%%} expands to ${VARIABLE} with all occurrences of '%' replaced by '%%'. + typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_CONTENT_EXPANSION='${P9K_GOOGLE_APP_CRED_PROJECT_ID//\%/%%}' + + ##############[ toolbox: toolbox name (https://github.com/containers/toolbox) ]############### + # Toolbox color. + typeset -g POWERLEVEL9K_TOOLBOX_FOREGROUND=3 + # Don't display the name of the toolbox if it matches fedora-toolbox-*. + typeset -g POWERLEVEL9K_TOOLBOX_CONTENT_EXPANSION='${P9K_TOOLBOX_NAME:#fedora-toolbox-*}' + # Custom icon. + # typeset -g POWERLEVEL9K_TOOLBOX_VISUAL_IDENTIFIER_EXPANSION='⭐' + # Custom prefix. + # typeset -g POWERLEVEL9K_TOOLBOX_PREFIX='%fin ' + + ###############################[ public_ip: public IP address ]############################### + # Public IP color. + typeset -g POWERLEVEL9K_PUBLIC_IP_FOREGROUND=6 + # Custom icon. + # typeset -g POWERLEVEL9K_PUBLIC_IP_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ########################[ vpn_ip: virtual private network indicator ]######################### + # VPN IP color. + typeset -g POWERLEVEL9K_VPN_IP_FOREGROUND=3 + # When on VPN, show just an icon without the IP address. + # Tip: To display the private IP address when on VPN, remove the next line. + typeset -g POWERLEVEL9K_VPN_IP_CONTENT_EXPANSION= + # Regular expression for the VPN network interface. Run `ifconfig` or `ip -4 a show` while on VPN + # to see the name of the interface. + typeset -g POWERLEVEL9K_VPN_IP_INTERFACE='(gpd|wg|(.*tun)|tailscale)[0-9]*|(zt.*)' + # If set to true, show one segment per matching network interface. If set to false, show only + # one segment corresponding to the first matching network interface. + # Tip: If you set it to true, you'll probably want to unset POWERLEVEL9K_VPN_IP_CONTENT_EXPANSION. + typeset -g POWERLEVEL9K_VPN_IP_SHOW_ALL=false + # Custom icon. + # typeset -g POWERLEVEL9K_VPN_IP_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ###########[ ip: ip address and bandwidth usage for a specified network interface ]########### + # IP color. + typeset -g POWERLEVEL9K_IP_FOREGROUND=4 + # The following parameters are accessible within the expansion: + # + # Parameter | Meaning + # ----------------------+------------------------------------------- + # P9K_IP_IP | IP address + # P9K_IP_INTERFACE | network interface + # P9K_IP_RX_BYTES | total number of bytes received + # P9K_IP_TX_BYTES | total number of bytes sent + # P9K_IP_RX_BYTES_DELTA | number of bytes received since last prompt + # P9K_IP_TX_BYTES_DELTA | number of bytes sent since last prompt + # P9K_IP_RX_RATE | receive rate (since last prompt) + # P9K_IP_TX_RATE | send rate (since last prompt) + typeset -g POWERLEVEL9K_IP_CONTENT_EXPANSION='$P9K_IP_IP${P9K_IP_RX_RATE:+ %2F⇣$P9K_IP_RX_RATE}${P9K_IP_TX_RATE:+ %3F⇡$P9K_IP_TX_RATE}' + # Show information for the first network interface whose name matches this regular expression. + # Run `ifconfig` or `ip -4 a show` to see the names of all network interfaces. + typeset -g POWERLEVEL9K_IP_INTERFACE='[ew].*' + # Custom icon. + # typeset -g POWERLEVEL9K_IP_VISUAL_IDENTIFIER_EXPANSION='⭐' + + #########################[ proxy: system-wide http/https/ftp proxy ]########################## + # Proxy color. + typeset -g POWERLEVEL9K_PROXY_FOREGROUND=2 + # Custom icon. + # typeset -g POWERLEVEL9K_PROXY_VISUAL_IDENTIFIER_EXPANSION='⭐' + + ################################[ battery: internal battery ]################################# + # Show battery in red when it's below this level and not connected to power supply. + typeset -g POWERLEVEL9K_BATTERY_LOW_THRESHOLD=20 + typeset -g POWERLEVEL9K_BATTERY_LOW_FOREGROUND=1 + # Show battery in green when it's charging or fully charged. + typeset -g POWERLEVEL9K_BATTERY_{CHARGING,CHARGED}_FOREGROUND=2 + # Show battery in yellow when it's discharging. + typeset -g POWERLEVEL9K_BATTERY_DISCONNECTED_FOREGROUND=3 + # Battery pictograms going from low to high level of charge. + typeset -g POWERLEVEL9K_BATTERY_STAGES='\UF008E\UF007A\UF007B\UF007C\UF007D\UF007E\UF007F\UF0080\UF0081\UF0082\UF0079' + # Don't show the remaining time to charge/discharge. + typeset -g POWERLEVEL9K_BATTERY_VERBOSE=false + + #####################################[ wifi: wifi speed ]##################################### + # WiFi color. + typeset -g POWERLEVEL9K_WIFI_FOREGROUND=4 + # Custom icon. + # typeset -g POWERLEVEL9K_WIFI_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # Use different colors and icons depending on signal strength ($P9K_WIFI_BARS). + # + # # Wifi colors and icons for different signal strength levels (low to high). + # typeset -g my_wifi_fg=(4 4 4 4 4) # <-- change these values + # typeset -g my_wifi_icon=('WiFi' 'WiFi' 'WiFi' 'WiFi' 'WiFi') # <-- change these values + # + # typeset -g POWERLEVEL9K_WIFI_CONTENT_EXPANSION='%F{${my_wifi_fg[P9K_WIFI_BARS+1]}}$P9K_WIFI_LAST_TX_RATE Mbps' + # typeset -g POWERLEVEL9K_WIFI_VISUAL_IDENTIFIER_EXPANSION='%F{${my_wifi_fg[P9K_WIFI_BARS+1]}}${my_wifi_icon[P9K_WIFI_BARS+1]}' + # + # The following parameters are accessible within the expansions: + # + # Parameter | Meaning + # ----------------------+--------------- + # P9K_WIFI_SSID | service set identifier, a.k.a. network name + # P9K_WIFI_LINK_AUTH | authentication protocol such as "wpa2-psk" or "none"; empty if unknown + # P9K_WIFI_LAST_TX_RATE | wireless transmit rate in megabits per second + # P9K_WIFI_RSSI | signal strength in dBm, from -120 to 0 + # P9K_WIFI_NOISE | noise in dBm, from -120 to 0 + # P9K_WIFI_BARS | signal strength in bars, from 0 to 4 (derived from P9K_WIFI_RSSI and P9K_WIFI_NOISE) + + ####################################[ time: current time ]#################################### + # Current time color. + typeset -g POWERLEVEL9K_TIME_FOREGROUND=6 + # Format for the current time: 09:51:02. See `man 3 strftime`. + typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}' + # If set to true, time will update when you hit enter. This way prompts for the past + # commands will contain the start times of their commands as opposed to the default + # behavior where they contain the end times of their preceding commands. + typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false + # Custom icon. + typeset -g POWERLEVEL9K_TIME_VISUAL_IDENTIFIER_EXPANSION= + # Custom prefix. + # typeset -g POWERLEVEL9K_TIME_PREFIX='%fat ' + + # Example of a user-defined prompt segment. Function prompt_example will be called on every + # prompt if `example` prompt segment is added to POWERLEVEL9K_LEFT_PROMPT_ELEMENTS or + # POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS. It displays an icon and green text greeting the user. + # + # Type `p10k help segment` for documentation and a more sophisticated example. + function prompt_example() { + p10k segment -f 2 -i '⭐' -t 'hello, %n' + } + + # User-defined prompt segments may optionally provide an instant_prompt_* function. Its job + # is to generate the prompt segment for display in instant prompt. See + # https://github.com/romkatv/powerlevel10k/blob/master/README.md#instant-prompt. + # + # Powerlevel10k will call instant_prompt_* at the same time as the regular prompt_* function + # and will record all `p10k segment` calls it makes. When displaying instant prompt, Powerlevel10k + # will replay these calls without actually calling instant_prompt_*. It is imperative that + # instant_prompt_* always makes the same `p10k segment` calls regardless of environment. If this + # rule is not observed, the content of instant prompt will be incorrect. + # + # Usually, you should either not define instant_prompt_* or simply call prompt_* from it. If + # instant_prompt_* is not defined for a segment, the segment won't be shown in instant prompt. + function instant_prompt_example() { + # Since prompt_example always makes the same `p10k segment` calls, we can call it from + # instant_prompt_example. This will give us the same `example` prompt segment in the instant + # and regular prompts. + prompt_example + } + + # User-defined prompt segments can be customized the same way as built-in segments. + # typeset -g POWERLEVEL9K_EXAMPLE_FOREGROUND=208 + # typeset -g POWERLEVEL9K_EXAMPLE_VISUAL_IDENTIFIER_EXPANSION='⭐' + + # Transient prompt works similarly to the builtin transient_rprompt option. It trims down prompt + # when accepting a command line. Supported values: + # + # - off: Don't change prompt when accepting a command line. + # - always: Trim down prompt when accepting a command line. + # - same-dir: Trim down prompt when accepting a command line unless this is the first command + # typed after changing current working directory. + typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=always + + # Instant prompt mode. + # + # - off: Disable instant prompt. Choose this if you've tried instant prompt and found + # it incompatible with your zsh configuration files. + # - quiet: Enable instant prompt and don't print warnings when detecting console output + # during zsh initialization. Choose this if you've read and understood + # https://github.com/romkatv/powerlevel10k/blob/master/README.md#instant-prompt. + # - verbose: Enable instant prompt and print a warning when detecting console output during + # zsh initialization. Choose this if you've never tried instant prompt, haven't + # seen the warning, or if you are unsure what this all means. + typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet + + # Hot reload allows you to change POWERLEVEL9K options after Powerlevel10k has been initialized. + # For example, you can type POWERLEVEL9K_BACKGROUND=red and see your prompt turn red. Hot reload + # can slow down prompt by 1-2 milliseconds, so it's better to keep it turned off unless you + # really need it. + typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true + + # If p10k is already loaded, reload configuration. + # This works even with POWERLEVEL9K_DISABLE_HOT_RELOAD=true. + (( ! $+functions[p10k] )) || p10k reload +} + +# Tell `p10k configure` which file it should overwrite. +typeset -g POWERLEVEL9K_CONFIG_FILE=${${(%):-%x}:a} + +(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]} +'builtin' 'unset' 'p10k_config_opts' diff --git a/.config/zsh/.zshenv b/.config/zsh/.zshenv new file mode 100644 index 0000000..f7ffaec --- /dev/null +++ b/.config/zsh/.zshenv @@ -0,0 +1,45 @@ +# Documentation: https://github.com/romkatv/zsh4humans/blob/v5/README.md. +# +# Do not modify this file unless you know exactly what you are doing. +# It is strongly recommended to keep all shell customization and configuration +# (including exported environment variables such as PATH) in ~/.zshrc or in +# files sourced from ~/.zshrc. If you are certain that you must export some +# environment variables in ~/.zshenv, do it where indicated by comments below. + +if [ -n "${ZSH_VERSION-}" ]; then + # If you are certain that you must export some environment variables + # in ~/.zshenv (see comments at the top!), do it here: + # + # export GOPATH=$HOME/go + # + # Do not change anything else in this file. + + : ${ZDOTDIR:=~} + setopt no_global_rcs + [[ -o no_interactive && -z "${Z4H_BOOTSTRAPPING-}" ]] && return + setopt no_rcs + unset Z4H_BOOTSTRAPPING +fi + +Z4H_URL="https://raw.githubusercontent.com/romkatv/zsh4humans/v5" +: "${Z4H:=${XDG_CACHE_HOME:-$HOME/.cache}/zsh4humans/v5}" + +umask o-w + +if [ ! -e "$Z4H"/z4h.zsh ]; then + mkdir -p -- "$Z4H" || return + >&2 printf '\033[33mz4h\033[0m: fetching \033[4mz4h.zsh\033[0m\n' + if command -v curl >/dev/null 2>&1; then + curl -fsSL -- "$Z4H_URL"/z4h.zsh >"$Z4H"/z4h.zsh.$$ || return + elif command -v wget >/dev/null 2>&1; then + wget -O- -- "$Z4H_URL"/z4h.zsh >"$Z4H"/z4h.zsh.$$ || return + else + >&2 printf '\033[33mz4h\033[0m: please install \033[32mcurl\033[0m or \033[32mwget\033[0m\n' + return 1 + fi + mv -- "$Z4H"/z4h.zsh.$$ "$Z4H"/z4h.zsh || return +fi + +. "$Z4H"/z4h.zsh || return + +setopt rcs diff --git a/.config/zsh/.zshrc b/.config/zsh/.zshrc new file mode 100644 index 0000000..0f985f1 --- /dev/null +++ b/.config/zsh/.zshrc @@ -0,0 +1,111 @@ +# Documentation: https://github.com/romkatv/zsh4humans/blob/v5/README.md. + +# You can manually run `z4h update` to update everything. +zstyle ':z4h:' auto-update 'no' +zstyle ':z4h:' auto-update-days '28' +zstyle ':z4h:bindkey' keyboard 'pc' +zstyle ':z4h:' start-tmux no +zstyle ':z4h:' term-shell-integration 'yes' +zstyle ':z4h:autosuggestions' forward-char 'accept' +zstyle ':z4h:fzf-complete' recurse-dirs yes +zstyle ':z4h:direnv' enable 'no' +zstyle ':z4h:direnv:success' notify 'yes' + +z4h init || return + +export PATH="$PATH:${$(find ~/.local/bin -type d -printf %p:)%%:}" +export PATH=$PATH:~/.local/share/npm/bin +export GPG_TTY=$TTY +# Default programs: +export EDITOR="nvim" +export TERMINAL="st" +export TERMINAL_PROG="st" +export BROWSER="firefox" +export MANPAGER="nvim +Man!" +export XDG_SESSION_TYPE="x11" +# ~/ Clean-up: +export XDG_CONFIG_HOME="$HOME/.config" +export XDG_DATA_HOME="$HOME/.local/share" +export XDG_CACHE_HOME="$HOME/.cache" +export XDG_STATE_HOME="$HOME/.local/state" +export XINITRC="$XDG_CONFIG_HOME/x11/xinitrc" +export XAUTHORITY="$XDG_RUNTIME_DIR/Xauthority" +export NOTMUCH_CONFIG="$XDG_CONFIG_HOME/notmuch-config" +export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc-2.0" +export WGETRC="$XDG_CONFIG_HOME/wget/wgetrc" +export INPUTRC="$XDG_CONFIG_HOME/shell/inputrc" +export RUSTUP_HOME="$XDG_DATA_HOME"/rustup +export PASSWORD_STORE_DIR="$XDG_DATA_HOME"/pass +export BUNDLE_PATH="$HOME/.cache/bundle" + +#export GNUPGHOME="$XDG_DATA_HOME/gnupg" +export TMUX_TMPDIR="$XDG_RUNTIME_DIR" +export CARGO_HOME="$XDG_DATA_HOME/cargo" +export GOPATH="$XDG_DATA_HOME/go" +export GOMODCACHE="$XDG_CACHE_HOME/go/mod" +export HISTFILE="$XDG_DATA_HOME/history" +export PYTHONSTARTUP="$XDG_CONFIG_HOME/python/pythonrc" +export SQLITE_HISTORY="$XDG_DATA_HOME/sqlite_history" +export TERMINFO="$XDG_DATA_HOME"/terminfo +export TERMINFO_DIRS="$XDG_DATA_HOME"/terminfo:/usr/share/terminfo +export NPM_CONFIG_USERCONFIG=$XDG_CONFIG_HOME/npm/npmrc +export DICS="/usr/share/stardict/dic/" +export SUDO_ASKPASS="$HOME/.local/bin/dmenupass" +export LESS=-R +export LESS_TERMCAP_mb="$(printf '%b' '')" +export LESS_TERMCAP_md="$(printf '%b' '')" +export LESS_TERMCAP_me="$(printf '%b' '')" +export LESS_TERMCAP_so="$(printf '%b' '')" +export LESS_TERMCAP_se="$(printf '%b' '')" +export LESS_TERMCAP_us="$(printf '%b' '')" +export LESS_TERMCAP_ue="$(printf '%b' '')" +export LESSOPEN="| /usr/bin/highlight -O ansi %s 2>/dev/null" +export QT_QPA_PLATFORMTHEME="gtk2" # Have QT use gtk2 theme. +export QT_SCALE_FACTOR=1.1 +export MOZ_USE_XINPUT2="1" # Mozilla smooth scrolling/touchpads. +export AWT_TOOLKIT="MToolkit wmname LG3D" # May have to install wmname +export _JAVA_AWT_WM_NONREPARENTING=1 # Fix for Java applications in dwm +export FZF_DEFAULT_OPTS="--layout=reverse --height=70% --inline-info" + +[ ! -f ${XDG_CONFIG_HOME:-$HOME/.config}/shell/shortcutrc ] && setsid shortcuts >/dev/null 2>&1 + +sudo -n loadkeys ${XDG_DATA_HOME:-$HOME/.local/share}/larbs/ttymaps.kmap 2>/dev/null + +z4h source ~/.config/shell/{aliasrc,shortcutrc,zshnameddirrc,exportsrc,vi.zsh} + +z4h bindkey z4h-backward-kill-word Ctrl+Backspace +z4h bindkey z4h-backward-kill-zword Ctrl+Alt+Backspace +z4h bindkey undo Ctrl+/ Shift+Tab +z4h bindkey redo Alt+/ + +z4h bindkey z4h-cd-back Alt+Left +z4h bindkey z4h-cd-forward Alt+Right +z4h bindkey z4h-cd-up Alt+Up +z4h bindkey z4h-cd-down Alt+Down +bindkey -s '^o' '^ulfcd\n' +bindkey -s '^f' '^ucd "$(dirname "$(fzf)")"\n' + +# Autoload functions. +autoload -Uz zmv + +function font-search () { + fc-list | cut -d: -f2- | fzf --layout=reverse --info=inline --padding=1 +} +# Use lf to switch directories and bind it to ctrl-o +function lfcd () { + tmp="$(mktemp -uq)" + trap 'rm -f $tmp >/dev/null 2>&1 && trap - HUP INT QUIT TERM PWR EXIT' HUP INT QUIT TERM PWR EXIT + lf -last-dir-path="$tmp" "$@" + if [ -f "$tmp" ]; then + dir="$(cat "$tmp")" + [ -d "$dir" ] && [ "$dir" != "$(pwd)" ] && cd "$dir" + fi +} +# Define functions and completions. +function md() { [[ $# == 1 ]] && mkdir -p -- "$1" && cd -- "$1" } +compdef _directories md + +unsetopt PROMPT_SP +setopt glob_dots +setopt autocd always_to_end interactive_comments extended_glob multios +setopt extended_history append_history hist_ignore_dups hist_find_no_dups hist_ignore_space hist_verify hist_save_no_dups diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b1bf04 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.stow-local-ignore +.config/nvim/spell diff --git a/.local/bin/confedit b/.local/bin/confedit new file mode 100755 index 0000000..e66b01b --- /dev/null +++ b/.local/bin/confedit @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +configs=( + "$XDG_CONFIG_HOME/suckless/dmenu/config.h" + "$XDG_CONFIG_HOME/suckless/dwm/config.h" + "$XDG_CONFIG_HOME/suckless/dwmblocks/config.h" + "$XDG_CONFIG_HOME/suckless/st/config.h" + "$XDG_CONFIG_HOME/x11/xresources" + "$XDG_CONFIG_HOME/nvim/lua" + "$XDG_CONFIG_HOME/zsh/.zshrc" + "$XDG_CONFIG_HOME/shell/aliasrc" + "$XDG_CONFIG_HOME/x11/xinitrc" + "$XDG_CONFIG_HOME/x11/xprofile" + "$HOME/.bashrc" + "$XDG_CONFIG_HOME/mpd/mpd.conf" + "$XDG_CONFIG_HOME/ncmpcpp/config" + "$XDG_CONFIG_HOME/dunst/dunstrc" + "$XDG_CONFIG_HOME/gtk-2.0/gtkrc-2.0" + "$XDG_CONFIG_HOME/gtk-3.0/settings.ini" + "$XDG_CONFIG_HOME/lf/lfrc" + "$XDG_CONFIG_HOME/newsboat/config" + "$XDG_CONFIG_HOME/newsboat/urls" + "$XDG_CONFIG_HOME/zathura/zathurarc" + "$XDG_DATA_HOME/script-data/keybinds" + "$XDG_CONFIG_HOME/dmenu_web" +) + +fzf_command="fzfp --ansi --layout=reverse -m --marker='󰄾' --pointer=' 󰶻'" + +selected=$(printf '%s\n' "${configs[@]}" | eval "$fzf_command") +if [ -n "$selected" ]; then + nvim "$selected" +fi diff --git a/.local/bin/desktop_click b/.local/bin/desktop_click new file mode 100755 index 0000000..bebcc5a --- /dev/null +++ b/.local/bin/desktop_click @@ -0,0 +1,9 @@ +#!/bin/bash + +# Check if dmenu is running +dunstctl close-all +if pgrep -x "dmenu" > /dev/null; then + killall dmenu; +else + dmenu_hub +fi diff --git a/.local/bin/dmenu_hub b/.local/bin/dmenu_hub new file mode 100755 index 0000000..8a26875 --- /dev/null +++ b/.local/bin/dmenu_hub @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +import subprocess + +dmenu_command = "dmenu -i -l 16 -W 200 -Y 15 -X 1151 -bw 2" +apps = "dmenu_run -bw 2 -i -W 390 -X 961 -Y 15 -l 16 -g 3" +camera = ( + "mpv --untimed --no-cache --no-osc " + "--no-input-default-bindings --profile=low-latency " + "--input-conf=/dev/null --title=webcam " + "$(ls /dev/video[0,2,4,6,8] | tail -n 1)" +) +bar_colors_toggle = '[ -e "$HOME/.cache/bar_color" ] && { rm "$HOME/.cache/bar_color"; renew-dwm; } || { touch "$HOME/.cache/bar_color"; renew-dwm; }' + +options = { + f"󰀻 Apps": apps, + f"󰉦 Bar colors": bar_colors_toggle, + f" Edit Configs": "st -e confedit", + f" Web Search": "dmenu_web", + f"󰌌 Keybinds": "keybinds", + f"󰋊 Mount": "mounter", + f"󱁌 Unmount": "unmounter", + f" Kill": "processkill", + f" Pick Color": "xcolor-pick", + f" Screenshot": "maimpick", + f" Record": "dmenurecord", + f"󰄄 Camera": camera, + f" NerdFont Icons": "dmenunerdsymbols", +} +option_list = list(options.keys()) +try: + selected_option = ( + subprocess.check_output( + dmenu_command.split(), input="\n".join(option_list).encode() + ) + .decode() + .strip() + ) + action = options[selected_option] + subprocess.run(action, shell=True) +except subprocess.CalledProcessError: + pass diff --git a/.local/bin/dmenu_web b/.local/bin/dmenu_web new file mode 100755 index 0000000..c7f4d2d --- /dev/null +++ b/.local/bin/dmenu_web @@ -0,0 +1,38 @@ +#! /usr/bin/env bash +BROWSER="firefox" +SEARCH_ENGINE="https://encrypted.google.com/search?hl=en&safe=off&num=50&pws=0&q=" +BOOKMARKS_FILE="$HOME/.config/dmenu_web/bookmarks" +SITES_FILE="$HOME/.config/dmenu_web/search_urls" +NOTIFICAION_FILE="$HOME/.config/dmenu_web/notification" +DMENU_COMMAND="dmenu -i -bw 2 -W 290 -X 810 -Y 19 -l 17 -g 2 -p \" \"" +DMENU_COMMAND_FOR_ADD_BOOKMARK="dmenu -bw 2 -W 800 -X 283 -Y 190 -p \"󰃅 Add Bookmark: \"" +declare -A SEARCH_URLS +while IFS=',' read -r site url; do + SEARCH_URLS["$site"]="$url" +done <"$SITES_FILE" +if [ "$1" == "--add" ]; then + bookmark="$(xclip -o)" + [ -z "$bookmark" ] || [ -z "${bookmark// /}" ] && notify-send "Bookmark not saved: Nothing to save" && exit 0 + echo "$bookmark" | grep -Eq '\.[a-zA-Z]{2,}$' || { + notify-send "Not a valid URL" + exit 0 + } + grep -qF "$bookmark" "$BOOKMARKS_FILE" && notify-send "Already bookmarked!" && exit 0 + user_input=$(eval "$DMENU_COMMAND_FOR_ADD_BOOKMARK" <&-) + [ -z "$user_input" ] || [ -z "${user_input// /}" ] && notify-send "Bookmark not saved: Empty Name" && exit 0 + bookmark_entry="${user_input},${bookmark}" + echo "$bookmark_entry" >>"$BOOKMARKS_FILE" + notify-send "Bookmark: $user_input" "$bookmark" + exit 0 +fi +descriptions=$(cut -d ',' -f 1 "$BOOKMARKS_FILE") +notify-send -t 30000 "$(cat "$NOTIFICAION_FILE")" && query=$(echo "$descriptions" | eval "$DMENU_COMMAND") +dunstctl close-all +[ -z "$query" ] || [ -z "${query// /}" ] && exit 0 +url=$(grep "^$query," "$BOOKMARKS_FILE" | cut -d ',' -f 2) +[ -n "$url" ] && "$BROWSER" "$url" && exit 0 +site=$(echo "$query" | cut -d ' ' -f 1) && search_url="${SEARCH_URLS[$site]}" +[ "$site" == "1337" ] && [ -n "$search_url" ] && search_query="${query//$site /}" && "$BROWSER" "$search_url$search_query/1/" && exit 0 +[ -n "$search_url" ] && search_query="${query//$site /}" && "$BROWSER" "$search_url$search_query" && exit 0 +echo "$query" | grep -Eq '\.[a-zA-Z]{2,}$' && "$BROWSER" "$query" && exit 0 +"$BROWSER" "$SEARCH_ENGINE$query" && exit 0 diff --git a/.local/bin/dmenuemoji b/.local/bin/dmenuemoji new file mode 100755 index 0000000..94ed472 --- /dev/null +++ b/.local/bin/dmenuemoji @@ -0,0 +1,20 @@ +#!/bin/sh + +# The get a "menu of emojis to copy" script. + +# Includes: +# Emoji (1630) + +chosen=$(cut -d ';' -f1 ~/.local/share/script-data/chars/e* | dmenu -i -l 30 -W 380 -X 971 -Y 15 -bw 2 | sed "s/ .*//") + +# Exit if none chosen. +[ -z "$chosen" ] && exit + +# If you run this command with an argument, it will automatically insert the +# character. Otherwise, show a message that the emoji has been copied. +if [ -n "$1" ]; then + xdotool type "$chosen" +else + printf "%s" "$chosen" | xclip -selection clipboard + notify-send "'$chosen' copied to clipboard." & +fi diff --git a/.local/bin/dmenuhandler b/.local/bin/dmenuhandler new file mode 100755 index 0000000..2e90720 --- /dev/null +++ b/.local/bin/dmenuhandler @@ -0,0 +1,20 @@ +#!/bin/sh + +# Feed this script a link and it will give dmenu +# some choice programs to use to open it. +feed="${1:-$(true | dmenu -p 'Paste URL or file path')}" + +case "$(printf "Search in Browser\\nOpen in Browser\\nCopy URL\\nQueue Video\\nQueue Audio\\nQueue Download\\nPlay\\nPlay (loop)\\nView Image\\nSet Background\\nOpen PDF\\nOpen in Vim" | dmenu -i -l 16 -W 200 -Y 15 -X 1151 -bw 2)" in + "Copy URL") echo "$feed" | xclip -selection clipboard ;; + "Play") setsid -f mpv -quiet "$feed" >/dev/null 2>&1 ;; + "Play (loop)") setsid -f mpv -quiet --loop "$feed" >/dev/null 2>&1 ;; + "Queue Video") qndl "$feed" >/dev/null 2>&1 ;; + "Queue Audio") qndl "$feed" 'yt-dlp -o "%(title)s.%(ext)s" -f bestaudio --embed-metadata --restrict-filenames' ;; + "Queue Download") qndl "$feed" 'curl -LO' >/dev/null 2>&1 ;; + "Open PDF") curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" && zathura "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" >/dev/null 2>&1 ;; + "Open Image") curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" && nsxiv -a "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" >/dev/null 2>&1 ;; + "Open in Vim") curl -sL "$feed" > "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" && setsid -f "$TERMINAL" -e "$EDITOR" "/tmp/$(echo "$feed" | sed "s|.*/||;s/%20/ /g")" >/dev/null 2>&1 ;; + "Set Background") curl -L "$feed" > $XDG_CACHE_HOME/pic ; xwallpaper --zoom $XDG_CACHE_HOME/pic >/dev/null 2>&1 ;; + "Search in Browser") setsid -f "$BROWSER" -search "$feed" >/dev/null 2>&1 ;; + "Open in Browser") setsid -f "$BROWSER" "$feed" >/dev/null 2>&1 ;; +esac diff --git a/.local/bin/dmenunerdsymbols b/.local/bin/dmenunerdsymbols new file mode 100755 index 0000000..8c1406b --- /dev/null +++ b/.local/bin/dmenunerdsymbols @@ -0,0 +1,28 @@ +#!/bin/bash + +json_url="https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/glyphnames.json" +local_file="$HOME/.local/share/script-data/chars/nerd-glyphs.json" + +function needs_update() { + local local_date + local current_date + local_date=$(stat -c %Y "$local_file" 2>/dev/null || echo 0) + current_date=$(date +%s) + [ "$((current_date - local_date))" -ge "$((14 * 24 * 3600))" ] +} + +if needs_update; then + remote_date=$(curl -sI "$json_url" | grep -i '^Last-Modified:' | sed 's/Last-Modified: //') + if [ "$remote_date" != "$(stat -c %y "$local_file" 2>/dev/null)" ]; then + curl -s "$json_url" -o "$local_file" + fi +fi + +selected=$(jq -r '. as $input | to_entries[] | select(.key != "METADATA") | "\(.value.char) \(.key)"' "$local_file" | dmenu -bw 2 -i -W 290 -X 1061 -Y 15 -l 30 | sed "s/ .*//") +[ -z "$selected" ] && exit +if [ -n "$1" ]; then + xdotool type "$selected" +else + printf "%s" "$selected" | xclip -selection clipboard + notify-send "$selected - copied to clipboard." & +fi diff --git a/.local/bin/dmenupass b/.local/bin/dmenupass new file mode 100755 index 0000000..e36f0c0 --- /dev/null +++ b/.local/bin/dmenupass @@ -0,0 +1,6 @@ +#!/bin/sh + +# This script is the SUDO_ASKPASS variable, meaning that it will be used as a +# password prompt if needed. + +dmenu -bw 2 -Y 190 -X 333 -W 700 -P -p "$1" <&- && echo diff --git a/.local/bin/dmenurecord b/.local/bin/dmenurecord new file mode 100755 index 0000000..f5ddd8b --- /dev/null +++ b/.local/bin/dmenurecord @@ -0,0 +1,124 @@ +#!/bin/sh + +# Usage: +# `$0`: Ask for recording type via dmenu +# `$0 screencast`: Record both audio and screen +# `$0 video`: Record only screen +# `$0 audio`: Record only audio +# `$0 kill`: Kill existing recording +# +# If there is already a running instance, user will be prompted to end it. + +getdim() { xrandr | sed -n "s/\s*\([0-9]\+x[0-9]\+\).*\*.*/\1/p"; } + +updateicon() { + echo "$1" >/tmp/recordingicon + pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}" +} + +killrecording() { + recpid="$(cat /tmp/recordingpid)" + kill -15 "$recpid" + rm -f /tmp/recordingpid + updateicon "" + pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}" +} + +screencast() { + ffmpeg -y \ + -f x11grab \ + -framerate 30 \ + -s "$(getdim)" \ + -i "$DISPLAY" \ + -r 24 \ + -use_wallclock_as_timestamps 1 \ + -f alsa -thread_queue_size 1024 -i default \ + -c:v h264 \ + -crf 0 -preset ultrafast -c:a aac \ + "$HOME/screencast-$(date '+%y%m%d-%H%M-%S').mp4" & + echo $! >/tmp/recordingpid + updateicon "^C4^  ^d^" +} + +video() { + ffmpeg \ + -f x11grab \ + -framerate 30 \ + -s "$(getdim)" \ + -i "$DISPLAY" \ + -c:v libx264 -qp 0 -r 30 \ + "$HOME/video-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! >/tmp/recordingpid + updateicon "^C4^ ^d^" +} + +webcamhidef() { + ffmpeg \ + -f v4l2 \ + -i /dev/video0 \ + -video_size 1920x1080 \ + "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! >/tmp/recordingpid + updateicon "^C4^󰄄 ^d^" +} + +webcam() { + ffmpeg \ + -f v4l2 \ + -i /dev/video0 \ + -video_size 640x480 \ + "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! >/tmp/recordingpid + updateicon "^C4^󰄄 ^d^" +} + +audio() { + ffmpeg \ + -f alsa -i default \ + -c:a flac \ + "$HOME/audio-$(date '+%y%m%d-%H%M-%S').flac" & + echo $! >/tmp/recordingpid + updateicon "^C4^ ^d^" +} + +askrecording() { + choice=$(printf "screencast\\nvideo\\nvideo selected\\naudio\\nwebcam 480p\\nwebcam 1080p" | dmenu -bw 2 -l 6 -X 1151 -Y 15 -W 200 -i -p "Recording style:") + case "$choice" in + screencast) screencast ;; + audio) audio ;; + video) video ;; + *selected) videoselected ;; + "webcam 480p") webcam ;; + "webcam 1080p") webcamhidef ;; + esac +} + +asktoend() { + response=$(printf "Yes\\nNo" | dmenu -i -bw 2 -W 200 -X 1151 -Y 15 -l 2 -p "End recording?") && + [ "$response" = "Yes" ] && killrecording +} + +videoselected() { + slop -f "%x %y %w %h" >/tmp/slop + read -r X Y W H /tmp/recordingpid + updateicon "^C4^ ^d^" +} + +case "$1" in +screencast) screencast ;; +audio) audio ;; +video) video ;; +*selected) videoselected ;; +kill) killrecording ;; +*) ([ -f /tmp/recordingpid ] && asktoend && exit) || askrecording ;; +esac diff --git a/.local/bin/dwmcol b/.local/bin/dwmcol new file mode 100755 index 0000000..753187e --- /dev/null +++ b/.local/bin/dwmcol @@ -0,0 +1,11 @@ +#!/bin/bash + +file_path="$HOME/.cache/dwm_bar_color" + +if [ -e "$file_path" ]; then + rm "$file_path" + echo "File '$file_path' deleted." +else + touch "$file_path" + echo "File '$file_path' created." +fi diff --git a/.local/bin/fetch b/.local/bin/fetch new file mode 100755 index 0000000..06c0816 Binary files /dev/null and b/.local/bin/fetch differ diff --git a/.local/bin/fetch.sh b/.local/bin/fetch.sh new file mode 100755 index 0000000..56de88c --- /dev/null +++ b/.local/bin/fetch.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash + +user_host="$(whoami)@$(hostname)" +# user_host="user@arch" +distro="$(awk -F= '/^NAME/{gsub(/"/, "", $2); print $2}' /etc/os-release)" +# distro="Arch Linux" +kernel="$(uname -r)" +wm="$(xprop -id "$(xprop -root -notype | awk '$1=="_NET_SUPPORTING_WM_CHECK:"{print $5}')" -notype -f _NET_WM_NAME 8t | grep "WM_NAME" | cut -f2 -d \")" +# wm="dwm" +memory="$(free -m | awk 'NR==2{printf "%.0f MiB / %.0f MiB\n", $3, $2}')" +term="$TERMINAL" +# term="st" +# up_time="$(uptime -p | sed 's/up //')" +up_time="$(awk '{if ($1>=86400) {printf "%d days, ", int($1/86400)};if ($1>=3600) {printf "%d hours, ", int(($1%86400)/3600)};if ($1>=60) {printf "%d mins ", int(($1%3600)/60)};if ($1<60) {printf "%d seconds", int($1)} }' /proc/uptime)" +pkg_count="$(pacman -Qq | wc -l) (pacman)" +pad=$(printf '%0.1s' " "{1..27}) +random_number=$((RANDOM % 7)) + +if [ $random_number -eq 0 ]; then + echo -e "\e[90m \e[90m╭─────┬─────────────────────────────╮" + echo -e "\e[90m ⠀⠀⠀⣀⣀⣤⣤⣦⣶⢶⣶⣿⣿⣿⣿⣿⣿⣿⣷⣶⣶⡄⠀⠀⠀⠀⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[32m$user_host${pad:${#user_host}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⣿⣿⣿⠿⣿⣿⣾⣿⣿⣿⣿⣿⣿⠟⠛⠛⢿⣿⡇⠀⠀⠀⠀⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$distro${pad:${#distro}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⣿⡟⠡⠂⠀⢹⣿⣿⣿⣿⣿⣿⡇⠘⠁⠀⠀⣿⡇⠀⢠⣄⠀⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$kernel${pad:${#kernel}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⢸⣗⢴⣶⣷⣷⣿⣿⣿⣿⣿⣿⣷⣤⣤⣤⣴⣿⣗⣄⣼⣷⣶⡄⠀⠀ \e[90m│ \e[34m󰙀 \e[90m│ \e[37m$wm${pad:${#wm}}\e[90m│" + echo -e "\e[90m ⠀⠀⢀⣾⣿⡅⠐⣶⣦⣶⠀⢰⣶⣴⣦⣦⣶⠴⠀⢠⣿⣿⣿⣿⣼⣿⡇⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$memory${pad:${#memory}}\e[90m│" + echo -e "\e[90m ⠀⢀⣾⣿⣿⣷⣬⡛⠷⣿⣿⣿⣿⣿⣿⣿⠿⠿⣠⣿⣿⣿⣿⣿⠿⠛⠃⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$term${pad:${#term}}\e[90m│" + echo -e "\e[90m ⠀⢸⣿⣿⣿⣿⣿⣿⣿⣶⣦⣭⣭⣥⣭⣵⣶⣿⣿⣿⣿⣟⠉⠀⠀⠀⠀⠀⠀ \e[90m│ \e[34m󰔚 \e[90m│ \e[37m$up_time${pad:${#up_time}}\e[90m│" + echo -e "\e[90m ⠀⠀⠙⠇⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$pkg_count${pad:${#pkg_count}}\e[90m│" + echo -e "\e[90m⠀ ⠀⠀⠀⣿⣿⣿⣿⣿⣛⠛⠛⠛⠛⠛⢛⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀ \e[90m├─────┴─────────────────────────────┤" + echo -e "\e[90m⠀⠀ ⠀⠀⠿⣿⣿⣿⠿⠿⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⠿⠇⠀⠀⠀⠀ \e[90m│ \e[33m󰮯 \e[31m󰊠 \e[32m󰊠 \e[34m󰊠 \e[35m󰊠 \e[36m󰊠 \e[37m󰊠 \e[90m󰊠 │" + echo -e "\e[90m \e[90m╰───────────────────────────────────╯" +elif [ $random_number -eq 1 ]; then + echo -e "\e[90m \e[90m╭─────┬─────────────────────────────╮" + echo -e "\e[90m ⣴⣶⣤⡤⠦⣤⣀⣤⠆ ⣈⣭⣿⣶⣿⣦⣼⣆ \e[90m│ \e[34m \e[90m│ \e[32m$user_host${pad:${#user_host}}\e[90m│" + echo -e "\e[90m ⠉⠻⢿⣿⠿⣿⣿⣶⣦⠤⠄⡠⢾⣿⣿⡿⠋⠉⠉⠻⣿⣿⡛⣦ \e[90m│ \e[34m \e[90m│ \e[37m$distro${pad:${#distro}}\e[90m│" + echo -e "\e[90m ⠈⢿⣿⣟⠦ ⣾⣿⣿⣷ ⠻⠿⢿⣿⣧⣄ \e[90m│ \e[34m \e[90m│ \e[37m$kernel${pad:${#kernel}}\e[90m│" + echo -e "\e[90m ⣸⣿⣿⢧ ⢻⠻⣿⣿⣷⣄⣀⠄⠢⣀⡀⠈⠙⠿⠄ \e[90m│ \e[34m󰙀 \e[90m│ \e[37m$wm${pad:${#wm}}\e[90m│" + echo -e "\e[90m ⢠⣿⣿⣿⠈ ⣻⣿⣿⣿⣿⣿⣿⣿⣛⣳⣤⣀⣀ \e[90m│ \e[34m \e[90m│ \e[37m$memory${pad:${#memory}}\e[90m│" + echo -e "\e[90m ⢠⣧⣶⣥⡤⢄ ⣸⣿⣿⠘ ⢀⣴⣿⣿⡿⠛⣿⣿⣧⠈⢿⠿⠟⠛⠻⠿⠄ \e[90m│ \e[34m \e[90m│ \e[37m$term${pad:${#term}}\e[90m│" + echo -e "\e[90m ⣰⣿⣿⠛⠻⣿⣿⡦⢹⣿⣷ ⢊⣿⣿⡏ ⢸⣿⣿⡇ ⢀⣠⣄⣾⠄ \e[90m│ \e[34m󰔚 \e[90m│ \e[37m$up_time${pad:${#up_time}}\e[90m│" + echo -e "\e[90m ⣠⣿⠿⠛ ⢀⣿⣿⣷⠘⢿⣿⣦⡀ ⢸⢿⣿⣿⣄ ⣸⣿⣿⡇⣪⣿⡿⠿⣿⣷⡄ \e[90m│ \e[34m \e[90m│ \e[37m$pkg_count${pad:${#pkg_count}}\e[90m│" + echo -e "\e[90m ⠙⠃ ⣼⣿⡟ ⠈⠻⣿⣿⣦⣌⡇⠻⣿⣿⣷⣿⣿⣿ ⣿⣿⡇ ⠛⠻⢷⣄ \e[90m├─────┴─────────────────────────────┤" + echo -e "\e[90m ⢻⣿⣿⣄ ⠈⠻⣿⣿⣿⣷⣿⣿⣿⣿⣿⡟ ⠫⢿⣿⡆ \e[90m│ \e[33m󰮯 \e[31m󰊠 \e[32m󰊠 \e[34m󰊠 \e[35m󰊠 \e[36m󰊠 \e[37m󰊠 \e[90m󰊠 │" + echo -e "\e[90m ⠻⣿⣿⣿⣿⣶⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⡟⢀⣀⣤⣾⡿⠃ \e[90m╰───────────────────────────────────╯" +elif [ $random_number -eq 2 ]; then + echo -e "\e[90m ⣀⣤⣴⣶⣶⣶⣶⣶⣶⣤⣄⣀ \e[90m╭─────┬─────────────────────────────╮" + echo -e "\e[90m ⢀⣠⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣄ \e[90m│ \e[34m \e[90m│ \e[32m$user_host${pad:${#user_host}}\e[90m│" + echo -e "\e[90m ⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣆ \e[90m│ \e[34m \e[90m│ \e[37m$distro${pad:${#distro}}\e[90m│" + echo -e "\e[90m ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧ \e[90m│ \e[34m \e[90m│ \e[37m$kernel${pad:${#kernel}}\e[90m│" + echo -e "\e[90m ⣾⣿⡿⠟⡋⠉⠛⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠛⠉⠉⠙⠻⣿⣿⣇ \e[90m│ \e[34m󰙀 \e[90m│ \e[37m$wm${pad:${#wm}}\e[90m│" + echo -e "\e[90m⢠⣿⡏⢰⣿⣿⡇ ⢸⣿⣿⣿⠿⠿⣿⣿⣿⠁⣾⣿⣷ ⠘⣿⣿ \e[90m│ \e[34m \e[90m│ \e[37m$memory${pad:${#memory}}\e[90m│" + echo -e "\e[90m⠸⣿⣇⠈⠉⠉ ⢀⣼⡿⠋ ⠙⢿⣄⠙⠛⠁ ⢠⣿⣿ \e[90m│ \e[34m \e[90m│ \e[37m$term${pad:${#term}}\e[90m│" + echo -e "\e[90m ⢿⣿⡇ ⣶⣿⣿⢁⣤⣤⣤⣤⣤⣤ ⣿⣷ ⠈⢹⣿⡟ \e[90m│ \e[34m󰦖 \e[90m│ \e[37m$up_time${pad:${#up_time}}\e[90m│" + echo -e "\e[90m ⠈⢿⡗ ⢸⣿⣿⣿⣶⣶⣶⣶⣶⣶⣶⣶⣿⣿ ⢸⡟ \e[90m│ \e[34m \e[90m│ \e[37m$pkg_count${pad:${#pkg_count}}\e[90m│" + echo -e "\e[90m ⠳⡀ ⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⠌ \e[90m├─────┴─────────────────────────────┤" + echo -e "\e[90m ⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣤ \e[90m│ \e[33m󰮯 \e[31m󰊠 \e[32m󰊠 \e[34m󰊠 \e[35m󰊠 \e[36m󰊠 \e[37m󰊠 \e[90m󰊠 │" + echo -e "\e[90m ⠉⠙⠻⠿⠿⣿⣿⣿⣿⠿⠿⠛⠉ \e[90m╰───────────────────────────────────╯" +elif [ $random_number -eq 3 ]; then + echo -e "\e[90m \e[90m╭─────┬─────────────────────────────╮" + echo -e "\e[90m \e[90m│ \e[34m \e[90m│ \e[32m$user_host${pad:${#user_host}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⡀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$distro${pad:${#distro}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠠⣀⣠⣶⣶⣶⣿⣿⣿⣟⠟⠉⠁⠀⠉⠀ \e[90m│ \e[34m \e[90m│ \e[37m$kernel${pad:${#kernel}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣵⣶⣿⣿⣿⡿⣟⢿⡝⠙⠀⠤⠤⣤⣤⡶⠂⠀ \e[90m│ \e[34m󰙀 \e[90m│ \e[37m$wm${pad:${#wm}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠀⢀⠴⣪⣾⣿⣿⣿⣿⣿⢿⡿⠃⢿⢸⣧⡍⠭⣭⣿⡿⠋⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$memory${pad:${#memory}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠀⠀⢀⣵⣿⣿⣿⣿⣿⢯⠟⡵⠋ ⢠⢾⣿⣿⣿⡤⣼⢏⣠⣀⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$term${pad:${#term}}\e[90m│" + echo -e "\e[90m ⠀⣰⣻⣿⣿⣿⣾⣿⣧⢡⣘⠁⠀⠀⠘⣄⣻⣿⣿⣷⣿⣿⡿⠍⠁⠀⠀ \e[90m│ \e[34m󰔚 \e[90m│ \e[37m$up_time${pad:${#up_time}}\e[90m│" + echo -e "\e[90m ⡇⡿⣿⣿⣿⡿⣿⡻⣿⣜⢄⣶⣤⣀⠀⠀⠀⠈⠛⢻⣟⠫⠉⠀⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$pkg_count${pad:${#pkg_count}}\e[90m│" + echo -e "\e[90m ⠀⠣⡻⣌⡻⠿⣿⣮⣽⣿⣶⣾⣿⣳⠶⠖⠬⠍⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀ \e[90m├─────┴─────────────────────────────┤" + echo -e "\e[90m ⠀⠀⠈⠀⠉⠉⠙⠛⠛⠒⠓⠒⠀⠀⠀⠒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ \e[90m│ \e[33m󰮯 \e[31m󰊠 \e[32m󰊠 \e[34m󰊠 \e[35m󰊠 \e[36m󰊠 \e[37m󰊠 \e[90m󰊠 │" + echo -e "\e[90m \e[90m╰───────────────────────────────────╯" +elif [ $random_number -eq 4 ]; then + echo -e "\e[90m ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⠀ \e[90m╭─────┬─────────────────────────────╮" + echo -e "\e[90m ⠀⠀⢤⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠠⣢⢃⡶ \e[90m│ \e[34m \e[90m│ \e[32m$user_host${pad:${#user_host}}\e[90m│" + echo -e "\e[90m ⠀⠀ ⠀⠀⣼⡶⠘⠀⠀⠀⠀⠀⠀⠀⠀⢠⢀⠄⠀⠢⢼⣿⣿⣷⡅ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$distro${pad:${#distro}}\e[90m│" + echo -e "\e[90m ⠀⠀ ⠠⠀⣿⣿⢇⡀⠀⠀⠀⠀⠀⠀⡤⠀⢈⢄⡇⣪⣿⣿⣿⢟⡠ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$kernel${pad:${#kernel}}\e[90m│" + echo -e "\e[90m ⠀⠀ ⠀⢸⣿⣿⣟⡐⠁⣀⠀⠀⠀⣠⡤⡨⣳⣿⣿⣿⣿⣿⣿⡿⠃ ⠀ \e[90m│ \e[34m󰙀 \e[90m│ \e[37m$wm${pad:${#wm}}\e[90m│" + echo -e "\e[90m ⠀⠀ ⠀⠀⢻⣿⣿⣇⠸⠠⠀⠀⣠⣿⣷⣿⣿⣿⣿⣿⣿⣿⠿⠁⠁ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$memory${pad:${#memory}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠀ ⠀⠀⠀⠙⠿⣿⣮⣄⣄⣈⣾⣿⣿⣿⣿⣿⣿⣿⣿⢏⠹⠄⠃ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$term${pad:${#term}}\e[90m│" + echo -e "\e[90m ⠀ ⠀⠀⠀⢀⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⠻⠀⠙⠠⠀⠀ ⠀ \e[90m│ \e[34m󰔚 \e[90m│ \e[37m$up_time${pad:${#up_time}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠈⢤⡟⠻⣿⣿⣿⣿⣿⣿⡿⠿⡻⠳⠁⠀⠁⠀⠀⠀ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$pkg_count${pad:${#pkg_count}}\e[90m│" + echo -e "\e[90m ⠀ ⠀⠀⠀⠀⠀⠀⠁⠙⢿⣿⣿⣿⣿⣶⣾⣷⣶⣦⣤⠀⠀⠀⠀ ⠀ \e[90m├─────┴─────────────────────────────┤" + echo -e "\e[90m ⠀ ⠀⠀⠀⠀⠀⢀⣤⡶⡖⠿⣿⣿⣿⣿⡿⠏⠝⠁⠀⠀⠀⠀⠀ ⠀ \e[90m│ \e[33m󰮯 \e[31m󰊠 \e[32m󰊠 \e[34m󰊠 \e[35m󰊠 \e[36m󰊠 \e[37m󰊠 \e[90m󰊠 │" + echo -e "\e[90m ⠀⠀⠀⠀⠀⠈⠀⠡⠔⠀⠈⠙⠙⠑⠂⠀⠀⠀⠀⠀⠀⠀⠀ \e[90m╰───────────────────────────────────╯" +elif [ $random_number -eq 5 ]; then + echo -e "\e[90m ⠀⠀⠀⠀⠀⠀⢀⢀⠀⣄⢂⣀⣂⣤⣀⢀⢀⠀⠀⠀⠀⠀⠀ \e[90m╭─────┬─────────────────────────────╮" + echo -e "\e[90m ⠀⠀⠀⠀⣄⣰⣝⣉⣙⢱⣞⠜⡖⣌⣌⣁⣻⣠⣀⠀⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[32m$user_host${pad:${#user_host}}\e[90m│" + echo -e "\e[90m ⠀ ⠀⠀⢔⢽⣊⣂⣇⡒⠮⢻⣇⠲⢍⣿⢟⣒⣰⣠⣑⡔⣀⠀⠀ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$distro${pad:${#distro}}\e[90m│" + echo -e "\e[90m ⠀ ⠀⠹⡸⢙⣕⡐⢂⠍⣩⡻⣿⣆⣾⠟⣉⢣⠪⠲⡰⡋⣢⢆⠀ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$kernel${pad:${#kernel}}\e[90m│" + echo -e "\e[90m ⠀ ⠀⣪⡹⣵⢦⠽⡓⠶⠶⣧⣹⣿⣏⣴⠶⠛⠟⠽⢛⣒⢮⡙⠀ ⠀ \e[90m│ \e[34m󰙀 \e[90m│ \e[37m$wm${pad:${#wm}}\e[90m│" + echo -e "\e[90m ⠀ ⠸⢋⢪⠑⢩⠈⠀⠀⠀⠈⣿⣿⣿⠁⠀⠀⠘⢠⠈⠆⢎⢱⠁ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$memory${pad:${#memory}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀ ⠀⠻⡕⡲⡈⠀⠀⠀⠀⠀⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠆⠄⠁ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$term${pad:${#term}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠇⠀⠀⠀⠀⠀⣰⣿⣿⣿⣤⡀⠀⠀⠀⠀⠌⠘⠀⠀ ⠀ \e[90m│ \e[34m󰔚 \e[90m│ \e[37m$up_time${pad:${#up_time}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⢱⠒⡶⡶⢖⣫⡿⢻⠿⡟⢿⣍⡱⢖⠶⠒⡆⠀⠀⠀ ⠀ \e[90m│ \e[34m \e[90m│ \e[37m$pkg_count${pad:${#pkg_count}}\e[90m│" + echo -e "\e[90m ⠀ ⠀⠀⠀⠀⠁⠬⡃⠴⣇⣴⠏⠖⠙⣦⣸⠦⡼⠣⠉⠀⠀⠀⠀ ⠀ \e[90m├─────┴─────────────────────────────┤" + echo -e "\e[90m ⠀⠀⠀⠀⠀⠀⠈⠁⠑⠢⠧⠭⠼⠵⠋⠊⠁⠀⠀⠀⠀⠀⠀ ⠀ \e[90m│ \e[33m󰮯 \e[31m󰊠 \e[32m󰊠 \e[34m󰊠 \e[35m󰊠 \e[36m󰊠 \e[37m󰊠 \e[90m󰊠 │" + echo -e "\e[90m ⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀ \e[90m╰───────────────────────────────────╯" +else + echo -e "\e[90m ⠀⠀⢀⣀⣀⡀⠒⠒⠦⣄⡀⠀⠀⠀⠀⠀⠀⠀ \e[90m╭─────┬─────────────────────────────╮" + echo -e "\e[90m ⠀⠀⠀⠀⠀⢀⣤⣶⡾⠿⠿⠿⠿⣿⣿⣶⣦⣄⠙⠷⣤⡀⠀⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[32m$user_host${pad:${#user_host}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠀⣠⡾⠛⠉⠀⠀⠀⠀⠀⠀⠀⠈⠙⠻⣿⣷⣄⠘⢿⡄⠀⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$distro${pad:${#distro}}\e[90m│" + echo -e "\e[90m ⠀⠀⢀⡾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠐⠂⠠⢄⡀⠈⢿⣿⣧⠈⢿⡄⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$kernel${pad:${#kernel}}\e[90m│" + echo -e "\e[90m ⠀⢀⠏⠀⠀⠀⢀⠄⣀⣴⣾⠿⠛⠛⠛⠷⣦⡙⢦⠀⢻⣿⡆⠘⡇⠀⠀⠀ \e[90m│ \e[34m󰙀 \e[90m│ \e[37m$wm${pad:${#wm}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠀⠀⡐⢁⣴⡿⠋⢀⠠⣠⠤⠒⠲⡜⣧⢸⠄⢸⣿⡇⠀⡇⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$memory${pad:${#memory}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠀⠀⠀⡼⠀⣾⡿⠁⣠⢃⡞⢁⢔⣆⠔⣰⠏⡼⠀⣸⣿⠃⢸⠃⠀⠀⠀ \e[90m│ \e[34m \e[90m│ \e[37m$term${pad:${#term}}\e[90m│" + echo -e "\e[90m ⠀⠀⢰⡇⢸⣿⡇⠀⡇⢸⡇⣇⣀⣠⠔⠫⠊⠀⣰⣿⠏⡠⠃⠀⠀⢀⠀ \e[90m│ \e[34m󰔚 \e[90m│ \e[37m$up_time${pad:${#up_time}}\e[90m│" + echo -e "\e[90m ⠀⠀⢸⡇⠸⣿⣷⠀⢳⡈⢿⣦⣀⣀⣀⣠⣴⣾⠟⠁⠀⠀⠀⠀⢀⡎⠀ \e[90m│ \e[34m \e[90m│ \e[37m$pkg_count${pad:${#pkg_count}}\e[90m│" + echo -e "\e[90m ⠀⠀⠀⠘⣷⠀⢻⣿⣧⠀⠙⠢⠌⢉⣛⠛⠋⠉⠀⠀⠀⠀⠀⠀⣠⠎⠀⠀ \e[90m├─────┴─────────────────────────────┤" + echo -e "\e[90m ⠀⠀⠀⠹⣧⡀⠻⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⡾⠃⠀⠀⠀ \e[90m│ \e[33m󰮯 \e[31m󰊠 \e[32m󰊠 \e[34m󰊠 \e[35m󰊠 \e[36m󰊠 \e[37m󰊠 \e[90m󰊠 │" + echo -e "\e[90m ⠀⠀⠀⠀⠈⠻⣤⡈⠻⢿⣿⣷⣦⣤⣤⣤⣤⣤⣴⡾⠛⠉⠀⠀⠀⠀ \e[90m╰───────────────────────────────────╯" + echo -e "\e[90m ⠀⠀⠀⠀⠀⠀⠈⠙⠶⢤⣈⣉⠛⠛⠛⠛⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀ " +fi diff --git a/.local/bin/ff b/.local/bin/ff new file mode 100755 index 0000000..1c9f71c --- /dev/null +++ b/.local/bin/ff @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +#----------------------------------------------------------------------------- +# █▀▀ ▄▀█ █▀ ▀█▀ █▀▀ █ █ █▀▀ █▀ +# █▀ █▀█ ▄█ █ █▀ █ █▄▄ ██▄ ▄█ +# +# Usage: ff [path file or folder] +# +# Arguments: --help : prints usage info +# -h : prints usage info +# +# Description: Bash script which is a combination of 'mkdir' and 'touch'. +# It can create directory structures and files simultaneously. +# +# Dependencies: bash +# +# Examples: - Single file: +# ff file +# - Single directory: +# ff dir/ +# - Multiple files: +# ff file1 file2 file3 +# - Multiple directories: +# ff dir1/ dir2/ dir3/ +# - File in a directory +# ff dir/file +# - Directory in a directory +# ff dir1/dir2/ +# - Multiple files in multiple directories +# ff dir1/dir2/file1 dir3/file2 +# - If your shell supports brace expansion e.g bash, zsh, fish +# ff dir1/{dir2/{file1,file2}.txt,dir3/file3.txt} +#----------------------------------------------------------------------------- + +if [[ $# -eq 0 ]]; then + echo "No arguments provided" + echo "Usage: ff [path file or folder]" + echo "For more information, run: ff --help" + exit 1 +fi + +if [[ "$1" == "--help" || "$1" == "-h" ]]; then + echo "Usage: ff [path file or folder]" + echo "Examples: - Single file: + ff file + - Single directory: + ff dir/ + - Multiple files: + ff file1 file2 file3 + - Multiple directories: + ff dir1/ dir2/ dir3/ + - File in a directory + ff dir/file + - Directory in a directory + ff dir1/dir2/ + - Multiple files in multiple directories + ff dir1/dir2/file1 dir3/file2 + - If your shell supports brace expansion e.g bash, zsh, fish + ff dir1/{dir2/{file1,file2}.txt,dir3/file3.txt}" + exit 0 +fi + +for path in "$@"; do + if [[ "$path" == */ ]]; then + mkdir -p "$path" + fi + parent_dir=$(dirname "$path") + if [[ -n "$parent_dir" ]] && [[ ! -d "$parent_dir" ]]; then + mkdir -p "$parent_dir" + fi + touch "$path" +done diff --git a/.local/bin/ffv b/.local/bin/ffv new file mode 100755 index 0000000..aad036e --- /dev/null +++ b/.local/bin/ffv @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +#----------------------------------------------------------------------------- +# █▀▀ ▄▀█ █▀ ▀█▀ █▀▀ █ █ █▀▀ █▀ █░█ █▀▀ █▀█ █▄▄ █▀█ █▀ █▀▀ +# █▀ █▀█ ▄█ █ █▀ █ █▄▄ ██▄ ▄█ ▀▄▀ ██▄ █▀▄ █▄█ █▄█ ▄█ ██▄ +# +# Usage: ffv [path file or folder] +# +# Arguments: --help : prints usage info +# -h : prints usage info +# +# Description: Bash script which is a combination of 'mkdir' and 'touch'. +# It can create directory structures and files simultaneously +# and lists the created objects using eza, lsd, or ls. +# +# Dependencies: bash, eza (optional), lsd (optional) +# +# Examples: - Single file: +# ffv file +# - Single directory: +# ffv dir/ +# - Multiple files: +# ffv file1 file2 file3 +# - Multiple directories: +# ffv dir1/ dir2/ dir3/ +# - File in a directory +# ffv dir/file +# - Directory in a directory +# ffv dir1/dir2/ +# - Multiple files in multiple directories +# ffv dir1/dir2/file1 dir3/file2 +# - If your shell supports brace expansion e.g bash, zsh, fish +# ffv dir1/{dir2/{file1,file2}.txt,dir3/file3.txt} +#----------------------------------------------------------------------------- + +if [[ $# -eq 0 ]]; then + echo "No arguments provided" + echo "Usage: ffv [path file or folder]" + echo "For more information, run: ffv --help" + exit 1 +fi + +if [[ "$1" == "--help" || "$1" == "-h" ]]; then + echo "Usage: ffv [path file or folder]" + echo "Examples: - Single file: + ffv file + - Single directory: + ffv dir/ + - Multiple files: + ffv file1 file2 file3 + - Multiple directories: + ffv dir1/ dir2/ dir3/ + - File in a directory + ffv dir/file + - Directory in a directory + ffv dir1/dir2/ + - Multiple files in multiple directories + ffv dir1/dir2/file1 dir3/file2 + - If your shell supports brace expansion e.g bash, zsh, fish + ffv dir1/{dir2/{file1,file2}.txt,dir3/file3.txt}" + exit 0 +fi + +# Create directory structures and files +for path in "$@"; do + if [[ "$path" == */ ]]; then + mkdir -p "$path" + fi + parent_dir=$(dirname "$path") + if [[ -n "$parent_dir" ]] && [[ ! -d "$parent_dir" ]]; then + mkdir -p "$parent_dir" + fi + touch "$path" +done + +# Get the created files and folder names and print them +unique_names=() +for arg in "$@"; do + name="${arg%%/*}" + if [ -n "$name" ]; then + if [[ ! " ${unique_names[*]} " =~ $name ]]; then + unique_names+=("$name") + fi + fi +done +if command -v eza &>/dev/null; then + eza -aU --no-user --no-filesize --no-permissions --tree --icons \ + --group-directories-first "${unique_names[@]}" +elif command -v lsd &>/dev/null; then + lsd -al --tree --icon=always --group-directories-first "${unique_names[@]}" +else + ls -ARl --color=always "${unique_names[@]}" +fi diff --git a/.local/bin/fontupdate b/.local/bin/fontupdate new file mode 100755 index 0000000..85de401 --- /dev/null +++ b/.local/bin/fontupdate @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +curl -o "$HOME/.local/share/fonts/JetBrainsMono" -LJO https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/patched-fonts/JetBrainsMono/Ligatures/Bold/JetBrainsMonoNerdFont-Bold.ttf +curl -o "$HOME/.local/share/fonts/JetBrainsMono" -LJO https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/patched-fonts/JetBrainsMono/Ligatures/Bold/JetBrainsMonoNerdFont-Italic.ttf +curl -o "$HOME/.local/share/fonts/JetBrainsMono" -LJO https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/patched-fonts/JetBrainsMono/Ligatures/Bold/JetBrainsMonoNerdFont-Medium.ttf +curl -o "$HOME/.local/share/fonts/JetBrainsMono" -LJO https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/patched-fonts/JetBrainsMono/Ligatures/Bold/JetBrainsMonoNerdFont-Regular.ttf +curl -o "$HOME/.local/share/fonts/JetBrainsMono" -LJO https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/patched-fonts/JetBrainsMono/Ligatures/Bold/JetBrainsMonoNerdFont-SemiBold.ttf diff --git a/.local/bin/fzf-fd b/.local/bin/fzf-fd new file mode 100755 index 0000000..ebcfb55 --- /dev/null +++ b/.local/bin/fzf-fd @@ -0,0 +1,30 @@ +#!/bin/sh + +search_dir="${1:-.}" +preview='bat --style=header,numbers --color=always {}' + +fd_command="fd . \ + --type file \ + --hidden \ + --follow \ + --color always \ + --exclude .git \ + --exclude .github \ + --exclude *.o \ + --exclude *.pyc \ + --full-path \"$search_dir\"" + +fzf_command="fzf \ + --ansi \ + --height=80% \ + --layout=reverse \ + --multi \ + --preview=\"[[ -n {1} ]] && $preview\" \ + --scroll-off=5 \ + --scrollbar='▐' \ + --ellipsis='…' \ + --marker='❱' \ + --pointer='❱'" + +eval "$fd_command" | eval "$fzf_command" +exit 0 diff --git a/.local/bin/fzf-grep b/.local/bin/fzf-grep new file mode 100755 index 0000000..d963ad1 --- /dev/null +++ b/.local/bin/fzf-grep @@ -0,0 +1,27 @@ +#!/bin/sh + +preview='bat -p --color=always --style=header,numbers -H {2} {1} | grep -C4 {q}' + +([ -z "$1" ] && search_dir=".") || search_dir="$1" + +selected=$(rg --color=always --hidden -nS "$2" "$search_dir" 2>/dev/null | + fzf -d: \ + --ansi \ + --height=80% \ + --multi \ + --query="$2" \ + --phony \ + --info=inline \ + --scroll-off=5 \ + --scrollbar='▐' \ + --ellipsis='…' \ + --marker='❱' \ + --pointer='❱' \ + --bind="change:reload:rg --hidden -nS --color=always {q} $search_dir" \ + --preview="[[ -n {1} ]] && $preview" \ + --preview-window=right:50%) + +if [ -n "$selected" ]; then + line_number=$(echo "$selected" | awk -F ':' '{print $2}') + echo "$selected" | cut -d: -f1 | uniq | xargs nvim +"$line_number" +fi diff --git a/.local/bin/keybinds b/.local/bin/keybinds new file mode 100755 index 0000000..c0f2da8 --- /dev/null +++ b/.local/bin/keybinds @@ -0,0 +1,14 @@ +#!/bin/bash + +keybinds_file="$HOME/.local/share/script-data/keybinds" +dmenu_cmd="dmenu -bw 2 -i -W 340 -X 1011 -Y 15 -l 29" +selected=$(awk -F, '{ + gsub(/^ +| +$/,"",$1); + gsub(/^ +| +$/,"",$2); + gsub(/^ +| +$/,"",$3); + printf "%-15s%25s\t%s\n", $1, $2, $3; + }' "$keybinds_file" | $dmenu_cmd) + +bind="$(echo "$selected" | awk '{print $1}')" +action="$(echo "$selected" | awk -F'[[:space:]]{2,}|\t' '{print $2}')" +notify-send "$bind" "$action" diff --git a/.local/bin/kitty_colors b/.local/bin/kitty_colors new file mode 100755 index 0000000..2bde9d4 --- /dev/null +++ b/.local/bin/kitty_colors @@ -0,0 +1,19 @@ +#!/bin/bash + +# Scrpt for generating a colors.conf file using the xresources file to use as a kitty-colorscheme + +# Colors from xresources +xresources_colors=("*.background" "*.foreground" "*.cursorColor" "*.color0" "*.color1" "*.color2" "*.color3" "*.color4" "*.color5" "*.color6" "*.color7" "*.color8" "*.color9" "*.color10" ".*color11" "*.color12" "*.color13" "*.color14" "*.color15") + +# Colors for kitty +kitty_colors=("background" "foreground" "cursor" "color0" "color1" "color2" "color3" "color4" "color5" "color6" "color7" "color8" "color9" "color10" "color11" "color12" "color13" "color14" "color15") + +# Loop through the xresources_colors and kitty_colors, and write them to the colors.conf file +cat <~/.config/kitty/colors.conf +# Colors generated from xresources file using the kitty_colors script +EOF + +for i in "${!xresources_colors[@]}"; do + color_value=$(xrdb -query | grep "${xresources_colors[$i]}:" | awk '{print $NF}') + echo "${kitty_colors[$i]} $color_value" >>~/.config/kitty/colors.conf +done diff --git a/.local/bin/lock b/.local/bin/lock new file mode 100755 index 0000000..f7ef00a --- /dev/null +++ b/.local/bin/lock @@ -0,0 +1,56 @@ +#!/bin/bash + +picture=$HOME/Pictures/lock.png + +fg=#c0caf5 +wrong=#df5b61 +date=#c0caf5 +verify=#9ece6a +# highlight=#565f89 + +# pkill -u "$USER" -USR1 dunst +i3lock -n --force-clock \ + -i "$picture" \ + -F -e --indicator --radius=15 \ + --ring-width=25 \ + --inside-color="$fg" \ + --ring-color="$fg" \ + --insidever-color="$verify" \ + --ringver-color="$verify" \ + --insidewrong-color="$wrong" \ + --ringwrong-color="$wrong" \ + --line-uses-inside \ + --keyhl-color="$verify" \ + --separator-color="$verify" \ + --bshl-color="$verify" \ + --time-str="%H:%M" \ + --time-size=90 \ + --date-str="%a, %d %b" \ + --date-size=28 \ + --verif-text="Verifying Password..." \ + --wrong-text="Wrong Password!" \ + --noinput-text="" \ + --greeter-text="Type the password to Unlock" \ + --ind-pos="215:390" \ + --time-font="Sofia Pro:style=Bold" \ + --date-font="Sofia Pro" \ + --verif-font="Sofia Pro" \ + --greeter-font="Sofia Pro" \ + --wrong-font="Sofia Pro" \ + --verif-size=14 \ + --greeter-size=14 \ + --wrong-size=14 \ + --time-pos="215:235" \ + --date-pos="215:275" \ + --greeter-pos="215:513" \ + --wrong-pos="215:513" \ + --verif-pos="215:423" \ + --date-color="$date" \ + --time-color="$date" \ + --greeter-color="$fg" \ + --wrong-color="$wrong" \ + --verif-color="$verify" \ + --verif-pos="215:513" \ + --refresh-rate=0 \ + --pass-media-keys \ + --pass-volume-keys diff --git a/.local/bin/maimpick b/.local/bin/maimpick new file mode 100755 index 0000000..9791202 --- /dev/null +++ b/.local/bin/maimpick @@ -0,0 +1,13 @@ +#!/bin/sh + +output="$(date '+%y%m%d-%H%M-%S').png" +xclip_cmd="xclip -sel clip -t image/png" + +case "$(printf "a selected area\\ncurrent window\\nfull screen\\na selected area (copy)\\ncurrent window (copy)\\nfull screen (copy)" | dmenu -bw 2 -l 6 -X 1151 -W 200 -Y 15 -i -p "Screenshot which area? ")" in + "a selected area") maim -u -s pic-selected-"${output}" ;; + "current window") maim -q -d 0.2 -i "$(xdotool getactivewindow)" pic-window-"${output}" ;; + "full screen") maim -q -d 0.2 pic-full-"${output}" ;; + "a selected area (copy)") maim -u -s | ${xclip_cmd} ;; + "current window (copy)") maim -q -d 0.2 -i "$(xdotool getactivewindow)" | ${xclip_cmd} ;; + "full screen (copy)") maim -q -d 0.2 | ${xclip_cmd} ;; +esac diff --git a/.local/bin/mounter b/.local/bin/mounter new file mode 100755 index 0000000..f8f258b --- /dev/null +++ b/.local/bin/mounter @@ -0,0 +1,114 @@ +#!/bin/bash + +# Mounts Android Phones and USB drives (encrypted or not). This script will +# replace the older `dmenumount` which had extra steps and couldn't handle +# encrypted drives. +# TODO: Try decrypt for drives in crtypttab +# TODO: Add some support for connecting iPhones (although they are annoying). + +IFS=' +' +# Function for escaping cell-phone names. +escape() { echo "$@" | iconv -cf UTF-8 -t ASCII//TRANSLIT | tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed "s/-\+/-/g;s/\(^-\|-\$\)//g"; } + +# Check for phones. +phones="$(simple-mtpfs -l 2>/dev/null | sed "s/^/📱/")" +mountedphones="$(grep "simple-mtpfs" /etc/mtab)" +# If there are already mounted phones, remove them from the list of mountables. +[ -n "$mountedphones" ] && phones="$(for phone in $phones; do + for mounted in $mountedphones; do + escphone="$(escape "$phone")" + [[ "$mounted" =~ "$escphone" ]] && break 1 + done && continue 1 + echo "$phone" +done)" + +# Check for drives. +lsblkoutput="$(lsblk -rpo "uuid,name,type,size,label,mountpoint,fstype")" +# Get all LUKS drives +allluks="$(echo "$lsblkoutput" | grep crypto_LUKS)" +# Get a list of the LUKS drive UUIDs already decrypted. +decrypted="$(find /dev/disk/by-id/dm-uuid-CRYPT-LUKS2-* | sed "s|.*LUKS2-||;s|-.*||")" +# Functioning for formatting drives correctly for dmenu: +filter() { sed "s/ /:/g" | awk -F':' '$7==""{printf "%s%s (%s) %s\n",$1,$3,$5,$6}'; } + +# Get only LUKS drives that are not decrypted. +unopenedluks="$(for drive in $allluks; do + uuid="${drive%% *}" + uuid="${uuid//-/}" # This is a bashism. + for open in $decrypted; do + [ "$uuid" = "$open" ] && break 1 + done && continue 1 + echo "🔒 $drive" +done | filter)" + +# Get all normal, non-encrypted or decrypted partitions that are not mounted. +normalparts="$(echo "$lsblkoutput" | grep -v crypto_LUKS | grep 'part\|rom\|crypt' | sed "s/^/󰋊 /" | filter)" + +# Add all to one variable. If no mountable drives found, exit. +alldrives="$(echo "$phones +$unopenedluks +$normalparts" | sed "/^$/d;s/ *$//")" + +# Quit the script if a sequential command fails. +set -e + +test -n "$alldrives" + +# Feed all found drives to dmenu and get user choice. +chosen="$(echo "$alldrives" | dmenu -p "Mount which drive?" -i -bw 2 -W 300 -X 1051 -Y 15 -l 10)" + +# Function for prompting user for a mountpoint. +getmount() { + mp="$(find /mnt /media /mount /home /home/user/win -maxdepth 1 -type d 2>/dev/null | dmenu -i -p "Mount this drive where?" -bw 2 -W 300 -X 1051 -Y 15 -l 10)" + test -n "$mp" + if [ ! -d "$mp" ]; then + mkdiryn=$(printf "No\\nYes" | dmenu -i -p "$mp does not exist. Create it?") + [ "$mkdiryn" = "Yes" ] && (mkdir -p "$mp" || sudo -A mkdir -p "$mp") + fi +} + +attemptmount() { + # Attempt to mount without a mountpoint, to see if drive is in fstab. + sudo -A mount "$chosen" || return 1 + notify-send "󰋊Drive Mounted." "$chosen mounted." + exit +} + +case "$chosen" in +󰋊*) + chosen="${chosen%% *}" + chosen="${chosen:1}" # This is a bashism. + attemptmount || getmount + sudo -A mount "$chosen" "$mp" -o uid="$(id -u)",gid="$(id -g)" + notify-send "󰋊Drive Mounted." "$chosen mounted to $mp." + ;; + +🔒*) + chosen="${chosen%% *}" + chosen="${chosen:1}" # This is a bashism. + # Number the drive. + while true; do + [ -f "/dev/mapper/usb$num" ] || break + num="$(printf "%02d" "$((num + 1))")" + done + + # Decrypt in a terminal window + ${TERMINAL:-st} -n floatterm -g 60x1 -e sudo cryptsetup open "$chosen" "usb$num" + # Check if now decrypted. + test -b "/dev/mapper/usb$num" + + attemptmount || getmount + sudo -A mount "/dev/mapper/usb$num" "$mp" -o uid="$(id -u)",gid="$(id -g)" + notify-send "🔓Decrypted drive Mounted." "$chosen decrypted and mounted to $mp." + ;; + +📱*) + notify-send "❗Note" "Remember to allow file access on your phone now." + getmount + number="${chosen%%:*}" + number="${chosen:1}" # This is a bashism. + sudo -A simple-mtpfs -o allow_other -o fsname="simple-mtpfs-$(escape "$chosen")" --device "$number" "$mp" + notify-send "🤖 Android Mounted." "Android device mounted to $mp." + ;; +esac diff --git a/.local/bin/networkmanager_dmenu b/.local/bin/networkmanager_dmenu new file mode 100755 index 0000000..8ba393d --- /dev/null +++ b/.local/bin/networkmanager_dmenu @@ -0,0 +1,951 @@ +#!/usr/bin/env python3 +# encoding:utf8 +"""NetworkManager command line dmenu script. + +To add new connections or enable/disable networking requires policykit +permissions setup per: +https://wiki.archlinux.org/index.php/NetworkManager#Set_up_PolicyKit_permissions + +OR running the script as root + +Add dmenu options and default terminal if desired to +~/.config/networkmanager-dmenu/config.ini + +""" +import pathlib +import struct +import configparser +import locale +import os +from os.path import basename, expanduser +import shlex +from shutil import which +import sys +from time import sleep +import uuid +import subprocess + +# pylint: disable=import-error +import gi +gi.require_version('NM', '1.0') +from gi.repository import GLib, NM # noqa pylint: disable=wrong-import-position +# pylint: enable=import-error + +ENV = os.environ.copy() +ENC = locale.getpreferredencoding() + +CONF = configparser.ConfigParser() +CONF.read(expanduser("~/.config/networkmanager-dmenu/config.ini")) + + +def cli_args(): + """ Don't override dmenu_cmd function arguments with CLI args. Removes -l + and -p if those are passed on the command line. + + Exception: if -l is passed and dmenu_command is not defined, assume that the + user wants to switch dmenu to the vertical layout and include -l. + + Returns: List of additional CLI arguments + + """ + args = sys.argv[1:] + cmd = CONF.get('dmenu', 'dmenu_command', fallback=False) + if "-l" in args or "-p" in args: + for nope in ['-l', '-p'] if cmd is not False else ['-p']: + try: + nope_idx = args.index(nope) + del args[nope_idx] + del args[nope_idx] + except ValueError: + pass + return args + + +def dmenu_pass(command, color): + """Check if dmenu passphrase patch is applied and return the correct command + line arg list + + Args: command - string + color - obscure color string + Returns: list or None + + """ + if command != 'dmenu': + return None + try: + # Check for dmenu password patch + dm_patch = b'P' in subprocess.run(["dmenu", "-h"], + capture_output=True, + check=False).stderr + except FileNotFoundError: + dm_patch = False + return ["-P"] if dm_patch else ["-nb", color, "-nf", color] + + +def dmenu_cmd(num_lines, prompt="Networks", active_lines=None): + """Parse config.ini for menu options + + Args: args - num_lines: number of lines to display + prompt: prompt to show + active_lines: list of line numbers to tag as active + Returns: command invocation (as a list of strings) for example + ["dmenu", "-l", "", "-p", "", "-i"] + + """ + # Create command string + commands = {"dmenu": ["-p", str(prompt)], + "rofi": ["-dmenu", "-p", str(prompt)], + "bemenu": ["-p", str(prompt)], + "wofi": ["-p", str(prompt)], + "fuzzel": ["-p", str(prompt), "-l", str(num_lines), "--log-level", "none"]} + command = shlex.split(CONF.get('dmenu', 'dmenu_command', fallback="dmenu")) + cmd_base = basename(command[0]) + command.extend(cli_args()) + command.extend(commands.get(cmd_base, [])) + # Rofi Highlighting + rofi_highlight = CONF.getboolean('dmenu', 'rofi_highlight', fallback=False) + if rofi_highlight is True and cmd_base == "rofi" and active_lines: + command.extend(["-a", ",".join([str(num) for num in active_lines])]) + # Passphrase prompts + obscure = CONF.getboolean('dmenu_passphrase', 'obscure', fallback=False) + if prompt == "Passphrase" and obscure is True: + obscure_color = CONF.get('dmenu_passphrase', 'obscure_color', fallback='#222222') + pass_prompts = {"dmenu": dmenu_pass(cmd_base, obscure_color), + "rofi": ['-password'], + "bemenu": ['-x'], + "wofi": ['-P'], + "fuzzel": ['--password']} + command.extend(pass_prompts.get(cmd_base, [])) + return command + + +def choose_adapter(client): + """If there is more than one wifi adapter installed, ask which one to use + + """ + devices = client.get_devices() + devices = [i for i in devices if i.get_device_type() == NM.DeviceType.WIFI] + if not devices: + return None + if len(devices) == 1: + return devices[0] + device_names = "\n".join([d.get_iface() for d in devices]) + sel = subprocess.run(dmenu_cmd(len(devices), "CHOOSE ADAPTER:"), + capture_output=True, + check=False, + env=ENV, + input=device_names, + encoding=ENC).stdout + if not sel.strip(): + sys.exit() + devices = [i for i in devices if i.get_iface() == sel.strip()] + if len(devices) != 1: + raise ValueError(f"Selection was ambiguous: '{str(sel.strip())}'") + return devices[0] + + +def is_installed(cmd): + """Check if a utility is installed""" + return which(cmd) is not None + + +def bluetooth_get_enabled(): + """Check if bluetooth is enabled via rfkill. + + Returns None if no bluetooth device was found. + """ + # See https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-rfkill + for path in pathlib.Path('/sys/class/rfkill/').glob('rfkill*'): + if (path / 'type').read_text().strip() == 'bluetooth': + return (path / 'soft').read_text().strip() == '0' + return None + + +def create_other_actions(client): + """Return list of other actions that can be taken + + """ + networking_enabled = client.networking_get_enabled() + networking_action = "Disable" if networking_enabled else "Enable" + + wifi_enabled = client.wireless_get_enabled() + wifi_action = "Disable" if wifi_enabled else "Enable" + + bluetooth_enabled = bluetooth_get_enabled() + bluetooth_action = "Disable" if bluetooth_enabled else "Enable" + + actions = [Action(f"{wifi_action} Wifi", toggle_wifi, + not wifi_enabled), + Action(f"{networking_action} Networking", + toggle_networking, not networking_enabled)] + if bluetooth_enabled is not None: + actions.append(Action(f"{bluetooth_action} Bluetooth", + toggle_bluetooth, not bluetooth_enabled)) + actions += [Action("Launch Connection Manager", launch_connection_editor), + Action("Delete a Connection", delete_connection)] + if wifi_enabled: + actions.append(Action("Rescan Wifi Networks", rescan_wifi)) + return actions + + +def rescan_wifi(): + """ + Rescan Wifi Access Points + """ + delay = CONF.getint('nmdm', 'rescan_delay', fallback=5) + for dev in CLIENT.get_devices(): + if gi.repository.NM.DeviceWifi == type(dev): + try: + dev.request_scan_async(None, rescan_cb, None) + LOOP.run() + sleep(delay) + notify("Wifi scan complete") + main() + except gi.repository.GLib.Error as err: + # Too frequent rescan error + notify("Wifi rescan failed", urgency="critical") + if not err.code == 6: # pylint: disable=no-member + raise err + + +def rescan_cb(dev, res, data): + """Callback for rescan_wifi. Just for notifications + + """ + if dev.request_scan_finish(res) is True: + notify("Wifi scan running...") + else: + notify("Wifi scan failed", urgency="critical") + LOOP.quit() + + +def ssid_to_utf8(nm_ap): + """ Convert binary ssid to utf-8 """ + ssid = nm_ap.get_ssid() + if not ssid: + return "" + ret = NM.utils_ssid_to_utf8(ssid.get_data()) + return ret + + +def prompt_saved(saved_cons): + """Prompt for a saved connection.""" + actions = create_saved_actions(saved_cons) + sel = get_selection(actions) + sel() + + +def ap_security(nm_ap): + """Parse the security flags to return a string with 'WPA2', etc. """ + flags = nm_ap.get_flags() + wpa_flags = nm_ap.get_wpa_flags() + rsn_flags = nm_ap.get_rsn_flags() + sec_str = "" + if ((flags & getattr(NM, '80211ApFlags').PRIVACY) and + (wpa_flags == 0) and (rsn_flags == 0)): + sec_str = " WEP" + if wpa_flags: + sec_str = " WPA1" + if rsn_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_PSK: + sec_str += " WPA2" + if rsn_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_SAE: + sec_str += " WPA3" + if ((wpa_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_802_1X) or + (rsn_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_802_1X)): + sec_str += " 802.1X" + if ((wpa_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_OWE) or + (rsn_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_OWE)): + sec_str += " OWE" + + # If there is no security use "--" + if sec_str == "": + sec_str = "--" + return sec_str.lstrip() + + +class Action(): # pylint: disable=too-few-public-methods + """Helper class to execute functions from a string variable""" + def __init__(self, + name, + func, + args=None, + active=False): + self.name = name + self.func = func + self.is_active = active + if args is None: + self.args = None + elif isinstance(args, list): + self.args = args + else: + self.args = [args] + + def __str__(self): + return self.name + + def __call__(self): + if self.args is None: + self.func() + else: + self.func(*self.args) + + +def conn_matches_adapter(conn, adapter): + """Return True if the connection is applicable for the given adapter. + + There seem to be two ways for a connection specify what interface it belongs + to: + + - By setting 'mac-address' in [wifi] to the adapter's MAC + - By setting 'interface-name` in [connection] to the adapter's name. + + Depending on how the connection was added, it seems like either + 'mac-address', 'interface-name' or neither of both is set. + """ + # [wifi] mac-address + setting_wireless = conn.get_setting_wireless() + mac = setting_wireless.get_mac_address() + if mac is not None: + return mac == adapter.get_permanent_hw_address() + + # [connection] interface-name + setting_connection = conn.get_setting_connection() + interface = setting_connection.get_interface_name() + if interface is not None: + return interface == adapter.get_iface() + + # Neither is set, let's assume this connection is for multiple/all adapters. + return True + + +def process_ap(nm_ap, is_active, adapter): + """Activate/Deactivate a connection and get password if required""" + if is_active: + CLIENT.deactivate_connection_async(nm_ap, None, deactivate_cb, nm_ap) + LOOP.run() + else: + conns_cur = [i for i in CONNS if + i.get_setting_wireless() is not None and + conn_matches_adapter(i, adapter)] + con = nm_ap.filter_connections(conns_cur) + if len(con) > 1: + raise ValueError("There are multiple connections possible") + + if len(con) == 1: + CLIENT.activate_connection_async(con[0], adapter, nm_ap.get_path(), + None, activate_cb, nm_ap) + LOOP.run() + else: + if ap_security(nm_ap) != "--": + password = get_passphrase() + else: + password = "" + set_new_connection(nm_ap, password, adapter) + + +def activate_cb(dev, res, data): + """Notification if activate connection completed successfully + + """ + try: + conn = dev.activate_connection_finish(res) + except GLib.Error: + conn = None + if conn is not None: + notify(f"Activated {conn.get_id()}") + else: + notify(f"Problem activating {data.get_id()}", urgency="critical") + LOOP.quit() + + +def deactivate_cb(dev, res, data): + """Notification if deactivate connection completed successfully + + """ + if dev.deactivate_connection_finish(res) is True: + notify(f"Deactivated {data.get_id()}") + else: + notify(f"Problem deactivating {data.get_id()}", urgency="critical") + LOOP.quit() + + +def process_vpngsm(con, activate): + """Activate/deactive VPN or GSM connections""" + if activate: + CLIENT.activate_connection_async(con, None, None, + None, activate_cb, con) + else: + CLIENT.deactivate_connection_async(con, None, deactivate_cb, con) + LOOP.run() + +def strength_bars(signal_strength): + bars = NM.utils_wifi_strength_bars(signal_strength) + wifi_chars = CONF.get("dmenu", "wifi_chars", fallback=False) + if wifi_chars: + bars = "".join([wifi_chars[i] for i, j in enumerate(bars) if j == '*']) + return bars + + +def strength_icon(signal_strength): + wifi_icons = CONF.get("dmenu", "wifi_icons", fallback=False) + if wifi_icons: + return wifi_icons[round(signal_strength / 100 * (len(wifi_icons) - 1))] + return "" + + +def create_ap_actions(aps, active_ap, active_connection, adapter): # noqa pylint: disable=too-many-locals,line-too-long + """For each AP in a list, create the string and its attached function + (activate/deactivate) + + """ + active_ap_bssid = active_ap.get_bssid() if active_ap is not None else "" + + names = [ssid_to_utf8(ap) for ap in aps] + max_len_name = max([len(name) for name in names]) if names else 0 + secs = [ap_security(ap) for ap in aps] + max_len_sec = max([len(sec) for sec in secs]) if secs else 0 + + ap_actions = [] + + if CONF.getboolean("dmenu", "compact", fallback=False): + format = CONF.get("dmenu", "format", fallback="{name} {sec} {bars}") + else: + format = CONF.get("dmenu", "format", fallback="{name:<{max_len_name}s} {sec:<{max_len_sec}s} {bars:>4}") + + for nm_ap, name, sec in zip(aps, names, secs): + is_active = nm_ap.get_bssid() == active_ap_bssid + signal_strength = nm_ap.get_strength() + bars = strength_bars(signal_strength) + icon = strength_icon(signal_strength) + action_name = format.format(name=name, sec=sec, signal=signal_strength, bars=bars, icon=icon, + max_len_name=max_len_name, max_len_sec=max_len_sec) + if is_active: + ap_actions.append(Action(action_name, process_ap, + [active_connection, True, adapter], + active=True)) + else: + ap_actions.append(Action(action_name, process_ap, + [nm_ap, False, adapter])) + return ap_actions + + +def create_vpn_actions(vpns, active): + """Create the list of strings to display with associated function + (activate/deactivate) for VPN connections. + + """ + active_vpns = [i for i in active if i.get_vpn()] + return _create_vpngsm_actions(vpns, active_vpns, "VPN") + + +def create_wireguard_actions(wgs, active): + """Create the list of strings to display with associated function + (activate/deactivate) for Wireguard connections. + + """ + active_wgs = [i for i in active if i.get_connection_type() == "wireguard"] + return _create_vpngsm_actions(wgs, active_wgs, "Wireguard") + + +def create_eth_actions(eths, active): + """Create the list of strings to display with associated function + (activate/deactivate) for Ethernet connections. + + """ + active_eths = [i for i in active if 'ethernet' in i.get_connection_type()] + return _create_vpngsm_actions(eths, active_eths, "Eth") + + +def create_gsm_actions(gsms, active): + """Create the list of strings to display with associated function + (activate/deactivate) GSM connections.""" + active_gsms = [i for i in active if + i.get_connection() is not None and + i.get_connection().is_type(NM.SETTING_GSM_SETTING_NAME)] + return _create_vpngsm_actions(gsms, active_gsms, "GSM") + + +def create_blue_actions(blues, active): + """Create the list of strings to display with associated function + (activate/deactivate) Bluetooth connections.""" + active_blues = [i for i in active if + i.get_connection() is not None and + i.get_connection().is_type(NM.SETTING_BLUETOOTH_SETTING_NAME)] + return _create_vpngsm_actions(blues, active_blues, "Bluetooth") + + +def create_saved_actions(saved): + """Create the list of strings to display with associated function + (activate/deactivate) for VPN connections. + + """ + return _create_vpngsm_actions(saved, [], "SAVED") + + +def _create_vpngsm_actions(cons, active_cons, label): + active_con_ids = [a.get_id() for a in active_cons] + actions = [] + for con in cons: + is_active = con.get_id() in active_con_ids + action_name = f"{con.get_id()}:{label}" + if is_active: + active_connection = [a for a in active_cons + if a.get_id() == con.get_id()] + if len(active_connection) != 1: + raise ValueError(f"Multiple active connections match {con.get_id()}") + active_connection = active_connection[0] + + actions.append(Action(action_name, process_vpngsm, + [active_connection, False], active=True)) + else: + actions.append(Action(action_name, process_vpngsm, + [con, True])) + return actions + + +def create_wwan_actions(client): + """Create WWWAN actions + + """ + wwan_enabled = client.wwan_get_enabled() + wwan_action = "Disable" if wwan_enabled else "Enable" + return [Action(f"{wwan_action} WWAN", toggle_wwan, not wwan_enabled)] + + +def combine_actions(eths, aps, vpns, wgs, gsms, blues, wwan, others, saved): + # pylint: disable=too-many-arguments + """Combine all given actions into a list of actions. + + Args: args - eths: list of Actions + aps: list of Actions + vpns: list of Actions + gsms: list of Actions + blues: list of Actions + wwan: list of Actions + others: list of Actions + """ + compact = CONF.getboolean("dmenu", "compact", fallback=False) + empty_action = [Action('', None)] if not compact else [] + all_actions = [] + all_actions += eths + empty_action if eths else [] + all_actions += aps + empty_action if aps else [] + all_actions += vpns + empty_action if vpns else [] + all_actions += wgs + empty_action if wgs else [] + all_actions += gsms + empty_action if (gsms and wwan) else [] + all_actions += blues + empty_action if blues else [] + all_actions += wwan + empty_action if wwan else [] + all_actions += others + empty_action if others else [] + all_actions += saved + empty_action if saved else [] + return all_actions + + +def get_selection(all_actions): + """Spawn dmenu for selection and execute the associated action.""" + rofi_highlight = CONF.getboolean('dmenu', 'rofi_highlight', fallback=False) + inp = [] + + if rofi_highlight is True: + inp = [str(action) for action in all_actions] + else: + inp = [('== ' if action.is_active else ' ') + str(action) + for action in all_actions] + active_lines = [index for index, action in enumerate(all_actions) + if action.is_active] + + command = dmenu_cmd(len(inp), active_lines=active_lines) + sel = subprocess.run(command, + capture_output=True, + check=False, + input="\n".join(inp), + encoding=ENC, + env=ENV).stdout + + if not sel.rstrip(): + sys.exit() + + if rofi_highlight is False: + action = [i for i in all_actions + if ((str(i).strip() == str(sel.strip()) + and not i.is_active) or + ('== ' + str(i) == str(sel.rstrip('\n')) + and i.is_active))] + else: + action = [i for i in all_actions if str(i).strip() == sel.strip()] + if len(action) != 1: + raise ValueError(f"Selection was ambiguous: '{str(sel.strip())}'") + return action[0] + + +def toggle_networking(enable): + """Enable/disable networking + + Args: enable - boolean + + """ + toggle = GLib.Variant.new_tuple(GLib.Variant.new_boolean(enable)) + try: + CLIENT.dbus_call(NM.DBUS_PATH, NM.DBUS_INTERFACE, "Enable", toggle, + None, -1, None, None, None) + except AttributeError: + # Workaround for older versions of python-gobject + CLIENT.networking_set_enabled(enable) + notify(f"Networking {'enabled' if enable is True else 'disabled'}") + + +def toggle_wifi(enable): + """Enable/disable Wifi + + Args: enable - boolean + + """ + toggle = GLib.Variant.new_boolean(enable) + try: + CLIENT.dbus_set_property(NM.DBUS_PATH, NM.DBUS_INTERFACE, "WirelessEnabled", toggle, + -1, None, None, None) + except AttributeError: + # Workaround for older versions of python-gobject + CLIENT.wireless_set_enabled(enable) + notify(f"Wifi {'enabled' if enable is True else 'disabled'}") + + +def toggle_wwan(enable): + """Enable/disable WWAN + + Args: enable - boolean + + """ + toggle = GLib.Variant.new_boolean(enable) + try: + CLIENT.dbus_set_property(NM.DBUS_PATH, NM.DBUS_INTERFACE, "WwanEnabled", toggle, + -1, None, None, None) + except AttributeError: + # Workaround for older versions of python-gobject + CLIENT.wwan_set_enabled(enable) + notify(f"Wwan {'enabled' if enable is True else 'disabled'}") + + +def toggle_bluetooth(enable): + """Enable/disable Bluetooth + + Args: enable - boolean + + References: + https://github.com/blueman-project/blueman/blob/master/blueman/plugins/mechanism/RfKill.py + https://www.kernel.org/doc/html/latest/driver-api/rfkill.html + https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/uapi/linux/rfkill.h?h=v5.8.9 + + """ + type_bluetooth = 2 + op_change_all = 3 + idx = 0 + soft_state = 0 if enable else 1 + hard_state = 0 + + data = struct.pack("IBBBB", idx, type_bluetooth, op_change_all, + soft_state, hard_state) + + try: + with open('/dev/rfkill', 'r+b', buffering=0) as rff: + rff.write(data) + except PermissionError: + notify("Lacking permission to write to /dev/rfkill.", + "Check README for configuration options.", + urgency="critical") + else: + notify(f"Bluetooth {'enabled' if enable else 'disabled'}") + + +def launch_connection_editor(): + """Launch nmtui or the gui nm-connection-editor + + """ + terminal = CONF.get("editor", "terminal", fallback="xterm") + gui_if_available = CONF.getboolean("editor", "gui_if_available", fallback=True) + guis = ["gnome-control-center", "nm-connection-editor"] + if gui_if_available is True: + for gui in guis: + if is_installed(gui): + subprocess.run(gui, check=False) + return + if is_installed("nmtui"): + subprocess.run([terminal, "-e", "nmtui"], check=False) + return + notify("No network connection editor installed", urgency="critical") + + +def get_passphrase(): + """Get a password + + Returns: string + + """ + pinentry = CONF.get("dmenu", "pinentry", fallback=None) + if pinentry: + description = CONF.get("pinentry", "description", fallback="Get network password") + prompt = CONF.get("pinentry", "prompt", fallback="Password: ") + pin = "" + out = subprocess.run(pinentry, + capture_output=True, + check=False, + encoding=ENC, + input=f"setdesc {description}\nsetprompt {prompt}\ngetpin\n").stdout + if out: + res = [i for i in out.split("\n") if i.startswith("D ")] + if res and res[0].startswith("D "): + pin = res[0].split("D ")[1] + return pin + return subprocess.run(dmenu_cmd(0, "Passphrase"), + stdin=subprocess.DEVNULL, + capture_output=True, + check=False, + encoding=ENC).stdout + + +def delete_connection(): + """Display list of NM connections and delete the selected one + + """ + conn_acts = [Action(i.get_id(), i.delete_async, args=[None, delete_cb, None]) for i in CONNS] + conn_names = "\n".join([str(i) for i in conn_acts]) + sel = subprocess.run(dmenu_cmd(len(conn_acts), "CHOOSE CONNECTION TO DELETE:"), + capture_output=True, + check=False, + input=conn_names, + encoding=ENC, + env=ENV).stdout + if not sel.strip(): + sys.exit() + action = [i for i in conn_acts if str(i) == sel.rstrip("\n")] + if len(action) != 1: + raise ValueError(f"Selection was ambiguous: {str(sel)}") + action[0]() + LOOP.run() + + +def delete_cb(dev, res, data): + """Notification if delete completed successfully + + """ + if dev.delete_finish(res) is True: + notify(f"Deleted {dev.get_id()}") + else: + notify(f"Problem deleting {dev.get_id()}", urgency="critical") + LOOP.quit() + + +def set_new_connection(nm_ap, nm_pw, adapter): + """Setup a new NetworkManager connection + + Args: ap - NM.AccessPoint + pw - string + + """ + nm_pw = str(nm_pw).strip() + profile = create_wifi_profile(nm_ap, nm_pw, adapter) + CLIENT.add_and_activate_connection_async(profile, adapter, nm_ap.get_path(), + None, verify_conn, profile) + LOOP.run() + + +def create_wifi_profile(nm_ap, password, adapter): + # pylint: disable=line-too-long + # noqa From https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/python/gi/add_connection.py + # noqa and https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/python/dbus/add-wifi-psk-connection.py + # pylint: enable=line-too-long + """Create the NM profile given the AP and passphrase""" + ap_sec = ap_security(nm_ap) + profile = NM.SimpleConnection.new() + + s_con = NM.SettingConnection.new() + s_con.set_property(NM.SETTING_CONNECTION_ID, ssid_to_utf8(nm_ap)) + s_con.set_property(NM.SETTING_CONNECTION_UUID, str(uuid.uuid4())) + s_con.set_property(NM.SETTING_CONNECTION_TYPE, "802-11-wireless") + profile.add_setting(s_con) + + s_wifi = NM.SettingWireless.new() + s_wifi.set_property(NM.SETTING_WIRELESS_SSID, nm_ap.get_ssid()) + s_wifi.set_property(NM.SETTING_WIRELESS_MODE, 'infrastructure') + s_wifi.set_property(NM.SETTING_WIRELESS_MAC_ADDRESS, adapter.get_permanent_hw_address()) + profile.add_setting(s_wifi) + + s_ip4 = NM.SettingIP4Config.new() + s_ip4.set_property(NM.SETTING_IP_CONFIG_METHOD, "auto") + profile.add_setting(s_ip4) + + s_ip6 = NM.SettingIP6Config.new() + s_ip6.set_property(NM.SETTING_IP_CONFIG_METHOD, "auto") + profile.add_setting(s_ip6) + + if ap_sec != "--": + s_wifi_sec = NM.SettingWirelessSecurity.new() + if "WPA" in ap_sec: + if "WPA3" in ap_sec: + s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT, + "sae") + else: + s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT, + "wpa-psk") + s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_AUTH_ALG, + "open") + s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_PSK, password) + elif "WEP" in ap_sec: + s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT, + "None") + s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + NM.WepKeyType.PASSPHRASE) + s_wifi_sec.set_wep_key(0, password) + profile.add_setting(s_wifi_sec) + + return profile + + +def verify_conn(client, result, data): + """Callback function for add_and_activate_connection_async + + Check if connection completes successfully. Delete the connection if there + is an error. + + """ + try: + act_conn = client.add_and_activate_connection_finish(result) + conn = act_conn.get_connection() + if not all([conn.verify(), + conn.verify_secrets(), + data.verify(), + data.verify_secrets()]): + raise GLib.Error + notify(f"Added {conn.get_id()}") + except GLib.Error: + try: + notify(f"Connection to {conn.get_id()} failed", + urgency="critical") + conn.delete_async(None, None, None) + except UnboundLocalError: + pass + finally: + LOOP.quit() + + +def create_ap_list(adapter, active_connections): + """Generate list of access points. Remove duplicate APs , keeping strongest + ones and the active AP + + Args: adapter + active_connections - list of all active connections + Returns: aps - list of access points + active_ap - active AP + active_ap_con - active Connection + adapter + + """ + aps = [] + ap_names = [] + active_ap = adapter.get_active_access_point() + aps_all = sorted(adapter.get_access_points(), + key=lambda a: a.get_strength(), reverse=True) + conns_cur = [i for i in CONNS if + i.get_setting_wireless() is not None and + conn_matches_adapter(i, adapter)] + try: + ap_conns = active_ap.filter_connections(conns_cur) + active_ap_name = ssid_to_utf8(active_ap) + active_ap_con = [active_conn for active_conn in active_connections + if active_conn.get_connection() in ap_conns] + except AttributeError: + active_ap_name = None + active_ap_con = [] + if len(active_ap_con) > 1: + raise ValueError("Multiple connection profiles match" + " the wireless AP") + active_ap_con = active_ap_con[0] if active_ap_con else None + for nm_ap in aps_all: + ap_name = ssid_to_utf8(nm_ap) + if nm_ap != active_ap and ap_name == active_ap_name: + # Skip adding AP if it's not active but same name as active AP + continue + if ap_name not in ap_names: + ap_names.append(ap_name) + aps.append(nm_ap) + return aps, active_ap, active_ap_con, adapter + + +def notify(message, details=None, urgency="low"): + """Use notify-send if available for notifications + + """ + delay = CONF.getint('nmdm', 'rescan_delay', fallback=5) + args = ["-u", urgency, "-a", "networkmanager-dmenu", + "-t", str(delay * 1000), message] + if details is not None: + args.append(details) + if is_installed("notify-send"): + subprocess.run(["notify-send"] + args, check=False) + + +def run(): # pylint: disable=too-many-locals + """Main script entrypoint""" + try: + subprocess.check_output(["pidof", "NetworkManager"]) + except subprocess.CalledProcessError: + notify("WARNING: NetworkManager don't seems to be running") + print("WARNING: NetworkManager don't seems to be running") + active = CLIENT.get_active_connections() + adapter = choose_adapter(CLIENT) + if adapter: + ap_actions = create_ap_actions(*create_ap_list(adapter, active)) + else: + ap_actions = [] + + vpns = [i for i in CONNS if i.is_type(NM.SETTING_VPN_SETTING_NAME)] + try: + wgs = [i for i in CONNS if i.is_type(NM.SETTING_WIREGUARD_SETTING_NAME)] + except AttributeError: + # Workaround for older versions of python-gobject with no wireguard support + wgs = [] + eths = [i for i in CONNS if i.is_type(NM.SETTING_WIRED_SETTING_NAME)] + blues = [i for i in CONNS if i.is_type(NM.SETTING_BLUETOOTH_SETTING_NAME)] + + vpn_actions = create_vpn_actions(vpns, active) + wg_actions = create_wireguard_actions(wgs, active) + eth_actions = create_eth_actions(eths, active) + blue_actions = create_blue_actions(blues, active) + other_actions = create_other_actions(CLIENT) + wwan_installed = is_installed("ModemManager") + if wwan_installed: + gsms = [i for i in CONNS if i.is_type(NM.SETTING_GSM_SETTING_NAME)] + gsm_actions = create_gsm_actions(gsms, active) + wwan_actions = create_wwan_actions(CLIENT) + else: + gsm_actions = [] + wwan_actions = [] + + list_saved = CONF.getboolean('dmenu', 'list_saved', fallback=False) + saved_cons = [i for i in CONNS if i not in vpns + wgs + eths + blues] + if list_saved: + saved_actions = create_saved_actions(saved_cons) + else: + saved_actions = [Action("Saved connections", prompt_saved, [saved_cons])] + + actions = combine_actions(eth_actions, ap_actions, vpn_actions, wg_actions, + gsm_actions, blue_actions, wwan_actions, + other_actions, saved_actions) + sel = get_selection(actions) + sel() + + +def main(): + """Main. Enables script to be re-run after a wifi rescan + + """ + global CLIENT, CONNS, LOOP # noqa pylint: disable=global-variable-undefined + CLIENT = NM.Client.new(None) + LOOP = GLib.MainLoop() + CONNS = CLIENT.get_connections() + + run() + + +if __name__ == '__main__': + main() + +# vim: set et ts=4 sw=4 : diff --git a/.local/bin/pgen b/.local/bin/pgen new file mode 100755 index 0000000..af45c77 --- /dev/null +++ b/.local/bin/pgen @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# Description: Creates a project for c++ + +[[ -z "$1" ]] && echo "Error: Project name not provided" >&2 && exit 1 +[[ ! $1 =~ ^[a-zA-Z0-9_-]+$ ]] && echo "Error: Invalid project name. Chars allowed: [a-zA-Z0-9_-]" >&2 && exit 1 + +project_dir="$HOME/Projects/cpp20/$1" + +[[ -d "$project_dir" ]] && cd "$project_dir" && nvim main.cpp && exit 1 + +ff "$project_dir"/{main.cpp,include/} + +cp ~/.local/share/script-data/cpp20/compile_flags.txt "$project_dir"/compile_flags.txt +cp ~/.local/share/script-data/cpp20/.clang-format "$project_dir"/.clang-format +cp ~/.local/share/script-data/cpp20/Makefile "$project_dir"/Makefile + +nvim "$project_dir"/main.cpp diff --git a/.local/bin/processkill b/.local/bin/processkill new file mode 100755 index 0000000..c234a46 --- /dev/null +++ b/.local/bin/processkill @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +selected_process=$(ps -eo pid,comm,%mem --sort=-%mem | awk '{print $1, $2}' | dmenu -l 30 -bw 2 -W 300 -X 1051 -Y 15 -i | awk '{print $1}') +[[ -z $selected_process ]] && exit 1 +if ps -p "$selected_process" >/dev/null 2>&1; then + choice=$(echo -e "yes\nno" | dmenu -i -l 2 -bw 2 -W 300 -X 1051 -Y 15 -p "Terminate '$(ps -o comm= -p "$selected_process")'?") && + ([[ $choice == "yes" ]] && kill "$selected_process") || exit 0 +else + notify-send "PID $selected_process not found" +fi diff --git a/.local/bin/qndl b/.local/bin/qndl new file mode 100755 index 0000000..f95bc37 --- /dev/null +++ b/.local/bin/qndl @@ -0,0 +1,12 @@ +#!/bin/sh + +# $1 is a url; $2 is a command +[ -z "$1" ] && exit +base="$(basename "$1")" +notify-send "󰞌 Queuing $base..." +cmd="$2" +[ -z "$cmd" ] && cmd="yt-dlp --embed-metadata -ic" +idnum="$(tsp $cmd "$1")" +realname="$(echo "$base" | sed "s/?\(source\|dest\).*//;s/%20/ /g")" +tsp -D "$idnum" mv "$base" "$realname" +tsp -D "$idnum" notify-send " $realname done." diff --git a/.local/bin/renew-dwm b/.local/bin/renew-dwm new file mode 100755 index 0000000..6d64aa4 --- /dev/null +++ b/.local/bin/renew-dwm @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +export WM="dwm" + +wmpid(){ + tree="$(pstree -ps $$)" + tree="${tree#*$WM(}" + echo "${tree%%)*}" +} + +kill -HUP "$(wmpid)" diff --git a/.local/bin/setbg b/.local/bin/setbg new file mode 100755 index 0000000..ae3313f --- /dev/null +++ b/.local/bin/setbg @@ -0,0 +1,42 @@ +#!/bin/sh + +# This script does the following: +# Run by itself, set the wallpaper (at X start). +# If given a file, set that as the new wallpaper. +# If given a directory, choose random file in it. +# If wal is installed, also generates a colorscheme. + +# Location of link to wallpaper link. +bgloc="${XDG_DATA_HOME:-$HOME/.local/share}/bg" + +# Configuration files of applications that have their themes changed by pywal. +dunstconf="${XDG_CONFIG_HOME:-$HOME/.config}/dunst/dunstrc" +zathuraconf="${XDG_CONFIG_HOME:-$HOME/.config}/zathura/zathurarc" + +# Give -s as parameter to make notifications silent. +while getopts "s" o; do case "${o}" in + s) silent='1' ;; + esac done + +shift $((OPTIND - 1)) + +trueloc="$(readlink -f "$1")" && + case "$(file --mime-type -b "$trueloc")" in + image/*) ln -sf "$trueloc" "$bgloc" && [ -z "$silent" ] && notify-send -i "$bgloc" "Wallpaper applied..." ;; + inode/directory) ln -sf "$(find "$trueloc" -iregex '.*.\(jpg\|jpeg\|png\|gif\)' -type f | shuf -n 1)" "$bgloc" && [ -z "$silent" ] && notify-send -i "$bgloc" "Random Wallpaper chosen." ;; + *) + [ -z "$silent" ] && notify-send "󰋩 Error" "Not a valid image or directory." + exit 1 + ;; + esac + +# If pywal is installed, use it. +if command -v wal >/dev/null 2>&1; then + wal -n -i "$(readlink -f $bgloc)" -o "${XDG_CONFIG_HOME:-$HOME/.config}/wal/postrun" >/dev/null 2>&1 +# If pywal is removed, return config files to normal. +else + [ -f "$dunstconf.bak" ] && unlink "$dunstconf" && mv "$dunstconf.bak" "$dunstconf" + [ -f "$zathuraconf.bak" ] && unlink "$zathuraconf" && mv "$zathuraconf.bak" "$zathuraconf" +fi + +xwallpaper --zoom "$bgloc" diff --git a/.local/bin/statusbar/sb-battery b/.local/bin/statusbar/sb-battery new file mode 100755 index 0000000..f7217fe --- /dev/null +++ b/.local/bin/statusbar/sb-battery @@ -0,0 +1,61 @@ +#!/bin/sh + +# Prints all batteries, their percentage remaining and an emoji corresponding +# to charge status (󱐋 for plugged up,  for discharging on battery, etc.). + +case $BLOCK_BUTTON in + 1) notify-send " Battery module" " : discharging +󰅙 : not charging + : stagnant charge +󱐋 : charging + : charged + : battery very low! + +- Scroll to adjust brightness" ;; + 3) notify-send " Battery module" " : discharging +󰅙 : not charging + : stagnant charge +󱐋 : charging + : charged + : battery very low! + +- Scroll to adjust brightness" ;; + 4) xbacklight -inc 15 ;; + 5) xbacklight -dec 15 ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac + +# Loop through all attached batteries and format the info +for battery in /sys/class/power_supply/BAT?*; do + # If non-first battery, print a space separator. + [ -n "${capacity+x}" ] && printf " " + # Sets up the status and capacity + if [ ! -e ~/.cache/bar_color ]; then + case "$(cat "$battery/status" 2>&1)" in + "Full") status=" " ;; + "Discharging") status=" " ;; + "Charging") status="󱐋 " ;; + "Not charging") status="󱐋 " ;; + "Unknown") status=" " ;; + *) exit 1 ;; + esac + else + case "$(cat "$battery/status" 2>&1)" in + "Full") status="^C2^ ^d^" ;; + "Discharging") status="^C5^ ^d^" ;; + "Charging") status="^C3^󱐋 ^d^" ;; + "Not charging") status="^C1^󱐋 ^d^" ;; + "Unknown") status="^C6^ ^d^" ;; + *) exit 1 ;; + esac + fi + capacity="$(cat "$battery/capacity" 2>&1)" + # Will make a warn variable if discharging and low + if [ ! -e ~/.cache/bar_color ]; then + [ "$status" = " " ] && [ "$capacity" -le 25 ] && warn=" " + else + [ "$status" = "^C1^ ^d^" ] && [ "$capacity" -le 25 ] && warn="^C3^ ^d^" + fi + # Prints the info + printf "%s%s%d%%" "$status" "$warn" "$capacity"; unset warn +done && printf "\\n" diff --git a/.local/bin/statusbar/sb-clock b/.local/bin/statusbar/sb-clock new file mode 100755 index 0000000..bf23ff8 --- /dev/null +++ b/.local/bin/statusbar/sb-clock @@ -0,0 +1,34 @@ +#!/bin/sh + +clock=$(date '+%I') + +case "$clock" in + "00") icon="󱑊 ";; + "01") icon="󱐿 ";; + "02") icon="󱑀 ";; + "03") icon="󱑁 ";; + "04") icon="󱑂 ";; + "05") icon="󱑃 ";; + "06") icon="󱑄 ";; + "07") icon="󱑅 ";; + "08") icon="󱑆 ";; + "09") icon="󱑇 ";; + "10") icon="󱑈 ";; + "11") icon="󱑉 ";; + "12") icon="󱑊 ";; +esac + +case $BLOCK_BUTTON in + 1) notify-send "This Month" "$(cal | sed "s/\<$(date +'%e')\>/&<\/span><\/b>/")" && notify-send "Appointments" "$(calcurse -d3)" ;; + 2) setsid -f "$TERMINAL" -e calcurse ;; + 3) notify-send "󰃭 Time/date module" "\- Left click to show upcoming appointments for the next three days via \`calcurse -d3\` and show the month via \`cal\` +- Middle click opens calcurse if installed" ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac + +# date "+^C1^󰃭 ^d^%a-%b-%d ^C5^$icon^d^ %I:%M %P" +if [ ! -e ~/.cache/bar_color ]; then + date "+$icon %I:%M %P" +else + date "+^C5^$icon^d^ %I:%M %P" +fi diff --git a/.local/bin/statusbar/sb-help-icon b/.local/bin/statusbar/sb-help-icon new file mode 100755 index 0000000..9f5d475 --- /dev/null +++ b/.local/bin/statusbar/sb-help-icon @@ -0,0 +1,12 @@ +#!/bin/sh + +case $BLOCK_BUTTON in + 1) keybinds ;; + 3) notify-send "󰌌 Help module" "\- Left click to open keybinds guide." ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac; +if [ ! -e ~/.cache/bar_color ]; then + echo "󰌌 " +else + echo "^C3^󰌌 ^d^" +fi diff --git a/.local/bin/statusbar/sb-internet b/.local/bin/statusbar/sb-internet new file mode 100755 index 0000000..5e32077 --- /dev/null +++ b/.local/bin/statusbar/sb-internet @@ -0,0 +1,42 @@ +#!/bin/sh + +# Show wifi 󰤪 and percent strength or 󰤭 if none. +# Show 󰈁 if connected to ethernet or 󰈂 if none. +# Show 󰖂 if a vpn connection is active + +case $BLOCK_BUTTON in + 1) networkmanager_dmenu && pkill -RTMIN+4 dwmblocks ;; + 3) notify-send "󰖟 Internet module" "\- Click to connect +󰇨 : wifi disabled +󰤭 : no wifi connection +󰤪 : wifi connected +󰈂 : no ethernet +󰈁 : ethernet working +󰖂 : vpn is active +" ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac + +# Wifi +if [ "$(cat /sys/class/net/w*/operstate 2>/dev/null)" = 'up' ] ; then + if [ ! -e ~/.cache/bar_color ]; then + wifiicon="$(awk '/^\s*w/ { cmd="nmcli -t -f active,ssid dev wifi | grep yes | cut -d: -f2"; cmd | getline output; close(cmd); print "󰤪 ", output }' /proc/net/wireless)" + else + wifiicon="$(awk '/^\s*w/ { cmd="nmcli -t -f active,ssid dev wifi | grep yes | cut -d: -f2"; cmd | getline output; close(cmd); print "^C2^󰤪 ^d^", output }' /proc/net/wireless)" + fi +elif [ "$(cat /sys/class/net/w*/operstate 2>/dev/null)" = 'down' ] ; then + if [ ! -e ~/.cache/bar_color ]; then + [ "$(cat /sys/class/net/w*/flags 2>/dev/null)" = '0x1003' ] && wifiicon="󰤭 " || wifiicon="󰇨 " + else + [ "$(cat /sys/class/net/w*/flags 2>/dev/null)" = '0x1003' ] && wifiicon="^C1^󰤭 ^d^" || wifiicon="^C3^󰇨 ^d^" + fi +fi + +# Ethernet +# [ "$(cat /sys/class/net/e*/operstate 2>/dev/null)" = 'up' ] && ethericon="󰈁 " || ethericon="󰈂 " + +# TUN +# [ -n "$(cat /sys/class/net/tun*/operstate 2>/dev/null)" ] && tunicon="󰖂 " + +# printf "%s%s%s\n" "$wifiicon" "$ethericon" "$tunicon" +printf "%s%s%s\n" "$wifiicon" diff --git a/.local/bin/statusbar/sb-nettraf b/.local/bin/statusbar/sb-nettraf new file mode 100755 index 0000000..4853296 --- /dev/null +++ b/.local/bin/statusbar/sb-nettraf @@ -0,0 +1,33 @@ +#!/bin/sh + +# Module showing network traffic. Shows how much data has been received (RX) or +# transmitted (TX) since the previous time this script ran. So if run every +# second, gives network traffic per second. + +case $BLOCK_BUTTON in + 1) setsid -f "$TERMINAL" -e bmon ;; + 3) notify-send "󰓅 Network traffic module" "󰄼 : Traffic received +󰄿 : Traffic transmitted" ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac + +update() { + sum=0 + for arg; do + read -r i < "$arg" + sum=$(( sum + i )) + done + cache=/tmp/${1##*/} + [ -f "$cache" ] && read -r old < "$cache" || old=0 + printf %d\\n "$sum" > "$cache" + printf %d\\n $(( sum - old )) +} + +rx=$(update /sys/class/net/[ew]*/statistics/rx_bytes) +tx=$(update /sys/class/net/[ew]*/statistics/tx_bytes) + +if [ ! -e ~/.cache/bar_color ]; then + printf "󰜮 %4sB 󰜷 %4sB\\n" $(numfmt --to=iec $rx $tx) + exit 0 +fi +printf "^C2^󰜮 ^d^%4sB ^C3^󰜷 ^d^%4sB\\n" $(numfmt --to=iec $rx $tx) diff --git a/.local/bin/statusbar/sb-news b/.local/bin/statusbar/sb-news new file mode 100755 index 0000000..e3d8126 --- /dev/null +++ b/.local/bin/statusbar/sb-news @@ -0,0 +1,22 @@ +#!/bin/sh + +# Displays number of unread news items and an loading icon if updating. +# When clicked, brings up `newsboat`. + +case $BLOCK_BUTTON in + 1) setsid "$TERMINAL" -e newsboat ;; + 2) setsid -f newsup >/dev/null exit ;; + 3) notify-send "󰑫 News module" "\- Shows unread news items +- Shows  if updating with \`newsup\` +- Left click opens newsboat +- Middle click syncs RSS feeds +Note: Only one instance of newsboat (including updates) may be running at a time." ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac + +if [ ! -e ~/.cache/bar_color ]; then + cat /tmp/newsupdate 2>/dev/null || echo "$(newsboat -x print-unread | awk '{ if($1>0) print "󰑫 " $1}')$(cat "${XDG_CONFIG_HOME:-$HOME/.config}"/newsboat/.update 2>/dev/null)" + exit 0 +fi + + cat /tmp/newsupdate 2>/dev/null || echo "$(newsboat -x print-unread | awk '{ if($1>0) print "^C1^󰑫 ^d^" $1}')$(cat "${XDG_CONFIG_HOME:-$HOME/.config}"/newsboat/.update 2>/dev/null)" diff --git a/.local/bin/statusbar/sb-powerbutton b/.local/bin/statusbar/sb-powerbutton new file mode 100755 index 0000000..65ab161 --- /dev/null +++ b/.local/bin/statusbar/sb-powerbutton @@ -0,0 +1,13 @@ +#!/bin/sh + +# The clickable help menu. Middle click to restart wm. + +case $BLOCK_BUTTON in + 1) sysact ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac; +if [ ! -e ~/.cache/bar_color ]; then + echo " " +else + echo "^C1^ ^d^" +fi diff --git a/.local/bin/statusbar/sb-volume b/.local/bin/statusbar/sb-volume new file mode 100755 index 0000000..2ff2579 --- /dev/null +++ b/.local/bin/statusbar/sb-volume @@ -0,0 +1,43 @@ +#!/bin/sh + +# Prints the current volume or  if muted. + +case $BLOCK_BUTTON in + 1) setsid -w -f "$TERMINAL" -c volume-ui -g=80x15+353+20 -e pulsemixer; pkill -RTMIN+10 "${STATUSBAR:-dwmblocks}" ;; + 2) wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle ;; + 4) wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+ ;; + 5) wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%- ;; + 3) notify-send "󰎈 Volume module" "\- Shows volume 󰎈,  if muted. +- Middle click to mute. +- Scroll to change." ;; + 6) "$TERMINAL" -e "$EDITOR" "$0" ;; +esac + +vol="$(wpctl get-volume @DEFAULT_AUDIO_SINK@)" + +# If muted, print  and exit. +[ "$vol" != "${vol%\[MUTED\]}" ] && echo  && exit + +vol="${vol#Volume: }" + +split() { + # For omitting the . without calling and external program. + IFS=$2 + set -- $1 + printf '%s' "$@" +} + +vol="$(printf "%.0f" "$(split "$vol" ".")")" + +case 1 in + $((vol >= 70)) ) icon="󰎈 " ;; + $((vol >= 30)) ) icon="󰎈 " ;; + $((vol >= 1)) ) icon="󰎈 " ;; + * ) echo  && exit ;; +esac + +if [ ! -e ~/.cache/bar_color ]; then + echo "$icon$vol%" +else + echo "^C4^$icon^d^$vol%" +fi diff --git a/.local/bin/sysact b/.local/bin/sysact new file mode 100755 index 0000000..8dd8da7 --- /dev/null +++ b/.local/bin/sysact @@ -0,0 +1,24 @@ +#!/bin/bash + +options=( + " Lock" + " Renew dwm" + "󰍃 Leave dwm" + " Shutdown" + " Reboot" + "󰶐 Display off" +) + +commands=( + "lock" + "renew-dwm" + "kill -TERM $(pidof -s dwm)" + "systemctl poweroff -i" + "systemctl reboot -i" + "xset dpms force off" +) + +if prompt=$(printf '%s\n' "${options[@]}" | dmenu -i -bw 2 -g 1 -l 9 -W 200 -X 1151 -Y 15); then + selected_index=$(printf '%s\n' "${options[@]}" | grep -xn "$prompt" | cut -d ":" -f 1) + ${commands[$selected_index - 1]} +fi diff --git a/.local/bin/unmounter b/.local/bin/unmounter new file mode 100755 index 0000000..9e6d696 --- /dev/null +++ b/.local/bin/unmounter @@ -0,0 +1,28 @@ +#!/bin/sh + +# Unmount USB drives or Android phones. Replaces the older `dmenuumount`. Fewer +# prompt and also de-decrypts LUKS drives that are unmounted. + +set -e + +mounteddroids="$(grep simple-mtpfs /etc/mtab | awk '{print "📱" $2}')" +lsblkoutput="$(lsblk -nrpo "name,type,size,mountpoint")" +mounteddrives="$(echo "$lsblkoutput" | awk '($2=="part"||$2="crypt")&&$4!~/\/boot|\/home$|SWAP/&&length($4)>1{printf "󰋊%s (%s)\n",$4,$3}')" + +allunmountable="$(echo "$mounteddroids +$mounteddrives" | sed "/^$/d;s/ *$//")" +test -n "$allunmountable" + +chosen="$(echo "$allunmountable" | dmenu -i -p "Unmount which drive?")" +chosen="${chosen%% *}" +test -n "$chosen" + +sudo -A umount -l "/${chosen#*/}" +notify-send "Device unmounted." "$chosen has been unmounted." + +# Close the chosen drive if decrypted. +cryptid="$(echo "$lsblkoutput" | grep "/${chosen#*/}$")" +cryptid="${cryptid%% *}" +test -b /dev/mapper/"${cryptid##*/}" +sudo -A cryptsetup close "$cryptid" +notify-send "🔒Device dencryption closed." "Drive is now securely locked again." diff --git a/.local/bin/xcolor-pick b/.local/bin/xcolor-pick new file mode 100755 index 0000000..7aa95ca --- /dev/null +++ b/.local/bin/xcolor-pick @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Simple Script To Pick Color Quickly Using Gpick. + +CMD=$(gpick --no-newline -pso) +TMP=/tmp/xcolor_$CMD.png + +check_dependencies() { + ! command -v gpick &>/dev/null && + notify-send -u critical -a "Color Picker" xcolor-pick "gpick needs to be installed" && exit 1 + + ! command -v magick &>/dev/null && + notify-send -u critical -a "Color Picker" xcolor-pick "imagemagick needs to be installed" && exit 1 +} + +main() { + convert -size 120x120 xc:"$CMD" "$TMP" + printf %s "$CMD" | xclip -selection clipboard + + notify-send -a "Color Picker" -i "$TMP" xcolor-pick "$CMD" +} + +check_dependencies +main diff --git a/.local/share/fonts/BerkeleyMono-Regular.ttf b/.local/share/fonts/BerkeleyMono-Regular.ttf new file mode 100644 index 0000000..5a9fb6a Binary files /dev/null and b/.local/share/fonts/BerkeleyMono-Regular.ttf differ diff --git a/.local/share/fonts/CaskaydiaCove/CaskaydiaCoveNerdFont-Regular.ttf b/.local/share/fonts/CaskaydiaCove/CaskaydiaCoveNerdFont-Regular.ttf new file mode 100644 index 0000000..f801654 Binary files /dev/null and b/.local/share/fonts/CaskaydiaCove/CaskaydiaCoveNerdFont-Regular.ttf differ diff --git a/.local/share/fonts/ComicCode-Medium.ttf b/.local/share/fonts/ComicCode-Medium.ttf new file mode 100644 index 0000000..c6090e6 Binary files /dev/null and b/.local/share/fonts/ComicCode-Medium.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/.uuid b/.local/share/fonts/MonoLisa-Static/.uuid new file mode 100644 index 0000000..c4b39fb --- /dev/null +++ b/.local/share/fonts/MonoLisa-Static/.uuid @@ -0,0 +1 @@ +9d5ad7f0-7e2b-401e-82d6-eef101f12753 \ No newline at end of file diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-Black.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-Black.ttf new file mode 100644 index 0000000..59c26ce Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-Black.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-BlackItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-BlackItalic.ttf new file mode 100644 index 0000000..8566bd1 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-BlackItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-Bold.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-Bold.ttf new file mode 100644 index 0000000..4f5188a Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-Bold.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-BoldItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-BoldItalic.ttf new file mode 100644 index 0000000..46eff35 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-BoldItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraBold.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraBold.ttf new file mode 100644 index 0000000..b0366b0 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraBold.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraBoldItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraBoldItalic.ttf new file mode 100644 index 0000000..13f4fce Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraBoldItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraLight.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraLight.ttf new file mode 100644 index 0000000..7c0bc2c Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraLight.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraLightItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraLightItalic.ttf new file mode 100644 index 0000000..bc3913c Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-ExtraLightItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-Light.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-Light.ttf new file mode 100644 index 0000000..adb62cd Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-Light.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-LightItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-LightItalic.ttf new file mode 100644 index 0000000..3f83805 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-LightItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-Medium.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-Medium.ttf new file mode 100644 index 0000000..59b19ae Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-Medium.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-MediumItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-MediumItalic.ttf new file mode 100644 index 0000000..a3f0d0e Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-MediumItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-Regular.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-Regular.ttf new file mode 100644 index 0000000..0efe8b5 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-Regular.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-RegularItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-RegularItalic.ttf new file mode 100644 index 0000000..416bbe4 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-RegularItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-SemiBold.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-SemiBold.ttf new file mode 100644 index 0000000..e0fcf21 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-SemiBold.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-SemiBoldItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-SemiBoldItalic.ttf new file mode 100644 index 0000000..e91919e Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-SemiBoldItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-Thin.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-Thin.ttf new file mode 100644 index 0000000..d0c6e15 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-Thin.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisa-ThinItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisa-ThinItalic.ttf new file mode 100644 index 0000000..23cc187 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisa-ThinItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisaItalic.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisaItalic.ttf new file mode 100644 index 0000000..d0fee57 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisaItalic.ttf differ diff --git a/.local/share/fonts/MonoLisa-Static/MonoLisaNormal.ttf b/.local/share/fonts/MonoLisa-Static/MonoLisaNormal.ttf new file mode 100644 index 0000000..ef19c83 Binary files /dev/null and b/.local/share/fonts/MonoLisa-Static/MonoLisaNormal.ttf differ diff --git a/.local/share/fonts/SofiaPro/.uuid b/.local/share/fonts/SofiaPro/.uuid new file mode 100644 index 0000000..1697593 --- /dev/null +++ b/.local/share/fonts/SofiaPro/.uuid @@ -0,0 +1 @@ +8a9fec04-5ce4-4051-8b60-068747e2ea14 \ No newline at end of file diff --git a/.local/share/fonts/SofiaPro/SofiaPro-Medium.ttf b/.local/share/fonts/SofiaPro/SofiaPro-Medium.ttf new file mode 100644 index 0000000..84033a2 Binary files /dev/null and b/.local/share/fonts/SofiaPro/SofiaPro-Medium.ttf differ diff --git a/.local/share/fonts/SofiaPro/SofiaPro-Regular.ttf b/.local/share/fonts/SofiaPro/SofiaPro-Regular.ttf new file mode 100644 index 0000000..6180dd7 Binary files /dev/null and b/.local/share/fonts/SofiaPro/SofiaPro-Regular.ttf differ diff --git a/.local/share/fonts/Symbols/.uuid b/.local/share/fonts/Symbols/.uuid new file mode 100644 index 0000000..431e0b8 --- /dev/null +++ b/.local/share/fonts/Symbols/.uuid @@ -0,0 +1 @@ +86af5719-dfd1-40f0-8e9b-559c17bc062c \ No newline at end of file diff --git a/.local/share/fonts/Symbols/SymbolsNerdFont-Regular.ttf b/.local/share/fonts/Symbols/SymbolsNerdFont-Regular.ttf new file mode 100644 index 0000000..e7ce229 Binary files /dev/null and b/.local/share/fonts/Symbols/SymbolsNerdFont-Regular.ttf differ diff --git a/.local/share/fonts/Symbols/feather-font-addon.ttf b/.local/share/fonts/Symbols/feather-font-addon.ttf new file mode 100644 index 0000000..c4aa630 Binary files /dev/null and b/.local/share/fonts/Symbols/feather-font-addon.ttf differ diff --git a/.local/share/fonts/Symbols/feather.ttf b/.local/share/fonts/Symbols/feather.ttf new file mode 100644 index 0000000..0b33dac Binary files /dev/null and b/.local/share/fonts/Symbols/feather.ttf differ diff --git a/.local/share/fonts/Symbols/material-design-icons.ttf b/.local/share/fonts/Symbols/material-design-icons.ttf new file mode 100644 index 0000000..7015564 Binary files /dev/null and b/.local/share/fonts/Symbols/material-design-icons.ttf differ diff --git a/.local/share/fonts/century-schoolbook/C059-BdIta.ttf b/.local/share/fonts/century-schoolbook/C059-BdIta.ttf new file mode 100644 index 0000000..af93623 Binary files /dev/null and b/.local/share/fonts/century-schoolbook/C059-BdIta.ttf differ diff --git a/.local/share/fonts/century-schoolbook/C059-Bold.otf b/.local/share/fonts/century-schoolbook/C059-Bold.otf new file mode 100644 index 0000000..f8718a8 Binary files /dev/null and b/.local/share/fonts/century-schoolbook/C059-Bold.otf differ diff --git a/.local/share/fonts/century-schoolbook/C059-Bold.ttf b/.local/share/fonts/century-schoolbook/C059-Bold.ttf new file mode 100644 index 0000000..3735d83 Binary files /dev/null and b/.local/share/fonts/century-schoolbook/C059-Bold.ttf differ diff --git a/.local/share/fonts/century-schoolbook/C059-Italic.ttf b/.local/share/fonts/century-schoolbook/C059-Italic.ttf new file mode 100644 index 0000000..3c8197f Binary files /dev/null and b/.local/share/fonts/century-schoolbook/C059-Italic.ttf differ diff --git a/.local/share/fonts/century-schoolbook/C059-Roman.ttf b/.local/share/fonts/century-schoolbook/C059-Roman.ttf new file mode 100644 index 0000000..7368c2e Binary files /dev/null and b/.local/share/fonts/century-schoolbook/C059-Roman.ttf differ diff --git a/.local/share/fonts/unifont-15.1.04.otf b/.local/share/fonts/unifont-15.1.04.otf new file mode 100644 index 0000000..99fd7e9 Binary files /dev/null and b/.local/share/fonts/unifont-15.1.04.otf differ diff --git a/.local/share/script-data/chars/emoji b/.local/share/script-data/chars/emoji new file mode 100644 index 0000000..6803731 --- /dev/null +++ b/.local/share/script-data/chars/emoji @@ -0,0 +1,1630 @@ +😀 grinning face +😃 grinning face with big eyes +😄 grinning face with smiling eyes +😁 beaming face with smiling eyes +😆 grinning squinting face +😅 grinning face with sweat +🤣 rolling on the floor laughing +😂 face with tears of joy +🙂 slightly smiling face +🙃 upside-down face +🫠 melting face +😉 winking face +😊 smiling face with smiling eyes +😇 smiling face with halo +🥰 smiling face with hearts +😍 smiling face with heart-eyes +🤩 star-struck +😘 face blowing a kiss +😗 kissing face +☺️ smiling face +😚 kissing face with closed eyes +😙 kissing face with smiling eyes +🥲 smiling face with tear +😋 face savoring food +😛 face with tongue +😜 winking face with tongue +🤪 zany face +😝 squinting face with tongue +🤑 money-mouth face +🤗 smiling face with open hands +🤭 face with hand over mouth +🫢 face with open eyes and hand over mouth +🫣 face with peeking eye +🤫 shushing face +🤔 thinking face +🫡 saluting face +🤐 zipper-mouth face +🤨 face with raised eyebrow +😐 neutral face +😑 expressionless face +😶 face without mouth +🫥 dotted line face +😏 smirking face +😒 unamused face +🙄 face with rolling eyes +😬 grimacing face +🤥 lying face +😌 relieved face +😔 pensive face +😪 sleepy face +🤤 drooling face +😴 sleeping face +😷 face with medical mask +🤒 face with thermometer +🤕 face with head-bandage +🤢 nauseated face +🤮 face vomiting +🤧 sneezing face +🥵 hot face +🥶 cold face +🥴 woozy face +😵 face with crossed-out eyes +🤯 exploding head +🤠 cowboy hat face +🥳 partying face +🥸 disguised face +😎 smiling face with sunglasses +🤓 nerd face +🧐 face with monocle +😕 confused face +🫤 face with diagonal mouth +😟 worried face +🙁 slightly frowning face +☹️ frowning face +😮 face with open mouth +😯 hushed face +😲 astonished face +😳 flushed face +🥺 pleading face +🥹 face holding back tears +😦 frowning face with open mouth +😧 anguished face +😨 fearful face +😰 anxious face with sweat +😥 sad but relieved face +😢 crying face +😭 loudly crying face +😱 face screaming in fear +😖 confounded face +😣 persevering face +😞 disappointed face +😓 downcast face with sweat +😩 weary face +😫 tired face +🥱 yawning face +😤 face with steam from nose +😡 pouting face +😠 angry face +🤬 face with symbols on mouth +😈 smiling face with horns +👿 angry face with horns +💀 skull +☠️ skull and crossbones +💩 pile of poo +🤡 clown face +👹 ogre +👺 goblin +👻 ghost +👽 alien +👾 alien monster +🤖 robot +😺 grinning cat +😸 grinning cat with smiling eyes +😹 cat with tears of joy +😻 smiling cat with heart-eyes +😼 cat with wry smile +😽 kissing cat +🙀 weary cat +😿 crying cat +😾 pouting cat +🙈 see-no-evil monkey +🙉 hear-no-evil monkey +🙊 speak-no-evil monkey +💋 kiss mark +💌 love letter +💘 heart with arrow +💝 heart with ribbon +💖 sparkling heart +💗 growing heart +💓 beating heart +💞 revolving hearts +💕 two hearts +💟 heart decoration +❣️ heart exclamation +💔 broken heart +❤️ red heart +🧡 orange heart +💛 yellow heart +💚 green heart +💙 blue heart +💜 purple heart +🤎 brown heart +🖤 black heart +🤍 white heart +💯 hundred points +💢 anger symbol +💥 collision +💫 dizzy +💦 sweat droplets +💨 dashing away +🕳️ hole +💣 bomb +💬 speech balloon +🗨️ left speech bubble +🗯️ right anger bubble +💭 thought balloon +💤 zzz +👋 waving hand +🤚 raised back of hand +🖐️ hand with fingers splayed +✋ raised hand +🖖 vulcan salute +🫱 rightwards hand +🫲 leftwards hand +🫳 palm down hand +🫴 palm up hand +👌 OK hand +🤌 pinched fingers +🤏 pinching hand +✌️ victory hand +🤞 crossed fingers +🫰 hand with index finger and thumb crossed +🤟 love-you gesture +🤘 sign of the horns +🤙 call me hand +👈 backhand index pointing left +👉 backhand index pointing right +👆 backhand index pointing up +🖕 middle finger +👇 backhand index pointing down +☝️ index pointing up +🫵 index pointing at the viewer +👍 thumbs up +👎 thumbs down +✊ raised fist +👊 oncoming fist +🤛 left-facing fist +🤜 right-facing fist +👏 clapping hands +🙌 raising hands +🫶 heart hands +👐 open hands +🤲 palms up together +🤝 handshake +🙏 folded hands +✍️ writing hand +💅 nail polish +🤳 selfie +💪 flexed biceps +🦾 mechanical arm +🦿 mechanical leg +🦵 leg +🦶 foot +👂 ear +🦻 ear with hearing aid +👃 nose +🧠 brain +🫀 anatomical heart +🫁 lungs +🦷 tooth +🦴 bone +👀 eyes +👁️ eye +👅 tongue +👄 mouth +🫦 biting lip +👶 baby +🧒 child +👦 boy +👧 girl +🧑 person +👱 person: blond hair +👨 man +🧔 person: beard +👩 woman +🧓 older person +👴 old man +👵 old woman +🙍 person frowning +🙎 person pouting +🙅 person gesturing NO +🙆 person gesturing OK +💁 person tipping hand +🙋 person raising hand +🧏 deaf person +🙇 person bowing +🤦 person facepalming +🤷 person shrugging +👮 police officer +🕵️ detective +💂 guard +🥷 ninja +👷 construction worker +🫅 person with crown +🤴 prince +👸 princess +👳 person wearing turban +👲 person with skullcap +🧕 woman with headscarf +🤵 person in tuxedo +👰 person with veil +🤰 pregnant woman +🫃 pregnant man +🫄 pregnant person +🤱 breast-feeding +👼 baby angel +🎅 Santa Claus +🤶 Mrs. Claus +🦸 superhero +🦹 supervillain +🧙 mage +🧚 fairy +🧛 vampire +🧜 merperson +🧝 elf +🧞 genie +🧟 zombie +🧌 troll +💆 person getting massage +💇 person getting haircut +🚶 person walking +🧍 person standing +🧎 person kneeling +🏃 person running +💃 woman dancing +🕺 man dancing +🕴️ person in suit levitating +👯 people with bunny ears +🧖 person in steamy room +🧗 person climbing +🤺 person fencing +🏇 horse racing +⛷️ skier +🏂 snowboarder +🏌️ person golfing +🏄 person surfing +🚣 person rowing boat +🏊 person swimming +⛹️ person bouncing ball +🏋️ person lifting weights +🚴 person biking +🚵 person mountain biking +🤸 person cartwheeling +🤼 people wrestling +🤽 person playing water polo +🤾 person playing handball +🤹 person juggling +🧘 person in lotus position +🛀 person taking bath +🛌 person in bed +👭 women holding hands +👫 woman and man holding hands +👬 men holding hands +💏 kiss +💑 couple with heart +👪 family +🗣️ speaking head +👤 bust in silhouette +👥 busts in silhouette +🫂 people hugging +👣 footprints +🐵 monkey face +🐒 monkey +🦍 gorilla +🦧 orangutan +🐶 dog face +🐕 dog +🦮 guide dog +🐩 poodle +🐺 wolf +🦊 fox +🦝 raccoon +🐱 cat face +🐈 cat +🦁 lion +🐯 tiger face +🐅 tiger +🐆 leopard +🐴 horse face +🐎 horse +🦄 unicorn +🦓 zebra +🦌 deer +🦬 bison +🐮 cow face +🐂 ox +🐃 water buffalo +🐄 cow +🐷 pig face +🐖 pig +🐗 boar +🐽 pig nose +🐏 ram +🐑 ewe +🐐 goat +🐪 camel +🐫 two-hump camel +🦙 llama +🦒 giraffe +🐘 elephant +🦣 mammoth +🦏 rhinoceros +🦛 hippopotamus +🐭 mouse face +🐁 mouse +🐀 rat +🐹 hamster +🐰 rabbit face +🐇 rabbit +🐿️ chipmunk +🦫 beaver +🦔 hedgehog +🦇 bat +🐻 bear +🐨 koala +🐼 panda +🦥 sloth +🦦 otter +🦨 skunk +🦘 kangaroo +🦡 badger +🐾 paw prints +🦃 turkey +🐔 chicken +🐓 rooster +🐣 hatching chick +🐤 baby chick +🐥 front-facing baby chick +🐦 bird +🐧 penguin +🕊️ dove +🦅 eagle +🦆 duck +🦢 swan +🦉 owl +🦤 dodo +🪶 feather +🦩 flamingo +🦚 peacock +🦜 parrot +🐸 frog +🐊 crocodile +🐢 turtle +🦎 lizard +🐍 snake +🐲 dragon face +🐉 dragon +🦕 sauropod +🦖 T-Rex +🐳 spouting whale +🐋 whale +🐬 dolphin +🦭 seal +🐟 fish +🐠 tropical fish +🐡 blowfish +🦈 shark +🐙 octopus +🐚 spiral shell +🪸 coral +🐌 snail +🦋 butterfly +🐛 bug +🐜 ant +🐝 honeybee +🪲 beetle +🐞 lady beetle +🦗 cricket +🪳 cockroach +🕷️ spider +🕸️ spider web +🦂 scorpion +🦟 mosquito +🪰 fly +🪱 worm +🦠 microbe +💐 bouquet +🌸 cherry blossom +💮 white flower +🪷 lotus +🏵️ rosette +🌹 rose +🥀 wilted flower +🌺 hibiscus +🌻 sunflower +🌼 blossom +🌷 tulip +🌱 seedling +🪴 potted plant +🌲 evergreen tree +🌳 deciduous tree +🌴 palm tree +🌵 cactus +🌾 sheaf of rice +🌿 herb +☘️ shamrock +🍀 four leaf clover +🍁 maple leaf +🍂 fallen leaf +🍃 leaf fluttering in wind +🪹 empty nest +🪺 nest with eggs +🍇 grapes +🍈 melon +🍉 watermelon +🍊 tangerine +🍋 lemon +🍌 banana +🍍 pineapple +🥭 mango +🍎 red apple +🍏 green apple +🍐 pear +🍑 peach +🍒 cherries +🍓 strawberry +🫐 blueberries +🥝 kiwi fruit +🍅 tomato +🫒 olive +🥥 coconut +🥑 avocado +🍆 eggplant +🥔 potato +🥕 carrot +🌽 ear of corn +🌶️ hot pepper +🫑 bell pepper +🥒 cucumber +🥬 leafy green +🥦 broccoli +🧄 garlic +🧅 onion +🍄 mushroom +🥜 peanuts +🫘 beans +🌰 chestnut +🍞 bread +🥐 croissant +🥖 baguette bread +🫓 flatbread +🥨 pretzel +🥯 bagel +🥞 pancakes +🧇 waffle +🧀 cheese wedge +🍖 meat on bone +🍗 poultry leg +🥩 cut of meat +🥓 bacon +🍔 hamburger +🍟 french fries +🍕 pizza +🌭 hot dog +🥪 sandwich +🌮 taco +🌯 burrito +🫔 tamale +🥙 stuffed flatbread +🧆 falafel +🥚 egg +🍳 cooking +🥘 shallow pan of food +🍲 pot of food +🫕 fondue +🥣 bowl with spoon +🥗 green salad +🍿 popcorn +🧈 butter +🧂 salt +🥫 canned food +🍱 bento box +🍘 rice cracker +🍙 rice ball +🍚 cooked rice +🍛 curry rice +🍜 steaming bowl +🍝 spaghetti +🍠 roasted sweet potato +🍢 oden +🍣 sushi +🍤 fried shrimp +🍥 fish cake with swirl +🥮 moon cake +🍡 dango +🥟 dumpling +🥠 fortune cookie +🥡 takeout box +🦀 crab +🦞 lobster +🦐 shrimp +🦑 squid +🦪 oyster +🍦 soft ice cream +🍧 shaved ice +🍨 ice cream +🍩 doughnut +🍪 cookie +🎂 birthday cake +🍰 shortcake +🧁 cupcake +🥧 pie +🍫 chocolate bar +🍬 candy +🍭 lollipop +🍮 custard +🍯 honey pot +🍼 baby bottle +🥛 glass of milk +☕ hot beverage +🫖 teapot +🍵 teacup without handle +🍶 sake +🍾 bottle with popping cork +🍷 wine glass +🍸 cocktail glass +🍹 tropical drink +🍺 beer mug +🍻 clinking beer mugs +🥂 clinking glasses +🥃 tumbler glass +🫗 pouring liquid +🥤 cup with straw +🧋 bubble tea +🧃 beverage box +🧉 mate +🧊 ice +🥢 chopsticks +🍽️ fork and knife with plate +🍴 fork and knife +🥄 spoon +🔪 kitchen knife +🫙 jar +🏺 amphora +🌍 globe showing Europe-Africa +🌎 globe showing Americas +🌏 globe showing Asia-Australia +🌐 globe with meridians +🗺️ world map +🗾 map of Japan +🧭 compass +🏔️ snow-capped mountain +⛰️ mountain +🌋 volcano +🗻 mount fuji +🏕️ camping +🏖️ beach with umbrella +🏜️ desert +🏝️ desert island +🏞️ national park +🏟️ stadium +🏛️ classical building +🏗️ building construction +🧱 brick +🪨 rock +🪵 wood +🛖 hut +🏘️ houses +🏚️ derelict house +🏠 house +🏡 house with garden +🏢 office building +🏣 Japanese post office +🏤 post office +🏥 hospital +🏦 bank +🏨 hotel +🏩 love hotel +🏪 convenience store +🏫 school +🏬 department store +🏭 factory +🏯 Japanese castle +🏰 castle +💒 wedding +🗼 Tokyo tower +🗽 Statue of Liberty +⛪ church +🕌 mosque +🛕 hindu temple +🕍 synagogue +⛩️ shinto shrine +🕋 kaaba +⛲ fountain +⛺ tent +🌁 foggy +🌃 night with stars +🏙️ cityscape +🌄 sunrise over mountains +🌅 sunrise +🌆 cityscape at dusk +🌇 sunset +🌉 bridge at night +♨️ hot springs +🎠 carousel horse +🛝 playground slide +🎡 ferris wheel +🎢 roller coaster +💈 barber pole +🎪 circus tent +🚂 locomotive +🚃 railway car +🚄 high-speed train +🚅 bullet train +🚆 train +🚇 metro +🚈 light rail +🚉 station +🚊 tram +🚝 monorail +🚞 mountain railway +🚋 tram car +🚌 bus +🚍 oncoming bus +🚎 trolleybus +🚐 minibus +🚑 ambulance +🚒 fire engine +🚓 police car +🚔 oncoming police car +🚕 taxi +🚖 oncoming taxi +🚗 automobile +🚘 oncoming automobile +🚙 sport utility vehicle +🛻 pickup truck +🚚 delivery truck +🚛 articulated lorry +🚜 tractor +🏎️ racing car +🏍️ motorcycle +🛵 motor scooter +🦽 manual wheelchair +🦼 motorized wheelchair +🛺 auto rickshaw +🚲 bicycle +🛴 kick scooter +🛹 skateboard +🛼 roller skate +🚏 bus stop +🛣️ motorway +🛤️ railway track +🛢️ oil drum +⛽ fuel pump +🛞 wheel +🚨 police car light +🚥 horizontal traffic light +🚦 vertical traffic light +🛑 stop sign +🚧 construction +⚓ anchor +🛟 ring buoy +⛵ sailboat +🛶 canoe +🚤 speedboat +🛳️ passenger ship +⛴️ ferry +🛥️ motor boat +🚢 ship +✈️ airplane +🛩️ small airplane +🛫 airplane departure +🛬 airplane arrival +🪂 parachute +💺 seat +🚁 helicopter +🚟 suspension railway +🚠 mountain cableway +🚡 aerial tramway +🛰️ satellite +🚀 rocket +🛸 flying saucer +🛎️ bellhop bell +🧳 luggage +⌛ hourglass done +⏳ hourglass not done +⌚ watch +⏰ alarm clock +⏱️ stopwatch +⏲️ timer clock +🕰️ mantelpiece clock +🕛 twelve o’clock +🕧 twelve-thirty +🕐 one o’clock +🕜 one-thirty +🕑 two o’clock +🕝 two-thirty +🕒 three o’clock +🕞 three-thirty +🕓 four o’clock +🕟 four-thirty +🕔 five o’clock +🕠 five-thirty +🕕 six o’clock +🕡 six-thirty +🕖 seven o’clock +🕢 seven-thirty +🕗 eight o’clock +🕣 eight-thirty +🕘 nine o’clock +🕤 nine-thirty +🕙 ten o’clock +🕥 ten-thirty +🕚 eleven o’clock +🕦 eleven-thirty +🌑 new moon +🌒 waxing crescent moon +🌓 first quarter moon +🌔 waxing gibbous moon +🌕 full moon +🌖 waning gibbous moon +🌗 last quarter moon +🌘 waning crescent moon +🌙 crescent moon +🌚 new moon face +🌛 first quarter moon face +🌜 last quarter moon face +🌡️ thermometer +☀️ sun +🌝 full moon face +🌞 sun with face +🪐 ringed planet +⭐ star +🌟 glowing star +🌠 shooting star +🌌 milky way +☁️ cloud +⛅ sun behind cloud +⛈️ cloud with lightning and rain +🌤️ sun behind small cloud +🌥️ sun behind large cloud +🌦️ sun behind rain cloud +🌧️ cloud with rain +🌨️ cloud with snow +🌩️ cloud with lightning +🌪️ tornado +🌫️ fog +🌬️ wind face +🌀 cyclone +🌈 rainbow +🌂 closed umbrella +☂️ umbrella +☔ umbrella with rain drops +⛱️ umbrella on ground +⚡ high voltage +❄️ snowflake +☃️ snowman +⛄ snowman without snow +☄️ comet +🔥 fire +💧 droplet +🌊 water wave +🎃 jack-o-lantern +🎄 Christmas tree +🎆 fireworks +🎇 sparkler +🧨 firecracker +✨ sparkles +🎈 balloon +🎉 party popper +🎊 confetti ball +🎋 tanabata tree +🎍 pine decoration +🎎 Japanese dolls +🎏 carp streamer +🎐 wind chime +🎑 moon viewing ceremony +🧧 red envelope +🎀 ribbon +🎁 wrapped gift +🎗️ reminder ribbon +🎟️ admission tickets +🎫 ticket +🎖️ military medal +🏆 trophy +🏅 sports medal +🥇 1st place medal +🥈 2nd place medal +🥉 3rd place medal +⚽ soccer ball +⚾ baseball +🥎 softball +🏀 basketball +🏐 volleyball +🏈 american football +🏉 rugby football +🎾 tennis +🥏 flying disc +🎳 bowling +🏏 cricket game +🏑 field hockey +🏒 ice hockey +🥍 lacrosse +🏓 ping pong +🏸 badminton +🥊 boxing glove +🥋 martial arts uniform +🥅 goal net +⛳ flag in hole +⛸️ ice skate +🎣 fishing pole +🤿 diving mask +🎽 running shirt +🎿 skis +🛷 sled +🥌 curling stone +🎯 bullseye +🪀 yo-yo +🪁 kite +🎱 pool 8 ball +🔮 crystal ball +🪄 magic wand +🧿 nazar amulet +🪬 hamsa +🎮 video game +🕹️ joystick +🎰 slot machine +🎲 game die +🧩 puzzle piece +🧸 teddy bear +🪅 piñata +🪩 mirror ball +🪆 nesting dolls +♠️ spade suit +♥️ heart suit +♦️ diamond suit +♣️ club suit +♟️ chess pawn +🃏 joker +🀄 mahjong red dragon +🎴 flower playing cards +🎭 performing arts +🖼️ framed picture +🎨 artist palette +🧵 thread +🪡 sewing needle +🧶 yarn +🪢 knot +👓 glasses +🕶️ sunglasses +🥽 goggles +🥼 lab coat +🦺 safety vest +👔 necktie +👕 t-shirt +👖 jeans +🧣 scarf +🧤 gloves +🧥 coat +🧦 socks +👗 dress +👘 kimono +🥻 sari +🩱 one-piece swimsuit +🩲 briefs +🩳 shorts +👙 bikini +👚 woman’s clothes +👛 purse +👜 handbag +👝 clutch bag +🛍️ shopping bags +🎒 backpack +🩴 thong sandal +👞 man’s shoe +👟 running shoe +🥾 hiking boot +🥿 flat shoe +👠 high-heeled shoe +👡 woman’s sandal +🩰 ballet shoes +👢 woman’s boot +👑 crown +👒 woman’s hat +🎩 top hat +🎓 graduation cap +🧢 billed cap +🪖 military helmet +⛑️ rescue worker’s helmet +📿 prayer beads +💄 lipstick +💍 ring +💎 gem stone +🔇 muted speaker +🔈 speaker low volume +🔉 speaker medium volume +🔊 speaker high volume +📢 loudspeaker +📣 megaphone +📯 postal horn +🔔 bell +🔕 bell with slash +🎼 musical score +🎵 musical note +🎶 musical notes +🎙️ studio microphone +🎚️ level slider +🎛️ control knobs +🎤 microphone +🎧 headphone +📻 radio +🎷 saxophone +🪗 accordion +🎸 guitar +🎹 musical keyboard +🎺 trumpet +🎻 violin +🪕 banjo +🥁 drum +🪘 long drum +📱 mobile phone +📲 mobile phone with arrow +☎️ telephone +📞 telephone receiver +📟 pager +📠 fax machine +🔋 battery +🪫 low battery +🔌 electric plug +💻 laptop +🖥️ desktop computer +🖨️ printer +⌨️ keyboard +🖱️ computer mouse +🖲️ trackball +💽 computer disk +💾 floppy disk +💿 optical disk +📀 dvd +🧮 abacus +🎥 movie camera +🎞️ film frames +📽️ film projector +🎬 clapper board +📺 television +📷 camera +📸 camera with flash +📹 video camera +📼 videocassette +🔍 magnifying glass tilted left +🔎 magnifying glass tilted right +🕯️ candle +💡 light bulb +🔦 flashlight +🏮 red paper lantern +🪔 diya lamp +📔 notebook with decorative cover +📕 closed book +📖 open book +📗 green book +📘 blue book +📙 orange book +📚 books +📓 notebook +📒 ledger +📃 page with curl +📜 scroll +📄 page facing up +📰 newspaper +🗞️ rolled-up newspaper +📑 bookmark tabs +🔖 bookmark +🏷️ label +💰 money bag +🪙 coin +💴 yen banknote +💵 dollar banknote +💶 euro banknote +💷 pound banknote +💸 money with wings +💳 credit card +🧾 receipt +💹 chart increasing with yen +✉️ envelope +📧 e-mail +📨 incoming envelope +📩 envelope with arrow +📤 outbox tray +📥 inbox tray +📦 package +📫 closed mailbox with raised flag +📪 closed mailbox with lowered flag +📬 open mailbox with raised flag +📭 open mailbox with lowered flag +📮 postbox +🗳️ ballot box with ballot +✏️ pencil +✒️ black nib +🖋️ fountain pen +🖊️ pen +🖌️ paintbrush +🖍️ crayon +📝 memo +💼 briefcase +📁 file folder +📂 open file folder +🗂️ card index dividers +📅 calendar +📆 tear-off calendar +🗒️ spiral notepad +🗓️ spiral calendar +📇 card index +📈 chart increasing +📉 chart decreasing +📊 bar chart +📋 clipboard +📌 pushpin +📍 round pushpin +📎 paperclip +🖇️ linked paperclips +📏 straight ruler +📐 triangular ruler +✂️ scissors +🗃️ card file box +🗄️ file cabinet +🗑️ wastebasket +🔒 locked +🔓 unlocked +🔏 locked with pen +🔐 locked with key +🔑 key +🗝️ old key +🔨 hammer +🪓 axe +⛏️ pick +⚒️ hammer and pick +🛠️ hammer and wrench +🗡️ dagger +⚔️ crossed swords +🔫 water pistol +🪃 boomerang +🏹 bow and arrow +🛡️ shield +🪚 carpentry saw +🔧 wrench +🪛 screwdriver +🔩 nut and bolt +⚙️ gear +🗜️ clamp +⚖️ balance scale +🦯 white cane +🔗 link +⛓️ chains +🪝 hook +🧰 toolbox +🧲 magnet +🪜 ladder +⚗️ alembic +🧪 test tube +🧫 petri dish +🧬 dna +🔬 microscope +🔭 telescope +📡 satellite antenna +💉 syringe +🩸 drop of blood +💊 pill +🩹 adhesive bandage +🩼 crutch +🩺 stethoscope +🩻 x-ray +🚪 door +🛗 elevator +🪞 mirror +🪟 window +🛏️ bed +🛋️ couch and lamp +🪑 chair +🚽 toilet +🪠 plunger +🚿 shower +🛁 bathtub +🪤 mouse trap +🪒 razor +🧴 lotion bottle +🧷 safety pin +🧹 broom +🧺 basket +🧻 roll of paper +🪣 bucket +🧼 soap +🫧 bubbles +🪥 toothbrush +🧽 sponge +🧯 fire extinguisher +🛒 shopping cart +🚬 cigarette +⚰️ coffin +🪦 headstone +⚱️ funeral urn +🗿 moai +🪧 placard +🪪 identification card +🏧 ATM sign +🚮 litter in bin sign +🚰 potable water +♿ wheelchair symbol +🚹 men’s room +🚺 women’s room +🚻 restroom +🚼 baby symbol +🚾 water closet +🛂 passport control +🛃 customs +🛄 baggage claim +🛅 left luggage +⚠️ warning +🚸 children crossing +⛔ no entry +🚫 prohibited +🚳 no bicycles +🚭 no smoking +🚯 no littering +🚱 non-potable water +🚷 no pedestrians +📵 no mobile phones +🔞 no one under eighteen +☢️ radioactive +☣️ biohazard +⬆️ up arrow +↗️ up-right arrow +➡️ right arrow +↘️ down-right arrow +⬇️ down arrow +↙️ down-left arrow +⬅️ left arrow +↖️ up-left arrow +↕️ up-down arrow +↔️ left-right arrow +↩️ right arrow curving left +↪️ left arrow curving right +⤴️ right arrow curving up +⤵️ right arrow curving down +🔃 clockwise vertical arrows +🔄 counterclockwise arrows button +🔙 BACK arrow +🔚 END arrow +🔛 ON! arrow +🔜 SOON arrow +🔝 TOP arrow +🛐 place of worship +⚛️ atom symbol +🕉️ om +✡️ star of David +☸️ wheel of dharma +☯️ yin yang +✝️ latin cross +☦️ orthodox cross +☪️ star and crescent +☮️ peace symbol +🕎 menorah +🔯 dotted six-pointed star +♈ Aries +♉ Taurus +♊ Gemini +♋ Cancer +♌ Leo +♍ Virgo +♎ Libra +♏ Scorpio +♐ Sagittarius +♑ Capricorn +♒ Aquarius +♓ Pisces +⛎ Ophiuchus +🔀 shuffle tracks button +🔁 repeat button +🔂 repeat single button +▶️ play button +⏩ fast-forward button +⏭️ next track button +⏯️ play or pause button +◀️ reverse button +⏪ fast reverse button +⏮️ last track button +🔼 upwards button +⏫ fast up button +🔽 downwards button +⏬ fast down button +⏸️ pause button +⏹️ stop button +⏺️ record button +⏏️ eject button +🎦 cinema +🔅 dim button +🔆 bright button +📶 antenna bars +📳 vibration mode +📴 mobile phone off +♀️ female sign +♂️ male sign +⚧️ transgender symbol +✖️ multiply +➕ plus +➖ minus +➗ divide +🟰 heavy equals sign +♾️ infinity +‼️ double exclamation mark +⁉️ exclamation question mark +❓ red question mark +❔ white question mark +❕ white exclamation mark +❗ red exclamation mark +〰️ wavy dash +💱 currency exchange +💲 heavy dollar sign +⚕️ medical symbol +♻️ recycling symbol +⚜️ fleur-de-lis +🔱 trident emblem +📛 name badge +🔰 Japanese symbol for beginner +⭕ hollow red circle +✅ check mark button +☑️ check box with check +✔️ check mark +❌ cross mark +❎ cross mark button +➰ curly loop +➿ double curly loop +〽️ part alternation mark +✳️ eight-spoked asterisk +✴️ eight-pointed star +❇️ sparkle +©️ copyright +®️ registered +™️ trade mark +#️⃣ keycap: # +*️⃣ keycap: * +0️⃣ keycap: 0 +1️⃣ keycap: 1 +2️⃣ keycap: 2 +3️⃣ keycap: 3 +4️⃣ keycap: 4 +5️⃣ keycap: 5 +6️⃣ keycap: 6 +7️⃣ keycap: 7 +8️⃣ keycap: 8 +9️⃣ keycap: 9 +🔟 keycap: 10 +🔠 input latin uppercase +🔡 input latin lowercase +🔢 input numbers +🔣 input symbols +🔤 input latin letters +🅰️ A button (blood type) +🆎 AB button (blood type) +🅱️ B button (blood type) +🆑 CL button +🆒 COOL button +🆓 FREE button +ℹ️ information +🆔 ID button +Ⓜ️ circled M +🆕 NEW button +🆖 NG button +🅾️ O button (blood type) +🆗 OK button +🅿️ P button +🆘 SOS button +🆙 UP! button +🆚 VS button +🈁 Japanese “here” button +🈂️ Japanese “service charge” button +🈷️ Japanese “monthly amount” button +🈶 Japanese “not free of charge” button +🈯 Japanese “reserved” button +🉐 Japanese “bargain” button +🈹 Japanese “discount” button +🈚 Japanese “free of charge” button +🈲 Japanese “prohibited” button +🉑 Japanese “acceptable” button +🈸 Japanese “application” button +🈴 Japanese “passing grade” button +🈳 Japanese “vacancy” button +㊗️ Japanese “congratulations” button +㊙️ Japanese “secret” button +🈺 Japanese “open for business” button +🈵 Japanese “no vacancy” button +🔴 red circle +🟠 orange circle +🟡 yellow circle +🟢 green circle +🔵 blue circle +🟣 purple circle +🟤 brown circle +⚫ black circle +⚪ white circle +🟥 red square +🟧 orange square +🟨 yellow square +🟩 green square +🟦 blue square +🟪 purple square +🟫 brown square +⬛ black large square +⬜ white large square +◼️ black medium square +◻️ white medium square +◾ black medium-small square +◽ white medium-small square +▪️ black small square +▫️ white small square +🔶 large orange diamond +🔷 large blue diamond +🔸 small orange diamond +🔹 small blue diamond +🔺 red triangle pointed up +🔻 red triangle pointed down +💠 diamond with a dot +🔘 radio button +🔳 white square button +🔲 black square button +🏁 chequered flag +🚩 triangular flag +🎌 crossed flags +🏴 black flag +🏳️ white flag +🇦🇨 flag: Ascension Island +🇦🇩 flag: Andorra +🇦🇪 flag: United Arab Emirates +🇦🇫 flag: Afghanistan +🇦🇬 flag: Antigua & Barbuda +🇦🇮 flag: Anguilla +🇦🇱 flag: Albania +🇦🇲 flag: Armenia +🇦🇴 flag: Angola +🇦🇶 flag: Antarctica +🇦🇷 flag: Argentina +🇦🇸 flag: American Samoa +🇦🇹 flag: Austria +🇦🇺 flag: Australia +🇦🇼 flag: Aruba +🇦🇽 flag: Åland Islands +🇦🇿 flag: Azerbaijan +🇧🇦 flag: Bosnia & Herzegovina +🇧🇧 flag: Barbados +🇧🇩 flag: Bangladesh +🇧🇪 flag: Belgium +🇧🇫 flag: Burkina Faso +🇧🇬 flag: Bulgaria +🇧🇭 flag: Bahrain +🇧🇮 flag: Burundi +🇧🇯 flag: Benin +🇧🇱 flag: St. Barthélemy +🇧🇲 flag: Bermuda +🇧🇳 flag: Brunei +🇧🇴 flag: Bolivia +🇧🇶 flag: Caribbean Netherlands +🇧🇷 flag: Brazil +🇧🇸 flag: Bahamas +🇧🇹 flag: Bhutan +🇧🇻 flag: Bouvet Island +🇧🇼 flag: Botswana +🇧🇾 flag: Belarus +🇧🇿 flag: Belize +🇨🇦 flag: Canada +🇨🇨 flag: Cocos (Keeling) Islands +🇨🇩 flag: Congo - Kinshasa +🇨🇫 flag: Central African Republic +🇨🇬 flag: Congo - Brazzaville +🇨🇭 flag: Switzerland +🇨🇮 flag: Côte d’Ivoire +🇨🇰 flag: Cook Islands +🇨🇱 flag: Chile +🇨🇲 flag: Cameroon +🇨🇳 flag: China +🇨🇴 flag: Colombia +🇨🇵 flag: Clipperton Island +🇨🇷 flag: Costa Rica +🇨🇺 flag: Cuba +🇨🇻 flag: Cape Verde +🇨🇼 flag: Curaçao +🇨🇽 flag: Christmas Island +🇨🇾 flag: Cyprus +🇨🇿 flag: Czechia +🇩🇪 flag: Germany +🇩🇬 flag: Diego Garcia +🇩🇯 flag: Djibouti +🇩🇰 flag: Denmark +🇩🇲 flag: Dominica +🇩🇴 flag: Dominican Republic +🇩🇿 flag: Algeria +🇪🇦 flag: Ceuta & Melilla +🇪🇨 flag: Ecuador +🇪🇪 flag: Estonia +🇪🇬 flag: Egypt +🇪🇭 flag: Western Sahara +🇪🇷 flag: Eritrea +🇪🇸 flag: Spain +🇪🇹 flag: Ethiopia +🇪🇺 flag: European Union +🇫🇮 flag: Finland +🇫🇯 flag: Fiji +🇫🇰 flag: Falkland Islands +🇫🇲 flag: Micronesia +🇫🇴 flag: Faroe Islands +🇫🇷 flag: France +🇬🇦 flag: Gabon +🇬🇧 flag: United Kingdom +🇬🇩 flag: Grenada +🇬🇪 flag: Georgia +🇬🇫 flag: French Guiana +🇬🇬 flag: Guernsey +🇬🇭 flag: Ghana +🇬🇮 flag: Gibraltar +🇬🇱 flag: Greenland +🇬🇲 flag: Gambia +🇬🇳 flag: Guinea +🇬🇵 flag: Guadeloupe +🇬🇶 flag: Equatorial Guinea +🇬🇷 flag: Greece +🇬🇸 flag: South Georgia & South Sandwich Islands +🇬🇹 flag: Guatemala +🇬🇺 flag: Guam +🇬🇼 flag: Guinea-Bissau +🇬🇾 flag: Guyana +🇭🇰 flag: Hong Kong SAR China +🇭🇲 flag: Heard & McDonald Islands +🇭🇳 flag: Honduras +🇭🇷 flag: Croatia +🇭🇹 flag: Haiti +🇭🇺 flag: Hungary +🇮🇨 flag: Canary Islands +🇮🇩 flag: Indonesia +🇮🇪 flag: Ireland +🇮🇱 flag: Israel +🇮🇲 flag: Isle of Man +🇮🇳 flag: India +🇮🇴 flag: British Indian Ocean Territory +🇮🇶 flag: Iraq +🇮🇷 flag: Iran +🇮🇸 flag: Iceland +🇮🇹 flag: Italy +🇯🇪 flag: Jersey +🇯🇲 flag: Jamaica +🇯🇴 flag: Jordan +🇯🇵 flag: Japan +🇰🇪 flag: Kenya +🇰🇬 flag: Kyrgyzstan +🇰🇭 flag: Cambodia +🇰🇮 flag: Kiribati +🇰🇲 flag: Comoros +🇰🇳 flag: St. Kitts & Nevis +🇰🇵 flag: North Korea +🇰🇷 flag: South Korea +🇰🇼 flag: Kuwait +🇰🇾 flag: Cayman Islands +🇰🇿 flag: Kazakhstan +🇱🇦 flag: Laos +🇱🇧 flag: Lebanon +🇱🇨 flag: St. Lucia +🇱🇮 flag: Liechtenstein +🇱🇰 flag: Sri Lanka +🇱🇷 flag: Liberia +🇱🇸 flag: Lesotho +🇱🇹 flag: Lithuania +🇱🇺 flag: Luxembourg +🇱🇻 flag: Latvia +🇱🇾 flag: Libya +🇲🇦 flag: Morocco +🇲🇨 flag: Monaco +🇲🇩 flag: Moldova +🇲🇪 flag: Montenegro +🇲🇫 flag: St. Martin +🇲🇬 flag: Madagascar +🇲🇭 flag: Marshall Islands +🇲🇰 flag: North Macedonia +🇲🇱 flag: Mali +🇲🇲 flag: Myanmar (Burma) +🇲🇳 flag: Mongolia +🇲🇴 flag: Macao SAR China +🇲🇵 flag: Northern Mariana Islands +🇲🇶 flag: Martinique +🇲🇷 flag: Mauritania +🇲🇸 flag: Montserrat +🇲🇹 flag: Malta +🇲🇺 flag: Mauritius +🇲🇻 flag: Maldives +🇲🇼 flag: Malawi +🇲🇽 flag: Mexico +🇲🇾 flag: Malaysia +🇲🇿 flag: Mozambique +🇳🇦 flag: Namibia +🇳🇨 flag: New Caledonia +🇳🇪 flag: Niger +🇳🇫 flag: Norfolk Island +🇳🇬 flag: Nigeria +🇳🇮 flag: Nicaragua +🇳🇱 flag: Netherlands +🇳🇴 flag: Norway +🇳🇵 flag: Nepal +🇳🇷 flag: Nauru +🇳🇺 flag: Niue +🇳🇿 flag: New Zealand +🇴🇲 flag: Oman +🇵🇦 flag: Panama +🇵🇪 flag: Peru +🇵🇫 flag: French Polynesia +🇵🇬 flag: Papua New Guinea +🇵🇭 flag: Philippines +🇵🇰 flag: Pakistan +🇵🇱 flag: Poland +🇵🇲 flag: St. Pierre & Miquelon +🇵🇳 flag: Pitcairn Islands +🇵🇷 flag: Puerto Rico +🇵🇸 flag: Palestinian Territories +🇵🇹 flag: Portugal +🇵🇼 flag: Palau +🇵🇾 flag: Paraguay +🇶🇦 flag: Qatar +🇷🇪 flag: Réunion +🇷🇴 flag: Romania +🇷🇸 flag: Serbia +🇷🇺 flag: Russia +🇷🇼 flag: Rwanda +🇸🇦 flag: Saudi Arabia +🇸🇧 flag: Solomon Islands +🇸🇨 flag: Seychelles +🇸🇩 flag: Sudan +🇸🇪 flag: Sweden +🇸🇬 flag: Singapore +🇸🇭 flag: St. Helena +🇸🇮 flag: Slovenia +🇸🇯 flag: Svalbard & Jan Mayen +🇸🇰 flag: Slovakia +🇸🇱 flag: Sierra Leone +🇸🇲 flag: San Marino +🇸🇳 flag: Senegal +🇸🇴 flag: Somalia +🇸🇷 flag: Suriname +🇸🇸 flag: South Sudan +🇸🇹 flag: São Tomé & Príncipe +🇸🇻 flag: El Salvador +🇸🇽 flag: Sint Maarten +🇸🇾 flag: Syria +🇸🇿 flag: Eswatini +🇹🇦 flag: Tristan da Cunha +🇹🇨 flag: Turks & Caicos Islands +🇹🇩 flag: Chad +🇹🇫 flag: French Southern Territories +🇹🇬 flag: Togo +🇹🇭 flag: Thailand +🇹🇯 flag: Tajikistan +🇹🇰 flag: Tokelau +🇹🇱 flag: Timor-Leste +🇹🇲 flag: Turkmenistan +🇹🇳 flag: Tunisia +🇹🇴 flag: Tonga +🇹🇷 flag: Turkey +🇹🇹 flag: Trinidad & Tobago +🇹🇻 flag: Tuvalu +🇹🇼 flag: Taiwan +🇹🇿 flag: Tanzania +🇺🇦 flag: Ukraine +🇺🇬 flag: Uganda +🇺🇲 flag: U.S. Outlying Islands +🇺🇳 flag: United Nations +🇺🇸 flag: United States +🇺🇾 flag: Uruguay +🇺🇿 flag: Uzbekistan +🇻🇦 flag: Vatican City +🇻🇨 flag: St. Vincent & Grenadines +🇻🇪 flag: Venezuela +🇻🇬 flag: British Virgin Islands +🇻🇮 flag: U.S. Virgin Islands +🇻🇳 flag: Vietnam +🇻🇺 flag: Vanuatu +🇼🇫 flag: Wallis & Futuna +🇼🇸 flag: Samoa +🇽🇰 flag: Kosovo +🇾🇪 flag: Yemen +🇾🇹 flag: Mayotte +🇿🇦 flag: South Africa +🇿🇲 flag: Zambia +🇿🇼 flag: Zimbabwe +🏴󠁧󠁢󠁥󠁮󠁧󠁿 flag: England +🏴󠁧󠁢󠁳󠁣󠁴󠁿 flag: Scotland +🏴󠁧󠁢󠁷󠁬󠁳󠁿 flag: Wales diff --git a/.local/share/script-data/chars/glyps.txt b/.local/share/script-data/chars/glyps.txt new file mode 100644 index 0000000..8746bde --- /dev/null +++ b/.local/share/script-data/chars/glyps.txt @@ -0,0 +1 @@ +                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ⏻ ⭘ ⏽ ⏾ ⏼                                                                                                                          󰇉 󱛠 󱌨 󱌩 󱌪 󱌫 󰀃 󱔸 󱔹 󰀂 󰯡 󱔑 󱔺 󱔻 󰀄 󰀅 󰭐 󱡨 󱡩 󰭑 󰭒 󰭓 󰭔 󱡧 󱡪 󰀆 󰤴 󱀊 󰀇 󱋟 󱋠 󱂗 󱂘 󰀈 󰯢 󰪉 󰪊 󱃈 󰀉 󰭕 󰭖 󰭗 󱍰 󱍱 󰀊 󱌁 󰺛 󱟳 󰘱 󱍲 󰚼 󰿻 󰐠 󱉻 󰤶 󰾝 󰡉 󰭘 󰖵 󱨟 󰢙 󰯣 󱠕 󱠖 󰀋 󰯤 󱅞 󱥠 󱥡 󱅟 󰀍 󰫬 󰀎 󰣅 󱇾 󰗓 󰯥 󰀏 󰀐 󰠀 󱈊 󱈋 󰠃 󰳩 󰀑 󰯦 󰀒 󰯧 󰀓 󰀔 󰠁 󰭙 󰭚 󱔫 󱔬 󰀕 󰫭 󱨠 󱨡 󰀖 󰤵 󰘰 󱃉 󰀗 󰯨 󰪋 󰪌 󱓬 󱄭 󰀙 󰓋 󱤛 󱤜 󰳣 󱢘 󱢙 󱃊 󱌈 󱌊 󱌋 󱌉 󱪌 󰗋 󰻔 󱢚 󱢛 󰀚 󱤪 󱤫 󰀛 󰵃 󰶬 󱂙 󱑦 󰵄 󰯩 󰀜 󱀋 󰀝 󱡺 󱡻 󱡼 󱡽 󱡾 󰗔 󱡿 󱢀 󰀞 󱢁 󱢂 󱢃 󱢄 󰗕 󰡋 󰀠 󰞎 󰀡 󰞏 󱜞 󱜟 󰯪 󰀢 󰹱 󰹲 󰀣 󱗄 󱗅 󰀤 󰚎 󰀥 󰀦 󰀧 󰳤 󰀨 󱇭 󱇮 󰗖 󰚽 󰳥 󱒻 󱒾 󰀩 󰳦 󰝧 󰳧 󰀪 󱒺 󱒽 󱒼 󱒿 󱇎 󱇏 󰢚 󱃋 󱇃 󱥢 󱇂 󱇄 󱇅 󱇆 󱥣 󱇇 󰚾 󱢍 󱢎 󱉘 󰀫 󰫮 󰬈 󰯫 󰯬 󰯭 󰫯 󰬉 󰯮 󰯯 󰯰 󰫰 󰬊 󰯱 󰯲 󰯳 󰫱 󰬋 󰯴 󰯵 󰯶 󰫲 󰬌 󰯷 󰯸 󰯹 󰫳 󰬍 󰯺 󰯻 󰯼 󰫴 󰬎 󰯽 󰯾 󰯿 󰫵 󰬏 󰰀 󰰁 󰰂 󰫶 󰬐 󰰃 󰰄 󰰅 󰫷 󰬑 󰰆 󰰇 󰰈 󰫸 󰬒 󰰉 󰰊 󰰋 󰫹 󰬓 󰰌 󰰍 󰰎 󰫺 󰬔 󰰏 󰰐 󰰑 󰫻 󰬕 󰰒 󰰓 󰰔 󰫼 󰬖 󰰕 󰰖 󰰗 󰫽 󰬗 󰰘 󰰙 󰰚 󰫾 󰬘 󰰛 󰰜 󰰝 󰫿 󰬙 󰰞 󰰟 󰰠 󰬀 󰬚 󰰡 󰰢 󰰣 󰬁 󰬛 󰰤 󰰥 󰰦 󰬂 󰬜 󰰧 󰰨 󰰩 󰬃 󰬝 󰰪 󰰫 󰰬 󰬄 󰬞 󰰭 󰰮 󰰯 󰬅 󰬟 󰰰 󰰱 󰰲 󰬆 󰬠 󰰳 󰰴 󰰵 󰬇 󰬡 󰰶 󰰷 󰰸 󱌬 󱌭 󱌮 󱌯 󱌰 󱌷 󰀬 󱀌 󱀍 󱀎 󰗗 󰀯 󰳨 󰪍 󰀰 󱆵 󰀱 󰀲 󰵅 󰀴 󰤷 󰤸 󰤹 󰚲 󰚿 󰗘 󰪏 󰤺 󰪐 󱂚 󱄙 󰢛 󱀏 󱂛 󱉗 󰀵 󰀶 󰀸 󰀷 󰘲 󰘳 󰘴 󰘵 󰘶 󰀹 󰣆 󱃵 󱃶 󱃷 󱃸 󰲋 󰲌 󰙵 󱕷 󰂮 󰘙 󰶭 󰶮 󰘔 󱃹 󱃺 󰭠 󱕕 󱃻 󱃼 󰾞 󰾟 󰀻 󰵆 󰣇 󰀼 󱓽 󱓾 󱉙 󱉚 󱉛 󱉜 󱝋 󱝌 󱝍 󱝎 󱝏 󱝐 󱝑 󱝒 󱝓 󱝔 󱝕 󱝖 󱝗 󱝘 󱝙 󱝚 󱝛 󱝜 󱝝 󱝞 󱝟 󱝠 󱝡 󱝢 󱈎 󱝣 󱝤 󱝥 󱝦 󱝧 󱝨 󱝩 󱝪 󱝫 󱝬 󱝭 󱝮 󱝯 󱝰 󰿗 󰿖 󰀽 󰀾 󰀿 󰁀 󰁁 󰁂 󱥤 󱥥 󰦷 󰦸 󱦶 󱖖 󰁃 󱥦 󱥧 󰦹 󰦺 󱦷 󱖕 󰘕 󰁄 󰞒 󰡌 󰞓 󰞔 󰞕 󰡍 󰦻 󰦼 󰦽 󰦾 󰁅 󰜮 󰜯 󰜰 󰁇 󰁈 󰁉 󰦿 󰛀 󰳛 󰳜 󰁊 󰁋 󱞡 󱞢 󱞣 󱞤 󰁆 󱦳 󱖙 󰘖 󰁌 󰞖 󰡎 󰞗 󰞘 󰞙 󰡏 󱅛 󰁍 󰜱 󰜲 󰜳 󰁏 󰁐 󰁑 󰧀 󱞥 󱞦 󰛁 󰳝 󰳞 󰁒 󰁓 󰹳 󰹴 󰧁 󰁎 󱦱 󱖚 󱞧 󱞨 󱡀 󱠿 󰁔 󰜴 󰜵 󰜶 󰁖 󰁗 󰁘 󰧂 󱞩 󱞪 󰛂 󰳟 󰳠 󰁙 󰁚 󰁕 󱦰 󱖘 󱞫 󱞬 󰤻 󰤼 󰁛 󱥨 󱥩 󰧃 󰹵 󰹶 󰧄 󱦵 󱖓 󰁜 󱥪 󱥫 󰧅 󰹷 󰹸 󰧆 󱦴 󱖔 󱞭 󱞮 󱞯 󱞰 󱞱 󱞲 󱞳 󱞴 󱞵 󱞶 󱞷 󱞸 󱞹 󱞺 󱞻 󱞼 󰁝 󰜷 󰜸 󰜹 󰁟 󰁠 󰁡 󰧇 󰛃 󰳡 󰳢 󰹹 󰹺 󰧈 󰁢 󰁣 󱞽 󱞾 󱞿 󱟀 󰁞 󱦲 󱖗 󱅜 󰭛 󰨤 󰁤 󰛄 󱨧 󰁥 󰠄 󰵇 󰝨 󰹻 󰁦 󱫁 󱧄 󱫂 󱫃 󱫄 󱫅 󱡫 󱡬 󱡭 󰤽 󱆶 󰡐 󱍾 󰁨 󰁩 󰁪 󱧧 󰁫 󰸏 󰣈 󱡂 󰵈 󰵉 󱐎 󰵊 󰵋 󰵌 󰵍 󰵎 󰵏 󰵐 󰵑 󰵒 󰵓 󰵔 󰵕 󰵖 󰵗 󰵘 󰨥 󰁬 󰼹 󰼺 󱏠 󰚏 󰾠 󰹼 󰹽 󰁭 󰁮 󰭜 󰹾 󰹿 󰁯 󰻕 󰻖 󰶧 󰶨 󰶩 󰸍 󰸎 󰶪 󰡑 󰼻 󰵥 󰼼 󰼽 󰸐 󰸑 󰸒 󰸓 󱖋 󱖍 󱖎 󱖌 󰼾 󱠗 󰨦 󰧉 󰧊 󰰹 󰰺 󰶯 󰁰 󱙕 󰶰 󱙖 󱙗 󰺀 󰶱 󰶲 󰨧 󰨨 󰨩 󰁱 󱈶 󰁲 󰁳 󰭝 󰭞 󰁴 󱨨 󰡒 󰡓 󱗬 󱗭 󱆃 󰁶 󱣥 󱣦 󰁷 󱔣 󱔤 󱔥 󱔦 󱆁 󱔧 󱔨 󱔩 󱔪 󰁸 󰠆 󰰻 󰰼 󰭟 󱠘 󱠙 󰁹 󰁺 󰤾 󰁻 󰤿 󰁼 󰥀 󰁽 󰥁 󰁾 󰥂 󰁿 󰥃 󰂀 󰥄 󰂁 󰥅 󰂂 󰥆 󰂃 󰥇 󱃌 󱃍 󱟞 󱟟 󱟠 󱟡 󰥈 󰥉 󰂄 󰢜 󰂅 󰂆 󰂇 󰂈 󰢝 󰂉 󰢞 󰂊 󰂋 󱊦 󱊤 󱊥 󰢟 󰠇 󰠈 󰠉 󰠊 󰠋 󰠌 󰠍 󰠎 󰠏 󰠐 󰠑 󰠒 󱟢 󱟣 󱧥 󱧦 󱈏 󱈐 󱈑 󱊣 󱞜 󱞝 󱊡 󱊢 󱟤 󱟥 󰂌 󰂍 󱉝 󱉞 󰂎 󱟦 󱟧 󰂏 󰂐 󱟨 󱟩 󱠴 󱠵 󰂑 󰥊 󰂒 󰳪 󱈩 󱈪 󱈫 󱈬 󱈭 󱈮 󰚐 󱈯 󱈰 󱈱 󱈲 󱈳 󱈴 󰋣 󰿔 󰿓 󰢠 󰿒 󰿑 󰂙 󰿐 󰿛 󱁭 󱁮 󰾡 󰾢 󱏭 󱃎 󱓢 󰂘 󱌌 󰂚 󰵙 󰺁 󱅫 󰅸 󱏧 󱏨 󱇥 󱇦 󰵚 󰵛 󱨩 󱨪 󱏩 󱏪 󰂛 󰪑 󰂜 󰂝 󰪒 󱏫 󱏬 󰂞 󰂟 󰂠 󰪓 󰂡 󰧋 󰸔 󱂜 󱈵 󱢜 󱖴 󱗩 󰂣 󱄟 󱀐 󰭡 󰭢 󰂥 󰂦 󰂧 󱗆 󰂨 󰠓 󰂩 󰳫 󱠚 󰂫 󰂬 󱨫 󱨬 󱀑 󱨭 󱨮 󰂭 󰳬 󰂯 󰂰 󰂱 󰂲 󰂳 󰂴 󰂵 󰂶 󰂷 󰂸 󰶳 󰚑 󰛅 󰂹 󱧠 󰂺 󱎭 󱎮 󱙼 󱙽 󰘝 󱙾 󱙿 󱚀 󱚁 󱚂 󱚃 󱚄 󱚅 󱚆 󱚇 󱓳 󱓴 󱚈 󱚉 󱚊 󱚋 󰂢 󱚌 󱚍 󱛉 󱛊 󱨝 󱨞 󱁯 󰞚 󰞛 󱚎 󱚏 󱚐 󱚑 󰗙 󰪔 󰤋 󱚒 󰂻 󰐶 󰁧 󱚓 󱚔 󱚕 󰂽 󰂾 󰭣 󰗚 󱗖 󱓷 󰭤 󰺂 󰺃 󰗛 󰪕 󰫞 󱚖 󱚗 󱚘 󰪗 󰪖 󰓊 󱚙 󰺄 󰺅 󱚚 󱚛 󱚜 󱛈 󰂿 󰂼 󰃀 󱥬 󱥭 󰃁 󱍻 󰧌 󰧍 󰸕 󰸖 󰃂 󱍹 󰧎 󰧏 󰃃 󰃅 󰃄 󰃆 󱍺 󱉟 󰺆 󰺇 󰺈 󰺉 󰺊 󰺌 󰺍 󰺋 󱟹 󱟺 󰗜 󱃏 󰛆 󰃇 󰢡 󰃈 󰢢 󰃉 󰃊 󰃋 󰃌 󰢣 󰃍 󰢤 󰃎 󰃏 󰢥 󰃐 󰃑 󰢦 󰃒 󱁰 󱁱 󱍣 󱁲 󱄮 󱄯 󱄰 󱄱 󱄲 󱄳 󰡔 󱌐 󱡁 󰙸 󰊎 󰘗 󰋤 󰊩 󰃓 󰃔 󰃕 󰭊 󰘷 󰭥 󰧐 󰧑 󰳮 󰳯 󰘘 󰃖 󰳰 󰳱 󱪍 󱪎 󱪏 󱪐 󰃗 󱌞 󱃐 󱃑 󰃘 󰰽 󰪘 󰰾 󱟙 󱟚 󰨪 󰰿 󱙘 󱙙 󰠔 󰨫 󰱀 󰨬 󰱁 󰨭 󰱂 󰃙 󰱃 󱒔 󱙚 󱙛 󱒕 󰃚 󰃛 󰃜 󰃝 󰃞 󰃟 󰃠 󰃡 󰳲 󱜠 󱜡 󰃢 󰃣 󱝱 󱨍 󱠓 󱐕 󱐖 󰕸 󰃤 󰨮 󰨯 󰨰 󰶴 󱨯 󰬢 󰳳 󰃥 󰃦 󰬣 󱥮 󱥯 󰗝 󰣉 󱋧 󱌂 󰂗 󰃧 󰪙 󰞜 󰞝 󰣊 󰞞 󱤝 󱈒 󰼿 󰞟 󰞠 󱀒 󱀓 󱀔 󱖉 󱖊 󱢌 󱎔 󰃨 󰶵 󰃩 󰃪 󰃫 󱟰 󰃬 󰪚 󱖦 󰃭 󰻗 󰻘 󰨱 󱄴 󱄵 󰃮 󱁳 󰭦 󰃯 󰱄 󰃰 󱛡 󱢝 󱕻 󰢧 󱙬 󱢞 󰬤 󰧒 󰬥 󱙁 󱙂 󰵜 󰸗 󰸘 󰃱 󰃲 󰨲 󰭧 󰃳 󰚒 󰙹 󰭨 󰇡 󰈃 󰃴 󰱅 󰥌 󰧓 󱙭 󰺎 󰺏 󰃵 󰱆 󰃶 󱨰 󰨳 󰨴 󱨱 󱨲 󱨳 󱨴 󰻙 󰻚 󰃷 󰃸 󰃹 󰃺 󰃻 󰃼 󰃿 󰄀 󰣋 󰚓 󰭩 󱡱 󱡲 󰄁 󰭪 󱗙 󱗚 󰄂 󰄃 󰞡 󰣌 󰄄 󱨔 󱨕 󱦧 󱦨 󰞢 󰞣 󰞤 󰞥 󰗟 󱦿 󰵝 󰄅 󰻛 󰻜 󰄆 󰄇 󰸙 󰸚 󰄈 󰡊 󰄉 󰶶 󰶷 󰻝 󰜺 󱟒 󱟓 󰗢 󱥰 󱥱 󱥲 󱥳 󰄊 󰞦 󱙮 󰪛 󰄋 󱀕 󱀖 󱎲 󱎳 󰸛 󰄌 󰱇 󰱈 󱤉 󰵞 󱤊 󰵟 󱀗 󱤋 󱤌 󰾣 󱥴 󱀘 󱏌 󰄍 󰞧 󱀙 󰵠 󰵡 󰵢 󰭫 󱂝 󰭬 󱖵 󱘏 󰱉 󰞨 󰞩 󱆾 󰭭 󱔭 󱤍 󰱊 󰱋 󰱌 󰣍 󰭮 󰸜 󱓭 󰵣 󰞪 󰾤 󰾥 󰾦 󱡹 󱏍 󰽀 󰞫 󱤎 󰞬 󰱍 󰵤 󱀚 󰄎 󱀛 󱀜 󱡸 󱠔 󱓀 󰞭 󰭯 󰗒 󰶫 󰊣 󰛛 󰆎 󰺘 󰺙 󰺚 󰭰 󰭱 󰭲 󰭳 󰭴 󰭵 󱘀 󱘁 󱟱 󱟲 󱘂 󱘃 󰭶 󱇿 󱈀 󱘄 󱘅 󱁴 󱁵 󰭷 󰭸 󰘸 󰣎 󱢟 󰣏 󱀝 󰘹 󱢡 󱢢 󱢣 󱢤 󱢥 󱢦 󱢧 󱢨 󱢩 󱢪 󱢫 󱢬 󱢭 󰘺 󱢮 󱢯 󱢰 󱢱 󰣑 󱢲 󰛇 󰄏 󰄐 󰵦 󰱎 󰵧 󱗪 󱣠 󰵨 󰙫 󰄑 󰄒 󰵩 󱗫 󰄓 󰄔 󰄕 󱓮 󱪑 󱡜 󱓪 󱓫 󰶸 󱉠 󰄖 󱉡 󰪜 󰳴 󱉢 󱪒 󰧔 󰄘 󱀞 󱝉 󰄙 󰸝 󰞊 󰀟 󰄚 󰄛 󰞮 󱡟 󱞗 󱞘 󰝩 󱣝 󱣞 󱟇 󰄜 󰧕 󱧅 󰄞 󱎗 󱟽 󰥑 󰄟 󰽁 󰥎 󰄡 󰄢 󰥏 󱠺 󰣓 󱃒 󰺐 󱋘 󰥐 󱀟 󰥍 󰨵 󰄣 󰥒 󰣒 󰠕 󱄚 󰄤 󱆈 󰽈 󰄥 󱞓 󰱏 󰄦 󰄧 󰺑 󰄨 󰝪 󰱐 󰾧 󱕍 󱕎 󱕏 󰗣 󰞯 󰞰 󰙬 󰄩 󰄪 󰝫 󰞱 󰣔 󱈓 󰄫 󱎀 󱇟 󱇠 󰺒 󰙭 󰙮 󰺓 󱖶 󰺔 󱤘 󰭹 󰭺 󱋉 󱐐 󱐓 󰻞 󱐏 󱐒 󰭻 󱋊 󱜸 󱜹 󱐑 󱐔 󱋑 󱋒 󰄬 󰄭 󰸞 󰗠 󰗡 󰞑 󱝀 󰱓 󰱔 󰡕 󰸟 󰸠 󰸡 󰪝 󰄮 󱅶 󰄗 󰄯 󰄰 󱋬 󱋭 󰄱 󰡖 󰄲 󰄳 󰄴 󱤧 󰄵 󰄶 󰘻 󰘼 󰄷 󰄸 󰘽 󰘾 󰄹 󰱑 󰱒 󰄺 󱈂 󱈁 󱈃 󱊹 󱏮 󰭼 󰄻 󰡜 󰡗 󰡘 󰡙 󰡚 󰡛 󰄼 󰄽 󰄾 󰄿 󰅀 󰧖 󰧗 󰬦 󰬧 󰅁 󰧘 󰧙 󰬨 󰬩 󰅂 󰧚 󰧛 󰬪 󰬫 󰶹 󰶺 󰶻 󰶼 󰅃 󰧜 󰧝 󰬬 󰬭 󱟪 󱟫 󰞲 󱟬 󰞳 󱟭 󰞴 󱟮 󱑧 󱟯 󰘚 󰅄 󱆉 󱐛 󱗜 󱗝 󰺕 󰣕 󰺖 󱎕 󱎖 󰧞 󰬸 󰚕 󱃓 󱡓 󰪞 󰪟 󰪠 󰪡 󰪢 󰪣 󰪤 󰪥 󰧟 󰸢 󰅆 󰨶 󰨷 󰅇 󰅈 󰱕 󰅉 󰳷 󰅊 󰱖 󰅋 󰳸 󰳹 󰳺 󰱗 󰱘 󰅎 󱉣 󱉤 󰢨 󱛢 󱛣 󱓥 󱓦 󱉥 󱉦 󰛈 󱄗 󱃔 󱃕 󱘘 󱘙 󱉧 󱉨 󱘚 󱘛 󰅌 󰱙 󱉩 󱉪 󰱚 󰝑 󱌟 󰡝 󰡞 󱘜 󱘝 󱘞 󱘟 󰅍 󱣹 󱣺 󱉫 󱉬 󱘠 󱘡 󰨸 󰱛 󰱜 󱘢 󱘣 󰅏 󰥔 󰥕 󰗎 󰾨 󰾩 󰺗 󱦺 󱦻 󰅑 󰅒 󰅓 󱡣 󱡤 󰅔 󰅐 󱡡 󱡢 󱡥 󱡦 󰅕 󱑆 󱑒 󱑉 󱑕 󱑃 󱑏 󱑂 󱑎 󱑇 󱑓 󱐿 󱑋 󱑅 󱑑 󱑄 󱑐 󱑈 󱑔 󱑁 󱑍 󱑊 󱑖 󱑀 󱑌 󰅖 󰅗 󰱝 󰱞 󰅘 󰅙 󰘪 󰢃 󰅚 󰅛 󰱟 󰅜 󰅝 󰛉 󱎘 󰅞 󰶽 󰅟 󰧠 󰞵 󰅠 󱋌 󰅡 󰅢 󰭽 󱇱 󱇲 󰅤 󰅣 󱨵 󱨶 󰅥 󰅦 󰨹 󰔪 󰥖 󰥗 󰘿 󱋖 󰞶 󰅧 󰭾 󰠖 󱀠 󱨷 󱂞 󰅨 󰅩 󱃖 󰅪 󰅫 󰅬 󰅭 󰘦 󰅮 󰅯 󰅰 󰅱 󰅲 󱃗 󰅳 󰅴 󰚔 󰅵 󰅶 󱂟 󱤱 󱤲 󱠛 󰾪 󰾫 󰛊 󰅷 󱌎 󰭿 󰒓 󰒔 󱇝 󱇞 󱏎 󱏏 󰢻 󱤳 󱤴 󱤵 󱤶 󱑞 󱑟 󱤷 󱤸 󱑠 󱑡 󱁛 󱁜 󰣖 󰙀 󰪦 󰪧 󰅹 󰸣 󰸫 󰸤 󰸥 󰸦 󰅺 󰅻 󰅼 󰅽 󰅾 󰧡 󰧢 󰧣 󰧤 󱖮 󱖯 󰅿 󰆀 󱆿 󱋄 󰨺 󰨻 󱖰 󱖱 󱗟 󱗠 󰡟 󰆁 󱗡 󱗢 󰆂 󰧥 󰆃 󰆄 󰆅 󰠗 󰆆 󱀡 󱀢 󰗞 󰆇 󰨼 󰨽 󰆈 󰡠 󰡡 󰆉 󰆊 󱒒 󱢳 󱒓 󰆋 󰮀 󰮁 󰆌 󱎂 󱨸 󱥌 󱥍 󱘖 󰆍 󰞷 󰢩 󰱠 󱃘 󰵪 󰌡 󰐈 󰛋 󰖸 󰨾 󰨿 󰩀 󰆏 󰆐 󰆑 󰆒 󰆓 󰽂 󰽃 󰆔 󰽄 󱣪 󱣫 󱑛 󱑜 󰳻 󰳼 󰸧 󰸨 󱙃 󱙄 󰠘 󰘛 󰬮 󰆕 󰆖 󰆗 󰮂 󰮃 󰆘 󱛐 󱛑 󱛒 󱛓 󱛤 󱛥 󱛔 󱛕 󱛦 󱛧 󱛨 󱛩 󱛚 󱛛 󱛪 󱛫 󱛞 󱛖 󱛗 󱛬 󱛭 󱛘 󱛙 󱛜 󱛝 󰏈 󱤹 󰗦 󰥘 󰞸 󱏯 󱑹 󰆙 󱠜 󱠝 󰆚 󱣼 󰻟 󰻠 󱦋 󱦑 󰡢 󰙴 󰵫 󰿯 󱏐 󱏑 󱤏 󱤐 󰻡 󰻢 󱟗 󱟘 󱤑 󱤒 󱣧 󱣨 󰚨 󰶾 󰾬 󰾭 󰿰 󰆜 󰿱 󰗤 󰆛 󰿲 󰙶 󱙅 󱙆 󰿳 󰪨 󰾮 󰾯 󰿴 󰆝 󱙇 󱙈 󰿵 󰣗 󱙉 󱙊 󰠂 󰕺 󰕻 󰵬 󰵭 󰆞 󰆟 󰆠 󰆡 󰚖 󰆢 󰥓 󰳭 󰳵 󰳶 󰆣 󰆤 󰽅 󱄶 󱥵 󰆥 󱟜 󱟝 󱇐 󰥙 󰬯 󰆦 󱐜 󱐝 󰆧 󰮄 󰆨 󰆩 󰆪 󰗥 󱍽 󱌏 󰆫 󰽆 󰽇 󰥚 󰡣 󰡤 󰮅 󰆬 󰞺 󰞻 󰆭 󱌕 󱨹 󰆮 󰱡 󰆯 󰞼 󰞽 󰡥 󱔒 󰆰 󰧦 󰺜 󰆱 󱥶 󰞾 󰆲 󰞿 󰇁 󰙺 󱒀 󰥜 󰇀 󰳽 󰳾 󱄧 󱄨 󰆿 󰆾 󰆽 󰗧 󱡆 󱡇 󱥎 󱥏 󱗻 󱕸 󱔼 󱔽 󱔾 󱔿 󱕀 󱕁 󰆼 󱘺 󱘤 󱘻 󱘥 󱘼 󱘦 󱘽 󱘧 󱘾 󱘨 󰪩 󱘩 󱘿 󱘪 󱙋 󱙌 󰮆 󱘫 󰥞 󱘬 󱤟 󱤠 󱤡 󱤢 󰥝 󱘭 󰪪 󱘮 󱋶 󱘯 󰆻 󱘰 󱙀 󱘱 󱘲 󰆺 󱘳 󰗂 󱘴 󰴀 󱘵 󰡦 󱘶 󰴁 󱘷 󰳿 󱘸 󰣘 󰣙 󰮇 󰣚 󰆹 󰆸 󰆷 󰝬 󰝭 󱂡 󱂢 󱂣 󱂤 󰆶 󰆵 󰆴 󱂥 󱂦 󰚃 󰮈 󱕖 󱕗 󰛌 󰺝 󰗨 󰮉 󱂧 󱂨 󰧧 󰠙 󰗩 󰱢 󰆳 󰇂 󱈹 󰥟 󰇃 󰟀 󰇄 󰧨 󰇅 󰪫 󰇆 󰵮 󰚗 󰇇 󰾰 󰥋 󱄦 󰘜 󰱣 󰱤 󰱥 󰮊 󰮋 󰇈 󰇊 󱅊 󰇋 󱅋 󰇌 󱅌 󰇍 󱅍 󰇎 󱅎 󰇏 󱅏 󱅓 󰝯 󱅔 󰡧 󱅕 󰗪 󱅐 󰗫 󱅑 󰗭 󱅒 󰗬 󰝮 󱅖 󱈷 󰟁 󰇐 󰙁 󰗮 󰇑 󰥠 󰙯 󰪬 󱆸 󱆹 󰇒 󱇉 󱇈 󱇊 󱇋 󱇌 󱇍 󱡷 󱥷 󰶿 󰷀 󰷁 󰷂 󰷃 󰷄 󰷅 󰇔 󰇕 󰩁 󰚄 󰇖 󰮌 󱂩 󱂪 󱂫 󱔓 󱂬 󰡨 󰩂 󰩃 󰪭 󰩄 󱛮 󰚳 󰺞 󱢴 󰇗 󰵯 󱂭 󱂮 󱐞 󱀣 󰟂 󰠚 󰠛 󱂯 󰠜 󱠞 󱠟 󱠠 󱋦 󰡩 󰪮 󱥸 󱗼 󱗿 󰇘 󰟃 󰮍 󱗽 󱗾 󰇙 󰟄 󰮎 󰇚 󱑢 󱑣 󱑤 󱑥 󱌠 󱌡 󰧩 󰛴 󰱦 󱂰 󱂱 󰮏 󰇛 󰇜 󱋰 󰮐 󰇝 󱋱 󰴂 󰽉 󱦹 󰇞 󰇟 󰽊 󰽋 󰇢 󰇣 󰇤 󰇥 󰇦 󰱧 󰟅 󱫮 󰩅 󱡏 󱡐 󱡑 󱡒 󰇧 󱌑 󰛍 󱐇 󰛎 󱐆 󱐈 󱐄 󰇨 󱐃 󱐅 󰪯 󰪰 󱡊 󱏰 󱏱 󱏲 󱕫 󰧪 󰇪 󰮑 󰺟 󱃙 󱀤 󰟆 󰇫 󰇬 󰇭 󱋂 󱎁 󱥹 󱥺 󱥻 󱋁 󰺠 󰺡 󰇮 󰛏 󰵂 󰴃 󰪱 󰪲 󰻣 󰻤 󱡯 󱡰 󰇱 󰮒 󰻥 󰻦 󰻧 󰻨 󰾱 󱏣 󱏤 󰇯 󰻩 󰻪 󰗯 󰇰 󰧫 󰧬 󱃚 󱃛 󱙡 󱙢 󱥛 󱥜 󰥡 󰥢 󱃜 󱃝 󱋇 󱋈 󰗰 󰬰 󰚴 󰱨 󰱩 󰱪 󱃞 󱃟 󰱫 󰇳 󰱬 󰱭 󰱮 󰚛 󰱯 󰇴 󰱰 󰚜 󰽌 󰽍 󰱱 󰇵 󰱲 󰱳 󱈔 󱈕 󰱴 󰇶 󰇲 󰇷 󰱵 󰱶 󰇸 󱕼 󱕽 󰇹 󰱷 󰱸 󰱹 󰇺 󰩆 󰩇 󰇻 󱃠 󰇼 󰇽 󰺢 󰺣 󰇾 󰙂 󰇿 󱎙 󱋀 󱊿 󰱺 󰪳 󰡪 󰈀 󰈁 󰈂 󱔙 󱔚 󱔛 󱔜 󱔝 󱔞 󰗱 󰈄 󱀥 󰈅 󱈸 󰩈 󰈆 󰪴 󰪵 󰢮 󰾲 󰥣 󰥤 󰈇 󰮓 󰈈 󱣽 󱣾 󱣿 󱤀 󰴄 󰴅 󰮔 󰮕 󱀦 󱀧 󰈉 󰛑 󰛐 󰡫 󰡬 󱥼 󱥽 󱗣 󱗤 󰡭 󰡮 󰈊 󱏝 󱏟 󱏜 󱏞 󰈋 󰵰 󰙃 󰮖 󰙄 󱗌 󱗍 󱖆 󱖇 󰱻 󱁷 󱁸 󱁶 󱗎 󱗏 󰈌 󰟝 󰈎 󰬱 󰈏 󱘎 󰈐 󱑬 󱜝 󱑭 󱑮 󱨺 󱑰 󰠝 󱑯 󱑱 󱑲 󱑳 󱑴 󰈑 󰵱 󱤺 󰴆 󱇸 󱘋 󰛒 󰈒 󰛓 󰩉 󰩊 󰣛 󱞚 󱟶 󱓁 󰺤 󰈓 󰈔 󰜻 󱀨 󰩋 󰩌 󱪓 󱪔 󱪕 󱪖 󰪶 󰻫 󰻬 󰷆 󰷇 󱆆 󱆇 󰈕 󱧆 󱧇 󱀩 󰈖 󰸩 󱋡 󱋢 󰈗 󱀪 󰈮 󱀫 󱁻 󱁼 󰢪 󰈘 󰺥 󰈙 󱪗 󱪘 󱪙 󱪚 󰷈 󰷉 󱪛 󱪜 󱔗 󱔘 󰧮 󱪝 󱪞 󱪟 󱪠 󰥥 󰥦 󱇧 󱇨 󰈛 󰈜 󱀬 󱀭 󰈝 󱀮 󰷊 󰷋 󰈞 󰮗 󰵸 󰘓 󰈟 󱝲 󱝳 󱤻 󱤼 󰺰 󱤽 󱤾 󱤿 󱥀 󰈠 󱀯 󰈥 󱆄 󱆅 󱅷 󱅸 󰈡 󱧈 󱧉 󱀰 󱝴 󱝵 󱪡 󱪢 󰪹 󱀱 󰈢 󱀲 󰈣 󰸪 󰈤 󰈦 󰠞 󱀳 󱅹 󱅺 󰝒 󰻭 󰸭 󰈧 󰈨 󱀴 󱀵 󰈩 󰡯 󱀶 󰤘 󰕁 󰮘 󱀷 󰬲 󰬳 󰙰 󱀸 󱨻 󱨼 󱨽 󱨾 󰱼 󰱽 󰈪 󱀹 󱁹 󱁺 󱧃 󱀺 󱀻 󰾴 󰾵 󱈖 󱈗 󰱾 󱃡 󱃢 󱃣 󱃤 󰱿 󰙅 󱏒 󰣜 󱀼 󰩍 󰩎 󰈫 󰸬 󰈬 󰈭 󱀽 󱀾 󰈯 󰈰 󰌲 󰴘 󰈱 󰈲 󱣬 󱣭 󱪣 󱪤 󱃥 󱃦 󰻮 󰻯 󱨿 󱩀 󱓯 󱓰 󰈳 󰻰 󰻱 󰈴 󰈵 󱪥 󱪦 󰈶 󱄒 󱄓 󱀿 󰠟 󰛔 󰈷 󰺱 󰈸 󱗗 󱠇 󰻲 󱄷 󱄸 󱄹 󱜢 󰢫 󰥧 󰈹 󰸮 󰸯 󰖾 󰸰 󱜣 󰈺 󱏳 󰻳 󰻴 󰻵 󰻶 󱣴 󱣵 󰈻 󰈼 󰮙 󱂲 󱣮 󱣯 󰈽 󰮚 󱂳 󰮛 󱂴 󰈿 󰉀 󰈾 󰵲 󰉁 󰻷 󰻸 󰉂 󰉃 󰛕 󰙻 󰉄 󰉅 󰂓 󰂔 󱈺 󱈻 󱏴 󱏵 󰂕 󱈼 󱈽 󱈾 󱈿 󱉀 󱉁 󱏶 󱏷 󰂖 󱉂 󱉃 󱉄 󱉅 󱉋 󱉌 󱉍 󱉎 󱌃 󱃧 󰉇 󰉈 󱃨 󰣝 󱁀 󱟎 󱟈 󱝇 󱟖 󱁁 󱟏 󰠡 󰉉 󰧯 󰉊 󰧰 󱢅 󱢆 󰴈 󰧱 󰧲 󰽎 󰽏 󰽐 󰽑 󰉋 󰉌 󰮜 󰷌 󰷍 󱧨 󱧩 󱧪 󱧫 󱧬 󱧭 󱧮 󱧯 󱧰 󱧱 󱧲 󱧳 󱧴 󱧵 󱥾 󱥿 󰪺 󰪻 󱁿 󱂀 󰉍 󱃩 󰣞 󰷎 󱞊 󱞋 󱧶 󱧷 󰉎 󱃪 󱃫 󱞞 󱂵 󱂶 󰉏 󱂷 󱂸 󰢬 󰢭 󰲀 󱃬 󰉐 󰉑 󱪧 󱪨 󱉭 󱉮 󰉒 󱉆 󰉓 󰉔 󰉕 󱑾 󱑿 󱍙 󱍚 󰡰 󰲁 󱧸 󱧹 󰝰 󰷏 󰉖 󱧺 󱧻 󰉗 󰮝 󰴉 󰴊 󱧊 󱧋 󰝉 󰕂 󰉘 󰮞 󰥨 󰥩 󱁽 󱁾 󰚝 󱏓 󱏔 󰮟 󰾶 󰾷 󰴋 󰴌 󱋣 󱋤 󰲂 󰲃 󰉙 󱃭 󱧼 󱧽 󰛫 󰞹 󰀺 󰉚 󰉛 󰲄 󰟈 󱐟 󱑨 󱑩 󱐠 󰗲 󱕲 󱡋 󱕳 󰗳 󱤕 󱤖 󱑪 󱑫 󱠶 󱠷 󱜜 󰉜 󱏥 󰽒 󰉝 󰉞 󰉟 󱢗 󰟉 󱐀 󱐁 󱂕 󰘎 󱍝 󰟵 󰝓 󰉠 󰉡 󰉢 󰝔 󰉣 󰝕 󰪼 󰙆 󰉤 󰉥 󰉦 󰸱 󱌓 󰚞 󰣟 󰉧 󰉨 󰉩 󰉪 󰛖 󰧳 󰧴 󰉫 󰉬 󰉭 󰉮 󰉯 󰉰 󰉱 󰉲 󰉳 󰉴 󰘞 󰘟 󰘠 󰉵 󰉶 󰉷 󰬴 󰬵 󰬶 󰾸 󰾹 󱥖 󰾺 󰉸 󰗈 󰗉 󰉹 󰷐 󰺲 󰉺 󰥪 󰝖 󱡠 󰉻 󰴍 󱉯 󰺳 󰛗 󱤗 󰉼 󰉽 󰛘 󰉾 󱆨 󰝗 󱆧 󰚪 󰚟 󰉿 󰊀 󰊁 󰊂 󰊃 󰊄 󰾻 󰾼 󰵳 󰾽 󰵴 󰾾 󰾿 󰸲 󱔏 󰴎 󰴏 󰴐 󰴑 󰊅 󰊆 󰗴 󰊇 󱣩 󰘡 󰘢 󰘣 󰊈 󰊉 󰊊 󰊋 󰊌 󱪩 󱪪 󰠢 󱪫 󱪬 󱪭 󱪮 󰊍 󰵵 󰥫 󰴒 󰴓 󱦒 󰣠 󱥗 󰺴 󰊐 󱆱 󱆲 󰊒 󱗮 󱗯 󱗰 󱗱 󱗲 󱗳 󱆯 󱆰 󰊏 󰊑 󱗴 󱗵 󱗶 󱗷 󱗸 󱗹 󱁂 󱏸 󱁃 󱏹 󱁄 󱁅 󱨎 󱁆 󱁇 󰟊 󱢵 󰊓 󰊔 󰊕 󰡱 󱂁 󱂂 󰲅 󱐭 󰲆 󱐬 󰊖 󰸳 󰸴 󰸵 󰸶 󰸷 󰸸 󰸹 󰸺 󱤙 󰸻 󰸼 󰸽 󰸾 󰸿 󰹀 󰹁 󰺵 󰺶 󰹂 󰊗 󰺷 󱃮 󰷑 󰛙 󰡲 󱋕 󱟻 󰛚 󱋔 󱋓 󱟼 󱨛 󰙇 󰊘 󱐉 󱐊 󰺸 󰊙 󱟸 󰣡 󱟷 󱅩 󰣢 󰣣 󰣤 󱅪 󰣥 󰣦 󰣧 󰹃 󰊚 󰡳 󰡴 󰡵 󰊛 󰊜 󰊝 󰊞 󱄿 󱅀 󰊟 󰣨 󰟋 󰜼 󰪽 󰪾 󰵶 󰜽 󰪿 󰜾 󰜿 󰝀 󰫀 󰝁 󱊩 󱊨 󰵷 󰝂 󰝃 󰊠 󰧵 󱙜 󱙝 󰹄 󱛯 󱛰 󱛱 󱛲 󰊡 󰊢 󰊤 󰮠 󰍖 󱗦 󰊥 󱡳 󰊦 󱗧 󱄖 󱗨 󱌍 󰊧 󰊨 󰡶 󰊪 󱋗 󰣩 󰊫 󰊬 󰵹 󰵺 󰮡 󱉏 󰠣 󱆤 󱂃 󰚆 󰵻 󰊭 󰲇 󰟌 󰟍 󰊮 󰊯 󰊰 󰊱 󰊲 󰊳 󰋀 󱇶 󰊴 󰊵 󱍢 󰊶 󰊷 󰥬 󰊸 󰋉 󰠤 󰛜 󰧶 󰗵 󱁈 󰊹 󰊼 󰊽 󰺹 󰧷 󰲈 󰊿 󱝊 󰚠 󰵼 󱁉 󱁊 󰡷 󱔐 󰮢 󰙈 󰥭 󰥮 󰀭 󰋁 󰝘 󰋂 󰹅 󱆊 󰋃 󰝱 󰋄 󰋅 󰋆 󰠥 󱩁 󰫁 󱃯 󱃰 󰮣 󰚅 󱝶 󱝷 󱝸 󱝹 󱝺 󰣪 󱌢 󱢇 󱌣 󰹆 󱠰 󱠲 󱠬 󰹇 󱠱 󱠳 󱠭 󱥋 󱩂 󱢏 󱢐 󱢶 󱢷 󱠫 󱠮 󰩏 󱠯 󱃱 󱕾 󰩐 󰩑 󰩒 󰩓 󰩔 󰋇 󰩕 󰹈 󱕿 󱖀 󱎟 󱠡 󱠢 󰽓 󱄾 󰕹 󱈘 󱖡 󰋈 󰥯 󰋊 󱁋 󱁌 󰮤 󰲉 󰵽 󰵾 󱍞 󱌸 󱌹 󱌺 󱌻 󱌼 󱌽 󱌾 󱌿 󱍀 󱍁 󱍂 󱍃 󱍄 󱍅 󱍆 󱍇 󱍟 󱍈 󱍉 󱍊 󱍋 󱍌 󱍍 󱍎 󱍏 󱍐 󱍑 󰋋 󰥰 󰋌 󰟎 󰋍 󰋎 󰋏 󰋐 󰋑 󰋒 󰋓 󰋔 󰴔 󰥱 󰥲 󱙣 󱙤 󰻹 󰛟 󰛞 󰛠 󱐯 󱐲 󰩖 󰩗 󰝙 󱐴 󰋕 󱐮 󱐱 󰗶 󱐰 󱐳 󱙥 󱙦 󱩃 󱩄 󱩅 󱪯 󰫂 󰋖 󰞋 󰋗 󰘥 󰛵 󰲊 󰮥 󰮦 󱊧 󰋘 󰛡 󱃲 󰋙 󰫃 󰫄 󰫅 󰫆 󰫇 󰫈 󰫉 󰫊 󰟏 󰡸 󰗷 󰵿 󰋚 󰡹 󰡺 󰋛 󰋜 󰠦 󰡻 󱗐 󰺺 󰟐 󰟑 󱤁 󱤂 󰟒 󱁍 󰴕 󰴖 󱨒 󱨓 󱅙 󱅚 󰾛 󰻺 󰷒 󰶀 󰶁 󰶂 󰶃 󰶄 󰶅 󰶆 󰷓 󰷔 󱧁 󱧀 󱧂 󰠧 󰾜 󱉑 󱉒 󱤃 󱤄 󰣫 󰣬 󰗸 󰥴 󱏕 󰋝 󱩆 󱩇 󰚡 󰥵 󱏖 󱉇 󱏗 󱄫 󱎰 󱎱 󱞔 󱞕 󰽔 󰽕 󰋞 󰮧 󰛢 󰛣 󰹖 󰋟 󱃳 󱃴 󱖿 󱗀 󱗁 󱡮 󰩘 󰿶 󰋠 󰿷 󰋡 󰋢 󰠨 󱑸 󰴗 󰠩 󰋦 󱎋 󱖁 󱖛 󱖜 󰋧 󱦀 󱓨 󰙉 󰩙 󱗉 󰩚 󰩛 󱟄 󱖝 󰙊 󰙋 󰙌 󰙍 󰢐 󰡆 󰩜 󱎌 󰋨 󱠣 󰩝 󰻻 󰻼 󰩞 󱡈 󰗏 󱕱 󱇩 󱎍 󱦁 󰝄 󱍒 󱖞 󱌤 󱌥 󱋥 󱢔 󰠪 󰹒 󰻽 󰿀 󰻾 󱌱 󱌲 󰋩 󰋪 󰋫 󰋬 󰿁 󰋭 󰋮 󱇣 󱇤 󰋰 󰋱 󰻿 󰼀 󰋲 󰋳 󰋴 󰋵 󰋶 󰋷 󰋸 󰹉 󱪰 󱪱 󱝻 󱝼 󱐙 󰧸 󰋹 󰋯 󰠫 󱇑 󰥶 󰡼 󱧾 󱧿 󱐘 󰥷 󰥸 󰲍 󰲎 󰲏 󱨀 󱨁 󱘍 󰋺 󰚇 󰋻 󱉰 󰏑 󱉱 󱉲 󱉳 󰢰 󰮨 󱉴 󱖟 󱖠 󰗹 󱐡 󱐢 󰁵 󱡌 󰛤 󰋼 󱞌 󱞍 󰋽 󰙎 󰋾 󱁎 󱤓 󰌁 󰹊 󱋨 󰩟 󰩠 󰲐 󱦂 󰲑 󱠤 󱠸 󱠥 󱁏 󱂹 󰷕 󰌂 󰼁 󰼂 󰌃 󰡽 󰌄 󱋿 󰶇 󱕘 󰠬 󰢯 󰌅 󰗺 󱌗 󱌘 󱌛 󱌜 󰽖 󱜼 󱌙 󱌚 󱌀 󰌆 󱦃 󱦄 󱌒 󱕴 󱕵 󰌇 󱆟 󰌈 󰷖 󰌉 󰌊 󱆞 󰌋 󰿂 󰌌 󰌍 󰌎 󰌏 󱊷 󱊫 󱊴 󱊵 󱊶 󱊬 󱊭 󱊮 󱊯 󱊰 󱊱 󱊲 󱊳 󰌐 󰹋 󰥻 󰌑 󰧹 󰧺 󱁐 󰌒 󰌥 󰌓 󱃽 󰝅 󱦅 󱦆 󱝄 󱍛 󰧻 󰧼 󱜿 󰌔 󱃾 󰌕 󱍵 󱍶 󰫋 󰫌 󰌖 󱋪 󱋫 󰫍 󰫎 󱖢 󰠭 󰘧 󰚵 󱟐 󱕶 󱟑 󰌗 󱊪 󰌘 󰌙 󰌚 󱪲 󱪳 󱪴 󱪵 󱪶 󱪷 󱩈 󱩉 󰙱 󰙲 󰌛 󰌜 󱈚 󰟓 󰲒 󰌝 󰬷 󰌞 󱈙 󰢱 󰍔 󰽛 󰌟 󰌠 󰟔 󰴭 󰫏 󱘗 󰛥 󰛦 󰙳 󰌢 󱩊 󰛧 󰫐 󱒄 󰼃 󰑆 󰽗 󰌧 󰟕 󰌨 󱢒 󰹌 󰌩 󰧽 󰧾 󰹍 󰹎 󱈆 󱈇 󰽘 󰽙 󰙏 󰌪 󱤅 󱤆 󰲓 󱋚 󱋙 󰷗 󰷘 󱫰 󰌫 󰌬 󰌭 󰟖 󱁑 󱩋 󰌮 󰌯 󰌰 󱅽 󰥼 󰥽 󰌱 󱨢 󰮩 󰿃 󰡾 󱦇 󱦈 󱞛 󰥾 󱨤 󰌵 󱧡 󱧢 󱠀 󱠁 󱈈 󱈉 󱉵 󱋃 󱠄 󱠅 󱉓 󱋍 󱋎 󱉔 󱉕 󱋏 󱋐 󱉖 󱩌 󱩍 󰹏 󰹐 󰛨 󱩎 󱩏 󱩐 󱩑 󱩒 󱩓 󱩔 󱩕 󱩖 󰛩 󰌶 󱧣 󱧤 󱟴 󱟵 󱠂 󱠃 󰧿 󰨀 󱐋 󰠠 󱐌 󰘤 󱑶 󰌷 󰴚 󰴛 󰴜 󰴝 󱂺 󰌸 󰲔 󰌹 󱃿 󰌺 󱄀 󱄁 󰌻 󰌽 󰣭 󱎵 󱠦 󱤞 󱖫 󰩡 󰝲 󰿄 󰿅 󰌾 󰣮 󱗑 󱎚 󱚨 󰥿 󱚩 󱚪 󱙱 󱙲 󰌿 󱎛 󱗒 󱎜 󱚫 󱚬 󱚭 󰍀 󱚮 󱚯 󱚰 󱚱 󰿆 󰿇 󰍁 󰛪 󰗻 󱚲 󰣯 󱚳 󱚴 󰝳 󰢲 󰟗 󰟘 󰍂 󰍃 󰗽 󰽚 󰍄 󱖂 󱖃 󱖄 󱖅 󰍅 󰍆 󱂄 󱡃 󰌤 󰌣 󱡄 󰍇 󰍈 󰍉 󰦀 󱡴 󰍊 󰩢 󰛬 󰍋 󰩣 󰛭 󱈌 󱈍 󱉶 󰺻 󰛮 󰶈 󰶉 󰶊 󰶋 󰶌 󰶍 󰶎 󱘊 󰍍 󰺼 󰺽 󰴞 󰴟 󰨁 󰍎 󱣣 󱣤 󰼅 󰼆 󰲕 󱋻 󰍏 󰣰 󱄂 󱋛 󱋝 󰙐 󱋹 󰍐 󱉷 󰍑 󱋽 󰟙 󰴠 󰙑 󱋸 󰼇 󰼈 󰍒 󱋼 󰼉 󱋺 󰼊 󱋜 󱋞 󱘈 󱘉 󱄃 󰦁 󰦂 󰦃 󰦄 󰦅 󰮪 󰍓 󰙒 󰷙 󰍕 󰫑 󰦆 󰍗 󰍘 󰲖 󰿈 󰿉 󱂅 󰿊 󰿋 󰲗 󰲘 󰘨 󰦇 󱌦 󰛯 󱪸 󱅻 󰍛 󱟔 󱟕 󰍜 󰍝 󰚶 󰍞 󰨂 󰮫 󰍟 󰨃 󰩤 󰩥 󰍠 󰚷 󰽜 󰍡 󰍢 󰨄 󱋲 󱋳 󱋴 󱋵 󱥁 󱥂 󱖬 󱖭 󰚢 󰚣 󰛱 󱅲 󰍣 󱧌 󱧍 󱖩 󱖪 󰍤 󱅬 󰿌 󱅭 󱅮 󱅯 󱙍 󱙎 󰍥 󰙓 󱂻 󰍦 󱅰 󱜺 󱜻 󰍧 󱜽 󰍨 󱜾 󰛰 󱅱 󰚚 󱉐 󰍩 󱅳 󱅴 󱧎 󱧏 󰿍 󱅵 󰍪 󰍫 󰘩 󱩗 󱩘 󱩙 󱩚 󰟚 󰟛 󰟜 󰍬 󰢳 󰍭 󰍮 󰢴 󱦉 󱦊 󰍯 󰍰 󰍱 󰙔 󰍲 󱎎 󰠅 󰿕 󰂤 󰦈 󰇩 󱎏 󰌀 󰏆 󰏊 󰝇 󰴢 󱎐 󱎑 󰊻 󰘐 󰨞 󰖳 󰨡 󱎒 󰖹 󰖺 󰝋 󰨢 󰝌 󰝍 󰝎 󰝏 󰝐 󰹯 󰖻 󰹰 󰲙 󱐣 󰽝 󰽞 󰣱 󰣲 󰷚 󰍳 󰨅 󰨆 󰍴 󰍵 󱅁 󱅂 󰛲 󰍶 󰍚 󰫓 󱑙 󱑚 󰍷 󰍸 󰲚 󱘹 󱇽 󱞟 󱞠 󰶏 󰡿 󰮬 󱋾 󰟤 󰍹 󱩛 󱧐 󱧑 󰦉 󰦊 󰨇 󱋆 󱎴 󰷛 󰍺 󰶐 󰹑 󱒃 󱄄 󱡶 󰽟 󰽠 󰷜 󰽡 󰽢 󰽣 󰽤 󰽥 󰽦 󰽧 󰽨 󱂆 󱖷 󱖸 󱖹 󰍻 󱝈 󰏱 󱠧 󱌔 󰴡 󱖲 󱖳 󱖐 󱖒 󱖏 󱖑 󰶑 󱐵 󰍼 󱖺 󰍽 󰦋 󱕐 󱕑 󱕒 󰍾 󰍿 󰎀 󰙕 󰙖 󰎁 󱛳 󱛴 󱛵 󱛶 󱄢 󱄣 󱄤 󱄥 󱛷 󱛸 󱛹 󱛺 󰿎 󱛻 󱛼 󱛽 󱛾 󱛿 󱜀 󱜁 󱜂 󱜃 󱜄 󰿏 󱜅 󱜆 󱜇 󱜈 󱜉 󱜊 󱜋 󱜌 󱜍 󱜎 󰷝 󱜏 󱜐 󱜑 󱜒 󱜓 󱜔 󰟞 󱇒 󱇓 󱜕 󱜖 󱜗 󱜘 󱙯 󱙰 󰦌 󱢓 󰎂 󰎃 󰟟 󱏺 󱏻 󰟠 󰝚 󰽩 󰽪 󰽫 󰽬 󰽭 󰎄 󰌳 󰼄 󰎅 󰎆 󰫔 󰽮 󰽯 󰽰 󰎇 󰗾 󰗿 󰽱 󰎉 󰽲 󰎊 󰽳 󰽴 󰷞 󰎋 󰽵 󰎌 󰽶 󰎍 󰽷 󰝛 󰽸 󰽹 󰽺 󰽻 󰽼 󱗞 󰷟 󰣳 󰢀 󰎎 󰎏 󰎐 󱘇 󱣱 󰗍 󰼋 󰎑 󱧒 󰝆 󰛳 󰲛 󰲜 󰲝 󱫋 󰣴 󰣵 󰣶 󰣷 󰣸 󰣹 󰣺 󰣻 󱤚 󰣼 󰣽 󰣾 󰎔 󰎕 󱥃 󰼌 󰼍 󱥄 󱀁 󱀂 󱀃 󱀄 󰎖 󰹓 󰎗 󰎘 󰹔 󰝴 󱎓 󰟡 󰖫 󰜭 󱄅 󰎙 󱅾 󰦍 󰦎 󰎚 󱝽 󱝾 󱝿 󱞀 󱞁 󱞂 󱙏 󱙐 󰚸 󰚹 󱞃 󱞄 󰎛 󰎜 󰎝 󱙑 󱙒 󱙓 󱙔 󰎞 󱇗 󰠮 󱓵 󱓶 󱓧 󱓩 󱨋 󱨌 󱘐 󱘑 󰹕 󰺿 󱘒 󱘓 󱘔 󱘕 󰎟 󰛷 󰚤 󰟢 󰎠 󰎡 󰼎 󰎢 󰎣 󰬺 󰿩 󰽽 󰿪 󰿫 󰽾 󰿬 󰿭 󰎤 󰼏 󰎥 󰎦 󰲠 󰲡 󰬻 󰎧 󰼐 󰎨 󰎩 󰲢 󰲣 󰬼 󰎪 󰼑 󰎫 󰎬 󰲤 󰲥 󰬽 󰎭 󰼒 󰎲 󰎮 󰲦 󰲧 󰬾 󰎱 󰼓 󰎯 󰎰 󰲨 󰲩 󰬿 󰎳 󰼔 󰎴 󰎵 󰲪 󰲫 󰭀 󰎶 󰼕 󰎷 󰎸 󰲬 󰲭 󰭁 󰎹 󰼖 󰎺 󰎻 󰲮 󰲯 󰭂 󰎼 󰼗 󰎽 󰎾 󰲰 󰲱 󰿮 󰎿 󰼘 󰏀 󰏁 󰲲 󰲳 󱁒 󱧓 󱗋 󰛸 󰏂 󱄆 󰙼 󰷠 󱋩 󱄺 󰏃 󰏄 󰛹 󰝵 󱥐 󱥑 󰏅 󱈛 󰦑 󱥉 󱥊 󱔠 󱔡 󱔟 󰏇 󰼙 󱁓 󰿸 󰥳 󰏉 󰮭 󰢁 󰗌 󰏋 󰏌 󰮮 󰏍 󰏎 󰀘 󱗛 󰈍 󰴇 󰊾 󰦏 󱎄 󰦐 󰕅 󰕆 󰭃 󰏏 󰏐 󱁔 󱀅 󰏒 󰮯 󰏓 󰏔 󰏕 󰏖 󰏗 󱧔 󱧕 󱧖 󱧗 󱧘 󱧙 󰘀 󰘁 󰛺 󰛻 󰛼 󰽿 󰛽 󰛾 󰮰 󰮱 󰮲 󰮳 󱐗 󱐷 󱐼 󱐹 󱐾 󱐺 󱐶 󱐻 󱐸 󱐽 󰏘 󰏙 󰸌 󰢵 󱍜 󱥚 󱁕 󰮴 󰮵 󰮶 󰮷 󰮸 󰮹 󰮺 󰮻 󰮼 󰮽 󰮾 󰏚 󰏛 󰏜 󰏝 󱤨 󰏞 󱦌 󱦍 󱦎 󱦏 󱦐 󱤩 󰏟 󱥟 󰏠 󰏡 󱅗 󱅘 󰏢 󱫆 󱧚 󱫇 󱫈 󱫉 󱫊 󰲴 󰲵 󱝅 󰏣 󱁖 󰟣 󰷡 󱅠 󰾀 󰢂 󰏤 󰏥 󰏦 󰏧 󰏨 󰏩 󰙗 󱙶 󱙵 󰢄 󰿼 󰿽 󰿿 󰿾 󰏪 󰷢 󰷣 󰷤 󰷥 󰷦 󰏫 󰏬 󱅄 󱅅 󰏭 󰛿 󰝶 󰏮 󰷧 󰷨 󰷩 󰏯 󰷪 󰲶 󰷫 󰷬 󰷭 󰷮 󱍓 󰻀 󰜁 󰜀 󱙧 󰏰 󱨂 󱨃 󱨄 󱨅 󱉸 󰢶 󰴣 󰴤 󱟅 󰏲 󰼚 󱆎 󰏳 󱆏 󱂼 󱆐 󱆩 󱆪 󰘂 󱉹 󱧛 󱕙 󱕚 󰏴 󱆑 󰏵 󱆒 󰏶 󱆂 󰏷 󱆓 󰏸 󱆔 󰏹 󱆕 󱆖 󱆗 󰙘 󱆘 󰏺 󱆥 󰷯 󱆦 󰏻 󱆙 󰷰 󰏼 󱆚 󰙙 󱆛 󱦓 󱦔 󱔯 󱔰 󰠯 󱆜 󱆫 󱆬 󰢅 󰢆 󰏽 󱆝 󱦕 󱦖 󰏾 󰏿 󰐀 󰷱 󰙽 󰚘 󰢷 󰹗 󰹘 󰹙 󰹚 󰢇 󰢈 󰐁 󱀆 󱙸 󱀇 󱙹 󰐂 󱩜 󰜂 󰐃 󰐄 󰤰 󰤱 󰐅 󰐆 󱐚 󰐇 󰫕 󰫖 󰟥 󰟦 󰢉 󱡍 󱍔 󰨈 󰜃 󰢊 󱕓 󰐉 󰐊 󱉺 󱨖 󱨗 󱨘 󱨙 󰴙 󱏦 󰐋 󰐌 󰐍 󰢋 󰲷 󰼛 󰐎 󰐏 󰣿 󰗇 󰤀 󰐐 󰲸 󰲹 󰐑 󰐒 󰐓 󰷲 󰚺 󱦤 󰐕 󰐖 󰌴 󱅃 󰜄 󰐗 󰍌 󰐘 󰐙 󱩝 󱩞 󰦒 󰦓 󱓉 󰐚 󰲺 󰜅 󱇬 󰦔 󰴥 󰴦 󰴧 󰴨 󰶒 󰐝 󰨉 󰠰 󰐞 󱅧 󱅨 󱠹 󰐟 󱓃 󰐡 󰘆 󱩟 󰐢 󱀈 󱩠 󱀉 󰲻 󰋥 󰙛 󰙷 󰋿 󰙚 󰌦 󰐣 󰐤 󱅿 󰐥 󰤁 󰤂 󰤃 󰚥 󰚦 󱐤 󱐥 󰐦 󰤄 󰐧 󰤅 󰾳 󱄇 󰟧 󱄈 󱓿 󱄉 󰟨 󰟩 󰤆 󰨊 󰜆 󰐨 󰐩 󱕢 󰐪 󰐫 󰹛 󱇀 󱇁 󱢸 󱢹 󰹜 󰐬 󱅆 󱑘 󰹝 󱞅 󱞆 󱁗 󱑗 󰜇 󰨋 󰘃 󰘄 󰐭 󰲼 󰦕 󰦖 󱄊 󰦗 󱞇 󱔢 󱞈 󰦘 󰲽 󰐮 󱨣 󰐯 󱠍 󱠎 󱜤 󱠏 󱠐 󱠑 󱠒 󱍗 󱍘 󰿘 󰚧 󱥅 󰐰 󱐂 󰮿 󰼜 󰼝 󰐱 󱐦 󱐧 󱓓 󱓙 󱓔 󱓚 󱓑 󱓗 󰩦 󱓐 󱓖 󱓒 󱓘 󱓕 󱓛 󱥒 󱥓 󰦙 󰘅 󰐲 󰢸 󱆌 󱆋 󱆍 󰐳 󰐴 󰐵 󰨌 󰨍 󰴩 󰤇 󱩡 󱩢 󰶓 󰶔 󰐷 󰐸 󰫗 󰫘 󰐹 󰲾 󰲿 󰐺 󱈜 󰐻 󰐼 󱡝 󱡞 󰻁 󰐾 󱓅 󱓆 󰳀 󰳁 󰼞 󱕄 󰐿 󱨏 󱨐 󰑀 󰑁 󰑂 󰑃 󰑄 󱗘 󰑅 󱦗 󱦘 󰜈 󰑇 󰑉 󱧜 󱩣 󱩤 󱩥 󱩦 󱩧 󱩨 󱩩 󱩪 󰑊 󰻂 󰻃 󰦚 󰑋 󰹞 󰹟 󰑌 󱎝 󰑍 󱄛 󰑎 󰑏 󰨎 󰨏 󰑐 󱣲 󱍷 󰑑 󰩧 󱖈 󱒖 󱒗 󱒘 󱒙 󱒚 󱒛 󱒜 󱒝 󱒞 󱒟 󱒠 󱒡 󱒢 󱒣 󱒤 󱒥 󱒦 󱒧 󱒨 󱒩 󱒪 󱒫 󱒬 󱒭 󱒮 󱒯 󱒰 󱒱 󱒲 󱒳 󱒴 󱒵 󱒶 󱒷 󱒸 󱒹 󰑒 󰑓 󱄋 󰢌 󰑔 󰢹 󰻄 󰻅 󰻆 󰑕 󰚈 󰚉 󰑖 󰑗 󰑘 󰕇 󰑙 󰑚 󰑛 󰼟 󱆮 󰼠 󰑜 󰭄 󰭅 󰩨 󰑝 󰑞 󰜉 󱄌 󰶕 󰦛 󱄍 󰑟 󰴪 󱥆 󰶖 󱇹 󱘌 󰜊 󰜋 󰨐 󱓜 󰜌 󰨑 󱓝 󰑠 󰟪 󱖻 󱖼 󰟫 󰹠 󰑡 󰑢 󱁘 󰚩 󱚝 󱚞 󱚟 󱚠 󱚡 󱚢 󱚣 󱚤 󱜙 󱜚 󰭆 󱨚 󱚥 󱚦 󱇷 󱇳 󱚧 󱙻 󱙺 󰜍 󰤈 󰑣 󱓞 󱓟 󱎯 󱌧 󱩫 󱩬 󰴫 󰅅 󰴬 󰀮 󰯀 󱪹 󱪺 󱂉 󱂊 󱂋 󱂍 󱂎 󱂏 󱂐 󰢍 󰶗 󱦙 󰻇 󰑤 󰑥 󰑦 󰶘 󰑧 󰑨 󰘇 󱇢 󱂇 󰑩 󱖣 󰩩 󰑪 󱁙 󰘈 󰑫 󰑬 󰼡 󱑵 󰶙 󰑭 󰳂 󰺾 󰜎 󰑮 󱇔 󰴮 󰴯 󰩪 󱉼 󱉽 󰴰 󰻈 󱫯 󰑯 󱨆 󰢎 󰟬 󰑰 󰤉 󰑱 󰢺 󱞉 󰹡 󱑺 󰘉 󰑲 󰗑 󰑳 󱁚 󱦸 󱏘 󰚫 󰤊 󰻉 󰻊 󱥘 󱥙 󰑴 󱆀 󰩫 󱖽 󱖾 󱉾 󱉿 󰑵 󰑸 󰷳 󰷴 󰷵 󰷶 󰷷 󰑶 󰯁 󰑷 󰯂 󱜥 󱜦 󰯃 󱜧 󱜨 󰑹 󰑺 󰿙 󰜏 󰳃 󰑻 󰑼 󰑽 󰑾 󰑿 󰒀 󰳄 󱉉 󰒁 󰒂 󰳅 󰒃 󰒄 󰹢 󱏽 󱏾 󰹣 󱩭 󱩮 󱖤 󰻋 󰒅 󰒆 󰴱 󰫙 󰩬 󰾂 󰒇 󱊀 󱊁 󱊂 󰒈 󰿚 󱟁 󱈄 󰒉 󰩭 󰴲 󰼢 󱟂 󱊃 󱊅 󱊄 󰝷 󱟃 󱈅 󱌖 󰒊 󱅡 󱅢 󰷸 󰷹 󱅣 󱅤 󰟭 󱅦 󱅥 󰙜 󰒋 󰒌 󰒍 󰒎 󰒏 󰒐 󰒑 󰒒 󰝸 󰝹 󰝺 󰝻 󰝼 󰝽 󱓠 󰝾 󰝿 󱓡 󱑝 󰦟 󰩮 󱄎 󱄏 󰠱 󰙝 󰠲 󱇺 󰒕 󰙞 󰙟 󰙠 󱓺 󰒖 󱇴 󱇵 󱆭 󰼣 󰼤 󰤲 󰒗 󱔔 󱢺 󱙳 󱙴 󱢻 󰳆 󰒘 󰢏 󰨒 󱖧 󱖨 󰚻 󰳇 󰻌 󰻍 󱏚 󱏛 󰾃 󰕥 󰳈 󰳉 󰳊 󱢼 󱢽 󱆠 󱆡 󱍠 󰞀 󰚊 󰳋 󰯄 󰯅 󰴳 󰴴 󰦝 󱦚 󱦛 󰳌 󱠨 󱠩 󰦞 󰦜 󰒙 󰫚 󰫛 󰂪 󰇠 󰫜 󰫝 󰶚 󱄻 󱄼 󱁝 󱁞 󱢾 󱢿 󱆢 󱆣 󱕅 󰠳 󱡎 󱗊 󱗇 󰭇 󰭈 󰷺 󱗈 󰒚 󰒛 󱇕 󰾄 󱩯 󱓹 󰜐 󰜑 󰦠 󰦡 󰒜 󰒝 󰒞 󰒟 󱍿 󱣀 󰒠 󰘫 󰒡 󰞁 󱀀 󰿜 󰿝 󱓸 󱄘 󰞂 󰒢 󰜒 󰜓 󰜔 󰩯 󰢼 󰢽 󰢾 󰢿 󰹤 󰜕 󰜖 󰞃 󰘊 󰷻 󰷼 󰷽 󰷾 󰭉 󰒣 󰿞 󰒤 󰩰 󰒥 󰒦 󰒧 󰒨 󱗓 󰒩 󱗔 󱗕 󱌝 󰫟 󰥛 󰒪 󱦜 󱎥 󱎤 󱎧 󱎣 󱎨 󱎢 󱎩 󰴵 󰚙 󱓂 󰔁 󰴶 󰴷 󱌄 󱌅 󱌆 󰒫 󰼥 󰒬 󰼦 󰒭 󰙡 󰙢 󰼧 󰒮 󰙣 󰙤 󰼨 󰚌 󰯆 󰯇 󰯈 󱓇 󱓈 󰒯 󰒰 󰒱 󰿟 󰿠 󰐛 󰒲 󰒳 󱖥 󰷿 󰸀 󱄔 󱄕 󱂽 󱣷 󱣸 󱂾 󱂿 󱃀 󰩱 󱞙 󰎒 󱤮 󱤯 󱠉 󱠊 󱠈 󱠋 󱤰 󱠌 󰒴 󰒵 󱐍 󱐨 󱙷 󱔎 󰒶 󱌇 󰜗 󰼩 󱩰 󱋋 󱓣 󱩱 󰼪 󰒷 󰛝 󱩲 󰒸 󰠴 󱕹 󱕺 󰒹 󱕭 󱕮 󱕯 󰶛 󰶜 󰩲 󱩳 󱩴 󱂒 󰚍 󰐔 󰒺 󰖽 󱅈 󰖿 󱅉 󰒻 󰒼 󱎅 󱎆 󱎇 󱎈 󱕇 󱕈 󱕉 󱕊 󱕋 󱕌 󰒽 󱎉 󰤍 󱎊 󰫒 󰒾 󰌼 󰒿 󰳍 󰳎 󱪻 󱅇 󱟛 󰓀 󰘬 󱓏 󱓋 󱓊 󱓍 󱓌 󱓎 󰜘 󰜙 󰜚 󰜛 󰜜 󰜝 󰜞 󰓁 󰘭 󰓂 󰳏 󰳐 󰟮 󱏼 󰳑 󰳒 󰯉 󱎃 󰹥 󰓃 󰦢 󰴸 󰓄 󰜟 󱡅 󰓅 󰾅 󰾆 󰓆 󱥔 󱥕 󱇪 󱇫 󰯊 󱓱 󱐩 󰓇 󰓈 󰓉 󰙥 󰫠 󱁟 󱦝 󱁠 󰹦 󰹧 󰝤 󱔀 󰤌 󰨓 󰨔 󱋮 󱋯 󱡔 󰝣 󰞄 󰦣 󱓻 󱨇 󱨈 󱓼 󰨕 󱑻 󰫡 󰣀 󰘋 󰓌 󰍙 󰿹 󰜠 󰓍 󱎞 󱊾 󱊽 󰴹 󰟯 󰓎 󰩳 󱊆 󱊇 󰩴 󱕦 󱕪 󰓏 󰦤 󱙨 󱙩 󰥹 󰥺 󰦥 󰫢 󰫣 󰉆 󰓐 󱕤 󱕨 󰓑 󱕛 󰓒 󱕣 󱕧 󱕥 󱕩 󱙪 󱙫 󱝁 󱝂 󰫤 󰫥 󱇯 󰓓 󰓔 󰤎 󰓕 󰓖 󰓗 󰓘 󰓙 󱍤 󱍥 󱍦 󱍧 󱍨 󰗐 󰞅 󱍩 󱍪 󱍫 󱍬 󱍭 󱍮 󱍯 󱞎 󱞏 󰓚 󱂓 󱥝 󱥞 󰓛 󰙦 󰙧 󱩵 󱩶 󰓜 󰓝 󱣁 󱣂 󱣃 󱣄 󱣅 󱣆 󱣇 󱣈 󱣉 󱣊 󱣋 󱣌 󱙞 󱣍 󱣎 󱣏 󱍡 󱙟 󱣐 󱙠 󱣑 󱣒 󱣓 󱣔 󱣕 󰟇 󱃁 󰓞 󱇖 󰼫 󰼬 󱊺 󱊻 󰘌 󰘍 󱕬 󰨖 󰨗 󰚬 󰶝 󰓟 󰞆 󱩷 󱩸 󱦥 󱞖 󱩹 󱣖 󱣗 󱟾 󱟿 󰓠 󱝆 󰗅 󰟰 󱜩 󰟱 󰟲 󱜪 󰟳 󰜡 󰓡 󰯍 󰿡 󰿢 󰣁 󰓢 󰯎 󰿣 󰿤 󰣂 󰓣 󰓤 󰓥 󰞇 󱌳 󱌴 󱌵 󱌶 󱔁 󰫦 󰓦 󰓧 󱍸 󰓨 󰓩 󰭋 󰝜 󰭌 󱦞 󰓪 󰓫 󱎹 󱎺 󱎻 󱎼 󱎽 󱎾 󰨘 󱎿 󱁡 󱏀 󱏁 󱏂 󰠵 󰓬 󰓭 󰓮 󰓯 󰓰 󱂔 󱏃 󰖼 󱈝 󱈞 󱏄 󱏅 󰓱 󰾇 󰾈 󱏆 󰦦 󱏇 󱏈 󱏉 󰠶 󱏊 󱝃 󱠼 󰩵 󱎠 󰩶 󰠷 󰓲 󰓳 󰓴 󰓵 󰤏 󰠸 󱐪 󱏋 󱎡 󰹨 󰓶 󰓷 󰦧 󰻎 󰝢 󰓹 󱜫 󱜬 󱜭 󱜮 󱜯 󱜰 󱜱 󱜲 󱩺 󱩻 󰓺 󰚋 󰯏 󰤐 󱈟 󰓻 󱋷 󱈠 󱈡 󰓼 󰜢 󱈢 󰜣 󱈣 󱤇 󱤈 󱈤 󰓽 󱏿 󱪼 󱪽 󱪾 󱪿 󱫀 󰓸 󰴺 󰿥 󱛟 󰭍 󰓾 󰯐 󰩷 󰓿 󰶞 󰶟 󰔀 󱣻 󰭎 󰔂 󱍖 󰠹 󰟴 󰠺 󰔃 󰠻 󰾉 󰻏 󱄐 󰾊 󰔄 󰔅 󰔆 󰶠 󰔇 󰔈 󱁢 󰙨 󰤑 󰤒 󰦨 󱕰 󰈚 󰺦 󰺧 󱩼 󱩽 󰺨 󰺩 󰪷 󰪸 󰧭 󰺪 󰺫 󰺬 󰺭 󰺮 󰺯 󰦪 󱄽 󱎸 󱩾 󰙩 󰦩 󰔊 󰔋 󰔌 󰿦 󰔍 󰔎 󰔏 󰸁 󱢕 󱩿 󰸂 󰸃 󱃂 󰔐 󱃃 󰸄 󱔱 󰸅 󱪀 󰎓 󰢑 󰟶 󰟷 󰔑 󰔒 󰔓 󰔔 󰔕 󱤔 󰔖 󰔗 󰔘 󱎪 󰤓 󰜤 󱐫 󰔙 󰜥 󱣳 󰔚 󰯑 󰾕 󰾘 󱔲 󱔳 󱇻 󱇼 󰾙 󰾚 󱔴 󱔵 󰯒 󰾖 󰾗 󱔶 󱔷 󰯓 󰯔 󱎫 󰔜 󰔝 󱫌 󱫍 󱫎 󱫏 󱫐 󱫑 󱤥 󱤦 󱫒 󱫓 󱫔 󱫕 󱫖 󱫗 󱫘 󱫙 󱫚 󱫛 󱫜 󱫝 󱎬 󰔞 󰔛 󱫞 󱫟 󱫠 󱫡 󱫢 󱫣 󱫤 󱫥 󱫦 󱫧 󰔟 󱦟 󰚭 󰞌 󱦠 󱤣 󱤤 󱫨 󱫩 󱫪 󱫫 󱫬 󱫭 󰔠 󱢖 󱁣 󱆷 󰳓 󰔡 󰔢 󰨙 󰨚 󱨥 󱨦 󰦫 󰦬 󰦭 󱁤 󰔣 󰀌 󱠻 󱕜 󱕝 󰔤 󱋅 󰔥 󰯕 󱕞 󱕟 󰔦 󰯖 󰔧 󱕠 󱕡 󰔨 󰯗 󰣃 󰔩 󱄩 󱄬 󱄪 󱘆 󰴻 󱊸 󰦮 󰠼 󰚁 󰚂 󱡵 󱊈 󱊉 󱊊 󱊋 󱊌 󱊍 󱊎 󱊏 󱊐 󱊑 󱊒 󱊓 󰤔 󰟸 󰤳 󰢒 󱓄 󰩸 󱍼 󰔫 󱠪 󰔬 󰯘 󱜳 󱜴 󱜵 󱜶 󰣄 󰔭 󰿧 󰔮 󰔯 󱁥 󰶡 󰶢 󰔰 󰶣 󰴼 󱕆 󰴽 󰾋 󱔕 󰚮 󰤕 󰤖 󰗊 󰸆 󰴾 󱤬 󱤭 󱧝 󰩹 󰩺 󱊔 󱊕 󰄠 󰄝 󱊖 󱊗 󱊘 󱊙 󰜦 󰔱 󰹩 󰔲 󰔳 󰔴 󰔵 󰔶 󰔷 󱨉 󱨊 󱑼 󰯙 󰔸 󰔹 󰶤 󰔺 󰔻 󰔼 󰔽 󱧞 󱧟 󱣘 󰳔 󱊚 󰔾 󱊛 󰞈 󱊜 󱢑 󱦮 󱦽 󱊝 󱦭 󱦼 󱦯 󱦾 󱦦 󰜧 󱂖 󰩻 󰔿 󰩼 󰕀 󱪁 󰤗 󱆺 󱆻 󰘮 󱕂 󰙪 󱕃 󱠽 󱠾 󱪂 󱜛 󰳕 󰳖 󰳗 󰕃 󰕄 󰦯 󰼭 󰯚 󰕈 󱃄 󱃅 󰟹 󰕉 󰕊 󱢊 󱢋 󰦰 󱏢 󱏡 󰕋 󰕌 󰕍 󰕎 󰝠 󰕏 󰝡 󰕐 󰻐 󱗂 󱗃 󱗥 󰚯 󰦱 󰚰 󰕒 󱍳 󱍴 󰠽 󰛶 󰳘 󱃆 󱃇 󰸇 󰕓 󱊞 󱊟 󱇰 󱦡 󱦢 󱁦 󱁧 󱁨 󰟺 󰟻 󰟼 󱕔 󱇡 󰫧 󱄑 󰕔 󰕕 󰫨 󰕖 󰕗 󰕘 󰕙 󰕚 󰕛 󰕜 󰢓 󰕝 󰕞 󰿨 󰕟 󰕠 󱡖 󰕡 󱈥 󱈦 󱈧 󱈨 󰝊 󰗆 󰕢 󰀁 󱡗 󱣙 󱣚 󱡘 󱣛 󱣜 󰕣 󰕤 󰨛 󰕦 󰳙 󰕧 󱨜 󰟽 󱏙 󰻑 󰠾 󰤙 󰃽 󰃾 󱁩 󱁪 󱔮 󰤚 󰠿 󰡀 󰡁 󰾌 󰡂 󱦩 󱦪 󰦲 󰊺 󰕨 󰯛 󰯜 󰦳 󰇓 󰤛 󰕩 󰞐 󰨜 󰻒 󰻓 󰕪 󱇘 󰕫 󱒅 󰕬 󱒆 󰕭 󱒇 󰹪 󱒈 󰹫 󰹬 󰕮 󱥇 󱥈 󰨝 󰡃 󱒉 󰕯 󱒊 󱢈 󱢉 󰕰 󱇙 󰾍 󱇚 󰕱 󰕲 󱒋 󰕳 󱒌 󰜨 󱒍 󰕴 󱒎 󰜩 󱒏 󰯋 󰯌 󰕵 󱒐 󰕶 󱒑 󰕷 󰘏 󰢔 󱎶 󱣡 󱣢 󱎷 󰕼 󰕽 󱪃 󱪄 󰦴 󰕾 󰕿 󰖀 󰝞 󰝟 󰖁 󰝝 󱄠 󰸈 󱄡 󰨟 󰨠 󰖂 󰡄 󰹭 󰖃 󰟾 󱨑 󰤜 󰤝 󱟉 󰐜 󱟊 󱟋 󰝈 󱟌 󰤞 󱟍 󰖄 󰖅 󰖆 󰯝 󰾎 󰾏 󰖇 󰸉 󰖈 󰾐 󰾑 󰾁 󰜪 󱆼 󱆽 󰖉 󰖊 󰢕 󰖋 󰢖 󰢗 󰚱 󰳚 󰖌 󱔂 󱔃 󰾒 󱆳 󱆴 󱔄 󱔅 󱠆 󱔆 󱔇 󰖍 󱔈 󱡕 󰸊 󰖎 󱔉 󱔊 󱔋 󱊠 󰖏 󰾓 󱔌 󱔍 󱟆 󱪅 󱪆 󱁫 󱁬 󱡉 󱒁 󱒂 󰘒 󰼮 󱑽 󰞍 󱡙 󱡚 󱡛 󰯞 󰖐 󰼯 󰹮 󱣶 󰖑 󰖒 󰼰 󰢘 󰖓 󰙾 󰖔 󰼱 󰖕 󰼲 󰼳 󰼴 󰼵 󰖖 󰖗 󰖘 󰼶 󰙿 󰖙 󰼷 󱓤 󰖚 󰖛 󰖜 󰼸 󰖝 󰖞 󰖟 󰾔 󱞐 󰞉 󱉊 󱂠 󰪎 󰀳 󱞑 󰕑 󱞒 󰖠 󱜷 󰘯 󰜫 󱉈 󰘑 󰖡 󰴿 󰖢 󱅝 󰦵 󰖣 󱓲 󱪇 󰖤 󰦶 󱊼 󰖥 󰖦 󰖧 󰖨 󰜬 󱍕 󰖩 󱚵 󱚶 󱚷 󱚸 󱚹 󱚺 󱚻 󱚼 󱚽 󱚾 󱚿 󱛀 󱛁 󱛂 󰖪 󱛃 󱛄 󱛅 󱛆 󰸋 󰤟 󰤠 󰤡 󱛋 󰤢 󰤣 󰤤 󱛌 󰤥 󰤦 󰤧 󱛍 󰤨 󰤩 󰤪 󱛎 󰤫 󱛏 󰤬 󰤭 󰤮 󰤯 󱛇 󰖬 󱪈 󱪉 󰶥 󱦫 󱦬 󰖭 󰖮 󱇛 󰖯 󰖰 󰖱 󱇜 󰖲 󱄜 󱄝 󱪊 󱄞 󱪋 󱗺 󰫩 󰶦 󱣟 󱑷 󰖴 󰖶 󰯟 󰖷 󱦣 󰯠 󰡅 󰗀 󰟿 󰭏 󰗁 󰚀 󱅼 󰗃 󰡈 󰡇 󰵀 󰑈 󱔖 󰫪 󰫫 󰵁 󰗄 󰿺 󰨣 󰩽 󰩾 󰩿 󰪀 󰪁 󰪂 󰪃 󰪄 󰪅 󰪆 󰪇 󰪈                                                                                                                                              ♥                                                                                                                                                                      ⚡                                                                                                                                                                                                                                                                                                                                                                                                                                                                    diff --git a/.local/share/script-data/chars/nerd-glyphs.json b/.local/share/script-data/chars/nerd-glyphs.json new file mode 100644 index 0000000..897ea9c --- /dev/null +++ b/.local/share/script-data/chars/nerd-glyphs.json @@ -0,0 +1 @@ +{"METADATA":{"website":"https://www.nerdfonts.com","development-website":"https://github.com/ryanoasis/nerd-fonts","version":"3.2.1","date":"2024-04-12 14:40:46+00:00"},"cod-account":{"char":"","code":"eb99"},"cod-activate_breakpoints":{"char":"","code":"ea97"},"cod-add":{"char":"","code":"ea60"},"cod-archive":{"char":"","code":"ea98"},"cod-arrow_both":{"char":"","code":"ea99"},"cod-arrow_circle_down":{"char":"","code":"ebfc"},"cod-arrow_circle_left":{"char":"","code":"ebfd"},"cod-arrow_circle_right":{"char":"","code":"ebfe"},"cod-arrow_circle_up":{"char":"","code":"ebff"},"cod-arrow_down":{"char":"","code":"ea9a"},"cod-arrow_left":{"char":"","code":"ea9b"},"cod-arrow_right":{"char":"","code":"ea9c"},"cod-arrow_small_down":{"char":"","code":"ea9d"},"cod-arrow_small_left":{"char":"","code":"ea9e"},"cod-arrow_small_right":{"char":"","code":"ea9f"},"cod-arrow_small_up":{"char":"","code":"eaa0"},"cod-arrow_swap":{"char":"","code":"ebcb"},"cod-arrow_up":{"char":"","code":"eaa1"},"cod-azure":{"char":"","code":"ebd8"},"cod-azure_devops":{"char":"","code":"ebe8"},"cod-beaker":{"char":"","code":"ea79"},"cod-beaker_stop":{"char":"","code":"ebe1"},"cod-bell":{"char":"","code":"eaa2"},"cod-bell_dot":{"char":"","code":"eb9a"},"cod-bell_slash":{"char":"","code":"ec08"},"cod-bell_slash_dot":{"char":"","code":"ec09"},"cod-blank":{"char":"","code":"ec03"},"cod-bold":{"char":"","code":"eaa3"},"cod-book":{"char":"","code":"eaa4"},"cod-bookmark":{"char":"","code":"eaa5"},"cod-bracket_dot":{"char":"","code":"ebe5"},"cod-bracket_error":{"char":"","code":"ebe6"},"cod-briefcase":{"char":"","code":"eaac"},"cod-broadcast":{"char":"","code":"eaad"},"cod-browser":{"char":"","code":"eaae"},"cod-bug":{"char":"","code":"eaaf"},"cod-calendar":{"char":"","code":"eab0"},"cod-call_incoming":{"char":"","code":"eb92"},"cod-call_outgoing":{"char":"","code":"eb93"},"cod-case_sensitive":{"char":"","code":"eab1"},"cod-check":{"char":"","code":"eab2"},"cod-check_all":{"char":"","code":"ebb1"},"cod-checklist":{"char":"","code":"eab3"},"cod-chevron_down":{"char":"","code":"eab4"},"cod-chevron_left":{"char":"","code":"eab5"},"cod-chevron_right":{"char":"","code":"eab6"},"cod-chevron_up":{"char":"","code":"eab7"},"cod-chip":{"char":"","code":"ec19"},"cod-chrome_close":{"char":"","code":"eab8"},"cod-chrome_maximize":{"char":"","code":"eab9"},"cod-chrome_minimize":{"char":"","code":"eaba"},"cod-chrome_restore":{"char":"","code":"eabb"},"cod-circle":{"char":"","code":"eabc"},"cod-circle_filled":{"char":"","code":"ea71"},"cod-circle_large":{"char":"","code":"ebb5"},"cod-circle_large_filled":{"char":"","code":"ebb4"},"cod-circle_slash":{"char":"","code":"eabd"},"cod-circle_small":{"char":"","code":"ec07"},"cod-circle_small_filled":{"char":"","code":"eb8a"},"cod-circuit_board":{"char":"","code":"eabe"},"cod-clear_all":{"char":"","code":"eabf"},"cod-clippy":{"char":"","code":"eac0"},"cod-close":{"char":"","code":"ea76"},"cod-close_all":{"char":"","code":"eac1"},"cod-cloud":{"char":"","code":"ebaa"},"cod-cloud_download":{"char":"","code":"eac2"},"cod-cloud_upload":{"char":"","code":"eac3"},"cod-code":{"char":"","code":"eac4"},"cod-coffee":{"char":"","code":"ec15"},"cod-collapse_all":{"char":"","code":"eac5"},"cod-color_mode":{"char":"","code":"eac6"},"cod-combine":{"char":"","code":"ebb6"},"cod-comment":{"char":"","code":"ea6b"},"cod-comment_discussion":{"char":"","code":"eac7"},"cod-comment_draft":{"char":"","code":"ec0e"},"cod-comment_unresolved":{"char":"","code":"ec0a"},"cod-compass":{"char":"","code":"ebd5"},"cod-compass_active":{"char":"","code":"ebd7"},"cod-compass_dot":{"char":"","code":"ebd6"},"cod-copilot":{"char":"","code":"ec1e"},"cod-copy":{"char":"","code":"ebcc"},"cod-credit_card":{"char":"","code":"eac9"},"cod-dash":{"char":"","code":"eacc"},"cod-dashboard":{"char":"","code":"eacd"},"cod-database":{"char":"","code":"eace"},"cod-debug":{"char":"","code":"ead8"},"cod-debug_all":{"char":"","code":"ebdc"},"cod-debug_alt":{"char":"","code":"eb91"},"cod-debug_alt_small":{"char":"","code":"eba8"},"cod-debug_breakpoint_conditional":{"char":"","code":"eaa7"},"cod-debug_breakpoint_conditional_unverified":{"char":"","code":"eaa6"},"cod-debug_breakpoint_data":{"char":"","code":"eaa9"},"cod-debug_breakpoint_data_unverified":{"char":"","code":"eaa8"},"cod-debug_breakpoint_function":{"char":"","code":"eb88"},"cod-debug_breakpoint_function_unverified":{"char":"","code":"eb87"},"cod-debug_breakpoint_log":{"char":"","code":"eaab"},"cod-debug_breakpoint_log_unverified":{"char":"","code":"eaaa"},"cod-debug_breakpoint_unsupported":{"char":"","code":"eb8c"},"cod-debug_console":{"char":"","code":"eb9b"},"cod-debug_continue":{"char":"","code":"eacf"},"cod-debug_continue_small":{"char":"","code":"ebe0"},"cod-debug_coverage":{"char":"","code":"ebdd"},"cod-debug_disconnect":{"char":"","code":"ead0"},"cod-debug_line_by_line":{"char":"","code":"ebd0"},"cod-debug_pause":{"char":"","code":"ead1"},"cod-debug_rerun":{"char":"","code":"ebc0"},"cod-debug_restart":{"char":"","code":"ead2"},"cod-debug_restart_frame":{"char":"","code":"eb90"},"cod-debug_reverse_continue":{"char":"","code":"eb8e"},"cod-debug_stackframe":{"char":"","code":"eb8b"},"cod-debug_stackframe_active":{"char":"","code":"eb89"},"cod-debug_start":{"char":"","code":"ead3"},"cod-debug_step_back":{"char":"","code":"eb8f"},"cod-debug_step_into":{"char":"","code":"ead4"},"cod-debug_step_out":{"char":"","code":"ead5"},"cod-debug_step_over":{"char":"","code":"ead6"},"cod-debug_stop":{"char":"","code":"ead7"},"cod-desktop_download":{"char":"","code":"ea78"},"cod-device_camera":{"char":"","code":"eada"},"cod-device_camera_video":{"char":"","code":"ead9"},"cod-device_mobile":{"char":"","code":"eadb"},"cod-diff":{"char":"","code":"eae1"},"cod-diff_added":{"char":"","code":"eadc"},"cod-diff_ignored":{"char":"","code":"eadd"},"cod-diff_modified":{"char":"","code":"eade"},"cod-diff_removed":{"char":"","code":"eadf"},"cod-diff_renamed":{"char":"","code":"eae0"},"cod-discard":{"char":"","code":"eae2"},"cod-edit":{"char":"","code":"ea73"},"cod-editor_layout":{"char":"","code":"eae3"},"cod-ellipsis":{"char":"","code":"ea7c"},"cod-empty_window":{"char":"","code":"eae4"},"cod-error":{"char":"","code":"ea87"},"cod-error_small":{"char":"","code":"ebfb"},"cod-exclude":{"char":"","code":"eae5"},"cod-expand_all":{"char":"","code":"eb95"},"cod-export":{"char":"","code":"ebac"},"cod-extensions":{"char":"","code":"eae6"},"cod-eye":{"char":"","code":"ea70"},"cod-eye_closed":{"char":"","code":"eae7"},"cod-feedback":{"char":"","code":"eb96"},"cod-file":{"char":"","code":"ea7b"},"cod-file_binary":{"char":"","code":"eae8"},"cod-file_code":{"char":"","code":"eae9"},"cod-file_media":{"char":"","code":"eaea"},"cod-file_pdf":{"char":"","code":"eaeb"},"cod-file_submodule":{"char":"","code":"eaec"},"cod-file_symlink_directory":{"char":"","code":"eaed"},"cod-file_symlink_file":{"char":"","code":"eaee"},"cod-file_zip":{"char":"","code":"eaef"},"cod-files":{"char":"","code":"eaf0"},"cod-filter":{"char":"","code":"eaf1"},"cod-filter_filled":{"char":"","code":"ebce"},"cod-flame":{"char":"","code":"eaf2"},"cod-fold":{"char":"","code":"eaf5"},"cod-fold_down":{"char":"","code":"eaf3"},"cod-fold_up":{"char":"","code":"eaf4"},"cod-folder":{"char":"","code":"ea83"},"cod-folder_active":{"char":"","code":"eaf6"},"cod-folder_library":{"char":"","code":"ebdf"},"cod-folder_opened":{"char":"","code":"eaf7"},"cod-game":{"char":"","code":"ec17"},"cod-gear":{"char":"","code":"eaf8"},"cod-gift":{"char":"","code":"eaf9"},"cod-gist_secret":{"char":"","code":"eafa"},"cod-git_commit":{"char":"","code":"eafc"},"cod-git_compare":{"char":"","code":"eafd"},"cod-git_fetch":{"char":"","code":"ec1d"},"cod-git_merge":{"char":"","code":"eafe"},"cod-git_pull_request":{"char":"","code":"ea64"},"cod-git_pull_request_closed":{"char":"","code":"ebda"},"cod-git_pull_request_create":{"char":"","code":"ebbc"},"cod-git_pull_request_draft":{"char":"","code":"ebdb"},"cod-git_pull_request_go_to_changes":{"char":"","code":"ec0b"},"cod-git_pull_request_new_changes":{"char":"","code":"ec0c"},"cod-github":{"char":"","code":"ea84"},"cod-github_action":{"char":"","code":"eaff"},"cod-github_alt":{"char":"","code":"eb00"},"cod-github_inverted":{"char":"","code":"eba1"},"cod-globe":{"char":"","code":"eb01"},"cod-go_to_file":{"char":"","code":"ea94"},"cod-grabber":{"char":"","code":"eb02"},"cod-graph":{"char":"","code":"eb03"},"cod-graph_left":{"char":"","code":"ebad"},"cod-graph_line":{"char":"","code":"ebe2"},"cod-graph_scatter":{"char":"","code":"ebe3"},"cod-gripper":{"char":"","code":"eb04"},"cod-group_by_ref_type":{"char":"","code":"eb97"},"cod-heart":{"char":"","code":"eb05"},"cod-heart_filled":{"char":"","code":"ec04"},"cod-history":{"char":"","code":"ea82"},"cod-home":{"char":"","code":"eb06"},"cod-horizontal_rule":{"char":"","code":"eb07"},"cod-hubot":{"char":"","code":"eb08"},"cod-inbox":{"char":"","code":"eb09"},"cod-indent":{"char":"","code":"ebf9"},"cod-info":{"char":"","code":"ea74"},"cod-insert":{"char":"","code":"ec11"},"cod-inspect":{"char":"","code":"ebd1"},"cod-issue_draft":{"char":"","code":"ebd9"},"cod-issue_reopened":{"char":"","code":"eb0b"},"cod-issues":{"char":"","code":"eb0c"},"cod-italic":{"char":"","code":"eb0d"},"cod-jersey":{"char":"","code":"eb0e"},"cod-json":{"char":"","code":"eb0f"},"cod-kebab_vertical":{"char":"","code":"eb10"},"cod-key":{"char":"","code":"eb11"},"cod-law":{"char":"","code":"eb12"},"cod-layers":{"char":"","code":"ebd2"},"cod-layers_active":{"char":"","code":"ebd4"},"cod-layers_dot":{"char":"","code":"ebd3"},"cod-layout":{"char":"","code":"ebeb"},"cod-layout_activitybar_left":{"char":"","code":"ebec"},"cod-layout_activitybar_right":{"char":"","code":"ebed"},"cod-layout_centered":{"char":"","code":"ebf7"},"cod-layout_menubar":{"char":"","code":"ebf6"},"cod-layout_panel":{"char":"","code":"ebf2"},"cod-layout_panel_center":{"char":"","code":"ebef"},"cod-layout_panel_justify":{"char":"","code":"ebf0"},"cod-layout_panel_left":{"char":"","code":"ebee"},"cod-layout_panel_off":{"char":"","code":"ec01"},"cod-layout_panel_right":{"char":"","code":"ebf1"},"cod-layout_sidebar_left":{"char":"","code":"ebf3"},"cod-layout_sidebar_left_off":{"char":"","code":"ec02"},"cod-layout_sidebar_right":{"char":"","code":"ebf4"},"cod-layout_sidebar_right_off":{"char":"","code":"ec00"},"cod-layout_statusbar":{"char":"","code":"ebf5"},"cod-library":{"char":"","code":"eb9c"},"cod-lightbulb":{"char":"","code":"ea61"},"cod-lightbulb_autofix":{"char":"","code":"eb13"},"cod-link":{"char":"","code":"eb15"},"cod-link_external":{"char":"","code":"eb14"},"cod-list_filter":{"char":"","code":"eb83"},"cod-list_flat":{"char":"","code":"eb84"},"cod-list_ordered":{"char":"","code":"eb16"},"cod-list_selection":{"char":"","code":"eb85"},"cod-list_tree":{"char":"","code":"eb86"},"cod-list_unordered":{"char":"","code":"eb17"},"cod-live_share":{"char":"","code":"eb18"},"cod-loading":{"char":"","code":"eb19"},"cod-location":{"char":"","code":"eb1a"},"cod-lock":{"char":"","code":"ea75"},"cod-lock_small":{"char":"","code":"ebe7"},"cod-magnet":{"char":"","code":"ebae"},"cod-mail":{"char":"","code":"eb1c"},"cod-mail_read":{"char":"","code":"eb1b"},"cod-map":{"char":"","code":"ec05"},"cod-map_filled":{"char":"","code":"ec06"},"cod-markdown":{"char":"","code":"eb1d"},"cod-megaphone":{"char":"","code":"eb1e"},"cod-mention":{"char":"","code":"eb1f"},"cod-menu":{"char":"","code":"eb94"},"cod-merge":{"char":"","code":"ebab"},"cod-mic":{"char":"","code":"ec12"},"cod-mic_filled":{"char":"","code":"ec1c"},"cod-milestone":{"char":"","code":"eb20"},"cod-mirror":{"char":"","code":"ea69"},"cod-mortar_board":{"char":"","code":"eb21"},"cod-move":{"char":"","code":"eb22"},"cod-multiple_windows":{"char":"","code":"eb23"},"cod-music":{"char":"","code":"ec1b"},"cod-mute":{"char":"","code":"eb24"},"cod-new_file":{"char":"","code":"ea7f"},"cod-new_folder":{"char":"","code":"ea80"},"cod-newline":{"char":"","code":"ebea"},"cod-no_newline":{"char":"","code":"eb25"},"cod-note":{"char":"","code":"eb26"},"cod-notebook":{"char":"","code":"ebaf"},"cod-notebook_template":{"char":"","code":"ebbf"},"cod-octoface":{"char":"","code":"eb27"},"cod-open_preview":{"char":"","code":"eb28"},"cod-organization":{"char":"","code":"ea7e"},"cod-output":{"char":"","code":"eb9d"},"cod-package":{"char":"","code":"eb29"},"cod-paintcan":{"char":"","code":"eb2a"},"cod-pass":{"char":"","code":"eba4"},"cod-pass_filled":{"char":"","code":"ebb3"},"cod-person":{"char":"","code":"ea67"},"cod-person_add":{"char":"","code":"ebcd"},"cod-piano":{"char":"","code":"ec1a"},"cod-pie_chart":{"char":"","code":"ebe4"},"cod-pin":{"char":"","code":"eb2b"},"cod-pinned":{"char":"","code":"eba0"},"cod-pinned_dirty":{"char":"","code":"ebb2"},"cod-play":{"char":"","code":"eb2c"},"cod-play_circle":{"char":"","code":"eba6"},"cod-plug":{"char":"","code":"eb2d"},"cod-preserve_case":{"char":"","code":"eb2e"},"cod-preview":{"char":"","code":"eb2f"},"cod-primitive_square":{"char":"","code":"ea72"},"cod-project":{"char":"","code":"eb30"},"cod-pulse":{"char":"","code":"eb31"},"cod-question":{"char":"","code":"eb32"},"cod-quote":{"char":"","code":"eb33"},"cod-radio_tower":{"char":"","code":"eb34"},"cod-reactions":{"char":"","code":"eb35"},"cod-record":{"char":"","code":"eba7"},"cod-record_keys":{"char":"","code":"ea65"},"cod-record_small":{"char":"","code":"ebfa"},"cod-redo":{"char":"","code":"ebb0"},"cod-references":{"char":"","code":"eb36"},"cod-refresh":{"char":"","code":"eb37"},"cod-regex":{"char":"","code":"eb38"},"cod-remote":{"char":"","code":"eb3a"},"cod-remote_explorer":{"char":"","code":"eb39"},"cod-remove":{"char":"","code":"eb3b"},"cod-replace":{"char":"","code":"eb3d"},"cod-replace_all":{"char":"","code":"eb3c"},"cod-reply":{"char":"","code":"ea7d"},"cod-repo":{"char":"","code":"ea62"},"cod-repo_clone":{"char":"","code":"eb3e"},"cod-repo_force_push":{"char":"","code":"eb3f"},"cod-repo_forked":{"char":"","code":"ea63"},"cod-repo_pull":{"char":"","code":"eb40"},"cod-repo_push":{"char":"","code":"eb41"},"cod-report":{"char":"","code":"eb42"},"cod-request_changes":{"char":"","code":"eb43"},"cod-rocket":{"char":"","code":"eb44"},"cod-root_folder":{"char":"","code":"eb46"},"cod-root_folder_opened":{"char":"","code":"eb45"},"cod-rss":{"char":"","code":"eb47"},"cod-ruby":{"char":"","code":"eb48"},"cod-run_above":{"char":"","code":"ebbd"},"cod-run_all":{"char":"","code":"eb9e"},"cod-run_below":{"char":"","code":"ebbe"},"cod-run_errors":{"char":"","code":"ebde"},"cod-save":{"char":"","code":"eb4b"},"cod-save_all":{"char":"","code":"eb49"},"cod-save_as":{"char":"","code":"eb4a"},"cod-screen_full":{"char":"","code":"eb4c"},"cod-screen_normal":{"char":"","code":"eb4d"},"cod-search":{"char":"","code":"ea6d"},"cod-search_fuzzy":{"char":"","code":"ec0d"},"cod-search_stop":{"char":"","code":"eb4e"},"cod-send":{"char":"","code":"ec0f"},"cod-server":{"char":"","code":"eb50"},"cod-server_environment":{"char":"","code":"eba3"},"cod-server_process":{"char":"","code":"eba2"},"cod-settings":{"char":"","code":"eb52"},"cod-settings_gear":{"char":"","code":"eb51"},"cod-shield":{"char":"","code":"eb53"},"cod-sign_in":{"char":"","code":"ea6f"},"cod-sign_out":{"char":"","code":"ea6e"},"cod-smiley":{"char":"","code":"eb54"},"cod-snake":{"char":"","code":"ec16"},"cod-sort_precedence":{"char":"","code":"eb55"},"cod-source_control":{"char":"","code":"ea68"},"cod-sparkle":{"char":"","code":"ec10"},"cod-split_horizontal":{"char":"","code":"eb56"},"cod-split_vertical":{"char":"","code":"eb57"},"cod-squirrel":{"char":"","code":"eb58"},"cod-star_empty":{"char":"","code":"ea6a"},"cod-star_full":{"char":"","code":"eb59"},"cod-star_half":{"char":"","code":"eb5a"},"cod-stop_circle":{"char":"","code":"eba5"},"cod-symbol_array":{"char":"","code":"ea8a"},"cod-symbol_boolean":{"char":"","code":"ea8f"},"cod-symbol_class":{"char":"","code":"eb5b"},"cod-symbol_color":{"char":"","code":"eb5c"},"cod-symbol_constant":{"char":"","code":"eb5d"},"cod-symbol_enum":{"char":"","code":"ea95"},"cod-symbol_enum_member":{"char":"","code":"eb5e"},"cod-symbol_event":{"char":"","code":"ea86"},"cod-symbol_field":{"char":"","code":"eb5f"},"cod-symbol_file":{"char":"","code":"eb60"},"cod-symbol_interface":{"char":"","code":"eb61"},"cod-symbol_key":{"char":"","code":"ea93"},"cod-symbol_keyword":{"char":"","code":"eb62"},"cod-symbol_method":{"char":"","code":"ea8c"},"cod-symbol_misc":{"char":"","code":"eb63"},"cod-symbol_namespace":{"char":"","code":"ea8b"},"cod-symbol_numeric":{"char":"","code":"ea90"},"cod-symbol_operator":{"char":"","code":"eb64"},"cod-symbol_parameter":{"char":"","code":"ea92"},"cod-symbol_property":{"char":"","code":"eb65"},"cod-symbol_ruler":{"char":"","code":"ea96"},"cod-symbol_snippet":{"char":"","code":"eb66"},"cod-symbol_string":{"char":"","code":"eb8d"},"cod-symbol_structure":{"char":"","code":"ea91"},"cod-symbol_variable":{"char":"","code":"ea88"},"cod-sync":{"char":"","code":"ea77"},"cod-sync_ignored":{"char":"","code":"eb9f"},"cod-table":{"char":"","code":"ebb7"},"cod-tag":{"char":"","code":"ea66"},"cod-target":{"char":"","code":"ebf8"},"cod-tasklist":{"char":"","code":"eb67"},"cod-telescope":{"char":"","code":"eb68"},"cod-terminal":{"char":"","code":"ea85"},"cod-terminal_bash":{"char":"","code":"ebca"},"cod-terminal_cmd":{"char":"","code":"ebc4"},"cod-terminal_debian":{"char":"","code":"ebc5"},"cod-terminal_linux":{"char":"","code":"ebc6"},"cod-terminal_powershell":{"char":"","code":"ebc7"},"cod-terminal_tmux":{"char":"","code":"ebc8"},"cod-terminal_ubuntu":{"char":"","code":"ebc9"},"cod-text_size":{"char":"","code":"eb69"},"cod-three_bars":{"char":"","code":"eb6a"},"cod-thumbsdown":{"char":"","code":"eb6b"},"cod-thumbsdown_filled":{"char":"","code":"ec13"},"cod-thumbsup":{"char":"","code":"eb6c"},"cod-thumbsup_filled":{"char":"","code":"ec14"},"cod-tools":{"char":"","code":"eb6d"},"cod-trash":{"char":"","code":"ea81"},"cod-triangle_down":{"char":"","code":"eb6e"},"cod-triangle_left":{"char":"","code":"eb6f"},"cod-triangle_right":{"char":"","code":"eb70"},"cod-triangle_up":{"char":"","code":"eb71"},"cod-twitter":{"char":"","code":"eb72"},"cod-type_hierarchy":{"char":"","code":"ebb9"},"cod-type_hierarchy_sub":{"char":"","code":"ebba"},"cod-type_hierarchy_super":{"char":"","code":"ebbb"},"cod-unfold":{"char":"","code":"eb73"},"cod-ungroup_by_ref_type":{"char":"","code":"eb98"},"cod-unlock":{"char":"","code":"eb74"},"cod-unmute":{"char":"","code":"eb75"},"cod-unverified":{"char":"","code":"eb76"},"cod-variable_group":{"char":"","code":"ebb8"},"cod-verified":{"char":"","code":"eb77"},"cod-verified_filled":{"char":"","code":"ebe9"},"cod-versions":{"char":"","code":"eb78"},"cod-vm":{"char":"","code":"ea7a"},"cod-vm_active":{"char":"","code":"eb79"},"cod-vm_connect":{"char":"","code":"eba9"},"cod-vm_outline":{"char":"","code":"eb7a"},"cod-vm_running":{"char":"","code":"eb7b"},"cod-vr":{"char":"","code":"ec18"},"cod-wand":{"char":"","code":"ebcf"},"cod-warning":{"char":"","code":"ea6c"},"cod-watch":{"char":"","code":"eb7c"},"cod-whitespace":{"char":"","code":"eb7d"},"cod-whole_word":{"char":"","code":"eb7e"},"cod-window":{"char":"","code":"eb7f"},"cod-word_wrap":{"char":"","code":"eb80"},"cod-workspace_trusted":{"char":"","code":"ebc1"},"cod-workspace_unknown":{"char":"","code":"ebc3"},"cod-workspace_untrusted":{"char":"","code":"ebc2"},"cod-zoom_in":{"char":"","code":"eb81"},"cod-zoom_out":{"char":"","code":"eb82"},"custom-ada":{"char":"","code":"e6b5"},"custom-asm":{"char":"","code":"e6ab"},"custom-astro":{"char":"","code":"e6b3"},"custom-c":{"char":"","code":"e61e"},"custom-common_lisp":{"char":"","code":"e6b0"},"custom-cpp":{"char":"","code":"e61d"},"custom-crystal":{"char":"","code":"e62f"},"custom-default":{"char":"","code":"e612"},"custom-electron":{"char":"","code":"e62e"},"custom-elixir":{"char":"","code":"e62d"},"custom-elm":{"char":"","code":"e62c"},"custom-emacs":{"char":"","code":"e632"},"custom-fennel":{"char":"","code":"e6af"},"custom-folder":{"char":"","code":"e5ff"},"custom-folder_config":{"char":"","code":"e5fc"},"custom-folder_git":{"char":"","code":"e5fb"},"custom-folder_git_branch":{"char":"","code":"e5fb"},"custom-folder_github":{"char":"","code":"e5fd"},"custom-folder_npm":{"char":"","code":"e5fa"},"custom-folder_oct":{"char":"","code":"e6ad"},"custom-folder_open":{"char":"","code":"e5fe"},"custom-go":{"char":"","code":"e626"},"custom-home":{"char":"","code":"e617"},"custom-kotlin":{"char":"","code":"e634"},"custom-msdos":{"char":"","code":"e629"},"custom-neovim":{"char":"","code":"e6ae"},"custom-orgmode":{"char":"","code":"e633"},"custom-play_arrow":{"char":"","code":"e602"},"custom-prettier":{"char":"","code":"e6b4"},"custom-puppet":{"char":"","code":"e631"},"custom-purescript":{"char":"","code":"e630"},"custom-scheme":{"char":"","code":"e6b1"},"custom-toml":{"char":"","code":"e6b2"},"custom-v_lang":{"char":"","code":"e6ac"},"custom-vim":{"char":"","code":"e62b"},"custom-windows":{"char":"","code":"e62a"},"dev-android":{"char":"","code":"e70e"},"dev-angular":{"char":"","code":"e753"},"dev-appcelerator":{"char":"","code":"e7ab"},"dev-apple":{"char":"","code":"e711"},"dev-appstore":{"char":"","code":"e713"},"dev-aptana":{"char":"","code":"e799"},"dev-asterisk":{"char":"","code":"e7ac"},"dev-atlassian":{"char":"","code":"e75b"},"dev-atom":{"char":"","code":"e764"},"dev-aws":{"char":"","code":"e7ad"},"dev-backbone":{"char":"","code":"e752"},"dev-bing_small":{"char":"","code":"e700"},"dev-bintray":{"char":"","code":"e794"},"dev-bitbucket":{"char":"","code":"e703"},"dev-blackberry":{"char":"","code":"e723"},"dev-bootstrap":{"char":"","code":"e747"},"dev-bower":{"char":"","code":"e74d"},"dev-brackets":{"char":"","code":"e79d"},"dev-bugsense":{"char":"","code":"e78d"},"dev-celluloid":{"char":"","code":"e76b"},"dev-chart":{"char":"","code":"e760"},"dev-chrome":{"char":"","code":"e743"},"dev-cisco":{"char":"","code":"e765"},"dev-clojure":{"char":"","code":"e768"},"dev-clojure_alt":{"char":"","code":"e76a"},"dev-cloud9":{"char":"","code":"e79f"},"dev-coda":{"char":"","code":"e793"},"dev-code":{"char":"","code":"e796"},"dev-code_badge":{"char":"","code":"e7a3"},"dev-codeigniter":{"char":"","code":"e780"},"dev-codepen":{"char":"","code":"e716"},"dev-codrops":{"char":"","code":"e72f"},"dev-coffeescript":{"char":"","code":"e751"},"dev-compass":{"char":"","code":"e761"},"dev-composer":{"char":"","code":"e783"},"dev-creativecommons":{"char":"","code":"e789"},"dev-creativecommons_badge":{"char":"","code":"e78a"},"dev-css3":{"char":"","code":"e749"},"dev-css3_full":{"char":"","code":"e74a"},"dev-css_tricks":{"char":"","code":"e701"},"dev-cssdeck":{"char":"","code":"e72a"},"dev-dart":{"char":"","code":"e798"},"dev-database":{"char":"","code":"e706"},"dev-debian":{"char":"","code":"e77d"},"dev-digital_ocean":{"char":"","code":"e7ae"},"dev-django":{"char":"","code":"e71d"},"dev-dlang":{"char":"","code":"e7af"},"dev-docker":{"char":"","code":"e7b0"},"dev-doctrine":{"char":"","code":"e774"},"dev-dojo":{"char":"","code":"e71c"},"dev-dotnet":{"char":"","code":"e77f"},"dev-dreamweaver":{"char":"","code":"e79c"},"dev-dropbox":{"char":"","code":"e707"},"dev-drupal":{"char":"","code":"e742"},"dev-eclipse":{"char":"","code":"e79e"},"dev-ember":{"char":"","code":"e71b"},"dev-envato":{"char":"","code":"e75d"},"dev-erlang":{"char":"","code":"e7b1"},"dev-extjs":{"char":"","code":"e78e"},"dev-firebase":{"char":"","code":"e787"},"dev-firefox":{"char":"","code":"e745"},"dev-fsharp":{"char":"","code":"e7a7"},"dev-ghost":{"char":"","code":"e71f"},"dev-ghost_small":{"char":"","code":"e714"},"dev-git":{"char":"","code":"e702"},"dev-git_branch":{"char":"","code":"e725"},"dev-git_commit":{"char":"","code":"e729"},"dev-git_compare":{"char":"","code":"e728"},"dev-git_merge":{"char":"","code":"e727"},"dev-git_pull_request":{"char":"","code":"e726"},"dev-github":{"char":"","code":"e70a"},"dev-github_alt":{"char":"","code":"e708"},"dev-github_badge":{"char":"","code":"e709"},"dev-github_full":{"char":"","code":"e717"},"dev-gnu":{"char":"","code":"e779"},"dev-go":{"char":"","code":"e724"},"dev-google_cloud_platform":{"char":"","code":"e7b2"},"dev-google_drive":{"char":"","code":"e731"},"dev-grails":{"char":"","code":"e7b3"},"dev-groovy":{"char":"","code":"e775"},"dev-grunt":{"char":"","code":"e74c"},"dev-gulp":{"char":"","code":"e763"},"dev-hackernews":{"char":"","code":"e71a"},"dev-haskell":{"char":"","code":"e777"},"dev-heroku":{"char":"","code":"e77b"},"dev-html5":{"char":"","code":"e736"},"dev-html5_3d_effects":{"char":"","code":"e735"},"dev-html5_connectivity":{"char":"","code":"e734"},"dev-html5_device_access":{"char":"","code":"e733"},"dev-html5_multimedia":{"char":"","code":"e732"},"dev-ie":{"char":"","code":"e744"},"dev-illustrator":{"char":"","code":"e7b4"},"dev-intellij":{"char":"","code":"e7b5"},"dev-ionic":{"char":"","code":"e7a9"},"dev-java":{"char":"","code":"e738"},"dev-javascript":{"char":"","code":"e74e"},"dev-javascript_badge":{"char":"","code":"e781"},"dev-javascript_shield":{"char":"","code":"e74f"},"dev-jekyll_small":{"char":"","code":"e70d"},"dev-jenkins":{"char":"","code":"e767"},"dev-jira":{"char":"","code":"e75c"},"dev-joomla":{"char":"","code":"e741"},"dev-jquery":{"char":"","code":"e750"},"dev-jquery_ui":{"char":"","code":"e754"},"dev-komodo":{"char":"","code":"e792"},"dev-krakenjs":{"char":"","code":"e785"},"dev-krakenjs_badge":{"char":"","code":"e784"},"dev-laravel":{"char":"","code":"e73f"},"dev-less":{"char":"","code":"e758"},"dev-linux":{"char":"","code":"e712"},"dev-magento":{"char":"","code":"e740"},"dev-mailchimp":{"char":"","code":"e79a"},"dev-markdown":{"char":"","code":"e73e"},"dev-materializecss":{"char":"","code":"e7b6"},"dev-meteor":{"char":"","code":"e7a5"},"dev-meteorfull":{"char":"","code":"e7a6"},"dev-mitlicence":{"char":"","code":"e78b"},"dev-modernizr":{"char":"","code":"e720"},"dev-mongodb":{"char":"","code":"e7a4"},"dev-mootools":{"char":"","code":"e790"},"dev-mootools_badge":{"char":"","code":"e78f"},"dev-mozilla":{"char":"","code":"e786"},"dev-msql_server":{"char":"","code":"e77c"},"dev-mysql":{"char":"","code":"e704"},"dev-nancy":{"char":"","code":"e766"},"dev-netbeans":{"char":"","code":"e79b"},"dev-netmagazine":{"char":"","code":"e72e"},"dev-nginx":{"char":"","code":"e776"},"dev-nodejs":{"char":"","code":"e719"},"dev-nodejs_small":{"char":"","code":"e718"},"dev-npm":{"char":"","code":"e71e"},"dev-onedrive":{"char":"","code":"e762"},"dev-openshift":{"char":"","code":"e7b7"},"dev-opensource":{"char":"","code":"e771"},"dev-opera":{"char":"","code":"e746"},"dev-perl":{"char":"","code":"e769"},"dev-phonegap":{"char":"","code":"e730"},"dev-photoshop":{"char":"","code":"e7b8"},"dev-php":{"char":"","code":"e73d"},"dev-postgresql":{"char":"","code":"e76e"},"dev-prolog":{"char":"","code":"e7a1"},"dev-python":{"char":"","code":"e73c"},"dev-rackspace":{"char":"","code":"e7b9"},"dev-raphael":{"char":"","code":"e75f"},"dev-rasberry_pi":{"char":"","code":"e722"},"dev-react":{"char":"","code":"e7ba"},"dev-redhat":{"char":"","code":"e7bb"},"dev-redis":{"char":"","code":"e76d"},"dev-requirejs":{"char":"","code":"e770"},"dev-responsive":{"char":"","code":"e797"},"dev-ruby":{"char":"","code":"e739"},"dev-ruby_on_rails":{"char":"","code":"e73b"},"dev-ruby_rough":{"char":"","code":"e791"},"dev-rust":{"char":"","code":"e7a8"},"dev-safari":{"char":"","code":"e748"},"dev-sass":{"char":"","code":"e74b"},"dev-scala":{"char":"","code":"e737"},"dev-scriptcs":{"char":"","code":"e7bc"},"dev-scrum":{"char":"","code":"e7a0"},"dev-senchatouch":{"char":"","code":"e78c"},"dev-sizzlejs":{"char":"","code":"e788"},"dev-smashing_magazine":{"char":"","code":"e72d"},"dev-snap_svg":{"char":"","code":"e75e"},"dev-sqllite":{"char":"","code":"e7c4"},"dev-stackoverflow":{"char":"","code":"e710"},"dev-streamline":{"char":"","code":"e705"},"dev-stylus":{"char":"","code":"e759"},"dev-sublime":{"char":"","code":"e7aa"},"dev-swift":{"char":"","code":"e755"},"dev-symfony":{"char":"","code":"e756"},"dev-symfony_badge":{"char":"","code":"e757"},"dev-techcrunch":{"char":"","code":"e72c"},"dev-terminal":{"char":"","code":"e795"},"dev-terminal_badge":{"char":"","code":"e7a2"},"dev-travis":{"char":"","code":"e77e"},"dev-trello":{"char":"","code":"e75a"},"dev-typo3":{"char":"","code":"e772"},"dev-ubuntu":{"char":"","code":"e73a"},"dev-uikit":{"char":"","code":"e773"},"dev-unity_small":{"char":"","code":"e721"},"dev-vim":{"char":"","code":"e7c5"},"dev-visualstudio":{"char":"","code":"e70c"},"dev-w3c":{"char":"","code":"e76c"},"dev-webplatform":{"char":"","code":"e76f"},"dev-windows":{"char":"","code":"e70f"},"dev-wordpress":{"char":"","code":"e70b"},"dev-yahoo":{"char":"","code":"e715"},"dev-yahoo_small":{"char":"","code":"e72b"},"dev-yeoman":{"char":"","code":"e77a"},"dev-yii":{"char":"","code":"e782"},"dev-zend":{"char":"","code":"e778"},"fa-500px":{"char":"","code":"f26e"},"fa-accessible_icon":{"char":"","code":"f29b"},"fa-accusoft":{"char":"","code":"f0b7"},"fa-address_book":{"char":"","code":"f2b9"},"fa-address_book_o":{"char":"","code":"f2ba"},"fa-address_card":{"char":"","code":"f2bb"},"fa-address_card_o":{"char":"","code":"f2bc"},"fa-adjust":{"char":"","code":"f042"},"fa-adn":{"char":"","code":"f170"},"fa-adversal":{"char":"","code":"f0b8"},"fa-affiliatetheme":{"char":"","code":"f0b9"},"fa-airbnb":{"char":"","code":"ef93"},"fa-algolia":{"char":"","code":"f0ba"},"fa-align_center":{"char":"","code":"f037"},"fa-align_justify":{"char":"","code":"f039"},"fa-align_left":{"char":"","code":"f036"},"fa-align_right":{"char":"","code":"f038"},"fa-alipay":{"char":"","code":"eebc"},"fa-amazon":{"char":"","code":"f270"},"fa-amazon_pay":{"char":"","code":"ed56"},"fa-ambulance":{"char":"","code":"f0f9"},"fa-american_sign_language_interpreting":{"char":"","code":"f2a3"},"fa-amilia":{"char":"","code":"f0bb"},"fa-anchor":{"char":"","code":"f13d"},"fa-android":{"char":"","code":"f17b"},"fa-angellist":{"char":"","code":"f209"},"fa-angle_double_down":{"char":"","code":"f103"},"fa-angle_double_left":{"char":"","code":"f100"},"fa-angle_double_right":{"char":"","code":"f101"},"fa-angle_double_up":{"char":"","code":"f102"},"fa-angle_down":{"char":"","code":"f107"},"fa-angle_left":{"char":"","code":"f104"},"fa-angle_right":{"char":"","code":"f105"},"fa-angle_up":{"char":"","code":"f106"},"fa-angles_down":{"char":"","code":"f103"},"fa-angles_left":{"char":"","code":"f100"},"fa-angles_right":{"char":"","code":"f101"},"fa-angles_up":{"char":"","code":"f102"},"fa-angrycreative":{"char":"","code":"f0bc"},"fa-angular":{"char":"","code":"ed4b"},"fa-ankh":{"char":"","code":"eebd"},"fa-app_store":{"char":"","code":"f0bd"},"fa-app_store_ios":{"char":"","code":"f0be"},"fa-apper":{"char":"","code":"f0bf"},"fa-apple":{"char":"","code":"f179"},"fa-apple_pay":{"char":"","code":"ed41"},"fa-apple_whole":{"char":"","code":"ee98"},"fa-archive":{"char":"","code":"f187"},"fa-archway":{"char":"","code":"ee20"},"fa-area_chart":{"char":"","code":"f1fe"},"fa-arrow_circle_down":{"char":"","code":"f0ab"},"fa-arrow_circle_left":{"char":"","code":"f0a8"},"fa-arrow_circle_o_down":{"char":"","code":"f01a"},"fa-arrow_circle_o_left":{"char":"","code":"f190"},"fa-arrow_circle_o_right":{"char":"","code":"f18e"},"fa-arrow_circle_o_up":{"char":"","code":"f01b"},"fa-arrow_circle_right":{"char":"","code":"f0a9"},"fa-arrow_circle_up":{"char":"","code":"f0aa"},"fa-arrow_down":{"char":"","code":"f063"},"fa-arrow_down_1_9":{"char":"","code":"f162"},"fa-arrow_down_9_1":{"char":"","code":"efb1"},"fa-arrow_down_a_z":{"char":"","code":"f15d"},"fa-arrow_down_long":{"char":"","code":"f175"},"fa-arrow_down_short_wide":{"char":"","code":"efaf"},"fa-arrow_down_wide_short":{"char":"","code":"f160"},"fa-arrow_down_z_a":{"char":"","code":"efad"},"fa-arrow_left":{"char":"","code":"f060"},"fa-arrow_left_long":{"char":"","code":"f177"},"fa-arrow_pointer":{"char":"","code":"f245"},"fa-arrow_right":{"char":"","code":"f061"},"fa-arrow_right_arrow_left":{"char":"","code":"f0ec"},"fa-arrow_right_from_bracket":{"char":"","code":"f08b"},"fa-arrow_right_long":{"char":"","code":"f178"},"fa-arrow_right_to_bracket":{"char":"","code":"f090"},"fa-arrow_rotate_left":{"char":"","code":"f0e2"},"fa-arrow_rotate_right":{"char":"","code":"f01e"},"fa-arrow_turn_down":{"char":"","code":"f149"},"fa-arrow_turn_up":{"char":"","code":"f148"},"fa-arrow_up":{"char":"","code":"f062"},"fa-arrow_up_1_9":{"char":"","code":"f163"},"fa-arrow_up_9_1":{"char":"","code":"efb2"},"fa-arrow_up_a_z":{"char":"","code":"f15e"},"fa-arrow_up_long":{"char":"","code":"f176"},"fa-arrow_up_right_from_square":{"char":"","code":"f08e"},"fa-arrow_up_short_wide":{"char":"","code":"efb0"},"fa-arrow_up_wide_short":{"char":"","code":"f161"},"fa-arrow_up_z_a":{"char":"","code":"efae"},"fa-arrows":{"char":"","code":"f047"},"fa-arrows_alt":{"char":"","code":"f0b2"},"fa-arrows_h":{"char":"","code":"f07e"},"fa-arrows_left_right":{"char":"","code":"f07e"},"fa-arrows_rotate":{"char":"","code":"f021"},"fa-arrows_up_down":{"char":"","code":"f07d"},"fa-arrows_up_down_left_right":{"char":"","code":"f047"},"fa-arrows_v":{"char":"","code":"f07d"},"fa-artstation":{"char":"","code":"ef31"},"fa-asl_interpreting":{"char":"","code":"f2a3"},"fa-assistive_listening_systems":{"char":"","code":"f2a2"},"fa-asterisk":{"char":"","code":"f069"},"fa-asymmetrik":{"char":"","code":"f0cf"},"fa-at":{"char":"","code":"f1fa"},"fa-atlassian":{"char":"","code":"ef32"},"fa-atom":{"char":"","code":"ee99"},"fa-audible":{"char":"","code":"f0df"},"fa-audio_description":{"char":"","code":"f29e"},"fa-automobile":{"char":"","code":"f1b9"},"fa-autoprefixer":{"char":"","code":"ed47"},"fa-avianex":{"char":"","code":"efc2"},"fa-aviato":{"char":"","code":"ed4c"},"fa-award":{"char":"","code":"ee22"},"fa-aws":{"char":"","code":"f0ef"},"fa-baby":{"char":"","code":"ef33"},"fa-baby_carriage":{"char":"","code":"ef34"},"fa-backward":{"char":"","code":"f04a"},"fa-backward_fast":{"char":"","code":"f049"},"fa-backward_step":{"char":"","code":"f048"},"fa-bacon":{"char":"","code":"ef77"},"fa-bag_shopping":{"char":"","code":"f290"},"fa-bahai":{"char":"","code":"eecb"},"fa-balance_scale":{"char":"","code":"f24e"},"fa-ban":{"char":"","code":"f05e"},"fa-ban_smoking":{"char":"","code":"ee16"},"fa-bandage":{"char":"","code":"ed74"},"fa-bandcamp":{"char":"","code":"f2d5"},"fa-bank":{"char":"","code":"f19c"},"fa-bar_chart":{"char":"","code":"f080"},"fa-bar_chart_o":{"char":"","code":"f080"},"fa-barcode":{"char":"","code":"f02a"},"fa-bars":{"char":"","code":"f0c9"},"fa-bars_progress":{"char":"","code":"ef8f"},"fa-bars_staggered":{"char":"","code":"ee19"},"fa-baseball":{"char":"","code":"ed5c"},"fa-baseball_bat_ball":{"char":"","code":"ed5b"},"fa-basket_shopping":{"char":"","code":"f291"},"fa-basketball":{"char":"","code":"ed5d"},"fa-bath":{"char":"","code":"f2cd"},"fa-bathtub":{"char":"","code":"f2cd"},"fa-battery":{"char":"","code":"f240"},"fa-battery_0":{"char":"","code":"f244"},"fa-battery_1":{"char":"","code":"f243"},"fa-battery_2":{"char":"","code":"f242"},"fa-battery_3":{"char":"","code":"f241"},"fa-battery_4":{"char":"","code":"f240"},"fa-battery_empty":{"char":"","code":"f244"},"fa-battery_full":{"char":"","code":"f240"},"fa-battery_half":{"char":"","code":"f242"},"fa-battery_quarter":{"char":"","code":"f243"},"fa-battery_three_quarters":{"char":"","code":"f241"},"fa-battle_net":{"char":"","code":"ef94"},"fa-bed":{"char":"","code":"f236"},"fa-bed_pulse":{"char":"","code":"ed8a"},"fa-beer":{"char":"","code":"f0fc"},"fa-beer_mug_empty":{"char":"","code":"f0fc"},"fa-behance":{"char":"","code":"f1b4"},"fa-behance_square":{"char":"","code":"f1b5"},"fa-bell":{"char":"","code":"f0f3"},"fa-bell_concierge":{"char":"","code":"ee2b"},"fa-bell_o":{"char":"","code":"f0a2"},"fa-bell_slash":{"char":"","code":"f1f6"},"fa-bell_slash_o":{"char":"","code":"f1f7"},"fa-bezier_curve":{"char":"","code":"ee24"},"fa-bicycle":{"char":"","code":"f206"},"fa-bimobject":{"char":"","code":"f0ff"},"fa-binoculars":{"char":"","code":"f1e5"},"fa-biohazard":{"char":"","code":"ef35"},"fa-birthday_cake":{"char":"","code":"f1fd"},"fa-bitbucket":{"char":"","code":"f171"},"fa-bitbucket_square":{"char":"","code":"f172"},"fa-bitcoin":{"char":"","code":"f10f"},"fa-bity":{"char":"","code":"f116"},"fa-black_tie":{"char":"","code":"f27e"},"fa-blackberry":{"char":"","code":"f117"},"fa-blender":{"char":"","code":"ede1"},"fa-blender_phone":{"char":"","code":"eeea"},"fa-blind":{"char":"","code":"f29d"},"fa-blog":{"char":"","code":"ef36"},"fa-blogger":{"char":"","code":"f11f"},"fa-blogger_b":{"char":"","code":"f12f"},"fa-bluetooth":{"char":"","code":"f293"},"fa-bluetooth_b":{"char":"","code":"f294"},"fa-bold":{"char":"","code":"f032"},"fa-bolt":{"char":"","code":"f0e7"},"fa-bomb":{"char":"","code":"f1e2"},"fa-bone":{"char":"","code":"ee9a"},"fa-bong":{"char":"","code":"ee25"},"fa-book":{"char":"","code":"f02d"},"fa-book_atlas":{"char":"","code":"ee21"},"fa-book_bible":{"char":"","code":"eebe"},"fa-book_journal_whills":{"char":"","code":"eecd"},"fa-book_medical":{"char":"","code":"ef78"},"fa-book_open":{"char":"","code":"ede2"},"fa-book_open_reader":{"char":"","code":"ee9b"},"fa-book_quran":{"char":"","code":"eedc"},"fa-book_skull":{"char":"","code":"eeeb"},"fa-book_tanakh":{"char":"","code":"ef8e"},"fa-bookmark":{"char":"","code":"f02e"},"fa-bookmark_o":{"char":"","code":"f097"},"fa-bootstrap":{"char":"","code":"ef95"},"fa-border_all":{"char":"","code":"efa3"},"fa-border_none":{"char":"","code":"efa4"},"fa-border_top_left":{"char":"","code":"efa5"},"fa-bowling_ball":{"char":"","code":"ed5e"},"fa-box":{"char":"","code":"ed75"},"fa-box_archive":{"char":"","code":"f187"},"fa-box_open":{"char":"","code":"ed95"},"fa-boxes_stacked":{"char":"","code":"ed76"},"fa-braille":{"char":"","code":"f2a1"},"fa-brain":{"char":"","code":"ee9c"},"fa-bread_slice":{"char":"","code":"ef79"},"fa-briefcase":{"char":"","code":"f0b1"},"fa-briefcase_medical":{"char":"","code":"ed77"},"fa-broom":{"char":"","code":"ede4"},"fa-broom_ball":{"char":"","code":"ed6e"},"fa-brush":{"char":"","code":"ee26"},"fa-btc":{"char":"","code":"f15a"},"fa-buffer":{"char":"","code":"ef96"},"fa-bug":{"char":"","code":"f188"},"fa-building":{"char":"","code":"f1ad"},"fa-building_columns":{"char":"","code":"f19c"},"fa-building_o":{"char":"","code":"f0f7"},"fa-bullhorn":{"char":"","code":"f0a1"},"fa-bullseye":{"char":"","code":"f140"},"fa-burger":{"char":"","code":"ef82"},"fa-buromobelexperte":{"char":"","code":"f13f"},"fa-bus":{"char":"","code":"f207"},"fa-bus_simple":{"char":"","code":"ee27"},"fa-business_time":{"char":"","code":"eebf"},"fa-buy_n_large":{"char":"","code":"efb6"},"fa-buysellads":{"char":"","code":"f20d"},"fa-cab":{"char":"","code":"f1ba"},"fa-cable_car":{"char":"","code":"ef71"},"fa-cake_candles":{"char":"","code":"f1fd"},"fa-calculator":{"char":"","code":"f1ec"},"fa-calendar":{"char":"","code":"f073"},"fa-calendar_check":{"char":"","code":"f274"},"fa-calendar_check_o":{"char":"","code":"f274"},"fa-calendar_day":{"char":"","code":"ef37"},"fa-calendar_days":{"char":"","code":"f073"},"fa-calendar_minus":{"char":"","code":"f272"},"fa-calendar_minus_o":{"char":"","code":"f272"},"fa-calendar_o":{"char":"","code":"f133"},"fa-calendar_plus":{"char":"","code":"f271"},"fa-calendar_plus_o":{"char":"","code":"f271"},"fa-calendar_times_o":{"char":"","code":"f273"},"fa-calendar_week":{"char":"","code":"ef38"},"fa-calendar_xmark":{"char":"","code":"f273"},"fa-camera":{"char":"","code":"f030"},"fa-camera_retro":{"char":"","code":"f083"},"fa-campground":{"char":"","code":"eeec"},"fa-canadian_maple_leaf":{"char":"","code":"ef39"},"fa-candy_cane":{"char":"","code":"ef3a"},"fa-cannabis":{"char":"","code":"ee28"},"fa-capsules":{"char":"","code":"ed79"},"fa-car":{"char":"","code":"f1b9"},"fa-car_battery":{"char":"","code":"ee9e"},"fa-car_burst":{"char":"","code":"ee9f"},"fa-car_rear":{"char":"","code":"ee9d"},"fa-car_side":{"char":"","code":"eea0"},"fa-caravan":{"char":"","code":"efc1"},"fa-caret_down":{"char":"","code":"f0d7"},"fa-caret_left":{"char":"","code":"f0d9"},"fa-caret_right":{"char":"","code":"f0da"},"fa-caret_square_o_down":{"char":"","code":"f150"},"fa-caret_square_o_left":{"char":"","code":"f191"},"fa-caret_square_o_right":{"char":"","code":"f152"},"fa-caret_square_o_up":{"char":"","code":"f151"},"fa-caret_up":{"char":"","code":"f0d8"},"fa-carrot":{"char":"","code":"ef3b"},"fa-cart_arrow_down":{"char":"","code":"f218"},"fa-cart_flatbed":{"char":"","code":"ed7f"},"fa-cart_flatbed_suitcase":{"char":"","code":"ee66"},"fa-cart_plus":{"char":"","code":"f217"},"fa-cart_shopping":{"char":"","code":"f07a"},"fa-cash_register":{"char":"","code":"ef3c"},"fa-cat":{"char":"","code":"eeed"},"fa-cc":{"char":"","code":"f20a"},"fa-cc_amazon_pay":{"char":"","code":"ed57"},"fa-cc_amex":{"char":"","code":"f1f3"},"fa-cc_apple_pay":{"char":"","code":"ed42"},"fa-cc_diners_club":{"char":"","code":"f24c"},"fa-cc_discover":{"char":"","code":"f1f2"},"fa-cc_jcb":{"char":"","code":"f24b"},"fa-cc_mastercard":{"char":"","code":"f1f1"},"fa-cc_paypal":{"char":"","code":"f1f4"},"fa-cc_stripe":{"char":"","code":"f1f5"},"fa-cc_visa":{"char":"","code":"f1f0"},"fa-centercode":{"char":"","code":"f14f"},"fa-centos":{"char":"","code":"ef3d"},"fa-certificate":{"char":"","code":"f0a3"},"fa-chain":{"char":"","code":"f0c1"},"fa-chain_broken":{"char":"","code":"f127"},"fa-chair":{"char":"","code":"eeee"},"fa-chalkboard":{"char":"","code":"ede5"},"fa-chalkboard_user":{"char":"","code":"ede6"},"fa-champagne_glasses":{"char":"","code":"ef49"},"fa-charging_station":{"char":"","code":"eea1"},"fa-chart_area":{"char":"","code":"f1fe"},"fa-chart_bar":{"char":"","code":"f080"},"fa-chart_line":{"char":"","code":"f201"},"fa-chart_pie":{"char":"","code":"f200"},"fa-check":{"char":"","code":"f00c"},"fa-check_circle":{"char":"","code":"f058"},"fa-check_circle_o":{"char":"","code":"f05d"},"fa-check_double":{"char":"","code":"ee29"},"fa-check_square":{"char":"","code":"f14a"},"fa-check_square_o":{"char":"","code":"f046"},"fa-check_to_slot":{"char":"","code":"ef2f"},"fa-cheese":{"char":"","code":"ef7a"},"fa-chess":{"char":"","code":"ed5f"},"fa-chess_bishop":{"char":"","code":"ed60"},"fa-chess_board":{"char":"","code":"ed61"},"fa-chess_king":{"char":"","code":"ed62"},"fa-chess_knight":{"char":"","code":"ed63"},"fa-chess_pawn":{"char":"","code":"ed64"},"fa-chess_queen":{"char":"","code":"ed65"},"fa-chess_rook":{"char":"","code":"ed66"},"fa-chevron_circle_down":{"char":"","code":"f13a"},"fa-chevron_circle_left":{"char":"","code":"f137"},"fa-chevron_circle_right":{"char":"","code":"f138"},"fa-chevron_circle_up":{"char":"","code":"f139"},"fa-chevron_down":{"char":"","code":"f078"},"fa-chevron_left":{"char":"","code":"f053"},"fa-chevron_right":{"char":"","code":"f054"},"fa-chevron_up":{"char":"","code":"f077"},"fa-child":{"char":"","code":"f1ae"},"fa-chrome":{"char":"","code":"f268"},"fa-chromecast":{"char":"","code":"ef97"},"fa-church":{"char":"","code":"ede7"},"fa-circle":{"char":"","code":"f111"},"fa-circle_arrow_down":{"char":"","code":"f0ab"},"fa-circle_arrow_left":{"char":"","code":"f0a8"},"fa-circle_arrow_right":{"char":"","code":"f0a9"},"fa-circle_arrow_up":{"char":"","code":"f0aa"},"fa-circle_check":{"char":"","code":"f05d"},"fa-circle_chevron_down":{"char":"","code":"f13a"},"fa-circle_chevron_left":{"char":"","code":"f137"},"fa-circle_chevron_right":{"char":"","code":"f138"},"fa-circle_chevron_up":{"char":"","code":"f139"},"fa-circle_dollar_to_slot":{"char":"","code":"ed98"},"fa-circle_dot":{"char":"","code":"f192"},"fa-circle_down":{"char":"","code":"f01a"},"fa-circle_exclamation":{"char":"","code":"f06a"},"fa-circle_h":{"char":"","code":"ed83"},"fa-circle_half_stroke":{"char":"","code":"f042"},"fa-circle_info":{"char":"","code":"f05a"},"fa-circle_left":{"char":"","code":"f190"},"fa-circle_minus":{"char":"","code":"f056"},"fa-circle_notch":{"char":"","code":"f1ce"},"fa-circle_o":{"char":"","code":"f10c"},"fa-circle_o_notch":{"char":"","code":"f1ce"},"fa-circle_pause":{"char":"","code":"f28b"},"fa-circle_play":{"char":"","code":"f144"},"fa-circle_plus":{"char":"","code":"f055"},"fa-circle_question":{"char":"","code":"f059"},"fa-circle_radiation":{"char":"","code":"ef5b"},"fa-circle_right":{"char":"","code":"f18e"},"fa-circle_stop":{"char":"","code":"f28d"},"fa-circle_thin":{"char":"","code":"f1db"},"fa-circle_up":{"char":"","code":"f01b"},"fa-circle_user":{"char":"","code":"f2bd"},"fa-circle_xmark":{"char":"","code":"f05c"},"fa-city":{"char":"","code":"eec0"},"fa-clipboard":{"char":"","code":"f0ea"},"fa-clipboard_alt":{"char":"","code":"f07f"},"fa-clipboard_check":{"char":"","code":"ed7a"},"fa-clipboard_list":{"char":"","code":"ed7b"},"fa-clipboard_user":{"char":"","code":"ef7c"},"fa-clock":{"char":"","code":"f017"},"fa-clock_o":{"char":"","code":"f017"},"fa-clock_rotate_left":{"char":"","code":"f1da"},"fa-clone":{"char":"","code":"f24d"},"fa-close":{"char":"","code":"f00d"},"fa-closed_captioning":{"char":"","code":"f20a"},"fa-cloud":{"char":"","code":"f0c2"},"fa-cloud_arrow_down":{"char":"","code":"f0ed"},"fa-cloud_arrow_up":{"char":"","code":"f0ee"},"fa-cloud_bolt":{"char":"","code":"ef2c"},"fa-cloud_download":{"char":"","code":"f0ed"},"fa-cloud_meatball":{"char":"","code":"ef1a"},"fa-cloud_moon":{"char":"","code":"eeef"},"fa-cloud_moon_rain":{"char":"","code":"ef1b"},"fa-cloud_rain":{"char":"","code":"ef1c"},"fa-cloud_showers_heavy":{"char":"","code":"ef1d"},"fa-cloud_sun":{"char":"","code":"eef0"},"fa-cloud_sun_rain":{"char":"","code":"ef1e"},"fa-cloud_upload":{"char":"","code":"f0ee"},"fa-cloudscale":{"char":"","code":"f15f"},"fa-cloudsmith":{"char":"","code":"f167"},"fa-cloudversify":{"char":"","code":"f16f"},"fa-cny":{"char":"","code":"f157"},"fa-code":{"char":"","code":"f121"},"fa-code_branch":{"char":"","code":"f126"},"fa-code_commit":{"char":"","code":"f172"},"fa-code_fork":{"char":"","code":"f126"},"fa-code_merge":{"char":"","code":"f17f"},"fa-codepen":{"char":"","code":"f1cb"},"fa-codiepie":{"char":"","code":"f284"},"fa-coffee":{"char":"","code":"f0f4"},"fa-cog":{"char":"","code":"f013"},"fa-cogs":{"char":"","code":"f085"},"fa-coins":{"char":"","code":"ede8"},"fa-columns":{"char":"","code":"f0db"},"fa-comment":{"char":"","code":"f075"},"fa-comment_dollar":{"char":"","code":"eec1"},"fa-comment_dots":{"char":"","code":"f27b"},"fa-comment_medical":{"char":"","code":"ef7d"},"fa-comment_o":{"char":"","code":"f0e5"},"fa-comment_slash":{"char":"","code":"ed96"},"fa-comment_sms":{"char":"","code":"ef68"},"fa-commenting":{"char":"","code":"f27a"},"fa-commenting_o":{"char":"","code":"f27b"},"fa-comments":{"char":"","code":"f086"},"fa-comments_dollar":{"char":"","code":"eec2"},"fa-comments_o":{"char":"","code":"f0e6"},"fa-compact_disc":{"char":"","code":"ede9"},"fa-compass":{"char":"","code":"f14e"},"fa-compass_drafting":{"char":"","code":"ee31"},"fa-compress":{"char":"","code":"f066"},"fa-computer_mouse":{"char":"","code":"efba"},"fa-confluence":{"char":"","code":"ef3f"},"fa-connectdevelop":{"char":"","code":"f20e"},"fa-contao":{"char":"","code":"f26d"},"fa-cookie":{"char":"","code":"ee2c"},"fa-cookie_bite":{"char":"","code":"ee2d"},"fa-copy":{"char":"","code":"f0c5"},"fa-copyright":{"char":"","code":"f1f9"},"fa-cotton_bureau":{"char":"","code":"efb5"},"fa-couch":{"char":"","code":"ed97"},"fa-cow":{"char":"","code":"eef1"},"fa-cpanel":{"char":"","code":"f18f"},"fa-creative_commons":{"char":"","code":"f25e"},"fa-creative_commons_by":{"char":"","code":"edb1"},"fa-creative_commons_nc":{"char":"","code":"edb2"},"fa-creative_commons_nc_eu":{"char":"","code":"edb3"},"fa-creative_commons_nc_jp":{"char":"","code":"edb4"},"fa-creative_commons_nd":{"char":"","code":"edb5"},"fa-creative_commons_pd":{"char":"","code":"edb6"},"fa-creative_commons_pd_alt":{"char":"","code":"edb7"},"fa-creative_commons_remix":{"char":"","code":"edb8"},"fa-creative_commons_sa":{"char":"","code":"edb9"},"fa-creative_commons_sampling":{"char":"","code":"edba"},"fa-creative_commons_sampling_plus":{"char":"","code":"edbb"},"fa-creative_commons_share":{"char":"","code":"edbc"},"fa-creative_commons_zero":{"char":"","code":"edbd"},"fa-credit_card":{"char":"","code":"f09d"},"fa-credit_card_alt":{"char":"","code":"f283"},"fa-critical_role":{"char":"","code":"eef2"},"fa-crop":{"char":"","code":"f125"},"fa-crop_simple":{"char":"","code":"ee2e"},"fa-cross":{"char":"","code":"eec3"},"fa-crosshairs":{"char":"","code":"f05b"},"fa-crow":{"char":"","code":"edea"},"fa-crown":{"char":"","code":"edeb"},"fa-crutch":{"char":"","code":"ef7e"},"fa-css3":{"char":"","code":"f13c"},"fa-css3_alt":{"char":"","code":"f19f"},"fa-cube":{"char":"","code":"f1b2"},"fa-cubes":{"char":"","code":"f1b3"},"fa-cut":{"char":"","code":"f0c4"},"fa-cutlery":{"char":"","code":"f0f5"},"fa-cuttlefish":{"char":"","code":"f1af"},"fa-d_and_d":{"char":"","code":"f1bf"},"fa-d_and_d_beyond":{"char":"","code":"eef3"},"fa-dashboard":{"char":"","code":"f0e4"},"fa-dashcube":{"char":"","code":"f210"},"fa-database":{"char":"","code":"f1c0"},"fa-deaf":{"char":"","code":"f2a4"},"fa-deafness":{"char":"","code":"f2a4"},"fa-dedent":{"char":"","code":"f03b"},"fa-delete_left":{"char":"","code":"ee23"},"fa-delicious":{"char":"","code":"f1a5"},"fa-democrat":{"char":"","code":"ef1f"},"fa-deploydog":{"char":"","code":"f1cf"},"fa-deskpro":{"char":"","code":"f1df"},"fa-desktop":{"char":"","code":"f108"},"fa-dev":{"char":"","code":"eef4"},"fa-deviantart":{"char":"","code":"f1bd"},"fa-dharmachakra":{"char":"","code":"eec4"},"fa-dhl":{"char":"","code":"ef40"},"fa-diagram_project":{"char":"","code":"efce"},"fa-diamond":{"char":"","code":"f29f"},"fa-diamond_turn_right":{"char":"","code":"eea2"},"fa-diaspora":{"char":"","code":"ef41"},"fa-dice":{"char":"","code":"edec"},"fa-dice_d20":{"char":"","code":"eef5"},"fa-dice_d6":{"char":"","code":"eef6"},"fa-dice_five":{"char":"","code":"eded"},"fa-dice_four":{"char":"","code":"edee"},"fa-dice_one":{"char":"","code":"edef"},"fa-dice_six":{"char":"","code":"edf0"},"fa-dice_three":{"char":"","code":"edf1"},"fa-dice_two":{"char":"","code":"edf2"},"fa-digg":{"char":"","code":"f1a6"},"fa-digital_ocean":{"char":"","code":"f1ef"},"fa-discord":{"char":"","code":"f1ff"},"fa-discourse":{"char":"","code":"f20c"},"fa-disease":{"char":"","code":"ef7f"},"fa-divide":{"char":"","code":"edf3"},"fa-dna":{"char":"","code":"ed7d"},"fa-dochub":{"char":"","code":"f20f"},"fa-docker":{"char":"","code":"f21f"},"fa-dog":{"char":"","code":"eef7"},"fa-dollar":{"char":"","code":"f155"},"fa-dollar_sign":{"char":"","code":"f155"},"fa-dolly":{"char":"","code":"ed7e"},"fa-door_closed":{"char":"","code":"edf4"},"fa-door_open":{"char":"","code":"edf5"},"fa-dot_circle_o":{"char":"","code":"f192"},"fa-dove":{"char":"","code":"ed99"},"fa-down_left_and_up_right_to_center":{"char":"","code":"ed4d"},"fa-down_long":{"char":"","code":"f03f"},"fa-download":{"char":"","code":"f019"},"fa-draft2digital":{"char":"","code":"f220"},"fa-dragon":{"char":"","code":"eef8"},"fa-draw_polygon":{"char":"","code":"eea3"},"fa-dribbble":{"char":"","code":"f17d"},"fa-drivers_license":{"char":"","code":"f2c2"},"fa-drivers_license_o":{"char":"","code":"f2c3"},"fa-dropbox":{"char":"","code":"f16b"},"fa-droplet":{"char":"","code":"f043"},"fa-droplet_slash":{"char":"","code":"ee8e"},"fa-drum":{"char":"","code":"ee32"},"fa-drum_steelpan":{"char":"","code":"ee33"},"fa-drumstick_bite":{"char":"","code":"eef9"},"fa-drupal":{"char":"","code":"f1a9"},"fa-dumbbell":{"char":"","code":"ed67"},"fa-dumpster":{"char":"","code":"ef42"},"fa-dumpster_fire":{"char":"","code":"ef43"},"fa-dungeon":{"char":"","code":"eefa"},"fa-dyalog":{"char":"","code":"f22f"},"fa-ear_deaf":{"char":"","code":"f2a4"},"fa-ear_listen":{"char":"","code":"f2a2"},"fa-earlybirds":{"char":"","code":"f230"},"fa-earth_africa":{"char":"","code":"ee45"},"fa-earth_americas":{"char":"","code":"ee46"},"fa-earth_asia":{"char":"","code":"ee47"},"fa-earth_europe":{"char":"","code":"ef4b"},"fa-ebay":{"char":"","code":"edbe"},"fa-edge":{"char":"","code":"f282"},"fa-edit":{"char":"","code":"f044"},"fa-eercast":{"char":"","code":"f2da"},"fa-egg":{"char":"","code":"ef80"},"fa-eject":{"char":"","code":"f052"},"fa-elementor":{"char":"","code":"ed5a"},"fa-ellipsis":{"char":"","code":"f141"},"fa-ellipsis_h":{"char":"","code":"f141"},"fa-ellipsis_v":{"char":"","code":"f142"},"fa-ellipsis_vertical":{"char":"","code":"f142"},"fa-ello":{"char":"","code":"eea4"},"fa-ember":{"char":"","code":"ed4e"},"fa-empire":{"char":"","code":"f1d1"},"fa-envelope":{"char":"","code":"f0e0"},"fa-envelope_o":{"char":"","code":"f003"},"fa-envelope_open":{"char":"","code":"f2b6"},"fa-envelope_open_o":{"char":"","code":"f2b7"},"fa-envelope_open_text":{"char":"","code":"eec5"},"fa-envelope_square":{"char":"","code":"f199"},"fa-envelopes_bulk":{"char":"","code":"eed1"},"fa-envira":{"char":"","code":"f299"},"fa-equals":{"char":"","code":"edf6"},"fa-eraser":{"char":"","code":"f12d"},"fa-erlang":{"char":"","code":"f23f"},"fa-ethereum":{"char":"","code":"ed58"},"fa-ethernet":{"char":"","code":"ef44"},"fa-etsy":{"char":"","code":"f2d7"},"fa-eur":{"char":"","code":"f153"},"fa-euro":{"char":"","code":"f153"},"fa-euro_sign":{"char":"","code":"f153"},"fa-evernote":{"char":"","code":"ef98"},"fa-exchange":{"char":"","code":"f0ec"},"fa-exclamation":{"char":"","code":"f12a"},"fa-exclamation_circle":{"char":"","code":"f06a"},"fa-exclamation_triangle":{"char":"","code":"f071"},"fa-expand":{"char":"","code":"f065"},"fa-expeditedssl":{"char":"","code":"f23e"},"fa-external_link":{"char":"","code":"f08e"},"fa-external_link_square":{"char":"","code":"f14c"},"fa-eye":{"char":"","code":"f06e"},"fa-eye_dropper":{"char":"","code":"f1fb"},"fa-eye_low_vision":{"char":"","code":"f2a8"},"fa-eye_slash":{"char":"","code":"f070"},"fa-eyedropper":{"char":"","code":"f1fb"},"fa-fa":{"char":"","code":"f2b4"},"fa-face_angry":{"char":"","code":"ee1f"},"fa-face_dizzy":{"char":"","code":"ee30"},"fa-face_flushed":{"char":"","code":"ee42"},"fa-face_frown":{"char":"","code":"f119"},"fa-face_frown_open":{"char":"","code":"ee43"},"fa-face_grimace":{"char":"","code":"ee48"},"fa-face_grin":{"char":"","code":"ee49"},"fa-face_grin_beam":{"char":"","code":"ee4b"},"fa-face_grin_beam_sweat":{"char":"","code":"ee4c"},"fa-face_grin_hearts":{"char":"","code":"ee4d"},"fa-face_grin_squint":{"char":"","code":"ee4e"},"fa-face_grin_squint_tears":{"char":"","code":"ee4f"},"fa-face_grin_stars":{"char":"","code":"ee50"},"fa-face_grin_tears":{"char":"","code":"ee51"},"fa-face_grin_tongue":{"char":"","code":"ee52"},"fa-face_grin_tongue_squint":{"char":"","code":"ee53"},"fa-face_grin_tongue_wink":{"char":"","code":"ee54"},"fa-face_grin_wide":{"char":"","code":"ee4a"},"fa-face_grin_wink":{"char":"","code":"ee55"},"fa-face_kiss":{"char":"","code":"ee5f"},"fa-face_kiss_beam":{"char":"","code":"ee60"},"fa-face_kiss_wink_heart":{"char":"","code":"ee61"},"fa-face_laugh":{"char":"","code":"ee62"},"fa-face_laugh_beam":{"char":"","code":"ee63"},"fa-face_laugh_squint":{"char":"","code":"ee64"},"fa-face_laugh_wink":{"char":"","code":"ee65"},"fa-face_meh":{"char":"","code":"f11a"},"fa-face_meh_blank":{"char":"","code":"ee6d"},"fa-face_rolling_eyes":{"char":"","code":"ee6e"},"fa-face_sad_cry":{"char":"","code":"ee7b"},"fa-face_sad_tear":{"char":"","code":"ee7c"},"fa-face_smile":{"char":"","code":"f118"},"fa-face_smile_beam":{"char":"","code":"ee80"},"fa-face_smile_wink":{"char":"","code":"eda9"},"fa-face_surprise":{"char":"","code":"ee89"},"fa-face_tired":{"char":"","code":"ee8f"},"fa-facebook":{"char":"","code":"f09a"},"fa-facebook_f":{"char":"","code":"f24f"},"fa-facebook_messenger":{"char":"","code":"f25f"},"fa-facebook_official":{"char":"","code":"f230"},"fa-facebook_square":{"char":"","code":"f082"},"fa-fan":{"char":"","code":"efa7"},"fa-fantasy_flight_games":{"char":"","code":"eefb"},"fa-fast_backward":{"char":"","code":"f049"},"fa-fast_forward":{"char":"","code":"f050"},"fa-fax":{"char":"","code":"f1ac"},"fa-feather":{"char":"","code":"edf7"},"fa-feather_pointed":{"char":"","code":"ee34"},"fa-fedex":{"char":"","code":"ef45"},"fa-fedora":{"char":"","code":"ef46"},"fa-feed":{"char":"","code":"f09e"},"fa-female":{"char":"","code":"f182"},"fa-fighter_jet":{"char":"","code":"f0fb"},"fa-figma":{"char":"","code":"ef47"},"fa-file":{"char":"","code":"f15b"},"fa-file_archive_o":{"char":"","code":"f1c6"},"fa-file_arrow_down":{"char":"","code":"ee36"},"fa-file_arrow_up":{"char":"","code":"ee3d"},"fa-file_audio":{"char":"","code":"f1c7"},"fa-file_audio_o":{"char":"","code":"f1c7"},"fa-file_code":{"char":"","code":"f1c9"},"fa-file_code_o":{"char":"","code":"f1c9"},"fa-file_contract":{"char":"","code":"ee35"},"fa-file_csv":{"char":"","code":"eefc"},"fa-file_excel":{"char":"","code":"f1c3"},"fa-file_excel_o":{"char":"","code":"f1c3"},"fa-file_export":{"char":"","code":"ee37"},"fa-file_image":{"char":"","code":"f1c5"},"fa-file_image_o":{"char":"","code":"f1c5"},"fa-file_import":{"char":"","code":"ee38"},"fa-file_invoice":{"char":"","code":"ee39"},"fa-file_invoice_dollar":{"char":"","code":"ee3a"},"fa-file_lines":{"char":"","code":"f15c"},"fa-file_medical":{"char":"","code":"ed80"},"fa-file_movie_o":{"char":"","code":"f1c8"},"fa-file_o":{"char":"","code":"f016"},"fa-file_pdf":{"char":"","code":"f1c1"},"fa-file_pdf_o":{"char":"","code":"f1c1"},"fa-file_pen":{"char":"","code":"f05f"},"fa-file_photo_o":{"char":"","code":"f1c5"},"fa-file_picture_o":{"char":"","code":"f1c5"},"fa-file_powerpoint":{"char":"","code":"f1c4"},"fa-file_powerpoint_o":{"char":"","code":"f1c4"},"fa-file_prescription":{"char":"","code":"ee3b"},"fa-file_signature":{"char":"","code":"ee3c"},"fa-file_sound_o":{"char":"","code":"f1c7"},"fa-file_text":{"char":"","code":"f15c"},"fa-file_text_o":{"char":"","code":"f0f6"},"fa-file_video":{"char":"","code":"f1c8"},"fa-file_video_o":{"char":"","code":"f1c8"},"fa-file_waveform":{"char":"","code":"ed81"},"fa-file_word":{"char":"","code":"f1c2"},"fa-file_word_o":{"char":"","code":"f1c2"},"fa-file_zip_o":{"char":"","code":"f1c6"},"fa-file_zipper":{"char":"","code":"f1c6"},"fa-files_o":{"char":"","code":"f0c5"},"fa-fill":{"char":"","code":"ee3e"},"fa-fill_drip":{"char":"","code":"ee3f"},"fa-film":{"char":"","code":"f008"},"fa-filter":{"char":"","code":"f0b0"},"fa-filter_circle_dollar":{"char":"","code":"eec8"},"fa-fingerprint":{"char":"","code":"ee40"},"fa-fire":{"char":"","code":"f06d"},"fa-fire_extinguisher":{"char":"","code":"f134"},"fa-fire_flame_curved":{"char":"","code":"ef76"},"fa-fire_flame_simple":{"char":"","code":"ed78"},"fa-firefox":{"char":"","code":"f269"},"fa-first_order":{"char":"","code":"f2b0"},"fa-first_order_alt":{"char":"","code":"edd4"},"fa-firstdraft":{"char":"","code":"f262"},"fa-fish":{"char":"","code":"ee41"},"fa-flag":{"char":"","code":"f024"},"fa-flag_checkered":{"char":"","code":"f11e"},"fa-flag_o":{"char":"","code":"f11d"},"fa-flag_usa":{"char":"","code":"ef20"},"fa-flash":{"char":"","code":"f0e7"},"fa-flask":{"char":"","code":"f0c3"},"fa-flickr":{"char":"","code":"f16e"},"fa-flipboard":{"char":"","code":"ed68"},"fa-floppy_disk":{"char":"","code":"f0c7"},"fa-floppy_o":{"char":"","code":"f0c7"},"fa-fly":{"char":"","code":"ed43"},"fa-folder":{"char":"","code":"f07b"},"fa-folder_minus":{"char":"","code":"eec6"},"fa-folder_o":{"char":"","code":"f114"},"fa-folder_open":{"char":"","code":"f07c"},"fa-folder_open_o":{"char":"","code":"f115"},"fa-folder_plus":{"char":"","code":"eec7"},"fa-folder_tree":{"char":"","code":"ef81"},"fa-font":{"char":"","code":"f031"},"fa-font_awesome":{"char":"","code":"f2b4"},"fa-fonticons":{"char":"","code":"f280"},"fa-fonticons_fi":{"char":"","code":"f26f"},"fa-football":{"char":"","code":"ed69"},"fa-fort_awesome":{"char":"","code":"f286"},"fa-fort_awesome_alt":{"char":"","code":"f27f"},"fa-forumbee":{"char":"","code":"f211"},"fa-forward":{"char":"","code":"f04e"},"fa-forward_fast":{"char":"","code":"f050"},"fa-forward_step":{"char":"","code":"f051"},"fa-foursquare":{"char":"","code":"f180"},"fa-free_code_camp":{"char":"","code":"f2c5"},"fa-freebsd":{"char":"","code":"f28f"},"fa-frog":{"char":"","code":"edf8"},"fa-frown_o":{"char":"","code":"f119"},"fa-fulcrum":{"char":"","code":"edd5"},"fa-futbol":{"char":"","code":"f1e3"},"fa-futbol_o":{"char":"","code":"f1e3"},"fa-galactic_republic":{"char":"","code":"edd6"},"fa-galactic_senate":{"char":"","code":"edd7"},"fa-gamepad":{"char":"","code":"f11b"},"fa-gas_pump":{"char":"","code":"edf9"},"fa-gauge":{"char":"","code":"eeb2"},"fa-gauge_high":{"char":"","code":"ed2f"},"fa-gauge_simple":{"char":"","code":"eeb3"},"fa-gauge_simple_high":{"char":"","code":"f0e4"},"fa-gavel":{"char":"","code":"f0e3"},"fa-gbp":{"char":"","code":"f154"},"fa-ge":{"char":"","code":"f1d1"},"fa-gear":{"char":"","code":"f013"},"fa-gears":{"char":"","code":"f085"},"fa-gem":{"char":"","code":"f219"},"fa-genderless":{"char":"","code":"f22d"},"fa-get_pocket":{"char":"","code":"f265"},"fa-gg":{"char":"","code":"f260"},"fa-gg_circle":{"char":"","code":"f261"},"fa-ghost":{"char":"","code":"eefe"},"fa-gift":{"char":"","code":"f06b"},"fa-gifts":{"char":"","code":"ef48"},"fa-git":{"char":"","code":"f1d3"},"fa-git_alt":{"char":"","code":"efa0"},"fa-git_square":{"char":"","code":"f1d2"},"fa-github":{"char":"","code":"f09b"},"fa-github_alt":{"char":"","code":"f113"},"fa-github_square":{"char":"","code":"f092"},"fa-gitkraken":{"char":"","code":"f2ac"},"fa-gitlab":{"char":"","code":"f296"},"fa-gitter":{"char":"","code":"ed50"},"fa-gittip":{"char":"","code":"f184"},"fa-glass":{"char":"","code":"f000"},"fa-glasses":{"char":"","code":"edfa"},"fa-glide":{"char":"","code":"f2a5"},"fa-glide_g":{"char":"","code":"f2a6"},"fa-globe":{"char":"","code":"f0ac"},"fa-gofore":{"char":"","code":"f2af"},"fa-golf_ball_tee":{"char":"","code":"ed6a"},"fa-goodreads":{"char":"","code":"f2bf"},"fa-goodreads_g":{"char":"","code":"f2cf"},"fa-google":{"char":"","code":"f1a0"},"fa-google_drive":{"char":"","code":"f2df"},"fa-google_play":{"char":"","code":"f2e1"},"fa-google_plus":{"char":"","code":"f0d5"},"fa-google_plus_circle":{"char":"","code":"f2b3"},"fa-google_plus_official":{"char":"","code":"f2b3"},"fa-google_plus_square":{"char":"","code":"f0d4"},"fa-google_wallet":{"char":"","code":"f1ee"},"fa-gopuram":{"char":"","code":"eec9"},"fa-graduation_cap":{"char":"","code":"f19d"},"fa-gratipay":{"char":"","code":"f184"},"fa-grav":{"char":"","code":"f2d6"},"fa-greater_than":{"char":"","code":"edfb"},"fa-greater_than_equal":{"char":"","code":"edfc"},"fa-grip":{"char":"","code":"ee56"},"fa-grip_lines":{"char":"","code":"ef4c"},"fa-grip_lines_vertical":{"char":"","code":"ef4d"},"fa-grip_vertical":{"char":"","code":"ee57"},"fa-gripfire":{"char":"","code":"f2e2"},"fa-group":{"char":"","code":"f0c0"},"fa-grunt":{"char":"","code":"f2e3"},"fa-guitar":{"char":"","code":"ef4e"},"fa-gulp":{"char":"","code":"f2e4"},"fa-h_square":{"char":"","code":"f0fd"},"fa-hacker_news":{"char":"","code":"f1d4"},"fa-hackerrank":{"char":"","code":"eea5"},"fa-hammer":{"char":"","code":"eeff"},"fa-hamsa":{"char":"","code":"eeca"},"fa-hand":{"char":"","code":"f256"},"fa-hand_back_fist":{"char":"","code":"f255"},"fa-hand_dots":{"char":"","code":"ed73"},"fa-hand_fist":{"char":"","code":"eefd"},"fa-hand_grab_o":{"char":"","code":"f255"},"fa-hand_holding":{"char":"","code":"ed9a"},"fa-hand_holding_dollar":{"char":"","code":"ed9c"},"fa-hand_holding_droplet":{"char":"","code":"ed9d"},"fa-hand_holding_heart":{"char":"","code":"ed9b"},"fa-hand_lizard":{"char":"","code":"f258"},"fa-hand_lizard_o":{"char":"","code":"f258"},"fa-hand_middle_finger":{"char":"","code":"ef83"},"fa-hand_o_down":{"char":"","code":"f0a7"},"fa-hand_o_left":{"char":"","code":"f0a5"},"fa-hand_o_right":{"char":"","code":"f0a4"},"fa-hand_o_up":{"char":"","code":"f0a6"},"fa-hand_paper_o":{"char":"","code":"f256"},"fa-hand_peace":{"char":"","code":"f25b"},"fa-hand_peace_o":{"char":"","code":"f25b"},"fa-hand_point_down":{"char":"","code":"f0a7"},"fa-hand_point_left":{"char":"","code":"f0a5"},"fa-hand_point_right":{"char":"","code":"f0a4"},"fa-hand_point_up":{"char":"","code":"f0a6"},"fa-hand_pointer":{"char":"","code":"f25a"},"fa-hand_pointer_o":{"char":"","code":"f25a"},"fa-hand_rock_o":{"char":"","code":"f255"},"fa-hand_scissors":{"char":"","code":"f257"},"fa-hand_scissors_o":{"char":"","code":"f257"},"fa-hand_spock":{"char":"","code":"f259"},"fa-hand_spock_o":{"char":"","code":"f259"},"fa-hand_stop_o":{"char":"","code":"f256"},"fa-hands":{"char":"","code":"f2a7"},"fa-hands_asl_interpreting":{"char":"","code":"f2a3"},"fa-hands_holding":{"char":"","code":"ed9e"},"fa-hands_praying":{"char":"","code":"eedb"},"fa-handshake":{"char":"","code":"f2b5"},"fa-handshake_angle":{"char":"","code":"ed9f"},"fa-handshake_o":{"char":"","code":"f2b5"},"fa-handshake_simple":{"char":"","code":"eda0"},"fa-hanukiah":{"char":"","code":"ef00"},"fa-hard_drive":{"char":"","code":"f0a0"},"fa-hard_of_hearing":{"char":"","code":"f2a4"},"fa-hashtag":{"char":"","code":"f292"},"fa-hat_cowboy":{"char":"","code":"efb7"},"fa-hat_cowboy_side":{"char":"","code":"efb8"},"fa-hat_wizard":{"char":"","code":"ef01"},"fa-hdd_o":{"char":"","code":"f0a0"},"fa-header":{"char":"","code":"f1dc"},"fa-heading":{"char":"","code":"f1dc"},"fa-headphones":{"char":"","code":"f025"},"fa-headphones_simple":{"char":"","code":"ee58"},"fa-headset":{"char":"","code":"ee59"},"fa-heard_o":{"char":"","code":"f08a"},"fa-heart":{"char":"","code":"f004"},"fa-heart_crack":{"char":"","code":"ef4f"},"fa-heart_o":{"char":"","code":"f08a"},"fa-heart_pulse":{"char":"","code":"f21e"},"fa-heartbeat":{"char":"","code":"f21e"},"fa-helicopter":{"char":"","code":"edfd"},"fa-helmet_safety":{"char":"","code":"ef84"},"fa-highlighter":{"char":"","code":"ee5a"},"fa-hippo":{"char":"","code":"ef03"},"fa-hips":{"char":"","code":"ed6b"},"fa-hire_a_helper":{"char":"","code":"f2e6"},"fa-history":{"char":"","code":"f1da"},"fa-hockey_puck":{"char":"","code":"ed6c"},"fa-holly_berry":{"char":"","code":"ef50"},"fa-home":{"char":"","code":"f015"},"fa-hooli":{"char":"","code":"ed51"},"fa-hornbill":{"char":"","code":"ee5b"},"fa-horse":{"char":"","code":"ef04"},"fa-horse_head":{"char":"","code":"ef51"},"fa-hospital":{"char":"","code":"f0f8"},"fa-hospital_o":{"char":"","code":"f0f8"},"fa-hospital_user":{"char":"","code":"ef86"},"fa-hot_tub_person":{"char":"","code":"ee5c"},"fa-hotdog":{"char":"","code":"ef87"},"fa-hotel":{"char":"","code":"f236"},"fa-hotel_building":{"char":"","code":"ee5d"},"fa-hotjar":{"char":"","code":"f2e7"},"fa-hourglass":{"char":"","code":"f254"},"fa-hourglass_1":{"char":"","code":"f251"},"fa-hourglass_2":{"char":"","code":"f252"},"fa-hourglass_3":{"char":"","code":"f253"},"fa-hourglass_end":{"char":"","code":"f253"},"fa-hourglass_half":{"char":"","code":"f252"},"fa-hourglass_o":{"char":"","code":"f250"},"fa-hourglass_start":{"char":"","code":"f251"},"fa-house":{"char":"","code":"f015"},"fa-house_chimney":{"char":"","code":"ef85"},"fa-house_chimney_crack":{"char":"","code":"ef05"},"fa-house_chimney_medical":{"char":"","code":"ef7b"},"fa-houzz":{"char":"","code":"f27c"},"fa-hryvnia_sign":{"char":"","code":"ef06"},"fa-html5":{"char":"","code":"f13b"},"fa-hubspot":{"char":"","code":"f2e8"},"fa-hurricane":{"char":"","code":"ef21"},"fa-i_cursor":{"char":"","code":"f246"},"fa-ice_cream":{"char":"","code":"ef88"},"fa-icicles":{"char":"","code":"ef52"},"fa-icons":{"char":"","code":"efa8"},"fa-id_badge":{"char":"","code":"f2c1"},"fa-id_card":{"char":"","code":"f2c2"},"fa-id_card_clip":{"char":"","code":"ed84"},"fa-id_card_o":{"char":"","code":"f2c3"},"fa-igloo":{"char":"","code":"ef53"},"fa-ils":{"char":"","code":"f20b"},"fa-image":{"char":"","code":"f03e"},"fa-image_portrait":{"char":"","code":"ed19"},"fa-images":{"char":"","code":"f00f"},"fa-imdb":{"char":"","code":"f2d8"},"fa-inbox":{"char":"","code":"f01c"},"fa-indent":{"char":"","code":"f03c"},"fa-industry":{"char":"","code":"f275"},"fa-infinity":{"char":"","code":"edfe"},"fa-info":{"char":"","code":"f129"},"fa-info_circle":{"char":"","code":"f05a"},"fa-inr":{"char":"","code":"f156"},"fa-instagram":{"char":"","code":"f16d"},"fa-institution":{"char":"","code":"f19c"},"fa-intercom":{"char":"","code":"ef54"},"fa-internet_explorer":{"char":"","code":"f26b"},"fa-intersex":{"char":"","code":"f224"},"fa-invision":{"char":"","code":"ef55"},"fa-ioxhost":{"char":"","code":"f208"},"fa-italic":{"char":"","code":"f033"},"fa-itch_io":{"char":"","code":"ef99"},"fa-itunes":{"char":"","code":"f2e9"},"fa-itunes_note":{"char":"","code":"f2eb"},"fa-java":{"char":"","code":"edaf"},"fa-jedi":{"char":"","code":"eecc"},"fa-jedi_order":{"char":"","code":"edd8"},"fa-jenkins":{"char":"","code":"f2ec"},"fa-jet_fighter":{"char":"","code":"f0fb"},"fa-jira":{"char":"","code":"ef56"},"fa-joget":{"char":"","code":"f2ed"},"fa-joint":{"char":"","code":"ee5e"},"fa-joomla":{"char":"","code":"f1aa"},"fa-jpy":{"char":"","code":"f157"},"fa-js":{"char":"","code":"f2ee"},"fa-jsfiddle":{"char":"","code":"f1cc"},"fa-kaaba":{"char":"","code":"eece"},"fa-kaggle":{"char":"","code":"eea6"},"fa-key":{"char":"","code":"f084"},"fa-keybase":{"char":"","code":"edbf"},"fa-keyboard":{"char":"","code":"f11c"},"fa-keyboard_o":{"char":"","code":"f11c"},"fa-keycdn":{"char":"","code":"f2f0"},"fa-khanda":{"char":"","code":"eecf"},"fa-kickstarter":{"char":"","code":"f2f3"},"fa-kickstarter_k":{"char":"","code":"f2f4"},"fa-kit_medical":{"char":"","code":"ed82"},"fa-kiwi_bird":{"char":"","code":"edff"},"fa-korvue":{"char":"","code":"ed59"},"fa-krw":{"char":"","code":"f159"},"fa-landmark":{"char":"","code":"eed0"},"fa-landmark_dome":{"char":"","code":"ef22"},"fa-language":{"char":"","code":"f1ab"},"fa-laptop":{"char":"","code":"f109"},"fa-laptop_code":{"char":"","code":"eea7"},"fa-laptop_medical":{"char":"","code":"ef89"},"fa-laravel":{"char":"","code":"f2f7"},"fa-lastfm":{"char":"","code":"f202"},"fa-lastfm_square":{"char":"","code":"f203"},"fa-layer_group":{"char":"","code":"eea8"},"fa-leaf":{"char":"","code":"f06c"},"fa-leanpub":{"char":"","code":"f212"},"fa-left_long":{"char":"","code":"f04f"},"fa-left_right":{"char":"","code":"f08f"},"fa-legal":{"char":"","code":"f0e3"},"fa-lemon":{"char":"","code":"f094"},"fa-lemon_o":{"char":"","code":"f094"},"fa-less":{"char":"","code":"ed48"},"fa-less_than":{"char":"","code":"efc3"},"fa-less_than_equal":{"char":"","code":"efc4"},"fa-level_down":{"char":"","code":"f149"},"fa-level_up":{"char":"","code":"f148"},"fa-life_bouy":{"char":"","code":"f1cd"},"fa-life_buoy":{"char":"","code":"f1cd"},"fa-life_ring":{"char":"","code":"f1cd"},"fa-life_saver":{"char":"","code":"f1cd"},"fa-lightbulb":{"char":"","code":"f0eb"},"fa-lightbulb_o":{"char":"","code":"f0eb"},"fa-line":{"char":"","code":"f2fb"},"fa-line_chart":{"char":"","code":"f201"},"fa-link":{"char":"","code":"f0c1"},"fa-link_slash":{"char":"","code":"f127"},"fa-linkedin":{"char":"","code":"f0e1"},"fa-linkedin_in":{"char":"","code":"f0e1"},"fa-linkedin_square":{"char":"","code":"f08c"},"fa-linode":{"char":"","code":"f2b8"},"fa-linux":{"char":"","code":"f17c"},"fa-lira_sign":{"char":"","code":"f195"},"fa-list":{"char":"","code":"f03a"},"fa-list_alt":{"char":"","code":"f022"},"fa-list_check":{"char":"","code":"f0ae"},"fa-list_ol":{"char":"","code":"f0cb"},"fa-list_ul":{"char":"","code":"f0ca"},"fa-location_arrow":{"char":"","code":"f124"},"fa-location_crosshairs":{"char":"","code":"eea9"},"fa-location_dot":{"char":"","code":"ed00"},"fa-location_pin":{"char":"","code":"f041"},"fa-lock":{"char":"","code":"f023"},"fa-lock_open":{"char":"","code":"f2fc"},"fa-long_arrow_down":{"char":"","code":"f175"},"fa-long_arrow_left":{"char":"","code":"f177"},"fa-long_arrow_right":{"char":"","code":"f178"},"fa-long_arrow_up":{"char":"","code":"f176"},"fa-low_vision":{"char":"","code":"f2a8"},"fa-lungs":{"char":"","code":"eeaa"},"fa-lyft":{"char":"","code":"f2fd"},"fa-magento":{"char":"","code":"f2ff"},"fa-magic":{"char":"","code":"f0d0"},"fa-magnet":{"char":"","code":"f076"},"fa-magnifying_glass":{"char":"","code":"f002"},"fa-magnifying_glass_dollar":{"char":"","code":"eedd"},"fa-magnifying_glass_location":{"char":"","code":"eede"},"fa-magnifying_glass_minus":{"char":"","code":"f010"},"fa-magnifying_glass_plus":{"char":"","code":"f00e"},"fa-mail_forward":{"char":"","code":"f064"},"fa-mail_reply":{"char":"","code":"f112"},"fa-mail_reply_all":{"char":"","code":"f122"},"fa-mailchimp":{"char":"","code":"ee67"},"fa-male":{"char":"","code":"f183"},"fa-mandalorian":{"char":"","code":"edd9"},"fa-map":{"char":"","code":"f279"},"fa-map_location":{"char":"","code":"ee68"},"fa-map_location_dot":{"char":"","code":"ee69"},"fa-map_marker":{"char":"","code":"f041"},"fa-map_o":{"char":"","code":"f278"},"fa-map_pin":{"char":"","code":"f276"},"fa-map_signs":{"char":"","code":"f277"},"fa-markdown":{"char":"","code":"eeab"},"fa-marker":{"char":"","code":"ee6a"},"fa-mars":{"char":"","code":"f222"},"fa-mars_double":{"char":"","code":"f227"},"fa-mars_stroke":{"char":"","code":"f229"},"fa-mars_stroke_h":{"char":"","code":"f22b"},"fa-mars_stroke_right":{"char":"","code":"f22b"},"fa-mars_stroke_up":{"char":"","code":"f22a"},"fa-mars_stroke_v":{"char":"","code":"f22a"},"fa-martini_glass":{"char":"","code":"ee44"},"fa-martini_glass_citrus":{"char":"","code":"ee2a"},"fa-martini_glass_empty":{"char":"","code":"f000"},"fa-mask":{"char":"","code":"ef07"},"fa-masks_theater":{"char":"","code":"eeb6"},"fa-mastodon":{"char":"","code":"edc0"},"fa-maxcdn":{"char":"","code":"f136"},"fa-maximize":{"char":"","code":"f06f"},"fa-mdb":{"char":"","code":"efb9"},"fa-meanpath":{"char":"","code":"f20c"},"fa-medal":{"char":"","code":"ee6b"},"fa-medapps":{"char":"","code":"ed01"},"fa-medium":{"char":"","code":"f23a"},"fa-medkit":{"char":"","code":"f0fa"},"fa-medrt":{"char":"","code":"ed02"},"fa-meetup":{"char":"","code":"f2e0"},"fa-megaport":{"char":"","code":"ee6c"},"fa-meh_o":{"char":"","code":"f11a"},"fa-memory":{"char":"","code":"efc5"},"fa-mendeley":{"char":"","code":"ef57"},"fa-menorah":{"char":"","code":"eed2"},"fa-mercury":{"char":"","code":"f223"},"fa-message":{"char":"","code":"f27a"},"fa-meteor":{"char":"","code":"ef23"},"fa-microchip":{"char":"","code":"f2db"},"fa-microphone":{"char":"","code":"f130"},"fa-microphone_lines":{"char":"","code":"ed03"},"fa-microphone_lines_slash":{"char":"","code":"efc6"},"fa-microphone_slash":{"char":"","code":"f131"},"fa-microscope":{"char":"","code":"eeac"},"fa-microsoft":{"char":"","code":"ed04"},"fa-minimize":{"char":"","code":"ef3e"},"fa-minus":{"char":"","code":"f068"},"fa-minus_circle":{"char":"","code":"f056"},"fa-minus_square":{"char":"","code":"f146"},"fa-minus_square_o":{"char":"","code":"f147"},"fa-mitten":{"char":"","code":"ef58"},"fa-mix":{"char":"","code":"ed05"},"fa-mixcloud":{"char":"","code":"f289"},"fa-mizuni":{"char":"","code":"ed06"},"fa-mobile":{"char":"","code":"ed08"},"fa-mobile_button":{"char":"","code":"ed07"},"fa-mobile_phone":{"char":"","code":"f10b"},"fa-mobile_screen":{"char":"","code":"ed09"},"fa-mobile_screen_button":{"char":"","code":"f10b"},"fa-modx":{"char":"","code":"f285"},"fa-monero":{"char":"","code":"ed0a"},"fa-money":{"char":"","code":"f0d6"},"fa-money_bill":{"char":"","code":"f0d6"},"fa-money_bill_1":{"char":"","code":"ed0b"},"fa-money_bill_1_wave":{"char":"","code":"efc8"},"fa-money_bill_wave":{"char":"","code":"efc7"},"fa-money_check":{"char":"","code":"efc9"},"fa-money_check_dollar":{"char":"","code":"efca"},"fa-monument":{"char":"","code":"ee6f"},"fa-moon":{"char":"","code":"f186"},"fa-moon_o":{"char":"","code":"f186"},"fa-mortar_board":{"char":"","code":"f19d"},"fa-mortar_pestle":{"char":"","code":"ee70"},"fa-mosque":{"char":"","code":"eed3"},"fa-motorcycle":{"char":"","code":"f21c"},"fa-mountain":{"char":"","code":"ef08"},"fa-mouse_pointer":{"char":"","code":"f245"},"fa-mug_hot":{"char":"","code":"ef59"},"fa-mug_saucer":{"char":"","code":"f0f4"},"fa-music":{"char":"","code":"f001"},"fa-napster":{"char":"","code":"ed0c"},"fa-navicon":{"char":"","code":"f0c9"},"fa-neos":{"char":"","code":"eead"},"fa-network_wired":{"char":"","code":"ef09"},"fa-neuter":{"char":"","code":"f22c"},"fa-newspaper":{"char":"","code":"f1ea"},"fa-newspaper_o":{"char":"","code":"f1ea"},"fa-nimblr":{"char":"","code":"ee71"},"fa-node":{"char":"","code":"ed44"},"fa-node_js":{"char":"","code":"ed0d"},"fa-not_equal":{"char":"","code":"efcb"},"fa-note_sticky":{"char":"","code":"f249"},"fa-notes_medical":{"char":"","code":"ed85"},"fa-npm":{"char":"","code":"ed0e"},"fa-ns8":{"char":"","code":"ed0f"},"fa-nutritionix":{"char":"","code":"ed10"},"fa-object_group":{"char":"","code":"f247"},"fa-object_ungroup":{"char":"","code":"f248"},"fa-odnoklassniki":{"char":"","code":"f263"},"fa-odnoklassniki_square":{"char":"","code":"f264"},"fa-oil_can":{"char":"","code":"eeae"},"fa-ok_sign":{"char":"","code":"f058"},"fa-old_republic":{"char":"","code":"edda"},"fa-om":{"char":"","code":"eed4"},"fa-opencart":{"char":"","code":"f23d"},"fa-openid":{"char":"","code":"f19b"},"fa-opera":{"char":"","code":"f26a"},"fa-optin_monster":{"char":"","code":"f23c"},"fa-orcid":{"char":"","code":"efbb"},"fa-osi":{"char":"","code":"ed45"},"fa-otter":{"char":"","code":"ef0a"},"fa-outdent":{"char":"","code":"f03b"},"fa-page4":{"char":"","code":"ed11"},"fa-pagelines":{"char":"","code":"f18c"},"fa-pager":{"char":"","code":"ef8a"},"fa-paint_brush":{"char":"","code":"f1fc"},"fa-paint_roller":{"char":"","code":"ee72"},"fa-paintbrush":{"char":"","code":"f1fc"},"fa-palette":{"char":"","code":"efcc"},"fa-palfed":{"char":"","code":"ed12"},"fa-pallet":{"char":"","code":"ed86"},"fa-paper_plane":{"char":"","code":"f1d8"},"fa-paper_plane_o":{"char":"","code":"f1d9"},"fa-paperclip":{"char":"","code":"f0c6"},"fa-parachute_box":{"char":"","code":"eda1"},"fa-paragraph":{"char":"","code":"f1dd"},"fa-passport":{"char":"","code":"ee73"},"fa-paste":{"char":"","code":"f0ea"},"fa-patreon":{"char":"","code":"ed13"},"fa-pause":{"char":"","code":"f04c"},"fa-pause_circle":{"char":"","code":"f28b"},"fa-pause_circle_o":{"char":"","code":"f28c"},"fa-paw":{"char":"","code":"f1b0"},"fa-paypal":{"char":"","code":"f1ed"},"fa-peace":{"char":"","code":"eed6"},"fa-pen":{"char":"","code":"f01f"},"fa-pen_clip":{"char":"","code":"f020"},"fa-pen_fancy":{"char":"","code":"ee74"},"fa-pen_nib":{"char":"","code":"ee75"},"fa-pen_ruler":{"char":"","code":"ee76"},"fa-pen_to_square":{"char":"","code":"f044"},"fa-pencil":{"char":"","code":"f040"},"fa-pencil_square":{"char":"","code":"f14b"},"fa-pencil_square_o":{"char":"","code":"f044"},"fa-people_carry_box":{"char":"","code":"eda2"},"fa-pepper_hot":{"char":"","code":"ef8b"},"fa-percent":{"char":"","code":"f295"},"fa-periscope":{"char":"","code":"ed14"},"fa-person":{"char":"","code":"f183"},"fa-person_biking":{"char":"","code":"efa2"},"fa-person_booth":{"char":"","code":"ef24"},"fa-person_digging":{"char":"","code":"efa6"},"fa-person_dots_from_line":{"char":"","code":"ed7c"},"fa-person_dress":{"char":"","code":"f182"},"fa-person_hiking":{"char":"","code":"ef02"},"fa-person_praying":{"char":"","code":"eeda"},"fa-person_running":{"char":"","code":"ef0c"},"fa-person_skating":{"char":"","code":"ef63"},"fa-person_skiing":{"char":"","code":"ef65"},"fa-person_skiing_nordic":{"char":"","code":"ef66"},"fa-person_snowboarding":{"char":"","code":"ef69"},"fa-person_swimming":{"char":"","code":"ee8b"},"fa-person_walking":{"char":"","code":"ee1d"},"fa-person_walking_with_cane":{"char":"","code":"f29d"},"fa-phabricator":{"char":"","code":"ed15"},"fa-phoenix_framework":{"char":"","code":"ed16"},"fa-phoenix_squadron":{"char":"","code":"eddb"},"fa-phone":{"char":"","code":"f095"},"fa-phone_flip":{"char":"","code":"efa9"},"fa-phone_slash":{"char":"","code":"ed17"},"fa-phone_square":{"char":"","code":"f098"},"fa-phone_volume":{"char":"","code":"f2a0"},"fa-photo":{"char":"","code":"f03e"},"fa-photo_film":{"char":"","code":"efab"},"fa-php":{"char":"","code":"ed6d"},"fa-picture_o":{"char":"","code":"f03e"},"fa-pie_chart":{"char":"","code":"f200"},"fa-pied_piper":{"char":"","code":"f2ae"},"fa-pied_piper_alt":{"char":"","code":"f1a8"},"fa-pied_piper_hat":{"char":"","code":"edb0"},"fa-pied_piper_pp":{"char":"","code":"f1a7"},"fa-piggy_bank":{"char":"","code":"eda3"},"fa-pills":{"char":"","code":"ed87"},"fa-pinterest":{"char":"","code":"f0d2"},"fa-pinterest_p":{"char":"","code":"f231"},"fa-pinterest_square":{"char":"","code":"f0d3"},"fa-pizza_slice":{"char":"","code":"ef8c"},"fa-place_of_worship":{"char":"","code":"eed7"},"fa-plane":{"char":"","code":"f072"},"fa-plane_arrival":{"char":"","code":"ee77"},"fa-plane_departure":{"char":"","code":"ee78"},"fa-play":{"char":"","code":"f04b"},"fa-play_circle":{"char":"","code":"f144"},"fa-play_circle_o":{"char":"","code":"f01d"},"fa-playstation":{"char":"","code":"ed18"},"fa-plug":{"char":"","code":"f1e6"},"fa-plus":{"char":"","code":"f067"},"fa-plus_circle":{"char":"","code":"f055"},"fa-plus_square":{"char":"","code":"f0fe"},"fa-plus_square_o":{"char":"","code":"f196"},"fa-podcast":{"char":"","code":"f2ce"},"fa-poo":{"char":"","code":"f2fe"},"fa-poo_storm":{"char":"","code":"ef25"},"fa-poop":{"char":"","code":"eeaf"},"fa-power_off":{"char":"","code":"f011"},"fa-prescription":{"char":"","code":"ee79"},"fa-prescription_bottle":{"char":"","code":"ed88"},"fa-prescription_bottle_medical":{"char":"","code":"ed89"},"fa-print":{"char":"","code":"f02f"},"fa-product_hunt":{"char":"","code":"f288"},"fa-pushed":{"char":"","code":"ed1a"},"fa-puzzle_piece":{"char":"","code":"f12e"},"fa-python":{"char":"","code":"ed1b"},"fa-qq":{"char":"","code":"f1d6"},"fa-qrcode":{"char":"","code":"f029"},"fa-question":{"char":"","code":"f128"},"fa-question_circle":{"char":"","code":"f059"},"fa-question_circle_o":{"char":"","code":"f29c"},"fa-quinscape":{"char":"","code":"ed6f"},"fa-quora":{"char":"","code":"f2c4"},"fa-quote_left":{"char":"","code":"f10d"},"fa-quote_right":{"char":"","code":"f10e"},"fa-r_project":{"char":"","code":"edc1"},"fa-ra":{"char":"","code":"f1d0"},"fa-radiation":{"char":"","code":"ef5a"},"fa-radio":{"char":"","code":"efbc"},"fa-rainbow":{"char":"","code":"ef26"},"fa-random":{"char":"","code":"f074"},"fa-raspberry_pi":{"char":"","code":"ef5c"},"fa-ravelry":{"char":"","code":"f2d9"},"fa-react":{"char":"","code":"ed46"},"fa-reacteurope":{"char":"","code":"ef27"},"fa-readme":{"char":"","code":"eda4"},"fa-rebel":{"char":"","code":"f1d0"},"fa-receipt":{"char":"","code":"ee0c"},"fa-record_vinyl":{"char":"","code":"efbd"},"fa-rectangle_ad":{"char":"","code":"eebb"},"fa-rectangle_list":{"char":"","code":"f022"},"fa-rectangle_xmark":{"char":"","code":"f2d4"},"fa-recycle":{"char":"","code":"f1b8"},"fa-red_river":{"char":"","code":"ed1c"},"fa-reddit":{"char":"","code":"f1a1"},"fa-reddit_alien":{"char":"","code":"f281"},"fa-reddit_square":{"char":"","code":"f1a2"},"fa-redhat":{"char":"","code":"ef5d"},"fa-refresh":{"char":"","code":"f021"},"fa-registered":{"char":"","code":"f25d"},"fa-remove":{"char":"","code":"f00d"},"fa-remove_sign":{"char":"","code":"f057"},"fa-renren":{"char":"","code":"f18b"},"fa-reorder":{"char":"","code":"f0c9"},"fa-repeat":{"char":"","code":"f01e"},"fa-repeat_alt":{"char":"","code":"f0b6"},"fa-reply":{"char":"","code":"f112"},"fa-reply_all":{"char":"","code":"f122"},"fa-replyd":{"char":"","code":"ed1e"},"fa-republican":{"char":"","code":"ef28"},"fa-researchgate":{"char":"","code":"edc2"},"fa-resistance":{"char":"","code":"f1d0"},"fa-resolving":{"char":"","code":"ed1f"},"fa-restroom":{"char":"","code":"ef5e"},"fa-retweet":{"char":"","code":"f079"},"fa-rev":{"char":"","code":"ee7a"},"fa-ribbon":{"char":"","code":"eda5"},"fa-right_from_bracket":{"char":"","code":"f2f5"},"fa-right_left":{"char":"","code":"f0b5"},"fa-right_to_bracket":{"char":"","code":"f2f6"},"fa-ring":{"char":"","code":"ef0b"},"fa-rmb":{"char":"","code":"f157"},"fa-road":{"char":"","code":"f018"},"fa-robot":{"char":"","code":"ee0d"},"fa-rocket":{"char":"","code":"f135"},"fa-rocketchat":{"char":"","code":"ed20"},"fa-rockrms":{"char":"","code":"ed21"},"fa-rotate":{"char":"","code":"f2f1"},"fa-rotate_left":{"char":"","code":"f2ea"},"fa-rotate_right":{"char":"","code":"f2f9"},"fa-rouble":{"char":"","code":"f158"},"fa-route":{"char":"","code":"eda6"},"fa-rss":{"char":"","code":"f09e"},"fa-rss_square":{"char":"","code":"f143"},"fa-rub":{"char":"","code":"f158"},"fa-ruble":{"char":"","code":"f158"},"fa-ruble_sign":{"char":"","code":"f158"},"fa-ruler":{"char":"","code":"ee0e"},"fa-ruler_combined":{"char":"","code":"ee0f"},"fa-ruler_horizontal":{"char":"","code":"ee10"},"fa-ruler_vertical":{"char":"","code":"ee11"},"fa-rupee":{"char":"","code":"f156"},"fa-rupee_sign":{"char":"","code":"f156"},"fa-s15":{"char":"","code":"f2cd"},"fa-sack_dollar":{"char":"","code":"ef8d"},"fa-safari":{"char":"","code":"f267"},"fa-salesforce":{"char":"","code":"ef9a"},"fa-sass":{"char":"","code":"ed49"},"fa-satellite":{"char":"","code":"ef5f"},"fa-satellite_dish":{"char":"","code":"ef60"},"fa-save":{"char":"","code":"f0c7"},"fa-scale_balanced":{"char":"","code":"f24e"},"fa-scale_unbalanced":{"char":"","code":"eddf"},"fa-scale_unbalanced_flip":{"char":"","code":"ede0"},"fa-schlix":{"char":"","code":"ed22"},"fa-school":{"char":"","code":"ee12"},"fa-scissors":{"char":"","code":"f0c4"},"fa-screwdriver":{"char":"","code":"ee13"},"fa-screwdriver_wrench":{"char":"","code":"ef70"},"fa-scribd":{"char":"","code":"f28a"},"fa-scroll":{"char":"","code":"ef0d"},"fa-scroll_torah":{"char":"","code":"eee5"},"fa-sd_card":{"char":"","code":"ef61"},"fa-search":{"char":"","code":"f002"},"fa-search_minus":{"char":"","code":"f010"},"fa-search_plus":{"char":"","code":"f00e"},"fa-searchengin":{"char":"","code":"ed23"},"fa-seedling":{"char":"","code":"eda7"},"fa-sellcast":{"char":"","code":"f2da"},"fa-sellsy":{"char":"","code":"f213"},"fa-send":{"char":"","code":"f1d8"},"fa-send_o":{"char":"","code":"f1d9"},"fa-server":{"char":"","code":"f233"},"fa-servicestack":{"char":"","code":"ed24"},"fa-shapes":{"char":"","code":"eeb0"},"fa-share":{"char":"","code":"f064"},"fa-share_alt":{"char":"","code":"f1e0"},"fa-share_alt_square":{"char":"","code":"f1e1"},"fa-share_from_square":{"char":"","code":"f14d"},"fa-share_nodes":{"char":"","code":"f1e0"},"fa-share_square":{"char":"","code":"f14d"},"fa-share_square_o":{"char":"","code":"f045"},"fa-shekel":{"char":"","code":"f20b"},"fa-shekel_sign":{"char":"","code":"f20b"},"fa-sheqel":{"char":"","code":"f20b"},"fa-shield":{"char":"","code":"f132"},"fa-shield_halved":{"char":"","code":"ed25"},"fa-ship":{"char":"","code":"f21a"},"fa-shirt":{"char":"","code":"ee1c"},"fa-shirtsinbulk":{"char":"","code":"f214"},"fa-shoe_prints":{"char":"","code":"ee14"},"fa-shop":{"char":"","code":"ee18"},"fa-shopping_bag":{"char":"","code":"f290"},"fa-shopping_basket":{"char":"","code":"f291"},"fa-shopping_cart":{"char":"","code":"f07a"},"fa-shopware":{"char":"","code":"ee7d"},"fa-shower":{"char":"","code":"f2cc"},"fa-shuffle":{"char":"","code":"f074"},"fa-shuttle_space":{"char":"","code":"f197"},"fa-sign_hanging":{"char":"","code":"eda8"},"fa-sign_in":{"char":"","code":"f090"},"fa-sign_language":{"char":"","code":"f2a7"},"fa-sign_out":{"char":"","code":"f08b"},"fa-signal":{"char":"","code":"f012"},"fa-signature":{"char":"","code":"ee7f"},"fa-signing":{"char":"","code":"f2a7"},"fa-signs_post":{"char":"","code":"f277"},"fa-sim_card":{"char":"","code":"ef62"},"fa-simplybuilt":{"char":"","code":"f215"},"fa-sistrix":{"char":"","code":"ed26"},"fa-sitemap":{"char":"","code":"f0e8"},"fa-sith":{"char":"","code":"eddc"},"fa-sketch":{"char":"","code":"ef64"},"fa-skull":{"char":"","code":"ee15"},"fa-skull_crossbones":{"char":"","code":"ef0e"},"fa-skyatlas":{"char":"","code":"f216"},"fa-skype":{"char":"","code":"f17e"},"fa-slack":{"char":"","code":"f198"},"fa-slash":{"char":"","code":"ef0f"},"fa-sleigh":{"char":"","code":"ef67"},"fa-sliders":{"char":"","code":"f1de"},"fa-slideshare":{"char":"","code":"f1e7"},"fa-smile_o":{"char":"","code":"f118"},"fa-smog":{"char":"","code":"ef29"},"fa-smoking":{"char":"","code":"ed8c"},"fa-snapchat":{"char":"","code":"f2ab"},"fa-snapchat_ghost":{"char":"","code":"f2ac"},"fa-snapchat_square":{"char":"","code":"f2ad"},"fa-snowflake":{"char":"","code":"f2dc"},"fa-snowflake_o":{"char":"","code":"f2dc"},"fa-snowman":{"char":"","code":"ef6a"},"fa-snowplow":{"char":"","code":"ef6b"},"fa-soccer_ball_o":{"char":"","code":"f1e3"},"fa-socks":{"char":"","code":"eedf"},"fa-solar_panel":{"char":"","code":"ee81"},"fa-sort":{"char":"","code":"f0dc"},"fa-sort_alpha_asc":{"char":"","code":"f15d"},"fa-sort_alpha_desc":{"char":"","code":"f15e"},"fa-sort_amount_asc":{"char":"","code":"f160"},"fa-sort_amount_desc":{"char":"","code":"f161"},"fa-sort_asc":{"char":"","code":"f0de"},"fa-sort_desc":{"char":"","code":"f0dd"},"fa-sort_down":{"char":"","code":"f0dd"},"fa-sort_numeric_asc":{"char":"","code":"f162"},"fa-sort_numeric_desc":{"char":"","code":"f163"},"fa-sort_up":{"char":"","code":"f0de"},"fa-soundcloud":{"char":"","code":"f1be"},"fa-sourcetree":{"char":"","code":"ef6c"},"fa-spa":{"char":"","code":"ee82"},"fa-space_shuttle":{"char":"","code":"f197"},"fa-spaghetti_monster_flying":{"char":"","code":"eed5"},"fa-speakap":{"char":"","code":"ed27"},"fa-speaker_deck":{"char":"","code":"ef9b"},"fa-spell_check":{"char":"","code":"efb3"},"fa-spider":{"char":"","code":"ef10"},"fa-spinner":{"char":"","code":"f110"},"fa-splotch":{"char":"","code":"ee83"},"fa-spoon":{"char":"","code":"f1b1"},"fa-spotify":{"char":"","code":"f1bc"},"fa-spray_can":{"char":"","code":"ee84"},"fa-spray_can_sparkles":{"char":"","code":"ee97"},"fa-square":{"char":"","code":"f0c8"},"fa-square_arrow_up_right":{"char":"","code":"f14c"},"fa-square_behance":{"char":"","code":"f1b5"},"fa-square_caret_down":{"char":"","code":"f150"},"fa-square_caret_left":{"char":"","code":"f191"},"fa-square_caret_right":{"char":"","code":"f152"},"fa-square_caret_up":{"char":"","code":"f151"},"fa-square_check":{"char":"","code":"f14a"},"fa-square_dribbble":{"char":"","code":"f22e"},"fa-square_envelope":{"char":"","code":"f199"},"fa-square_facebook":{"char":"","code":"f082"},"fa-square_font_awesome_stroke":{"char":"","code":"f0af"},"fa-square_full":{"char":"","code":"ed70"},"fa-square_git":{"char":"","code":"f1d2"},"fa-square_github":{"char":"","code":"f092"},"fa-square_google_plus":{"char":"","code":"f0d4"},"fa-square_h":{"char":"","code":"f0fd"},"fa-square_hacker_news":{"char":"","code":"f2e5"},"fa-square_js":{"char":"","code":"f2ef"},"fa-square_lastfm":{"char":"","code":"f203"},"fa-square_minus":{"char":"","code":"f146"},"fa-square_o":{"char":"","code":"f096"},"fa-square_odnoklassniki":{"char":"","code":"f264"},"fa-square_parking":{"char":"","code":"efcd"},"fa-square_pen":{"char":"","code":"f14b"},"fa-square_phone":{"char":"","code":"f098"},"fa-square_phone_flip":{"char":"","code":"efaa"},"fa-square_pinterest":{"char":"","code":"f0d3"},"fa-square_plus":{"char":"","code":"f0fe"},"fa-square_poll_horizontal":{"char":"","code":"eed9"},"fa-square_poll_vertical":{"char":"","code":"eed8"},"fa-square_reddit":{"char":"","code":"f1a2"},"fa-square_root_variable":{"char":"","code":"eee0"},"fa-square_rss":{"char":"","code":"f143"},"fa-square_share_nodes":{"char":"","code":"f1e1"},"fa-square_snapchat":{"char":"","code":"f2ad"},"fa-square_steam":{"char":"","code":"f1b7"},"fa-square_tumblr":{"char":"","code":"f174"},"fa-square_twitter":{"char":"","code":"f081"},"fa-square_up_right":{"char":"","code":"f0b4"},"fa-square_viadeo":{"char":"","code":"f2aa"},"fa-square_vimeo":{"char":"","code":"f194"},"fa-square_whatsapp":{"char":"","code":"ed3b"},"fa-square_xing":{"char":"","code":"f169"},"fa-square_xmark":{"char":"","code":"f2d3"},"fa-square_youtube":{"char":"","code":"f166"},"fa-squarespace":{"char":"","code":"ee85"},"fa-stack_exchange":{"char":"","code":"f18d"},"fa-stack_overflow":{"char":"","code":"f16c"},"fa-stackpath":{"char":"","code":"efa1"},"fa-stamp":{"char":"","code":"ee86"},"fa-star":{"char":"","code":"f005"},"fa-star_and_crescent":{"char":"","code":"eee1"},"fa-star_half":{"char":"","code":"f089"},"fa-star_half_empty":{"char":"","code":"f123"},"fa-star_half_full":{"char":"","code":"f123"},"fa-star_half_o":{"char":"","code":"f123"},"fa-star_half_stroke":{"char":"","code":"ee87"},"fa-star_o":{"char":"","code":"f006"},"fa-star_of_david":{"char":"","code":"eee2"},"fa-star_of_life":{"char":"","code":"eeb1"},"fa-staylinked":{"char":"","code":"ed28"},"fa-steam":{"char":"","code":"f1b6"},"fa-steam_square":{"char":"","code":"f1b7"},"fa-steam_symbol":{"char":"","code":"ed29"},"fa-step_backward":{"char":"","code":"f048"},"fa-step_forward":{"char":"","code":"f051"},"fa-sterling_sign":{"char":"","code":"f154"},"fa-stethoscope":{"char":"","code":"f0f1"},"fa-sticker_mule":{"char":"","code":"ed2a"},"fa-sticky_note":{"char":"","code":"f249"},"fa-sticky_note_o":{"char":"","code":"f24a"},"fa-stop":{"char":"","code":"f04d"},"fa-stop_circle":{"char":"","code":"f28d"},"fa-stop_circle_o":{"char":"","code":"f28e"},"fa-stopwatch":{"char":"","code":"f2f2"},"fa-store":{"char":"","code":"ee17"},"fa-strava":{"char":"","code":"ed52"},"fa-street_view":{"char":"","code":"f21d"},"fa-strikethrough":{"char":"","code":"f0cc"},"fa-stripe":{"char":"","code":"ed53"},"fa-stripe_s":{"char":"","code":"ed54"},"fa-stroopwafel":{"char":"","code":"ee1a"},"fa-studiovinari":{"char":"","code":"ed2b"},"fa-stumbleupon":{"char":"","code":"f1a4"},"fa-stumbleupon_circle":{"char":"","code":"f1a3"},"fa-subscript":{"char":"","code":"f12c"},"fa-subway":{"char":"","code":"f239"},"fa-suitcase":{"char":"","code":"f0f2"},"fa-suitcase_medical":{"char":"","code":"f0fa"},"fa-suitcase_rolling":{"char":"","code":"ee88"},"fa-sun":{"char":"","code":"f185"},"fa-sun_o":{"char":"","code":"f185"},"fa-superpowers":{"char":"","code":"f2dd"},"fa-superscript":{"char":"","code":"f12b"},"fa-supple":{"char":"","code":"ed2c"},"fa-support":{"char":"","code":"f1cd"},"fa-suse":{"char":"","code":"ef6d"},"fa-swatchbook":{"char":"","code":"ee8a"},"fa-swift":{"char":"","code":"efbe"},"fa-symfony":{"char":"","code":"ef9c"},"fa-synagogue":{"char":"","code":"eee3"},"fa-syringe":{"char":"","code":"ed8d"},"fa-table":{"char":"","code":"f0ce"},"fa-table_cells":{"char":"","code":"f00a"},"fa-table_cells_large":{"char":"","code":"f009"},"fa-table_columns":{"char":"","code":"f0db"},"fa-table_list":{"char":"","code":"f00b"},"fa-table_tennis_paddle_ball":{"char":"","code":"ed71"},"fa-tablet":{"char":"","code":"ed2e"},"fa-tablet_button":{"char":"","code":"ed2d"},"fa-tablet_screen_button":{"char":"","code":"f10a"},"fa-tablets":{"char":"","code":"ed8e"},"fa-tachograph_digital":{"char":"","code":"ee2f"},"fa-tachometer":{"char":"","code":"f0e4"},"fa-tag":{"char":"","code":"f02b"},"fa-tags":{"char":"","code":"f02c"},"fa-tape":{"char":"","code":"edaa"},"fa-tasks":{"char":"","code":"f0ae"},"fa-taxi":{"char":"","code":"f1ba"},"fa-teamspeak":{"char":"","code":"edc3"},"fa-teeth":{"char":"","code":"eeb4"},"fa-teeth_open":{"char":"","code":"eeb5"},"fa-telegram":{"char":"","code":"f2c6"},"fa-television":{"char":"","code":"f26c"},"fa-temperature_empty":{"char":"","code":"f2cb"},"fa-temperature_full":{"char":"","code":"f2c7"},"fa-temperature_half":{"char":"","code":"f2c9"},"fa-temperature_high":{"char":"","code":"ef2a"},"fa-temperature_low":{"char":"","code":"ef2b"},"fa-temperature_quarter":{"char":"","code":"f2ca"},"fa-temperature_three_quarters":{"char":"","code":"f2c8"},"fa-tencent_weibo":{"char":"","code":"f1d5"},"fa-tenge_sign":{"char":"","code":"ef6e"},"fa-terminal":{"char":"","code":"f120"},"fa-text_height":{"char":"","code":"f034"},"fa-text_slash":{"char":"","code":"efac"},"fa-text_width":{"char":"","code":"f035"},"fa-th":{"char":"","code":"f00a"},"fa-th_large":{"char":"","code":"f009"},"fa-th_list":{"char":"","code":"f00b"},"fa-the_red_yeti":{"char":"","code":"eee4"},"fa-themeco":{"char":"","code":"ee8d"},"fa-themeisle":{"char":"","code":"f2b2"},"fa-thermometer":{"char":"","code":"f2c7"},"fa-thermometer_0":{"char":"","code":"f2cb"},"fa-thermometer_1":{"char":"","code":"f2ca"},"fa-thermometer_2":{"char":"","code":"f2c9"},"fa-thermometer_3":{"char":"","code":"f2c8"},"fa-thermometer_4":{"char":"","code":"f2c7"},"fa-thermometer_alt":{"char":"","code":"ed8f"},"fa-thermometer_empty":{"char":"","code":"f2cb"},"fa-thermometer_full":{"char":"","code":"f2c7"},"fa-thermometer_half":{"char":"","code":"f2c9"},"fa-thermometer_quarter":{"char":"","code":"f2ca"},"fa-thermometer_three_quarters":{"char":"","code":"f2c8"},"fa-think_peaks":{"char":"","code":"ef19"},"fa-thumb_tack":{"char":"","code":"f08d"},"fa-thumbs_down":{"char":"","code":"f165"},"fa-thumbs_o_down":{"char":"","code":"f088"},"fa-thumbs_o_up":{"char":"","code":"f087"},"fa-thumbs_up":{"char":"","code":"f164"},"fa-thumbtack":{"char":"","code":"f08d"},"fa-ticket":{"char":"","code":"f145"},"fa-ticket_simple":{"char":"","code":"ed30"},"fa-times":{"char":"","code":"f00d"},"fa-times_circle":{"char":"","code":"f057"},"fa-times_circle_o":{"char":"","code":"f05c"},"fa-times_rectangle":{"char":"","code":"f2d3"},"fa-times_rectangle_o":{"char":"","code":"f2d4"},"fa-tint":{"char":"","code":"f043"},"fa-toggle_down":{"char":"","code":"f150"},"fa-toggle_left":{"char":"","code":"f191"},"fa-toggle_off":{"char":"","code":"f204"},"fa-toggle_on":{"char":"","code":"f205"},"fa-toggle_right":{"char":"","code":"f152"},"fa-toggle_up":{"char":"","code":"f151"},"fa-toilet":{"char":"","code":"ef6f"},"fa-toilet_paper":{"char":"","code":"ef11"},"fa-toolbox":{"char":"","code":"ee1b"},"fa-tooth":{"char":"","code":"ee90"},"fa-torii_gate":{"char":"","code":"eee6"},"fa-tornado":{"char":"","code":"ef2d"},"fa-tower_broadcast":{"char":"","code":"ede3"},"fa-tractor":{"char":"","code":"ef12"},"fa-trade_federation":{"char":"","code":"eddd"},"fa-trademark":{"char":"","code":"f25c"},"fa-traffic_light":{"char":"","code":"eeb7"},"fa-train":{"char":"","code":"f238"},"fa-train_subway":{"char":"","code":"f239"},"fa-transgender":{"char":"","code":"f224"},"fa-transgender_alt":{"char":"","code":"f225"},"fa-trash":{"char":"","code":"f1f8"},"fa-trash_arrow_up":{"char":"","code":"ef90"},"fa-trash_can":{"char":"","code":"f014"},"fa-trash_can_arrow_up":{"char":"","code":"ef91"},"fa-trash_o":{"char":"","code":"f014"},"fa-tree":{"char":"","code":"f1bb"},"fa-trello":{"char":"","code":"f181"},"fa-triangle_exclamation":{"char":"","code":"f071"},"fa-tripadvisor":{"char":"","code":"f262"},"fa-trophy":{"char":"","code":"f091"},"fa-truck":{"char":"","code":"f0d1"},"fa-truck_fast":{"char":"","code":"ed8b"},"fa-truck_medical":{"char":"","code":"f0f9"},"fa-truck_monster":{"char":"","code":"eeb8"},"fa-truck_moving":{"char":"","code":"edac"},"fa-truck_pickup":{"char":"","code":"eeb9"},"fa-truck_ramp_box":{"char":"","code":"edab"},"fa-try":{"char":"","code":"f195"},"fa-tty":{"char":"","code":"f1e4"},"fa-tumblr":{"char":"","code":"f173"},"fa-tumblr_square":{"char":"","code":"f174"},"fa-turkish_lira":{"char":"","code":"f195"},"fa-turn_down":{"char":"","code":"f2f8"},"fa-turn_up":{"char":"","code":"f2fa"},"fa-tv":{"char":"","code":"f26c"},"fa-twitch":{"char":"","code":"f1e8"},"fa-twitter":{"char":"","code":"f099"},"fa-twitter_square":{"char":"","code":"f081"},"fa-typo3":{"char":"","code":"ed55"},"fa-uber":{"char":"","code":"ed31"},"fa-ubuntu":{"char":"","code":"ef72"},"fa-uikit":{"char":"","code":"ed32"},"fa-umbraco":{"char":"","code":"efbf"},"fa-umbrella":{"char":"","code":"f0e9"},"fa-umbrella_beach":{"char":"","code":"ee91"},"fa-underline":{"char":"","code":"f0cd"},"fa-undo":{"char":"","code":"f0e2"},"fa-uniregistry":{"char":"","code":"ed33"},"fa-universal_access":{"char":"","code":"f29a"},"fa-university":{"char":"","code":"f19c"},"fa-unlink":{"char":"","code":"f127"},"fa-unlock":{"char":"","code":"f09c"},"fa-unlock_alt":{"char":"","code":"f13e"},"fa-unlock_keyhole":{"char":"","code":"f13e"},"fa-unsorted":{"char":"","code":"f0dc"},"fa-untappd":{"char":"","code":"ed34"},"fa-up_down":{"char":"","code":"f09f"},"fa-up_down_left_right":{"char":"","code":"f0b2"},"fa-up_right_and_down_left_from_center":{"char":"","code":"ed4f"},"fa-up_right_from_square":{"char":"","code":"f0b3"},"fa-upload":{"char":"","code":"f093"},"fa-ups":{"char":"","code":"ef73"},"fa-usb":{"char":"","code":"f287"},"fa-usd":{"char":"","code":"f155"},"fa-user":{"char":"","code":"f007"},"fa-user_astronaut":{"char":"","code":"edc5"},"fa-user_check":{"char":"","code":"edc6"},"fa-user_circle":{"char":"","code":"f2bd"},"fa-user_circle_o":{"char":"","code":"f2be"},"fa-user_clock":{"char":"","code":"edc7"},"fa-user_doctor":{"char":"","code":"f0f0"},"fa-user_gear":{"char":"","code":"edc8"},"fa-user_graduate":{"char":"","code":"edcb"},"fa-user_group":{"char":"","code":"edca"},"fa-user_injured":{"char":"","code":"ef13"},"fa-user_large":{"char":"","code":"ed35"},"fa-user_large_slash":{"char":"","code":"edc4"},"fa-user_lock":{"char":"","code":"edcc"},"fa-user_md":{"char":"","code":"f0f0"},"fa-user_minus":{"char":"","code":"edcd"},"fa-user_ninja":{"char":"","code":"edce"},"fa-user_nurse":{"char":"","code":"ef92"},"fa-user_o":{"char":"","code":"f2c0"},"fa-user_pen":{"char":"","code":"edc9"},"fa-user_plus":{"char":"","code":"f234"},"fa-user_secret":{"char":"","code":"f21b"},"fa-user_shield":{"char":"","code":"edcf"},"fa-user_slash":{"char":"","code":"edd0"},"fa-user_tag":{"char":"","code":"edd1"},"fa-user_tie":{"char":"","code":"edd2"},"fa-user_times":{"char":"","code":"f235"},"fa-user_xmark":{"char":"","code":"f235"},"fa-users":{"char":"","code":"f0c0"},"fa-users_gear":{"char":"","code":"edd3"},"fa-usps":{"char":"","code":"ef74"},"fa-ussunnah":{"char":"","code":"ed36"},"fa-utensils":{"char":"","code":"f0f5"},"fa-vaadin":{"char":"","code":"ed37"},"fa-van_shuttle":{"char":"","code":"ee7e"},"fa-vcard":{"char":"","code":"f2bb"},"fa-vcard_o":{"char":"","code":"f2bc"},"fa-vector_square":{"char":"","code":"ee92"},"fa-venus":{"char":"","code":"f221"},"fa-venus_double":{"char":"","code":"f226"},"fa-venus_mars":{"char":"","code":"f228"},"fa-viacoin":{"char":"","code":"f237"},"fa-viadeo":{"char":"","code":"f2a9"},"fa-viadeo_square":{"char":"","code":"f2aa"},"fa-vial":{"char":"","code":"ed90"},"fa-vials":{"char":"","code":"ed91"},"fa-viber":{"char":"","code":"ed38"},"fa-video":{"char":"","code":"f03d"},"fa-video_camera":{"char":"","code":"f03d"},"fa-video_slash":{"char":"","code":"edad"},"fa-vihara":{"char":"","code":"eee7"},"fa-vimeo":{"char":"","code":"ed39"},"fa-vimeo_square":{"char":"","code":"f194"},"fa-vimeo_v":{"char":"","code":"f27d"},"fa-vine":{"char":"","code":"f1ca"},"fa-vk":{"char":"","code":"f189"},"fa-vnv":{"char":"","code":"ed3a"},"fa-voicemail":{"char":"","code":"efb4"},"fa-volcano":{"char":"","code":"ef2e"},"fa-volleyball":{"char":"","code":"ed72"},"fa-volume_control_phone":{"char":"","code":"f2a0"},"fa-volume_down":{"char":"","code":"f027"},"fa-volume_high":{"char":"","code":"f028"},"fa-volume_low":{"char":"","code":"f027"},"fa-volume_off":{"char":"","code":"f026"},"fa-volume_up":{"char":"","code":"f028"},"fa-volume_xmark":{"char":"","code":"eee8"},"fa-vr_cardboard":{"char":"","code":"ef14"},"fa-vuejs":{"char":"","code":"ed4a"},"fa-walkie_talkie":{"char":"","code":"efc0"},"fa-wallet":{"char":"","code":"ee1e"},"fa-wand_magic":{"char":"","code":"f0d0"},"fa-wand_sparkles":{"char":"","code":"ef15"},"fa-warehouse":{"char":"","code":"ed92"},"fa-warning":{"char":"","code":"f071"},"fa-water":{"char":"","code":"ef30"},"fa-water_ladder":{"char":"","code":"ee8c"},"fa-wave_square":{"char":"","code":"ef9d"},"fa-waze":{"char":"","code":"ef9e"},"fa-wechat":{"char":"","code":"f1d7"},"fa-weebly":{"char":"","code":"ee93"},"fa-weibo":{"char":"","code":"f18a"},"fa-weight_hanging":{"char":"","code":"ee94"},"fa-weight_scale":{"char":"","code":"ed93"},"fa-weixin":{"char":"","code":"f1d7"},"fa-whatsapp":{"char":"","code":"f232"},"fa-wheelchair":{"char":"","code":"f193"},"fa-wheelchair_alt":{"char":"","code":"f29b"},"fa-whiskey_glass":{"char":"","code":"ef4a"},"fa-whmcs":{"char":"","code":"ed3c"},"fa-wifi":{"char":"","code":"f1eb"},"fa-wikipedia_w":{"char":"","code":"f266"},"fa-wind":{"char":"","code":"ef16"},"fa-window_close":{"char":"","code":"f2d3"},"fa-window_close_o":{"char":"","code":"f2d4"},"fa-window_maximize":{"char":"","code":"f2d0"},"fa-window_minimize":{"char":"","code":"f2d1"},"fa-window_restore":{"char":"","code":"f2d2"},"fa-windows":{"char":"","code":"f17a"},"fa-wine_bottle":{"char":"","code":"ef17"},"fa-wine_glass":{"char":"","code":"edae"},"fa-wine_glass_empty":{"char":"","code":"ee95"},"fa-wix":{"char":"","code":"ee96"},"fa-wizards_of_the_coast":{"char":"","code":"ef18"},"fa-wolf_pack_battalion":{"char":"","code":"edde"},"fa-won":{"char":"","code":"f159"},"fa-won_sign":{"char":"","code":"f159"},"fa-wordpress":{"char":"","code":"f19a"},"fa-wordpress_simple":{"char":"","code":"ed3d"},"fa-wpbeginner":{"char":"","code":"f297"},"fa-wpexplorer":{"char":"","code":"f2de"},"fa-wpforms":{"char":"","code":"f298"},"fa-wpressr":{"char":"","code":"ed1d"},"fa-wrench":{"char":"","code":"f0ad"},"fa-x_ray":{"char":"","code":"ed94"},"fa-xbox":{"char":"","code":"ed3e"},"fa-xing":{"char":"","code":"f168"},"fa-xing_square":{"char":"","code":"f169"},"fa-xmark":{"char":"","code":"f00d"},"fa-y_combinator":{"char":"","code":"f23b"},"fa-y_combinator_square":{"char":"","code":"f1d4"},"fa-yahoo":{"char":"","code":"f19e"},"fa-yammer":{"char":"","code":"ef9f"},"fa-yandex":{"char":"","code":"ed3f"},"fa-yandex_international":{"char":"","code":"ed40"},"fa-yarn":{"char":"","code":"ef75"},"fa-yc":{"char":"","code":"f23b"},"fa-yc_square":{"char":"","code":"f1d4"},"fa-yelp":{"char":"","code":"f1e9"},"fa-yen":{"char":"","code":"f157"},"fa-yen_sign":{"char":"","code":"f157"},"fa-yin_yang":{"char":"","code":"eee9"},"fa-yoast":{"char":"","code":"f2b1"},"fa-youtube":{"char":"","code":"f16a"},"fa-youtube_play":{"char":"","code":"f16a"},"fa-youtube_square":{"char":"","code":"f166"},"fa-zhihu":{"char":"","code":"eeba"},"fae-apple_fruit":{"char":"","code":"e29e"},"fae-atom":{"char":"","code":"e27f"},"fae-bacteria":{"char":"","code":"e280"},"fae-banana":{"char":"","code":"e281"},"fae-bath":{"char":"","code":"e282"},"fae-bed":{"char":"","code":"e283"},"fae-benzene":{"char":"","code":"e284"},"fae-bigger":{"char":"","code":"e285"},"fae-biohazard":{"char":"","code":"e286"},"fae-blogger_circle":{"char":"","code":"e287"},"fae-blogger_square":{"char":"","code":"e288"},"fae-bones":{"char":"","code":"e289"},"fae-book_open":{"char":"","code":"e28a"},"fae-book_open_o":{"char":"","code":"e28b"},"fae-brain":{"char":"","code":"e28c"},"fae-bread":{"char":"","code":"e28d"},"fae-butterfly":{"char":"","code":"e28e"},"fae-carot":{"char":"","code":"e28f"},"fae-cc_by":{"char":"","code":"e290"},"fae-cc_cc":{"char":"","code":"e291"},"fae-cc_nc":{"char":"","code":"e292"},"fae-cc_nc_eu":{"char":"","code":"e293"},"fae-cc_nc_jp":{"char":"","code":"e294"},"fae-cc_nd":{"char":"","code":"e295"},"fae-cc_remix":{"char":"","code":"e296"},"fae-cc_sa":{"char":"","code":"e297"},"fae-cc_share":{"char":"","code":"e298"},"fae-cc_zero":{"char":"","code":"e299"},"fae-checklist_o":{"char":"","code":"e29a"},"fae-cheese":{"char":"","code":"e264"},"fae-cherry":{"char":"","code":"e29b"},"fae-chess_bishop":{"char":"","code":"e29c"},"fae-chess_horse":{"char":"","code":"e25f"},"fae-chess_king":{"char":"","code":"e260"},"fae-chess_pawn":{"char":"","code":"e261"},"fae-chess_queen":{"char":"","code":"e262"},"fae-chess_tower":{"char":"","code":"e263"},"fae-chicken_thigh":{"char":"","code":"e29f"},"fae-chilli":{"char":"","code":"e265"},"fae-chip":{"char":"","code":"e266"},"fae-cicling":{"char":"","code":"e267"},"fae-cloud":{"char":"","code":"e268"},"fae-cockroach":{"char":"","code":"e269"},"fae-coffe_beans":{"char":"","code":"e26a"},"fae-coins":{"char":"","code":"e26b"},"fae-comb":{"char":"","code":"e26c"},"fae-comet":{"char":"","code":"e26d"},"fae-crown":{"char":"","code":"e26e"},"fae-cup_coffe":{"char":"","code":"e26f"},"fae-dice":{"char":"","code":"e270"},"fae-disco":{"char":"","code":"e271"},"fae-dna":{"char":"","code":"e272"},"fae-donut":{"char":"","code":"e273"},"fae-dress":{"char":"","code":"e274"},"fae-drop":{"char":"","code":"e275"},"fae-ello":{"char":"","code":"e276"},"fae-envelope_open":{"char":"","code":"e277"},"fae-envelope_open_o":{"char":"","code":"e278"},"fae-equal":{"char":"","code":"e279"},"fae-equal_bigger":{"char":"","code":"e27a"},"fae-feedly":{"char":"","code":"e27b"},"fae-file_export":{"char":"","code":"e27c"},"fae-file_import":{"char":"","code":"e27d"},"fae-fingerprint":{"char":"","code":"e23f"},"fae-floppy":{"char":"","code":"e240"},"fae-footprint":{"char":"","code":"e241"},"fae-freecodecamp":{"char":"","code":"e242"},"fae-galaxy":{"char":"","code":"e243"},"fae-galery":{"char":"","code":"e244"},"fae-gift_card":{"char":"","code":"e2a0"},"fae-glass":{"char":"","code":"e245"},"fae-google_drive":{"char":"","code":"e246"},"fae-google_play":{"char":"","code":"e247"},"fae-gps":{"char":"","code":"e248"},"fae-grav":{"char":"","code":"e249"},"fae-guitar":{"char":"","code":"e24a"},"fae-gut":{"char":"","code":"e24b"},"fae-halter":{"char":"","code":"e24c"},"fae-hamburger":{"char":"","code":"e24d"},"fae-hat":{"char":"","code":"e24e"},"fae-hexagon":{"char":"","code":"e24f"},"fae-high_heel":{"char":"","code":"e250"},"fae-hotdog":{"char":"","code":"e251"},"fae-ice_cream":{"char":"","code":"e252"},"fae-id_card":{"char":"","code":"e253"},"fae-imdb":{"char":"","code":"e254"},"fae-infinity":{"char":"","code":"e255"},"fae-injection":{"char":"","code":"e2a1"},"fae-isle":{"char":"","code":"e2a2"},"fae-java":{"char":"","code":"e256"},"fae-layers":{"char":"","code":"e257"},"fae-lips":{"char":"","code":"e258"},"fae-lipstick":{"char":"","code":"e259"},"fae-liver":{"char":"","code":"e25a"},"fae-lollipop":{"char":"","code":"e2a3"},"fae-loyalty_card":{"char":"","code":"e2a4"},"fae-lung":{"char":"","code":"e25b"},"fae-makeup_brushes":{"char":"","code":"e25c"},"fae-maximize":{"char":"","code":"e25d"},"fae-meat":{"char":"","code":"e2a5"},"fae-medicine":{"char":"","code":"e221"},"fae-microscope":{"char":"","code":"e222"},"fae-milk_bottle":{"char":"","code":"e223"},"fae-minimize":{"char":"","code":"e224"},"fae-molecule":{"char":"","code":"e225"},"fae-moon_cloud":{"char":"","code":"e226"},"fae-mountains":{"char":"","code":"e2a6"},"fae-mushroom":{"char":"","code":"e227"},"fae-mustache":{"char":"","code":"e228"},"fae-mysql":{"char":"","code":"e229"},"fae-nintendo":{"char":"","code":"e22a"},"fae-orange":{"char":"","code":"e2a7"},"fae-palette_color":{"char":"","code":"e22b"},"fae-peach":{"char":"","code":"e2a8"},"fae-pear":{"char":"","code":"e2a9"},"fae-pi":{"char":"","code":"e22c"},"fae-pizza":{"char":"","code":"e22d"},"fae-planet":{"char":"","code":"e22e"},"fae-plant":{"char":"","code":"e22f"},"fae-playstation":{"char":"","code":"e230"},"fae-poison":{"char":"","code":"e231"},"fae-popcorn":{"char":"","code":"e232"},"fae-popsicle":{"char":"","code":"e233"},"fae-pulse":{"char":"","code":"e234"},"fae-python":{"char":"","code":"e235"},"fae-quora_circle":{"char":"","code":"e236"},"fae-quora_square":{"char":"","code":"e237"},"fae-radioactive":{"char":"","code":"e238"},"fae-raining":{"char":"","code":"e239"},"fae-real_heart":{"char":"","code":"e23a"},"fae-refrigerator":{"char":"","code":"e23b"},"fae-restore":{"char":"","code":"e23c"},"fae-ring":{"char":"","code":"e23d"},"fae-ruby":{"char":"","code":"e23e"},"fae-ruby_o":{"char":"","code":"e21e"},"fae-ruler":{"char":"","code":"e21f"},"fae-shirt":{"char":"","code":"e218"},"fae-slash":{"char":"","code":"e216"},"fae-smaller":{"char":"","code":"e200"},"fae-snowing":{"char":"","code":"e201"},"fae-soda":{"char":"","code":"e202"},"fae-sofa":{"char":"","code":"e203"},"fae-soup":{"char":"","code":"e204"},"fae-spermatozoon":{"char":"","code":"e205"},"fae-spin_double":{"char":"","code":"e206"},"fae-stomach":{"char":"","code":"e207"},"fae-storm":{"char":"","code":"e208"},"fae-sun_cloud":{"char":"","code":"e21d"},"fae-sushi":{"char":"","code":"e21a"},"fae-tacos":{"char":"","code":"e219"},"fae-telegram":{"char":"","code":"e217"},"fae-telegram_circle":{"char":"","code":"e215"},"fae-telescope":{"char":"","code":"e209"},"fae-thermometer":{"char":"","code":"e20a"},"fae-thermometer_high":{"char":"","code":"e20b"},"fae-thermometer_low":{"char":"","code":"e20c"},"fae-thin_close":{"char":"","code":"e20d"},"fae-toilet":{"char":"","code":"e20e"},"fae-tools":{"char":"","code":"e20f"},"fae-tooth":{"char":"","code":"e210"},"fae-tree":{"char":"","code":"e21c"},"fae-triangle_ruler":{"char":"","code":"e21b"},"fae-umbrella":{"char":"","code":"e220"},"fae-uterus":{"char":"","code":"e211"},"fae-virus":{"char":"","code":"e214"},"fae-w3c":{"char":"","code":"e212"},"fae-walking":{"char":"","code":"e213"},"fae-wallet":{"char":"","code":"e25e"},"fae-wind":{"char":"","code":"e27e"},"fae-xbox":{"char":"","code":"e29d"},"iec-power":{"char":"⏻","code":"23fb"},"iec-power_off":{"char":"⭘","code":"2b58"},"iec-power_on":{"char":"⏽","code":"23fd"},"iec-sleep_mode":{"char":"⏾","code":"23fe"},"iec-toggle_power":{"char":"⏼","code":"23fc"},"indent-dotted_guide":{"char":"","code":"e621"},"indent-line":{"char":"","code":"e621"},"indentation-line":{"char":"","code":"e621"},"linux-almalinux":{"char":"","code":"f31d"},"linux-alpine":{"char":"","code":"f300"},"linux-aosc":{"char":"","code":"f301"},"linux-apple":{"char":"","code":"f302"},"linux-archcraft":{"char":"","code":"f345"},"linux-archlabs":{"char":"","code":"f31e"},"linux-archlinux":{"char":"","code":"f303"},"linux-arcolinux":{"char":"","code":"f346"},"linux-arduino":{"char":"","code":"f34b"},"linux-artix":{"char":"","code":"f31f"},"linux-awesome":{"char":"","code":"f354"},"linux-biglinux":{"char":"","code":"f347"},"linux-bspwm":{"char":"","code":"f355"},"linux-budgie":{"char":"","code":"f320"},"linux-centos":{"char":"","code":"f304"},"linux-cinnamon":{"char":"","code":"f35f"},"linux-codeberg":{"char":"","code":"f330"},"linux-coreos":{"char":"","code":"f305"},"linux-crystal":{"char":"","code":"f348"},"linux-debian":{"char":"","code":"f306"},"linux-deepin":{"char":"","code":"f321"},"linux-devuan":{"char":"","code":"f307"},"linux-docker":{"char":"","code":"f308"},"linux-dwm":{"char":"","code":"f356"},"linux-elementary":{"char":"","code":"f309"},"linux-endeavour":{"char":"","code":"f322"},"linux-enlightenment":{"char":"","code":"f357"},"linux-fdroid":{"char":"","code":"f36a"},"linux-fedora":{"char":"","code":"f30a"},"linux-fedora_inverse":{"char":"","code":"f30b"},"linux-ferris":{"char":"","code":"f323"},"linux-flathub":{"char":"","code":"f324"},"linux-fluxbox":{"char":"","code":"f358"},"linux-forgejo":{"char":"","code":"f335"},"linux-fosdem":{"char":"","code":"f36b"},"linux-freebsd":{"char":"","code":"f30c"},"linux-freecad":{"char":"","code":"f336"},"linux-freedesktop":{"char":"","code":"f360"},"linux-garuda":{"char":"","code":"f337"},"linux-gentoo":{"char":"","code":"f30d"},"linux-gimp":{"char":"","code":"f338"},"linux-gitea":{"char":"","code":"f339"},"linux-gnome":{"char":"","code":"f361"},"linux-gnu_guix":{"char":"","code":"f325"},"linux-gtk":{"char":"","code":"f362"},"linux-hyperbola":{"char":"","code":"f33a"},"linux-hyprland":{"char":"","code":"f359"},"linux-i3":{"char":"","code":"f35a"},"linux-illumos":{"char":"","code":"f326"},"linux-inkscape":{"char":"","code":"f33b"},"linux-jwm":{"char":"","code":"f35b"},"linux-kali_linux":{"char":"","code":"f327"},"linux-kde":{"char":"","code":"f373"},"linux-kde_neon":{"char":"","code":"f331"},"linux-kde_plasma":{"char":"","code":"f332"},"linux-kdenlive":{"char":"","code":"f33c"},"linux-kicad":{"char":"","code":"f34c"},"linux-krita":{"char":"","code":"f33d"},"linux-kubuntu":{"char":"","code":"f333"},"linux-kubuntu_inverse":{"char":"","code":"f334"},"linux-linuxmint":{"char":"","code":"f30e"},"linux-linuxmint_inverse":{"char":"","code":"f30f"},"linux-locos":{"char":"","code":"f349"},"linux-lxde":{"char":"","code":"f363"},"linux-lxle":{"char":"","code":"f33e"},"linux-lxqt":{"char":"","code":"f364"},"linux-mageia":{"char":"","code":"f310"},"linux-mandriva":{"char":"","code":"f311"},"linux-manjaro":{"char":"","code":"f312"},"linux-mate":{"char":"","code":"f365"},"linux-mpv":{"char":"","code":"f36e"},"linux-mxlinux":{"char":"","code":"f33f"},"linux-neovim":{"char":"","code":"f36f"},"linux-nixos":{"char":"","code":"f313"},"linux-octoprint":{"char":"","code":"f34d"},"linux-openbsd":{"char":"","code":"f328"},"linux-openscad":{"char":"","code":"f34e"},"linux-opensuse":{"char":"","code":"f314"},"linux-osh":{"char":"","code":"f34f"},"linux-oshwa":{"char":"","code":"f350"},"linux-osi":{"char":"","code":"f36c"},"linux-parabola":{"char":"","code":"f340"},"linux-parrot":{"char":"","code":"f329"},"linux-pop_os":{"char":"","code":"f32a"},"linux-postmarketos":{"char":"","code":"f374"},"linux-prusaslicer":{"char":"","code":"f351"},"linux-puppy":{"char":"","code":"f341"},"linux-qt":{"char":"","code":"f375"},"linux-qtile":{"char":"","code":"f35c"},"linux-qubesos":{"char":"","code":"f342"},"linux-raspberry_pi":{"char":"","code":"f315"},"linux-redhat":{"char":"","code":"f316"},"linux-reprap":{"char":"","code":"f352"},"linux-riscv":{"char":"","code":"f353"},"linux-rocky_linux":{"char":"","code":"f32b"},"linux-sabayon":{"char":"","code":"f317"},"linux-slackware":{"char":"","code":"f318"},"linux-slackware_inverse":{"char":"","code":"f319"},"linux-snappy":{"char":"","code":"f32c"},"linux-solus":{"char":"","code":"f32d"},"linux-sway":{"char":"","code":"f35d"},"linux-tails":{"char":"","code":"f343"},"linux-thunderbird":{"char":"","code":"f370"},"linux-tor":{"char":"","code":"f371"},"linux-trisquel":{"char":"","code":"f344"},"linux-tux":{"char":"","code":"f31a"},"linux-ubuntu":{"char":"","code":"f31b"},"linux-ubuntu_inverse":{"char":"","code":"f31c"},"linux-vanilla":{"char":"","code":"f366"},"linux-void":{"char":"","code":"f32e"},"linux-vscodium":{"char":"","code":"f372"},"linux-wayland":{"char":"","code":"f367"},"linux-wikimedia":{"char":"","code":"f36d"},"linux-xerolinux":{"char":"","code":"f34a"},"linux-xfce":{"char":"","code":"f368"},"linux-xmonad":{"char":"","code":"f35e"},"linux-xorg":{"char":"","code":"f369"},"linux-zorin":{"char":"","code":"f32f"},"md-ab_testing":{"char":"󰇉","code":"f01c9"},"md-abacus":{"char":"󱛠","code":"f16e0"},"md-abjad_arabic":{"char":"󱌨","code":"f1328"},"md-abjad_hebrew":{"char":"󱌩","code":"f1329"},"md-abugida_devanagari":{"char":"󱌪","code":"f132a"},"md-abugida_thai":{"char":"󱌫","code":"f132b"},"md-access_point":{"char":"󰀃","code":"f0003"},"md-access_point_check":{"char":"󱔸","code":"f1538"},"md-access_point_minus":{"char":"󱔹","code":"f1539"},"md-access_point_network":{"char":"󰀂","code":"f0002"},"md-access_point_network_off":{"char":"󰯡","code":"f0be1"},"md-access_point_off":{"char":"󱔑","code":"f1511"},"md-access_point_plus":{"char":"󱔺","code":"f153a"},"md-access_point_remove":{"char":"󱔻","code":"f153b"},"md-account":{"char":"󰀄","code":"f0004"},"md-account_alert":{"char":"󰀅","code":"f0005"},"md-account_alert_outline":{"char":"󰭐","code":"f0b50"},"md-account_arrow_down":{"char":"󱡨","code":"f1868"},"md-account_arrow_down_outline":{"char":"󱡩","code":"f1869"},"md-account_arrow_left":{"char":"󰭑","code":"f0b51"},"md-account_arrow_left_outline":{"char":"󰭒","code":"f0b52"},"md-account_arrow_right":{"char":"󰭓","code":"f0b53"},"md-account_arrow_right_outline":{"char":"󰭔","code":"f0b54"},"md-account_arrow_up":{"char":"󱡧","code":"f1867"},"md-account_arrow_up_outline":{"char":"󱡪","code":"f186a"},"md-account_box":{"char":"󰀆","code":"f0006"},"md-account_box_multiple":{"char":"󰤴","code":"f0934"},"md-account_box_multiple_outline":{"char":"󱀊","code":"f100a"},"md-account_box_outline":{"char":"󰀇","code":"f0007"},"md-account_cancel":{"char":"󱋟","code":"f12df"},"md-account_cancel_outline":{"char":"󱋠","code":"f12e0"},"md-account_cash":{"char":"󱂗","code":"f1097"},"md-account_cash_outline":{"char":"󱂘","code":"f1098"},"md-account_check":{"char":"󰀈","code":"f0008"},"md-account_check_outline":{"char":"󰯢","code":"f0be2"},"md-account_child":{"char":"󰪉","code":"f0a89"},"md-account_child_circle":{"char":"󰪊","code":"f0a8a"},"md-account_child_outline":{"char":"󱃈","code":"f10c8"},"md-account_circle":{"char":"󰀉","code":"f0009"},"md-account_circle_outline":{"char":"󰭕","code":"f0b55"},"md-account_clock":{"char":"󰭖","code":"f0b56"},"md-account_clock_outline":{"char":"󰭗","code":"f0b57"},"md-account_cog":{"char":"󱍰","code":"f1370"},"md-account_cog_outline":{"char":"󱍱","code":"f1371"},"md-account_convert":{"char":"󰀊","code":"f000a"},"md-account_convert_outline":{"char":"󱌁","code":"f1301"},"md-account_cowboy_hat":{"char":"󰺛","code":"f0e9b"},"md-account_cowboy_hat_outline":{"char":"󱟳","code":"f17f3"},"md-account_details":{"char":"󰘱","code":"f0631"},"md-account_details_outline":{"char":"󱍲","code":"f1372"},"md-account_edit":{"char":"󰚼","code":"f06bc"},"md-account_edit_outline":{"char":"󰿻","code":"f0ffb"},"md-account_eye":{"char":"󰐠","code":"f0420"},"md-account_eye_outline":{"char":"󱉻","code":"f127b"},"md-account_filter":{"char":"󰤶","code":"f0936"},"md-account_filter_outline":{"char":"󰾝","code":"f0f9d"},"md-account_group":{"char":"󰡉","code":"f0849"},"md-account_group_outline":{"char":"󰭘","code":"f0b58"},"md-account_hard_hat":{"char":"󰖵","code":"f05b5"},"md-account_hard_hat_outline":{"char":"󱨟","code":"f1a1f"},"md-account_heart":{"char":"󰢙","code":"f0899"},"md-account_heart_outline":{"char":"󰯣","code":"f0be3"},"md-account_injury":{"char":"󱠕","code":"f1815"},"md-account_injury_outline":{"char":"󱠖","code":"f1816"},"md-account_key":{"char":"󰀋","code":"f000b"},"md-account_key_outline":{"char":"󰯤","code":"f0be4"},"md-account_lock":{"char":"󱅞","code":"f115e"},"md-account_lock_open":{"char":"󱥠","code":"f1960"},"md-account_lock_open_outline":{"char":"󱥡","code":"f1961"},"md-account_lock_outline":{"char":"󱅟","code":"f115f"},"md-account_minus":{"char":"󰀍","code":"f000d"},"md-account_minus_outline":{"char":"󰫬","code":"f0aec"},"md-account_multiple":{"char":"󰀎","code":"f000e"},"md-account_multiple_check":{"char":"󰣅","code":"f08c5"},"md-account_multiple_check_outline":{"char":"󱇾","code":"f11fe"},"md-account_multiple_minus":{"char":"󰗓","code":"f05d3"},"md-account_multiple_minus_outline":{"char":"󰯥","code":"f0be5"},"md-account_multiple_outline":{"char":"󰀏","code":"f000f"},"md-account_multiple_plus":{"char":"󰀐","code":"f0010"},"md-account_multiple_plus_outline":{"char":"󰠀","code":"f0800"},"md-account_multiple_remove":{"char":"󱈊","code":"f120a"},"md-account_multiple_remove_outline":{"char":"󱈋","code":"f120b"},"md-account_music":{"char":"󰠃","code":"f0803"},"md-account_music_outline":{"char":"󰳩","code":"f0ce9"},"md-account_network":{"char":"󰀑","code":"f0011"},"md-account_network_outline":{"char":"󰯦","code":"f0be6"},"md-account_off":{"char":"󰀒","code":"f0012"},"md-account_off_outline":{"char":"󰯧","code":"f0be7"},"md-account_outline":{"char":"󰀓","code":"f0013"},"md-account_plus":{"char":"󰀔","code":"f0014"},"md-account_plus_outline":{"char":"󰠁","code":"f0801"},"md-account_question":{"char":"󰭙","code":"f0b59"},"md-account_question_outline":{"char":"󰭚","code":"f0b5a"},"md-account_reactivate":{"char":"󱔫","code":"f152b"},"md-account_reactivate_outline":{"char":"󱔬","code":"f152c"},"md-account_remove":{"char":"󰀕","code":"f0015"},"md-account_remove_outline":{"char":"󰫭","code":"f0aed"},"md-account_school":{"char":"󱨠","code":"f1a20"},"md-account_school_outline":{"char":"󱨡","code":"f1a21"},"md-account_search":{"char":"󰀖","code":"f0016"},"md-account_search_outline":{"char":"󰤵","code":"f0935"},"md-account_settings":{"char":"󰘰","code":"f0630"},"md-account_settings_outline":{"char":"󱃉","code":"f10c9"},"md-account_star":{"char":"󰀗","code":"f0017"},"md-account_star_outline":{"char":"󰯨","code":"f0be8"},"md-account_supervisor":{"char":"󰪋","code":"f0a8b"},"md-account_supervisor_circle":{"char":"󰪌","code":"f0a8c"},"md-account_supervisor_circle_outline":{"char":"󱓬","code":"f14ec"},"md-account_supervisor_outline":{"char":"󱄭","code":"f112d"},"md-account_switch":{"char":"󰀙","code":"f0019"},"md-account_switch_outline":{"char":"󰓋","code":"f04cb"},"md-account_sync":{"char":"󱤛","code":"f191b"},"md-account_sync_outline":{"char":"󱤜","code":"f191c"},"md-account_tie":{"char":"󰳣","code":"f0ce3"},"md-account_tie_hat":{"char":"󱢘","code":"f1898"},"md-account_tie_hat_outline":{"char":"󱢙","code":"f1899"},"md-account_tie_outline":{"char":"󱃊","code":"f10ca"},"md-account_tie_voice":{"char":"󱌈","code":"f1308"},"md-account_tie_voice_off":{"char":"󱌊","code":"f130a"},"md-account_tie_voice_off_outline":{"char":"󱌋","code":"f130b"},"md-account_tie_voice_outline":{"char":"󱌉","code":"f1309"},"md-account_tie_woman":{"char":"󱪌","code":"f1a8c"},"md-account_voice":{"char":"󰗋","code":"f05cb"},"md-account_voice_off":{"char":"󰻔","code":"f0ed4"},"md-account_wrench":{"char":"󱢚","code":"f189a"},"md-account_wrench_outline":{"char":"󱢛","code":"f189b"},"md-adjust":{"char":"󰀚","code":"f001a"},"md-advertisements":{"char":"󱤪","code":"f192a"},"md-advertisements_off":{"char":"󱤫","code":"f192b"},"md-air_conditioner":{"char":"󰀛","code":"f001b"},"md-air_filter":{"char":"󰵃","code":"f0d43"},"md-air_horn":{"char":"󰶬","code":"f0dac"},"md-air_humidifier":{"char":"󱂙","code":"f1099"},"md-air_humidifier_off":{"char":"󱑦","code":"f1466"},"md-air_purifier":{"char":"󰵄","code":"f0d44"},"md-airbag":{"char":"󰯩","code":"f0be9"},"md-airballoon":{"char":"󰀜","code":"f001c"},"md-airballoon_outline":{"char":"󱀋","code":"f100b"},"md-airplane":{"char":"󰀝","code":"f001d"},"md-airplane_alert":{"char":"󱡺","code":"f187a"},"md-airplane_check":{"char":"󱡻","code":"f187b"},"md-airplane_clock":{"char":"󱡼","code":"f187c"},"md-airplane_cog":{"char":"󱡽","code":"f187d"},"md-airplane_edit":{"char":"󱡾","code":"f187e"},"md-airplane_landing":{"char":"󰗔","code":"f05d4"},"md-airplane_marker":{"char":"󱡿","code":"f187f"},"md-airplane_minus":{"char":"󱢀","code":"f1880"},"md-airplane_off":{"char":"󰀞","code":"f001e"},"md-airplane_plus":{"char":"󱢁","code":"f1881"},"md-airplane_remove":{"char":"󱢂","code":"f1882"},"md-airplane_search":{"char":"󱢃","code":"f1883"},"md-airplane_settings":{"char":"󱢄","code":"f1884"},"md-airplane_takeoff":{"char":"󰗕","code":"f05d5"},"md-airport":{"char":"󰡋","code":"f084b"},"md-alarm":{"char":"󰀠","code":"f0020"},"md-alarm_bell":{"char":"󰞎","code":"f078e"},"md-alarm_check":{"char":"󰀡","code":"f0021"},"md-alarm_light":{"char":"󰞏","code":"f078f"},"md-alarm_light_off":{"char":"󱜞","code":"f171e"},"md-alarm_light_off_outline":{"char":"󱜟","code":"f171f"},"md-alarm_light_outline":{"char":"󰯪","code":"f0bea"},"md-alarm_multiple":{"char":"󰀢","code":"f0022"},"md-alarm_note":{"char":"󰹱","code":"f0e71"},"md-alarm_note_off":{"char":"󰹲","code":"f0e72"},"md-alarm_off":{"char":"󰀣","code":"f0023"},"md-alarm_panel":{"char":"󱗄","code":"f15c4"},"md-alarm_panel_outline":{"char":"󱗅","code":"f15c5"},"md-alarm_plus":{"char":"󰀤","code":"f0024"},"md-alarm_snooze":{"char":"󰚎","code":"f068e"},"md-album":{"char":"󰀥","code":"f0025"},"md-alert":{"char":"󰀦","code":"f0026"},"md-alert_box":{"char":"󰀧","code":"f0027"},"md-alert_box_outline":{"char":"󰳤","code":"f0ce4"},"md-alert_circle":{"char":"󰀨","code":"f0028"},"md-alert_circle_check":{"char":"󱇭","code":"f11ed"},"md-alert_circle_check_outline":{"char":"󱇮","code":"f11ee"},"md-alert_circle_outline":{"char":"󰗖","code":"f05d6"},"md-alert_decagram":{"char":"󰚽","code":"f06bd"},"md-alert_decagram_outline":{"char":"󰳥","code":"f0ce5"},"md-alert_minus":{"char":"󱒻","code":"f14bb"},"md-alert_minus_outline":{"char":"󱒾","code":"f14be"},"md-alert_octagon":{"char":"󰀩","code":"f0029"},"md-alert_octagon_outline":{"char":"󰳦","code":"f0ce6"},"md-alert_octagram":{"char":"󰝧","code":"f0767"},"md-alert_octagram_outline":{"char":"󰳧","code":"f0ce7"},"md-alert_outline":{"char":"󰀪","code":"f002a"},"md-alert_plus":{"char":"󱒺","code":"f14ba"},"md-alert_plus_outline":{"char":"󱒽","code":"f14bd"},"md-alert_remove":{"char":"󱒼","code":"f14bc"},"md-alert_remove_outline":{"char":"󱒿","code":"f14bf"},"md-alert_rhombus":{"char":"󱇎","code":"f11ce"},"md-alert_rhombus_outline":{"char":"󱇏","code":"f11cf"},"md-alien":{"char":"󰢚","code":"f089a"},"md-alien_outline":{"char":"󱃋","code":"f10cb"},"md-align_horizontal_center":{"char":"󱇃","code":"f11c3"},"md-align_horizontal_distribute":{"char":"󱥢","code":"f1962"},"md-align_horizontal_left":{"char":"󱇂","code":"f11c2"},"md-align_horizontal_right":{"char":"󱇄","code":"f11c4"},"md-align_vertical_bottom":{"char":"󱇅","code":"f11c5"},"md-align_vertical_center":{"char":"󱇆","code":"f11c6"},"md-align_vertical_distribute":{"char":"󱥣","code":"f1963"},"md-align_vertical_top":{"char":"󱇇","code":"f11c7"},"md-all_inclusive":{"char":"󰚾","code":"f06be"},"md-all_inclusive_box":{"char":"󱢍","code":"f188d"},"md-all_inclusive_box_outline":{"char":"󱢎","code":"f188e"},"md-allergy":{"char":"󱉘","code":"f1258"},"md-alpha":{"char":"󰀫","code":"f002b"},"md-alpha_a":{"char":"󰫮","code":"f0aee"},"md-alpha_a_box":{"char":"󰬈","code":"f0b08"},"md-alpha_a_box_outline":{"char":"󰯫","code":"f0beb"},"md-alpha_a_circle":{"char":"󰯬","code":"f0bec"},"md-alpha_a_circle_outline":{"char":"󰯭","code":"f0bed"},"md-alpha_b":{"char":"󰫯","code":"f0aef"},"md-alpha_b_box":{"char":"󰬉","code":"f0b09"},"md-alpha_b_box_outline":{"char":"󰯮","code":"f0bee"},"md-alpha_b_circle":{"char":"󰯯","code":"f0bef"},"md-alpha_b_circle_outline":{"char":"󰯰","code":"f0bf0"},"md-alpha_c":{"char":"󰫰","code":"f0af0"},"md-alpha_c_box":{"char":"󰬊","code":"f0b0a"},"md-alpha_c_box_outline":{"char":"󰯱","code":"f0bf1"},"md-alpha_c_circle":{"char":"󰯲","code":"f0bf2"},"md-alpha_c_circle_outline":{"char":"󰯳","code":"f0bf3"},"md-alpha_d":{"char":"󰫱","code":"f0af1"},"md-alpha_d_box":{"char":"󰬋","code":"f0b0b"},"md-alpha_d_box_outline":{"char":"󰯴","code":"f0bf4"},"md-alpha_d_circle":{"char":"󰯵","code":"f0bf5"},"md-alpha_d_circle_outline":{"char":"󰯶","code":"f0bf6"},"md-alpha_e":{"char":"󰫲","code":"f0af2"},"md-alpha_e_box":{"char":"󰬌","code":"f0b0c"},"md-alpha_e_box_outline":{"char":"󰯷","code":"f0bf7"},"md-alpha_e_circle":{"char":"󰯸","code":"f0bf8"},"md-alpha_e_circle_outline":{"char":"󰯹","code":"f0bf9"},"md-alpha_f":{"char":"󰫳","code":"f0af3"},"md-alpha_f_box":{"char":"󰬍","code":"f0b0d"},"md-alpha_f_box_outline":{"char":"󰯺","code":"f0bfa"},"md-alpha_f_circle":{"char":"󰯻","code":"f0bfb"},"md-alpha_f_circle_outline":{"char":"󰯼","code":"f0bfc"},"md-alpha_g":{"char":"󰫴","code":"f0af4"},"md-alpha_g_box":{"char":"󰬎","code":"f0b0e"},"md-alpha_g_box_outline":{"char":"󰯽","code":"f0bfd"},"md-alpha_g_circle":{"char":"󰯾","code":"f0bfe"},"md-alpha_g_circle_outline":{"char":"󰯿","code":"f0bff"},"md-alpha_h":{"char":"󰫵","code":"f0af5"},"md-alpha_h_box":{"char":"󰬏","code":"f0b0f"},"md-alpha_h_box_outline":{"char":"󰰀","code":"f0c00"},"md-alpha_h_circle":{"char":"󰰁","code":"f0c01"},"md-alpha_h_circle_outline":{"char":"󰰂","code":"f0c02"},"md-alpha_i":{"char":"󰫶","code":"f0af6"},"md-alpha_i_box":{"char":"󰬐","code":"f0b10"},"md-alpha_i_box_outline":{"char":"󰰃","code":"f0c03"},"md-alpha_i_circle":{"char":"󰰄","code":"f0c04"},"md-alpha_i_circle_outline":{"char":"󰰅","code":"f0c05"},"md-alpha_j":{"char":"󰫷","code":"f0af7"},"md-alpha_j_box":{"char":"󰬑","code":"f0b11"},"md-alpha_j_box_outline":{"char":"󰰆","code":"f0c06"},"md-alpha_j_circle":{"char":"󰰇","code":"f0c07"},"md-alpha_j_circle_outline":{"char":"󰰈","code":"f0c08"},"md-alpha_k":{"char":"󰫸","code":"f0af8"},"md-alpha_k_box":{"char":"󰬒","code":"f0b12"},"md-alpha_k_box_outline":{"char":"󰰉","code":"f0c09"},"md-alpha_k_circle":{"char":"󰰊","code":"f0c0a"},"md-alpha_k_circle_outline":{"char":"󰰋","code":"f0c0b"},"md-alpha_l":{"char":"󰫹","code":"f0af9"},"md-alpha_l_box":{"char":"󰬓","code":"f0b13"},"md-alpha_l_box_outline":{"char":"󰰌","code":"f0c0c"},"md-alpha_l_circle":{"char":"󰰍","code":"f0c0d"},"md-alpha_l_circle_outline":{"char":"󰰎","code":"f0c0e"},"md-alpha_m":{"char":"󰫺","code":"f0afa"},"md-alpha_m_box":{"char":"󰬔","code":"f0b14"},"md-alpha_m_box_outline":{"char":"󰰏","code":"f0c0f"},"md-alpha_m_circle":{"char":"󰰐","code":"f0c10"},"md-alpha_m_circle_outline":{"char":"󰰑","code":"f0c11"},"md-alpha_n":{"char":"󰫻","code":"f0afb"},"md-alpha_n_box":{"char":"󰬕","code":"f0b15"},"md-alpha_n_box_outline":{"char":"󰰒","code":"f0c12"},"md-alpha_n_circle":{"char":"󰰓","code":"f0c13"},"md-alpha_n_circle_outline":{"char":"󰰔","code":"f0c14"},"md-alpha_o":{"char":"󰫼","code":"f0afc"},"md-alpha_o_box":{"char":"󰬖","code":"f0b16"},"md-alpha_o_box_outline":{"char":"󰰕","code":"f0c15"},"md-alpha_o_circle":{"char":"󰰖","code":"f0c16"},"md-alpha_o_circle_outline":{"char":"󰰗","code":"f0c17"},"md-alpha_p":{"char":"󰫽","code":"f0afd"},"md-alpha_p_box":{"char":"󰬗","code":"f0b17"},"md-alpha_p_box_outline":{"char":"󰰘","code":"f0c18"},"md-alpha_p_circle":{"char":"󰰙","code":"f0c19"},"md-alpha_p_circle_outline":{"char":"󰰚","code":"f0c1a"},"md-alpha_q":{"char":"󰫾","code":"f0afe"},"md-alpha_q_box":{"char":"󰬘","code":"f0b18"},"md-alpha_q_box_outline":{"char":"󰰛","code":"f0c1b"},"md-alpha_q_circle":{"char":"󰰜","code":"f0c1c"},"md-alpha_q_circle_outline":{"char":"󰰝","code":"f0c1d"},"md-alpha_r":{"char":"󰫿","code":"f0aff"},"md-alpha_r_box":{"char":"󰬙","code":"f0b19"},"md-alpha_r_box_outline":{"char":"󰰞","code":"f0c1e"},"md-alpha_r_circle":{"char":"󰰟","code":"f0c1f"},"md-alpha_r_circle_outline":{"char":"󰰠","code":"f0c20"},"md-alpha_s":{"char":"󰬀","code":"f0b00"},"md-alpha_s_box":{"char":"󰬚","code":"f0b1a"},"md-alpha_s_box_outline":{"char":"󰰡","code":"f0c21"},"md-alpha_s_circle":{"char":"󰰢","code":"f0c22"},"md-alpha_s_circle_outline":{"char":"󰰣","code":"f0c23"},"md-alpha_t":{"char":"󰬁","code":"f0b01"},"md-alpha_t_box":{"char":"󰬛","code":"f0b1b"},"md-alpha_t_box_outline":{"char":"󰰤","code":"f0c24"},"md-alpha_t_circle":{"char":"󰰥","code":"f0c25"},"md-alpha_t_circle_outline":{"char":"󰰦","code":"f0c26"},"md-alpha_u":{"char":"󰬂","code":"f0b02"},"md-alpha_u_box":{"char":"󰬜","code":"f0b1c"},"md-alpha_u_box_outline":{"char":"󰰧","code":"f0c27"},"md-alpha_u_circle":{"char":"󰰨","code":"f0c28"},"md-alpha_u_circle_outline":{"char":"󰰩","code":"f0c29"},"md-alpha_v":{"char":"󰬃","code":"f0b03"},"md-alpha_v_box":{"char":"󰬝","code":"f0b1d"},"md-alpha_v_box_outline":{"char":"󰰪","code":"f0c2a"},"md-alpha_v_circle":{"char":"󰰫","code":"f0c2b"},"md-alpha_v_circle_outline":{"char":"󰰬","code":"f0c2c"},"md-alpha_w":{"char":"󰬄","code":"f0b04"},"md-alpha_w_box":{"char":"󰬞","code":"f0b1e"},"md-alpha_w_box_outline":{"char":"󰰭","code":"f0c2d"},"md-alpha_w_circle":{"char":"󰰮","code":"f0c2e"},"md-alpha_w_circle_outline":{"char":"󰰯","code":"f0c2f"},"md-alpha_x":{"char":"󰬅","code":"f0b05"},"md-alpha_x_box":{"char":"󰬟","code":"f0b1f"},"md-alpha_x_box_outline":{"char":"󰰰","code":"f0c30"},"md-alpha_x_circle":{"char":"󰰱","code":"f0c31"},"md-alpha_x_circle_outline":{"char":"󰰲","code":"f0c32"},"md-alpha_y":{"char":"󰬆","code":"f0b06"},"md-alpha_y_box":{"char":"󰬠","code":"f0b20"},"md-alpha_y_box_outline":{"char":"󰰳","code":"f0c33"},"md-alpha_y_circle":{"char":"󰰴","code":"f0c34"},"md-alpha_y_circle_outline":{"char":"󰰵","code":"f0c35"},"md-alpha_z":{"char":"󰬇","code":"f0b07"},"md-alpha_z_box":{"char":"󰬡","code":"f0b21"},"md-alpha_z_box_outline":{"char":"󰰶","code":"f0c36"},"md-alpha_z_circle":{"char":"󰰷","code":"f0c37"},"md-alpha_z_circle_outline":{"char":"󰰸","code":"f0c38"},"md-alphabet_aurebesh":{"char":"󱌬","code":"f132c"},"md-alphabet_cyrillic":{"char":"󱌭","code":"f132d"},"md-alphabet_greek":{"char":"󱌮","code":"f132e"},"md-alphabet_latin":{"char":"󱌯","code":"f132f"},"md-alphabet_piqad":{"char":"󱌰","code":"f1330"},"md-alphabet_tengwar":{"char":"󱌷","code":"f1337"},"md-alphabetical":{"char":"󰀬","code":"f002c"},"md-alphabetical_off":{"char":"󱀌","code":"f100c"},"md-alphabetical_variant":{"char":"󱀍","code":"f100d"},"md-alphabetical_variant_off":{"char":"󱀎","code":"f100e"},"md-altimeter":{"char":"󰗗","code":"f05d7"},"md-ambulance":{"char":"󰀯","code":"f002f"},"md-ammunition":{"char":"󰳨","code":"f0ce8"},"md-ampersand":{"char":"󰪍","code":"f0a8d"},"md-amplifier":{"char":"󰀰","code":"f0030"},"md-amplifier_off":{"char":"󱆵","code":"f11b5"},"md-anchor":{"char":"󰀱","code":"f0031"},"md-android":{"char":"󰀲","code":"f0032"},"md-android_messages":{"char":"󰵅","code":"f0d45"},"md-android_studio":{"char":"󰀴","code":"f0034"},"md-angle_acute":{"char":"󰤷","code":"f0937"},"md-angle_obtuse":{"char":"󰤸","code":"f0938"},"md-angle_right":{"char":"󰤹","code":"f0939"},"md-angular":{"char":"󰚲","code":"f06b2"},"md-angularjs":{"char":"󰚿","code":"f06bf"},"md-animation":{"char":"󰗘","code":"f05d8"},"md-animation_outline":{"char":"󰪏","code":"f0a8f"},"md-animation_play":{"char":"󰤺","code":"f093a"},"md-animation_play_outline":{"char":"󰪐","code":"f0a90"},"md-ansible":{"char":"󱂚","code":"f109a"},"md-antenna":{"char":"󱄙","code":"f1119"},"md-anvil":{"char":"󰢛","code":"f089b"},"md-apache_kafka":{"char":"󱀏","code":"f100f"},"md-api":{"char":"󱂛","code":"f109b"},"md-api_off":{"char":"󱉗","code":"f1257"},"md-apple":{"char":"󰀵","code":"f0035"},"md-apple_finder":{"char":"󰀶","code":"f0036"},"md-apple_icloud":{"char":"󰀸","code":"f0038"},"md-apple_ios":{"char":"󰀷","code":"f0037"},"md-apple_keyboard_caps":{"char":"󰘲","code":"f0632"},"md-apple_keyboard_command":{"char":"󰘳","code":"f0633"},"md-apple_keyboard_control":{"char":"󰘴","code":"f0634"},"md-apple_keyboard_option":{"char":"󰘵","code":"f0635"},"md-apple_keyboard_shift":{"char":"󰘶","code":"f0636"},"md-apple_safari":{"char":"󰀹","code":"f0039"},"md-application":{"char":"󰣆","code":"f08c6"},"md-application_array":{"char":"󱃵","code":"f10f5"},"md-application_array_outline":{"char":"󱃶","code":"f10f6"},"md-application_braces":{"char":"󱃷","code":"f10f7"},"md-application_braces_outline":{"char":"󱃸","code":"f10f8"},"md-application_brackets":{"char":"󰲋","code":"f0c8b"},"md-application_brackets_outline":{"char":"󰲌","code":"f0c8c"},"md-application_cog":{"char":"󰙵","code":"f0675"},"md-application_cog_outline":{"char":"󱕷","code":"f1577"},"md-application_edit":{"char":"󰂮","code":"f00ae"},"md-application_edit_outline":{"char":"󰘙","code":"f0619"},"md-application_export":{"char":"󰶭","code":"f0dad"},"md-application_import":{"char":"󰶮","code":"f0dae"},"md-application_outline":{"char":"󰘔","code":"f0614"},"md-application_parentheses":{"char":"󱃹","code":"f10f9"},"md-application_parentheses_outline":{"char":"󱃺","code":"f10fa"},"md-application_settings":{"char":"󰭠","code":"f0b60"},"md-application_settings_outline":{"char":"󱕕","code":"f1555"},"md-application_variable":{"char":"󱃻","code":"f10fb"},"md-application_variable_outline":{"char":"󱃼","code":"f10fc"},"md-approximately_equal":{"char":"󰾞","code":"f0f9e"},"md-approximately_equal_box":{"char":"󰾟","code":"f0f9f"},"md-apps":{"char":"󰀻","code":"f003b"},"md-apps_box":{"char":"󰵆","code":"f0d46"},"md-arch":{"char":"󰣇","code":"f08c7"},"md-archive":{"char":"󰀼","code":"f003c"},"md-archive_alert":{"char":"󱓽","code":"f14fd"},"md-archive_alert_outline":{"char":"󱓾","code":"f14fe"},"md-archive_arrow_down":{"char":"󱉙","code":"f1259"},"md-archive_arrow_down_outline":{"char":"󱉚","code":"f125a"},"md-archive_arrow_up":{"char":"󱉛","code":"f125b"},"md-archive_arrow_up_outline":{"char":"󱉜","code":"f125c"},"md-archive_cancel":{"char":"󱝋","code":"f174b"},"md-archive_cancel_outline":{"char":"󱝌","code":"f174c"},"md-archive_check":{"char":"󱝍","code":"f174d"},"md-archive_check_outline":{"char":"󱝎","code":"f174e"},"md-archive_clock":{"char":"󱝏","code":"f174f"},"md-archive_clock_outline":{"char":"󱝐","code":"f1750"},"md-archive_cog":{"char":"󱝑","code":"f1751"},"md-archive_cog_outline":{"char":"󱝒","code":"f1752"},"md-archive_edit":{"char":"󱝓","code":"f1753"},"md-archive_edit_outline":{"char":"󱝔","code":"f1754"},"md-archive_eye":{"char":"󱝕","code":"f1755"},"md-archive_eye_outline":{"char":"󱝖","code":"f1756"},"md-archive_lock":{"char":"󱝗","code":"f1757"},"md-archive_lock_open":{"char":"󱝘","code":"f1758"},"md-archive_lock_open_outline":{"char":"󱝙","code":"f1759"},"md-archive_lock_outline":{"char":"󱝚","code":"f175a"},"md-archive_marker":{"char":"󱝛","code":"f175b"},"md-archive_marker_outline":{"char":"󱝜","code":"f175c"},"md-archive_minus":{"char":"󱝝","code":"f175d"},"md-archive_minus_outline":{"char":"󱝞","code":"f175e"},"md-archive_music":{"char":"󱝟","code":"f175f"},"md-archive_music_outline":{"char":"󱝠","code":"f1760"},"md-archive_off":{"char":"󱝡","code":"f1761"},"md-archive_off_outline":{"char":"󱝢","code":"f1762"},"md-archive_outline":{"char":"󱈎","code":"f120e"},"md-archive_plus":{"char":"󱝣","code":"f1763"},"md-archive_plus_outline":{"char":"󱝤","code":"f1764"},"md-archive_refresh":{"char":"󱝥","code":"f1765"},"md-archive_refresh_outline":{"char":"󱝦","code":"f1766"},"md-archive_remove":{"char":"󱝧","code":"f1767"},"md-archive_remove_outline":{"char":"󱝨","code":"f1768"},"md-archive_search":{"char":"󱝩","code":"f1769"},"md-archive_search_outline":{"char":"󱝪","code":"f176a"},"md-archive_settings":{"char":"󱝫","code":"f176b"},"md-archive_settings_outline":{"char":"󱝬","code":"f176c"},"md-archive_star":{"char":"󱝭","code":"f176d"},"md-archive_star_outline":{"char":"󱝮","code":"f176e"},"md-archive_sync":{"char":"󱝯","code":"f176f"},"md-archive_sync_outline":{"char":"󱝰","code":"f1770"},"md-arm_flex":{"char":"󰿗","code":"f0fd7"},"md-arm_flex_outline":{"char":"󰿖","code":"f0fd6"},"md-arrange_bring_forward":{"char":"󰀽","code":"f003d"},"md-arrange_bring_to_front":{"char":"󰀾","code":"f003e"},"md-arrange_send_backward":{"char":"󰀿","code":"f003f"},"md-arrange_send_to_back":{"char":"󰁀","code":"f0040"},"md-arrow_all":{"char":"󰁁","code":"f0041"},"md-arrow_bottom_left":{"char":"󰁂","code":"f0042"},"md-arrow_bottom_left_bold_box":{"char":"󱥤","code":"f1964"},"md-arrow_bottom_left_bold_box_outline":{"char":"󱥥","code":"f1965"},"md-arrow_bottom_left_bold_outline":{"char":"󰦷","code":"f09b7"},"md-arrow_bottom_left_thick":{"char":"󰦸","code":"f09b8"},"md-arrow_bottom_left_thin":{"char":"󱦶","code":"f19b6"},"md-arrow_bottom_left_thin_circle_outline":{"char":"󱖖","code":"f1596"},"md-arrow_bottom_right":{"char":"󰁃","code":"f0043"},"md-arrow_bottom_right_bold_box":{"char":"󱥦","code":"f1966"},"md-arrow_bottom_right_bold_box_outline":{"char":"󱥧","code":"f1967"},"md-arrow_bottom_right_bold_outline":{"char":"󰦹","code":"f09b9"},"md-arrow_bottom_right_thick":{"char":"󰦺","code":"f09ba"},"md-arrow_bottom_right_thin":{"char":"󱦷","code":"f19b7"},"md-arrow_bottom_right_thin_circle_outline":{"char":"󱖕","code":"f1595"},"md-arrow_collapse":{"char":"󰘕","code":"f0615"},"md-arrow_collapse_all":{"char":"󰁄","code":"f0044"},"md-arrow_collapse_down":{"char":"󰞒","code":"f0792"},"md-arrow_collapse_horizontal":{"char":"󰡌","code":"f084c"},"md-arrow_collapse_left":{"char":"󰞓","code":"f0793"},"md-arrow_collapse_right":{"char":"󰞔","code":"f0794"},"md-arrow_collapse_up":{"char":"󰞕","code":"f0795"},"md-arrow_collapse_vertical":{"char":"󰡍","code":"f084d"},"md-arrow_decision":{"char":"󰦻","code":"f09bb"},"md-arrow_decision_auto":{"char":"󰦼","code":"f09bc"},"md-arrow_decision_auto_outline":{"char":"󰦽","code":"f09bd"},"md-arrow_decision_outline":{"char":"󰦾","code":"f09be"},"md-arrow_down":{"char":"󰁅","code":"f0045"},"md-arrow_down_bold":{"char":"󰜮","code":"f072e"},"md-arrow_down_bold_box":{"char":"󰜯","code":"f072f"},"md-arrow_down_bold_box_outline":{"char":"󰜰","code":"f0730"},"md-arrow_down_bold_circle":{"char":"󰁇","code":"f0047"},"md-arrow_down_bold_circle_outline":{"char":"󰁈","code":"f0048"},"md-arrow_down_bold_hexagon_outline":{"char":"󰁉","code":"f0049"},"md-arrow_down_bold_outline":{"char":"󰦿","code":"f09bf"},"md-arrow_down_box":{"char":"󰛀","code":"f06c0"},"md-arrow_down_circle":{"char":"󰳛","code":"f0cdb"},"md-arrow_down_circle_outline":{"char":"󰳜","code":"f0cdc"},"md-arrow_down_drop_circle":{"char":"󰁊","code":"f004a"},"md-arrow_down_drop_circle_outline":{"char":"󰁋","code":"f004b"},"md-arrow_down_left":{"char":"󱞡","code":"f17a1"},"md-arrow_down_left_bold":{"char":"󱞢","code":"f17a2"},"md-arrow_down_right":{"char":"󱞣","code":"f17a3"},"md-arrow_down_right_bold":{"char":"󱞤","code":"f17a4"},"md-arrow_down_thick":{"char":"󰁆","code":"f0046"},"md-arrow_down_thin":{"char":"󱦳","code":"f19b3"},"md-arrow_down_thin_circle_outline":{"char":"󱖙","code":"f1599"},"md-arrow_expand":{"char":"󰘖","code":"f0616"},"md-arrow_expand_all":{"char":"󰁌","code":"f004c"},"md-arrow_expand_down":{"char":"󰞖","code":"f0796"},"md-arrow_expand_horizontal":{"char":"󰡎","code":"f084e"},"md-arrow_expand_left":{"char":"󰞗","code":"f0797"},"md-arrow_expand_right":{"char":"󰞘","code":"f0798"},"md-arrow_expand_up":{"char":"󰞙","code":"f0799"},"md-arrow_expand_vertical":{"char":"󰡏","code":"f084f"},"md-arrow_horizontal_lock":{"char":"󱅛","code":"f115b"},"md-arrow_left":{"char":"󰁍","code":"f004d"},"md-arrow_left_bold":{"char":"󰜱","code":"f0731"},"md-arrow_left_bold_box":{"char":"󰜲","code":"f0732"},"md-arrow_left_bold_box_outline":{"char":"󰜳","code":"f0733"},"md-arrow_left_bold_circle":{"char":"󰁏","code":"f004f"},"md-arrow_left_bold_circle_outline":{"char":"󰁐","code":"f0050"},"md-arrow_left_bold_hexagon_outline":{"char":"󰁑","code":"f0051"},"md-arrow_left_bold_outline":{"char":"󰧀","code":"f09c0"},"md-arrow_left_bottom":{"char":"󱞥","code":"f17a5"},"md-arrow_left_bottom_bold":{"char":"󱞦","code":"f17a6"},"md-arrow_left_box":{"char":"󰛁","code":"f06c1"},"md-arrow_left_circle":{"char":"󰳝","code":"f0cdd"},"md-arrow_left_circle_outline":{"char":"󰳞","code":"f0cde"},"md-arrow_left_drop_circle":{"char":"󰁒","code":"f0052"},"md-arrow_left_drop_circle_outline":{"char":"󰁓","code":"f0053"},"md-arrow_left_right":{"char":"󰹳","code":"f0e73"},"md-arrow_left_right_bold":{"char":"󰹴","code":"f0e74"},"md-arrow_left_right_bold_outline":{"char":"󰧁","code":"f09c1"},"md-arrow_left_thick":{"char":"󰁎","code":"f004e"},"md-arrow_left_thin":{"char":"󱦱","code":"f19b1"},"md-arrow_left_thin_circle_outline":{"char":"󱖚","code":"f159a"},"md-arrow_left_top":{"char":"󱞧","code":"f17a7"},"md-arrow_left_top_bold":{"char":"󱞨","code":"f17a8"},"md-arrow_projectile":{"char":"󱡀","code":"f1840"},"md-arrow_projectile_multiple":{"char":"󱠿","code":"f183f"},"md-arrow_right":{"char":"󰁔","code":"f0054"},"md-arrow_right_bold":{"char":"󰜴","code":"f0734"},"md-arrow_right_bold_box":{"char":"󰜵","code":"f0735"},"md-arrow_right_bold_box_outline":{"char":"󰜶","code":"f0736"},"md-arrow_right_bold_circle":{"char":"󰁖","code":"f0056"},"md-arrow_right_bold_circle_outline":{"char":"󰁗","code":"f0057"},"md-arrow_right_bold_hexagon_outline":{"char":"󰁘","code":"f0058"},"md-arrow_right_bold_outline":{"char":"󰧂","code":"f09c2"},"md-arrow_right_bottom":{"char":"󱞩","code":"f17a9"},"md-arrow_right_bottom_bold":{"char":"󱞪","code":"f17aa"},"md-arrow_right_box":{"char":"󰛂","code":"f06c2"},"md-arrow_right_circle":{"char":"󰳟","code":"f0cdf"},"md-arrow_right_circle_outline":{"char":"󰳠","code":"f0ce0"},"md-arrow_right_drop_circle":{"char":"󰁙","code":"f0059"},"md-arrow_right_drop_circle_outline":{"char":"󰁚","code":"f005a"},"md-arrow_right_thick":{"char":"󰁕","code":"f0055"},"md-arrow_right_thin":{"char":"󱦰","code":"f19b0"},"md-arrow_right_thin_circle_outline":{"char":"󱖘","code":"f1598"},"md-arrow_right_top":{"char":"󱞫","code":"f17ab"},"md-arrow_right_top_bold":{"char":"󱞬","code":"f17ac"},"md-arrow_split_horizontal":{"char":"󰤻","code":"f093b"},"md-arrow_split_vertical":{"char":"󰤼","code":"f093c"},"md-arrow_top_left":{"char":"󰁛","code":"f005b"},"md-arrow_top_left_bold_box":{"char":"󱥨","code":"f1968"},"md-arrow_top_left_bold_box_outline":{"char":"󱥩","code":"f1969"},"md-arrow_top_left_bold_outline":{"char":"󰧃","code":"f09c3"},"md-arrow_top_left_bottom_right":{"char":"󰹵","code":"f0e75"},"md-arrow_top_left_bottom_right_bold":{"char":"󰹶","code":"f0e76"},"md-arrow_top_left_thick":{"char":"󰧄","code":"f09c4"},"md-arrow_top_left_thin":{"char":"󱦵","code":"f19b5"},"md-arrow_top_left_thin_circle_outline":{"char":"󱖓","code":"f1593"},"md-arrow_top_right":{"char":"󰁜","code":"f005c"},"md-arrow_top_right_bold_box":{"char":"󱥪","code":"f196a"},"md-arrow_top_right_bold_box_outline":{"char":"󱥫","code":"f196b"},"md-arrow_top_right_bold_outline":{"char":"󰧅","code":"f09c5"},"md-arrow_top_right_bottom_left":{"char":"󰹷","code":"f0e77"},"md-arrow_top_right_bottom_left_bold":{"char":"󰹸","code":"f0e78"},"md-arrow_top_right_thick":{"char":"󰧆","code":"f09c6"},"md-arrow_top_right_thin":{"char":"󱦴","code":"f19b4"},"md-arrow_top_right_thin_circle_outline":{"char":"󱖔","code":"f1594"},"md-arrow_u_down_left":{"char":"󱞭","code":"f17ad"},"md-arrow_u_down_left_bold":{"char":"󱞮","code":"f17ae"},"md-arrow_u_down_right":{"char":"󱞯","code":"f17af"},"md-arrow_u_down_right_bold":{"char":"󱞰","code":"f17b0"},"md-arrow_u_left_bottom":{"char":"󱞱","code":"f17b1"},"md-arrow_u_left_bottom_bold":{"char":"󱞲","code":"f17b2"},"md-arrow_u_left_top":{"char":"󱞳","code":"f17b3"},"md-arrow_u_left_top_bold":{"char":"󱞴","code":"f17b4"},"md-arrow_u_right_bottom":{"char":"󱞵","code":"f17b5"},"md-arrow_u_right_bottom_bold":{"char":"󱞶","code":"f17b6"},"md-arrow_u_right_top":{"char":"󱞷","code":"f17b7"},"md-arrow_u_right_top_bold":{"char":"󱞸","code":"f17b8"},"md-arrow_u_up_left":{"char":"󱞹","code":"f17b9"},"md-arrow_u_up_left_bold":{"char":"󱞺","code":"f17ba"},"md-arrow_u_up_right":{"char":"󱞻","code":"f17bb"},"md-arrow_u_up_right_bold":{"char":"󱞼","code":"f17bc"},"md-arrow_up":{"char":"󰁝","code":"f005d"},"md-arrow_up_bold":{"char":"󰜷","code":"f0737"},"md-arrow_up_bold_box":{"char":"󰜸","code":"f0738"},"md-arrow_up_bold_box_outline":{"char":"󰜹","code":"f0739"},"md-arrow_up_bold_circle":{"char":"󰁟","code":"f005f"},"md-arrow_up_bold_circle_outline":{"char":"󰁠","code":"f0060"},"md-arrow_up_bold_hexagon_outline":{"char":"󰁡","code":"f0061"},"md-arrow_up_bold_outline":{"char":"󰧇","code":"f09c7"},"md-arrow_up_box":{"char":"󰛃","code":"f06c3"},"md-arrow_up_circle":{"char":"󰳡","code":"f0ce1"},"md-arrow_up_circle_outline":{"char":"󰳢","code":"f0ce2"},"md-arrow_up_down":{"char":"󰹹","code":"f0e79"},"md-arrow_up_down_bold":{"char":"󰹺","code":"f0e7a"},"md-arrow_up_down_bold_outline":{"char":"󰧈","code":"f09c8"},"md-arrow_up_drop_circle":{"char":"󰁢","code":"f0062"},"md-arrow_up_drop_circle_outline":{"char":"󰁣","code":"f0063"},"md-arrow_up_left":{"char":"󱞽","code":"f17bd"},"md-arrow_up_left_bold":{"char":"󱞾","code":"f17be"},"md-arrow_up_right":{"char":"󱞿","code":"f17bf"},"md-arrow_up_right_bold":{"char":"󱟀","code":"f17c0"},"md-arrow_up_thick":{"char":"󰁞","code":"f005e"},"md-arrow_up_thin":{"char":"󱦲","code":"f19b2"},"md-arrow_up_thin_circle_outline":{"char":"󱖗","code":"f1597"},"md-arrow_vertical_lock":{"char":"󱅜","code":"f115c"},"md-artstation":{"char":"󰭛","code":"f0b5b"},"md-aspect_ratio":{"char":"󰨤","code":"f0a24"},"md-assistant":{"char":"󰁤","code":"f0064"},"md-asterisk":{"char":"󰛄","code":"f06c4"},"md-asterisk_circle_outline":{"char":"󱨧","code":"f1a27"},"md-at":{"char":"󰁥","code":"f0065"},"md-atlassian":{"char":"󰠄","code":"f0804"},"md-atm":{"char":"󰵇","code":"f0d47"},"md-atom":{"char":"󰝨","code":"f0768"},"md-atom_variant":{"char":"󰹻","code":"f0e7b"},"md-attachment":{"char":"󰁦","code":"f0066"},"md-attachment_check":{"char":"󱫁","code":"f1ac1"},"md-attachment_lock":{"char":"󱧄","code":"f19c4"},"md-attachment_minus":{"char":"󱫂","code":"f1ac2"},"md-attachment_off":{"char":"󱫃","code":"f1ac3"},"md-attachment_plus":{"char":"󱫄","code":"f1ac4"},"md-attachment_remove":{"char":"󱫅","code":"f1ac5"},"md-audio_input_rca":{"char":"󱡫","code":"f186b"},"md-audio_input_stereo_minijack":{"char":"󱡬","code":"f186c"},"md-audio_input_xlr":{"char":"󱡭","code":"f186d"},"md-audio_video":{"char":"󰤽","code":"f093d"},"md-audio_video_off":{"char":"󱆶","code":"f11b6"},"md-augmented_reality":{"char":"󰡐","code":"f0850"},"md-auto_download":{"char":"󱍾","code":"f137e"},"md-auto_fix":{"char":"󰁨","code":"f0068"},"md-auto_upload":{"char":"󰁩","code":"f0069"},"md-autorenew":{"char":"󰁪","code":"f006a"},"md-autorenew_off":{"char":"󱧧","code":"f19e7"},"md-av_timer":{"char":"󰁫","code":"f006b"},"md-aws":{"char":"󰸏","code":"f0e0f"},"md-axe":{"char":"󰣈","code":"f08c8"},"md-axe_battle":{"char":"󱡂","code":"f1842"},"md-axis":{"char":"󰵈","code":"f0d48"},"md-axis_arrow":{"char":"󰵉","code":"f0d49"},"md-axis_arrow_info":{"char":"󱐎","code":"f140e"},"md-axis_arrow_lock":{"char":"󰵊","code":"f0d4a"},"md-axis_lock":{"char":"󰵋","code":"f0d4b"},"md-axis_x_arrow":{"char":"󰵌","code":"f0d4c"},"md-axis_x_arrow_lock":{"char":"󰵍","code":"f0d4d"},"md-axis_x_rotate_clockwise":{"char":"󰵎","code":"f0d4e"},"md-axis_x_rotate_counterclockwise":{"char":"󰵏","code":"f0d4f"},"md-axis_x_y_arrow_lock":{"char":"󰵐","code":"f0d50"},"md-axis_y_arrow":{"char":"󰵑","code":"f0d51"},"md-axis_y_arrow_lock":{"char":"󰵒","code":"f0d52"},"md-axis_y_rotate_clockwise":{"char":"󰵓","code":"f0d53"},"md-axis_y_rotate_counterclockwise":{"char":"󰵔","code":"f0d54"},"md-axis_z_arrow":{"char":"󰵕","code":"f0d55"},"md-axis_z_arrow_lock":{"char":"󰵖","code":"f0d56"},"md-axis_z_rotate_clockwise":{"char":"󰵗","code":"f0d57"},"md-axis_z_rotate_counterclockwise":{"char":"󰵘","code":"f0d58"},"md-babel":{"char":"󰨥","code":"f0a25"},"md-baby":{"char":"󰁬","code":"f006c"},"md-baby_bottle":{"char":"󰼹","code":"f0f39"},"md-baby_bottle_outline":{"char":"󰼺","code":"f0f3a"},"md-baby_buggy":{"char":"󱏠","code":"f13e0"},"md-baby_carriage":{"char":"󰚏","code":"f068f"},"md-baby_carriage_off":{"char":"󰾠","code":"f0fa0"},"md-baby_face":{"char":"󰹼","code":"f0e7c"},"md-baby_face_outline":{"char":"󰹽","code":"f0e7d"},"md-backburger":{"char":"󰁭","code":"f006d"},"md-backspace":{"char":"󰁮","code":"f006e"},"md-backspace_outline":{"char":"󰭜","code":"f0b5c"},"md-backspace_reverse":{"char":"󰹾","code":"f0e7e"},"md-backspace_reverse_outline":{"char":"󰹿","code":"f0e7f"},"md-backup_restore":{"char":"󰁯","code":"f006f"},"md-bacteria":{"char":"󰻕","code":"f0ed5"},"md-bacteria_outline":{"char":"󰻖","code":"f0ed6"},"md-badge_account":{"char":"󰶧","code":"f0da7"},"md-badge_account_alert":{"char":"󰶨","code":"f0da8"},"md-badge_account_alert_outline":{"char":"󰶩","code":"f0da9"},"md-badge_account_horizontal":{"char":"󰸍","code":"f0e0d"},"md-badge_account_horizontal_outline":{"char":"󰸎","code":"f0e0e"},"md-badge_account_outline":{"char":"󰶪","code":"f0daa"},"md-badminton":{"char":"󰡑","code":"f0851"},"md-bag_carry_on":{"char":"󰼻","code":"f0f3b"},"md-bag_carry_on_check":{"char":"󰵥","code":"f0d65"},"md-bag_carry_on_off":{"char":"󰼼","code":"f0f3c"},"md-bag_checked":{"char":"󰼽","code":"f0f3d"},"md-bag_personal":{"char":"󰸐","code":"f0e10"},"md-bag_personal_off":{"char":"󰸑","code":"f0e11"},"md-bag_personal_off_outline":{"char":"󰸒","code":"f0e12"},"md-bag_personal_outline":{"char":"󰸓","code":"f0e13"},"md-bag_suitcase":{"char":"󱖋","code":"f158b"},"md-bag_suitcase_off":{"char":"󱖍","code":"f158d"},"md-bag_suitcase_off_outline":{"char":"󱖎","code":"f158e"},"md-bag_suitcase_outline":{"char":"󱖌","code":"f158c"},"md-baguette":{"char":"󰼾","code":"f0f3e"},"md-balcony":{"char":"󱠗","code":"f1817"},"md-balloon":{"char":"󰨦","code":"f0a26"},"md-ballot":{"char":"󰧉","code":"f09c9"},"md-ballot_outline":{"char":"󰧊","code":"f09ca"},"md-ballot_recount":{"char":"󰰹","code":"f0c39"},"md-ballot_recount_outline":{"char":"󰰺","code":"f0c3a"},"md-bandage":{"char":"󰶯","code":"f0daf"},"md-bank":{"char":"󰁰","code":"f0070"},"md-bank_check":{"char":"󱙕","code":"f1655"},"md-bank_minus":{"char":"󰶰","code":"f0db0"},"md-bank_off":{"char":"󱙖","code":"f1656"},"md-bank_off_outline":{"char":"󱙗","code":"f1657"},"md-bank_outline":{"char":"󰺀","code":"f0e80"},"md-bank_plus":{"char":"󰶱","code":"f0db1"},"md-bank_remove":{"char":"󰶲","code":"f0db2"},"md-bank_transfer":{"char":"󰨧","code":"f0a27"},"md-bank_transfer_in":{"char":"󰨨","code":"f0a28"},"md-bank_transfer_out":{"char":"󰨩","code":"f0a29"},"md-barcode":{"char":"󰁱","code":"f0071"},"md-barcode_off":{"char":"󱈶","code":"f1236"},"md-barcode_scan":{"char":"󰁲","code":"f0072"},"md-barley":{"char":"󰁳","code":"f0073"},"md-barley_off":{"char":"󰭝","code":"f0b5d"},"md-barn":{"char":"󰭞","code":"f0b5e"},"md-barrel":{"char":"󰁴","code":"f0074"},"md-barrel_outline":{"char":"󱨨","code":"f1a28"},"md-baseball":{"char":"󰡒","code":"f0852"},"md-baseball_bat":{"char":"󰡓","code":"f0853"},"md-baseball_diamond":{"char":"󱗬","code":"f15ec"},"md-baseball_diamond_outline":{"char":"󱗭","code":"f15ed"},"md-bash":{"char":"󱆃","code":"f1183"},"md-basket":{"char":"󰁶","code":"f0076"},"md-basket_check":{"char":"󱣥","code":"f18e5"},"md-basket_check_outline":{"char":"󱣦","code":"f18e6"},"md-basket_fill":{"char":"󰁷","code":"f0077"},"md-basket_minus":{"char":"󱔣","code":"f1523"},"md-basket_minus_outline":{"char":"󱔤","code":"f1524"},"md-basket_off":{"char":"󱔥","code":"f1525"},"md-basket_off_outline":{"char":"󱔦","code":"f1526"},"md-basket_outline":{"char":"󱆁","code":"f1181"},"md-basket_plus":{"char":"󱔧","code":"f1527"},"md-basket_plus_outline":{"char":"󱔨","code":"f1528"},"md-basket_remove":{"char":"󱔩","code":"f1529"},"md-basket_remove_outline":{"char":"󱔪","code":"f152a"},"md-basket_unfill":{"char":"󰁸","code":"f0078"},"md-basketball":{"char":"󰠆","code":"f0806"},"md-basketball_hoop":{"char":"󰰻","code":"f0c3b"},"md-basketball_hoop_outline":{"char":"󰰼","code":"f0c3c"},"md-bat":{"char":"󰭟","code":"f0b5f"},"md-bathtub":{"char":"󱠘","code":"f1818"},"md-bathtub_outline":{"char":"󱠙","code":"f1819"},"md-battery":{"char":"󰁹","code":"f0079"},"md-battery_10":{"char":"󰁺","code":"f007a"},"md-battery_10_bluetooth":{"char":"󰤾","code":"f093e"},"md-battery_20":{"char":"󰁻","code":"f007b"},"md-battery_20_bluetooth":{"char":"󰤿","code":"f093f"},"md-battery_30":{"char":"󰁼","code":"f007c"},"md-battery_30_bluetooth":{"char":"󰥀","code":"f0940"},"md-battery_40":{"char":"󰁽","code":"f007d"},"md-battery_40_bluetooth":{"char":"󰥁","code":"f0941"},"md-battery_50":{"char":"󰁾","code":"f007e"},"md-battery_50_bluetooth":{"char":"󰥂","code":"f0942"},"md-battery_60":{"char":"󰁿","code":"f007f"},"md-battery_60_bluetooth":{"char":"󰥃","code":"f0943"},"md-battery_70":{"char":"󰂀","code":"f0080"},"md-battery_70_bluetooth":{"char":"󰥄","code":"f0944"},"md-battery_80":{"char":"󰂁","code":"f0081"},"md-battery_80_bluetooth":{"char":"󰥅","code":"f0945"},"md-battery_90":{"char":"󰂂","code":"f0082"},"md-battery_90_bluetooth":{"char":"󰥆","code":"f0946"},"md-battery_alert":{"char":"󰂃","code":"f0083"},"md-battery_alert_bluetooth":{"char":"󰥇","code":"f0947"},"md-battery_alert_variant":{"char":"󱃌","code":"f10cc"},"md-battery_alert_variant_outline":{"char":"󱃍","code":"f10cd"},"md-battery_arrow_down":{"char":"󱟞","code":"f17de"},"md-battery_arrow_down_outline":{"char":"󱟟","code":"f17df"},"md-battery_arrow_up":{"char":"󱟠","code":"f17e0"},"md-battery_arrow_up_outline":{"char":"󱟡","code":"f17e1"},"md-battery_bluetooth":{"char":"󰥈","code":"f0948"},"md-battery_bluetooth_variant":{"char":"󰥉","code":"f0949"},"md-battery_charging":{"char":"󰂄","code":"f0084"},"md-battery_charging_10":{"char":"󰢜","code":"f089c"},"md-battery_charging_100":{"char":"󰂅","code":"f0085"},"md-battery_charging_20":{"char":"󰂆","code":"f0086"},"md-battery_charging_30":{"char":"󰂇","code":"f0087"},"md-battery_charging_40":{"char":"󰂈","code":"f0088"},"md-battery_charging_50":{"char":"󰢝","code":"f089d"},"md-battery_charging_60":{"char":"󰂉","code":"f0089"},"md-battery_charging_70":{"char":"󰢞","code":"f089e"},"md-battery_charging_80":{"char":"󰂊","code":"f008a"},"md-battery_charging_90":{"char":"󰂋","code":"f008b"},"md-battery_charging_high":{"char":"󱊦","code":"f12a6"},"md-battery_charging_low":{"char":"󱊤","code":"f12a4"},"md-battery_charging_medium":{"char":"󱊥","code":"f12a5"},"md-battery_charging_outline":{"char":"󰢟","code":"f089f"},"md-battery_charging_wireless":{"char":"󰠇","code":"f0807"},"md-battery_charging_wireless_10":{"char":"󰠈","code":"f0808"},"md-battery_charging_wireless_20":{"char":"󰠉","code":"f0809"},"md-battery_charging_wireless_30":{"char":"󰠊","code":"f080a"},"md-battery_charging_wireless_40":{"char":"󰠋","code":"f080b"},"md-battery_charging_wireless_50":{"char":"󰠌","code":"f080c"},"md-battery_charging_wireless_60":{"char":"󰠍","code":"f080d"},"md-battery_charging_wireless_70":{"char":"󰠎","code":"f080e"},"md-battery_charging_wireless_80":{"char":"󰠏","code":"f080f"},"md-battery_charging_wireless_90":{"char":"󰠐","code":"f0810"},"md-battery_charging_wireless_alert":{"char":"󰠑","code":"f0811"},"md-battery_charging_wireless_outline":{"char":"󰠒","code":"f0812"},"md-battery_check":{"char":"󱟢","code":"f17e2"},"md-battery_check_outline":{"char":"󱟣","code":"f17e3"},"md-battery_clock":{"char":"󱧥","code":"f19e5"},"md-battery_clock_outline":{"char":"󱧦","code":"f19e6"},"md-battery_heart":{"char":"󱈏","code":"f120f"},"md-battery_heart_outline":{"char":"󱈐","code":"f1210"},"md-battery_heart_variant":{"char":"󱈑","code":"f1211"},"md-battery_high":{"char":"󱊣","code":"f12a3"},"md-battery_lock":{"char":"󱞜","code":"f179c"},"md-battery_lock_open":{"char":"󱞝","code":"f179d"},"md-battery_low":{"char":"󱊡","code":"f12a1"},"md-battery_medium":{"char":"󱊢","code":"f12a2"},"md-battery_minus":{"char":"󱟤","code":"f17e4"},"md-battery_minus_outline":{"char":"󱟥","code":"f17e5"},"md-battery_minus_variant":{"char":"󰂌","code":"f008c"},"md-battery_negative":{"char":"󰂍","code":"f008d"},"md-battery_off":{"char":"󱉝","code":"f125d"},"md-battery_off_outline":{"char":"󱉞","code":"f125e"},"md-battery_outline":{"char":"󰂎","code":"f008e"},"md-battery_plus":{"char":"󱟦","code":"f17e6"},"md-battery_plus_outline":{"char":"󱟧","code":"f17e7"},"md-battery_plus_variant":{"char":"󰂏","code":"f008f"},"md-battery_positive":{"char":"󰂐","code":"f0090"},"md-battery_remove":{"char":"󱟨","code":"f17e8"},"md-battery_remove_outline":{"char":"󱟩","code":"f17e9"},"md-battery_sync":{"char":"󱠴","code":"f1834"},"md-battery_sync_outline":{"char":"󱠵","code":"f1835"},"md-battery_unknown":{"char":"󰂑","code":"f0091"},"md-battery_unknown_bluetooth":{"char":"󰥊","code":"f094a"},"md-beach":{"char":"󰂒","code":"f0092"},"md-beaker":{"char":"󰳪","code":"f0cea"},"md-beaker_alert":{"char":"󱈩","code":"f1229"},"md-beaker_alert_outline":{"char":"󱈪","code":"f122a"},"md-beaker_check":{"char":"󱈫","code":"f122b"},"md-beaker_check_outline":{"char":"󱈬","code":"f122c"},"md-beaker_minus":{"char":"󱈭","code":"f122d"},"md-beaker_minus_outline":{"char":"󱈮","code":"f122e"},"md-beaker_outline":{"char":"󰚐","code":"f0690"},"md-beaker_plus":{"char":"󱈯","code":"f122f"},"md-beaker_plus_outline":{"char":"󱈰","code":"f1230"},"md-beaker_question":{"char":"󱈱","code":"f1231"},"md-beaker_question_outline":{"char":"󱈲","code":"f1232"},"md-beaker_remove":{"char":"󱈳","code":"f1233"},"md-beaker_remove_outline":{"char":"󱈴","code":"f1234"},"md-bed":{"char":"󰋣","code":"f02e3"},"md-bed_double":{"char":"󰿔","code":"f0fd4"},"md-bed_double_outline":{"char":"󰿓","code":"f0fd3"},"md-bed_empty":{"char":"󰢠","code":"f08a0"},"md-bed_king":{"char":"󰿒","code":"f0fd2"},"md-bed_king_outline":{"char":"󰿑","code":"f0fd1"},"md-bed_outline":{"char":"󰂙","code":"f0099"},"md-bed_queen":{"char":"󰿐","code":"f0fd0"},"md-bed_queen_outline":{"char":"󰿛","code":"f0fdb"},"md-bed_single":{"char":"󱁭","code":"f106d"},"md-bed_single_outline":{"char":"󱁮","code":"f106e"},"md-bee":{"char":"󰾡","code":"f0fa1"},"md-bee_flower":{"char":"󰾢","code":"f0fa2"},"md-beehive_off_outline":{"char":"󱏭","code":"f13ed"},"md-beehive_outline":{"char":"󱃎","code":"f10ce"},"md-beekeeper":{"char":"󱓢","code":"f14e2"},"md-beer":{"char":"󰂘","code":"f0098"},"md-beer_outline":{"char":"󱌌","code":"f130c"},"md-bell":{"char":"󰂚","code":"f009a"},"md-bell_alert":{"char":"󰵙","code":"f0d59"},"md-bell_alert_outline":{"char":"󰺁","code":"f0e81"},"md-bell_badge":{"char":"󱅫","code":"f116b"},"md-bell_badge_outline":{"char":"󰅸","code":"f0178"},"md-bell_cancel":{"char":"󱏧","code":"f13e7"},"md-bell_cancel_outline":{"char":"󱏨","code":"f13e8"},"md-bell_check":{"char":"󱇥","code":"f11e5"},"md-bell_check_outline":{"char":"󱇦","code":"f11e6"},"md-bell_circle":{"char":"󰵚","code":"f0d5a"},"md-bell_circle_outline":{"char":"󰵛","code":"f0d5b"},"md-bell_cog":{"char":"󱨩","code":"f1a29"},"md-bell_cog_outline":{"char":"󱨪","code":"f1a2a"},"md-bell_minus":{"char":"󱏩","code":"f13e9"},"md-bell_minus_outline":{"char":"󱏪","code":"f13ea"},"md-bell_off":{"char":"󰂛","code":"f009b"},"md-bell_off_outline":{"char":"󰪑","code":"f0a91"},"md-bell_outline":{"char":"󰂜","code":"f009c"},"md-bell_plus":{"char":"󰂝","code":"f009d"},"md-bell_plus_outline":{"char":"󰪒","code":"f0a92"},"md-bell_remove":{"char":"󱏫","code":"f13eb"},"md-bell_remove_outline":{"char":"󱏬","code":"f13ec"},"md-bell_ring":{"char":"󰂞","code":"f009e"},"md-bell_ring_outline":{"char":"󰂟","code":"f009f"},"md-bell_sleep":{"char":"󰂠","code":"f00a0"},"md-bell_sleep_outline":{"char":"󰪓","code":"f0a93"},"md-beta":{"char":"󰂡","code":"f00a1"},"md-betamax":{"char":"󰧋","code":"f09cb"},"md-biathlon":{"char":"󰸔","code":"f0e14"},"md-bicycle":{"char":"󱂜","code":"f109c"},"md-bicycle_basket":{"char":"󱈵","code":"f1235"},"md-bicycle_cargo":{"char":"󱢜","code":"f189c"},"md-bicycle_electric":{"char":"󱖴","code":"f15b4"},"md-bicycle_penny_farthing":{"char":"󱗩","code":"f15e9"},"md-bike":{"char":"󰂣","code":"f00a3"},"md-bike_fast":{"char":"󱄟","code":"f111f"},"md-billboard":{"char":"󱀐","code":"f1010"},"md-billiards":{"char":"󰭡","code":"f0b61"},"md-billiards_rack":{"char":"󰭢","code":"f0b62"},"md-binoculars":{"char":"󰂥","code":"f00a5"},"md-bio":{"char":"󰂦","code":"f00a6"},"md-biohazard":{"char":"󰂧","code":"f00a7"},"md-bird":{"char":"󱗆","code":"f15c6"},"md-bitbucket":{"char":"󰂨","code":"f00a8"},"md-bitcoin":{"char":"󰠓","code":"f0813"},"md-black_mesa":{"char":"󰂩","code":"f00a9"},"md-blender":{"char":"󰳫","code":"f0ceb"},"md-blender_outline":{"char":"󱠚","code":"f181a"},"md-blender_software":{"char":"󰂫","code":"f00ab"},"md-blinds":{"char":"󰂬","code":"f00ac"},"md-blinds_horizontal":{"char":"󱨫","code":"f1a2b"},"md-blinds_horizontal_closed":{"char":"󱨬","code":"f1a2c"},"md-blinds_open":{"char":"󱀑","code":"f1011"},"md-blinds_vertical":{"char":"󱨭","code":"f1a2d"},"md-blinds_vertical_closed":{"char":"󱨮","code":"f1a2e"},"md-block_helper":{"char":"󰂭","code":"f00ad"},"md-blood_bag":{"char":"󰳬","code":"f0cec"},"md-bluetooth":{"char":"󰂯","code":"f00af"},"md-bluetooth_audio":{"char":"󰂰","code":"f00b0"},"md-bluetooth_connect":{"char":"󰂱","code":"f00b1"},"md-bluetooth_off":{"char":"󰂲","code":"f00b2"},"md-bluetooth_settings":{"char":"󰂳","code":"f00b3"},"md-bluetooth_transfer":{"char":"󰂴","code":"f00b4"},"md-blur":{"char":"󰂵","code":"f00b5"},"md-blur_linear":{"char":"󰂶","code":"f00b6"},"md-blur_off":{"char":"󰂷","code":"f00b7"},"md-blur_radial":{"char":"󰂸","code":"f00b8"},"md-bolt":{"char":"󰶳","code":"f0db3"},"md-bomb":{"char":"󰚑","code":"f0691"},"md-bomb_off":{"char":"󰛅","code":"f06c5"},"md-bone":{"char":"󰂹","code":"f00b9"},"md-bone_off":{"char":"󱧠","code":"f19e0"},"md-book":{"char":"󰂺","code":"f00ba"},"md-book_account":{"char":"󱎭","code":"f13ad"},"md-book_account_outline":{"char":"󱎮","code":"f13ae"},"md-book_alert":{"char":"󱙼","code":"f167c"},"md-book_alert_outline":{"char":"󱙽","code":"f167d"},"md-book_alphabet":{"char":"󰘝","code":"f061d"},"md-book_arrow_down":{"char":"󱙾","code":"f167e"},"md-book_arrow_down_outline":{"char":"󱙿","code":"f167f"},"md-book_arrow_left":{"char":"󱚀","code":"f1680"},"md-book_arrow_left_outline":{"char":"󱚁","code":"f1681"},"md-book_arrow_right":{"char":"󱚂","code":"f1682"},"md-book_arrow_right_outline":{"char":"󱚃","code":"f1683"},"md-book_arrow_up":{"char":"󱚄","code":"f1684"},"md-book_arrow_up_outline":{"char":"󱚅","code":"f1685"},"md-book_cancel":{"char":"󱚆","code":"f1686"},"md-book_cancel_outline":{"char":"󱚇","code":"f1687"},"md-book_check":{"char":"󱓳","code":"f14f3"},"md-book_check_outline":{"char":"󱓴","code":"f14f4"},"md-book_clock":{"char":"󱚈","code":"f1688"},"md-book_clock_outline":{"char":"󱚉","code":"f1689"},"md-book_cog":{"char":"󱚊","code":"f168a"},"md-book_cog_outline":{"char":"󱚋","code":"f168b"},"md-book_cross":{"char":"󰂢","code":"f00a2"},"md-book_edit":{"char":"󱚌","code":"f168c"},"md-book_edit_outline":{"char":"󱚍","code":"f168d"},"md-book_education":{"char":"󱛉","code":"f16c9"},"md-book_education_outline":{"char":"󱛊","code":"f16ca"},"md-book_heart":{"char":"󱨝","code":"f1a1d"},"md-book_heart_outline":{"char":"󱨞","code":"f1a1e"},"md-book_information_variant":{"char":"󱁯","code":"f106f"},"md-book_lock":{"char":"󰞚","code":"f079a"},"md-book_lock_open":{"char":"󰞛","code":"f079b"},"md-book_lock_open_outline":{"char":"󱚎","code":"f168e"},"md-book_lock_outline":{"char":"󱚏","code":"f168f"},"md-book_marker":{"char":"󱚐","code":"f1690"},"md-book_marker_outline":{"char":"󱚑","code":"f1691"},"md-book_minus":{"char":"󰗙","code":"f05d9"},"md-book_minus_multiple":{"char":"󰪔","code":"f0a94"},"md-book_minus_multiple_outline":{"char":"󰤋","code":"f090b"},"md-book_minus_outline":{"char":"󱚒","code":"f1692"},"md-book_multiple":{"char":"󰂻","code":"f00bb"},"md-book_multiple_outline":{"char":"󰐶","code":"f0436"},"md-book_music":{"char":"󰁧","code":"f0067"},"md-book_music_outline":{"char":"󱚓","code":"f1693"},"md-book_off":{"char":"󱚔","code":"f1694"},"md-book_off_outline":{"char":"󱚕","code":"f1695"},"md-book_open":{"char":"󰂽","code":"f00bd"},"md-book_open_blank_variant":{"char":"󰂾","code":"f00be"},"md-book_open_outline":{"char":"󰭣","code":"f0b63"},"md-book_open_page_variant":{"char":"󰗚","code":"f05da"},"md-book_open_page_variant_outline":{"char":"󱗖","code":"f15d6"},"md-book_open_variant":{"char":"󱓷","code":"f14f7"},"md-book_outline":{"char":"󰭤","code":"f0b64"},"md-book_play":{"char":"󰺂","code":"f0e82"},"md-book_play_outline":{"char":"󰺃","code":"f0e83"},"md-book_plus":{"char":"󰗛","code":"f05db"},"md-book_plus_multiple":{"char":"󰪕","code":"f0a95"},"md-book_plus_multiple_outline":{"char":"󰫞","code":"f0ade"},"md-book_plus_outline":{"char":"󱚖","code":"f1696"},"md-book_refresh":{"char":"󱚗","code":"f1697"},"md-book_refresh_outline":{"char":"󱚘","code":"f1698"},"md-book_remove":{"char":"󰪗","code":"f0a97"},"md-book_remove_multiple":{"char":"󰪖","code":"f0a96"},"md-book_remove_multiple_outline":{"char":"󰓊","code":"f04ca"},"md-book_remove_outline":{"char":"󱚙","code":"f1699"},"md-book_search":{"char":"󰺄","code":"f0e84"},"md-book_search_outline":{"char":"󰺅","code":"f0e85"},"md-book_settings":{"char":"󱚚","code":"f169a"},"md-book_settings_outline":{"char":"󱚛","code":"f169b"},"md-book_sync":{"char":"󱚜","code":"f169c"},"md-book_sync_outline":{"char":"󱛈","code":"f16c8"},"md-book_variant":{"char":"󰂿","code":"f00bf"},"md-book_variant_multiple":{"char":"󰂼","code":"f00bc"},"md-bookmark":{"char":"󰃀","code":"f00c0"},"md-bookmark_box_multiple":{"char":"󱥬","code":"f196c"},"md-bookmark_box_multiple_outline":{"char":"󱥭","code":"f196d"},"md-bookmark_check":{"char":"󰃁","code":"f00c1"},"md-bookmark_check_outline":{"char":"󱍻","code":"f137b"},"md-bookmark_minus":{"char":"󰧌","code":"f09cc"},"md-bookmark_minus_outline":{"char":"󰧍","code":"f09cd"},"md-bookmark_multiple":{"char":"󰸕","code":"f0e15"},"md-bookmark_multiple_outline":{"char":"󰸖","code":"f0e16"},"md-bookmark_music":{"char":"󰃂","code":"f00c2"},"md-bookmark_music_outline":{"char":"󱍹","code":"f1379"},"md-bookmark_off":{"char":"󰧎","code":"f09ce"},"md-bookmark_off_outline":{"char":"󰧏","code":"f09cf"},"md-bookmark_outline":{"char":"󰃃","code":"f00c3"},"md-bookmark_plus":{"char":"󰃅","code":"f00c5"},"md-bookmark_plus_outline":{"char":"󰃄","code":"f00c4"},"md-bookmark_remove":{"char":"󰃆","code":"f00c6"},"md-bookmark_remove_outline":{"char":"󱍺","code":"f137a"},"md-bookshelf":{"char":"󱉟","code":"f125f"},"md-boom_gate":{"char":"󰺆","code":"f0e86"},"md-boom_gate_alert":{"char":"󰺇","code":"f0e87"},"md-boom_gate_alert_outline":{"char":"󰺈","code":"f0e88"},"md-boom_gate_arrow_down":{"char":"󰺉","code":"f0e89"},"md-boom_gate_arrow_down_outline":{"char":"󰺊","code":"f0e8a"},"md-boom_gate_arrow_up":{"char":"󰺌","code":"f0e8c"},"md-boom_gate_arrow_up_outline":{"char":"󰺍","code":"f0e8d"},"md-boom_gate_outline":{"char":"󰺋","code":"f0e8b"},"md-boom_gate_up":{"char":"󱟹","code":"f17f9"},"md-boom_gate_up_outline":{"char":"󱟺","code":"f17fa"},"md-boombox":{"char":"󰗜","code":"f05dc"},"md-boomerang":{"char":"󱃏","code":"f10cf"},"md-bootstrap":{"char":"󰛆","code":"f06c6"},"md-border_all":{"char":"󰃇","code":"f00c7"},"md-border_all_variant":{"char":"󰢡","code":"f08a1"},"md-border_bottom":{"char":"󰃈","code":"f00c8"},"md-border_bottom_variant":{"char":"󰢢","code":"f08a2"},"md-border_color":{"char":"󰃉","code":"f00c9"},"md-border_horizontal":{"char":"󰃊","code":"f00ca"},"md-border_inside":{"char":"󰃋","code":"f00cb"},"md-border_left":{"char":"󰃌","code":"f00cc"},"md-border_left_variant":{"char":"󰢣","code":"f08a3"},"md-border_none":{"char":"󰃍","code":"f00cd"},"md-border_none_variant":{"char":"󰢤","code":"f08a4"},"md-border_outside":{"char":"󰃎","code":"f00ce"},"md-border_right":{"char":"󰃏","code":"f00cf"},"md-border_right_variant":{"char":"󰢥","code":"f08a5"},"md-border_style":{"char":"󰃐","code":"f00d0"},"md-border_top":{"char":"󰃑","code":"f00d1"},"md-border_top_variant":{"char":"󰢦","code":"f08a6"},"md-border_vertical":{"char":"󰃒","code":"f00d2"},"md-bottle_soda":{"char":"󱁰","code":"f1070"},"md-bottle_soda_classic":{"char":"󱁱","code":"f1071"},"md-bottle_soda_classic_outline":{"char":"󱍣","code":"f1363"},"md-bottle_soda_outline":{"char":"󱁲","code":"f1072"},"md-bottle_tonic":{"char":"󱄮","code":"f112e"},"md-bottle_tonic_outline":{"char":"󱄯","code":"f112f"},"md-bottle_tonic_plus":{"char":"󱄰","code":"f1130"},"md-bottle_tonic_plus_outline":{"char":"󱄱","code":"f1131"},"md-bottle_tonic_skull":{"char":"󱄲","code":"f1132"},"md-bottle_tonic_skull_outline":{"char":"󱄳","code":"f1133"},"md-bottle_wine":{"char":"󰡔","code":"f0854"},"md-bottle_wine_outline":{"char":"󱌐","code":"f1310"},"md-bow_arrow":{"char":"󱡁","code":"f1841"},"md-bow_tie":{"char":"󰙸","code":"f0678"},"md-bowl":{"char":"󰊎","code":"f028e"},"md-bowl_mix":{"char":"󰘗","code":"f0617"},"md-bowl_mix_outline":{"char":"󰋤","code":"f02e4"},"md-bowl_outline":{"char":"󰊩","code":"f02a9"},"md-bowling":{"char":"󰃓","code":"f00d3"},"md-box":{"char":"󰃔","code":"f00d4"},"md-box_cutter":{"char":"󰃕","code":"f00d5"},"md-box_cutter_off":{"char":"󰭊","code":"f0b4a"},"md-box_shadow":{"char":"󰘷","code":"f0637"},"md-boxing_glove":{"char":"󰭥","code":"f0b65"},"md-braille":{"char":"󰧐","code":"f09d0"},"md-brain":{"char":"󰧑","code":"f09d1"},"md-bread_slice":{"char":"󰳮","code":"f0cee"},"md-bread_slice_outline":{"char":"󰳯","code":"f0cef"},"md-bridge":{"char":"󰘘","code":"f0618"},"md-briefcase":{"char":"󰃖","code":"f00d6"},"md-briefcase_account":{"char":"󰳰","code":"f0cf0"},"md-briefcase_account_outline":{"char":"󰳱","code":"f0cf1"},"md-briefcase_arrow_left_right":{"char":"󱪍","code":"f1a8d"},"md-briefcase_arrow_left_right_outline":{"char":"󱪎","code":"f1a8e"},"md-briefcase_arrow_up_down":{"char":"󱪏","code":"f1a8f"},"md-briefcase_arrow_up_down_outline":{"char":"󱪐","code":"f1a90"},"md-briefcase_check":{"char":"󰃗","code":"f00d7"},"md-briefcase_check_outline":{"char":"󱌞","code":"f131e"},"md-briefcase_clock":{"char":"󱃐","code":"f10d0"},"md-briefcase_clock_outline":{"char":"󱃑","code":"f10d1"},"md-briefcase_download":{"char":"󰃘","code":"f00d8"},"md-briefcase_download_outline":{"char":"󰰽","code":"f0c3d"},"md-briefcase_edit":{"char":"󰪘","code":"f0a98"},"md-briefcase_edit_outline":{"char":"󰰾","code":"f0c3e"},"md-briefcase_eye":{"char":"󱟙","code":"f17d9"},"md-briefcase_eye_outline":{"char":"󱟚","code":"f17da"},"md-briefcase_minus":{"char":"󰨪","code":"f0a2a"},"md-briefcase_minus_outline":{"char":"󰰿","code":"f0c3f"},"md-briefcase_off":{"char":"󱙘","code":"f1658"},"md-briefcase_off_outline":{"char":"󱙙","code":"f1659"},"md-briefcase_outline":{"char":"󰠔","code":"f0814"},"md-briefcase_plus":{"char":"󰨫","code":"f0a2b"},"md-briefcase_plus_outline":{"char":"󰱀","code":"f0c40"},"md-briefcase_remove":{"char":"󰨬","code":"f0a2c"},"md-briefcase_remove_outline":{"char":"󰱁","code":"f0c41"},"md-briefcase_search":{"char":"󰨭","code":"f0a2d"},"md-briefcase_search_outline":{"char":"󰱂","code":"f0c42"},"md-briefcase_upload":{"char":"󰃙","code":"f00d9"},"md-briefcase_upload_outline":{"char":"󰱃","code":"f0c43"},"md-briefcase_variant":{"char":"󱒔","code":"f1494"},"md-briefcase_variant_off":{"char":"󱙚","code":"f165a"},"md-briefcase_variant_off_outline":{"char":"󱙛","code":"f165b"},"md-briefcase_variant_outline":{"char":"󱒕","code":"f1495"},"md-brightness_1":{"char":"󰃚","code":"f00da"},"md-brightness_2":{"char":"󰃛","code":"f00db"},"md-brightness_3":{"char":"󰃜","code":"f00dc"},"md-brightness_4":{"char":"󰃝","code":"f00dd"},"md-brightness_5":{"char":"󰃞","code":"f00de"},"md-brightness_6":{"char":"󰃟","code":"f00df"},"md-brightness_7":{"char":"󰃠","code":"f00e0"},"md-brightness_auto":{"char":"󰃡","code":"f00e1"},"md-brightness_percent":{"char":"󰳲","code":"f0cf2"},"md-broadcast":{"char":"󱜠","code":"f1720"},"md-broadcast_off":{"char":"󱜡","code":"f1721"},"md-broom":{"char":"󰃢","code":"f00e2"},"md-brush":{"char":"󰃣","code":"f00e3"},"md-brush_off":{"char":"󱝱","code":"f1771"},"md-brush_outline":{"char":"󱨍","code":"f1a0d"},"md-brush_variant":{"char":"󱠓","code":"f1813"},"md-bucket":{"char":"󱐕","code":"f1415"},"md-bucket_outline":{"char":"󱐖","code":"f1416"},"md-buffet":{"char":"󰕸","code":"f0578"},"md-bug":{"char":"󰃤","code":"f00e4"},"md-bug_check":{"char":"󰨮","code":"f0a2e"},"md-bug_check_outline":{"char":"󰨯","code":"f0a2f"},"md-bug_outline":{"char":"󰨰","code":"f0a30"},"md-bugle":{"char":"󰶴","code":"f0db4"},"md-bulkhead_light":{"char":"󱨯","code":"f1a2f"},"md-bulldozer":{"char":"󰬢","code":"f0b22"},"md-bullet":{"char":"󰳳","code":"f0cf3"},"md-bulletin_board":{"char":"󰃥","code":"f00e5"},"md-bullhorn":{"char":"󰃦","code":"f00e6"},"md-bullhorn_outline":{"char":"󰬣","code":"f0b23"},"md-bullhorn_variant":{"char":"󱥮","code":"f196e"},"md-bullhorn_variant_outline":{"char":"󱥯","code":"f196f"},"md-bullseye":{"char":"󰗝","code":"f05dd"},"md-bullseye_arrow":{"char":"󰣉","code":"f08c9"},"md-bulma":{"char":"󱋧","code":"f12e7"},"md-bunk_bed":{"char":"󱌂","code":"f1302"},"md-bunk_bed_outline":{"char":"󰂗","code":"f0097"},"md-bus":{"char":"󰃧","code":"f00e7"},"md-bus_alert":{"char":"󰪙","code":"f0a99"},"md-bus_articulated_end":{"char":"󰞜","code":"f079c"},"md-bus_articulated_front":{"char":"󰞝","code":"f079d"},"md-bus_clock":{"char":"󰣊","code":"f08ca"},"md-bus_double_decker":{"char":"󰞞","code":"f079e"},"md-bus_electric":{"char":"󱤝","code":"f191d"},"md-bus_marker":{"char":"󱈒","code":"f1212"},"md-bus_multiple":{"char":"󰼿","code":"f0f3f"},"md-bus_school":{"char":"󰞟","code":"f079f"},"md-bus_side":{"char":"󰞠","code":"f07a0"},"md-bus_stop":{"char":"󱀒","code":"f1012"},"md-bus_stop_covered":{"char":"󱀓","code":"f1013"},"md-bus_stop_uncovered":{"char":"󱀔","code":"f1014"},"md-butterfly":{"char":"󱖉","code":"f1589"},"md-butterfly_outline":{"char":"󱖊","code":"f158a"},"md-cabin_a_frame":{"char":"󱢌","code":"f188c"},"md-cable_data":{"char":"󱎔","code":"f1394"},"md-cached":{"char":"󰃨","code":"f00e8"},"md-cactus":{"char":"󰶵","code":"f0db5"},"md-cake":{"char":"󰃩","code":"f00e9"},"md-cake_layered":{"char":"󰃪","code":"f00ea"},"md-cake_variant":{"char":"󰃫","code":"f00eb"},"md-cake_variant_outline":{"char":"󱟰","code":"f17f0"},"md-calculator":{"char":"󰃬","code":"f00ec"},"md-calculator_variant":{"char":"󰪚","code":"f0a9a"},"md-calculator_variant_outline":{"char":"󱖦","code":"f15a6"},"md-calendar":{"char":"󰃭","code":"f00ed"},"md-calendar_account":{"char":"󰻗","code":"f0ed7"},"md-calendar_account_outline":{"char":"󰻘","code":"f0ed8"},"md-calendar_alert":{"char":"󰨱","code":"f0a31"},"md-calendar_arrow_left":{"char":"󱄴","code":"f1134"},"md-calendar_arrow_right":{"char":"󱄵","code":"f1135"},"md-calendar_blank":{"char":"󰃮","code":"f00ee"},"md-calendar_blank_multiple":{"char":"󱁳","code":"f1073"},"md-calendar_blank_outline":{"char":"󰭦","code":"f0b66"},"md-calendar_check":{"char":"󰃯","code":"f00ef"},"md-calendar_check_outline":{"char":"󰱄","code":"f0c44"},"md-calendar_clock":{"char":"󰃰","code":"f00f0"},"md-calendar_clock_outline":{"char":"󱛡","code":"f16e1"},"md-calendar_collapse_horizontal":{"char":"󱢝","code":"f189d"},"md-calendar_cursor":{"char":"󱕻","code":"f157b"},"md-calendar_edit":{"char":"󰢧","code":"f08a7"},"md-calendar_end":{"char":"󱙬","code":"f166c"},"md-calendar_expand_horizontal":{"char":"󱢞","code":"f189e"},"md-calendar_export":{"char":"󰬤","code":"f0b24"},"md-calendar_heart":{"char":"󰧒","code":"f09d2"},"md-calendar_import":{"char":"󰬥","code":"f0b25"},"md-calendar_lock":{"char":"󱙁","code":"f1641"},"md-calendar_lock_outline":{"char":"󱙂","code":"f1642"},"md-calendar_minus":{"char":"󰵜","code":"f0d5c"},"md-calendar_month":{"char":"󰸗","code":"f0e17"},"md-calendar_month_outline":{"char":"󰸘","code":"f0e18"},"md-calendar_multiple":{"char":"󰃱","code":"f00f1"},"md-calendar_multiple_check":{"char":"󰃲","code":"f00f2"},"md-calendar_multiselect":{"char":"󰨲","code":"f0a32"},"md-calendar_outline":{"char":"󰭧","code":"f0b67"},"md-calendar_plus":{"char":"󰃳","code":"f00f3"},"md-calendar_question":{"char":"󰚒","code":"f0692"},"md-calendar_range":{"char":"󰙹","code":"f0679"},"md-calendar_range_outline":{"char":"󰭨","code":"f0b68"},"md-calendar_refresh":{"char":"󰇡","code":"f01e1"},"md-calendar_refresh_outline":{"char":"󰈃","code":"f0203"},"md-calendar_remove":{"char":"󰃴","code":"f00f4"},"md-calendar_remove_outline":{"char":"󰱅","code":"f0c45"},"md-calendar_search":{"char":"󰥌","code":"f094c"},"md-calendar_star":{"char":"󰧓","code":"f09d3"},"md-calendar_start":{"char":"󱙭","code":"f166d"},"md-calendar_sync":{"char":"󰺎","code":"f0e8e"},"md-calendar_sync_outline":{"char":"󰺏","code":"f0e8f"},"md-calendar_text":{"char":"󰃵","code":"f00f5"},"md-calendar_text_outline":{"char":"󰱆","code":"f0c46"},"md-calendar_today":{"char":"󰃶","code":"f00f6"},"md-calendar_today_outline":{"char":"󱨰","code":"f1a30"},"md-calendar_week":{"char":"󰨳","code":"f0a33"},"md-calendar_week_begin":{"char":"󰨴","code":"f0a34"},"md-calendar_week_begin_outline":{"char":"󱨱","code":"f1a31"},"md-calendar_week_end":{"char":"󱨲","code":"f1a32"},"md-calendar_week_end_outline":{"char":"󱨳","code":"f1a33"},"md-calendar_week_outline":{"char":"󱨴","code":"f1a34"},"md-calendar_weekend":{"char":"󰻙","code":"f0ed9"},"md-calendar_weekend_outline":{"char":"󰻚","code":"f0eda"},"md-call_made":{"char":"󰃷","code":"f00f7"},"md-call_merge":{"char":"󰃸","code":"f00f8"},"md-call_missed":{"char":"󰃹","code":"f00f9"},"md-call_received":{"char":"󰃺","code":"f00fa"},"md-call_split":{"char":"󰃻","code":"f00fb"},"md-camcorder":{"char":"󰃼","code":"f00fc"},"md-camcorder_off":{"char":"󰃿","code":"f00ff"},"md-camera":{"char":"󰄀","code":"f0100"},"md-camera_account":{"char":"󰣋","code":"f08cb"},"md-camera_burst":{"char":"󰚓","code":"f0693"},"md-camera_control":{"char":"󰭩","code":"f0b69"},"md-camera_document":{"char":"󱡱","code":"f1871"},"md-camera_document_off":{"char":"󱡲","code":"f1872"},"md-camera_enhance":{"char":"󰄁","code":"f0101"},"md-camera_enhance_outline":{"char":"󰭪","code":"f0b6a"},"md-camera_flip":{"char":"󱗙","code":"f15d9"},"md-camera_flip_outline":{"char":"󱗚","code":"f15da"},"md-camera_front":{"char":"󰄂","code":"f0102"},"md-camera_front_variant":{"char":"󰄃","code":"f0103"},"md-camera_gopro":{"char":"󰞡","code":"f07a1"},"md-camera_image":{"char":"󰣌","code":"f08cc"},"md-camera_iris":{"char":"󰄄","code":"f0104"},"md-camera_lock":{"char":"󱨔","code":"f1a14"},"md-camera_lock_outline":{"char":"󱨕","code":"f1a15"},"md-camera_marker":{"char":"󱦧","code":"f19a7"},"md-camera_marker_outline":{"char":"󱦨","code":"f19a8"},"md-camera_metering_center":{"char":"󰞢","code":"f07a2"},"md-camera_metering_matrix":{"char":"󰞣","code":"f07a3"},"md-camera_metering_partial":{"char":"󰞤","code":"f07a4"},"md-camera_metering_spot":{"char":"󰞥","code":"f07a5"},"md-camera_off":{"char":"󰗟","code":"f05df"},"md-camera_off_outline":{"char":"󱦿","code":"f19bf"},"md-camera_outline":{"char":"󰵝","code":"f0d5d"},"md-camera_party_mode":{"char":"󰄅","code":"f0105"},"md-camera_plus":{"char":"󰻛","code":"f0edb"},"md-camera_plus_outline":{"char":"󰻜","code":"f0edc"},"md-camera_rear":{"char":"󰄆","code":"f0106"},"md-camera_rear_variant":{"char":"󰄇","code":"f0107"},"md-camera_retake":{"char":"󰸙","code":"f0e19"},"md-camera_retake_outline":{"char":"󰸚","code":"f0e1a"},"md-camera_switch":{"char":"󰄈","code":"f0108"},"md-camera_switch_outline":{"char":"󰡊","code":"f084a"},"md-camera_timer":{"char":"󰄉","code":"f0109"},"md-camera_wireless":{"char":"󰶶","code":"f0db6"},"md-camera_wireless_outline":{"char":"󰶷","code":"f0db7"},"md-campfire":{"char":"󰻝","code":"f0edd"},"md-cancel":{"char":"󰜺","code":"f073a"},"md-candelabra":{"char":"󱟒","code":"f17d2"},"md-candelabra_fire":{"char":"󱟓","code":"f17d3"},"md-candle":{"char":"󰗢","code":"f05e2"},"md-candy":{"char":"󱥰","code":"f1970"},"md-candy_off":{"char":"󱥱","code":"f1971"},"md-candy_off_outline":{"char":"󱥲","code":"f1972"},"md-candy_outline":{"char":"󱥳","code":"f1973"},"md-candycane":{"char":"󰄊","code":"f010a"},"md-cannabis":{"char":"󰞦","code":"f07a6"},"md-cannabis_off":{"char":"󱙮","code":"f166e"},"md-caps_lock":{"char":"󰪛","code":"f0a9b"},"md-car":{"char":"󰄋","code":"f010b"},"md-car_2_plus":{"char":"󱀕","code":"f1015"},"md-car_3_plus":{"char":"󱀖","code":"f1016"},"md-car_arrow_left":{"char":"󱎲","code":"f13b2"},"md-car_arrow_right":{"char":"󱎳","code":"f13b3"},"md-car_back":{"char":"󰸛","code":"f0e1b"},"md-car_battery":{"char":"󰄌","code":"f010c"},"md-car_brake_abs":{"char":"󰱇","code":"f0c47"},"md-car_brake_alert":{"char":"󰱈","code":"f0c48"},"md-car_brake_fluid_level":{"char":"󱤉","code":"f1909"},"md-car_brake_hold":{"char":"󰵞","code":"f0d5e"},"md-car_brake_low_pressure":{"char":"󱤊","code":"f190a"},"md-car_brake_parking":{"char":"󰵟","code":"f0d5f"},"md-car_brake_retarder":{"char":"󱀗","code":"f1017"},"md-car_brake_temperature":{"char":"󱤋","code":"f190b"},"md-car_brake_worn_linings":{"char":"󱤌","code":"f190c"},"md-car_child_seat":{"char":"󰾣","code":"f0fa3"},"md-car_clock":{"char":"󱥴","code":"f1974"},"md-car_clutch":{"char":"󱀘","code":"f1018"},"md-car_cog":{"char":"󱏌","code":"f13cc"},"md-car_connected":{"char":"󰄍","code":"f010d"},"md-car_convertible":{"char":"󰞧","code":"f07a7"},"md-car_coolant_level":{"char":"󱀙","code":"f1019"},"md-car_cruise_control":{"char":"󰵠","code":"f0d60"},"md-car_defrost_front":{"char":"󰵡","code":"f0d61"},"md-car_defrost_rear":{"char":"󰵢","code":"f0d62"},"md-car_door":{"char":"󰭫","code":"f0b6b"},"md-car_door_lock":{"char":"󱂝","code":"f109d"},"md-car_electric":{"char":"󰭬","code":"f0b6c"},"md-car_electric_outline":{"char":"󱖵","code":"f15b5"},"md-car_emergency":{"char":"󱘏","code":"f160f"},"md-car_esp":{"char":"󰱉","code":"f0c49"},"md-car_estate":{"char":"󰞨","code":"f07a8"},"md-car_hatchback":{"char":"󰞩","code":"f07a9"},"md-car_info":{"char":"󱆾","code":"f11be"},"md-car_key":{"char":"󰭭","code":"f0b6d"},"md-car_lifted_pickup":{"char":"󱔭","code":"f152d"},"md-car_light_alert":{"char":"󱤍","code":"f190d"},"md-car_light_dimmed":{"char":"󰱊","code":"f0c4a"},"md-car_light_fog":{"char":"󰱋","code":"f0c4b"},"md-car_light_high":{"char":"󰱌","code":"f0c4c"},"md-car_limousine":{"char":"󰣍","code":"f08cd"},"md-car_multiple":{"char":"󰭮","code":"f0b6e"},"md-car_off":{"char":"󰸜","code":"f0e1c"},"md-car_outline":{"char":"󱓭","code":"f14ed"},"md-car_parking_lights":{"char":"󰵣","code":"f0d63"},"md-car_pickup":{"char":"󰞪","code":"f07aa"},"md-car_seat":{"char":"󰾤","code":"f0fa4"},"md-car_seat_cooler":{"char":"󰾥","code":"f0fa5"},"md-car_seat_heater":{"char":"󰾦","code":"f0fa6"},"md-car_select":{"char":"󱡹","code":"f1879"},"md-car_settings":{"char":"󱏍","code":"f13cd"},"md-car_shift_pattern":{"char":"󰽀","code":"f0f40"},"md-car_side":{"char":"󰞫","code":"f07ab"},"md-car_speed_limiter":{"char":"󱤎","code":"f190e"},"md-car_sports":{"char":"󰞬","code":"f07ac"},"md-car_tire_alert":{"char":"󰱍","code":"f0c4d"},"md-car_traction_control":{"char":"󰵤","code":"f0d64"},"md-car_turbocharger":{"char":"󱀚","code":"f101a"},"md-car_wash":{"char":"󰄎","code":"f010e"},"md-car_windshield":{"char":"󱀛","code":"f101b"},"md-car_windshield_outline":{"char":"󱀜","code":"f101c"},"md-car_wireless":{"char":"󱡸","code":"f1878"},"md-car_wrench":{"char":"󱠔","code":"f1814"},"md-carabiner":{"char":"󱓀","code":"f14c0"},"md-caravan":{"char":"󰞭","code":"f07ad"},"md-card":{"char":"󰭯","code":"f0b6f"},"md-card_account_details":{"char":"󰗒","code":"f05d2"},"md-card_account_details_outline":{"char":"󰶫","code":"f0dab"},"md-card_account_details_star":{"char":"󰊣","code":"f02a3"},"md-card_account_details_star_outline":{"char":"󰛛","code":"f06db"},"md-card_account_mail":{"char":"󰆎","code":"f018e"},"md-card_account_mail_outline":{"char":"󰺘","code":"f0e98"},"md-card_account_phone":{"char":"󰺙","code":"f0e99"},"md-card_account_phone_outline":{"char":"󰺚","code":"f0e9a"},"md-card_bulleted":{"char":"󰭰","code":"f0b70"},"md-card_bulleted_off":{"char":"󰭱","code":"f0b71"},"md-card_bulleted_off_outline":{"char":"󰭲","code":"f0b72"},"md-card_bulleted_outline":{"char":"󰭳","code":"f0b73"},"md-card_bulleted_settings":{"char":"󰭴","code":"f0b74"},"md-card_bulleted_settings_outline":{"char":"󰭵","code":"f0b75"},"md-card_minus":{"char":"󱘀","code":"f1600"},"md-card_minus_outline":{"char":"󱘁","code":"f1601"},"md-card_multiple":{"char":"󱟱","code":"f17f1"},"md-card_multiple_outline":{"char":"󱟲","code":"f17f2"},"md-card_off":{"char":"󱘂","code":"f1602"},"md-card_off_outline":{"char":"󱘃","code":"f1603"},"md-card_outline":{"char":"󰭶","code":"f0b76"},"md-card_plus":{"char":"󱇿","code":"f11ff"},"md-card_plus_outline":{"char":"󱈀","code":"f1200"},"md-card_remove":{"char":"󱘄","code":"f1604"},"md-card_remove_outline":{"char":"󱘅","code":"f1605"},"md-card_search":{"char":"󱁴","code":"f1074"},"md-card_search_outline":{"char":"󱁵","code":"f1075"},"md-card_text":{"char":"󰭷","code":"f0b77"},"md-card_text_outline":{"char":"󰭸","code":"f0b78"},"md-cards":{"char":"󰘸","code":"f0638"},"md-cards_club":{"char":"󰣎","code":"f08ce"},"md-cards_club_outline":{"char":"󱢟","code":"f189f"},"md-cards_diamond":{"char":"󰣏","code":"f08cf"},"md-cards_diamond_outline":{"char":"󱀝","code":"f101d"},"md-cards_outline":{"char":"󰘹","code":"f0639"},"md-cards_playing":{"char":"󱢡","code":"f18a1"},"md-cards_playing_club":{"char":"󱢢","code":"f18a2"},"md-cards_playing_club_multiple":{"char":"󱢣","code":"f18a3"},"md-cards_playing_club_multiple_outline":{"char":"󱢤","code":"f18a4"},"md-cards_playing_club_outline":{"char":"󱢥","code":"f18a5"},"md-cards_playing_diamond":{"char":"󱢦","code":"f18a6"},"md-cards_playing_diamond_multiple":{"char":"󱢧","code":"f18a7"},"md-cards_playing_diamond_multiple_outline":{"char":"󱢨","code":"f18a8"},"md-cards_playing_diamond_outline":{"char":"󱢩","code":"f18a9"},"md-cards_playing_heart":{"char":"󱢪","code":"f18aa"},"md-cards_playing_heart_multiple":{"char":"󱢫","code":"f18ab"},"md-cards_playing_heart_multiple_outline":{"char":"󱢬","code":"f18ac"},"md-cards_playing_heart_outline":{"char":"󱢭","code":"f18ad"},"md-cards_playing_outline":{"char":"󰘺","code":"f063a"},"md-cards_playing_spade":{"char":"󱢮","code":"f18ae"},"md-cards_playing_spade_multiple":{"char":"󱢯","code":"f18af"},"md-cards_playing_spade_multiple_outline":{"char":"󱢰","code":"f18b0"},"md-cards_playing_spade_outline":{"char":"󱢱","code":"f18b1"},"md-cards_spade":{"char":"󰣑","code":"f08d1"},"md-cards_spade_outline":{"char":"󱢲","code":"f18b2"},"md-cards_variant":{"char":"󰛇","code":"f06c7"},"md-carrot":{"char":"󰄏","code":"f010f"},"md-cart":{"char":"󰄐","code":"f0110"},"md-cart_arrow_down":{"char":"󰵦","code":"f0d66"},"md-cart_arrow_right":{"char":"󰱎","code":"f0c4e"},"md-cart_arrow_up":{"char":"󰵧","code":"f0d67"},"md-cart_check":{"char":"󱗪","code":"f15ea"},"md-cart_heart":{"char":"󱣠","code":"f18e0"},"md-cart_minus":{"char":"󰵨","code":"f0d68"},"md-cart_off":{"char":"󰙫","code":"f066b"},"md-cart_outline":{"char":"󰄑","code":"f0111"},"md-cart_plus":{"char":"󰄒","code":"f0112"},"md-cart_remove":{"char":"󰵩","code":"f0d69"},"md-cart_variant":{"char":"󱗫","code":"f15eb"},"md-case_sensitive_alt":{"char":"󰄓","code":"f0113"},"md-cash":{"char":"󰄔","code":"f0114"},"md-cash_100":{"char":"󰄕","code":"f0115"},"md-cash_check":{"char":"󱓮","code":"f14ee"},"md-cash_clock":{"char":"󱪑","code":"f1a91"},"md-cash_fast":{"char":"󱡜","code":"f185c"},"md-cash_lock":{"char":"󱓪","code":"f14ea"},"md-cash_lock_open":{"char":"󱓫","code":"f14eb"},"md-cash_marker":{"char":"󰶸","code":"f0db8"},"md-cash_minus":{"char":"󱉠","code":"f1260"},"md-cash_multiple":{"char":"󰄖","code":"f0116"},"md-cash_plus":{"char":"󱉡","code":"f1261"},"md-cash_refund":{"char":"󰪜","code":"f0a9c"},"md-cash_register":{"char":"󰳴","code":"f0cf4"},"md-cash_remove":{"char":"󱉢","code":"f1262"},"md-cash_sync":{"char":"󱪒","code":"f1a92"},"md-cassette":{"char":"󰧔","code":"f09d4"},"md-cast":{"char":"󰄘","code":"f0118"},"md-cast_audio":{"char":"󱀞","code":"f101e"},"md-cast_audio_variant":{"char":"󱝉","code":"f1749"},"md-cast_connected":{"char":"󰄙","code":"f0119"},"md-cast_education":{"char":"󰸝","code":"f0e1d"},"md-cast_off":{"char":"󰞊","code":"f078a"},"md-cast_variant":{"char":"󰀟","code":"f001f"},"md-castle":{"char":"󰄚","code":"f011a"},"md-cat":{"char":"󰄛","code":"f011b"},"md-cctv":{"char":"󰞮","code":"f07ae"},"md-cctv_off":{"char":"󱡟","code":"f185f"},"md-ceiling_fan":{"char":"󱞗","code":"f1797"},"md-ceiling_fan_light":{"char":"󱞘","code":"f1798"},"md-ceiling_light":{"char":"󰝩","code":"f0769"},"md-ceiling_light_multiple":{"char":"󱣝","code":"f18dd"},"md-ceiling_light_multiple_outline":{"char":"󱣞","code":"f18de"},"md-ceiling_light_outline":{"char":"󱟇","code":"f17c7"},"md-cellphone":{"char":"󰄜","code":"f011c"},"md-cellphone_arrow_down":{"char":"󰧕","code":"f09d5"},"md-cellphone_arrow_down_variant":{"char":"󱧅","code":"f19c5"},"md-cellphone_basic":{"char":"󰄞","code":"f011e"},"md-cellphone_charging":{"char":"󱎗","code":"f1397"},"md-cellphone_check":{"char":"󱟽","code":"f17fd"},"md-cellphone_cog":{"char":"󰥑","code":"f0951"},"md-cellphone_dock":{"char":"󰄟","code":"f011f"},"md-cellphone_information":{"char":"󰽁","code":"f0f41"},"md-cellphone_key":{"char":"󰥎","code":"f094e"},"md-cellphone_link":{"char":"󰄡","code":"f0121"},"md-cellphone_link_off":{"char":"󰄢","code":"f0122"},"md-cellphone_lock":{"char":"󰥏","code":"f094f"},"md-cellphone_marker":{"char":"󱠺","code":"f183a"},"md-cellphone_message":{"char":"󰣓","code":"f08d3"},"md-cellphone_message_off":{"char":"󱃒","code":"f10d2"},"md-cellphone_nfc":{"char":"󰺐","code":"f0e90"},"md-cellphone_nfc_off":{"char":"󱋘","code":"f12d8"},"md-cellphone_off":{"char":"󰥐","code":"f0950"},"md-cellphone_play":{"char":"󱀟","code":"f101f"},"md-cellphone_remove":{"char":"󰥍","code":"f094d"},"md-cellphone_screenshot":{"char":"󰨵","code":"f0a35"},"md-cellphone_settings":{"char":"󰄣","code":"f0123"},"md-cellphone_sound":{"char":"󰥒","code":"f0952"},"md-cellphone_text":{"char":"󰣒","code":"f08d2"},"md-cellphone_wireless":{"char":"󰠕","code":"f0815"},"md-centos":{"char":"󱄚","code":"f111a"},"md-certificate":{"char":"󰄤","code":"f0124"},"md-certificate_outline":{"char":"󱆈","code":"f1188"},"md-chair_rolling":{"char":"󰽈","code":"f0f48"},"md-chair_school":{"char":"󰄥","code":"f0125"},"md-chandelier":{"char":"󱞓","code":"f1793"},"md-charity":{"char":"󰱏","code":"f0c4f"},"md-chart_arc":{"char":"󰄦","code":"f0126"},"md-chart_areaspline":{"char":"󰄧","code":"f0127"},"md-chart_areaspline_variant":{"char":"󰺑","code":"f0e91"},"md-chart_bar":{"char":"󰄨","code":"f0128"},"md-chart_bar_stacked":{"char":"󰝪","code":"f076a"},"md-chart_bell_curve":{"char":"󰱐","code":"f0c50"},"md-chart_bell_curve_cumulative":{"char":"󰾧","code":"f0fa7"},"md-chart_box":{"char":"󱕍","code":"f154d"},"md-chart_box_outline":{"char":"󱕎","code":"f154e"},"md-chart_box_plus_outline":{"char":"󱕏","code":"f154f"},"md-chart_bubble":{"char":"󰗣","code":"f05e3"},"md-chart_donut":{"char":"󰞯","code":"f07af"},"md-chart_donut_variant":{"char":"󰞰","code":"f07b0"},"md-chart_gantt":{"char":"󰙬","code":"f066c"},"md-chart_histogram":{"char":"󰄩","code":"f0129"},"md-chart_line":{"char":"󰄪","code":"f012a"},"md-chart_line_stacked":{"char":"󰝫","code":"f076b"},"md-chart_line_variant":{"char":"󰞱","code":"f07b1"},"md-chart_multiline":{"char":"󰣔","code":"f08d4"},"md-chart_multiple":{"char":"󱈓","code":"f1213"},"md-chart_pie":{"char":"󰄫","code":"f012b"},"md-chart_ppf":{"char":"󱎀","code":"f1380"},"md-chart_sankey":{"char":"󱇟","code":"f11df"},"md-chart_sankey_variant":{"char":"󱇠","code":"f11e0"},"md-chart_scatter_plot":{"char":"󰺒","code":"f0e92"},"md-chart_scatter_plot_hexbin":{"char":"󰙭","code":"f066d"},"md-chart_timeline":{"char":"󰙮","code":"f066e"},"md-chart_timeline_variant":{"char":"󰺓","code":"f0e93"},"md-chart_timeline_variant_shimmer":{"char":"󱖶","code":"f15b6"},"md-chart_tree":{"char":"󰺔","code":"f0e94"},"md-chart_waterfall":{"char":"󱤘","code":"f1918"},"md-chat":{"char":"󰭹","code":"f0b79"},"md-chat_alert":{"char":"󰭺","code":"f0b7a"},"md-chat_alert_outline":{"char":"󱋉","code":"f12c9"},"md-chat_minus":{"char":"󱐐","code":"f1410"},"md-chat_minus_outline":{"char":"󱐓","code":"f1413"},"md-chat_outline":{"char":"󰻞","code":"f0ede"},"md-chat_plus":{"char":"󱐏","code":"f140f"},"md-chat_plus_outline":{"char":"󱐒","code":"f1412"},"md-chat_processing":{"char":"󰭻","code":"f0b7b"},"md-chat_processing_outline":{"char":"󱋊","code":"f12ca"},"md-chat_question":{"char":"󱜸","code":"f1738"},"md-chat_question_outline":{"char":"󱜹","code":"f1739"},"md-chat_remove":{"char":"󱐑","code":"f1411"},"md-chat_remove_outline":{"char":"󱐔","code":"f1414"},"md-chat_sleep":{"char":"󱋑","code":"f12d1"},"md-chat_sleep_outline":{"char":"󱋒","code":"f12d2"},"md-check":{"char":"󰄬","code":"f012c"},"md-check_all":{"char":"󰄭","code":"f012d"},"md-check_bold":{"char":"󰸞","code":"f0e1e"},"md-check_circle":{"char":"󰗠","code":"f05e0"},"md-check_circle_outline":{"char":"󰗡","code":"f05e1"},"md-check_decagram":{"char":"󰞑","code":"f0791"},"md-check_decagram_outline":{"char":"󱝀","code":"f1740"},"md-check_network":{"char":"󰱓","code":"f0c53"},"md-check_network_outline":{"char":"󰱔","code":"f0c54"},"md-check_outline":{"char":"󰡕","code":"f0855"},"md-check_underline":{"char":"󰸟","code":"f0e1f"},"md-check_underline_circle":{"char":"󰸠","code":"f0e20"},"md-check_underline_circle_outline":{"char":"󰸡","code":"f0e21"},"md-checkbook":{"char":"󰪝","code":"f0a9d"},"md-checkbox_blank":{"char":"󰄮","code":"f012e"},"md-checkbox_blank_badge":{"char":"󱅶","code":"f1176"},"md-checkbox_blank_badge_outline":{"char":"󰄗","code":"f0117"},"md-checkbox_blank_circle":{"char":"󰄯","code":"f012f"},"md-checkbox_blank_circle_outline":{"char":"󰄰","code":"f0130"},"md-checkbox_blank_off":{"char":"󱋬","code":"f12ec"},"md-checkbox_blank_off_outline":{"char":"󱋭","code":"f12ed"},"md-checkbox_blank_outline":{"char":"󰄱","code":"f0131"},"md-checkbox_intermediate":{"char":"󰡖","code":"f0856"},"md-checkbox_marked":{"char":"󰄲","code":"f0132"},"md-checkbox_marked_circle":{"char":"󰄳","code":"f0133"},"md-checkbox_marked_circle_outline":{"char":"󰄴","code":"f0134"},"md-checkbox_marked_circle_plus_outline":{"char":"󱤧","code":"f1927"},"md-checkbox_marked_outline":{"char":"󰄵","code":"f0135"},"md-checkbox_multiple_blank":{"char":"󰄶","code":"f0136"},"md-checkbox_multiple_blank_circle":{"char":"󰘻","code":"f063b"},"md-checkbox_multiple_blank_circle_outline":{"char":"󰘼","code":"f063c"},"md-checkbox_multiple_blank_outline":{"char":"󰄷","code":"f0137"},"md-checkbox_multiple_marked":{"char":"󰄸","code":"f0138"},"md-checkbox_multiple_marked_circle":{"char":"󰘽","code":"f063d"},"md-checkbox_multiple_marked_circle_outline":{"char":"󰘾","code":"f063e"},"md-checkbox_multiple_marked_outline":{"char":"󰄹","code":"f0139"},"md-checkbox_multiple_outline":{"char":"󰱑","code":"f0c51"},"md-checkbox_outline":{"char":"󰱒","code":"f0c52"},"md-checkerboard":{"char":"󰄺","code":"f013a"},"md-checkerboard_minus":{"char":"󱈂","code":"f1202"},"md-checkerboard_plus":{"char":"󱈁","code":"f1201"},"md-checkerboard_remove":{"char":"󱈃","code":"f1203"},"md-cheese":{"char":"󱊹","code":"f12b9"},"md-cheese_off":{"char":"󱏮","code":"f13ee"},"md-chef_hat":{"char":"󰭼","code":"f0b7c"},"md-chemical_weapon":{"char":"󰄻","code":"f013b"},"md-chess_bishop":{"char":"󰡜","code":"f085c"},"md-chess_king":{"char":"󰡗","code":"f0857"},"md-chess_knight":{"char":"󰡘","code":"f0858"},"md-chess_pawn":{"char":"󰡙","code":"f0859"},"md-chess_queen":{"char":"󰡚","code":"f085a"},"md-chess_rook":{"char":"󰡛","code":"f085b"},"md-chevron_double_down":{"char":"󰄼","code":"f013c"},"md-chevron_double_left":{"char":"󰄽","code":"f013d"},"md-chevron_double_right":{"char":"󰄾","code":"f013e"},"md-chevron_double_up":{"char":"󰄿","code":"f013f"},"md-chevron_down":{"char":"󰅀","code":"f0140"},"md-chevron_down_box":{"char":"󰧖","code":"f09d6"},"md-chevron_down_box_outline":{"char":"󰧗","code":"f09d7"},"md-chevron_down_circle":{"char":"󰬦","code":"f0b26"},"md-chevron_down_circle_outline":{"char":"󰬧","code":"f0b27"},"md-chevron_left":{"char":"󰅁","code":"f0141"},"md-chevron_left_box":{"char":"󰧘","code":"f09d8"},"md-chevron_left_box_outline":{"char":"󰧙","code":"f09d9"},"md-chevron_left_circle":{"char":"󰬨","code":"f0b28"},"md-chevron_left_circle_outline":{"char":"󰬩","code":"f0b29"},"md-chevron_right":{"char":"󰅂","code":"f0142"},"md-chevron_right_box":{"char":"󰧚","code":"f09da"},"md-chevron_right_box_outline":{"char":"󰧛","code":"f09db"},"md-chevron_right_circle":{"char":"󰬪","code":"f0b2a"},"md-chevron_right_circle_outline":{"char":"󰬫","code":"f0b2b"},"md-chevron_triple_down":{"char":"󰶹","code":"f0db9"},"md-chevron_triple_left":{"char":"󰶺","code":"f0dba"},"md-chevron_triple_right":{"char":"󰶻","code":"f0dbb"},"md-chevron_triple_up":{"char":"󰶼","code":"f0dbc"},"md-chevron_up":{"char":"󰅃","code":"f0143"},"md-chevron_up_box":{"char":"󰧜","code":"f09dc"},"md-chevron_up_box_outline":{"char":"󰧝","code":"f09dd"},"md-chevron_up_circle":{"char":"󰬬","code":"f0b2c"},"md-chevron_up_circle_outline":{"char":"󰬭","code":"f0b2d"},"md-chili_alert":{"char":"󱟪","code":"f17ea"},"md-chili_alert_outline":{"char":"󱟫","code":"f17eb"},"md-chili_hot":{"char":"󰞲","code":"f07b2"},"md-chili_hot_outline":{"char":"󱟬","code":"f17ec"},"md-chili_medium":{"char":"󰞳","code":"f07b3"},"md-chili_medium_outline":{"char":"󱟭","code":"f17ed"},"md-chili_mild":{"char":"󰞴","code":"f07b4"},"md-chili_mild_outline":{"char":"󱟮","code":"f17ee"},"md-chili_off":{"char":"󱑧","code":"f1467"},"md-chili_off_outline":{"char":"󱟯","code":"f17ef"},"md-chip":{"char":"󰘚","code":"f061a"},"md-church":{"char":"󰅄","code":"f0144"},"md-cigar":{"char":"󱆉","code":"f1189"},"md-cigar_off":{"char":"󱐛","code":"f141b"},"md-circle_box":{"char":"󱗜","code":"f15dc"},"md-circle_box_outline":{"char":"󱗝","code":"f15dd"},"md-circle_double":{"char":"󰺕","code":"f0e95"},"md-circle_edit_outline":{"char":"󰣕","code":"f08d5"},"md-circle_expand":{"char":"󰺖","code":"f0e96"},"md-circle_half":{"char":"󱎕","code":"f1395"},"md-circle_half_full":{"char":"󱎖","code":"f1396"},"md-circle_medium":{"char":"󰧞","code":"f09de"},"md-circle_multiple":{"char":"󰬸","code":"f0b38"},"md-circle_multiple_outline":{"char":"󰚕","code":"f0695"},"md-circle_off_outline":{"char":"󱃓","code":"f10d3"},"md-circle_opacity":{"char":"󱡓","code":"f1853"},"md-circle_slice_1":{"char":"󰪞","code":"f0a9e"},"md-circle_slice_2":{"char":"󰪟","code":"f0a9f"},"md-circle_slice_3":{"char":"󰪠","code":"f0aa0"},"md-circle_slice_4":{"char":"󰪡","code":"f0aa1"},"md-circle_slice_5":{"char":"󰪢","code":"f0aa2"},"md-circle_slice_6":{"char":"󰪣","code":"f0aa3"},"md-circle_slice_7":{"char":"󰪤","code":"f0aa4"},"md-circle_slice_8":{"char":"󰪥","code":"f0aa5"},"md-circle_small":{"char":"󰧟","code":"f09df"},"md-circular_saw":{"char":"󰸢","code":"f0e22"},"md-city":{"char":"󰅆","code":"f0146"},"md-city_variant":{"char":"󰨶","code":"f0a36"},"md-city_variant_outline":{"char":"󰨷","code":"f0a37"},"md-clipboard":{"char":"󰅇","code":"f0147"},"md-clipboard_account":{"char":"󰅈","code":"f0148"},"md-clipboard_account_outline":{"char":"󰱕","code":"f0c55"},"md-clipboard_alert":{"char":"󰅉","code":"f0149"},"md-clipboard_alert_outline":{"char":"󰳷","code":"f0cf7"},"md-clipboard_arrow_down":{"char":"󰅊","code":"f014a"},"md-clipboard_arrow_down_outline":{"char":"󰱖","code":"f0c56"},"md-clipboard_arrow_left":{"char":"󰅋","code":"f014b"},"md-clipboard_arrow_left_outline":{"char":"󰳸","code":"f0cf8"},"md-clipboard_arrow_right":{"char":"󰳹","code":"f0cf9"},"md-clipboard_arrow_right_outline":{"char":"󰳺","code":"f0cfa"},"md-clipboard_arrow_up":{"char":"󰱗","code":"f0c57"},"md-clipboard_arrow_up_outline":{"char":"󰱘","code":"f0c58"},"md-clipboard_check":{"char":"󰅎","code":"f014e"},"md-clipboard_check_multiple":{"char":"󱉣","code":"f1263"},"md-clipboard_check_multiple_outline":{"char":"󱉤","code":"f1264"},"md-clipboard_check_outline":{"char":"󰢨","code":"f08a8"},"md-clipboard_clock":{"char":"󱛢","code":"f16e2"},"md-clipboard_clock_outline":{"char":"󱛣","code":"f16e3"},"md-clipboard_edit":{"char":"󱓥","code":"f14e5"},"md-clipboard_edit_outline":{"char":"󱓦","code":"f14e6"},"md-clipboard_file":{"char":"󱉥","code":"f1265"},"md-clipboard_file_outline":{"char":"󱉦","code":"f1266"},"md-clipboard_flow":{"char":"󰛈","code":"f06c8"},"md-clipboard_flow_outline":{"char":"󱄗","code":"f1117"},"md-clipboard_list":{"char":"󱃔","code":"f10d4"},"md-clipboard_list_outline":{"char":"󱃕","code":"f10d5"},"md-clipboard_minus":{"char":"󱘘","code":"f1618"},"md-clipboard_minus_outline":{"char":"󱘙","code":"f1619"},"md-clipboard_multiple":{"char":"󱉧","code":"f1267"},"md-clipboard_multiple_outline":{"char":"󱉨","code":"f1268"},"md-clipboard_off":{"char":"󱘚","code":"f161a"},"md-clipboard_off_outline":{"char":"󱘛","code":"f161b"},"md-clipboard_outline":{"char":"󰅌","code":"f014c"},"md-clipboard_play":{"char":"󰱙","code":"f0c59"},"md-clipboard_play_multiple":{"char":"󱉩","code":"f1269"},"md-clipboard_play_multiple_outline":{"char":"󱉪","code":"f126a"},"md-clipboard_play_outline":{"char":"󰱚","code":"f0c5a"},"md-clipboard_plus":{"char":"󰝑","code":"f0751"},"md-clipboard_plus_outline":{"char":"󱌟","code":"f131f"},"md-clipboard_pulse":{"char":"󰡝","code":"f085d"},"md-clipboard_pulse_outline":{"char":"󰡞","code":"f085e"},"md-clipboard_remove":{"char":"󱘜","code":"f161c"},"md-clipboard_remove_outline":{"char":"󱘝","code":"f161d"},"md-clipboard_search":{"char":"󱘞","code":"f161e"},"md-clipboard_search_outline":{"char":"󱘟","code":"f161f"},"md-clipboard_text":{"char":"󰅍","code":"f014d"},"md-clipboard_text_clock":{"char":"󱣹","code":"f18f9"},"md-clipboard_text_clock_outline":{"char":"󱣺","code":"f18fa"},"md-clipboard_text_multiple":{"char":"󱉫","code":"f126b"},"md-clipboard_text_multiple_outline":{"char":"󱉬","code":"f126c"},"md-clipboard_text_off":{"char":"󱘠","code":"f1620"},"md-clipboard_text_off_outline":{"char":"󱘡","code":"f1621"},"md-clipboard_text_outline":{"char":"󰨸","code":"f0a38"},"md-clipboard_text_play":{"char":"󰱛","code":"f0c5b"},"md-clipboard_text_play_outline":{"char":"󰱜","code":"f0c5c"},"md-clipboard_text_search":{"char":"󱘢","code":"f1622"},"md-clipboard_text_search_outline":{"char":"󱘣","code":"f1623"},"md-clippy":{"char":"󰅏","code":"f014f"},"md-clock":{"char":"󰥔","code":"f0954"},"md-clock_alert":{"char":"󰥕","code":"f0955"},"md-clock_alert_outline":{"char":"󰗎","code":"f05ce"},"md-clock_check":{"char":"󰾨","code":"f0fa8"},"md-clock_check_outline":{"char":"󰾩","code":"f0fa9"},"md-clock_digital":{"char":"󰺗","code":"f0e97"},"md-clock_edit":{"char":"󱦺","code":"f19ba"},"md-clock_edit_outline":{"char":"󱦻","code":"f19bb"},"md-clock_end":{"char":"󰅑","code":"f0151"},"md-clock_fast":{"char":"󰅒","code":"f0152"},"md-clock_in":{"char":"󰅓","code":"f0153"},"md-clock_minus":{"char":"󱡣","code":"f1863"},"md-clock_minus_outline":{"char":"󱡤","code":"f1864"},"md-clock_out":{"char":"󰅔","code":"f0154"},"md-clock_outline":{"char":"󰅐","code":"f0150"},"md-clock_plus":{"char":"󱡡","code":"f1861"},"md-clock_plus_outline":{"char":"󱡢","code":"f1862"},"md-clock_remove":{"char":"󱡥","code":"f1865"},"md-clock_remove_outline":{"char":"󱡦","code":"f1866"},"md-clock_start":{"char":"󰅕","code":"f0155"},"md-clock_time_eight":{"char":"󱑆","code":"f1446"},"md-clock_time_eight_outline":{"char":"󱑒","code":"f1452"},"md-clock_time_eleven":{"char":"󱑉","code":"f1449"},"md-clock_time_eleven_outline":{"char":"󱑕","code":"f1455"},"md-clock_time_five":{"char":"󱑃","code":"f1443"},"md-clock_time_five_outline":{"char":"󱑏","code":"f144f"},"md-clock_time_four":{"char":"󱑂","code":"f1442"},"md-clock_time_four_outline":{"char":"󱑎","code":"f144e"},"md-clock_time_nine":{"char":"󱑇","code":"f1447"},"md-clock_time_nine_outline":{"char":"󱑓","code":"f1453"},"md-clock_time_one":{"char":"󱐿","code":"f143f"},"md-clock_time_one_outline":{"char":"󱑋","code":"f144b"},"md-clock_time_seven":{"char":"󱑅","code":"f1445"},"md-clock_time_seven_outline":{"char":"󱑑","code":"f1451"},"md-clock_time_six":{"char":"󱑄","code":"f1444"},"md-clock_time_six_outline":{"char":"󱑐","code":"f1450"},"md-clock_time_ten":{"char":"󱑈","code":"f1448"},"md-clock_time_ten_outline":{"char":"󱑔","code":"f1454"},"md-clock_time_three":{"char":"󱑁","code":"f1441"},"md-clock_time_three_outline":{"char":"󱑍","code":"f144d"},"md-clock_time_twelve":{"char":"󱑊","code":"f144a"},"md-clock_time_twelve_outline":{"char":"󱑖","code":"f1456"},"md-clock_time_two":{"char":"󱑀","code":"f1440"},"md-clock_time_two_outline":{"char":"󱑌","code":"f144c"},"md-close":{"char":"󰅖","code":"f0156"},"md-close_box":{"char":"󰅗","code":"f0157"},"md-close_box_multiple":{"char":"󰱝","code":"f0c5d"},"md-close_box_multiple_outline":{"char":"󰱞","code":"f0c5e"},"md-close_box_outline":{"char":"󰅘","code":"f0158"},"md-close_circle":{"char":"󰅙","code":"f0159"},"md-close_circle_multiple":{"char":"󰘪","code":"f062a"},"md-close_circle_multiple_outline":{"char":"󰢃","code":"f0883"},"md-close_circle_outline":{"char":"󰅚","code":"f015a"},"md-close_network":{"char":"󰅛","code":"f015b"},"md-close_network_outline":{"char":"󰱟","code":"f0c5f"},"md-close_octagon":{"char":"󰅜","code":"f015c"},"md-close_octagon_outline":{"char":"󰅝","code":"f015d"},"md-close_outline":{"char":"󰛉","code":"f06c9"},"md-close_thick":{"char":"󱎘","code":"f1398"},"md-closed_caption":{"char":"󰅞","code":"f015e"},"md-closed_caption_outline":{"char":"󰶽","code":"f0dbd"},"md-cloud":{"char":"󰅟","code":"f015f"},"md-cloud_alert":{"char":"󰧠","code":"f09e0"},"md-cloud_braces":{"char":"󰞵","code":"f07b5"},"md-cloud_check":{"char":"󰅠","code":"f0160"},"md-cloud_check_outline":{"char":"󱋌","code":"f12cc"},"md-cloud_circle":{"char":"󰅡","code":"f0161"},"md-cloud_download":{"char":"󰅢","code":"f0162"},"md-cloud_download_outline":{"char":"󰭽","code":"f0b7d"},"md-cloud_lock":{"char":"󱇱","code":"f11f1"},"md-cloud_lock_outline":{"char":"󱇲","code":"f11f2"},"md-cloud_off_outline":{"char":"󰅤","code":"f0164"},"md-cloud_outline":{"char":"󰅣","code":"f0163"},"md-cloud_percent":{"char":"󱨵","code":"f1a35"},"md-cloud_percent_outline":{"char":"󱨶","code":"f1a36"},"md-cloud_print":{"char":"󰅥","code":"f0165"},"md-cloud_print_outline":{"char":"󰅦","code":"f0166"},"md-cloud_question":{"char":"󰨹","code":"f0a39"},"md-cloud_refresh":{"char":"󰔪","code":"f052a"},"md-cloud_search":{"char":"󰥖","code":"f0956"},"md-cloud_search_outline":{"char":"󰥗","code":"f0957"},"md-cloud_sync":{"char":"󰘿","code":"f063f"},"md-cloud_sync_outline":{"char":"󱋖","code":"f12d6"},"md-cloud_tags":{"char":"󰞶","code":"f07b6"},"md-cloud_upload":{"char":"󰅧","code":"f0167"},"md-cloud_upload_outline":{"char":"󰭾","code":"f0b7e"},"md-clover":{"char":"󰠖","code":"f0816"},"md-coach_lamp":{"char":"󱀠","code":"f1020"},"md-coach_lamp_variant":{"char":"󱨷","code":"f1a37"},"md-coat_rack":{"char":"󱂞","code":"f109e"},"md-code_array":{"char":"󰅨","code":"f0168"},"md-code_braces":{"char":"󰅩","code":"f0169"},"md-code_braces_box":{"char":"󱃖","code":"f10d6"},"md-code_brackets":{"char":"󰅪","code":"f016a"},"md-code_equal":{"char":"󰅫","code":"f016b"},"md-code_greater_than":{"char":"󰅬","code":"f016c"},"md-code_greater_than_or_equal":{"char":"󰅭","code":"f016d"},"md-code_json":{"char":"󰘦","code":"f0626"},"md-code_less_than":{"char":"󰅮","code":"f016e"},"md-code_less_than_or_equal":{"char":"󰅯","code":"f016f"},"md-code_not_equal":{"char":"󰅰","code":"f0170"},"md-code_not_equal_variant":{"char":"󰅱","code":"f0171"},"md-code_parentheses":{"char":"󰅲","code":"f0172"},"md-code_parentheses_box":{"char":"󱃗","code":"f10d7"},"md-code_string":{"char":"󰅳","code":"f0173"},"md-code_tags":{"char":"󰅴","code":"f0174"},"md-code_tags_check":{"char":"󰚔","code":"f0694"},"md-codepen":{"char":"󰅵","code":"f0175"},"md-coffee":{"char":"󰅶","code":"f0176"},"md-coffee_maker":{"char":"󱂟","code":"f109f"},"md-coffee_maker_check":{"char":"󱤱","code":"f1931"},"md-coffee_maker_check_outline":{"char":"󱤲","code":"f1932"},"md-coffee_maker_outline":{"char":"󱠛","code":"f181b"},"md-coffee_off":{"char":"󰾪","code":"f0faa"},"md-coffee_off_outline":{"char":"󰾫","code":"f0fab"},"md-coffee_outline":{"char":"󰛊","code":"f06ca"},"md-coffee_to_go":{"char":"󰅷","code":"f0177"},"md-coffee_to_go_outline":{"char":"󱌎","code":"f130e"},"md-coffin":{"char":"󰭿","code":"f0b7f"},"md-cog":{"char":"󰒓","code":"f0493"},"md-cog_box":{"char":"󰒔","code":"f0494"},"md-cog_clockwise":{"char":"󱇝","code":"f11dd"},"md-cog_counterclockwise":{"char":"󱇞","code":"f11de"},"md-cog_off":{"char":"󱏎","code":"f13ce"},"md-cog_off_outline":{"char":"󱏏","code":"f13cf"},"md-cog_outline":{"char":"󰢻","code":"f08bb"},"md-cog_pause":{"char":"󱤳","code":"f1933"},"md-cog_pause_outline":{"char":"󱤴","code":"f1934"},"md-cog_play":{"char":"󱤵","code":"f1935"},"md-cog_play_outline":{"char":"󱤶","code":"f1936"},"md-cog_refresh":{"char":"󱑞","code":"f145e"},"md-cog_refresh_outline":{"char":"󱑟","code":"f145f"},"md-cog_stop":{"char":"󱤷","code":"f1937"},"md-cog_stop_outline":{"char":"󱤸","code":"f1938"},"md-cog_sync":{"char":"󱑠","code":"f1460"},"md-cog_sync_outline":{"char":"󱑡","code":"f1461"},"md-cog_transfer":{"char":"󱁛","code":"f105b"},"md-cog_transfer_outline":{"char":"󱁜","code":"f105c"},"md-cogs":{"char":"󰣖","code":"f08d6"},"md-collage":{"char":"󰙀","code":"f0640"},"md-collapse_all":{"char":"󰪦","code":"f0aa6"},"md-collapse_all_outline":{"char":"󰪧","code":"f0aa7"},"md-color_helper":{"char":"󰅹","code":"f0179"},"md-comma":{"char":"󰸣","code":"f0e23"},"md-comma_box":{"char":"󰸫","code":"f0e2b"},"md-comma_box_outline":{"char":"󰸤","code":"f0e24"},"md-comma_circle":{"char":"󰸥","code":"f0e25"},"md-comma_circle_outline":{"char":"󰸦","code":"f0e26"},"md-comment":{"char":"󰅺","code":"f017a"},"md-comment_account":{"char":"󰅻","code":"f017b"},"md-comment_account_outline":{"char":"󰅼","code":"f017c"},"md-comment_alert":{"char":"󰅽","code":"f017d"},"md-comment_alert_outline":{"char":"󰅾","code":"f017e"},"md-comment_arrow_left":{"char":"󰧡","code":"f09e1"},"md-comment_arrow_left_outline":{"char":"󰧢","code":"f09e2"},"md-comment_arrow_right":{"char":"󰧣","code":"f09e3"},"md-comment_arrow_right_outline":{"char":"󰧤","code":"f09e4"},"md-comment_bookmark":{"char":"󱖮","code":"f15ae"},"md-comment_bookmark_outline":{"char":"󱖯","code":"f15af"},"md-comment_check":{"char":"󰅿","code":"f017f"},"md-comment_check_outline":{"char":"󰆀","code":"f0180"},"md-comment_edit":{"char":"󱆿","code":"f11bf"},"md-comment_edit_outline":{"char":"󱋄","code":"f12c4"},"md-comment_eye":{"char":"󰨺","code":"f0a3a"},"md-comment_eye_outline":{"char":"󰨻","code":"f0a3b"},"md-comment_flash":{"char":"󱖰","code":"f15b0"},"md-comment_flash_outline":{"char":"󱖱","code":"f15b1"},"md-comment_minus":{"char":"󱗟","code":"f15df"},"md-comment_minus_outline":{"char":"󱗠","code":"f15e0"},"md-comment_multiple":{"char":"󰡟","code":"f085f"},"md-comment_multiple_outline":{"char":"󰆁","code":"f0181"},"md-comment_off":{"char":"󱗡","code":"f15e1"},"md-comment_off_outline":{"char":"󱗢","code":"f15e2"},"md-comment_outline":{"char":"󰆂","code":"f0182"},"md-comment_plus":{"char":"󰧥","code":"f09e5"},"md-comment_plus_outline":{"char":"󰆃","code":"f0183"},"md-comment_processing":{"char":"󰆄","code":"f0184"},"md-comment_processing_outline":{"char":"󰆅","code":"f0185"},"md-comment_question":{"char":"󰠗","code":"f0817"},"md-comment_question_outline":{"char":"󰆆","code":"f0186"},"md-comment_quote":{"char":"󱀡","code":"f1021"},"md-comment_quote_outline":{"char":"󱀢","code":"f1022"},"md-comment_remove":{"char":"󰗞","code":"f05de"},"md-comment_remove_outline":{"char":"󰆇","code":"f0187"},"md-comment_search":{"char":"󰨼","code":"f0a3c"},"md-comment_search_outline":{"char":"󰨽","code":"f0a3d"},"md-comment_text":{"char":"󰆈","code":"f0188"},"md-comment_text_multiple":{"char":"󰡠","code":"f0860"},"md-comment_text_multiple_outline":{"char":"󰡡","code":"f0861"},"md-comment_text_outline":{"char":"󰆉","code":"f0189"},"md-compare":{"char":"󰆊","code":"f018a"},"md-compare_horizontal":{"char":"󱒒","code":"f1492"},"md-compare_remove":{"char":"󱢳","code":"f18b3"},"md-compare_vertical":{"char":"󱒓","code":"f1493"},"md-compass":{"char":"󰆋","code":"f018b"},"md-compass_off":{"char":"󰮀","code":"f0b80"},"md-compass_off_outline":{"char":"󰮁","code":"f0b81"},"md-compass_outline":{"char":"󰆌","code":"f018c"},"md-compass_rose":{"char":"󱎂","code":"f1382"},"md-compost":{"char":"󱨸","code":"f1a38"},"md-cone":{"char":"󱥌","code":"f194c"},"md-cone_off":{"char":"󱥍","code":"f194d"},"md-connection":{"char":"󱘖","code":"f1616"},"md-console":{"char":"󰆍","code":"f018d"},"md-console_line":{"char":"󰞷","code":"f07b7"},"md-console_network":{"char":"󰢩","code":"f08a9"},"md-console_network_outline":{"char":"󰱠","code":"f0c60"},"md-consolidate":{"char":"󱃘","code":"f10d8"},"md-contactless_payment":{"char":"󰵪","code":"f0d6a"},"md-contactless_payment_circle":{"char":"󰌡","code":"f0321"},"md-contactless_payment_circle_outline":{"char":"󰐈","code":"f0408"},"md-contacts":{"char":"󰛋","code":"f06cb"},"md-contacts_outline":{"char":"󰖸","code":"f05b8"},"md-contain":{"char":"󰨾","code":"f0a3e"},"md-contain_end":{"char":"󰨿","code":"f0a3f"},"md-contain_start":{"char":"󰩀","code":"f0a40"},"md-content_copy":{"char":"󰆏","code":"f018f"},"md-content_cut":{"char":"󰆐","code":"f0190"},"md-content_duplicate":{"char":"󰆑","code":"f0191"},"md-content_paste":{"char":"󰆒","code":"f0192"},"md-content_save":{"char":"󰆓","code":"f0193"},"md-content_save_alert":{"char":"󰽂","code":"f0f42"},"md-content_save_alert_outline":{"char":"󰽃","code":"f0f43"},"md-content_save_all":{"char":"󰆔","code":"f0194"},"md-content_save_all_outline":{"char":"󰽄","code":"f0f44"},"md-content_save_check":{"char":"󱣪","code":"f18ea"},"md-content_save_check_outline":{"char":"󱣫","code":"f18eb"},"md-content_save_cog":{"char":"󱑛","code":"f145b"},"md-content_save_cog_outline":{"char":"󱑜","code":"f145c"},"md-content_save_edit":{"char":"󰳻","code":"f0cfb"},"md-content_save_edit_outline":{"char":"󰳼","code":"f0cfc"},"md-content_save_move":{"char":"󰸧","code":"f0e27"},"md-content_save_move_outline":{"char":"󰸨","code":"f0e28"},"md-content_save_off":{"char":"󱙃","code":"f1643"},"md-content_save_off_outline":{"char":"󱙄","code":"f1644"},"md-content_save_outline":{"char":"󰠘","code":"f0818"},"md-content_save_settings":{"char":"󰘛","code":"f061b"},"md-content_save_settings_outline":{"char":"󰬮","code":"f0b2e"},"md-contrast":{"char":"󰆕","code":"f0195"},"md-contrast_box":{"char":"󰆖","code":"f0196"},"md-contrast_circle":{"char":"󰆗","code":"f0197"},"md-controller_classic":{"char":"󰮂","code":"f0b82"},"md-controller_classic_outline":{"char":"󰮃","code":"f0b83"},"md-cookie":{"char":"󰆘","code":"f0198"},"md-cookie_alert":{"char":"󱛐","code":"f16d0"},"md-cookie_alert_outline":{"char":"󱛑","code":"f16d1"},"md-cookie_check":{"char":"󱛒","code":"f16d2"},"md-cookie_check_outline":{"char":"󱛓","code":"f16d3"},"md-cookie_clock":{"char":"󱛤","code":"f16e4"},"md-cookie_clock_outline":{"char":"󱛥","code":"f16e5"},"md-cookie_cog":{"char":"󱛔","code":"f16d4"},"md-cookie_cog_outline":{"char":"󱛕","code":"f16d5"},"md-cookie_edit":{"char":"󱛦","code":"f16e6"},"md-cookie_edit_outline":{"char":"󱛧","code":"f16e7"},"md-cookie_lock":{"char":"󱛨","code":"f16e8"},"md-cookie_lock_outline":{"char":"󱛩","code":"f16e9"},"md-cookie_minus":{"char":"󱛚","code":"f16da"},"md-cookie_minus_outline":{"char":"󱛛","code":"f16db"},"md-cookie_off":{"char":"󱛪","code":"f16ea"},"md-cookie_off_outline":{"char":"󱛫","code":"f16eb"},"md-cookie_outline":{"char":"󱛞","code":"f16de"},"md-cookie_plus":{"char":"󱛖","code":"f16d6"},"md-cookie_plus_outline":{"char":"󱛗","code":"f16d7"},"md-cookie_refresh":{"char":"󱛬","code":"f16ec"},"md-cookie_refresh_outline":{"char":"󱛭","code":"f16ed"},"md-cookie_remove":{"char":"󱛘","code":"f16d8"},"md-cookie_remove_outline":{"char":"󱛙","code":"f16d9"},"md-cookie_settings":{"char":"󱛜","code":"f16dc"},"md-cookie_settings_outline":{"char":"󱛝","code":"f16dd"},"md-coolant_temperature":{"char":"󰏈","code":"f03c8"},"md-copyleft":{"char":"󱤹","code":"f1939"},"md-copyright":{"char":"󰗦","code":"f05e6"},"md-cordova":{"char":"󰥘","code":"f0958"},"md-corn":{"char":"󰞸","code":"f07b8"},"md-corn_off":{"char":"󱏯","code":"f13ef"},"md-cosine_wave":{"char":"󱑹","code":"f1479"},"md-counter":{"char":"󰆙","code":"f0199"},"md-countertop":{"char":"󱠜","code":"f181c"},"md-countertop_outline":{"char":"󱠝","code":"f181d"},"md-cow":{"char":"󰆚","code":"f019a"},"md-cow_off":{"char":"󱣼","code":"f18fc"},"md-cpu_32_bit":{"char":"󰻟","code":"f0edf"},"md-cpu_64_bit":{"char":"󰻠","code":"f0ee0"},"md-cradle":{"char":"󱦋","code":"f198b"},"md-cradle_outline":{"char":"󱦑","code":"f1991"},"md-crane":{"char":"󰡢","code":"f0862"},"md-creation":{"char":"󰙴","code":"f0674"},"md-creative_commons":{"char":"󰵫","code":"f0d6b"},"md-credit_card":{"char":"󰿯","code":"f0fef"},"md-credit_card_check":{"char":"󱏐","code":"f13d0"},"md-credit_card_check_outline":{"char":"󱏑","code":"f13d1"},"md-credit_card_chip":{"char":"󱤏","code":"f190f"},"md-credit_card_chip_outline":{"char":"󱤐","code":"f1910"},"md-credit_card_clock":{"char":"󰻡","code":"f0ee1"},"md-credit_card_clock_outline":{"char":"󰻢","code":"f0ee2"},"md-credit_card_edit":{"char":"󱟗","code":"f17d7"},"md-credit_card_edit_outline":{"char":"󱟘","code":"f17d8"},"md-credit_card_fast":{"char":"󱤑","code":"f1911"},"md-credit_card_fast_outline":{"char":"󱤒","code":"f1912"},"md-credit_card_lock":{"char":"󱣧","code":"f18e7"},"md-credit_card_lock_outline":{"char":"󱣨","code":"f18e8"},"md-credit_card_marker":{"char":"󰚨","code":"f06a8"},"md-credit_card_marker_outline":{"char":"󰶾","code":"f0dbe"},"md-credit_card_minus":{"char":"󰾬","code":"f0fac"},"md-credit_card_minus_outline":{"char":"󰾭","code":"f0fad"},"md-credit_card_multiple":{"char":"󰿰","code":"f0ff0"},"md-credit_card_multiple_outline":{"char":"󰆜","code":"f019c"},"md-credit_card_off":{"char":"󰿱","code":"f0ff1"},"md-credit_card_off_outline":{"char":"󰗤","code":"f05e4"},"md-credit_card_outline":{"char":"󰆛","code":"f019b"},"md-credit_card_plus":{"char":"󰿲","code":"f0ff2"},"md-credit_card_plus_outline":{"char":"󰙶","code":"f0676"},"md-credit_card_refresh":{"char":"󱙅","code":"f1645"},"md-credit_card_refresh_outline":{"char":"󱙆","code":"f1646"},"md-credit_card_refund":{"char":"󰿳","code":"f0ff3"},"md-credit_card_refund_outline":{"char":"󰪨","code":"f0aa8"},"md-credit_card_remove":{"char":"󰾮","code":"f0fae"},"md-credit_card_remove_outline":{"char":"󰾯","code":"f0faf"},"md-credit_card_scan":{"char":"󰿴","code":"f0ff4"},"md-credit_card_scan_outline":{"char":"󰆝","code":"f019d"},"md-credit_card_search":{"char":"󱙇","code":"f1647"},"md-credit_card_search_outline":{"char":"󱙈","code":"f1648"},"md-credit_card_settings":{"char":"󰿵","code":"f0ff5"},"md-credit_card_settings_outline":{"char":"󰣗","code":"f08d7"},"md-credit_card_sync":{"char":"󱙉","code":"f1649"},"md-credit_card_sync_outline":{"char":"󱙊","code":"f164a"},"md-credit_card_wireless":{"char":"󰠂","code":"f0802"},"md-credit_card_wireless_off":{"char":"󰕺","code":"f057a"},"md-credit_card_wireless_off_outline":{"char":"󰕻","code":"f057b"},"md-credit_card_wireless_outline":{"char":"󰵬","code":"f0d6c"},"md-cricket":{"char":"󰵭","code":"f0d6d"},"md-crop":{"char":"󰆞","code":"f019e"},"md-crop_free":{"char":"󰆟","code":"f019f"},"md-crop_landscape":{"char":"󰆠","code":"f01a0"},"md-crop_portrait":{"char":"󰆡","code":"f01a1"},"md-crop_rotate":{"char":"󰚖","code":"f0696"},"md-crop_square":{"char":"󰆢","code":"f01a2"},"md-cross":{"char":"󰥓","code":"f0953"},"md-cross_bolnisi":{"char":"󰳭","code":"f0ced"},"md-cross_celtic":{"char":"󰳵","code":"f0cf5"},"md-cross_outline":{"char":"󰳶","code":"f0cf6"},"md-crosshairs":{"char":"󰆣","code":"f01a3"},"md-crosshairs_gps":{"char":"󰆤","code":"f01a4"},"md-crosshairs_off":{"char":"󰽅","code":"f0f45"},"md-crosshairs_question":{"char":"󱄶","code":"f1136"},"md-crowd":{"char":"󱥵","code":"f1975"},"md-crown":{"char":"󰆥","code":"f01a5"},"md-crown_circle":{"char":"󱟜","code":"f17dc"},"md-crown_circle_outline":{"char":"󱟝","code":"f17dd"},"md-crown_outline":{"char":"󱇐","code":"f11d0"},"md-cryengine":{"char":"󰥙","code":"f0959"},"md-crystal_ball":{"char":"󰬯","code":"f0b2f"},"md-cube":{"char":"󰆦","code":"f01a6"},"md-cube_off":{"char":"󱐜","code":"f141c"},"md-cube_off_outline":{"char":"󱐝","code":"f141d"},"md-cube_outline":{"char":"󰆧","code":"f01a7"},"md-cube_scan":{"char":"󰮄","code":"f0b84"},"md-cube_send":{"char":"󰆨","code":"f01a8"},"md-cube_unfolded":{"char":"󰆩","code":"f01a9"},"md-cup":{"char":"󰆪","code":"f01aa"},"md-cup_off":{"char":"󰗥","code":"f05e5"},"md-cup_off_outline":{"char":"󱍽","code":"f137d"},"md-cup_outline":{"char":"󱌏","code":"f130f"},"md-cup_water":{"char":"󰆫","code":"f01ab"},"md-cupboard":{"char":"󰽆","code":"f0f46"},"md-cupboard_outline":{"char":"󰽇","code":"f0f47"},"md-cupcake":{"char":"󰥚","code":"f095a"},"md-curling":{"char":"󰡣","code":"f0863"},"md-currency_bdt":{"char":"󰡤","code":"f0864"},"md-currency_brl":{"char":"󰮅","code":"f0b85"},"md-currency_btc":{"char":"󰆬","code":"f01ac"},"md-currency_cny":{"char":"󰞺","code":"f07ba"},"md-currency_eth":{"char":"󰞻","code":"f07bb"},"md-currency_eur":{"char":"󰆭","code":"f01ad"},"md-currency_eur_off":{"char":"󱌕","code":"f1315"},"md-currency_fra":{"char":"󱨹","code":"f1a39"},"md-currency_gbp":{"char":"󰆮","code":"f01ae"},"md-currency_ils":{"char":"󰱡","code":"f0c61"},"md-currency_inr":{"char":"󰆯","code":"f01af"},"md-currency_jpy":{"char":"󰞼","code":"f07bc"},"md-currency_krw":{"char":"󰞽","code":"f07bd"},"md-currency_kzt":{"char":"󰡥","code":"f0865"},"md-currency_mnt":{"char":"󱔒","code":"f1512"},"md-currency_ngn":{"char":"󰆰","code":"f01b0"},"md-currency_php":{"char":"󰧦","code":"f09e6"},"md-currency_rial":{"char":"󰺜","code":"f0e9c"},"md-currency_rub":{"char":"󰆱","code":"f01b1"},"md-currency_rupee":{"char":"󱥶","code":"f1976"},"md-currency_sign":{"char":"󰞾","code":"f07be"},"md-currency_try":{"char":"󰆲","code":"f01b2"},"md-currency_twd":{"char":"󰞿","code":"f07bf"},"md-currency_usd":{"char":"󰇁","code":"f01c1"},"md-currency_usd_off":{"char":"󰙺","code":"f067a"},"md-current_ac":{"char":"󱒀","code":"f1480"},"md-current_dc":{"char":"󰥜","code":"f095c"},"md-cursor_default":{"char":"󰇀","code":"f01c0"},"md-cursor_default_click":{"char":"󰳽","code":"f0cfd"},"md-cursor_default_click_outline":{"char":"󰳾","code":"f0cfe"},"md-cursor_default_gesture":{"char":"󱄧","code":"f1127"},"md-cursor_default_gesture_outline":{"char":"󱄨","code":"f1128"},"md-cursor_default_outline":{"char":"󰆿","code":"f01bf"},"md-cursor_move":{"char":"󰆾","code":"f01be"},"md-cursor_pointer":{"char":"󰆽","code":"f01bd"},"md-cursor_text":{"char":"󰗧","code":"f05e7"},"md-curtains":{"char":"󱡆","code":"f1846"},"md-curtains_closed":{"char":"󱡇","code":"f1847"},"md-cylinder":{"char":"󱥎","code":"f194e"},"md-cylinder_off":{"char":"󱥏","code":"f194f"},"md-dance_ballroom":{"char":"󱗻","code":"f15fb"},"md-dance_pole":{"char":"󱕸","code":"f1578"},"md-data_matrix":{"char":"󱔼","code":"f153c"},"md-data_matrix_edit":{"char":"󱔽","code":"f153d"},"md-data_matrix_minus":{"char":"󱔾","code":"f153e"},"md-data_matrix_plus":{"char":"󱔿","code":"f153f"},"md-data_matrix_remove":{"char":"󱕀","code":"f1540"},"md-data_matrix_scan":{"char":"󱕁","code":"f1541"},"md-database":{"char":"󰆼","code":"f01bc"},"md-database_alert":{"char":"󱘺","code":"f163a"},"md-database_alert_outline":{"char":"󱘤","code":"f1624"},"md-database_arrow_down":{"char":"󱘻","code":"f163b"},"md-database_arrow_down_outline":{"char":"󱘥","code":"f1625"},"md-database_arrow_left":{"char":"󱘼","code":"f163c"},"md-database_arrow_left_outline":{"char":"󱘦","code":"f1626"},"md-database_arrow_right":{"char":"󱘽","code":"f163d"},"md-database_arrow_right_outline":{"char":"󱘧","code":"f1627"},"md-database_arrow_up":{"char":"󱘾","code":"f163e"},"md-database_arrow_up_outline":{"char":"󱘨","code":"f1628"},"md-database_check":{"char":"󰪩","code":"f0aa9"},"md-database_check_outline":{"char":"󱘩","code":"f1629"},"md-database_clock":{"char":"󱘿","code":"f163f"},"md-database_clock_outline":{"char":"󱘪","code":"f162a"},"md-database_cog":{"char":"󱙋","code":"f164b"},"md-database_cog_outline":{"char":"󱙌","code":"f164c"},"md-database_edit":{"char":"󰮆","code":"f0b86"},"md-database_edit_outline":{"char":"󱘫","code":"f162b"},"md-database_export":{"char":"󰥞","code":"f095e"},"md-database_export_outline":{"char":"󱘬","code":"f162c"},"md-database_eye":{"char":"󱤟","code":"f191f"},"md-database_eye_off":{"char":"󱤠","code":"f1920"},"md-database_eye_off_outline":{"char":"󱤡","code":"f1921"},"md-database_eye_outline":{"char":"󱤢","code":"f1922"},"md-database_import":{"char":"󰥝","code":"f095d"},"md-database_import_outline":{"char":"󱘭","code":"f162d"},"md-database_lock":{"char":"󰪪","code":"f0aaa"},"md-database_lock_outline":{"char":"󱘮","code":"f162e"},"md-database_marker":{"char":"󱋶","code":"f12f6"},"md-database_marker_outline":{"char":"󱘯","code":"f162f"},"md-database_minus":{"char":"󰆻","code":"f01bb"},"md-database_minus_outline":{"char":"󱘰","code":"f1630"},"md-database_off":{"char":"󱙀","code":"f1640"},"md-database_off_outline":{"char":"󱘱","code":"f1631"},"md-database_outline":{"char":"󱘲","code":"f1632"},"md-database_plus":{"char":"󰆺","code":"f01ba"},"md-database_plus_outline":{"char":"󱘳","code":"f1633"},"md-database_refresh":{"char":"󰗂","code":"f05c2"},"md-database_refresh_outline":{"char":"󱘴","code":"f1634"},"md-database_remove":{"char":"󰴀","code":"f0d00"},"md-database_remove_outline":{"char":"󱘵","code":"f1635"},"md-database_search":{"char":"󰡦","code":"f0866"},"md-database_search_outline":{"char":"󱘶","code":"f1636"},"md-database_settings":{"char":"󰴁","code":"f0d01"},"md-database_settings_outline":{"char":"󱘷","code":"f1637"},"md-database_sync":{"char":"󰳿","code":"f0cff"},"md-database_sync_outline":{"char":"󱘸","code":"f1638"},"md-death_star":{"char":"󰣘","code":"f08d8"},"md-death_star_variant":{"char":"󰣙","code":"f08d9"},"md-deathly_hallows":{"char":"󰮇","code":"f0b87"},"md-debian":{"char":"󰣚","code":"f08da"},"md-debug_step_into":{"char":"󰆹","code":"f01b9"},"md-debug_step_out":{"char":"󰆸","code":"f01b8"},"md-debug_step_over":{"char":"󰆷","code":"f01b7"},"md-decagram":{"char":"󰝬","code":"f076c"},"md-decagram_outline":{"char":"󰝭","code":"f076d"},"md-decimal":{"char":"󱂡","code":"f10a1"},"md-decimal_comma":{"char":"󱂢","code":"f10a2"},"md-decimal_comma_decrease":{"char":"󱂣","code":"f10a3"},"md-decimal_comma_increase":{"char":"󱂤","code":"f10a4"},"md-decimal_decrease":{"char":"󰆶","code":"f01b6"},"md-decimal_increase":{"char":"󰆵","code":"f01b5"},"md-delete":{"char":"󰆴","code":"f01b4"},"md-delete_alert":{"char":"󱂥","code":"f10a5"},"md-delete_alert_outline":{"char":"󱂦","code":"f10a6"},"md-delete_circle":{"char":"󰚃","code":"f0683"},"md-delete_circle_outline":{"char":"󰮈","code":"f0b88"},"md-delete_clock":{"char":"󱕖","code":"f1556"},"md-delete_clock_outline":{"char":"󱕗","code":"f1557"},"md-delete_empty":{"char":"󰛌","code":"f06cc"},"md-delete_empty_outline":{"char":"󰺝","code":"f0e9d"},"md-delete_forever":{"char":"󰗨","code":"f05e8"},"md-delete_forever_outline":{"char":"󰮉","code":"f0b89"},"md-delete_off":{"char":"󱂧","code":"f10a7"},"md-delete_off_outline":{"char":"󱂨","code":"f10a8"},"md-delete_outline":{"char":"󰧧","code":"f09e7"},"md-delete_restore":{"char":"󰠙","code":"f0819"},"md-delete_sweep":{"char":"󰗩","code":"f05e9"},"md-delete_sweep_outline":{"char":"󰱢","code":"f0c62"},"md-delete_variant":{"char":"󰆳","code":"f01b3"},"md-delta":{"char":"󰇂","code":"f01c2"},"md-desk":{"char":"󱈹","code":"f1239"},"md-desk_lamp":{"char":"󰥟","code":"f095f"},"md-deskphone":{"char":"󰇃","code":"f01c3"},"md-desktop_classic":{"char":"󰟀","code":"f07c0"},"md-desktop_mac":{"char":"󰇄","code":"f01c4"},"md-desktop_mac_dashboard":{"char":"󰧨","code":"f09e8"},"md-desktop_tower":{"char":"󰇅","code":"f01c5"},"md-desktop_tower_monitor":{"char":"󰪫","code":"f0aab"},"md-details":{"char":"󰇆","code":"f01c6"},"md-dev_to":{"char":"󰵮","code":"f0d6e"},"md-developer_board":{"char":"󰚗","code":"f0697"},"md-deviantart":{"char":"󰇇","code":"f01c7"},"md-devices":{"char":"󰾰","code":"f0fb0"},"md-dharmachakra":{"char":"󰥋","code":"f094b"},"md-diabetes":{"char":"󱄦","code":"f1126"},"md-dialpad":{"char":"󰘜","code":"f061c"},"md-diameter":{"char":"󰱣","code":"f0c63"},"md-diameter_outline":{"char":"󰱤","code":"f0c64"},"md-diameter_variant":{"char":"󰱥","code":"f0c65"},"md-diamond":{"char":"󰮊","code":"f0b8a"},"md-diamond_outline":{"char":"󰮋","code":"f0b8b"},"md-diamond_stone":{"char":"󰇈","code":"f01c8"},"md-dice_1":{"char":"󰇊","code":"f01ca"},"md-dice_1_outline":{"char":"󱅊","code":"f114a"},"md-dice_2":{"char":"󰇋","code":"f01cb"},"md-dice_2_outline":{"char":"󱅋","code":"f114b"},"md-dice_3":{"char":"󰇌","code":"f01cc"},"md-dice_3_outline":{"char":"󱅌","code":"f114c"},"md-dice_4":{"char":"󰇍","code":"f01cd"},"md-dice_4_outline":{"char":"󱅍","code":"f114d"},"md-dice_5":{"char":"󰇎","code":"f01ce"},"md-dice_5_outline":{"char":"󱅎","code":"f114e"},"md-dice_6":{"char":"󰇏","code":"f01cf"},"md-dice_6_outline":{"char":"󱅏","code":"f114f"},"md-dice_d10":{"char":"󱅓","code":"f1153"},"md-dice_d10_outline":{"char":"󰝯","code":"f076f"},"md-dice_d12":{"char":"󱅔","code":"f1154"},"md-dice_d12_outline":{"char":"󰡧","code":"f0867"},"md-dice_d20":{"char":"󱅕","code":"f1155"},"md-dice_d20_outline":{"char":"󰗪","code":"f05ea"},"md-dice_d4":{"char":"󱅐","code":"f1150"},"md-dice_d4_outline":{"char":"󰗫","code":"f05eb"},"md-dice_d6":{"char":"󱅑","code":"f1151"},"md-dice_d6_outline":{"char":"󰗭","code":"f05ed"},"md-dice_d8":{"char":"󱅒","code":"f1152"},"md-dice_d8_outline":{"char":"󰗬","code":"f05ec"},"md-dice_multiple":{"char":"󰝮","code":"f076e"},"md-dice_multiple_outline":{"char":"󱅖","code":"f1156"},"md-digital_ocean":{"char":"󱈷","code":"f1237"},"md-dip_switch":{"char":"󰟁","code":"f07c1"},"md-directions":{"char":"󰇐","code":"f01d0"},"md-directions_fork":{"char":"󰙁","code":"f0641"},"md-disc":{"char":"󰗮","code":"f05ee"},"md-disc_alert":{"char":"󰇑","code":"f01d1"},"md-disc_player":{"char":"󰥠","code":"f0960"},"md-discord":{"char":"󰙯","code":"f066f"},"md-dishwasher":{"char":"󰪬","code":"f0aac"},"md-dishwasher_alert":{"char":"󱆸","code":"f11b8"},"md-dishwasher_off":{"char":"󱆹","code":"f11b9"},"md-disqus":{"char":"󰇒","code":"f01d2"},"md-distribute_horizontal_center":{"char":"󱇉","code":"f11c9"},"md-distribute_horizontal_left":{"char":"󱇈","code":"f11c8"},"md-distribute_horizontal_right":{"char":"󱇊","code":"f11ca"},"md-distribute_vertical_bottom":{"char":"󱇋","code":"f11cb"},"md-distribute_vertical_center":{"char":"󱇌","code":"f11cc"},"md-distribute_vertical_top":{"char":"󱇍","code":"f11cd"},"md-diversify":{"char":"󱡷","code":"f1877"},"md-diving":{"char":"󱥷","code":"f1977"},"md-diving_flippers":{"char":"󰶿","code":"f0dbf"},"md-diving_helmet":{"char":"󰷀","code":"f0dc0"},"md-diving_scuba":{"char":"󰷁","code":"f0dc1"},"md-diving_scuba_flag":{"char":"󰷂","code":"f0dc2"},"md-diving_scuba_tank":{"char":"󰷃","code":"f0dc3"},"md-diving_scuba_tank_multiple":{"char":"󰷄","code":"f0dc4"},"md-diving_snorkel":{"char":"󰷅","code":"f0dc5"},"md-division":{"char":"󰇔","code":"f01d4"},"md-division_box":{"char":"󰇕","code":"f01d5"},"md-dlna":{"char":"󰩁","code":"f0a41"},"md-dna":{"char":"󰚄","code":"f0684"},"md-dns":{"char":"󰇖","code":"f01d6"},"md-dns_outline":{"char":"󰮌","code":"f0b8c"},"md-dock_bottom":{"char":"󱂩","code":"f10a9"},"md-dock_left":{"char":"󱂪","code":"f10aa"},"md-dock_right":{"char":"󱂫","code":"f10ab"},"md-dock_top":{"char":"󱔓","code":"f1513"},"md-dock_window":{"char":"󱂬","code":"f10ac"},"md-docker":{"char":"󰡨","code":"f0868"},"md-doctor":{"char":"󰩂","code":"f0a42"},"md-dog":{"char":"󰩃","code":"f0a43"},"md-dog_service":{"char":"󰪭","code":"f0aad"},"md-dog_side":{"char":"󰩄","code":"f0a44"},"md-dog_side_off":{"char":"󱛮","code":"f16ee"},"md-dolby":{"char":"󰚳","code":"f06b3"},"md-dolly":{"char":"󰺞","code":"f0e9e"},"md-dolphin":{"char":"󱢴","code":"f18b4"},"md-domain":{"char":"󰇗","code":"f01d7"},"md-domain_off":{"char":"󰵯","code":"f0d6f"},"md-domain_plus":{"char":"󱂭","code":"f10ad"},"md-domain_remove":{"char":"󱂮","code":"f10ae"},"md-dome_light":{"char":"󱐞","code":"f141e"},"md-domino_mask":{"char":"󱀣","code":"f1023"},"md-donkey":{"char":"󰟂","code":"f07c2"},"md-door":{"char":"󰠚","code":"f081a"},"md-door_closed":{"char":"󰠛","code":"f081b"},"md-door_closed_lock":{"char":"󱂯","code":"f10af"},"md-door_open":{"char":"󰠜","code":"f081c"},"md-door_sliding":{"char":"󱠞","code":"f181e"},"md-door_sliding_lock":{"char":"󱠟","code":"f181f"},"md-door_sliding_open":{"char":"󱠠","code":"f1820"},"md-doorbell":{"char":"󱋦","code":"f12e6"},"md-doorbell_video":{"char":"󰡩","code":"f0869"},"md-dot_net":{"char":"󰪮","code":"f0aae"},"md-dots_circle":{"char":"󱥸","code":"f1978"},"md-dots_grid":{"char":"󱗼","code":"f15fc"},"md-dots_hexagon":{"char":"󱗿","code":"f15ff"},"md-dots_horizontal":{"char":"󰇘","code":"f01d8"},"md-dots_horizontal_circle":{"char":"󰟃","code":"f07c3"},"md-dots_horizontal_circle_outline":{"char":"󰮍","code":"f0b8d"},"md-dots_square":{"char":"󱗽","code":"f15fd"},"md-dots_triangle":{"char":"󱗾","code":"f15fe"},"md-dots_vertical":{"char":"󰇙","code":"f01d9"},"md-dots_vertical_circle":{"char":"󰟄","code":"f07c4"},"md-dots_vertical_circle_outline":{"char":"󰮎","code":"f0b8e"},"md-download":{"char":"󰇚","code":"f01da"},"md-download_box":{"char":"󱑢","code":"f1462"},"md-download_box_outline":{"char":"󱑣","code":"f1463"},"md-download_circle":{"char":"󱑤","code":"f1464"},"md-download_circle_outline":{"char":"󱑥","code":"f1465"},"md-download_lock":{"char":"󱌠","code":"f1320"},"md-download_lock_outline":{"char":"󱌡","code":"f1321"},"md-download_multiple":{"char":"󰧩","code":"f09e9"},"md-download_network":{"char":"󰛴","code":"f06f4"},"md-download_network_outline":{"char":"󰱦","code":"f0c66"},"md-download_off":{"char":"󱂰","code":"f10b0"},"md-download_off_outline":{"char":"󱂱","code":"f10b1"},"md-download_outline":{"char":"󰮏","code":"f0b8f"},"md-drag":{"char":"󰇛","code":"f01db"},"md-drag_horizontal":{"char":"󰇜","code":"f01dc"},"md-drag_horizontal_variant":{"char":"󱋰","code":"f12f0"},"md-drag_variant":{"char":"󰮐","code":"f0b90"},"md-drag_vertical":{"char":"󰇝","code":"f01dd"},"md-drag_vertical_variant":{"char":"󱋱","code":"f12f1"},"md-drama_masks":{"char":"󰴂","code":"f0d02"},"md-draw":{"char":"󰽉","code":"f0f49"},"md-draw_pen":{"char":"󱦹","code":"f19b9"},"md-drawing":{"char":"󰇞","code":"f01de"},"md-drawing_box":{"char":"󰇟","code":"f01df"},"md-dresser":{"char":"󰽊","code":"f0f4a"},"md-dresser_outline":{"char":"󰽋","code":"f0f4b"},"md-drone":{"char":"󰇢","code":"f01e2"},"md-dropbox":{"char":"󰇣","code":"f01e3"},"md-drupal":{"char":"󰇤","code":"f01e4"},"md-duck":{"char":"󰇥","code":"f01e5"},"md-dumbbell":{"char":"󰇦","code":"f01e6"},"md-dump_truck":{"char":"󰱧","code":"f0c67"},"md-ear_hearing":{"char":"󰟅","code":"f07c5"},"md-ear_hearing_loop":{"char":"󱫮","code":"f1aee"},"md-ear_hearing_off":{"char":"󰩅","code":"f0a45"},"md-earbuds":{"char":"󱡏","code":"f184f"},"md-earbuds_off":{"char":"󱡐","code":"f1850"},"md-earbuds_off_outline":{"char":"󱡑","code":"f1851"},"md-earbuds_outline":{"char":"󱡒","code":"f1852"},"md-earth":{"char":"󰇧","code":"f01e7"},"md-earth_arrow_right":{"char":"󱌑","code":"f1311"},"md-earth_box":{"char":"󰛍","code":"f06cd"},"md-earth_box_minus":{"char":"󱐇","code":"f1407"},"md-earth_box_off":{"char":"󰛎","code":"f06ce"},"md-earth_box_plus":{"char":"󱐆","code":"f1406"},"md-earth_box_remove":{"char":"󱐈","code":"f1408"},"md-earth_minus":{"char":"󱐄","code":"f1404"},"md-earth_off":{"char":"󰇨","code":"f01e8"},"md-earth_plus":{"char":"󱐃","code":"f1403"},"md-earth_remove":{"char":"󱐅","code":"f1405"},"md-egg":{"char":"󰪯","code":"f0aaf"},"md-egg_easter":{"char":"󰪰","code":"f0ab0"},"md-egg_fried":{"char":"󱡊","code":"f184a"},"md-egg_off":{"char":"󱏰","code":"f13f0"},"md-egg_off_outline":{"char":"󱏱","code":"f13f1"},"md-egg_outline":{"char":"󱏲","code":"f13f2"},"md-eiffel_tower":{"char":"󱕫","code":"f156b"},"md-eight_track":{"char":"󰧪","code":"f09ea"},"md-eject":{"char":"󰇪","code":"f01ea"},"md-eject_outline":{"char":"󰮑","code":"f0b91"},"md-electric_switch":{"char":"󰺟","code":"f0e9f"},"md-electric_switch_closed":{"char":"󱃙","code":"f10d9"},"md-electron_framework":{"char":"󱀤","code":"f1024"},"md-elephant":{"char":"󰟆","code":"f07c6"},"md-elevation_decline":{"char":"󰇫","code":"f01eb"},"md-elevation_rise":{"char":"󰇬","code":"f01ec"},"md-elevator":{"char":"󰇭","code":"f01ed"},"md-elevator_down":{"char":"󱋂","code":"f12c2"},"md-elevator_passenger":{"char":"󱎁","code":"f1381"},"md-elevator_passenger_off":{"char":"󱥹","code":"f1979"},"md-elevator_passenger_off_outline":{"char":"󱥺","code":"f197a"},"md-elevator_passenger_outline":{"char":"󱥻","code":"f197b"},"md-elevator_up":{"char":"󱋁","code":"f12c1"},"md-ellipse":{"char":"󰺠","code":"f0ea0"},"md-ellipse_outline":{"char":"󰺡","code":"f0ea1"},"md-email":{"char":"󰇮","code":"f01ee"},"md-email_alert":{"char":"󰛏","code":"f06cf"},"md-email_alert_outline":{"char":"󰵂","code":"f0d42"},"md-email_box":{"char":"󰴃","code":"f0d03"},"md-email_check":{"char":"󰪱","code":"f0ab1"},"md-email_check_outline":{"char":"󰪲","code":"f0ab2"},"md-email_edit":{"char":"󰻣","code":"f0ee3"},"md-email_edit_outline":{"char":"󰻤","code":"f0ee4"},"md-email_fast":{"char":"󱡯","code":"f186f"},"md-email_fast_outline":{"char":"󱡰","code":"f1870"},"md-email_lock":{"char":"󰇱","code":"f01f1"},"md-email_mark_as_unread":{"char":"󰮒","code":"f0b92"},"md-email_minus":{"char":"󰻥","code":"f0ee5"},"md-email_minus_outline":{"char":"󰻦","code":"f0ee6"},"md-email_multiple":{"char":"󰻧","code":"f0ee7"},"md-email_multiple_outline":{"char":"󰻨","code":"f0ee8"},"md-email_newsletter":{"char":"󰾱","code":"f0fb1"},"md-email_off":{"char":"󱏣","code":"f13e3"},"md-email_off_outline":{"char":"󱏤","code":"f13e4"},"md-email_open":{"char":"󰇯","code":"f01ef"},"md-email_open_multiple":{"char":"󰻩","code":"f0ee9"},"md-email_open_multiple_outline":{"char":"󰻪","code":"f0eea"},"md-email_open_outline":{"char":"󰗯","code":"f05ef"},"md-email_outline":{"char":"󰇰","code":"f01f0"},"md-email_plus":{"char":"󰧫","code":"f09eb"},"md-email_plus_outline":{"char":"󰧬","code":"f09ec"},"md-email_receive":{"char":"󱃚","code":"f10da"},"md-email_receive_outline":{"char":"󱃛","code":"f10db"},"md-email_remove":{"char":"󱙡","code":"f1661"},"md-email_remove_outline":{"char":"󱙢","code":"f1662"},"md-email_seal":{"char":"󱥛","code":"f195b"},"md-email_seal_outline":{"char":"󱥜","code":"f195c"},"md-email_search":{"char":"󰥡","code":"f0961"},"md-email_search_outline":{"char":"󰥢","code":"f0962"},"md-email_send":{"char":"󱃜","code":"f10dc"},"md-email_send_outline":{"char":"󱃝","code":"f10dd"},"md-email_sync":{"char":"󱋇","code":"f12c7"},"md-email_sync_outline":{"char":"󱋈","code":"f12c8"},"md-email_variant":{"char":"󰗰","code":"f05f0"},"md-ember":{"char":"󰬰","code":"f0b30"},"md-emby":{"char":"󰚴","code":"f06b4"},"md-emoticon":{"char":"󰱨","code":"f0c68"},"md-emoticon_angry":{"char":"󰱩","code":"f0c69"},"md-emoticon_angry_outline":{"char":"󰱪","code":"f0c6a"},"md-emoticon_confused":{"char":"󱃞","code":"f10de"},"md-emoticon_confused_outline":{"char":"󱃟","code":"f10df"},"md-emoticon_cool":{"char":"󰱫","code":"f0c6b"},"md-emoticon_cool_outline":{"char":"󰇳","code":"f01f3"},"md-emoticon_cry":{"char":"󰱬","code":"f0c6c"},"md-emoticon_cry_outline":{"char":"󰱭","code":"f0c6d"},"md-emoticon_dead":{"char":"󰱮","code":"f0c6e"},"md-emoticon_dead_outline":{"char":"󰚛","code":"f069b"},"md-emoticon_devil":{"char":"󰱯","code":"f0c6f"},"md-emoticon_devil_outline":{"char":"󰇴","code":"f01f4"},"md-emoticon_excited":{"char":"󰱰","code":"f0c70"},"md-emoticon_excited_outline":{"char":"󰚜","code":"f069c"},"md-emoticon_frown":{"char":"󰽌","code":"f0f4c"},"md-emoticon_frown_outline":{"char":"󰽍","code":"f0f4d"},"md-emoticon_happy":{"char":"󰱱","code":"f0c71"},"md-emoticon_happy_outline":{"char":"󰇵","code":"f01f5"},"md-emoticon_kiss":{"char":"󰱲","code":"f0c72"},"md-emoticon_kiss_outline":{"char":"󰱳","code":"f0c73"},"md-emoticon_lol":{"char":"󱈔","code":"f1214"},"md-emoticon_lol_outline":{"char":"󱈕","code":"f1215"},"md-emoticon_neutral":{"char":"󰱴","code":"f0c74"},"md-emoticon_neutral_outline":{"char":"󰇶","code":"f01f6"},"md-emoticon_outline":{"char":"󰇲","code":"f01f2"},"md-emoticon_poop":{"char":"󰇷","code":"f01f7"},"md-emoticon_poop_outline":{"char":"󰱵","code":"f0c75"},"md-emoticon_sad":{"char":"󰱶","code":"f0c76"},"md-emoticon_sad_outline":{"char":"󰇸","code":"f01f8"},"md-emoticon_sick":{"char":"󱕼","code":"f157c"},"md-emoticon_sick_outline":{"char":"󱕽","code":"f157d"},"md-emoticon_tongue":{"char":"󰇹","code":"f01f9"},"md-emoticon_tongue_outline":{"char":"󰱷","code":"f0c77"},"md-emoticon_wink":{"char":"󰱸","code":"f0c78"},"md-emoticon_wink_outline":{"char":"󰱹","code":"f0c79"},"md-engine":{"char":"󰇺","code":"f01fa"},"md-engine_off":{"char":"󰩆","code":"f0a46"},"md-engine_off_outline":{"char":"󰩇","code":"f0a47"},"md-engine_outline":{"char":"󰇻","code":"f01fb"},"md-epsilon":{"char":"󱃠","code":"f10e0"},"md-equal":{"char":"󰇼","code":"f01fc"},"md-equal_box":{"char":"󰇽","code":"f01fd"},"md-equalizer":{"char":"󰺢","code":"f0ea2"},"md-equalizer_outline":{"char":"󰺣","code":"f0ea3"},"md-eraser":{"char":"󰇾","code":"f01fe"},"md-eraser_variant":{"char":"󰙂","code":"f0642"},"md-escalator":{"char":"󰇿","code":"f01ff"},"md-escalator_box":{"char":"󱎙","code":"f1399"},"md-escalator_down":{"char":"󱋀","code":"f12c0"},"md-escalator_up":{"char":"󱊿","code":"f12bf"},"md-eslint":{"char":"󰱺","code":"f0c7a"},"md-et":{"char":"󰪳","code":"f0ab3"},"md-ethereum":{"char":"󰡪","code":"f086a"},"md-ethernet":{"char":"󰈀","code":"f0200"},"md-ethernet_cable":{"char":"󰈁","code":"f0201"},"md-ethernet_cable_off":{"char":"󰈂","code":"f0202"},"md-ev_plug_ccs1":{"char":"󱔙","code":"f1519"},"md-ev_plug_ccs2":{"char":"󱔚","code":"f151a"},"md-ev_plug_chademo":{"char":"󱔛","code":"f151b"},"md-ev_plug_tesla":{"char":"󱔜","code":"f151c"},"md-ev_plug_type1":{"char":"󱔝","code":"f151d"},"md-ev_plug_type2":{"char":"󱔞","code":"f151e"},"md-ev_station":{"char":"󰗱","code":"f05f1"},"md-evernote":{"char":"󰈄","code":"f0204"},"md-excavator":{"char":"󱀥","code":"f1025"},"md-exclamation":{"char":"󰈅","code":"f0205"},"md-exclamation_thick":{"char":"󱈸","code":"f1238"},"md-exit_run":{"char":"󰩈","code":"f0a48"},"md-exit_to_app":{"char":"󰈆","code":"f0206"},"md-expand_all":{"char":"󰪴","code":"f0ab4"},"md-expand_all_outline":{"char":"󰪵","code":"f0ab5"},"md-expansion_card":{"char":"󰢮","code":"f08ae"},"md-expansion_card_variant":{"char":"󰾲","code":"f0fb2"},"md-exponent":{"char":"󰥣","code":"f0963"},"md-exponent_box":{"char":"󰥤","code":"f0964"},"md-export":{"char":"󰈇","code":"f0207"},"md-export_variant":{"char":"󰮓","code":"f0b93"},"md-eye":{"char":"󰈈","code":"f0208"},"md-eye_arrow_left":{"char":"󱣽","code":"f18fd"},"md-eye_arrow_left_outline":{"char":"󱣾","code":"f18fe"},"md-eye_arrow_right":{"char":"󱣿","code":"f18ff"},"md-eye_arrow_right_outline":{"char":"󱤀","code":"f1900"},"md-eye_check":{"char":"󰴄","code":"f0d04"},"md-eye_check_outline":{"char":"󰴅","code":"f0d05"},"md-eye_circle":{"char":"󰮔","code":"f0b94"},"md-eye_circle_outline":{"char":"󰮕","code":"f0b95"},"md-eye_minus":{"char":"󱀦","code":"f1026"},"md-eye_minus_outline":{"char":"󱀧","code":"f1027"},"md-eye_off":{"char":"󰈉","code":"f0209"},"md-eye_off_outline":{"char":"󰛑","code":"f06d1"},"md-eye_outline":{"char":"󰛐","code":"f06d0"},"md-eye_plus":{"char":"󰡫","code":"f086b"},"md-eye_plus_outline":{"char":"󰡬","code":"f086c"},"md-eye_refresh":{"char":"󱥼","code":"f197c"},"md-eye_refresh_outline":{"char":"󱥽","code":"f197d"},"md-eye_remove":{"char":"󱗣","code":"f15e3"},"md-eye_remove_outline":{"char":"󱗤","code":"f15e4"},"md-eye_settings":{"char":"󰡭","code":"f086d"},"md-eye_settings_outline":{"char":"󰡮","code":"f086e"},"md-eyedropper":{"char":"󰈊","code":"f020a"},"md-eyedropper_minus":{"char":"󱏝","code":"f13dd"},"md-eyedropper_off":{"char":"󱏟","code":"f13df"},"md-eyedropper_plus":{"char":"󱏜","code":"f13dc"},"md-eyedropper_remove":{"char":"󱏞","code":"f13de"},"md-eyedropper_variant":{"char":"󰈋","code":"f020b"},"md-face_agent":{"char":"󰵰","code":"f0d70"},"md-face_man":{"char":"󰙃","code":"f0643"},"md-face_man_outline":{"char":"󰮖","code":"f0b96"},"md-face_man_profile":{"char":"󰙄","code":"f0644"},"md-face_man_shimmer":{"char":"󱗌","code":"f15cc"},"md-face_man_shimmer_outline":{"char":"󱗍","code":"f15cd"},"md-face_mask":{"char":"󱖆","code":"f1586"},"md-face_mask_outline":{"char":"󱖇","code":"f1587"},"md-face_recognition":{"char":"󰱻","code":"f0c7b"},"md-face_woman":{"char":"󱁷","code":"f1077"},"md-face_woman_outline":{"char":"󱁸","code":"f1078"},"md-face_woman_profile":{"char":"󱁶","code":"f1076"},"md-face_woman_shimmer":{"char":"󱗎","code":"f15ce"},"md-face_woman_shimmer_outline":{"char":"󱗏","code":"f15cf"},"md-facebook":{"char":"󰈌","code":"f020c"},"md-facebook_gaming":{"char":"󰟝","code":"f07dd"},"md-facebook_messenger":{"char":"󰈎","code":"f020e"},"md-facebook_workplace":{"char":"󰬱","code":"f0b31"},"md-factory":{"char":"󰈏","code":"f020f"},"md-family_tree":{"char":"󱘎","code":"f160e"},"md-fan":{"char":"󰈐","code":"f0210"},"md-fan_alert":{"char":"󱑬","code":"f146c"},"md-fan_auto":{"char":"󱜝","code":"f171d"},"md-fan_chevron_down":{"char":"󱑭","code":"f146d"},"md-fan_chevron_up":{"char":"󱑮","code":"f146e"},"md-fan_clock":{"char":"󱨺","code":"f1a3a"},"md-fan_minus":{"char":"󱑰","code":"f1470"},"md-fan_off":{"char":"󰠝","code":"f081d"},"md-fan_plus":{"char":"󱑯","code":"f146f"},"md-fan_remove":{"char":"󱑱","code":"f1471"},"md-fan_speed_1":{"char":"󱑲","code":"f1472"},"md-fan_speed_2":{"char":"󱑳","code":"f1473"},"md-fan_speed_3":{"char":"󱑴","code":"f1474"},"md-fast_forward":{"char":"󰈑","code":"f0211"},"md-fast_forward_10":{"char":"󰵱","code":"f0d71"},"md-fast_forward_15":{"char":"󱤺","code":"f193a"},"md-fast_forward_30":{"char":"󰴆","code":"f0d06"},"md-fast_forward_5":{"char":"󱇸","code":"f11f8"},"md-fast_forward_60":{"char":"󱘋","code":"f160b"},"md-fast_forward_outline":{"char":"󰛒","code":"f06d2"},"md-fax":{"char":"󰈒","code":"f0212"},"md-feather":{"char":"󰛓","code":"f06d3"},"md-feature_search":{"char":"󰩉","code":"f0a49"},"md-feature_search_outline":{"char":"󰩊","code":"f0a4a"},"md-fedora":{"char":"󰣛","code":"f08db"},"md-fence":{"char":"󱞚","code":"f179a"},"md-fence_electric":{"char":"󱟶","code":"f17f6"},"md-fencing":{"char":"󱓁","code":"f14c1"},"md-ferris_wheel":{"char":"󰺤","code":"f0ea4"},"md-ferry":{"char":"󰈓","code":"f0213"},"md-file":{"char":"󰈔","code":"f0214"},"md-file_account":{"char":"󰜻","code":"f073b"},"md-file_account_outline":{"char":"󱀨","code":"f1028"},"md-file_alert":{"char":"󰩋","code":"f0a4b"},"md-file_alert_outline":{"char":"󰩌","code":"f0a4c"},"md-file_arrow_left_right":{"char":"󱪓","code":"f1a93"},"md-file_arrow_left_right_outline":{"char":"󱪔","code":"f1a94"},"md-file_arrow_up_down":{"char":"󱪕","code":"f1a95"},"md-file_arrow_up_down_outline":{"char":"󱪖","code":"f1a96"},"md-file_cabinet":{"char":"󰪶","code":"f0ab6"},"md-file_cad":{"char":"󰻫","code":"f0eeb"},"md-file_cad_box":{"char":"󰻬","code":"f0eec"},"md-file_cancel":{"char":"󰷆","code":"f0dc6"},"md-file_cancel_outline":{"char":"󰷇","code":"f0dc7"},"md-file_certificate":{"char":"󱆆","code":"f1186"},"md-file_certificate_outline":{"char":"󱆇","code":"f1187"},"md-file_chart":{"char":"󰈕","code":"f0215"},"md-file_chart_check":{"char":"󱧆","code":"f19c6"},"md-file_chart_check_outline":{"char":"󱧇","code":"f19c7"},"md-file_chart_outline":{"char":"󱀩","code":"f1029"},"md-file_check":{"char":"󰈖","code":"f0216"},"md-file_check_outline":{"char":"󰸩","code":"f0e29"},"md-file_clock":{"char":"󱋡","code":"f12e1"},"md-file_clock_outline":{"char":"󱋢","code":"f12e2"},"md-file_cloud":{"char":"󰈗","code":"f0217"},"md-file_cloud_outline":{"char":"󱀪","code":"f102a"},"md-file_code":{"char":"󰈮","code":"f022e"},"md-file_code_outline":{"char":"󱀫","code":"f102b"},"md-file_cog":{"char":"󱁻","code":"f107b"},"md-file_cog_outline":{"char":"󱁼","code":"f107c"},"md-file_compare":{"char":"󰢪","code":"f08aa"},"md-file_delimited":{"char":"󰈘","code":"f0218"},"md-file_delimited_outline":{"char":"󰺥","code":"f0ea5"},"md-file_document":{"char":"󰈙","code":"f0219"},"md-file_document_alert":{"char":"󱪗","code":"f1a97"},"md-file_document_alert_outline":{"char":"󱪘","code":"f1a98"},"md-file_document_check":{"char":"󱪙","code":"f1a99"},"md-file_document_check_outline":{"char":"󱪚","code":"f1a9a"},"md-file_document_edit":{"char":"󰷈","code":"f0dc8"},"md-file_document_edit_outline":{"char":"󰷉","code":"f0dc9"},"md-file_document_minus":{"char":"󱪛","code":"f1a9b"},"md-file_document_minus_outline":{"char":"󱪜","code":"f1a9c"},"md-file_document_multiple":{"char":"󱔗","code":"f1517"},"md-file_document_multiple_outline":{"char":"󱔘","code":"f1518"},"md-file_document_outline":{"char":"󰧮","code":"f09ee"},"md-file_document_plus":{"char":"󱪝","code":"f1a9d"},"md-file_document_plus_outline":{"char":"󱪞","code":"f1a9e"},"md-file_document_remove":{"char":"󱪟","code":"f1a9f"},"md-file_document_remove_outline":{"char":"󱪠","code":"f1aa0"},"md-file_download":{"char":"󰥥","code":"f0965"},"md-file_download_outline":{"char":"󰥦","code":"f0966"},"md-file_edit":{"char":"󱇧","code":"f11e7"},"md-file_edit_outline":{"char":"󱇨","code":"f11e8"},"md-file_excel":{"char":"󰈛","code":"f021b"},"md-file_excel_box":{"char":"󰈜","code":"f021c"},"md-file_excel_box_outline":{"char":"󱀬","code":"f102c"},"md-file_excel_outline":{"char":"󱀭","code":"f102d"},"md-file_export":{"char":"󰈝","code":"f021d"},"md-file_export_outline":{"char":"󱀮","code":"f102e"},"md-file_eye":{"char":"󰷊","code":"f0dca"},"md-file_eye_outline":{"char":"󰷋","code":"f0dcb"},"md-file_find":{"char":"󰈞","code":"f021e"},"md-file_find_outline":{"char":"󰮗","code":"f0b97"},"md-file_gif_box":{"char":"󰵸","code":"f0d78"},"md-file_hidden":{"char":"󰘓","code":"f0613"},"md-file_image":{"char":"󰈟","code":"f021f"},"md-file_image_marker":{"char":"󱝲","code":"f1772"},"md-file_image_marker_outline":{"char":"󱝳","code":"f1773"},"md-file_image_minus":{"char":"󱤻","code":"f193b"},"md-file_image_minus_outline":{"char":"󱤼","code":"f193c"},"md-file_image_outline":{"char":"󰺰","code":"f0eb0"},"md-file_image_plus":{"char":"󱤽","code":"f193d"},"md-file_image_plus_outline":{"char":"󱤾","code":"f193e"},"md-file_image_remove":{"char":"󱤿","code":"f193f"},"md-file_image_remove_outline":{"char":"󱥀","code":"f1940"},"md-file_import":{"char":"󰈠","code":"f0220"},"md-file_import_outline":{"char":"󱀯","code":"f102f"},"md-file_jpg_box":{"char":"󰈥","code":"f0225"},"md-file_key":{"char":"󱆄","code":"f1184"},"md-file_key_outline":{"char":"󱆅","code":"f1185"},"md-file_link":{"char":"󱅷","code":"f1177"},"md-file_link_outline":{"char":"󱅸","code":"f1178"},"md-file_lock":{"char":"󰈡","code":"f0221"},"md-file_lock_open":{"char":"󱧈","code":"f19c8"},"md-file_lock_open_outline":{"char":"󱧉","code":"f19c9"},"md-file_lock_outline":{"char":"󱀰","code":"f1030"},"md-file_marker":{"char":"󱝴","code":"f1774"},"md-file_marker_outline":{"char":"󱝵","code":"f1775"},"md-file_minus":{"char":"󱪡","code":"f1aa1"},"md-file_minus_outline":{"char":"󱪢","code":"f1aa2"},"md-file_move":{"char":"󰪹","code":"f0ab9"},"md-file_move_outline":{"char":"󱀱","code":"f1031"},"md-file_multiple":{"char":"󰈢","code":"f0222"},"md-file_multiple_outline":{"char":"󱀲","code":"f1032"},"md-file_music":{"char":"󰈣","code":"f0223"},"md-file_music_outline":{"char":"󰸪","code":"f0e2a"},"md-file_outline":{"char":"󰈤","code":"f0224"},"md-file_pdf_box":{"char":"󰈦","code":"f0226"},"md-file_percent":{"char":"󰠞","code":"f081e"},"md-file_percent_outline":{"char":"󱀳","code":"f1033"},"md-file_phone":{"char":"󱅹","code":"f1179"},"md-file_phone_outline":{"char":"󱅺","code":"f117a"},"md-file_plus":{"char":"󰝒","code":"f0752"},"md-file_plus_outline":{"char":"󰻭","code":"f0eed"},"md-file_png_box":{"char":"󰸭","code":"f0e2d"},"md-file_powerpoint":{"char":"󰈧","code":"f0227"},"md-file_powerpoint_box":{"char":"󰈨","code":"f0228"},"md-file_powerpoint_box_outline":{"char":"󱀴","code":"f1034"},"md-file_powerpoint_outline":{"char":"󱀵","code":"f1035"},"md-file_presentation_box":{"char":"󰈩","code":"f0229"},"md-file_question":{"char":"󰡯","code":"f086f"},"md-file_question_outline":{"char":"󱀶","code":"f1036"},"md-file_refresh":{"char":"󰤘","code":"f0918"},"md-file_refresh_outline":{"char":"󰕁","code":"f0541"},"md-file_remove":{"char":"󰮘","code":"f0b98"},"md-file_remove_outline":{"char":"󱀷","code":"f1037"},"md-file_replace":{"char":"󰬲","code":"f0b32"},"md-file_replace_outline":{"char":"󰬳","code":"f0b33"},"md-file_restore":{"char":"󰙰","code":"f0670"},"md-file_restore_outline":{"char":"󱀸","code":"f1038"},"md-file_rotate_left":{"char":"󱨻","code":"f1a3b"},"md-file_rotate_left_outline":{"char":"󱨼","code":"f1a3c"},"md-file_rotate_right":{"char":"󱨽","code":"f1a3d"},"md-file_rotate_right_outline":{"char":"󱨾","code":"f1a3e"},"md-file_search":{"char":"󰱼","code":"f0c7c"},"md-file_search_outline":{"char":"󰱽","code":"f0c7d"},"md-file_send":{"char":"󰈪","code":"f022a"},"md-file_send_outline":{"char":"󱀹","code":"f1039"},"md-file_settings":{"char":"󱁹","code":"f1079"},"md-file_settings_outline":{"char":"󱁺","code":"f107a"},"md-file_sign":{"char":"󱧃","code":"f19c3"},"md-file_star":{"char":"󱀺","code":"f103a"},"md-file_star_outline":{"char":"󱀻","code":"f103b"},"md-file_swap":{"char":"󰾴","code":"f0fb4"},"md-file_swap_outline":{"char":"󰾵","code":"f0fb5"},"md-file_sync":{"char":"󱈖","code":"f1216"},"md-file_sync_outline":{"char":"󱈗","code":"f1217"},"md-file_table":{"char":"󰱾","code":"f0c7e"},"md-file_table_box":{"char":"󱃡","code":"f10e1"},"md-file_table_box_multiple":{"char":"󱃢","code":"f10e2"},"md-file_table_box_multiple_outline":{"char":"󱃣","code":"f10e3"},"md-file_table_box_outline":{"char":"󱃤","code":"f10e4"},"md-file_table_outline":{"char":"󰱿","code":"f0c7f"},"md-file_tree":{"char":"󰙅","code":"f0645"},"md-file_tree_outline":{"char":"󱏒","code":"f13d2"},"md-file_undo":{"char":"󰣜","code":"f08dc"},"md-file_undo_outline":{"char":"󱀼","code":"f103c"},"md-file_upload":{"char":"󰩍","code":"f0a4d"},"md-file_upload_outline":{"char":"󰩎","code":"f0a4e"},"md-file_video":{"char":"󰈫","code":"f022b"},"md-file_video_outline":{"char":"󰸬","code":"f0e2c"},"md-file_word":{"char":"󰈬","code":"f022c"},"md-file_word_box":{"char":"󰈭","code":"f022d"},"md-file_word_box_outline":{"char":"󱀽","code":"f103d"},"md-file_word_outline":{"char":"󱀾","code":"f103e"},"md-film":{"char":"󰈯","code":"f022f"},"md-filmstrip":{"char":"󰈰","code":"f0230"},"md-filmstrip_box":{"char":"󰌲","code":"f0332"},"md-filmstrip_box_multiple":{"char":"󰴘","code":"f0d18"},"md-filmstrip_off":{"char":"󰈱","code":"f0231"},"md-filter":{"char":"󰈲","code":"f0232"},"md-filter_check":{"char":"󱣬","code":"f18ec"},"md-filter_check_outline":{"char":"󱣭","code":"f18ed"},"md-filter_cog":{"char":"󱪣","code":"f1aa3"},"md-filter_cog_outline":{"char":"󱪤","code":"f1aa4"},"md-filter_menu":{"char":"󱃥","code":"f10e5"},"md-filter_menu_outline":{"char":"󱃦","code":"f10e6"},"md-filter_minus":{"char":"󰻮","code":"f0eee"},"md-filter_minus_outline":{"char":"󰻯","code":"f0eef"},"md-filter_multiple":{"char":"󱨿","code":"f1a3f"},"md-filter_multiple_outline":{"char":"󱩀","code":"f1a40"},"md-filter_off":{"char":"󱓯","code":"f14ef"},"md-filter_off_outline":{"char":"󱓰","code":"f14f0"},"md-filter_outline":{"char":"󰈳","code":"f0233"},"md-filter_plus":{"char":"󰻰","code":"f0ef0"},"md-filter_plus_outline":{"char":"󰻱","code":"f0ef1"},"md-filter_remove":{"char":"󰈴","code":"f0234"},"md-filter_remove_outline":{"char":"󰈵","code":"f0235"},"md-filter_settings":{"char":"󱪥","code":"f1aa5"},"md-filter_settings_outline":{"char":"󱪦","code":"f1aa6"},"md-filter_variant":{"char":"󰈶","code":"f0236"},"md-filter_variant_minus":{"char":"󱄒","code":"f1112"},"md-filter_variant_plus":{"char":"󱄓","code":"f1113"},"md-filter_variant_remove":{"char":"󱀿","code":"f103f"},"md-finance":{"char":"󰠟","code":"f081f"},"md-find_replace":{"char":"󰛔","code":"f06d4"},"md-fingerprint":{"char":"󰈷","code":"f0237"},"md-fingerprint_off":{"char":"󰺱","code":"f0eb1"},"md-fire":{"char":"󰈸","code":"f0238"},"md-fire_alert":{"char":"󱗗","code":"f15d7"},"md-fire_circle":{"char":"󱠇","code":"f1807"},"md-fire_extinguisher":{"char":"󰻲","code":"f0ef2"},"md-fire_hydrant":{"char":"󱄷","code":"f1137"},"md-fire_hydrant_alert":{"char":"󱄸","code":"f1138"},"md-fire_hydrant_off":{"char":"󱄹","code":"f1139"},"md-fire_off":{"char":"󱜢","code":"f1722"},"md-fire_truck":{"char":"󰢫","code":"f08ab"},"md-firebase":{"char":"󰥧","code":"f0967"},"md-firefox":{"char":"󰈹","code":"f0239"},"md-fireplace":{"char":"󰸮","code":"f0e2e"},"md-fireplace_off":{"char":"󰸯","code":"f0e2f"},"md-firewire":{"char":"󰖾","code":"f05be"},"md-firework":{"char":"󰸰","code":"f0e30"},"md-firework_off":{"char":"󱜣","code":"f1723"},"md-fish":{"char":"󰈺","code":"f023a"},"md-fish_off":{"char":"󱏳","code":"f13f3"},"md-fishbowl":{"char":"󰻳","code":"f0ef3"},"md-fishbowl_outline":{"char":"󰻴","code":"f0ef4"},"md-fit_to_page":{"char":"󰻵","code":"f0ef5"},"md-fit_to_page_outline":{"char":"󰻶","code":"f0ef6"},"md-fit_to_screen":{"char":"󱣴","code":"f18f4"},"md-fit_to_screen_outline":{"char":"󱣵","code":"f18f5"},"md-flag":{"char":"󰈻","code":"f023b"},"md-flag_checkered":{"char":"󰈼","code":"f023c"},"md-flag_minus":{"char":"󰮙","code":"f0b99"},"md-flag_minus_outline":{"char":"󱂲","code":"f10b2"},"md-flag_off":{"char":"󱣮","code":"f18ee"},"md-flag_off_outline":{"char":"󱣯","code":"f18ef"},"md-flag_outline":{"char":"󰈽","code":"f023d"},"md-flag_plus":{"char":"󰮚","code":"f0b9a"},"md-flag_plus_outline":{"char":"󱂳","code":"f10b3"},"md-flag_remove":{"char":"󰮛","code":"f0b9b"},"md-flag_remove_outline":{"char":"󱂴","code":"f10b4"},"md-flag_triangle":{"char":"󰈿","code":"f023f"},"md-flag_variant":{"char":"󰉀","code":"f0240"},"md-flag_variant_outline":{"char":"󰈾","code":"f023e"},"md-flare":{"char":"󰵲","code":"f0d72"},"md-flash":{"char":"󰉁","code":"f0241"},"md-flash_alert":{"char":"󰻷","code":"f0ef7"},"md-flash_alert_outline":{"char":"󰻸","code":"f0ef8"},"md-flash_auto":{"char":"󰉂","code":"f0242"},"md-flash_off":{"char":"󰉃","code":"f0243"},"md-flash_outline":{"char":"󰛕","code":"f06d5"},"md-flash_red_eye":{"char":"󰙻","code":"f067b"},"md-flashlight":{"char":"󰉄","code":"f0244"},"md-flashlight_off":{"char":"󰉅","code":"f0245"},"md-flask":{"char":"󰂓","code":"f0093"},"md-flask_empty":{"char":"󰂔","code":"f0094"},"md-flask_empty_minus":{"char":"󱈺","code":"f123a"},"md-flask_empty_minus_outline":{"char":"󱈻","code":"f123b"},"md-flask_empty_off":{"char":"󱏴","code":"f13f4"},"md-flask_empty_off_outline":{"char":"󱏵","code":"f13f5"},"md-flask_empty_outline":{"char":"󰂕","code":"f0095"},"md-flask_empty_plus":{"char":"󱈼","code":"f123c"},"md-flask_empty_plus_outline":{"char":"󱈽","code":"f123d"},"md-flask_empty_remove":{"char":"󱈾","code":"f123e"},"md-flask_empty_remove_outline":{"char":"󱈿","code":"f123f"},"md-flask_minus":{"char":"󱉀","code":"f1240"},"md-flask_minus_outline":{"char":"󱉁","code":"f1241"},"md-flask_off":{"char":"󱏶","code":"f13f6"},"md-flask_off_outline":{"char":"󱏷","code":"f13f7"},"md-flask_outline":{"char":"󰂖","code":"f0096"},"md-flask_plus":{"char":"󱉂","code":"f1242"},"md-flask_plus_outline":{"char":"󱉃","code":"f1243"},"md-flask_remove":{"char":"󱉄","code":"f1244"},"md-flask_remove_outline":{"char":"󱉅","code":"f1245"},"md-flask_round_bottom":{"char":"󱉋","code":"f124b"},"md-flask_round_bottom_empty":{"char":"󱉌","code":"f124c"},"md-flask_round_bottom_empty_outline":{"char":"󱉍","code":"f124d"},"md-flask_round_bottom_outline":{"char":"󱉎","code":"f124e"},"md-fleur_de_lis":{"char":"󱌃","code":"f1303"},"md-flip_horizontal":{"char":"󱃧","code":"f10e7"},"md-flip_to_back":{"char":"󰉇","code":"f0247"},"md-flip_to_front":{"char":"󰉈","code":"f0248"},"md-flip_vertical":{"char":"󱃨","code":"f10e8"},"md-floor_lamp":{"char":"󰣝","code":"f08dd"},"md-floor_lamp_dual":{"char":"󱁀","code":"f1040"},"md-floor_lamp_dual_outline":{"char":"󱟎","code":"f17ce"},"md-floor_lamp_outline":{"char":"󱟈","code":"f17c8"},"md-floor_lamp_torchiere":{"char":"󱝇","code":"f1747"},"md-floor_lamp_torchiere_outline":{"char":"󱟖","code":"f17d6"},"md-floor_lamp_torchiere_variant":{"char":"󱁁","code":"f1041"},"md-floor_lamp_torchiere_variant_outline":{"char":"󱟏","code":"f17cf"},"md-floor_plan":{"char":"󰠡","code":"f0821"},"md-floppy":{"char":"󰉉","code":"f0249"},"md-floppy_variant":{"char":"󰧯","code":"f09ef"},"md-flower":{"char":"󰉊","code":"f024a"},"md-flower_outline":{"char":"󰧰","code":"f09f0"},"md-flower_pollen":{"char":"󱢅","code":"f1885"},"md-flower_pollen_outline":{"char":"󱢆","code":"f1886"},"md-flower_poppy":{"char":"󰴈","code":"f0d08"},"md-flower_tulip":{"char":"󰧱","code":"f09f1"},"md-flower_tulip_outline":{"char":"󰧲","code":"f09f2"},"md-focus_auto":{"char":"󰽎","code":"f0f4e"},"md-focus_field":{"char":"󰽏","code":"f0f4f"},"md-focus_field_horizontal":{"char":"󰽐","code":"f0f50"},"md-focus_field_vertical":{"char":"󰽑","code":"f0f51"},"md-folder":{"char":"󰉋","code":"f024b"},"md-folder_account":{"char":"󰉌","code":"f024c"},"md-folder_account_outline":{"char":"󰮜","code":"f0b9c"},"md-folder_alert":{"char":"󰷌","code":"f0dcc"},"md-folder_alert_outline":{"char":"󰷍","code":"f0dcd"},"md-folder_arrow_down":{"char":"󱧨","code":"f19e8"},"md-folder_arrow_down_outline":{"char":"󱧩","code":"f19e9"},"md-folder_arrow_left":{"char":"󱧪","code":"f19ea"},"md-folder_arrow_left_outline":{"char":"󱧫","code":"f19eb"},"md-folder_arrow_left_right":{"char":"󱧬","code":"f19ec"},"md-folder_arrow_left_right_outline":{"char":"󱧭","code":"f19ed"},"md-folder_arrow_right":{"char":"󱧮","code":"f19ee"},"md-folder_arrow_right_outline":{"char":"󱧯","code":"f19ef"},"md-folder_arrow_up":{"char":"󱧰","code":"f19f0"},"md-folder_arrow_up_down":{"char":"󱧱","code":"f19f1"},"md-folder_arrow_up_down_outline":{"char":"󱧲","code":"f19f2"},"md-folder_arrow_up_outline":{"char":"󱧳","code":"f19f3"},"md-folder_cancel":{"char":"󱧴","code":"f19f4"},"md-folder_cancel_outline":{"char":"󱧵","code":"f19f5"},"md-folder_check":{"char":"󱥾","code":"f197e"},"md-folder_check_outline":{"char":"󱥿","code":"f197f"},"md-folder_clock":{"char":"󰪺","code":"f0aba"},"md-folder_clock_outline":{"char":"󰪻","code":"f0abb"},"md-folder_cog":{"char":"󱁿","code":"f107f"},"md-folder_cog_outline":{"char":"󱂀","code":"f1080"},"md-folder_download":{"char":"󰉍","code":"f024d"},"md-folder_download_outline":{"char":"󱃩","code":"f10e9"},"md-folder_edit":{"char":"󰣞","code":"f08de"},"md-folder_edit_outline":{"char":"󰷎","code":"f0dce"},"md-folder_eye":{"char":"󱞊","code":"f178a"},"md-folder_eye_outline":{"char":"󱞋","code":"f178b"},"md-folder_file":{"char":"󱧶","code":"f19f6"},"md-folder_file_outline":{"char":"󱧷","code":"f19f7"},"md-folder_google_drive":{"char":"󰉎","code":"f024e"},"md-folder_heart":{"char":"󱃪","code":"f10ea"},"md-folder_heart_outline":{"char":"󱃫","code":"f10eb"},"md-folder_hidden":{"char":"󱞞","code":"f179e"},"md-folder_home":{"char":"󱂵","code":"f10b5"},"md-folder_home_outline":{"char":"󱂶","code":"f10b6"},"md-folder_image":{"char":"󰉏","code":"f024f"},"md-folder_information":{"char":"󱂷","code":"f10b7"},"md-folder_information_outline":{"char":"󱂸","code":"f10b8"},"md-folder_key":{"char":"󰢬","code":"f08ac"},"md-folder_key_network":{"char":"󰢭","code":"f08ad"},"md-folder_key_network_outline":{"char":"󰲀","code":"f0c80"},"md-folder_key_outline":{"char":"󱃬","code":"f10ec"},"md-folder_lock":{"char":"󰉐","code":"f0250"},"md-folder_lock_open":{"char":"󰉑","code":"f0251"},"md-folder_lock_open_outline":{"char":"󱪧","code":"f1aa7"},"md-folder_lock_outline":{"char":"󱪨","code":"f1aa8"},"md-folder_marker":{"char":"󱉭","code":"f126d"},"md-folder_marker_outline":{"char":"󱉮","code":"f126e"},"md-folder_move":{"char":"󰉒","code":"f0252"},"md-folder_move_outline":{"char":"󱉆","code":"f1246"},"md-folder_multiple":{"char":"󰉓","code":"f0253"},"md-folder_multiple_image":{"char":"󰉔","code":"f0254"},"md-folder_multiple_outline":{"char":"󰉕","code":"f0255"},"md-folder_multiple_plus":{"char":"󱑾","code":"f147e"},"md-folder_multiple_plus_outline":{"char":"󱑿","code":"f147f"},"md-folder_music":{"char":"󱍙","code":"f1359"},"md-folder_music_outline":{"char":"󱍚","code":"f135a"},"md-folder_network":{"char":"󰡰","code":"f0870"},"md-folder_network_outline":{"char":"󰲁","code":"f0c81"},"md-folder_off":{"char":"󱧸","code":"f19f8"},"md-folder_off_outline":{"char":"󱧹","code":"f19f9"},"md-folder_open":{"char":"󰝰","code":"f0770"},"md-folder_open_outline":{"char":"󰷏","code":"f0dcf"},"md-folder_outline":{"char":"󰉖","code":"f0256"},"md-folder_play":{"char":"󱧺","code":"f19fa"},"md-folder_play_outline":{"char":"󱧻","code":"f19fb"},"md-folder_plus":{"char":"󰉗","code":"f0257"},"md-folder_plus_outline":{"char":"󰮝","code":"f0b9d"},"md-folder_pound":{"char":"󰴉","code":"f0d09"},"md-folder_pound_outline":{"char":"󰴊","code":"f0d0a"},"md-folder_question":{"char":"󱧊","code":"f19ca"},"md-folder_question_outline":{"char":"󱧋","code":"f19cb"},"md-folder_refresh":{"char":"󰝉","code":"f0749"},"md-folder_refresh_outline":{"char":"󰕂","code":"f0542"},"md-folder_remove":{"char":"󰉘","code":"f0258"},"md-folder_remove_outline":{"char":"󰮞","code":"f0b9e"},"md-folder_search":{"char":"󰥨","code":"f0968"},"md-folder_search_outline":{"char":"󰥩","code":"f0969"},"md-folder_settings":{"char":"󱁽","code":"f107d"},"md-folder_settings_outline":{"char":"󱁾","code":"f107e"},"md-folder_star":{"char":"󰚝","code":"f069d"},"md-folder_star_multiple":{"char":"󱏓","code":"f13d3"},"md-folder_star_multiple_outline":{"char":"󱏔","code":"f13d4"},"md-folder_star_outline":{"char":"󰮟","code":"f0b9f"},"md-folder_swap":{"char":"󰾶","code":"f0fb6"},"md-folder_swap_outline":{"char":"󰾷","code":"f0fb7"},"md-folder_sync":{"char":"󰴋","code":"f0d0b"},"md-folder_sync_outline":{"char":"󰴌","code":"f0d0c"},"md-folder_table":{"char":"󱋣","code":"f12e3"},"md-folder_table_outline":{"char":"󱋤","code":"f12e4"},"md-folder_text":{"char":"󰲂","code":"f0c82"},"md-folder_text_outline":{"char":"󰲃","code":"f0c83"},"md-folder_upload":{"char":"󰉙","code":"f0259"},"md-folder_upload_outline":{"char":"󱃭","code":"f10ed"},"md-folder_wrench":{"char":"󱧼","code":"f19fc"},"md-folder_wrench_outline":{"char":"󱧽","code":"f19fd"},"md-folder_zip":{"char":"󰛫","code":"f06eb"},"md-folder_zip_outline":{"char":"󰞹","code":"f07b9"},"md-font_awesome":{"char":"󰀺","code":"f003a"},"md-food":{"char":"󰉚","code":"f025a"},"md-food_apple":{"char":"󰉛","code":"f025b"},"md-food_apple_outline":{"char":"󰲄","code":"f0c84"},"md-food_croissant":{"char":"󰟈","code":"f07c8"},"md-food_drumstick":{"char":"󱐟","code":"f141f"},"md-food_drumstick_off":{"char":"󱑨","code":"f1468"},"md-food_drumstick_off_outline":{"char":"󱑩","code":"f1469"},"md-food_drumstick_outline":{"char":"󱐠","code":"f1420"},"md-food_fork_drink":{"char":"󰗲","code":"f05f2"},"md-food_halal":{"char":"󱕲","code":"f1572"},"md-food_hot_dog":{"char":"󱡋","code":"f184b"},"md-food_kosher":{"char":"󱕳","code":"f1573"},"md-food_off":{"char":"󰗳","code":"f05f3"},"md-food_off_outline":{"char":"󱤕","code":"f1915"},"md-food_outline":{"char":"󱤖","code":"f1916"},"md-food_steak":{"char":"󱑪","code":"f146a"},"md-food_steak_off":{"char":"󱑫","code":"f146b"},"md-food_takeout_box":{"char":"󱠶","code":"f1836"},"md-food_takeout_box_outline":{"char":"󱠷","code":"f1837"},"md-food_turkey":{"char":"󱜜","code":"f171c"},"md-food_variant":{"char":"󰉜","code":"f025c"},"md-food_variant_off":{"char":"󱏥","code":"f13e5"},"md-foot_print":{"char":"󰽒","code":"f0f52"},"md-football":{"char":"󰉝","code":"f025d"},"md-football_australian":{"char":"󰉞","code":"f025e"},"md-football_helmet":{"char":"󰉟","code":"f025f"},"md-forest":{"char":"󱢗","code":"f1897"},"md-forklift":{"char":"󰟉","code":"f07c9"},"md-form_dropdown":{"char":"󱐀","code":"f1400"},"md-form_select":{"char":"󱐁","code":"f1401"},"md-form_textarea":{"char":"󱂕","code":"f1095"},"md-form_textbox":{"char":"󰘎","code":"f060e"},"md-form_textbox_lock":{"char":"󱍝","code":"f135d"},"md-form_textbox_password":{"char":"󰟵","code":"f07f5"},"md-format_align_bottom":{"char":"󰝓","code":"f0753"},"md-format_align_center":{"char":"󰉠","code":"f0260"},"md-format_align_justify":{"char":"󰉡","code":"f0261"},"md-format_align_left":{"char":"󰉢","code":"f0262"},"md-format_align_middle":{"char":"󰝔","code":"f0754"},"md-format_align_right":{"char":"󰉣","code":"f0263"},"md-format_align_top":{"char":"󰝕","code":"f0755"},"md-format_annotation_minus":{"char":"󰪼","code":"f0abc"},"md-format_annotation_plus":{"char":"󰙆","code":"f0646"},"md-format_bold":{"char":"󰉤","code":"f0264"},"md-format_clear":{"char":"󰉥","code":"f0265"},"md-format_color_fill":{"char":"󰉦","code":"f0266"},"md-format_color_highlight":{"char":"󰸱","code":"f0e31"},"md-format_color_marker_cancel":{"char":"󱌓","code":"f1313"},"md-format_color_text":{"char":"󰚞","code":"f069e"},"md-format_columns":{"char":"󰣟","code":"f08df"},"md-format_float_center":{"char":"󰉧","code":"f0267"},"md-format_float_left":{"char":"󰉨","code":"f0268"},"md-format_float_none":{"char":"󰉩","code":"f0269"},"md-format_float_right":{"char":"󰉪","code":"f026a"},"md-format_font":{"char":"󰛖","code":"f06d6"},"md-format_font_size_decrease":{"char":"󰧳","code":"f09f3"},"md-format_font_size_increase":{"char":"󰧴","code":"f09f4"},"md-format_header_1":{"char":"󰉫","code":"f026b"},"md-format_header_2":{"char":"󰉬","code":"f026c"},"md-format_header_3":{"char":"󰉭","code":"f026d"},"md-format_header_4":{"char":"󰉮","code":"f026e"},"md-format_header_5":{"char":"󰉯","code":"f026f"},"md-format_header_6":{"char":"󰉰","code":"f0270"},"md-format_header_decrease":{"char":"󰉱","code":"f0271"},"md-format_header_equal":{"char":"󰉲","code":"f0272"},"md-format_header_increase":{"char":"󰉳","code":"f0273"},"md-format_header_pound":{"char":"󰉴","code":"f0274"},"md-format_horizontal_align_center":{"char":"󰘞","code":"f061e"},"md-format_horizontal_align_left":{"char":"󰘟","code":"f061f"},"md-format_horizontal_align_right":{"char":"󰘠","code":"f0620"},"md-format_indent_decrease":{"char":"󰉵","code":"f0275"},"md-format_indent_increase":{"char":"󰉶","code":"f0276"},"md-format_italic":{"char":"󰉷","code":"f0277"},"md-format_letter_case":{"char":"󰬴","code":"f0b34"},"md-format_letter_case_lower":{"char":"󰬵","code":"f0b35"},"md-format_letter_case_upper":{"char":"󰬶","code":"f0b36"},"md-format_letter_ends_with":{"char":"󰾸","code":"f0fb8"},"md-format_letter_matches":{"char":"󰾹","code":"f0fb9"},"md-format_letter_spacing":{"char":"󱥖","code":"f1956"},"md-format_letter_starts_with":{"char":"󰾺","code":"f0fba"},"md-format_line_spacing":{"char":"󰉸","code":"f0278"},"md-format_line_style":{"char":"󰗈","code":"f05c8"},"md-format_line_weight":{"char":"󰗉","code":"f05c9"},"md-format_list_bulleted":{"char":"󰉹","code":"f0279"},"md-format_list_bulleted_square":{"char":"󰷐","code":"f0dd0"},"md-format_list_bulleted_triangle":{"char":"󰺲","code":"f0eb2"},"md-format_list_bulleted_type":{"char":"󰉺","code":"f027a"},"md-format_list_checkbox":{"char":"󰥪","code":"f096a"},"md-format_list_checks":{"char":"󰝖","code":"f0756"},"md-format_list_group":{"char":"󱡠","code":"f1860"},"md-format_list_numbered":{"char":"󰉻","code":"f027b"},"md-format_list_numbered_rtl":{"char":"󰴍","code":"f0d0d"},"md-format_list_text":{"char":"󱉯","code":"f126f"},"md-format_overline":{"char":"󰺳","code":"f0eb3"},"md-format_page_break":{"char":"󰛗","code":"f06d7"},"md-format_page_split":{"char":"󱤗","code":"f1917"},"md-format_paint":{"char":"󰉼","code":"f027c"},"md-format_paragraph":{"char":"󰉽","code":"f027d"},"md-format_pilcrow":{"char":"󰛘","code":"f06d8"},"md-format_quote_close":{"char":"󰉾","code":"f027e"},"md-format_quote_close_outline":{"char":"󱆨","code":"f11a8"},"md-format_quote_open":{"char":"󰝗","code":"f0757"},"md-format_quote_open_outline":{"char":"󱆧","code":"f11a7"},"md-format_rotate_90":{"char":"󰚪","code":"f06aa"},"md-format_section":{"char":"󰚟","code":"f069f"},"md-format_size":{"char":"󰉿","code":"f027f"},"md-format_strikethrough":{"char":"󰊀","code":"f0280"},"md-format_strikethrough_variant":{"char":"󰊁","code":"f0281"},"md-format_subscript":{"char":"󰊂","code":"f0282"},"md-format_superscript":{"char":"󰊃","code":"f0283"},"md-format_text":{"char":"󰊄","code":"f0284"},"md-format_text_rotation_angle_down":{"char":"󰾻","code":"f0fbb"},"md-format_text_rotation_angle_up":{"char":"󰾼","code":"f0fbc"},"md-format_text_rotation_down":{"char":"󰵳","code":"f0d73"},"md-format_text_rotation_down_vertical":{"char":"󰾽","code":"f0fbd"},"md-format_text_rotation_none":{"char":"󰵴","code":"f0d74"},"md-format_text_rotation_up":{"char":"󰾾","code":"f0fbe"},"md-format_text_rotation_vertical":{"char":"󰾿","code":"f0fbf"},"md-format_text_variant":{"char":"󰸲","code":"f0e32"},"md-format_text_variant_outline":{"char":"󱔏","code":"f150f"},"md-format_text_wrapping_clip":{"char":"󰴎","code":"f0d0e"},"md-format_text_wrapping_overflow":{"char":"󰴏","code":"f0d0f"},"md-format_text_wrapping_wrap":{"char":"󰴐","code":"f0d10"},"md-format_textbox":{"char":"󰴑","code":"f0d11"},"md-format_textdirection_l_to_r":{"char":"󰊅","code":"f0285"},"md-format_textdirection_r_to_l":{"char":"󰊆","code":"f0286"},"md-format_title":{"char":"󰗴","code":"f05f4"},"md-format_underline":{"char":"󰊇","code":"f0287"},"md-format_underline_wavy":{"char":"󱣩","code":"f18e9"},"md-format_vertical_align_bottom":{"char":"󰘡","code":"f0621"},"md-format_vertical_align_center":{"char":"󰘢","code":"f0622"},"md-format_vertical_align_top":{"char":"󰘣","code":"f0623"},"md-format_wrap_inline":{"char":"󰊈","code":"f0288"},"md-format_wrap_square":{"char":"󰊉","code":"f0289"},"md-format_wrap_tight":{"char":"󰊊","code":"f028a"},"md-format_wrap_top_bottom":{"char":"󰊋","code":"f028b"},"md-forum":{"char":"󰊌","code":"f028c"},"md-forum_minus":{"char":"󱪩","code":"f1aa9"},"md-forum_minus_outline":{"char":"󱪪","code":"f1aaa"},"md-forum_outline":{"char":"󰠢","code":"f0822"},"md-forum_plus":{"char":"󱪫","code":"f1aab"},"md-forum_plus_outline":{"char":"󱪬","code":"f1aac"},"md-forum_remove":{"char":"󱪭","code":"f1aad"},"md-forum_remove_outline":{"char":"󱪮","code":"f1aae"},"md-forward":{"char":"󰊍","code":"f028d"},"md-forwardburger":{"char":"󰵵","code":"f0d75"},"md-fountain":{"char":"󰥫","code":"f096b"},"md-fountain_pen":{"char":"󰴒","code":"f0d12"},"md-fountain_pen_tip":{"char":"󰴓","code":"f0d13"},"md-fraction_one_half":{"char":"󱦒","code":"f1992"},"md-freebsd":{"char":"󰣠","code":"f08e0"},"md-french_fries":{"char":"󱥗","code":"f1957"},"md-frequently_asked_questions":{"char":"󰺴","code":"f0eb4"},"md-fridge":{"char":"󰊐","code":"f0290"},"md-fridge_alert":{"char":"󱆱","code":"f11b1"},"md-fridge_alert_outline":{"char":"󱆲","code":"f11b2"},"md-fridge_bottom":{"char":"󰊒","code":"f0292"},"md-fridge_industrial":{"char":"󱗮","code":"f15ee"},"md-fridge_industrial_alert":{"char":"󱗯","code":"f15ef"},"md-fridge_industrial_alert_outline":{"char":"󱗰","code":"f15f0"},"md-fridge_industrial_off":{"char":"󱗱","code":"f15f1"},"md-fridge_industrial_off_outline":{"char":"󱗲","code":"f15f2"},"md-fridge_industrial_outline":{"char":"󱗳","code":"f15f3"},"md-fridge_off":{"char":"󱆯","code":"f11af"},"md-fridge_off_outline":{"char":"󱆰","code":"f11b0"},"md-fridge_outline":{"char":"󰊏","code":"f028f"},"md-fridge_top":{"char":"󰊑","code":"f0291"},"md-fridge_variant":{"char":"󱗴","code":"f15f4"},"md-fridge_variant_alert":{"char":"󱗵","code":"f15f5"},"md-fridge_variant_alert_outline":{"char":"󱗶","code":"f15f6"},"md-fridge_variant_off":{"char":"󱗷","code":"f15f7"},"md-fridge_variant_off_outline":{"char":"󱗸","code":"f15f8"},"md-fridge_variant_outline":{"char":"󱗹","code":"f15f9"},"md-fruit_cherries":{"char":"󱁂","code":"f1042"},"md-fruit_cherries_off":{"char":"󱏸","code":"f13f8"},"md-fruit_citrus":{"char":"󱁃","code":"f1043"},"md-fruit_citrus_off":{"char":"󱏹","code":"f13f9"},"md-fruit_grapes":{"char":"󱁄","code":"f1044"},"md-fruit_grapes_outline":{"char":"󱁅","code":"f1045"},"md-fruit_pear":{"char":"󱨎","code":"f1a0e"},"md-fruit_pineapple":{"char":"󱁆","code":"f1046"},"md-fruit_watermelon":{"char":"󱁇","code":"f1047"},"md-fuel":{"char":"󰟊","code":"f07ca"},"md-fuel_cell":{"char":"󱢵","code":"f18b5"},"md-fullscreen":{"char":"󰊓","code":"f0293"},"md-fullscreen_exit":{"char":"󰊔","code":"f0294"},"md-function":{"char":"󰊕","code":"f0295"},"md-function_variant":{"char":"󰡱","code":"f0871"},"md-furigana_horizontal":{"char":"󱂁","code":"f1081"},"md-furigana_vertical":{"char":"󱂂","code":"f1082"},"md-fuse":{"char":"󰲅","code":"f0c85"},"md-fuse_alert":{"char":"󱐭","code":"f142d"},"md-fuse_blade":{"char":"󰲆","code":"f0c86"},"md-fuse_off":{"char":"󱐬","code":"f142c"},"md-gamepad":{"char":"󰊖","code":"f0296"},"md-gamepad_circle":{"char":"󰸳","code":"f0e33"},"md-gamepad_circle_down":{"char":"󰸴","code":"f0e34"},"md-gamepad_circle_left":{"char":"󰸵","code":"f0e35"},"md-gamepad_circle_outline":{"char":"󰸶","code":"f0e36"},"md-gamepad_circle_right":{"char":"󰸷","code":"f0e37"},"md-gamepad_circle_up":{"char":"󰸸","code":"f0e38"},"md-gamepad_down":{"char":"󰸹","code":"f0e39"},"md-gamepad_left":{"char":"󰸺","code":"f0e3a"},"md-gamepad_outline":{"char":"󱤙","code":"f1919"},"md-gamepad_right":{"char":"󰸻","code":"f0e3b"},"md-gamepad_round":{"char":"󰸼","code":"f0e3c"},"md-gamepad_round_down":{"char":"󰸽","code":"f0e3d"},"md-gamepad_round_left":{"char":"󰸾","code":"f0e3e"},"md-gamepad_round_outline":{"char":"󰸿","code":"f0e3f"},"md-gamepad_round_right":{"char":"󰹀","code":"f0e40"},"md-gamepad_round_up":{"char":"󰹁","code":"f0e41"},"md-gamepad_square":{"char":"󰺵","code":"f0eb5"},"md-gamepad_square_outline":{"char":"󰺶","code":"f0eb6"},"md-gamepad_up":{"char":"󰹂","code":"f0e42"},"md-gamepad_variant":{"char":"󰊗","code":"f0297"},"md-gamepad_variant_outline":{"char":"󰺷","code":"f0eb7"},"md-gamma":{"char":"󱃮","code":"f10ee"},"md-gantry_crane":{"char":"󰷑","code":"f0dd1"},"md-garage":{"char":"󰛙","code":"f06d9"},"md-garage_alert":{"char":"󰡲","code":"f0872"},"md-garage_alert_variant":{"char":"󱋕","code":"f12d5"},"md-garage_lock":{"char":"󱟻","code":"f17fb"},"md-garage_open":{"char":"󰛚","code":"f06da"},"md-garage_open_variant":{"char":"󱋔","code":"f12d4"},"md-garage_variant":{"char":"󱋓","code":"f12d3"},"md-garage_variant_lock":{"char":"󱟼","code":"f17fc"},"md-gas_burner":{"char":"󱨛","code":"f1a1b"},"md-gas_cylinder":{"char":"󰙇","code":"f0647"},"md-gas_station":{"char":"󰊘","code":"f0298"},"md-gas_station_off":{"char":"󱐉","code":"f1409"},"md-gas_station_off_outline":{"char":"󱐊","code":"f140a"},"md-gas_station_outline":{"char":"󰺸","code":"f0eb8"},"md-gate":{"char":"󰊙","code":"f0299"},"md-gate_alert":{"char":"󱟸","code":"f17f8"},"md-gate_and":{"char":"󰣡","code":"f08e1"},"md-gate_arrow_left":{"char":"󱟷","code":"f17f7"},"md-gate_arrow_right":{"char":"󱅩","code":"f1169"},"md-gate_nand":{"char":"󰣢","code":"f08e2"},"md-gate_nor":{"char":"󰣣","code":"f08e3"},"md-gate_not":{"char":"󰣤","code":"f08e4"},"md-gate_open":{"char":"󱅪","code":"f116a"},"md-gate_or":{"char":"󰣥","code":"f08e5"},"md-gate_xnor":{"char":"󰣦","code":"f08e6"},"md-gate_xor":{"char":"󰣧","code":"f08e7"},"md-gatsby":{"char":"󰹃","code":"f0e43"},"md-gauge":{"char":"󰊚","code":"f029a"},"md-gauge_empty":{"char":"󰡳","code":"f0873"},"md-gauge_full":{"char":"󰡴","code":"f0874"},"md-gauge_low":{"char":"󰡵","code":"f0875"},"md-gavel":{"char":"󰊛","code":"f029b"},"md-gender_female":{"char":"󰊜","code":"f029c"},"md-gender_male":{"char":"󰊝","code":"f029d"},"md-gender_male_female":{"char":"󰊞","code":"f029e"},"md-gender_male_female_variant":{"char":"󱄿","code":"f113f"},"md-gender_non_binary":{"char":"󱅀","code":"f1140"},"md-gender_transgender":{"char":"󰊟","code":"f029f"},"md-gentoo":{"char":"󰣨","code":"f08e8"},"md-gesture":{"char":"󰟋","code":"f07cb"},"md-gesture_double_tap":{"char":"󰜼","code":"f073c"},"md-gesture_pinch":{"char":"󰪽","code":"f0abd"},"md-gesture_spread":{"char":"󰪾","code":"f0abe"},"md-gesture_swipe":{"char":"󰵶","code":"f0d76"},"md-gesture_swipe_down":{"char":"󰜽","code":"f073d"},"md-gesture_swipe_horizontal":{"char":"󰪿","code":"f0abf"},"md-gesture_swipe_left":{"char":"󰜾","code":"f073e"},"md-gesture_swipe_right":{"char":"󰜿","code":"f073f"},"md-gesture_swipe_up":{"char":"󰝀","code":"f0740"},"md-gesture_swipe_vertical":{"char":"󰫀","code":"f0ac0"},"md-gesture_tap":{"char":"󰝁","code":"f0741"},"md-gesture_tap_box":{"char":"󱊩","code":"f12a9"},"md-gesture_tap_button":{"char":"󱊨","code":"f12a8"},"md-gesture_tap_hold":{"char":"󰵷","code":"f0d77"},"md-gesture_two_double_tap":{"char":"󰝂","code":"f0742"},"md-gesture_two_tap":{"char":"󰝃","code":"f0743"},"md-ghost":{"char":"󰊠","code":"f02a0"},"md-ghost_off":{"char":"󰧵","code":"f09f5"},"md-ghost_off_outline":{"char":"󱙜","code":"f165c"},"md-ghost_outline":{"char":"󱙝","code":"f165d"},"md-gift":{"char":"󰹄","code":"f0e44"},"md-gift_off":{"char":"󱛯","code":"f16ef"},"md-gift_off_outline":{"char":"󱛰","code":"f16f0"},"md-gift_open":{"char":"󱛱","code":"f16f1"},"md-gift_open_outline":{"char":"󱛲","code":"f16f2"},"md-gift_outline":{"char":"󰊡","code":"f02a1"},"md-git":{"char":"󰊢","code":"f02a2"},"md-github":{"char":"󰊤","code":"f02a4"},"md-gitlab":{"char":"󰮠","code":"f0ba0"},"md-glass_cocktail":{"char":"󰍖","code":"f0356"},"md-glass_cocktail_off":{"char":"󱗦","code":"f15e6"},"md-glass_flute":{"char":"󰊥","code":"f02a5"},"md-glass_fragile":{"char":"󱡳","code":"f1873"},"md-glass_mug":{"char":"󰊦","code":"f02a6"},"md-glass_mug_off":{"char":"󱗧","code":"f15e7"},"md-glass_mug_variant":{"char":"󱄖","code":"f1116"},"md-glass_mug_variant_off":{"char":"󱗨","code":"f15e8"},"md-glass_pint_outline":{"char":"󱌍","code":"f130d"},"md-glass_stange":{"char":"󰊧","code":"f02a7"},"md-glass_tulip":{"char":"󰊨","code":"f02a8"},"md-glass_wine":{"char":"󰡶","code":"f0876"},"md-glasses":{"char":"󰊪","code":"f02aa"},"md-globe_light":{"char":"󱋗","code":"f12d7"},"md-globe_model":{"char":"󰣩","code":"f08e9"},"md-gmail":{"char":"󰊫","code":"f02ab"},"md-gnome":{"char":"󰊬","code":"f02ac"},"md-go_kart":{"char":"󰵹","code":"f0d79"},"md-go_kart_track":{"char":"󰵺","code":"f0d7a"},"md-gog":{"char":"󰮡","code":"f0ba1"},"md-gold":{"char":"󱉏","code":"f124f"},"md-golf":{"char":"󰠣","code":"f0823"},"md-golf_cart":{"char":"󱆤","code":"f11a4"},"md-golf_tee":{"char":"󱂃","code":"f1083"},"md-gondola":{"char":"󰚆","code":"f0686"},"md-goodreads":{"char":"󰵻","code":"f0d7b"},"md-google":{"char":"󰊭","code":"f02ad"},"md-google_ads":{"char":"󰲇","code":"f0c87"},"md-google_analytics":{"char":"󰟌","code":"f07cc"},"md-google_assistant":{"char":"󰟍","code":"f07cd"},"md-google_cardboard":{"char":"󰊮","code":"f02ae"},"md-google_chrome":{"char":"󰊯","code":"f02af"},"md-google_circles":{"char":"󰊰","code":"f02b0"},"md-google_circles_communities":{"char":"󰊱","code":"f02b1"},"md-google_circles_extended":{"char":"󰊲","code":"f02b2"},"md-google_circles_group":{"char":"󰊳","code":"f02b3"},"md-google_classroom":{"char":"󰋀","code":"f02c0"},"md-google_cloud":{"char":"󱇶","code":"f11f6"},"md-google_controller":{"char":"󰊴","code":"f02b4"},"md-google_controller_off":{"char":"󰊵","code":"f02b5"},"md-google_downasaur":{"char":"󱍢","code":"f1362"},"md-google_drive":{"char":"󰊶","code":"f02b6"},"md-google_earth":{"char":"󰊷","code":"f02b7"},"md-google_fit":{"char":"󰥬","code":"f096c"},"md-google_glass":{"char":"󰊸","code":"f02b8"},"md-google_hangouts":{"char":"󰋉","code":"f02c9"},"md-google_home":{"char":"󰠤","code":"f0824"},"md-google_keep":{"char":"󰛜","code":"f06dc"},"md-google_lens":{"char":"󰧶","code":"f09f6"},"md-google_maps":{"char":"󰗵","code":"f05f5"},"md-google_my_business":{"char":"󱁈","code":"f1048"},"md-google_nearby":{"char":"󰊹","code":"f02b9"},"md-google_play":{"char":"󰊼","code":"f02bc"},"md-google_plus":{"char":"󰊽","code":"f02bd"},"md-google_podcast":{"char":"󰺹","code":"f0eb9"},"md-google_spreadsheet":{"char":"󰧷","code":"f09f7"},"md-google_street_view":{"char":"󰲈","code":"f0c88"},"md-google_translate":{"char":"󰊿","code":"f02bf"},"md-gradient_horizontal":{"char":"󱝊","code":"f174a"},"md-gradient_vertical":{"char":"󰚠","code":"f06a0"},"md-grain":{"char":"󰵼","code":"f0d7c"},"md-graph":{"char":"󱁉","code":"f1049"},"md-graph_outline":{"char":"󱁊","code":"f104a"},"md-graphql":{"char":"󰡷","code":"f0877"},"md-grass":{"char":"󱔐","code":"f1510"},"md-grave_stone":{"char":"󰮢","code":"f0ba2"},"md-grease_pencil":{"char":"󰙈","code":"f0648"},"md-greater_than":{"char":"󰥭","code":"f096d"},"md-greater_than_or_equal":{"char":"󰥮","code":"f096e"},"md-greenhouse":{"char":"󰀭","code":"f002d"},"md-grid":{"char":"󰋁","code":"f02c1"},"md-grid_large":{"char":"󰝘","code":"f0758"},"md-grid_off":{"char":"󰋂","code":"f02c2"},"md-grill":{"char":"󰹅","code":"f0e45"},"md-grill_outline":{"char":"󱆊","code":"f118a"},"md-group":{"char":"󰋃","code":"f02c3"},"md-guitar_acoustic":{"char":"󰝱","code":"f0771"},"md-guitar_electric":{"char":"󰋄","code":"f02c4"},"md-guitar_pick":{"char":"󰋅","code":"f02c5"},"md-guitar_pick_outline":{"char":"󰋆","code":"f02c6"},"md-guy_fawkes_mask":{"char":"󰠥","code":"f0825"},"md-gymnastics":{"char":"󱩁","code":"f1a41"},"md-hail":{"char":"󰫁","code":"f0ac1"},"md-hair_dryer":{"char":"󱃯","code":"f10ef"},"md-hair_dryer_outline":{"char":"󱃰","code":"f10f0"},"md-halloween":{"char":"󰮣","code":"f0ba3"},"md-hamburger":{"char":"󰚅","code":"f0685"},"md-hamburger_check":{"char":"󱝶","code":"f1776"},"md-hamburger_minus":{"char":"󱝷","code":"f1777"},"md-hamburger_off":{"char":"󱝸","code":"f1778"},"md-hamburger_plus":{"char":"󱝹","code":"f1779"},"md-hamburger_remove":{"char":"󱝺","code":"f177a"},"md-hammer":{"char":"󰣪","code":"f08ea"},"md-hammer_screwdriver":{"char":"󱌢","code":"f1322"},"md-hammer_sickle":{"char":"󱢇","code":"f1887"},"md-hammer_wrench":{"char":"󱌣","code":"f1323"},"md-hand_back_left":{"char":"󰹆","code":"f0e46"},"md-hand_back_left_off":{"char":"󱠰","code":"f1830"},"md-hand_back_left_off_outline":{"char":"󱠲","code":"f1832"},"md-hand_back_left_outline":{"char":"󱠬","code":"f182c"},"md-hand_back_right":{"char":"󰹇","code":"f0e47"},"md-hand_back_right_off":{"char":"󱠱","code":"f1831"},"md-hand_back_right_off_outline":{"char":"󱠳","code":"f1833"},"md-hand_back_right_outline":{"char":"󱠭","code":"f182d"},"md-hand_clap":{"char":"󱥋","code":"f194b"},"md-hand_clap_off":{"char":"󱩂","code":"f1a42"},"md-hand_coin":{"char":"󱢏","code":"f188f"},"md-hand_coin_outline":{"char":"󱢐","code":"f1890"},"md-hand_extended":{"char":"󱢶","code":"f18b6"},"md-hand_extended_outline":{"char":"󱢷","code":"f18b7"},"md-hand_front_left":{"char":"󱠫","code":"f182b"},"md-hand_front_left_outline":{"char":"󱠮","code":"f182e"},"md-hand_front_right":{"char":"󰩏","code":"f0a4f"},"md-hand_front_right_outline":{"char":"󱠯","code":"f182f"},"md-hand_heart":{"char":"󱃱","code":"f10f1"},"md-hand_heart_outline":{"char":"󱕾","code":"f157e"},"md-hand_okay":{"char":"󰩐","code":"f0a50"},"md-hand_peace":{"char":"󰩑","code":"f0a51"},"md-hand_peace_variant":{"char":"󰩒","code":"f0a52"},"md-hand_pointing_down":{"char":"󰩓","code":"f0a53"},"md-hand_pointing_left":{"char":"󰩔","code":"f0a54"},"md-hand_pointing_right":{"char":"󰋇","code":"f02c7"},"md-hand_pointing_up":{"char":"󰩕","code":"f0a55"},"md-hand_saw":{"char":"󰹈","code":"f0e48"},"md-hand_wash":{"char":"󱕿","code":"f157f"},"md-hand_wash_outline":{"char":"󱖀","code":"f1580"},"md-hand_water":{"char":"󱎟","code":"f139f"},"md-hand_wave":{"char":"󱠡","code":"f1821"},"md-hand_wave_outline":{"char":"󱠢","code":"f1822"},"md-handball":{"char":"󰽓","code":"f0f53"},"md-handcuffs":{"char":"󱄾","code":"f113e"},"md-hands_pray":{"char":"󰕹","code":"f0579"},"md-handshake":{"char":"󱈘","code":"f1218"},"md-handshake_outline":{"char":"󱖡","code":"f15a1"},"md-hanger":{"char":"󰋈","code":"f02c8"},"md-hard_hat":{"char":"󰥯","code":"f096f"},"md-harddisk":{"char":"󰋊","code":"f02ca"},"md-harddisk_plus":{"char":"󱁋","code":"f104b"},"md-harddisk_remove":{"char":"󱁌","code":"f104c"},"md-hat_fedora":{"char":"󰮤","code":"f0ba4"},"md-hazard_lights":{"char":"󰲉","code":"f0c89"},"md-hdr":{"char":"󰵽","code":"f0d7d"},"md-hdr_off":{"char":"󰵾","code":"f0d7e"},"md-head":{"char":"󱍞","code":"f135e"},"md-head_alert":{"char":"󱌸","code":"f1338"},"md-head_alert_outline":{"char":"󱌹","code":"f1339"},"md-head_check":{"char":"󱌺","code":"f133a"},"md-head_check_outline":{"char":"󱌻","code":"f133b"},"md-head_cog":{"char":"󱌼","code":"f133c"},"md-head_cog_outline":{"char":"󱌽","code":"f133d"},"md-head_dots_horizontal":{"char":"󱌾","code":"f133e"},"md-head_dots_horizontal_outline":{"char":"󱌿","code":"f133f"},"md-head_flash":{"char":"󱍀","code":"f1340"},"md-head_flash_outline":{"char":"󱍁","code":"f1341"},"md-head_heart":{"char":"󱍂","code":"f1342"},"md-head_heart_outline":{"char":"󱍃","code":"f1343"},"md-head_lightbulb":{"char":"󱍄","code":"f1344"},"md-head_lightbulb_outline":{"char":"󱍅","code":"f1345"},"md-head_minus":{"char":"󱍆","code":"f1346"},"md-head_minus_outline":{"char":"󱍇","code":"f1347"},"md-head_outline":{"char":"󱍟","code":"f135f"},"md-head_plus":{"char":"󱍈","code":"f1348"},"md-head_plus_outline":{"char":"󱍉","code":"f1349"},"md-head_question":{"char":"󱍊","code":"f134a"},"md-head_question_outline":{"char":"󱍋","code":"f134b"},"md-head_remove":{"char":"󱍌","code":"f134c"},"md-head_remove_outline":{"char":"󱍍","code":"f134d"},"md-head_snowflake":{"char":"󱍎","code":"f134e"},"md-head_snowflake_outline":{"char":"󱍏","code":"f134f"},"md-head_sync":{"char":"󱍐","code":"f1350"},"md-head_sync_outline":{"char":"󱍑","code":"f1351"},"md-headphones":{"char":"󰋋","code":"f02cb"},"md-headphones_bluetooth":{"char":"󰥰","code":"f0970"},"md-headphones_box":{"char":"󰋌","code":"f02cc"},"md-headphones_off":{"char":"󰟎","code":"f07ce"},"md-headphones_settings":{"char":"󰋍","code":"f02cd"},"md-headset":{"char":"󰋎","code":"f02ce"},"md-headset_dock":{"char":"󰋏","code":"f02cf"},"md-headset_off":{"char":"󰋐","code":"f02d0"},"md-heart":{"char":"󰋑","code":"f02d1"},"md-heart_box":{"char":"󰋒","code":"f02d2"},"md-heart_box_outline":{"char":"󰋓","code":"f02d3"},"md-heart_broken":{"char":"󰋔","code":"f02d4"},"md-heart_broken_outline":{"char":"󰴔","code":"f0d14"},"md-heart_circle":{"char":"󰥱","code":"f0971"},"md-heart_circle_outline":{"char":"󰥲","code":"f0972"},"md-heart_cog":{"char":"󱙣","code":"f1663"},"md-heart_cog_outline":{"char":"󱙤","code":"f1664"},"md-heart_flash":{"char":"󰻹","code":"f0ef9"},"md-heart_half":{"char":"󰛟","code":"f06df"},"md-heart_half_full":{"char":"󰛞","code":"f06de"},"md-heart_half_outline":{"char":"󰛠","code":"f06e0"},"md-heart_minus":{"char":"󱐯","code":"f142f"},"md-heart_minus_outline":{"char":"󱐲","code":"f1432"},"md-heart_multiple":{"char":"󰩖","code":"f0a56"},"md-heart_multiple_outline":{"char":"󰩗","code":"f0a57"},"md-heart_off":{"char":"󰝙","code":"f0759"},"md-heart_off_outline":{"char":"󱐴","code":"f1434"},"md-heart_outline":{"char":"󰋕","code":"f02d5"},"md-heart_plus":{"char":"󱐮","code":"f142e"},"md-heart_plus_outline":{"char":"󱐱","code":"f1431"},"md-heart_pulse":{"char":"󰗶","code":"f05f6"},"md-heart_remove":{"char":"󱐰","code":"f1430"},"md-heart_remove_outline":{"char":"󱐳","code":"f1433"},"md-heart_settings":{"char":"󱙥","code":"f1665"},"md-heart_settings_outline":{"char":"󱙦","code":"f1666"},"md-heat_pump":{"char":"󱩃","code":"f1a43"},"md-heat_pump_outline":{"char":"󱩄","code":"f1a44"},"md-heat_wave":{"char":"󱩅","code":"f1a45"},"md-heating_coil":{"char":"󱪯","code":"f1aaf"},"md-helicopter":{"char":"󰫂","code":"f0ac2"},"md-help":{"char":"󰋖","code":"f02d6"},"md-help_box":{"char":"󰞋","code":"f078b"},"md-help_circle":{"char":"󰋗","code":"f02d7"},"md-help_circle_outline":{"char":"󰘥","code":"f0625"},"md-help_network":{"char":"󰛵","code":"f06f5"},"md-help_network_outline":{"char":"󰲊","code":"f0c8a"},"md-help_rhombus":{"char":"󰮥","code":"f0ba5"},"md-help_rhombus_outline":{"char":"󰮦","code":"f0ba6"},"md-hexadecimal":{"char":"󱊧","code":"f12a7"},"md-hexagon":{"char":"󰋘","code":"f02d8"},"md-hexagon_multiple":{"char":"󰛡","code":"f06e1"},"md-hexagon_multiple_outline":{"char":"󱃲","code":"f10f2"},"md-hexagon_outline":{"char":"󰋙","code":"f02d9"},"md-hexagon_slice_1":{"char":"󰫃","code":"f0ac3"},"md-hexagon_slice_2":{"char":"󰫄","code":"f0ac4"},"md-hexagon_slice_3":{"char":"󰫅","code":"f0ac5"},"md-hexagon_slice_4":{"char":"󰫆","code":"f0ac6"},"md-hexagon_slice_5":{"char":"󰫇","code":"f0ac7"},"md-hexagon_slice_6":{"char":"󰫈","code":"f0ac8"},"md-hexagram":{"char":"󰫉","code":"f0ac9"},"md-hexagram_outline":{"char":"󰫊","code":"f0aca"},"md-high_definition":{"char":"󰟏","code":"f07cf"},"md-high_definition_box":{"char":"󰡸","code":"f0878"},"md-highway":{"char":"󰗷","code":"f05f7"},"md-hiking":{"char":"󰵿","code":"f0d7f"},"md-history":{"char":"󰋚","code":"f02da"},"md-hockey_puck":{"char":"󰡹","code":"f0879"},"md-hockey_sticks":{"char":"󰡺","code":"f087a"},"md-hololens":{"char":"󰋛","code":"f02db"},"md-home":{"char":"󰋜","code":"f02dc"},"md-home_account":{"char":"󰠦","code":"f0826"},"md-home_alert":{"char":"󰡻","code":"f087b"},"md-home_alert_outline":{"char":"󱗐","code":"f15d0"},"md-home_analytics":{"char":"󰺺","code":"f0eba"},"md-home_assistant":{"char":"󰟐","code":"f07d0"},"md-home_automation":{"char":"󰟑","code":"f07d1"},"md-home_battery":{"char":"󱤁","code":"f1901"},"md-home_battery_outline":{"char":"󱤂","code":"f1902"},"md-home_circle":{"char":"󰟒","code":"f07d2"},"md-home_circle_outline":{"char":"󱁍","code":"f104d"},"md-home_city":{"char":"󰴕","code":"f0d15"},"md-home_city_outline":{"char":"󰴖","code":"f0d16"},"md-home_clock":{"char":"󱨒","code":"f1a12"},"md-home_clock_outline":{"char":"󱨓","code":"f1a13"},"md-home_edit":{"char":"󱅙","code":"f1159"},"md-home_edit_outline":{"char":"󱅚","code":"f115a"},"md-home_export_outline":{"char":"󰾛","code":"f0f9b"},"md-home_flood":{"char":"󰻺","code":"f0efa"},"md-home_floor_0":{"char":"󰷒","code":"f0dd2"},"md-home_floor_1":{"char":"󰶀","code":"f0d80"},"md-home_floor_2":{"char":"󰶁","code":"f0d81"},"md-home_floor_3":{"char":"󰶂","code":"f0d82"},"md-home_floor_a":{"char":"󰶃","code":"f0d83"},"md-home_floor_b":{"char":"󰶄","code":"f0d84"},"md-home_floor_g":{"char":"󰶅","code":"f0d85"},"md-home_floor_l":{"char":"󰶆","code":"f0d86"},"md-home_floor_negative_1":{"char":"󰷓","code":"f0dd3"},"md-home_group":{"char":"󰷔","code":"f0dd4"},"md-home_group_minus":{"char":"󱧁","code":"f19c1"},"md-home_group_plus":{"char":"󱧀","code":"f19c0"},"md-home_group_remove":{"char":"󱧂","code":"f19c2"},"md-home_heart":{"char":"󰠧","code":"f0827"},"md-home_import_outline":{"char":"󰾜","code":"f0f9c"},"md-home_lightbulb":{"char":"󱉑","code":"f1251"},"md-home_lightbulb_outline":{"char":"󱉒","code":"f1252"},"md-home_lightning_bolt":{"char":"󱤃","code":"f1903"},"md-home_lightning_bolt_outline":{"char":"󱤄","code":"f1904"},"md-home_lock":{"char":"󰣫","code":"f08eb"},"md-home_lock_open":{"char":"󰣬","code":"f08ec"},"md-home_map_marker":{"char":"󰗸","code":"f05f8"},"md-home_minus":{"char":"󰥴","code":"f0974"},"md-home_minus_outline":{"char":"󱏕","code":"f13d5"},"md-home_modern":{"char":"󰋝","code":"f02dd"},"md-home_off":{"char":"󱩆","code":"f1a46"},"md-home_off_outline":{"char":"󱩇","code":"f1a47"},"md-home_outline":{"char":"󰚡","code":"f06a1"},"md-home_plus":{"char":"󰥵","code":"f0975"},"md-home_plus_outline":{"char":"󱏖","code":"f13d6"},"md-home_remove":{"char":"󱉇","code":"f1247"},"md-home_remove_outline":{"char":"󱏗","code":"f13d7"},"md-home_roof":{"char":"󱄫","code":"f112b"},"md-home_search":{"char":"󱎰","code":"f13b0"},"md-home_search_outline":{"char":"󱎱","code":"f13b1"},"md-home_switch":{"char":"󱞔","code":"f1794"},"md-home_switch_outline":{"char":"󱞕","code":"f1795"},"md-home_thermometer":{"char":"󰽔","code":"f0f54"},"md-home_thermometer_outline":{"char":"󰽕","code":"f0f55"},"md-home_variant":{"char":"󰋞","code":"f02de"},"md-home_variant_outline":{"char":"󰮧","code":"f0ba7"},"md-hook":{"char":"󰛢","code":"f06e2"},"md-hook_off":{"char":"󰛣","code":"f06e3"},"md-hoop_house":{"char":"󰹖","code":"f0e56"},"md-hops":{"char":"󰋟","code":"f02df"},"md-horizontal_rotate_clockwise":{"char":"󱃳","code":"f10f3"},"md-horizontal_rotate_counterclockwise":{"char":"󱃴","code":"f10f4"},"md-horse":{"char":"󱖿","code":"f15bf"},"md-horse_human":{"char":"󱗀","code":"f15c0"},"md-horse_variant":{"char":"󱗁","code":"f15c1"},"md-horse_variant_fast":{"char":"󱡮","code":"f186e"},"md-horseshoe":{"char":"󰩘","code":"f0a58"},"md-hospital":{"char":"󰿶","code":"f0ff6"},"md-hospital_box":{"char":"󰋠","code":"f02e0"},"md-hospital_box_outline":{"char":"󰿷","code":"f0ff7"},"md-hospital_building":{"char":"󰋡","code":"f02e1"},"md-hospital_marker":{"char":"󰋢","code":"f02e2"},"md-hot_tub":{"char":"󰠨","code":"f0828"},"md-hours_24":{"char":"󱑸","code":"f1478"},"md-hubspot":{"char":"󰴗","code":"f0d17"},"md-hulu":{"char":"󰠩","code":"f0829"},"md-human":{"char":"󰋦","code":"f02e6"},"md-human_baby_changing_table":{"char":"󱎋","code":"f138b"},"md-human_cane":{"char":"󱖁","code":"f1581"},"md-human_capacity_decrease":{"char":"󱖛","code":"f159b"},"md-human_capacity_increase":{"char":"󱖜","code":"f159c"},"md-human_child":{"char":"󰋧","code":"f02e7"},"md-human_dolly":{"char":"󱦀","code":"f1980"},"md-human_edit":{"char":"󱓨","code":"f14e8"},"md-human_female":{"char":"󰙉","code":"f0649"},"md-human_female_boy":{"char":"󰩙","code":"f0a59"},"md-human_female_dance":{"char":"󱗉","code":"f15c9"},"md-human_female_female":{"char":"󰩚","code":"f0a5a"},"md-human_female_girl":{"char":"󰩛","code":"f0a5b"},"md-human_greeting":{"char":"󱟄","code":"f17c4"},"md-human_greeting_proximity":{"char":"󱖝","code":"f159d"},"md-human_greeting_variant":{"char":"󰙊","code":"f064a"},"md-human_handsdown":{"char":"󰙋","code":"f064b"},"md-human_handsup":{"char":"󰙌","code":"f064c"},"md-human_male":{"char":"󰙍","code":"f064d"},"md-human_male_board":{"char":"󰢐","code":"f0890"},"md-human_male_board_poll":{"char":"󰡆","code":"f0846"},"md-human_male_boy":{"char":"󰩜","code":"f0a5c"},"md-human_male_child":{"char":"󱎌","code":"f138c"},"md-human_male_female":{"char":"󰋨","code":"f02e8"},"md-human_male_female_child":{"char":"󱠣","code":"f1823"},"md-human_male_girl":{"char":"󰩝","code":"f0a5d"},"md-human_male_height":{"char":"󰻻","code":"f0efb"},"md-human_male_height_variant":{"char":"󰻼","code":"f0efc"},"md-human_male_male":{"char":"󰩞","code":"f0a5e"},"md-human_non_binary":{"char":"󱡈","code":"f1848"},"md-human_pregnant":{"char":"󰗏","code":"f05cf"},"md-human_queue":{"char":"󱕱","code":"f1571"},"md-human_scooter":{"char":"󱇩","code":"f11e9"},"md-human_wheelchair":{"char":"󱎍","code":"f138d"},"md-human_white_cane":{"char":"󱦁","code":"f1981"},"md-humble_bundle":{"char":"󰝄","code":"f0744"},"md-hvac":{"char":"󱍒","code":"f1352"},"md-hvac_off":{"char":"󱖞","code":"f159e"},"md-hydraulic_oil_level":{"char":"󱌤","code":"f1324"},"md-hydraulic_oil_temperature":{"char":"󱌥","code":"f1325"},"md-hydro_power":{"char":"󱋥","code":"f12e5"},"md-hydrogen_station":{"char":"󱢔","code":"f1894"},"md-ice_cream":{"char":"󰠪","code":"f082a"},"md-ice_cream_off":{"char":"󰹒","code":"f0e52"},"md-ice_pop":{"char":"󰻽","code":"f0efd"},"md-id_card":{"char":"󰿀","code":"f0fc0"},"md-identifier":{"char":"󰻾","code":"f0efe"},"md-ideogram_cjk":{"char":"󱌱","code":"f1331"},"md-ideogram_cjk_variant":{"char":"󱌲","code":"f1332"},"md-image":{"char":"󰋩","code":"f02e9"},"md-image_album":{"char":"󰋪","code":"f02ea"},"md-image_area":{"char":"󰋫","code":"f02eb"},"md-image_area_close":{"char":"󰋬","code":"f02ec"},"md-image_auto_adjust":{"char":"󰿁","code":"f0fc1"},"md-image_broken":{"char":"󰋭","code":"f02ed"},"md-image_broken_variant":{"char":"󰋮","code":"f02ee"},"md-image_edit":{"char":"󱇣","code":"f11e3"},"md-image_edit_outline":{"char":"󱇤","code":"f11e4"},"md-image_filter_black_white":{"char":"󰋰","code":"f02f0"},"md-image_filter_center_focus":{"char":"󰋱","code":"f02f1"},"md-image_filter_center_focus_strong":{"char":"󰻿","code":"f0eff"},"md-image_filter_center_focus_strong_outline":{"char":"󰼀","code":"f0f00"},"md-image_filter_center_focus_weak":{"char":"󰋲","code":"f02f2"},"md-image_filter_drama":{"char":"󰋳","code":"f02f3"},"md-image_filter_frames":{"char":"󰋴","code":"f02f4"},"md-image_filter_hdr":{"char":"󰋵","code":"f02f5"},"md-image_filter_none":{"char":"󰋶","code":"f02f6"},"md-image_filter_tilt_shift":{"char":"󰋷","code":"f02f7"},"md-image_filter_vintage":{"char":"󰋸","code":"f02f8"},"md-image_frame":{"char":"󰹉","code":"f0e49"},"md-image_lock":{"char":"󱪰","code":"f1ab0"},"md-image_lock_outline":{"char":"󱪱","code":"f1ab1"},"md-image_marker":{"char":"󱝻","code":"f177b"},"md-image_marker_outline":{"char":"󱝼","code":"f177c"},"md-image_minus":{"char":"󱐙","code":"f1419"},"md-image_move":{"char":"󰧸","code":"f09f8"},"md-image_multiple":{"char":"󰋹","code":"f02f9"},"md-image_multiple_outline":{"char":"󰋯","code":"f02ef"},"md-image_off":{"char":"󰠫","code":"f082b"},"md-image_off_outline":{"char":"󱇑","code":"f11d1"},"md-image_outline":{"char":"󰥶","code":"f0976"},"md-image_plus":{"char":"󰡼","code":"f087c"},"md-image_refresh":{"char":"󱧾","code":"f19fe"},"md-image_refresh_outline":{"char":"󱧿","code":"f19ff"},"md-image_remove":{"char":"󱐘","code":"f1418"},"md-image_search":{"char":"󰥷","code":"f0977"},"md-image_search_outline":{"char":"󰥸","code":"f0978"},"md-image_size_select_actual":{"char":"󰲍","code":"f0c8d"},"md-image_size_select_large":{"char":"󰲎","code":"f0c8e"},"md-image_size_select_small":{"char":"󰲏","code":"f0c8f"},"md-image_sync":{"char":"󱨀","code":"f1a00"},"md-image_sync_outline":{"char":"󱨁","code":"f1a01"},"md-image_text":{"char":"󱘍","code":"f160d"},"md-import":{"char":"󰋺","code":"f02fa"},"md-inbox":{"char":"󰚇","code":"f0687"},"md-inbox_arrow_down":{"char":"󰋻","code":"f02fb"},"md-inbox_arrow_down_outline":{"char":"󱉰","code":"f1270"},"md-inbox_arrow_up":{"char":"󰏑","code":"f03d1"},"md-inbox_arrow_up_outline":{"char":"󱉱","code":"f1271"},"md-inbox_full":{"char":"󱉲","code":"f1272"},"md-inbox_full_outline":{"char":"󱉳","code":"f1273"},"md-inbox_multiple":{"char":"󰢰","code":"f08b0"},"md-inbox_multiple_outline":{"char":"󰮨","code":"f0ba8"},"md-inbox_outline":{"char":"󱉴","code":"f1274"},"md-inbox_remove":{"char":"󱖟","code":"f159f"},"md-inbox_remove_outline":{"char":"󱖠","code":"f15a0"},"md-incognito":{"char":"󰗹","code":"f05f9"},"md-incognito_circle":{"char":"󱐡","code":"f1421"},"md-incognito_circle_off":{"char":"󱐢","code":"f1422"},"md-incognito_off":{"char":"󰁵","code":"f0075"},"md-induction":{"char":"󱡌","code":"f184c"},"md-infinity":{"char":"󰛤","code":"f06e4"},"md-information":{"char":"󰋼","code":"f02fc"},"md-information_off":{"char":"󱞌","code":"f178c"},"md-information_off_outline":{"char":"󱞍","code":"f178d"},"md-information_outline":{"char":"󰋽","code":"f02fd"},"md-information_variant":{"char":"󰙎","code":"f064e"},"md-instagram":{"char":"󰋾","code":"f02fe"},"md-instrument_triangle":{"char":"󱁎","code":"f104e"},"md-integrated_circuit_chip":{"char":"󱤓","code":"f1913"},"md-invert_colors":{"char":"󰌁","code":"f0301"},"md-invert_colors_off":{"char":"󰹊","code":"f0e4a"},"md-iobroker":{"char":"󱋨","code":"f12e8"},"md-ip":{"char":"󰩟","code":"f0a5f"},"md-ip_network":{"char":"󰩠","code":"f0a60"},"md-ip_network_outline":{"char":"󰲐","code":"f0c90"},"md-ip_outline":{"char":"󱦂","code":"f1982"},"md-ipod":{"char":"󰲑","code":"f0c91"},"md-iron":{"char":"󱠤","code":"f1824"},"md-iron_board":{"char":"󱠸","code":"f1838"},"md-iron_outline":{"char":"󱠥","code":"f1825"},"md-island":{"char":"󱁏","code":"f104f"},"md-iv_bag":{"char":"󱂹","code":"f10b9"},"md-jabber":{"char":"󰷕","code":"f0dd5"},"md-jeepney":{"char":"󰌂","code":"f0302"},"md-jellyfish":{"char":"󰼁","code":"f0f01"},"md-jellyfish_outline":{"char":"󰼂","code":"f0f02"},"md-jira":{"char":"󰌃","code":"f0303"},"md-jquery":{"char":"󰡽","code":"f087d"},"md-jsfiddle":{"char":"󰌄","code":"f0304"},"md-jump_rope":{"char":"󱋿","code":"f12ff"},"md-kabaddi":{"char":"󰶇","code":"f0d87"},"md-kangaroo":{"char":"󱕘","code":"f1558"},"md-karate":{"char":"󰠬","code":"f082c"},"md-kayaking":{"char":"󰢯","code":"f08af"},"md-keg":{"char":"󰌅","code":"f0305"},"md-kettle":{"char":"󰗺","code":"f05fa"},"md-kettle_alert":{"char":"󱌗","code":"f1317"},"md-kettle_alert_outline":{"char":"󱌘","code":"f1318"},"md-kettle_off":{"char":"󱌛","code":"f131b"},"md-kettle_off_outline":{"char":"󱌜","code":"f131c"},"md-kettle_outline":{"char":"󰽖","code":"f0f56"},"md-kettle_pour_over":{"char":"󱜼","code":"f173c"},"md-kettle_steam":{"char":"󱌙","code":"f1319"},"md-kettle_steam_outline":{"char":"󱌚","code":"f131a"},"md-kettlebell":{"char":"󱌀","code":"f1300"},"md-key":{"char":"󰌆","code":"f0306"},"md-key_alert":{"char":"󱦃","code":"f1983"},"md-key_alert_outline":{"char":"󱦄","code":"f1984"},"md-key_arrow_right":{"char":"󱌒","code":"f1312"},"md-key_chain":{"char":"󱕴","code":"f1574"},"md-key_chain_variant":{"char":"󱕵","code":"f1575"},"md-key_change":{"char":"󰌇","code":"f0307"},"md-key_link":{"char":"󱆟","code":"f119f"},"md-key_minus":{"char":"󰌈","code":"f0308"},"md-key_outline":{"char":"󰷖","code":"f0dd6"},"md-key_plus":{"char":"󰌉","code":"f0309"},"md-key_remove":{"char":"󰌊","code":"f030a"},"md-key_star":{"char":"󱆞","code":"f119e"},"md-key_variant":{"char":"󰌋","code":"f030b"},"md-key_wireless":{"char":"󰿂","code":"f0fc2"},"md-keyboard":{"char":"󰌌","code":"f030c"},"md-keyboard_backspace":{"char":"󰌍","code":"f030d"},"md-keyboard_caps":{"char":"󰌎","code":"f030e"},"md-keyboard_close":{"char":"󰌏","code":"f030f"},"md-keyboard_esc":{"char":"󱊷","code":"f12b7"},"md-keyboard_f1":{"char":"󱊫","code":"f12ab"},"md-keyboard_f10":{"char":"󱊴","code":"f12b4"},"md-keyboard_f11":{"char":"󱊵","code":"f12b5"},"md-keyboard_f12":{"char":"󱊶","code":"f12b6"},"md-keyboard_f2":{"char":"󱊬","code":"f12ac"},"md-keyboard_f3":{"char":"󱊭","code":"f12ad"},"md-keyboard_f4":{"char":"󱊮","code":"f12ae"},"md-keyboard_f5":{"char":"󱊯","code":"f12af"},"md-keyboard_f6":{"char":"󱊰","code":"f12b0"},"md-keyboard_f7":{"char":"󱊱","code":"f12b1"},"md-keyboard_f8":{"char":"󱊲","code":"f12b2"},"md-keyboard_f9":{"char":"󱊳","code":"f12b3"},"md-keyboard_off":{"char":"󰌐","code":"f0310"},"md-keyboard_off_outline":{"char":"󰹋","code":"f0e4b"},"md-keyboard_outline":{"char":"󰥻","code":"f097b"},"md-keyboard_return":{"char":"󰌑","code":"f0311"},"md-keyboard_settings":{"char":"󰧹","code":"f09f9"},"md-keyboard_settings_outline":{"char":"󰧺","code":"f09fa"},"md-keyboard_space":{"char":"󱁐","code":"f1050"},"md-keyboard_tab":{"char":"󰌒","code":"f0312"},"md-keyboard_tab_reverse":{"char":"󰌥","code":"f0325"},"md-keyboard_variant":{"char":"󰌓","code":"f0313"},"md-khanda":{"char":"󱃽","code":"f10fd"},"md-kickstarter":{"char":"󰝅","code":"f0745"},"md-kite":{"char":"󱦅","code":"f1985"},"md-kite_outline":{"char":"󱦆","code":"f1986"},"md-kitesurfing":{"char":"󱝄","code":"f1744"},"md-klingon":{"char":"󱍛","code":"f135b"},"md-knife":{"char":"󰧻","code":"f09fb"},"md-knife_military":{"char":"󰧼","code":"f09fc"},"md-koala":{"char":"󱜿","code":"f173f"},"md-kodi":{"char":"󰌔","code":"f0314"},"md-kubernetes":{"char":"󱃾","code":"f10fe"},"md-label":{"char":"󰌕","code":"f0315"},"md-label_multiple":{"char":"󱍵","code":"f1375"},"md-label_multiple_outline":{"char":"󱍶","code":"f1376"},"md-label_off":{"char":"󰫋","code":"f0acb"},"md-label_off_outline":{"char":"󰫌","code":"f0acc"},"md-label_outline":{"char":"󰌖","code":"f0316"},"md-label_percent":{"char":"󱋪","code":"f12ea"},"md-label_percent_outline":{"char":"󱋫","code":"f12eb"},"md-label_variant":{"char":"󰫍","code":"f0acd"},"md-label_variant_outline":{"char":"󰫎","code":"f0ace"},"md-ladder":{"char":"󱖢","code":"f15a2"},"md-ladybug":{"char":"󰠭","code":"f082d"},"md-lambda":{"char":"󰘧","code":"f0627"},"md-lamp":{"char":"󰚵","code":"f06b5"},"md-lamp_outline":{"char":"󱟐","code":"f17d0"},"md-lamps":{"char":"󱕶","code":"f1576"},"md-lamps_outline":{"char":"󱟑","code":"f17d1"},"md-lan":{"char":"󰌗","code":"f0317"},"md-lan_check":{"char":"󱊪","code":"f12aa"},"md-lan_connect":{"char":"󰌘","code":"f0318"},"md-lan_disconnect":{"char":"󰌙","code":"f0319"},"md-lan_pending":{"char":"󰌚","code":"f031a"},"md-land_fields":{"char":"󱪲","code":"f1ab2"},"md-land_plots":{"char":"󱪳","code":"f1ab3"},"md-land_plots_circle":{"char":"󱪴","code":"f1ab4"},"md-land_plots_circle_variant":{"char":"󱪵","code":"f1ab5"},"md-land_rows_horizontal":{"char":"󱪶","code":"f1ab6"},"md-land_rows_vertical":{"char":"󱪷","code":"f1ab7"},"md-landslide":{"char":"󱩈","code":"f1a48"},"md-landslide_outline":{"char":"󱩉","code":"f1a49"},"md-language_c":{"char":"󰙱","code":"f0671"},"md-language_cpp":{"char":"󰙲","code":"f0672"},"md-language_csharp":{"char":"󰌛","code":"f031b"},"md-language_css3":{"char":"󰌜","code":"f031c"},"md-language_fortran":{"char":"󱈚","code":"f121a"},"md-language_go":{"char":"󰟓","code":"f07d3"},"md-language_haskell":{"char":"󰲒","code":"f0c92"},"md-language_html5":{"char":"󰌝","code":"f031d"},"md-language_java":{"char":"󰬷","code":"f0b37"},"md-language_javascript":{"char":"󰌞","code":"f031e"},"md-language_kotlin":{"char":"󱈙","code":"f1219"},"md-language_lua":{"char":"󰢱","code":"f08b1"},"md-language_markdown":{"char":"󰍔","code":"f0354"},"md-language_markdown_outline":{"char":"󰽛","code":"f0f5b"},"md-language_php":{"char":"󰌟","code":"f031f"},"md-language_python":{"char":"󰌠","code":"f0320"},"md-language_r":{"char":"󰟔","code":"f07d4"},"md-language_ruby":{"char":"󰴭","code":"f0d2d"},"md-language_ruby_on_rails":{"char":"󰫏","code":"f0acf"},"md-language_rust":{"char":"󱘗","code":"f1617"},"md-language_swift":{"char":"󰛥","code":"f06e5"},"md-language_typescript":{"char":"󰛦","code":"f06e6"},"md-language_xaml":{"char":"󰙳","code":"f0673"},"md-laptop":{"char":"󰌢","code":"f0322"},"md-laptop_account":{"char":"󱩊","code":"f1a4a"},"md-laptop_off":{"char":"󰛧","code":"f06e7"},"md-laravel":{"char":"󰫐","code":"f0ad0"},"md-laser_pointer":{"char":"󱒄","code":"f1484"},"md-lasso":{"char":"󰼃","code":"f0f03"},"md-lastpass":{"char":"󰑆","code":"f0446"},"md-latitude":{"char":"󰽗","code":"f0f57"},"md-launch":{"char":"󰌧","code":"f0327"},"md-lava_lamp":{"char":"󰟕","code":"f07d5"},"md-layers":{"char":"󰌨","code":"f0328"},"md-layers_edit":{"char":"󱢒","code":"f1892"},"md-layers_minus":{"char":"󰹌","code":"f0e4c"},"md-layers_off":{"char":"󰌩","code":"f0329"},"md-layers_off_outline":{"char":"󰧽","code":"f09fd"},"md-layers_outline":{"char":"󰧾","code":"f09fe"},"md-layers_plus":{"char":"󰹍","code":"f0e4d"},"md-layers_remove":{"char":"󰹎","code":"f0e4e"},"md-layers_search":{"char":"󱈆","code":"f1206"},"md-layers_search_outline":{"char":"󱈇","code":"f1207"},"md-layers_triple":{"char":"󰽘","code":"f0f58"},"md-layers_triple_outline":{"char":"󰽙","code":"f0f59"},"md-lead_pencil":{"char":"󰙏","code":"f064f"},"md-leaf":{"char":"󰌪","code":"f032a"},"md-leaf_circle":{"char":"󱤅","code":"f1905"},"md-leaf_circle_outline":{"char":"󱤆","code":"f1906"},"md-leaf_maple":{"char":"󰲓","code":"f0c93"},"md-leaf_maple_off":{"char":"󱋚","code":"f12da"},"md-leaf_off":{"char":"󱋙","code":"f12d9"},"md-leak":{"char":"󰷗","code":"f0dd7"},"md-leak_off":{"char":"󰷘","code":"f0dd8"},"md-lecturn":{"char":"󱫰","code":"f1af0"},"md-led_off":{"char":"󰌫","code":"f032b"},"md-led_on":{"char":"󰌬","code":"f032c"},"md-led_outline":{"char":"󰌭","code":"f032d"},"md-led_strip":{"char":"󰟖","code":"f07d6"},"md-led_strip_variant":{"char":"󱁑","code":"f1051"},"md-led_strip_variant_off":{"char":"󱩋","code":"f1a4b"},"md-led_variant_off":{"char":"󰌮","code":"f032e"},"md-led_variant_on":{"char":"󰌯","code":"f032f"},"md-led_variant_outline":{"char":"󰌰","code":"f0330"},"md-leek":{"char":"󱅽","code":"f117d"},"md-less_than":{"char":"󰥼","code":"f097c"},"md-less_than_or_equal":{"char":"󰥽","code":"f097d"},"md-library":{"char":"󰌱","code":"f0331"},"md-library_outline":{"char":"󱨢","code":"f1a22"},"md-library_shelves":{"char":"󰮩","code":"f0ba9"},"md-license":{"char":"󰿃","code":"f0fc3"},"md-lifebuoy":{"char":"󰡾","code":"f087e"},"md-light_flood_down":{"char":"󱦇","code":"f1987"},"md-light_flood_up":{"char":"󱦈","code":"f1988"},"md-light_recessed":{"char":"󱞛","code":"f179b"},"md-light_switch":{"char":"󰥾","code":"f097e"},"md-light_switch_off":{"char":"󱨤","code":"f1a24"},"md-lightbulb":{"char":"󰌵","code":"f0335"},"md-lightbulb_alert":{"char":"󱧡","code":"f19e1"},"md-lightbulb_alert_outline":{"char":"󱧢","code":"f19e2"},"md-lightbulb_auto":{"char":"󱠀","code":"f1800"},"md-lightbulb_auto_outline":{"char":"󱠁","code":"f1801"},"md-lightbulb_cfl":{"char":"󱈈","code":"f1208"},"md-lightbulb_cfl_off":{"char":"󱈉","code":"f1209"},"md-lightbulb_cfl_spiral":{"char":"󱉵","code":"f1275"},"md-lightbulb_cfl_spiral_off":{"char":"󱋃","code":"f12c3"},"md-lightbulb_fluorescent_tube":{"char":"󱠄","code":"f1804"},"md-lightbulb_fluorescent_tube_outline":{"char":"󱠅","code":"f1805"},"md-lightbulb_group":{"char":"󱉓","code":"f1253"},"md-lightbulb_group_off":{"char":"󱋍","code":"f12cd"},"md-lightbulb_group_off_outline":{"char":"󱋎","code":"f12ce"},"md-lightbulb_group_outline":{"char":"󱉔","code":"f1254"},"md-lightbulb_multiple":{"char":"󱉕","code":"f1255"},"md-lightbulb_multiple_off":{"char":"󱋏","code":"f12cf"},"md-lightbulb_multiple_off_outline":{"char":"󱋐","code":"f12d0"},"md-lightbulb_multiple_outline":{"char":"󱉖","code":"f1256"},"md-lightbulb_night":{"char":"󱩌","code":"f1a4c"},"md-lightbulb_night_outline":{"char":"󱩍","code":"f1a4d"},"md-lightbulb_off":{"char":"󰹏","code":"f0e4f"},"md-lightbulb_off_outline":{"char":"󰹐","code":"f0e50"},"md-lightbulb_on":{"char":"󰛨","code":"f06e8"},"md-lightbulb_on_10":{"char":"󱩎","code":"f1a4e"},"md-lightbulb_on_20":{"char":"󱩏","code":"f1a4f"},"md-lightbulb_on_30":{"char":"󱩐","code":"f1a50"},"md-lightbulb_on_40":{"char":"󱩑","code":"f1a51"},"md-lightbulb_on_50":{"char":"󱩒","code":"f1a52"},"md-lightbulb_on_60":{"char":"󱩓","code":"f1a53"},"md-lightbulb_on_70":{"char":"󱩔","code":"f1a54"},"md-lightbulb_on_80":{"char":"󱩕","code":"f1a55"},"md-lightbulb_on_90":{"char":"󱩖","code":"f1a56"},"md-lightbulb_on_outline":{"char":"󰛩","code":"f06e9"},"md-lightbulb_outline":{"char":"󰌶","code":"f0336"},"md-lightbulb_question":{"char":"󱧣","code":"f19e3"},"md-lightbulb_question_outline":{"char":"󱧤","code":"f19e4"},"md-lightbulb_spot":{"char":"󱟴","code":"f17f4"},"md-lightbulb_spot_off":{"char":"󱟵","code":"f17f5"},"md-lightbulb_variant":{"char":"󱠂","code":"f1802"},"md-lightbulb_variant_outline":{"char":"󱠃","code":"f1803"},"md-lighthouse":{"char":"󰧿","code":"f09ff"},"md-lighthouse_on":{"char":"󰨀","code":"f0a00"},"md-lightning_bolt":{"char":"󱐋","code":"f140b"},"md-lightning_bolt_circle":{"char":"󰠠","code":"f0820"},"md-lightning_bolt_outline":{"char":"󱐌","code":"f140c"},"md-line_scan":{"char":"󰘤","code":"f0624"},"md-lingerie":{"char":"󱑶","code":"f1476"},"md-link":{"char":"󰌷","code":"f0337"},"md-link_box":{"char":"󰴚","code":"f0d1a"},"md-link_box_outline":{"char":"󰴛","code":"f0d1b"},"md-link_box_variant":{"char":"󰴜","code":"f0d1c"},"md-link_box_variant_outline":{"char":"󰴝","code":"f0d1d"},"md-link_lock":{"char":"󱂺","code":"f10ba"},"md-link_off":{"char":"󰌸","code":"f0338"},"md-link_plus":{"char":"󰲔","code":"f0c94"},"md-link_variant":{"char":"󰌹","code":"f0339"},"md-link_variant_minus":{"char":"󱃿","code":"f10ff"},"md-link_variant_off":{"char":"󰌺","code":"f033a"},"md-link_variant_plus":{"char":"󱄀","code":"f1100"},"md-link_variant_remove":{"char":"󱄁","code":"f1101"},"md-linkedin":{"char":"󰌻","code":"f033b"},"md-linux":{"char":"󰌽","code":"f033d"},"md-linux_mint":{"char":"󰣭","code":"f08ed"},"md-lipstick":{"char":"󱎵","code":"f13b5"},"md-liquid_spot":{"char":"󱠦","code":"f1826"},"md-liquor":{"char":"󱤞","code":"f191e"},"md-list_status":{"char":"󱖫","code":"f15ab"},"md-litecoin":{"char":"󰩡","code":"f0a61"},"md-loading":{"char":"󰝲","code":"f0772"},"md-location_enter":{"char":"󰿄","code":"f0fc4"},"md-location_exit":{"char":"󰿅","code":"f0fc5"},"md-lock":{"char":"󰌾","code":"f033e"},"md-lock_alert":{"char":"󰣮","code":"f08ee"},"md-lock_alert_outline":{"char":"󱗑","code":"f15d1"},"md-lock_check":{"char":"󱎚","code":"f139a"},"md-lock_check_outline":{"char":"󱚨","code":"f16a8"},"md-lock_clock":{"char":"󰥿","code":"f097f"},"md-lock_minus":{"char":"󱚩","code":"f16a9"},"md-lock_minus_outline":{"char":"󱚪","code":"f16aa"},"md-lock_off":{"char":"󱙱","code":"f1671"},"md-lock_off_outline":{"char":"󱙲","code":"f1672"},"md-lock_open":{"char":"󰌿","code":"f033f"},"md-lock_open_alert":{"char":"󱎛","code":"f139b"},"md-lock_open_alert_outline":{"char":"󱗒","code":"f15d2"},"md-lock_open_check":{"char":"󱎜","code":"f139c"},"md-lock_open_check_outline":{"char":"󱚫","code":"f16ab"},"md-lock_open_minus":{"char":"󱚬","code":"f16ac"},"md-lock_open_minus_outline":{"char":"󱚭","code":"f16ad"},"md-lock_open_outline":{"char":"󰍀","code":"f0340"},"md-lock_open_plus":{"char":"󱚮","code":"f16ae"},"md-lock_open_plus_outline":{"char":"󱚯","code":"f16af"},"md-lock_open_remove":{"char":"󱚰","code":"f16b0"},"md-lock_open_remove_outline":{"char":"󱚱","code":"f16b1"},"md-lock_open_variant":{"char":"󰿆","code":"f0fc6"},"md-lock_open_variant_outline":{"char":"󰿇","code":"f0fc7"},"md-lock_outline":{"char":"󰍁","code":"f0341"},"md-lock_pattern":{"char":"󰛪","code":"f06ea"},"md-lock_plus":{"char":"󰗻","code":"f05fb"},"md-lock_plus_outline":{"char":"󱚲","code":"f16b2"},"md-lock_question":{"char":"󰣯","code":"f08ef"},"md-lock_remove":{"char":"󱚳","code":"f16b3"},"md-lock_remove_outline":{"char":"󱚴","code":"f16b4"},"md-lock_reset":{"char":"󰝳","code":"f0773"},"md-lock_smart":{"char":"󰢲","code":"f08b2"},"md-locker":{"char":"󰟗","code":"f07d7"},"md-locker_multiple":{"char":"󰟘","code":"f07d8"},"md-login":{"char":"󰍂","code":"f0342"},"md-logout":{"char":"󰍃","code":"f0343"},"md-logout_variant":{"char":"󰗽","code":"f05fd"},"md-longitude":{"char":"󰽚","code":"f0f5a"},"md-looks":{"char":"󰍄","code":"f0344"},"md-lotion":{"char":"󱖂","code":"f1582"},"md-lotion_outline":{"char":"󱖃","code":"f1583"},"md-lotion_plus":{"char":"󱖄","code":"f1584"},"md-lotion_plus_outline":{"char":"󱖅","code":"f1585"},"md-loupe":{"char":"󰍅","code":"f0345"},"md-lumx":{"char":"󰍆","code":"f0346"},"md-lungs":{"char":"󱂄","code":"f1084"},"md-mace":{"char":"󱡃","code":"f1843"},"md-magazine_pistol":{"char":"󰌤","code":"f0324"},"md-magazine_rifle":{"char":"󰌣","code":"f0323"},"md-magic_staff":{"char":"󱡄","code":"f1844"},"md-magnet":{"char":"󰍇","code":"f0347"},"md-magnet_on":{"char":"󰍈","code":"f0348"},"md-magnify":{"char":"󰍉","code":"f0349"},"md-magnify_close":{"char":"󰦀","code":"f0980"},"md-magnify_expand":{"char":"󱡴","code":"f1874"},"md-magnify_minus":{"char":"󰍊","code":"f034a"},"md-magnify_minus_cursor":{"char":"󰩢","code":"f0a62"},"md-magnify_minus_outline":{"char":"󰛬","code":"f06ec"},"md-magnify_plus":{"char":"󰍋","code":"f034b"},"md-magnify_plus_cursor":{"char":"󰩣","code":"f0a63"},"md-magnify_plus_outline":{"char":"󰛭","code":"f06ed"},"md-magnify_remove_cursor":{"char":"󱈌","code":"f120c"},"md-magnify_remove_outline":{"char":"󱈍","code":"f120d"},"md-magnify_scan":{"char":"󱉶","code":"f1276"},"md-mail":{"char":"󰺻","code":"f0ebb"},"md-mailbox":{"char":"󰛮","code":"f06ee"},"md-mailbox_open":{"char":"󰶈","code":"f0d88"},"md-mailbox_open_outline":{"char":"󰶉","code":"f0d89"},"md-mailbox_open_up":{"char":"󰶊","code":"f0d8a"},"md-mailbox_open_up_outline":{"char":"󰶋","code":"f0d8b"},"md-mailbox_outline":{"char":"󰶌","code":"f0d8c"},"md-mailbox_up":{"char":"󰶍","code":"f0d8d"},"md-mailbox_up_outline":{"char":"󰶎","code":"f0d8e"},"md-manjaro":{"char":"󱘊","code":"f160a"},"md-map":{"char":"󰍍","code":"f034d"},"md-map_check":{"char":"󰺼","code":"f0ebc"},"md-map_check_outline":{"char":"󰺽","code":"f0ebd"},"md-map_clock":{"char":"󰴞","code":"f0d1e"},"md-map_clock_outline":{"char":"󰴟","code":"f0d1f"},"md-map_legend":{"char":"󰨁","code":"f0a01"},"md-map_marker":{"char":"󰍎","code":"f034e"},"md-map_marker_account":{"char":"󱣣","code":"f18e3"},"md-map_marker_account_outline":{"char":"󱣤","code":"f18e4"},"md-map_marker_alert":{"char":"󰼅","code":"f0f05"},"md-map_marker_alert_outline":{"char":"󰼆","code":"f0f06"},"md-map_marker_check":{"char":"󰲕","code":"f0c95"},"md-map_marker_check_outline":{"char":"󱋻","code":"f12fb"},"md-map_marker_circle":{"char":"󰍏","code":"f034f"},"md-map_marker_distance":{"char":"󰣰","code":"f08f0"},"md-map_marker_down":{"char":"󱄂","code":"f1102"},"md-map_marker_left":{"char":"󱋛","code":"f12db"},"md-map_marker_left_outline":{"char":"󱋝","code":"f12dd"},"md-map_marker_minus":{"char":"󰙐","code":"f0650"},"md-map_marker_minus_outline":{"char":"󱋹","code":"f12f9"},"md-map_marker_multiple":{"char":"󰍐","code":"f0350"},"md-map_marker_multiple_outline":{"char":"󱉷","code":"f1277"},"md-map_marker_off":{"char":"󰍑","code":"f0351"},"md-map_marker_off_outline":{"char":"󱋽","code":"f12fd"},"md-map_marker_outline":{"char":"󰟙","code":"f07d9"},"md-map_marker_path":{"char":"󰴠","code":"f0d20"},"md-map_marker_plus":{"char":"󰙑","code":"f0651"},"md-map_marker_plus_outline":{"char":"󱋸","code":"f12f8"},"md-map_marker_question":{"char":"󰼇","code":"f0f07"},"md-map_marker_question_outline":{"char":"󰼈","code":"f0f08"},"md-map_marker_radius":{"char":"󰍒","code":"f0352"},"md-map_marker_radius_outline":{"char":"󱋼","code":"f12fc"},"md-map_marker_remove":{"char":"󰼉","code":"f0f09"},"md-map_marker_remove_outline":{"char":"󱋺","code":"f12fa"},"md-map_marker_remove_variant":{"char":"󰼊","code":"f0f0a"},"md-map_marker_right":{"char":"󱋜","code":"f12dc"},"md-map_marker_right_outline":{"char":"󱋞","code":"f12de"},"md-map_marker_star":{"char":"󱘈","code":"f1608"},"md-map_marker_star_outline":{"char":"󱘉","code":"f1609"},"md-map_marker_up":{"char":"󱄃","code":"f1103"},"md-map_minus":{"char":"󰦁","code":"f0981"},"md-map_outline":{"char":"󰦂","code":"f0982"},"md-map_plus":{"char":"󰦃","code":"f0983"},"md-map_search":{"char":"󰦄","code":"f0984"},"md-map_search_outline":{"char":"󰦅","code":"f0985"},"md-mapbox":{"char":"󰮪","code":"f0baa"},"md-margin":{"char":"󰍓","code":"f0353"},"md-marker":{"char":"󰙒","code":"f0652"},"md-marker_cancel":{"char":"󰷙","code":"f0dd9"},"md-marker_check":{"char":"󰍕","code":"f0355"},"md-mastodon":{"char":"󰫑","code":"f0ad1"},"md-material_design":{"char":"󰦆","code":"f0986"},"md-material_ui":{"char":"󰍗","code":"f0357"},"md-math_compass":{"char":"󰍘","code":"f0358"},"md-math_cos":{"char":"󰲖","code":"f0c96"},"md-math_integral":{"char":"󰿈","code":"f0fc8"},"md-math_integral_box":{"char":"󰿉","code":"f0fc9"},"md-math_log":{"char":"󱂅","code":"f1085"},"md-math_norm":{"char":"󰿊","code":"f0fca"},"md-math_norm_box":{"char":"󰿋","code":"f0fcb"},"md-math_sin":{"char":"󰲗","code":"f0c97"},"md-math_tan":{"char":"󰲘","code":"f0c98"},"md-matrix":{"char":"󰘨","code":"f0628"},"md-medal":{"char":"󰦇","code":"f0987"},"md-medal_outline":{"char":"󱌦","code":"f1326"},"md-medical_bag":{"char":"󰛯","code":"f06ef"},"md-medical_cotton_swab":{"char":"󱪸","code":"f1ab8"},"md-meditation":{"char":"󱅻","code":"f117b"},"md-memory":{"char":"󰍛","code":"f035b"},"md-menorah":{"char":"󱟔","code":"f17d4"},"md-menorah_fire":{"char":"󱟕","code":"f17d5"},"md-menu":{"char":"󰍜","code":"f035c"},"md-menu_down":{"char":"󰍝","code":"f035d"},"md-menu_down_outline":{"char":"󰚶","code":"f06b6"},"md-menu_left":{"char":"󰍞","code":"f035e"},"md-menu_left_outline":{"char":"󰨂","code":"f0a02"},"md-menu_open":{"char":"󰮫","code":"f0bab"},"md-menu_right":{"char":"󰍟","code":"f035f"},"md-menu_right_outline":{"char":"󰨃","code":"f0a03"},"md-menu_swap":{"char":"󰩤","code":"f0a64"},"md-menu_swap_outline":{"char":"󰩥","code":"f0a65"},"md-menu_up":{"char":"󰍠","code":"f0360"},"md-menu_up_outline":{"char":"󰚷","code":"f06b7"},"md-merge":{"char":"󰽜","code":"f0f5c"},"md-message":{"char":"󰍡","code":"f0361"},"md-message_alert":{"char":"󰍢","code":"f0362"},"md-message_alert_outline":{"char":"󰨄","code":"f0a04"},"md-message_arrow_left":{"char":"󱋲","code":"f12f2"},"md-message_arrow_left_outline":{"char":"󱋳","code":"f12f3"},"md-message_arrow_right":{"char":"󱋴","code":"f12f4"},"md-message_arrow_right_outline":{"char":"󱋵","code":"f12f5"},"md-message_badge":{"char":"󱥁","code":"f1941"},"md-message_badge_outline":{"char":"󱥂","code":"f1942"},"md-message_bookmark":{"char":"󱖬","code":"f15ac"},"md-message_bookmark_outline":{"char":"󱖭","code":"f15ad"},"md-message_bulleted":{"char":"󰚢","code":"f06a2"},"md-message_bulleted_off":{"char":"󰚣","code":"f06a3"},"md-message_cog":{"char":"󰛱","code":"f06f1"},"md-message_cog_outline":{"char":"󱅲","code":"f1172"},"md-message_draw":{"char":"󰍣","code":"f0363"},"md-message_fast":{"char":"󱧌","code":"f19cc"},"md-message_fast_outline":{"char":"󱧍","code":"f19cd"},"md-message_flash":{"char":"󱖩","code":"f15a9"},"md-message_flash_outline":{"char":"󱖪","code":"f15aa"},"md-message_image":{"char":"󰍤","code":"f0364"},"md-message_image_outline":{"char":"󱅬","code":"f116c"},"md-message_lock":{"char":"󰿌","code":"f0fcc"},"md-message_lock_outline":{"char":"󱅭","code":"f116d"},"md-message_minus":{"char":"󱅮","code":"f116e"},"md-message_minus_outline":{"char":"󱅯","code":"f116f"},"md-message_off":{"char":"󱙍","code":"f164d"},"md-message_off_outline":{"char":"󱙎","code":"f164e"},"md-message_outline":{"char":"󰍥","code":"f0365"},"md-message_plus":{"char":"󰙓","code":"f0653"},"md-message_plus_outline":{"char":"󱂻","code":"f10bb"},"md-message_processing":{"char":"󰍦","code":"f0366"},"md-message_processing_outline":{"char":"󱅰","code":"f1170"},"md-message_question":{"char":"󱜺","code":"f173a"},"md-message_question_outline":{"char":"󱜻","code":"f173b"},"md-message_reply":{"char":"󰍧","code":"f0367"},"md-message_reply_outline":{"char":"󱜽","code":"f173d"},"md-message_reply_text":{"char":"󰍨","code":"f0368"},"md-message_reply_text_outline":{"char":"󱜾","code":"f173e"},"md-message_settings":{"char":"󰛰","code":"f06f0"},"md-message_settings_outline":{"char":"󱅱","code":"f1171"},"md-message_star":{"char":"󰚚","code":"f069a"},"md-message_star_outline":{"char":"󱉐","code":"f1250"},"md-message_text":{"char":"󰍩","code":"f0369"},"md-message_text_clock":{"char":"󱅳","code":"f1173"},"md-message_text_clock_outline":{"char":"󱅴","code":"f1174"},"md-message_text_fast":{"char":"󱧎","code":"f19ce"},"md-message_text_fast_outline":{"char":"󱧏","code":"f19cf"},"md-message_text_lock":{"char":"󰿍","code":"f0fcd"},"md-message_text_lock_outline":{"char":"󱅵","code":"f1175"},"md-message_text_outline":{"char":"󰍪","code":"f036a"},"md-message_video":{"char":"󰍫","code":"f036b"},"md-meteor":{"char":"󰘩","code":"f0629"},"md-meter_electric":{"char":"󱩗","code":"f1a57"},"md-meter_electric_outline":{"char":"󱩘","code":"f1a58"},"md-meter_gas":{"char":"󱩙","code":"f1a59"},"md-meter_gas_outline":{"char":"󱩚","code":"f1a5a"},"md-metronome":{"char":"󰟚","code":"f07da"},"md-metronome_tick":{"char":"󰟛","code":"f07db"},"md-micro_sd":{"char":"󰟜","code":"f07dc"},"md-microphone":{"char":"󰍬","code":"f036c"},"md-microphone_minus":{"char":"󰢳","code":"f08b3"},"md-microphone_off":{"char":"󰍭","code":"f036d"},"md-microphone_outline":{"char":"󰍮","code":"f036e"},"md-microphone_plus":{"char":"󰢴","code":"f08b4"},"md-microphone_question":{"char":"󱦉","code":"f1989"},"md-microphone_question_outline":{"char":"󱦊","code":"f198a"},"md-microphone_settings":{"char":"󰍯","code":"f036f"},"md-microphone_variant":{"char":"󰍰","code":"f0370"},"md-microphone_variant_off":{"char":"󰍱","code":"f0371"},"md-microscope":{"char":"󰙔","code":"f0654"},"md-microsoft":{"char":"󰍲","code":"f0372"},"md-microsoft_access":{"char":"󱎎","code":"f138e"},"md-microsoft_azure":{"char":"󰠅","code":"f0805"},"md-microsoft_azure_devops":{"char":"󰿕","code":"f0fd5"},"md-microsoft_bing":{"char":"󰂤","code":"f00a4"},"md-microsoft_dynamics_365":{"char":"󰦈","code":"f0988"},"md-microsoft_edge":{"char":"󰇩","code":"f01e9"},"md-microsoft_excel":{"char":"󱎏","code":"f138f"},"md-microsoft_internet_explorer":{"char":"󰌀","code":"f0300"},"md-microsoft_office":{"char":"󰏆","code":"f03c6"},"md-microsoft_onedrive":{"char":"󰏊","code":"f03ca"},"md-microsoft_onenote":{"char":"󰝇","code":"f0747"},"md-microsoft_outlook":{"char":"󰴢","code":"f0d22"},"md-microsoft_powerpoint":{"char":"󱎐","code":"f1390"},"md-microsoft_sharepoint":{"char":"󱎑","code":"f1391"},"md-microsoft_teams":{"char":"󰊻","code":"f02bb"},"md-microsoft_visual_studio":{"char":"󰘐","code":"f0610"},"md-microsoft_visual_studio_code":{"char":"󰨞","code":"f0a1e"},"md-microsoft_windows":{"char":"󰖳","code":"f05b3"},"md-microsoft_windows_classic":{"char":"󰨡","code":"f0a21"},"md-microsoft_word":{"char":"󱎒","code":"f1392"},"md-microsoft_xbox":{"char":"󰖹","code":"f05b9"},"md-microsoft_xbox_controller":{"char":"󰖺","code":"f05ba"},"md-microsoft_xbox_controller_battery_alert":{"char":"󰝋","code":"f074b"},"md-microsoft_xbox_controller_battery_charging":{"char":"󰨢","code":"f0a22"},"md-microsoft_xbox_controller_battery_empty":{"char":"󰝌","code":"f074c"},"md-microsoft_xbox_controller_battery_full":{"char":"󰝍","code":"f074d"},"md-microsoft_xbox_controller_battery_low":{"char":"󰝎","code":"f074e"},"md-microsoft_xbox_controller_battery_medium":{"char":"󰝏","code":"f074f"},"md-microsoft_xbox_controller_battery_unknown":{"char":"󰝐","code":"f0750"},"md-microsoft_xbox_controller_menu":{"char":"󰹯","code":"f0e6f"},"md-microsoft_xbox_controller_off":{"char":"󰖻","code":"f05bb"},"md-microsoft_xbox_controller_view":{"char":"󰹰","code":"f0e70"},"md-microwave":{"char":"󰲙","code":"f0c99"},"md-microwave_off":{"char":"󱐣","code":"f1423"},"md-middleware":{"char":"󰽝","code":"f0f5d"},"md-middleware_outline":{"char":"󰽞","code":"f0f5e"},"md-midi":{"char":"󰣱","code":"f08f1"},"md-midi_port":{"char":"󰣲","code":"f08f2"},"md-mine":{"char":"󰷚","code":"f0dda"},"md-minecraft":{"char":"󰍳","code":"f0373"},"md-mini_sd":{"char":"󰨅","code":"f0a05"},"md-minidisc":{"char":"󰨆","code":"f0a06"},"md-minus":{"char":"󰍴","code":"f0374"},"md-minus_box":{"char":"󰍵","code":"f0375"},"md-minus_box_multiple":{"char":"󱅁","code":"f1141"},"md-minus_box_multiple_outline":{"char":"󱅂","code":"f1142"},"md-minus_box_outline":{"char":"󰛲","code":"f06f2"},"md-minus_circle":{"char":"󰍶","code":"f0376"},"md-minus_circle_multiple":{"char":"󰍚","code":"f035a"},"md-minus_circle_multiple_outline":{"char":"󰫓","code":"f0ad3"},"md-minus_circle_off":{"char":"󱑙","code":"f1459"},"md-minus_circle_off_outline":{"char":"󱑚","code":"f145a"},"md-minus_circle_outline":{"char":"󰍷","code":"f0377"},"md-minus_network":{"char":"󰍸","code":"f0378"},"md-minus_network_outline":{"char":"󰲚","code":"f0c9a"},"md-minus_thick":{"char":"󱘹","code":"f1639"},"md-mirror":{"char":"󱇽","code":"f11fd"},"md-mirror_rectangle":{"char":"󱞟","code":"f179f"},"md-mirror_variant":{"char":"󱞠","code":"f17a0"},"md-mixed_martial_arts":{"char":"󰶏","code":"f0d8f"},"md-mixed_reality":{"char":"󰡿","code":"f087f"},"md-molecule":{"char":"󰮬","code":"f0bac"},"md-molecule_co":{"char":"󱋾","code":"f12fe"},"md-molecule_co2":{"char":"󰟤","code":"f07e4"},"md-monitor":{"char":"󰍹","code":"f0379"},"md-monitor_account":{"char":"󱩛","code":"f1a5b"},"md-monitor_arrow_down":{"char":"󱧐","code":"f19d0"},"md-monitor_arrow_down_variant":{"char":"󱧑","code":"f19d1"},"md-monitor_cellphone":{"char":"󰦉","code":"f0989"},"md-monitor_cellphone_star":{"char":"󰦊","code":"f098a"},"md-monitor_dashboard":{"char":"󰨇","code":"f0a07"},"md-monitor_edit":{"char":"󱋆","code":"f12c6"},"md-monitor_eye":{"char":"󱎴","code":"f13b4"},"md-monitor_lock":{"char":"󰷛","code":"f0ddb"},"md-monitor_multiple":{"char":"󰍺","code":"f037a"},"md-monitor_off":{"char":"󰶐","code":"f0d90"},"md-monitor_screenshot":{"char":"󰹑","code":"f0e51"},"md-monitor_share":{"char":"󱒃","code":"f1483"},"md-monitor_shimmer":{"char":"󱄄","code":"f1104"},"md-monitor_small":{"char":"󱡶","code":"f1876"},"md-monitor_speaker":{"char":"󰽟","code":"f0f5f"},"md-monitor_speaker_off":{"char":"󰽠","code":"f0f60"},"md-monitor_star":{"char":"󰷜","code":"f0ddc"},"md-moon_first_quarter":{"char":"󰽡","code":"f0f61"},"md-moon_full":{"char":"󰽢","code":"f0f62"},"md-moon_last_quarter":{"char":"󰽣","code":"f0f63"},"md-moon_new":{"char":"󰽤","code":"f0f64"},"md-moon_waning_crescent":{"char":"󰽥","code":"f0f65"},"md-moon_waning_gibbous":{"char":"󰽦","code":"f0f66"},"md-moon_waxing_crescent":{"char":"󰽧","code":"f0f67"},"md-moon_waxing_gibbous":{"char":"󰽨","code":"f0f68"},"md-moped":{"char":"󱂆","code":"f1086"},"md-moped_electric":{"char":"󱖷","code":"f15b7"},"md-moped_electric_outline":{"char":"󱖸","code":"f15b8"},"md-moped_outline":{"char":"󱖹","code":"f15b9"},"md-more":{"char":"󰍻","code":"f037b"},"md-mortar_pestle":{"char":"󱝈","code":"f1748"},"md-mortar_pestle_plus":{"char":"󰏱","code":"f03f1"},"md-mosque":{"char":"󱠧","code":"f1827"},"md-mother_heart":{"char":"󱌔","code":"f1314"},"md-mother_nurse":{"char":"󰴡","code":"f0d21"},"md-motion":{"char":"󱖲","code":"f15b2"},"md-motion_outline":{"char":"󱖳","code":"f15b3"},"md-motion_pause":{"char":"󱖐","code":"f1590"},"md-motion_pause_outline":{"char":"󱖒","code":"f1592"},"md-motion_play":{"char":"󱖏","code":"f158f"},"md-motion_play_outline":{"char":"󱖑","code":"f1591"},"md-motion_sensor":{"char":"󰶑","code":"f0d91"},"md-motion_sensor_off":{"char":"󱐵","code":"f1435"},"md-motorbike":{"char":"󰍼","code":"f037c"},"md-motorbike_electric":{"char":"󱖺","code":"f15ba"},"md-mouse":{"char":"󰍽","code":"f037d"},"md-mouse_bluetooth":{"char":"󰦋","code":"f098b"},"md-mouse_move_down":{"char":"󱕐","code":"f1550"},"md-mouse_move_up":{"char":"󱕑","code":"f1551"},"md-mouse_move_vertical":{"char":"󱕒","code":"f1552"},"md-mouse_off":{"char":"󰍾","code":"f037e"},"md-mouse_variant":{"char":"󰍿","code":"f037f"},"md-mouse_variant_off":{"char":"󰎀","code":"f0380"},"md-move_resize":{"char":"󰙕","code":"f0655"},"md-move_resize_variant":{"char":"󰙖","code":"f0656"},"md-movie":{"char":"󰎁","code":"f0381"},"md-movie_check":{"char":"󱛳","code":"f16f3"},"md-movie_check_outline":{"char":"󱛴","code":"f16f4"},"md-movie_cog":{"char":"󱛵","code":"f16f5"},"md-movie_cog_outline":{"char":"󱛶","code":"f16f6"},"md-movie_edit":{"char":"󱄢","code":"f1122"},"md-movie_edit_outline":{"char":"󱄣","code":"f1123"},"md-movie_filter":{"char":"󱄤","code":"f1124"},"md-movie_filter_outline":{"char":"󱄥","code":"f1125"},"md-movie_minus":{"char":"󱛷","code":"f16f7"},"md-movie_minus_outline":{"char":"󱛸","code":"f16f8"},"md-movie_off":{"char":"󱛹","code":"f16f9"},"md-movie_off_outline":{"char":"󱛺","code":"f16fa"},"md-movie_open":{"char":"󰿎","code":"f0fce"},"md-movie_open_check":{"char":"󱛻","code":"f16fb"},"md-movie_open_check_outline":{"char":"󱛼","code":"f16fc"},"md-movie_open_cog":{"char":"󱛽","code":"f16fd"},"md-movie_open_cog_outline":{"char":"󱛾","code":"f16fe"},"md-movie_open_edit":{"char":"󱛿","code":"f16ff"},"md-movie_open_edit_outline":{"char":"󱜀","code":"f1700"},"md-movie_open_minus":{"char":"󱜁","code":"f1701"},"md-movie_open_minus_outline":{"char":"󱜂","code":"f1702"},"md-movie_open_off":{"char":"󱜃","code":"f1703"},"md-movie_open_off_outline":{"char":"󱜄","code":"f1704"},"md-movie_open_outline":{"char":"󰿏","code":"f0fcf"},"md-movie_open_play":{"char":"󱜅","code":"f1705"},"md-movie_open_play_outline":{"char":"󱜆","code":"f1706"},"md-movie_open_plus":{"char":"󱜇","code":"f1707"},"md-movie_open_plus_outline":{"char":"󱜈","code":"f1708"},"md-movie_open_remove":{"char":"󱜉","code":"f1709"},"md-movie_open_remove_outline":{"char":"󱜊","code":"f170a"},"md-movie_open_settings":{"char":"󱜋","code":"f170b"},"md-movie_open_settings_outline":{"char":"󱜌","code":"f170c"},"md-movie_open_star":{"char":"󱜍","code":"f170d"},"md-movie_open_star_outline":{"char":"󱜎","code":"f170e"},"md-movie_outline":{"char":"󰷝","code":"f0ddd"},"md-movie_play":{"char":"󱜏","code":"f170f"},"md-movie_play_outline":{"char":"󱜐","code":"f1710"},"md-movie_plus":{"char":"󱜑","code":"f1711"},"md-movie_plus_outline":{"char":"󱜒","code":"f1712"},"md-movie_remove":{"char":"󱜓","code":"f1713"},"md-movie_remove_outline":{"char":"󱜔","code":"f1714"},"md-movie_roll":{"char":"󰟞","code":"f07de"},"md-movie_search":{"char":"󱇒","code":"f11d2"},"md-movie_search_outline":{"char":"󱇓","code":"f11d3"},"md-movie_settings":{"char":"󱜕","code":"f1715"},"md-movie_settings_outline":{"char":"󱜖","code":"f1716"},"md-movie_star":{"char":"󱜗","code":"f1717"},"md-movie_star_outline":{"char":"󱜘","code":"f1718"},"md-mower":{"char":"󱙯","code":"f166f"},"md-mower_bag":{"char":"󱙰","code":"f1670"},"md-muffin":{"char":"󰦌","code":"f098c"},"md-multicast":{"char":"󱢓","code":"f1893"},"md-multiplication":{"char":"󰎂","code":"f0382"},"md-multiplication_box":{"char":"󰎃","code":"f0383"},"md-mushroom":{"char":"󰟟","code":"f07df"},"md-mushroom_off":{"char":"󱏺","code":"f13fa"},"md-mushroom_off_outline":{"char":"󱏻","code":"f13fb"},"md-mushroom_outline":{"char":"󰟠","code":"f07e0"},"md-music":{"char":"󰝚","code":"f075a"},"md-music_accidental_double_flat":{"char":"󰽩","code":"f0f69"},"md-music_accidental_double_sharp":{"char":"󰽪","code":"f0f6a"},"md-music_accidental_flat":{"char":"󰽫","code":"f0f6b"},"md-music_accidental_natural":{"char":"󰽬","code":"f0f6c"},"md-music_accidental_sharp":{"char":"󰽭","code":"f0f6d"},"md-music_box":{"char":"󰎄","code":"f0384"},"md-music_box_multiple":{"char":"󰌳","code":"f0333"},"md-music_box_multiple_outline":{"char":"󰼄","code":"f0f04"},"md-music_box_outline":{"char":"󰎅","code":"f0385"},"md-music_circle":{"char":"󰎆","code":"f0386"},"md-music_circle_outline":{"char":"󰫔","code":"f0ad4"},"md-music_clef_alto":{"char":"󰽮","code":"f0f6e"},"md-music_clef_bass":{"char":"󰽯","code":"f0f6f"},"md-music_clef_treble":{"char":"󰽰","code":"f0f70"},"md-music_note":{"char":"󰎇","code":"f0387"},"md-music_note_bluetooth":{"char":"󰗾","code":"f05fe"},"md-music_note_bluetooth_off":{"char":"󰗿","code":"f05ff"},"md-music_note_eighth_dotted":{"char":"󰽱","code":"f0f71"},"md-music_note_half":{"char":"󰎉","code":"f0389"},"md-music_note_half_dotted":{"char":"󰽲","code":"f0f72"},"md-music_note_off":{"char":"󰎊","code":"f038a"},"md-music_note_off_outline":{"char":"󰽳","code":"f0f73"},"md-music_note_outline":{"char":"󰽴","code":"f0f74"},"md-music_note_plus":{"char":"󰷞","code":"f0dde"},"md-music_note_quarter":{"char":"󰎋","code":"f038b"},"md-music_note_quarter_dotted":{"char":"󰽵","code":"f0f75"},"md-music_note_sixteenth":{"char":"󰎌","code":"f038c"},"md-music_note_sixteenth_dotted":{"char":"󰽶","code":"f0f76"},"md-music_note_whole":{"char":"󰎍","code":"f038d"},"md-music_note_whole_dotted":{"char":"󰽷","code":"f0f77"},"md-music_off":{"char":"󰝛","code":"f075b"},"md-music_rest_eighth":{"char":"󰽸","code":"f0f78"},"md-music_rest_half":{"char":"󰽹","code":"f0f79"},"md-music_rest_quarter":{"char":"󰽺","code":"f0f7a"},"md-music_rest_sixteenth":{"char":"󰽻","code":"f0f7b"},"md-music_rest_whole":{"char":"󰽼","code":"f0f7c"},"md-mustache":{"char":"󱗞","code":"f15de"},"md-nail":{"char":"󰷟","code":"f0ddf"},"md-nas":{"char":"󰣳","code":"f08f3"},"md-nativescript":{"char":"󰢀","code":"f0880"},"md-nature":{"char":"󰎎","code":"f038e"},"md-nature_people":{"char":"󰎏","code":"f038f"},"md-navigation":{"char":"󰎐","code":"f0390"},"md-navigation_outline":{"char":"󱘇","code":"f1607"},"md-navigation_variant_outline":{"char":"󱣱","code":"f18f1"},"md-near_me":{"char":"󰗍","code":"f05cd"},"md-necklace":{"char":"󰼋","code":"f0f0b"},"md-needle":{"char":"󰎑","code":"f0391"},"md-needle_off":{"char":"󱧒","code":"f19d2"},"md-netflix":{"char":"󰝆","code":"f0746"},"md-network":{"char":"󰛳","code":"f06f3"},"md-network_off":{"char":"󰲛","code":"f0c9b"},"md-network_off_outline":{"char":"󰲜","code":"f0c9c"},"md-network_outline":{"char":"󰲝","code":"f0c9d"},"md-network_pos":{"char":"󱫋","code":"f1acb"},"md-network_strength_1":{"char":"󰣴","code":"f08f4"},"md-network_strength_1_alert":{"char":"󰣵","code":"f08f5"},"md-network_strength_2":{"char":"󰣶","code":"f08f6"},"md-network_strength_2_alert":{"char":"󰣷","code":"f08f7"},"md-network_strength_3":{"char":"󰣸","code":"f08f8"},"md-network_strength_3_alert":{"char":"󰣹","code":"f08f9"},"md-network_strength_4":{"char":"󰣺","code":"f08fa"},"md-network_strength_4_alert":{"char":"󰣻","code":"f08fb"},"md-network_strength_4_cog":{"char":"󱤚","code":"f191a"},"md-network_strength_off":{"char":"󰣼","code":"f08fc"},"md-network_strength_off_outline":{"char":"󰣽","code":"f08fd"},"md-network_strength_outline":{"char":"󰣾","code":"f08fe"},"md-new_box":{"char":"󰎔","code":"f0394"},"md-newspaper":{"char":"󰎕","code":"f0395"},"md-newspaper_check":{"char":"󱥃","code":"f1943"},"md-newspaper_minus":{"char":"󰼌","code":"f0f0c"},"md-newspaper_plus":{"char":"󰼍","code":"f0f0d"},"md-newspaper_remove":{"char":"󱥄","code":"f1944"},"md-newspaper_variant":{"char":"󱀁","code":"f1001"},"md-newspaper_variant_multiple":{"char":"󱀂","code":"f1002"},"md-newspaper_variant_multiple_outline":{"char":"󱀃","code":"f1003"},"md-newspaper_variant_outline":{"char":"󱀄","code":"f1004"},"md-nfc":{"char":"󰎖","code":"f0396"},"md-nfc_search_variant":{"char":"󰹓","code":"f0e53"},"md-nfc_tap":{"char":"󰎗","code":"f0397"},"md-nfc_variant":{"char":"󰎘","code":"f0398"},"md-nfc_variant_off":{"char":"󰹔","code":"f0e54"},"md-ninja":{"char":"󰝴","code":"f0774"},"md-nintendo_game_boy":{"char":"󱎓","code":"f1393"},"md-nintendo_switch":{"char":"󰟡","code":"f07e1"},"md-nintendo_wii":{"char":"󰖫","code":"f05ab"},"md-nintendo_wiiu":{"char":"󰜭","code":"f072d"},"md-nix":{"char":"󱄅","code":"f1105"},"md-nodejs":{"char":"󰎙","code":"f0399"},"md-noodles":{"char":"󱅾","code":"f117e"},"md-not_equal":{"char":"󰦍","code":"f098d"},"md-not_equal_variant":{"char":"󰦎","code":"f098e"},"md-note":{"char":"󰎚","code":"f039a"},"md-note_alert":{"char":"󱝽","code":"f177d"},"md-note_alert_outline":{"char":"󱝾","code":"f177e"},"md-note_check":{"char":"󱝿","code":"f177f"},"md-note_check_outline":{"char":"󱞀","code":"f1780"},"md-note_edit":{"char":"󱞁","code":"f1781"},"md-note_edit_outline":{"char":"󱞂","code":"f1782"},"md-note_minus":{"char":"󱙏","code":"f164f"},"md-note_minus_outline":{"char":"󱙐","code":"f1650"},"md-note_multiple":{"char":"󰚸","code":"f06b8"},"md-note_multiple_outline":{"char":"󰚹","code":"f06b9"},"md-note_off":{"char":"󱞃","code":"f1783"},"md-note_off_outline":{"char":"󱞄","code":"f1784"},"md-note_outline":{"char":"󰎛","code":"f039b"},"md-note_plus":{"char":"󰎜","code":"f039c"},"md-note_plus_outline":{"char":"󰎝","code":"f039d"},"md-note_remove":{"char":"󱙑","code":"f1651"},"md-note_remove_outline":{"char":"󱙒","code":"f1652"},"md-note_search":{"char":"󱙓","code":"f1653"},"md-note_search_outline":{"char":"󱙔","code":"f1654"},"md-note_text":{"char":"󰎞","code":"f039e"},"md-note_text_outline":{"char":"󱇗","code":"f11d7"},"md-notebook":{"char":"󰠮","code":"f082e"},"md-notebook_check":{"char":"󱓵","code":"f14f5"},"md-notebook_check_outline":{"char":"󱓶","code":"f14f6"},"md-notebook_edit":{"char":"󱓧","code":"f14e7"},"md-notebook_edit_outline":{"char":"󱓩","code":"f14e9"},"md-notebook_heart":{"char":"󱨋","code":"f1a0b"},"md-notebook_heart_outline":{"char":"󱨌","code":"f1a0c"},"md-notebook_minus":{"char":"󱘐","code":"f1610"},"md-notebook_minus_outline":{"char":"󱘑","code":"f1611"},"md-notebook_multiple":{"char":"󰹕","code":"f0e55"},"md-notebook_outline":{"char":"󰺿","code":"f0ebf"},"md-notebook_plus":{"char":"󱘒","code":"f1612"},"md-notebook_plus_outline":{"char":"󱘓","code":"f1613"},"md-notebook_remove":{"char":"󱘔","code":"f1614"},"md-notebook_remove_outline":{"char":"󱘕","code":"f1615"},"md-notification_clear_all":{"char":"󰎟","code":"f039f"},"md-npm":{"char":"󰛷","code":"f06f7"},"md-nuke":{"char":"󰚤","code":"f06a4"},"md-null":{"char":"󰟢","code":"f07e2"},"md-numeric":{"char":"󰎠","code":"f03a0"},"md-numeric_0_box":{"char":"󰎡","code":"f03a1"},"md-numeric_0_box_multiple":{"char":"󰼎","code":"f0f0e"},"md-numeric_0_box_multiple_outline":{"char":"󰎢","code":"f03a2"},"md-numeric_0_box_outline":{"char":"󰎣","code":"f03a3"},"md-numeric_1":{"char":"󰬺","code":"f0b3a"},"md-numeric_10":{"char":"󰿩","code":"f0fe9"},"md-numeric_10_box":{"char":"󰽽","code":"f0f7d"},"md-numeric_10_box_multiple":{"char":"󰿪","code":"f0fea"},"md-numeric_10_box_multiple_outline":{"char":"󰿫","code":"f0feb"},"md-numeric_10_box_outline":{"char":"󰽾","code":"f0f7e"},"md-numeric_10_circle":{"char":"󰿬","code":"f0fec"},"md-numeric_10_circle_outline":{"char":"󰿭","code":"f0fed"},"md-numeric_1_box":{"char":"󰎤","code":"f03a4"},"md-numeric_1_box_multiple":{"char":"󰼏","code":"f0f0f"},"md-numeric_1_box_multiple_outline":{"char":"󰎥","code":"f03a5"},"md-numeric_1_box_outline":{"char":"󰎦","code":"f03a6"},"md-numeric_1_circle":{"char":"󰲠","code":"f0ca0"},"md-numeric_1_circle_outline":{"char":"󰲡","code":"f0ca1"},"md-numeric_2":{"char":"󰬻","code":"f0b3b"},"md-numeric_2_box":{"char":"󰎧","code":"f03a7"},"md-numeric_2_box_multiple":{"char":"󰼐","code":"f0f10"},"md-numeric_2_box_multiple_outline":{"char":"󰎨","code":"f03a8"},"md-numeric_2_box_outline":{"char":"󰎩","code":"f03a9"},"md-numeric_2_circle":{"char":"󰲢","code":"f0ca2"},"md-numeric_2_circle_outline":{"char":"󰲣","code":"f0ca3"},"md-numeric_3":{"char":"󰬼","code":"f0b3c"},"md-numeric_3_box":{"char":"󰎪","code":"f03aa"},"md-numeric_3_box_multiple":{"char":"󰼑","code":"f0f11"},"md-numeric_3_box_multiple_outline":{"char":"󰎫","code":"f03ab"},"md-numeric_3_box_outline":{"char":"󰎬","code":"f03ac"},"md-numeric_3_circle":{"char":"󰲤","code":"f0ca4"},"md-numeric_3_circle_outline":{"char":"󰲥","code":"f0ca5"},"md-numeric_4":{"char":"󰬽","code":"f0b3d"},"md-numeric_4_box":{"char":"󰎭","code":"f03ad"},"md-numeric_4_box_multiple":{"char":"󰼒","code":"f0f12"},"md-numeric_4_box_multiple_outline":{"char":"󰎲","code":"f03b2"},"md-numeric_4_box_outline":{"char":"󰎮","code":"f03ae"},"md-numeric_4_circle":{"char":"󰲦","code":"f0ca6"},"md-numeric_4_circle_outline":{"char":"󰲧","code":"f0ca7"},"md-numeric_5":{"char":"󰬾","code":"f0b3e"},"md-numeric_5_box":{"char":"󰎱","code":"f03b1"},"md-numeric_5_box_multiple":{"char":"󰼓","code":"f0f13"},"md-numeric_5_box_multiple_outline":{"char":"󰎯","code":"f03af"},"md-numeric_5_box_outline":{"char":"󰎰","code":"f03b0"},"md-numeric_5_circle":{"char":"󰲨","code":"f0ca8"},"md-numeric_5_circle_outline":{"char":"󰲩","code":"f0ca9"},"md-numeric_6":{"char":"󰬿","code":"f0b3f"},"md-numeric_6_box":{"char":"󰎳","code":"f03b3"},"md-numeric_6_box_multiple":{"char":"󰼔","code":"f0f14"},"md-numeric_6_box_multiple_outline":{"char":"󰎴","code":"f03b4"},"md-numeric_6_box_outline":{"char":"󰎵","code":"f03b5"},"md-numeric_6_circle":{"char":"󰲪","code":"f0caa"},"md-numeric_6_circle_outline":{"char":"󰲫","code":"f0cab"},"md-numeric_7":{"char":"󰭀","code":"f0b40"},"md-numeric_7_box":{"char":"󰎶","code":"f03b6"},"md-numeric_7_box_multiple":{"char":"󰼕","code":"f0f15"},"md-numeric_7_box_multiple_outline":{"char":"󰎷","code":"f03b7"},"md-numeric_7_box_outline":{"char":"󰎸","code":"f03b8"},"md-numeric_7_circle":{"char":"󰲬","code":"f0cac"},"md-numeric_7_circle_outline":{"char":"󰲭","code":"f0cad"},"md-numeric_8":{"char":"󰭁","code":"f0b41"},"md-numeric_8_box":{"char":"󰎹","code":"f03b9"},"md-numeric_8_box_multiple":{"char":"󰼖","code":"f0f16"},"md-numeric_8_box_multiple_outline":{"char":"󰎺","code":"f03ba"},"md-numeric_8_box_outline":{"char":"󰎻","code":"f03bb"},"md-numeric_8_circle":{"char":"󰲮","code":"f0cae"},"md-numeric_8_circle_outline":{"char":"󰲯","code":"f0caf"},"md-numeric_9":{"char":"󰭂","code":"f0b42"},"md-numeric_9_box":{"char":"󰎼","code":"f03bc"},"md-numeric_9_box_multiple":{"char":"󰼗","code":"f0f17"},"md-numeric_9_box_multiple_outline":{"char":"󰎽","code":"f03bd"},"md-numeric_9_box_outline":{"char":"󰎾","code":"f03be"},"md-numeric_9_circle":{"char":"󰲰","code":"f0cb0"},"md-numeric_9_circle_outline":{"char":"󰲱","code":"f0cb1"},"md-numeric_9_plus":{"char":"󰿮","code":"f0fee"},"md-numeric_9_plus_box":{"char":"󰎿","code":"f03bf"},"md-numeric_9_plus_box_multiple":{"char":"󰼘","code":"f0f18"},"md-numeric_9_plus_box_multiple_outline":{"char":"󰏀","code":"f03c0"},"md-numeric_9_plus_box_outline":{"char":"󰏁","code":"f03c1"},"md-numeric_9_plus_circle":{"char":"󰲲","code":"f0cb2"},"md-numeric_9_plus_circle_outline":{"char":"󰲳","code":"f0cb3"},"md-numeric_negative_1":{"char":"󱁒","code":"f1052"},"md-numeric_off":{"char":"󱧓","code":"f19d3"},"md-numeric_positive_1":{"char":"󱗋","code":"f15cb"},"md-nut":{"char":"󰛸","code":"f06f8"},"md-nutrition":{"char":"󰏂","code":"f03c2"},"md-nuxt":{"char":"󱄆","code":"f1106"},"md-oar":{"char":"󰙼","code":"f067c"},"md-ocarina":{"char":"󰷠","code":"f0de0"},"md-oci":{"char":"󱋩","code":"f12e9"},"md-ocr":{"char":"󱄺","code":"f113a"},"md-octagon":{"char":"󰏃","code":"f03c3"},"md-octagon_outline":{"char":"󰏄","code":"f03c4"},"md-octagram":{"char":"󰛹","code":"f06f9"},"md-octagram_outline":{"char":"󰝵","code":"f0775"},"md-octahedron":{"char":"󱥐","code":"f1950"},"md-octahedron_off":{"char":"󱥑","code":"f1951"},"md-odnoklassniki":{"char":"󰏅","code":"f03c5"},"md-offer":{"char":"󱈛","code":"f121b"},"md-office_building":{"char":"󰦑","code":"f0991"},"md-office_building_cog":{"char":"󱥉","code":"f1949"},"md-office_building_cog_outline":{"char":"󱥊","code":"f194a"},"md-office_building_marker":{"char":"󱔠","code":"f1520"},"md-office_building_marker_outline":{"char":"󱔡","code":"f1521"},"md-office_building_outline":{"char":"󱔟","code":"f151f"},"md-oil":{"char":"󰏇","code":"f03c7"},"md-oil_lamp":{"char":"󰼙","code":"f0f19"},"md-oil_level":{"char":"󱁓","code":"f1053"},"md-oil_temperature":{"char":"󰿸","code":"f0ff8"},"md-om":{"char":"󰥳","code":"f0973"},"md-omega":{"char":"󰏉","code":"f03c9"},"md-one_up":{"char":"󰮭","code":"f0bad"},"md-onepassword":{"char":"󰢁","code":"f0881"},"md-opacity":{"char":"󰗌","code":"f05cc"},"md-open_in_app":{"char":"󰏋","code":"f03cb"},"md-open_in_new":{"char":"󰏌","code":"f03cc"},"md-open_source_initiative":{"char":"󰮮","code":"f0bae"},"md-openid":{"char":"󰏍","code":"f03cd"},"md-opera":{"char":"󰏎","code":"f03ce"},"md-orbit":{"char":"󰀘","code":"f0018"},"md-orbit_variant":{"char":"󱗛","code":"f15db"},"md-order_alphabetical_ascending":{"char":"󰈍","code":"f020d"},"md-order_alphabetical_descending":{"char":"󰴇","code":"f0d07"},"md-order_bool_ascending":{"char":"󰊾","code":"f02be"},"md-order_bool_ascending_variant":{"char":"󰦏","code":"f098f"},"md-order_bool_descending":{"char":"󱎄","code":"f1384"},"md-order_bool_descending_variant":{"char":"󰦐","code":"f0990"},"md-order_numeric_ascending":{"char":"󰕅","code":"f0545"},"md-order_numeric_descending":{"char":"󰕆","code":"f0546"},"md-origin":{"char":"󰭃","code":"f0b43"},"md-ornament":{"char":"󰏏","code":"f03cf"},"md-ornament_variant":{"char":"󰏐","code":"f03d0"},"md-outdoor_lamp":{"char":"󱁔","code":"f1054"},"md-overscan":{"char":"󱀅","code":"f1005"},"md-owl":{"char":"󰏒","code":"f03d2"},"md-pac_man":{"char":"󰮯","code":"f0baf"},"md-package":{"char":"󰏓","code":"f03d3"},"md-package_down":{"char":"󰏔","code":"f03d4"},"md-package_up":{"char":"󰏕","code":"f03d5"},"md-package_variant":{"char":"󰏖","code":"f03d6"},"md-package_variant_closed":{"char":"󰏗","code":"f03d7"},"md-package_variant_closed_minus":{"char":"󱧔","code":"f19d4"},"md-package_variant_closed_plus":{"char":"󱧕","code":"f19d5"},"md-package_variant_closed_remove":{"char":"󱧖","code":"f19d6"},"md-package_variant_minus":{"char":"󱧗","code":"f19d7"},"md-package_variant_plus":{"char":"󱧘","code":"f19d8"},"md-package_variant_remove":{"char":"󱧙","code":"f19d9"},"md-page_first":{"char":"󰘀","code":"f0600"},"md-page_last":{"char":"󰘁","code":"f0601"},"md-page_layout_body":{"char":"󰛺","code":"f06fa"},"md-page_layout_footer":{"char":"󰛻","code":"f06fb"},"md-page_layout_header":{"char":"󰛼","code":"f06fc"},"md-page_layout_header_footer":{"char":"󰽿","code":"f0f7f"},"md-page_layout_sidebar_left":{"char":"󰛽","code":"f06fd"},"md-page_layout_sidebar_right":{"char":"󰛾","code":"f06fe"},"md-page_next":{"char":"󰮰","code":"f0bb0"},"md-page_next_outline":{"char":"󰮱","code":"f0bb1"},"md-page_previous":{"char":"󰮲","code":"f0bb2"},"md-page_previous_outline":{"char":"󰮳","code":"f0bb3"},"md-pail":{"char":"󱐗","code":"f1417"},"md-pail_minus":{"char":"󱐷","code":"f1437"},"md-pail_minus_outline":{"char":"󱐼","code":"f143c"},"md-pail_off":{"char":"󱐹","code":"f1439"},"md-pail_off_outline":{"char":"󱐾","code":"f143e"},"md-pail_outline":{"char":"󱐺","code":"f143a"},"md-pail_plus":{"char":"󱐶","code":"f1436"},"md-pail_plus_outline":{"char":"󱐻","code":"f143b"},"md-pail_remove":{"char":"󱐸","code":"f1438"},"md-pail_remove_outline":{"char":"󱐽","code":"f143d"},"md-palette":{"char":"󰏘","code":"f03d8"},"md-palette_advanced":{"char":"󰏙","code":"f03d9"},"md-palette_outline":{"char":"󰸌","code":"f0e0c"},"md-palette_swatch":{"char":"󰢵","code":"f08b5"},"md-palette_swatch_outline":{"char":"󱍜","code":"f135c"},"md-palette_swatch_variant":{"char":"󱥚","code":"f195a"},"md-palm_tree":{"char":"󱁕","code":"f1055"},"md-pan":{"char":"󰮴","code":"f0bb4"},"md-pan_bottom_left":{"char":"󰮵","code":"f0bb5"},"md-pan_bottom_right":{"char":"󰮶","code":"f0bb6"},"md-pan_down":{"char":"󰮷","code":"f0bb7"},"md-pan_horizontal":{"char":"󰮸","code":"f0bb8"},"md-pan_left":{"char":"󰮹","code":"f0bb9"},"md-pan_right":{"char":"󰮺","code":"f0bba"},"md-pan_top_left":{"char":"󰮻","code":"f0bbb"},"md-pan_top_right":{"char":"󰮼","code":"f0bbc"},"md-pan_up":{"char":"󰮽","code":"f0bbd"},"md-pan_vertical":{"char":"󰮾","code":"f0bbe"},"md-panda":{"char":"󰏚","code":"f03da"},"md-pandora":{"char":"󰏛","code":"f03db"},"md-panorama":{"char":"󰏜","code":"f03dc"},"md-panorama_fisheye":{"char":"󰏝","code":"f03dd"},"md-panorama_horizontal":{"char":"󱤨","code":"f1928"},"md-panorama_horizontal_outline":{"char":"󰏞","code":"f03de"},"md-panorama_outline":{"char":"󱦌","code":"f198c"},"md-panorama_sphere":{"char":"󱦍","code":"f198d"},"md-panorama_sphere_outline":{"char":"󱦎","code":"f198e"},"md-panorama_variant":{"char":"󱦏","code":"f198f"},"md-panorama_variant_outline":{"char":"󱦐","code":"f1990"},"md-panorama_vertical":{"char":"󱤩","code":"f1929"},"md-panorama_vertical_outline":{"char":"󰏟","code":"f03df"},"md-panorama_wide_angle":{"char":"󱥟","code":"f195f"},"md-panorama_wide_angle_outline":{"char":"󰏠","code":"f03e0"},"md-paper_cut_vertical":{"char":"󰏡","code":"f03e1"},"md-paper_roll":{"char":"󱅗","code":"f1157"},"md-paper_roll_outline":{"char":"󱅘","code":"f1158"},"md-paperclip":{"char":"󰏢","code":"f03e2"},"md-paperclip_check":{"char":"󱫆","code":"f1ac6"},"md-paperclip_lock":{"char":"󱧚","code":"f19da"},"md-paperclip_minus":{"char":"󱫇","code":"f1ac7"},"md-paperclip_off":{"char":"󱫈","code":"f1ac8"},"md-paperclip_plus":{"char":"󱫉","code":"f1ac9"},"md-paperclip_remove":{"char":"󱫊","code":"f1aca"},"md-parachute":{"char":"󰲴","code":"f0cb4"},"md-parachute_outline":{"char":"󰲵","code":"f0cb5"},"md-paragliding":{"char":"󱝅","code":"f1745"},"md-parking":{"char":"󰏣","code":"f03e3"},"md-party_popper":{"char":"󱁖","code":"f1056"},"md-passport":{"char":"󰟣","code":"f07e3"},"md-passport_biometric":{"char":"󰷡","code":"f0de1"},"md-pasta":{"char":"󱅠","code":"f1160"},"md-patio_heater":{"char":"󰾀","code":"f0f80"},"md-patreon":{"char":"󰢂","code":"f0882"},"md-pause":{"char":"󰏤","code":"f03e4"},"md-pause_circle":{"char":"󰏥","code":"f03e5"},"md-pause_circle_outline":{"char":"󰏦","code":"f03e6"},"md-pause_octagon":{"char":"󰏧","code":"f03e7"},"md-pause_octagon_outline":{"char":"󰏨","code":"f03e8"},"md-paw":{"char":"󰏩","code":"f03e9"},"md-paw_off":{"char":"󰙗","code":"f0657"},"md-paw_off_outline":{"char":"󱙶","code":"f1676"},"md-paw_outline":{"char":"󱙵","code":"f1675"},"md-peace":{"char":"󰢄","code":"f0884"},"md-peanut":{"char":"󰿼","code":"f0ffc"},"md-peanut_off":{"char":"󰿽","code":"f0ffd"},"md-peanut_off_outline":{"char":"󰿿","code":"f0fff"},"md-peanut_outline":{"char":"󰿾","code":"f0ffe"},"md-pen":{"char":"󰏪","code":"f03ea"},"md-pen_lock":{"char":"󰷢","code":"f0de2"},"md-pen_minus":{"char":"󰷣","code":"f0de3"},"md-pen_off":{"char":"󰷤","code":"f0de4"},"md-pen_plus":{"char":"󰷥","code":"f0de5"},"md-pen_remove":{"char":"󰷦","code":"f0de6"},"md-pencil":{"char":"󰏫","code":"f03eb"},"md-pencil_box":{"char":"󰏬","code":"f03ec"},"md-pencil_box_multiple":{"char":"󱅄","code":"f1144"},"md-pencil_box_multiple_outline":{"char":"󱅅","code":"f1145"},"md-pencil_box_outline":{"char":"󰏭","code":"f03ed"},"md-pencil_circle":{"char":"󰛿","code":"f06ff"},"md-pencil_circle_outline":{"char":"󰝶","code":"f0776"},"md-pencil_lock":{"char":"󰏮","code":"f03ee"},"md-pencil_lock_outline":{"char":"󰷧","code":"f0de7"},"md-pencil_minus":{"char":"󰷨","code":"f0de8"},"md-pencil_minus_outline":{"char":"󰷩","code":"f0de9"},"md-pencil_off":{"char":"󰏯","code":"f03ef"},"md-pencil_off_outline":{"char":"󰷪","code":"f0dea"},"md-pencil_outline":{"char":"󰲶","code":"f0cb6"},"md-pencil_plus":{"char":"󰷫","code":"f0deb"},"md-pencil_plus_outline":{"char":"󰷬","code":"f0dec"},"md-pencil_remove":{"char":"󰷭","code":"f0ded"},"md-pencil_remove_outline":{"char":"󰷮","code":"f0dee"},"md-pencil_ruler":{"char":"󱍓","code":"f1353"},"md-penguin":{"char":"󰻀","code":"f0ec0"},"md-pentagon":{"char":"󰜁","code":"f0701"},"md-pentagon_outline":{"char":"󰜀","code":"f0700"},"md-pentagram":{"char":"󱙧","code":"f1667"},"md-percent":{"char":"󰏰","code":"f03f0"},"md-percent_box":{"char":"󱨂","code":"f1a02"},"md-percent_box_outline":{"char":"󱨃","code":"f1a03"},"md-percent_circle":{"char":"󱨄","code":"f1a04"},"md-percent_circle_outline":{"char":"󱨅","code":"f1a05"},"md-percent_outline":{"char":"󱉸","code":"f1278"},"md-periodic_table":{"char":"󰢶","code":"f08b6"},"md-perspective_less":{"char":"󰴣","code":"f0d23"},"md-perspective_more":{"char":"󰴤","code":"f0d24"},"md-ph":{"char":"󱟅","code":"f17c5"},"md-phone":{"char":"󰏲","code":"f03f2"},"md-phone_alert":{"char":"󰼚","code":"f0f1a"},"md-phone_alert_outline":{"char":"󱆎","code":"f118e"},"md-phone_bluetooth":{"char":"󰏳","code":"f03f3"},"md-phone_bluetooth_outline":{"char":"󱆏","code":"f118f"},"md-phone_cancel":{"char":"󱂼","code":"f10bc"},"md-phone_cancel_outline":{"char":"󱆐","code":"f1190"},"md-phone_check":{"char":"󱆩","code":"f11a9"},"md-phone_check_outline":{"char":"󱆪","code":"f11aa"},"md-phone_classic":{"char":"󰘂","code":"f0602"},"md-phone_classic_off":{"char":"󱉹","code":"f1279"},"md-phone_clock":{"char":"󱧛","code":"f19db"},"md-phone_dial":{"char":"󱕙","code":"f1559"},"md-phone_dial_outline":{"char":"󱕚","code":"f155a"},"md-phone_forward":{"char":"󰏴","code":"f03f4"},"md-phone_forward_outline":{"char":"󱆑","code":"f1191"},"md-phone_hangup":{"char":"󰏵","code":"f03f5"},"md-phone_hangup_outline":{"char":"󱆒","code":"f1192"},"md-phone_in_talk":{"char":"󰏶","code":"f03f6"},"md-phone_in_talk_outline":{"char":"󱆂","code":"f1182"},"md-phone_incoming":{"char":"󰏷","code":"f03f7"},"md-phone_incoming_outline":{"char":"󱆓","code":"f1193"},"md-phone_lock":{"char":"󰏸","code":"f03f8"},"md-phone_lock_outline":{"char":"󱆔","code":"f1194"},"md-phone_log":{"char":"󰏹","code":"f03f9"},"md-phone_log_outline":{"char":"󱆕","code":"f1195"},"md-phone_message":{"char":"󱆖","code":"f1196"},"md-phone_message_outline":{"char":"󱆗","code":"f1197"},"md-phone_minus":{"char":"󰙘","code":"f0658"},"md-phone_minus_outline":{"char":"󱆘","code":"f1198"},"md-phone_missed":{"char":"󰏺","code":"f03fa"},"md-phone_missed_outline":{"char":"󱆥","code":"f11a5"},"md-phone_off":{"char":"󰷯","code":"f0def"},"md-phone_off_outline":{"char":"󱆦","code":"f11a6"},"md-phone_outgoing":{"char":"󰏻","code":"f03fb"},"md-phone_outgoing_outline":{"char":"󱆙","code":"f1199"},"md-phone_outline":{"char":"󰷰","code":"f0df0"},"md-phone_paused":{"char":"󰏼","code":"f03fc"},"md-phone_paused_outline":{"char":"󱆚","code":"f119a"},"md-phone_plus":{"char":"󰙙","code":"f0659"},"md-phone_plus_outline":{"char":"󱆛","code":"f119b"},"md-phone_refresh":{"char":"󱦓","code":"f1993"},"md-phone_refresh_outline":{"char":"󱦔","code":"f1994"},"md-phone_remove":{"char":"󱔯","code":"f152f"},"md-phone_remove_outline":{"char":"󱔰","code":"f1530"},"md-phone_return":{"char":"󰠯","code":"f082f"},"md-phone_return_outline":{"char":"󱆜","code":"f119c"},"md-phone_ring":{"char":"󱆫","code":"f11ab"},"md-phone_ring_outline":{"char":"󱆬","code":"f11ac"},"md-phone_rotate_landscape":{"char":"󰢅","code":"f0885"},"md-phone_rotate_portrait":{"char":"󰢆","code":"f0886"},"md-phone_settings":{"char":"󰏽","code":"f03fd"},"md-phone_settings_outline":{"char":"󱆝","code":"f119d"},"md-phone_sync":{"char":"󱦕","code":"f1995"},"md-phone_sync_outline":{"char":"󱦖","code":"f1996"},"md-phone_voip":{"char":"󰏾","code":"f03fe"},"md-pi":{"char":"󰏿","code":"f03ff"},"md-pi_box":{"char":"󰐀","code":"f0400"},"md-pi_hole":{"char":"󰷱","code":"f0df1"},"md-piano":{"char":"󰙽","code":"f067d"},"md-piano_off":{"char":"󰚘","code":"f0698"},"md-pickaxe":{"char":"󰢷","code":"f08b7"},"md-picture_in_picture_bottom_right":{"char":"󰹗","code":"f0e57"},"md-picture_in_picture_bottom_right_outline":{"char":"󰹘","code":"f0e58"},"md-picture_in_picture_top_right":{"char":"󰹙","code":"f0e59"},"md-picture_in_picture_top_right_outline":{"char":"󰹚","code":"f0e5a"},"md-pier":{"char":"󰢇","code":"f0887"},"md-pier_crane":{"char":"󰢈","code":"f0888"},"md-pig":{"char":"󰐁","code":"f0401"},"md-pig_variant":{"char":"󱀆","code":"f1006"},"md-pig_variant_outline":{"char":"󱙸","code":"f1678"},"md-piggy_bank":{"char":"󱀇","code":"f1007"},"md-piggy_bank_outline":{"char":"󱙹","code":"f1679"},"md-pill":{"char":"󰐂","code":"f0402"},"md-pill_off":{"char":"󱩜","code":"f1a5c"},"md-pillar":{"char":"󰜂","code":"f0702"},"md-pin":{"char":"󰐃","code":"f0403"},"md-pin_off":{"char":"󰐄","code":"f0404"},"md-pin_off_outline":{"char":"󰤰","code":"f0930"},"md-pin_outline":{"char":"󰤱","code":"f0931"},"md-pine_tree":{"char":"󰐅","code":"f0405"},"md-pine_tree_box":{"char":"󰐆","code":"f0406"},"md-pine_tree_fire":{"char":"󱐚","code":"f141a"},"md-pinterest":{"char":"󰐇","code":"f0407"},"md-pinwheel":{"char":"󰫕","code":"f0ad5"},"md-pinwheel_outline":{"char":"󰫖","code":"f0ad6"},"md-pipe":{"char":"󰟥","code":"f07e5"},"md-pipe_disconnected":{"char":"󰟦","code":"f07e6"},"md-pipe_leak":{"char":"󰢉","code":"f0889"},"md-pipe_valve":{"char":"󱡍","code":"f184d"},"md-pipe_wrench":{"char":"󱍔","code":"f1354"},"md-pirate":{"char":"󰨈","code":"f0a08"},"md-pistol":{"char":"󰜃","code":"f0703"},"md-piston":{"char":"󰢊","code":"f088a"},"md-pitchfork":{"char":"󱕓","code":"f1553"},"md-pizza":{"char":"󰐉","code":"f0409"},"md-play":{"char":"󰐊","code":"f040a"},"md-play_box":{"char":"󱉺","code":"f127a"},"md-play_box_lock":{"char":"󱨖","code":"f1a16"},"md-play_box_lock_open":{"char":"󱨗","code":"f1a17"},"md-play_box_lock_open_outline":{"char":"󱨘","code":"f1a18"},"md-play_box_lock_outline":{"char":"󱨙","code":"f1a19"},"md-play_box_multiple":{"char":"󰴙","code":"f0d19"},"md-play_box_multiple_outline":{"char":"󱏦","code":"f13e6"},"md-play_box_outline":{"char":"󰐋","code":"f040b"},"md-play_circle":{"char":"󰐌","code":"f040c"},"md-play_circle_outline":{"char":"󰐍","code":"f040d"},"md-play_network":{"char":"󰢋","code":"f088b"},"md-play_network_outline":{"char":"󰲷","code":"f0cb7"},"md-play_outline":{"char":"󰼛","code":"f0f1b"},"md-play_pause":{"char":"󰐎","code":"f040e"},"md-play_protected_content":{"char":"󰐏","code":"f040f"},"md-play_speed":{"char":"󰣿","code":"f08ff"},"md-playlist_check":{"char":"󰗇","code":"f05c7"},"md-playlist_edit":{"char":"󰤀","code":"f0900"},"md-playlist_minus":{"char":"󰐐","code":"f0410"},"md-playlist_music":{"char":"󰲸","code":"f0cb8"},"md-playlist_music_outline":{"char":"󰲹","code":"f0cb9"},"md-playlist_play":{"char":"󰐑","code":"f0411"},"md-playlist_plus":{"char":"󰐒","code":"f0412"},"md-playlist_remove":{"char":"󰐓","code":"f0413"},"md-playlist_star":{"char":"󰷲","code":"f0df2"},"md-plex":{"char":"󰚺","code":"f06ba"},"md-pliers":{"char":"󱦤","code":"f19a4"},"md-plus":{"char":"󰐕","code":"f0415"},"md-plus_box":{"char":"󰐖","code":"f0416"},"md-plus_box_multiple":{"char":"󰌴","code":"f0334"},"md-plus_box_multiple_outline":{"char":"󱅃","code":"f1143"},"md-plus_box_outline":{"char":"󰜄","code":"f0704"},"md-plus_circle":{"char":"󰐗","code":"f0417"},"md-plus_circle_multiple":{"char":"󰍌","code":"f034c"},"md-plus_circle_multiple_outline":{"char":"󰐘","code":"f0418"},"md-plus_circle_outline":{"char":"󰐙","code":"f0419"},"md-plus_lock":{"char":"󱩝","code":"f1a5d"},"md-plus_lock_open":{"char":"󱩞","code":"f1a5e"},"md-plus_minus":{"char":"󰦒","code":"f0992"},"md-plus_minus_box":{"char":"󰦓","code":"f0993"},"md-plus_minus_variant":{"char":"󱓉","code":"f14c9"},"md-plus_network":{"char":"󰐚","code":"f041a"},"md-plus_network_outline":{"char":"󰲺","code":"f0cba"},"md-plus_outline":{"char":"󰜅","code":"f0705"},"md-plus_thick":{"char":"󱇬","code":"f11ec"},"md-podcast":{"char":"󰦔","code":"f0994"},"md-podium":{"char":"󰴥","code":"f0d25"},"md-podium_bronze":{"char":"󰴦","code":"f0d26"},"md-podium_gold":{"char":"󰴧","code":"f0d27"},"md-podium_silver":{"char":"󰴨","code":"f0d28"},"md-point_of_sale":{"char":"󰶒","code":"f0d92"},"md-pokeball":{"char":"󰐝","code":"f041d"},"md-pokemon_go":{"char":"󰨉","code":"f0a09"},"md-poker_chip":{"char":"󰠰","code":"f0830"},"md-polaroid":{"char":"󰐞","code":"f041e"},"md-police_badge":{"char":"󱅧","code":"f1167"},"md-police_badge_outline":{"char":"󱅨","code":"f1168"},"md-police_station":{"char":"󱠹","code":"f1839"},"md-poll":{"char":"󰐟","code":"f041f"},"md-polo":{"char":"󱓃","code":"f14c3"},"md-polymer":{"char":"󰐡","code":"f0421"},"md-pool":{"char":"󰘆","code":"f0606"},"md-pool_thermometer":{"char":"󱩟","code":"f1a5f"},"md-popcorn":{"char":"󰐢","code":"f0422"},"md-post":{"char":"󱀈","code":"f1008"},"md-post_lamp":{"char":"󱩠","code":"f1a60"},"md-post_outline":{"char":"󱀉","code":"f1009"},"md-postage_stamp":{"char":"󰲻","code":"f0cbb"},"md-pot":{"char":"󰋥","code":"f02e5"},"md-pot_mix":{"char":"󰙛","code":"f065b"},"md-pot_mix_outline":{"char":"󰙷","code":"f0677"},"md-pot_outline":{"char":"󰋿","code":"f02ff"},"md-pot_steam":{"char":"󰙚","code":"f065a"},"md-pot_steam_outline":{"char":"󰌦","code":"f0326"},"md-pound":{"char":"󰐣","code":"f0423"},"md-pound_box":{"char":"󰐤","code":"f0424"},"md-pound_box_outline":{"char":"󱅿","code":"f117f"},"md-power":{"char":"󰐥","code":"f0425"},"md-power_cycle":{"char":"󰤁","code":"f0901"},"md-power_off":{"char":"󰤂","code":"f0902"},"md-power_on":{"char":"󰤃","code":"f0903"},"md-power_plug":{"char":"󰚥","code":"f06a5"},"md-power_plug_off":{"char":"󰚦","code":"f06a6"},"md-power_plug_off_outline":{"char":"󱐤","code":"f1424"},"md-power_plug_outline":{"char":"󱐥","code":"f1425"},"md-power_settings":{"char":"󰐦","code":"f0426"},"md-power_sleep":{"char":"󰤄","code":"f0904"},"md-power_socket":{"char":"󰐧","code":"f0427"},"md-power_socket_au":{"char":"󰤅","code":"f0905"},"md-power_socket_ch":{"char":"󰾳","code":"f0fb3"},"md-power_socket_de":{"char":"󱄇","code":"f1107"},"md-power_socket_eu":{"char":"󰟧","code":"f07e7"},"md-power_socket_fr":{"char":"󱄈","code":"f1108"},"md-power_socket_it":{"char":"󱓿","code":"f14ff"},"md-power_socket_jp":{"char":"󱄉","code":"f1109"},"md-power_socket_uk":{"char":"󰟨","code":"f07e8"},"md-power_socket_us":{"char":"󰟩","code":"f07e9"},"md-power_standby":{"char":"󰤆","code":"f0906"},"md-powershell":{"char":"󰨊","code":"f0a0a"},"md-prescription":{"char":"󰜆","code":"f0706"},"md-presentation":{"char":"󰐨","code":"f0428"},"md-presentation_play":{"char":"󰐩","code":"f0429"},"md-pretzel":{"char":"󱕢","code":"f1562"},"md-printer":{"char":"󰐪","code":"f042a"},"md-printer_3d":{"char":"󰐫","code":"f042b"},"md-printer_3d_nozzle":{"char":"󰹛","code":"f0e5b"},"md-printer_3d_nozzle_alert":{"char":"󱇀","code":"f11c0"},"md-printer_3d_nozzle_alert_outline":{"char":"󱇁","code":"f11c1"},"md-printer_3d_nozzle_heat":{"char":"󱢸","code":"f18b8"},"md-printer_3d_nozzle_heat_outline":{"char":"󱢹","code":"f18b9"},"md-printer_3d_nozzle_outline":{"char":"󰹜","code":"f0e5c"},"md-printer_alert":{"char":"󰐬","code":"f042c"},"md-printer_check":{"char":"󱅆","code":"f1146"},"md-printer_eye":{"char":"󱑘","code":"f1458"},"md-printer_off":{"char":"󰹝","code":"f0e5d"},"md-printer_off_outline":{"char":"󱞅","code":"f1785"},"md-printer_outline":{"char":"󱞆","code":"f1786"},"md-printer_pos":{"char":"󱁗","code":"f1057"},"md-printer_search":{"char":"󱑗","code":"f1457"},"md-printer_settings":{"char":"󰜇","code":"f0707"},"md-printer_wireless":{"char":"󰨋","code":"f0a0b"},"md-priority_high":{"char":"󰘃","code":"f0603"},"md-priority_low":{"char":"󰘄","code":"f0604"},"md-professional_hexagon":{"char":"󰐭","code":"f042d"},"md-progress_alert":{"char":"󰲼","code":"f0cbc"},"md-progress_check":{"char":"󰦕","code":"f0995"},"md-progress_clock":{"char":"󰦖","code":"f0996"},"md-progress_close":{"char":"󱄊","code":"f110a"},"md-progress_download":{"char":"󰦗","code":"f0997"},"md-progress_pencil":{"char":"󱞇","code":"f1787"},"md-progress_question":{"char":"󱔢","code":"f1522"},"md-progress_star":{"char":"󱞈","code":"f1788"},"md-progress_upload":{"char":"󰦘","code":"f0998"},"md-progress_wrench":{"char":"󰲽","code":"f0cbd"},"md-projector":{"char":"󰐮","code":"f042e"},"md-projector_off":{"char":"󱨣","code":"f1a23"},"md-projector_screen":{"char":"󰐯","code":"f042f"},"md-projector_screen_off":{"char":"󱠍","code":"f180d"},"md-projector_screen_off_outline":{"char":"󱠎","code":"f180e"},"md-projector_screen_outline":{"char":"󱜤","code":"f1724"},"md-projector_screen_variant":{"char":"󱠏","code":"f180f"},"md-projector_screen_variant_off":{"char":"󱠐","code":"f1810"},"md-projector_screen_variant_off_outline":{"char":"󱠑","code":"f1811"},"md-projector_screen_variant_outline":{"char":"󱠒","code":"f1812"},"md-propane_tank":{"char":"󱍗","code":"f1357"},"md-propane_tank_outline":{"char":"󱍘","code":"f1358"},"md-protocol":{"char":"󰿘","code":"f0fd8"},"md-publish":{"char":"󰚧","code":"f06a7"},"md-publish_off":{"char":"󱥅","code":"f1945"},"md-pulse":{"char":"󰐰","code":"f0430"},"md-pump":{"char":"󱐂","code":"f1402"},"md-pumpkin":{"char":"󰮿","code":"f0bbf"},"md-purse":{"char":"󰼜","code":"f0f1c"},"md-purse_outline":{"char":"󰼝","code":"f0f1d"},"md-puzzle":{"char":"󰐱","code":"f0431"},"md-puzzle_check":{"char":"󱐦","code":"f1426"},"md-puzzle_check_outline":{"char":"󱐧","code":"f1427"},"md-puzzle_edit":{"char":"󱓓","code":"f14d3"},"md-puzzle_edit_outline":{"char":"󱓙","code":"f14d9"},"md-puzzle_heart":{"char":"󱓔","code":"f14d4"},"md-puzzle_heart_outline":{"char":"󱓚","code":"f14da"},"md-puzzle_minus":{"char":"󱓑","code":"f14d1"},"md-puzzle_minus_outline":{"char":"󱓗","code":"f14d7"},"md-puzzle_outline":{"char":"󰩦","code":"f0a66"},"md-puzzle_plus":{"char":"󱓐","code":"f14d0"},"md-puzzle_plus_outline":{"char":"󱓖","code":"f14d6"},"md-puzzle_remove":{"char":"󱓒","code":"f14d2"},"md-puzzle_remove_outline":{"char":"󱓘","code":"f14d8"},"md-puzzle_star":{"char":"󱓕","code":"f14d5"},"md-puzzle_star_outline":{"char":"󱓛","code":"f14db"},"md-pyramid":{"char":"󱥒","code":"f1952"},"md-pyramid_off":{"char":"󱥓","code":"f1953"},"md-qi":{"char":"󰦙","code":"f0999"},"md-qqchat":{"char":"󰘅","code":"f0605"},"md-qrcode":{"char":"󰐲","code":"f0432"},"md-qrcode_edit":{"char":"󰢸","code":"f08b8"},"md-qrcode_minus":{"char":"󱆌","code":"f118c"},"md-qrcode_plus":{"char":"󱆋","code":"f118b"},"md-qrcode_remove":{"char":"󱆍","code":"f118d"},"md-qrcode_scan":{"char":"󰐳","code":"f0433"},"md-quadcopter":{"char":"󰐴","code":"f0434"},"md-quality_high":{"char":"󰐵","code":"f0435"},"md-quality_low":{"char":"󰨌","code":"f0a0c"},"md-quality_medium":{"char":"󰨍","code":"f0a0d"},"md-quora":{"char":"󰴩","code":"f0d29"},"md-rabbit":{"char":"󰤇","code":"f0907"},"md-rabbit_variant":{"char":"󱩡","code":"f1a61"},"md-rabbit_variant_outline":{"char":"󱩢","code":"f1a62"},"md-racing_helmet":{"char":"󰶓","code":"f0d93"},"md-racquetball":{"char":"󰶔","code":"f0d94"},"md-radar":{"char":"󰐷","code":"f0437"},"md-radiator":{"char":"󰐸","code":"f0438"},"md-radiator_disabled":{"char":"󰫗","code":"f0ad7"},"md-radiator_off":{"char":"󰫘","code":"f0ad8"},"md-radio":{"char":"󰐹","code":"f0439"},"md-radio_am":{"char":"󰲾","code":"f0cbe"},"md-radio_fm":{"char":"󰲿","code":"f0cbf"},"md-radio_handheld":{"char":"󰐺","code":"f043a"},"md-radio_off":{"char":"󱈜","code":"f121c"},"md-radio_tower":{"char":"󰐻","code":"f043b"},"md-radioactive":{"char":"󰐼","code":"f043c"},"md-radioactive_circle":{"char":"󱡝","code":"f185d"},"md-radioactive_circle_outline":{"char":"󱡞","code":"f185e"},"md-radioactive_off":{"char":"󰻁","code":"f0ec1"},"md-radiobox_marked":{"char":"󰐾","code":"f043e"},"md-radiology_box":{"char":"󱓅","code":"f14c5"},"md-radiology_box_outline":{"char":"󱓆","code":"f14c6"},"md-radius":{"char":"󰳀","code":"f0cc0"},"md-radius_outline":{"char":"󰳁","code":"f0cc1"},"md-railroad_light":{"char":"󰼞","code":"f0f1e"},"md-rake":{"char":"󱕄","code":"f1544"},"md-raspberry_pi":{"char":"󰐿","code":"f043f"},"md-raw":{"char":"󱨏","code":"f1a0f"},"md-raw_off":{"char":"󱨐","code":"f1a10"},"md-ray_end":{"char":"󰑀","code":"f0440"},"md-ray_end_arrow":{"char":"󰑁","code":"f0441"},"md-ray_start":{"char":"󰑂","code":"f0442"},"md-ray_start_arrow":{"char":"󰑃","code":"f0443"},"md-ray_start_end":{"char":"󰑄","code":"f0444"},"md-ray_start_vertex_end":{"char":"󱗘","code":"f15d8"},"md-ray_vertex":{"char":"󰑅","code":"f0445"},"md-razor_double_edge":{"char":"󱦗","code":"f1997"},"md-razor_single_edge":{"char":"󱦘","code":"f1998"},"md-react":{"char":"󰜈","code":"f0708"},"md-read":{"char":"󰑇","code":"f0447"},"md-receipt":{"char":"󰑉","code":"f0449"},"md-receipt_outline":{"char":"󱧜","code":"f19dc"},"md-receipt_text_check":{"char":"󱩣","code":"f1a63"},"md-receipt_text_check_outline":{"char":"󱩤","code":"f1a64"},"md-receipt_text_minus":{"char":"󱩥","code":"f1a65"},"md-receipt_text_minus_outline":{"char":"󱩦","code":"f1a66"},"md-receipt_text_plus":{"char":"󱩧","code":"f1a67"},"md-receipt_text_plus_outline":{"char":"󱩨","code":"f1a68"},"md-receipt_text_remove":{"char":"󱩩","code":"f1a69"},"md-receipt_text_remove_outline":{"char":"󱩪","code":"f1a6a"},"md-record":{"char":"󰑊","code":"f044a"},"md-record_circle":{"char":"󰻂","code":"f0ec2"},"md-record_circle_outline":{"char":"󰻃","code":"f0ec3"},"md-record_player":{"char":"󰦚","code":"f099a"},"md-record_rec":{"char":"󰑋","code":"f044b"},"md-rectangle":{"char":"󰹞","code":"f0e5e"},"md-rectangle_outline":{"char":"󰹟","code":"f0e5f"},"md-recycle":{"char":"󰑌","code":"f044c"},"md-recycle_variant":{"char":"󱎝","code":"f139d"},"md-reddit":{"char":"󰑍","code":"f044d"},"md-redhat":{"char":"󱄛","code":"f111b"},"md-redo":{"char":"󰑎","code":"f044e"},"md-redo_variant":{"char":"󰑏","code":"f044f"},"md-reflect_horizontal":{"char":"󰨎","code":"f0a0e"},"md-reflect_vertical":{"char":"󰨏","code":"f0a0f"},"md-refresh":{"char":"󰑐","code":"f0450"},"md-refresh_auto":{"char":"󱣲","code":"f18f2"},"md-refresh_circle":{"char":"󱍷","code":"f1377"},"md-regex":{"char":"󰑑","code":"f0451"},"md-registered_trademark":{"char":"󰩧","code":"f0a67"},"md-reiterate":{"char":"󱖈","code":"f1588"},"md-relation_many_to_many":{"char":"󱒖","code":"f1496"},"md-relation_many_to_one":{"char":"󱒗","code":"f1497"},"md-relation_many_to_one_or_many":{"char":"󱒘","code":"f1498"},"md-relation_many_to_only_one":{"char":"󱒙","code":"f1499"},"md-relation_many_to_zero_or_many":{"char":"󱒚","code":"f149a"},"md-relation_many_to_zero_or_one":{"char":"󱒛","code":"f149b"},"md-relation_one_or_many_to_many":{"char":"󱒜","code":"f149c"},"md-relation_one_or_many_to_one":{"char":"󱒝","code":"f149d"},"md-relation_one_or_many_to_one_or_many":{"char":"󱒞","code":"f149e"},"md-relation_one_or_many_to_only_one":{"char":"󱒟","code":"f149f"},"md-relation_one_or_many_to_zero_or_many":{"char":"󱒠","code":"f14a0"},"md-relation_one_or_many_to_zero_or_one":{"char":"󱒡","code":"f14a1"},"md-relation_one_to_many":{"char":"󱒢","code":"f14a2"},"md-relation_one_to_one":{"char":"󱒣","code":"f14a3"},"md-relation_one_to_one_or_many":{"char":"󱒤","code":"f14a4"},"md-relation_one_to_only_one":{"char":"󱒥","code":"f14a5"},"md-relation_one_to_zero_or_many":{"char":"󱒦","code":"f14a6"},"md-relation_one_to_zero_or_one":{"char":"󱒧","code":"f14a7"},"md-relation_only_one_to_many":{"char":"󱒨","code":"f14a8"},"md-relation_only_one_to_one":{"char":"󱒩","code":"f14a9"},"md-relation_only_one_to_one_or_many":{"char":"󱒪","code":"f14aa"},"md-relation_only_one_to_only_one":{"char":"󱒫","code":"f14ab"},"md-relation_only_one_to_zero_or_many":{"char":"󱒬","code":"f14ac"},"md-relation_only_one_to_zero_or_one":{"char":"󱒭","code":"f14ad"},"md-relation_zero_or_many_to_many":{"char":"󱒮","code":"f14ae"},"md-relation_zero_or_many_to_one":{"char":"󱒯","code":"f14af"},"md-relation_zero_or_many_to_one_or_many":{"char":"󱒰","code":"f14b0"},"md-relation_zero_or_many_to_only_one":{"char":"󱒱","code":"f14b1"},"md-relation_zero_or_many_to_zero_or_many":{"char":"󱒲","code":"f14b2"},"md-relation_zero_or_many_to_zero_or_one":{"char":"󱒳","code":"f14b3"},"md-relation_zero_or_one_to_many":{"char":"󱒴","code":"f14b4"},"md-relation_zero_or_one_to_one":{"char":"󱒵","code":"f14b5"},"md-relation_zero_or_one_to_one_or_many":{"char":"󱒶","code":"f14b6"},"md-relation_zero_or_one_to_only_one":{"char":"󱒷","code":"f14b7"},"md-relation_zero_or_one_to_zero_or_many":{"char":"󱒸","code":"f14b8"},"md-relation_zero_or_one_to_zero_or_one":{"char":"󱒹","code":"f14b9"},"md-relative_scale":{"char":"󰑒","code":"f0452"},"md-reload":{"char":"󰑓","code":"f0453"},"md-reload_alert":{"char":"󱄋","code":"f110b"},"md-reminder":{"char":"󰢌","code":"f088c"},"md-remote":{"char":"󰑔","code":"f0454"},"md-remote_desktop":{"char":"󰢹","code":"f08b9"},"md-remote_off":{"char":"󰻄","code":"f0ec4"},"md-remote_tv":{"char":"󰻅","code":"f0ec5"},"md-remote_tv_off":{"char":"󰻆","code":"f0ec6"},"md-rename_box":{"char":"󰑕","code":"f0455"},"md-reorder_horizontal":{"char":"󰚈","code":"f0688"},"md-reorder_vertical":{"char":"󰚉","code":"f0689"},"md-repeat":{"char":"󰑖","code":"f0456"},"md-repeat_off":{"char":"󰑗","code":"f0457"},"md-repeat_once":{"char":"󰑘","code":"f0458"},"md-repeat_variant":{"char":"󰕇","code":"f0547"},"md-replay":{"char":"󰑙","code":"f0459"},"md-reply":{"char":"󰑚","code":"f045a"},"md-reply_all":{"char":"󰑛","code":"f045b"},"md-reply_all_outline":{"char":"󰼟","code":"f0f1f"},"md-reply_circle":{"char":"󱆮","code":"f11ae"},"md-reply_outline":{"char":"󰼠","code":"f0f20"},"md-reproduction":{"char":"󰑜","code":"f045c"},"md-resistor":{"char":"󰭄","code":"f0b44"},"md-resistor_nodes":{"char":"󰭅","code":"f0b45"},"md-resize":{"char":"󰩨","code":"f0a68"},"md-resize_bottom_right":{"char":"󰑝","code":"f045d"},"md-responsive":{"char":"󰑞","code":"f045e"},"md-restart":{"char":"󰜉","code":"f0709"},"md-restart_alert":{"char":"󱄌","code":"f110c"},"md-restart_off":{"char":"󰶕","code":"f0d95"},"md-restore":{"char":"󰦛","code":"f099b"},"md-restore_alert":{"char":"󱄍","code":"f110d"},"md-rewind":{"char":"󰑟","code":"f045f"},"md-rewind_10":{"char":"󰴪","code":"f0d2a"},"md-rewind_15":{"char":"󱥆","code":"f1946"},"md-rewind_30":{"char":"󰶖","code":"f0d96"},"md-rewind_5":{"char":"󱇹","code":"f11f9"},"md-rewind_60":{"char":"󱘌","code":"f160c"},"md-rewind_outline":{"char":"󰜊","code":"f070a"},"md-rhombus":{"char":"󰜋","code":"f070b"},"md-rhombus_medium":{"char":"󰨐","code":"f0a10"},"md-rhombus_medium_outline":{"char":"󱓜","code":"f14dc"},"md-rhombus_outline":{"char":"󰜌","code":"f070c"},"md-rhombus_split":{"char":"󰨑","code":"f0a11"},"md-rhombus_split_outline":{"char":"󱓝","code":"f14dd"},"md-ribbon":{"char":"󰑠","code":"f0460"},"md-rice":{"char":"󰟪","code":"f07ea"},"md-rickshaw":{"char":"󱖻","code":"f15bb"},"md-rickshaw_electric":{"char":"󱖼","code":"f15bc"},"md-ring":{"char":"󰟫","code":"f07eb"},"md-rivet":{"char":"󰹠","code":"f0e60"},"md-road":{"char":"󰑡","code":"f0461"},"md-road_variant":{"char":"󰑢","code":"f0462"},"md-robber":{"char":"󱁘","code":"f1058"},"md-robot":{"char":"󰚩","code":"f06a9"},"md-robot_angry":{"char":"󱚝","code":"f169d"},"md-robot_angry_outline":{"char":"󱚞","code":"f169e"},"md-robot_confused":{"char":"󱚟","code":"f169f"},"md-robot_confused_outline":{"char":"󱚠","code":"f16a0"},"md-robot_dead":{"char":"󱚡","code":"f16a1"},"md-robot_dead_outline":{"char":"󱚢","code":"f16a2"},"md-robot_excited":{"char":"󱚣","code":"f16a3"},"md-robot_excited_outline":{"char":"󱚤","code":"f16a4"},"md-robot_happy":{"char":"󱜙","code":"f1719"},"md-robot_happy_outline":{"char":"󱜚","code":"f171a"},"md-robot_industrial":{"char":"󰭆","code":"f0b46"},"md-robot_industrial_outline":{"char":"󱨚","code":"f1a1a"},"md-robot_love":{"char":"󱚥","code":"f16a5"},"md-robot_love_outline":{"char":"󱚦","code":"f16a6"},"md-robot_mower":{"char":"󱇷","code":"f11f7"},"md-robot_mower_outline":{"char":"󱇳","code":"f11f3"},"md-robot_off":{"char":"󱚧","code":"f16a7"},"md-robot_off_outline":{"char":"󱙻","code":"f167b"},"md-robot_outline":{"char":"󱙺","code":"f167a"},"md-robot_vacuum":{"char":"󰜍","code":"f070d"},"md-robot_vacuum_variant":{"char":"󰤈","code":"f0908"},"md-rocket":{"char":"󰑣","code":"f0463"},"md-rocket_launch":{"char":"󱓞","code":"f14de"},"md-rocket_launch_outline":{"char":"󱓟","code":"f14df"},"md-rocket_outline":{"char":"󱎯","code":"f13af"},"md-rodent":{"char":"󱌧","code":"f1327"},"md-roller_shade":{"char":"󱩫","code":"f1a6b"},"md-roller_shade_closed":{"char":"󱩬","code":"f1a6c"},"md-roller_skate":{"char":"󰴫","code":"f0d2b"},"md-roller_skate_off":{"char":"󰅅","code":"f0145"},"md-rollerblade":{"char":"󰴬","code":"f0d2c"},"md-rollerblade_off":{"char":"󰀮","code":"f002e"},"md-rollupjs":{"char":"󰯀","code":"f0bc0"},"md-rolodex":{"char":"󱪹","code":"f1ab9"},"md-rolodex_outline":{"char":"󱪺","code":"f1aba"},"md-roman_numeral_2":{"char":"󱂉","code":"f1089"},"md-roman_numeral_3":{"char":"󱂊","code":"f108a"},"md-roman_numeral_4":{"char":"󱂋","code":"f108b"},"md-roman_numeral_6":{"char":"󱂍","code":"f108d"},"md-roman_numeral_7":{"char":"󱂎","code":"f108e"},"md-roman_numeral_8":{"char":"󱂏","code":"f108f"},"md-roman_numeral_9":{"char":"󱂐","code":"f1090"},"md-room_service":{"char":"󰢍","code":"f088d"},"md-room_service_outline":{"char":"󰶗","code":"f0d97"},"md-rotate_360":{"char":"󱦙","code":"f1999"},"md-rotate_3d":{"char":"󰻇","code":"f0ec7"},"md-rotate_3d_variant":{"char":"󰑤","code":"f0464"},"md-rotate_left":{"char":"󰑥","code":"f0465"},"md-rotate_left_variant":{"char":"󰑦","code":"f0466"},"md-rotate_orbit":{"char":"󰶘","code":"f0d98"},"md-rotate_right":{"char":"󰑧","code":"f0467"},"md-rotate_right_variant":{"char":"󰑨","code":"f0468"},"md-rounded_corner":{"char":"󰘇","code":"f0607"},"md-router":{"char":"󱇢","code":"f11e2"},"md-router_network":{"char":"󱂇","code":"f1087"},"md-router_wireless":{"char":"󰑩","code":"f0469"},"md-router_wireless_off":{"char":"󱖣","code":"f15a3"},"md-router_wireless_settings":{"char":"󰩩","code":"f0a69"},"md-routes":{"char":"󰑪","code":"f046a"},"md-routes_clock":{"char":"󱁙","code":"f1059"},"md-rowing":{"char":"󰘈","code":"f0608"},"md-rss":{"char":"󰑫","code":"f046b"},"md-rss_box":{"char":"󰑬","code":"f046c"},"md-rss_off":{"char":"󰼡","code":"f0f21"},"md-rug":{"char":"󱑵","code":"f1475"},"md-rugby":{"char":"󰶙","code":"f0d99"},"md-ruler":{"char":"󰑭","code":"f046d"},"md-ruler_square":{"char":"󰳂","code":"f0cc2"},"md-ruler_square_compass":{"char":"󰺾","code":"f0ebe"},"md-run":{"char":"󰜎","code":"f070e"},"md-run_fast":{"char":"󰑮","code":"f046e"},"md-rv_truck":{"char":"󱇔","code":"f11d4"},"md-sack":{"char":"󰴮","code":"f0d2e"},"md-sack_percent":{"char":"󰴯","code":"f0d2f"},"md-safe":{"char":"󰩪","code":"f0a6a"},"md-safe_square":{"char":"󱉼","code":"f127c"},"md-safe_square_outline":{"char":"󱉽","code":"f127d"},"md-safety_goggles":{"char":"󰴰","code":"f0d30"},"md-sail_boat":{"char":"󰻈","code":"f0ec8"},"md-sail_boat_sink":{"char":"󱫯","code":"f1aef"},"md-sale":{"char":"󰑯","code":"f046f"},"md-sale_outline":{"char":"󱨆","code":"f1a06"},"md-salesforce":{"char":"󰢎","code":"f088e"},"md-sass":{"char":"󰟬","code":"f07ec"},"md-satellite":{"char":"󰑰","code":"f0470"},"md-satellite_uplink":{"char":"󰤉","code":"f0909"},"md-satellite_variant":{"char":"󰑱","code":"f0471"},"md-sausage":{"char":"󰢺","code":"f08ba"},"md-sausage_off":{"char":"󱞉","code":"f1789"},"md-saw_blade":{"char":"󰹡","code":"f0e61"},"md-sawtooth_wave":{"char":"󱑺","code":"f147a"},"md-saxophone":{"char":"󰘉","code":"f0609"},"md-scale":{"char":"󰑲","code":"f0472"},"md-scale_balance":{"char":"󰗑","code":"f05d1"},"md-scale_bathroom":{"char":"󰑳","code":"f0473"},"md-scale_off":{"char":"󱁚","code":"f105a"},"md-scale_unbalanced":{"char":"󱦸","code":"f19b8"},"md-scan_helper":{"char":"󱏘","code":"f13d8"},"md-scanner":{"char":"󰚫","code":"f06ab"},"md-scanner_off":{"char":"󰤊","code":"f090a"},"md-scatter_plot":{"char":"󰻉","code":"f0ec9"},"md-scatter_plot_outline":{"char":"󰻊","code":"f0eca"},"md-scent":{"char":"󱥘","code":"f1958"},"md-scent_off":{"char":"󱥙","code":"f1959"},"md-school":{"char":"󰑴","code":"f0474"},"md-school_outline":{"char":"󱆀","code":"f1180"},"md-scissors_cutting":{"char":"󰩫","code":"f0a6b"},"md-scooter":{"char":"󱖽","code":"f15bd"},"md-scooter_electric":{"char":"󱖾","code":"f15be"},"md-scoreboard":{"char":"󱉾","code":"f127e"},"md-scoreboard_outline":{"char":"󱉿","code":"f127f"},"md-screen_rotation":{"char":"󰑵","code":"f0475"},"md-screen_rotation_lock":{"char":"󰑸","code":"f0478"},"md-screw_flat_top":{"char":"󰷳","code":"f0df3"},"md-screw_lag":{"char":"󰷴","code":"f0df4"},"md-screw_machine_flat_top":{"char":"󰷵","code":"f0df5"},"md-screw_machine_round_top":{"char":"󰷶","code":"f0df6"},"md-screw_round_top":{"char":"󰷷","code":"f0df7"},"md-screwdriver":{"char":"󰑶","code":"f0476"},"md-script":{"char":"󰯁","code":"f0bc1"},"md-script_outline":{"char":"󰑷","code":"f0477"},"md-script_text":{"char":"󰯂","code":"f0bc2"},"md-script_text_key":{"char":"󱜥","code":"f1725"},"md-script_text_key_outline":{"char":"󱜦","code":"f1726"},"md-script_text_outline":{"char":"󰯃","code":"f0bc3"},"md-script_text_play":{"char":"󱜧","code":"f1727"},"md-script_text_play_outline":{"char":"󱜨","code":"f1728"},"md-sd":{"char":"󰑹","code":"f0479"},"md-seal":{"char":"󰑺","code":"f047a"},"md-seal_variant":{"char":"󰿙","code":"f0fd9"},"md-search_web":{"char":"󰜏","code":"f070f"},"md-seat":{"char":"󰳃","code":"f0cc3"},"md-seat_flat":{"char":"󰑻","code":"f047b"},"md-seat_flat_angled":{"char":"󰑼","code":"f047c"},"md-seat_individual_suite":{"char":"󰑽","code":"f047d"},"md-seat_legroom_extra":{"char":"󰑾","code":"f047e"},"md-seat_legroom_normal":{"char":"󰑿","code":"f047f"},"md-seat_legroom_reduced":{"char":"󰒀","code":"f0480"},"md-seat_outline":{"char":"󰳄","code":"f0cc4"},"md-seat_passenger":{"char":"󱉉","code":"f1249"},"md-seat_recline_extra":{"char":"󰒁","code":"f0481"},"md-seat_recline_normal":{"char":"󰒂","code":"f0482"},"md-seatbelt":{"char":"󰳅","code":"f0cc5"},"md-security":{"char":"󰒃","code":"f0483"},"md-security_network":{"char":"󰒄","code":"f0484"},"md-seed":{"char":"󰹢","code":"f0e62"},"md-seed_off":{"char":"󱏽","code":"f13fd"},"md-seed_off_outline":{"char":"󱏾","code":"f13fe"},"md-seed_outline":{"char":"󰹣","code":"f0e63"},"md-seed_plus":{"char":"󱩭","code":"f1a6d"},"md-seed_plus_outline":{"char":"󱩮","code":"f1a6e"},"md-seesaw":{"char":"󱖤","code":"f15a4"},"md-segment":{"char":"󰻋","code":"f0ecb"},"md-select":{"char":"󰒅","code":"f0485"},"md-select_all":{"char":"󰒆","code":"f0486"},"md-select_color":{"char":"󰴱","code":"f0d31"},"md-select_compare":{"char":"󰫙","code":"f0ad9"},"md-select_drag":{"char":"󰩬","code":"f0a6c"},"md-select_group":{"char":"󰾂","code":"f0f82"},"md-select_inverse":{"char":"󰒇","code":"f0487"},"md-select_marker":{"char":"󱊀","code":"f1280"},"md-select_multiple":{"char":"󱊁","code":"f1281"},"md-select_multiple_marker":{"char":"󱊂","code":"f1282"},"md-select_off":{"char":"󰒈","code":"f0488"},"md-select_place":{"char":"󰿚","code":"f0fda"},"md-select_remove":{"char":"󱟁","code":"f17c1"},"md-select_search":{"char":"󱈄","code":"f1204"},"md-selection":{"char":"󰒉","code":"f0489"},"md-selection_drag":{"char":"󰩭","code":"f0a6d"},"md-selection_ellipse":{"char":"󰴲","code":"f0d32"},"md-selection_ellipse_arrow_inside":{"char":"󰼢","code":"f0f22"},"md-selection_ellipse_remove":{"char":"󱟂","code":"f17c2"},"md-selection_marker":{"char":"󱊃","code":"f1283"},"md-selection_multiple":{"char":"󱊅","code":"f1285"},"md-selection_multiple_marker":{"char":"󱊄","code":"f1284"},"md-selection_off":{"char":"󰝷","code":"f0777"},"md-selection_remove":{"char":"󱟃","code":"f17c3"},"md-selection_search":{"char":"󱈅","code":"f1205"},"md-semantic_web":{"char":"󱌖","code":"f1316"},"md-send":{"char":"󰒊","code":"f048a"},"md-send_check":{"char":"󱅡","code":"f1161"},"md-send_check_outline":{"char":"󱅢","code":"f1162"},"md-send_circle":{"char":"󰷸","code":"f0df8"},"md-send_circle_outline":{"char":"󰷹","code":"f0df9"},"md-send_clock":{"char":"󱅣","code":"f1163"},"md-send_clock_outline":{"char":"󱅤","code":"f1164"},"md-send_lock":{"char":"󰟭","code":"f07ed"},"md-send_lock_outline":{"char":"󱅦","code":"f1166"},"md-send_outline":{"char":"󱅥","code":"f1165"},"md-serial_port":{"char":"󰙜","code":"f065c"},"md-server":{"char":"󰒋","code":"f048b"},"md-server_minus":{"char":"󰒌","code":"f048c"},"md-server_network":{"char":"󰒍","code":"f048d"},"md-server_network_off":{"char":"󰒎","code":"f048e"},"md-server_off":{"char":"󰒏","code":"f048f"},"md-server_plus":{"char":"󰒐","code":"f0490"},"md-server_remove":{"char":"󰒑","code":"f0491"},"md-server_security":{"char":"󰒒","code":"f0492"},"md-set_all":{"char":"󰝸","code":"f0778"},"md-set_center":{"char":"󰝹","code":"f0779"},"md-set_center_right":{"char":"󰝺","code":"f077a"},"md-set_left":{"char":"󰝻","code":"f077b"},"md-set_left_center":{"char":"󰝼","code":"f077c"},"md-set_left_right":{"char":"󰝽","code":"f077d"},"md-set_merge":{"char":"󱓠","code":"f14e0"},"md-set_none":{"char":"󰝾","code":"f077e"},"md-set_right":{"char":"󰝿","code":"f077f"},"md-set_split":{"char":"󱓡","code":"f14e1"},"md-set_square":{"char":"󱑝","code":"f145d"},"md-set_top_box":{"char":"󰦟","code":"f099f"},"md-settings_helper":{"char":"󰩮","code":"f0a6e"},"md-shaker":{"char":"󱄎","code":"f110e"},"md-shaker_outline":{"char":"󱄏","code":"f110f"},"md-shape":{"char":"󰠱","code":"f0831"},"md-shape_circle_plus":{"char":"󰙝","code":"f065d"},"md-shape_outline":{"char":"󰠲","code":"f0832"},"md-shape_oval_plus":{"char":"󱇺","code":"f11fa"},"md-shape_plus":{"char":"󰒕","code":"f0495"},"md-shape_polygon_plus":{"char":"󰙞","code":"f065e"},"md-shape_rectangle_plus":{"char":"󰙟","code":"f065f"},"md-shape_square_plus":{"char":"󰙠","code":"f0660"},"md-shape_square_rounded_plus":{"char":"󱓺","code":"f14fa"},"md-share":{"char":"󰒖","code":"f0496"},"md-share_all":{"char":"󱇴","code":"f11f4"},"md-share_all_outline":{"char":"󱇵","code":"f11f5"},"md-share_circle":{"char":"󱆭","code":"f11ad"},"md-share_off":{"char":"󰼣","code":"f0f23"},"md-share_off_outline":{"char":"󰼤","code":"f0f24"},"md-share_outline":{"char":"󰤲","code":"f0932"},"md-share_variant":{"char":"󰒗","code":"f0497"},"md-share_variant_outline":{"char":"󱔔","code":"f1514"},"md-shark":{"char":"󱢺","code":"f18ba"},"md-shark_fin":{"char":"󱙳","code":"f1673"},"md-shark_fin_outline":{"char":"󱙴","code":"f1674"},"md-shark_off":{"char":"󱢻","code":"f18bb"},"md-sheep":{"char":"󰳆","code":"f0cc6"},"md-shield":{"char":"󰒘","code":"f0498"},"md-shield_account":{"char":"󰢏","code":"f088f"},"md-shield_account_outline":{"char":"󰨒","code":"f0a12"},"md-shield_account_variant":{"char":"󱖧","code":"f15a7"},"md-shield_account_variant_outline":{"char":"󱖨","code":"f15a8"},"md-shield_airplane":{"char":"󰚻","code":"f06bb"},"md-shield_airplane_outline":{"char":"󰳇","code":"f0cc7"},"md-shield_alert":{"char":"󰻌","code":"f0ecc"},"md-shield_alert_outline":{"char":"󰻍","code":"f0ecd"},"md-shield_bug":{"char":"󱏚","code":"f13da"},"md-shield_bug_outline":{"char":"󱏛","code":"f13db"},"md-shield_car":{"char":"󰾃","code":"f0f83"},"md-shield_check":{"char":"󰕥","code":"f0565"},"md-shield_check_outline":{"char":"󰳈","code":"f0cc8"},"md-shield_cross":{"char":"󰳉","code":"f0cc9"},"md-shield_cross_outline":{"char":"󰳊","code":"f0cca"},"md-shield_crown":{"char":"󱢼","code":"f18bc"},"md-shield_crown_outline":{"char":"󱢽","code":"f18bd"},"md-shield_edit":{"char":"󱆠","code":"f11a0"},"md-shield_edit_outline":{"char":"󱆡","code":"f11a1"},"md-shield_half":{"char":"󱍠","code":"f1360"},"md-shield_half_full":{"char":"󰞀","code":"f0780"},"md-shield_home":{"char":"󰚊","code":"f068a"},"md-shield_home_outline":{"char":"󰳋","code":"f0ccb"},"md-shield_key":{"char":"󰯄","code":"f0bc4"},"md-shield_key_outline":{"char":"󰯅","code":"f0bc5"},"md-shield_link_variant":{"char":"󰴳","code":"f0d33"},"md-shield_link_variant_outline":{"char":"󰴴","code":"f0d34"},"md-shield_lock":{"char":"󰦝","code":"f099d"},"md-shield_lock_open":{"char":"󱦚","code":"f199a"},"md-shield_lock_open_outline":{"char":"󱦛","code":"f199b"},"md-shield_lock_outline":{"char":"󰳌","code":"f0ccc"},"md-shield_moon":{"char":"󱠨","code":"f1828"},"md-shield_moon_outline":{"char":"󱠩","code":"f1829"},"md-shield_off":{"char":"󰦞","code":"f099e"},"md-shield_off_outline":{"char":"󰦜","code":"f099c"},"md-shield_outline":{"char":"󰒙","code":"f0499"},"md-shield_plus":{"char":"󰫚","code":"f0ada"},"md-shield_plus_outline":{"char":"󰫛","code":"f0adb"},"md-shield_refresh":{"char":"󰂪","code":"f00aa"},"md-shield_refresh_outline":{"char":"󰇠","code":"f01e0"},"md-shield_remove":{"char":"󰫜","code":"f0adc"},"md-shield_remove_outline":{"char":"󰫝","code":"f0add"},"md-shield_search":{"char":"󰶚","code":"f0d9a"},"md-shield_star":{"char":"󱄻","code":"f113b"},"md-shield_star_outline":{"char":"󱄼","code":"f113c"},"md-shield_sun":{"char":"󱁝","code":"f105d"},"md-shield_sun_outline":{"char":"󱁞","code":"f105e"},"md-shield_sword":{"char":"󱢾","code":"f18be"},"md-shield_sword_outline":{"char":"󱢿","code":"f18bf"},"md-shield_sync":{"char":"󱆢","code":"f11a2"},"md-shield_sync_outline":{"char":"󱆣","code":"f11a3"},"md-shimmer":{"char":"󱕅","code":"f1545"},"md-ship_wheel":{"char":"󰠳","code":"f0833"},"md-shipping_pallet":{"char":"󱡎","code":"f184e"},"md-shoe_ballet":{"char":"󱗊","code":"f15ca"},"md-shoe_cleat":{"char":"󱗇","code":"f15c7"},"md-shoe_formal":{"char":"󰭇","code":"f0b47"},"md-shoe_heel":{"char":"󰭈","code":"f0b48"},"md-shoe_print":{"char":"󰷺","code":"f0dfa"},"md-shoe_sneaker":{"char":"󱗈","code":"f15c8"},"md-shopping":{"char":"󰒚","code":"f049a"},"md-shopping_music":{"char":"󰒛","code":"f049b"},"md-shopping_outline":{"char":"󱇕","code":"f11d5"},"md-shopping_search":{"char":"󰾄","code":"f0f84"},"md-shopping_search_outline":{"char":"󱩯","code":"f1a6f"},"md-shore":{"char":"󱓹","code":"f14f9"},"md-shovel":{"char":"󰜐","code":"f0710"},"md-shovel_off":{"char":"󰜑","code":"f0711"},"md-shower":{"char":"󰦠","code":"f09a0"},"md-shower_head":{"char":"󰦡","code":"f09a1"},"md-shredder":{"char":"󰒜","code":"f049c"},"md-shuffle":{"char":"󰒝","code":"f049d"},"md-shuffle_disabled":{"char":"󰒞","code":"f049e"},"md-shuffle_variant":{"char":"󰒟","code":"f049f"},"md-shuriken":{"char":"󱍿","code":"f137f"},"md-sickle":{"char":"󱣀","code":"f18c0"},"md-sigma":{"char":"󰒠","code":"f04a0"},"md-sigma_lower":{"char":"󰘫","code":"f062b"},"md-sign_caution":{"char":"󰒡","code":"f04a1"},"md-sign_direction":{"char":"󰞁","code":"f0781"},"md-sign_direction_minus":{"char":"󱀀","code":"f1000"},"md-sign_direction_plus":{"char":"󰿜","code":"f0fdc"},"md-sign_direction_remove":{"char":"󰿝","code":"f0fdd"},"md-sign_pole":{"char":"󱓸","code":"f14f8"},"md-sign_real_estate":{"char":"󱄘","code":"f1118"},"md-sign_text":{"char":"󰞂","code":"f0782"},"md-signal":{"char":"󰒢","code":"f04a2"},"md-signal_2g":{"char":"󰜒","code":"f0712"},"md-signal_3g":{"char":"󰜓","code":"f0713"},"md-signal_4g":{"char":"󰜔","code":"f0714"},"md-signal_5g":{"char":"󰩯","code":"f0a6f"},"md-signal_cellular_1":{"char":"󰢼","code":"f08bc"},"md-signal_cellular_2":{"char":"󰢽","code":"f08bd"},"md-signal_cellular_3":{"char":"󰢾","code":"f08be"},"md-signal_cellular_outline":{"char":"󰢿","code":"f08bf"},"md-signal_distance_variant":{"char":"󰹤","code":"f0e64"},"md-signal_hspa":{"char":"󰜕","code":"f0715"},"md-signal_hspa_plus":{"char":"󰜖","code":"f0716"},"md-signal_off":{"char":"󰞃","code":"f0783"},"md-signal_variant":{"char":"󰘊","code":"f060a"},"md-signature":{"char":"󰷻","code":"f0dfb"},"md-signature_freehand":{"char":"󰷼","code":"f0dfc"},"md-signature_image":{"char":"󰷽","code":"f0dfd"},"md-signature_text":{"char":"󰷾","code":"f0dfe"},"md-silo":{"char":"󰭉","code":"f0b49"},"md-silverware":{"char":"󰒣","code":"f04a3"},"md-silverware_clean":{"char":"󰿞","code":"f0fde"},"md-silverware_fork":{"char":"󰒤","code":"f04a4"},"md-silverware_fork_knife":{"char":"󰩰","code":"f0a70"},"md-silverware_spoon":{"char":"󰒥","code":"f04a5"},"md-silverware_variant":{"char":"󰒦","code":"f04a6"},"md-sim":{"char":"󰒧","code":"f04a7"},"md-sim_alert":{"char":"󰒨","code":"f04a8"},"md-sim_alert_outline":{"char":"󱗓","code":"f15d3"},"md-sim_off":{"char":"󰒩","code":"f04a9"},"md-sim_off_outline":{"char":"󱗔","code":"f15d4"},"md-sim_outline":{"char":"󱗕","code":"f15d5"},"md-simple_icons":{"char":"󱌝","code":"f131d"},"md-sina_weibo":{"char":"󰫟","code":"f0adf"},"md-sine_wave":{"char":"󰥛","code":"f095b"},"md-sitemap":{"char":"󰒪","code":"f04aa"},"md-sitemap_outline":{"char":"󱦜","code":"f199c"},"md-size_m":{"char":"󱎥","code":"f13a5"},"md-size_s":{"char":"󱎤","code":"f13a4"},"md-size_xl":{"char":"󱎧","code":"f13a7"},"md-size_xs":{"char":"󱎣","code":"f13a3"},"md-size_xxl":{"char":"󱎨","code":"f13a8"},"md-size_xxs":{"char":"󱎢","code":"f13a2"},"md-size_xxxl":{"char":"󱎩","code":"f13a9"},"md-skate":{"char":"󰴵","code":"f0d35"},"md-skate_off":{"char":"󰚙","code":"f0699"},"md-skateboard":{"char":"󱓂","code":"f14c2"},"md-skateboarding":{"char":"󰔁","code":"f0501"},"md-skew_less":{"char":"󰴶","code":"f0d36"},"md-skew_more":{"char":"󰴷","code":"f0d37"},"md-ski":{"char":"󱌄","code":"f1304"},"md-ski_cross_country":{"char":"󱌅","code":"f1305"},"md-ski_water":{"char":"󱌆","code":"f1306"},"md-skip_backward":{"char":"󰒫","code":"f04ab"},"md-skip_backward_outline":{"char":"󰼥","code":"f0f25"},"md-skip_forward":{"char":"󰒬","code":"f04ac"},"md-skip_forward_outline":{"char":"󰼦","code":"f0f26"},"md-skip_next":{"char":"󰒭","code":"f04ad"},"md-skip_next_circle":{"char":"󰙡","code":"f0661"},"md-skip_next_circle_outline":{"char":"󰙢","code":"f0662"},"md-skip_next_outline":{"char":"󰼧","code":"f0f27"},"md-skip_previous":{"char":"󰒮","code":"f04ae"},"md-skip_previous_circle":{"char":"󰙣","code":"f0663"},"md-skip_previous_circle_outline":{"char":"󰙤","code":"f0664"},"md-skip_previous_outline":{"char":"󰼨","code":"f0f28"},"md-skull":{"char":"󰚌","code":"f068c"},"md-skull_crossbones":{"char":"󰯆","code":"f0bc6"},"md-skull_crossbones_outline":{"char":"󰯇","code":"f0bc7"},"md-skull_outline":{"char":"󰯈","code":"f0bc8"},"md-skull_scan":{"char":"󱓇","code":"f14c7"},"md-skull_scan_outline":{"char":"󱓈","code":"f14c8"},"md-skype":{"char":"󰒯","code":"f04af"},"md-skype_business":{"char":"󰒰","code":"f04b0"},"md-slack":{"char":"󰒱","code":"f04b1"},"md-slash_forward":{"char":"󰿟","code":"f0fdf"},"md-slash_forward_box":{"char":"󰿠","code":"f0fe0"},"md-sledding":{"char":"󰐛","code":"f041b"},"md-sleep":{"char":"󰒲","code":"f04b2"},"md-sleep_off":{"char":"󰒳","code":"f04b3"},"md-slide":{"char":"󱖥","code":"f15a5"},"md-slope_downhill":{"char":"󰷿","code":"f0dff"},"md-slope_uphill":{"char":"󰸀","code":"f0e00"},"md-slot_machine":{"char":"󱄔","code":"f1114"},"md-slot_machine_outline":{"char":"󱄕","code":"f1115"},"md-smart_card":{"char":"󱂽","code":"f10bd"},"md-smart_card_off":{"char":"󱣷","code":"f18f7"},"md-smart_card_off_outline":{"char":"󱣸","code":"f18f8"},"md-smart_card_outline":{"char":"󱂾","code":"f10be"},"md-smart_card_reader":{"char":"󱂿","code":"f10bf"},"md-smart_card_reader_outline":{"char":"󱃀","code":"f10c0"},"md-smog":{"char":"󰩱","code":"f0a71"},"md-smoke":{"char":"󱞙","code":"f1799"},"md-smoke_detector":{"char":"󰎒","code":"f0392"},"md-smoke_detector_alert":{"char":"󱤮","code":"f192e"},"md-smoke_detector_alert_outline":{"char":"󱤯","code":"f192f"},"md-smoke_detector_off":{"char":"󱠉","code":"f1809"},"md-smoke_detector_off_outline":{"char":"󱠊","code":"f180a"},"md-smoke_detector_outline":{"char":"󱠈","code":"f1808"},"md-smoke_detector_variant":{"char":"󱠋","code":"f180b"},"md-smoke_detector_variant_alert":{"char":"󱤰","code":"f1930"},"md-smoke_detector_variant_off":{"char":"󱠌","code":"f180c"},"md-smoking":{"char":"󰒴","code":"f04b4"},"md-smoking_off":{"char":"󰒵","code":"f04b5"},"md-smoking_pipe":{"char":"󱐍","code":"f140d"},"md-smoking_pipe_off":{"char":"󱐨","code":"f1428"},"md-snail":{"char":"󱙷","code":"f1677"},"md-snake":{"char":"󱔎","code":"f150e"},"md-snapchat":{"char":"󰒶","code":"f04b6"},"md-snowboard":{"char":"󱌇","code":"f1307"},"md-snowflake":{"char":"󰜗","code":"f0717"},"md-snowflake_alert":{"char":"󰼩","code":"f0f29"},"md-snowflake_check":{"char":"󱩰","code":"f1a70"},"md-snowflake_melt":{"char":"󱋋","code":"f12cb"},"md-snowflake_off":{"char":"󱓣","code":"f14e3"},"md-snowflake_thermometer":{"char":"󱩱","code":"f1a71"},"md-snowflake_variant":{"char":"󰼪","code":"f0f2a"},"md-snowman":{"char":"󰒷","code":"f04b7"},"md-snowmobile":{"char":"󰛝","code":"f06dd"},"md-snowshoeing":{"char":"󱩲","code":"f1a72"},"md-soccer":{"char":"󰒸","code":"f04b8"},"md-soccer_field":{"char":"󰠴","code":"f0834"},"md-social_distance_2_meters":{"char":"󱕹","code":"f1579"},"md-social_distance_6_feet":{"char":"󱕺","code":"f157a"},"md-sofa":{"char":"󰒹","code":"f04b9"},"md-sofa_outline":{"char":"󱕭","code":"f156d"},"md-sofa_single":{"char":"󱕮","code":"f156e"},"md-sofa_single_outline":{"char":"󱕯","code":"f156f"},"md-solar_panel":{"char":"󰶛","code":"f0d9b"},"md-solar_panel_large":{"char":"󰶜","code":"f0d9c"},"md-solar_power":{"char":"󰩲","code":"f0a72"},"md-solar_power_variant":{"char":"󱩳","code":"f1a73"},"md-solar_power_variant_outline":{"char":"󱩴","code":"f1a74"},"md-soldering_iron":{"char":"󱂒","code":"f1092"},"md-solid":{"char":"󰚍","code":"f068d"},"md-sony_playstation":{"char":"󰐔","code":"f0414"},"md-sort":{"char":"󰒺","code":"f04ba"},"md-sort_alphabetical_ascending":{"char":"󰖽","code":"f05bd"},"md-sort_alphabetical_ascending_variant":{"char":"󱅈","code":"f1148"},"md-sort_alphabetical_descending":{"char":"󰖿","code":"f05bf"},"md-sort_alphabetical_descending_variant":{"char":"󱅉","code":"f1149"},"md-sort_alphabetical_variant":{"char":"󰒻","code":"f04bb"},"md-sort_ascending":{"char":"󰒼","code":"f04bc"},"md-sort_bool_ascending":{"char":"󱎅","code":"f1385"},"md-sort_bool_ascending_variant":{"char":"󱎆","code":"f1386"},"md-sort_bool_descending":{"char":"󱎇","code":"f1387"},"md-sort_bool_descending_variant":{"char":"󱎈","code":"f1388"},"md-sort_calendar_ascending":{"char":"󱕇","code":"f1547"},"md-sort_calendar_descending":{"char":"󱕈","code":"f1548"},"md-sort_clock_ascending":{"char":"󱕉","code":"f1549"},"md-sort_clock_ascending_outline":{"char":"󱕊","code":"f154a"},"md-sort_clock_descending":{"char":"󱕋","code":"f154b"},"md-sort_clock_descending_outline":{"char":"󱕌","code":"f154c"},"md-sort_descending":{"char":"󰒽","code":"f04bd"},"md-sort_numeric_ascending":{"char":"󱎉","code":"f1389"},"md-sort_numeric_ascending_variant":{"char":"󰤍","code":"f090d"},"md-sort_numeric_descending":{"char":"󱎊","code":"f138a"},"md-sort_numeric_descending_variant":{"char":"󰫒","code":"f0ad2"},"md-sort_numeric_variant":{"char":"󰒾","code":"f04be"},"md-sort_reverse_variant":{"char":"󰌼","code":"f033c"},"md-sort_variant":{"char":"󰒿","code":"f04bf"},"md-sort_variant_lock":{"char":"󰳍","code":"f0ccd"},"md-sort_variant_lock_open":{"char":"󰳎","code":"f0cce"},"md-sort_variant_off":{"char":"󱪻","code":"f1abb"},"md-sort_variant_remove":{"char":"󱅇","code":"f1147"},"md-soundbar":{"char":"󱟛","code":"f17db"},"md-soundcloud":{"char":"󰓀","code":"f04c0"},"md-source_branch":{"char":"󰘬","code":"f062c"},"md-source_branch_check":{"char":"󱓏","code":"f14cf"},"md-source_branch_minus":{"char":"󱓋","code":"f14cb"},"md-source_branch_plus":{"char":"󱓊","code":"f14ca"},"md-source_branch_refresh":{"char":"󱓍","code":"f14cd"},"md-source_branch_remove":{"char":"󱓌","code":"f14cc"},"md-source_branch_sync":{"char":"󱓎","code":"f14ce"},"md-source_commit":{"char":"󰜘","code":"f0718"},"md-source_commit_end":{"char":"󰜙","code":"f0719"},"md-source_commit_end_local":{"char":"󰜚","code":"f071a"},"md-source_commit_local":{"char":"󰜛","code":"f071b"},"md-source_commit_next_local":{"char":"󰜜","code":"f071c"},"md-source_commit_start":{"char":"󰜝","code":"f071d"},"md-source_commit_start_next_local":{"char":"󰜞","code":"f071e"},"md-source_fork":{"char":"󰓁","code":"f04c1"},"md-source_merge":{"char":"󰘭","code":"f062d"},"md-source_pull":{"char":"󰓂","code":"f04c2"},"md-source_repository":{"char":"󰳏","code":"f0ccf"},"md-source_repository_multiple":{"char":"󰳐","code":"f0cd0"},"md-soy_sauce":{"char":"󰟮","code":"f07ee"},"md-soy_sauce_off":{"char":"󱏼","code":"f13fc"},"md-spa":{"char":"󰳑","code":"f0cd1"},"md-spa_outline":{"char":"󰳒","code":"f0cd2"},"md-space_invaders":{"char":"󰯉","code":"f0bc9"},"md-space_station":{"char":"󱎃","code":"f1383"},"md-spade":{"char":"󰹥","code":"f0e65"},"md-speaker":{"char":"󰓃","code":"f04c3"},"md-speaker_bluetooth":{"char":"󰦢","code":"f09a2"},"md-speaker_multiple":{"char":"󰴸","code":"f0d38"},"md-speaker_off":{"char":"󰓄","code":"f04c4"},"md-speaker_wireless":{"char":"󰜟","code":"f071f"},"md-spear":{"char":"󱡅","code":"f1845"},"md-speedometer":{"char":"󰓅","code":"f04c5"},"md-speedometer_medium":{"char":"󰾅","code":"f0f85"},"md-speedometer_slow":{"char":"󰾆","code":"f0f86"},"md-spellcheck":{"char":"󰓆","code":"f04c6"},"md-sphere":{"char":"󱥔","code":"f1954"},"md-sphere_off":{"char":"󱥕","code":"f1955"},"md-spider":{"char":"󱇪","code":"f11ea"},"md-spider_thread":{"char":"󱇫","code":"f11eb"},"md-spider_web":{"char":"󰯊","code":"f0bca"},"md-spirit_level":{"char":"󱓱","code":"f14f1"},"md-spoon_sugar":{"char":"󱐩","code":"f1429"},"md-spotify":{"char":"󰓇","code":"f04c7"},"md-spotlight":{"char":"󰓈","code":"f04c8"},"md-spotlight_beam":{"char":"󰓉","code":"f04c9"},"md-spray":{"char":"󰙥","code":"f0665"},"md-spray_bottle":{"char":"󰫠","code":"f0ae0"},"md-sprinkler":{"char":"󱁟","code":"f105f"},"md-sprinkler_fire":{"char":"󱦝","code":"f199d"},"md-sprinkler_variant":{"char":"󱁠","code":"f1060"},"md-sprout":{"char":"󰹦","code":"f0e66"},"md-sprout_outline":{"char":"󰹧","code":"f0e67"},"md-square":{"char":"󰝤","code":"f0764"},"md-square_circle":{"char":"󱔀","code":"f1500"},"md-square_edit_outline":{"char":"󰤌","code":"f090c"},"md-square_medium":{"char":"󰨓","code":"f0a13"},"md-square_medium_outline":{"char":"󰨔","code":"f0a14"},"md-square_off":{"char":"󱋮","code":"f12ee"},"md-square_off_outline":{"char":"󱋯","code":"f12ef"},"md-square_opacity":{"char":"󱡔","code":"f1854"},"md-square_outline":{"char":"󰝣","code":"f0763"},"md-square_root":{"char":"󰞄","code":"f0784"},"md-square_root_box":{"char":"󰦣","code":"f09a3"},"md-square_rounded":{"char":"󱓻","code":"f14fb"},"md-square_rounded_badge":{"char":"󱨇","code":"f1a07"},"md-square_rounded_badge_outline":{"char":"󱨈","code":"f1a08"},"md-square_rounded_outline":{"char":"󱓼","code":"f14fc"},"md-square_small":{"char":"󰨕","code":"f0a15"},"md-square_wave":{"char":"󱑻","code":"f147b"},"md-squeegee":{"char":"󰫡","code":"f0ae1"},"md-ssh":{"char":"󰣀","code":"f08c0"},"md-stack_exchange":{"char":"󰘋","code":"f060b"},"md-stack_overflow":{"char":"󰓌","code":"f04cc"},"md-stackpath":{"char":"󰍙","code":"f0359"},"md-stadium":{"char":"󰿹","code":"f0ff9"},"md-stadium_variant":{"char":"󰜠","code":"f0720"},"md-stairs":{"char":"󰓍","code":"f04cd"},"md-stairs_box":{"char":"󱎞","code":"f139e"},"md-stairs_down":{"char":"󱊾","code":"f12be"},"md-stairs_up":{"char":"󱊽","code":"f12bd"},"md-stamper":{"char":"󰴹","code":"f0d39"},"md-standard_definition":{"char":"󰟯","code":"f07ef"},"md-star":{"char":"󰓎","code":"f04ce"},"md-star_box":{"char":"󰩳","code":"f0a73"},"md-star_box_multiple":{"char":"󱊆","code":"f1286"},"md-star_box_multiple_outline":{"char":"󱊇","code":"f1287"},"md-star_box_outline":{"char":"󰩴","code":"f0a74"},"md-star_check":{"char":"󱕦","code":"f1566"},"md-star_check_outline":{"char":"󱕪","code":"f156a"},"md-star_circle":{"char":"󰓏","code":"f04cf"},"md-star_circle_outline":{"char":"󰦤","code":"f09a4"},"md-star_cog":{"char":"󱙨","code":"f1668"},"md-star_cog_outline":{"char":"󱙩","code":"f1669"},"md-star_crescent":{"char":"󰥹","code":"f0979"},"md-star_david":{"char":"󰥺","code":"f097a"},"md-star_face":{"char":"󰦥","code":"f09a5"},"md-star_four_points":{"char":"󰫢","code":"f0ae2"},"md-star_four_points_outline":{"char":"󰫣","code":"f0ae3"},"md-star_half":{"char":"󰉆","code":"f0246"},"md-star_half_full":{"char":"󰓐","code":"f04d0"},"md-star_minus":{"char":"󱕤","code":"f1564"},"md-star_minus_outline":{"char":"󱕨","code":"f1568"},"md-star_off":{"char":"󰓑","code":"f04d1"},"md-star_off_outline":{"char":"󱕛","code":"f155b"},"md-star_outline":{"char":"󰓒","code":"f04d2"},"md-star_plus":{"char":"󱕣","code":"f1563"},"md-star_plus_outline":{"char":"󱕧","code":"f1567"},"md-star_remove":{"char":"󱕥","code":"f1565"},"md-star_remove_outline":{"char":"󱕩","code":"f1569"},"md-star_settings":{"char":"󱙪","code":"f166a"},"md-star_settings_outline":{"char":"󱙫","code":"f166b"},"md-star_shooting":{"char":"󱝁","code":"f1741"},"md-star_shooting_outline":{"char":"󱝂","code":"f1742"},"md-star_three_points":{"char":"󰫤","code":"f0ae4"},"md-star_three_points_outline":{"char":"󰫥","code":"f0ae5"},"md-state_machine":{"char":"󱇯","code":"f11ef"},"md-steam":{"char":"󰓓","code":"f04d3"},"md-steering":{"char":"󰓔","code":"f04d4"},"md-steering_off":{"char":"󰤎","code":"f090e"},"md-step_backward":{"char":"󰓕","code":"f04d5"},"md-step_backward_2":{"char":"󰓖","code":"f04d6"},"md-step_forward":{"char":"󰓗","code":"f04d7"},"md-step_forward_2":{"char":"󰓘","code":"f04d8"},"md-stethoscope":{"char":"󰓙","code":"f04d9"},"md-sticker":{"char":"󱍤","code":"f1364"},"md-sticker_alert":{"char":"󱍥","code":"f1365"},"md-sticker_alert_outline":{"char":"󱍦","code":"f1366"},"md-sticker_check":{"char":"󱍧","code":"f1367"},"md-sticker_check_outline":{"char":"󱍨","code":"f1368"},"md-sticker_circle_outline":{"char":"󰗐","code":"f05d0"},"md-sticker_emoji":{"char":"󰞅","code":"f0785"},"md-sticker_minus":{"char":"󱍩","code":"f1369"},"md-sticker_minus_outline":{"char":"󱍪","code":"f136a"},"md-sticker_outline":{"char":"󱍫","code":"f136b"},"md-sticker_plus":{"char":"󱍬","code":"f136c"},"md-sticker_plus_outline":{"char":"󱍭","code":"f136d"},"md-sticker_remove":{"char":"󱍮","code":"f136e"},"md-sticker_remove_outline":{"char":"󱍯","code":"f136f"},"md-sticker_text":{"char":"󱞎","code":"f178e"},"md-sticker_text_outline":{"char":"󱞏","code":"f178f"},"md-stocking":{"char":"󰓚","code":"f04da"},"md-stomach":{"char":"󱂓","code":"f1093"},"md-stool":{"char":"󱥝","code":"f195d"},"md-stool_outline":{"char":"󱥞","code":"f195e"},"md-stop":{"char":"󰓛","code":"f04db"},"md-stop_circle":{"char":"󰙦","code":"f0666"},"md-stop_circle_outline":{"char":"󰙧","code":"f0667"},"md-storage_tank":{"char":"󱩵","code":"f1a75"},"md-storage_tank_outline":{"char":"󱩶","code":"f1a76"},"md-store":{"char":"󰓜","code":"f04dc"},"md-store_24_hour":{"char":"󰓝","code":"f04dd"},"md-store_alert":{"char":"󱣁","code":"f18c1"},"md-store_alert_outline":{"char":"󱣂","code":"f18c2"},"md-store_check":{"char":"󱣃","code":"f18c3"},"md-store_check_outline":{"char":"󱣄","code":"f18c4"},"md-store_clock":{"char":"󱣅","code":"f18c5"},"md-store_clock_outline":{"char":"󱣆","code":"f18c6"},"md-store_cog":{"char":"󱣇","code":"f18c7"},"md-store_cog_outline":{"char":"󱣈","code":"f18c8"},"md-store_edit":{"char":"󱣉","code":"f18c9"},"md-store_edit_outline":{"char":"󱣊","code":"f18ca"},"md-store_marker":{"char":"󱣋","code":"f18cb"},"md-store_marker_outline":{"char":"󱣌","code":"f18cc"},"md-store_minus":{"char":"󱙞","code":"f165e"},"md-store_minus_outline":{"char":"󱣍","code":"f18cd"},"md-store_off":{"char":"󱣎","code":"f18ce"},"md-store_off_outline":{"char":"󱣏","code":"f18cf"},"md-store_outline":{"char":"󱍡","code":"f1361"},"md-store_plus":{"char":"󱙟","code":"f165f"},"md-store_plus_outline":{"char":"󱣐","code":"f18d0"},"md-store_remove":{"char":"󱙠","code":"f1660"},"md-store_remove_outline":{"char":"󱣑","code":"f18d1"},"md-store_search":{"char":"󱣒","code":"f18d2"},"md-store_search_outline":{"char":"󱣓","code":"f18d3"},"md-store_settings":{"char":"󱣔","code":"f18d4"},"md-store_settings_outline":{"char":"󱣕","code":"f18d5"},"md-storefront":{"char":"󰟇","code":"f07c7"},"md-storefront_outline":{"char":"󱃁","code":"f10c1"},"md-stove":{"char":"󰓞","code":"f04de"},"md-strategy":{"char":"󱇖","code":"f11d6"},"md-stretch_to_page":{"char":"󰼫","code":"f0f2b"},"md-stretch_to_page_outline":{"char":"󰼬","code":"f0f2c"},"md-string_lights":{"char":"󱊺","code":"f12ba"},"md-string_lights_off":{"char":"󱊻","code":"f12bb"},"md-subdirectory_arrow_left":{"char":"󰘌","code":"f060c"},"md-subdirectory_arrow_right":{"char":"󰘍","code":"f060d"},"md-submarine":{"char":"󱕬","code":"f156c"},"md-subtitles":{"char":"󰨖","code":"f0a16"},"md-subtitles_outline":{"char":"󰨗","code":"f0a17"},"md-subway":{"char":"󰚬","code":"f06ac"},"md-subway_alert_variant":{"char":"󰶝","code":"f0d9d"},"md-subway_variant":{"char":"󰓟","code":"f04df"},"md-summit":{"char":"󰞆","code":"f0786"},"md-sun_clock":{"char":"󱩷","code":"f1a77"},"md-sun_clock_outline":{"char":"󱩸","code":"f1a78"},"md-sun_compass":{"char":"󱦥","code":"f19a5"},"md-sun_snowflake":{"char":"󱞖","code":"f1796"},"md-sun_snowflake_variant":{"char":"󱩹","code":"f1a79"},"md-sun_thermometer":{"char":"󱣖","code":"f18d6"},"md-sun_thermometer_outline":{"char":"󱣗","code":"f18d7"},"md-sun_wireless":{"char":"󱟾","code":"f17fe"},"md-sun_wireless_outline":{"char":"󱟿","code":"f17ff"},"md-sunglasses":{"char":"󰓠","code":"f04e0"},"md-surfing":{"char":"󱝆","code":"f1746"},"md-surround_sound":{"char":"󰗅","code":"f05c5"},"md-surround_sound_2_0":{"char":"󰟰","code":"f07f0"},"md-surround_sound_2_1":{"char":"󱜩","code":"f1729"},"md-surround_sound_3_1":{"char":"󰟱","code":"f07f1"},"md-surround_sound_5_1":{"char":"󰟲","code":"f07f2"},"md-surround_sound_5_1_2":{"char":"󱜪","code":"f172a"},"md-surround_sound_7_1":{"char":"󰟳","code":"f07f3"},"md-svg":{"char":"󰜡","code":"f0721"},"md-swap_horizontal":{"char":"󰓡","code":"f04e1"},"md-swap_horizontal_bold":{"char":"󰯍","code":"f0bcd"},"md-swap_horizontal_circle":{"char":"󰿡","code":"f0fe1"},"md-swap_horizontal_circle_outline":{"char":"󰿢","code":"f0fe2"},"md-swap_horizontal_variant":{"char":"󰣁","code":"f08c1"},"md-swap_vertical":{"char":"󰓢","code":"f04e2"},"md-swap_vertical_bold":{"char":"󰯎","code":"f0bce"},"md-swap_vertical_circle":{"char":"󰿣","code":"f0fe3"},"md-swap_vertical_circle_outline":{"char":"󰿤","code":"f0fe4"},"md-swap_vertical_variant":{"char":"󰣂","code":"f08c2"},"md-swim":{"char":"󰓣","code":"f04e3"},"md-switch":{"char":"󰓤","code":"f04e4"},"md-sword":{"char":"󰓥","code":"f04e5"},"md-sword_cross":{"char":"󰞇","code":"f0787"},"md-syllabary_hangul":{"char":"󱌳","code":"f1333"},"md-syllabary_hiragana":{"char":"󱌴","code":"f1334"},"md-syllabary_katakana":{"char":"󱌵","code":"f1335"},"md-syllabary_katakana_halfwidth":{"char":"󱌶","code":"f1336"},"md-symbol":{"char":"󱔁","code":"f1501"},"md-symfony":{"char":"󰫦","code":"f0ae6"},"md-sync":{"char":"󰓦","code":"f04e6"},"md-sync_alert":{"char":"󰓧","code":"f04e7"},"md-sync_circle":{"char":"󱍸","code":"f1378"},"md-sync_off":{"char":"󰓨","code":"f04e8"},"md-tab":{"char":"󰓩","code":"f04e9"},"md-tab_minus":{"char":"󰭋","code":"f0b4b"},"md-tab_plus":{"char":"󰝜","code":"f075c"},"md-tab_remove":{"char":"󰭌","code":"f0b4c"},"md-tab_search":{"char":"󱦞","code":"f199e"},"md-tab_unselected":{"char":"󰓪","code":"f04ea"},"md-table":{"char":"󰓫","code":"f04eb"},"md-table_account":{"char":"󱎹","code":"f13b9"},"md-table_alert":{"char":"󱎺","code":"f13ba"},"md-table_arrow_down":{"char":"󱎻","code":"f13bb"},"md-table_arrow_left":{"char":"󱎼","code":"f13bc"},"md-table_arrow_right":{"char":"󱎽","code":"f13bd"},"md-table_arrow_up":{"char":"󱎾","code":"f13be"},"md-table_border":{"char":"󰨘","code":"f0a18"},"md-table_cancel":{"char":"󱎿","code":"f13bf"},"md-table_chair":{"char":"󱁡","code":"f1061"},"md-table_check":{"char":"󱏀","code":"f13c0"},"md-table_clock":{"char":"󱏁","code":"f13c1"},"md-table_cog":{"char":"󱏂","code":"f13c2"},"md-table_column":{"char":"󰠵","code":"f0835"},"md-table_column_plus_after":{"char":"󰓬","code":"f04ec"},"md-table_column_plus_before":{"char":"󰓭","code":"f04ed"},"md-table_column_remove":{"char":"󰓮","code":"f04ee"},"md-table_column_width":{"char":"󰓯","code":"f04ef"},"md-table_edit":{"char":"󰓰","code":"f04f0"},"md-table_eye":{"char":"󱂔","code":"f1094"},"md-table_eye_off":{"char":"󱏃","code":"f13c3"},"md-table_furniture":{"char":"󰖼","code":"f05bc"},"md-table_headers_eye":{"char":"󱈝","code":"f121d"},"md-table_headers_eye_off":{"char":"󱈞","code":"f121e"},"md-table_heart":{"char":"󱏄","code":"f13c4"},"md-table_key":{"char":"󱏅","code":"f13c5"},"md-table_large":{"char":"󰓱","code":"f04f1"},"md-table_large_plus":{"char":"󰾇","code":"f0f87"},"md-table_large_remove":{"char":"󰾈","code":"f0f88"},"md-table_lock":{"char":"󱏆","code":"f13c6"},"md-table_merge_cells":{"char":"󰦦","code":"f09a6"},"md-table_minus":{"char":"󱏇","code":"f13c7"},"md-table_multiple":{"char":"󱏈","code":"f13c8"},"md-table_network":{"char":"󱏉","code":"f13c9"},"md-table_of_contents":{"char":"󰠶","code":"f0836"},"md-table_off":{"char":"󱏊","code":"f13ca"},"md-table_picnic":{"char":"󱝃","code":"f1743"},"md-table_pivot":{"char":"󱠼","code":"f183c"},"md-table_plus":{"char":"󰩵","code":"f0a75"},"md-table_refresh":{"char":"󱎠","code":"f13a0"},"md-table_remove":{"char":"󰩶","code":"f0a76"},"md-table_row":{"char":"󰠷","code":"f0837"},"md-table_row_height":{"char":"󰓲","code":"f04f2"},"md-table_row_plus_after":{"char":"󰓳","code":"f04f3"},"md-table_row_plus_before":{"char":"󰓴","code":"f04f4"},"md-table_row_remove":{"char":"󰓵","code":"f04f5"},"md-table_search":{"char":"󰤏","code":"f090f"},"md-table_settings":{"char":"󰠸","code":"f0838"},"md-table_split_cell":{"char":"󱐪","code":"f142a"},"md-table_star":{"char":"󱏋","code":"f13cb"},"md-table_sync":{"char":"󱎡","code":"f13a1"},"md-table_tennis":{"char":"󰹨","code":"f0e68"},"md-tablet":{"char":"󰓶","code":"f04f6"},"md-tablet_android":{"char":"󰓷","code":"f04f7"},"md-tablet_cellphone":{"char":"󰦧","code":"f09a7"},"md-tablet_dashboard":{"char":"󰻎","code":"f0ece"},"md-taco":{"char":"󰝢","code":"f0762"},"md-tag":{"char":"󰓹","code":"f04f9"},"md-tag_arrow_down":{"char":"󱜫","code":"f172b"},"md-tag_arrow_down_outline":{"char":"󱜬","code":"f172c"},"md-tag_arrow_left":{"char":"󱜭","code":"f172d"},"md-tag_arrow_left_outline":{"char":"󱜮","code":"f172e"},"md-tag_arrow_right":{"char":"󱜯","code":"f172f"},"md-tag_arrow_right_outline":{"char":"󱜰","code":"f1730"},"md-tag_arrow_up":{"char":"󱜱","code":"f1731"},"md-tag_arrow_up_outline":{"char":"󱜲","code":"f1732"},"md-tag_check":{"char":"󱩺","code":"f1a7a"},"md-tag_check_outline":{"char":"󱩻","code":"f1a7b"},"md-tag_faces":{"char":"󰓺","code":"f04fa"},"md-tag_heart":{"char":"󰚋","code":"f068b"},"md-tag_heart_outline":{"char":"󰯏","code":"f0bcf"},"md-tag_minus":{"char":"󰤐","code":"f0910"},"md-tag_minus_outline":{"char":"󱈟","code":"f121f"},"md-tag_multiple":{"char":"󰓻","code":"f04fb"},"md-tag_multiple_outline":{"char":"󱋷","code":"f12f7"},"md-tag_off":{"char":"󱈠","code":"f1220"},"md-tag_off_outline":{"char":"󱈡","code":"f1221"},"md-tag_outline":{"char":"󰓼","code":"f04fc"},"md-tag_plus":{"char":"󰜢","code":"f0722"},"md-tag_plus_outline":{"char":"󱈢","code":"f1222"},"md-tag_remove":{"char":"󰜣","code":"f0723"},"md-tag_remove_outline":{"char":"󱈣","code":"f1223"},"md-tag_search":{"char":"󱤇","code":"f1907"},"md-tag_search_outline":{"char":"󱤈","code":"f1908"},"md-tag_text":{"char":"󱈤","code":"f1224"},"md-tag_text_outline":{"char":"󰓽","code":"f04fd"},"md-tailwind":{"char":"󱏿","code":"f13ff"},"md-tally_mark_1":{"char":"󱪼","code":"f1abc"},"md-tally_mark_2":{"char":"󱪽","code":"f1abd"},"md-tally_mark_3":{"char":"󱪾","code":"f1abe"},"md-tally_mark_4":{"char":"󱪿","code":"f1abf"},"md-tally_mark_5":{"char":"󱫀","code":"f1ac0"},"md-tangram":{"char":"󰓸","code":"f04f8"},"md-tank":{"char":"󰴺","code":"f0d3a"},"md-tanker_truck":{"char":"󰿥","code":"f0fe5"},"md-tape_drive":{"char":"󱛟","code":"f16df"},"md-tape_measure":{"char":"󰭍","code":"f0b4d"},"md-target":{"char":"󰓾","code":"f04fe"},"md-target_account":{"char":"󰯐","code":"f0bd0"},"md-target_variant":{"char":"󰩷","code":"f0a77"},"md-taxi":{"char":"󰓿","code":"f04ff"},"md-tea":{"char":"󰶞","code":"f0d9e"},"md-tea_outline":{"char":"󰶟","code":"f0d9f"},"md-teamviewer":{"char":"󰔀","code":"f0500"},"md-teddy_bear":{"char":"󱣻","code":"f18fb"},"md-telescope":{"char":"󰭎","code":"f0b4e"},"md-television":{"char":"󰔂","code":"f0502"},"md-television_ambient_light":{"char":"󱍖","code":"f1356"},"md-television_box":{"char":"󰠹","code":"f0839"},"md-television_classic":{"char":"󰟴","code":"f07f4"},"md-television_classic_off":{"char":"󰠺","code":"f083a"},"md-television_guide":{"char":"󰔃","code":"f0503"},"md-television_off":{"char":"󰠻","code":"f083b"},"md-television_pause":{"char":"󰾉","code":"f0f89"},"md-television_play":{"char":"󰻏","code":"f0ecf"},"md-television_shimmer":{"char":"󱄐","code":"f1110"},"md-television_stop":{"char":"󰾊","code":"f0f8a"},"md-temperature_celsius":{"char":"󰔄","code":"f0504"},"md-temperature_fahrenheit":{"char":"󰔅","code":"f0505"},"md-temperature_kelvin":{"char":"󰔆","code":"f0506"},"md-tennis":{"char":"󰶠","code":"f0da0"},"md-tennis_ball":{"char":"󰔇","code":"f0507"},"md-tent":{"char":"󰔈","code":"f0508"},"md-terraform":{"char":"󱁢","code":"f1062"},"md-test_tube":{"char":"󰙨","code":"f0668"},"md-test_tube_empty":{"char":"󰤑","code":"f0911"},"md-test_tube_off":{"char":"󰤒","code":"f0912"},"md-text":{"char":"󰦨","code":"f09a8"},"md-text_account":{"char":"󱕰","code":"f1570"},"md-text_box":{"char":"󰈚","code":"f021a"},"md-text_box_check":{"char":"󰺦","code":"f0ea6"},"md-text_box_check_outline":{"char":"󰺧","code":"f0ea7"},"md-text_box_edit":{"char":"󱩼","code":"f1a7c"},"md-text_box_edit_outline":{"char":"󱩽","code":"f1a7d"},"md-text_box_minus":{"char":"󰺨","code":"f0ea8"},"md-text_box_minus_outline":{"char":"󰺩","code":"f0ea9"},"md-text_box_multiple":{"char":"󰪷","code":"f0ab7"},"md-text_box_multiple_outline":{"char":"󰪸","code":"f0ab8"},"md-text_box_outline":{"char":"󰧭","code":"f09ed"},"md-text_box_plus":{"char":"󰺪","code":"f0eaa"},"md-text_box_plus_outline":{"char":"󰺫","code":"f0eab"},"md-text_box_remove":{"char":"󰺬","code":"f0eac"},"md-text_box_remove_outline":{"char":"󰺭","code":"f0ead"},"md-text_box_search":{"char":"󰺮","code":"f0eae"},"md-text_box_search_outline":{"char":"󰺯","code":"f0eaf"},"md-text_long":{"char":"󰦪","code":"f09aa"},"md-text_recognition":{"char":"󱄽","code":"f113d"},"md-text_search":{"char":"󱎸","code":"f13b8"},"md-text_search_variant":{"char":"󱩾","code":"f1a7e"},"md-text_shadow":{"char":"󰙩","code":"f0669"},"md-text_short":{"char":"󰦩","code":"f09a9"},"md-text_to_speech":{"char":"󰔊","code":"f050a"},"md-text_to_speech_off":{"char":"󰔋","code":"f050b"},"md-texture":{"char":"󰔌","code":"f050c"},"md-texture_box":{"char":"󰿦","code":"f0fe6"},"md-theater":{"char":"󰔍","code":"f050d"},"md-theme_light_dark":{"char":"󰔎","code":"f050e"},"md-thermometer":{"char":"󰔏","code":"f050f"},"md-thermometer_alert":{"char":"󰸁","code":"f0e01"},"md-thermometer_bluetooth":{"char":"󱢕","code":"f1895"},"md-thermometer_check":{"char":"󱩿","code":"f1a7f"},"md-thermometer_chevron_down":{"char":"󰸂","code":"f0e02"},"md-thermometer_chevron_up":{"char":"󰸃","code":"f0e03"},"md-thermometer_high":{"char":"󱃂","code":"f10c2"},"md-thermometer_lines":{"char":"󰔐","code":"f0510"},"md-thermometer_low":{"char":"󱃃","code":"f10c3"},"md-thermometer_minus":{"char":"󰸄","code":"f0e04"},"md-thermometer_off":{"char":"󱔱","code":"f1531"},"md-thermometer_plus":{"char":"󰸅","code":"f0e05"},"md-thermometer_water":{"char":"󱪀","code":"f1a80"},"md-thermostat":{"char":"󰎓","code":"f0393"},"md-thermostat_box":{"char":"󰢑","code":"f0891"},"md-thought_bubble":{"char":"󰟶","code":"f07f6"},"md-thought_bubble_outline":{"char":"󰟷","code":"f07f7"},"md-thumb_down":{"char":"󰔑","code":"f0511"},"md-thumb_down_outline":{"char":"󰔒","code":"f0512"},"md-thumb_up":{"char":"󰔓","code":"f0513"},"md-thumb_up_outline":{"char":"󰔔","code":"f0514"},"md-thumbs_up_down":{"char":"󰔕","code":"f0515"},"md-thumbs_up_down_outline":{"char":"󱤔","code":"f1914"},"md-ticket":{"char":"󰔖","code":"f0516"},"md-ticket_account":{"char":"󰔗","code":"f0517"},"md-ticket_confirmation":{"char":"󰔘","code":"f0518"},"md-ticket_confirmation_outline":{"char":"󱎪","code":"f13aa"},"md-ticket_outline":{"char":"󰤓","code":"f0913"},"md-ticket_percent":{"char":"󰜤","code":"f0724"},"md-ticket_percent_outline":{"char":"󱐫","code":"f142b"},"md-tie":{"char":"󰔙","code":"f0519"},"md-tilde":{"char":"󰜥","code":"f0725"},"md-tilde_off":{"char":"󱣳","code":"f18f3"},"md-timelapse":{"char":"󰔚","code":"f051a"},"md-timeline":{"char":"󰯑","code":"f0bd1"},"md-timeline_alert":{"char":"󰾕","code":"f0f95"},"md-timeline_alert_outline":{"char":"󰾘","code":"f0f98"},"md-timeline_check":{"char":"󱔲","code":"f1532"},"md-timeline_check_outline":{"char":"󱔳","code":"f1533"},"md-timeline_clock":{"char":"󱇻","code":"f11fb"},"md-timeline_clock_outline":{"char":"󱇼","code":"f11fc"},"md-timeline_help":{"char":"󰾙","code":"f0f99"},"md-timeline_help_outline":{"char":"󰾚","code":"f0f9a"},"md-timeline_minus":{"char":"󱔴","code":"f1534"},"md-timeline_minus_outline":{"char":"󱔵","code":"f1535"},"md-timeline_outline":{"char":"󰯒","code":"f0bd2"},"md-timeline_plus":{"char":"󰾖","code":"f0f96"},"md-timeline_plus_outline":{"char":"󰾗","code":"f0f97"},"md-timeline_remove":{"char":"󱔶","code":"f1536"},"md-timeline_remove_outline":{"char":"󱔷","code":"f1537"},"md-timeline_text":{"char":"󰯓","code":"f0bd3"},"md-timeline_text_outline":{"char":"󰯔","code":"f0bd4"},"md-timer":{"char":"󱎫","code":"f13ab"},"md-timer_10":{"char":"󰔜","code":"f051c"},"md-timer_3":{"char":"󰔝","code":"f051d"},"md-timer_alert":{"char":"󱫌","code":"f1acc"},"md-timer_alert_outline":{"char":"󱫍","code":"f1acd"},"md-timer_cancel":{"char":"󱫎","code":"f1ace"},"md-timer_cancel_outline":{"char":"󱫏","code":"f1acf"},"md-timer_check":{"char":"󱫐","code":"f1ad0"},"md-timer_check_outline":{"char":"󱫑","code":"f1ad1"},"md-timer_cog":{"char":"󱤥","code":"f1925"},"md-timer_cog_outline":{"char":"󱤦","code":"f1926"},"md-timer_edit":{"char":"󱫒","code":"f1ad2"},"md-timer_edit_outline":{"char":"󱫓","code":"f1ad3"},"md-timer_lock":{"char":"󱫔","code":"f1ad4"},"md-timer_lock_open":{"char":"󱫕","code":"f1ad5"},"md-timer_lock_open_outline":{"char":"󱫖","code":"f1ad6"},"md-timer_lock_outline":{"char":"󱫗","code":"f1ad7"},"md-timer_marker":{"char":"󱫘","code":"f1ad8"},"md-timer_marker_outline":{"char":"󱫙","code":"f1ad9"},"md-timer_minus":{"char":"󱫚","code":"f1ada"},"md-timer_minus_outline":{"char":"󱫛","code":"f1adb"},"md-timer_music":{"char":"󱫜","code":"f1adc"},"md-timer_music_outline":{"char":"󱫝","code":"f1add"},"md-timer_off":{"char":"󱎬","code":"f13ac"},"md-timer_off_outline":{"char":"󰔞","code":"f051e"},"md-timer_outline":{"char":"󰔛","code":"f051b"},"md-timer_pause":{"char":"󱫞","code":"f1ade"},"md-timer_pause_outline":{"char":"󱫟","code":"f1adf"},"md-timer_play":{"char":"󱫠","code":"f1ae0"},"md-timer_play_outline":{"char":"󱫡","code":"f1ae1"},"md-timer_plus":{"char":"󱫢","code":"f1ae2"},"md-timer_plus_outline":{"char":"󱫣","code":"f1ae3"},"md-timer_refresh":{"char":"󱫤","code":"f1ae4"},"md-timer_refresh_outline":{"char":"󱫥","code":"f1ae5"},"md-timer_remove":{"char":"󱫦","code":"f1ae6"},"md-timer_remove_outline":{"char":"󱫧","code":"f1ae7"},"md-timer_sand":{"char":"󰔟","code":"f051f"},"md-timer_sand_complete":{"char":"󱦟","code":"f199f"},"md-timer_sand_empty":{"char":"󰚭","code":"f06ad"},"md-timer_sand_full":{"char":"󰞌","code":"f078c"},"md-timer_sand_paused":{"char":"󱦠","code":"f19a0"},"md-timer_settings":{"char":"󱤣","code":"f1923"},"md-timer_settings_outline":{"char":"󱤤","code":"f1924"},"md-timer_star":{"char":"󱫨","code":"f1ae8"},"md-timer_star_outline":{"char":"󱫩","code":"f1ae9"},"md-timer_stop":{"char":"󱫪","code":"f1aea"},"md-timer_stop_outline":{"char":"󱫫","code":"f1aeb"},"md-timer_sync":{"char":"󱫬","code":"f1aec"},"md-timer_sync_outline":{"char":"󱫭","code":"f1aed"},"md-timetable":{"char":"󰔠","code":"f0520"},"md-tire":{"char":"󱢖","code":"f1896"},"md-toaster":{"char":"󱁣","code":"f1063"},"md-toaster_off":{"char":"󱆷","code":"f11b7"},"md-toaster_oven":{"char":"󰳓","code":"f0cd3"},"md-toggle_switch":{"char":"󰔡","code":"f0521"},"md-toggle_switch_off":{"char":"󰔢","code":"f0522"},"md-toggle_switch_off_outline":{"char":"󰨙","code":"f0a19"},"md-toggle_switch_outline":{"char":"󰨚","code":"f0a1a"},"md-toggle_switch_variant":{"char":"󱨥","code":"f1a25"},"md-toggle_switch_variant_off":{"char":"󱨦","code":"f1a26"},"md-toilet":{"char":"󰦫","code":"f09ab"},"md-toolbox":{"char":"󰦬","code":"f09ac"},"md-toolbox_outline":{"char":"󰦭","code":"f09ad"},"md-tools":{"char":"󱁤","code":"f1064"},"md-tooltip":{"char":"󰔣","code":"f0523"},"md-tooltip_account":{"char":"󰀌","code":"f000c"},"md-tooltip_cellphone":{"char":"󱠻","code":"f183b"},"md-tooltip_check":{"char":"󱕜","code":"f155c"},"md-tooltip_check_outline":{"char":"󱕝","code":"f155d"},"md-tooltip_edit":{"char":"󰔤","code":"f0524"},"md-tooltip_edit_outline":{"char":"󱋅","code":"f12c5"},"md-tooltip_image":{"char":"󰔥","code":"f0525"},"md-tooltip_image_outline":{"char":"󰯕","code":"f0bd5"},"md-tooltip_minus":{"char":"󱕞","code":"f155e"},"md-tooltip_minus_outline":{"char":"󱕟","code":"f155f"},"md-tooltip_outline":{"char":"󰔦","code":"f0526"},"md-tooltip_plus":{"char":"󰯖","code":"f0bd6"},"md-tooltip_plus_outline":{"char":"󰔧","code":"f0527"},"md-tooltip_remove":{"char":"󱕠","code":"f1560"},"md-tooltip_remove_outline":{"char":"󱕡","code":"f1561"},"md-tooltip_text":{"char":"󰔨","code":"f0528"},"md-tooltip_text_outline":{"char":"󰯗","code":"f0bd7"},"md-tooth":{"char":"󰣃","code":"f08c3"},"md-tooth_outline":{"char":"󰔩","code":"f0529"},"md-toothbrush":{"char":"󱄩","code":"f1129"},"md-toothbrush_electric":{"char":"󱄬","code":"f112c"},"md-toothbrush_paste":{"char":"󱄪","code":"f112a"},"md-torch":{"char":"󱘆","code":"f1606"},"md-tortoise":{"char":"󰴻","code":"f0d3b"},"md-toslink":{"char":"󱊸","code":"f12b8"},"md-tournament":{"char":"󰦮","code":"f09ae"},"md-tow_truck":{"char":"󰠼","code":"f083c"},"md-tower_beach":{"char":"󰚁","code":"f0681"},"md-tower_fire":{"char":"󰚂","code":"f0682"},"md-town_hall":{"char":"󱡵","code":"f1875"},"md-toy_brick":{"char":"󱊈","code":"f1288"},"md-toy_brick_marker":{"char":"󱊉","code":"f1289"},"md-toy_brick_marker_outline":{"char":"󱊊","code":"f128a"},"md-toy_brick_minus":{"char":"󱊋","code":"f128b"},"md-toy_brick_minus_outline":{"char":"󱊌","code":"f128c"},"md-toy_brick_outline":{"char":"󱊍","code":"f128d"},"md-toy_brick_plus":{"char":"󱊎","code":"f128e"},"md-toy_brick_plus_outline":{"char":"󱊏","code":"f128f"},"md-toy_brick_remove":{"char":"󱊐","code":"f1290"},"md-toy_brick_remove_outline":{"char":"󱊑","code":"f1291"},"md-toy_brick_search":{"char":"󱊒","code":"f1292"},"md-toy_brick_search_outline":{"char":"󱊓","code":"f1293"},"md-track_light":{"char":"󰤔","code":"f0914"},"md-trackpad":{"char":"󰟸","code":"f07f8"},"md-trackpad_lock":{"char":"󰤳","code":"f0933"},"md-tractor":{"char":"󰢒","code":"f0892"},"md-tractor_variant":{"char":"󱓄","code":"f14c4"},"md-trademark":{"char":"󰩸","code":"f0a78"},"md-traffic_cone":{"char":"󱍼","code":"f137c"},"md-traffic_light":{"char":"󰔫","code":"f052b"},"md-traffic_light_outline":{"char":"󱠪","code":"f182a"},"md-train":{"char":"󰔬","code":"f052c"},"md-train_car":{"char":"󰯘","code":"f0bd8"},"md-train_car_passenger":{"char":"󱜳","code":"f1733"},"md-train_car_passenger_door":{"char":"󱜴","code":"f1734"},"md-train_car_passenger_door_open":{"char":"󱜵","code":"f1735"},"md-train_car_passenger_variant":{"char":"󱜶","code":"f1736"},"md-train_variant":{"char":"󰣄","code":"f08c4"},"md-tram":{"char":"󰔭","code":"f052d"},"md-tram_side":{"char":"󰿧","code":"f0fe7"},"md-transcribe":{"char":"󰔮","code":"f052e"},"md-transcribe_close":{"char":"󰔯","code":"f052f"},"md-transfer":{"char":"󱁥","code":"f1065"},"md-transfer_down":{"char":"󰶡","code":"f0da1"},"md-transfer_left":{"char":"󰶢","code":"f0da2"},"md-transfer_right":{"char":"󰔰","code":"f0530"},"md-transfer_up":{"char":"󰶣","code":"f0da3"},"md-transit_connection":{"char":"󰴼","code":"f0d3c"},"md-transit_connection_horizontal":{"char":"󱕆","code":"f1546"},"md-transit_connection_variant":{"char":"󰴽","code":"f0d3d"},"md-transit_detour":{"char":"󰾋","code":"f0f8b"},"md-transit_skip":{"char":"󱔕","code":"f1515"},"md-transit_transfer":{"char":"󰚮","code":"f06ae"},"md-transition":{"char":"󰤕","code":"f0915"},"md-transition_masked":{"char":"󰤖","code":"f0916"},"md-translate":{"char":"󰗊","code":"f05ca"},"md-translate_off":{"char":"󰸆","code":"f0e06"},"md-transmission_tower":{"char":"󰴾","code":"f0d3e"},"md-transmission_tower_export":{"char":"󱤬","code":"f192c"},"md-transmission_tower_import":{"char":"󱤭","code":"f192d"},"md-transmission_tower_off":{"char":"󱧝","code":"f19dd"},"md-trash_can":{"char":"󰩹","code":"f0a79"},"md-trash_can_outline":{"char":"󰩺","code":"f0a7a"},"md-tray":{"char":"󱊔","code":"f1294"},"md-tray_alert":{"char":"󱊕","code":"f1295"},"md-tray_arrow_down":{"char":"󰄠","code":"f0120"},"md-tray_arrow_up":{"char":"󰄝","code":"f011d"},"md-tray_full":{"char":"󱊖","code":"f1296"},"md-tray_minus":{"char":"󱊗","code":"f1297"},"md-tray_plus":{"char":"󱊘","code":"f1298"},"md-tray_remove":{"char":"󱊙","code":"f1299"},"md-treasure_chest":{"char":"󰜦","code":"f0726"},"md-tree":{"char":"󰔱","code":"f0531"},"md-tree_outline":{"char":"󰹩","code":"f0e69"},"md-trello":{"char":"󰔲","code":"f0532"},"md-trending_down":{"char":"󰔳","code":"f0533"},"md-trending_neutral":{"char":"󰔴","code":"f0534"},"md-trending_up":{"char":"󰔵","code":"f0535"},"md-triangle":{"char":"󰔶","code":"f0536"},"md-triangle_outline":{"char":"󰔷","code":"f0537"},"md-triangle_small_down":{"char":"󱨉","code":"f1a09"},"md-triangle_small_up":{"char":"󱨊","code":"f1a0a"},"md-triangle_wave":{"char":"󱑼","code":"f147c"},"md-triforce":{"char":"󰯙","code":"f0bd9"},"md-trophy":{"char":"󰔸","code":"f0538"},"md-trophy_award":{"char":"󰔹","code":"f0539"},"md-trophy_broken":{"char":"󰶤","code":"f0da4"},"md-trophy_outline":{"char":"󰔺","code":"f053a"},"md-trophy_variant":{"char":"󰔻","code":"f053b"},"md-trophy_variant_outline":{"char":"󰔼","code":"f053c"},"md-truck":{"char":"󰔽","code":"f053d"},"md-truck_alert":{"char":"󱧞","code":"f19de"},"md-truck_alert_outline":{"char":"󱧟","code":"f19df"},"md-truck_cargo_container":{"char":"󱣘","code":"f18d8"},"md-truck_check":{"char":"󰳔","code":"f0cd4"},"md-truck_check_outline":{"char":"󱊚","code":"f129a"},"md-truck_delivery":{"char":"󰔾","code":"f053e"},"md-truck_delivery_outline":{"char":"󱊛","code":"f129b"},"md-truck_fast":{"char":"󰞈","code":"f0788"},"md-truck_fast_outline":{"char":"󱊜","code":"f129c"},"md-truck_flatbed":{"char":"󱢑","code":"f1891"},"md-truck_minus":{"char":"󱦮","code":"f19ae"},"md-truck_minus_outline":{"char":"󱦽","code":"f19bd"},"md-truck_outline":{"char":"󱊝","code":"f129d"},"md-truck_plus":{"char":"󱦭","code":"f19ad"},"md-truck_plus_outline":{"char":"󱦼","code":"f19bc"},"md-truck_remove":{"char":"󱦯","code":"f19af"},"md-truck_remove_outline":{"char":"󱦾","code":"f19be"},"md-truck_snowflake":{"char":"󱦦","code":"f19a6"},"md-truck_trailer":{"char":"󰜧","code":"f0727"},"md-trumpet":{"char":"󱂖","code":"f1096"},"md-tshirt_crew":{"char":"󰩻","code":"f0a7b"},"md-tshirt_crew_outline":{"char":"󰔿","code":"f053f"},"md-tshirt_v":{"char":"󰩼","code":"f0a7c"},"md-tshirt_v_outline":{"char":"󰕀","code":"f0540"},"md-tsunami":{"char":"󱪁","code":"f1a81"},"md-tumble_dryer":{"char":"󰤗","code":"f0917"},"md-tumble_dryer_alert":{"char":"󱆺","code":"f11ba"},"md-tumble_dryer_off":{"char":"󱆻","code":"f11bb"},"md-tune":{"char":"󰘮","code":"f062e"},"md-tune_variant":{"char":"󱕂","code":"f1542"},"md-tune_vertical":{"char":"󰙪","code":"f066a"},"md-tune_vertical_variant":{"char":"󱕃","code":"f1543"},"md-tunnel":{"char":"󱠽","code":"f183d"},"md-tunnel_outline":{"char":"󱠾","code":"f183e"},"md-turbine":{"char":"󱪂","code":"f1a82"},"md-turkey":{"char":"󱜛","code":"f171b"},"md-turnstile":{"char":"󰳕","code":"f0cd5"},"md-turnstile_outline":{"char":"󰳖","code":"f0cd6"},"md-turtle":{"char":"󰳗","code":"f0cd7"},"md-twitch":{"char":"󰕃","code":"f0543"},"md-twitter":{"char":"󰕄","code":"f0544"},"md-two_factor_authentication":{"char":"󰦯","code":"f09af"},"md-typewriter":{"char":"󰼭","code":"f0f2d"},"md-ubisoft":{"char":"󰯚","code":"f0bda"},"md-ubuntu":{"char":"󰕈","code":"f0548"},"md-ufo":{"char":"󱃄","code":"f10c4"},"md-ufo_outline":{"char":"󱃅","code":"f10c5"},"md-ultra_high_definition":{"char":"󰟹","code":"f07f9"},"md-umbraco":{"char":"󰕉","code":"f0549"},"md-umbrella":{"char":"󰕊","code":"f054a"},"md-umbrella_beach":{"char":"󱢊","code":"f188a"},"md-umbrella_beach_outline":{"char":"󱢋","code":"f188b"},"md-umbrella_closed":{"char":"󰦰","code":"f09b0"},"md-umbrella_closed_outline":{"char":"󱏢","code":"f13e2"},"md-umbrella_closed_variant":{"char":"󱏡","code":"f13e1"},"md-umbrella_outline":{"char":"󰕋","code":"f054b"},"md-undo":{"char":"󰕌","code":"f054c"},"md-undo_variant":{"char":"󰕍","code":"f054d"},"md-unfold_less_horizontal":{"char":"󰕎","code":"f054e"},"md-unfold_less_vertical":{"char":"󰝠","code":"f0760"},"md-unfold_more_horizontal":{"char":"󰕏","code":"f054f"},"md-unfold_more_vertical":{"char":"󰝡","code":"f0761"},"md-ungroup":{"char":"󰕐","code":"f0550"},"md-unicode":{"char":"󰻐","code":"f0ed0"},"md-unicorn":{"char":"󱗂","code":"f15c2"},"md-unicorn_variant":{"char":"󱗃","code":"f15c3"},"md-unicycle":{"char":"󱗥","code":"f15e5"},"md-unity":{"char":"󰚯","code":"f06af"},"md-unreal":{"char":"󰦱","code":"f09b1"},"md-update":{"char":"󰚰","code":"f06b0"},"md-upload":{"char":"󰕒","code":"f0552"},"md-upload_lock":{"char":"󱍳","code":"f1373"},"md-upload_lock_outline":{"char":"󱍴","code":"f1374"},"md-upload_multiple":{"char":"󰠽","code":"f083d"},"md-upload_network":{"char":"󰛶","code":"f06f6"},"md-upload_network_outline":{"char":"󰳘","code":"f0cd8"},"md-upload_off":{"char":"󱃆","code":"f10c6"},"md-upload_off_outline":{"char":"󱃇","code":"f10c7"},"md-upload_outline":{"char":"󰸇","code":"f0e07"},"md-usb":{"char":"󰕓","code":"f0553"},"md-usb_flash_drive":{"char":"󱊞","code":"f129e"},"md-usb_flash_drive_outline":{"char":"󱊟","code":"f129f"},"md-usb_port":{"char":"󱇰","code":"f11f0"},"md-vacuum":{"char":"󱦡","code":"f19a1"},"md-vacuum_outline":{"char":"󱦢","code":"f19a2"},"md-valve":{"char":"󱁦","code":"f1066"},"md-valve_closed":{"char":"󱁧","code":"f1067"},"md-valve_open":{"char":"󱁨","code":"f1068"},"md-van_passenger":{"char":"󰟺","code":"f07fa"},"md-van_utility":{"char":"󰟻","code":"f07fb"},"md-vanish":{"char":"󰟼","code":"f07fc"},"md-vanish_quarter":{"char":"󱕔","code":"f1554"},"md-vanity_light":{"char":"󱇡","code":"f11e1"},"md-variable":{"char":"󰫧","code":"f0ae7"},"md-variable_box":{"char":"󱄑","code":"f1111"},"md-vector_arrange_above":{"char":"󰕔","code":"f0554"},"md-vector_arrange_below":{"char":"󰕕","code":"f0555"},"md-vector_bezier":{"char":"󰫨","code":"f0ae8"},"md-vector_circle":{"char":"󰕖","code":"f0556"},"md-vector_circle_variant":{"char":"󰕗","code":"f0557"},"md-vector_combine":{"char":"󰕘","code":"f0558"},"md-vector_curve":{"char":"󰕙","code":"f0559"},"md-vector_difference":{"char":"󰕚","code":"f055a"},"md-vector_difference_ab":{"char":"󰕛","code":"f055b"},"md-vector_difference_ba":{"char":"󰕜","code":"f055c"},"md-vector_ellipse":{"char":"󰢓","code":"f0893"},"md-vector_intersection":{"char":"󰕝","code":"f055d"},"md-vector_line":{"char":"󰕞","code":"f055e"},"md-vector_link":{"char":"󰿨","code":"f0fe8"},"md-vector_point":{"char":"󰕟","code":"f055f"},"md-vector_polygon":{"char":"󰕠","code":"f0560"},"md-vector_polygon_variant":{"char":"󱡖","code":"f1856"},"md-vector_polyline":{"char":"󰕡","code":"f0561"},"md-vector_polyline_edit":{"char":"󱈥","code":"f1225"},"md-vector_polyline_minus":{"char":"󱈦","code":"f1226"},"md-vector_polyline_plus":{"char":"󱈧","code":"f1227"},"md-vector_polyline_remove":{"char":"󱈨","code":"f1228"},"md-vector_radius":{"char":"󰝊","code":"f074a"},"md-vector_rectangle":{"char":"󰗆","code":"f05c6"},"md-vector_selection":{"char":"󰕢","code":"f0562"},"md-vector_square":{"char":"󰀁","code":"f0001"},"md-vector_square_close":{"char":"󱡗","code":"f1857"},"md-vector_square_edit":{"char":"󱣙","code":"f18d9"},"md-vector_square_minus":{"char":"󱣚","code":"f18da"},"md-vector_square_open":{"char":"󱡘","code":"f1858"},"md-vector_square_plus":{"char":"󱣛","code":"f18db"},"md-vector_square_remove":{"char":"󱣜","code":"f18dc"},"md-vector_triangle":{"char":"󰕣","code":"f0563"},"md-vector_union":{"char":"󰕤","code":"f0564"},"md-vhs":{"char":"󰨛","code":"f0a1b"},"md-vibrate":{"char":"󰕦","code":"f0566"},"md-vibrate_off":{"char":"󰳙","code":"f0cd9"},"md-video":{"char":"󰕧","code":"f0567"},"md-video_2d":{"char":"󱨜","code":"f1a1c"},"md-video_3d":{"char":"󰟽","code":"f07fd"},"md-video_3d_off":{"char":"󱏙","code":"f13d9"},"md-video_3d_variant":{"char":"󰻑","code":"f0ed1"},"md-video_4k_box":{"char":"󰠾","code":"f083e"},"md-video_account":{"char":"󰤙","code":"f0919"},"md-video_box":{"char":"󰃽","code":"f00fd"},"md-video_box_off":{"char":"󰃾","code":"f00fe"},"md-video_check":{"char":"󱁩","code":"f1069"},"md-video_check_outline":{"char":"󱁪","code":"f106a"},"md-video_high_definition":{"char":"󱔮","code":"f152e"},"md-video_image":{"char":"󰤚","code":"f091a"},"md-video_input_antenna":{"char":"󰠿","code":"f083f"},"md-video_input_component":{"char":"󰡀","code":"f0840"},"md-video_input_hdmi":{"char":"󰡁","code":"f0841"},"md-video_input_scart":{"char":"󰾌","code":"f0f8c"},"md-video_input_svideo":{"char":"󰡂","code":"f0842"},"md-video_marker":{"char":"󱦩","code":"f19a9"},"md-video_marker_outline":{"char":"󱦪","code":"f19aa"},"md-video_minus":{"char":"󰦲","code":"f09b2"},"md-video_minus_outline":{"char":"󰊺","code":"f02ba"},"md-video_off":{"char":"󰕨","code":"f0568"},"md-video_off_outline":{"char":"󰯛","code":"f0bdb"},"md-video_outline":{"char":"󰯜","code":"f0bdc"},"md-video_plus":{"char":"󰦳","code":"f09b3"},"md-video_plus_outline":{"char":"󰇓","code":"f01d3"},"md-video_stabilization":{"char":"󰤛","code":"f091b"},"md-video_switch":{"char":"󰕩","code":"f0569"},"md-video_switch_outline":{"char":"󰞐","code":"f0790"},"md-video_vintage":{"char":"󰨜","code":"f0a1c"},"md-video_wireless":{"char":"󰻒","code":"f0ed2"},"md-video_wireless_outline":{"char":"󰻓","code":"f0ed3"},"md-view_agenda":{"char":"󰕪","code":"f056a"},"md-view_agenda_outline":{"char":"󱇘","code":"f11d8"},"md-view_array":{"char":"󰕫","code":"f056b"},"md-view_array_outline":{"char":"󱒅","code":"f1485"},"md-view_carousel":{"char":"󰕬","code":"f056c"},"md-view_carousel_outline":{"char":"󱒆","code":"f1486"},"md-view_column":{"char":"󰕭","code":"f056d"},"md-view_column_outline":{"char":"󱒇","code":"f1487"},"md-view_comfy":{"char":"󰹪","code":"f0e6a"},"md-view_comfy_outline":{"char":"󱒈","code":"f1488"},"md-view_compact":{"char":"󰹫","code":"f0e6b"},"md-view_compact_outline":{"char":"󰹬","code":"f0e6c"},"md-view_dashboard":{"char":"󰕮","code":"f056e"},"md-view_dashboard_edit":{"char":"󱥇","code":"f1947"},"md-view_dashboard_edit_outline":{"char":"󱥈","code":"f1948"},"md-view_dashboard_outline":{"char":"󰨝","code":"f0a1d"},"md-view_dashboard_variant":{"char":"󰡃","code":"f0843"},"md-view_dashboard_variant_outline":{"char":"󱒉","code":"f1489"},"md-view_day":{"char":"󰕯","code":"f056f"},"md-view_day_outline":{"char":"󱒊","code":"f148a"},"md-view_gallery":{"char":"󱢈","code":"f1888"},"md-view_gallery_outline":{"char":"󱢉","code":"f1889"},"md-view_grid":{"char":"󰕰","code":"f0570"},"md-view_grid_outline":{"char":"󱇙","code":"f11d9"},"md-view_grid_plus":{"char":"󰾍","code":"f0f8d"},"md-view_grid_plus_outline":{"char":"󱇚","code":"f11da"},"md-view_headline":{"char":"󰕱","code":"f0571"},"md-view_list":{"char":"󰕲","code":"f0572"},"md-view_list_outline":{"char":"󱒋","code":"f148b"},"md-view_module":{"char":"󰕳","code":"f0573"},"md-view_module_outline":{"char":"󱒌","code":"f148c"},"md-view_parallel":{"char":"󰜨","code":"f0728"},"md-view_parallel_outline":{"char":"󱒍","code":"f148d"},"md-view_quilt":{"char":"󰕴","code":"f0574"},"md-view_quilt_outline":{"char":"󱒎","code":"f148e"},"md-view_sequential":{"char":"󰜩","code":"f0729"},"md-view_sequential_outline":{"char":"󱒏","code":"f148f"},"md-view_split_horizontal":{"char":"󰯋","code":"f0bcb"},"md-view_split_vertical":{"char":"󰯌","code":"f0bcc"},"md-view_stream":{"char":"󰕵","code":"f0575"},"md-view_stream_outline":{"char":"󱒐","code":"f1490"},"md-view_week":{"char":"󰕶","code":"f0576"},"md-view_week_outline":{"char":"󱒑","code":"f1491"},"md-vimeo":{"char":"󰕷","code":"f0577"},"md-violin":{"char":"󰘏","code":"f060f"},"md-virtual_reality":{"char":"󰢔","code":"f0894"},"md-virus":{"char":"󱎶","code":"f13b6"},"md-virus_off":{"char":"󱣡","code":"f18e1"},"md-virus_off_outline":{"char":"󱣢","code":"f18e2"},"md-virus_outline":{"char":"󱎷","code":"f13b7"},"md-vlc":{"char":"󰕼","code":"f057c"},"md-voicemail":{"char":"󰕽","code":"f057d"},"md-volcano":{"char":"󱪃","code":"f1a83"},"md-volcano_outline":{"char":"󱪄","code":"f1a84"},"md-volleyball":{"char":"󰦴","code":"f09b4"},"md-volume_high":{"char":"󰕾","code":"f057e"},"md-volume_low":{"char":"󰕿","code":"f057f"},"md-volume_medium":{"char":"󰖀","code":"f0580"},"md-volume_minus":{"char":"󰝞","code":"f075e"},"md-volume_mute":{"char":"󰝟","code":"f075f"},"md-volume_off":{"char":"󰖁","code":"f0581"},"md-volume_plus":{"char":"󰝝","code":"f075d"},"md-volume_source":{"char":"󱄠","code":"f1120"},"md-volume_variant_off":{"char":"󰸈","code":"f0e08"},"md-volume_vibrate":{"char":"󱄡","code":"f1121"},"md-vote":{"char":"󰨟","code":"f0a1f"},"md-vote_outline":{"char":"󰨠","code":"f0a20"},"md-vpn":{"char":"󰖂","code":"f0582"},"md-vuejs":{"char":"󰡄","code":"f0844"},"md-vuetify":{"char":"󰹭","code":"f0e6d"},"md-walk":{"char":"󰖃","code":"f0583"},"md-wall":{"char":"󰟾","code":"f07fe"},"md-wall_fire":{"char":"󱨑","code":"f1a11"},"md-wall_sconce":{"char":"󰤜","code":"f091c"},"md-wall_sconce_flat":{"char":"󰤝","code":"f091d"},"md-wall_sconce_flat_outline":{"char":"󱟉","code":"f17c9"},"md-wall_sconce_flat_variant":{"char":"󰐜","code":"f041c"},"md-wall_sconce_flat_variant_outline":{"char":"󱟊","code":"f17ca"},"md-wall_sconce_outline":{"char":"󱟋","code":"f17cb"},"md-wall_sconce_round":{"char":"󰝈","code":"f0748"},"md-wall_sconce_round_outline":{"char":"󱟌","code":"f17cc"},"md-wall_sconce_round_variant":{"char":"󰤞","code":"f091e"},"md-wall_sconce_round_variant_outline":{"char":"󱟍","code":"f17cd"},"md-wallet":{"char":"󰖄","code":"f0584"},"md-wallet_giftcard":{"char":"󰖅","code":"f0585"},"md-wallet_membership":{"char":"󰖆","code":"f0586"},"md-wallet_outline":{"char":"󰯝","code":"f0bdd"},"md-wallet_plus":{"char":"󰾎","code":"f0f8e"},"md-wallet_plus_outline":{"char":"󰾏","code":"f0f8f"},"md-wallet_travel":{"char":"󰖇","code":"f0587"},"md-wallpaper":{"char":"󰸉","code":"f0e09"},"md-wan":{"char":"󰖈","code":"f0588"},"md-wardrobe":{"char":"󰾐","code":"f0f90"},"md-wardrobe_outline":{"char":"󰾑","code":"f0f91"},"md-warehouse":{"char":"󰾁","code":"f0f81"},"md-washing_machine":{"char":"󰜪","code":"f072a"},"md-washing_machine_alert":{"char":"󱆼","code":"f11bc"},"md-washing_machine_off":{"char":"󱆽","code":"f11bd"},"md-watch":{"char":"󰖉","code":"f0589"},"md-watch_export":{"char":"󰖊","code":"f058a"},"md-watch_export_variant":{"char":"󰢕","code":"f0895"},"md-watch_import":{"char":"󰖋","code":"f058b"},"md-watch_import_variant":{"char":"󰢖","code":"f0896"},"md-watch_variant":{"char":"󰢗","code":"f0897"},"md-watch_vibrate":{"char":"󰚱","code":"f06b1"},"md-watch_vibrate_off":{"char":"󰳚","code":"f0cda"},"md-water":{"char":"󰖌","code":"f058c"},"md-water_alert":{"char":"󱔂","code":"f1502"},"md-water_alert_outline":{"char":"󱔃","code":"f1503"},"md-water_boiler":{"char":"󰾒","code":"f0f92"},"md-water_boiler_alert":{"char":"󱆳","code":"f11b3"},"md-water_boiler_off":{"char":"󱆴","code":"f11b4"},"md-water_check":{"char":"󱔄","code":"f1504"},"md-water_check_outline":{"char":"󱔅","code":"f1505"},"md-water_circle":{"char":"󱠆","code":"f1806"},"md-water_minus":{"char":"󱔆","code":"f1506"},"md-water_minus_outline":{"char":"󱔇","code":"f1507"},"md-water_off":{"char":"󰖍","code":"f058d"},"md-water_off_outline":{"char":"󱔈","code":"f1508"},"md-water_opacity":{"char":"󱡕","code":"f1855"},"md-water_outline":{"char":"󰸊","code":"f0e0a"},"md-water_percent":{"char":"󰖎","code":"f058e"},"md-water_percent_alert":{"char":"󱔉","code":"f1509"},"md-water_plus":{"char":"󱔊","code":"f150a"},"md-water_plus_outline":{"char":"󱔋","code":"f150b"},"md-water_polo":{"char":"󱊠","code":"f12a0"},"md-water_pump":{"char":"󰖏","code":"f058f"},"md-water_pump_off":{"char":"󰾓","code":"f0f93"},"md-water_remove":{"char":"󱔌","code":"f150c"},"md-water_remove_outline":{"char":"󱔍","code":"f150d"},"md-water_sync":{"char":"󱟆","code":"f17c6"},"md-water_thermometer":{"char":"󱪅","code":"f1a85"},"md-water_thermometer_outline":{"char":"󱪆","code":"f1a86"},"md-water_well":{"char":"󱁫","code":"f106b"},"md-water_well_outline":{"char":"󱁬","code":"f106c"},"md-waterfall":{"char":"󱡉","code":"f1849"},"md-watering_can":{"char":"󱒁","code":"f1481"},"md-watering_can_outline":{"char":"󱒂","code":"f1482"},"md-watermark":{"char":"󰘒","code":"f0612"},"md-wave":{"char":"󰼮","code":"f0f2e"},"md-waveform":{"char":"󱑽","code":"f147d"},"md-waves":{"char":"󰞍","code":"f078d"},"md-waves_arrow_left":{"char":"󱡙","code":"f1859"},"md-waves_arrow_right":{"char":"󱡚","code":"f185a"},"md-waves_arrow_up":{"char":"󱡛","code":"f185b"},"md-waze":{"char":"󰯞","code":"f0bde"},"md-weather_cloudy":{"char":"󰖐","code":"f0590"},"md-weather_cloudy_alert":{"char":"󰼯","code":"f0f2f"},"md-weather_cloudy_arrow_right":{"char":"󰹮","code":"f0e6e"},"md-weather_cloudy_clock":{"char":"󱣶","code":"f18f6"},"md-weather_fog":{"char":"󰖑","code":"f0591"},"md-weather_hail":{"char":"󰖒","code":"f0592"},"md-weather_hazy":{"char":"󰼰","code":"f0f30"},"md-weather_hurricane":{"char":"󰢘","code":"f0898"},"md-weather_lightning":{"char":"󰖓","code":"f0593"},"md-weather_lightning_rainy":{"char":"󰙾","code":"f067e"},"md-weather_night":{"char":"󰖔","code":"f0594"},"md-weather_night_partly_cloudy":{"char":"󰼱","code":"f0f31"},"md-weather_partly_cloudy":{"char":"󰖕","code":"f0595"},"md-weather_partly_lightning":{"char":"󰼲","code":"f0f32"},"md-weather_partly_rainy":{"char":"󰼳","code":"f0f33"},"md-weather_partly_snowy":{"char":"󰼴","code":"f0f34"},"md-weather_partly_snowy_rainy":{"char":"󰼵","code":"f0f35"},"md-weather_pouring":{"char":"󰖖","code":"f0596"},"md-weather_rainy":{"char":"󰖗","code":"f0597"},"md-weather_snowy":{"char":"󰖘","code":"f0598"},"md-weather_snowy_heavy":{"char":"󰼶","code":"f0f36"},"md-weather_snowy_rainy":{"char":"󰙿","code":"f067f"},"md-weather_sunny":{"char":"󰖙","code":"f0599"},"md-weather_sunny_alert":{"char":"󰼷","code":"f0f37"},"md-weather_sunny_off":{"char":"󱓤","code":"f14e4"},"md-weather_sunset":{"char":"󰖚","code":"f059a"},"md-weather_sunset_down":{"char":"󰖛","code":"f059b"},"md-weather_sunset_up":{"char":"󰖜","code":"f059c"},"md-weather_tornado":{"char":"󰼸","code":"f0f38"},"md-weather_windy":{"char":"󰖝","code":"f059d"},"md-weather_windy_variant":{"char":"󰖞","code":"f059e"},"md-web":{"char":"󰖟","code":"f059f"},"md-web_box":{"char":"󰾔","code":"f0f94"},"md-web_cancel":{"char":"󱞐","code":"f1790"},"md-web_check":{"char":"󰞉","code":"f0789"},"md-web_clock":{"char":"󱉊","code":"f124a"},"md-web_minus":{"char":"󱂠","code":"f10a0"},"md-web_off":{"char":"󰪎","code":"f0a8e"},"md-web_plus":{"char":"󰀳","code":"f0033"},"md-web_refresh":{"char":"󱞑","code":"f1791"},"md-web_remove":{"char":"󰕑","code":"f0551"},"md-web_sync":{"char":"󱞒","code":"f1792"},"md-webcam":{"char":"󰖠","code":"f05a0"},"md-webcam_off":{"char":"󱜷","code":"f1737"},"md-webhook":{"char":"󰘯","code":"f062f"},"md-webpack":{"char":"󰜫","code":"f072b"},"md-webrtc":{"char":"󱉈","code":"f1248"},"md-wechat":{"char":"󰘑","code":"f0611"},"md-weight":{"char":"󰖡","code":"f05a1"},"md-weight_gram":{"char":"󰴿","code":"f0d3f"},"md-weight_kilogram":{"char":"󰖢","code":"f05a2"},"md-weight_lifter":{"char":"󱅝","code":"f115d"},"md-weight_pound":{"char":"󰦵","code":"f09b5"},"md-whatsapp":{"char":"󰖣","code":"f05a3"},"md-wheel_barrow":{"char":"󱓲","code":"f14f2"},"md-wheelchair":{"char":"󱪇","code":"f1a87"},"md-wheelchair_accessibility":{"char":"󰖤","code":"f05a4"},"md-whistle":{"char":"󰦶","code":"f09b6"},"md-whistle_outline":{"char":"󱊼","code":"f12bc"},"md-white_balance_auto":{"char":"󰖥","code":"f05a5"},"md-white_balance_incandescent":{"char":"󰖦","code":"f05a6"},"md-white_balance_iridescent":{"char":"󰖧","code":"f05a7"},"md-white_balance_sunny":{"char":"󰖨","code":"f05a8"},"md-widgets":{"char":"󰜬","code":"f072c"},"md-widgets_outline":{"char":"󱍕","code":"f1355"},"md-wifi":{"char":"󰖩","code":"f05a9"},"md-wifi_alert":{"char":"󱚵","code":"f16b5"},"md-wifi_arrow_down":{"char":"󱚶","code":"f16b6"},"md-wifi_arrow_left":{"char":"󱚷","code":"f16b7"},"md-wifi_arrow_left_right":{"char":"󱚸","code":"f16b8"},"md-wifi_arrow_right":{"char":"󱚹","code":"f16b9"},"md-wifi_arrow_up":{"char":"󱚺","code":"f16ba"},"md-wifi_arrow_up_down":{"char":"󱚻","code":"f16bb"},"md-wifi_cancel":{"char":"󱚼","code":"f16bc"},"md-wifi_check":{"char":"󱚽","code":"f16bd"},"md-wifi_cog":{"char":"󱚾","code":"f16be"},"md-wifi_lock":{"char":"󱚿","code":"f16bf"},"md-wifi_lock_open":{"char":"󱛀","code":"f16c0"},"md-wifi_marker":{"char":"󱛁","code":"f16c1"},"md-wifi_minus":{"char":"󱛂","code":"f16c2"},"md-wifi_off":{"char":"󰖪","code":"f05aa"},"md-wifi_plus":{"char":"󱛃","code":"f16c3"},"md-wifi_refresh":{"char":"󱛄","code":"f16c4"},"md-wifi_remove":{"char":"󱛅","code":"f16c5"},"md-wifi_settings":{"char":"󱛆","code":"f16c6"},"md-wifi_star":{"char":"󰸋","code":"f0e0b"},"md-wifi_strength_1":{"char":"󰤟","code":"f091f"},"md-wifi_strength_1_alert":{"char":"󰤠","code":"f0920"},"md-wifi_strength_1_lock":{"char":"󰤡","code":"f0921"},"md-wifi_strength_1_lock_open":{"char":"󱛋","code":"f16cb"},"md-wifi_strength_2":{"char":"󰤢","code":"f0922"},"md-wifi_strength_2_alert":{"char":"󰤣","code":"f0923"},"md-wifi_strength_2_lock":{"char":"󰤤","code":"f0924"},"md-wifi_strength_2_lock_open":{"char":"󱛌","code":"f16cc"},"md-wifi_strength_3":{"char":"󰤥","code":"f0925"},"md-wifi_strength_3_alert":{"char":"󰤦","code":"f0926"},"md-wifi_strength_3_lock":{"char":"󰤧","code":"f0927"},"md-wifi_strength_3_lock_open":{"char":"󱛍","code":"f16cd"},"md-wifi_strength_4":{"char":"󰤨","code":"f0928"},"md-wifi_strength_4_alert":{"char":"󰤩","code":"f0929"},"md-wifi_strength_4_lock":{"char":"󰤪","code":"f092a"},"md-wifi_strength_4_lock_open":{"char":"󱛎","code":"f16ce"},"md-wifi_strength_alert_outline":{"char":"󰤫","code":"f092b"},"md-wifi_strength_lock_open_outline":{"char":"󱛏","code":"f16cf"},"md-wifi_strength_lock_outline":{"char":"󰤬","code":"f092c"},"md-wifi_strength_off":{"char":"󰤭","code":"f092d"},"md-wifi_strength_off_outline":{"char":"󰤮","code":"f092e"},"md-wifi_strength_outline":{"char":"󰤯","code":"f092f"},"md-wifi_sync":{"char":"󱛇","code":"f16c7"},"md-wikipedia":{"char":"󰖬","code":"f05ac"},"md-wind_power":{"char":"󱪈","code":"f1a88"},"md-wind_power_outline":{"char":"󱪉","code":"f1a89"},"md-wind_turbine":{"char":"󰶥","code":"f0da5"},"md-wind_turbine_alert":{"char":"󱦫","code":"f19ab"},"md-wind_turbine_check":{"char":"󱦬","code":"f19ac"},"md-window_close":{"char":"󰖭","code":"f05ad"},"md-window_closed":{"char":"󰖮","code":"f05ae"},"md-window_closed_variant":{"char":"󱇛","code":"f11db"},"md-window_maximize":{"char":"󰖯","code":"f05af"},"md-window_minimize":{"char":"󰖰","code":"f05b0"},"md-window_open":{"char":"󰖱","code":"f05b1"},"md-window_open_variant":{"char":"󱇜","code":"f11dc"},"md-window_restore":{"char":"󰖲","code":"f05b2"},"md-window_shutter":{"char":"󱄜","code":"f111c"},"md-window_shutter_alert":{"char":"󱄝","code":"f111d"},"md-window_shutter_cog":{"char":"󱪊","code":"f1a8a"},"md-window_shutter_open":{"char":"󱄞","code":"f111e"},"md-window_shutter_settings":{"char":"󱪋","code":"f1a8b"},"md-windsock":{"char":"󱗺","code":"f15fa"},"md-wiper":{"char":"󰫩","code":"f0ae9"},"md-wiper_wash":{"char":"󰶦","code":"f0da6"},"md-wiper_wash_alert":{"char":"󱣟","code":"f18df"},"md-wizard_hat":{"char":"󱑷","code":"f1477"},"md-wordpress":{"char":"󰖴","code":"f05b4"},"md-wrap":{"char":"󰖶","code":"f05b6"},"md-wrap_disabled":{"char":"󰯟","code":"f0bdf"},"md-wrench":{"char":"󰖷","code":"f05b7"},"md-wrench_clock":{"char":"󱦣","code":"f19a3"},"md-wrench_outline":{"char":"󰯠","code":"f0be0"},"md-xamarin":{"char":"󰡅","code":"f0845"},"md-xml":{"char":"󰗀","code":"f05c0"},"md-xmpp":{"char":"󰟿","code":"f07ff"},"md-yahoo":{"char":"󰭏","code":"f0b4f"},"md-yeast":{"char":"󰗁","code":"f05c1"},"md-yin_yang":{"char":"󰚀","code":"f0680"},"md-yoga":{"char":"󱅼","code":"f117c"},"md-youtube":{"char":"󰗃","code":"f05c3"},"md-youtube_gaming":{"char":"󰡈","code":"f0848"},"md-youtube_studio":{"char":"󰡇","code":"f0847"},"md-youtube_subscription":{"char":"󰵀","code":"f0d40"},"md-youtube_tv":{"char":"󰑈","code":"f0448"},"md-yurt":{"char":"󱔖","code":"f1516"},"md-z_wave":{"char":"󰫪","code":"f0aea"},"md-zend":{"char":"󰫫","code":"f0aeb"},"md-zigbee":{"char":"󰵁","code":"f0d41"},"md-zip_box":{"char":"󰗄","code":"f05c4"},"md-zip_box_outline":{"char":"󰿺","code":"f0ffa"},"md-zip_disk":{"char":"󰨣","code":"f0a23"},"md-zodiac_aquarius":{"char":"󰩽","code":"f0a7d"},"md-zodiac_aries":{"char":"󰩾","code":"f0a7e"},"md-zodiac_cancer":{"char":"󰩿","code":"f0a7f"},"md-zodiac_capricorn":{"char":"󰪀","code":"f0a80"},"md-zodiac_gemini":{"char":"󰪁","code":"f0a81"},"md-zodiac_leo":{"char":"󰪂","code":"f0a82"},"md-zodiac_libra":{"char":"󰪃","code":"f0a83"},"md-zodiac_pisces":{"char":"󰪄","code":"f0a84"},"md-zodiac_sagittarius":{"char":"󰪅","code":"f0a85"},"md-zodiac_scorpio":{"char":"󰪆","code":"f0a86"},"md-zodiac_taurus":{"char":"󰪇","code":"f0a87"},"md-zodiac_virgo":{"char":"󰪈","code":"f0a88"},"oct-accessibility":{"char":"","code":"f406"},"oct-accessibility_inset":{"char":"","code":"f40b"},"oct-alert":{"char":"","code":"f421"},"oct-alert_fill":{"char":"","code":"f40c"},"oct-apps":{"char":"","code":"f40e"},"oct-archive":{"char":"","code":"f411"},"oct-arrow_both":{"char":"","code":"f416"},"oct-arrow_down":{"char":"","code":"f433"},"oct-arrow_down_left":{"char":"","code":"f424"},"oct-arrow_down_right":{"char":"","code":"f43e"},"oct-arrow_left":{"char":"","code":"f434"},"oct-arrow_right":{"char":"","code":"f432"},"oct-arrow_switch":{"char":"","code":"f443"},"oct-arrow_up":{"char":"","code":"f431"},"oct-arrow_up_left":{"char":"","code":"f45c"},"oct-arrow_up_right":{"char":"","code":"f46c"},"oct-beaker":{"char":"","code":"f499"},"oct-bell":{"char":"","code":"f49a"},"oct-bell_fill":{"char":"","code":"f476"},"oct-bell_slash":{"char":"","code":"f478"},"oct-blocked":{"char":"","code":"f479"},"oct-bold":{"char":"","code":"f49d"},"oct-book":{"char":"","code":"f405"},"oct-bookmark":{"char":"","code":"f461"},"oct-bookmark_fill":{"char":"","code":"f47a"},"oct-bookmark_slash":{"char":"","code":"f533"},"oct-bookmark_slash_fill":{"char":"","code":"f493"},"oct-briefcase":{"char":"","code":"f491"},"oct-broadcast":{"char":"","code":"f43c"},"oct-browser":{"char":"","code":"f488"},"oct-bug":{"char":"","code":"f46f"},"oct-cache":{"char":"","code":"f49b"},"oct-calendar":{"char":"","code":"f455"},"oct-check":{"char":"","code":"f42e"},"oct-check_circle":{"char":"","code":"f49e"},"oct-check_circle_fill":{"char":"","code":"f4a4"},"oct-checkbox":{"char":"","code":"f4a7"},"oct-checklist":{"char":"","code":"f45e"},"oct-chevron_down":{"char":"","code":"f47c"},"oct-chevron_left":{"char":"","code":"f47d"},"oct-chevron_right":{"char":"","code":"f460"},"oct-chevron_up":{"char":"","code":"f47b"},"oct-circle":{"char":"","code":"f4aa"},"oct-circle_slash":{"char":"","code":"f468"},"oct-clock":{"char":"","code":"f43a"},"oct-clock_fill":{"char":"","code":"f4ab"},"oct-cloud":{"char":"","code":"f4ac"},"oct-cloud_offline":{"char":"","code":"f4ad"},"oct-code":{"char":"","code":"f44f"},"oct-code_of_conduct":{"char":"","code":"f4ae"},"oct-code_review":{"char":"","code":"f4af"},"oct-code_square":{"char":"","code":"f4b0"},"oct-codescan":{"char":"","code":"f4b1"},"oct-codescan_checkmark":{"char":"","code":"f4b2"},"oct-codespaces":{"char":"","code":"f4b3"},"oct-columns":{"char":"","code":"f4b4"},"oct-command_palette":{"char":"","code":"f4b5"},"oct-comment":{"char":"","code":"f41f"},"oct-comment_discussion":{"char":"","code":"f442"},"oct-commit":{"char":"","code":"f4b6"},"oct-container":{"char":"","code":"f4b7"},"oct-copilot":{"char":"","code":"f4b8"},"oct-copilot_error":{"char":"","code":"f4b9"},"oct-copilot_warning":{"char":"","code":"f4ba"},"oct-copy":{"char":"","code":"f4bb"},"oct-cpu":{"char":"","code":"f4bc"},"oct-credit_card":{"char":"","code":"f439"},"oct-cross_reference":{"char":"","code":"f4bd"},"oct-dash":{"char":"","code":"f48b"},"oct-database":{"char":"","code":"f472"},"oct-dependabot":{"char":"","code":"f4be"},"oct-desktop_download":{"char":"","code":"f498"},"oct-device_camera":{"char":"","code":"f446"},"oct-device_camera_video":{"char":"","code":"f447"},"oct-device_desktop":{"char":"","code":"f4a9"},"oct-device_mobile":{"char":"","code":"f42c"},"oct-diamond":{"char":"","code":"f4bf"},"oct-diff":{"char":"","code":"f440"},"oct-diff_added":{"char":"","code":"f457"},"oct-diff_ignored":{"char":"","code":"f474"},"oct-diff_modified":{"char":"","code":"f459"},"oct-diff_removed":{"char":"","code":"f458"},"oct-diff_renamed":{"char":"","code":"f45a"},"oct-discussion_closed":{"char":"","code":"f4c0"},"oct-discussion_duplicate":{"char":"","code":"f4c1"},"oct-discussion_outdated":{"char":"","code":"f4c2"},"oct-dot":{"char":"","code":"f4c3"},"oct-dot_fill":{"char":"","code":"f444"},"oct-download":{"char":"","code":"f409"},"oct-duplicate":{"char":"","code":"f4c4"},"oct-ellipsis":{"char":"","code":"f475"},"oct-eye":{"char":"","code":"f441"},"oct-eye_closed":{"char":"","code":"f4c5"},"oct-feed_discussion":{"char":"","code":"f4c6"},"oct-feed_forked":{"char":"","code":"f4c7"},"oct-feed_heart":{"char":"","code":"f4c8"},"oct-feed_merged":{"char":"","code":"f4c9"},"oct-feed_person":{"char":"","code":"f4ca"},"oct-feed_repo":{"char":"","code":"f4cb"},"oct-feed_rocket":{"char":"","code":"f4cc"},"oct-feed_star":{"char":"","code":"f4cd"},"oct-feed_tag":{"char":"","code":"f4ce"},"oct-feed_trophy":{"char":"","code":"f4cf"},"oct-file":{"char":"","code":"f4a5"},"oct-file_added":{"char":"","code":"f4d0"},"oct-file_badge":{"char":"","code":"f4d1"},"oct-file_binary":{"char":"","code":"f471"},"oct-file_code":{"char":"","code":"f40d"},"oct-file_diff":{"char":"","code":"f4d2"},"oct-file_directory":{"char":"","code":"f413"},"oct-file_directory_fill":{"char":"","code":"f4d3"},"oct-file_directory_open_fill":{"char":"","code":"f4d4"},"oct-file_media":{"char":"","code":"f40f"},"oct-file_moved":{"char":"","code":"f4d5"},"oct-file_removed":{"char":"","code":"f4d6"},"oct-file_submodule":{"char":"","code":"f414"},"oct-file_symlink_directory":{"char":"","code":"f482"},"oct-file_symlink_file":{"char":"","code":"f481"},"oct-file_zip":{"char":"","code":"f410"},"oct-filter":{"char":"","code":"f4d7"},"oct-fiscal_host":{"char":"","code":"f4d8"},"oct-flame":{"char":"","code":"f490"},"oct-fold":{"char":"","code":"f48c"},"oct-fold_down":{"char":"","code":"f4d9"},"oct-fold_up":{"char":"","code":"f4da"},"oct-gear":{"char":"","code":"f423"},"oct-gift":{"char":"","code":"f436"},"oct-git_branch":{"char":"","code":"f418"},"oct-git_commit":{"char":"","code":"f417"},"oct-git_compare":{"char":"","code":"f47f"},"oct-git_merge":{"char":"","code":"f419"},"oct-git_merge_queue":{"char":"","code":"f4db"},"oct-git_pull_request":{"char":"","code":"f407"},"oct-git_pull_request_closed":{"char":"","code":"f4dc"},"oct-git_pull_request_draft":{"char":"","code":"f4dd"},"oct-globe":{"char":"","code":"f484"},"oct-goal":{"char":"","code":"f4de"},"oct-grabber":{"char":"","code":"f4a6"},"oct-graph":{"char":"","code":"f437"},"oct-hash":{"char":"","code":"f4df"},"oct-heading":{"char":"","code":"f4e0"},"oct-heart":{"char":"♥","code":"2665"},"oct-heart_fill":{"char":"","code":"f4e1"},"oct-history":{"char":"","code":"f464"},"oct-home":{"char":"","code":"f46d"},"oct-home_fill":{"char":"","code":"f4e2"},"oct-horizontal_rule":{"char":"","code":"f45b"},"oct-hourglass":{"char":"","code":"f4e3"},"oct-hubot":{"char":"","code":"f477"},"oct-id_badge":{"char":"","code":"f4e4"},"oct-image":{"char":"","code":"f4e5"},"oct-inbox":{"char":"","code":"f48d"},"oct-infinity":{"char":"","code":"f4e6"},"oct-info":{"char":"","code":"f449"},"oct-issue_closed":{"char":"","code":"f41d"},"oct-issue_draft":{"char":"","code":"f4e7"},"oct-issue_opened":{"char":"","code":"f41b"},"oct-issue_reopened":{"char":"","code":"f41c"},"oct-issue_tracked_by":{"char":"","code":"f4e8"},"oct-issue_tracks":{"char":"","code":"f4e9"},"oct-italic":{"char":"","code":"f49f"},"oct-iterations":{"char":"","code":"f4ea"},"oct-kebab_horizontal":{"char":"","code":"f4eb"},"oct-key":{"char":"","code":"f43d"},"oct-key_asterisk":{"char":"","code":"f4ec"},"oct-law":{"char":"","code":"f495"},"oct-light_bulb":{"char":"","code":"f400"},"oct-link":{"char":"","code":"f44c"},"oct-link_external":{"char":"","code":"f465"},"oct-list_ordered":{"char":"","code":"f452"},"oct-list_unordered":{"char":"","code":"f451"},"oct-location":{"char":"","code":"f450"},"oct-lock":{"char":"","code":"f456"},"oct-log":{"char":"","code":"f4ed"},"oct-logo_gist":{"char":"","code":"f480"},"oct-logo_github":{"char":"","code":"f470"},"oct-mail":{"char":"","code":"f42f"},"oct-mark_github":{"char":"","code":"f408"},"oct-markdown":{"char":"","code":"f48a"},"oct-megaphone":{"char":"","code":"f45f"},"oct-mention":{"char":"","code":"f486"},"oct-meter":{"char":"","code":"f463"},"oct-milestone":{"char":"","code":"f45d"},"oct-mirror":{"char":"","code":"f41a"},"oct-moon":{"char":"","code":"f4ee"},"oct-mortar_board":{"char":"","code":"f494"},"oct-move_to_bottom":{"char":"","code":"f4ef"},"oct-move_to_end":{"char":"","code":"f4f0"},"oct-move_to_start":{"char":"","code":"f4f1"},"oct-move_to_top":{"char":"","code":"f4f2"},"oct-multi_select":{"char":"","code":"f4f3"},"oct-mute":{"char":"","code":"f466"},"oct-no_entry":{"char":"","code":"f4f4"},"oct-north_star":{"char":"","code":"f4f5"},"oct-note":{"char":"","code":"f4f6"},"oct-number":{"char":"","code":"f4f7"},"oct-organization":{"char":"","code":"f42b"},"oct-package":{"char":"","code":"f487"},"oct-package_dependencies":{"char":"","code":"f4f8"},"oct-package_dependents":{"char":"","code":"f4f9"},"oct-paintbrush":{"char":"","code":"f48f"},"oct-paper_airplane":{"char":"","code":"f4fa"},"oct-paperclip":{"char":"","code":"f4fb"},"oct-passkey_fill":{"char":"","code":"f4fc"},"oct-paste":{"char":"","code":"f429"},"oct-pencil":{"char":"","code":"f448"},"oct-people":{"char":"","code":"f4fd"},"oct-person":{"char":"","code":"f415"},"oct-person_add":{"char":"","code":"f4fe"},"oct-person_fill":{"char":"","code":"f4ff"},"oct-pin":{"char":"","code":"f435"},"oct-play":{"char":"","code":"f500"},"oct-plug":{"char":"","code":"f492"},"oct-plus":{"char":"","code":"f44d"},"oct-plus_circle":{"char":"","code":"f501"},"oct-project":{"char":"","code":"f502"},"oct-project_roadmap":{"char":"","code":"f503"},"oct-project_symlink":{"char":"","code":"f504"},"oct-project_template":{"char":"","code":"f505"},"oct-pulse":{"char":"","code":"f469"},"oct-question":{"char":"","code":"f420"},"oct-quote":{"char":"","code":"f453"},"oct-read":{"char":"","code":"f430"},"oct-rel_file_path":{"char":"","code":"f506"},"oct-reply":{"char":"","code":"f4a8"},"oct-repo":{"char":"","code":"f401"},"oct-repo_clone":{"char":"","code":"f43f"},"oct-repo_deleted":{"char":"","code":"f507"},"oct-repo_forked":{"char":"","code":"f402"},"oct-repo_locked":{"char":"","code":"f508"},"oct-repo_pull":{"char":"","code":"f404"},"oct-repo_push":{"char":"","code":"f403"},"oct-repo_template":{"char":"","code":"f509"},"oct-report":{"char":"","code":"f50a"},"oct-rocket":{"char":"","code":"f427"},"oct-rows":{"char":"","code":"f50b"},"oct-rss":{"char":"","code":"f428"},"oct-ruby":{"char":"","code":"f43b"},"oct-screen_full":{"char":"","code":"f50c"},"oct-screen_normal":{"char":"","code":"f50d"},"oct-search":{"char":"","code":"f422"},"oct-server":{"char":"","code":"f473"},"oct-share":{"char":"","code":"f50e"},"oct-share_android":{"char":"","code":"f50f"},"oct-shield":{"char":"","code":"f49c"},"oct-shield_check":{"char":"","code":"f510"},"oct-shield_lock":{"char":"","code":"f511"},"oct-shield_slash":{"char":"","code":"f512"},"oct-shield_x":{"char":"","code":"f513"},"oct-sidebar_collapse":{"char":"","code":"f514"},"oct-sidebar_expand":{"char":"","code":"f515"},"oct-sign_in":{"char":"","code":"f42a"},"oct-sign_out":{"char":"","code":"f426"},"oct-single_select":{"char":"","code":"f516"},"oct-skip":{"char":"","code":"f517"},"oct-skip_fill":{"char":"","code":"f518"},"oct-sliders":{"char":"","code":"f462"},"oct-smiley":{"char":"","code":"f4a2"},"oct-sort_asc":{"char":"","code":"f519"},"oct-sort_desc":{"char":"","code":"f51a"},"oct-sparkle_fill":{"char":"","code":"f51b"},"oct-sponsor_tiers":{"char":"","code":"f51c"},"oct-square":{"char":"","code":"f51d"},"oct-square_fill":{"char":"","code":"f445"},"oct-squirrel":{"char":"","code":"f483"},"oct-stack":{"char":"","code":"f51e"},"oct-star":{"char":"","code":"f41e"},"oct-star_fill":{"char":"","code":"f51f"},"oct-stop":{"char":"","code":"f46e"},"oct-stopwatch":{"char":"","code":"f520"},"oct-strikethrough":{"char":"","code":"f521"},"oct-sun":{"char":"","code":"f522"},"oct-sync":{"char":"","code":"f46a"},"oct-tab":{"char":"","code":"f523"},"oct-tab_external":{"char":"","code":"f524"},"oct-table":{"char":"","code":"f525"},"oct-tag":{"char":"","code":"f412"},"oct-tasklist":{"char":"","code":"f4a0"},"oct-telescope":{"char":"","code":"f46b"},"oct-telescope_fill":{"char":"","code":"f526"},"oct-terminal":{"char":"","code":"f489"},"oct-three_bars":{"char":"","code":"f44e"},"oct-thumbsdown":{"char":"","code":"f497"},"oct-thumbsup":{"char":"","code":"f496"},"oct-tools":{"char":"","code":"f425"},"oct-trash":{"char":"","code":"f48e"},"oct-triangle_down":{"char":"","code":"f44b"},"oct-triangle_left":{"char":"","code":"f438"},"oct-triangle_right":{"char":"","code":"f44a"},"oct-triangle_up":{"char":"","code":"f47e"},"oct-trophy":{"char":"","code":"f527"},"oct-typography":{"char":"","code":"f528"},"oct-unfold":{"char":"","code":"f42d"},"oct-unlink":{"char":"","code":"f529"},"oct-unlock":{"char":"","code":"f52a"},"oct-unmute":{"char":"","code":"f485"},"oct-unread":{"char":"","code":"f52b"},"oct-unverified":{"char":"","code":"f4a3"},"oct-upload":{"char":"","code":"f40a"},"oct-verified":{"char":"","code":"f4a1"},"oct-versions":{"char":"","code":"f454"},"oct-video":{"char":"","code":"f52c"},"oct-webhook":{"char":"","code":"f52d"},"oct-workflow":{"char":"","code":"f52e"},"oct-x":{"char":"","code":"f467"},"oct-x_circle":{"char":"","code":"f52f"},"oct-x_circle_fill":{"char":"","code":"f530"},"oct-zap":{"char":"⚡","code":"26a1"},"oct-zoom_in":{"char":"","code":"f531"},"oct-zoom_out":{"char":"","code":"f532"},"pl-branch":{"char":"","code":"e0a0"},"pl-current_line":{"char":"","code":"e0a1"},"pl-hostname":{"char":"","code":"e0a2"},"pl-left_hard_divider":{"char":"","code":"e0b0"},"pl-left_soft_divider":{"char":"","code":"e0b1"},"pl-line_number":{"char":"","code":"e0a1"},"pl-readonly":{"char":"","code":"e0a2"},"pl-right_hard_divider":{"char":"","code":"e0b2"},"pl-right_soft_divider":{"char":"","code":"e0b3"},"ple-backslash_separator":{"char":"","code":"e0b9"},"ple-backslash_separator_redundant":{"char":"","code":"e0bf"},"ple-column_number":{"char":"","code":"e0a3"},"ple-current_column":{"char":"","code":"e0a3"},"ple-flame_thick":{"char":"","code":"e0c0"},"ple-flame_thick_mirrored":{"char":"","code":"e0c2"},"ple-flame_thin":{"char":"","code":"e0c1"},"ple-flame_thin_mirrored":{"char":"","code":"e0c3"},"ple-forwardslash_separator":{"char":"","code":"e0bb"},"ple-forwardslash_separator_redundant":{"char":"","code":"e0bd"},"ple-honeycomb":{"char":"","code":"e0cc"},"ple-honeycomb_outline":{"char":"","code":"e0cd"},"ple-ice_waveform":{"char":"","code":"e0c8"},"ple-ice_waveform_mirrored":{"char":"","code":"e0ca"},"ple-left_half_circle_thick":{"char":"","code":"e0b6"},"ple-left_half_circle_thin":{"char":"","code":"e0b7"},"ple-left_hard_divider_inverse":{"char":"","code":"e0d7"},"ple-lego_block_facing":{"char":"","code":"e0d0"},"ple-lego_block_sideways":{"char":"","code":"e0d1"},"ple-lego_separator":{"char":"","code":"e0ce"},"ple-lego_separator_thin":{"char":"","code":"e0cf"},"ple-lower_left_triangle":{"char":"","code":"e0b8"},"ple-lower_right_triangle":{"char":"","code":"e0ba"},"ple-pixelated_squares_big":{"char":"","code":"e0c6"},"ple-pixelated_squares_big_mirrored":{"char":"","code":"e0c7"},"ple-pixelated_squares_small":{"char":"","code":"e0c4"},"ple-pixelated_squares_small_mirrored":{"char":"","code":"e0c5"},"ple-right_half_circle_thick":{"char":"","code":"e0b4"},"ple-right_half_circle_thin":{"char":"","code":"e0b5"},"ple-right_hard_divider_inverse":{"char":"","code":"e0d6"},"ple-trapezoid_top_bottom":{"char":"","code":"e0d2"},"ple-trapezoid_top_bottom_mirrored":{"char":"","code":"e0d4"},"ple-upper_left_triangle":{"char":"","code":"e0bc"},"ple-upper_right_triangle":{"char":"","code":"e0be"},"pom-away":{"char":"","code":"e007"},"pom-clean_code":{"char":"","code":"e000"},"pom-external_interruption":{"char":"","code":"e00a"},"pom-internal_interruption":{"char":"","code":"e009"},"pom-long_pause":{"char":"","code":"e006"},"pom-pair_programming":{"char":"","code":"e008"},"pom-pomodoro_done":{"char":"","code":"e001"},"pom-pomodoro_estimated":{"char":"","code":"e002"},"pom-pomodoro_squashed":{"char":"","code":"e004"},"pom-pomodoro_ticking":{"char":"","code":"e003"},"pom-short_pause":{"char":"","code":"e005"},"seti-apple":{"char":"","code":"e635"},"seti-argdown":{"char":"","code":"e636"},"seti-asm":{"char":"","code":"e637"},"seti-audio":{"char":"","code":"e638"},"seti-babel":{"char":"","code":"e639"},"seti-bazel":{"char":"","code":"e63a"},"seti-bicep":{"char":"","code":"e63b"},"seti-bower":{"char":"","code":"e61a"},"seti-bsl":{"char":"","code":"e63c"},"seti-c":{"char":"","code":"e649"},"seti-c_sharp":{"char":"","code":"e648"},"seti-cake":{"char":"","code":"e63e"},"seti-cake_php":{"char":"","code":"e63d"},"seti-checkbox":{"char":"","code":"e63f"},"seti-checkbox_unchecked":{"char":"","code":"e640"},"seti-cjsx":{"char":"","code":"e61b"},"seti-clock":{"char":"","code":"e641"},"seti-clojure":{"char":"","code":"e642"},"seti-code_climate":{"char":"","code":"e643"},"seti-code_search":{"char":"","code":"e644"},"seti-coffee":{"char":"","code":"e61b"},"seti-coldfusion":{"char":"","code":"e645"},"seti-config":{"char":"","code":"e615"},"seti-cpp":{"char":"","code":"e646"},"seti-crystal":{"char":"","code":"e62f"},"seti-crystal_embedded":{"char":"","code":"e647"},"seti-css":{"char":"","code":"e614"},"seti-csv":{"char":"","code":"e64a"},"seti-cu":{"char":"","code":"e64b"},"seti-d":{"char":"","code":"e651"},"seti-dart":{"char":"","code":"e64c"},"seti-db":{"char":"","code":"e64d"},"seti-default":{"char":"","code":"e64e"},"seti-deprecation_cop":{"char":"","code":"e64f"},"seti-docker":{"char":"","code":"e650"},"seti-editorconfig":{"char":"","code":"e652"},"seti-ejs":{"char":"","code":"e618"},"seti-elixir":{"char":"","code":"e62d"},"seti-elixir_script":{"char":"","code":"e653"},"seti-elm":{"char":"","code":"e62c"},"seti-error":{"char":"","code":"e654"},"seti-eslint":{"char":"","code":"e655"},"seti-ethereum":{"char":"","code":"e656"},"seti-f_sharp":{"char":"","code":"e65a"},"seti-favicon":{"char":"","code":"e623"},"seti-firebase":{"char":"","code":"e657"},"seti-firefox":{"char":"","code":"e658"},"seti-folder":{"char":"","code":"e613"},"seti-font":{"char":"","code":"e659"},"seti-git":{"char":"","code":"e65d"},"seti-git_folder":{"char":"","code":"e65d"},"seti-git_ignore":{"char":"","code":"e65d"},"seti-github":{"char":"","code":"e65b"},"seti-gitlab":{"char":"","code":"e65c"},"seti-go":{"char":"","code":"e627"},"seti-go2":{"char":"","code":"e65e"},"seti-godot":{"char":"","code":"e65f"},"seti-gradle":{"char":"","code":"e660"},"seti-grails":{"char":"","code":"e661"},"seti-graphql":{"char":"","code":"e662"},"seti-grunt":{"char":"","code":"e611"},"seti-gulp":{"char":"","code":"e610"},"seti-hacklang":{"char":"","code":"e663"},"seti-haml":{"char":"","code":"e664"},"seti-happenings":{"char":"","code":"e665"},"seti-haskell":{"char":"","code":"e61f"},"seti-haxe":{"char":"","code":"e666"},"seti-heroku":{"char":"","code":"e607"},"seti-hex":{"char":"","code":"e667"},"seti-home":{"char":"","code":"e617"},"seti-html":{"char":"","code":"e60e"},"seti-ignored":{"char":"","code":"e668"},"seti-illustrator":{"char":"","code":"e669"},"seti-image":{"char":"","code":"e60d"},"seti-info":{"char":"","code":"e66a"},"seti-ionic":{"char":"","code":"e66b"},"seti-jade":{"char":"","code":"e66c"},"seti-java":{"char":"","code":"e66d"},"seti-javascript":{"char":"","code":"e60c"},"seti-jenkins":{"char":"","code":"e66e"},"seti-jinja":{"char":"","code":"e66f"},"seti-json":{"char":"","code":"e60b"},"seti-julia":{"char":"","code":"e624"},"seti-karma":{"char":"","code":"e622"},"seti-kotlin":{"char":"","code":"e634"},"seti-less":{"char":"","code":"e60b"},"seti-license":{"char":"","code":"e60a"},"seti-liquid":{"char":"","code":"e670"},"seti-livescript":{"char":"","code":"e671"},"seti-lock":{"char":"","code":"e672"},"seti-lua":{"char":"","code":"e620"},"seti-makefile":{"char":"","code":"e673"},"seti-markdown":{"char":"","code":"e609"},"seti-maven":{"char":"","code":"e674"},"seti-mdo":{"char":"","code":"e675"},"seti-mustache":{"char":"","code":"e60f"},"seti-new_file":{"char":"","code":"e676"},"seti-nim":{"char":"","code":"e677"},"seti-notebook":{"char":"","code":"e678"},"seti-npm":{"char":"","code":"e616"},"seti-npm_ignored":{"char":"","code":"e616"},"seti-nunjucks":{"char":"","code":"e679"},"seti-ocaml":{"char":"","code":"e67a"},"seti-odata":{"char":"","code":"e67b"},"seti-pddl":{"char":"","code":"e67c"},"seti-pdf":{"char":"","code":"e67d"},"seti-perl":{"char":"","code":"e67e"},"seti-photoshop":{"char":"","code":"e67f"},"seti-php":{"char":"","code":"e608"},"seti-pipeline":{"char":"","code":"e680"},"seti-plan":{"char":"","code":"e681"},"seti-platformio":{"char":"","code":"e682"},"seti-play_arrow":{"char":"","code":"e602"},"seti-powershell":{"char":"","code":"e683"},"seti-prisma":{"char":"","code":"e684"},"seti-project":{"char":"","code":"e601"},"seti-prolog":{"char":"","code":"e685"},"seti-pug":{"char":"","code":"e686"},"seti-puppet":{"char":"","code":"e631"},"seti-purescript":{"char":"","code":"e630"},"seti-python":{"char":"","code":"e606"},"seti-r":{"char":"","code":"e68a"},"seti-rails":{"char":"","code":"e604"},"seti-react":{"char":"","code":"e625"},"seti-reasonml":{"char":"","code":"e687"},"seti-rescript":{"char":"","code":"e688"},"seti-rollup":{"char":"","code":"e689"},"seti-ruby":{"char":"","code":"e605"},"seti-rust":{"char":"","code":"e68b"},"seti-salesforce":{"char":"","code":"e68c"},"seti-sass":{"char":"","code":"e603"},"seti-sbt":{"char":"","code":"e68d"},"seti-scala":{"char":"","code":"e68e"},"seti-search":{"char":"","code":"e68f"},"seti-settings":{"char":"","code":"e690"},"seti-shell":{"char":"","code":"e691"},"seti-slim":{"char":"","code":"e692"},"seti-smarty":{"char":"","code":"e693"},"seti-spring":{"char":"","code":"e694"},"seti-stylelint":{"char":"","code":"e695"},"seti-stylus":{"char":"","code":"e600"},"seti-sublime":{"char":"","code":"e696"},"seti-svelte":{"char":"","code":"e697"},"seti-svg":{"char":"","code":"e698"},"seti-swift":{"char":"","code":"e699"},"seti-terraform":{"char":"","code":"e69a"},"seti-tex":{"char":"","code":"e69b"},"seti-text":{"char":"","code":"e64e"},"seti-time_cop":{"char":"","code":"e641"},"seti-todo":{"char":"","code":"e69c"},"seti-tsconfig":{"char":"","code":"e69d"},"seti-twig":{"char":"","code":"e61c"},"seti-typescript":{"char":"","code":"e628"},"seti-vala":{"char":"","code":"e69e"},"seti-video":{"char":"","code":"e69f"},"seti-vue":{"char":"","code":"e6a0"},"seti-wasm":{"char":"","code":"e6a1"},"seti-wat":{"char":"","code":"e6a2"},"seti-webpack":{"char":"","code":"e6a3"},"seti-wgt":{"char":"","code":"e6a4"},"seti-word":{"char":"","code":"e6a5"},"seti-xls":{"char":"","code":"e6a6"},"seti-xml":{"char":"","code":"e619"},"seti-yarn":{"char":"","code":"e6a7"},"seti-yml":{"char":"","code":"e6a8"},"seti-zig":{"char":"","code":"e6a9"},"seti-zip":{"char":"","code":"e6aa"},"weather-alien":{"char":"","code":"e36e"},"weather-aliens":{"char":"","code":"e345"},"weather-barometer":{"char":"","code":"e372"},"weather-celsius":{"char":"","code":"e339"},"weather-cloud":{"char":"","code":"e33d"},"weather-cloud_down":{"char":"","code":"e33a"},"weather-cloud_refresh":{"char":"","code":"e33b"},"weather-cloud_up":{"char":"","code":"e33c"},"weather-cloudy":{"char":"","code":"e312"},"weather-cloudy_gusts":{"char":"","code":"e310"},"weather-cloudy_windy":{"char":"","code":"e311"},"weather-day_cloudy":{"char":"","code":"e302"},"weather-day_cloudy_gusts":{"char":"","code":"e300"},"weather-day_cloudy_high":{"char":"","code":"e376"},"weather-day_cloudy_windy":{"char":"","code":"e301"},"weather-day_fog":{"char":"","code":"e303"},"weather-day_hail":{"char":"","code":"e304"},"weather-day_haze":{"char":"","code":"e3ae"},"weather-day_light_wind":{"char":"","code":"e3bc"},"weather-day_lightning":{"char":"","code":"e305"},"weather-day_rain":{"char":"","code":"e308"},"weather-day_rain_mix":{"char":"","code":"e306"},"weather-day_rain_wind":{"char":"","code":"e307"},"weather-day_showers":{"char":"","code":"e309"},"weather-day_sleet":{"char":"","code":"e3aa"},"weather-day_sleet_storm":{"char":"","code":"e362"},"weather-day_snow":{"char":"","code":"e30a"},"weather-day_snow_thunderstorm":{"char":"","code":"e365"},"weather-day_snow_wind":{"char":"","code":"e35f"},"weather-day_sprinkle":{"char":"","code":"e30b"},"weather-day_storm_showers":{"char":"","code":"e30e"},"weather-day_sunny":{"char":"","code":"e30d"},"weather-day_sunny_overcast":{"char":"","code":"e30c"},"weather-day_thunderstorm":{"char":"","code":"e30f"},"weather-day_windy":{"char":"","code":"e37d"},"weather-degrees":{"char":"","code":"e33e"},"weather-direction_down":{"char":"","code":"e340"},"weather-direction_down_left":{"char":"","code":"e33f"},"weather-direction_down_right":{"char":"","code":"e380"},"weather-direction_left":{"char":"","code":"e344"},"weather-direction_right":{"char":"","code":"e349"},"weather-direction_up":{"char":"","code":"e353"},"weather-direction_up_left":{"char":"","code":"e37f"},"weather-direction_up_right":{"char":"","code":"e352"},"weather-dust":{"char":"","code":"e35d"},"weather-earthquake":{"char":"","code":"e3be"},"weather-fahrenheit":{"char":"","code":"e341"},"weather-fire":{"char":"","code":"e3bf"},"weather-flood":{"char":"","code":"e375"},"weather-fog":{"char":"","code":"e313"},"weather-gale_warning":{"char":"","code":"e3c5"},"weather-hail":{"char":"","code":"e314"},"weather-horizon":{"char":"","code":"e343"},"weather-horizon_alt":{"char":"","code":"e342"},"weather-hot":{"char":"","code":"e36b"},"weather-humidity":{"char":"","code":"e373"},"weather-hurricane":{"char":"","code":"e36c"},"weather-hurricane_warning":{"char":"","code":"e3c7"},"weather-lightning":{"char":"","code":"e315"},"weather-lunar_eclipse":{"char":"","code":"e369"},"weather-meteor":{"char":"","code":"e36a"},"weather-moon_alt_first_quarter":{"char":"","code":"e3ce"},"weather-moon_alt_full":{"char":"","code":"e3d5"},"weather-moon_alt_new":{"char":"","code":"e3e3"},"weather-moon_alt_third_quarter":{"char":"","code":"e3dc"},"weather-moon_alt_waning_crescent_1":{"char":"","code":"e3dd"},"weather-moon_alt_waning_crescent_2":{"char":"","code":"e3de"},"weather-moon_alt_waning_crescent_3":{"char":"","code":"e3df"},"weather-moon_alt_waning_crescent_4":{"char":"","code":"e3e0"},"weather-moon_alt_waning_crescent_5":{"char":"","code":"e3e1"},"weather-moon_alt_waning_crescent_6":{"char":"","code":"e3e2"},"weather-moon_alt_waning_gibbous_1":{"char":"","code":"e3d6"},"weather-moon_alt_waning_gibbous_2":{"char":"","code":"e3d7"},"weather-moon_alt_waning_gibbous_3":{"char":"","code":"e3d8"},"weather-moon_alt_waning_gibbous_4":{"char":"","code":"e3d9"},"weather-moon_alt_waning_gibbous_5":{"char":"","code":"e3da"},"weather-moon_alt_waning_gibbous_6":{"char":"","code":"e3db"},"weather-moon_alt_waxing_crescent_1":{"char":"","code":"e3c8"},"weather-moon_alt_waxing_crescent_2":{"char":"","code":"e3c9"},"weather-moon_alt_waxing_crescent_3":{"char":"","code":"e3ca"},"weather-moon_alt_waxing_crescent_4":{"char":"","code":"e3cb"},"weather-moon_alt_waxing_crescent_5":{"char":"","code":"e3cc"},"weather-moon_alt_waxing_crescent_6":{"char":"","code":"e3cd"},"weather-moon_alt_waxing_gibbous_1":{"char":"","code":"e3cf"},"weather-moon_alt_waxing_gibbous_2":{"char":"","code":"e3d0"},"weather-moon_alt_waxing_gibbous_3":{"char":"","code":"e3d1"},"weather-moon_alt_waxing_gibbous_4":{"char":"","code":"e3d2"},"weather-moon_alt_waxing_gibbous_5":{"char":"","code":"e3d3"},"weather-moon_alt_waxing_gibbous_6":{"char":"","code":"e3d4"},"weather-moon_first_quarter":{"char":"","code":"e394"},"weather-moon_full":{"char":"","code":"e39b"},"weather-moon_new":{"char":"","code":"e38d"},"weather-moon_third_quarter":{"char":"","code":"e3a2"},"weather-moon_waning_crescent_1":{"char":"","code":"e3a3"},"weather-moon_waning_crescent_2":{"char":"","code":"e3a4"},"weather-moon_waning_crescent_3":{"char":"","code":"e3a5"},"weather-moon_waning_crescent_4":{"char":"","code":"e3a6"},"weather-moon_waning_crescent_5":{"char":"","code":"e3a7"},"weather-moon_waning_crescent_6":{"char":"","code":"e3a8"},"weather-moon_waning_gibbous_1":{"char":"","code":"e39c"},"weather-moon_waning_gibbous_2":{"char":"","code":"e39d"},"weather-moon_waning_gibbous_3":{"char":"","code":"e39e"},"weather-moon_waning_gibbous_4":{"char":"","code":"e39f"},"weather-moon_waning_gibbous_5":{"char":"","code":"e3a0"},"weather-moon_waning_gibbous_6":{"char":"","code":"e3a1"},"weather-moon_waxing_crescent_1":{"char":"","code":"e38e"},"weather-moon_waxing_crescent_2":{"char":"","code":"e38f"},"weather-moon_waxing_crescent_3":{"char":"","code":"e390"},"weather-moon_waxing_crescent_4":{"char":"","code":"e391"},"weather-moon_waxing_crescent_5":{"char":"","code":"e392"},"weather-moon_waxing_crescent_6":{"char":"","code":"e393"},"weather-moon_waxing_gibbous_1":{"char":"","code":"e395"},"weather-moon_waxing_gibbous_2":{"char":"","code":"e396"},"weather-moon_waxing_gibbous_3":{"char":"","code":"e397"},"weather-moon_waxing_gibbous_4":{"char":"","code":"e398"},"weather-moon_waxing_gibbous_5":{"char":"","code":"e399"},"weather-moon_waxing_gibbous_6":{"char":"","code":"e39a"},"weather-moonrise":{"char":"","code":"e3c1"},"weather-moonset":{"char":"","code":"e3c2"},"weather-na":{"char":"","code":"e374"},"weather-night_alt_cloudy":{"char":"","code":"e37e"},"weather-night_alt_cloudy_gusts":{"char":"","code":"e31f"},"weather-night_alt_cloudy_high":{"char":"","code":"e377"},"weather-night_alt_cloudy_windy":{"char":"","code":"e320"},"weather-night_alt_hail":{"char":"","code":"e321"},"weather-night_alt_lightning":{"char":"","code":"e322"},"weather-night_alt_partly_cloudy":{"char":"","code":"e379"},"weather-night_alt_rain":{"char":"","code":"e325"},"weather-night_alt_rain_mix":{"char":"","code":"e323"},"weather-night_alt_rain_wind":{"char":"","code":"e324"},"weather-night_alt_showers":{"char":"","code":"e326"},"weather-night_alt_sleet":{"char":"","code":"e3ac"},"weather-night_alt_sleet_storm":{"char":"","code":"e364"},"weather-night_alt_snow":{"char":"","code":"e327"},"weather-night_alt_snow_thunderstorm":{"char":"","code":"e367"},"weather-night_alt_snow_wind":{"char":"","code":"e361"},"weather-night_alt_sprinkle":{"char":"","code":"e328"},"weather-night_alt_storm_showers":{"char":"","code":"e329"},"weather-night_alt_thunderstorm":{"char":"","code":"e32a"},"weather-night_clear":{"char":"","code":"e32b"},"weather-night_cloudy":{"char":"","code":"e32e"},"weather-night_cloudy_gusts":{"char":"","code":"e32c"},"weather-night_cloudy_high":{"char":"","code":"e378"},"weather-night_cloudy_windy":{"char":"","code":"e32d"},"weather-night_fog":{"char":"","code":"e346"},"weather-night_hail":{"char":"","code":"e32f"},"weather-night_lightning":{"char":"","code":"e330"},"weather-night_partly_cloudy":{"char":"","code":"e37b"},"weather-night_rain":{"char":"","code":"e333"},"weather-night_rain_mix":{"char":"","code":"e331"},"weather-night_rain_wind":{"char":"","code":"e332"},"weather-night_showers":{"char":"","code":"e334"},"weather-night_sleet":{"char":"","code":"e3ab"},"weather-night_sleet_storm":{"char":"","code":"e363"},"weather-night_snow":{"char":"","code":"e335"},"weather-night_snow_thunderstorm":{"char":"","code":"e366"},"weather-night_snow_wind":{"char":"","code":"e360"},"weather-night_sprinkle":{"char":"","code":"e336"},"weather-night_storm_showers":{"char":"","code":"e337"},"weather-night_thunderstorm":{"char":"","code":"e338"},"weather-rain":{"char":"","code":"e318"},"weather-rain_mix":{"char":"","code":"e316"},"weather-rain_wind":{"char":"","code":"e317"},"weather-raindrop":{"char":"","code":"e371"},"weather-raindrops":{"char":"","code":"e34a"},"weather-refresh":{"char":"","code":"e348"},"weather-refresh_alt":{"char":"","code":"e347"},"weather-sandstorm":{"char":"","code":"e37a"},"weather-showers":{"char":"","code":"e319"},"weather-sleet":{"char":"","code":"e3ad"},"weather-small_craft_advisory":{"char":"","code":"e3c4"},"weather-smog":{"char":"","code":"e36d"},"weather-smoke":{"char":"","code":"e35c"},"weather-snow":{"char":"","code":"e31a"},"weather-snow_wind":{"char":"","code":"e35e"},"weather-snowflake_cold":{"char":"","code":"e36f"},"weather-solar_eclipse":{"char":"","code":"e368"},"weather-sprinkle":{"char":"","code":"e31b"},"weather-stars":{"char":"","code":"e370"},"weather-storm_showers":{"char":"","code":"e31c"},"weather-storm_warning":{"char":"","code":"e3c6"},"weather-strong_wind":{"char":"","code":"e34b"},"weather-sunrise":{"char":"","code":"e34c"},"weather-sunset":{"char":"","code":"e34d"},"weather-thermometer":{"char":"","code":"e350"},"weather-thermometer_exterior":{"char":"","code":"e34e"},"weather-thermometer_internal":{"char":"","code":"e34f"},"weather-thunderstorm":{"char":"","code":"e31d"},"weather-time_1":{"char":"","code":"e382"},"weather-time_10":{"char":"","code":"e38b"},"weather-time_11":{"char":"","code":"e38c"},"weather-time_12":{"char":"","code":"e381"},"weather-time_2":{"char":"","code":"e383"},"weather-time_3":{"char":"","code":"e384"},"weather-time_4":{"char":"","code":"e385"},"weather-time_5":{"char":"","code":"e386"},"weather-time_6":{"char":"","code":"e387"},"weather-time_7":{"char":"","code":"e388"},"weather-time_8":{"char":"","code":"e389"},"weather-time_9":{"char":"","code":"e38a"},"weather-tornado":{"char":"","code":"e351"},"weather-train":{"char":"","code":"e3c3"},"weather-tsunami":{"char":"","code":"e3bd"},"weather-umbrella":{"char":"","code":"e37c"},"weather-volcano":{"char":"","code":"e3c0"},"weather-wind_beaufort_0":{"char":"","code":"e3af"},"weather-wind_beaufort_1":{"char":"","code":"e3b0"},"weather-wind_beaufort_10":{"char":"","code":"e3b9"},"weather-wind_beaufort_11":{"char":"","code":"e3ba"},"weather-wind_beaufort_12":{"char":"","code":"e3bb"},"weather-wind_beaufort_2":{"char":"","code":"e3b1"},"weather-wind_beaufort_3":{"char":"","code":"e3b2"},"weather-wind_beaufort_4":{"char":"","code":"e3b3"},"weather-wind_beaufort_5":{"char":"","code":"e3b4"},"weather-wind_beaufort_6":{"char":"","code":"e3b5"},"weather-wind_beaufort_7":{"char":"","code":"e3b6"},"weather-wind_beaufort_8":{"char":"","code":"e3b7"},"weather-wind_beaufort_9":{"char":"","code":"e3b8"},"weather-wind_direction":{"char":"","code":"e3a9"},"weather-wind_east":{"char":"","code":"e35b"},"weather-wind_north":{"char":"","code":"e35a"},"weather-wind_north_east":{"char":"","code":"e359"},"weather-wind_north_west":{"char":"","code":"e358"},"weather-wind_south":{"char":"","code":"e357"},"weather-wind_south_east":{"char":"","code":"e356"},"weather-wind_south_west":{"char":"","code":"e355"},"weather-wind_west":{"char":"","code":"e354"},"weather-windy":{"char":"","code":"e31e"}} diff --git a/.local/share/script-data/chars/nerdfont b/.local/share/script-data/chars/nerdfont new file mode 100644 index 0000000..e35609f --- /dev/null +++ b/.local/share/script-data/chars/nerdfont @@ -0,0 +1,9191 @@ + cod_add + cod_lightbulb + cod_repo + cod_repo_forked + cod_git_pull_request + cod_record_keys + cod_tag + cod_person + cod_source_control + cod_mirror + cod_star_empty + cod_comment + cod_warning + cod_search + cod_sign_out + cod_sign_in + cod_eye + cod_circle_filled + cod_primitive_square + cod_edit + cod_info + cod_lock + cod_close + cod_sync + cod_desktop_download + cod_beaker + cod_vm + cod_file + cod_ellipsis + cod_reply + cod_organization + cod_new_file + cod_new_folder + cod_trash + cod_history + cod_folder + cod_github + cod_terminal + cod_symbol_event + cod_error + cod_symbol_variable + cod_symbol_array + cod_symbol_namespace + cod_symbol_method + cod_symbol_boolean + cod_symbol_numeric + cod_symbol_structure + cod_symbol_parameter + cod_symbol_key + cod_go_to_file + cod_symbol_enum + cod_symbol_ruler + cod_activate_breakpoints + cod_archive + cod_arrow_both + cod_arrow_down + cod_arrow_left + cod_arrow_right + cod_arrow_small_down + cod_arrow_small_left + cod_arrow_small_right + cod_arrow_small_up + cod_arrow_up + cod_bell + cod_bold + cod_book + cod_bookmark + cod_debug_breakpoint_conditional_unverified + cod_debug_breakpoint_conditional + cod_debug_breakpoint_data_unverified + cod_debug_breakpoint_data + cod_debug_breakpoint_log_unverified + cod_debug_breakpoint_log + cod_briefcase + cod_broadcast + cod_browser + cod_bug + cod_calendar + cod_case_sensitive + cod_check + cod_checklist + cod_chevron_down + cod_chevron_left + cod_chevron_right + cod_chevron_up + cod_chrome_close + cod_chrome_maximize + cod_chrome_minimize + cod_chrome_restore + cod_circle + cod_circle_slash + cod_circuit_board + cod_clear_all + cod_clippy + cod_close_all + cod_cloud_download + cod_cloud_upload + cod_code + cod_collapse_all + cod_color_mode + cod_comment_discussion + cod_credit_card + cod_dash + cod_dashboard + cod_database + cod_debug_continue + cod_debug_disconnect + cod_debug_pause + cod_debug_restart + cod_debug_start + cod_debug_step_into + cod_debug_step_out + cod_debug_step_over + cod_debug_stop + cod_debug + cod_device_camera_video + cod_device_camera + cod_device_mobile + cod_diff_added + cod_diff_ignored + cod_diff_modified + cod_diff_removed + cod_diff_renamed + cod_diff + cod_discard + cod_editor_layout + cod_empty_window + cod_exclude + cod_extensions + cod_eye_closed + cod_file_binary + cod_file_code + cod_file_media + cod_file_pdf + cod_file_submodule + cod_file_symlink_directory + cod_file_symlink_file + cod_file_zip + cod_files + cod_filter + cod_flame + cod_fold_down + cod_fold_up + cod_fold + cod_folder_active + cod_folder_opened + cod_gear + cod_gift + cod_gist_secret + cod_git_commit + cod_git_compare + cod_git_merge + cod_github_action + cod_github_alt + cod_globe + cod_grabber + cod_graph + cod_gripper + cod_heart + cod_home + cod_horizontal_rule + cod_hubot + cod_inbox + cod_issue_reopened + cod_issues + cod_italic + cod_jersey + cod_json + cod_kebab_vertical + cod_key + cod_law + cod_lightbulb_autofix + cod_link_external + cod_link + cod_list_ordered + cod_list_unordered + cod_live_share + cod_loading + cod_location + cod_mail_read + cod_mail + cod_markdown + cod_megaphone + cod_mention + cod_milestone + cod_mortar_board + cod_move + cod_multiple_windows + cod_mute + cod_no_newline + cod_note + cod_octoface + cod_open_preview + cod_package + cod_paintcan + cod_pin + cod_play + cod_plug + cod_preserve_case + cod_preview + cod_project + cod_pulse + cod_question + cod_quote + cod_radio_tower + cod_reactions + cod_references + cod_refresh + cod_regex + cod_remote_explorer + cod_remote + cod_remove + cod_replace_all + cod_replace + cod_repo_clone + cod_repo_force_push + cod_repo_pull + cod_repo_push + cod_report + cod_request_changes + cod_rocket + cod_root_folder_opened + cod_root_folder + cod_rss + cod_ruby + cod_save_all + cod_save_as + cod_save + cod_screen_full + cod_screen_normal + cod_search_stop + cod_server + cod_settings_gear + cod_settings + cod_shield + cod_smiley + cod_sort_precedence + cod_split_horizontal + cod_split_vertical + cod_squirrel + cod_star_full + cod_star_half + cod_symbol_class + cod_symbol_color + cod_symbol_constant + cod_symbol_enum_member + cod_symbol_field + cod_symbol_file + cod_symbol_interface + cod_symbol_keyword + cod_symbol_misc + cod_symbol_operator + cod_symbol_property + cod_symbol_snippet + cod_tasklist + cod_telescope + cod_text_size + cod_three_bars + cod_thumbsdown + cod_thumbsup + cod_tools + cod_triangle_down + cod_triangle_left + cod_triangle_right + cod_triangle_up + cod_twitter + cod_unfold + cod_unlock + cod_unmute + cod_unverified + cod_verified + cod_versions + cod_vm_active + cod_vm_outline + cod_vm_running + cod_watch + cod_whitespace + cod_whole_word + cod_window + cod_word_wrap + cod_zoom_in + cod_zoom_out + cod_list_filter + cod_list_flat + cod_list_selection + cod_list_tree + cod_debug_breakpoint_function_unverified + cod_debug_breakpoint_function + cod_debug_stackframe_active + cod_circle_small_filled + cod_debug_stackframe + cod_debug_breakpoint_unsupported + cod_symbol_string + cod_debug_reverse_continue + cod_debug_step_back + cod_debug_restart_frame + cod_debug_alt + cod_call_incoming + cod_call_outgoing + cod_menu + cod_expand_all + cod_feedback + cod_group_by_ref_type + cod_ungroup_by_ref_type + cod_account + cod_bell_dot + cod_debug_console + cod_library + cod_output + cod_run_all + cod_sync_ignored + cod_pinned + cod_github_inverted + cod_server_process + cod_server_environment + cod_pass + cod_stop_circle + cod_play_circle + cod_record + cod_debug_alt_small + cod_vm_connect + cod_cloud + cod_merge + cod_export + cod_graph_left + cod_magnet + cod_notebook + cod_redo + cod_check_all + cod_pinned_dirty + cod_pass_filled + cod_circle_large_filled + cod_circle_large + cod_combine + cod_table + cod_variable_group + cod_type_hierarchy + cod_type_hierarchy_sub + cod_type_hierarchy_super + cod_git_pull_request_create + cod_run_above + cod_run_below + cod_notebook_template + cod_debug_rerun + cod_workspace_trusted + cod_workspace_untrusted + cod_workspace_unknown + cod_terminal_cmd + cod_terminal_debian + cod_terminal_linux + cod_terminal_powershell + cod_terminal_tmux + cod_terminal_ubuntu + cod_terminal_bash + cod_arrow_swap + cod_copy + cod_person_add + cod_filter_filled + cod_wand + cod_debug_line_by_line + cod_inspect + cod_layers + cod_layers_dot + cod_layers_active + cod_compass + cod_compass_dot + cod_compass_active + cod_azure + cod_issue_draft + cod_git_pull_request_closed + cod_git_pull_request_draft + cod_debug_all + cod_debug_coverage + cod_run_errors + cod_folder_library + cod_debug_continue_small + cod_beaker_stop + cod_graph_line + cod_graph_scatter + cod_pie_chart + cod_bracket_dot + cod_bracket_error + cod_lock_small + cod_azure_devops + cod_verified_filled + cod_newline + cod_layout + dev_bing_small + dev_css_tricks + dev_git + dev_bitbucket + dev_mysql + dev_streamline + dev_database + dev_dropbox + dev_github_alt + dev_github_badge + dev_github + dev_wordpress + dev_visualstudio + dev_jekyll_small + dev_android + dev_windows + dev_stackoverflow + dev_apple + dev_linux + dev_appstore + dev_ghost_small + dev_yahoo + dev_codepen + dev_github_full + dev_nodejs_small + dev_nodejs + dev_hackernews + dev_ember + dev_dojo + dev_django + dev_npm + dev_ghost + dev_modernizr + dev_unity_small + dev_rasberry_pi + dev_blackberry + dev_go + dev_git_branch + dev_git_pull_request + dev_git_merge + dev_git_compare + dev_git_commit + dev_cssdeck + dev_yahoo_small + dev_techcrunch + dev_smashing_magazine + dev_netmagazine + dev_codrops + dev_phonegap + dev_google_drive + dev_html5_multimedia + dev_html5_device_access + dev_html5_connectivity + dev_html5_3d_effects + dev_html5 + dev_scala + dev_java + dev_ruby + dev_ubuntu + dev_ruby_on_rails + dev_python + dev_php + dev_markdown + dev_laravel + dev_magento + dev_joomla + dev_drupal + dev_chrome + dev_ie + dev_firefox + dev_opera + dev_bootstrap + dev_safari + dev_css3 + dev_css3_full + dev_sass + dev_grunt + dev_bower + dev_javascript + dev_javascript_shield + dev_jquery + dev_coffeescript + dev_backbone + dev_angular + dev_jquery_ui + dev_swift + dev_symfony + dev_symfony_badge + dev_less + dev_stylus + dev_trello + dev_atlassian + dev_jira + dev_envato + dev_snap_svg + dev_raphael + dev_chart + dev_compass + dev_onedrive + dev_gulp + dev_atom + dev_cisco + dev_nancy + dev_jenkins + dev_clojure + dev_perl + dev_clojure_alt + dev_celluloid + dev_w3c + dev_redis + dev_postgresql + dev_webplatform + dev_requirejs + dev_opensource + dev_typo3 + dev_uikit + dev_doctrine + dev_groovy + dev_nginx + dev_haskell + dev_zend + dev_gnu + dev_yeoman + dev_heroku + dev_msql_server + dev_debian + dev_travis + dev_dotnet + dev_codeigniter + dev_javascript_badge + dev_yii + dev_composer + dev_krakenjs_badge + dev_krakenjs + dev_mozilla + dev_firebase + dev_sizzlejs + dev_creativecommons + dev_creativecommons_badge + dev_mitlicence + dev_senchatouch + dev_bugsense + dev_extjs + dev_mootools_badge + dev_mootools + dev_ruby_rough + dev_komodo + dev_coda + dev_bintray + dev_terminal + dev_code + dev_responsive + dev_dart + dev_aptana + dev_mailchimp + dev_netbeans + dev_dreamweaver + dev_brackets + dev_eclipse + dev_cloud9 + dev_scrum + dev_prolog + dev_terminal_badge + dev_code_badge + dev_mongodb + dev_meteor + dev_meteorfull + dev_fsharp + dev_rust + dev_ionic + dev_sublime + dev_appcelerator + dev_asterisk + dev_aws + dev_digital_ocean + dev_dlang + dev_docker + dev_erlang + dev_google_cloud_platform + dev_grails + dev_illustrator + dev_intellij + dev_materializecss + dev_openshift + dev_photoshop + dev_rackspace + dev_react + dev_redhat + dev_scriptcs +' +' +' +' +' +' +' + dev_sqllite + dev_vim + fa_glass + fa_music + fa_search + fa_envelope_o + fa_heart + fa_star + fa_star_o + fa_user + fa_film + fa_th_large + fa_th + fa_th_list + fa_check + fa_times_close_remove + fa_search_plus + fa_search_minus + fa_power_off + fa_signal + fa_cog_gear + fa_trash_o + fa_home + fa_file_o + fa_clock_o + fa_road + fa_download + fa_arrow_circle_o_down + fa_arrow_circle_o_up + fa_inbox + fa_play_circle_o + fa_repeat_rotate_right + fa_refresh + fa_list_alt + fa_lock + fa_flag + fa_headphones + fa_volume_off + fa_volume_down + fa_volume_up + fa_qrcode + fa_barcode + fa_tag + fa_tags + fa_book + fa_bookmark + fa_print + fa_camera + fa_font + fa_bold + fa_italic + fa_text_height + fa_text_width + fa_align_left + fa_align_center + fa_align_right + fa_align_justify + fa_list + fa_outdent_dedent + fa_indent + fa_video_camera + fa_picture_o_image_photo + fa_pencil + fa_map_marker + fa_adjust + fa_tint + fa_pencil_square_o_edit + fa_share_square_o + fa_check_square_o + fa_arrows + fa_step_backward + fa_fast_backward + fa_backward + fa_play + fa_pause + fa_stop + fa_forward + fa_fast_forward + fa_step_forward + fa_eject + fa_chevron_left + fa_chevron_right + fa_plus_circle + fa_minus_circle + fa_times_circle + fa_check_circle + fa_question_circle + fa_info_circle + fa_crosshairs + fa_times_circle_o + fa_check_circle_o + fa_ban + fa_arrow_left + fa_arrow_right + fa_arrow_up + fa_arrow_down + fa_share_mail_forward + fa_expand + fa_compress + fa_plus + fa_minus + fa_asterisk + fa_exclamation_circle + fa_gift + fa_leaf + fa_fire + fa_eye + fa_eye_slash + fa_exclamation_triangle_warning + fa_plane + fa_calendar + fa_random + fa_comment + fa_magnet + fa_chevron_up + fa_chevron_down + fa_retweet + fa_shopping_cart + fa_folder + fa_folder_open + fa_arrows_v + fa_arrows_h + fa_bar_chart_bar_chart_o + fa_twitter_square + fa_facebook_square + fa_camera_retro + fa_key + fa_cogs_gears + fa_comments + fa_thumbs_o_up + fa_thumbs_o_down + fa_star_half + fa_heart_o + fa_sign_out + fa_linkedin_square + fa_thumb_tack + fa_external_link + fa_sign_in + fa_trophy + fa_github_square + fa_upload + fa_lemon_o + fa_phone + fa_square_o + fa_bookmark_o + fa_phone_square + fa_twitter + fa_facebook_fa_facebook_f + fa_github + fa_unlock + fa_credit_card + fa_rss_feed + fa_hdd_o + fa_bullhorn + fa_bell_o + fa_certificate + fa_hand_o_right + fa_hand_o_left + fa_hand_o_up + fa_hand_o_down + fa_arrow_circle_left + fa_arrow_circle_right + fa_arrow_circle_up + fa_arrow_circle_down + fa_globe + fa_wrench + fa_tasks + fa_filter + fa_briefcase + fa_arrows_alt + fa_users_group + fa_link_fa_chain + fa_cloud + fa_flask + fa_scissors_cut + fa_files_o_copy + fa_paperclip + fa_floppy_o_save + fa_square + fa_bars_navicon_reorder + fa_list_ul + fa_list_ol + fa_strikethrough + fa_underline + fa_table + fa_magic + fa_truck + fa_pinterest + fa_pinterest_square + fa_google_plus_square + fa_google_plus + fa_money + fa_caret_down + fa_caret_up + fa_caret_left + fa_caret_right + fa_columns + fa_sort_unsorted + fa_sort_desc_sort_down + fa_sort_asc_sort_up + fa_envelope + fa_linkedin + fa_undo_rotate_left + fa_gavel_legal + fa_tachometer_dashboard + fa_comment_o + fa_comments_o + fa_bolt_flash + fa_sitemap + fa_umbrella + fa_clipboard_paste + fa_lightbulb_o + fa_exchange + fa_cloud_download + fa_cloud_upload + fa_user_md + fa_stethoscope + fa_suitcase + fa_bell + fa_coffee + fa_cutlery + fa_file_text_o + fa_building_o + fa_hospital_o + fa_ambulance + fa_medkit + fa_fighter_jet + fa_beer + fa_h_square + fa_plus_square + fa_angle_double_left + fa_angle_double_right + fa_angle_double_up + fa_angle_double_down + fa_angle_left + fa_angle_right + fa_angle_up + fa_angle_down + fa_desktop + fa_laptop + fa_tablet + fa_mobile_mobile_phone + fa_circle_o + fa_quote_left + fa_quote_right + fa_spinner + fa_circle + fa_reply_mail_reply + fa_github_alt + fa_folder_o + fa_folder_open_o + fa_smile_o + fa_frown_o + fa_meh_o + fa_gamepad + fa_keyboard_o + fa_flag_o + fa_flag_checkered + fa_terminal + fa_code + fa_reply_all_mail_reply_all + fa_star_half_o_star_half_empty_star_half_full + fa_location_arrow + fa_crop + fa_code_fork + fa_chain_broken_unlink + fa_question + fa_info + fa_exclamation + fa_superscript + fa_subscript + fa_eraser + fa_puzzle_piece + fa_microphone + fa_microphone_slash + fa_shield + fa_calendar_o + fa_fire_extinguisher + fa_rocket + fa_maxcdn + fa_chevron_circle_left + fa_chevron_circle_right + fa_chevron_circle_up + fa_chevron_circle_down + fa_html5 + fa_css3 + fa_anchor + fa_unlock_alt + fa_bullseye + fa_ellipsis_h + fa_ellipsis_v + fa_rss_square + fa_play_circle + fa_ticket + fa_minus_square + fa_minus_square_o + fa_level_up + fa_level_down + fa_check_square + fa_pencil_square + fa_external_link_square + fa_share_square + fa_compass + fa_caret_square_o_down_toggle_down + fa_caret_square_o_up_toggle_up + fa_caret_square_o_right_toggle_right + fa_eur_euro + fa_gbp + fa_usd_dollar + fa_inr_rupee + fa_jpy_cny_rmb_yen + fa_rub_rouble_ruble + fa_krw_won + fa_btc_bitcoin + fa_file + fa_file_text + fa_sort_alpha_asc + fa_sort_alpha_desc + fa_sort_amount_asc + fa_sort_amount_desc + fa_sort_numeric_asc + fa_sort_numeric_desc + fa_thumbs_up + fa_thumbs_down + fa_youtube_square + fa_youtube + fa_xing + fa_xing_square + fa_youtube_play + fa_dropbox + fa_stack_overflow + fa_instagram + fa_flickr + fa_adn + fa_bitbucket + fa_bitbucket_square + fa_tumblr + fa_tumblr_square + fa_long_arrow_down + fa_long_arrow_up + fa_long_arrow_left + fa_long_arrow_right + fa_apple + fa_windows + fa_android + fa_linux + fa_dribbble + fa_skype + fa_foursquare + fa_trello + fa_female + fa_male + fa_gratipay_gittip + fa_sun_o + fa_moon_o + fa_archive + fa_bug + fa_vk + fa_weibo + fa_renren + fa_pagelines + fa_stack_exchange + fa_arrow_circle_o_right + fa_arrow_circle_o_left + fa_caret_square_o_lef_toggle_left + fa_dot_circle_o + fa_wheelchair + fa_vimeo_square + fa_try_turkish_lira + fa_plus_square_o + fa_space_shuttle + fa_slack + fa_envelope_square + fa_wordpress + fa_openid + fa_university_bank_institution + fa_graduation_cap_mortar_board + fa_yahoo + fa_google + fa_reddit + fa_reddit_square + fa_stumbleupon_circle + fa_stumbleupon + fa_delicious + fa_digg + fa_pied_piper_pp + fa_pied_piper_alt + fa_drupal + fa_joomla + fa_language + fa_fax + fa_building + fa_child + fa_paw + fa_spoon + fa_cube + fa_cubes + fa_behance + fa_behance_square + fa_steam + fa_steam_square + fa_recycle + fa_car_automobile + fa_taxi_cab + fa_tree + fa_spotify + fa_deviantart + fa_soundcloud + fa_database + fa_file_pdf_o + fa_file_word_o + fa_file_excel_o + fa_file_powerpoint_o + fa_file_image_o_file_photo_file_picture_o + fa_file_archive__file_zip_o + fa_file_audio_o_file_sound_o + fa_file_video_o_file_movie_o + fa_file_code_o + fa_vine + fa_codepen + fa_jsfiddle + fa_life_ring_life_bouy_life_buoy_life_saver_support + fa_circle_o_notch + fa_rebel_ra_resistance + fa_empire_ge + fa_git_square + fa_git + fa_hacker_news_combinator_square_yc_square + fa_tencent_weibo + fa_qq + fa_weixin_fa_wechat + fa_paper_plane_send + fa_paper_plane_o_send_o + fa_history + fa_circle_thin + fa_header + fa_paragraph + fa_sliders + fa_share_alt + fa_share_alt_square + fa_bomb + fa_futbol_o_soccer_ball_o + fa_tty + fa_binoculars + fa_plug + fa_slideshare + fa_twitch + fa_yelp + fa_newspaper_o + fa_wifi + fa_calculator + fa_paypal + fa_google_wallet + fa_cc_visa + fa_cc_mastercard + fa_cc_discover + fa_cc_amex + fa_cc_paypal + fa_cc_stripe + fa_bell_slash + fa_bell_slash_o + fa_trash + fa_copyright + fa_at + fa_eyedropper + fa_paint_brush + fa_birthday_cake + fa_area_chart + fa_pie_chart + fa_line_chart + fa_lastfm + fa_lastfm_square + fa_toggle_off + fa_toggle_on + fa_bicycle + fa_bus + fa_ioxhost + fa_angellist + fa_cc + fa_ils_shekel_sheqel + fa_meanpath + fa_buysellads + fa_connectdevelop + fa_dashcube + fa_forumbee + fa_leanpub + fa_sellsy + fa_shirtsinbulk + fa_simplybuilt + fa_skyatlas + fa_cart_plus + fa_cart_arrow_down + fa_diamond + fa_ship + fa_user_secret + fa_motorcycle + fa_street_view + fa_heartbeat + fa_venus + fa_mars + fa_mercury + fa_transgender_intersex + fa_transgender_alt + fa_venus_double + fa_mars_double + fa_venus_mars + fa_mars_stroke + fa_mars_stroke_v + fa_mars_stroke_h + fa_neuter + fa_genderless + fa_facebook_official + fa_pinterest_p + fa_whatsapp + fa_server + fa_user_plus + fa_user_times + fa_bed_hotel + fa_viacoin + fa_train + fa_subway + fa_medium + fa_y_combinator_yc + fa_optin_monster + fa_opencart + fa_expeditedssl + fa_battery_full_battery_battery_4 + fa_battery_three_quarter_battery_3 + fa_battery_half_battery_2 + fa_battery_quarter_battery_1 + fa_battery_empty_battery_0 + fa_mouse_pointer + fa_i_cursor + fa_object_group + fa_object_ungroup + fa_sticky_note + fa_sticky_note_o + fa_cc_jcb + fa_cc_diners_club + fa_clone + fa_balance_scale + fa_hourglass_o + fa_hourglass_start_hourglass_1 + fa_hourglass_half_hourglass_2 + fa_hourglass_end_hourglass_3 + fa_hourglass + fa_hand_rock_o_hand_grab_o + fa_hand_paper_o_hand_stop_o + fa_hand_scissors_o + fa_hand_lizard_o + fa_hand_spock_o + fa_hand_pointer_o + fa_hand_peace_o + fa_trademark + fa_registered + fa_creative_commons + fa_gg + fa_gg_circle + fa_tripadvisor + fa_odnoklassniki + fa_odnoklassniki_square + fa_get_pocket + fa_wikipedia_w + fa_safari + fa_chrome + fa_firefox + fa_opera + fa_internet_explorer + fa_television_tv + fa_contao + fa_500px + fa_amazon + fa_calendar_plus_o + fa_calendar_minus_o + fa_calendar_times_o + fa_calendar_check_o + fa_industry + fa_map_pin + fa_map_signs + fa_map_o + fa_map + fa_commenting + fa_commenting_o + fa_houzz + fa_vimeo + fa_black_tie + fa_fonticons + fa_reddit_alien + fa_edge + fa_credit_card_alt + fa_codiepie + fa_modx + fa_fort_awesome + fa_usb + fa_product_hunt + fa_mixcloud + fa_scribd + fa_pause_circle + fa_pause_circle_o + fa_stop_circle + fa_stop_circle_o + fa_shopping_bag + fa_shopping_basket + fa_hashtag + fa_bluetooth + fa_bluetooth_b + fa_percent + fa_gitlab + fa_wpbeginner + fa_wpforms + fa_envira + fa_universal_access + fa_wheelchair_alt + fa_question_circle_o + fa_blind + fa_audio_description + fa_volume_control_phone + fa_braille + fa_assistive_listening_systems + fa_american_sign_language_interpreting_asl_interpreting + fa_deaf_deafness_hard_of_hearing + fa_glide + fa_glide_g + fa_sign_language_signing + fa_low_vision + fa_viadeo + fa_viadeo_square + fa_snapchat + fa_snapchat_ghost + fa_snapchat_square + fa_pied_piper + fa_first_order + fa_yoast + fa_themeisle + fa_google_plus_official_google_plus_circle + fa_font_awesome_fa + fa_handshake_o + fa_envelope_open + fa_envelope_open_o + fa_linode + fa_address_book + fa_address_book_o + fa_address_card_vcard + fa_address_card_o_vcard_o + fa_user_circle + fa_user_circle_o + fa_user_o + fa_id_badge + fa_id_card_drivers_license + fa_id_card_o_drivers_license_o + fa_quora + fa_free_code_camp + fa_telegram + fa_thermometer_full_thermometer_thermometer_4 + fa_thermometer_three_quarters_thermometer_3 + fa_thermometer_half_thermometer_2 + fa_thermometer_quarter_thermometer_1 + fa_thermometer_empty_thermometer_0 + fa_shower + fa_bath_bathtub_s15 + fa_podcast + fa_window_maximize + fa_window_minimize + fa_window_restore + fa_window_close_times_rectangle + fa_window_close_o_times_rectangle_o + fa_bandcamp + fa_grav + fa_etsy + fa_imdb + fa_ravelry + fa_eercast + fa_microchip + fa_snowflake_o + fa_superpowers + fa_wpexplorer + fa_meetup + fae_smaller + fae_snowing + fae_soda + fae_sofa + fae_soup + fae_spermatozoon + fae_spin_double + fae_stomach + fae_storm + fae_telescope + fae_thermometer + fae_thermometer_high + fae_thermometer_low + fae_thin_close + fae_toilet + fae_tools + fae_tooth + fae_uterus + fae_w3c + fae_walking + fae_virus + fae_telegram_circle + fae_slash + fae_telegram + fae_shirt + fae_tacos + fae_sushi + fae_triangle_ruler + fae_tree + fae_sun_cloud + fae_ruby_o + fae_ruler + fae_umbrella + fae_medicine + fae_microscope + fae_milk_bottle + fae_minimize + fae_molecule + fae_moon_cloud + fae_mushroom + fae_mustache + fae_mysql + fae_nintendo + fae_palette_color + fae_pi + fae_pizza + fae_planet + fae_plant + fae_playstation + fae_poison + fae_popcorn + fae_popsicle + fae_pulse + fae_python + fae_quora_circle + fae_quora_square + fae_radioactive + fae_raining + fae_real_heart + fae_refrigerator + fae_restore + fae_ring + fae_ruby + fae_fingerprint + fae_floppy + fae_footprint + fae_freecodecamp + fae_galaxy + fae_galery + fae_glass + fae_google_drive + fae_google_play + fae_gps + fae_grav + fae_guitar + fae_gut + fae_halter + fae_hamburger + fae_hat + fae_hexagon + fae_high_heel + fae_hotdog + fae_ice_cream + fae_id_card + fae_imdb + fae_infinity + fae_java + fae_layers + fae_lips + fae_lipstick + fae_liver + fae_lung + fae_makeup_brushes + fae_maximize + fae_wallet + fae_chess_horse + fae_chess_king + fae_chess_pawn + fae_chess_queen + fae_chess_tower + fae_cheese + fae_chilli + fae_chip + fae_cicling + fae_cloud + fae_cockroach + fae_coffe_beans + fae_coins + fae_comb + fae_comet + fae_crown + fae_cup_coffe + fae_dice + fae_disco + fae_dna + fae_donut + fae_dress + fae_drop + fae_ello + fae_envelope_open + fae_envelope_open_o + fae_equal + fae_equal_bigger + fae_feedly + fae_file_export + fae_file_import + fae_wind + fae_atom + fae_bacteria + fae_banana + fae_bath + fae_bed + fae_benzene + fae_bigger + fae_biohazard + fae_blogger_circle + fae_blogger_square + fae_bones + fae_book_open + fae_book_open_o + fae_brain + fae_bread + fae_butterfly + fae_carot + fae_cc_by + fae_cc_cc + fae_cc_nc + fae_cc_nc_eu + fae_cc_nc_jp + fae_cc_nd + fae_cc_remix + fae_cc_sa + fae_cc_share + fae_cc_zero + fae_checklist_o + fae_cherry + fae_chess_bishop + fae_xbox + fae_apple_fruit + fae_chicken_thigh + fae_gift_card + fae_injection + fae_isle + fae_lollipop + fae_loyalty_card + fae_meat + fae_mountains + fae_orange + fae_peach + fae_pear +⏻ iec_power +⏼ iec_toggle_power +⏽ iec_power_on +⏾ iec_sleep_mode +⭘ iec_power_off + linux_alpine + linux_aosc + linux_apple + linux_archlinux + linux_centos + linux_coreos + linux_debian + linux_devuan + linux_docker + linux_elementary + linux_fedora + linux_fedora_inverse + linux_freebsd + linux_gentoo + linux_linuxmint + linux_linuxmint_inverse + linux_mageia + linux_mandriva + linux_manjaro + linux_nixos + linux_opensuse + linux_raspberry_pi + linux_redhat + linux_sabayon + linux_slackware + linux_slackware_inverse + linux_tux + linux_ubuntu + linux_ubuntu_inverse + linux_almalinux + linux_archlabs + linux_artix + linux_budgie + linux_deepin + linux_endeavour + linux_ferris + linux_flathub + linux_gnu_guix + linux_illumos + linux_kali_linux + linux_openbsd + linux_parrot + linux_pop_os + linux_rocky_linux + linux_snappy + linux_solus + linux_void + linux_zorin +󰀁 md_vector_square +󰀂 md_access_point_network +󰀃 md_access_point +󰀄 md_account +󰀅 md_account_alert +󰀆 md_account_box +󰀇 md_account_box_outline +󰀈 md_account_check +󰀉 md_account_circle +󰀊 md_account_convert +󰀋 md_account_key +󰀌 md_tooltip_account +󰀍 md_account_minus +󰀎 md_account_multiple +󰀏 md_account_multiple_outline +󰀐 md_account_multiple_plus +󰀑 md_account_network +󰀒 md_account_off +󰀓 md_account_outline +󰀔 md_account_plus +󰀕 md_account_remove +󰀖 md_account_search +󰀗 md_account_star +󰀘 md_orbit +󰀙 md_account_switch +󰀚 md_adjust +󰀛 md_air_conditioner +󰀜 md_airballoon +󰀝 md_airplane +󰀞 md_airplane_off +󰀟 md_cast_variant +󰀠 md_alarm +󰀡 md_alarm_check +󰀢 md_alarm_multiple +󰀣 md_alarm_off +󰀤 md_alarm_plus +󰀥 md_album +󰀦 md_alert +󰀧 md_alert_box +󰀨 md_alert_circle +󰀩 md_alert_octagon +󰀪 md_alert_outline +󰀫 md_alpha +󰀬 md_alphabetical +󰀭 md_greenhouse +󰀮 md_rollerblade_off +󰀯 md_ambulance +󰀰 md_amplifier +󰀱 md_anchor +󰀲 md_android +󰀳 md_web_plus +󰀴 md_android_studio +󰀵 md_apple +󰀶 md_apple_finder +󰀷 md_apple_ios +󰀸 md_apple_icloud +󰀹 md_apple_safari +󰀺 md_font_awesome +󰀻 md_apps +󰀼 md_archive +󰀽 md_arrange_bring_forward +󰀾 md_arrange_bring_to_front +󰀿 md_arrange_send_backward +󰁀 md_arrange_send_to_back +󰁁 md_arrow_all +󰁂 md_arrow_bottom_left +󰁃 md_arrow_bottom_right +󰁄 md_arrow_collapse_all +󰁅 md_arrow_down +󰁆 md_arrow_down_thick +󰁇 md_arrow_down_bold_circle +󰁈 md_arrow_down_bold_circle_outline +󰁉 md_arrow_down_bold_hexagon_outline +󰁊 md_arrow_down_drop_circle +󰁋 md_arrow_down_drop_circle_outline +󰁌 md_arrow_expand_all +󰁍 md_arrow_left +󰁎 md_arrow_left_thick +󰁏 md_arrow_left_bold_circle +󰁐 md_arrow_left_bold_circle_outline +󰁑 md_arrow_left_bold_hexagon_outline +󰁒 md_arrow_left_drop_circle +󰁓 md_arrow_left_drop_circle_outline +󰁔 md_arrow_right +󰁕 md_arrow_right_thick +󰁖 md_arrow_right_bold_circle +󰁗 md_arrow_right_bold_circle_outline +󰁘 md_arrow_right_bold_hexagon_outline +󰁙 md_arrow_right_drop_circle +󰁚 md_arrow_right_drop_circle_outline +󰁛 md_arrow_top_left +󰁜 md_arrow_top_right +󰁝 md_arrow_up +󰁞 md_arrow_up_thick +󰁟 md_arrow_up_bold_circle +󰁠 md_arrow_up_bold_circle_outline +󰁡 md_arrow_up_bold_hexagon_outline +󰁢 md_arrow_up_drop_circle +󰁣 md_arrow_up_drop_circle_outline +󰁤 md_assistant +󰁥 md_at +󰁦 md_attachment +󰁧 md_book_music +󰁨 md_auto_fix +󰁩 md_auto_upload +󰁪 md_autorenew +󰁫 md_av_timer +󰁬 md_baby +󰁭 md_backburger +󰁮 md_backspace +󰁯 md_backup_restore +󰁰 md_bank +󰁱 md_barcode +󰁲 md_barcode_scan +󰁳 md_barley +󰁴 md_barrel +󰁵 md_incognito_off +󰁶 md_basket +󰁷 md_basket_fill +󰁸 md_basket_unfill +󰁹 md_battery +󰁺 md_battery_10 +󰁻 md_battery_20 +󰁼 md_battery_30 +󰁽 md_battery_40 +󰁾 md_battery_50 +󰁿 md_battery_60 +󰂀 md_battery_70 +󰂁 md_battery_80 +󰂂 md_battery_90 +󰂃 md_battery_alert +󰂄 md_battery_charging +󰂅 md_battery_charging_100 +󰂆 md_battery_charging_20 +󰂇 md_battery_charging_30 +󰂈 md_battery_charging_40 +󰂉 md_battery_charging_60 +󰂊 md_battery_charging_80 +󰂋 md_battery_charging_90 +󰂌 md_battery_minus_variant +󰂍 md_battery_negative +󰂎 md_battery_outline +󰂏 md_battery_plus_variant +󰂐 md_battery_positive +󰂑 md_battery_unknown +󰂒 md_beach +󰂓 md_flask +󰂔 md_flask_empty +󰂕 md_flask_empty_outline +󰂖 md_flask_outline +󰂗 md_bunk_bed_outline +󰂘 md_beer +󰂙 md_bed_outline +󰂚 md_bell +󰂛 md_bell_off +󰂜 md_bell_outline +󰂝 md_bell_plus +󰂞 md_bell_ring +󰂟 md_bell_ring_outline +󰂠 md_bell_sleep +󰂡 md_beta +󰂢 md_book_cross +󰂣 md_bike +󰂤 md_microsoft_bing +󰂥 md_binoculars +󰂦 md_bio +󰂧 md_biohazard +󰂨 md_bitbucket +󰂩 md_black_mesa +󰂪 md_shield_refresh +󰂫 md_blender_software +󰂬 md_blinds +󰂭 md_block_helper +󰂮 md_application_edit +󰂯 md_bluetooth +󰂰 md_bluetooth_audio +󰂱 md_bluetooth_connect +󰂲 md_bluetooth_off +󰂳 md_bluetooth_settings +󰂴 md_bluetooth_transfer +󰂵 md_blur +󰂶 md_blur_linear +󰂷 md_blur_off +󰂸 md_blur_radial +󰂹 md_bone +󰂺 md_book +󰂻 md_book_multiple +󰂼 md_book_variant_multiple +󰂽 md_book_open +󰂾 md_book_open_blank_variant +󰂿 md_book_variant +󰃀 md_bookmark +󰃁 md_bookmark_check +󰃂 md_bookmark_music +󰃃 md_bookmark_outline +󰃄 md_bookmark_plus_outline +󰃅 md_bookmark_plus +󰃆 md_bookmark_remove +󰃇 md_border_all +󰃈 md_border_bottom +󰃉 md_border_color +󰃊 md_border_horizontal +󰃋 md_border_inside +󰃌 md_border_left +󰃍 md_border_none +󰃎 md_border_outside +󰃏 md_border_right +󰃐 md_border_style +󰃑 md_border_top +󰃒 md_border_vertical +󰃓 md_bowling +󰃔 md_box +󰃕 md_box_cutter +󰃖 md_briefcase +󰃗 md_briefcase_check +󰃘 md_briefcase_download +󰃙 md_briefcase_upload +󰃚 md_brightness_1 +󰃛 md_brightness_2 +󰃜 md_brightness_3 +󰃝 md_brightness_4 +󰃞 md_brightness_5 +󰃟 md_brightness_6 +󰃠 md_brightness_7 +󰃡 md_brightness_auto +󰃢 md_broom +󰃣 md_brush +󰃤 md_bug +󰃥 md_bulletin_board +󰃦 md_bullhorn +󰃧 md_bus +󰃨 md_cached +󰃩 md_cake +󰃪 md_cake_layered +󰃫 md_cake_variant +󰃬 md_calculator +󰃭 md_calendar +󰃮 md_calendar_blank +󰃯 md_calendar_check +󰃰 md_calendar_clock +󰃱 md_calendar_multiple +󰃲 md_calendar_multiple_check +󰃳 md_calendar_plus +󰃴 md_calendar_remove +󰃵 md_calendar_text +󰃶 md_calendar_today +󰃷 md_call_made +󰃸 md_call_merge +󰃹 md_call_missed +󰃺 md_call_received +󰃻 md_call_split +󰃼 md_camcorder +󰃽 md_video_box +󰃾 md_video_box_off +󰃿 md_camcorder_off +󰄀 md_camera +󰄁 md_camera_enhance +󰄂 md_camera_front +󰄃 md_camera_front_variant +󰄄 md_camera_iris +󰄅 md_camera_party_mode +󰄆 md_camera_rear +󰄇 md_camera_rear_variant +󰄈 md_camera_switch +󰄉 md_camera_timer +󰄊 md_candycane +󰄋 md_car +󰄌 md_car_battery +󰄍 md_car_connected +󰄎 md_car_wash +󰄏 md_carrot +󰄐 md_cart +󰄑 md_cart_outline +󰄒 md_cart_plus +󰄓 md_case_sensitive_alt +󰄔 md_cash +󰄕 md_cash_100 +󰄖 md_cash_multiple +󰄗 md_checkbox_blank_badge_outline +󰄘 md_cast +󰄙 md_cast_connected +󰄚 md_castle +󰄛 md_cat +󰄜 md_cellphone +󰄝 md_tray_arrow_up +󰄞 md_cellphone_basic +󰄟 md_cellphone_dock +󰄠 md_tray_arrow_down +󰄡 md_cellphone_link +󰄢 md_cellphone_link_off +󰄣 md_cellphone_settings +󰄤 md_certificate +󰄥 md_chair_school +󰄦 md_chart_arc +󰄧 md_chart_areaspline +󰄨 md_chart_bar +󰄩 md_chart_histogram +󰄪 md_chart_line +󰄫 md_chart_pie +󰄬 md_check +󰄭 md_check_all +󰄮 md_checkbox_blank +󰝥 md_checkbox_blank_circle +󰝦 md_checkbox_blank_circle_outline +󰄱 md_checkbox_blank_outline +󰄲 md_checkbox_marked +󰄳 md_checkbox_marked_circle +󰄴 md_checkbox_marked_circle_outline +󰄵 md_checkbox_marked_outline +󰄶 md_checkbox_multiple_blank +󰄷 md_checkbox_multiple_blank_outline +󰄸 md_checkbox_multiple_marked +󰄹 md_checkbox_multiple_marked_outline +󰄺 md_checkerboard +󰄻 md_chemical_weapon +󰄼 md_chevron_double_down +󰄽 md_chevron_double_left +󰄾 md_chevron_double_right +󰄿 md_chevron_double_up +󰅀 md_chevron_down +󰅁 md_chevron_left +󰅂 md_chevron_right +󰅃 md_chevron_up +󰅄 md_church +󰅅 md_roller_skate_off +󰅆 md_city +󰅇 md_clipboard +󰅈 md_clipboard_account +󰅉 md_clipboard_alert +󰅊 md_clipboard_arrow_down +󰅋 md_clipboard_arrow_left +󰅌 md_clipboard_outline +󰅍 md_clipboard_text +󰅎 md_clipboard_check +󰅏 md_clippy +󰅐 md_clock_outline +󰅑 md_clock_end +󰅒 md_clock_fast +󰅓 md_clock_in +󰅔 md_clock_out +󰅕 md_clock_start +󰅖 md_close +󰅗 md_close_box +󰅘 md_close_box_outline +󰅙 md_close_circle +󰅚 md_close_circle_outline +󰅛 md_close_network +󰅜 md_close_octagon +󰅝 md_close_octagon_outline +󰅞 md_closed_caption +󰅟 md_cloud +󰅠 md_cloud_check +󰅡 md_cloud_circle +󰅢 md_cloud_download +󰅣 md_cloud_outline +󰅤 md_cloud_off_outline +󰅥 md_cloud_print +󰅦 md_cloud_print_outline +󰅧 md_cloud_upload +󰅨 md_code_array +󰅩 md_code_braces +󰅪 md_code_brackets +󰅫 md_code_equal +󰅬 md_code_greater_than +󰅭 md_code_greater_than_or_equal +󰅮 md_code_less_than +󰅯 md_code_less_than_or_equal +󰅰 md_code_not_equal +󰅱 md_code_not_equal_variant +󰅲 md_code_parentheses +󰅳 md_code_string +󰅴 md_code_tags +󰅵 md_codepen +󰅶 md_coffee +󰅷 md_coffee_to_go +󰅸 md_bell_badge_outline +󰅹 md_color_helper +󰅺 md_comment +󰅻 md_comment_account +󰅼 md_comment_account_outline +󰅽 md_comment_alert +󰅾 md_comment_alert_outline +󰅿 md_comment_check +󰆀 md_comment_check_outline +󰆁 md_comment_multiple_outline +󰆂 md_comment_outline +󰆃 md_comment_plus_outline +󰆄 md_comment_processing +󰆅 md_comment_processing_outline +󰆆 md_comment_question_outline +󰆇 md_comment_remove_outline +󰆈 md_comment_text +󰆉 md_comment_text_outline +󰆊 md_compare +󰆋 md_compass +󰆌 md_compass_outline +󰆍 md_console +󰆎 md_card_account_mail +󰆏 md_content_copy +󰆐 md_content_cut +󰆑 md_content_duplicate +󰆒 md_content_paste +󰆓 md_content_save +󰆔 md_content_save_all +󰆕 md_contrast +󰆖 md_contrast_box +󰆗 md_contrast_circle +󰆘 md_cookie +󰆙 md_counter +󰆚 md_cow +󰆛 md_credit_card_outline +󰆜 md_credit_card_multiple_outline +󰆝 md_credit_card_scan_outline +󰆞 md_crop +󰆟 md_crop_free +󰆠 md_crop_landscape +󰆡 md_crop_portrait +󰆢 md_crop_square +󰆣 md_crosshairs +󰆤 md_crosshairs_gps +󰆥 md_crown +󰆦 md_cube +󰆧 md_cube_outline +󰆨 md_cube_send +󰆩 md_cube_unfolded +󰆪 md_cup +󰆫 md_cup_water +󰆬 md_currency_btc +󰆭 md_currency_eur +󰆮 md_currency_gbp +󰆯 md_currency_inr +󰆰 md_currency_ngn +󰆱 md_currency_rub +󰆲 md_currency_try +󰆳 md_delete_variant +󰆴 md_delete +󰆵 md_decimal_increase +󰆶 md_decimal_decrease +󰆷 md_debug_step_over +󰆸 md_debug_step_out +󰆹 md_debug_step_into +󰆺 md_database_plus +󰆻 md_database_minus +󰆼 md_database +󰆽 md_cursor_pointer +󰆾 md_cursor_move +󰆿 md_cursor_default_outline +󰇀 md_cursor_default +󰇁 md_currency_usd +󰇂 md_delta +󰇃 md_deskphone +󰇄 md_desktop_mac +󰇅 md_desktop_tower +󰇆 md_details +󰇇 md_deviantart +󰇈 md_diamond_stone +󰇉 md_ab_testing +󰇊 md_dice_1 +󰇋 md_dice_2 +󰇌 md_dice_3 +󰇍 md_dice_4 +󰇎 md_dice_5 +󰇏 md_dice_6 +󰇐 md_directions +󰇑 md_disc_alert +󰇒 md_disqus +󰇓 md_video_plus_outline +󰇔 md_division +󰇕 md_division_box +󰇖 md_dns +󰇗 md_domain +󰇘 md_dots_horizontal +󰇙 md_dots_vertical +󰇚 md_download +󰇛 md_drag +󰇜 md_drag_horizontal +󰇝 md_drag_vertical +󰇞 md_drawing +󰇟 md_drawing_box +󰇠 md_shield_refresh_outline +󰇡 md_calendar_refresh +󰇢 md_drone +󰇣 md_dropbox +󰇤 md_drupal +󰇥 md_duck +󰇦 md_dumbbell +󰇧 md_earth +󰇨 md_earth_off +󰇩 md_microsoft_edge +󰇪 md_eject +󰇫 md_elevation_decline +󰇬 md_elevation_rise +󰇭 md_elevator +󰇮 md_email +󰇯 md_email_open +󰇰 md_email_outline +󰇱 md_email_lock +󰇲 md_emoticon_outline +󰇳 md_emoticon_cool_outline +󰇴 md_emoticon_devil_outline +󰇵 md_emoticon_happy_outline +󰇶 md_emoticon_neutral_outline +󰇷 md_emoticon_poop +󰇸 md_emoticon_sad_outline +󰇹 md_emoticon_tongue +󰇺 md_engine +󰇻 md_engine_outline +󰇼 md_equal +󰇽 md_equal_box +󰇾 md_eraser +󰇿 md_escalator +󰈀 md_ethernet +󰈁 md_ethernet_cable +󰈂 md_ethernet_cable_off +󰈃 md_calendar_refresh_outline +󰈄 md_evernote +󰈅 md_exclamation +󰗼 md_exit_to_app +󰈇 md_export +󰈈 md_eye +󰈉 md_eye_off +󰈊 md_eyedropper +󰈋 md_eyedropper_variant +󰈌 md_facebook +󰈍 md_order_alphabetical_ascending +󰈎 md_facebook_messenger +󰈏 md_factory +󰈐 md_fan +󰈑 md_fast_forward +󰈒 md_fax +󰈓 md_ferry +󰈔 md_file +󰈕 md_file_chart +󰈖 md_file_check +󰈗 md_file_cloud +󰈘 md_file_delimited +󰈙 md_file_document +󰈚 md_text_box +󰈛 md_file_excel +󰈜 md_file_excel_box +󰈝 md_file_export +󰈞 md_file_find +󰈟 md_file_image +󰈠 md_file_import +󰈡 md_file_lock +󰈢 md_file_multiple +󰈣 md_file_music +󰈤 md_file_outline +󰈥 md_file_jpg_box +󰈦 md_file_pdf_box +󰈧 md_file_powerpoint +󰈨 md_file_powerpoint_box +󰈩 md_file_presentation_box +󰈪 md_file_send +󰈫 md_file_video +󰈬 md_file_word +󰈭 md_file_word_box +󰈮 md_file_code +󰈯 md_film +󰈰 md_filmstrip +󰈱 md_filmstrip_off +󰈲 md_filter +󰈳 md_filter_outline +󰈴 md_filter_remove +󰈵 md_filter_remove_outline +󰈶 md_filter_variant +󰈷 md_fingerprint +󰈸 md_fire +󰈹 md_firefox +󰈺 md_fish +󰈻 md_flag +󰈼 md_flag_checkered +󰈽 md_flag_outline +󰈾 md_flag_variant_outline +󰈿 md_flag_triangle +󰉀 md_flag_variant +󰉁 md_flash +󰉂 md_flash_auto +󰉃 md_flash_off +󰉄 md_flashlight +󰉅 md_flashlight_off +󰉆 md_star_half +󰉇 md_flip_to_back +󰉈 md_flip_to_front +󰉉 md_floppy +󰉊 md_flower +󰉋 md_folder +󰉌 md_folder_account +󰉍 md_folder_download +󰉎 md_folder_google_drive +󰉏 md_folder_image +󰉐 md_folder_lock +󰉑 md_folder_lock_open +󰉒 md_folder_move +󰉓 md_folder_multiple +󰉔 md_folder_multiple_image +󰉕 md_folder_multiple_outline +󰉖 md_folder_outline +󰉗 md_folder_plus +󰉘 md_folder_remove +󰉙 md_folder_upload +󰉚 md_food +󰉛 md_food_apple +󰉜 md_food_variant +󰉝 md_football +󰉞 md_football_australian +󰉟 md_football_helmet +󰉠 md_format_align_center +󰉡 md_format_align_justify +󰉢 md_format_align_left +󰉣 md_format_align_right +󰉤 md_format_bold +󰉥 md_format_clear +󰉦 md_format_color_fill +󰉧 md_format_float_center +󰉨 md_format_float_left +󰉩 md_format_float_none +󰉪 md_format_float_right +󰉫 md_format_header_1 +󰉬 md_format_header_2 +󰉭 md_format_header_3 +󰉮 md_format_header_4 +󰉯 md_format_header_5 +󰉰 md_format_header_6 +󰉱 md_format_header_decrease +󰉲 md_format_header_equal +󰉳 md_format_header_increase +󰉴 md_format_header_pound +󰉵 md_format_indent_decrease +󰉶 md_format_indent_increase +󰉷 md_format_italic +󰉸 md_format_line_spacing +󰉹 md_format_list_bulleted +󰉺 md_format_list_bulleted_type +󰉻 md_format_list_numbered +󰉼 md_format_paint +󰉽 md_format_paragraph +󰉾 md_format_quote_close +󰉿 md_format_size +󰊀 md_format_strikethrough +󰊁 md_format_strikethrough_variant +󰊂 md_format_subscript +󰊃 md_format_superscript +󰊄 md_format_text +󰊅 md_format_textdirection_l_to_r +󰊆 md_format_textdirection_r_to_l +󰊇 md_format_underline +󰊈 md_format_wrap_inline +󰊉 md_format_wrap_square +󰊊 md_format_wrap_tight +󰊋 md_format_wrap_top_bottom +󰊌 md_forum +󰊍 md_forward +󰊎 md_bowl +󰊏 md_fridge_outline +󰊐 md_fridge +󰊑 md_fridge_top +󰊒 md_fridge_bottom +󰊓 md_fullscreen +󰊔 md_fullscreen_exit +󰊕 md_function +󰊖 md_gamepad +󰊗 md_gamepad_variant +󰊘 md_gas_station +󰊙 md_gate +󰊚 md_gauge +󰊛 md_gavel +󰊜 md_gender_female +󰊝 md_gender_male +󰊞 md_gender_male_female +󰊟 md_gender_transgender +󰊠 md_ghost +󰊡 md_gift_outline +󰊢 md_git +󰊣 md_card_account_details_star +󰊤 md_github +󰊥 md_glass_flute +󰊦 md_glass_mug +󰊧 md_glass_stange +󰊨 md_glass_tulip +󰊩 md_bowl_outline +󰊪 md_glasses +󰊫 md_gmail +󰊬 md_gnome +󰊭 md_google +󰊮 md_google_cardboard +󰊯 md_google_chrome +󰊰 md_google_circles +󰊱 md_google_circles_communities +󰊲 md_google_circles_extended +󰊳 md_google_circles_group +󰊴 md_google_controller +󰊵 md_google_controller_off +󰊶 md_google_drive +󰊷 md_google_earth +󰊸 md_google_glass +󰊹 md_google_nearby +󰊺 md_video_minus_outline +󰊻 md_microsoft_teams +󰊼 md_google_play +󰊽 md_google_plus +󰊾 md_order_bool_ascending +󰊿 md_google_translate +󰋀 md_google_classroom +󰋁 md_grid +󰋂 md_grid_off +󰋃 md_group +󰋄 md_guitar_electric +󰋅 md_guitar_pick +󰋆 md_guitar_pick_outline +󰋇 md_hand_pointing_right +󰋈 md_hanger +󰋉 md_google_hangouts +󰋊 md_harddisk +󰋋 md_headphones +󰋌 md_headphones_box +󰋍 md_headphones_settings +󰋎 md_headset +󰋏 md_headset_dock +󰋐 md_headset_off +󰣐 md_heart +󰋒 md_heart_box +󰋓 md_heart_box_outline +󰋔 md_heart_broken +󱢠 md_heart_outline +󰋖 md_help +󰋗 md_help_circle +󰋘 md_hexagon +󰋙 md_hexagon_outline +󰋚 md_history +󰋛 md_hololens +󰋜 md_home +󰋝 md_home_modern +󰋞 md_home_variant +󰋟 md_hops +󰋠 md_hospital_box +󰋡 md_hospital_building +󰋢 md_hospital_marker +󰋣 md_bed +󰋤 md_bowl_mix_outline +󰋥 md_pot +󰋦 md_human +󰋧 md_human_child +󰋨 md_human_male_female +󰋩 md_image +󰋪 md_image_album +󰋫 md_image_area +󰋬 md_image_area_close +󰋭 md_image_broken +󰋮 md_image_broken_variant +󰋯 md_image_multiple_outline +󰋰 md_image_filter_black_white +󰋱 md_image_filter_center_focus +󰋲 md_image_filter_center_focus_weak +󰋳 md_image_filter_drama +󰋴 md_image_filter_frames +󰔉 md_image_filter_hdr +󰋶 md_image_filter_none +󰋷 md_image_filter_tilt_shift +󰋸 md_image_filter_vintage +󰋹 md_image_multiple +󰋺 md_import +󰋻 md_inbox_arrow_down +󰋼 md_information +󰋽 md_information_outline +󰋾 md_instagram +󰋿 md_pot_outline +󰌀 md_microsoft_internet_explorer +󰌁 md_invert_colors +󰌂 md_jeepney +󰌃 md_jira +󰌄 md_jsfiddle +󰌅 md_keg +󰌆 md_key +󰌇 md_key_change +󰌈 md_key_minus +󰌉 md_key_plus +󰌊 md_key_remove +󰌋 md_key_variant +󰌌 md_keyboard +󰌍 md_keyboard_backspace +󰌎 md_keyboard_caps +󰌏 md_keyboard_close +󰌐 md_keyboard_off +󰌑 md_keyboard_return +󰌒 md_keyboard_tab +󰌓 md_keyboard_variant +󰌔 md_kodi +󰌕 md_label +󰌖 md_label_outline +󰌗 md_lan +󰌘 md_lan_connect +󰌙 md_lan_disconnect +󰌚 md_lan_pending +󰌛 md_language_csharp +󰌜 md_language_css3 +󰌝 md_language_html5 +󰌞 md_language_javascript +󰌟 md_language_php +󰌠 md_language_python +󰌡 md_contactless_payment_circle +󰌢 md_laptop +󰌣 md_magazine_rifle +󰌤 md_magazine_pistol +󰌥 md_keyboard_tab_reverse +󰌦 md_pot_steam_outline +󰌧 md_launch +󰌨 md_layers +󰌩 md_layers_off +󰌪 md_leaf +󰌫 md_led_off +󰌬 md_led_on +󰌭 md_led_outline +󰌮 md_led_variant_off +󰌯 md_led_variant_on +󰌰 md_led_variant_outline +󰌱 md_library +󰌲 md_filmstrip_box +󰌳 md_music_box_multiple +󰌴 md_plus_box_multiple +󰌵 md_lightbulb +󰌶 md_lightbulb_outline +󰌷 md_link +󰌸 md_link_off +󰌹 md_link_variant +󰌺 md_link_variant_off +󰌻 md_linkedin +󰌼 md_sort_reverse_variant +󰌽 md_linux +󰌾 md_lock +󰌿 md_lock_open +󰍀 md_lock_open_outline +󰍁 md_lock_outline +󰍂 md_login +󰍃 md_logout +󰍄 md_looks +󰍅 md_loupe +󰍆 md_lumx +󰍇 md_magnet +󰍈 md_magnet_on +󰍉 md_magnify +󰍊 md_magnify_minus +󰍋 md_magnify_plus +󰍌 md_plus_circle_multiple +󰍍 md_map +󰍎 md_map_marker +󰍏 md_map_marker_circle +󰍐 md_map_marker_multiple +󰍑 md_map_marker_off +󰍒 md_map_marker_radius +󰍓 md_margin +󰍔 md_language_markdown +󰍕 md_marker_check +󰍖 md_glass_cocktail +󰍗 md_material_ui +󰍘 md_math_compass +󰍙 md_stackpath +󰍚 md_minus_circle_multiple +󰍛 md_memory +󰍜 md_menu +󰍝 md_menu_down +󰍞 md_menu_left +󰍟 md_menu_right +󰍠 md_menu_up +󰍡 md_message +󰍢 md_message_alert +󰍣 md_message_draw +󰍤 md_message_image +󰍥 md_message_outline +󰍦 md_message_processing +󰍧 md_message_reply +󰍨 md_message_reply_text +󰍩 md_message_text +󰍪 md_message_text_outline +󰍫 md_message_video +󰍬 md_microphone +󰍭 md_microphone_off +󰍮 md_microphone_outline +󰍯 md_microphone_settings +󰍰 md_microphone_variant +󰍱 md_microphone_variant_off +󰍲 md_microsoft +󰍳 md_minecraft +󰍴 md_minus +󰍵 md_minus_box +󰍶 md_minus_circle +󰍷 md_minus_circle_outline +󰍸 md_minus_network +󰍹 md_monitor +󰍺 md_monitor_multiple +󰍻 md_more +󰍼 md_motorbike +󰍽 md_mouse +󰍾 md_mouse_off +󰍿 md_mouse_variant +󰎀 md_mouse_variant_off +󰎁 md_movie +󰎂 md_multiplication +󰎃 md_multiplication_box +󰎄 md_music_box +󰎅 md_music_box_outline +󰎆 md_music_circle +󰎈 md_music_note +󰎈 md_music_note +󰎉 md_music_note_half +󰎊 md_music_note_off +󰎋 md_music_note_quarter +󰎌 md_music_note_sixteenth +󰎍 md_music_note_whole +󰎎 md_nature +󰎏 md_nature_people +󰎐 md_navigation +󰎑 md_needle +󰎒 md_smoke_detector +󰎓 md_thermostat +󰎔 md_new_box +󰎕 md_newspaper +󰎖 md_nfc +󰎗 md_nfc_tap +󰎘 md_nfc_variant +󰎙 md_nodejs +󰎚 md_note +󰎛 md_note_outline +󰎜 md_note_plus +󰎝 md_note_plus_outline +󰎞 md_note_text +󰎟 md_notification_clear_all +󰎠 md_numeric +󰎡 md_numeric_0_box +󰎢 md_numeric_0_box_multiple_outline +󰎣 md_numeric_0_box_outline +󰎤 md_numeric_1_box +󰎥 md_numeric_1_box_multiple_outline +󰎦 md_numeric_1_box_outline +󰎧 md_numeric_2_box +󰎨 md_numeric_2_box_multiple_outline +󰎩 md_numeric_2_box_outline +󰎪 md_numeric_3_box +󰎫 md_numeric_3_box_multiple_outline +󰎬 md_numeric_3_box_outline +󰎭 md_numeric_4_box +󰎮 md_numeric_4_box_outline +󰎯 md_numeric_5_box_multiple_outline +󰎰 md_numeric_5_box_outline +󰎱 md_numeric_5_box +󰎲 md_numeric_4_box_multiple_outline +󰎳 md_numeric_6_box +󰎴 md_numeric_6_box_multiple_outline +󰎵 md_numeric_6_box_outline +󰎶 md_numeric_7_box +󰎷 md_numeric_7_box_multiple_outline +󰎸 md_numeric_7_box_outline +󰎹 md_numeric_8_box +󰎺 md_numeric_8_box_multiple_outline +󰎻 md_numeric_8_box_outline +󰎼 md_numeric_9_box +󰎽 md_numeric_9_box_multiple_outline +󰎾 md_numeric_9_box_outline +󰎿 md_numeric_9_plus_box +󰏀 md_numeric_9_plus_box_multiple_outline +󰏁 md_numeric_9_plus_box_outline +󰏂 md_nutrition +󰏃 md_octagon +󰏄 md_octagon_outline +󰏅 md_odnoklassniki +󰏆 md_microsoft_office +󰏇 md_oil +󰏈 md_coolant_temperature +󰏉 md_omega +󰏊 md_microsoft_onedrive +󰏋 md_open_in_app +󰏌 md_open_in_new +󰏍 md_openid +󰏎 md_opera +󰏏 md_ornament +󰏐 md_ornament_variant +󰏑 md_inbox_arrow_up +󰏒 md_owl +󰏓 md_package +󰏔 md_package_down +󰏕 md_package_up +󰏖 md_package_variant +󰏗 md_package_variant_closed +󰏘 md_palette +󰏙 md_palette_advanced +󰏚 md_panda +󰏛 md_pandora +󰏜 md_panorama +󰏝 md_panorama_fisheye +󰏞 md_panorama_horizontal_outline +󰏟 md_panorama_vertical_outline +󰏠 md_panorama_wide_angle_outline +󰏡 md_paper_cut_vertical +󰏢 md_paperclip +󰏣 md_parking +󰏤 md_pause +󰏥 md_pause_circle +󰏦 md_pause_circle_outline +󰏧 md_pause_octagon +󰏨 md_pause_octagon_outline +󰏩 md_paw +󰏪 md_pen +󰏫 md_pencil +󰏬 md_pencil_box +󰏭 md_pencil_box_outline +󰏮 md_pencil_lock +󰏯 md_pencil_off +󰏰 md_percent +󰏱 md_mortar_pestle_plus +󰏲 md_phone +󰏳 md_phone_bluetooth +󰏴 md_phone_forward +󰏵 md_phone_hangup +󰏶 md_phone_in_talk +󰏷 md_phone_incoming +󰏸 md_phone_lock +󰏹 md_phone_log +󰏺 md_phone_missed +󰏻 md_phone_outgoing +󰏼 md_phone_paused +󰏽 md_phone_settings +󰏾 md_phone_voip +󰏿 md_pi +󰐀 md_pi_box +󰐁 md_pig +󰐂 md_pill +󰐃 md_pin +󰐄 md_pin_off +󰐅 md_pine_tree +󰐆 md_pine_tree_box +󰐇 md_pinterest +󰐈 md_contactless_payment_circle_outline +󰐉 md_pizza +󰐊 md_play +󰐋 md_play_box_outline +󰐌 md_play_circle +󰐍 md_play_circle_outline +󰐎 md_play_pause +󰐏 md_play_protected_content +󰐐 md_playlist_minus +󰐑 md_playlist_play +󰐒 md_playlist_plus +󰐓 md_playlist_remove +󰐔 md_sony_playstation +󰐕 md_plus +󰐖 md_plus_box +󰐗 md_plus_circle +󰐘 md_plus_circle_multiple_outline +󰐙 md_plus_circle_outline +󰐚 md_plus_network +󰐛 md_sledding +󰐜 md_wall_sconce_flat_variant +󰐝 md_pokeball +󰐞 md_polaroid +󰐟 md_poll +󰐠 md_account_eye +󰐡 md_polymer +󰐢 md_popcorn +󰐣 md_pound +󰐤 md_pound_box +󰐥 md_power +󰐦 md_power_settings +󰐧 md_power_socket +󰐨 md_presentation +󰐩 md_presentation_play +󰐪 md_printer +󰐫 md_printer_3d +󰐬 md_printer_alert +󰐭 md_professional_hexagon +󰐮 md_projector +󰐯 md_projector_screen +󰐰 md_pulse +󰐱 md_puzzle +󰐲 md_qrcode +󰐳 md_qrcode_scan +󰐴 md_quadcopter +󰐵 md_quality_high +󰐶 md_book_multiple_outline +󰐷 md_radar +󰐸 md_radiator +󰐹 md_radio +󰐺 md_radio_handheld +󰐻 md_radio_tower +󰐼 md_radioactive +󰝦 md_checkbox_blank_circle_outline +󰐾 md_radiobox_marked +󰐿 md_raspberry_pi +󰑀 md_ray_end +󰑁 md_ray_end_arrow +󰑂 md_ray_start +󰑃 md_ray_start_arrow +󰑄 md_ray_start_end +󰑅 md_ray_vertex +󰑆 md_lastpass +󰑇 md_read +󰑈 md_youtube_tv +󰑉 md_receipt +󰑊 md_record +󰑋 md_record_rec +󰑌 md_recycle +󰑍 md_reddit +󰑎 md_redo +󰑏 md_redo_variant +󰑐 md_refresh +󰑑 md_regex +󰑒 md_relative_scale +󰑓 md_reload +󰑔 md_remote +󰑕 md_rename_box +󰑖 md_repeat +󰑗 md_repeat_off +󰑘 md_repeat_once +󰑙 md_replay +󰑚 md_reply +󰑛 md_reply_all +󰑜 md_reproduction +󰑝 md_resize_bottom_right +󰑞 md_responsive +󰑟 md_rewind +󰑠 md_ribbon +󰑡 md_road +󰑢 md_road_variant +󰑣 md_rocket +󰑤 md_rotate_3d_variant +󰑥 md_rotate_left +󰑦 md_rotate_left_variant +󰑧 md_rotate_right +󰑨 md_rotate_right_variant +󰑩 md_router_wireless +󰑪 md_routes +󰑫 md_rss +󰑬 md_rss_box +󰑭 md_ruler +󰑮 md_run_fast +󰑯 md_sale +󰑰 md_satellite +󰑱 md_satellite_variant +󰑲 md_scale +󰑳 md_scale_bathroom +󰑴 md_school +󰑵 md_screen_rotation +󰑶 md_screwdriver +󰑷 md_script_outline +󰑸 md_screen_rotation_lock +󰑹 md_sd +󰑺 md_seal +󰑻 md_seat_flat +󰑼 md_seat_flat_angled +󰑽 md_seat_individual_suite +󰑾 md_seat_legroom_extra +󰑿 md_seat_legroom_normal +󰒀 md_seat_legroom_reduced +󰒁 md_seat_recline_extra +󰒂 md_seat_recline_normal +󰒃 md_security +󰒄 md_security_network +󰒅 md_select +󰒆 md_select_all +󰒇 md_select_inverse +󰒈 md_select_off +󰒉 md_selection +󰒊 md_send +󰒋 md_server +󰒌 md_server_minus +󰒍 md_server_network +󰒎 md_server_network_off +󰒏 md_server_off +󰒐 md_server_plus +󰒑 md_server_remove +󰒒 md_server_security +󰒓 md_cog +󰒔 md_cog_box +󰒕 md_shape_plus +󰒖 md_share +󰒗 md_share_variant +󰒘 md_shield +󰒙 md_shield_outline +󰒚 md_shopping +󰒛 md_shopping_music +󰒜 md_shredder +󰒝 md_shuffle +󰒞 md_shuffle_disabled +󰒟 md_shuffle_variant +󰒠 md_sigma +󰒡 md_sign_caution +󰒢 md_signal +󰒣 md_silverware +󰒤 md_silverware_fork +󰒥 md_silverware_spoon +󰒦 md_silverware_variant +󰒧 md_sim +󰒨 md_sim_alert +󰒩 md_sim_off +󰒪 md_sitemap +󰒫 md_skip_backward +󰒬 md_skip_forward +󰒭 md_skip_next +󰒮 md_skip_previous +󰒯 md_skype +󰒰 md_skype_business +󰒱 md_slack +󰒲 md_sleep +󰒳 md_sleep_off +󰒴 md_smoking +󰒵 md_smoking_off +󰒶 md_snapchat +󰒷 md_snowman +󰒸 md_soccer +󰒹 md_sofa +󰒺 md_sort +󰒻 md_sort_alphabetical_variant +󰒼 md_sort_ascending +󰒽 md_sort_descending +󰒾 md_sort_numeric_variant +󰒿 md_sort_variant +󰓀 md_soundcloud +󰓁 md_source_fork +󰓂 md_source_pull +󰓃 md_speaker +󰓄 md_speaker_off +󰓅 md_speedometer +󰓆 md_spellcheck +󰓇 md_spotify +󰓈 md_spotlight +󰓉 md_spotlight_beam +󰓊 md_book_remove_multiple_outline +󰓋 md_account_switch_outline +󰓌 md_stack_overflow +󰓍 md_stairs +󰓎 md_star +󰓏 md_star_circle +󰓐 md_star_half_full +󰓑 md_star_off +󰓒 md_star_outline +󰓓 md_steam +󰓔 md_steering +󰓕 md_step_backward +󰓖 md_step_backward_2 +󰓗 md_step_forward +󰓘 md_step_forward_2 +󰓙 md_stethoscope +󰓚 md_stocking +󰓛 md_stop +󰓜 md_store +󰓝 md_store_24_hour +󰓞 md_stove +󰓟 md_subway_variant +󰓠 md_sunglasses +󰓡 md_swap_horizontal +󰓢 md_swap_vertical +󰓣 md_swim +󰓤 md_switch +󰓥 md_sword +󰓦 md_sync +󰓧 md_sync_alert +󰓨 md_sync_off +󰓩 md_tab +󰓪 md_tab_unselected +󰓫 md_table +󰓬 md_table_column_plus_after +󰓭 md_table_column_plus_before +󰓮 md_table_column_remove +󰓯 md_table_column_width +󰓰 md_table_edit +󰓱 md_table_large +󰓲 md_table_row_height +󰓳 md_table_row_plus_after +󰓴 md_table_row_plus_before +󰓵 md_table_row_remove +󰓶 md_tablet +󰓷 md_tablet_android +󰓸 md_tangram +󰓹 md_tag +󰓺 md_tag_faces +󰓻 md_tag_multiple +󰓼 md_tag_outline +󰓽 md_tag_text_outline +󰓾 md_target +󰓿 md_taxi +󰔀 md_teamviewer +󰔁 md_skateboarding +󰔂 md_television +󰔃 md_television_guide +󰔄 md_temperature_celsius +󰔅 md_temperature_fahrenheit +󰔆 md_temperature_kelvin +󰔇 md_tennis_ball +󰔈 md_tent +󰔉 md_image_filter_hdr +󰔊 md_text_to_speech +󰔋 md_text_to_speech_off +󰔌 md_texture +󰔍 md_theater +󰔎 md_theme_light_dark +󰔏 md_thermometer +󰔐 md_thermometer_lines +󰔑 md_thumb_down +󰔒 md_thumb_down_outline +󰔓 md_thumb_up +󰔔 md_thumb_up_outline +󰔕 md_thumbs_up_down +󰔖 md_ticket +󰔗 md_ticket_account +󰔘 md_ticket_confirmation +󰔙 md_tie +󰔚 md_timelapse +󰔛 md_timer_outline +󰔜 md_timer_10 +󰔝 md_timer_3 +󰔞 md_timer_off_outline +󰔟 md_timer_sand +󰔠 md_timetable +󰔡 md_toggle_switch +󰔢 md_toggle_switch_off +󰔣 md_tooltip +󰔤 md_tooltip_edit +󰔥 md_tooltip_image +󰔦 md_tooltip_outline +󰔧 md_tooltip_plus_outline +󰔨 md_tooltip_text +󰔩 md_tooth_outline +󰔪 md_cloud_refresh +󰔫 md_traffic_light +󰔬 md_train +󰔭 md_tram +󰔮 md_transcribe +󰔯 md_transcribe_close +󰔰 md_transfer_right +󰔱 md_tree +󰔲 md_trello +󰔳 md_trending_down +󰔴 md_trending_neutral +󰔵 md_trending_up +󰔶 md_triangle +󰔷 md_triangle_outline +󰔸 md_trophy +󰔹 md_trophy_award +󰔺 md_trophy_outline +󰔻 md_trophy_variant +󰔼 md_trophy_variant_outline +󰔽 md_truck +󰔾 md_truck_delivery +󰔿 md_tshirt_crew_outline +󰕀 md_tshirt_v_outline +󰕁 md_file_refresh_outline +󰕂 md_folder_refresh_outline +󰕃 md_twitch +󰕄 md_twitter +󰕅 md_order_numeric_ascending +󰕆 md_order_numeric_descending +󰕇 md_repeat_variant +󰕈 md_ubuntu +󰕉 md_umbraco +󰕊 md_umbrella +󰕋 md_umbrella_outline +󰕌 md_undo +󰕍 md_undo_variant +󰕎 md_unfold_less_horizontal +󰕏 md_unfold_more_horizontal +󰕐 md_ungroup +󰕑 md_web_remove +󰕒 md_upload +󰕓 md_usb +󰕔 md_vector_arrange_above +󰕕 md_vector_arrange_below +󰕖 md_vector_circle +󰕗 md_vector_circle_variant +󰕘 md_vector_combine +󰕙 md_vector_curve +󰕚 md_vector_difference +󰕛 md_vector_difference_ab +󰕜 md_vector_difference_ba +󰕝 md_vector_intersection +󰕞 md_vector_line +󰕟 md_vector_point +󰕠 md_vector_polygon +󰕡 md_vector_polyline +󰕢 md_vector_selection +󰕣 md_vector_triangle +󰕤 md_vector_union +󰕥 md_shield_check +󰕦 md_vibrate +󰕧 md_video +󰕨 md_video_off +󰕩 md_video_switch +󰕪 md_view_agenda +󰕫 md_view_array +󰕬 md_view_carousel +󰕭 md_view_column +󰕮 md_view_dashboard +󰕯 md_view_day +󰕰 md_view_grid +󰕱 md_view_headline +󰕲 md_view_list +󰕳 md_view_module +󰕴 md_view_quilt +󰕵 md_view_stream +󰕶 md_view_week +󰕷 md_vimeo +󰕸 md_buffet +󰕹 md_hands_pray +󰕺 md_credit_card_wireless_off +󰕻 md_credit_card_wireless_off_outline +󰕼 md_vlc +󰕽 md_voicemail +󰕾 md_volume_high +󰕿 md_volume_low +󰖀 md_volume_medium +󰖁 md_volume_off +󰖂 md_vpn +󰖃 md_walk +󰖄 md_wallet +󰖅 md_wallet_giftcard +󰖆 md_wallet_membership +󰖇 md_wallet_travel +󰖈 md_wan +󰖉 md_watch +󰖊 md_watch_export +󰖋 md_watch_import +󰖌 md_water +󰖍 md_water_off +󰖎 md_water_percent +󰖏 md_water_pump +󰖐 md_weather_cloudy +󰖑 md_weather_fog +󰖒 md_weather_hail +󰖓 md_weather_lightning +󰖔 md_weather_night +󰖕 md_weather_partly_cloudy +󰖖 md_weather_pouring +󰖗 md_weather_rainy +󰖘 md_weather_snowy +󰖙 md_weather_sunny +󰖚 md_weather_sunset +󰖛 md_weather_sunset_down +󰖜 md_weather_sunset_up +󰖝 md_weather_windy +󰖞 md_weather_windy_variant +󰖟 md_web +󰖠 md_webcam +󰖡 md_weight +󰖢 md_weight_kilogram +󰖣 md_whatsapp +󰖤 md_wheelchair_accessibility +󰖥 md_white_balance_auto +󰖦 md_white_balance_incandescent +󰖧 md_white_balance_iridescent +󰖨 md_white_balance_sunny +󰖩 md_wifi +󰖪 md_wifi_off +󰖫 md_nintendo_wii +󰖬 md_wikipedia +󰖭 md_window_close +󰖮 md_window_closed +󰖯 md_window_maximize +󰖰 md_window_minimize +󰖱 md_window_open +󰖲 md_window_restore +󰖳 md_microsoft_windows +󰖴 md_wordpress +󰖵 md_account_hard_hat +󰖶 md_wrap +󰖷 md_wrench +󰖸 md_contacts_outline +󰖹 md_microsoft_xbox +󰖺 md_microsoft_xbox_controller +󰖻 md_microsoft_xbox_controller_off +󰖼 md_table_furniture +󰖽 md_sort_alphabetical_ascending +󰖾 md_firewire +󰖿 md_sort_alphabetical_descending +󰗀 md_xml +󰗁 md_yeast +󰗂 md_database_refresh +󰗃 md_youtube +󰗄 md_zip_box +󰗅 md_surround_sound +󰗆 md_vector_rectangle +󰗇 md_playlist_check +󰗈 md_format_line_style +󰗉 md_format_line_weight +󰗊 md_translate +󰗋 md_account_voice +󰗌 md_opacity +󱣰 md_near_me +󰗎 md_clock_alert_outline +󰗏 md_human_pregnant +󰗐 md_sticker_circle_outline +󰗑 md_scale_balance +󰗒 md_card_account_details +󰗓 md_account_multiple_minus +󰗔 md_airplane_landing +󰗕 md_airplane_takeoff +󰗖 md_alert_circle_outline +󰗗 md_altimeter +󰗘 md_animation +󰗙 md_book_minus +󰗚 md_book_open_page_variant +󰗛 md_book_plus +󰗜 md_boombox +󰗝 md_bullseye +󰗞 md_comment_remove +󰗟 md_camera_off +󰗠 md_check_circle +󰗡 md_check_circle_outline +󰗢 md_candle +󰗣 md_chart_bubble +󰗤 md_credit_card_off_outline +󰗥 md_cup_off +󰗦 md_copyright +󰗧 md_cursor_text +󰗨 md_delete_forever +󰗩 md_delete_sweep +󰗪 md_dice_d20_outline +󰗫 md_dice_d4_outline +󰗬 md_dice_d8_outline +󰗭 md_dice_d6_outline +󰗮 md_disc +󰗯 md_email_open_outline +󰗰 md_email_variant +󰗱 md_ev_station +󰗲 md_food_fork_drink +󰗳 md_food_off +󰗴 md_format_title +󰗵 md_google_maps +󰗶 md_heart_pulse +󰗷 md_highway +󰗸 md_home_map_marker +󰗹 md_incognito +󰗺 md_kettle +󰗻 md_lock_plus +󰗼 md_exit_to_app +󰗽 md_logout_variant +󰗾 md_music_note_bluetooth +󰗿 md_music_note_bluetooth_off +󰘀 md_page_first +󰘁 md_page_last +󰘂 md_phone_classic +󰘃 md_priority_high +󰘄 md_priority_low +󰘅 md_qqchat +󰘆 md_pool +󰘇 md_rounded_corner +󰘈 md_rowing +󰘉 md_saxophone +󰘊 md_signal_variant +󰘋 md_stack_exchange +󰘌 md_subdirectory_arrow_left +󰘍 md_subdirectory_arrow_right +󰘎 md_form_textbox +󰘏 md_violin +󰘐 md_microsoft_visual_studio +󰘑 md_wechat +󰘒 md_watermark +󰘓 md_file_hidden +󰘔 md_application_outline +󰘕 md_arrow_collapse +󰘖 md_arrow_expand +󰘗 md_bowl_mix +󰘘 md_bridge +󰘙 md_application_edit_outline +󰘚 md_chip +󰘛 md_content_save_settings +󰘜 md_dialpad +󰘝 md_book_alphabet +󰘞 md_format_horizontal_align_center +󰘟 md_format_horizontal_align_left +󰘠 md_format_horizontal_align_right +󰘡 md_format_vertical_align_bottom +󰘢 md_format_vertical_align_center +󰘣 md_format_vertical_align_top +󰘤 md_line_scan +󰘥 md_help_circle_outline +󰘦 md_code_json +󰘧 md_lambda +󰘨 md_matrix +󰘩 md_meteor +󰘪 md_close_circle_multiple +󰘫 md_sigma_lower +󰘬 md_source_branch +󰘭 md_source_merge +󰘮 md_tune +󰘯 md_webhook +󰘰 md_account_settings +󰘱 md_account_details +󰘲 md_apple_keyboard_caps +󰘳 md_apple_keyboard_command +󰘴 md_apple_keyboard_control +󰘵 md_apple_keyboard_option +󰘶 md_apple_keyboard_shift +󰘷 md_box_shadow +󰘸 md_cards +󰘹 md_cards_outline +󰘺 md_cards_playing_outline +󰘻 md_checkbox_multiple_blank_circle +󰘼 md_checkbox_multiple_blank_circle_outline +󰘽 md_checkbox_multiple_marked_circle +󰘾 md_checkbox_multiple_marked_circle_outline +󰘿 md_cloud_sync +󰙀 md_collage +󰙁 md_directions_fork +󰙂 md_eraser_variant +󰙃 md_face_man +󰙄 md_face_man_profile +󰙅 md_file_tree +󰙆 md_format_annotation_plus +󰙇 md_gas_cylinder +󰙈 md_grease_pencil +󰙉 md_human_female +󰙊 md_human_greeting_variant +󰙋 md_human_handsdown +󰙌 md_human_handsup +󰙍 md_human_male +󰙎 md_information_variant +󰙏 md_lead_pencil +󰙐 md_map_marker_minus +󰙑 md_map_marker_plus +󰙒 md_marker +󰙓 md_message_plus +󰙔 md_microscope +󰙕 md_move_resize +󰙖 md_move_resize_variant +󰙗 md_paw_off +󰙘 md_phone_minus +󰙙 md_phone_plus +󰙚 md_pot_steam +󰙛 md_pot_mix +󰙜 md_serial_port +󰙝 md_shape_circle_plus +󰙞 md_shape_polygon_plus +󰙟 md_shape_rectangle_plus +󰙠 md_shape_square_plus +󰙡 md_skip_next_circle +󰙢 md_skip_next_circle_outline +󰙣 md_skip_previous_circle +󰙤 md_skip_previous_circle_outline +󰙥 md_spray +󰙦 md_stop_circle +󰙧 md_stop_circle_outline +󰙨 md_test_tube +󰙩 md_text_shadow +󰙪 md_tune_vertical +󰙫 md_cart_off +󰙬 md_chart_gantt +󰙭 md_chart_scatter_plot_hexbin +󰙮 md_chart_timeline +󰙯 md_discord +󰙰 md_file_restore +󰙱 md_language_c +󰙲 md_language_cpp +󰙳 md_language_xaml +󰙴 md_creation +󰙵 md_application_cog +󰙶 md_credit_card_plus_outline +󰙷 md_pot_mix_outline +󰙸 md_bow_tie +󰙹 md_calendar_range +󰙺 md_currency_usd_off +󰙻 md_flash_red_eye +󰙼 md_oar +󰙽 md_piano +󰙾 md_weather_lightning_rainy +󰙿 md_weather_snowy_rainy +󰚀 md_yin_yang +󰚁 md_tower_beach +󰚂 md_tower_fire +󰚃 md_delete_circle +󰚄 md_dna +󰚅 md_hamburger +󰚆 md_gondola +󰚇 md_inbox +󰚈 md_reorder_horizontal +󰚉 md_reorder_vertical +󰚊 md_shield_home +󰚋 md_tag_heart +󰚌 md_skull +󰚍 md_solid +󰚎 md_alarm_snooze +󰚏 md_baby_carriage +󰚐 md_beaker_outline +󰚑 md_bomb +󰚒 md_calendar_question +󰚓 md_camera_burst +󰚔 md_code_tags_check +󰚕 md_circle_multiple_outline +󰚖 md_crop_rotate +󰚗 md_developer_board +󰚘 md_piano_off +󰚙 md_skate_off +󰚚 md_message_star +󰚛 md_emoticon_dead_outline +󰚜 md_emoticon_excited_outline +󰚝 md_folder_star +󰚞 md_format_color_text +󰚟 md_format_section +󰚠 md_gradient_vertical +󰚡 md_home_outline +󰚢 md_message_bulleted +󰚣 md_message_bulleted_off +󰚤 md_nuke +󰚥 md_power_plug +󰚦 md_power_plug_off +󰚧 md_publish +󰚨 md_credit_card_marker +󰚩 md_robot +󰚪 md_format_rotate_90 +󰚫 md_scanner +󰚬 md_subway +󰚭 md_timer_sand_empty +󰚮 md_transit_transfer +󰚯 md_unity +󰚰 md_update +󰚱 md_watch_vibrate +󰚲 md_angular +󰚳 md_dolby +󰚴 md_emby +󰚵 md_lamp +󰚶 md_menu_down_outline +󰚷 md_menu_up_outline +󰚸 md_note_multiple +󰚹 md_note_multiple_outline +󰚺 md_plex +󰚻 md_shield_airplane +󰚼 md_account_edit +󰚽 md_alert_decagram +󰚾 md_all_inclusive +󰚿 md_angularjs +󰛀 md_arrow_down_box +󰛁 md_arrow_left_box +󰛂 md_arrow_right_box +󰛃 md_arrow_up_box +󰛄 md_asterisk +󰛅 md_bomb_off +󰛆 md_bootstrap +󰛇 md_cards_variant +󰛈 md_clipboard_flow +󰛉 md_close_outline +󰛊 md_coffee_outline +󰛋 md_contacts +󰛌 md_delete_empty +󰛍 md_earth_box +󰛎 md_earth_box_off +󰛏 md_email_alert +󰛐 md_eye_outline +󰛑 md_eye_off_outline +󰛒 md_fast_forward_outline +󰛓 md_feather +󰛔 md_find_replace +󰛕 md_flash_outline +󰛖 md_format_font +󰛗 md_format_page_break +󰛘 md_format_pilcrow +󰛙 md_garage +󰛚 md_garage_open +󰛛 md_card_account_details_star_outline +󰛜 md_google_keep +󰛝 md_snowmobile +󰛞 md_heart_half_full +󰛟 md_heart_half +󰛠 md_heart_half_outline +󰛡 md_hexagon_multiple +󰛢 md_hook +󰛣 md_hook_off +󰛤 md_infinity +󰛥 md_language_swift +󰛦 md_language_typescript +󰛧 md_laptop_off +󰛨 md_lightbulb_on +󰛩 md_lightbulb_on_outline +󰛪 md_lock_pattern +󰛫 md_folder_zip +󰛬 md_magnify_minus_outline +󰛭 md_magnify_plus_outline +󰛮 md_mailbox +󰛯 md_medical_bag +󰛰 md_message_settings +󰛱 md_message_cog +󰛲 md_minus_box_outline +󰛳 md_network +󰛴 md_download_network +󰛵 md_help_network +󰛶 md_upload_network +󰛷 md_npm +󰛸 md_nut +󰛹 md_octagram +󰛺 md_page_layout_body +󰛻 md_page_layout_footer +󰛼 md_page_layout_header +󰛽 md_page_layout_sidebar_left +󰛾 md_page_layout_sidebar_right +󰛿 md_pencil_circle +󰜀 md_pentagon_outline +󰜁 md_pentagon +󰜂 md_pillar +󰜃 md_pistol +󰜄 md_plus_box_outline +󰜅 md_plus_outline +󰜆 md_prescription +󰜇 md_printer_settings +󰜈 md_react +󰜉 md_restart +󰜊 md_rewind_outline +󰜋 md_rhombus +󰜌 md_rhombus_outline +󰜍 md_robot_vacuum +󰜎 md_run +󰜏 md_search_web +󰜐 md_shovel +󰜑 md_shovel_off +󰜒 md_signal_2g +󰜓 md_signal_3g +󰜔 md_signal_4g +󰜕 md_signal_hspa +󰜖 md_signal_hspa_plus +󰜗 md_snowflake +󰜘 md_source_commit +󰜙 md_source_commit_end +󰜚 md_source_commit_end_local +󰜛 md_source_commit_local +󰜜 md_source_commit_next_local +󰜝 md_source_commit_start +󰜞 md_source_commit_start_next_local +󰜟 md_speaker_wireless +󰜠 md_stadium_variant +󰜡 md_svg +󰜢 md_tag_plus +󰜣 md_tag_remove +󰜤 md_ticket_percent +󰜥 md_tilde +󰜦 md_treasure_chest +󰜧 md_truck_trailer +󰜨 md_view_parallel +󰜩 md_view_sequential +󰜪 md_washing_machine +󰜫 md_webpack +󰜬 md_widgets +󰜭 md_nintendo_wiiu +󰜮 md_arrow_down_bold +󰜯 md_arrow_down_bold_box +󰜰 md_arrow_down_bold_box_outline +󰜱 md_arrow_left_bold +󰜲 md_arrow_left_bold_box +󰜳 md_arrow_left_bold_box_outline +󰜴 md_arrow_right_bold +󰜵 md_arrow_right_bold_box +󰜶 md_arrow_right_bold_box_outline +󰜷 md_arrow_up_bold +󰜸 md_arrow_up_bold_box +󰜹 md_arrow_up_bold_box_outline +󰜺 md_cancel +󰜻 md_file_account +󰜼 md_gesture_double_tap +󰜽 md_gesture_swipe_down +󰜾 md_gesture_swipe_left +󰜿 md_gesture_swipe_right +󰝀 md_gesture_swipe_up +󰝁 md_gesture_tap +󰝂 md_gesture_two_double_tap +󰝃 md_gesture_two_tap +󰝄 md_humble_bundle +󰝅 md_kickstarter +󰝆 md_netflix +󰝇 md_microsoft_onenote +󰝈 md_wall_sconce_round +󰝉 md_folder_refresh +󰝊 md_vector_radius +󰝋 md_microsoft_xbox_controller_battery_alert +󰝌 md_microsoft_xbox_controller_battery_empty +󰝍 md_microsoft_xbox_controller_battery_full +󰝎 md_microsoft_xbox_controller_battery_low +󰝏 md_microsoft_xbox_controller_battery_medium +󰝐 md_microsoft_xbox_controller_battery_unknown +󰝑 md_clipboard_plus +󰝒 md_file_plus +󰝓 md_format_align_bottom +󰝔 md_format_align_middle +󰝕 md_format_align_top +󰝖 md_format_list_checks +󰝗 md_format_quote_open +󰝘 md_grid_large +󰝙 md_heart_off +󰝚 md_music +󰝛 md_music_off +󰝜 md_tab_plus +󰝝 md_volume_plus +󰝞 md_volume_minus +󰝟 md_volume_mute +󰝠 md_unfold_less_vertical +󰝡 md_unfold_more_vertical +󰝢 md_taco +󰝣 md_square_outline +󰝤 md_square +󰝥 md_checkbox_blank_circle +󰝦 md_checkbox_blank_circle_outline +󰝧 md_alert_octagram +󰝨 md_atom +󰝩 md_ceiling_light +󰝪 md_chart_bar_stacked +󰝫 md_chart_line_stacked +󰝬 md_decagram +󰝭 md_decagram_outline +󰝮 md_dice_multiple +󰝯 md_dice_d10_outline +󰝰 md_folder_open +󰝱 md_guitar_acoustic +󰝲 md_loading +󰝳 md_lock_reset +󰝴 md_ninja +󰝵 md_octagram_outline +󰝶 md_pencil_circle_outline +󰝷 md_selection_off +󰝸 md_set_all +󰝹 md_set_center +󰝺 md_set_center_right +󰝻 md_set_left +󰝼 md_set_left_center +󰝽 md_set_left_right +󰝾 md_set_none +󰝿 md_set_right +󰞀 md_shield_half_full +󰞁 md_sign_direction +󰞂 md_sign_text +󰞃 md_signal_off +󰞄 md_square_root +󰞅 md_sticker_emoji +󰞆 md_summit +󰞇 md_sword_cross +󰞈 md_truck_fast +󰞉 md_web_check +󰞊 md_cast_off +󰞋 md_help_box +󰞌 md_timer_sand_full +󰞍 md_waves +󰞎 md_alarm_bell +󰞏 md_alarm_light +󰞐 md_video_switch_outline +󰞑 md_check_decagram +󰞒 md_arrow_collapse_down +󰞓 md_arrow_collapse_left +󰞔 md_arrow_collapse_right +󰞕 md_arrow_collapse_up +󰞖 md_arrow_expand_down +󰞗 md_arrow_expand_left +󰞘 md_arrow_expand_right +󰞙 md_arrow_expand_up +󰞚 md_book_lock +󰞛 md_book_lock_open +󰞜 md_bus_articulated_end +󰞝 md_bus_articulated_front +󰞞 md_bus_double_decker +󰞟 md_bus_school +󰞠 md_bus_side +󰞡 md_camera_gopro +󰞢 md_camera_metering_center +󰞣 md_camera_metering_matrix +󰞤 md_camera_metering_partial +󰞥 md_camera_metering_spot +󰞦 md_cannabis +󰞧 md_car_convertible +󰞨 md_car_estate +󰞩 md_car_hatchback +󰞪 md_car_pickup +󰞫 md_car_side +󰞬 md_car_sports +󰞭 md_caravan +󰞮 md_cctv +󰞯 md_chart_donut +󰞰 md_chart_donut_variant +󰞱 md_chart_line_variant +󰞲 md_chili_hot +󰞳 md_chili_medium +󰞴 md_chili_mild +󰞵 md_cloud_braces +󰞶 md_cloud_tags +󰞷 md_console_line +󰞸 md_corn +󰞹 md_folder_zip_outline +󰞺 md_currency_cny +󰞻 md_currency_eth +󰞼 md_currency_jpy +󰞽 md_currency_krw +󰞾 md_currency_sign +󰞿 md_currency_twd +󰟀 md_desktop_classic +󰟁 md_dip_switch +󰟂 md_donkey +󰟃 md_dots_horizontal_circle +󰟄 md_dots_vertical_circle +󰟅 md_ear_hearing +󰟆 md_elephant +󰟇 md_storefront +󰟈 md_food_croissant +󰟉 md_forklift +󰟊 md_fuel +󰟋 md_gesture +󰟌 md_google_analytics +󰟍 md_google_assistant +󰟎 md_headphones_off +󰟏 md_high_definition +󰟐 md_home_assistant +󰟑 md_home_automation +󰟒 md_home_circle +󰟓 md_language_go +󰟔 md_language_r +󰟕 md_lava_lamp +󰟖 md_led_strip +󰟗 md_locker +󰟘 md_locker_multiple +󰟙 md_map_marker_outline +󰟚 md_metronome +󰟛 md_metronome_tick +󰟜 md_micro_sd +󰟝 md_facebook_gaming +󰟞 md_movie_roll +󰟟 md_mushroom +󰟠 md_mushroom_outline +󰟡 md_nintendo_switch +󰟢 md_null +󰟣 md_passport +󰟤 md_molecule_co2 +󰟥 md_pipe +󰟦 md_pipe_disconnected +󰟧 md_power_socket_eu +󰟨 md_power_socket_uk +󰟩 md_power_socket_us +󰟪 md_rice +󰟫 md_ring +󰟬 md_sass +󰟭 md_send_lock +󰟮 md_soy_sauce +󰟯 md_standard_definition +󰟰 md_surround_sound_2_0 +󰟱 md_surround_sound_3_1 +󰟲 md_surround_sound_5_1 +󰟳 md_surround_sound_7_1 +󰟴 md_television_classic +󰟵 md_form_textbox_password +󰟶 md_thought_bubble +󰟷 md_thought_bubble_outline +󰟸 md_trackpad +󰟹 md_ultra_high_definition +󰟺 md_van_passenger +󰟻 md_van_utility +󰟼 md_vanish +󰟽 md_video_3d +󰟾 md_wall +󰟿 md_xmpp +󰠀 md_account_multiple_plus_outline +󰠁 md_account_plus_outline +󰠂 md_credit_card_wireless +󰠃 md_account_music +󰠄 md_atlassian +󰠅 md_microsoft_azure +󰠆 md_basketball +󰠇 md_battery_charging_wireless +󰠈 md_battery_charging_wireless_10 +󰠉 md_battery_charging_wireless_20 +󰠊 md_battery_charging_wireless_30 +󰠋 md_battery_charging_wireless_40 +󰠌 md_battery_charging_wireless_50 +󰠍 md_battery_charging_wireless_60 +󰠎 md_battery_charging_wireless_70 +󰠏 md_battery_charging_wireless_80 +󰠐 md_battery_charging_wireless_90 +󰠑 md_battery_charging_wireless_alert +󰠒 md_battery_charging_wireless_outline +󰠓 md_bitcoin +󰠔 md_briefcase_outline +󰠕 md_cellphone_wireless +󰠖 md_clover +󰠗 md_comment_question +󰠘 md_content_save_outline +󰠙 md_delete_restore +󰠚 md_door +󰠛 md_door_closed +󰠜 md_door_open +󰠝 md_fan_off +󰠞 md_file_percent +󰠟 md_finance +󰠠 md_lightning_bolt_circle +󰠡 md_floor_plan +󰠢 md_forum_outline +󰠣 md_golf +󰠤 md_google_home +󰠥 md_guy_fawkes_mask +󰠦 md_home_account +󰠧 md_home_heart +󰠨 md_hot_tub +󰠩 md_hulu +󰠪 md_ice_cream +󰠫 md_image_off +󰠬 md_karate +󰠭 md_ladybug +󰠮 md_notebook +󰠯 md_phone_return +󰠰 md_poker_chip +󰠱 md_shape +󰠲 md_shape_outline +󰠳 md_ship_wheel +󰠴 md_soccer_field +󰠵 md_table_column +󰠶 md_table_of_contents +󰠷 md_table_row +󰠸 md_table_settings +󰠹 md_television_box +󰠺 md_television_classic_off +󰠻 md_television_off +󰠼 md_tow_truck +󰠽 md_upload_multiple +󰠾 md_video_4k_box +󰠿 md_video_input_antenna +󰡀 md_video_input_component +󰡁 md_video_input_hdmi +󰡂 md_video_input_svideo +󰡃 md_view_dashboard_variant +󰡄 md_vuejs +󰡅 md_xamarin +󰡆 md_human_male_board_poll +󰡇 md_youtube_studio +󰡈 md_youtube_gaming +󰡉 md_account_group +󰡊 md_camera_switch_outline +󰡋 md_airport +󰡌 md_arrow_collapse_horizontal +󰡍 md_arrow_collapse_vertical +󰡎 md_arrow_expand_horizontal +󰡏 md_arrow_expand_vertical +󰡐 md_augmented_reality +󰡑 md_badminton +󰡒 md_baseball +󰡓 md_baseball_bat +󰡔 md_bottle_wine +󰡕 md_check_outline +󰡖 md_checkbox_intermediate +󰡗 md_chess_king +󰡘 md_chess_knight +󰡙 md_chess_pawn +󰡚 md_chess_queen +󰡛 md_chess_rook +󰡜 md_chess_bishop +󰡝 md_clipboard_pulse +󰡞 md_clipboard_pulse_outline +󰡟 md_comment_multiple +󰡠 md_comment_text_multiple +󰡡 md_comment_text_multiple_outline +󰡢 md_crane +󰡣 md_curling +󰡤 md_currency_bdt +󰡥 md_currency_kzt +󰡦 md_database_search +󰡧 md_dice_d12_outline +󰡨 md_docker +󰡩 md_doorbell_video +󰡪 md_ethereum +󰡫 md_eye_plus +󰡬 md_eye_plus_outline +󰡭 md_eye_settings +󰡮 md_eye_settings_outline +󰡯 md_file_question +󰡰 md_folder_network +󰡱 md_function_variant +󰡲 md_garage_alert +󰡳 md_gauge_empty +󰡴 md_gauge_full +󰡵 md_gauge_low +󰡶 md_glass_wine +󰡷 md_graphql +󰡸 md_high_definition_box +󰡹 md_hockey_puck +󰡺 md_hockey_sticks +󰡻 md_home_alert +󰡼 md_image_plus +󰡽 md_jquery +󰡾 md_lifebuoy +󰡿 md_mixed_reality +󰢀 md_nativescript +󰢁 md_onepassword +󰢂 md_patreon +󰢃 md_close_circle_multiple_outline +󰢄 md_peace +󰢅 md_phone_rotate_landscape +󰢆 md_phone_rotate_portrait +󰢇 md_pier +󰢈 md_pier_crane +󰢉 md_pipe_leak +󰢊 md_piston +󰢋 md_play_network +󰢌 md_reminder +󰢍 md_room_service +󰢎 md_salesforce +󰢏 md_shield_account +󰢐 md_human_male_board +󰢑 md_thermostat_box +󰢒 md_tractor +󰢓 md_vector_ellipse +󰢔 md_virtual_reality +󰢕 md_watch_export_variant +󰢖 md_watch_import_variant +󰢗 md_watch_variant +󰢘 md_weather_hurricane +󰢙 md_account_heart +󰢚 md_alien +󰢛 md_anvil +󰢜 md_battery_charging_10 +󰢝 md_battery_charging_50 +󰢞 md_battery_charging_70 +󰢟 md_battery_charging_outline +󰢠 md_bed_empty +󰢡 md_border_all_variant +󰢢 md_border_bottom_variant +󰢣 md_border_left_variant +󰢤 md_border_none_variant +󰢥 md_border_right_variant +󰢦 md_border_top_variant +󰢧 md_calendar_edit +󰢨 md_clipboard_check_outline +󰢩 md_console_network +󰢪 md_file_compare +󰢫 md_fire_truck +󰢬 md_folder_key +󰢭 md_folder_key_network +󰢮 md_expansion_card +󰢯 md_kayaking +󰢰 md_inbox_multiple +󰢱 md_language_lua +󰢲 md_lock_smart +󰢳 md_microphone_minus +󰢴 md_microphone_plus +󰢵 md_palette_swatch +󰢶 md_periodic_table +󰢷 md_pickaxe +󰢸 md_qrcode_edit +󰢹 md_remote_desktop +󰢺 md_sausage +󰢻 md_cog_outline +󰢼 md_signal_cellular_1 +󰢽 md_signal_cellular_2 +󰢾 md_signal_cellular_3 +󰢿 md_signal_cellular_outline +󰣀 md_ssh +󰣁 md_swap_horizontal_variant +󰣂 md_swap_vertical_variant +󰣃 md_tooth +󰣄 md_train_variant +󰣅 md_account_multiple_check +󰣆 md_application +󰣇 md_arch +󰣈 md_axe +󰣉 md_bullseye_arrow +󰣊 md_bus_clock +󰣋 md_camera_account +󰣌 md_camera_image +󰣍 md_car_limousine +󰣎 md_cards_club +󰣏 md_cards_diamond +󰣐 md_heart +󰣑 md_cards_spade +󰣒 md_cellphone_text +󰣓 md_cellphone_message +󰣔 md_chart_multiline +󰣕 md_circle_edit_outline +󰣖 md_cogs +󰣗 md_credit_card_settings_outline +󰣘 md_death_star +󰣙 md_death_star_variant +󰣚 md_debian +󰣛 md_fedora +󰣜 md_file_undo +󰣝 md_floor_lamp +󰣞 md_folder_edit +󰣟 md_format_columns +󰣠 md_freebsd +󰣡 md_gate_and +󰣢 md_gate_nand +󰣣 md_gate_nor +󰣤 md_gate_not +󰣥 md_gate_or +󰣦 md_gate_xnor +󰣧 md_gate_xor +󰣨 md_gentoo +󰣩 md_globe_model +󰣪 md_hammer +󰣫 md_home_lock +󰣬 md_home_lock_open +󰣭 md_linux_mint +󰣮 md_lock_alert +󰣯 md_lock_question +󰣰 md_map_marker_distance +󰣱 md_midi +󰣲 md_midi_port +󰣳 md_nas +󰣴 md_network_strength_1 +󰣵 md_network_strength_1_alert +󰣶 md_network_strength_2 +󰣷 md_network_strength_2_alert +󰣸 md_network_strength_3 +󰣹 md_network_strength_3_alert +󰣺 md_network_strength_4 +󰣻 md_network_strength_4_alert +󰣼 md_network_strength_off +󰣽 md_network_strength_off_outline +󰣾 md_network_strength_outline +󰣿 md_play_speed +󰤀 md_playlist_edit +󰤁 md_power_cycle +󰤂 md_power_off +󰤃 md_power_on +󰤄 md_power_sleep +󰤅 md_power_socket_au +󰤆 md_power_standby +󰤇 md_rabbit +󰤈 md_robot_vacuum_variant +󰤉 md_satellite_uplink +󰤊 md_scanner_off +󰤋 md_book_minus_multiple_outline +󰤌 md_square_edit_outline +󰤍 md_sort_numeric_ascending_variant +󰤎 md_steering_off +󰤏 md_table_search +󰤐 md_tag_minus +󰤑 md_test_tube_empty +󰤒 md_test_tube_off +󰤓 md_ticket_outline +󰤔 md_track_light +󰤕 md_transition +󰤖 md_transition_masked +󰤗 md_tumble_dryer +󰤘 md_file_refresh +󰤙 md_video_account +󰤚 md_video_image +󰤛 md_video_stabilization +󰤜 md_wall_sconce +󰤝 md_wall_sconce_flat +󰤞 md_wall_sconce_round_variant +󰤟 md_wifi_strength_1 +󰤠 md_wifi_strength_1_alert +󰤡 md_wifi_strength_1_lock +󰤢 md_wifi_strength_2 +󰤣 md_wifi_strength_2_alert +󰤤 md_wifi_strength_2_lock +󰤥 md_wifi_strength_3 +󰤦 md_wifi_strength_3_alert +󰤧 md_wifi_strength_3_lock +󰤨 md_wifi_strength_4 +󰤩 md_wifi_strength_4_alert +󰤪 md_wifi_strength_4_lock +󰤫 md_wifi_strength_alert_outline +󰤬 md_wifi_strength_lock_outline +󰤭 md_wifi_strength_off +󰤮 md_wifi_strength_off_outline +󰤯 md_wifi_strength_outline +󰤰 md_pin_off_outline +󰤱 md_pin_outline +󰤲 md_share_outline +󰤳 md_trackpad_lock +󰤴 md_account_box_multiple +󰤵 md_account_search_outline +󰤶 md_account_filter +󰤷 md_angle_acute +󰤸 md_angle_obtuse +󰤹 md_angle_right +󰤺 md_animation_play +󰤻 md_arrow_split_horizontal +󰤼 md_arrow_split_vertical +󰤽 md_audio_video +󰤾 md_battery_10_bluetooth +󰤿 md_battery_20_bluetooth +󰥀 md_battery_30_bluetooth +󰥁 md_battery_40_bluetooth +󰥂 md_battery_50_bluetooth +󰥃 md_battery_60_bluetooth +󰥄 md_battery_70_bluetooth +󰥅 md_battery_80_bluetooth +󰥆 md_battery_90_bluetooth +󰥇 md_battery_alert_bluetooth +󰥈 md_battery_bluetooth +󰥉 md_battery_bluetooth_variant +󰥊 md_battery_unknown_bluetooth +󰥋 md_dharmachakra +󰥌 md_calendar_search +󰥍 md_cellphone_remove +󰥎 md_cellphone_key +󰥏 md_cellphone_lock +󰥐 md_cellphone_off +󰥑 md_cellphone_cog +󰥒 md_cellphone_sound +󰥓 md_cross +󰥔 md_clock +󰥕 md_clock_alert +󰥖 md_cloud_search +󰥗 md_cloud_search_outline +󰥘 md_cordova +󰥙 md_cryengine +󰥚 md_cupcake +󰥛 md_sine_wave +󰥜 md_current_dc +󰥝 md_database_import +󰥞 md_database_export +󰥟 md_desk_lamp +󰥠 md_disc_player +󰥡 md_email_search +󰥢 md_email_search_outline +󰥣 md_exponent +󰥤 md_exponent_box +󰥥 md_file_download +󰥦 md_file_download_outline +󰥧 md_firebase +󰥨 md_folder_search +󰥩 md_folder_search_outline +󰥪 md_format_list_checkbox +󰥫 md_fountain +󰥬 md_google_fit +󰥭 md_greater_than +󰥮 md_greater_than_or_equal +󰥯 md_hard_hat +󰥰 md_headphones_bluetooth +󰥱 md_heart_circle +󰥲 md_heart_circle_outline +󰥳 md_om +󰥴 md_home_minus +󰥵 md_home_plus +󰥶 md_image_outline +󰥷 md_image_search +󰥸 md_image_search_outline +󰥹 md_star_crescent +󰥺 md_star_david +󰥻 md_keyboard_outline +󰥼 md_less_than +󰥽 md_less_than_or_equal +󰥾 md_light_switch +󰥿 md_lock_clock +󰦀 md_magnify_close +󰦁 md_map_minus +󰦂 md_map_outline +󰦃 md_map_plus +󰦄 md_map_search +󰦅 md_map_search_outline +󰦆 md_material_design +󰦇 md_medal +󰦈 md_microsoft_dynamics_365 +󰦉 md_monitor_cellphone +󰦊 md_monitor_cellphone_star +󰦋 md_mouse_bluetooth +󰦌 md_muffin +󰦍 md_not_equal +󰦎 md_not_equal_variant +󰦏 md_order_bool_ascending_variant +󰦐 md_order_bool_descending_variant +󰦑 md_office_building +󰦒 md_plus_minus +󰦓 md_plus_minus_box +󰦔 md_podcast +󰦕 md_progress_check +󰦖 md_progress_clock +󰦗 md_progress_download +󰦘 md_progress_upload +󰦙 md_qi +󰦚 md_record_player +󰦛 md_restore +󰦜 md_shield_off_outline +󰦝 md_shield_lock +󰦞 md_shield_off +󰦟 md_set_top_box +󰦠 md_shower +󰦡 md_shower_head +󰦢 md_speaker_bluetooth +󰦣 md_square_root_box +󰦤 md_star_circle_outline +󰦥 md_star_face +󰦦 md_table_merge_cells +󰦧 md_tablet_cellphone +󰦨 md_text +󰦩 md_text_short +󰦪 md_text_long +󰦫 md_toilet +󰦬 md_toolbox +󰦭 md_toolbox_outline +󰦮 md_tournament +󰦯 md_two_factor_authentication +󰦰 md_umbrella_closed +󰦱 md_unreal +󰦲 md_video_minus +󰦳 md_video_plus +󰦴 md_volleyball +󰦵 md_weight_pound +󰦶 md_whistle +󰦷 md_arrow_bottom_left_bold_outline +󰦸 md_arrow_bottom_left_thick +󰦹 md_arrow_bottom_right_bold_outline +󰦺 md_arrow_bottom_right_thick +󰦻 md_arrow_decision +󰦼 md_arrow_decision_auto +󰦽 md_arrow_decision_auto_outline +󰦾 md_arrow_decision_outline +󰦿 md_arrow_down_bold_outline +󰧀 md_arrow_left_bold_outline +󰧁 md_arrow_left_right_bold_outline +󰧂 md_arrow_right_bold_outline +󰧃 md_arrow_top_left_bold_outline +󰧄 md_arrow_top_left_thick +󰧅 md_arrow_top_right_bold_outline +󰧆 md_arrow_top_right_thick +󰧇 md_arrow_up_bold_outline +󰧈 md_arrow_up_down_bold_outline +󰧉 md_ballot +󰧊 md_ballot_outline +󰧋 md_betamax +󰧌 md_bookmark_minus +󰧍 md_bookmark_minus_outline +󰧎 md_bookmark_off +󰧏 md_bookmark_off_outline +󰧐 md_braille +󰧑 md_brain +󰧒 md_calendar_heart +󰧓 md_calendar_star +󰧔 md_cassette +󰧕 md_cellphone_arrow_down +󰧖 md_chevron_down_box +󰧗 md_chevron_down_box_outline +󰧘 md_chevron_left_box +󰧙 md_chevron_left_box_outline +󰧚 md_chevron_right_box +󰧛 md_chevron_right_box_outline +󰧜 md_chevron_up_box +󰧝 md_chevron_up_box_outline +󰧞 md_circle_medium +󰧟 md_circle_small +󰧠 md_cloud_alert +󰧡 md_comment_arrow_left +󰧢 md_comment_arrow_left_outline +󰧣 md_comment_arrow_right +󰧤 md_comment_arrow_right_outline +󰧥 md_comment_plus +󰧦 md_currency_php +󰧧 md_delete_outline +󰧨 md_desktop_mac_dashboard +󰧩 md_download_multiple +󰧪 md_eight_track +󰧫 md_email_plus +󰧬 md_email_plus_outline +󰧭 md_text_box_outline +󰧮 md_file_document_outline +󰧯 md_floppy_variant +󰧰 md_flower_outline +󰧱 md_flower_tulip +󰧲 md_flower_tulip_outline +󰧳 md_format_font_size_decrease +󰧴 md_format_font_size_increase +󰧵 md_ghost_off +󰧶 md_google_lens +󰧷 md_google_spreadsheet +󰧸 md_image_move +󰧹 md_keyboard_settings +󰧺 md_keyboard_settings_outline +󰧻 md_knife +󰧼 md_knife_military +󰧽 md_layers_off_outline +󰧾 md_layers_outline +󰧿 md_lighthouse +󰨀 md_lighthouse_on +󰨁 md_map_legend +󰨂 md_menu_left_outline +󰨃 md_menu_right_outline +󰨄 md_message_alert_outline +󰨅 md_mini_sd +󰨆 md_minidisc +󰨇 md_monitor_dashboard +󰨈 md_pirate +󰨉 md_pokemon_go +󰨊 md_powershell +󰨋 md_printer_wireless +󰨌 md_quality_low +󰨍 md_quality_medium +󰨎 md_reflect_horizontal +󰨏 md_reflect_vertical +󰨐 md_rhombus_medium +󰨑 md_rhombus_split +󰨒 md_shield_account_outline +󰨓 md_square_medium +󰨔 md_square_medium_outline +󰨕 md_square_small +󰨖 md_subtitles +󰨗 md_subtitles_outline +󰨘 md_table_border +󰨙 md_toggle_switch_off_outline +󰨚 md_toggle_switch_outline +󰨛 md_vhs +󰨜 md_video_vintage +󰨝 md_view_dashboard_outline +󰨞 md_microsoft_visual_studio_code +󰨟 md_vote +󰨠 md_vote_outline +󰨡 md_microsoft_windows_classic +󰨢 md_microsoft_xbox_controller_battery_charging +󰨣 md_zip_disk +󰨤 md_aspect_ratio +󰨥 md_babel +󰨦 md_balloon +󰨧 md_bank_transfer +󰨨 md_bank_transfer_in +󰨩 md_bank_transfer_out +󰨪 md_briefcase_minus +󰨫 md_briefcase_plus +󰨬 md_briefcase_remove +󰨭 md_briefcase_search +󰨮 md_bug_check +󰨯 md_bug_check_outline +󰨰 md_bug_outline +󰨱 md_calendar_alert +󰨲 md_calendar_multiselect +󰨳 md_calendar_week +󰨴 md_calendar_week_begin +󰨵 md_cellphone_screenshot +󰨶 md_city_variant +󰨷 md_city_variant_outline +󰨸 md_clipboard_text_outline +󰨹 md_cloud_question +󰨺 md_comment_eye +󰨻 md_comment_eye_outline +󰨼 md_comment_search +󰨽 md_comment_search_outline +󰨾 md_contain +󰨿 md_contain_end +󰩀 md_contain_start +󰩁 md_dlna +󰩂 md_doctor +󰩃 md_dog +󰩄 md_dog_side +󰩅 md_ear_hearing_off +󰩆 md_engine_off +󰩇 md_engine_off_outline +󰩈 md_exit_run +󰩉 md_feature_search +󰩊 md_feature_search_outline +󰩋 md_file_alert +󰩌 md_file_alert_outline +󰩍 md_file_upload +󰩎 md_file_upload_outline +󰩏 md_hand_front_right +󰩐 md_hand_okay +󰩑 md_hand_peace +󰩒 md_hand_peace_variant +󰩓 md_hand_pointing_down +󰩔 md_hand_pointing_left +󰩕 md_hand_pointing_up +󰩖 md_heart_multiple +󰩗 md_heart_multiple_outline +󰩘 md_horseshoe +󰩙 md_human_female_boy +󰩚 md_human_female_female +󰩛 md_human_female_girl +󰩜 md_human_male_boy +󰩝 md_human_male_girl +󰩞 md_human_male_male +󰩟 md_ip +󰩠 md_ip_network +󰩡 md_litecoin +󰩢 md_magnify_minus_cursor +󰩣 md_magnify_plus_cursor +󰩤 md_menu_swap +󰩥 md_menu_swap_outline +󰩦 md_puzzle_outline +󰩧 md_registered_trademark +󰩨 md_resize +󰩩 md_router_wireless_settings +󰩪 md_safe +󰩫 md_scissors_cutting +󰩬 md_select_drag +󰩭 md_selection_drag +󰩮 md_settings_helper +󰩯 md_signal_5g +󰩰 md_silverware_fork_knife +󰩱 md_smog +󰩲 md_solar_power +󰩳 md_star_box +󰩴 md_star_box_outline +󰩵 md_table_plus +󰩶 md_table_remove +󰩷 md_target_variant +󰩸 md_trademark +󰩹 md_trash_can +󰩺 md_trash_can_outline +󰩻 md_tshirt_crew +󰩼 md_tshirt_v +󰩽 md_zodiac_aquarius +󰩾 md_zodiac_aries +󰩿 md_zodiac_cancer +󰪀 md_zodiac_capricorn +󰪁 md_zodiac_gemini +󰪂 md_zodiac_leo +󰪃 md_zodiac_libra +󰪄 md_zodiac_pisces +󰪅 md_zodiac_sagittarius +󰪆 md_zodiac_scorpio +󰪇 md_zodiac_taurus +󰪈 md_zodiac_virgo +󰪉 md_account_child +󰪊 md_account_child_circle +󰪋 md_account_supervisor +󰪌 md_account_supervisor_circle +󰪍 md_ampersand +󰪎 md_web_off +󰪏 md_animation_outline +󰪐 md_animation_play_outline +󰪑 md_bell_off_outline +󰪒 md_bell_plus_outline +󰪓 md_bell_sleep_outline +󰪔 md_book_minus_multiple +󰪕 md_book_plus_multiple +󰪖 md_book_remove_multiple +󰪗 md_book_remove +󰪘 md_briefcase_edit +󰪙 md_bus_alert +󰪚 md_calculator_variant +󰪛 md_caps_lock +󰪜 md_cash_refund +󰪝 md_checkbook +󰪞 md_circle_slice_1 +󰪟 md_circle_slice_2 +󰪠 md_circle_slice_3 +󰪡 md_circle_slice_4 +󰪢 md_circle_slice_5 +󰪣 md_circle_slice_6 +󰪤 md_circle_slice_7 +󰪥 md_circle_slice_8 +󰪦 md_collapse_all +󰪧 md_collapse_all_outline +󰪨 md_credit_card_refund_outline +󰪩 md_database_check +󰪪 md_database_lock +󰪫 md_desktop_tower_monitor +󰪬 md_dishwasher +󰪭 md_dog_service +󰪮 md_dot_net +󰪯 md_egg +󰪰 md_egg_easter +󰪱 md_email_check +󰪲 md_email_check_outline +󰪳 md_et +󰪴 md_expand_all +󰪵 md_expand_all_outline +󰪶 md_file_cabinet +󰪷 md_text_box_multiple +󰪸 md_text_box_multiple_outline +󰪹 md_file_move +󰪺 md_folder_clock +󰪻 md_folder_clock_outline +󰪼 md_format_annotation_minus +󰪽 md_gesture_pinch +󰪾 md_gesture_spread +󰪿 md_gesture_swipe_horizontal +󰫀 md_gesture_swipe_vertical +󰫁 md_hail +󰫂 md_helicopter +󰫃 md_hexagon_slice_1 +󰫄 md_hexagon_slice_2 +󰫅 md_hexagon_slice_3 +󰫆 md_hexagon_slice_4 +󰫇 md_hexagon_slice_5 +󰫈 md_hexagon_slice_6 +󰫉 md_hexagram +󰫊 md_hexagram_outline +󰫋 md_label_off +󰫌 md_label_off_outline +󰫍 md_label_variant +󰫎 md_label_variant_outline +󰫏 md_language_ruby_on_rails +󰫐 md_laravel +󰫑 md_mastodon +󰫒 md_sort_numeric_descending_variant +󰫓 md_minus_circle_multiple_outline +󰫔 md_music_circle_outline +󰫕 md_pinwheel +󰫖 md_pinwheel_outline +󰫗 md_radiator_disabled +󰫘 md_radiator_off +󰫙 md_select_compare +󰫚 md_shield_plus +󰫛 md_shield_plus_outline +󰫜 md_shield_remove +󰫝 md_shield_remove_outline +󰫞 md_book_plus_multiple_outline +󰫟 md_sina_weibo +󰫠 md_spray_bottle +󰫡 md_squeegee +󰫢 md_star_four_points +󰫣 md_star_four_points_outline +󰫤 md_star_three_points +󰫥 md_star_three_points_outline +󰫦 md_symfony +󰫧 md_variable +󰫨 md_vector_bezier +󰫩 md_wiper +󰫪 md_z_wave +󰫫 md_zend +󰫬 md_account_minus_outline +󰫭 md_account_remove_outline +󰫮 md_alpha_a +󰫯 md_alpha_b +󰫰 md_alpha_c +󰫱 md_alpha_d +󰫲 md_alpha_e +󰫳 md_alpha_f +󰫴 md_alpha_g +󰫵 md_alpha_h +󱂈 md_alpha_i +󰫷 md_alpha_j +󰫸 md_alpha_k +󱎦 md_alpha_l +󰫺 md_alpha_m +󰫻 md_alpha_n +󰬹 md_alpha_o +󰫽 md_alpha_p +󰫾 md_alpha_q +󰫿 md_alpha_r +󰬀 md_alpha_s +󰬁 md_alpha_t +󰬂 md_alpha_u +󱂌 md_alpha_v +󰬄 md_alpha_w +󱂑 md_alpha_x +󰬆 md_alpha_y +󰬇 md_alpha_z +󰬈 md_alpha_a_box +󰬉 md_alpha_b_box +󰬊 md_alpha_c_box +󰬋 md_alpha_d_box +󰬌 md_alpha_e_box +󰬍 md_alpha_f_box +󰬎 md_alpha_g_box +󰬏 md_alpha_h_box +󰬐 md_alpha_i_box +󰬑 md_alpha_j_box +󰬒 md_alpha_k_box +󰬓 md_alpha_l_box +󰬔 md_alpha_m_box +󰬕 md_alpha_n_box +󰬖 md_alpha_o_box +󰬗 md_alpha_p_box +󰬘 md_alpha_q_box +󰬙 md_alpha_r_box +󰬚 md_alpha_s_box +󰬛 md_alpha_t_box +󰬜 md_alpha_u_box +󰬝 md_alpha_v_box +󰬞 md_alpha_w_box +󰬟 md_alpha_x_box +󰬠 md_alpha_y_box +󰬡 md_alpha_z_box +󰬢 md_bulldozer +󰬣 md_bullhorn_outline +󰬤 md_calendar_export +󰬥 md_calendar_import +󰬦 md_chevron_down_circle +󰬧 md_chevron_down_circle_outline +󰬨 md_chevron_left_circle +󰬩 md_chevron_left_circle_outline +󰬪 md_chevron_right_circle +󰬫 md_chevron_right_circle_outline +󰬬 md_chevron_up_circle +󰬭 md_chevron_up_circle_outline +󰬮 md_content_save_settings_outline +󰬯 md_crystal_ball +󰬰 md_ember +󰬱 md_facebook_workplace +󰬲 md_file_replace +󰬳 md_file_replace_outline +󰬴 md_format_letter_case +󰬵 md_format_letter_case_lower +󰬶 md_format_letter_case_upper +󰬷 md_language_java +󰬸 md_circle_multiple +󰬹 md_alpha_o +󰬺 md_numeric_1 +󰬻 md_numeric_2 +󰬼 md_numeric_3 +󰬽 md_numeric_4 +󰬾 md_numeric_5 +󰬿 md_numeric_6 +󰭀 md_numeric_7 +󰭁 md_numeric_8 +󰭂 md_numeric_9 +󰭃 md_origin +󰭄 md_resistor +󰭅 md_resistor_nodes +󰭆 md_robot_industrial +󰭇 md_shoe_formal +󰭈 md_shoe_heel +󰭉 md_silo +󰭊 md_box_cutter_off +󰭋 md_tab_minus +󰭌 md_tab_remove +󰭍 md_tape_measure +󰭎 md_telescope +󰭏 md_yahoo +󰭐 md_account_alert_outline +󰭑 md_account_arrow_left +󰭒 md_account_arrow_left_outline +󰭓 md_account_arrow_right +󰭔 md_account_arrow_right_outline +󰭕 md_account_circle_outline +󰭖 md_account_clock +󰭗 md_account_clock_outline +󰭘 md_account_group_outline +󰭙 md_account_question +󰭚 md_account_question_outline +󰭛 md_artstation +󰭜 md_backspace_outline +󰭝 md_barley_off +󰭞 md_barn +󰭟 md_bat +󰭠 md_application_settings +󰭡 md_billiards +󰭢 md_billiards_rack +󰭣 md_book_open_outline +󰭤 md_book_outline +󰭥 md_boxing_glove +󰭦 md_calendar_blank_outline +󰭧 md_calendar_outline +󰭨 md_calendar_range_outline +󰭩 md_camera_control +󰭪 md_camera_enhance_outline +󰭫 md_car_door +󰭬 md_car_electric +󰭭 md_car_key +󰭮 md_car_multiple +󰭯 md_card +󰭰 md_card_bulleted +󰭱 md_card_bulleted_off +󰭲 md_card_bulleted_off_outline +󰭳 md_card_bulleted_outline +󰭴 md_card_bulleted_settings +󰭵 md_card_bulleted_settings_outline +󰭶 md_card_outline +󰭷 md_card_text +󰭸 md_card_text_outline +󰭹 md_chat +󰭺 md_chat_alert +󰭻 md_chat_processing +󰭼 md_chef_hat +󰭽 md_cloud_download_outline +󰭾 md_cloud_upload_outline +󰭿 md_coffin +󰮀 md_compass_off +󰮁 md_compass_off_outline +󰮂 md_controller_classic +󰮃 md_controller_classic_outline +󰮄 md_cube_scan +󰮅 md_currency_brl +󰮆 md_database_edit +󰮇 md_deathly_hallows +󰮈 md_delete_circle_outline +󰮉 md_delete_forever_outline +󰮊 md_diamond +󰮋 md_diamond_outline +󰮌 md_dns_outline +󰮍 md_dots_horizontal_circle_outline +󰮎 md_dots_vertical_circle_outline +󰮏 md_download_outline +󰮐 md_drag_variant +󰮑 md_eject_outline +󰮒 md_email_mark_as_unread +󰮓 md_export_variant +󰮔 md_eye_circle +󰮕 md_eye_circle_outline +󰮖 md_face_man_outline +󰮗 md_file_find_outline +󰮘 md_file_remove +󰮙 md_flag_minus +󰮚 md_flag_plus +󰮛 md_flag_remove +󰮜 md_folder_account_outline +󰮝 md_folder_plus_outline +󰮞 md_folder_remove_outline +󰮟 md_folder_star_outline +󰮠 md_gitlab +󰮡 md_gog +󰮢 md_grave_stone +󰮣 md_halloween +󰮤 md_hat_fedora +󰮥 md_help_rhombus +󰮦 md_help_rhombus_outline +󰮧 md_home_variant_outline +󰮨 md_inbox_multiple_outline +󰮩 md_library_shelves +󰮪 md_mapbox +󰮫 md_menu_open +󰮬 md_molecule +󰮭 md_one_up +󰮮 md_open_source_initiative +󰮯 md_pac_man +󰮰 md_page_next +󰮱 md_page_next_outline +󰮲 md_page_previous +󰮳 md_page_previous_outline +󰮴 md_pan +󰮵 md_pan_bottom_left +󰮶 md_pan_bottom_right +󰮷 md_pan_down +󰮸 md_pan_horizontal +󰮹 md_pan_left +󰮺 md_pan_right +󰮻 md_pan_top_left +󰮼 md_pan_top_right +󰮽 md_pan_up +󰮾 md_pan_vertical +󰮿 md_pumpkin +󰯀 md_rollupjs +󰯁 md_script +󰯂 md_script_text +󰯃 md_script_text_outline +󰯄 md_shield_key +󰯅 md_shield_key_outline +󰯆 md_skull_crossbones +󰯇 md_skull_crossbones_outline +󰯈 md_skull_outline +󰯉 md_space_invaders +󰯊 md_spider_web +󰯋 md_view_split_horizontal +󰯌 md_view_split_vertical +󰯍 md_swap_horizontal_bold +󰯎 md_swap_vertical_bold +󰯏 md_tag_heart_outline +󰯐 md_target_account +󰯑 md_timeline +󰯒 md_timeline_outline +󰯓 md_timeline_text +󰯔 md_timeline_text_outline +󰯕 md_tooltip_image_outline +󰯖 md_tooltip_plus +󰯗 md_tooltip_text_outline +󰯘 md_train_car +󰯙 md_triforce +󰯚 md_ubisoft +󰯛 md_video_off_outline +󰯜 md_video_outline +󰯝 md_wallet_outline +󰯞 md_waze +󰯟 md_wrap_disabled +󰯠 md_wrench_outline +󰯡 md_access_point_network_off +󰯢 md_account_check_outline +󰯣 md_account_heart_outline +󰯤 md_account_key_outline +󰯥 md_account_multiple_minus_outline +󰯦 md_account_network_outline +󰯧 md_account_off_outline +󰯨 md_account_star_outline +󰯩 md_airbag +󰯪 md_alarm_light_outline +󰯫 md_alpha_a_box_outline +󰯬 md_alpha_a_circle +󰯭 md_alpha_a_circle_outline +󰯮 md_alpha_b_box_outline +󰯯 md_alpha_b_circle +󰯰 md_alpha_b_circle_outline +󰯱 md_alpha_c_box_outline +󰯲 md_alpha_c_circle +󰯳 md_alpha_c_circle_outline +󰯴 md_alpha_d_box_outline +󰯵 md_alpha_d_circle +󰯶 md_alpha_d_circle_outline +󰯷 md_alpha_e_box_outline +󰯸 md_alpha_e_circle +󰯹 md_alpha_e_circle_outline +󰯺 md_alpha_f_box_outline +󰯻 md_alpha_f_circle +󰯼 md_alpha_f_circle_outline +󰯽 md_alpha_g_box_outline +󰯾 md_alpha_g_circle +󰯿 md_alpha_g_circle_outline +󰰀 md_alpha_h_box_outline +󰰁 md_alpha_h_circle +󰰂 md_alpha_h_circle_outline +󰰃 md_alpha_i_box_outline +󰰄 md_alpha_i_circle +󰰅 md_alpha_i_circle_outline +󰰆 md_alpha_j_box_outline +󰰇 md_alpha_j_circle +󰰈 md_alpha_j_circle_outline +󰰉 md_alpha_k_box_outline +󰰊 md_alpha_k_circle +󰰋 md_alpha_k_circle_outline +󰰌 md_alpha_l_box_outline +󰰍 md_alpha_l_circle +󰰎 md_alpha_l_circle_outline +󰰏 md_alpha_m_box_outline +󰰐 md_alpha_m_circle +󰰑 md_alpha_m_circle_outline +󰰒 md_alpha_n_box_outline +󰰓 md_alpha_n_circle +󰰔 md_alpha_n_circle_outline +󰰕 md_alpha_o_box_outline +󰲞 md_alpha_o_circle +󰲟 md_alpha_o_circle_outline +󰰘 md_alpha_p_box_outline +󰰙 md_alpha_p_circle +󰰚 md_alpha_p_circle_outline +󰰛 md_alpha_q_box_outline +󰰜 md_alpha_q_circle +󰰝 md_alpha_q_circle_outline +󰰞 md_alpha_r_box_outline +󰰟 md_alpha_r_circle +󰰠 md_alpha_r_circle_outline +󰰡 md_alpha_s_box_outline +󰰢 md_alpha_s_circle +󰰣 md_alpha_s_circle_outline +󰰤 md_alpha_t_box_outline +󰰥 md_alpha_t_circle +󰰦 md_alpha_t_circle_outline +󰰧 md_alpha_u_box_outline +󰰨 md_alpha_u_circle +󰰩 md_alpha_u_circle_outline +󰰪 md_alpha_v_box_outline +󰰫 md_alpha_v_circle +󰰬 md_alpha_v_circle_outline +󰰭 md_alpha_w_box_outline +󰰮 md_alpha_w_circle +󰰯 md_alpha_w_circle_outline +󰰰 md_alpha_x_box_outline +󰰱 md_alpha_x_circle +󰰲 md_alpha_x_circle_outline +󰰳 md_alpha_y_box_outline +󰰴 md_alpha_y_circle +󰰵 md_alpha_y_circle_outline +󰰶 md_alpha_z_box_outline +󰰷 md_alpha_z_circle +󰰸 md_alpha_z_circle_outline +󰰹 md_ballot_recount +󰰺 md_ballot_recount_outline +󰰻 md_basketball_hoop +󰰼 md_basketball_hoop_outline +󰰽 md_briefcase_download_outline +󰰾 md_briefcase_edit_outline +󰰿 md_briefcase_minus_outline +󰱀 md_briefcase_plus_outline +󰱁 md_briefcase_remove_outline +󰱂 md_briefcase_search_outline +󰱃 md_briefcase_upload_outline +󰱄 md_calendar_check_outline +󰱅 md_calendar_remove_outline +󰱆 md_calendar_text_outline +󰱇 md_car_brake_abs +󰱈 md_car_brake_alert +󰱉 md_car_esp +󰱊 md_car_light_dimmed +󰱋 md_car_light_fog +󰱌 md_car_light_high +󰱍 md_car_tire_alert +󰱎 md_cart_arrow_right +󰱏 md_charity +󰱐 md_chart_bell_curve +󰱑 md_checkbox_multiple_outline +󰱒 md_checkbox_outline +󰱓 md_check_network +󰱔 md_check_network_outline +󰱕 md_clipboard_account_outline +󰱖 md_clipboard_arrow_down_outline +󰱗 md_clipboard_arrow_up +󰱘 md_clipboard_arrow_up_outline +󰱙 md_clipboard_play +󰱚 md_clipboard_play_outline +󰱛 md_clipboard_text_play +󰱜 md_clipboard_text_play_outline +󰱝 md_close_box_multiple +󰱞 md_close_box_multiple_outline +󰱟 md_close_network_outline +󰱠 md_console_network_outline +󰱡 md_currency_ils +󰱢 md_delete_sweep_outline +󰱣 md_diameter +󰱤 md_diameter_outline +󰱥 md_diameter_variant +󰱦 md_download_network_outline +󰱧 md_dump_truck +󰱨 md_emoticon +󰱩 md_emoticon_angry +󰱪 md_emoticon_angry_outline +󰱫 md_emoticon_cool +󰱬 md_emoticon_cry +󰱭 md_emoticon_cry_outline +󰱮 md_emoticon_dead +󰱯 md_emoticon_devil +󰱰 md_emoticon_excited +󰱱 md_emoticon_happy +󰱲 md_emoticon_kiss +󰱳 md_emoticon_kiss_outline +󰱴 md_emoticon_neutral +󰱵 md_emoticon_poop_outline +󰱶 md_emoticon_sad +󰱷 md_emoticon_tongue_outline +󰱸 md_emoticon_wink +󰱹 md_emoticon_wink_outline +󰱺 md_eslint +󰱻 md_face_recognition +󰱼 md_file_search +󰱽 md_file_search_outline +󰱾 md_file_table +󰱿 md_file_table_outline +󰲀 md_folder_key_network_outline +󰲁 md_folder_network_outline +󰲂 md_folder_text +󰲃 md_folder_text_outline +󰲄 md_food_apple_outline +󰲅 md_fuse +󰲆 md_fuse_blade +󰲇 md_google_ads +󰲈 md_google_street_view +󰲉 md_hazard_lights +󰲊 md_help_network_outline +󰲋 md_application_brackets +󰲌 md_application_brackets_outline +󰲍 md_image_size_select_actual +󰲎 md_image_size_select_large +󰲏 md_image_size_select_small +󰲐 md_ip_network_outline +󰲑 md_ipod +󰲒 md_language_haskell +󰲓 md_leaf_maple +󰲔 md_link_plus +󰲕 md_map_marker_check +󰲖 md_math_cos +󰲗 md_math_sin +󰲘 md_math_tan +󰲙 md_microwave +󰲚 md_minus_network_outline +󰲛 md_network_off +󰲜 md_network_off_outline +󰲝 md_network_outline +󰲞 md_alpha_o_circle +󰲟 md_alpha_o_circle_outline +󰲠 md_numeric_1_circle +󰲡 md_numeric_1_circle_outline +󰲢 md_numeric_2_circle +󰲣 md_numeric_2_circle_outline +󰲤 md_numeric_3_circle +󰲥 md_numeric_3_circle_outline +󰲦 md_numeric_4_circle +󰲧 md_numeric_4_circle_outline +󰲨 md_numeric_5_circle +󰲩 md_numeric_5_circle_outline +󰲪 md_numeric_6_circle +󰲫 md_numeric_6_circle_outline +󰲬 md_numeric_7_circle +󰲭 md_numeric_7_circle_outline +󰲮 md_numeric_8_circle +󰲯 md_numeric_8_circle_outline +󰲰 md_numeric_9_circle +󰲱 md_numeric_9_circle_outline +󰲲 md_numeric_9_plus_circle +󰲳 md_numeric_9_plus_circle_outline +󰲴 md_parachute +󰲵 md_parachute_outline +󰲶 md_pencil_outline +󰲷 md_play_network_outline +󰲸 md_playlist_music +󰲹 md_playlist_music_outline +󰲺 md_plus_network_outline +󰲻 md_postage_stamp +󰲼 md_progress_alert +󰲽 md_progress_wrench +󰲾 md_radio_am +󰲿 md_radio_fm +󰳀 md_radius +󰳁 md_radius_outline +󰳂 md_ruler_square +󰳃 md_seat +󰳄 md_seat_outline +󰳅 md_seatbelt +󰳆 md_sheep +󰳇 md_shield_airplane_outline +󰳈 md_shield_check_outline +󰳉 md_shield_cross +󰳊 md_shield_cross_outline +󰳋 md_shield_home_outline +󰳌 md_shield_lock_outline +󰳍 md_sort_variant_lock +󰳎 md_sort_variant_lock_open +󰳏 md_source_repository +󰳐 md_source_repository_multiple +󰳑 md_spa +󰳒 md_spa_outline +󰳓 md_toaster_oven +󰳔 md_truck_check +󰳕 md_turnstile +󰳖 md_turnstile_outline +󰳗 md_turtle +󰳘 md_upload_network_outline +󰳙 md_vibrate_off +󰳚 md_watch_vibrate_off +󰳛 md_arrow_down_circle +󰳜 md_arrow_down_circle_outline +󰳝 md_arrow_left_circle +󰳞 md_arrow_left_circle_outline +󰳟 md_arrow_right_circle +󰳠 md_arrow_right_circle_outline +󰳡 md_arrow_up_circle +󰳢 md_arrow_up_circle_outline +󰳣 md_account_tie +󰳤 md_alert_box_outline +󰳥 md_alert_decagram_outline +󰳦 md_alert_octagon_outline +󰳧 md_alert_octagram_outline +󰳨 md_ammunition +󰳩 md_account_music_outline +󰳪 md_beaker +󰳫 md_blender +󰳬 md_blood_bag +󰳭 md_cross_bolnisi +󰳮 md_bread_slice +󰳯 md_bread_slice_outline +󰳰 md_briefcase_account +󰳱 md_briefcase_account_outline +󰳲 md_brightness_percent +󰳳 md_bullet +󰳴 md_cash_register +󰳵 md_cross_celtic +󰳶 md_cross_outline +󰳷 md_clipboard_alert_outline +󰳸 md_clipboard_arrow_left_outline +󰳹 md_clipboard_arrow_right +󰳺 md_clipboard_arrow_right_outline +󰳻 md_content_save_edit +󰳼 md_content_save_edit_outline +󰳽 md_cursor_default_click +󰳾 md_cursor_default_click_outline +󰳿 md_database_sync +󰴀 md_database_remove +󰴁 md_database_settings +󰴂 md_drama_masks +󰴃 md_email_box +󰴄 md_eye_check +󰴅 md_eye_check_outline +󰴆 md_fast_forward_30 +󰴇 md_order_alphabetical_descending +󰴈 md_flower_poppy +󰴉 md_folder_pound +󰴊 md_folder_pound_outline +󰴋 md_folder_sync +󰴌 md_folder_sync_outline +󰴍 md_format_list_numbered_rtl +󰴎 md_format_text_wrapping_clip +󰴏 md_format_text_wrapping_overflow +󰴐 md_format_text_wrapping_wrap +󰴑 md_format_textbox +󰴒 md_fountain_pen +󰴓 md_fountain_pen_tip +󰴔 md_heart_broken_outline +󰴕 md_home_city +󰴖 md_home_city_outline +󰴗 md_hubspot +󰴘 md_filmstrip_box_multiple +󰴙 md_play_box_multiple +󰴚 md_link_box +󰴛 md_link_box_outline +󰴜 md_link_box_variant +󰴝 md_link_box_variant_outline +󰴞 md_map_clock +󰴟 md_map_clock_outline +󰴠 md_map_marker_path +󰴡 md_mother_nurse +󰴢 md_microsoft_outlook +󰴣 md_perspective_less +󰴤 md_perspective_more +󰴥 md_podium +󰴦 md_podium_bronze +󰴧 md_podium_gold +󰴨 md_podium_silver +󰴩 md_quora +󰴪 md_rewind_10 +󰴫 md_roller_skate +󰴬 md_rollerblade +󰴭 md_language_ruby +󰴮 md_sack +󰴯 md_sack_percent +󰴰 md_safety_goggles +󰴱 md_select_color +󰴲 md_selection_ellipse +󰴳 md_shield_link_variant +󰴴 md_shield_link_variant_outline +󰴵 md_skate +󰴶 md_skew_less +󰴷 md_skew_more +󰴸 md_speaker_multiple +󰴹 md_stamper +󰴺 md_tank +󰴻 md_tortoise +󰴼 md_transit_connection +󰴽 md_transit_connection_variant +󰴾 md_transmission_tower +󰴿 md_weight_gram +󰵀 md_youtube_subscription +󰵁 md_zigbee +󰵂 md_email_alert_outline +󰵃 md_air_filter +󰵄 md_air_purifier +󰵅 md_android_messages +󰵆 md_apps_box +󰵇 md_atm +󰵈 md_axis +󰵉 md_axis_arrow +󰵊 md_axis_arrow_lock +󰵋 md_axis_lock +󰵌 md_axis_x_arrow +󰵍 md_axis_x_arrow_lock +󰵎 md_axis_x_rotate_clockwise +󰵏 md_axis_x_rotate_counterclockwise +󰵐 md_axis_x_y_arrow_lock +󰵑 md_axis_y_arrow +󰵒 md_axis_y_arrow_lock +󰵓 md_axis_y_rotate_clockwise +󰵔 md_axis_y_rotate_counterclockwise +󰵕 md_axis_z_arrow +󰵖 md_axis_z_arrow_lock +󰵗 md_axis_z_rotate_clockwise +󰵘 md_axis_z_rotate_counterclockwise +󰵙 md_bell_alert +󰵚 md_bell_circle +󰵛 md_bell_circle_outline +󰵜 md_calendar_minus +󰵝 md_camera_outline +󰵞 md_car_brake_hold +󰵟 md_car_brake_parking +󰵠 md_car_cruise_control +󰵡 md_car_defrost_front +󰵢 md_car_defrost_rear +󰵣 md_car_parking_lights +󰵤 md_car_traction_control +󰵥 md_bag_carry_on_check +󰵦 md_cart_arrow_down +󰵧 md_cart_arrow_up +󰵨 md_cart_minus +󰵩 md_cart_remove +󰵪 md_contactless_payment +󰵫 md_creative_commons +󰵬 md_credit_card_wireless_outline +󰵭 md_cricket +󰵮 md_dev_to +󰵯 md_domain_off +󰵰 md_face_agent +󰵱 md_fast_forward_10 +󰵲 md_flare +󰵳 md_format_text_rotation_down +󰵴 md_format_text_rotation_none +󰵵 md_forwardburger +󰵶 md_gesture_swipe +󰵷 md_gesture_tap_hold +󰵸 md_file_gif_box +󰵹 md_go_kart +󰵺 md_go_kart_track +󰵻 md_goodreads +󰵼 md_grain +󰵽 md_hdr +󰵾 md_hdr_off +󰵿 md_hiking +󰶀 md_home_floor_1 +󰶁 md_home_floor_2 +󰶂 md_home_floor_3 +󰶃 md_home_floor_a +󰶄 md_home_floor_b +󰶅 md_home_floor_g +󰶆 md_home_floor_l +󰶇 md_kabaddi +󰶈 md_mailbox_open +󰶉 md_mailbox_open_outline +󰶊 md_mailbox_open_up +󰶋 md_mailbox_open_up_outline +󰶌 md_mailbox_outline +󰶍 md_mailbox_up +󰶎 md_mailbox_up_outline +󰶏 md_mixed_martial_arts +󰶐 md_monitor_off +󰶑 md_motion_sensor +󰶒 md_point_of_sale +󰶓 md_racing_helmet +󰶔 md_racquetball +󰶕 md_restart_off +󰶖 md_rewind_30 +󰶗 md_room_service_outline +󰶘 md_rotate_orbit +󰶙 md_rugby +󰶚 md_shield_search +󰶛 md_solar_panel +󰶜 md_solar_panel_large +󰶝 md_subway_alert_variant +󰶞 md_tea +󰶟 md_tea_outline +󰶠 md_tennis +󰶡 md_transfer_down +󰶢 md_transfer_left +󰶣 md_transfer_up +󰶤 md_trophy_broken +󰶥 md_wind_turbine +󰶦 md_wiper_wash +󰶧 md_badge_account +󰶨 md_badge_account_alert +󰶩 md_badge_account_alert_outline +󰶪 md_badge_account_outline +󰶫 md_card_account_details_outline +󰶬 md_air_horn +󰶭 md_application_export +󰶮 md_application_import +󰶯 md_bandage +󰶰 md_bank_minus +󰶱 md_bank_plus +󰶲 md_bank_remove +󰶳 md_bolt +󰶴 md_bugle +󰶵 md_cactus +󰶶 md_camera_wireless +󰶷 md_camera_wireless_outline +󰶸 md_cash_marker +󰶹 md_chevron_triple_down +󰶺 md_chevron_triple_left +󰶻 md_chevron_triple_right +󰶼 md_chevron_triple_up +󰶽 md_closed_caption_outline +󰶾 md_credit_card_marker_outline +󰶿 md_diving_flippers +󰷀 md_diving_helmet +󰷁 md_diving_scuba +󰷂 md_diving_scuba_flag +󰷃 md_diving_scuba_tank +󰷄 md_diving_scuba_tank_multiple +󰷅 md_diving_snorkel +󰷆 md_file_cancel +󰷇 md_file_cancel_outline +󰷈 md_file_document_edit +󰷉 md_file_document_edit_outline +󰷊 md_file_eye +󰷋 md_file_eye_outline +󰷌 md_folder_alert +󰷍 md_folder_alert_outline +󰷎 md_folder_edit_outline +󰷏 md_folder_open_outline +󰷐 md_format_list_bulleted_square +󰷑 md_gantry_crane +󰷒 md_home_floor_0 +󰷓 md_home_floor_negative_1 +󰷔 md_home_group +󰷕 md_jabber +󰷖 md_key_outline +󰷗 md_leak +󰷘 md_leak_off +󰷙 md_marker_cancel +󰷚 md_mine +󰷛 md_monitor_lock +󰷜 md_monitor_star +󰷝 md_movie_outline +󰷞 md_music_note_plus +󰷟 md_nail +󰷠 md_ocarina +󰷡 md_passport_biometric +󰷢 md_pen_lock +󰷣 md_pen_minus +󰷤 md_pen_off +󰷥 md_pen_plus +󰷦 md_pen_remove +󰷧 md_pencil_lock_outline +󰷨 md_pencil_minus +󰷩 md_pencil_minus_outline +󰷪 md_pencil_off_outline +󰷫 md_pencil_plus +󰷬 md_pencil_plus_outline +󰷭 md_pencil_remove +󰷮 md_pencil_remove_outline +󰷯 md_phone_off +󰷰 md_phone_outline +󰷱 md_pi_hole +󰷲 md_playlist_star +󰷳 md_screw_flat_top +󰷴 md_screw_lag +󰷵 md_screw_machine_flat_top +󰷶 md_screw_machine_round_top +󰷷 md_screw_round_top +󰷸 md_send_circle +󰷹 md_send_circle_outline +󰷺 md_shoe_print +󰷻 md_signature +󰷼 md_signature_freehand +󰷽 md_signature_image +󰷾 md_signature_text +󰷿 md_slope_downhill +󰸀 md_slope_uphill +󰸁 md_thermometer_alert +󰸂 md_thermometer_chevron_down +󰸃 md_thermometer_chevron_up +󰸄 md_thermometer_minus +󰸅 md_thermometer_plus +󰸆 md_translate_off +󰸇 md_upload_outline +󰸈 md_volume_variant_off +󰸉 md_wallpaper +󰸊 md_water_outline +󰸋 md_wifi_star +󰸌 md_palette_outline +󰸍 md_badge_account_horizontal +󰸎 md_badge_account_horizontal_outline +󰸏 md_aws +󰸐 md_bag_personal +󰸑 md_bag_personal_off +󰸒 md_bag_personal_off_outline +󰸓 md_bag_personal_outline +󰸔 md_biathlon +󰸕 md_bookmark_multiple +󰸖 md_bookmark_multiple_outline +󰸗 md_calendar_month +󰸘 md_calendar_month_outline +󰸙 md_camera_retake +󰸚 md_camera_retake_outline +󰸛 md_car_back +󰸜 md_car_off +󰸝 md_cast_education +󰸞 md_check_bold +󰸟 md_check_underline +󰸠 md_check_underline_circle +󰸡 md_check_underline_circle_outline +󰸢 md_circular_saw +󰸣 md_comma +󰸤 md_comma_box_outline +󰸥 md_comma_circle +󰸦 md_comma_circle_outline +󰸧 md_content_save_move +󰸨 md_content_save_move_outline +󰸩 md_file_check_outline +󰸪 md_file_music_outline +󰸫 md_comma_box +󰸬 md_file_video_outline +󰸭 md_file_png_box +󰸮 md_fireplace +󰸯 md_fireplace_off +󰸰 md_firework +󰸱 md_format_color_highlight +󰸲 md_format_text_variant +󰸳 md_gamepad_circle +󰸴 md_gamepad_circle_down +󰸵 md_gamepad_circle_left +󰸶 md_gamepad_circle_outline +󰸷 md_gamepad_circle_right +󰸸 md_gamepad_circle_up +󰸹 md_gamepad_down +󰸺 md_gamepad_left +󰸻 md_gamepad_right +󰸼 md_gamepad_round +󰸽 md_gamepad_round_down +󰸾 md_gamepad_round_left +󰸿 md_gamepad_round_outline +󰹀 md_gamepad_round_right +󰹁 md_gamepad_round_up +󰹂 md_gamepad_up +󰹃 md_gatsby +󰹄 md_gift +󰹅 md_grill +󰹆 md_hand_back_left +󰹇 md_hand_back_right +󰹈 md_hand_saw +󰹉 md_image_frame +󰹊 md_invert_colors_off +󰹋 md_keyboard_off_outline +󰹌 md_layers_minus +󰹍 md_layers_plus +󰹎 md_layers_remove +󰹏 md_lightbulb_off +󰹐 md_lightbulb_off_outline +󰹑 md_monitor_screenshot +󰹒 md_ice_cream_off +󰹓 md_nfc_search_variant +󰹔 md_nfc_variant_off +󰹕 md_notebook_multiple +󰹖 md_hoop_house +󰹗 md_picture_in_picture_bottom_right +󰹘 md_picture_in_picture_bottom_right_outline +󰹙 md_picture_in_picture_top_right +󰹚 md_picture_in_picture_top_right_outline +󰹛 md_printer_3d_nozzle +󰹜 md_printer_3d_nozzle_outline +󰹝 md_printer_off +󰹞 md_rectangle +󰹟 md_rectangle_outline +󰹠 md_rivet +󰹡 md_saw_blade +󰹢 md_seed +󰹣 md_seed_outline +󰹤 md_signal_distance_variant +󰹥 md_spade +󰹦 md_sprout +󰹧 md_sprout_outline +󰹨 md_table_tennis +󰹩 md_tree_outline +󰹪 md_view_comfy +󰹫 md_view_compact +󰹬 md_view_compact_outline +󰹭 md_vuetify +󰹮 md_weather_cloudy_arrow_right +󰹯 md_microsoft_xbox_controller_menu +󰹰 md_microsoft_xbox_controller_view +󰹱 md_alarm_note +󰹲 md_alarm_note_off +󰹳 md_arrow_left_right +󰹴 md_arrow_left_right_bold +󰹵 md_arrow_top_left_bottom_right +󰹶 md_arrow_top_left_bottom_right_bold +󰹷 md_arrow_top_right_bottom_left +󰹸 md_arrow_top_right_bottom_left_bold +󰹹 md_arrow_up_down +󰹺 md_arrow_up_down_bold +󰹻 md_atom_variant +󰹼 md_baby_face +󰹽 md_baby_face_outline +󰹾 md_backspace_reverse +󰹿 md_backspace_reverse_outline +󰺀 md_bank_outline +󰺁 md_bell_alert_outline +󰺂 md_book_play +󰺃 md_book_play_outline +󰺄 md_book_search +󰺅 md_book_search_outline +󰺆 md_boom_gate +󰺇 md_boom_gate_alert +󰺈 md_boom_gate_alert_outline +󰺉 md_boom_gate_arrow_down +󰺊 md_boom_gate_arrow_down_outline +󰺋 md_boom_gate_outline +󰺌 md_boom_gate_arrow_up +󰺍 md_boom_gate_arrow_up_outline +󰺎 md_calendar_sync +󰺏 md_calendar_sync_outline +󰺐 md_cellphone_nfc +󰺑 md_chart_areaspline_variant +󰺒 md_chart_scatter_plot +󰺓 md_chart_timeline_variant +󰺔 md_chart_tree +󰺕 md_circle_double +󰺖 md_circle_expand +󰺗 md_clock_digital +󰺘 md_card_account_mail_outline +󰺙 md_card_account_phone +󰺚 md_card_account_phone_outline +󰺛 md_account_cowboy_hat +󰺜 md_currency_rial +󰺝 md_delete_empty_outline +󰺞 md_dolly +󰺟 md_electric_switch +󰺠 md_ellipse +󰺡 md_ellipse_outline +󰺢 md_equalizer +󰺣 md_equalizer_outline +󰺤 md_ferris_wheel +󰺥 md_file_delimited_outline +󰺦 md_text_box_check +󰺧 md_text_box_check_outline +󰺨 md_text_box_minus +󰺩 md_text_box_minus_outline +󰺪 md_text_box_plus +󰺫 md_text_box_plus_outline +󰺬 md_text_box_remove +󰺭 md_text_box_remove_outline +󰺮 md_text_box_search +󰺯 md_text_box_search_outline +󰺰 md_file_image_outline +󰺱 md_fingerprint_off +󰺲 md_format_list_bulleted_triangle +󰺳 md_format_overline +󰺴 md_frequently_asked_questions +󰺵 md_gamepad_square +󰺶 md_gamepad_square_outline +󰺷 md_gamepad_variant_outline +󰺸 md_gas_station_outline +󰺹 md_google_podcast +󰺺 md_home_analytics +󰺻 md_mail +󰺼 md_map_check +󰺽 md_map_check_outline +󰺾 md_ruler_square_compass +󰺿 md_notebook_outline +󰻀 md_penguin +󰻁 md_radioactive_off +󰻂 md_record_circle +󰻃 md_record_circle_outline +󰻄 md_remote_off +󰻅 md_remote_tv +󰻆 md_remote_tv_off +󰻇 md_rotate_3d +󰻈 md_sail_boat +󰻉 md_scatter_plot +󰻊 md_scatter_plot_outline +󰻋 md_segment +󰻌 md_shield_alert +󰻍 md_shield_alert_outline +󰻎 md_tablet_dashboard +󰻏 md_television_play +󰻐 md_unicode +󰻑 md_video_3d_variant +󰻒 md_video_wireless +󰻓 md_video_wireless_outline +󰻔 md_account_voice_off +󰻕 md_bacteria +󰻖 md_bacteria_outline +󰻗 md_calendar_account +󰻘 md_calendar_account_outline +󰻙 md_calendar_weekend +󰻚 md_calendar_weekend_outline +󰻛 md_camera_plus +󰻜 md_camera_plus_outline +󰻝 md_campfire +󰻞 md_chat_outline +󰻟 md_cpu_32_bit +󰻠 md_cpu_64_bit +󰻡 md_credit_card_clock +󰻢 md_credit_card_clock_outline +󰻣 md_email_edit +󰻤 md_email_edit_outline +󰻥 md_email_minus +󰻦 md_email_minus_outline +󰻧 md_email_multiple +󰻨 md_email_multiple_outline +󰻩 md_email_open_multiple +󰻪 md_email_open_multiple_outline +󰻫 md_file_cad +󰻬 md_file_cad_box +󰻭 md_file_plus_outline +󰻮 md_filter_minus +󰻯 md_filter_minus_outline +󰻰 md_filter_plus +󰻱 md_filter_plus_outline +󰻲 md_fire_extinguisher +󰻳 md_fishbowl +󰻴 md_fishbowl_outline +󰻵 md_fit_to_page +󰻶 md_fit_to_page_outline +󰻷 md_flash_alert +󰻸 md_flash_alert_outline +󰻹 md_heart_flash +󰻺 md_home_flood +󰻻 md_human_male_height +󰻼 md_human_male_height_variant +󰻽 md_ice_pop +󰻾 md_identifier +󰻿 md_image_filter_center_focus_strong +󰼀 md_image_filter_center_focus_strong_outline +󰼁 md_jellyfish +󰼂 md_jellyfish_outline +󰼃 md_lasso +󰼄 md_music_box_multiple_outline +󰼅 md_map_marker_alert +󰼆 md_map_marker_alert_outline +󰼇 md_map_marker_question +󰼈 md_map_marker_question_outline +󰼉 md_map_marker_remove +󰼊 md_map_marker_remove_variant +󰼋 md_necklace +󰼌 md_newspaper_minus +󰼍 md_newspaper_plus +󰼎 md_numeric_0_box_multiple +󰼏 md_numeric_1_box_multiple +󰼐 md_numeric_2_box_multiple +󰼑 md_numeric_3_box_multiple +󰼒 md_numeric_4_box_multiple +󰼓 md_numeric_5_box_multiple +󰼔 md_numeric_6_box_multiple +󰼕 md_numeric_7_box_multiple +󰼖 md_numeric_8_box_multiple +󰼗 md_numeric_9_box_multiple +󰼘 md_numeric_9_plus_box_multiple +󰼙 md_oil_lamp +󰼚 md_phone_alert +󰼛 md_play_outline +󰼜 md_purse +󰼝 md_purse_outline +󰼞 md_railroad_light +󰼟 md_reply_all_outline +󰼠 md_reply_outline +󰼡 md_rss_off +󰼢 md_selection_ellipse_arrow_inside +󰼣 md_share_off +󰼤 md_share_off_outline +󰼥 md_skip_backward_outline +󰼦 md_skip_forward_outline +󰼧 md_skip_next_outline +󰼨 md_skip_previous_outline +󰼩 md_snowflake_alert +󰼪 md_snowflake_variant +󰼫 md_stretch_to_page +󰼬 md_stretch_to_page_outline +󰼭 md_typewriter +󰼮 md_wave +󰼯 md_weather_cloudy_alert +󰼰 md_weather_hazy +󰼱 md_weather_night_partly_cloudy +󰼲 md_weather_partly_lightning +󰼳 md_weather_partly_rainy +󰼴 md_weather_partly_snowy +󰼵 md_weather_partly_snowy_rainy +󰼶 md_weather_snowy_heavy +󰼷 md_weather_sunny_alert +󰼸 md_weather_tornado +󰼹 md_baby_bottle +󰼺 md_baby_bottle_outline +󰼻 md_bag_carry_on +󰼼 md_bag_carry_on_off +󰼽 md_bag_checked +󰼾 md_baguette +󰼿 md_bus_multiple +󰽀 md_car_shift_pattern +󰽁 md_cellphone_information +󰽂 md_content_save_alert +󰽃 md_content_save_alert_outline +󰽄 md_content_save_all_outline +󰽅 md_crosshairs_off +󰽆 md_cupboard +󰽇 md_cupboard_outline +󰽈 md_chair_rolling +󰽉 md_draw +󰽊 md_dresser +󰽋 md_dresser_outline +󰽌 md_emoticon_frown +󰽍 md_emoticon_frown_outline +󰽎 md_focus_auto +󰽏 md_focus_field +󰽐 md_focus_field_horizontal +󰽑 md_focus_field_vertical +󰽒 md_foot_print +󰽓 md_handball +󰽔 md_home_thermometer +󰽕 md_home_thermometer_outline +󰽖 md_kettle_outline +󰽗 md_latitude +󰽘 md_layers_triple +󰽙 md_layers_triple_outline +󰽚 md_longitude +󰽛 md_language_markdown_outline +󰽜 md_merge +󰽝 md_middleware +󰽞 md_middleware_outline +󰽟 md_monitor_speaker +󰽠 md_monitor_speaker_off +󰽡 md_moon_first_quarter +󰽢 md_moon_full +󰽣 md_moon_last_quarter +󰽤 md_moon_new +󰽥 md_moon_waning_crescent +󰽦 md_moon_waning_gibbous +󰽧 md_moon_waxing_crescent +󰽨 md_moon_waxing_gibbous +󰽩 md_music_accidental_double_flat +󰽪 md_music_accidental_double_sharp +󰽫 md_music_accidental_flat +󰽬 md_music_accidental_natural +󰽭 md_music_accidental_sharp +󰽮 md_music_clef_alto +󰽯 md_music_clef_bass +󰽰 md_music_clef_treble +󰽱 md_music_note_eighth_dotted +󰽲 md_music_note_half_dotted +󰽳 md_music_note_off_outline +󰽴 md_music_note_outline +󰽵 md_music_note_quarter_dotted +󰽶 md_music_note_sixteenth_dotted +󰽷 md_music_note_whole_dotted +󰽸 md_music_rest_eighth +󰽹 md_music_rest_half +󰽺 md_music_rest_quarter +󰽻 md_music_rest_sixteenth +󰽼 md_music_rest_whole +󰽽 md_numeric_10_box +󰽾 md_numeric_10_box_outline +󰽿 md_page_layout_header_footer +󰾀 md_patio_heater +󰾁 md_warehouse +󰾂 md_select_group +󰾃 md_shield_car +󰾄 md_shopping_search +󰾅 md_speedometer_medium +󰾆 md_speedometer_slow +󰾇 md_table_large_plus +󰾈 md_table_large_remove +󰾉 md_television_pause +󰾊 md_television_stop +󰾋 md_transit_detour +󰾌 md_video_input_scart +󰾍 md_view_grid_plus +󰾎 md_wallet_plus +󰾏 md_wallet_plus_outline +󰾐 md_wardrobe +󰾑 md_wardrobe_outline +󰾒 md_water_boiler +󰾓 md_water_pump_off +󰾔 md_web_box +󰾕 md_timeline_alert +󰾖 md_timeline_plus +󰾗 md_timeline_plus_outline +󰾘 md_timeline_alert_outline +󰾙 md_timeline_help +󰾚 md_timeline_help_outline +󰾛 md_home_export_outline +󰾜 md_home_import_outline +󰾝 md_account_filter_outline +󰾞 md_approximately_equal +󰾟 md_approximately_equal_box +󰾠 md_baby_carriage_off +󰾡 md_bee +󰾢 md_bee_flower +󰾣 md_car_child_seat +󰾤 md_car_seat +󰾥 md_car_seat_cooler +󰾦 md_car_seat_heater +󰾧 md_chart_bell_curve_cumulative +󰾨 md_clock_check +󰾩 md_clock_check_outline +󰾪 md_coffee_off +󰾫 md_coffee_off_outline +󰾬 md_credit_card_minus +󰾭 md_credit_card_minus_outline +󰾮 md_credit_card_remove +󰾯 md_credit_card_remove_outline +󰾰 md_devices +󰾱 md_email_newsletter +󰾲 md_expansion_card_variant +󰾳 md_power_socket_ch +󰾴 md_file_swap +󰾵 md_file_swap_outline +󰾶 md_folder_swap +󰾷 md_folder_swap_outline +󰾸 md_format_letter_ends_with +󰾹 md_format_letter_matches +󰾺 md_format_letter_starts_with +󰾻 md_format_text_rotation_angle_down +󰾼 md_format_text_rotation_angle_up +󰾽 md_format_text_rotation_down_vertical +󰾾 md_format_text_rotation_up +󰾿 md_format_text_rotation_vertical +󰿀 md_id_card +󰿁 md_image_auto_adjust +󰿂 md_key_wireless +󰿃 md_license +󰿄 md_location_enter +󰿅 md_location_exit +󰿆 md_lock_open_variant +󰿇 md_lock_open_variant_outline +󰿈 md_math_integral +󰿉 md_math_integral_box +󰿊 md_math_norm +󰿋 md_math_norm_box +󰿌 md_message_lock +󰿍 md_message_text_lock +󰿎 md_movie_open +󰿏 md_movie_open_outline +󰿐 md_bed_queen +󰿑 md_bed_king_outline +󰿒 md_bed_king +󰿓 md_bed_double_outline +󰿔 md_bed_double +󰿕 md_microsoft_azure_devops +󰿖 md_arm_flex_outline +󰿗 md_arm_flex +󰿘 md_protocol +󰿙 md_seal_variant +󰿚 md_select_place +󰿛 md_bed_queen_outline +󰿜 md_sign_direction_plus +󰿝 md_sign_direction_remove +󰿞 md_silverware_clean +󰿟 md_slash_forward +󰿠 md_slash_forward_box +󰿡 md_swap_horizontal_circle +󰿢 md_swap_horizontal_circle_outline +󰿣 md_swap_vertical_circle +󰿤 md_swap_vertical_circle_outline +󰿥 md_tanker_truck +󰿦 md_texture_box +󰿧 md_tram_side +󰿨 md_vector_link +󰿩 md_numeric_10 +󰿪 md_numeric_10_box_multiple +󰿫 md_numeric_10_box_multiple_outline +󰿬 md_numeric_10_circle +󰿭 md_numeric_10_circle_outline +󰿮 md_numeric_9_plus +󰿯 md_credit_card +󰿰 md_credit_card_multiple +󰿱 md_credit_card_off +󰿲 md_credit_card_plus +󰿳 md_credit_card_refund +󰿴 md_credit_card_scan +󰿵 md_credit_card_settings +󰿶 md_hospital +󰿷 md_hospital_box_outline +󰿸 md_oil_temperature +󰿹 md_stadium +󰿺 md_zip_box_outline +󰿻 md_account_edit_outline +󰿼 md_peanut +󰿽 md_peanut_off +󰿾 md_peanut_outline +󰿿 md_peanut_off_outline +󱀀 md_sign_direction_minus +󱀁 md_newspaper_variant +󱀂 md_newspaper_variant_multiple +󱀃 md_newspaper_variant_multiple_outline +󱀄 md_newspaper_variant_outline +󱀅 md_overscan +󱀆 md_pig_variant +󱀇 md_piggy_bank +󱀈 md_post +󱀉 md_post_outline +󱀊 md_account_box_multiple_outline +󱀋 md_airballoon_outline +󱀌 md_alphabetical_off +󱀍 md_alphabetical_variant +󱀎 md_alphabetical_variant_off +󱀏 md_apache_kafka +󱀐 md_billboard +󱀑 md_blinds_open +󱀒 md_bus_stop +󱀓 md_bus_stop_covered +󱀔 md_bus_stop_uncovered +󱀕 md_car_2_plus +󱀖 md_car_3_plus +󱀗 md_car_brake_retarder +󱀘 md_car_clutch +󱀙 md_car_coolant_level +󱀚 md_car_turbocharger +󱀛 md_car_windshield +󱀜 md_car_windshield_outline +󱀝 md_cards_diamond_outline +󱀞 md_cast_audio +󱀟 md_cellphone_play +󱀠 md_coach_lamp +󱀡 md_comment_quote +󱀢 md_comment_quote_outline +󱀣 md_domino_mask +󱀤 md_electron_framework +󱀥 md_excavator +󱀦 md_eye_minus +󱀧 md_eye_minus_outline +󱀨 md_file_account_outline +󱀩 md_file_chart_outline +󱀪 md_file_cloud_outline +󱀫 md_file_code_outline +󱀬 md_file_excel_box_outline +󱀭 md_file_excel_outline +󱀮 md_file_export_outline +󱀯 md_file_import_outline +󱀰 md_file_lock_outline +󱀱 md_file_move_outline +󱀲 md_file_multiple_outline +󱀳 md_file_percent_outline +󱀴 md_file_powerpoint_box_outline +󱀵 md_file_powerpoint_outline +󱀶 md_file_question_outline +󱀷 md_file_remove_outline +󱀸 md_file_restore_outline +󱀹 md_file_send_outline +󱀺 md_file_star +󱀻 md_file_star_outline +󱀼 md_file_undo_outline +󱀽 md_file_word_box_outline +󱀾 md_file_word_outline +󱀿 md_filter_variant_remove +󱁀 md_floor_lamp_dual +󱁁 md_floor_lamp_torchiere_variant +󱁂 md_fruit_cherries +󱁃 md_fruit_citrus +󱁄 md_fruit_grapes +󱁅 md_fruit_grapes_outline +󱁆 md_fruit_pineapple +󱁇 md_fruit_watermelon +󱁈 md_google_my_business +󱁉 md_graph +󱁊 md_graph_outline +󱁋 md_harddisk_plus +󱁌 md_harddisk_remove +󱁍 md_home_circle_outline +󱁎 md_instrument_triangle +󱁏 md_island +󱁐 md_keyboard_space +󱁑 md_led_strip_variant +󱁒 md_numeric_negative_1 +󱁓 md_oil_level +󱁔 md_outdoor_lamp +󱁕 md_palm_tree +󱁖 md_party_popper +󱁗 md_printer_pos +󱁘 md_robber +󱁙 md_routes_clock +󱁚 md_scale_off +󱁛 md_cog_transfer +󱁜 md_cog_transfer_outline +󱁝 md_shield_sun +󱁞 md_shield_sun_outline +󱁟 md_sprinkler +󱁠 md_sprinkler_variant +󱁡 md_table_chair +󱁢 md_terraform +󱁣 md_toaster +󱁤 md_tools +󱁥 md_transfer +󱁦 md_valve +󱁧 md_valve_closed +󱁨 md_valve_open +󱁩 md_video_check +󱁪 md_video_check_outline +󱁫 md_water_well +󱁬 md_water_well_outline +󱁭 md_bed_single +󱁮 md_bed_single_outline +󱁯 md_book_information_variant +󱁰 md_bottle_soda +󱁱 md_bottle_soda_classic +󱁲 md_bottle_soda_outline +󱁳 md_calendar_blank_multiple +󱁴 md_card_search +󱁵 md_card_search_outline +󱁶 md_face_woman_profile +󱁷 md_face_woman +󱁸 md_face_woman_outline +󱁹 md_file_settings +󱁺 md_file_settings_outline +󱁻 md_file_cog +󱁼 md_file_cog_outline +󱁽 md_folder_settings +󱁾 md_folder_settings_outline +󱁿 md_folder_cog +󱂀 md_folder_cog_outline +󱂁 md_furigana_horizontal +󱂂 md_furigana_vertical +󱂃 md_golf_tee +󱂄 md_lungs +󱂅 md_math_log +󱂆 md_moped +󱂇 md_router_network +󱂈 md_alpha_i +󱂉 md_roman_numeral_2 +󱂊 md_roman_numeral_3 +󱂋 md_roman_numeral_4 +󱂌 md_alpha_v +󱂍 md_roman_numeral_6 +󱂎 md_roman_numeral_7 +󱂏 md_roman_numeral_8 +󱂐 md_roman_numeral_9 +󱂑 md_alpha_x +󱂒 md_soldering_iron +󱂓 md_stomach +󱂔 md_table_eye +󱂕 md_form_textarea +󱂖 md_trumpet +󱂗 md_account_cash +󱂘 md_account_cash_outline +󱂙 md_air_humidifier +󱂚 md_ansible +󱂛 md_api +󱂜 md_bicycle +󱂝 md_car_door_lock +󱂞 md_coat_rack +󱂟 md_coffee_maker +󱂠 md_web_minus +󱂡 md_decimal +󱂢 md_decimal_comma +󱂣 md_decimal_comma_decrease +󱂤 md_decimal_comma_increase +󱂥 md_delete_alert +󱂦 md_delete_alert_outline +󱂧 md_delete_off +󱂨 md_delete_off_outline +󱂩 md_dock_bottom +󱂪 md_dock_left +󱂫 md_dock_right +󱂬 md_dock_window +󱂭 md_domain_plus +󱂮 md_domain_remove +󱂯 md_door_closed_lock +󱂰 md_download_off +󱂱 md_download_off_outline +󱂲 md_flag_minus_outline +󱂳 md_flag_plus_outline +󱂴 md_flag_remove_outline +󱂵 md_folder_home +󱂶 md_folder_home_outline +󱂷 md_folder_information +󱂸 md_folder_information_outline +󱂹 md_iv_bag +󱂺 md_link_lock +󱂻 md_message_plus_outline +󱂼 md_phone_cancel +󱂽 md_smart_card +󱂾 md_smart_card_outline +󱂿 md_smart_card_reader +󱃀 md_smart_card_reader_outline +󱃁 md_storefront_outline +󱃂 md_thermometer_high +󱃃 md_thermometer_low +󱃄 md_ufo +󱃅 md_ufo_outline +󱃆 md_upload_off +󱃇 md_upload_off_outline +󱃈 md_account_child_outline +󱃉 md_account_settings_outline +󱃊 md_account_tie_outline +󱃋 md_alien_outline +󱃌 md_battery_alert_variant +󱃍 md_battery_alert_variant_outline +󱃎 md_beehive_outline +󱃏 md_boomerang +󱃐 md_briefcase_clock +󱃑 md_briefcase_clock_outline +󱃒 md_cellphone_message_off +󱃓 md_circle_off_outline +󱃔 md_clipboard_list +󱃕 md_clipboard_list_outline +󱃖 md_code_braces_box +󱃗 md_code_parentheses_box +󱃘 md_consolidate +󱃙 md_electric_switch_closed +󱃚 md_email_receive +󱃛 md_email_receive_outline +󱃜 md_email_send +󱃝 md_email_send_outline +󱃞 md_emoticon_confused +󱃟 md_emoticon_confused_outline +󱃠 md_epsilon +󱃡 md_file_table_box +󱃢 md_file_table_box_multiple +󱃣 md_file_table_box_multiple_outline +󱃤 md_file_table_box_outline +󱃥 md_filter_menu +󱃦 md_filter_menu_outline +󱃧 md_flip_horizontal +󱃨 md_flip_vertical +󱃩 md_folder_download_outline +󱃪 md_folder_heart +󱃫 md_folder_heart_outline +󱃬 md_folder_key_outline +󱃭 md_folder_upload_outline +󱃮 md_gamma +󱃯 md_hair_dryer +󱃰 md_hair_dryer_outline +󱃱 md_hand_heart +󱃲 md_hexagon_multiple_outline +󱃳 md_horizontal_rotate_clockwise +󱃴 md_horizontal_rotate_counterclockwise +󱃵 md_application_array +󱃶 md_application_array_outline +󱃷 md_application_braces +󱃸 md_application_braces_outline +󱃹 md_application_parentheses +󱃺 md_application_parentheses_outline +󱃻 md_application_variable +󱃼 md_application_variable_outline +󱃽 md_khanda +󱃾 md_kubernetes +󱃿 md_link_variant_minus +󱄀 md_link_variant_plus +󱄁 md_link_variant_remove +󱄂 md_map_marker_down +󱄃 md_map_marker_up +󱄄 md_monitor_shimmer +󱄅 md_nix +󱄆 md_nuxt +󱄇 md_power_socket_de +󱄈 md_power_socket_fr +󱄉 md_power_socket_jp +󱄊 md_progress_close +󱄋 md_reload_alert +󱄌 md_restart_alert +󱄍 md_restore_alert +󱄎 md_shaker +󱄏 md_shaker_outline +󱄐 md_television_shimmer +󱄑 md_variable_box +󱄒 md_filter_variant_minus +󱄓 md_filter_variant_plus +󱄔 md_slot_machine +󱄕 md_slot_machine_outline +󱄖 md_glass_mug_variant +󱄗 md_clipboard_flow_outline +󱄘 md_sign_real_estate +󱄙 md_antenna +󱄚 md_centos +󱄛 md_redhat +󱄜 md_window_shutter +󱄝 md_window_shutter_alert +󱄞 md_window_shutter_open +󱄟 md_bike_fast +󱄠 md_volume_source +󱄡 md_volume_vibrate +󱄢 md_movie_edit +󱄣 md_movie_edit_outline +󱄤 md_movie_filter +󱄥 md_movie_filter_outline +󱄦 md_diabetes +󱄧 md_cursor_default_gesture +󱄨 md_cursor_default_gesture_outline +󱄩 md_toothbrush +󱄪 md_toothbrush_paste +󱄫 md_home_roof +󱄬 md_toothbrush_electric +󱄭 md_account_supervisor_outline +󱄮 md_bottle_tonic +󱄯 md_bottle_tonic_outline +󱄰 md_bottle_tonic_plus +󱄱 md_bottle_tonic_plus_outline +󱄲 md_bottle_tonic_skull +󱄳 md_bottle_tonic_skull_outline +󱄴 md_calendar_arrow_left +󱄵 md_calendar_arrow_right +󱄶 md_crosshairs_question +󱄷 md_fire_hydrant +󱄸 md_fire_hydrant_alert +󱄹 md_fire_hydrant_off +󱄺 md_ocr +󱄻 md_shield_star +󱄼 md_shield_star_outline +󱄽 md_text_recognition +󱄾 md_handcuffs +󱄿 md_gender_male_female_variant +󱅀 md_gender_non_binary +󱅁 md_minus_box_multiple +󱅂 md_minus_box_multiple_outline +󱅃 md_plus_box_multiple_outline +󱅄 md_pencil_box_multiple +󱅅 md_pencil_box_multiple_outline +󱅆 md_printer_check +󱅇 md_sort_variant_remove +󱅈 md_sort_alphabetical_ascending_variant +󱅉 md_sort_alphabetical_descending_variant +󱅊 md_dice_1_outline +󱅋 md_dice_2_outline +󱅌 md_dice_3_outline +󱅍 md_dice_4_outline +󱅎 md_dice_5_outline +󱅏 md_dice_6_outline +󱅐 md_dice_d4 +󱅑 md_dice_d6 +󱅒 md_dice_d8 +󱅓 md_dice_d10 +󱅔 md_dice_d12 +󱅕 md_dice_d20 +󱅖 md_dice_multiple_outline +󱅗 md_paper_roll +󱅘 md_paper_roll_outline +󱅙 md_home_edit +󱅚 md_home_edit_outline +󱅛 md_arrow_horizontal_lock +󱅜 md_arrow_vertical_lock +󱅝 md_weight_lifter +󱅞 md_account_lock +󱅟 md_account_lock_outline +󱅠 md_pasta +󱅡 md_send_check +󱅢 md_send_check_outline +󱅣 md_send_clock +󱅤 md_send_clock_outline +󱅥 md_send_outline +󱅦 md_send_lock_outline +󱅧 md_police_badge +󱅨 md_police_badge_outline +󱅩 md_gate_arrow_right +󱅪 md_gate_open +󱅫 md_bell_badge +󱅬 md_message_image_outline +󱅭 md_message_lock_outline +󱅮 md_message_minus +󱅯 md_message_minus_outline +󱅰 md_message_processing_outline +󱅱 md_message_settings_outline +󱅲 md_message_cog_outline +󱅳 md_message_text_clock +󱅴 md_message_text_clock_outline +󱅵 md_message_text_lock_outline +󱅶 md_checkbox_blank_badge +󱅷 md_file_link +󱅸 md_file_link_outline +󱅹 md_file_phone +󱅺 md_file_phone_outline +󱅻 md_meditation +󱅼 md_yoga +󱅽 md_leek +󱅾 md_noodles +󱅿 md_pound_box_outline +󱆀 md_school_outline +󱆁 md_basket_outline +󱆂 md_phone_in_talk_outline +󱆃 md_bash +󱆄 md_file_key +󱆅 md_file_key_outline +󱆆 md_file_certificate +󱆇 md_file_certificate_outline +󱆈 md_certificate_outline +󱆉 md_cigar +󱆊 md_grill_outline +󱆋 md_qrcode_plus +󱆌 md_qrcode_minus +󱆍 md_qrcode_remove +󱆎 md_phone_alert_outline +󱆏 md_phone_bluetooth_outline +󱆐 md_phone_cancel_outline +󱆑 md_phone_forward_outline +󱆒 md_phone_hangup_outline +󱆓 md_phone_incoming_outline +󱆔 md_phone_lock_outline +󱆕 md_phone_log_outline +󱆖 md_phone_message +󱆗 md_phone_message_outline +󱆘 md_phone_minus_outline +󱆙 md_phone_outgoing_outline +󱆚 md_phone_paused_outline +󱆛 md_phone_plus_outline +󱆜 md_phone_return_outline +󱆝 md_phone_settings_outline +󱆞 md_key_star +󱆟 md_key_link +󱆠 md_shield_edit +󱆡 md_shield_edit_outline +󱆢 md_shield_sync +󱆣 md_shield_sync_outline +󱆤 md_golf_cart +󱆥 md_phone_missed_outline +󱆦 md_phone_off_outline +󱆧 md_format_quote_open_outline +󱆨 md_format_quote_close_outline +󱆩 md_phone_check +󱆪 md_phone_check_outline +󱆫 md_phone_ring +󱆬 md_phone_ring_outline +󱆭 md_share_circle +󱆮 md_reply_circle +󱆯 md_fridge_off +󱆰 md_fridge_off_outline +󱆱 md_fridge_alert +󱆲 md_fridge_alert_outline +󱆳 md_water_boiler_alert +󱆴 md_water_boiler_off +󱆵 md_amplifier_off +󱆶 md_audio_video_off +󱆷 md_toaster_off +󱆸 md_dishwasher_alert +󱆹 md_dishwasher_off +󱆺 md_tumble_dryer_alert +󱆻 md_tumble_dryer_off +󱆼 md_washing_machine_alert +󱆽 md_washing_machine_off +󱆾 md_car_info +󱆿 md_comment_edit +󱇀 md_printer_3d_nozzle_alert +󱇁 md_printer_3d_nozzle_alert_outline +󱇂 md_align_horizontal_left +󱇃 md_align_horizontal_center +󱇄 md_align_horizontal_right +󱇅 md_align_vertical_bottom +󱇆 md_align_vertical_center +󱇇 md_align_vertical_top +󱇈 md_distribute_horizontal_left +󱇉 md_distribute_horizontal_center +󱇊 md_distribute_horizontal_right +󱇋 md_distribute_vertical_bottom +󱇌 md_distribute_vertical_center +󱇍 md_distribute_vertical_top +󱇎 md_alert_rhombus +󱇏 md_alert_rhombus_outline +󱇐 md_crown_outline +󱇑 md_image_off_outline +󱇒 md_movie_search +󱇓 md_movie_search_outline +󱇔 md_rv_truck +󱇕 md_shopping_outline +󱇖 md_strategy +󱇗 md_note_text_outline +󱇘 md_view_agenda_outline +󱇙 md_view_grid_outline +󱇚 md_view_grid_plus_outline +󱇛 md_window_closed_variant +󱇜 md_window_open_variant +󱇝 md_cog_clockwise +󱇞 md_cog_counterclockwise +󱇟 md_chart_sankey +󱇠 md_chart_sankey_variant +󱇡 md_vanity_light +󱇢 md_router +󱇣 md_image_edit +󱇤 md_image_edit_outline +󱇥 md_bell_check +󱇦 md_bell_check_outline +󱇧 md_file_edit +󱇨 md_file_edit_outline +󱇩 md_human_scooter +󱇪 md_spider +󱇫 md_spider_thread +󱇬 md_plus_thick +󱇭 md_alert_circle_check +󱇮 md_alert_circle_check_outline +󱇯 md_state_machine +󱇰 md_usb_port +󱇱 md_cloud_lock +󱇲 md_cloud_lock_outline +󱇳 md_robot_mower_outline +󱇴 md_share_all +󱇵 md_share_all_outline +󱇶 md_google_cloud +󱇷 md_robot_mower +󱇸 md_fast_forward_5 +󱇹 md_rewind_5 +󱇺 md_shape_oval_plus +󱇻 md_timeline_clock +󱇼 md_timeline_clock_outline +󱇽 md_mirror +󱇾 md_account_multiple_check_outline +󱇿 md_card_plus +󱈀 md_card_plus_outline +󱈁 md_checkerboard_plus +󱈂 md_checkerboard_minus +󱈃 md_checkerboard_remove +󱈄 md_select_search +󱈅 md_selection_search +󱈆 md_layers_search +󱈇 md_layers_search_outline +󱈈 md_lightbulb_cfl +󱈉 md_lightbulb_cfl_off +󱈊 md_account_multiple_remove +󱈋 md_account_multiple_remove_outline +󱈌 md_magnify_remove_cursor +󱈍 md_magnify_remove_outline +󱈎 md_archive_outline +󱈏 md_battery_heart +󱈐 md_battery_heart_outline +󱈑 md_battery_heart_variant +󱈒 md_bus_marker +󱈓 md_chart_multiple +󱈔 md_emoticon_lol +󱈕 md_emoticon_lol_outline +󱈖 md_file_sync +󱈗 md_file_sync_outline +󱈘 md_handshake +󱈙 md_language_kotlin +󱈚 md_language_fortran +󱈛 md_offer +󱈜 md_radio_off +󱈝 md_table_headers_eye +󱈞 md_table_headers_eye_off +󱈟 md_tag_minus_outline +󱈠 md_tag_off +󱈡 md_tag_off_outline +󱈢 md_tag_plus_outline +󱈣 md_tag_remove_outline +󱈤 md_tag_text +󱈥 md_vector_polyline_edit +󱈦 md_vector_polyline_minus +󱈧 md_vector_polyline_plus +󱈨 md_vector_polyline_remove +󱈩 md_beaker_alert +󱈪 md_beaker_alert_outline +󱈫 md_beaker_check +󱈬 md_beaker_check_outline +󱈭 md_beaker_minus +󱈮 md_beaker_minus_outline +󱈯 md_beaker_plus +󱈰 md_beaker_plus_outline +󱈱 md_beaker_question +󱈲 md_beaker_question_outline +󱈳 md_beaker_remove +󱈴 md_beaker_remove_outline +󱈵 md_bicycle_basket +󱈶 md_barcode_off +󱈷 md_digital_ocean +󱈸 md_exclamation_thick +󱈹 md_desk +󱈺 md_flask_empty_minus +󱈻 md_flask_empty_minus_outline +󱈼 md_flask_empty_plus +󱈽 md_flask_empty_plus_outline +󱈾 md_flask_empty_remove +󱈿 md_flask_empty_remove_outline +󱉀 md_flask_minus +󱉁 md_flask_minus_outline +󱉂 md_flask_plus +󱉃 md_flask_plus_outline +󱉄 md_flask_remove +󱉅 md_flask_remove_outline +󱉆 md_folder_move_outline +󱉇 md_home_remove +󱉈 md_webrtc +󱉉 md_seat_passenger +󱉊 md_web_clock +󱉋 md_flask_round_bottom +󱉌 md_flask_round_bottom_empty +󱉍 md_flask_round_bottom_empty_outline +󱉎 md_flask_round_bottom_outline +󱉏 md_gold +󱉐 md_message_star_outline +󱉑 md_home_lightbulb +󱉒 md_home_lightbulb_outline +󱉓 md_lightbulb_group +󱉔 md_lightbulb_group_outline +󱉕 md_lightbulb_multiple +󱉖 md_lightbulb_multiple_outline +󱉗 md_api_off +󱉘 md_allergy +󱉙 md_archive_arrow_down +󱉚 md_archive_arrow_down_outline +󱉛 md_archive_arrow_up +󱉜 md_archive_arrow_up_outline +󱉝 md_battery_off +󱉞 md_battery_off_outline +󱉟 md_bookshelf +󱉠 md_cash_minus +󱉡 md_cash_plus +󱉢 md_cash_remove +󱉣 md_clipboard_check_multiple +󱉤 md_clipboard_check_multiple_outline +󱉥 md_clipboard_file +󱉦 md_clipboard_file_outline +󱉧 md_clipboard_multiple +󱉨 md_clipboard_multiple_outline +󱉩 md_clipboard_play_multiple +󱉪 md_clipboard_play_multiple_outline +󱉫 md_clipboard_text_multiple +󱉬 md_clipboard_text_multiple_outline +󱉭 md_folder_marker +󱉮 md_folder_marker_outline +󱉯 md_format_list_text +󱉰 md_inbox_arrow_down_outline +󱉱 md_inbox_arrow_up_outline +󱉲 md_inbox_full +󱉳 md_inbox_full_outline +󱉴 md_inbox_outline +󱉵 md_lightbulb_cfl_spiral +󱉶 md_magnify_scan +󱉷 md_map_marker_multiple_outline +󱉸 md_percent_outline +󱉹 md_phone_classic_off +󱉺 md_play_box +󱉻 md_account_eye_outline +󱉼 md_safe_square +󱉽 md_safe_square_outline +󱉾 md_scoreboard +󱉿 md_scoreboard_outline +󱊀 md_select_marker +󱊁 md_select_multiple +󱊂 md_select_multiple_marker +󱊃 md_selection_marker +󱊄 md_selection_multiple_marker +󱊅 md_selection_multiple +󱊆 md_star_box_multiple +󱊇 md_star_box_multiple_outline +󱊈 md_toy_brick +󱊉 md_toy_brick_marker +󱊊 md_toy_brick_marker_outline +󱊋 md_toy_brick_minus +󱊌 md_toy_brick_minus_outline +󱊍 md_toy_brick_outline +󱊎 md_toy_brick_plus +󱊏 md_toy_brick_plus_outline +󱊐 md_toy_brick_remove +󱊑 md_toy_brick_remove_outline +󱊒 md_toy_brick_search +󱊓 md_toy_brick_search_outline +󱊔 md_tray +󱊕 md_tray_alert +󱊖 md_tray_full +󱊗 md_tray_minus +󱊘 md_tray_plus +󱊙 md_tray_remove +󱊚 md_truck_check_outline +󱊛 md_truck_delivery_outline +󱊜 md_truck_fast_outline +󱊝 md_truck_outline +󱊞 md_usb_flash_drive +󱊟 md_usb_flash_drive_outline +󱊠 md_water_polo +󱊡 md_battery_low +󱊢 md_battery_medium +󱊣 md_battery_high +󱊤 md_battery_charging_low +󱊥 md_battery_charging_medium +󱊦 md_battery_charging_high +󱊧 md_hexadecimal +󱊨 md_gesture_tap_button +󱊩 md_gesture_tap_box +󱊪 md_lan_check +󱊫 md_keyboard_f1 +󱊬 md_keyboard_f2 +󱊭 md_keyboard_f3 +󱊮 md_keyboard_f4 +󱊯 md_keyboard_f5 +󱊰 md_keyboard_f6 +󱊱 md_keyboard_f7 +󱊲 md_keyboard_f8 +󱊳 md_keyboard_f9 +󱊴 md_keyboard_f10 +󱊵 md_keyboard_f11 +󱊶 md_keyboard_f12 +󱊷 md_keyboard_esc +󱊸 md_toslink +󱊹 md_cheese +󱊺 md_string_lights +󱊻 md_string_lights_off +󱊼 md_whistle_outline +󱊽 md_stairs_up +󱊾 md_stairs_down +󱊿 md_escalator_up +󱋀 md_escalator_down +󱋁 md_elevator_up +󱋂 md_elevator_down +󱋃 md_lightbulb_cfl_spiral_off +󱋄 md_comment_edit_outline +󱋅 md_tooltip_edit_outline +󱋆 md_monitor_edit +󱋇 md_email_sync +󱋈 md_email_sync_outline +󱋉 md_chat_alert_outline +󱋊 md_chat_processing_outline +󱋋 md_snowflake_melt +󱋌 md_cloud_check_outline +󱋍 md_lightbulb_group_off +󱋎 md_lightbulb_group_off_outline +󱋏 md_lightbulb_multiple_off +󱋐 md_lightbulb_multiple_off_outline +󱋑 md_chat_sleep +󱋒 md_chat_sleep_outline +󱋓 md_garage_variant +󱋔 md_garage_open_variant +󱋕 md_garage_alert_variant +󱋖 md_cloud_sync_outline +󱋗 md_globe_light +󱋘 md_cellphone_nfc_off +󱋙 md_leaf_off +󱋚 md_leaf_maple_off +󱋛 md_map_marker_left +󱋜 md_map_marker_right +󱋝 md_map_marker_left_outline +󱋞 md_map_marker_right_outline +󱋟 md_account_cancel +󱋠 md_account_cancel_outline +󱋡 md_file_clock +󱋢 md_file_clock_outline +󱋣 md_folder_table +󱋤 md_folder_table_outline +󱋥 md_hydro_power +󱋦 md_doorbell +󱋧 md_bulma +󱋨 md_iobroker +󱋩 md_oci +󱋪 md_label_percent +󱋫 md_label_percent_outline +󱋬 md_checkbox_blank_off +󱋭 md_checkbox_blank_off_outline +󱋮 md_square_off +󱋯 md_square_off_outline +󱋰 md_drag_horizontal_variant +󱋱 md_drag_vertical_variant +󱋲 md_message_arrow_left +󱋳 md_message_arrow_left_outline +󱋴 md_message_arrow_right +󱋵 md_message_arrow_right_outline +󱋶 md_database_marker +󱋷 md_tag_multiple_outline +󱋸 md_map_marker_plus_outline +󱋹 md_map_marker_minus_outline +󱋺 md_map_marker_remove_outline +󱋻 md_map_marker_check_outline +󱋼 md_map_marker_radius_outline +󱋽 md_map_marker_off_outline +󱋾 md_molecule_co +󱋿 md_jump_rope +󱌀 md_kettlebell +󱌁 md_account_convert_outline +󱌂 md_bunk_bed +󱌃 md_fleur_de_lis +󱌄 md_ski +󱌅 md_ski_cross_country +󱌆 md_ski_water +󱌇 md_snowboard +󱌈 md_account_tie_voice +󱌉 md_account_tie_voice_outline +󱌊 md_account_tie_voice_off +󱌋 md_account_tie_voice_off_outline +󱌌 md_beer_outline +󱌍 md_glass_pint_outline +󱌎 md_coffee_to_go_outline +󱌏 md_cup_outline +󱌐 md_bottle_wine_outline +󱌑 md_earth_arrow_right +󱌒 md_key_arrow_right +󱌓 md_format_color_marker_cancel +󱌔 md_mother_heart +󱌕 md_currency_eur_off +󱌖 md_semantic_web +󱌗 md_kettle_alert +󱌘 md_kettle_alert_outline +󱌙 md_kettle_steam +󱌚 md_kettle_steam_outline +󱌛 md_kettle_off +󱌜 md_kettle_off_outline +󱌝 md_simple_icons +󱌞 md_briefcase_check_outline +󱌟 md_clipboard_plus_outline +󱌠 md_download_lock +󱌡 md_download_lock_outline +󱌢 md_hammer_screwdriver +󱌣 md_hammer_wrench +󱌤 md_hydraulic_oil_level +󱌥 md_hydraulic_oil_temperature +󱌦 md_medal_outline +󱌧 md_rodent +󱌨 md_abjad_arabic +󱌩 md_abjad_hebrew +󱌪 md_abugida_devanagari +󱌫 md_abugida_thai +󱌬 md_alphabet_aurebesh +󱌭 md_alphabet_cyrillic +󱌮 md_alphabet_greek +󱌯 md_alphabet_latin +󱌰 md_alphabet_piqad +󱌱 md_ideogram_cjk +󱌲 md_ideogram_cjk_variant +󱌳 md_syllabary_hangul +󱌴 md_syllabary_hiragana +󱌵 md_syllabary_katakana +󱌶 md_syllabary_katakana_halfwidth +󱌷 md_alphabet_tengwar +󱌸 md_head_alert +󱌹 md_head_alert_outline +󱌺 md_head_check +󱌻 md_head_check_outline +󱌼 md_head_cog +󱌽 md_head_cog_outline +󱌾 md_head_dots_horizontal +󱌿 md_head_dots_horizontal_outline +󱍀 md_head_flash +󱍁 md_head_flash_outline +󱍂 md_head_heart +󱍃 md_head_heart_outline +󱍄 md_head_lightbulb +󱍅 md_head_lightbulb_outline +󱍆 md_head_minus +󱍇 md_head_minus_outline +󱍈 md_head_plus +󱍉 md_head_plus_outline +󱍊 md_head_question +󱍋 md_head_question_outline +󱍌 md_head_remove +󱍍 md_head_remove_outline +󱍎 md_head_snowflake +󱍏 md_head_snowflake_outline +󱍐 md_head_sync +󱍑 md_head_sync_outline +󱍒 md_hvac +󱍓 md_pencil_ruler +󱍔 md_pipe_wrench +󱍕 md_widgets_outline +󱍖 md_television_ambient_light +󱍗 md_propane_tank +󱍘 md_propane_tank_outline +󱍙 md_folder_music +󱍚 md_folder_music_outline +󱍛 md_klingon +󱍜 md_palette_swatch_outline +󱍝 md_form_textbox_lock +󱍞 md_head +󱍟 md_head_outline +󱍠 md_shield_half +󱍡 md_store_outline +󱍢 md_google_downasaur +󱍣 md_bottle_soda_classic_outline +󱍤 md_sticker +󱍥 md_sticker_alert +󱍦 md_sticker_alert_outline +󱍧 md_sticker_check +󱍨 md_sticker_check_outline +󱍩 md_sticker_minus +󱍪 md_sticker_minus_outline +󱍫 md_sticker_outline +󱍬 md_sticker_plus +󱍭 md_sticker_plus_outline +󱍮 md_sticker_remove +󱍯 md_sticker_remove_outline +󱍰 md_account_cog +󱍱 md_account_cog_outline +󱍲 md_account_details_outline +󱍳 md_upload_lock +󱍴 md_upload_lock_outline +󱍵 md_label_multiple +󱍶 md_label_multiple_outline +󱍷 md_refresh_circle +󱍸 md_sync_circle +󱍹 md_bookmark_music_outline +󱍺 md_bookmark_remove_outline +󱍻 md_bookmark_check_outline +󱍼 md_traffic_cone +󱍽 md_cup_off_outline +󱍾 md_auto_download +󱍿 md_shuriken +󱎀 md_chart_ppf +󱎁 md_elevator_passenger +󱎂 md_compass_rose +󱎃 md_space_station +󱎄 md_order_bool_descending +󱎅 md_sort_bool_ascending +󱎆 md_sort_bool_ascending_variant +󱎇 md_sort_bool_descending +󱎈 md_sort_bool_descending_variant +󱎉 md_sort_numeric_ascending +󱎊 md_sort_numeric_descending +󱎋 md_human_baby_changing_table +󱎌 md_human_male_child +󱎍 md_human_wheelchair +󱎎 md_microsoft_access +󱎏 md_microsoft_excel +󱎐 md_microsoft_powerpoint +󱎑 md_microsoft_sharepoint +󱎒 md_microsoft_word +󱎓 md_nintendo_game_boy +󱎔 md_cable_data +󱎕 md_circle_half +󱎖 md_circle_half_full +󱎗 md_cellphone_charging +󱎘 md_close_thick +󱎙 md_escalator_box +󱎚 md_lock_check +󱎛 md_lock_open_alert +󱎜 md_lock_open_check +󱎝 md_recycle_variant +󱎞 md_stairs_box +󱎟 md_hand_water +󱎠 md_table_refresh +󱎡 md_table_sync +󱎢 md_size_xxs +󱎣 md_size_xs +󱎤 md_size_s +󱎥 md_size_m +󱎦 md_alpha_l +󱎧 md_size_xl +󱎨 md_size_xxl +󱎩 md_size_xxxl +󱎪 md_ticket_confirmation_outline +󱎫 md_timer +󱎬 md_timer_off +󱎭 md_book_account +󱎮 md_book_account_outline +󱎯 md_rocket_outline +󱎰 md_home_search +󱎱 md_home_search_outline +󱎲 md_car_arrow_left +󱎳 md_car_arrow_right +󱎴 md_monitor_eye +󱎵 md_lipstick +󱎶 md_virus +󱎷 md_virus_outline +󱎸 md_text_search +󱎹 md_table_account +󱎺 md_table_alert +󱎻 md_table_arrow_down +󱎼 md_table_arrow_left +󱎽 md_table_arrow_right +󱎾 md_table_arrow_up +󱎿 md_table_cancel +󱏀 md_table_check +󱏁 md_table_clock +󱏂 md_table_cog +󱏃 md_table_eye_off +󱏄 md_table_heart +󱏅 md_table_key +󱏆 md_table_lock +󱏇 md_table_minus +󱏈 md_table_multiple +󱏉 md_table_network +󱏊 md_table_off +󱏋 md_table_star +󱏌 md_car_cog +󱏍 md_car_settings +󱏎 md_cog_off +󱏏 md_cog_off_outline +󱏐 md_credit_card_check +󱏑 md_credit_card_check_outline +󱏒 md_file_tree_outline +󱏓 md_folder_star_multiple +󱏔 md_folder_star_multiple_outline +󱏕 md_home_minus_outline +󱏖 md_home_plus_outline +󱏗 md_home_remove_outline +󱏘 md_scan_helper +󱏙 md_video_3d_off +󱏚 md_shield_bug +󱏛 md_shield_bug_outline +󱏜 md_eyedropper_plus +󱏝 md_eyedropper_minus +󱏞 md_eyedropper_remove +󱏟 md_eyedropper_off +󱏠 md_baby_buggy +󱏡 md_umbrella_closed_variant +󱏢 md_umbrella_closed_outline +󱏣 md_email_off +󱏤 md_email_off_outline +󱏥 md_food_variant_off +󱏦 md_play_box_multiple_outline +󱏧 md_bell_cancel +󱏨 md_bell_cancel_outline +󱏩 md_bell_minus +󱏪 md_bell_minus_outline +󱏫 md_bell_remove +󱏬 md_bell_remove_outline +󱏭 md_beehive_off_outline +󱏮 md_cheese_off +󱏯 md_corn_off +󱏰 md_egg_off +󱏱 md_egg_off_outline +󱏲 md_egg_outline +󱏳 md_fish_off +󱏴 md_flask_empty_off +󱏵 md_flask_empty_off_outline +󱏶 md_flask_off +󱏷 md_flask_off_outline +󱏸 md_fruit_cherries_off +󱏹 md_fruit_citrus_off +󱏺 md_mushroom_off +󱏻 md_mushroom_off_outline +󱏼 md_soy_sauce_off +󱏽 md_seed_off +󱏾 md_seed_off_outline +󱏿 md_tailwind +󱐀 md_form_dropdown +󱐁 md_form_select +󱐂 md_pump +󱐃 md_earth_plus +󱐄 md_earth_minus +󱐅 md_earth_remove +󱐆 md_earth_box_plus +󱐇 md_earth_box_minus +󱐈 md_earth_box_remove +󱐉 md_gas_station_off +󱐊 md_gas_station_off_outline +󱐋 md_lightning_bolt +󱐌 md_lightning_bolt_outline +󱐍 md_smoking_pipe +󱐎 md_axis_arrow_info +󱐏 md_chat_plus +󱐐 md_chat_minus +󱐑 md_chat_remove +󱐒 md_chat_plus_outline +󱐓 md_chat_minus_outline +󱐔 md_chat_remove_outline +󱐕 md_bucket +󱐖 md_bucket_outline +󱐗 md_pail +󱐘 md_image_remove +󱐙 md_image_minus +󱐚 md_pine_tree_fire +󱐛 md_cigar_off +󱐜 md_cube_off +󱐝 md_cube_off_outline +󱐞 md_dome_light +󱐟 md_food_drumstick +󱐠 md_food_drumstick_outline +󱐡 md_incognito_circle +󱐢 md_incognito_circle_off +󱐣 md_microwave_off +󱐤 md_power_plug_off_outline +󱐥 md_power_plug_outline +󱐦 md_puzzle_check +󱐧 md_puzzle_check_outline +󱐨 md_smoking_pipe_off +󱐩 md_spoon_sugar +󱐪 md_table_split_cell +󱐫 md_ticket_percent_outline +󱐬 md_fuse_off +󱐭 md_fuse_alert +󱐮 md_heart_plus +󱐯 md_heart_minus +󱐰 md_heart_remove +󱐱 md_heart_plus_outline +󱐲 md_heart_minus_outline +󱐳 md_heart_remove_outline +󱐴 md_heart_off_outline +󱐵 md_motion_sensor_off +󱐶 md_pail_plus +󱐷 md_pail_minus +󱐸 md_pail_remove +󱐹 md_pail_off +󱐺 md_pail_outline +󱐻 md_pail_plus_outline +󱐼 md_pail_minus_outline +󱐽 md_pail_remove_outline +󱐾 md_pail_off_outline +󱐿 md_clock_time_one +󱑀 md_clock_time_two +󱑁 md_clock_time_three +󱑂 md_clock_time_four +󱑃 md_clock_time_five +󱑄 md_clock_time_six +󱑅 md_clock_time_seven +󱑆 md_clock_time_eight +󱑇 md_clock_time_nine +󱑈 md_clock_time_ten +󱑉 md_clock_time_eleven +󱑊 md_clock_time_twelve +󱑋 md_clock_time_one_outline +󱑌 md_clock_time_two_outline +󱑍 md_clock_time_three_outline +󱑎 md_clock_time_four_outline +󱑏 md_clock_time_five_outline +󱑐 md_clock_time_six_outline +󱑑 md_clock_time_seven_outline +󱑒 md_clock_time_eight_outline +󱑓 md_clock_time_nine_outline +󱑔 md_clock_time_ten_outline +󱑕 md_clock_time_eleven_outline +󱑖 md_clock_time_twelve_outline +󱑗 md_printer_search +󱑘 md_printer_eye +󱑙 md_minus_circle_off +󱑚 md_minus_circle_off_outline +󱑛 md_content_save_cog +󱑜 md_content_save_cog_outline +󱑝 md_set_square +󱑞 md_cog_refresh +󱑟 md_cog_refresh_outline +󱑠 md_cog_sync +󱑡 md_cog_sync_outline +󱑢 md_download_box +󱑣 md_download_box_outline +󱑤 md_download_circle +󱑥 md_download_circle_outline +󱑦 md_air_humidifier_off +󱑧 md_chili_off +󱑨 md_food_drumstick_off +󱑩 md_food_drumstick_off_outline +󱑪 md_food_steak +󱑫 md_food_steak_off +󱑬 md_fan_alert +󱑭 md_fan_chevron_down +󱑮 md_fan_chevron_up +󱑯 md_fan_plus +󱑰 md_fan_minus +󱑱 md_fan_remove +󱑲 md_fan_speed_1 +󱑳 md_fan_speed_2 +󱑴 md_fan_speed_3 +󱑵 md_rug +󱑶 md_lingerie +󱑷 md_wizard_hat +󱑸 md_hours_24 +󱑹 md_cosine_wave +󱑺 md_sawtooth_wave +󱑻 md_square_wave +󱑼 md_triangle_wave +󱑽 md_waveform +󱑾 md_folder_multiple_plus +󱑿 md_folder_multiple_plus_outline +󱒀 md_current_ac +󱒁 md_watering_can +󱒂 md_watering_can_outline +󱒃 md_monitor_share +󱒄 md_laser_pointer +󱒅 md_view_array_outline +󱒆 md_view_carousel_outline +󱒇 md_view_column_outline +󱒈 md_view_comfy_outline +󱒉 md_view_dashboard_variant_outline +󱒊 md_view_day_outline +󱒋 md_view_list_outline +󱒌 md_view_module_outline +󱒍 md_view_parallel_outline +󱒎 md_view_quilt_outline +󱒏 md_view_sequential_outline +󱒐 md_view_stream_outline +󱒑 md_view_week_outline +󱒒 md_compare_horizontal +󱒓 md_compare_vertical +󱒔 md_briefcase_variant +󱒕 md_briefcase_variant_outline +󱒖 md_relation_many_to_many +󱒗 md_relation_many_to_one +󱒘 md_relation_many_to_one_or_many +󱒙 md_relation_many_to_only_one +󱒚 md_relation_many_to_zero_or_many +󱒛 md_relation_many_to_zero_or_one +󱒜 md_relation_one_or_many_to_many +󱒝 md_relation_one_or_many_to_one +󱒞 md_relation_one_or_many_to_one_or_many +󱒟 md_relation_one_or_many_to_only_one +󱒠 md_relation_one_or_many_to_zero_or_many +󱒡 md_relation_one_or_many_to_zero_or_one +󱒢 md_relation_one_to_many +󱒣 md_relation_one_to_one +󱒤 md_relation_one_to_one_or_many +󱒥 md_relation_one_to_only_one +󱒦 md_relation_one_to_zero_or_many +󱒧 md_relation_one_to_zero_or_one +󱒨 md_relation_only_one_to_many +󱒩 md_relation_only_one_to_one +󱒪 md_relation_only_one_to_one_or_many +󱒫 md_relation_only_one_to_only_one +󱒬 md_relation_only_one_to_zero_or_many +󱒭 md_relation_only_one_to_zero_or_one +󱒮 md_relation_zero_or_many_to_many +󱒯 md_relation_zero_or_many_to_one +󱒰 md_relation_zero_or_many_to_one_or_many +󱒱 md_relation_zero_or_many_to_only_one +󱒲 md_relation_zero_or_many_to_zero_or_many +󱒳 md_relation_zero_or_many_to_zero_or_one +󱒴 md_relation_zero_or_one_to_many +󱒵 md_relation_zero_or_one_to_one +󱒶 md_relation_zero_or_one_to_one_or_many +󱒷 md_relation_zero_or_one_to_only_one +󱒸 md_relation_zero_or_one_to_zero_or_many +󱒹 md_relation_zero_or_one_to_zero_or_one +󱒺 md_alert_plus +󱒻 md_alert_minus +󱒼 md_alert_remove +󱒽 md_alert_plus_outline +󱒾 md_alert_minus_outline +󱒿 md_alert_remove_outline +󱓀 md_carabiner +󱓁 md_fencing +󱓂 md_skateboard +󱓃 md_polo +󱓄 md_tractor_variant +󱓅 md_radiology_box +󱓆 md_radiology_box_outline +󱓇 md_skull_scan +󱓈 md_skull_scan_outline +󱓉 md_plus_minus_variant +󱓊 md_source_branch_plus +󱓋 md_source_branch_minus +󱓌 md_source_branch_remove +󱓍 md_source_branch_refresh +󱓎 md_source_branch_sync +󱓏 md_source_branch_check +󱓐 md_puzzle_plus +󱓑 md_puzzle_minus +󱓒 md_puzzle_remove +󱓓 md_puzzle_edit +󱓔 md_puzzle_heart +󱓕 md_puzzle_star +󱓖 md_puzzle_plus_outline +󱓗 md_puzzle_minus_outline +󱓘 md_puzzle_remove_outline +󱓙 md_puzzle_edit_outline +󱓚 md_puzzle_heart_outline +󱓛 md_puzzle_star_outline +󱓜 md_rhombus_medium_outline +󱓝 md_rhombus_split_outline +󱓞 md_rocket_launch +󱓟 md_rocket_launch_outline +󱓠 md_set_merge +󱓡 md_set_split +󱓢 md_beekeeper +󱓣 md_snowflake_off +󱓤 md_weather_sunny_off +󱓥 md_clipboard_edit +󱓦 md_clipboard_edit_outline +󱓧 md_notebook_edit +󱓨 md_human_edit +󱓩 md_notebook_edit_outline +󱓪 md_cash_lock +󱓫 md_cash_lock_open +󱓬 md_account_supervisor_circle_outline +󱓭 md_car_outline +󱓮 md_cash_check +󱓯 md_filter_off +󱓰 md_filter_off_outline +󱓱 md_spirit_level +󱓲 md_wheel_barrow +󱓳 md_book_check +󱓴 md_book_check_outline +󱓵 md_notebook_check +󱓶 md_notebook_check_outline +󱓷 md_book_open_variant +󱓸 md_sign_pole +󱓹 md_shore +󱓺 md_shape_square_rounded_plus +󱓻 md_square_rounded +󱓼 md_square_rounded_outline +󱓽 md_archive_alert +󱓾 md_archive_alert_outline +󱓿 md_power_socket_it +󱔀 md_square_circle +󱔁 md_symbol +󱔂 md_water_alert +󱔃 md_water_alert_outline +󱔄 md_water_check +󱔅 md_water_check_outline +󱔆 md_water_minus +󱔇 md_water_minus_outline +󱔈 md_water_off_outline +󱔉 md_water_percent_alert +󱔊 md_water_plus +󱔋 md_water_plus_outline +󱔌 md_water_remove +󱔍 md_water_remove_outline +󱔎 md_snake +󱔏 md_format_text_variant_outline +󱔐 md_grass +󱔑 md_access_point_off +󱔒 md_currency_mnt +󱔓 md_dock_top +󱔔 md_share_variant_outline +󱔕 md_transit_skip +󱔖 md_yurt +󱔗 md_file_document_multiple +󱔘 md_file_document_multiple_outline +󱔙 md_ev_plug_ccs1 +󱔚 md_ev_plug_ccs2 +󱔛 md_ev_plug_chademo +󱔜 md_ev_plug_tesla +󱔝 md_ev_plug_type1 +󱔞 md_ev_plug_type2 +󱔟 md_office_building_outline +󱔠 md_office_building_marker +󱔡 md_office_building_marker_outline +󱔢 md_progress_question +󱔣 md_basket_minus +󱔤 md_basket_minus_outline +󱔥 md_basket_off +󱔦 md_basket_off_outline +󱔧 md_basket_plus +󱔨 md_basket_plus_outline +󱔩 md_basket_remove +󱔪 md_basket_remove_outline +󱔫 md_account_reactivate +󱔬 md_account_reactivate_outline +󱔭 md_car_lifted_pickup +󱔮 md_video_high_definition +󱔯 md_phone_remove +󱔰 md_phone_remove_outline +󱔱 md_thermometer_off +󱔲 md_timeline_check +󱔳 md_timeline_check_outline +󱔴 md_timeline_minus +󱔵 md_timeline_minus_outline +󱔶 md_timeline_remove +󱔷 md_timeline_remove_outline +󱔸 md_access_point_check +󱔹 md_access_point_minus +󱔺 md_access_point_plus +󱔻 md_access_point_remove +󱔼 md_data_matrix +󱔽 md_data_matrix_edit +󱔾 md_data_matrix_minus +󱔿 md_data_matrix_plus +󱕀 md_data_matrix_remove +󱕁 md_data_matrix_scan +󱕂 md_tune_variant +󱕃 md_tune_vertical_variant +󱕄 md_rake +󱕅 md_shimmer +󱕆 md_transit_connection_horizontal +󱕇 md_sort_calendar_ascending +󱕈 md_sort_calendar_descending +󱕉 md_sort_clock_ascending +󱕊 md_sort_clock_ascending_outline +󱕋 md_sort_clock_descending +󱕌 md_sort_clock_descending_outline +󱕍 md_chart_box +󱕎 md_chart_box_outline +󱕏 md_chart_box_plus_outline +󱕐 md_mouse_move_down +󱕑 md_mouse_move_up +󱕒 md_mouse_move_vertical +󱕓 md_pitchfork +󱕔 md_vanish_quarter +󱕕 md_application_settings_outline +󱕖 md_delete_clock +󱕗 md_delete_clock_outline +󱕘 md_kangaroo +󱕙 md_phone_dial +󱕚 md_phone_dial_outline +󱕛 md_star_off_outline +󱕜 md_tooltip_check +󱕝 md_tooltip_check_outline +󱕞 md_tooltip_minus +󱕟 md_tooltip_minus_outline +󱕠 md_tooltip_remove +󱕡 md_tooltip_remove_outline +󱕢 md_pretzel +󱕣 md_star_plus +󱕤 md_star_minus +󱕥 md_star_remove +󱕦 md_star_check +󱕧 md_star_plus_outline +󱕨 md_star_minus_outline +󱕩 md_star_remove_outline +󱕪 md_star_check_outline +󱕫 md_eiffel_tower +󱕬 md_submarine +󱕭 md_sofa_outline +󱕮 md_sofa_single +󱕯 md_sofa_single_outline +󱕰 md_text_account +󱕱 md_human_queue +󱕲 md_food_halal +󱕳 md_food_kosher +󱕴 md_key_chain +󱕵 md_key_chain_variant +󱕶 md_lamps +󱕷 md_application_cog_outline +󱕸 md_dance_pole +󱕹 md_social_distance_2_meters +󱕺 md_social_distance_6_feet +󱕻 md_calendar_cursor +󱕼 md_emoticon_sick +󱕽 md_emoticon_sick_outline +󱕾 md_hand_heart_outline +󱕿 md_hand_wash +󱖀 md_hand_wash_outline +󱖁 md_human_cane +󱖂 md_lotion +󱖃 md_lotion_outline +󱖄 md_lotion_plus +󱖅 md_lotion_plus_outline +󱖆 md_face_mask +󱖇 md_face_mask_outline +󱖈 md_reiterate +󱖉 md_butterfly +󱖊 md_butterfly_outline +󱖋 md_bag_suitcase +󱖌 md_bag_suitcase_outline +󱖍 md_bag_suitcase_off +󱖎 md_bag_suitcase_off_outline +󱖏 md_motion_play +󱖐 md_motion_pause +󱖑 md_motion_play_outline +󱖒 md_motion_pause_outline +󱖓 md_arrow_top_left_thin_circle_outline +󱖔 md_arrow_top_right_thin_circle_outline +󱖕 md_arrow_bottom_right_thin_circle_outline +󱖖 md_arrow_bottom_left_thin_circle_outline +󱖗 md_arrow_up_thin_circle_outline +󱖘 md_arrow_right_thin_circle_outline +󱖙 md_arrow_down_thin_circle_outline +󱖚 md_arrow_left_thin_circle_outline +󱖛 md_human_capacity_decrease +󱖜 md_human_capacity_increase +󱖝 md_human_greeting_proximity +󱖞 md_hvac_off +󱖟 md_inbox_remove +󱖠 md_inbox_remove_outline +󱖡 md_handshake_outline +󱖢 md_ladder +󱖣 md_router_wireless_off +󱖤 md_seesaw +󱖥 md_slide +󱖦 md_calculator_variant_outline +󱖧 md_shield_account_variant +󱖨 md_shield_account_variant_outline +󱖩 md_message_flash +󱖪 md_message_flash_outline +󱖫 md_list_status +󱖬 md_message_bookmark +󱖭 md_message_bookmark_outline +󱖮 md_comment_bookmark +󱖯 md_comment_bookmark_outline +󱖰 md_comment_flash +󱖱 md_comment_flash_outline +󱖲 md_motion +󱖳 md_motion_outline +󱖴 md_bicycle_electric +󱖵 md_car_electric_outline +󱖶 md_chart_timeline_variant_shimmer +󱖷 md_moped_electric +󱖸 md_moped_electric_outline +󱖹 md_moped_outline +󱖺 md_motorbike_electric +󱖻 md_rickshaw +󱖼 md_rickshaw_electric +󱖽 md_scooter +󱖾 md_scooter_electric +󱖿 md_horse +󱗀 md_horse_human +󱗁 md_horse_variant +󱗂 md_unicorn +󱗃 md_unicorn_variant +󱗄 md_alarm_panel +󱗅 md_alarm_panel_outline +󱗆 md_bird +󱗇 md_shoe_cleat +󱗈 md_shoe_sneaker +󱗉 md_human_female_dance +󱗊 md_shoe_ballet +󱗋 md_numeric_positive_1 +󱗌 md_face_man_shimmer +󱗍 md_face_man_shimmer_outline +󱗎 md_face_woman_shimmer +󱗏 md_face_woman_shimmer_outline +󱗐 md_home_alert_outline +󱗑 md_lock_alert_outline +󱗒 md_lock_open_alert_outline +󱗓 md_sim_alert_outline +󱗔 md_sim_off_outline +󱗕 md_sim_outline +󱗖 md_book_open_page_variant_outline +󱗗 md_fire_alert +󱗘 md_ray_start_vertex_end +󱗙 md_camera_flip +󱗚 md_camera_flip_outline +󱗛 md_orbit_variant +󱗜 md_circle_box +󱗝 md_circle_box_outline +󱗞 md_mustache +󱗟 md_comment_minus +󱗠 md_comment_minus_outline +󱗡 md_comment_off +󱗢 md_comment_off_outline +󱗣 md_eye_remove +󱗤 md_eye_remove_outline +󱗥 md_unicycle +󱗦 md_glass_cocktail_off +󱗧 md_glass_mug_off +󱗨 md_glass_mug_variant_off +󱗩 md_bicycle_penny_farthing +󱗪 md_cart_check +󱗫 md_cart_variant +󱗬 md_baseball_diamond +󱗭 md_baseball_diamond_outline +󱗮 md_fridge_industrial +󱗯 md_fridge_industrial_alert +󱗰 md_fridge_industrial_alert_outline +󱗱 md_fridge_industrial_off +󱗲 md_fridge_industrial_off_outline +󱗳 md_fridge_industrial_outline +󱗴 md_fridge_variant +󱗵 md_fridge_variant_alert +󱗶 md_fridge_variant_alert_outline +󱗷 md_fridge_variant_off +󱗸 md_fridge_variant_off_outline +󱗹 md_fridge_variant_outline +󱗺 md_windsock +󱗻 md_dance_ballroom +󱗼 md_dots_grid +󱗽 md_dots_square +󱗾 md_dots_triangle +󱗿 md_dots_hexagon +󱘀 md_card_minus +󱘁 md_card_minus_outline +󱘂 md_card_off +󱘃 md_card_off_outline +󱘄 md_card_remove +󱘅 md_card_remove_outline +󱘆 md_torch +󱘇 md_navigation_outline +󱘈 md_map_marker_star +󱘉 md_map_marker_star_outline +󱘊 md_manjaro +󱘋 md_fast_forward_60 +󱘌 md_rewind_60 +󱘍 md_image_text +󱘎 md_family_tree +󱘏 md_car_emergency +󱘐 md_notebook_minus +󱘑 md_notebook_minus_outline +󱘒 md_notebook_plus +󱘓 md_notebook_plus_outline +󱘔 md_notebook_remove +󱘕 md_notebook_remove_outline +󱘖 md_connection +󱘗 md_language_rust +󱘘 md_clipboard_minus +󱘙 md_clipboard_minus_outline +󱘚 md_clipboard_off +󱘛 md_clipboard_off_outline +󱘜 md_clipboard_remove +󱘝 md_clipboard_remove_outline +󱘞 md_clipboard_search +󱘟 md_clipboard_search_outline +󱘠 md_clipboard_text_off +󱘡 md_clipboard_text_off_outline +󱘢 md_clipboard_text_search +󱘣 md_clipboard_text_search_outline +󱘤 md_database_alert_outline +󱘥 md_database_arrow_down_outline +󱘦 md_database_arrow_left_outline +󱘧 md_database_arrow_right_outline +󱘨 md_database_arrow_up_outline +󱘩 md_database_check_outline +󱘪 md_database_clock_outline +󱘫 md_database_edit_outline +󱘬 md_database_export_outline +󱘭 md_database_import_outline +󱘮 md_database_lock_outline +󱘯 md_database_marker_outline +󱘰 md_database_minus_outline +󱘱 md_database_off_outline +󱘲 md_database_outline +󱘳 md_database_plus_outline +󱘴 md_database_refresh_outline +󱘵 md_database_remove_outline +󱘶 md_database_search_outline +󱘷 md_database_settings_outline +󱘸 md_database_sync_outline +󱘹 md_minus_thick +󱘺 md_database_alert +󱘻 md_database_arrow_down +󱘼 md_database_arrow_left +󱘽 md_database_arrow_right +󱘾 md_database_arrow_up +󱘿 md_database_clock +󱙀 md_database_off +󱙁 md_calendar_lock +󱙂 md_calendar_lock_outline +󱙃 md_content_save_off +󱙄 md_content_save_off_outline +󱙅 md_credit_card_refresh +󱙆 md_credit_card_refresh_outline +󱙇 md_credit_card_search +󱙈 md_credit_card_search_outline +󱙉 md_credit_card_sync +󱙊 md_credit_card_sync_outline +󱙋 md_database_cog +󱙌 md_database_cog_outline +󱙍 md_message_off +󱙎 md_message_off_outline +󱙏 md_note_minus +󱙐 md_note_minus_outline +󱙑 md_note_remove +󱙒 md_note_remove_outline +󱙓 md_note_search +󱙔 md_note_search_outline +󱙕 md_bank_check +󱙖 md_bank_off +󱙗 md_bank_off_outline +󱙘 md_briefcase_off +󱙙 md_briefcase_off_outline +󱙚 md_briefcase_variant_off +󱙛 md_briefcase_variant_off_outline +󱙜 md_ghost_off_outline +󱙝 md_ghost_outline +󱙞 md_store_minus +󱙟 md_store_plus +󱙠 md_store_remove +󱙡 md_email_remove +󱙢 md_email_remove_outline +󱙣 md_heart_cog +󱙤 md_heart_cog_outline +󱙥 md_heart_settings +󱙦 md_heart_settings_outline +󱙧 md_pentagram +󱙨 md_star_cog +󱙩 md_star_cog_outline +󱙪 md_star_settings +󱙫 md_star_settings_outline +󱙬 md_calendar_end +󱙭 md_calendar_start +󱙮 md_cannabis_off +󱙯 md_mower +󱙰 md_mower_bag +󱙱 md_lock_off +󱙲 md_lock_off_outline +󱙳 md_shark_fin +󱙴 md_shark_fin_outline +󱙵 md_paw_outline +󱙶 md_paw_off_outline +󱙷 md_snail +󱙸 md_pig_variant_outline +󱙹 md_piggy_bank_outline +󱙺 md_robot_outline +󱙻 md_robot_off_outline +󱙼 md_book_alert +󱙽 md_book_alert_outline +󱙾 md_book_arrow_down +󱙿 md_book_arrow_down_outline +󱚀 md_book_arrow_left +󱚁 md_book_arrow_left_outline +󱚂 md_book_arrow_right +󱚃 md_book_arrow_right_outline +󱚄 md_book_arrow_up +󱚅 md_book_arrow_up_outline +󱚆 md_book_cancel +󱚇 md_book_cancel_outline +󱚈 md_book_clock +󱚉 md_book_clock_outline +󱚊 md_book_cog +󱚋 md_book_cog_outline +󱚌 md_book_edit +󱚍 md_book_edit_outline +󱚎 md_book_lock_open_outline +󱚏 md_book_lock_outline +󱚐 md_book_marker +󱚑 md_book_marker_outline +󱚒 md_book_minus_outline +󱚓 md_book_music_outline +󱚔 md_book_off +󱚕 md_book_off_outline +󱚖 md_book_plus_outline +󱚗 md_book_refresh +󱚘 md_book_refresh_outline +󱚙 md_book_remove_outline +󱚚 md_book_settings +󱚛 md_book_settings_outline +󱚜 md_book_sync +󱚝 md_robot_angry +󱚞 md_robot_angry_outline +󱚟 md_robot_confused +󱚠 md_robot_confused_outline +󱚡 md_robot_dead +󱚢 md_robot_dead_outline +󱚣 md_robot_excited +󱚤 md_robot_excited_outline +󱚥 md_robot_love +󱚦 md_robot_love_outline +󱚧 md_robot_off +󱚨 md_lock_check_outline +󱚩 md_lock_minus +󱚪 md_lock_minus_outline +󱚫 md_lock_open_check_outline +󱚬 md_lock_open_minus +󱚭 md_lock_open_minus_outline +󱚮 md_lock_open_plus +󱚯 md_lock_open_plus_outline +󱚰 md_lock_open_remove +󱚱 md_lock_open_remove_outline +󱚲 md_lock_plus_outline +󱚳 md_lock_remove +󱚴 md_lock_remove_outline +󱚵 md_wifi_alert +󱚶 md_wifi_arrow_down +󱚷 md_wifi_arrow_left +󱚸 md_wifi_arrow_left_right +󱚹 md_wifi_arrow_right +󱚺 md_wifi_arrow_up +󱚻 md_wifi_arrow_up_down +󱚼 md_wifi_cancel +󱚽 md_wifi_check +󱚾 md_wifi_cog +󱚿 md_wifi_lock +󱛀 md_wifi_lock_open +󱛁 md_wifi_marker +󱛂 md_wifi_minus +󱛃 md_wifi_plus +󱛄 md_wifi_refresh +󱛅 md_wifi_remove +󱛆 md_wifi_settings +󱛇 md_wifi_sync +󱛈 md_book_sync_outline +󱛉 md_book_education +󱛊 md_book_education_outline +󱛋 md_wifi_strength_1_lock_open +󱛌 md_wifi_strength_2_lock_open +󱛍 md_wifi_strength_3_lock_open +󱛎 md_wifi_strength_4_lock_open +󱛏 md_wifi_strength_lock_open_outline +󱛐 md_cookie_alert +󱛑 md_cookie_alert_outline +󱛒 md_cookie_check +󱛓 md_cookie_check_outline +󱛔 md_cookie_cog +󱛕 md_cookie_cog_outline +󱛖 md_cookie_plus +󱛗 md_cookie_plus_outline +󱛘 md_cookie_remove +󱛙 md_cookie_remove_outline +󱛚 md_cookie_minus +󱛛 md_cookie_minus_outline +󱛜 md_cookie_settings +󱛝 md_cookie_settings_outline +󱛞 md_cookie_outline +󱛟 md_tape_drive +󱛠 md_abacus +󱛡 md_calendar_clock_outline +󱛢 md_clipboard_clock +󱛣 md_clipboard_clock_outline +󱛤 md_cookie_clock +󱛥 md_cookie_clock_outline +󱛦 md_cookie_edit +󱛧 md_cookie_edit_outline +󱛨 md_cookie_lock +󱛩 md_cookie_lock_outline +󱛪 md_cookie_off +󱛫 md_cookie_off_outline +󱛬 md_cookie_refresh +󱛭 md_cookie_refresh_outline +󱛮 md_dog_side_off +󱛯 md_gift_off +󱛰 md_gift_off_outline +󱛱 md_gift_open +󱛲 md_gift_open_outline +󱛳 md_movie_check +󱛴 md_movie_check_outline +󱛵 md_movie_cog +󱛶 md_movie_cog_outline +󱛷 md_movie_minus +󱛸 md_movie_minus_outline +󱛹 md_movie_off +󱛺 md_movie_off_outline +󱛻 md_movie_open_check +󱛼 md_movie_open_check_outline +󱛽 md_movie_open_cog +󱛾 md_movie_open_cog_outline +󱛿 md_movie_open_edit +󱜀 md_movie_open_edit_outline +󱜁 md_movie_open_minus +󱜂 md_movie_open_minus_outline +󱜃 md_movie_open_off +󱜄 md_movie_open_off_outline +󱜅 md_movie_open_play +󱜆 md_movie_open_play_outline +󱜇 md_movie_open_plus +󱜈 md_movie_open_plus_outline +󱜉 md_movie_open_remove +󱜊 md_movie_open_remove_outline +󱜋 md_movie_open_settings +󱜌 md_movie_open_settings_outline +󱜍 md_movie_open_star +󱜎 md_movie_open_star_outline +󱜏 md_movie_play +󱜐 md_movie_play_outline +󱜑 md_movie_plus +󱜒 md_movie_plus_outline +󱜓 md_movie_remove +󱜔 md_movie_remove_outline +󱜕 md_movie_settings +󱜖 md_movie_settings_outline +󱜗 md_movie_star +󱜘 md_movie_star_outline +󱜙 md_robot_happy +󱜚 md_robot_happy_outline +󱜛 md_turkey +󱜜 md_food_turkey +󱜝 md_fan_auto +󱜞 md_alarm_light_off +󱜟 md_alarm_light_off_outline +󱜠 md_broadcast +󱜡 md_broadcast_off +󱜢 md_fire_off +󱜣 md_firework_off +󱜤 md_projector_screen_outline +󱜥 md_script_text_key +󱜦 md_script_text_key_outline +󱜧 md_script_text_play +󱜨 md_script_text_play_outline +󱜩 md_surround_sound_2_1 +󱜪 md_surround_sound_5_1_2 +󱜫 md_tag_arrow_down +󱜬 md_tag_arrow_down_outline +󱜭 md_tag_arrow_left +󱜮 md_tag_arrow_left_outline +󱜯 md_tag_arrow_right +󱜰 md_tag_arrow_right_outline +󱜱 md_tag_arrow_up +󱜲 md_tag_arrow_up_outline +󱜳 md_train_car_passenger +󱜴 md_train_car_passenger_door +󱜵 md_train_car_passenger_door_open +󱜶 md_train_car_passenger_variant +󱜷 md_webcam_off +󱜸 md_chat_question +󱜹 md_chat_question_outline +󱜺 md_message_question +󱜻 md_message_question_outline +󱜼 md_kettle_pour_over +󱜽 md_message_reply_outline +󱜾 md_message_reply_text_outline +󱜿 md_koala +󱝀 md_check_decagram_outline +󱝁 md_star_shooting +󱝂 md_star_shooting_outline +󱝃 md_table_picnic +󱝄 md_kitesurfing +󱝅 md_paragliding +󱝆 md_surfing +󱝇 md_floor_lamp_torchiere +󱝈 md_mortar_pestle +󱝉 md_cast_audio_variant +󱝊 md_gradient_horizontal +󱝋 md_archive_cancel +󱝌 md_archive_cancel_outline +󱝍 md_archive_check +󱝎 md_archive_check_outline +󱝏 md_archive_clock +󱝐 md_archive_clock_outline +󱝑 md_archive_cog +󱝒 md_archive_cog_outline +󱝓 md_archive_edit +󱝔 md_archive_edit_outline +󱝕 md_archive_eye +󱝖 md_archive_eye_outline +󱝗 md_archive_lock +󱝘 md_archive_lock_open +󱝙 md_archive_lock_open_outline +󱝚 md_archive_lock_outline +󱝛 md_archive_marker +󱝜 md_archive_marker_outline +󱝝 md_archive_minus +󱝞 md_archive_minus_outline +󱝟 md_archive_music +󱝠 md_archive_music_outline +󱝡 md_archive_off +󱝢 md_archive_off_outline +󱝣 md_archive_plus +󱝤 md_archive_plus_outline +󱝥 md_archive_refresh +󱝦 md_archive_refresh_outline +󱝧 md_archive_remove +󱝨 md_archive_remove_outline +󱝩 md_archive_search +󱝪 md_archive_search_outline +󱝫 md_archive_settings +󱝬 md_archive_settings_outline +󱝭 md_archive_star +󱝮 md_archive_star_outline +󱝯 md_archive_sync +󱝰 md_archive_sync_outline +󱝱 md_brush_off +󱝲 md_file_image_marker +󱝳 md_file_image_marker_outline +󱝴 md_file_marker +󱝵 md_file_marker_outline +󱝶 md_hamburger_check +󱝷 md_hamburger_minus +󱝸 md_hamburger_off +󱝹 md_hamburger_plus +󱝺 md_hamburger_remove +󱝻 md_image_marker +󱝼 md_image_marker_outline +󱝽 md_note_alert +󱝾 md_note_alert_outline +󱝿 md_note_check +󱞀 md_note_check_outline +󱞁 md_note_edit +󱞂 md_note_edit_outline +󱞃 md_note_off +󱞄 md_note_off_outline +󱞅 md_printer_off_outline +󱞆 md_printer_outline +󱞇 md_progress_pencil +󱞈 md_progress_star +󱞉 md_sausage_off +󱞊 md_folder_eye +󱞋 md_folder_eye_outline +󱞌 md_information_off +󱞍 md_information_off_outline +󱞎 md_sticker_text +󱞏 md_sticker_text_outline +󱞐 md_web_cancel +󱞑 md_web_refresh +󱞒 md_web_sync +󱞓 md_chandelier +󱞔 md_home_switch +󱞕 md_home_switch_outline +󱞖 md_sun_snowflake +󱞗 md_ceiling_fan +󱞘 md_ceiling_fan_light +󱞙 md_smoke +󱞚 md_fence +󱞛 md_light_recessed +󱞜 md_battery_lock +󱞝 md_battery_lock_open +󱞞 md_folder_hidden +󱞟 md_mirror_rectangle +󱞠 md_mirror_variant +󱞡 md_arrow_down_left +󱞢 md_arrow_down_left_bold +󱞣 md_arrow_down_right +󱞤 md_arrow_down_right_bold +󱞥 md_arrow_left_bottom +󱞦 md_arrow_left_bottom_bold +󱞧 md_arrow_left_top +󱞨 md_arrow_left_top_bold +󱞩 md_arrow_right_bottom +󱞪 md_arrow_right_bottom_bold +󱞫 md_arrow_right_top +󱞬 md_arrow_right_top_bold +󱞭 md_arrow_u_down_left +󱞮 md_arrow_u_down_left_bold +󱞯 md_arrow_u_down_right +󱞰 md_arrow_u_down_right_bold +󱞱 md_arrow_u_left_bottom +󱞲 md_arrow_u_left_bottom_bold +󱞳 md_arrow_u_left_top +󱞴 md_arrow_u_left_top_bold +󱞵 md_arrow_u_right_bottom +󱞶 md_arrow_u_right_bottom_bold +󱞷 md_arrow_u_right_top +󱞸 md_arrow_u_right_top_bold +󱞹 md_arrow_u_up_left +󱞺 md_arrow_u_up_left_bold +󱞻 md_arrow_u_up_right +󱞼 md_arrow_u_up_right_bold +󱞽 md_arrow_up_left +󱞾 md_arrow_up_left_bold +󱞿 md_arrow_up_right +󱟀 md_arrow_up_right_bold +󱟁 md_select_remove +󱟂 md_selection_ellipse_remove +󱟃 md_selection_remove +󱟄 md_human_greeting +󱟅 md_ph +󱟆 md_water_sync +󱟇 md_ceiling_light_outline +󱟈 md_floor_lamp_outline +󱟉 md_wall_sconce_flat_outline +󱟊 md_wall_sconce_flat_variant_outline +󱟋 md_wall_sconce_outline +󱟌 md_wall_sconce_round_outline +󱟍 md_wall_sconce_round_variant_outline +󱟎 md_floor_lamp_dual_outline +󱟏 md_floor_lamp_torchiere_variant_outline +󱟐 md_lamp_outline +󱟑 md_lamps_outline +󱟒 md_candelabra +󱟓 md_candelabra_fire +󱟔 md_menorah +󱟕 md_menorah_fire +󱟖 md_floor_lamp_torchiere_outline +󱟗 md_credit_card_edit +󱟘 md_credit_card_edit_outline +󱟙 md_briefcase_eye +󱟚 md_briefcase_eye_outline +󱟛 md_soundbar +󱟜 md_crown_circle +󱟝 md_crown_circle_outline +󱟞 md_battery_arrow_down +󱟟 md_battery_arrow_down_outline +󱟠 md_battery_arrow_up +󱟡 md_battery_arrow_up_outline +󱟢 md_battery_check +󱟣 md_battery_check_outline +󱟤 md_battery_minus +󱟥 md_battery_minus_outline +󱟦 md_battery_plus +󱟧 md_battery_plus_outline +󱟨 md_battery_remove +󱟩 md_battery_remove_outline +󱟪 md_chili_alert +󱟫 md_chili_alert_outline +󱟬 md_chili_hot_outline +󱟭 md_chili_medium_outline +󱟮 md_chili_mild_outline +󱟯 md_chili_off_outline +󱟰 md_cake_variant_outline +󱟱 md_card_multiple +󱟲 md_card_multiple_outline +󱟳 md_account_cowboy_hat_outline +󱟴 md_lightbulb_spot +󱟵 md_lightbulb_spot_off +󱟶 md_fence_electric +󱟷 md_gate_arrow_left +󱟸 md_gate_alert +󱟹 md_boom_gate_up +󱟺 md_boom_gate_up_outline +󱟻 md_garage_lock +󱟼 md_garage_variant_lock +󱟽 md_cellphone_check +󱟾 md_sun_wireless +󱟿 md_sun_wireless_outline +󱠀 md_lightbulb_auto +󱠁 md_lightbulb_auto_outline +󱠂 md_lightbulb_variant +󱠃 md_lightbulb_variant_outline +󱠄 md_lightbulb_fluorescent_tube +󱠅 md_lightbulb_fluorescent_tube_outline +󱠆 md_water_circle +󱠇 md_fire_circle +󱠈 md_smoke_detector_outline +󱠉 md_smoke_detector_off +󱠊 md_smoke_detector_off_outline +󱠋 md_smoke_detector_variant +󱠌 md_smoke_detector_variant_off +󱠍 md_projector_screen_off +󱠎 md_projector_screen_off_outline +󱠏 md_projector_screen_variant +󱠐 md_projector_screen_variant_off +󱠑 md_projector_screen_variant_off_outline +󱠒 md_projector_screen_variant_outline +󱠓 md_brush_variant +󱠔 md_car_wrench +󱠕 md_account_injury +󱠖 md_account_injury_outline +󱠗 md_balcony +󱠘 md_bathtub +󱠙 md_bathtub_outline +󱠚 md_blender_outline +󱠛 md_coffee_maker_outline +󱠜 md_countertop +󱠝 md_countertop_outline +󱠞 md_door_sliding +󱠟 md_door_sliding_lock +󱠠 md_door_sliding_open +󱠡 md_hand_wave +󱠢 md_hand_wave_outline +󱠣 md_human_male_female_child +󱠤 md_iron +󱠥 md_iron_outline +󱠦 md_liquid_spot +󱠧 md_mosque +󱠨 md_shield_moon +󱠩 md_shield_moon_outline +󱠪 md_traffic_light_outline +󱠫 md_hand_front_left +󱠬 md_hand_back_left_outline +󱠭 md_hand_back_right_outline +󱠮 md_hand_front_left_outline +󱠯 md_hand_front_right_outline +󱠰 md_hand_back_left_off +󱠱 md_hand_back_right_off +󱠲 md_hand_back_left_off_outline +󱠳 md_hand_back_right_off_outline +󱠴 md_battery_sync +󱠵 md_battery_sync_outline +󱠶 md_food_takeout_box +󱠷 md_food_takeout_box_outline +󱠸 md_iron_board +󱠹 md_police_station +󱠺 md_cellphone_marker +󱠻 md_tooltip_cellphone +󱠼 md_table_pivot +󱠽 md_tunnel +󱠾 md_tunnel_outline +󱠿 md_arrow_projectile_multiple +󱡀 md_arrow_projectile +󱡁 md_bow_arrow +󱡂 md_axe_battle +󱡃 md_mace +󱡄 md_magic_staff +󱡅 md_spear +󱡆 md_curtains +󱡇 md_curtains_closed +󱡈 md_human_non_binary +󱡉 md_waterfall +󱡊 md_egg_fried +󱡋 md_food_hot_dog +󱡌 md_induction +󱡍 md_pipe_valve +󱡎 md_shipping_pallet +󱡏 md_earbuds +󱡐 md_earbuds_off +󱡑 md_earbuds_off_outline +󱡒 md_earbuds_outline +󱡓 md_circle_opacity +󱡔 md_square_opacity +󱡕 md_water_opacity +󱡖 md_vector_polygon_variant +󱡗 md_vector_square_close +󱡘 md_vector_square_open +󱡙 md_waves_arrow_left +󱡚 md_waves_arrow_right +󱡛 md_waves_arrow_up +󱡜 md_cash_fast +󱡝 md_radioactive_circle +󱡞 md_radioactive_circle_outline +󱡟 md_cctv_off +󱡠 md_format_list_group +󱡡 md_clock_plus +󱡢 md_clock_plus_outline +󱡣 md_clock_minus +󱡤 md_clock_minus_outline +󱡥 md_clock_remove +󱡦 md_clock_remove_outline +󱡧 md_account_arrow_up +󱡨 md_account_arrow_down +󱡩 md_account_arrow_down_outline +󱡪 md_account_arrow_up_outline +󱡫 md_audio_input_rca +󱡬 md_audio_input_stereo_minijack +󱡭 md_audio_input_xlr +󱡮 md_horse_variant_fast +󱡯 md_email_fast +󱡰 md_email_fast_outline +󱡱 md_camera_document +󱡲 md_camera_document_off +󱡳 md_glass_fragile +󱡴 md_magnify_expand +󱡵 md_town_hall +󱡶 md_monitor_small +󱡷 md_diversify +󱡸 md_car_wireless +󱡹 md_car_select +󱡺 md_airplane_alert +󱡻 md_airplane_check +󱡼 md_airplane_clock +󱡽 md_airplane_cog +󱡾 md_airplane_edit +󱡿 md_airplane_marker +󱢀 md_airplane_minus +󱢁 md_airplane_plus +󱢂 md_airplane_remove +󱢃 md_airplane_search +󱢄 md_airplane_settings +󱢅 md_flower_pollen +󱢆 md_flower_pollen_outline +󱢇 md_hammer_sickle +󱢈 md_view_gallery +󱢉 md_view_gallery_outline +󱢊 md_umbrella_beach +󱢋 md_umbrella_beach_outline +󱢌 md_cabin_a_frame +󱢍 md_all_inclusive_box +󱢎 md_all_inclusive_box_outline +󱢏 md_hand_coin +󱢐 md_hand_coin_outline +󱢑 md_truck_flatbed +󱢒 md_layers_edit +󱢓 md_multicast +󱢔 md_hydrogen_station +󱢕 md_thermometer_bluetooth +󱢖 md_tire +󱢗 md_forest +󱢘 md_account_tie_hat +󱢙 md_account_tie_hat_outline +󱢚 md_account_wrench +󱢛 md_account_wrench_outline +󱢜 md_bicycle_cargo +󱢝 md_calendar_collapse_horizontal +󱢞 md_calendar_expand_horizontal +󱢟 md_cards_club_outline +󱢠 md_heart_outline +󱢡 md_cards_playing +󱢢 md_cards_playing_club +󱢣 md_cards_playing_club_multiple +󱢤 md_cards_playing_club_multiple_outline +󱢥 md_cards_playing_club_outline +󱢦 md_cards_playing_diamond +󱢧 md_cards_playing_diamond_multiple +󱢨 md_cards_playing_diamond_multiple_outline +󱢩 md_cards_playing_diamond_outline +󱢪 md_cards_playing_heart +󱢫 md_cards_playing_heart_multiple +󱢬 md_cards_playing_heart_multiple_outline +󱢭 md_cards_playing_heart_outline +󱢮 md_cards_playing_spade +󱢯 md_cards_playing_spade_multiple +󱢰 md_cards_playing_spade_multiple_outline +󱢱 md_cards_playing_spade_outline +󱢲 md_cards_spade_outline +󱢳 md_compare_remove +󱢴 md_dolphin +󱢵 md_fuel_cell +󱢶 md_hand_extended +󱢷 md_hand_extended_outline +󱢸 md_printer_3d_nozzle_heat +󱢹 md_printer_3d_nozzle_heat_outline +󱢺 md_shark +󱢻 md_shark_off +󱢼 md_shield_crown +󱢽 md_shield_crown_outline +󱢾 md_shield_sword +󱢿 md_shield_sword_outline +󱣀 md_sickle +󱣁 md_store_alert +󱣂 md_store_alert_outline +󱣃 md_store_check +󱣄 md_store_check_outline +󱣅 md_store_clock +󱣆 md_store_clock_outline +󱣇 md_store_cog +󱣈 md_store_cog_outline +󱣉 md_store_edit +󱣊 md_store_edit_outline +󱣋 md_store_marker +󱣌 md_store_marker_outline +󱣍 md_store_minus_outline +󱣎 md_store_off +󱣏 md_store_off_outline +󱣐 md_store_plus_outline +󱣑 md_store_remove_outline +󱣒 md_store_search +󱣓 md_store_search_outline +󱣔 md_store_settings +󱣕 md_store_settings_outline +󱣖 md_sun_thermometer +󱣗 md_sun_thermometer_outline +󱣘 md_truck_cargo_container +󱣙 md_vector_square_edit +󱣚 md_vector_square_minus +󱣛 md_vector_square_plus +󱣜 md_vector_square_remove +󱣝 md_ceiling_light_multiple +󱣞 md_ceiling_light_multiple_outline +󱣟 md_wiper_wash_alert +󱣠 md_cart_heart +󱣡 md_virus_off +󱣢 md_virus_off_outline +󱣣 md_map_marker_account +󱣤 md_map_marker_account_outline +󱣥 md_basket_check +󱣦 md_basket_check_outline +󱣧 md_credit_card_lock +󱣨 md_credit_card_lock_outline +󱣩 md_format_underline_wavy +󱣪 md_content_save_check +󱣫 md_content_save_check_outline +󱣬 md_filter_check +󱣭 md_filter_check_outline +󱣮 md_flag_off +󱣯 md_flag_off_outline +󱣰 md_near_me +󱣱 md_navigation_variant_outline +󱣲 md_refresh_auto +󱣳 md_tilde_off +󱣴 md_fit_to_screen +󱣵 md_fit_to_screen_outline +󱣶 md_weather_cloudy_clock +󱣷 md_smart_card_off +󱣸 md_smart_card_off_outline +󱣹 md_clipboard_text_clock +󱣺 md_clipboard_text_clock_outline +󱣻 md_teddy_bear +󱣼 md_cow_off +󱣽 md_eye_arrow_left +󱣾 md_eye_arrow_left_outline +󱣿 md_eye_arrow_right +󱤀 md_eye_arrow_right_outline +󱤁 md_home_battery +󱤂 md_home_battery_outline +󱤃 md_home_lightning_bolt +󱤄 md_home_lightning_bolt_outline +󱤅 md_leaf_circle +󱤆 md_leaf_circle_outline +󱤇 md_tag_search +󱤈 md_tag_search_outline +󱤉 md_car_brake_fluid_level +󱤊 md_car_brake_low_pressure +󱤋 md_car_brake_temperature +󱤌 md_car_brake_worn_linings +󱤍 md_car_light_alert +󱤎 md_car_speed_limiter +󱤏 md_credit_card_chip +󱤐 md_credit_card_chip_outline +󱤑 md_credit_card_fast +󱤒 md_credit_card_fast_outline +󱤓 md_integrated_circuit_chip +󱤔 md_thumbs_up_down_outline +󱤕 md_food_off_outline +󱤖 md_food_outline +󱤗 md_format_page_split +󱤘 md_chart_waterfall +󱤙 md_gamepad_outline +󱤚 md_network_strength_4_cog +󱤛 md_account_sync +󱤜 md_account_sync_outline +󱤝 md_bus_electric +󱤞 md_liquor +󱤟 md_database_eye +󱤠 md_database_eye_off +󱤡 md_database_eye_off_outline +󱤢 md_database_eye_outline +󱤣 md_timer_settings +󱤤 md_timer_settings_outline +󱤥 md_timer_cog +󱤦 md_timer_cog_outline +󱤧 md_checkbox_marked_circle_plus_outline +󱤨 md_panorama_horizontal +󱤩 md_panorama_vertical +󱤪 md_advertisements +󱤫 md_advertisements_off +󱤬 md_transmission_tower_export +󱤭 md_transmission_tower_import +󱤮 md_smoke_detector_alert +󱤯 md_smoke_detector_alert_outline +󱤰 md_smoke_detector_variant_alert +󱤱 md_coffee_maker_check +󱤲 md_coffee_maker_check_outline +󱤳 md_cog_pause +󱤴 md_cog_pause_outline +󱤵 md_cog_play +󱤶 md_cog_play_outline +󱤷 md_cog_stop +󱤸 md_cog_stop_outline +󱤹 md_copyleft +󱤺 md_fast_forward_15 +󱤻 md_file_image_minus +󱤼 md_file_image_minus_outline +󱤽 md_file_image_plus +󱤾 md_file_image_plus_outline +󱤿 md_file_image_remove +󱥀 md_file_image_remove_outline +󱥁 md_message_badge +󱥂 md_message_badge_outline +󱥃 md_newspaper_check +󱥄 md_newspaper_remove +󱥅 md_publish_off +󱥆 md_rewind_15 +󱥇 md_view_dashboard_edit +󱥈 md_view_dashboard_edit_outline +󱥉 md_office_building_cog +󱥊 md_office_building_cog_outline +󱥋 md_hand_clap +󱥌 md_cone +󱥍 md_cone_off +󱥎 md_cylinder +󱥏 md_cylinder_off +󱥐 md_octahedron +󱥑 md_octahedron_off +󱥒 md_pyramid +󱥓 md_pyramid_off +󱥔 md_sphere +󱥕 md_sphere_off +󱥖 md_format_letter_spacing +󱥗 md_french_fries +󱥘 md_scent +󱥙 md_scent_off +󱥚 md_palette_swatch_variant +󱥛 md_email_seal +󱥜 md_email_seal_outline +󱥝 md_stool +󱥞 md_stool_outline +󱥟 md_panorama_wide_angle +󱥠 md_account_lock_open +󱥡 md_account_lock_open_outline +󱥢 md_align_horizontal_distribute +󱥣 md_align_vertical_distribute +󱥤 md_arrow_bottom_left_bold_box +󱥥 md_arrow_bottom_left_bold_box_outline +󱥦 md_arrow_bottom_right_bold_box +󱥧 md_arrow_bottom_right_bold_box_outline +󱥨 md_arrow_top_left_bold_box +󱥩 md_arrow_top_left_bold_box_outline +󱥪 md_arrow_top_right_bold_box +󱥫 md_arrow_top_right_bold_box_outline +󱥬 md_bookmark_box_multiple +󱥭 md_bookmark_box_multiple_outline +󱥮 md_bullhorn_variant +󱥯 md_bullhorn_variant_outline +󱥰 md_candy +󱥱 md_candy_off +󱥲 md_candy_off_outline +󱥳 md_candy_outline +󱥴 md_car_clock +󱥵 md_crowd +󱥶 md_currency_rupee +󱥷 md_diving +󱥸 md_dots_circle +󱥹 md_elevator_passenger_off +󱥺 md_elevator_passenger_off_outline +󱥻 md_elevator_passenger_outline +󱥼 md_eye_refresh +󱥽 md_eye_refresh_outline +󱥾 md_folder_check +󱥿 md_folder_check_outline +󱦀 md_human_dolly +󱦁 md_human_white_cane +󱦂 md_ip_outline +󱦃 md_key_alert +󱦄 md_key_alert_outline +󱦅 md_kite +󱦆 md_kite_outline +󱦇 md_light_flood_down +󱦈 md_light_flood_up +󱦉 md_microphone_question +󱦊 md_microphone_question_outline +󱦋 md_cradle +󱦌 md_panorama_outline +󱦍 md_panorama_sphere +󱦎 md_panorama_sphere_outline +󱦏 md_panorama_variant +󱦐 md_panorama_variant_outline +󱦑 md_cradle_outline +󱦒 md_fraction_one_half +󱦓 md_phone_refresh +󱦔 md_phone_refresh_outline +󱦕 md_phone_sync +󱦖 md_phone_sync_outline +󱦗 md_razor_double_edge +󱦘 md_razor_single_edge +󱦙 md_rotate_360 +󱦚 md_shield_lock_open +󱦛 md_shield_lock_open_outline +󱦜 md_sitemap_outline +󱦝 md_sprinkler_fire +󱦞 md_tab_search +󱦟 md_timer_sand_complete +󱦠 md_timer_sand_paused +󱦡 md_vacuum +󱦢 md_vacuum_outline +󱦣 md_wrench_clock +󱦤 md_pliers +󱦥 md_sun_compass +󱦦 md_truck_snowflake +󱦧 md_camera_marker +󱦨 md_camera_marker_outline +󱦩 md_video_marker +󱦪 md_video_marker_outline +󱦫 md_wind_turbine_alert +󱦬 md_wind_turbine_check +󱦭 md_truck_plus +󱦮 md_truck_minus +󱦯 md_truck_remove +󱦰 md_arrow_right_thin +󱦱 md_arrow_left_thin +󱦲 md_arrow_up_thin +󱦳 md_arrow_down_thin +󱦴 md_arrow_top_right_thin +󱦵 md_arrow_top_left_thin +󱦶 md_arrow_bottom_left_thin +󱦷 md_arrow_bottom_right_thin +󱦸 md_scale_unbalanced +󱦹 md_draw_pen +󱦺 md_clock_edit +󱦻 md_clock_edit_outline +󱦼 md_truck_plus_outline +󱦽 md_truck_minus_outline +󱦾 md_truck_remove_outline +󱦿 md_camera_off_outline +󱧀 md_home_group_plus +󱧁 md_home_group_minus +󱧂 md_home_group_remove +󱧃 md_file_sign +󱧄 md_attachment_lock +󱧅 md_cellphone_arrow_down_variant +󱧆 md_file_chart_check +󱧇 md_file_chart_check_outline +󱧈 md_file_lock_open +󱧉 md_file_lock_open_outline +󱧊 md_folder_question +󱧋 md_folder_question_outline +󱧌 md_message_fast +󱧍 md_message_fast_outline +󱧎 md_message_text_fast +󱧏 md_message_text_fast_outline +󱧐 md_monitor_arrow_down +󱧑 md_monitor_arrow_down_variant +󱧒 md_needle_off +󱧓 md_numeric_off +󱧔 md_package_variant_closed_minus +󱧕 md_package_variant_closed_plus +󱧖 md_package_variant_closed_remove +󱧗 md_package_variant_minus +󱧘 md_package_variant_plus +󱧙 md_package_variant_remove +󱧚 md_paperclip_lock +󱧛 md_phone_clock +󱧜 md_receipt_outline +󱧝 md_transmission_tower_off +󱧞 md_truck_alert +󱧟 md_truck_alert_outline +󱧠 md_bone_off +󱧡 md_lightbulb_alert +󱧢 md_lightbulb_alert_outline +󱧣 md_lightbulb_question +󱧤 md_lightbulb_question_outline +󱧥 md_battery_clock +󱧦 md_battery_clock_outline +󱧧 md_autorenew_off +󱧨 md_folder_arrow_down +󱧩 md_folder_arrow_down_outline +󱧪 md_folder_arrow_left +󱧫 md_folder_arrow_left_outline +󱧬 md_folder_arrow_left_right +󱧭 md_folder_arrow_left_right_outline +󱧮 md_folder_arrow_right +󱧯 md_folder_arrow_right_outline +󱧰 md_folder_arrow_up +󱧱 md_folder_arrow_up_down +󱧲 md_folder_arrow_up_down_outline +󱧳 md_folder_arrow_up_outline +󱧴 md_folder_cancel +󱧵 md_folder_cancel_outline +󱧶 md_folder_file +󱧷 md_folder_file_outline +󱧸 md_folder_off +󱧹 md_folder_off_outline +󱧺 md_folder_play +󱧻 md_folder_play_outline +󱧼 md_folder_wrench +󱧽 md_folder_wrench_outline +󱧾 md_image_refresh +󱧿 md_image_refresh_outline +󱨀 md_image_sync +󱨁 md_image_sync_outline +󱨂 md_percent_box +󱨃 md_percent_box_outline +󱨄 md_percent_circle +󱨅 md_percent_circle_outline +󱨆 md_sale_outline +󱨇 md_square_rounded_badge +󱨈 md_square_rounded_badge_outline +󱨉 md_triangle_small_down +󱨊 md_triangle_small_up +󱨋 md_notebook_heart +󱨌 md_notebook_heart_outline +󱨍 md_brush_outline +󱨎 md_fruit_pear +󱨏 md_raw +󱨐 md_raw_off +󱨑 md_wall_fire +󱨒 md_home_clock +󱨓 md_home_clock_outline +󱨔 md_camera_lock +󱨕 md_camera_lock_outline +󱨖 md_play_box_lock +󱨗 md_play_box_lock_open +󱨘 md_play_box_lock_open_outline +󱨙 md_play_box_lock_outline +󱨚 md_robot_industrial_outline +󱨛 md_gas_burner +󱨜 md_video_2d +󱨝 md_book_heart +󱨞 md_book_heart_outline +󱨟 md_account_hard_hat_outline +󱨠 md_account_school +󱨡 md_account_school_outline +󱨢 md_library_outline +󱨣 md_projector_off +󱨤 md_light_switch_off +󱨥 md_toggle_switch_variant +󱨦 md_toggle_switch_variant_off +󱨧 md_asterisk_circle_outline +󱨨 md_barrel_outline +󱨩 md_bell_cog +󱨪 md_bell_cog_outline +󱨫 md_blinds_horizontal +󱨬 md_blinds_horizontal_closed +󱨭 md_blinds_vertical +󱨮 md_blinds_vertical_closed +󱨯 md_bulkhead_light +󱨰 md_calendar_today_outline +󱨱 md_calendar_week_begin_outline +󱨲 md_calendar_week_end +󱨳 md_calendar_week_end_outline +󱨴 md_calendar_week_outline +󱨵 md_cloud_percent +󱨶 md_cloud_percent_outline +󱨷 md_coach_lamp_variant +󱨸 md_compost +󱨹 md_currency_fra +󱨺 md_fan_clock +󱨻 md_file_rotate_left +󱨼 md_file_rotate_left_outline +󱨽 md_file_rotate_right +󱨾 md_file_rotate_right_outline +󱨿 md_filter_multiple +󱩀 md_filter_multiple_outline +󱩁 md_gymnastics +󱩂 md_hand_clap_off +󱩃 md_heat_pump +󱩄 md_heat_pump_outline +󱩅 md_heat_wave +󱩆 md_home_off +󱩇 md_home_off_outline +󱩈 md_landslide +󱩉 md_landslide_outline +󱩊 md_laptop_account +󱩋 md_led_strip_variant_off +󱩌 md_lightbulb_night +󱩍 md_lightbulb_night_outline +󱩎 md_lightbulb_on_10 +󱩏 md_lightbulb_on_20 +󱩐 md_lightbulb_on_30 +󱩑 md_lightbulb_on_40 +󱩒 md_lightbulb_on_50 +󱩓 md_lightbulb_on_60 +󱩔 md_lightbulb_on_70 +󱩕 md_lightbulb_on_80 +󱩖 md_lightbulb_on_90 +󱩗 md_meter_electric +󱩘 md_meter_electric_outline +󱩙 md_meter_gas +󱩚 md_meter_gas_outline +󱩛 md_monitor_account +󱩜 md_pill_off +󱩝 md_plus_lock +󱩞 md_plus_lock_open +󱩟 md_pool_thermometer +󱩠 md_post_lamp +󱩡 md_rabbit_variant +󱩢 md_rabbit_variant_outline +󱩣 md_receipt_text_check +󱩤 md_receipt_text_check_outline +󱩥 md_receipt_text_minus +󱩦 md_receipt_text_minus_outline +󱩧 md_receipt_text_plus +󱩨 md_receipt_text_plus_outline +󱩩 md_receipt_text_remove +󱩪 md_receipt_text_remove_outline +󱩫 md_roller_shade +󱩬 md_roller_shade_closed +󱩭 md_seed_plus +󱩮 md_seed_plus_outline +󱩯 md_shopping_search_outline +󱩰 md_snowflake_check +󱩱 md_snowflake_thermometer +󱩲 md_snowshoeing +󱩳 md_solar_power_variant +󱩴 md_solar_power_variant_outline +󱩵 md_storage_tank +󱩶 md_storage_tank_outline +󱩷 md_sun_clock +󱩸 md_sun_clock_outline +󱩹 md_sun_snowflake_variant +󱩺 md_tag_check +󱩻 md_tag_check_outline +󱩼 md_text_box_edit +󱩽 md_text_box_edit_outline +󱩾 md_text_search_variant +󱩿 md_thermometer_check +󱪀 md_thermometer_water +󱪁 md_tsunami +󱪂 md_turbine +󱪃 md_volcano +󱪄 md_volcano_outline +󱪅 md_water_thermometer +󱪆 md_water_thermometer_outline +󱪇 md_wheelchair +󱪈 md_wind_power +󱪉 md_wind_power_outline +󱪊 md_window_shutter_cog +󱪋 md_window_shutter_settings +󱪌 md_account_tie_woman +󱪍 md_briefcase_arrow_left_right +󱪎 md_briefcase_arrow_left_right_outline +󱪏 md_briefcase_arrow_up_down +󱪐 md_briefcase_arrow_up_down_outline +󱪑 md_cash_clock +󱪒 md_cash_sync +󱪓 md_file_arrow_left_right +󱪔 md_file_arrow_left_right_outline +󱪕 md_file_arrow_up_down +󱪖 md_file_arrow_up_down_outline +󱪗 md_file_document_alert +󱪘 md_file_document_alert_outline +󱪙 md_file_document_check +󱪚 md_file_document_check_outline +󱪛 md_file_document_minus +󱪜 md_file_document_minus_outline +󱪝 md_file_document_plus +󱪞 md_file_document_plus_outline +󱪟 md_file_document_remove +󱪠 md_file_document_remove_outline +󱪡 md_file_minus +󱪢 md_file_minus_outline +󱪣 md_filter_cog +󱪤 md_filter_cog_outline +󱪥 md_filter_settings +󱪦 md_filter_settings_outline +󱪧 md_folder_lock_open_outline +󱪨 md_folder_lock_outline +󱪩 md_forum_minus +󱪪 md_forum_minus_outline +󱪫 md_forum_plus +󱪬 md_forum_plus_outline +󱪭 md_forum_remove +󱪮 md_forum_remove_outline +󱪯 md_heating_coil +󱪰 md_image_lock +󱪱 md_image_lock_outline +󱪲 md_land_fields +󱪳 md_land_plots +󱪴 md_land_plots_circle +󱪵 md_land_plots_circle_variant +󱪶 md_land_rows_horizontal +󱪷 md_land_rows_vertical +󱪸 md_medical_cotton_swab +󱪹 md_rolodex +󱪺 md_rolodex_outline +󱪻 md_sort_variant_off +󱪼 md_tally_mark_1 +󱪽 md_tally_mark_2 +󱪾 md_tally_mark_3 +󱪿 md_tally_mark_4 +󱫀 md_tally_mark_5 +󱫁 md_attachment_check +󱫂 md_attachment_minus +󱫃 md_attachment_off +󱫄 md_attachment_plus +󱫅 md_attachment_remove +󱫆 md_paperclip_check +󱫇 md_paperclip_minus +󱫈 md_paperclip_off +󱫉 md_paperclip_plus +󱫊 md_paperclip_remove +󱫋 md_network_pos +󱫌 md_timer_alert +󱫍 md_timer_alert_outline +󱫎 md_timer_cancel +󱫏 md_timer_cancel_outline +󱫐 md_timer_check +󱫑 md_timer_check_outline +󱫒 md_timer_edit +󱫓 md_timer_edit_outline +󱫔 md_timer_lock +󱫕 md_timer_lock_open +󱫖 md_timer_lock_open_outline +󱫗 md_timer_lock_outline +󱫘 md_timer_marker +󱫙 md_timer_marker_outline +󱫚 md_timer_minus +󱫛 md_timer_minus_outline +󱫜 md_timer_music +󱫝 md_timer_music_outline +󱫞 md_timer_pause +󱫟 md_timer_pause_outline +󱫠 md_timer_play +󱫡 md_timer_play_outline +󱫢 md_timer_plus +󱫣 md_timer_plus_outline +󱫤 md_timer_refresh +󱫥 md_timer_refresh_outline +󱫦 md_timer_remove +󱫧 md_timer_remove_outline +󱫨 md_timer_star +󱫩 md_timer_star_outline +󱫪 md_timer_stop +󱫫 md_timer_stop_outline +󱫬 md_timer_sync +󱫭 md_timer_sync_outline +󱫮 md_ear_hearing_loop +󱫯 md_sail_boat_sink +󱫰 md_lecturn +♥ oct_heart +⚡ oct_zap + oct_light_bulb + oct_repo + oct_repo_forked + oct_repo_push + oct_repo_pull + oct_book + oct_accessibility + oct_git_pull_request + oct_mark_github + oct_download + oct_upload + oct_accessibility_inset + oct_alert_fill + oct_file_code + oct_apps + oct_file_media + oct_file_zip + oct_archive + oct_tag + oct_file_directory + oct_file_submodule + oct_person + oct_arrow_both + oct_git_commit + oct_git_branch + oct_git_merge + oct_mirror + oct_issue_opened + oct_issue_reopened + oct_issue_closed + oct_star + oct_comment + oct_question + oct_alert + oct_search + oct_gear + oct_arrow_down_left + oct_tools + oct_sign_out + oct_rocket + oct_rss + oct_paste + oct_sign_in + oct_organization + oct_device_mobile + oct_unfold + oct_check + oct_mail + oct_read + oct_arrow_up + oct_arrow_right + oct_arrow_down + oct_arrow_left + oct_pin + oct_gift + oct_graph + oct_triangle_left + oct_credit_card + oct_clock + oct_ruby + oct_broadcast + oct_key + oct_arrow_down_right + oct_repo_clone + oct_diff + oct_eye + oct_comment_discussion + oct_arrow_switch + oct_dot_fill + oct_square_fill + oct_device_camera + oct_device_camera_video + oct_pencil + oct_info + oct_triangle_right + oct_triangle_down + oct_link + oct_plus + oct_three_bars + oct_code + oct_location + oct_list_unordered + oct_list_ordered + oct_quote + oct_versions + oct_calendar + oct_lock + oct_diff_added + oct_diff_removed + oct_diff_modified + oct_diff_renamed + oct_horizontal_rule + oct_arrow_up_left + oct_milestone + oct_checklist + oct_megaphone + oct_chevron_right + oct_bookmark + oct_sliders + oct_meter + oct_history + oct_link_external + oct_mute + oct_x + oct_circle_slash + oct_pulse + oct_sync + oct_telescope + oct_arrow_up_right + oct_home + oct_stop + oct_bug + oct_logo_github + oct_file_binary + oct_database + oct_server + oct_diff_ignored + oct_ellipsis + oct_bell_fill + oct_hubot + oct_bell_slash + oct_blocked + oct_bookmark_fill + oct_chevron_up + oct_chevron_down + oct_chevron_left + oct_triangle_up + oct_git_compare + oct_logo_gist + oct_file_symlink_file + oct_file_symlink_directory + oct_squirrel + oct_globe + oct_unmute + oct_mention + oct_package + oct_browser + oct_terminal + oct_markdown + oct_dash + oct_fold + oct_inbox + oct_trash + oct_paintbrush + oct_flame + oct_briefcase + oct_plug + oct_bookmark_slash_fill + oct_mortar_board + oct_law + oct_thumbsup + oct_thumbsdown + oct_desktop_download + oct_beaker + oct_bell + oct_cache + oct_shield + oct_bold + oct_check_circle + oct_italic + oct_tasklist + oct_verified + oct_smiley + oct_unverified + oct_check_circle_fill + oct_file + oct_grabber + oct_checkbox + oct_reply + oct_device_desktop + oct_circle + oct_clock_fill + oct_cloud + oct_cloud_offline + oct_code_of_conduct + oct_code_review + oct_code_square + oct_codescan + oct_codescan_checkmark + oct_codespaces + oct_columns + oct_command_palette + oct_commit + oct_container + oct_copilot + oct_copilot_error + oct_copilot_warning + oct_copy + oct_cpu + oct_cross_reference + oct_dependabot + oct_diamond + oct_discussion_closed + oct_discussion_duplicate + oct_discussion_outdated + oct_dot + oct_duplicate + oct_eye_closed + oct_feed_discussion + oct_feed_forked + oct_feed_heart + oct_feed_merged + oct_feed_person + oct_feed_repo + oct_feed_rocket + oct_feed_star + oct_feed_tag + oct_feed_trophy + oct_file_added + oct_file_badge + oct_file_diff + oct_file_directory_fill + oct_file_directory_open_fill + oct_file_moved + oct_file_removed + oct_filter + oct_fiscal_host + oct_fold_down + oct_fold_up + oct_git_merge_queue + oct_git_pull_request_closed + oct_git_pull_request_draft + oct_goal + oct_hash + oct_heading + oct_heart_fill + oct_home_fill + oct_hourglass + oct_id_badge + oct_image + oct_infinity + oct_issue_draft + oct_issue_tracked_by + oct_issue_tracks + oct_iterations + oct_kebab_horizontal + oct_key_asterisk + oct_log + oct_moon + oct_move_to_bottom + oct_move_to_end + oct_move_to_start + oct_move_to_top + oct_multi_select + oct_no_entry + oct_north_star + oct_note + oct_number + oct_package_dependencies + oct_package_dependents + oct_paper_airplane + oct_paperclip + oct_passkey_fill + oct_people + oct_person_add + oct_person_fill + oct_play + oct_plus_circle + oct_project + oct_project_roadmap + oct_project_symlink + oct_project_template + oct_rel_file_path + oct_repo_deleted + oct_repo_locked + oct_repo_template + oct_report + oct_rows + oct_screen_full + oct_screen_normal + oct_share + oct_share_android + oct_shield_check + oct_shield_lock + oct_shield_slash + oct_shield_x + oct_sidebar_collapse + oct_sidebar_expand + oct_single_select + oct_skip + oct_skip_fill + oct_sort_asc + oct_sort_desc + oct_sparkle_fill + oct_sponsor_tiers + oct_square + oct_stack + oct_star_fill + oct_stopwatch + oct_strikethrough + oct_sun + oct_tab + oct_tab_external + oct_table + oct_telescope_fill + oct_trophy + oct_typography + oct_unlink + oct_unlock + oct_unread + oct_video + oct_webhook + oct_workflow + oct_x_circle + oct_x_circle_fill + oct_zoom_in + oct_zoom_out + oct_bookmark_slash + pl_branch + pl_line_number_current_line + pl_hostname_readonly + ple_column_number_ple_current_column + pl_left_hard_divider + pl_left_soft_divider + pl_right_hard_divider + pl_right_soft_divider + ple_right_half_circle_thick + ple_right_half_circle_thin + ple_left_half_circle_thick + ple_left_half_circle_thin + ple_lower_left_triangle + ple_backslash_separator + ple_lower_right_triangle + ple_forwardslash_separator + ple_upper_left_triangle + ple_forwardslash_separator_redundant + ple_upper_right_triangle + ple_backslash_separator_redundant + ple_flame_thick + ple_flame_thin + ple_flame_thick_mirrored + ple_flame_thin_mirrored + ple_pixelated_squares_small + ple_pixelated_squares_small_mirrored + ple_pixelated_squares_big + ple_pixelated_squares_big_mirrored + ple_ice_waveform + ple_ice_waveform_mirrored + ple_honeycomb + ple_honeycomb_outline + ple_lego_separator + ple_lego_separator_thin + ple_lego_block_facing + ple_lego_block_sideways + ple_trapezoid_top_bottom + ple_trapezoid_top_bottom_mirrored + pom_clean_code + pom_pomodoro_done + pom_pomodoro_estimated + pom_pomodoro_ticking + pom_pomodoro_squashed + pom_short_pause + pom_long_pause + pom_away + pom_pair_programming + pom_internal_interruption + pom_external_interruption + custom_folder_npm + custom_folder_git_custom_folder_git_branch + custom_folder_config + custom_folder_github + custom_folder_open + custom_folder + seti_stylus + seti_project + custom_play_arrow_play_arrow + seti_sass + seti_rails + seti_ruby + seti_python + seti_heroku + seti_php + seti_markdown + seti_license + seti_json_less + seti_javascript + seti_image + seti_html + seti_mustache + seti_gulp + seti_grunt + custom_default_default_text + seti_folder + seti_css + seti_config + seti_npm_npm_ignored + custom_home_seti_home + seti_ejs + seti_xml + seti_bower + seti_coffee_cjsx + seti_twig + custom_cpp + custom_c + seti_haskell + seti_lua + indent_line_indentation_line_indent_dotted_guide + seti_karma + seti_favicon + seti_julia + seti_react + custom_go + seti_go + seti_typescript + custom_msdos + custom_windows + custom_vim + custom_elm_elm + custom_elixir_elixir + custom_electron + custom_crystal_crystal + custom_purescript_purescript + seti_puppet_custom_puppet + custom_emacs + custom_orgmode + custom_kotlin_seti_kotlin + seti_apple + seti_argdown + seti_asm + seti_audio + seti_babel + seti_bazel + seti_bicep + seti_bsl + seti_cake_php + seti_cake + seti_checkbox + seti_checkbox_unchecked + seti_clock_seti_time_cop + seti_clojure + seti_code_climate + seti_code_search + seti_coldfusion + seti_cpp + seti_crystal_embedded + seti_c_sharp + seti_c + seti_csv + seti_cu + seti_dart + seti_db + seti_default + seti_deprecation_cop + seti_docker + seti_d + seti_editorconfig + seti_elixir_script + seti_error + seti_eslint + seti_ethereum + seti_firebase + seti_firefox + seti_font + seti_f_sharp + seti_github + seti_gitlab + seti_git_git_folder_git_ignore + seti_go2 + seti_godot + seti_gradle + seti_grails + seti_graphql + seti_hacklang + seti_haml + seti_happenings + seti_haxe + seti_hex + seti_ignored + seti_illustrator + seti_info + seti_ionic + seti_jade + seti_java + seti_jenkins + seti_jinja + seti_liquid + seti_livescript + seti_lock + seti_makefile + seti_maven + seti_mdo + seti_new_file + seti_nim + seti_notebook + seti_nunjucks + seti_ocaml + seti_odata + seti_pddl + seti_pdf + seti_perl + seti_photoshop + seti_pipeline + seti_plan + seti_platformio + seti_powershell + seti_prisma + seti_prolog + seti_pug + seti_reasonml + seti_rescript + seti_rollup + seti_r + seti_rust + seti_salesforce + seti_sbt + seti_scala + seti_search + seti_settings + seti_shell + seti_slim + seti_smarty + seti_spring + seti_stylelint + seti_sublime + seti_svelte + seti_svg + seti_swift + seti_terraform + seti_tex + seti_todo + seti_tsconfig + seti_vala + seti_video + seti_vue + seti_wasm + seti_wat + seti_webpack + seti_wgt + seti_word + seti_xls + seti_yarn + seti_yml + seti_zig + seti_zip + custom_asm + custom_v_lang + custom_folder_oct + weather_day_cloudy_gusts + weather_day_cloudy_windy + weather_day_cloudy + weather_day_fog + weather_day_hail + weather_day_lightning + weather_day_rain_mix + weather_day_rain_wind + weather_day_rain + weather_day_showers + weather_day_snow + weather_day_sprinkle + weather_day_sunny_overcast + weather_day_sunny + weather_day_storm_showers + weather_day_thunderstorm + weather_cloudy_gusts + weather_cloudy_windy + weather_cloudy + weather_fog + weather_hail + weather_lightning + weather_rain_mix + weather_rain_wind + weather_rain + weather_showers + weather_snow + weather_sprinkle + weather_storm_showers + weather_thunderstorm + weather_windy + weather_night_alt_cloudy_gusts + weather_night_alt_cloudy_windy + weather_night_alt_hail + weather_night_alt_lightning + weather_night_alt_rain_mix + weather_night_alt_rain_wind + weather_night_alt_rain + weather_night_alt_showers + weather_night_alt_snow + weather_night_alt_sprinkle + weather_night_alt_storm_showers + weather_night_alt_thunderstorm + weather_night_clear + weather_night_cloudy_gusts + weather_night_cloudy_windy + weather_night_cloudy + weather_night_hail + weather_night_lightning + weather_night_rain_mix + weather_night_rain_wind + weather_night_rain + weather_night_showers + weather_night_snow + weather_night_sprinkle + weather_night_storm_showers + weather_night_thunderstorm + weather_celsius + weather_cloud_down + weather_cloud_refresh + weather_cloud_up + weather_cloud + weather_degrees + weather_direction_down_left + weather_direction_down + weather_fahrenheit + weather_horizon_alt + weather_horizon + weather_direction_left + weather_aliens + weather_night_fog + weather_refresh_alt + weather_refresh + weather_direction_right + weather_raindrops + weather_strong_wind + weather_sunrise + weather_sunset + weather_thermometer_exterior + weather_thermometer_internal + weather_thermometer + weather_tornado + weather_direction_up_right + weather_direction_up + weather_wind_west + weather_wind_south_west + weather_wind_south_east + weather_wind_south + weather_wind_north_west + weather_wind_north_east + weather_wind_north + weather_wind_east + weather_smoke + weather_dust + weather_snow_wind + weather_day_snow_wind + weather_night_snow_wind + weather_night_alt_snow_wind + weather_day_sleet_storm + weather_night_sleet_storm + weather_night_alt_sleet_storm + weather_day_snow_thunderstorm + weather_night_snow_thunderstorm + weather_night_alt_snow_thunderstorm + weather_solar_eclipse + weather_lunar_eclipse + weather_meteor + weather_hot + weather_hurricane + weather_smog + weather_alien + weather_snowflake_cold + weather_stars + weather_raindrop + weather_barometer + weather_humidity + weather_na + weather_flood + weather_day_cloudy_high + weather_night_alt_cloudy_high + weather_night_cloudy_high + weather_night_alt_partly_cloudy + weather_sandstorm + weather_night_partly_cloudy + weather_umbrella + weather_day_windy + weather_night_alt_cloudy + weather_direction_up_left + weather_direction_down_right + weather_time_12 + weather_time_1 + weather_time_2 + weather_time_3 + weather_time_4 + weather_time_5 + weather_time_6 + weather_time_7 + weather_time_8 + weather_time_9 + weather_time_10 + weather_time_11 + weather_moon_new + weather_moon_waxing_crescent_1 + weather_moon_waxing_crescent_2 + weather_moon_waxing_crescent_3 + weather_moon_waxing_crescent_4 + weather_moon_waxing_crescent_5 + weather_moon_waxing_crescent_6 + weather_moon_first_quarter + weather_moon_waxing_gibbous_1 + weather_moon_waxing_gibbous_2 + weather_moon_waxing_gibbous_3 + weather_moon_waxing_gibbous_4 + weather_moon_waxing_gibbous_5 + weather_moon_waxing_gibbous_6 + weather_moon_full + weather_moon_waning_gibbous_1 + weather_moon_waning_gibbous_2 + weather_moon_waning_gibbous_3 + weather_moon_waning_gibbous_4 + weather_moon_waning_gibbous_5 + weather_moon_waning_gibbous_6 + weather_moon_third_quarter + weather_moon_waning_crescent_1 + weather_moon_waning_crescent_2 + weather_moon_waning_crescent_3 + weather_moon_waning_crescent_4 + weather_moon_waning_crescent_5 + weather_moon_waning_crescent_6 + weather_wind_direction + weather_day_sleet + weather_night_sleet + weather_night_alt_sleet + weather_sleet + weather_day_haze + weather_wind_beaufort_0 + weather_wind_beaufort_1 + weather_wind_beaufort_2 + weather_wind_beaufort_3 + weather_wind_beaufort_4 + weather_wind_beaufort_5 + weather_wind_beaufort_6 + weather_wind_beaufort_7 + weather_wind_beaufort_8 + weather_wind_beaufort_9 + weather_wind_beaufort_10 + weather_wind_beaufort_11 + weather_wind_beaufort_12 + weather_day_light_wind + weather_tsunami + weather_earthquake + weather_fire + weather_volcano + weather_moonrise + weather_moonset + weather_train + weather_small_craft_advisory + weather_gale_warning + weather_storm_warning + weather_hurricane_warning + weather_moon_alt_waxing_crescent_1 + weather_moon_alt_waxing_crescent_2 + weather_moon_alt_waxing_crescent_3 + weather_moon_alt_waxing_crescent_4 + weather_moon_alt_waxing_crescent_5 + weather_moon_alt_waxing_crescent_6 + weather_moon_alt_first_quarter + weather_moon_alt_waxing_gibbous_1 + weather_moon_alt_waxing_gibbous_2 + weather_moon_alt_waxing_gibbous_3 + weather_moon_alt_waxing_gibbous_4 + weather_moon_alt_waxing_gibbous_5 + weather_moon_alt_waxing_gibbous_6 + weather_moon_alt_full + weather_moon_alt_waning_gibbous_1 + weather_moon_alt_waning_gibbous_2 + weather_moon_alt_waning_gibbous_3 + weather_moon_alt_waning_gibbous_4 + weather_moon_alt_waning_gibbous_5 + weather_moon_alt_waning_gibbous_6 + weather_moon_alt_third_quarter + weather_moon_alt_waning_crescent_1 + weather_moon_alt_waning_crescent_2 + weather_moon_alt_waning_crescent_3 + weather_moon_alt_waning_crescent_4 + weather_moon_alt_waning_crescent_5 + weather_moon_alt_waning_crescent_6 + weather_moon_alt_new +𝔸 bbA +𝔹 bbB +𝔻 bbD +𝔼 bbE +𝔽 bbF +𝔾 bbG +𝕀 bbI +𝕁 bbJ +𝕂 bbK +𝕃 bbL +𝕄 bbM +𝕆 bbO +𝕊 bbS +𝕋 bbT +𝕌 bbU +𝕍 bbV +𝕎 bbW +𝕏 bbX +𝕐 bbY +𝕒 bba +𝕓 bbb +𝕔 bbc +𝕕 bbd +𝕖 bbe +𝕗 bbf +𝕘 bbg +𝕙 bbh +𝕚 bbi +𝕛 bbj +𝕜 bbk +𝕝 bbl +𝕞 bbm +𝕟 bbn +𝕠 bbo +𝕡 bbp +𝕢 bbq +𝕣 bbr +𝕤 bbs +𝕥 bbt +𝕦 bbu +𝕧 bbv +𝕨 bbw +𝕩 bbx +𝕪 bby +𝕫 bbz diff --git a/.local/share/script-data/cpp20/.clang-format b/.local/share/script-data/cpp20/.clang-format new file mode 100644 index 0000000..b9f7877 --- /dev/null +++ b/.local/share/script-data/cpp20/.clang-format @@ -0,0 +1,250 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: true +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: NextLine +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: pb + BasedOnStyle: google +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RequiresClausePosition: OwnLine +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/.local/share/script-data/cpp20/Makefile b/.local/share/script-data/cpp20/Makefile new file mode 100644 index 0000000..2b50de1 --- /dev/null +++ b/.local/share/script-data/cpp20/Makefile @@ -0,0 +1,26 @@ +CXX = clang++ +CXXFLAGS = -std=c++20 --debug +SRCDIR := . +BUILDDIR := build +INCDIR := include +SRCS := $(wildcard $(SRCDIR)/*.cpp) +OBJS := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.o,$(SRCS)) +DEPS := $(OBJS:.o=.d) +EXEC := main +all: compile_msg build +compile_msg: + @echo -e "\e[33m Compile: $(SRCS)\e[0m" +$(EXEC): $(OBJS) + @echo -e "\n\e[33m Link: $(EXEC)\e[0m" + $(CXX) $(CXXFLAGS) $(OBJS) -o $(EXEC) +build: $(EXEC) +$(BUILDDIR)/%.o: $(SRCDIR)/%.cpp + @mkdir -p $(BUILDDIR) + $(CXX) $(CXXFLAGS) -I$(INCDIR) -MMD -MP -c $< -o $@ +-include $(DEPS) +run: $(EXEC) + @echo -e "\n\e[33m󱓞 Execute : $(EXEC)\e[0m" + ./$(EXEC) +clean: + rm -rf $(BUILDDIR) $(EXEC) +.PHONY: all build run clean diff --git a/.local/share/script-data/cpp20/Makefile.bak b/.local/share/script-data/cpp20/Makefile.bak new file mode 100644 index 0000000..bf87caa --- /dev/null +++ b/.local/share/script-data/cpp20/Makefile.bak @@ -0,0 +1,29 @@ +CXX = clang++ +CXXFLAGS = -std=c++20 --debug -I$(INCLUDE_DIR) +INCLUDE_DIR = include +BUILD_DIR = build +TARGET_DIR = $(BUILD_DIR) +OBJ_DIR = $(BUILD_DIR)/obj +TARGET = $(TARGET_DIR)/$(notdir $(CURDIR)) +SRCS = $(wildcard src/*.cpp) +OBJS = $(patsubst src/%.cpp,$(OBJ_DIR)/%.o,$(SRCS)) +all: + @echo -e "\e[33m󱁤 Build:\n\e[0m" + $(MAKE) $(TARGET) +$(TARGET): $(OBJS) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) +$(OBJ_DIR)/%.o: src/%.cpp | $(OBJ_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + @$(CXX) -MM $(CXXFLAGS) src/$*.cpp | sed 's|^|$(OBJ_DIR)/|' > $(OBJ_DIR)/$*.d +-include $(OBJS:.o=.d) +$(OBJ_DIR): + mkdir -p $(OBJ_DIR) +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) +run: $(TARGET) + @echo -e "\n\e[33m󱓞 Run:\n\e[0m" + ./$(TARGET) +.PHONY: all clean run +clean: + @echo -e "\n\e[33m󰃢 Clean:\n\e[0m" + rm -rf $(BUILD_DIR) diff --git a/.local/share/script-data/cpp20/compile_flags.txt b/.local/share/script-data/cpp20/compile_flags.txt new file mode 100644 index 0000000..74b8ebf --- /dev/null +++ b/.local/share/script-data/cpp20/compile_flags.txt @@ -0,0 +1,10 @@ +-std=c++20 +-Wall +-Weffc++ +-Wextra +-Wconversion +-Wsign-conversion +-Werror +-pedantic-errors +--debug +-Iinclude diff --git a/.local/share/script-data/keybinds b/.local/share/script-data/keybinds new file mode 100644 index 0000000..994ddd6 --- /dev/null +++ b/.local/share/script-data/keybinds @@ -0,0 +1,58 @@ +w, firefox, browser google chrome web empty internet +return, st, shell command prompt st empty enter +r, lf, file manager empty +d, dmenu_run, empty apps rofi programs +a, dmenu_hub, empty scripts mount color picker edit config kill +n, nvim, editor text empty +space, dmenu_web, websearch bookmarks internet empty +backspace, systerm action, empty sysact reboot restart renew reload lock leave dwm +mod-w, firefox, browser google chrome web +mod-return, open terminal, shell command prompt st +mod-backspace, system actions, sysact reboot restart renew reload lock leave dwm +mod-r, lf, file manager +mod-d, dmenu_run, apps rofi programs +mod-a, dmenu_hub, scripts mount color picker edit config kill +mod-space, dmenu_web, websearch bookmarks internet +mod-n, nvim, editor text +mute, mute volume, sound +raisevolume, increase volume, sound +lowervolume, lower volume, sound +prev, previous media, song +next, next media, song +pause, pause media, song +play, play media, song +brightnessUp, increase brightness, backlight +brightnessDown, decrease brightness, backlight +print_scr, screenshot tool, capture +mod-print_scr, recording tool, capture video cast +mod-shift-del, kill dwm, leave log out +mod-del, renew dwm, refresh wm +mod-q, close window, kill client +mod-shift-r, gui file manager, thunar files +mod-t, tile layout, tiling +mod-y, monocle layout, layout +mod-u, floating layout, no layout +mod-o, increase master windows, master +mod-shift-o, decrease master windows, master +mod-f, fake fullscreen, maximize +mod-h, adjust master/stack ratio, resize +mod-l, adjust master/stack ratio, resize +mod-', calculator, apostrophe qalculate math +mod-b, toggle statusbar, dwmblocks hide +mod-shift-n, newsboat, rss +mod-m, music, ncmpcpp mpd songs mp3 +mod-left, focus left window, activate client +mod-right, focus right window, activate client +mod-up, focus upper window, activate client +mod-down, focus lower window, activate client +mod-ctrl-up, rotate windows CW, move clients clockwise +mod-ctrl-down, rotate windows CCW, move clients anti counter clockwise +mod-alt-left, shift window and tag, move change workspaces tags +mod-alt-right, shift window and tag, move change workspaces tags +mod-ctrl-left, switch to adjacent tag, change workspaces tags +mod-ctrl-right, switch to adjacent tag, change workspaces tags +mod-shift-space, toggle window floating, client +mod-[1-9], change tag, switch workspaces 123456789 +mod-0, toggle all-tag, all workspaces +mod-scroll, resize floating windows, client +F7, clipboard manager, clipmenu copy paste diff --git a/.zshenv b/.zshenv new file mode 100644 index 0000000..444cdcb --- /dev/null +++ b/.zshenv @@ -0,0 +1,2 @@ +ZDOTDIR=~/.config/zsh +source -- "$ZDOTDIR"/.zshenv diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f629709 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Minty Cube + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b8ab858 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +

DotFiles

+ +screenshot + +These dotfiles are meant to be used after installing [LARBS](https://github.com/LukeSmithxyz/LARBS). +Here are some details about this setup: + +- **OS**: EndeavourOS +- **Login Manager**: None +- **WM**: [dwm](https://github.com/mintycube/dotfiles/tree/dwm/.config/suckless/dwm) +- **Bar**: [dwmblocks](https://github.com/mintycube/dotfiles/tree/dwm/.config/suckless/dwmblocks) +- **Compositor**: [picom](https://github.com/yshui/picom) +- **Cursor-theme** = [Bibata-Modern-Ice](https://github.com/ful1e5/Bibata_Cursor) +- **Shell**: [zsh](https://wiki.archlinux.org/index.php/Zsh) + [zsh4humans](https://github.com/romkatv/zsh4humans) +- **Terminal**: [st](https://github.com/mintycube/dotfiles/tree/dwm/.config/suckless/st) +- **Font**: JetBrainsMono Nerd Font +- **Editor**: [Neovim](https://github.com/mintycube/dotfiles/tree/dwm/.config/nvim) +- **File Manager**: [lf](https://github.com/gokcehan/lf) + [ctpv](https://github.com/NikitaIvanovV/ctpv) +- **Browser**: Firefox +- **Menu**: [dmenu](https://github.com/mintycube/dotfiles/tree/dwm/.config/suckless/dmenu) +- **Image-viewer** = [nsxiv](https://github.com/nsxiv/nsxiv) +- **Music-player** = [mpd](https://github.com/MusicPlayerDaemon/MPD) + [ncmpcpp](https://github.com/ncmpcpp/ncmpcpp) +- **Pdf-viewer** = [zathura](https://github.com/pwmt/zathura) +- **Calculator** = [qalculate-gtk](https://github.com/Qalculate/qalculate-gtk) +- **Networkmanager** = [dmenu](https://github.com/firecat53/networkmanager-dmenu) +- **Notification Client** = [dunst](https://github.com/dunst-project/dunst) diff --git a/firefox/userChrome.css b/firefox/userChrome.css new file mode 100644 index 0000000..a1f47bc --- /dev/null +++ b/firefox/userChrome.css @@ -0,0 +1,192 @@ +:root { + --tab-active-bg-color: #464646; /* background color of an active tab */ + --tab-inactive-bg-color: #161616; /* background color of an inactive tab */ + --tab-active-fg-fallback-color: #dde1e6; /* color of text in an active tab without a container */ + --tab-inactive-fg-fallback-color: #565656; /* color of text in an inactive tab without a container */ + + /* try increasing if you encounter problems */ + --urlbar-height-setting: 24px; + --tab-min-height: 16px !important; + + /* I don't recommend you touch this unless you know what you're doing */ + --arrowpanel-menuitem-padding: 2px !important; + --arrowpanel-border-radius: 0px !important; + --arrowpanel-menuitem-border-radius: 0px !important; + --toolbarbutton-border-radius: 0px !important; + --toolbarbutton-inner-padding: 0px 2px !important; +} + +/* --- GENERAL DEBLOAT ---------------------------------- */ + +/* Bottom left page loading status or url preview */ +#statuspanel { display: none !important; } + +/* Hide dropdown that appears when you type in search bar */ +.autocomplete-history-popup, panel[type=autocomplete-richlistbox], panel[type=autocomplete] { + display: none !important; +} + +/* --- DEBLOAT NAVBAR ----------------------------------- */ + +#back-button { display: none; } +#forward-button { display: none; } +#reload-button { display: none; } +#stop-button { display: none; } +#home-button { display: none; } +#library-button { display: none; } +#fxa-toolbar-menu-button { display: none; } +/* empty space before and after the url bar */ +#customizableui-special-spring1, #customizableui-special-spring2 { display: none; } + +/* --- STYLE NAVBAR ------------------------------------ */ + +/* remove padding between toolbar buttons */ +toolbar .toolbarbutton-1 { padding: 0 0 !important; } + +/* add padding to the right of the last button so that it doesn't touch the edge of the window */ +#PanelUI-menu-button { + padding: 0px 4px 0px 0px !important; +} + +#nav-bar, #navigator-toolbox { + border-width: 0 !important; + --toolbar-field-focus-border-color: #42414d; +} + +#urlbar-container { + --urlbar-container-height: var(--urlbar-height-setting) !important; + margin-left: 0 !important; + margin-right: 0 !important; + padding-top: 0 !important; + padding-bottom: 0 !important; + font-family: 'Jetbrains Mono', monospace; + font-size: 11px; +} + +#urlbar { + --urlbar-height: var(--urlbar-height-setting) !important; + --urlbar-toolbar-height: var(--urlbar-height-setting) !important; + min-height: var(--urlbar-height-setting) !important; + border-color: var(--lwt-toolbar-field-border-color, hsla(240,5%,5%,.25)) !important; +} + +#urlbar-background { + border-width: 0 !important; + border-radius: 0 !important; +} + +#urlbar-input-container { + border-width: 0 !important; + margin-left: 0.5em !important; +} + +#urlbar-input { + margin-left: 0.4em !important; + margin-right: 0.4em !important; +} + +/* weird hack to keep pop-up menus from overlapping with navbar */ +#widget-overflow { margin: 0 !important; } +#appMenu-popup { margin: 0 !important; } +#customizationui-widget-panel { margin: 0 !important; } + +/* --- DEBLOAT URLBAR ----------------------------------- */ + +#identity-box { display: none; } +#pageActionButton { display: none; } +#pocket-button { display: none; } +#urlbar-zoom-button { display: none; } +#tracking-protection-icon-container { display: none !important; } +#reader-mode-button{ display: none !important; } +#star-button { display: none; } + +/* this will remove the invisible box at the end of urlbar but also will + * disable the Ctrl+D shortcut */ +/* #star-button-box { display: none; } */ + +/* Go to arrow button at the end of the urlbar when searching */ +#urlbar-go-button { display: none; } + +/* remove container indicator from urlbar */ +#userContext-label, #userContext-indicator { display: none !important;} + +/* --- STYLE TAB TOOLBAR -------------------------------- */ + +#titlebar { + --proton-tab-block-margin: 0px !important; + --tab-block-margin: 0 !important; +} + +#TabsToolbar, .tabbrowser-tab { + max-height: var(--tab-min-height) !important; + font-size: 11px !important; +} + +/* Change color of normal tabs */ +tab:not([selected="true"]) { + background-color: var(--tab-inactive-bg-color) !important; + color: var(--identity-icon-color, var(--tab-inactive-fg-fallback-color)) !important; +} + +tab { + font-family: 'JetBrainsMono Nerd Font', monospace; + font-weight: bold; + border: none !important; +} + +/* safari style tab width */ +.tabbrowser-tab[fadein] { max-width: 100vw !important; border: none } + +/* Hide close button on tabs */ +#tabbrowser-tabs .tabbrowser-tab .tab-close-button { display: none !important; } + +/* disable favicons in tab */ +.tab-icon-stack:not([pinned]) { display: none !important; } + +.tabbrowser-tab { + /* remove border between tabs */ + padding-inline: 0px !important; + /* reduce fade effect of tab text */ + --tab-label-mask-size: 1em !important; + /* fix pinned tab behaviour on overflow */ + overflow-clip-margin: 0px !important; +} + +/* Tab: selected colors */ +#tabbrowser-tabs .tabbrowser-tab[selected] .tab-content { + background: var(--tab-active-bg-color) !important; + color: var(--tab-active-fg-fallback-color, var(--tab-active-fg-fallback-color)) !important; +} + +/* Tab: hovered colors */ +#tabbrowser-tabs .tabbrowser-tab:hover:not([selected]) .tab-content { + background: var(--tab-active-bg-color) !important; + color: var(--tab-active-fg-fallback-color, var(--tab-active-fg-fallback-color)) !important; +} + +/* hide window controls */ +.titlebar-buttonbox-container { display: none; } + +/* remove titlebar spacers */ +.titlebar-spacer { display: none !important; } + +/* disable tab shadow */ +#tabbrowser-tabs:not([noshadowfortests]) .tab-background:is([selected], [multiselected]) { + box-shadow: none !important; +} + +/* remove dark space between pinned tab and first non-pinned tab */ +#tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs]) > +#tabbrowser-arrowscrollbox > +.tabbrowser-tab[first-visible-unpinned-tab] { + margin-inline-start: 0px !important; +} + +/* remove dropdown menu button which displays all tabs on overflow */ +#alltabs-button { display: none !important } + +/* fix displaying of pinned tabs on overflow */ +#tabbrowser-tabs:not([secondarytext-unsupported]) .tab-label-container { height: var(--tab-min-height) !important; } + +/* remove overflow scroll buttons */ +#scrollbutton-up, #scrollbutton-down { display: none !important; } diff --git a/images/lock.png b/images/lock.png new file mode 100644 index 0000000..f90f9f9 Binary files /dev/null and b/images/lock.png differ diff --git a/images/screenshot.png b/images/screenshot.png new file mode 100644 index 0000000..f1bf8c3 Binary files /dev/null and b/images/screenshot.png differ diff --git a/images/wall0.png b/images/wall0.png new file mode 100644 index 0000000..0de9d5b Binary files /dev/null and b/images/wall0.png differ diff --git a/images/wall1.png b/images/wall1.png new file mode 100644 index 0000000..5384efd Binary files /dev/null and b/images/wall1.png differ diff --git a/images/wall2.png b/images/wall2.png new file mode 100644 index 0000000..d2a5505 Binary files /dev/null and b/images/wall2.png differ