From 14791883624bf10227a6ffa9172c8030b87d4675 Mon Sep 17 00:00:00 2001 From: InigoGutierrez Date: Thu, 15 Jul 2021 01:57:30 +0200 Subject: Lots of renames: stow can't handle folder with --dotfiles option. --- stow/XserverDotfiles/.xinitrcbspwm | 1 + stow/XserverDotfiles/.xinitrcdwm | 2 + stow/XserverDotfiles/.xinitrcgnome | 3 + stow/XserverDotfiles/.xinitrci3 | 1 + stow/XserverDotfiles/.xinitrcpostintel | 0 stow/XserverDotfiles/.xinitrcpostnvidia | 2 + stow/XserverDotfiles/.xinitrcprevintel | 0 stow/XserverDotfiles/.xinitrcprevnvidia | 4 + stow/XserverDotfiles/.xinitrcxfce4 | 1 + stow/XserverDotfiles/dot-xinitrcbspwm | 1 - stow/XserverDotfiles/dot-xinitrcdwm | 2 - stow/XserverDotfiles/dot-xinitrcgnome | 3 - stow/XserverDotfiles/dot-xinitrci3 | 1 - stow/XserverDotfiles/dot-xinitrcpostintel | 0 stow/XserverDotfiles/dot-xinitrcpostnvidia | 2 - stow/XserverDotfiles/dot-xinitrcprevintel | 0 stow/XserverDotfiles/dot-xinitrcprevnvidia | 4 - stow/XserverDotfiles/dot-xinitrcxfce4 | 1 - stow/bspwm/.config/bspwm/bspwmrc | 28 + stow/bspwm/dot-config/bspwm/bspwmrc | 28 - stow/cmus/.config/cmus/autosave | 217 + stow/cmus/dot-config/cmus/autosave | 217 - stow/colorschemes/.config/colorschemes/customBlue | 29 + stow/colorschemes/.config/colorschemes/gruvbox | 31 + stow/colorschemes/.config/colorschemes/nord | 47 + .../dot-config/colorschemes/customBlue | 29 - stow/colorschemes/dot-config/colorschemes/gruvbox | 31 - stow/colorschemes/dot-config/colorschemes/nord | 47 - stow/dunst/.config/dunst/dunstifyIDs | 12 + stow/dunst/.config/dunst/dunstrc | 94 + stow/dunst/dot-config/dunst/dunstifyIDs | 12 - stow/dunst/dot-config/dunst/dunstrc | 94 - stow/emoji/.config/emoji | 4267 ++++++++++++++++++++ stow/emoji/dot-config/emoji | 4267 -------------------- stow/i3/.config/i3/config | 279 ++ stow/i3/dot-config/i3/config | 279 -- stow/i3blocks/.config/i3blocks/config | 101 + stow/i3blocks/dot-config/i3blocks/config | 101 - stow/mpv/.config/mpv/input.conf | 213 + stow/mpv/.config/mpv/mpv.conf | 21 + .../mpv/scripts-opts/mpv_thumbnail_script.conf | 70 + .../.config/mpv/scripts-opts/youtube-quality.conf | 41 + stow/mpv/.config/mpv/scripts/mpv-splice.lua | 328 ++ .../scripts/mpv_thumbnail_script_client_osc.lua | 3886 ++++++++++++++++++ .../mpv/scripts/mpv_thumbnail_script_server.lua | 736 ++++ stow/mpv/.config/mpv/scripts/youtube-quality.lua | 275 ++ stow/mpv/dot-config/mpv/input.conf | 213 - stow/mpv/dot-config/mpv/mpv.conf | 21 - .../mpv/scripts-opts/mpv_thumbnail_script.conf | 70 - .../mpv/scripts-opts/youtube-quality.conf | 41 - stow/mpv/dot-config/mpv/scripts/mpv-splice.lua | 328 -- .../scripts/mpv_thumbnail_script_client_osc.lua | 3886 ------------------ .../mpv/scripts/mpv_thumbnail_script_server.lua | 736 ---- .../mpv/dot-config/mpv/scripts/youtube-quality.lua | 275 -- stow/neofetch/.config/neofetch/config.conf | 764 ++++ stow/neofetch/.config/neofetch/neofetchLogin.conf | 63 + stow/neofetch/dot-config/neofetch/config.conf | 764 ---- .../dot-config/neofetch/neofetchLogin.conf | 63 - stow/newsboat/.config/newsboat/config | 11 + stow/newsboat/dot-config/newsboat/config | 11 - stow/nvim/.config/nvim/init.vim | 3 + stow/nvim/dot-config/nvim/init.vim | 3 - .../pandoc/luascripts/diagram-generator.lua | 299 ++ .../pandoc/luascripts/diagram-generator.lua | 299 -- stow/picom/.config/picom/picom.conf | 502 +++ .../picom/.config/picom/picom.jonaburg.sample.conf | 512 +++ stow/picom/.config/picom/picom.upstream.conf | 235 ++ stow/picom/dot-config/picom/picom.conf | 502 --- .../dot-config/picom/picom.jonaburg.sample.conf | 512 --- stow/picom/dot-config/picom/picom.upstream.conf | 235 -- stow/qutebrowser/.config/qutebrowser/config.py | 1729 ++++++++ stow/qutebrowser/dot-config/qutebrowser/config.py | 1729 -------- stow/ranger/.config/ranger/rc.conf | 640 +++ stow/ranger/.config/ranger/rifle.conf | 226 ++ stow/ranger/.config/ranger/scope.sh | 350 ++ stow/ranger/dot-config/ranger/rc.conf | 640 --- stow/ranger/dot-config/ranger/rifle.conf | 226 -- stow/ranger/dot-config/ranger/scope.sh | 350 -- stow/rcs/.Xresources | 40 + stow/rcs/.bash_aliases | 44 + stow/rcs/.bash_vars | 87 + stow/rcs/.bashrc | 66 + stow/rcs/.config/ttymaps.kmap | 2 + stow/rcs/.inputrc | 16 + stow/rcs/.profile | 46 + stow/rcs/dot-Xresources | 40 - stow/rcs/dot-bash_aliases | 44 - stow/rcs/dot-bash_vars | 87 - stow/rcs/dot-bashrc | 66 - stow/rcs/dot-config/ttymaps.kmap | 2 - stow/rcs/dot-inputrc | 16 - stow/rcs/dot-profile | 46 - stow/sxhkd/.config/sxhkd/sxhkdrc | 129 + stow/sxhkd/.config/sxhkd/sxhkdrcbspc | 92 + stow/sxhkd/dot-config/sxhkd/sxhkdrc | 129 - stow/sxhkd/dot-config/sxhkd/sxhkdrcbspc | 92 - stow/sxiv/.config/sxiv/exec/image-info | 18 + stow/sxiv/.config/sxiv/exec/key-handler | 128 + stow/sxiv/dot-config/sxiv/exec/image-info | 18 - stow/sxiv/dot-config/sxiv/exec/key-handler | 128 - stow/tmux/.tmux.conf | 70 + stow/tmux/dot-tmux.conf | 70 - stow/vim/.vim/autoload/plug.vim | 2788 +++++++++++++ stow/vim/.vim/autoload/plug.vim.old | 2788 +++++++++++++ stow/vim/.vim/colors/burnttoast256.vim | 116 + stow/vim/.vim/colors/nord.vim | 764 ++++ stow/vim/.vim/ftplugin/antlr/antlr3.vim | 91 + stow/vim/.vim/ftplugin/antlr/antlr4.vim | 76 + stow/vim/.vim/ftplugin/asciidoc/asciidoc.vim | 19 + stow/vim/.vim/ftplugin/cpp/cpp.vim | 28 + stow/vim/.vim/ftplugin/cpp/snips/template.txt | 6 + stow/vim/.vim/ftplugin/css/css.vim | 20 + stow/vim/.vim/ftplugin/html/html.vim | 78 + stow/vim/.vim/ftplugin/html/snips/template.txt | 12 + stow/vim/.vim/ftplugin/java/java.vim | 14 + stow/vim/.vim/ftplugin/javascript/javascript.vim | 38 + stow/vim/.vim/ftplugin/plantuml/plantuml.vim | 20 + stow/vim/.vim/ftplugin/plantuml/snips/template.txt | 9 + stow/vim/.vim/ftplugin/python/python.vim | 34 + stow/vim/.vim/ftplugin/python/snips/class | 3 + stow/vim/.vim/ftplugin/python/snips/template | 5 + stow/vim/.vim/ftplugin/sent/sent.vim | 19 + stow/vim/.vim/ftplugin/sh/sh.vim | 16 + stow/vim/.vim/ftplugin/sh/snippets/if.txt | 3 + stow/vim/.vim/ftplugin/tex/snips/template.txt | 30 + stow/vim/.vim/ftplugin/tex/tex.vim | 45 + stow/vim/.vim/ftplugin/text/text.vim | 20 + stow/vim/.vim/ftplugin/typescript/typescript.vim | 33 + stow/vim/.vim/ftplugin/vimwiki/snips/plantUml.txt | 5 + stow/vim/.vim/ftplugin/vimwiki/snips/template.txt | 15 + stow/vim/.vim/ftplugin/vimwiki/vimwiki.vim | 39 + stow/vim/.vim/plugin/SWTC.vim | 339 ++ stow/vim/.vim/plugin/dragvisuals.vim | 345 ++ stow/vim/.vim/plugin/rng.vim | 83 + stow/vim/.vimrc | 280 ++ stow/vim/dot-vim/autoload/plug.vim | 2788 ------------- stow/vim/dot-vim/autoload/plug.vim.old | 2788 ------------- stow/vim/dot-vim/colors/burnttoast256.vim | 116 - stow/vim/dot-vim/colors/nord.vim | 764 ---- stow/vim/dot-vim/ftplugin/antlr/antlr3.vim | 91 - stow/vim/dot-vim/ftplugin/antlr/antlr4.vim | 76 - stow/vim/dot-vim/ftplugin/asciidoc/asciidoc.vim | 19 - stow/vim/dot-vim/ftplugin/cpp/cpp.vim | 28 - stow/vim/dot-vim/ftplugin/cpp/snips/template.txt | 6 - stow/vim/dot-vim/ftplugin/css/css.vim | 20 - stow/vim/dot-vim/ftplugin/html/html.vim | 78 - stow/vim/dot-vim/ftplugin/html/snips/template.txt | 12 - stow/vim/dot-vim/ftplugin/java/java.vim | 14 - .../vim/dot-vim/ftplugin/javascript/javascript.vim | 38 - stow/vim/dot-vim/ftplugin/plantuml/plantuml.vim | 20 - .../dot-vim/ftplugin/plantuml/snips/template.txt | 9 - stow/vim/dot-vim/ftplugin/python/python.vim | 34 - stow/vim/dot-vim/ftplugin/python/snips/class | 3 - stow/vim/dot-vim/ftplugin/python/snips/template | 5 - stow/vim/dot-vim/ftplugin/sent/sent.vim | 19 - stow/vim/dot-vim/ftplugin/sh/sh.vim | 16 - stow/vim/dot-vim/ftplugin/sh/snippets/if.txt | 3 - stow/vim/dot-vim/ftplugin/tex/snips/template.txt | 30 - stow/vim/dot-vim/ftplugin/tex/tex.vim | 45 - stow/vim/dot-vim/ftplugin/text/text.vim | 20 - .../vim/dot-vim/ftplugin/typescript/typescript.vim | 33 - .../dot-vim/ftplugin/vimwiki/snips/plantUml.txt | 5 - .../dot-vim/ftplugin/vimwiki/snips/template.txt | 15 - stow/vim/dot-vim/ftplugin/vimwiki/vimwiki.vim | 39 - stow/vim/dot-vim/plugin/SWTC.vim | 339 -- stow/vim/dot-vim/plugin/dragvisuals.vim | 345 -- stow/vim/dot-vim/plugin/rng.vim | 83 - stow/vim/dot-vimrc | 280 -- stow/vis/.config/vis/colors/basic_colors | 15 + stow/vis/.config/vis/colors/rainbow | 30 + stow/vis/.config/vis/config | 91 + stow/vis/dot-config/vis/colors/basic_colors | 15 - stow/vis/dot-config/vis/colors/rainbow | 30 - stow/vis/dot-config/vis/config | 91 - stow/zathura/.config/zathura/zathurarc | 58 + stow/zathura/dot-config/zathura/zathurarc | 58 - 176 files changed, 25136 insertions(+), 25136 deletions(-) create mode 100644 stow/XserverDotfiles/.xinitrcbspwm create mode 100644 stow/XserverDotfiles/.xinitrcdwm create mode 100644 stow/XserverDotfiles/.xinitrcgnome create mode 100644 stow/XserverDotfiles/.xinitrci3 create mode 100644 stow/XserverDotfiles/.xinitrcpostintel create mode 100644 stow/XserverDotfiles/.xinitrcpostnvidia create mode 100644 stow/XserverDotfiles/.xinitrcprevintel create mode 100644 stow/XserverDotfiles/.xinitrcprevnvidia create mode 100644 stow/XserverDotfiles/.xinitrcxfce4 delete mode 100644 stow/XserverDotfiles/dot-xinitrcbspwm delete mode 100644 stow/XserverDotfiles/dot-xinitrcdwm delete mode 100644 stow/XserverDotfiles/dot-xinitrcgnome delete mode 100644 stow/XserverDotfiles/dot-xinitrci3 delete mode 100644 stow/XserverDotfiles/dot-xinitrcpostintel delete mode 100644 stow/XserverDotfiles/dot-xinitrcpostnvidia delete mode 100644 stow/XserverDotfiles/dot-xinitrcprevintel delete mode 100644 stow/XserverDotfiles/dot-xinitrcprevnvidia delete mode 100644 stow/XserverDotfiles/dot-xinitrcxfce4 create mode 100755 stow/bspwm/.config/bspwm/bspwmrc delete mode 100755 stow/bspwm/dot-config/bspwm/bspwmrc create mode 100644 stow/cmus/.config/cmus/autosave delete mode 100644 stow/cmus/dot-config/cmus/autosave create mode 100644 stow/colorschemes/.config/colorschemes/customBlue create mode 100644 stow/colorschemes/.config/colorschemes/gruvbox create mode 100644 stow/colorschemes/.config/colorschemes/nord delete mode 100644 stow/colorschemes/dot-config/colorschemes/customBlue delete mode 100644 stow/colorschemes/dot-config/colorschemes/gruvbox delete mode 100644 stow/colorschemes/dot-config/colorschemes/nord create mode 100644 stow/dunst/.config/dunst/dunstifyIDs create mode 100644 stow/dunst/.config/dunst/dunstrc delete mode 100644 stow/dunst/dot-config/dunst/dunstifyIDs delete mode 100644 stow/dunst/dot-config/dunst/dunstrc create mode 100644 stow/emoji/.config/emoji delete mode 100644 stow/emoji/dot-config/emoji create mode 100644 stow/i3/.config/i3/config delete mode 100644 stow/i3/dot-config/i3/config create mode 100644 stow/i3blocks/.config/i3blocks/config delete mode 100644 stow/i3blocks/dot-config/i3blocks/config create mode 100644 stow/mpv/.config/mpv/input.conf create mode 100644 stow/mpv/.config/mpv/mpv.conf create mode 100644 stow/mpv/.config/mpv/scripts-opts/mpv_thumbnail_script.conf create mode 100644 stow/mpv/.config/mpv/scripts-opts/youtube-quality.conf create mode 100644 stow/mpv/.config/mpv/scripts/mpv-splice.lua create mode 100644 stow/mpv/.config/mpv/scripts/mpv_thumbnail_script_client_osc.lua create mode 100644 stow/mpv/.config/mpv/scripts/mpv_thumbnail_script_server.lua create mode 100644 stow/mpv/.config/mpv/scripts/youtube-quality.lua delete mode 100644 stow/mpv/dot-config/mpv/input.conf delete mode 100644 stow/mpv/dot-config/mpv/mpv.conf delete mode 100644 stow/mpv/dot-config/mpv/scripts-opts/mpv_thumbnail_script.conf delete mode 100644 stow/mpv/dot-config/mpv/scripts-opts/youtube-quality.conf delete mode 100644 stow/mpv/dot-config/mpv/scripts/mpv-splice.lua delete mode 100644 stow/mpv/dot-config/mpv/scripts/mpv_thumbnail_script_client_osc.lua delete mode 100644 stow/mpv/dot-config/mpv/scripts/mpv_thumbnail_script_server.lua delete mode 100644 stow/mpv/dot-config/mpv/scripts/youtube-quality.lua create mode 100644 stow/neofetch/.config/neofetch/config.conf create mode 100644 stow/neofetch/.config/neofetch/neofetchLogin.conf delete mode 100644 stow/neofetch/dot-config/neofetch/config.conf delete mode 100644 stow/neofetch/dot-config/neofetch/neofetchLogin.conf create mode 100644 stow/newsboat/.config/newsboat/config delete mode 100644 stow/newsboat/dot-config/newsboat/config create mode 100644 stow/nvim/.config/nvim/init.vim delete mode 100644 stow/nvim/dot-config/nvim/init.vim create mode 100644 stow/pandoc/.config/pandoc/luascripts/diagram-generator.lua delete mode 100644 stow/pandoc/dot-config/pandoc/luascripts/diagram-generator.lua create mode 100644 stow/picom/.config/picom/picom.conf create mode 100644 stow/picom/.config/picom/picom.jonaburg.sample.conf create mode 100644 stow/picom/.config/picom/picom.upstream.conf delete mode 100644 stow/picom/dot-config/picom/picom.conf delete mode 100644 stow/picom/dot-config/picom/picom.jonaburg.sample.conf delete mode 100644 stow/picom/dot-config/picom/picom.upstream.conf create mode 100644 stow/qutebrowser/.config/qutebrowser/config.py delete mode 100644 stow/qutebrowser/dot-config/qutebrowser/config.py create mode 100644 stow/ranger/.config/ranger/rc.conf create mode 100644 stow/ranger/.config/ranger/rifle.conf create mode 100755 stow/ranger/.config/ranger/scope.sh delete mode 100644 stow/ranger/dot-config/ranger/rc.conf delete mode 100644 stow/ranger/dot-config/ranger/rifle.conf delete mode 100755 stow/ranger/dot-config/ranger/scope.sh create mode 100644 stow/rcs/.Xresources create mode 100644 stow/rcs/.bash_aliases create mode 100644 stow/rcs/.bash_vars create mode 100644 stow/rcs/.bashrc create mode 100644 stow/rcs/.config/ttymaps.kmap create mode 100644 stow/rcs/.inputrc create mode 100644 stow/rcs/.profile delete mode 100644 stow/rcs/dot-Xresources delete mode 100644 stow/rcs/dot-bash_aliases delete mode 100644 stow/rcs/dot-bash_vars delete mode 100644 stow/rcs/dot-bashrc delete mode 100644 stow/rcs/dot-config/ttymaps.kmap delete mode 100644 stow/rcs/dot-inputrc delete mode 100644 stow/rcs/dot-profile create mode 100644 stow/sxhkd/.config/sxhkd/sxhkdrc create mode 100644 stow/sxhkd/.config/sxhkd/sxhkdrcbspc delete mode 100644 stow/sxhkd/dot-config/sxhkd/sxhkdrc delete mode 100644 stow/sxhkd/dot-config/sxhkd/sxhkdrcbspc create mode 100755 stow/sxiv/.config/sxiv/exec/image-info create mode 100755 stow/sxiv/.config/sxiv/exec/key-handler delete mode 100755 stow/sxiv/dot-config/sxiv/exec/image-info delete mode 100755 stow/sxiv/dot-config/sxiv/exec/key-handler create mode 100644 stow/tmux/.tmux.conf delete mode 100644 stow/tmux/dot-tmux.conf create mode 100644 stow/vim/.vim/autoload/plug.vim create mode 100644 stow/vim/.vim/autoload/plug.vim.old create mode 100644 stow/vim/.vim/colors/burnttoast256.vim create mode 100644 stow/vim/.vim/colors/nord.vim create mode 100644 stow/vim/.vim/ftplugin/antlr/antlr3.vim create mode 100644 stow/vim/.vim/ftplugin/antlr/antlr4.vim create mode 100644 stow/vim/.vim/ftplugin/asciidoc/asciidoc.vim create mode 100644 stow/vim/.vim/ftplugin/cpp/cpp.vim create mode 100644 stow/vim/.vim/ftplugin/cpp/snips/template.txt create mode 100644 stow/vim/.vim/ftplugin/css/css.vim create mode 100644 stow/vim/.vim/ftplugin/html/html.vim create mode 100644 stow/vim/.vim/ftplugin/html/snips/template.txt create mode 100644 stow/vim/.vim/ftplugin/java/java.vim create mode 100644 stow/vim/.vim/ftplugin/javascript/javascript.vim create mode 100644 stow/vim/.vim/ftplugin/plantuml/plantuml.vim create mode 100644 stow/vim/.vim/ftplugin/plantuml/snips/template.txt create mode 100644 stow/vim/.vim/ftplugin/python/python.vim create mode 100644 stow/vim/.vim/ftplugin/python/snips/class create mode 100644 stow/vim/.vim/ftplugin/python/snips/template create mode 100644 stow/vim/.vim/ftplugin/sent/sent.vim create mode 100644 stow/vim/.vim/ftplugin/sh/sh.vim create mode 100644 stow/vim/.vim/ftplugin/sh/snippets/if.txt create mode 100644 stow/vim/.vim/ftplugin/tex/snips/template.txt create mode 100644 stow/vim/.vim/ftplugin/tex/tex.vim create mode 100644 stow/vim/.vim/ftplugin/text/text.vim create mode 100644 stow/vim/.vim/ftplugin/typescript/typescript.vim create mode 100644 stow/vim/.vim/ftplugin/vimwiki/snips/plantUml.txt create mode 100644 stow/vim/.vim/ftplugin/vimwiki/snips/template.txt create mode 100644 stow/vim/.vim/ftplugin/vimwiki/vimwiki.vim create mode 100644 stow/vim/.vim/plugin/SWTC.vim create mode 100644 stow/vim/.vim/plugin/dragvisuals.vim create mode 100644 stow/vim/.vim/plugin/rng.vim create mode 100644 stow/vim/.vimrc delete mode 100644 stow/vim/dot-vim/autoload/plug.vim delete mode 100644 stow/vim/dot-vim/autoload/plug.vim.old delete mode 100644 stow/vim/dot-vim/colors/burnttoast256.vim delete mode 100644 stow/vim/dot-vim/colors/nord.vim delete mode 100644 stow/vim/dot-vim/ftplugin/antlr/antlr3.vim delete mode 100644 stow/vim/dot-vim/ftplugin/antlr/antlr4.vim delete mode 100644 stow/vim/dot-vim/ftplugin/asciidoc/asciidoc.vim delete mode 100644 stow/vim/dot-vim/ftplugin/cpp/cpp.vim delete mode 100644 stow/vim/dot-vim/ftplugin/cpp/snips/template.txt delete mode 100644 stow/vim/dot-vim/ftplugin/css/css.vim delete mode 100644 stow/vim/dot-vim/ftplugin/html/html.vim delete mode 100644 stow/vim/dot-vim/ftplugin/html/snips/template.txt delete mode 100644 stow/vim/dot-vim/ftplugin/java/java.vim delete mode 100644 stow/vim/dot-vim/ftplugin/javascript/javascript.vim delete mode 100644 stow/vim/dot-vim/ftplugin/plantuml/plantuml.vim delete mode 100644 stow/vim/dot-vim/ftplugin/plantuml/snips/template.txt delete mode 100644 stow/vim/dot-vim/ftplugin/python/python.vim delete mode 100644 stow/vim/dot-vim/ftplugin/python/snips/class delete mode 100644 stow/vim/dot-vim/ftplugin/python/snips/template delete mode 100644 stow/vim/dot-vim/ftplugin/sent/sent.vim delete mode 100644 stow/vim/dot-vim/ftplugin/sh/sh.vim delete mode 100644 stow/vim/dot-vim/ftplugin/sh/snippets/if.txt delete mode 100644 stow/vim/dot-vim/ftplugin/tex/snips/template.txt delete mode 100644 stow/vim/dot-vim/ftplugin/tex/tex.vim delete mode 100644 stow/vim/dot-vim/ftplugin/text/text.vim delete mode 100644 stow/vim/dot-vim/ftplugin/typescript/typescript.vim delete mode 100644 stow/vim/dot-vim/ftplugin/vimwiki/snips/plantUml.txt delete mode 100644 stow/vim/dot-vim/ftplugin/vimwiki/snips/template.txt delete mode 100644 stow/vim/dot-vim/ftplugin/vimwiki/vimwiki.vim delete mode 100644 stow/vim/dot-vim/plugin/SWTC.vim delete mode 100644 stow/vim/dot-vim/plugin/dragvisuals.vim delete mode 100644 stow/vim/dot-vim/plugin/rng.vim delete mode 100644 stow/vim/dot-vimrc create mode 100644 stow/vis/.config/vis/colors/basic_colors create mode 100644 stow/vis/.config/vis/colors/rainbow create mode 100644 stow/vis/.config/vis/config delete mode 100644 stow/vis/dot-config/vis/colors/basic_colors delete mode 100644 stow/vis/dot-config/vis/colors/rainbow delete mode 100644 stow/vis/dot-config/vis/config create mode 100644 stow/zathura/.config/zathura/zathurarc delete mode 100644 stow/zathura/dot-config/zathura/zathurarc diff --git a/stow/XserverDotfiles/.xinitrcbspwm b/stow/XserverDotfiles/.xinitrcbspwm new file mode 100644 index 0000000..ac7f120 --- /dev/null +++ b/stow/XserverDotfiles/.xinitrcbspwm @@ -0,0 +1 @@ +exec bspwm diff --git a/stow/XserverDotfiles/.xinitrcdwm b/stow/XserverDotfiles/.xinitrcdwm new file mode 100644 index 0000000..e59268d --- /dev/null +++ b/stow/XserverDotfiles/.xinitrcdwm @@ -0,0 +1,2 @@ +dwmblocks & +xinit.sh; exec dwm diff --git a/stow/XserverDotfiles/.xinitrcgnome b/stow/XserverDotfiles/.xinitrcgnome new file mode 100644 index 0000000..74f16d6 --- /dev/null +++ b/stow/XserverDotfiles/.xinitrcgnome @@ -0,0 +1,3 @@ +export XDG_SESSION_TYPE=x11 +export GDK_BACKEND=x11 +xinit.sh; exec gnome-session diff --git a/stow/XserverDotfiles/.xinitrci3 b/stow/XserverDotfiles/.xinitrci3 new file mode 100644 index 0000000..ba0c6ef --- /dev/null +++ b/stow/XserverDotfiles/.xinitrci3 @@ -0,0 +1 @@ +exec i3 diff --git a/stow/XserverDotfiles/.xinitrcpostintel b/stow/XserverDotfiles/.xinitrcpostintel new file mode 100644 index 0000000..e69de29 diff --git a/stow/XserverDotfiles/.xinitrcpostnvidia b/stow/XserverDotfiles/.xinitrcpostnvidia new file mode 100644 index 0000000..7412099 --- /dev/null +++ b/stow/XserverDotfiles/.xinitrcpostnvidia @@ -0,0 +1,2 @@ +sudo /usr/bin/prime-switch + diff --git a/stow/XserverDotfiles/.xinitrcprevintel b/stow/XserverDotfiles/.xinitrcprevintel new file mode 100644 index 0000000..e69de29 diff --git a/stow/XserverDotfiles/.xinitrcprevnvidia b/stow/XserverDotfiles/.xinitrcprevnvidia new file mode 100644 index 0000000..18e2dfc --- /dev/null +++ b/stow/XserverDotfiles/.xinitrcprevnvidia @@ -0,0 +1,4 @@ +xrandr --setprovideroutputsource modesetting NVIDIA-0 +xrandr --auto +xrandr --dpi 96 +/usr/bin/prime-offload diff --git a/stow/XserverDotfiles/.xinitrcxfce4 b/stow/XserverDotfiles/.xinitrcxfce4 new file mode 100644 index 0000000..d6c8552 --- /dev/null +++ b/stow/XserverDotfiles/.xinitrcxfce4 @@ -0,0 +1 @@ +exec xfce4-session diff --git a/stow/XserverDotfiles/dot-xinitrcbspwm b/stow/XserverDotfiles/dot-xinitrcbspwm deleted file mode 100644 index ac7f120..0000000 --- a/stow/XserverDotfiles/dot-xinitrcbspwm +++ /dev/null @@ -1 +0,0 @@ -exec bspwm diff --git a/stow/XserverDotfiles/dot-xinitrcdwm b/stow/XserverDotfiles/dot-xinitrcdwm deleted file mode 100644 index e59268d..0000000 --- a/stow/XserverDotfiles/dot-xinitrcdwm +++ /dev/null @@ -1,2 +0,0 @@ -dwmblocks & -xinit.sh; exec dwm diff --git a/stow/XserverDotfiles/dot-xinitrcgnome b/stow/XserverDotfiles/dot-xinitrcgnome deleted file mode 100644 index 74f16d6..0000000 --- a/stow/XserverDotfiles/dot-xinitrcgnome +++ /dev/null @@ -1,3 +0,0 @@ -export XDG_SESSION_TYPE=x11 -export GDK_BACKEND=x11 -xinit.sh; exec gnome-session diff --git a/stow/XserverDotfiles/dot-xinitrci3 b/stow/XserverDotfiles/dot-xinitrci3 deleted file mode 100644 index ba0c6ef..0000000 --- a/stow/XserverDotfiles/dot-xinitrci3 +++ /dev/null @@ -1 +0,0 @@ -exec i3 diff --git a/stow/XserverDotfiles/dot-xinitrcpostintel b/stow/XserverDotfiles/dot-xinitrcpostintel deleted file mode 100644 index e69de29..0000000 diff --git a/stow/XserverDotfiles/dot-xinitrcpostnvidia b/stow/XserverDotfiles/dot-xinitrcpostnvidia deleted file mode 100644 index 7412099..0000000 --- a/stow/XserverDotfiles/dot-xinitrcpostnvidia +++ /dev/null @@ -1,2 +0,0 @@ -sudo /usr/bin/prime-switch - diff --git a/stow/XserverDotfiles/dot-xinitrcprevintel b/stow/XserverDotfiles/dot-xinitrcprevintel deleted file mode 100644 index e69de29..0000000 diff --git a/stow/XserverDotfiles/dot-xinitrcprevnvidia b/stow/XserverDotfiles/dot-xinitrcprevnvidia deleted file mode 100644 index 18e2dfc..0000000 --- a/stow/XserverDotfiles/dot-xinitrcprevnvidia +++ /dev/null @@ -1,4 +0,0 @@ -xrandr --setprovideroutputsource modesetting NVIDIA-0 -xrandr --auto -xrandr --dpi 96 -/usr/bin/prime-offload diff --git a/stow/XserverDotfiles/dot-xinitrcxfce4 b/stow/XserverDotfiles/dot-xinitrcxfce4 deleted file mode 100644 index d6c8552..0000000 --- a/stow/XserverDotfiles/dot-xinitrcxfce4 +++ /dev/null @@ -1 +0,0 @@ -exec xfce4-session diff --git a/stow/bspwm/.config/bspwm/bspwmrc b/stow/bspwm/.config/bspwm/bspwmrc new file mode 100755 index 0000000..5dd20e5 --- /dev/null +++ b/stow/bspwm/.config/bspwm/bspwmrc @@ -0,0 +1,28 @@ +#!/bin/sh + +desktops="I II III IV V" + +if xrandr | grep -q 'HDMI-1-1 connected'; then + bspc monitor '^1' -d $desktops + bspc monitor '^2' -d $desktops +else + bspc monitor -d $desktops +fi + +bspc config border_width 4 +bspc config window_gap 10 + +bspc config split_ratio 0.50 +bspc config borderless_monocle true +bspc config gapless_monocle true + +#bspc rule -a Gimp desktop='^8' state=floating follow=on +#bspc rule -a Chromium desktop='^2' +#bspc rule -a mplayer2 state=floating +#bspc rule -a mpv state=floating +#bspc rule -a Kupfer.py focus=on +bspc rule -a Screenkey manage=off + +pgrep -x sxhkd > /dev/null || sxhkd "$XDG_CONFIG_HOME/sxhkd/sxhkdrcbspc" >~/logs/sxhkd.log & + +xinit.sh diff --git a/stow/bspwm/dot-config/bspwm/bspwmrc b/stow/bspwm/dot-config/bspwm/bspwmrc deleted file mode 100755 index 5dd20e5..0000000 --- a/stow/bspwm/dot-config/bspwm/bspwmrc +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -desktops="I II III IV V" - -if xrandr | grep -q 'HDMI-1-1 connected'; then - bspc monitor '^1' -d $desktops - bspc monitor '^2' -d $desktops -else - bspc monitor -d $desktops -fi - -bspc config border_width 4 -bspc config window_gap 10 - -bspc config split_ratio 0.50 -bspc config borderless_monocle true -bspc config gapless_monocle true - -#bspc rule -a Gimp desktop='^8' state=floating follow=on -#bspc rule -a Chromium desktop='^2' -#bspc rule -a mplayer2 state=floating -#bspc rule -a mpv state=floating -#bspc rule -a Kupfer.py focus=on -bspc rule -a Screenkey manage=off - -pgrep -x sxhkd > /dev/null || sxhkd "$XDG_CONFIG_HOME/sxhkd/sxhkdrcbspc" >~/logs/sxhkd.log & - -xinit.sh diff --git a/stow/cmus/.config/cmus/autosave b/stow/cmus/.config/cmus/autosave new file mode 100644 index 0000000..86d1436 --- /dev/null +++ b/stow/cmus/.config/cmus/autosave @@ -0,0 +1,217 @@ +set aaa_mode=all +set altformat_current= %F +set altformat_playlist= %f%= %d +set altformat_title=%f +set altformat_trackwin= %f%= %d +set auto_expand_albums_follow=true +set auto_expand_albums_search=true +set auto_expand_albums_selcur=true +set auto_reshuffle=true +set buffer_seconds=10 +set color_cmdline_attr=default +set color_cmdline_bg=default +set color_cmdline_fg=default +set color_cur_sel_attr=default +set color_error=lightred +set color_info=lightcyan +set color_separator=blue +set color_statusline_attr=default +set color_statusline_bg=gray +set color_statusline_fg=black +set color_titleline_attr=default +set color_titleline_bg=blue +set color_titleline_fg=white +set color_trackwin_album_attr=bold +set color_trackwin_album_bg=default +set color_trackwin_album_fg=default +set color_win_attr=default +set color_win_bg=default +set color_win_cur=lightgreen +set color_win_cur_attr=default +set color_win_cur_sel_attr=default +set color_win_cur_sel_bg=blue +set color_win_cur_sel_fg=lightgreen +set color_win_dir=lightblue +set color_win_fg=default +set color_win_inactive_cur_sel_attr=default +set color_win_inactive_cur_sel_bg=lightblue +set color_win_inactive_cur_sel_fg=lightgreen +set color_win_inactive_sel_attr=default +set color_win_inactive_sel_bg=lightblue +set color_win_inactive_sel_fg=black +set color_win_sel_attr=default +set color_win_sel_bg=blue +set color_win_sel_fg=white +set color_win_title_attr=default +set color_win_title_bg=blue +set color_win_title_fg=white +set confirm_run=true +set continue=true +set continue_album=true +set device=/dev/cdrom +set display_artist_sort_name=false +set dsp.alsa.device= +set dsp.ao.buffer_size=16384 +set dsp.ao.device_interface= +set dsp.ao.driver= +set dsp.ao.wav_counter=1 +set dsp.ao.wav_dir=/home/taamas +set dsp.jack.resampling_quality=2 +set dsp.jack.server_name= +set dsp.oss.device= +set follow=true +set format_current= %a - %l -%3n. %t%= %y +set format_playlist= %-21%a %3n. %t%= %y %d %{?X!=0?%3X ? } +set format_playlist_va= %-21%A %3n. %t (%a)%= %y %d %{?X!=0?%3X ? } +set format_statusline= %{status} %{?show_playback_position?%{position} %{?duration?/ %{duration} }?%{?duration?%{duration} }}- %{total} %{?bpm>0?at %{bpm} BPM }%{?volume>=0?vol: %{?lvolume!=rvolume?%{lvolume},%{rvolume} ?%{volume} }}%{?stream?buf: %{buffer} }%{?show_current_bitrate & bitrate>=0? %{bitrate} kbps }%=%{?repeat_current?repeat current?%{?play_library?%{playlist_mode} from %{?play_sorted?sorted }library?playlist}} | %1{continue}%1{follow}%1{repeat}%1{shuffle} +set format_title=%a - %l - %t (%y) +set format_trackwin=%3n. %t%= %y %d +set format_trackwin_album= %l %= %{albumduration} +set format_trackwin_va=%3n. %t (%a)%= %y %d +set format_treewin= %l +set format_treewin_artist=%a +set icecast_default_charset=ISO-8859-1 +set id3_default_charset=ISO-8859-1 +set input.aac.priority=50 +set input.cdio.cddb_url=freedb.freedb.org:8880 +set input.cdio.priority=50 +set input.cue.priority=50 +set input.ffmpeg.priority=30 +set input.flac.priority=50 +set input.mad.priority=55 +set input.modplug.priority=50 +set input.mpc.priority=50 +set input.opus.priority=50 +set input.vorbis.priority=50 +set input.wav.priority=50 +set input.wavpack.priority=50 +set lib_add_filter= +set lib_sort=albumartist date album discnumber tracknumber title filename play_count +set mixer.alsa.channel= +set mixer.alsa.device= +set mixer.oss.channel=PCM +set mixer.oss.device= +set mixer.pulse.restore_volume=1 +set mouse=false +set mpris=true +set output_plugin=pulse +set passwd= +set pl_sort= +set play_library=true +set play_sorted=false +set repeat=true +set repeat_current=false +set replaygain=disabled +set replaygain_limit=true +set replaygain_preamp=0.000000 +set resume=false +set rewind_offset=5 +set scroll_offset=2 +set set_term_title=true +set show_all_tracks=true +set show_current_bitrate=false +set show_hidden=false +set show_playback_position=true +set show_remaining_time=false +set shuffle=true +set skip_track_info=false +set smart_artist_sort=true +set softvol=false +set softvol_state=0 0 +set start_view=tree +set status_display_program= +set stop_after_queue=false +set time_show_leading_zero=false +set tree_width_max=0 +set tree_width_percent=33 +set wrap_search=true +bind browser backspace browser-up +bind browser i toggle show_hidden +bind browser space win-activate +bind browser u win-update +bind common ! push shell +bind common + vol +10% +bind common , seek -1m +bind common - vol -10% +bind common . seek +1m +bind common / search-start +bind common 1 view tree +bind common 2 view sorted +bind common 3 view playlist +bind common 4 view queue +bind common 5 view browser +bind common 6 view filters +bind common 7 view settings +bind common = vol +10% +bind common ? search-b-start +bind common C toggle continue +bind common D win-remove +bind common E win-add-Q +bind common F push filter +bind common G win-bottom +bind common I echo {} +bind common L push live-filter +bind common M toggle play_library +bind common N search-prev +bind common P win-mv-before +bind common U win-update-cache +bind common [ vol +1% +0 +bind common ] vol +0 +1% +bind common ^B win-page-up +bind common ^C echo Type :quit to exit cmus. +bind common ^D win-half-page-down +bind common ^E win-scroll-down +bind common ^F win-page-down +bind common ^L refresh +bind common ^R toggle repeat_current +bind common ^U win-half-page-up +bind common ^Y win-scroll-up +bind common a win-add-l +bind common b player-next +bind common c player-pause +bind common delete win-remove +bind common down win-down +bind common e win-add-q +bind common end win-bottom +bind common enter win-activate +bind common f toggle follow +bind common g win-top +bind common h seek -5 +bind common home win-top +bind common i win-sel-cur +bind common j win-down +bind common k win-up +bind common l seek +5 +bind common left seek -5 +bind common m toggle aaa_mode +bind common mlb_click_selected win-activate +bind common mouse_scroll_down win-down +bind common mouse_scroll_up win-up +bind common n search-next +bind common o toggle play_sorted +bind common p win-mv-after +bind common page_down win-page-down +bind common page_up win-page-up +bind common q quit -i +bind common r toggle repeat +bind common right seek +5 +bind common s toggle shuffle +bind common space win-toggle +bind common t toggle show_remaining_time +bind common tab win-next +bind common u update-cache +bind common up win-up +bind common v player-stop +bind common x player-play +bind common y win-add-p +bind common z player-prev +bind common { vol -1% -0 +bind common } vol -0 -1% +fset 90s=date>=1990&date<2000 +fset classical=genre="Classical" +fset missing-tag=!stream&(artist=""|album=""|title=""|tracknumber=-1|date=-1) +fset mp3=filename="*.mp3" +fset ogg=filename="*.ogg" +fset ogg-or-mp3=ogg|mp3 +fset unheard=play_count=0 +factivate diff --git a/stow/cmus/dot-config/cmus/autosave b/stow/cmus/dot-config/cmus/autosave deleted file mode 100644 index 86d1436..0000000 --- a/stow/cmus/dot-config/cmus/autosave +++ /dev/null @@ -1,217 +0,0 @@ -set aaa_mode=all -set altformat_current= %F -set altformat_playlist= %f%= %d -set altformat_title=%f -set altformat_trackwin= %f%= %d -set auto_expand_albums_follow=true -set auto_expand_albums_search=true -set auto_expand_albums_selcur=true -set auto_reshuffle=true -set buffer_seconds=10 -set color_cmdline_attr=default -set color_cmdline_bg=default -set color_cmdline_fg=default -set color_cur_sel_attr=default -set color_error=lightred -set color_info=lightcyan -set color_separator=blue -set color_statusline_attr=default -set color_statusline_bg=gray -set color_statusline_fg=black -set color_titleline_attr=default -set color_titleline_bg=blue -set color_titleline_fg=white -set color_trackwin_album_attr=bold -set color_trackwin_album_bg=default -set color_trackwin_album_fg=default -set color_win_attr=default -set color_win_bg=default -set color_win_cur=lightgreen -set color_win_cur_attr=default -set color_win_cur_sel_attr=default -set color_win_cur_sel_bg=blue -set color_win_cur_sel_fg=lightgreen -set color_win_dir=lightblue -set color_win_fg=default -set color_win_inactive_cur_sel_attr=default -set color_win_inactive_cur_sel_bg=lightblue -set color_win_inactive_cur_sel_fg=lightgreen -set color_win_inactive_sel_attr=default -set color_win_inactive_sel_bg=lightblue -set color_win_inactive_sel_fg=black -set color_win_sel_attr=default -set color_win_sel_bg=blue -set color_win_sel_fg=white -set color_win_title_attr=default -set color_win_title_bg=blue -set color_win_title_fg=white -set confirm_run=true -set continue=true -set continue_album=true -set device=/dev/cdrom -set display_artist_sort_name=false -set dsp.alsa.device= -set dsp.ao.buffer_size=16384 -set dsp.ao.device_interface= -set dsp.ao.driver= -set dsp.ao.wav_counter=1 -set dsp.ao.wav_dir=/home/taamas -set dsp.jack.resampling_quality=2 -set dsp.jack.server_name= -set dsp.oss.device= -set follow=true -set format_current= %a - %l -%3n. %t%= %y -set format_playlist= %-21%a %3n. %t%= %y %d %{?X!=0?%3X ? } -set format_playlist_va= %-21%A %3n. %t (%a)%= %y %d %{?X!=0?%3X ? } -set format_statusline= %{status} %{?show_playback_position?%{position} %{?duration?/ %{duration} }?%{?duration?%{duration} }}- %{total} %{?bpm>0?at %{bpm} BPM }%{?volume>=0?vol: %{?lvolume!=rvolume?%{lvolume},%{rvolume} ?%{volume} }}%{?stream?buf: %{buffer} }%{?show_current_bitrate & bitrate>=0? %{bitrate} kbps }%=%{?repeat_current?repeat current?%{?play_library?%{playlist_mode} from %{?play_sorted?sorted }library?playlist}} | %1{continue}%1{follow}%1{repeat}%1{shuffle} -set format_title=%a - %l - %t (%y) -set format_trackwin=%3n. %t%= %y %d -set format_trackwin_album= %l %= %{albumduration} -set format_trackwin_va=%3n. %t (%a)%= %y %d -set format_treewin= %l -set format_treewin_artist=%a -set icecast_default_charset=ISO-8859-1 -set id3_default_charset=ISO-8859-1 -set input.aac.priority=50 -set input.cdio.cddb_url=freedb.freedb.org:8880 -set input.cdio.priority=50 -set input.cue.priority=50 -set input.ffmpeg.priority=30 -set input.flac.priority=50 -set input.mad.priority=55 -set input.modplug.priority=50 -set input.mpc.priority=50 -set input.opus.priority=50 -set input.vorbis.priority=50 -set input.wav.priority=50 -set input.wavpack.priority=50 -set lib_add_filter= -set lib_sort=albumartist date album discnumber tracknumber title filename play_count -set mixer.alsa.channel= -set mixer.alsa.device= -set mixer.oss.channel=PCM -set mixer.oss.device= -set mixer.pulse.restore_volume=1 -set mouse=false -set mpris=true -set output_plugin=pulse -set passwd= -set pl_sort= -set play_library=true -set play_sorted=false -set repeat=true -set repeat_current=false -set replaygain=disabled -set replaygain_limit=true -set replaygain_preamp=0.000000 -set resume=false -set rewind_offset=5 -set scroll_offset=2 -set set_term_title=true -set show_all_tracks=true -set show_current_bitrate=false -set show_hidden=false -set show_playback_position=true -set show_remaining_time=false -set shuffle=true -set skip_track_info=false -set smart_artist_sort=true -set softvol=false -set softvol_state=0 0 -set start_view=tree -set status_display_program= -set stop_after_queue=false -set time_show_leading_zero=false -set tree_width_max=0 -set tree_width_percent=33 -set wrap_search=true -bind browser backspace browser-up -bind browser i toggle show_hidden -bind browser space win-activate -bind browser u win-update -bind common ! push shell -bind common + vol +10% -bind common , seek -1m -bind common - vol -10% -bind common . seek +1m -bind common / search-start -bind common 1 view tree -bind common 2 view sorted -bind common 3 view playlist -bind common 4 view queue -bind common 5 view browser -bind common 6 view filters -bind common 7 view settings -bind common = vol +10% -bind common ? search-b-start -bind common C toggle continue -bind common D win-remove -bind common E win-add-Q -bind common F push filter -bind common G win-bottom -bind common I echo {} -bind common L push live-filter -bind common M toggle play_library -bind common N search-prev -bind common P win-mv-before -bind common U win-update-cache -bind common [ vol +1% +0 -bind common ] vol +0 +1% -bind common ^B win-page-up -bind common ^C echo Type :quit to exit cmus. -bind common ^D win-half-page-down -bind common ^E win-scroll-down -bind common ^F win-page-down -bind common ^L refresh -bind common ^R toggle repeat_current -bind common ^U win-half-page-up -bind common ^Y win-scroll-up -bind common a win-add-l -bind common b player-next -bind common c player-pause -bind common delete win-remove -bind common down win-down -bind common e win-add-q -bind common end win-bottom -bind common enter win-activate -bind common f toggle follow -bind common g win-top -bind common h seek -5 -bind common home win-top -bind common i win-sel-cur -bind common j win-down -bind common k win-up -bind common l seek +5 -bind common left seek -5 -bind common m toggle aaa_mode -bind common mlb_click_selected win-activate -bind common mouse_scroll_down win-down -bind common mouse_scroll_up win-up -bind common n search-next -bind common o toggle play_sorted -bind common p win-mv-after -bind common page_down win-page-down -bind common page_up win-page-up -bind common q quit -i -bind common r toggle repeat -bind common right seek +5 -bind common s toggle shuffle -bind common space win-toggle -bind common t toggle show_remaining_time -bind common tab win-next -bind common u update-cache -bind common up win-up -bind common v player-stop -bind common x player-play -bind common y win-add-p -bind common z player-prev -bind common { vol -1% -0 -bind common } vol -0 -1% -fset 90s=date>=1990&date<2000 -fset classical=genre="Classical" -fset missing-tag=!stream&(artist=""|album=""|title=""|tracknumber=-1|date=-1) -fset mp3=filename="*.mp3" -fset ogg=filename="*.ogg" -fset ogg-or-mp3=ogg|mp3 -fset unheard=play_count=0 -factivate diff --git a/stow/colorschemes/.config/colorschemes/customBlue b/stow/colorschemes/.config/colorschemes/customBlue new file mode 100644 index 0000000..a96475f --- /dev/null +++ b/stow/colorschemes/.config/colorschemes/customBlue @@ -0,0 +1,29 @@ +!Custom blue +!*background: #181820 +*background: #232f40 +!*foreground: #ebdbb2 +*foreground: #ffffff +! Black + DarkGrey +*color0: #000000 +*color8: #181820 +! DarkRed + Red +*color1: #ff3333 +*color9: #ff6666 +! DarkGreen + Green +*color2: #66ff66 +*color10: #b2ff66 +! DarkYellow + Yellow +*color3: #fabd2f +*color11: #ffff66 +! DarkBlue + Blue +*color4: #6666ff +*color12: #66b2ff +! DarkMagenta + Magenta +*color5: #ff3366 +*color13: #ff66bb +! DarkCyan + Cyan +*color6: #33ddff +*color14: #66ffff +! LightGrey + White +*color7: #ebdbb2 +*color15: #ffffff diff --git a/stow/colorschemes/.config/colorschemes/gruvbox b/stow/colorschemes/.config/colorschemes/gruvbox new file mode 100644 index 0000000..5c83041 --- /dev/null +++ b/stow/colorschemes/.config/colorschemes/gruvbox @@ -0,0 +1,31 @@ +!Gruvbox +*background: #1d2021 +!*background: #32302f +!*background: #282828 +!*foreground: #d5c4a1 +*foreground: #fbf1c7 +!*foreground: #ebdbb2 +! Black + DarkGrey +*color0: #282828 +*color8: #928374 +! DarkRed + Red +*color1: #cc241d +*color9: #fb4934 +! DarkGreen + Green +*color2: #98971a +*color10: #b8bb26 +! DarkYellow + Yellow +*color3: #d79921 +*color11: #fabd2f +! DarkBlue + Blue +*color4: #358588 +*color12: #83a598 +! DarkMagenta + Magenta +*color5: #b16286 +*color13: #d3869b +! DarkCyan + Cyan +*color6: #689d6a +*color14: #8ec07c +! LightGrey + White +*color7: #a89984 +*color15: #ebdbb2 diff --git a/stow/colorschemes/.config/colorschemes/nord b/stow/colorschemes/.config/colorschemes/nord new file mode 100644 index 0000000..916a0ff --- /dev/null +++ b/stow/colorschemes/.config/colorschemes/nord @@ -0,0 +1,47 @@ +! Copyright (c) 2016-present Arctic Ice Studio +! Copyright (c) 2016-present Sven Greb + +! Project: Nord XResources +! Version: 0.1.0 +! Repository: https://github.com/arcticicestudio/nord-xresources +! License: MIT + +#define nord0 #2E3440 +#define nord1 #3B4252 +#define nord2 #434C5E +#define nord3 #4C566A +#define nord4 #D8DEE9 +#define nord5 #E5E9F0 +#define nord6 #ECEFF4 +#define nord7 #8FBCBB +#define nord8 #88C0D0 +#define nord9 #81A1C1 +#define nord10 #5E81AC +#define nord11 #BF616A +#define nord12 #D08770 +#define nord13 #EBCB8B +#define nord14 #A3BE8C +#define nord15 #B48EAD + +*.foreground: nord4 +*.background: nord0 +*.cursorColor: nord4 +*fading: 35 +*fadeColor: nord3 + +*.color0: nord1 +*.color1: nord11 +*.color2: nord14 +*.color3: nord13 +*.color4: nord9 +*.color5: nord15 +*.color6: nord8 +*.color7: nord5 +*.color8: nord3 +*.color9: nord11 +*.color10: nord14 +*.color11: nord13 +*.color12: nord9 +*.color13: nord15 +*.color14: nord7 +*.color15: nord6 diff --git a/stow/colorschemes/dot-config/colorschemes/customBlue b/stow/colorschemes/dot-config/colorschemes/customBlue deleted file mode 100644 index a96475f..0000000 --- a/stow/colorschemes/dot-config/colorschemes/customBlue +++ /dev/null @@ -1,29 +0,0 @@ -!Custom blue -!*background: #181820 -*background: #232f40 -!*foreground: #ebdbb2 -*foreground: #ffffff -! Black + DarkGrey -*color0: #000000 -*color8: #181820 -! DarkRed + Red -*color1: #ff3333 -*color9: #ff6666 -! DarkGreen + Green -*color2: #66ff66 -*color10: #b2ff66 -! DarkYellow + Yellow -*color3: #fabd2f -*color11: #ffff66 -! DarkBlue + Blue -*color4: #6666ff -*color12: #66b2ff -! DarkMagenta + Magenta -*color5: #ff3366 -*color13: #ff66bb -! DarkCyan + Cyan -*color6: #33ddff -*color14: #66ffff -! LightGrey + White -*color7: #ebdbb2 -*color15: #ffffff diff --git a/stow/colorschemes/dot-config/colorschemes/gruvbox b/stow/colorschemes/dot-config/colorschemes/gruvbox deleted file mode 100644 index 5c83041..0000000 --- a/stow/colorschemes/dot-config/colorschemes/gruvbox +++ /dev/null @@ -1,31 +0,0 @@ -!Gruvbox -*background: #1d2021 -!*background: #32302f -!*background: #282828 -!*foreground: #d5c4a1 -*foreground: #fbf1c7 -!*foreground: #ebdbb2 -! Black + DarkGrey -*color0: #282828 -*color8: #928374 -! DarkRed + Red -*color1: #cc241d -*color9: #fb4934 -! DarkGreen + Green -*color2: #98971a -*color10: #b8bb26 -! DarkYellow + Yellow -*color3: #d79921 -*color11: #fabd2f -! DarkBlue + Blue -*color4: #358588 -*color12: #83a598 -! DarkMagenta + Magenta -*color5: #b16286 -*color13: #d3869b -! DarkCyan + Cyan -*color6: #689d6a -*color14: #8ec07c -! LightGrey + White -*color7: #a89984 -*color15: #ebdbb2 diff --git a/stow/colorschemes/dot-config/colorschemes/nord b/stow/colorschemes/dot-config/colorschemes/nord deleted file mode 100644 index 916a0ff..0000000 --- a/stow/colorschemes/dot-config/colorschemes/nord +++ /dev/null @@ -1,47 +0,0 @@ -! Copyright (c) 2016-present Arctic Ice Studio -! Copyright (c) 2016-present Sven Greb - -! Project: Nord XResources -! Version: 0.1.0 -! Repository: https://github.com/arcticicestudio/nord-xresources -! License: MIT - -#define nord0 #2E3440 -#define nord1 #3B4252 -#define nord2 #434C5E -#define nord3 #4C566A -#define nord4 #D8DEE9 -#define nord5 #E5E9F0 -#define nord6 #ECEFF4 -#define nord7 #8FBCBB -#define nord8 #88C0D0 -#define nord9 #81A1C1 -#define nord10 #5E81AC -#define nord11 #BF616A -#define nord12 #D08770 -#define nord13 #EBCB8B -#define nord14 #A3BE8C -#define nord15 #B48EAD - -*.foreground: nord4 -*.background: nord0 -*.cursorColor: nord4 -*fading: 35 -*fadeColor: nord3 - -*.color0: nord1 -*.color1: nord11 -*.color2: nord14 -*.color3: nord13 -*.color4: nord9 -*.color5: nord15 -*.color6: nord8 -*.color7: nord5 -*.color8: nord3 -*.color9: nord11 -*.color10: nord14 -*.color11: nord13 -*.color12: nord9 -*.color13: nord15 -*.color14: nord7 -*.color15: nord6 diff --git a/stow/dunst/.config/dunst/dunstifyIDs b/stow/dunst/.config/dunst/dunstifyIDs new file mode 100644 index 0000000..2bccbf4 --- /dev/null +++ b/stow/dunst/.config/dunst/dunstifyIDs @@ -0,0 +1,12 @@ +vol 1001 +musicMode 1002 +brightness 1003 +cpu 1004 +memory 1005 +disk 1006 +batteryLow 1007 +moon 1008 +calcurse 1009 +bspwmDesktop 1010 +toggleKBLayouts 1011 +bspwmRunningStuff 1012 diff --git a/stow/dunst/.config/dunst/dunstrc b/stow/dunst/.config/dunst/dunstrc new file mode 100644 index 0000000..80004aa --- /dev/null +++ b/stow/dunst/.config/dunst/dunstrc @@ -0,0 +1,94 @@ +[global] + monitor = 0 + follow = keyboard + geometry = "500x5-25+20" + indicate_hidden = yes + shrink = yes + transparency = 0 + notification_height = 0 + separator_height = 2 + padding = 8 + horizontal_padding = 8 + frame_width = 3 + frame_color = "#000000" + separator_color = frame + sort = yes + idle_threshold = 120 + + ### Text ### + font = Inconsolata 10 + line_height = 0 + markup = full + format = "%s\n%b" + alignment = center + show_age_threshold = -1 + word_wrap = yes + ellipsize = middle + ignore_newline = no + stack_duplicates = true + hide_duplicate_count = false + show_indicators = yes + + ### Icons ### + icon_position = off + #max_icon_size = 128 + #icon_path = /usr/share/icons/hicolor/16x16/status/:/usr/share/icons/hicolor/16x16/devices/ + + ### History ### + sticky_history = yes + history_length = 20 + + ### Misc/Advanced ### + + dmenu = /usr/bin/dmenu -p dunst: + browser = /usr/bin/firefox -new-tab + always_run_script = true + title = Dunst + class = Dunst + startup_notification = false + + ### Legacy + force_xinerama = false + +[experimental] + per_monitor_dpi = false + +[shortcuts] + close = ctrl+space + close_all = ctrl+shift+space + #history = ctrl+grave + context = ctrl+shift+period + +[urgency_low] + background = "#222222" + foreground = "#888888" + timeout = 5 + +[urgency_normal] + #background = "#285577" # default + #foreground = "#ffffff" # default + background = "#2e3440" + #foreground = "#81a1c1" + foreground = "#88c0d0" + timeout = 5 + +[urgency_critical] + background = "#900000" + foreground = "#ffffff" + frame_color = "#ff0000" + timeout = 0 + +[moon] + summary = "moon" + #urgency = normal + foreground = "#00ffff" + alignment = left + markup = no + timeout = 5 + +#[musicMode] +# summary = "testsummaryforshowingtime" # If empty, ALL notifications match! +# urgency = normal +# timeout = 0 + +# vim: ft=cfg diff --git a/stow/dunst/dot-config/dunst/dunstifyIDs b/stow/dunst/dot-config/dunst/dunstifyIDs deleted file mode 100644 index 2bccbf4..0000000 --- a/stow/dunst/dot-config/dunst/dunstifyIDs +++ /dev/null @@ -1,12 +0,0 @@ -vol 1001 -musicMode 1002 -brightness 1003 -cpu 1004 -memory 1005 -disk 1006 -batteryLow 1007 -moon 1008 -calcurse 1009 -bspwmDesktop 1010 -toggleKBLayouts 1011 -bspwmRunningStuff 1012 diff --git a/stow/dunst/dot-config/dunst/dunstrc b/stow/dunst/dot-config/dunst/dunstrc deleted file mode 100644 index 80004aa..0000000 --- a/stow/dunst/dot-config/dunst/dunstrc +++ /dev/null @@ -1,94 +0,0 @@ -[global] - monitor = 0 - follow = keyboard - geometry = "500x5-25+20" - indicate_hidden = yes - shrink = yes - transparency = 0 - notification_height = 0 - separator_height = 2 - padding = 8 - horizontal_padding = 8 - frame_width = 3 - frame_color = "#000000" - separator_color = frame - sort = yes - idle_threshold = 120 - - ### Text ### - font = Inconsolata 10 - line_height = 0 - markup = full - format = "%s\n%b" - alignment = center - show_age_threshold = -1 - word_wrap = yes - ellipsize = middle - ignore_newline = no - stack_duplicates = true - hide_duplicate_count = false - show_indicators = yes - - ### Icons ### - icon_position = off - #max_icon_size = 128 - #icon_path = /usr/share/icons/hicolor/16x16/status/:/usr/share/icons/hicolor/16x16/devices/ - - ### History ### - sticky_history = yes - history_length = 20 - - ### Misc/Advanced ### - - dmenu = /usr/bin/dmenu -p dunst: - browser = /usr/bin/firefox -new-tab - always_run_script = true - title = Dunst - class = Dunst - startup_notification = false - - ### Legacy - force_xinerama = false - -[experimental] - per_monitor_dpi = false - -[shortcuts] - close = ctrl+space - close_all = ctrl+shift+space - #history = ctrl+grave - context = ctrl+shift+period - -[urgency_low] - background = "#222222" - foreground = "#888888" - timeout = 5 - -[urgency_normal] - #background = "#285577" # default - #foreground = "#ffffff" # default - background = "#2e3440" - #foreground = "#81a1c1" - foreground = "#88c0d0" - timeout = 5 - -[urgency_critical] - background = "#900000" - foreground = "#ffffff" - frame_color = "#ff0000" - timeout = 0 - -[moon] - summary = "moon" - #urgency = normal - foreground = "#00ffff" - alignment = left - markup = no - timeout = 5 - -#[musicMode] -# summary = "testsummaryforshowingtime" # If empty, ALL notifications match! -# urgency = normal -# timeout = 0 - -# vim: ft=cfg diff --git a/stow/emoji/.config/emoji b/stow/emoji/.config/emoji new file mode 100644 index 0000000..2441237 --- /dev/null +++ b/stow/emoji/.config/emoji @@ -0,0 +1,4267 @@ +~ Obtained from https://emojipedia.org/emoji/ on Mon 15 Jun 2020 +๐Ÿ˜€ Grinning Face U+1F600 +๐Ÿ˜ƒ Grinning Face with Big Eyes U+1F603 +๐Ÿ˜„ Grinning Face with Smiling Eyes U+1F604 +๐Ÿ˜ Beaming Face with Smiling Eyes U+1F601 +๐Ÿ˜† Grinning Squinting Face U+1F606 +๐Ÿ˜… Grinning Face with Sweat U+1F605 +๐Ÿคฃ Rolling on the Floor Laughing U+1F923 +๐Ÿ˜‚ Face with Tears of Joy U+1F602 +๐Ÿ™‚ Slightly Smiling Face U+1F642 +๐Ÿ™ƒ Upside-Down Face U+1F643 +๐Ÿ˜‰ Winking Face U+1F609 +๐Ÿ˜Š Smiling Face with Smiling Eyes U+1F60A +๐Ÿ˜‡ Smiling Face with Halo U+1F607 +๐Ÿฅฐ Smiling Face with Hearts U+1F970 +๐Ÿ˜ Smiling Face with Heart-Eyes U+1F60D +๐Ÿคฉ Star-Struck U+1F929 +๐Ÿ˜˜ Face Blowing a Kiss U+1F618 +๐Ÿ˜— Kissing Face U+1F617 +โ˜บ๏ธ Smiling Face U+263A, U+FE0F +๐Ÿ˜š Kissing Face with Closed Eyes U+1F61A +๐Ÿ˜™ Kissing Face with Smiling Eyes U+1F619 +๐Ÿฅฒ Smiling Face with Tear U+1F972 +๐Ÿ˜‹ Face Savoring Food U+1F60B +๐Ÿ˜› Face with Tongue U+1F61B +๐Ÿ˜œ Winking Face with Tongue U+1F61C +๐Ÿคช Zany Face U+1F92A +๐Ÿ˜ Squinting Face with Tongue U+1F61D +๐Ÿค‘ Money-Mouth Face U+1F911 +๐Ÿค— Hugging Face U+1F917 +๐Ÿคญ Face with Hand Over Mouth U+1F92D +๐Ÿคซ Shushing Face U+1F92B +๐Ÿค” Thinking Face U+1F914 +๐Ÿค Zipper-Mouth Face U+1F910 +๐Ÿคจ Face with Raised Eyebrow U+1F928 +๐Ÿ˜ Neutral Face U+1F610 +๐Ÿ˜‘ Expressionless Face U+1F611 +๐Ÿ˜ถ Face Without Mouth U+1F636 +๐Ÿ˜ Smirking Face U+1F60F +๐Ÿ˜’ Unamused Face U+1F612 +๐Ÿ™„ Face with Rolling Eyes U+1F644 +๐Ÿ˜ฌ Grimacing Face U+1F62C +๐Ÿคฅ Lying Face U+1F925 +๐Ÿ˜Œ Relieved Face U+1F60C +๐Ÿ˜” Pensive Face U+1F614 +๐Ÿ˜ช Sleepy Face U+1F62A +๐Ÿคค Drooling Face U+1F924 +๐Ÿ˜ด Sleeping Face U+1F634 +๐Ÿ˜ท Face with Medical Mask U+1F637 +๐Ÿค’ Face with Thermometer U+1F912 +๐Ÿค• Face with Head-Bandage U+1F915 +๐Ÿคข Nauseated Face U+1F922 +๐Ÿคฎ Face Vomiting U+1F92E +๐Ÿคง Sneezing Face U+1F927 +๐Ÿฅต Hot Face U+1F975 +๐Ÿฅถ Cold Face U+1F976 +๐Ÿฅด Woozy Face U+1F974 +๐Ÿ˜ต Dizzy Face U+1F635 +๐Ÿคฏ Exploding Head U+1F92F +๐Ÿค  Cowboy Hat Face U+1F920 +๐Ÿฅณ Partying Face U+1F973 +๐Ÿฅธ Disguised Face U+1F978 +๐Ÿ˜Ž Smiling Face with Sunglasses U+1F60E +๐Ÿค“ Nerd Face U+1F913 +๐Ÿง Face with Monocle U+1F9D0 +๐Ÿ˜• Confused Face U+1F615 +๐Ÿ˜Ÿ Worried Face U+1F61F +๐Ÿ™ Slightly Frowning Face U+1F641 +โ˜น๏ธ Frowning Face U+2639, U+FE0F +๐Ÿ˜ฎ Face with Open Mouth U+1F62E +๐Ÿ˜ฏ Hushed Face U+1F62F +๐Ÿ˜ฒ Astonished Face U+1F632 +๐Ÿ˜ณ Flushed Face U+1F633 +๐Ÿฅบ Pleading Face U+1F97A +๐Ÿ˜ฆ Frowning Face with Open Mouth U+1F626 +๐Ÿ˜ง Anguished Face U+1F627 +๐Ÿ˜จ Fearful Face U+1F628 +๐Ÿ˜ฐ Anxious Face with Sweat U+1F630 +๐Ÿ˜ฅ Sad but Relieved Face U+1F625 +๐Ÿ˜ข Crying Face U+1F622 +๐Ÿ˜ญ Loudly Crying Face U+1F62D +๐Ÿ˜ฑ Face Screaming in Fear U+1F631 +๐Ÿ˜– Confounded Face U+1F616 +๐Ÿ˜ฃ Persevering Face U+1F623 +๐Ÿ˜ž Disappointed Face U+1F61E +๐Ÿ˜“ Downcast Face with Sweat U+1F613 +๐Ÿ˜ฉ Weary Face U+1F629 +๐Ÿ˜ซ Tired Face U+1F62B +๐Ÿฅฑ Yawning Face U+1F971 +๐Ÿ˜ค Face with Steam From Nose U+1F624 +๐Ÿ˜ก Pouting Face U+1F621 +๐Ÿ˜  Angry Face U+1F620 +๐Ÿคฌ Face with Symbols on Mouth U+1F92C +๐Ÿ˜ˆ Smiling Face with Horns U+1F608 +๐Ÿ‘ฟ Angry Face with Horns U+1F47F +๐Ÿ’€ Skull U+1F480 +โ˜ ๏ธ Skull and Crossbones U+2620, U+FE0F +๐Ÿ’ฉ Pile of Poo U+1F4A9 +๐Ÿคก Clown Face U+1F921 +๐Ÿ‘น Ogre U+1F479 +๐Ÿ‘บ Goblin U+1F47A +๐Ÿ‘ป Ghost U+1F47B +๐Ÿ‘ฝ Alien U+1F47D +๐Ÿ‘พ Alien Monster U+1F47E +๐Ÿค– Robot U+1F916 +๐Ÿ˜บ Grinning Cat U+1F63A +๐Ÿ˜ธ Grinning Cat with Smiling Eyes U+1F638 +๐Ÿ˜น Cat with Tears of Joy U+1F639 +๐Ÿ˜ป Smiling Cat with Heart-Eyes U+1F63B +๐Ÿ˜ผ Cat with Wry Smile U+1F63C +๐Ÿ˜ฝ Kissing Cat U+1F63D +๐Ÿ™€ Weary Cat U+1F640 +๐Ÿ˜ฟ Crying Cat U+1F63F +๐Ÿ˜พ Pouting Cat U+1F63E +๐Ÿ™ˆ See-No-Evil Monkey U+1F648 +๐Ÿ™‰ Hear-No-Evil Monkey U+1F649 +๐Ÿ™Š Speak-No-Evil Monkey U+1F64A +๐Ÿ’‹ Kiss Mark U+1F48B +๐Ÿ’Œ Love Letter U+1F48C +๐Ÿ’˜ Heart with Arrow U+1F498 +๐Ÿ’ Heart with Ribbon U+1F49D +๐Ÿ’– Sparkling Heart U+1F496 +๐Ÿ’— Growing Heart U+1F497 +๐Ÿ’“ Beating Heart U+1F493 +๐Ÿ’ž Revolving Hearts U+1F49E +๐Ÿ’• Two Hearts U+1F495 +๐Ÿ’Ÿ Heart Decoration U+1F49F +โฃ๏ธ Heart Exclamation U+2763, U+FE0F +๐Ÿ’” Broken Heart U+1F494 +โค๏ธ Red Heart U+2764, U+FE0F +๐Ÿงก Orange Heart U+1F9E1 +๐Ÿ’› Yellow Heart U+1F49B +๐Ÿ’š Green Heart U+1F49A +๐Ÿ’™ Blue Heart U+1F499 +๐Ÿ’œ Purple Heart U+1F49C +๐ŸคŽ Brown Heart U+1F90E +๐Ÿ–ค Black Heart U+1F5A4 +๐Ÿค White Heart U+1F90D +๐Ÿ’ฏ Hundred Points U+1F4AF +๐Ÿ’ข Anger Symbol U+1F4A2 +๐Ÿ’ฅ Collision U+1F4A5 +๐Ÿ’ซ Dizzy U+1F4AB +๐Ÿ’ฆ Sweat Droplets U+1F4A6 +๐Ÿ’จ Dashing Away U+1F4A8 +๐Ÿ•ณ๏ธ Hole U+1F573, U+FE0F +๐Ÿ’ฃ Bomb U+1F4A3 +๐Ÿ’ฌ Speech Balloon U+1F4AC +๐Ÿ‘๏ธโ€๐Ÿ—จ๏ธ Eye in Speech Bubble U+1F441, U+FE0F, U+200D, U+1F5E8, + U+FE0F +๐Ÿ—จ๏ธ Left Speech Bubble U+1F5E8, U+FE0F +๐Ÿ—ฏ๏ธ Right Anger Bubble U+1F5EF, U+FE0F +๐Ÿ’ญ Thought Balloon U+1F4AD +๐Ÿ’ค Zzz U+1F4A4 +๐Ÿ‘‹ Waving Hand U+1F44B +๐Ÿ‘‹๐Ÿป Waving Hand: Light Skin Tone U+1F44B, U+1F3FB +๐Ÿ‘‹๐Ÿผ Waving Hand: Medium-Light Skin Tone U+1F44B, U+1F3FC +๐Ÿ‘‹๐Ÿฝ Waving Hand: Medium Skin Tone U+1F44B, U+1F3FD +๐Ÿ‘‹๐Ÿพ Waving Hand: Medium-Dark Skin Tone U+1F44B, U+1F3FE +๐Ÿ‘‹๐Ÿฟ Waving Hand: Dark Skin Tone U+1F44B, U+1F3FF +๐Ÿคš Raised Back of Hand U+1F91A +๐Ÿคš๐Ÿป Raised Back of Hand: Light Skin Tone U+1F91A, U+1F3FB +๐Ÿคš๐Ÿผ Raised Back of Hand: Medium-Light Skin U+1F91A, U+1F3FC +Tone +๐Ÿคš๐Ÿฝ Raised Back of Hand: Medium Skin Tone U+1F91A, U+1F3FD +๐Ÿคš๐Ÿพ Raised Back of Hand: Medium-Dark Skin U+1F91A, U+1F3FE +Tone +๐Ÿคš๐Ÿฟ Raised Back of Hand: Dark Skin Tone U+1F91A, U+1F3FF +๐Ÿ–๏ธ Hand with Fingers Splayed U+1F590, U+FE0F +๐Ÿ–๐Ÿป Hand with Fingers Splayed: Light Skin U+1F590, U+1F3FB +Tone +๐Ÿ–๐Ÿผ Hand with Fingers Splayed: Medium-Light U+1F590, U+1F3FC +Skin Tone +๐Ÿ–๐Ÿฝ Hand with Fingers Splayed: Medium Skin U+1F590, U+1F3FD +Tone +๐Ÿ–๐Ÿพ Hand with Fingers Splayed: Medium-Dark U+1F590, U+1F3FE +Skin Tone +๐Ÿ–๐Ÿฟ Hand with Fingers Splayed: Dark Skin Tone U+1F590, U+1F3FF +โœ‹ Raised Hand U+270B +โœ‹๐Ÿป Raised Hand: Light Skin Tone U+270B, U+1F3FB +โœ‹๐Ÿผ Raised Hand: Medium-Light Skin Tone U+270B, U+1F3FC +โœ‹๐Ÿฝ Raised Hand: Medium Skin Tone U+270B, U+1F3FD +โœ‹๐Ÿพ Raised Hand: Medium-Dark Skin Tone U+270B, U+1F3FE +โœ‹๐Ÿฟ Raised Hand: Dark Skin Tone U+270B, U+1F3FF +๐Ÿ–– Vulcan Salute U+1F596 +๐Ÿ––๐Ÿป Vulcan Salute: Light Skin Tone U+1F596, U+1F3FB +๐Ÿ––๐Ÿผ Vulcan Salute: Medium-Light Skin Tone U+1F596, U+1F3FC +๐Ÿ––๐Ÿฝ Vulcan Salute: Medium Skin Tone U+1F596, U+1F3FD +๐Ÿ––๐Ÿพ Vulcan Salute: Medium-Dark Skin Tone U+1F596, U+1F3FE +๐Ÿ––๐Ÿฟ Vulcan Salute: Dark Skin Tone U+1F596, U+1F3FF +๐Ÿ‘Œ OK Hand U+1F44C +๐Ÿ‘Œ๐Ÿป OK Hand: Light Skin Tone U+1F44C, U+1F3FB +๐Ÿ‘Œ๐Ÿผ OK Hand: Medium-Light Skin Tone U+1F44C, U+1F3FC +๐Ÿ‘Œ๐Ÿฝ OK Hand: Medium Skin Tone U+1F44C, U+1F3FD +๐Ÿ‘Œ๐Ÿพ OK Hand: Medium-Dark Skin Tone U+1F44C, U+1F3FE +๐Ÿ‘Œ๐Ÿฟ OK Hand: Dark Skin Tone U+1F44C, U+1F3FF +๐ŸคŒ Pinched Fingers U+1F90C +๐ŸคŒ๐Ÿป Pinched Fingers: Light Skin Tone U+1F90C, U+1F3FB +๐ŸคŒ๐Ÿผ Pinched Fingers: Medium-Light Skin Tone U+1F90C, U+1F3FC +๐ŸคŒ๐Ÿฝ Pinched Fingers: Medium Skin Tone U+1F90C, U+1F3FD +๐ŸคŒ๐Ÿพ Pinched Fingers: Medium-Dark Skin Tone U+1F90C, U+1F3FE +๐ŸคŒ๐Ÿฟ Pinched Fingers: Dark Skin Tone U+1F90C, U+1F3FF +๐Ÿค Pinching Hand U+1F90F +๐Ÿค๐Ÿป Pinching Hand: Light Skin Tone U+1F90F, U+1F3FB +๐Ÿค๐Ÿผ Pinching Hand: Medium-Light Skin Tone U+1F90F, U+1F3FC +๐Ÿค๐Ÿฝ Pinching Hand: Medium Skin Tone U+1F90F, U+1F3FD +๐Ÿค๐Ÿพ Pinching Hand: Medium-Dark Skin Tone U+1F90F, U+1F3FE +๐Ÿค๐Ÿฟ Pinching Hand: Dark Skin Tone U+1F90F, U+1F3FF +โœŒ๏ธ Victory Hand U+270C, U+FE0F +โœŒ๐Ÿป Victory Hand: Light Skin Tone U+270C, U+1F3FB +โœŒ๐Ÿผ Victory Hand: Medium-Light Skin Tone U+270C, U+1F3FC +โœŒ๐Ÿฝ Victory Hand: Medium Skin Tone U+270C, U+1F3FD +โœŒ๐Ÿพ Victory Hand: Medium-Dark Skin Tone U+270C, U+1F3FE +โœŒ๐Ÿฟ Victory Hand: Dark Skin Tone U+270C, U+1F3FF +๐Ÿคž Crossed Fingers U+1F91E +๐Ÿคž๐Ÿป Crossed Fingers: Light Skin Tone U+1F91E, U+1F3FB +๐Ÿคž๐Ÿผ Crossed Fingers: Medium-Light Skin Tone U+1F91E, U+1F3FC +๐Ÿคž๐Ÿฝ Crossed Fingers: Medium Skin Tone U+1F91E, U+1F3FD +๐Ÿคž๐Ÿพ Crossed Fingers: Medium-Dark Skin Tone U+1F91E, U+1F3FE +๐Ÿคž๐Ÿฟ Crossed Fingers: Dark Skin Tone U+1F91E, U+1F3FF +๐ŸคŸ Love-You Gesture U+1F91F +๐ŸคŸ๐Ÿป Love-You Gesture: Light Skin Tone U+1F91F, U+1F3FB +๐ŸคŸ๐Ÿผ Love-You Gesture: Medium-Light Skin Tone U+1F91F, U+1F3FC +๐ŸคŸ๐Ÿฝ Love-You Gesture: Medium Skin Tone U+1F91F, U+1F3FD +๐ŸคŸ๐Ÿพ Love-You Gesture: Medium-Dark Skin Tone U+1F91F, U+1F3FE +๐ŸคŸ๐Ÿฟ Love-You Gesture: Dark Skin Tone U+1F91F, U+1F3FF +๐Ÿค˜ Sign of the Horns U+1F918 +๐Ÿค˜๐Ÿป Sign of the Horns: Light Skin Tone U+1F918, U+1F3FB +๐Ÿค˜๐Ÿผ Sign of the Horns: Medium-Light Skin Tone U+1F918, U+1F3FC +๐Ÿค˜๐Ÿฝ Sign of the Horns: Medium Skin Tone U+1F918, U+1F3FD +๐Ÿค˜๐Ÿพ Sign of the Horns: Medium-Dark Skin Tone U+1F918, U+1F3FE +๐Ÿค˜๐Ÿฟ Sign of the Horns: Dark Skin Tone U+1F918, U+1F3FF +๐Ÿค™ Call Me Hand U+1F919 +๐Ÿค™๐Ÿป Call Me Hand: Light Skin Tone U+1F919, U+1F3FB +๐Ÿค™๐Ÿผ Call Me Hand: Medium-Light Skin Tone U+1F919, U+1F3FC +๐Ÿค™๐Ÿฝ Call Me Hand: Medium Skin Tone U+1F919, U+1F3FD +๐Ÿค™๐Ÿพ Call Me Hand: Medium-Dark Skin Tone U+1F919, U+1F3FE +๐Ÿค™๐Ÿฟ Call Me Hand: Dark Skin Tone U+1F919, U+1F3FF +๐Ÿ‘ˆ Backhand Index Pointing Left U+1F448 +๐Ÿ‘ˆ๐Ÿป Backhand Index Pointing Left: Light Skin U+1F448, U+1F3FB +Tone +๐Ÿ‘ˆ๐Ÿผ Backhand Index Pointing Left: U+1F448, U+1F3FC +Medium-Light Skin Tone +๐Ÿ‘ˆ๐Ÿฝ Backhand Index Pointing Left: Medium Skin U+1F448, U+1F3FD +Tone +๐Ÿ‘ˆ๐Ÿพ Backhand Index Pointing Left: Medium-Dark U+1F448, U+1F3FE +Skin Tone +๐Ÿ‘ˆ๐Ÿฟ Backhand Index Pointing Left: Dark Skin U+1F448, U+1F3FF +Tone +๐Ÿ‘‰ Backhand Index Pointing Right U+1F449 +๐Ÿ‘‰๐Ÿป Backhand Index Pointing Right: Light Skin U+1F449, U+1F3FB +Tone +๐Ÿ‘‰๐Ÿผ Backhand Index Pointing Right: U+1F449, U+1F3FC +Medium-Light Skin Tone +๐Ÿ‘‰๐Ÿฝ Backhand Index Pointing Right: Medium U+1F449, U+1F3FD +Skin Tone +๐Ÿ‘‰๐Ÿพ Backhand Index Pointing Right: U+1F449, U+1F3FE +Medium-Dark Skin Tone +๐Ÿ‘‰๐Ÿฟ Backhand Index Pointing Right: Dark Skin U+1F449, U+1F3FF +Tone +๐Ÿ‘† Backhand Index Pointing Up U+1F446 +๐Ÿ‘†๐Ÿป Backhand Index Pointing Up: Light Skin U+1F446, U+1F3FB +Tone +๐Ÿ‘†๐Ÿผ Backhand Index Pointing Up: Medium-Light U+1F446, U+1F3FC +Skin Tone +๐Ÿ‘†๐Ÿฝ Backhand Index Pointing Up: Medium Skin U+1F446, U+1F3FD +Tone +๐Ÿ‘†๐Ÿพ Backhand Index Pointing Up: Medium-Dark U+1F446, U+1F3FE +Skin Tone +๐Ÿ‘†๐Ÿฟ Backhand Index Pointing Up: Dark Skin U+1F446, U+1F3FF +Tone +๐Ÿ–• Middle Finger U+1F595 +๐Ÿ–•๐Ÿป Middle Finger: Light Skin Tone U+1F595, U+1F3FB +๐Ÿ–•๐Ÿผ Middle Finger: Medium-Light Skin Tone U+1F595, U+1F3FC +๐Ÿ–•๐Ÿฝ Middle Finger: Medium Skin Tone U+1F595, U+1F3FD +๐Ÿ–•๐Ÿพ Middle Finger: Medium-Dark Skin Tone U+1F595, U+1F3FE +๐Ÿ–•๐Ÿฟ Middle Finger: Dark Skin Tone U+1F595, U+1F3FF +๐Ÿ‘‡ Backhand Index Pointing Down U+1F447 +๐Ÿ‘‡๐Ÿป Backhand Index Pointing Down: Light Skin U+1F447, U+1F3FB +Tone +๐Ÿ‘‡๐Ÿผ Backhand Index Pointing Down: U+1F447, U+1F3FC +Medium-Light Skin Tone +๐Ÿ‘‡๐Ÿฝ Backhand Index Pointing Down: Medium Skin U+1F447, U+1F3FD +Tone +๐Ÿ‘‡๐Ÿพ Backhand Index Pointing Down: Medium-Dark U+1F447, U+1F3FE +Skin Tone +๐Ÿ‘‡๐Ÿฟ Backhand Index Pointing Down: Dark Skin U+1F447, U+1F3FF +Tone +โ˜๏ธ Index Pointing Up U+261D, U+FE0F +โ˜๐Ÿป Index Pointing Up: Light Skin Tone U+261D, U+1F3FB +โ˜๐Ÿผ Index Pointing Up: Medium-Light Skin Tone U+261D, U+1F3FC +โ˜๐Ÿฝ Index Pointing Up: Medium Skin Tone U+261D, U+1F3FD +โ˜๐Ÿพ Index Pointing Up: Medium-Dark Skin Tone U+261D, U+1F3FE +โ˜๐Ÿฟ Index Pointing Up: Dark Skin Tone U+261D, U+1F3FF +๐Ÿ‘ Thumbs Up U+1F44D +๐Ÿ‘๐Ÿป Thumbs Up: Light Skin Tone U+1F44D, U+1F3FB +๐Ÿ‘๐Ÿผ Thumbs Up: Medium-Light Skin Tone U+1F44D, U+1F3FC +๐Ÿ‘๐Ÿฝ Thumbs Up: Medium Skin Tone U+1F44D, U+1F3FD +๐Ÿ‘๐Ÿพ Thumbs Up: Medium-Dark Skin Tone U+1F44D, U+1F3FE +๐Ÿ‘๐Ÿฟ Thumbs Up: Dark Skin Tone U+1F44D, U+1F3FF +๐Ÿ‘Ž Thumbs Down U+1F44E +๐Ÿ‘Ž๐Ÿป Thumbs Down: Light Skin Tone U+1F44E, U+1F3FB +๐Ÿ‘Ž๐Ÿผ Thumbs Down: Medium-Light Skin Tone U+1F44E, U+1F3FC +๐Ÿ‘Ž๐Ÿฝ Thumbs Down: Medium Skin Tone U+1F44E, U+1F3FD +๐Ÿ‘Ž๐Ÿพ Thumbs Down: Medium-Dark Skin Tone U+1F44E, U+1F3FE +๐Ÿ‘Ž๐Ÿฟ Thumbs Down: Dark Skin Tone U+1F44E, U+1F3FF +โœŠ Raised Fist U+270A +โœŠ๐Ÿป Raised Fist: Light Skin Tone U+270A, U+1F3FB +โœŠ๐Ÿผ Raised Fist: Medium-Light Skin Tone U+270A, U+1F3FC +โœŠ๐Ÿฝ Raised Fist: Medium Skin Tone U+270A, U+1F3FD +โœŠ๐Ÿพ Raised Fist: Medium-Dark Skin Tone U+270A, U+1F3FE +โœŠ๐Ÿฟ Raised Fist: Dark Skin Tone U+270A, U+1F3FF +๐Ÿ‘Š Oncoming Fist U+1F44A +๐Ÿ‘Š๐Ÿป Oncoming Fist: Light Skin Tone U+1F44A, U+1F3FB +๐Ÿ‘Š๐Ÿผ Oncoming Fist: Medium-Light Skin Tone U+1F44A, U+1F3FC +๐Ÿ‘Š๐Ÿฝ Oncoming Fist: Medium Skin Tone U+1F44A, U+1F3FD +๐Ÿ‘Š๐Ÿพ Oncoming Fist: Medium-Dark Skin Tone U+1F44A, U+1F3FE +๐Ÿ‘Š๐Ÿฟ Oncoming Fist: Dark Skin Tone U+1F44A, U+1F3FF +๐Ÿค› Left-Facing Fist U+1F91B +๐Ÿค›๐Ÿป Left-Facing Fist: Light Skin Tone U+1F91B, U+1F3FB +๐Ÿค›๐Ÿผ Left-Facing Fist: Medium-Light Skin Tone U+1F91B, U+1F3FC +๐Ÿค›๐Ÿฝ Left-Facing Fist: Medium Skin Tone U+1F91B, U+1F3FD +๐Ÿค›๐Ÿพ Left-Facing Fist: Medium-Dark Skin Tone U+1F91B, U+1F3FE +๐Ÿค›๐Ÿฟ Left-Facing Fist: Dark Skin Tone U+1F91B, U+1F3FF +๐Ÿคœ Right-Facing Fist U+1F91C +๐Ÿคœ๐Ÿป Right-Facing Fist: Light Skin Tone U+1F91C, U+1F3FB +๐Ÿคœ๐Ÿผ Right-Facing Fist: Medium-Light Skin Tone U+1F91C, U+1F3FC +๐Ÿคœ๐Ÿฝ Right-Facing Fist: Medium Skin Tone U+1F91C, U+1F3FD +๐Ÿคœ๐Ÿพ Right-Facing Fist: Medium-Dark Skin Tone U+1F91C, U+1F3FE +๐Ÿคœ๐Ÿฟ Right-Facing Fist: Dark Skin Tone U+1F91C, U+1F3FF +๐Ÿ‘ Clapping Hands U+1F44F +๐Ÿ‘๐Ÿป Clapping Hands: Light Skin Tone U+1F44F, U+1F3FB +๐Ÿ‘๐Ÿผ Clapping Hands: Medium-Light Skin Tone U+1F44F, U+1F3FC +๐Ÿ‘๐Ÿฝ Clapping Hands: Medium Skin Tone U+1F44F, U+1F3FD +๐Ÿ‘๐Ÿพ Clapping Hands: Medium-Dark Skin Tone U+1F44F, U+1F3FE +๐Ÿ‘๐Ÿฟ Clapping Hands: Dark Skin Tone U+1F44F, U+1F3FF +๐Ÿ™Œ Raising Hands U+1F64C +๐Ÿ™Œ๐Ÿป Raising Hands: Light Skin Tone U+1F64C, U+1F3FB +๐Ÿ™Œ๐Ÿผ Raising Hands: Medium-Light Skin Tone U+1F64C, U+1F3FC +๐Ÿ™Œ๐Ÿฝ Raising Hands: Medium Skin Tone U+1F64C, U+1F3FD +๐Ÿ™Œ๐Ÿพ Raising Hands: Medium-Dark Skin Tone U+1F64C, U+1F3FE +๐Ÿ™Œ๐Ÿฟ Raising Hands: Dark Skin Tone U+1F64C, U+1F3FF +๐Ÿ‘ Open Hands U+1F450 +๐Ÿ‘๐Ÿป Open Hands: Light Skin Tone U+1F450, U+1F3FB +๐Ÿ‘๐Ÿผ Open Hands: Medium-Light Skin Tone U+1F450, U+1F3FC +๐Ÿ‘๐Ÿฝ Open Hands: Medium Skin Tone U+1F450, U+1F3FD +๐Ÿ‘๐Ÿพ Open Hands: Medium-Dark Skin Tone U+1F450, U+1F3FE +๐Ÿ‘๐Ÿฟ Open Hands: Dark Skin Tone U+1F450, U+1F3FF +๐Ÿคฒ Palms Up Together U+1F932 +๐Ÿคฒ๐Ÿป Palms Up Together: Light Skin Tone U+1F932, U+1F3FB +๐Ÿคฒ๐Ÿผ Palms Up Together: Medium-Light Skin Tone U+1F932, U+1F3FC +๐Ÿคฒ๐Ÿฝ Palms Up Together: Medium Skin Tone U+1F932, U+1F3FD +๐Ÿคฒ๐Ÿพ Palms Up Together: Medium-Dark Skin Tone U+1F932, U+1F3FE +๐Ÿคฒ๐Ÿฟ Palms Up Together: Dark Skin Tone U+1F932, U+1F3FF +๐Ÿค Handshake U+1F91D +๐Ÿ™ Folded Hands U+1F64F +๐Ÿ™๐Ÿป Folded Hands: Light Skin Tone U+1F64F, U+1F3FB +๐Ÿ™๐Ÿผ Folded Hands: Medium-Light Skin Tone U+1F64F, U+1F3FC +๐Ÿ™๐Ÿฝ Folded Hands: Medium Skin Tone U+1F64F, U+1F3FD +๐Ÿ™๐Ÿพ Folded Hands: Medium-Dark Skin Tone U+1F64F, U+1F3FE +๐Ÿ™๐Ÿฟ Folded Hands: Dark Skin Tone U+1F64F, U+1F3FF +โœ๏ธ Writing Hand U+270D, U+FE0F +โœ๐Ÿป Writing Hand: Light Skin Tone U+270D, U+1F3FB +โœ๐Ÿผ Writing Hand: Medium-Light Skin Tone U+270D, U+1F3FC +โœ๐Ÿฝ Writing Hand: Medium Skin Tone U+270D, U+1F3FD +โœ๐Ÿพ Writing Hand: Medium-Dark Skin Tone U+270D, U+1F3FE +โœ๐Ÿฟ Writing Hand: Dark Skin Tone U+270D, U+1F3FF +๐Ÿ’… Nail Polish U+1F485 +๐Ÿ’…๐Ÿป Nail Polish: Light Skin Tone U+1F485, U+1F3FB +๐Ÿ’…๐Ÿผ Nail Polish: Medium-Light Skin Tone U+1F485, U+1F3FC +๐Ÿ’…๐Ÿฝ Nail Polish: Medium Skin Tone U+1F485, U+1F3FD +๐Ÿ’…๐Ÿพ Nail Polish: Medium-Dark Skin Tone U+1F485, U+1F3FE +๐Ÿ’…๐Ÿฟ Nail Polish: Dark Skin Tone U+1F485, U+1F3FF +๐Ÿคณ Selfie U+1F933 +๐Ÿคณ๐Ÿป Selfie: Light Skin Tone U+1F933, U+1F3FB +๐Ÿคณ๐Ÿผ Selfie: Medium-Light Skin Tone U+1F933, U+1F3FC +๐Ÿคณ๐Ÿฝ Selfie: Medium Skin Tone U+1F933, U+1F3FD +๐Ÿคณ๐Ÿพ Selfie: Medium-Dark Skin Tone U+1F933, U+1F3FE +๐Ÿคณ๐Ÿฟ Selfie: Dark Skin Tone U+1F933, U+1F3FF +๐Ÿ’ช Flexed Biceps U+1F4AA +๐Ÿ’ช๐Ÿป Flexed Biceps: Light Skin Tone U+1F4AA, U+1F3FB +๐Ÿ’ช๐Ÿผ Flexed Biceps: Medium-Light Skin Tone U+1F4AA, U+1F3FC +๐Ÿ’ช๐Ÿฝ Flexed Biceps: Medium Skin Tone U+1F4AA, U+1F3FD +๐Ÿ’ช๐Ÿพ Flexed Biceps: Medium-Dark Skin Tone U+1F4AA, U+1F3FE +๐Ÿ’ช๐Ÿฟ Flexed Biceps: Dark Skin Tone U+1F4AA, U+1F3FF +๐Ÿฆพ Mechanical Arm U+1F9BE +๐Ÿฆฟ Mechanical Leg U+1F9BF +๐Ÿฆต Leg U+1F9B5 +๐Ÿฆต๐Ÿป Leg: Light Skin Tone U+1F9B5, U+1F3FB +๐Ÿฆต๐Ÿผ Leg: Medium-Light Skin Tone U+1F9B5, U+1F3FC +๐Ÿฆต๐Ÿฝ Leg: Medium Skin Tone U+1F9B5, U+1F3FD +๐Ÿฆต๐Ÿพ Leg: Medium-Dark Skin Tone U+1F9B5, U+1F3FE +๐Ÿฆต๐Ÿฟ Leg: Dark Skin Tone U+1F9B5, U+1F3FF +๐Ÿฆถ Foot U+1F9B6 +๐Ÿฆถ๐Ÿป Foot: Light Skin Tone U+1F9B6, U+1F3FB +๐Ÿฆถ๐Ÿผ Foot: Medium-Light Skin Tone U+1F9B6, U+1F3FC +๐Ÿฆถ๐Ÿฝ Foot: Medium Skin Tone U+1F9B6, U+1F3FD +๐Ÿฆถ๐Ÿพ Foot: Medium-Dark Skin Tone U+1F9B6, U+1F3FE +๐Ÿฆถ๐Ÿฟ Foot: Dark Skin Tone U+1F9B6, U+1F3FF +๐Ÿ‘‚ Ear U+1F442 +๐Ÿ‘‚๐Ÿป Ear: Light Skin Tone U+1F442, U+1F3FB +๐Ÿ‘‚๐Ÿผ Ear: Medium-Light Skin Tone U+1F442, U+1F3FC +๐Ÿ‘‚๐Ÿฝ Ear: Medium Skin Tone U+1F442, U+1F3FD +๐Ÿ‘‚๐Ÿพ Ear: Medium-Dark Skin Tone U+1F442, U+1F3FE +๐Ÿ‘‚๐Ÿฟ Ear: Dark Skin Tone U+1F442, U+1F3FF +๐Ÿฆป Ear with Hearing Aid U+1F9BB +๐Ÿฆป๐Ÿป Ear with Hearing Aid: Light Skin Tone U+1F9BB, U+1F3FB +๐Ÿฆป๐Ÿผ Ear with Hearing Aid: Medium-Light Skin U+1F9BB, U+1F3FC +Tone +๐Ÿฆป๐Ÿฝ Ear with Hearing Aid: Medium Skin Tone U+1F9BB, U+1F3FD +๐Ÿฆป๐Ÿพ Ear with Hearing Aid: Medium-Dark Skin U+1F9BB, U+1F3FE +Tone +๐Ÿฆป๐Ÿฟ Ear with Hearing Aid: Dark Skin Tone U+1F9BB, U+1F3FF +๐Ÿ‘ƒ Nose U+1F443 +๐Ÿ‘ƒ๐Ÿป Nose: Light Skin Tone U+1F443, U+1F3FB +๐Ÿ‘ƒ๐Ÿผ Nose: Medium-Light Skin Tone U+1F443, U+1F3FC +๐Ÿ‘ƒ๐Ÿฝ Nose: Medium Skin Tone U+1F443, U+1F3FD +๐Ÿ‘ƒ๐Ÿพ Nose: Medium-Dark Skin Tone U+1F443, U+1F3FE +๐Ÿ‘ƒ๐Ÿฟ Nose: Dark Skin Tone U+1F443, U+1F3FF +๐Ÿง  Brain U+1F9E0 +๐Ÿซ€ Anatomical Heart U+1FAC0 +๐Ÿซ Lungs U+1FAC1 +๐Ÿฆท Tooth U+1F9B7 +๐Ÿฆด Bone U+1F9B4 +๐Ÿ‘€ Eyes U+1F440 +๐Ÿ‘๏ธ Eye U+1F441, U+FE0F +๐Ÿ‘… Tongue U+1F445 +๐Ÿ‘„ Mouth U+1F444 +๐Ÿ‘ถ Baby U+1F476 +๐Ÿ‘ถ๐Ÿป Baby: Light Skin Tone U+1F476, U+1F3FB +๐Ÿ‘ถ๐Ÿผ Baby: Medium-Light Skin Tone U+1F476, U+1F3FC +๐Ÿ‘ถ๐Ÿฝ Baby: Medium Skin Tone U+1F476, U+1F3FD +๐Ÿ‘ถ๐Ÿพ Baby: Medium-Dark Skin Tone U+1F476, U+1F3FE +๐Ÿ‘ถ๐Ÿฟ Baby: Dark Skin Tone U+1F476, U+1F3FF +๐Ÿง’ Child U+1F9D2 +๐Ÿง’๐Ÿป Child: Light Skin Tone U+1F9D2, U+1F3FB +๐Ÿง’๐Ÿผ Child: Medium-Light Skin Tone U+1F9D2, U+1F3FC +๐Ÿง’๐Ÿฝ Child: Medium Skin Tone U+1F9D2, U+1F3FD +๐Ÿง’๐Ÿพ Child: Medium-Dark Skin Tone U+1F9D2, U+1F3FE +๐Ÿง’๐Ÿฟ Child: Dark Skin Tone U+1F9D2, U+1F3FF +๐Ÿ‘ฆ Boy U+1F466 +๐Ÿ‘ฆ๐Ÿป Boy: Light Skin Tone U+1F466, U+1F3FB +๐Ÿ‘ฆ๐Ÿผ Boy: Medium-Light Skin Tone U+1F466, U+1F3FC +๐Ÿ‘ฆ๐Ÿฝ Boy: Medium Skin Tone U+1F466, U+1F3FD +๐Ÿ‘ฆ๐Ÿพ Boy: Medium-Dark Skin Tone U+1F466, U+1F3FE +๐Ÿ‘ฆ๐Ÿฟ Boy: Dark Skin Tone U+1F466, U+1F3FF +๐Ÿ‘ง Girl U+1F467 +๐Ÿ‘ง๐Ÿป Girl: Light Skin Tone U+1F467, U+1F3FB +๐Ÿ‘ง๐Ÿผ Girl: Medium-Light Skin Tone U+1F467, U+1F3FC +๐Ÿ‘ง๐Ÿฝ Girl: Medium Skin Tone U+1F467, U+1F3FD +๐Ÿ‘ง๐Ÿพ Girl: Medium-Dark Skin Tone U+1F467, U+1F3FE +๐Ÿ‘ง๐Ÿฟ Girl: Dark Skin Tone U+1F467, U+1F3FF +๐Ÿง‘ Person U+1F9D1 +๐Ÿง‘๐Ÿป Person: Light Skin Tone U+1F9D1, U+1F3FB +๐Ÿง‘๐Ÿผ Person: Medium-Light Skin Tone U+1F9D1, U+1F3FC +๐Ÿง‘๐Ÿฝ Person: Medium Skin Tone U+1F9D1, U+1F3FD +๐Ÿง‘๐Ÿพ Person: Medium-Dark Skin Tone U+1F9D1, U+1F3FE +๐Ÿง‘๐Ÿฟ Person: Dark Skin Tone U+1F9D1, U+1F3FF +๐Ÿ‘ฑ Person: Blond Hair U+1F471 +๐Ÿ‘ฑ๐Ÿป Person: Light Skin Tone, Blond Hair U+1F471, U+1F3FB +๐Ÿ‘ฑ๐Ÿผ Person: Medium-Light Skin Tone, Blond U+1F471, U+1F3FC +Hair +๐Ÿ‘ฑ๐Ÿฝ Person: Medium Skin Tone, Blond Hair U+1F471, U+1F3FD +๐Ÿ‘ฑ๐Ÿพ Person: Medium-Dark Skin Tone, Blond Hair U+1F471, U+1F3FE +๐Ÿ‘ฑ๐Ÿฟ Person: Dark Skin Tone, Blond Hair U+1F471, U+1F3FF +๐Ÿ‘จ Man U+1F468 +๐Ÿ‘จ๐Ÿป Man: Light Skin Tone U+1F468, U+1F3FB +๐Ÿ‘จ๐Ÿผ Man: Medium-Light Skin Tone U+1F468, U+1F3FC +๐Ÿ‘จ๐Ÿฝ Man: Medium Skin Tone U+1F468, U+1F3FD +๐Ÿ‘จ๐Ÿพ Man: Medium-Dark Skin Tone U+1F468, U+1F3FE +๐Ÿ‘จ๐Ÿฟ Man: Dark Skin Tone U+1F468, U+1F3FF +๐Ÿง” Man: Beard U+1F9D4 +๐Ÿง”๐Ÿป Man: Light Skin Tone, Beard U+1F9D4, U+1F3FB +๐Ÿง”๐Ÿผ Man: Medium-Light Skin Tone, Beard U+1F9D4, U+1F3FC +๐Ÿง”๐Ÿฝ Man: Medium Skin Tone, Beard U+1F9D4, U+1F3FD +๐Ÿง”๐Ÿพ Man: Medium-Dark Skin Tone, Beard U+1F9D4, U+1F3FE +๐Ÿง”๐Ÿฟ Man: Dark Skin Tone, Beard U+1F9D4, U+1F3FF +๐Ÿ‘จโ€๐Ÿฆฐ Man: Red Hair U+1F468, U+200D, U+1F9B0 +๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฐ Man: Light Skin Tone, Red Hair U+1F468, U+1F3FB, U+200D, U+1F9B0 +๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฐ Man: Medium-Light Skin Tone, Red Hair U+1F468, U+1F3FC, U+200D, U+1F9B0 +๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฐ Man: Medium Skin Tone, Red Hair U+1F468, U+1F3FD, U+200D, U+1F9B0 +๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฐ Man: Medium-Dark Skin Tone, Red Hair U+1F468, U+1F3FE, U+200D, U+1F9B0 +๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฐ Man: Dark Skin Tone, Red Hair U+1F468, U+1F3FF, U+200D, U+1F9B0 +๐Ÿ‘จโ€๐Ÿฆฑ Man: Curly Hair U+1F468, U+200D, U+1F9B1 +๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฑ Man: Light Skin Tone, Curly Hair U+1F468, U+1F3FB, U+200D, U+1F9B1 +๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฑ Man: Medium-Light Skin Tone, Curly Hair U+1F468, U+1F3FC, U+200D, U+1F9B1 +๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฑ Man: Medium Skin Tone, Curly Hair U+1F468, U+1F3FD, U+200D, U+1F9B1 +๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฑ Man: Medium-Dark Skin Tone, Curly Hair U+1F468, U+1F3FE, U+200D, U+1F9B1 +๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฑ Man: Dark Skin Tone, Curly Hair U+1F468, U+1F3FF, U+200D, U+1F9B1 +๐Ÿ‘จโ€๐Ÿฆณ Man: White Hair U+1F468, U+200D, U+1F9B3 +๐Ÿ‘จ๐Ÿปโ€๐Ÿฆณ Man: Light Skin Tone, White Hair U+1F468, U+1F3FB, U+200D, U+1F9B3 +๐Ÿ‘จ๐Ÿผโ€๐Ÿฆณ Man: Medium-Light Skin Tone, White Hair U+1F468, U+1F3FC, U+200D, U+1F9B3 +๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆณ Man: Medium Skin Tone, White Hair U+1F468, U+1F3FD, U+200D, U+1F9B3 +๐Ÿ‘จ๐Ÿพโ€๐Ÿฆณ Man: Medium-Dark Skin Tone, White Hair U+1F468, U+1F3FE, U+200D, U+1F9B3 +๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆณ Man: Dark Skin Tone, White Hair U+1F468, U+1F3FF, U+200D, U+1F9B3 +๐Ÿ‘จโ€๐Ÿฆฒ Man: Bald U+1F468, U+200D, U+1F9B2 +๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฒ Man: Light Skin Tone, Bald U+1F468, U+1F3FB, U+200D, U+1F9B2 +๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฒ Man: Medium-Light Skin Tone, Bald U+1F468, U+1F3FC, U+200D, U+1F9B2 +๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฒ Man: Medium Skin Tone, Bald U+1F468, U+1F3FD, U+200D, U+1F9B2 +๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฒ Man: Medium-Dark Skin Tone, Bald U+1F468, U+1F3FE, U+200D, U+1F9B2 +๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฒ Man: Dark Skin Tone, Bald U+1F468, U+1F3FF, U+200D, U+1F9B2 +๐Ÿ‘ฉ Woman U+1F469 +๐Ÿ‘ฉ๐Ÿป Woman: Light Skin Tone U+1F469, U+1F3FB +๐Ÿ‘ฉ๐Ÿผ Woman: Medium-Light Skin Tone U+1F469, U+1F3FC +๐Ÿ‘ฉ๐Ÿฝ Woman: Medium Skin Tone U+1F469, U+1F3FD +๐Ÿ‘ฉ๐Ÿพ Woman: Medium-Dark Skin Tone U+1F469, U+1F3FE +๐Ÿ‘ฉ๐Ÿฟ Woman: Dark Skin Tone U+1F469, U+1F3FF +๐Ÿ‘ฉโ€๐Ÿฆฐ Woman: Red Hair U+1F469, U+200D, U+1F9B0 +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฐ Woman: Light Skin Tone, Red Hair U+1F469, U+1F3FB, U+200D, U+1F9B0 +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฐ Woman: Medium-Light Skin Tone, Red Hair U+1F469, U+1F3FC, U+200D, U+1F9B0 +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฐ Woman: Medium Skin Tone, Red Hair U+1F469, U+1F3FD, U+200D, U+1F9B0 +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฐ Woman: Medium-Dark Skin Tone, Red Hair U+1F469, U+1F3FE, U+200D, U+1F9B0 +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฐ Woman: Dark Skin Tone, Red Hair U+1F469, U+1F3FF, U+200D, U+1F9B0 +๐Ÿง‘โ€๐Ÿฆฐ Person: Red Hair U+1F9D1, U+200D, U+1F9B0 +๐Ÿง‘๐Ÿปโ€๐Ÿฆฐ Person: Light Skin Tone, Red Hair U+1F9D1, U+1F3FB, U+200D, U+1F9B0 +๐Ÿง‘๐Ÿผโ€๐Ÿฆฐ Person: Medium-Light Skin Tone, Red U+1F9D1, U+1F3FC, U+200D, U+1F9B0 +Hair +๐Ÿง‘๐Ÿฝโ€๐Ÿฆฐ Person: Medium Skin Tone, Red Hair U+1F9D1, U+1F3FD, U+200D, U+1F9B0 +๐Ÿง‘๐Ÿพโ€๐Ÿฆฐ Person: Medium-Dark Skin Tone, Red Hair U+1F9D1, U+1F3FE, U+200D, U+1F9B0 +๐Ÿง‘๐Ÿฟโ€๐Ÿฆฐ Person: Dark Skin Tone, Red Hair U+1F9D1, U+1F3FF, U+200D, U+1F9B0 +๐Ÿ‘ฉโ€๐Ÿฆฑ Woman: Curly Hair U+1F469, U+200D, U+1F9B1 +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฑ Woman: Light Skin Tone, Curly Hair U+1F469, U+1F3FB, U+200D, U+1F9B1 +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฑ Woman: Medium-Light Skin Tone, Curly U+1F469, U+1F3FC, U+200D, U+1F9B1 +Hair +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฑ Woman: Medium Skin Tone, Curly Hair U+1F469, U+1F3FD, U+200D, U+1F9B1 +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฑ Woman: Medium-Dark Skin Tone, Curly U+1F469, U+1F3FE, U+200D, U+1F9B1 +Hair +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฑ Woman: Dark Skin Tone, Curly Hair U+1F469, U+1F3FF, U+200D, U+1F9B1 +๐Ÿง‘โ€๐Ÿฆฑ Person: Curly Hair U+1F9D1, U+200D, U+1F9B1 +๐Ÿง‘๐Ÿปโ€๐Ÿฆฑ Person: Light Skin Tone, Curly Hair U+1F9D1, U+1F3FB, U+200D, U+1F9B1 +๐Ÿง‘๐Ÿผโ€๐Ÿฆฑ Person: Medium-Light Skin Tone, Curly U+1F9D1, U+1F3FC, U+200D, U+1F9B1 +Hair +๐Ÿง‘๐Ÿฝโ€๐Ÿฆฑ Person: Medium Skin Tone, Curly Hair U+1F9D1, U+1F3FD, U+200D, U+1F9B1 +๐Ÿง‘๐Ÿพโ€๐Ÿฆฑ Person: Medium-Dark Skin Tone, Curly U+1F9D1, U+1F3FE, U+200D, U+1F9B1 +Hair +๐Ÿง‘๐Ÿฟโ€๐Ÿฆฑ Person: Dark Skin Tone, Curly Hair U+1F9D1, U+1F3FF, U+200D, U+1F9B1 +๐Ÿ‘ฉโ€๐Ÿฆณ Woman: White Hair U+1F469, U+200D, U+1F9B3 +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆณ Woman: Light Skin Tone, White Hair U+1F469, U+1F3FB, U+200D, U+1F9B3 +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆณ Woman: Medium-Light Skin Tone, White U+1F469, U+1F3FC, U+200D, U+1F9B3 +Hair +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆณ Woman: Medium Skin Tone, White Hair U+1F469, U+1F3FD, U+200D, U+1F9B3 +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆณ Woman: Medium-Dark Skin Tone, White U+1F469, U+1F3FE, U+200D, U+1F9B3 +Hair +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆณ Woman: Dark Skin Tone, White Hair U+1F469, U+1F3FF, U+200D, U+1F9B3 +๐Ÿง‘โ€๐Ÿฆณ Person: White Hair U+1F9D1, U+200D, U+1F9B3 +๐Ÿง‘๐Ÿปโ€๐Ÿฆณ Person: Light Skin Tone, White Hair U+1F9D1, U+1F3FB, U+200D, U+1F9B3 +๐Ÿง‘๐Ÿผโ€๐Ÿฆณ Person: Medium-Light Skin Tone, White U+1F9D1, U+1F3FC, U+200D, U+1F9B3 +Hair +๐Ÿง‘๐Ÿฝโ€๐Ÿฆณ Person: Medium Skin Tone, White Hair U+1F9D1, U+1F3FD, U+200D, U+1F9B3 +๐Ÿง‘๐Ÿพโ€๐Ÿฆณ Person: Medium-Dark Skin Tone, White U+1F9D1, U+1F3FE, U+200D, U+1F9B3 +Hair +๐Ÿง‘๐Ÿฟโ€๐Ÿฆณ Person: Dark Skin Tone, White Hair U+1F9D1, U+1F3FF, U+200D, U+1F9B3 +๐Ÿ‘ฉโ€๐Ÿฆฒ Woman: Bald U+1F469, U+200D, U+1F9B2 +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฒ Woman: Light Skin Tone, Bald U+1F469, U+1F3FB, U+200D, U+1F9B2 +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฒ Woman: Medium-Light Skin Tone, Bald U+1F469, U+1F3FC, U+200D, U+1F9B2 +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฒ Woman: Medium Skin Tone, Bald U+1F469, U+1F3FD, U+200D, U+1F9B2 +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฒ Woman: Medium-Dark Skin Tone, Bald U+1F469, U+1F3FE, U+200D, U+1F9B2 +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฒ Woman: Dark Skin Tone, Bald U+1F469, U+1F3FF, U+200D, U+1F9B2 +๐Ÿง‘โ€๐Ÿฆฒ Person: Bald U+1F9D1, U+200D, U+1F9B2 +๐Ÿง‘๐Ÿปโ€๐Ÿฆฒ Person: Light Skin Tone, Bald U+1F9D1, U+1F3FB, U+200D, U+1F9B2 +๐Ÿง‘๐Ÿผโ€๐Ÿฆฒ Person: Medium-Light Skin Tone, Bald U+1F9D1, U+1F3FC, U+200D, U+1F9B2 +๐Ÿง‘๐Ÿฝโ€๐Ÿฆฒ Person: Medium Skin Tone, Bald U+1F9D1, U+1F3FD, U+200D, U+1F9B2 +๐Ÿง‘๐Ÿพโ€๐Ÿฆฒ Person: Medium-Dark Skin Tone, Bald U+1F9D1, U+1F3FE, U+200D, U+1F9B2 +๐Ÿง‘๐Ÿฟโ€๐Ÿฆฒ Person: Dark Skin Tone, Bald U+1F9D1, U+1F3FF, U+200D, U+1F9B2 +๐Ÿ‘ฑโ€โ™€๏ธ Woman: Blond Hair U+1F471, U+200D, U+2640, U+FE0F +๐Ÿ‘ฑ๐Ÿปโ€โ™€๏ธ Woman: Light Skin Tone, Blond Hair U+1F471, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฑ๐Ÿผโ€โ™€๏ธ Woman: Medium-Light Skin Tone, Blond U+1F471, U+1F3FC, U+200D, U+2640, +Hair U+FE0F +๐Ÿ‘ฑ๐Ÿฝโ€โ™€๏ธ Woman: Medium Skin Tone, Blond Hair U+1F471, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฑ๐Ÿพโ€โ™€๏ธ Woman: Medium-Dark Skin Tone, Blond U+1F471, U+1F3FE, U+200D, U+2640, +Hair U+FE0F +๐Ÿ‘ฑ๐Ÿฟโ€โ™€๏ธ Woman: Dark Skin Tone, Blond Hair U+1F471, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฑโ€โ™‚๏ธ Man: Blond Hair U+1F471, U+200D, U+2642, U+FE0F +๐Ÿ‘ฑ๐Ÿปโ€โ™‚๏ธ Man: Light Skin Tone, Blond Hair U+1F471, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฑ๐Ÿผโ€โ™‚๏ธ Man: Medium-Light Skin Tone, Blond U+1F471, U+1F3FC, U+200D, U+2642, +Hair U+FE0F +๐Ÿ‘ฑ๐Ÿฝโ€โ™‚๏ธ Man: Medium Skin Tone, Blond Hair U+1F471, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฑ๐Ÿพโ€โ™‚๏ธ Man: Medium-Dark Skin Tone, Blond Hair U+1F471, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฑ๐Ÿฟโ€โ™‚๏ธ Man: Dark Skin Tone, Blond Hair U+1F471, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿง“ Older Person U+1F9D3 +๐Ÿง“๐Ÿป Older Person: Light Skin Tone U+1F9D3, U+1F3FB +๐Ÿง“๐Ÿผ Older Person: Medium-Light Skin Tone U+1F9D3, U+1F3FC +๐Ÿง“๐Ÿฝ Older Person: Medium Skin Tone U+1F9D3, U+1F3FD +๐Ÿง“๐Ÿพ Older Person: Medium-Dark Skin Tone U+1F9D3, U+1F3FE +๐Ÿง“๐Ÿฟ Older Person: Dark Skin Tone U+1F9D3, U+1F3FF +๐Ÿ‘ด Old Man U+1F474 +๐Ÿ‘ด๐Ÿป Old Man: Light Skin Tone U+1F474, U+1F3FB +๐Ÿ‘ด๐Ÿผ Old Man: Medium-Light Skin Tone U+1F474, U+1F3FC +๐Ÿ‘ด๐Ÿฝ Old Man: Medium Skin Tone U+1F474, U+1F3FD +๐Ÿ‘ด๐Ÿพ Old Man: Medium-Dark Skin Tone U+1F474, U+1F3FE +๐Ÿ‘ด๐Ÿฟ Old Man: Dark Skin Tone U+1F474, U+1F3FF +๐Ÿ‘ต Old Woman U+1F475 +๐Ÿ‘ต๐Ÿป Old Woman: Light Skin Tone U+1F475, U+1F3FB +๐Ÿ‘ต๐Ÿผ Old Woman: Medium-Light Skin Tone U+1F475, U+1F3FC +๐Ÿ‘ต๐Ÿฝ Old Woman: Medium Skin Tone U+1F475, U+1F3FD +๐Ÿ‘ต๐Ÿพ Old Woman: Medium-Dark Skin Tone U+1F475, U+1F3FE +๐Ÿ‘ต๐Ÿฟ Old Woman: Dark Skin Tone U+1F475, U+1F3FF +๐Ÿ™ Person Frowning U+1F64D +๐Ÿ™๐Ÿป Person Frowning: Light Skin Tone U+1F64D, U+1F3FB +๐Ÿ™๐Ÿผ Person Frowning: Medium-Light Skin Tone U+1F64D, U+1F3FC +๐Ÿ™๐Ÿฝ Person Frowning: Medium Skin Tone U+1F64D, U+1F3FD +๐Ÿ™๐Ÿพ Person Frowning: Medium-Dark Skin Tone U+1F64D, U+1F3FE +๐Ÿ™๐Ÿฟ Person Frowning: Dark Skin Tone U+1F64D, U+1F3FF +๐Ÿ™โ€โ™‚๏ธ Man Frowning U+1F64D, U+200D, U+2642, U+FE0F +๐Ÿ™๐Ÿปโ€โ™‚๏ธ Man Frowning: Light Skin Tone U+1F64D, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ™๐Ÿผโ€โ™‚๏ธ Man Frowning: Medium-Light Skin Tone U+1F64D, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿ™๐Ÿฝโ€โ™‚๏ธ Man Frowning: Medium Skin Tone U+1F64D, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ™๐Ÿพโ€โ™‚๏ธ Man Frowning: Medium-Dark Skin Tone U+1F64D, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿ™๐Ÿฟโ€โ™‚๏ธ Man Frowning: Dark Skin Tone U+1F64D, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ™โ€โ™€๏ธ Woman Frowning U+1F64D, U+200D, U+2640, U+FE0F +๐Ÿ™๐Ÿปโ€โ™€๏ธ Woman Frowning: Light Skin Tone U+1F64D, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ™๐Ÿผโ€โ™€๏ธ Woman Frowning: Medium-Light Skin Tone U+1F64D, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿ™๐Ÿฝโ€โ™€๏ธ Woman Frowning: Medium Skin Tone U+1F64D, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ™๐Ÿพโ€โ™€๏ธ Woman Frowning: Medium-Dark Skin Tone U+1F64D, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿ™๐Ÿฟโ€โ™€๏ธ Woman Frowning: Dark Skin Tone U+1F64D, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ™Ž Person Pouting U+1F64E +๐Ÿ™Ž๐Ÿป Person Pouting: Light Skin Tone U+1F64E, U+1F3FB +๐Ÿ™Ž๐Ÿผ Person Pouting: Medium-Light Skin Tone U+1F64E, U+1F3FC +๐Ÿ™Ž๐Ÿฝ Person Pouting: Medium Skin Tone U+1F64E, U+1F3FD +๐Ÿ™Ž๐Ÿพ Person Pouting: Medium-Dark Skin Tone U+1F64E, U+1F3FE +๐Ÿ™Ž๐Ÿฟ Person Pouting: Dark Skin Tone U+1F64E, U+1F3FF +๐Ÿ™Žโ€โ™‚๏ธ Man Pouting U+1F64E, U+200D, U+2642, U+FE0F +๐Ÿ™Ž๐Ÿปโ€โ™‚๏ธ Man Pouting: Light Skin Tone U+1F64E, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ™Ž๐Ÿผโ€โ™‚๏ธ Man Pouting: Medium-Light Skin Tone U+1F64E, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿ™Ž๐Ÿฝโ€โ™‚๏ธ Man Pouting: Medium Skin Tone U+1F64E, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ™Ž๐Ÿพโ€โ™‚๏ธ Man Pouting: Medium-Dark Skin Tone U+1F64E, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿ™Ž๐Ÿฟโ€โ™‚๏ธ Man Pouting: Dark Skin Tone U+1F64E, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ™Žโ€โ™€๏ธ Woman Pouting U+1F64E, U+200D, U+2640, U+FE0F +๐Ÿ™Ž๐Ÿปโ€โ™€๏ธ Woman Pouting: Light Skin Tone U+1F64E, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ™Ž๐Ÿผโ€โ™€๏ธ Woman Pouting: Medium-Light Skin Tone U+1F64E, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿ™Ž๐Ÿฝโ€โ™€๏ธ Woman Pouting: Medium Skin Tone U+1F64E, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ™Ž๐Ÿพโ€โ™€๏ธ Woman Pouting: Medium-Dark Skin Tone U+1F64E, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿ™Ž๐Ÿฟโ€โ™€๏ธ Woman Pouting: Dark Skin Tone U+1F64E, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ™… Person Gesturing No U+1F645 +๐Ÿ™…๐Ÿป Person Gesturing No: Light Skin Tone U+1F645, U+1F3FB +๐Ÿ™…๐Ÿผ Person Gesturing No: Medium-Light Skin U+1F645, U+1F3FC +Tone +๐Ÿ™…๐Ÿฝ Person Gesturing No: Medium Skin Tone U+1F645, U+1F3FD +๐Ÿ™…๐Ÿพ Person Gesturing No: Medium-Dark Skin U+1F645, U+1F3FE +Tone +๐Ÿ™…๐Ÿฟ Person Gesturing No: Dark Skin Tone U+1F645, U+1F3FF +๐Ÿ™…โ€โ™‚๏ธ Man Gesturing No U+1F645, U+200D, U+2642, U+FE0F +๐Ÿ™…๐Ÿปโ€โ™‚๏ธ Man Gesturing No: Light Skin Tone U+1F645, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ™…๐Ÿผโ€โ™‚๏ธ Man Gesturing No: Medium-Light Skin U+1F645, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿ™…๐Ÿฝโ€โ™‚๏ธ Man Gesturing No: Medium Skin Tone U+1F645, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ™…๐Ÿพโ€โ™‚๏ธ Man Gesturing No: Medium-Dark Skin U+1F645, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿ™…๐Ÿฟโ€โ™‚๏ธ Man Gesturing No: Dark Skin Tone U+1F645, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ™…โ€โ™€๏ธ Woman Gesturing No U+1F645, U+200D, U+2640, U+FE0F +๐Ÿ™…๐Ÿปโ€โ™€๏ธ Woman Gesturing No: Light Skin Tone U+1F645, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ™…๐Ÿผโ€โ™€๏ธ Woman Gesturing No: Medium-Light Skin U+1F645, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿ™…๐Ÿฝโ€โ™€๏ธ Woman Gesturing No: Medium Skin Tone U+1F645, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ™…๐Ÿพโ€โ™€๏ธ Woman Gesturing No: Medium-Dark Skin U+1F645, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿ™…๐Ÿฟโ€โ™€๏ธ Woman Gesturing No: Dark Skin Tone U+1F645, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ™† Person Gesturing OK U+1F646 +๐Ÿ™†๐Ÿป Person Gesturing OK: Light Skin Tone U+1F646, U+1F3FB +๐Ÿ™†๐Ÿผ Person Gesturing OK: Medium-Light Skin U+1F646, U+1F3FC +Tone +๐Ÿ™†๐Ÿฝ Person Gesturing OK: Medium Skin Tone U+1F646, U+1F3FD +๐Ÿ™†๐Ÿพ Person Gesturing OK: Medium-Dark Skin U+1F646, U+1F3FE +Tone +๐Ÿ™†๐Ÿฟ Person Gesturing OK: Dark Skin Tone U+1F646, U+1F3FF +๐Ÿ™†โ€โ™‚๏ธ Man Gesturing OK U+1F646, U+200D, U+2642, U+FE0F +๐Ÿ™†๐Ÿปโ€โ™‚๏ธ Man Gesturing OK: Light Skin Tone U+1F646, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ™†๐Ÿผโ€โ™‚๏ธ Man Gesturing OK: Medium-Light Skin U+1F646, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿ™†๐Ÿฝโ€โ™‚๏ธ Man Gesturing OK: Medium Skin Tone U+1F646, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ™†๐Ÿพโ€โ™‚๏ธ Man Gesturing OK: Medium-Dark Skin U+1F646, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿ™†๐Ÿฟโ€โ™‚๏ธ Man Gesturing OK: Dark Skin Tone U+1F646, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ™†โ€โ™€๏ธ Woman Gesturing OK U+1F646, U+200D, U+2640, U+FE0F +๐Ÿ™†๐Ÿปโ€โ™€๏ธ Woman Gesturing OK: Light Skin Tone U+1F646, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ™†๐Ÿผโ€โ™€๏ธ Woman Gesturing OK: Medium-Light Skin U+1F646, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿ™†๐Ÿฝโ€โ™€๏ธ Woman Gesturing OK: Medium Skin Tone U+1F646, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ™†๐Ÿพโ€โ™€๏ธ Woman Gesturing OK: Medium-Dark Skin U+1F646, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿ™†๐Ÿฟโ€โ™€๏ธ Woman Gesturing OK: Dark Skin Tone U+1F646, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ’ Person Tipping Hand U+1F481 +๐Ÿ’๐Ÿป Person Tipping Hand: Light Skin Tone U+1F481, U+1F3FB +๐Ÿ’๐Ÿผ Person Tipping Hand: Medium-Light Skin U+1F481, U+1F3FC +Tone +๐Ÿ’๐Ÿฝ Person Tipping Hand: Medium Skin Tone U+1F481, U+1F3FD +๐Ÿ’๐Ÿพ Person Tipping Hand: Medium-Dark Skin U+1F481, U+1F3FE +Tone +๐Ÿ’๐Ÿฟ Person Tipping Hand: Dark Skin Tone U+1F481, U+1F3FF +๐Ÿ’โ€โ™‚๏ธ Man Tipping Hand U+1F481, U+200D, U+2642, U+FE0F +๐Ÿ’๐Ÿปโ€โ™‚๏ธ Man Tipping Hand: Light Skin Tone U+1F481, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ’๐Ÿผโ€โ™‚๏ธ Man Tipping Hand: Medium-Light Skin U+1F481, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿ’๐Ÿฝโ€โ™‚๏ธ Man Tipping Hand: Medium Skin Tone U+1F481, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ’๐Ÿพโ€โ™‚๏ธ Man Tipping Hand: Medium-Dark Skin U+1F481, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿ’๐Ÿฟโ€โ™‚๏ธ Man Tipping Hand: Dark Skin Tone U+1F481, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ’โ€โ™€๏ธ Woman Tipping Hand U+1F481, U+200D, U+2640, U+FE0F +๐Ÿ’๐Ÿปโ€โ™€๏ธ Woman Tipping Hand: Light Skin Tone U+1F481, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ’๐Ÿผโ€โ™€๏ธ Woman Tipping Hand: Medium-Light Skin U+1F481, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿ’๐Ÿฝโ€โ™€๏ธ Woman Tipping Hand: Medium Skin Tone U+1F481, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ’๐Ÿพโ€โ™€๏ธ Woman Tipping Hand: Medium-Dark Skin U+1F481, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿ’๐Ÿฟโ€โ™€๏ธ Woman Tipping Hand: Dark Skin Tone U+1F481, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ™‹ Person Raising Hand U+1F64B +๐Ÿ™‹๐Ÿป Person Raising Hand: Light Skin Tone U+1F64B, U+1F3FB +๐Ÿ™‹๐Ÿผ Person Raising Hand: Medium-Light Skin U+1F64B, U+1F3FC +Tone +๐Ÿ™‹๐Ÿฝ Person Raising Hand: Medium Skin Tone U+1F64B, U+1F3FD +๐Ÿ™‹๐Ÿพ Person Raising Hand: Medium-Dark Skin U+1F64B, U+1F3FE +Tone +๐Ÿ™‹๐Ÿฟ Person Raising Hand: Dark Skin Tone U+1F64B, U+1F3FF +๐Ÿ™‹โ€โ™‚๏ธ Man Raising Hand U+1F64B, U+200D, U+2642, U+FE0F +๐Ÿ™‹๐Ÿปโ€โ™‚๏ธ Man Raising Hand: Light Skin Tone U+1F64B, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ™‹๐Ÿผโ€โ™‚๏ธ Man Raising Hand: Medium-Light Skin U+1F64B, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿ™‹๐Ÿฝโ€โ™‚๏ธ Man Raising Hand: Medium Skin Tone U+1F64B, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ™‹๐Ÿพโ€โ™‚๏ธ Man Raising Hand: Medium-Dark Skin U+1F64B, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿ™‹๐Ÿฟโ€โ™‚๏ธ Man Raising Hand: Dark Skin Tone U+1F64B, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ™‹โ€โ™€๏ธ Woman Raising Hand U+1F64B, U+200D, U+2640, U+FE0F +๐Ÿ™‹๐Ÿปโ€โ™€๏ธ Woman Raising Hand: Light Skin Tone U+1F64B, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ™‹๐Ÿผโ€โ™€๏ธ Woman Raising Hand: Medium-Light Skin U+1F64B, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿ™‹๐Ÿฝโ€โ™€๏ธ Woman Raising Hand: Medium Skin Tone U+1F64B, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ™‹๐Ÿพโ€โ™€๏ธ Woman Raising Hand: Medium-Dark Skin U+1F64B, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿ™‹๐Ÿฟโ€โ™€๏ธ Woman Raising Hand: Dark Skin Tone U+1F64B, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿง Deaf Person U+1F9CF +๐Ÿง๐Ÿป Deaf Person: Light Skin Tone U+1F9CF, U+1F3FB +๐Ÿง๐Ÿผ Deaf Person: Medium-Light Skin Tone U+1F9CF, U+1F3FC +๐Ÿง๐Ÿฝ Deaf Person: Medium Skin Tone U+1F9CF, U+1F3FD +๐Ÿง๐Ÿพ Deaf Person: Medium-Dark Skin Tone U+1F9CF, U+1F3FE +๐Ÿง๐Ÿฟ Deaf Person: Dark Skin Tone U+1F9CF, U+1F3FF +๐Ÿงโ€โ™‚๏ธ Deaf Man U+1F9CF, U+200D, U+2642, U+FE0F +๐Ÿง๐Ÿปโ€โ™‚๏ธ Deaf Man: Light Skin Tone U+1F9CF, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿผโ€โ™‚๏ธ Deaf Man: Medium-Light Skin Tone U+1F9CF, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿฝโ€โ™‚๏ธ Deaf Man: Medium Skin Tone U+1F9CF, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿพโ€โ™‚๏ธ Deaf Man: Medium-Dark Skin Tone U+1F9CF, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿฟโ€โ™‚๏ธ Deaf Man: Dark Skin Tone U+1F9CF, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿงโ€โ™€๏ธ Deaf Woman U+1F9CF, U+200D, U+2640, U+FE0F +๐Ÿง๐Ÿปโ€โ™€๏ธ Deaf Woman: Light Skin Tone U+1F9CF, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿผโ€โ™€๏ธ Deaf Woman: Medium-Light Skin Tone U+1F9CF, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿฝโ€โ™€๏ธ Deaf Woman: Medium Skin Tone U+1F9CF, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿพโ€โ™€๏ธ Deaf Woman: Medium-Dark Skin Tone U+1F9CF, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿฟโ€โ™€๏ธ Deaf Woman: Dark Skin Tone U+1F9CF, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ™‡ Person Bowing U+1F647 +๐Ÿ™‡๐Ÿป Person Bowing: Light Skin Tone U+1F647, U+1F3FB +๐Ÿ™‡๐Ÿผ Person Bowing: Medium-Light Skin Tone U+1F647, U+1F3FC +๐Ÿ™‡๐Ÿฝ Person Bowing: Medium Skin Tone U+1F647, U+1F3FD +๐Ÿ™‡๐Ÿพ Person Bowing: Medium-Dark Skin Tone U+1F647, U+1F3FE +๐Ÿ™‡๐Ÿฟ Person Bowing: Dark Skin Tone U+1F647, U+1F3FF +๐Ÿ™‡โ€โ™‚๏ธ Man Bowing U+1F647, U+200D, U+2642, U+FE0F +๐Ÿ™‡๐Ÿปโ€โ™‚๏ธ Man Bowing: Light Skin Tone U+1F647, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ™‡๐Ÿผโ€โ™‚๏ธ Man Bowing: Medium-Light Skin Tone U+1F647, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿ™‡๐Ÿฝโ€โ™‚๏ธ Man Bowing: Medium Skin Tone U+1F647, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ™‡๐Ÿพโ€โ™‚๏ธ Man Bowing: Medium-Dark Skin Tone U+1F647, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿ™‡๐Ÿฟโ€โ™‚๏ธ Man Bowing: Dark Skin Tone U+1F647, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ™‡โ€โ™€๏ธ Woman Bowing U+1F647, U+200D, U+2640, U+FE0F +๐Ÿ™‡๐Ÿปโ€โ™€๏ธ Woman Bowing: Light Skin Tone U+1F647, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ™‡๐Ÿผโ€โ™€๏ธ Woman Bowing: Medium-Light Skin Tone U+1F647, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿ™‡๐Ÿฝโ€โ™€๏ธ Woman Bowing: Medium Skin Tone U+1F647, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ™‡๐Ÿพโ€โ™€๏ธ Woman Bowing: Medium-Dark Skin Tone U+1F647, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿ™‡๐Ÿฟโ€โ™€๏ธ Woman Bowing: Dark Skin Tone U+1F647, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿคฆ Person Facepalming U+1F926 +๐Ÿคฆ๐Ÿป Person Facepalming: Light Skin Tone U+1F926, U+1F3FB +๐Ÿคฆ๐Ÿผ Person Facepalming: Medium-Light Skin U+1F926, U+1F3FC +Tone +๐Ÿคฆ๐Ÿฝ Person Facepalming: Medium Skin Tone U+1F926, U+1F3FD +๐Ÿคฆ๐Ÿพ Person Facepalming: Medium-Dark Skin Tone U+1F926, U+1F3FE +๐Ÿคฆ๐Ÿฟ Person Facepalming: Dark Skin Tone U+1F926, U+1F3FF +๐Ÿคฆโ€โ™‚๏ธ Man Facepalming U+1F926, U+200D, U+2642, U+FE0F +๐Ÿคฆ๐Ÿปโ€โ™‚๏ธ Man Facepalming: Light Skin Tone U+1F926, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿคฆ๐Ÿผโ€โ™‚๏ธ Man Facepalming: Medium-Light Skin U+1F926, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿคฆ๐Ÿฝโ€โ™‚๏ธ Man Facepalming: Medium Skin Tone U+1F926, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿคฆ๐Ÿพโ€โ™‚๏ธ Man Facepalming: Medium-Dark Skin Tone U+1F926, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿคฆ๐Ÿฟโ€โ™‚๏ธ Man Facepalming: Dark Skin Tone U+1F926, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿคฆโ€โ™€๏ธ Woman Facepalming U+1F926, U+200D, U+2640, U+FE0F +๐Ÿคฆ๐Ÿปโ€โ™€๏ธ Woman Facepalming: Light Skin Tone U+1F926, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿคฆ๐Ÿผโ€โ™€๏ธ Woman Facepalming: Medium-Light Skin U+1F926, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿคฆ๐Ÿฝโ€โ™€๏ธ Woman Facepalming: Medium Skin Tone U+1F926, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿคฆ๐Ÿพโ€โ™€๏ธ Woman Facepalming: Medium-Dark Skin U+1F926, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿคฆ๐Ÿฟโ€โ™€๏ธ Woman Facepalming: Dark Skin Tone U+1F926, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿคท Person Shrugging U+1F937 +๐Ÿคท๐Ÿป Person Shrugging: Light Skin Tone U+1F937, U+1F3FB +๐Ÿคท๐Ÿผ Person Shrugging: Medium-Light Skin Tone U+1F937, U+1F3FC +๐Ÿคท๐Ÿฝ Person Shrugging: Medium Skin Tone U+1F937, U+1F3FD +๐Ÿคท๐Ÿพ Person Shrugging: Medium-Dark Skin Tone U+1F937, U+1F3FE +๐Ÿคท๐Ÿฟ Person Shrugging: Dark Skin Tone U+1F937, U+1F3FF +๐Ÿคทโ€โ™‚๏ธ Man Shrugging U+1F937, U+200D, U+2642, U+FE0F +๐Ÿคท๐Ÿปโ€โ™‚๏ธ Man Shrugging: Light Skin Tone U+1F937, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿคท๐Ÿผโ€โ™‚๏ธ Man Shrugging: Medium-Light Skin Tone U+1F937, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿคท๐Ÿฝโ€โ™‚๏ธ Man Shrugging: Medium Skin Tone U+1F937, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿคท๐Ÿพโ€โ™‚๏ธ Man Shrugging: Medium-Dark Skin Tone U+1F937, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿคท๐Ÿฟโ€โ™‚๏ธ Man Shrugging: Dark Skin Tone U+1F937, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿคทโ€โ™€๏ธ Woman Shrugging U+1F937, U+200D, U+2640, U+FE0F +๐Ÿคท๐Ÿปโ€โ™€๏ธ Woman Shrugging: Light Skin Tone U+1F937, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿคท๐Ÿผโ€โ™€๏ธ Woman Shrugging: Medium-Light Skin U+1F937, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿคท๐Ÿฝโ€โ™€๏ธ Woman Shrugging: Medium Skin Tone U+1F937, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿคท๐Ÿพโ€โ™€๏ธ Woman Shrugging: Medium-Dark Skin Tone U+1F937, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿคท๐Ÿฟโ€โ™€๏ธ Woman Shrugging: Dark Skin Tone U+1F937, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿง‘โ€โš•๏ธ Health Worker U+1F9D1, U+200D, U+2695, U+FE0F +๐Ÿง‘๐Ÿปโ€โš•๏ธ Health Worker: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+2695, + U+FE0F +๐Ÿง‘๐Ÿผโ€โš•๏ธ Health Worker: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+2695, + U+FE0F +๐Ÿง‘๐Ÿฝโ€โš•๏ธ Health Worker: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+2695, + U+FE0F +๐Ÿง‘๐Ÿพโ€โš•๏ธ Health Worker: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+2695, + U+FE0F +๐Ÿง‘๐Ÿฟโ€โš•๏ธ Health Worker: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+2695, + U+FE0F +๐Ÿ‘จโ€โš•๏ธ Man Health Worker U+1F468, U+200D, U+2695, U+FE0F +๐Ÿ‘จ๐Ÿปโ€โš•๏ธ Man Health Worker: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+2695, + U+FE0F +๐Ÿ‘จ๐Ÿผโ€โš•๏ธ Man Health Worker: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+2695, +Tone U+FE0F +๐Ÿ‘จ๐Ÿฝโ€โš•๏ธ Man Health Worker: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+2695, + U+FE0F +๐Ÿ‘จ๐Ÿพโ€โš•๏ธ Man Health Worker: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+2695, +Tone U+FE0F +๐Ÿ‘จ๐Ÿฟโ€โš•๏ธ Man Health Worker: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+2695, + U+FE0F +๐Ÿ‘ฉโ€โš•๏ธ Woman Health Worker U+1F469, U+200D, U+2695, U+FE0F +๐Ÿ‘ฉ๐Ÿปโ€โš•๏ธ Woman Health Worker: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+2695, + U+FE0F +๐Ÿ‘ฉ๐Ÿผโ€โš•๏ธ Woman Health Worker: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+2695, +Tone U+FE0F +๐Ÿ‘ฉ๐Ÿฝโ€โš•๏ธ Woman Health Worker: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+2695, + U+FE0F +๐Ÿ‘ฉ๐Ÿพโ€โš•๏ธ Woman Health Worker: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+2695, +Tone U+FE0F +๐Ÿ‘ฉ๐Ÿฟโ€โš•๏ธ Woman Health Worker: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+2695, + U+FE0F +๐Ÿง‘โ€๐ŸŽ“ Student U+1F9D1, U+200D, U+1F393 +๐Ÿง‘๐Ÿปโ€๐ŸŽ“ Student: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F393 +๐Ÿง‘๐Ÿผโ€๐ŸŽ“ Student: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F393 +๐Ÿง‘๐Ÿฝโ€๐ŸŽ“ Student: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F393 +๐Ÿง‘๐Ÿพโ€๐ŸŽ“ Student: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F393 +๐Ÿง‘๐Ÿฟโ€๐ŸŽ“ Student: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F393 +๐Ÿ‘จโ€๐ŸŽ“ Man Student U+1F468, U+200D, U+1F393 +๐Ÿ‘จ๐Ÿปโ€๐ŸŽ“ Man Student: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F393 +๐Ÿ‘จ๐Ÿผโ€๐ŸŽ“ Man Student: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F393 +๐Ÿ‘จ๐Ÿฝโ€๐ŸŽ“ Man Student: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F393 +๐Ÿ‘จ๐Ÿพโ€๐ŸŽ“ Man Student: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F393 +๐Ÿ‘จ๐Ÿฟโ€๐ŸŽ“ Man Student: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F393 +๐Ÿ‘ฉโ€๐ŸŽ“ Woman Student U+1F469, U+200D, U+1F393 +๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽ“ Woman Student: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F393 +๐Ÿ‘ฉ๐Ÿผโ€๐ŸŽ“ Woman Student: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F393 +๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽ“ Woman Student: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F393 +๐Ÿ‘ฉ๐Ÿพโ€๐ŸŽ“ Woman Student: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F393 +๐Ÿ‘ฉ๐Ÿฟโ€๐ŸŽ“ Woman Student: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F393 +๐Ÿง‘โ€๐Ÿซ Teacher U+1F9D1, U+200D, U+1F3EB +๐Ÿง‘๐Ÿปโ€๐Ÿซ Teacher: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F3EB +๐Ÿง‘๐Ÿผโ€๐Ÿซ Teacher: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F3EB +๐Ÿง‘๐Ÿฝโ€๐Ÿซ Teacher: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F3EB +๐Ÿง‘๐Ÿพโ€๐Ÿซ Teacher: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F3EB +๐Ÿง‘๐Ÿฟโ€๐Ÿซ Teacher: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F3EB +๐Ÿ‘จโ€๐Ÿซ Man Teacher U+1F468, U+200D, U+1F3EB +๐Ÿ‘จ๐Ÿปโ€๐Ÿซ Man Teacher: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F3EB +๐Ÿ‘จ๐Ÿผโ€๐Ÿซ Man Teacher: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F3EB +๐Ÿ‘จ๐Ÿฝโ€๐Ÿซ Man Teacher: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F3EB +๐Ÿ‘จ๐Ÿพโ€๐Ÿซ Man Teacher: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F3EB +๐Ÿ‘จ๐Ÿฟโ€๐Ÿซ Man Teacher: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F3EB +๐Ÿ‘ฉโ€๐Ÿซ Woman Teacher U+1F469, U+200D, U+1F3EB +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿซ Woman Teacher: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F3EB +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿซ Woman Teacher: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F3EB +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿซ Woman Teacher: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F3EB +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿซ Woman Teacher: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F3EB +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿซ Woman Teacher: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F3EB +๐Ÿง‘โ€โš–๏ธ Judge U+1F9D1, U+200D, U+2696, U+FE0F +๐Ÿง‘๐Ÿปโ€โš–๏ธ Judge: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+2696, + U+FE0F +๐Ÿง‘๐Ÿผโ€โš–๏ธ Judge: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+2696, + U+FE0F +๐Ÿง‘๐Ÿฝโ€โš–๏ธ Judge: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+2696, + U+FE0F +๐Ÿง‘๐Ÿพโ€โš–๏ธ Judge: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+2696, + U+FE0F +๐Ÿง‘๐Ÿฟโ€โš–๏ธ Judge: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+2696, + U+FE0F +๐Ÿ‘จโ€โš–๏ธ Man Judge U+1F468, U+200D, U+2696, U+FE0F +๐Ÿ‘จ๐Ÿปโ€โš–๏ธ Man Judge: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+2696, + U+FE0F +๐Ÿ‘จ๐Ÿผโ€โš–๏ธ Man Judge: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+2696, + U+FE0F +๐Ÿ‘จ๐Ÿฝโ€โš–๏ธ Man Judge: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+2696, + U+FE0F +๐Ÿ‘จ๐Ÿพโ€โš–๏ธ Man Judge: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+2696, + U+FE0F +๐Ÿ‘จ๐Ÿฟโ€โš–๏ธ Man Judge: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+2696, + U+FE0F +๐Ÿ‘ฉโ€โš–๏ธ Woman Judge U+1F469, U+200D, U+2696, U+FE0F +๐Ÿ‘ฉ๐Ÿปโ€โš–๏ธ Woman Judge: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+2696, + U+FE0F +๐Ÿ‘ฉ๐Ÿผโ€โš–๏ธ Woman Judge: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+2696, + U+FE0F +๐Ÿ‘ฉ๐Ÿฝโ€โš–๏ธ Woman Judge: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+2696, + U+FE0F +๐Ÿ‘ฉ๐Ÿพโ€โš–๏ธ Woman Judge: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+2696, + U+FE0F +๐Ÿ‘ฉ๐Ÿฟโ€โš–๏ธ Woman Judge: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+2696, + U+FE0F +๐Ÿง‘โ€๐ŸŒพ Farmer U+1F9D1, U+200D, U+1F33E +๐Ÿง‘๐Ÿปโ€๐ŸŒพ Farmer: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F33E +๐Ÿง‘๐Ÿผโ€๐ŸŒพ Farmer: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F33E +๐Ÿง‘๐Ÿฝโ€๐ŸŒพ Farmer: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F33E +๐Ÿง‘๐Ÿพโ€๐ŸŒพ Farmer: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F33E +๐Ÿง‘๐Ÿฟโ€๐ŸŒพ Farmer: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F33E +๐Ÿ‘จโ€๐ŸŒพ Man Farmer U+1F468, U+200D, U+1F33E +๐Ÿ‘จ๐Ÿปโ€๐ŸŒพ Man Farmer: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F33E +๐Ÿ‘จ๐Ÿผโ€๐ŸŒพ Man Farmer: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F33E +๐Ÿ‘จ๐Ÿฝโ€๐ŸŒพ Man Farmer: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F33E +๐Ÿ‘จ๐Ÿพโ€๐ŸŒพ Man Farmer: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F33E +๐Ÿ‘จ๐Ÿฟโ€๐ŸŒพ Man Farmer: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F33E +๐Ÿ‘ฉโ€๐ŸŒพ Woman Farmer U+1F469, U+200D, U+1F33E +๐Ÿ‘ฉ๐Ÿปโ€๐ŸŒพ Woman Farmer: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F33E +๐Ÿ‘ฉ๐Ÿผโ€๐ŸŒพ Woman Farmer: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F33E +๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŒพ Woman Farmer: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F33E +๐Ÿ‘ฉ๐Ÿพโ€๐ŸŒพ Woman Farmer: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F33E +๐Ÿ‘ฉ๐Ÿฟโ€๐ŸŒพ Woman Farmer: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F33E +๐Ÿง‘โ€๐Ÿณ Cook U+1F9D1, U+200D, U+1F373 +๐Ÿง‘๐Ÿปโ€๐Ÿณ Cook: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F373 +๐Ÿง‘๐Ÿผโ€๐Ÿณ Cook: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F373 +๐Ÿง‘๐Ÿฝโ€๐Ÿณ Cook: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F373 +๐Ÿง‘๐Ÿพโ€๐Ÿณ Cook: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F373 +๐Ÿง‘๐Ÿฟโ€๐Ÿณ Cook: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F373 +๐Ÿ‘จโ€๐Ÿณ Man Cook U+1F468, U+200D, U+1F373 +๐Ÿ‘จ๐Ÿปโ€๐Ÿณ Man Cook: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F373 +๐Ÿ‘จ๐Ÿผโ€๐Ÿณ Man Cook: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F373 +๐Ÿ‘จ๐Ÿฝโ€๐Ÿณ Man Cook: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F373 +๐Ÿ‘จ๐Ÿพโ€๐Ÿณ Man Cook: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F373 +๐Ÿ‘จ๐Ÿฟโ€๐Ÿณ Man Cook: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F373 +๐Ÿ‘ฉโ€๐Ÿณ Woman Cook U+1F469, U+200D, U+1F373 +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿณ Woman Cook: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F373 +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿณ Woman Cook: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F373 +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿณ Woman Cook: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F373 +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿณ Woman Cook: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F373 +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿณ Woman Cook: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F373 +๐Ÿง‘โ€๐Ÿ”ง Mechanic U+1F9D1, U+200D, U+1F527 +๐Ÿง‘๐Ÿปโ€๐Ÿ”ง Mechanic: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F527 +๐Ÿง‘๐Ÿผโ€๐Ÿ”ง Mechanic: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F527 +๐Ÿง‘๐Ÿฝโ€๐Ÿ”ง Mechanic: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F527 +๐Ÿง‘๐Ÿพโ€๐Ÿ”ง Mechanic: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F527 +๐Ÿง‘๐Ÿฟโ€๐Ÿ”ง Mechanic: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F527 +๐Ÿ‘จโ€๐Ÿ”ง Man Mechanic U+1F468, U+200D, U+1F527 +๐Ÿ‘จ๐Ÿปโ€๐Ÿ”ง Man Mechanic: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F527 +๐Ÿ‘จ๐Ÿผโ€๐Ÿ”ง Man Mechanic: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F527 +๐Ÿ‘จ๐Ÿฝโ€๐Ÿ”ง Man Mechanic: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F527 +๐Ÿ‘จ๐Ÿพโ€๐Ÿ”ง Man Mechanic: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F527 +๐Ÿ‘จ๐Ÿฟโ€๐Ÿ”ง Man Mechanic: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F527 +๐Ÿ‘ฉโ€๐Ÿ”ง Woman Mechanic U+1F469, U+200D, U+1F527 +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ”ง Woman Mechanic: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F527 +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ”ง Woman Mechanic: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F527 +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ”ง Woman Mechanic: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F527 +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿ”ง Woman Mechanic: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F527 +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ”ง Woman Mechanic: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F527 +๐Ÿง‘โ€๐Ÿญ Factory Worker U+1F9D1, U+200D, U+1F3ED +๐Ÿง‘๐Ÿปโ€๐Ÿญ Factory Worker: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F3ED +๐Ÿง‘๐Ÿผโ€๐Ÿญ Factory Worker: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F3ED +๐Ÿง‘๐Ÿฝโ€๐Ÿญ Factory Worker: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F3ED +๐Ÿง‘๐Ÿพโ€๐Ÿญ Factory Worker: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F3ED +๐Ÿง‘๐Ÿฟโ€๐Ÿญ Factory Worker: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F3ED +๐Ÿ‘จโ€๐Ÿญ Man Factory Worker U+1F468, U+200D, U+1F3ED +๐Ÿ‘จ๐Ÿปโ€๐Ÿญ Man Factory Worker: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F3ED +๐Ÿ‘จ๐Ÿผโ€๐Ÿญ Man Factory Worker: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F3ED +Tone +๐Ÿ‘จ๐Ÿฝโ€๐Ÿญ Man Factory Worker: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F3ED +๐Ÿ‘จ๐Ÿพโ€๐Ÿญ Man Factory Worker: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F3ED +Tone +๐Ÿ‘จ๐Ÿฟโ€๐Ÿญ Man Factory Worker: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F3ED +๐Ÿ‘ฉโ€๐Ÿญ Woman Factory Worker U+1F469, U+200D, U+1F3ED +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿญ Woman Factory Worker: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F3ED +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿญ Woman Factory Worker: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F3ED +Tone +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿญ Woman Factory Worker: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F3ED +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿญ Woman Factory Worker: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F3ED +Tone +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿญ Woman Factory Worker: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F3ED +๐Ÿง‘โ€๐Ÿ’ผ Office Worker U+1F9D1, U+200D, U+1F4BC +๐Ÿง‘๐Ÿปโ€๐Ÿ’ผ Office Worker: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F4BC +๐Ÿง‘๐Ÿผโ€๐Ÿ’ผ Office Worker: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F4BC +๐Ÿง‘๐Ÿฝโ€๐Ÿ’ผ Office Worker: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F4BC +๐Ÿง‘๐Ÿพโ€๐Ÿ’ผ Office Worker: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F4BC +๐Ÿง‘๐Ÿฟโ€๐Ÿ’ผ Office Worker: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F4BC +๐Ÿ‘จโ€๐Ÿ’ผ Man Office Worker U+1F468, U+200D, U+1F4BC +๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ผ Man Office Worker: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F4BC +๐Ÿ‘จ๐Ÿผโ€๐Ÿ’ผ Man Office Worker: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F4BC +Tone +๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ผ Man Office Worker: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F4BC +๐Ÿ‘จ๐Ÿพโ€๐Ÿ’ผ Man Office Worker: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F4BC +Tone +๐Ÿ‘จ๐Ÿฟโ€๐Ÿ’ผ Man Office Worker: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F4BC +๐Ÿ‘ฉโ€๐Ÿ’ผ Woman Office Worker U+1F469, U+200D, U+1F4BC +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ผ Woman Office Worker: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F4BC +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ’ผ Woman Office Worker: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F4BC +Tone +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ผ Woman Office Worker: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F4BC +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿ’ผ Woman Office Worker: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F4BC +Tone +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ’ผ Woman Office Worker: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F4BC +๐Ÿง‘โ€๐Ÿ”ฌ Scientist U+1F9D1, U+200D, U+1F52C +๐Ÿง‘๐Ÿปโ€๐Ÿ”ฌ Scientist: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F52C +๐Ÿง‘๐Ÿผโ€๐Ÿ”ฌ Scientist: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F52C +๐Ÿง‘๐Ÿฝโ€๐Ÿ”ฌ Scientist: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F52C +๐Ÿง‘๐Ÿพโ€๐Ÿ”ฌ Scientist: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F52C +๐Ÿง‘๐Ÿฟโ€๐Ÿ”ฌ Scientist: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F52C +๐Ÿ‘จโ€๐Ÿ”ฌ Man Scientist U+1F468, U+200D, U+1F52C +๐Ÿ‘จ๐Ÿปโ€๐Ÿ”ฌ Man Scientist: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F52C +๐Ÿ‘จ๐Ÿผโ€๐Ÿ”ฌ Man Scientist: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F52C +๐Ÿ‘จ๐Ÿฝโ€๐Ÿ”ฌ Man Scientist: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F52C +๐Ÿ‘จ๐Ÿพโ€๐Ÿ”ฌ Man Scientist: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F52C +๐Ÿ‘จ๐Ÿฟโ€๐Ÿ”ฌ Man Scientist: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F52C +๐Ÿ‘ฉโ€๐Ÿ”ฌ Woman Scientist U+1F469, U+200D, U+1F52C +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ”ฌ Woman Scientist: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F52C +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ”ฌ Woman Scientist: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F52C +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ”ฌ Woman Scientist: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F52C +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿ”ฌ Woman Scientist: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F52C +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ”ฌ Woman Scientist: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F52C +๐Ÿง‘โ€๐Ÿ’ป Technologist U+1F9D1, U+200D, U+1F4BB +๐Ÿง‘๐Ÿปโ€๐Ÿ’ป Technologist: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F4BB +๐Ÿง‘๐Ÿผโ€๐Ÿ’ป Technologist: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F4BB +๐Ÿง‘๐Ÿฝโ€๐Ÿ’ป Technologist: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F4BB +๐Ÿง‘๐Ÿพโ€๐Ÿ’ป Technologist: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F4BB +๐Ÿง‘๐Ÿฟโ€๐Ÿ’ป Technologist: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F4BB +๐Ÿ‘จโ€๐Ÿ’ป Man Technologist U+1F468, U+200D, U+1F4BB +๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Man Technologist: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F4BB +๐Ÿ‘จ๐Ÿผโ€๐Ÿ’ป Man Technologist: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F4BB +Tone +๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ป Man Technologist: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F4BB +๐Ÿ‘จ๐Ÿพโ€๐Ÿ’ป Man Technologist: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F4BB +๐Ÿ‘จ๐Ÿฟโ€๐Ÿ’ป Man Technologist: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F4BB +๐Ÿ‘ฉโ€๐Ÿ’ป Woman Technologist U+1F469, U+200D, U+1F4BB +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป Woman Technologist: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F4BB +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ’ป Woman Technologist: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F4BB +Tone +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Woman Technologist: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F4BB +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿ’ป Woman Technologist: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F4BB +Tone +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ’ป Woman Technologist: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F4BB +๐Ÿง‘โ€๐ŸŽค Singer U+1F9D1, U+200D, U+1F3A4 +๐Ÿง‘๐Ÿปโ€๐ŸŽค Singer: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F3A4 +๐Ÿง‘๐Ÿผโ€๐ŸŽค Singer: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F3A4 +๐Ÿง‘๐Ÿฝโ€๐ŸŽค Singer: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F3A4 +๐Ÿง‘๐Ÿพโ€๐ŸŽค Singer: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F3A4 +๐Ÿง‘๐Ÿฟโ€๐ŸŽค Singer: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F3A4 +๐Ÿ‘จโ€๐ŸŽค Man Singer U+1F468, U+200D, U+1F3A4 +๐Ÿ‘จ๐Ÿปโ€๐ŸŽค Man Singer: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F3A4 +๐Ÿ‘จ๐Ÿผโ€๐ŸŽค Man Singer: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F3A4 +๐Ÿ‘จ๐Ÿฝโ€๐ŸŽค Man Singer: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F3A4 +๐Ÿ‘จ๐Ÿพโ€๐ŸŽค Man Singer: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F3A4 +๐Ÿ‘จ๐Ÿฟโ€๐ŸŽค Man Singer: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F3A4 +๐Ÿ‘ฉโ€๐ŸŽค Woman Singer U+1F469, U+200D, U+1F3A4 +๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽค Woman Singer: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F3A4 +๐Ÿ‘ฉ๐Ÿผโ€๐ŸŽค Woman Singer: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F3A4 +๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽค Woman Singer: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F3A4 +๐Ÿ‘ฉ๐Ÿพโ€๐ŸŽค Woman Singer: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F3A4 +๐Ÿ‘ฉ๐Ÿฟโ€๐ŸŽค Woman Singer: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F3A4 +๐Ÿง‘โ€๐ŸŽจ Artist U+1F9D1, U+200D, U+1F3A8 +๐Ÿง‘๐Ÿปโ€๐ŸŽจ Artist: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F3A8 +๐Ÿง‘๐Ÿผโ€๐ŸŽจ Artist: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F3A8 +๐Ÿง‘๐Ÿฝโ€๐ŸŽจ Artist: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F3A8 +๐Ÿง‘๐Ÿพโ€๐ŸŽจ Artist: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F3A8 +๐Ÿง‘๐Ÿฟโ€๐ŸŽจ Artist: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F3A8 +๐Ÿ‘จโ€๐ŸŽจ Man Artist U+1F468, U+200D, U+1F3A8 +๐Ÿ‘จ๐Ÿปโ€๐ŸŽจ Man Artist: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F3A8 +๐Ÿ‘จ๐Ÿผโ€๐ŸŽจ Man Artist: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F3A8 +๐Ÿ‘จ๐Ÿฝโ€๐ŸŽจ Man Artist: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F3A8 +๐Ÿ‘จ๐Ÿพโ€๐ŸŽจ Man Artist: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F3A8 +๐Ÿ‘จ๐Ÿฟโ€๐ŸŽจ Man Artist: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F3A8 +๐Ÿ‘ฉโ€๐ŸŽจ Woman Artist U+1F469, U+200D, U+1F3A8 +๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽจ Woman Artist: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F3A8 +๐Ÿ‘ฉ๐Ÿผโ€๐ŸŽจ Woman Artist: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F3A8 +๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽจ Woman Artist: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F3A8 +๐Ÿ‘ฉ๐Ÿพโ€๐ŸŽจ Woman Artist: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F3A8 +๐Ÿ‘ฉ๐Ÿฟโ€๐ŸŽจ Woman Artist: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F3A8 +๐Ÿง‘โ€โœˆ๏ธ Pilot U+1F9D1, U+200D, U+2708, U+FE0F +๐Ÿง‘๐Ÿปโ€โœˆ๏ธ Pilot: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+2708, + U+FE0F +๐Ÿง‘๐Ÿผโ€โœˆ๏ธ Pilot: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+2708, + U+FE0F +๐Ÿง‘๐Ÿฝโ€โœˆ๏ธ Pilot: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+2708, + U+FE0F +๐Ÿง‘๐Ÿพโ€โœˆ๏ธ Pilot: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+2708, + U+FE0F +๐Ÿง‘๐Ÿฟโ€โœˆ๏ธ Pilot: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+2708, + U+FE0F +๐Ÿ‘จโ€โœˆ๏ธ Man Pilot U+1F468, U+200D, U+2708, U+FE0F +๐Ÿ‘จ๐Ÿปโ€โœˆ๏ธ Man Pilot: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+2708, + U+FE0F +๐Ÿ‘จ๐Ÿผโ€โœˆ๏ธ Man Pilot: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+2708, + U+FE0F +๐Ÿ‘จ๐Ÿฝโ€โœˆ๏ธ Man Pilot: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+2708, + U+FE0F +๐Ÿ‘จ๐Ÿพโ€โœˆ๏ธ Man Pilot: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+2708, + U+FE0F +๐Ÿ‘จ๐Ÿฟโ€โœˆ๏ธ Man Pilot: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+2708, + U+FE0F +๐Ÿ‘ฉโ€โœˆ๏ธ Woman Pilot U+1F469, U+200D, U+2708, U+FE0F +๐Ÿ‘ฉ๐Ÿปโ€โœˆ๏ธ Woman Pilot: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+2708, + U+FE0F +๐Ÿ‘ฉ๐Ÿผโ€โœˆ๏ธ Woman Pilot: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+2708, + U+FE0F +๐Ÿ‘ฉ๐Ÿฝโ€โœˆ๏ธ Woman Pilot: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+2708, + U+FE0F +๐Ÿ‘ฉ๐Ÿพโ€โœˆ๏ธ Woman Pilot: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+2708, + U+FE0F +๐Ÿ‘ฉ๐Ÿฟโ€โœˆ๏ธ Woman Pilot: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+2708, + U+FE0F +๐Ÿง‘โ€๐Ÿš€ Astronaut U+1F9D1, U+200D, U+1F680 +๐Ÿง‘๐Ÿปโ€๐Ÿš€ Astronaut: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F680 +๐Ÿง‘๐Ÿผโ€๐Ÿš€ Astronaut: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F680 +๐Ÿง‘๐Ÿฝโ€๐Ÿš€ Astronaut: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F680 +๐Ÿง‘๐Ÿพโ€๐Ÿš€ Astronaut: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F680 +๐Ÿง‘๐Ÿฟโ€๐Ÿš€ Astronaut: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F680 +๐Ÿ‘จโ€๐Ÿš€ Man Astronaut U+1F468, U+200D, U+1F680 +๐Ÿ‘จ๐Ÿปโ€๐Ÿš€ Man Astronaut: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F680 +๐Ÿ‘จ๐Ÿผโ€๐Ÿš€ Man Astronaut: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F680 +๐Ÿ‘จ๐Ÿฝโ€๐Ÿš€ Man Astronaut: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F680 +๐Ÿ‘จ๐Ÿพโ€๐Ÿš€ Man Astronaut: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F680 +๐Ÿ‘จ๐Ÿฟโ€๐Ÿš€ Man Astronaut: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F680 +๐Ÿ‘ฉโ€๐Ÿš€ Woman Astronaut U+1F469, U+200D, U+1F680 +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿš€ Woman Astronaut: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F680 +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿš€ Woman Astronaut: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F680 +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿš€ Woman Astronaut: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F680 +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿš€ Woman Astronaut: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F680 +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿš€ Woman Astronaut: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F680 +๐Ÿง‘โ€๐Ÿš’ Firefighter U+1F9D1, U+200D, U+1F692 +๐Ÿง‘๐Ÿปโ€๐Ÿš’ Firefighter: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F692 +๐Ÿง‘๐Ÿผโ€๐Ÿš’ Firefighter: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F692 +๐Ÿง‘๐Ÿฝโ€๐Ÿš’ Firefighter: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F692 +๐Ÿง‘๐Ÿพโ€๐Ÿš’ Firefighter: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F692 +๐Ÿง‘๐Ÿฟโ€๐Ÿš’ Firefighter: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F692 +๐Ÿ‘จโ€๐Ÿš’ Man Firefighter U+1F468, U+200D, U+1F692 +๐Ÿ‘จ๐Ÿปโ€๐Ÿš’ Man Firefighter: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F692 +๐Ÿ‘จ๐Ÿผโ€๐Ÿš’ Man Firefighter: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F692 +๐Ÿ‘จ๐Ÿฝโ€๐Ÿš’ Man Firefighter: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F692 +๐Ÿ‘จ๐Ÿพโ€๐Ÿš’ Man Firefighter: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F692 +๐Ÿ‘จ๐Ÿฟโ€๐Ÿš’ Man Firefighter: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F692 +๐Ÿ‘ฉโ€๐Ÿš’ Woman Firefighter U+1F469, U+200D, U+1F692 +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿš’ Woman Firefighter: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F692 +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿš’ Woman Firefighter: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F692 +Tone +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿš’ Woman Firefighter: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F692 +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿš’ Woman Firefighter: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F692 +Tone +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿš’ Woman Firefighter: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F692 +๐Ÿ‘ฎ Police Officer U+1F46E +๐Ÿ‘ฎ๐Ÿป Police Officer: Light Skin Tone U+1F46E, U+1F3FB +๐Ÿ‘ฎ๐Ÿผ Police Officer: Medium-Light Skin Tone U+1F46E, U+1F3FC +๐Ÿ‘ฎ๐Ÿฝ Police Officer: Medium Skin Tone U+1F46E, U+1F3FD +๐Ÿ‘ฎ๐Ÿพ Police Officer: Medium-Dark Skin Tone U+1F46E, U+1F3FE +๐Ÿ‘ฎ๐Ÿฟ Police Officer: Dark Skin Tone U+1F46E, U+1F3FF +๐Ÿ‘ฎโ€โ™‚๏ธ Man Police Officer U+1F46E, U+200D, U+2642, U+FE0F +๐Ÿ‘ฎ๐Ÿปโ€โ™‚๏ธ Man Police Officer: Light Skin Tone U+1F46E, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฎ๐Ÿผโ€โ™‚๏ธ Man Police Officer: Medium-Light Skin U+1F46E, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‘ฎ๐Ÿฝโ€โ™‚๏ธ Man Police Officer: Medium Skin Tone U+1F46E, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฎ๐Ÿพโ€โ™‚๏ธ Man Police Officer: Medium-Dark Skin U+1F46E, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‘ฎ๐Ÿฟโ€โ™‚๏ธ Man Police Officer: Dark Skin Tone U+1F46E, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฎโ€โ™€๏ธ Woman Police Officer U+1F46E, U+200D, U+2640, U+FE0F +๐Ÿ‘ฎ๐Ÿปโ€โ™€๏ธ Woman Police Officer: Light Skin Tone U+1F46E, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฎ๐Ÿผโ€โ™€๏ธ Woman Police Officer: Medium-Light U+1F46E, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ‘ฎ๐Ÿฝโ€โ™€๏ธ Woman Police Officer: Medium Skin Tone U+1F46E, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฎ๐Ÿพโ€โ™€๏ธ Woman Police Officer: Medium-Dark Skin U+1F46E, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿ‘ฎ๐Ÿฟโ€โ™€๏ธ Woman Police Officer: Dark Skin Tone U+1F46E, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ•ต๏ธ Detective U+1F575, U+FE0F +๐Ÿ•ต๐Ÿป Detective: Light Skin Tone U+1F575, U+1F3FB +๐Ÿ•ต๐Ÿผ Detective: Medium-Light Skin Tone U+1F575, U+1F3FC +๐Ÿ•ต๐Ÿฝ Detective: Medium Skin Tone U+1F575, U+1F3FD +๐Ÿ•ต๐Ÿพ Detective: Medium-Dark Skin Tone U+1F575, U+1F3FE +๐Ÿ•ต๐Ÿฟ Detective: Dark Skin Tone U+1F575, U+1F3FF +๐Ÿ•ต๏ธโ€โ™‚๏ธ Man Detective U+1F575, U+FE0F, U+200D, U+2642, + U+FE0F +๐Ÿ•ต๐Ÿปโ€โ™‚๏ธ Man Detective: Light Skin Tone U+1F575, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ•ต๐Ÿผโ€โ™‚๏ธ Man Detective: Medium-Light Skin Tone U+1F575, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿ•ต๐Ÿฝโ€โ™‚๏ธ Man Detective: Medium Skin Tone U+1F575, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ•ต๐Ÿพโ€โ™‚๏ธ Man Detective: Medium-Dark Skin Tone U+1F575, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿ•ต๐Ÿฟโ€โ™‚๏ธ Man Detective: Dark Skin Tone U+1F575, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ•ต๏ธโ€โ™€๏ธ Woman Detective U+1F575, U+FE0F, U+200D, U+2640, + U+FE0F +๐Ÿ•ต๐Ÿปโ€โ™€๏ธ Woman Detective: Light Skin Tone U+1F575, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ•ต๐Ÿผโ€โ™€๏ธ Woman Detective: Medium-Light Skin U+1F575, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿ•ต๐Ÿฝโ€โ™€๏ธ Woman Detective: Medium Skin Tone U+1F575, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ•ต๐Ÿพโ€โ™€๏ธ Woman Detective: Medium-Dark Skin Tone U+1F575, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿ•ต๐Ÿฟโ€โ™€๏ธ Woman Detective: Dark Skin Tone U+1F575, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ’‚ Guard U+1F482 +๐Ÿ’‚๐Ÿป Guard: Light Skin Tone U+1F482, U+1F3FB +๐Ÿ’‚๐Ÿผ Guard: Medium-Light Skin Tone U+1F482, U+1F3FC +๐Ÿ’‚๐Ÿฝ Guard: Medium Skin Tone U+1F482, U+1F3FD +๐Ÿ’‚๐Ÿพ Guard: Medium-Dark Skin Tone U+1F482, U+1F3FE +๐Ÿ’‚๐Ÿฟ Guard: Dark Skin Tone U+1F482, U+1F3FF +๐Ÿ’‚โ€โ™‚๏ธ Man Guard U+1F482, U+200D, U+2642, U+FE0F +๐Ÿ’‚๐Ÿปโ€โ™‚๏ธ Man Guard: Light Skin Tone U+1F482, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ’‚๐Ÿผโ€โ™‚๏ธ Man Guard: Medium-Light Skin Tone U+1F482, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿ’‚๐Ÿฝโ€โ™‚๏ธ Man Guard: Medium Skin Tone U+1F482, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ’‚๐Ÿพโ€โ™‚๏ธ Man Guard: Medium-Dark Skin Tone U+1F482, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿ’‚๐Ÿฟโ€โ™‚๏ธ Man Guard: Dark Skin Tone U+1F482, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ’‚โ€โ™€๏ธ Woman Guard U+1F482, U+200D, U+2640, U+FE0F +๐Ÿ’‚๐Ÿปโ€โ™€๏ธ Woman Guard: Light Skin Tone U+1F482, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ’‚๐Ÿผโ€โ™€๏ธ Woman Guard: Medium-Light Skin Tone U+1F482, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿ’‚๐Ÿฝโ€โ™€๏ธ Woman Guard: Medium Skin Tone U+1F482, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ’‚๐Ÿพโ€โ™€๏ธ Woman Guard: Medium-Dark Skin Tone U+1F482, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿ’‚๐Ÿฟโ€โ™€๏ธ Woman Guard: Dark Skin Tone U+1F482, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿฅท Ninja U+1F977 +๐Ÿฅท๐Ÿป Ninja: Light Skin Tone U+1F977, U+1F3FB +๐Ÿฅท๐Ÿผ Ninja: Medium-Light Skin Tone U+1F977, U+1F3FC +๐Ÿฅท๐Ÿฝ Ninja: Medium Skin Tone U+1F977, U+1F3FD +๐Ÿฅท๐Ÿพ Ninja: Medium-Dark Skin Tone U+1F977, U+1F3FE +๐Ÿฅท๐Ÿฟ Ninja: Dark Skin Tone U+1F977, U+1F3FF +๐Ÿ‘ท Construction Worker U+1F477 +๐Ÿ‘ท๐Ÿป Construction Worker: Light Skin Tone U+1F477, U+1F3FB +๐Ÿ‘ท๐Ÿผ Construction Worker: Medium-Light Skin U+1F477, U+1F3FC +Tone +๐Ÿ‘ท๐Ÿฝ Construction Worker: Medium Skin Tone U+1F477, U+1F3FD +๐Ÿ‘ท๐Ÿพ Construction Worker: Medium-Dark Skin U+1F477, U+1F3FE +Tone +๐Ÿ‘ท๐Ÿฟ Construction Worker: Dark Skin Tone U+1F477, U+1F3FF +๐Ÿ‘ทโ€โ™‚๏ธ Man Construction Worker U+1F477, U+200D, U+2642, U+FE0F +๐Ÿ‘ท๐Ÿปโ€โ™‚๏ธ Man Construction Worker: Light Skin U+1F477, U+1F3FB, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‘ท๐Ÿผโ€โ™‚๏ธ Man Construction Worker: Medium-Light U+1F477, U+1F3FC, U+200D, U+2642, +Skin Tone U+FE0F +๐Ÿ‘ท๐Ÿฝโ€โ™‚๏ธ Man Construction Worker: Medium Skin U+1F477, U+1F3FD, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‘ท๐Ÿพโ€โ™‚๏ธ Man Construction Worker: Medium-Dark U+1F477, U+1F3FE, U+200D, U+2642, +Skin Tone U+FE0F +๐Ÿ‘ท๐Ÿฟโ€โ™‚๏ธ Man Construction Worker: Dark Skin U+1F477, U+1F3FF, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‘ทโ€โ™€๏ธ Woman Construction Worker U+1F477, U+200D, U+2640, U+FE0F +๐Ÿ‘ท๐Ÿปโ€โ™€๏ธ Woman Construction Worker: Light Skin U+1F477, U+1F3FB, U+200D, U+2640, +Tone U+FE0F +๐Ÿ‘ท๐Ÿผโ€โ™€๏ธ Woman Construction Worker: U+1F477, U+1F3FC, U+200D, U+2640, +Medium-Light Skin Tone U+FE0F +๐Ÿ‘ท๐Ÿฝโ€โ™€๏ธ Woman Construction Worker: Medium Skin U+1F477, U+1F3FD, U+200D, U+2640, +Tone U+FE0F +๐Ÿ‘ท๐Ÿพโ€โ™€๏ธ Woman Construction Worker: Medium-Dark U+1F477, U+1F3FE, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ‘ท๐Ÿฟโ€โ™€๏ธ Woman Construction Worker: Dark Skin U+1F477, U+1F3FF, U+200D, U+2640, +Tone U+FE0F +๐Ÿคด Prince U+1F934 +๐Ÿคด๐Ÿป Prince: Light Skin Tone U+1F934, U+1F3FB +๐Ÿคด๐Ÿผ Prince: Medium-Light Skin Tone U+1F934, U+1F3FC +๐Ÿคด๐Ÿฝ Prince: Medium Skin Tone U+1F934, U+1F3FD +๐Ÿคด๐Ÿพ Prince: Medium-Dark Skin Tone U+1F934, U+1F3FE +๐Ÿคด๐Ÿฟ Prince: Dark Skin Tone U+1F934, U+1F3FF +๐Ÿ‘ธ Princess U+1F478 +๐Ÿ‘ธ๐Ÿป Princess: Light Skin Tone U+1F478, U+1F3FB +๐Ÿ‘ธ๐Ÿผ Princess: Medium-Light Skin Tone U+1F478, U+1F3FC +๐Ÿ‘ธ๐Ÿฝ Princess: Medium Skin Tone U+1F478, U+1F3FD +๐Ÿ‘ธ๐Ÿพ Princess: Medium-Dark Skin Tone U+1F478, U+1F3FE +๐Ÿ‘ธ๐Ÿฟ Princess: Dark Skin Tone U+1F478, U+1F3FF +๐Ÿ‘ณ Person Wearing Turban U+1F473 +๐Ÿ‘ณ๐Ÿป Person Wearing Turban: Light Skin Tone U+1F473, U+1F3FB +๐Ÿ‘ณ๐Ÿผ Person Wearing Turban: Medium-Light Skin U+1F473, U+1F3FC +Tone +๐Ÿ‘ณ๐Ÿฝ Person Wearing Turban: Medium Skin Tone U+1F473, U+1F3FD +๐Ÿ‘ณ๐Ÿพ Person Wearing Turban: Medium-Dark Skin U+1F473, U+1F3FE +Tone +๐Ÿ‘ณ๐Ÿฟ Person Wearing Turban: Dark Skin Tone U+1F473, U+1F3FF +๐Ÿ‘ณโ€โ™‚๏ธ Man Wearing Turban U+1F473, U+200D, U+2642, U+FE0F +๐Ÿ‘ณ๐Ÿปโ€โ™‚๏ธ Man Wearing Turban: Light Skin Tone U+1F473, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ‘ณ๐Ÿผโ€โ™‚๏ธ Man Wearing Turban: Medium-Light Skin U+1F473, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‘ณ๐Ÿฝโ€โ™‚๏ธ Man Wearing Turban: Medium Skin Tone U+1F473, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ‘ณ๐Ÿพโ€โ™‚๏ธ Man Wearing Turban: Medium-Dark Skin U+1F473, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‘ณ๐Ÿฟโ€โ™‚๏ธ Man Wearing Turban: Dark Skin Tone U+1F473, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ‘ณโ€โ™€๏ธ Woman Wearing Turban U+1F473, U+200D, U+2640, U+FE0F +๐Ÿ‘ณ๐Ÿปโ€โ™€๏ธ Woman Wearing Turban: Light Skin Tone U+1F473, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ‘ณ๐Ÿผโ€โ™€๏ธ Woman Wearing Turban: Medium-Light U+1F473, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ‘ณ๐Ÿฝโ€โ™€๏ธ Woman Wearing Turban: Medium Skin Tone U+1F473, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ‘ณ๐Ÿพโ€โ™€๏ธ Woman Wearing Turban: Medium-Dark Skin U+1F473, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿ‘ณ๐Ÿฟโ€โ™€๏ธ Woman Wearing Turban: Dark Skin Tone U+1F473, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฒ Person With Skullcap U+1F472 +๐Ÿ‘ฒ๐Ÿป Person With Skullcap: Light Skin Tone U+1F472, U+1F3FB +๐Ÿ‘ฒ๐Ÿผ Person With Skullcap: Medium-Light Skin U+1F472, U+1F3FC +Tone +๐Ÿ‘ฒ๐Ÿฝ Person With Skullcap: Medium Skin Tone U+1F472, U+1F3FD +๐Ÿ‘ฒ๐Ÿพ Person With Skullcap: Medium-Dark Skin U+1F472, U+1F3FE +Tone +๐Ÿ‘ฒ๐Ÿฟ Person With Skullcap: Dark Skin Tone U+1F472, U+1F3FF +๐Ÿง• Woman with Headscarf U+1F9D5 +๐Ÿง•๐Ÿป Woman with Headscarf: Light Skin Tone U+1F9D5, U+1F3FB +๐Ÿง•๐Ÿผ Woman with Headscarf: Medium-Light Skin U+1F9D5, U+1F3FC +Tone +๐Ÿง•๐Ÿฝ Woman with Headscarf: Medium Skin Tone U+1F9D5, U+1F3FD +๐Ÿง•๐Ÿพ Woman with Headscarf: Medium-Dark Skin U+1F9D5, U+1F3FE +Tone +๐Ÿง•๐Ÿฟ Woman with Headscarf: Dark Skin Tone U+1F9D5, U+1F3FF +๐Ÿคต Person in Tuxedo U+1F935 +๐Ÿคต๐Ÿป Person in Tuxedo: Light Skin Tone U+1F935, U+1F3FB +๐Ÿคต๐Ÿผ Person in Tuxedo: Medium-Light Skin Tone U+1F935, U+1F3FC +๐Ÿคต๐Ÿฝ Person in Tuxedo: Medium Skin Tone U+1F935, U+1F3FD +๐Ÿคต๐Ÿพ Person in Tuxedo: Medium-Dark Skin Tone U+1F935, U+1F3FE +๐Ÿคต๐Ÿฟ Person in Tuxedo: Dark Skin Tone U+1F935, U+1F3FF +๐Ÿคตโ€โ™‚๏ธ Man in Tuxedo U+1F935, U+200D, U+2642, U+FE0F +๐Ÿคต๐Ÿปโ€โ™‚๏ธ Man in Tuxedo: Light Skin Tone U+1F935, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿคต๐Ÿผโ€โ™‚๏ธ Man in Tuxedo: Medium-Light Skin Tone U+1F935, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿคต๐Ÿฝโ€โ™‚๏ธ Man in Tuxedo: Medium Skin Tone U+1F935, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿคต๐Ÿพโ€โ™‚๏ธ Man in Tuxedo: Medium-Dark Skin Tone U+1F935, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿคต๐Ÿฟโ€โ™‚๏ธ Man in Tuxedo: Dark Skin Tone U+1F935, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿคตโ€โ™€๏ธ Woman in Tuxedo U+1F935, U+200D, U+2640, U+FE0F +๐Ÿคต๐Ÿปโ€โ™€๏ธ Woman in Tuxedo: Light Skin Tone U+1F935, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿคต๐Ÿผโ€โ™€๏ธ Woman in Tuxedo: Medium-Light Skin U+1F935, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿคต๐Ÿฝโ€โ™€๏ธ Woman in Tuxedo: Medium Skin Tone U+1F935, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿคต๐Ÿพโ€โ™€๏ธ Woman in Tuxedo: Medium-Dark Skin Tone U+1F935, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿคต๐Ÿฟโ€โ™€๏ธ Woman in Tuxedo: Dark Skin Tone U+1F935, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฐ Person With Veil U+1F470 +๐Ÿ‘ฐ๐Ÿป Person With Veil: Light Skin Tone U+1F470, U+1F3FB +๐Ÿ‘ฐ๐Ÿผ Person With Veil: Medium-Light Skin Tone U+1F470, U+1F3FC +๐Ÿ‘ฐ๐Ÿฝ Person With Veil: Medium Skin Tone U+1F470, U+1F3FD +๐Ÿ‘ฐ๐Ÿพ Person With Veil: Medium-Dark Skin Tone U+1F470, U+1F3FE +๐Ÿ‘ฐ๐Ÿฟ Person With Veil: Dark Skin Tone U+1F470, U+1F3FF +๐Ÿ‘ฐโ€โ™‚๏ธ Man with Veil U+1F470, U+200D, U+2642, U+FE0F +๐Ÿ‘ฐ๐Ÿปโ€โ™‚๏ธ Man with Veil: Light Skin Tone U+1F470, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฐ๐Ÿผโ€โ™‚๏ธ Man with Veil: Medium-Light Skin Tone U+1F470, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฐ๐Ÿฝโ€โ™‚๏ธ Man with Veil: Medium Skin Tone U+1F470, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฐ๐Ÿพโ€โ™‚๏ธ Man with Veil: Medium-Dark Skin Tone U+1F470, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฐ๐Ÿฟโ€โ™‚๏ธ Man with Veil: Dark Skin Tone U+1F470, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฐโ€โ™€๏ธ Woman with Veil U+1F470, U+200D, U+2640, U+FE0F +๐Ÿ‘ฐ๐Ÿปโ€โ™€๏ธ Woman with Veil: Light Skin Tone U+1F470, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฐ๐Ÿผโ€โ™€๏ธ Woman with Veil: Medium-Light Skin U+1F470, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿ‘ฐ๐Ÿฝโ€โ™€๏ธ Woman with Veil: Medium Skin Tone U+1F470, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฐ๐Ÿพโ€โ™€๏ธ Woman with Veil: Medium-Dark Skin Tone U+1F470, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿ‘ฐ๐Ÿฟโ€โ™€๏ธ Woman with Veil: Dark Skin Tone U+1F470, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿคฐ Pregnant Woman U+1F930 +๐Ÿคฐ๐Ÿป Pregnant Woman: Light Skin Tone U+1F930, U+1F3FB +๐Ÿคฐ๐Ÿผ Pregnant Woman: Medium-Light Skin Tone U+1F930, U+1F3FC +๐Ÿคฐ๐Ÿฝ Pregnant Woman: Medium Skin Tone U+1F930, U+1F3FD +๐Ÿคฐ๐Ÿพ Pregnant Woman: Medium-Dark Skin Tone U+1F930, U+1F3FE +๐Ÿคฐ๐Ÿฟ Pregnant Woman: Dark Skin Tone U+1F930, U+1F3FF +๐Ÿคฑ Breast-Feeding U+1F931 +๐Ÿคฑ๐Ÿป Breast-Feeding: Light Skin Tone U+1F931, U+1F3FB +๐Ÿคฑ๐Ÿผ Breast-Feeding: Medium-Light Skin Tone U+1F931, U+1F3FC +๐Ÿคฑ๐Ÿฝ Breast-Feeding: Medium Skin Tone U+1F931, U+1F3FD +๐Ÿคฑ๐Ÿพ Breast-Feeding: Medium-Dark Skin Tone U+1F931, U+1F3FE +๐Ÿคฑ๐Ÿฟ Breast-Feeding: Dark Skin Tone U+1F931, U+1F3FF +๐Ÿ‘ฉโ€๐Ÿผ Woman Feeding Baby U+1F469, U+200D, U+1F37C +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿผ Woman Feeding Baby: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F37C +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿผ Woman Feeding Baby: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F37C +Tone +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿผ Woman Feeding Baby: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F37C +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿผ Woman Feeding Baby: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F37C +Tone +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿผ Woman Feeding Baby: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F37C +๐Ÿ‘จโ€๐Ÿผ Man Feeding Baby U+1F468, U+200D, U+1F37C +๐Ÿ‘จ๐Ÿปโ€๐Ÿผ Man Feeding Baby: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F37C +๐Ÿ‘จ๐Ÿผโ€๐Ÿผ Man Feeding Baby: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F37C +Tone +๐Ÿ‘จ๐Ÿฝโ€๐Ÿผ Man Feeding Baby: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F37C +๐Ÿ‘จ๐Ÿพโ€๐Ÿผ Man Feeding Baby: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F37C +๐Ÿ‘จ๐Ÿฟโ€๐Ÿผ Man Feeding Baby: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F37C +๐Ÿง‘โ€๐Ÿผ Person Feeding Baby U+1F9D1, U+200D, U+1F37C +๐Ÿง‘๐Ÿปโ€๐Ÿผ Person Feeding Baby: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F37C +๐Ÿง‘๐Ÿผโ€๐Ÿผ Person Feeding Baby: Medium-Light Skin U+1F9D1, U+1F3FC, U+200D, U+1F37C +Tone +๐Ÿง‘๐Ÿฝโ€๐Ÿผ Person Feeding Baby: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F37C +๐Ÿง‘๐Ÿพโ€๐Ÿผ Person Feeding Baby: Medium-Dark Skin U+1F9D1, U+1F3FE, U+200D, U+1F37C +Tone +๐Ÿง‘๐Ÿฟโ€๐Ÿผ Person Feeding Baby: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F37C +๐Ÿ‘ผ Baby Angel U+1F47C +๐Ÿ‘ผ๐Ÿป Baby Angel: Light Skin Tone U+1F47C, U+1F3FB +๐Ÿ‘ผ๐Ÿผ Baby Angel: Medium-Light Skin Tone U+1F47C, U+1F3FC +๐Ÿ‘ผ๐Ÿฝ Baby Angel: Medium Skin Tone U+1F47C, U+1F3FD +๐Ÿ‘ผ๐Ÿพ Baby Angel: Medium-Dark Skin Tone U+1F47C, U+1F3FE +๐Ÿ‘ผ๐Ÿฟ Baby Angel: Dark Skin Tone U+1F47C, U+1F3FF +๐ŸŽ… Santa Claus U+1F385 +๐ŸŽ…๐Ÿป Santa Claus: Light Skin Tone U+1F385, U+1F3FB +๐ŸŽ…๐Ÿผ Santa Claus: Medium-Light Skin Tone U+1F385, U+1F3FC +๐ŸŽ…๐Ÿฝ Santa Claus: Medium Skin Tone U+1F385, U+1F3FD +๐ŸŽ…๐Ÿพ Santa Claus: Medium-Dark Skin Tone U+1F385, U+1F3FE +๐ŸŽ…๐Ÿฟ Santa Claus: Dark Skin Tone U+1F385, U+1F3FF +๐Ÿคถ Mrs. Claus U+1F936 +๐Ÿคถ๐Ÿป Mrs. Claus: Light Skin Tone U+1F936, U+1F3FB +๐Ÿคถ๐Ÿผ Mrs. Claus: Medium-Light Skin Tone U+1F936, U+1F3FC +๐Ÿคถ๐Ÿฝ Mrs. Claus: Medium Skin Tone U+1F936, U+1F3FD +๐Ÿคถ๐Ÿพ Mrs. Claus: Medium-Dark Skin Tone U+1F936, U+1F3FE +๐Ÿคถ๐Ÿฟ Mrs. Claus: Dark Skin Tone U+1F936, U+1F3FF +๐Ÿง‘โ€๐ŸŽ„ Mx Claus U+1F9D1, U+200D, U+1F384 +๐Ÿง‘๐Ÿปโ€๐ŸŽ„ Mx Claus: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F384 +๐Ÿง‘๐Ÿผโ€๐ŸŽ„ Mx Claus: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F384 +๐Ÿง‘๐Ÿฝโ€๐ŸŽ„ Mx Claus: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F384 +๐Ÿง‘๐Ÿพโ€๐ŸŽ„ Mx Claus: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F384 +๐Ÿง‘๐Ÿฟโ€๐ŸŽ„ Mx Claus: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F384 +๐Ÿฆธ Superhero U+1F9B8 +๐Ÿฆธ๐Ÿป Superhero: Light Skin Tone U+1F9B8, U+1F3FB +๐Ÿฆธ๐Ÿผ Superhero: Medium-Light Skin Tone U+1F9B8, U+1F3FC +๐Ÿฆธ๐Ÿฝ Superhero: Medium Skin Tone U+1F9B8, U+1F3FD +๐Ÿฆธ๐Ÿพ Superhero: Medium-Dark Skin Tone U+1F9B8, U+1F3FE +๐Ÿฆธ๐Ÿฟ Superhero: Dark Skin Tone U+1F9B8, U+1F3FF +๐Ÿฆธโ€โ™‚๏ธ Man Superhero U+1F9B8, U+200D, U+2642, U+FE0F +๐Ÿฆธ๐Ÿปโ€โ™‚๏ธ Man Superhero: Light Skin Tone U+1F9B8, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿฆธ๐Ÿผโ€โ™‚๏ธ Man Superhero: Medium-Light Skin Tone U+1F9B8, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿฆธ๐Ÿฝโ€โ™‚๏ธ Man Superhero: Medium Skin Tone U+1F9B8, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿฆธ๐Ÿพโ€โ™‚๏ธ Man Superhero: Medium-Dark Skin Tone U+1F9B8, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿฆธ๐Ÿฟโ€โ™‚๏ธ Man Superhero: Dark Skin Tone U+1F9B8, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿฆธโ€โ™€๏ธ Woman Superhero U+1F9B8, U+200D, U+2640, U+FE0F +๐Ÿฆธ๐Ÿปโ€โ™€๏ธ Woman Superhero: Light Skin Tone U+1F9B8, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿฆธ๐Ÿผโ€โ™€๏ธ Woman Superhero: Medium-Light Skin U+1F9B8, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿฆธ๐Ÿฝโ€โ™€๏ธ Woman Superhero: Medium Skin Tone U+1F9B8, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿฆธ๐Ÿพโ€โ™€๏ธ Woman Superhero: Medium-Dark Skin Tone U+1F9B8, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿฆธ๐Ÿฟโ€โ™€๏ธ Woman Superhero: Dark Skin Tone U+1F9B8, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿฆน Supervillain U+1F9B9 +๐Ÿฆน๐Ÿป Supervillain: Light Skin Tone U+1F9B9, U+1F3FB +๐Ÿฆน๐Ÿผ Supervillain: Medium-Light Skin Tone U+1F9B9, U+1F3FC +๐Ÿฆน๐Ÿฝ Supervillain: Medium Skin Tone U+1F9B9, U+1F3FD +๐Ÿฆน๐Ÿพ Supervillain: Medium-Dark Skin Tone U+1F9B9, U+1F3FE +๐Ÿฆน๐Ÿฟ Supervillain: Dark Skin Tone U+1F9B9, U+1F3FF +๐Ÿฆนโ€โ™‚๏ธ Man Supervillain U+1F9B9, U+200D, U+2642, U+FE0F +๐Ÿฆน๐Ÿปโ€โ™‚๏ธ Man Supervillain: Light Skin Tone U+1F9B9, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿฆน๐Ÿผโ€โ™‚๏ธ Man Supervillain: Medium-Light Skin U+1F9B9, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿฆน๐Ÿฝโ€โ™‚๏ธ Man Supervillain: Medium Skin Tone U+1F9B9, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿฆน๐Ÿพโ€โ™‚๏ธ Man Supervillain: Medium-Dark Skin U+1F9B9, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿฆน๐Ÿฟโ€โ™‚๏ธ Man Supervillain: Dark Skin Tone U+1F9B9, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿฆนโ€โ™€๏ธ Woman Supervillain U+1F9B9, U+200D, U+2640, U+FE0F +๐Ÿฆน๐Ÿปโ€โ™€๏ธ Woman Supervillain: Light Skin Tone U+1F9B9, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿฆน๐Ÿผโ€โ™€๏ธ Woman Supervillain: Medium-Light Skin U+1F9B9, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿฆน๐Ÿฝโ€โ™€๏ธ Woman Supervillain: Medium Skin Tone U+1F9B9, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿฆน๐Ÿพโ€โ™€๏ธ Woman Supervillain: Medium-Dark Skin U+1F9B9, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿฆน๐Ÿฟโ€โ™€๏ธ Woman Supervillain: Dark Skin Tone U+1F9B9, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿง™ Mage U+1F9D9 +๐Ÿง™๐Ÿป Mage: Light Skin Tone U+1F9D9, U+1F3FB +๐Ÿง™๐Ÿผ Mage: Medium-Light Skin Tone U+1F9D9, U+1F3FC +๐Ÿง™๐Ÿฝ Mage: Medium Skin Tone U+1F9D9, U+1F3FD +๐Ÿง™๐Ÿพ Mage: Medium-Dark Skin Tone U+1F9D9, U+1F3FE +๐Ÿง™๐Ÿฟ Mage: Dark Skin Tone U+1F9D9, U+1F3FF +๐Ÿง™โ€โ™‚๏ธ Man Mage U+1F9D9, U+200D, U+2642, U+FE0F +๐Ÿง™๐Ÿปโ€โ™‚๏ธ Man Mage: Light Skin Tone U+1F9D9, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿง™๐Ÿผโ€โ™‚๏ธ Man Mage: Medium-Light Skin Tone U+1F9D9, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿง™๐Ÿฝโ€โ™‚๏ธ Man Mage: Medium Skin Tone U+1F9D9, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿง™๐Ÿพโ€โ™‚๏ธ Man Mage: Medium-Dark Skin Tone U+1F9D9, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿง™๐Ÿฟโ€โ™‚๏ธ Man Mage: Dark Skin Tone U+1F9D9, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿง™โ€โ™€๏ธ Woman Mage U+1F9D9, U+200D, U+2640, U+FE0F +๐Ÿง™๐Ÿปโ€โ™€๏ธ Woman Mage: Light Skin Tone U+1F9D9, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿง™๐Ÿผโ€โ™€๏ธ Woman Mage: Medium-Light Skin Tone U+1F9D9, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿง™๐Ÿฝโ€โ™€๏ธ Woman Mage: Medium Skin Tone U+1F9D9, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿง™๐Ÿพโ€โ™€๏ธ Woman Mage: Medium-Dark Skin Tone U+1F9D9, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿง™๐Ÿฟโ€โ™€๏ธ Woman Mage: Dark Skin Tone U+1F9D9, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿงš Fairy U+1F9DA +๐Ÿงš๐Ÿป Fairy: Light Skin Tone U+1F9DA, U+1F3FB +๐Ÿงš๐Ÿผ Fairy: Medium-Light Skin Tone U+1F9DA, U+1F3FC +๐Ÿงš๐Ÿฝ Fairy: Medium Skin Tone U+1F9DA, U+1F3FD +๐Ÿงš๐Ÿพ Fairy: Medium-Dark Skin Tone U+1F9DA, U+1F3FE +๐Ÿงš๐Ÿฟ Fairy: Dark Skin Tone U+1F9DA, U+1F3FF +๐Ÿงšโ€โ™‚๏ธ Man Fairy U+1F9DA, U+200D, U+2642, U+FE0F +๐Ÿงš๐Ÿปโ€โ™‚๏ธ Man Fairy: Light Skin Tone U+1F9DA, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿงš๐Ÿผโ€โ™‚๏ธ Man Fairy: Medium-Light Skin Tone U+1F9DA, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿงš๐Ÿฝโ€โ™‚๏ธ Man Fairy: Medium Skin Tone U+1F9DA, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿงš๐Ÿพโ€โ™‚๏ธ Man Fairy: Medium-Dark Skin Tone U+1F9DA, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿงš๐Ÿฟโ€โ™‚๏ธ Man Fairy: Dark Skin Tone U+1F9DA, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿงšโ€โ™€๏ธ Woman Fairy U+1F9DA, U+200D, U+2640, U+FE0F +๐Ÿงš๐Ÿปโ€โ™€๏ธ Woman Fairy: Light Skin Tone U+1F9DA, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿงš๐Ÿผโ€โ™€๏ธ Woman Fairy: Medium-Light Skin Tone U+1F9DA, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿงš๐Ÿฝโ€โ™€๏ธ Woman Fairy: Medium Skin Tone U+1F9DA, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿงš๐Ÿพโ€โ™€๏ธ Woman Fairy: Medium-Dark Skin Tone U+1F9DA, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿงš๐Ÿฟโ€โ™€๏ธ Woman Fairy: Dark Skin Tone U+1F9DA, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿง› Vampire U+1F9DB +๐Ÿง›๐Ÿป Vampire: Light Skin Tone U+1F9DB, U+1F3FB +๐Ÿง›๐Ÿผ Vampire: Medium-Light Skin Tone U+1F9DB, U+1F3FC +๐Ÿง›๐Ÿฝ Vampire: Medium Skin Tone U+1F9DB, U+1F3FD +๐Ÿง›๐Ÿพ Vampire: Medium-Dark Skin Tone U+1F9DB, U+1F3FE +๐Ÿง›๐Ÿฟ Vampire: Dark Skin Tone U+1F9DB, U+1F3FF +๐Ÿง›โ€โ™‚๏ธ Man Vampire U+1F9DB, U+200D, U+2642, U+FE0F +๐Ÿง›๐Ÿปโ€โ™‚๏ธ Man Vampire: Light Skin Tone U+1F9DB, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿง›๐Ÿผโ€โ™‚๏ธ Man Vampire: Medium-Light Skin Tone U+1F9DB, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿง›๐Ÿฝโ€โ™‚๏ธ Man Vampire: Medium Skin Tone U+1F9DB, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿง›๐Ÿพโ€โ™‚๏ธ Man Vampire: Medium-Dark Skin Tone U+1F9DB, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿง›๐Ÿฟโ€โ™‚๏ธ Man Vampire: Dark Skin Tone U+1F9DB, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿง›โ€โ™€๏ธ Woman Vampire U+1F9DB, U+200D, U+2640, U+FE0F +๐Ÿง›๐Ÿปโ€โ™€๏ธ Woman Vampire: Light Skin Tone U+1F9DB, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿง›๐Ÿผโ€โ™€๏ธ Woman Vampire: Medium-Light Skin Tone U+1F9DB, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿง›๐Ÿฝโ€โ™€๏ธ Woman Vampire: Medium Skin Tone U+1F9DB, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿง›๐Ÿพโ€โ™€๏ธ Woman Vampire: Medium-Dark Skin Tone U+1F9DB, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿง›๐Ÿฟโ€โ™€๏ธ Woman Vampire: Dark Skin Tone U+1F9DB, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿงœ Merperson U+1F9DC +๐Ÿงœ๐Ÿป Merperson: Light Skin Tone U+1F9DC, U+1F3FB +๐Ÿงœ๐Ÿผ Merperson: Medium-Light Skin Tone U+1F9DC, U+1F3FC +๐Ÿงœ๐Ÿฝ Merperson: Medium Skin Tone U+1F9DC, U+1F3FD +๐Ÿงœ๐Ÿพ Merperson: Medium-Dark Skin Tone U+1F9DC, U+1F3FE +๐Ÿงœ๐Ÿฟ Merperson: Dark Skin Tone U+1F9DC, U+1F3FF +๐Ÿงœโ€โ™‚๏ธ Merman U+1F9DC, U+200D, U+2642, U+FE0F +๐Ÿงœ๐Ÿปโ€โ™‚๏ธ Merman: Light Skin Tone U+1F9DC, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿงœ๐Ÿผโ€โ™‚๏ธ Merman: Medium-Light Skin Tone U+1F9DC, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿงœ๐Ÿฝโ€โ™‚๏ธ Merman: Medium Skin Tone U+1F9DC, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿงœ๐Ÿพโ€โ™‚๏ธ Merman: Medium-Dark Skin Tone U+1F9DC, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿงœ๐Ÿฟโ€โ™‚๏ธ Merman: Dark Skin Tone U+1F9DC, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿงœโ€โ™€๏ธ Mermaid U+1F9DC, U+200D, U+2640, U+FE0F +๐Ÿงœ๐Ÿปโ€โ™€๏ธ Mermaid: Light Skin Tone U+1F9DC, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿงœ๐Ÿผโ€โ™€๏ธ Mermaid: Medium-Light Skin Tone U+1F9DC, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿงœ๐Ÿฝโ€โ™€๏ธ Mermaid: Medium Skin Tone U+1F9DC, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿงœ๐Ÿพโ€โ™€๏ธ Mermaid: Medium-Dark Skin Tone U+1F9DC, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿงœ๐Ÿฟโ€โ™€๏ธ Mermaid: Dark Skin Tone U+1F9DC, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿง Elf U+1F9DD +๐Ÿง๐Ÿป Elf: Light Skin Tone U+1F9DD, U+1F3FB +๐Ÿง๐Ÿผ Elf: Medium-Light Skin Tone U+1F9DD, U+1F3FC +๐Ÿง๐Ÿฝ Elf: Medium Skin Tone U+1F9DD, U+1F3FD +๐Ÿง๐Ÿพ Elf: Medium-Dark Skin Tone U+1F9DD, U+1F3FE +๐Ÿง๐Ÿฟ Elf: Dark Skin Tone U+1F9DD, U+1F3FF +๐Ÿงโ€โ™‚๏ธ Man Elf U+1F9DD, U+200D, U+2642, U+FE0F +๐Ÿง๐Ÿปโ€โ™‚๏ธ Man Elf: Light Skin Tone U+1F9DD, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿผโ€โ™‚๏ธ Man Elf: Medium-Light Skin Tone U+1F9DD, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿฝโ€โ™‚๏ธ Man Elf: Medium Skin Tone U+1F9DD, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿพโ€โ™‚๏ธ Man Elf: Medium-Dark Skin Tone U+1F9DD, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿฟโ€โ™‚๏ธ Man Elf: Dark Skin Tone U+1F9DD, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿงโ€โ™€๏ธ Woman Elf U+1F9DD, U+200D, U+2640, U+FE0F +๐Ÿง๐Ÿปโ€โ™€๏ธ Woman Elf: Light Skin Tone U+1F9DD, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿผโ€โ™€๏ธ Woman Elf: Medium-Light Skin Tone U+1F9DD, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿฝโ€โ™€๏ธ Woman Elf: Medium Skin Tone U+1F9DD, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿพโ€โ™€๏ธ Woman Elf: Medium-Dark Skin Tone U+1F9DD, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿฟโ€โ™€๏ธ Woman Elf: Dark Skin Tone U+1F9DD, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿงž Genie U+1F9DE +๐Ÿงžโ€โ™‚๏ธ Man Genie U+1F9DE, U+200D, U+2642, U+FE0F +๐Ÿงžโ€โ™€๏ธ Woman Genie U+1F9DE, U+200D, U+2640, U+FE0F +๐ŸงŸ Zombie U+1F9DF +๐ŸงŸโ€โ™‚๏ธ Man Zombie U+1F9DF, U+200D, U+2642, U+FE0F +๐ŸงŸโ€โ™€๏ธ Woman Zombie U+1F9DF, U+200D, U+2640, U+FE0F +๐Ÿ’† Person Getting Massage U+1F486 +๐Ÿ’†๐Ÿป Person Getting Massage: Light Skin Tone U+1F486, U+1F3FB +๐Ÿ’†๐Ÿผ Person Getting Massage: Medium-Light Skin U+1F486, U+1F3FC +Tone +๐Ÿ’†๐Ÿฝ Person Getting Massage: Medium Skin Tone U+1F486, U+1F3FD +๐Ÿ’†๐Ÿพ Person Getting Massage: Medium-Dark Skin U+1F486, U+1F3FE +Tone +๐Ÿ’†๐Ÿฟ Person Getting Massage: Dark Skin Tone U+1F486, U+1F3FF +๐Ÿ’†โ€โ™‚๏ธ Man Getting Massage U+1F486, U+200D, U+2642, U+FE0F +๐Ÿ’†๐Ÿปโ€โ™‚๏ธ Man Getting Massage: Light Skin Tone U+1F486, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ’†๐Ÿผโ€โ™‚๏ธ Man Getting Massage: Medium-Light Skin U+1F486, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿ’†๐Ÿฝโ€โ™‚๏ธ Man Getting Massage: Medium Skin Tone U+1F486, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ’†๐Ÿพโ€โ™‚๏ธ Man Getting Massage: Medium-Dark Skin U+1F486, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿ’†๐Ÿฟโ€โ™‚๏ธ Man Getting Massage: Dark Skin Tone U+1F486, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ’†โ€โ™€๏ธ Woman Getting Massage U+1F486, U+200D, U+2640, U+FE0F +๐Ÿ’†๐Ÿปโ€โ™€๏ธ Woman Getting Massage: Light Skin Tone U+1F486, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ’†๐Ÿผโ€โ™€๏ธ Woman Getting Massage: Medium-Light U+1F486, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ’†๐Ÿฝโ€โ™€๏ธ Woman Getting Massage: Medium Skin U+1F486, U+1F3FD, U+200D, U+2640, +Tone U+FE0F +๐Ÿ’†๐Ÿพโ€โ™€๏ธ Woman Getting Massage: Medium-Dark U+1F486, U+1F3FE, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ’†๐Ÿฟโ€โ™€๏ธ Woman Getting Massage: Dark Skin Tone U+1F486, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ’‡ Person Getting Haircut U+1F487 +๐Ÿ’‡๐Ÿป Person Getting Haircut: Light Skin Tone U+1F487, U+1F3FB +๐Ÿ’‡๐Ÿผ Person Getting Haircut: Medium-Light Skin U+1F487, U+1F3FC +Tone +๐Ÿ’‡๐Ÿฝ Person Getting Haircut: Medium Skin Tone U+1F487, U+1F3FD +๐Ÿ’‡๐Ÿพ Person Getting Haircut: Medium-Dark Skin U+1F487, U+1F3FE +Tone +๐Ÿ’‡๐Ÿฟ Person Getting Haircut: Dark Skin Tone U+1F487, U+1F3FF +๐Ÿ’‡โ€โ™‚๏ธ Man Getting Haircut U+1F487, U+200D, U+2642, U+FE0F +๐Ÿ’‡๐Ÿปโ€โ™‚๏ธ Man Getting Haircut: Light Skin Tone U+1F487, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ’‡๐Ÿผโ€โ™‚๏ธ Man Getting Haircut: Medium-Light Skin U+1F487, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿ’‡๐Ÿฝโ€โ™‚๏ธ Man Getting Haircut: Medium Skin Tone U+1F487, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ’‡๐Ÿพโ€โ™‚๏ธ Man Getting Haircut: Medium-Dark Skin U+1F487, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿ’‡๐Ÿฟโ€โ™‚๏ธ Man Getting Haircut: Dark Skin Tone U+1F487, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ’‡โ€โ™€๏ธ Woman Getting Haircut U+1F487, U+200D, U+2640, U+FE0F +๐Ÿ’‡๐Ÿปโ€โ™€๏ธ Woman Getting Haircut: Light Skin Tone U+1F487, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ’‡๐Ÿผโ€โ™€๏ธ Woman Getting Haircut: Medium-Light U+1F487, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ’‡๐Ÿฝโ€โ™€๏ธ Woman Getting Haircut: Medium Skin U+1F487, U+1F3FD, U+200D, U+2640, +Tone U+FE0F +๐Ÿ’‡๐Ÿพโ€โ™€๏ธ Woman Getting Haircut: Medium-Dark U+1F487, U+1F3FE, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ’‡๐Ÿฟโ€โ™€๏ธ Woman Getting Haircut: Dark Skin Tone U+1F487, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿšถ Person Walking U+1F6B6 +๐Ÿšถ๐Ÿป Person Walking: Light Skin Tone U+1F6B6, U+1F3FB +๐Ÿšถ๐Ÿผ Person Walking: Medium-Light Skin Tone U+1F6B6, U+1F3FC +๐Ÿšถ๐Ÿฝ Person Walking: Medium Skin Tone U+1F6B6, U+1F3FD +๐Ÿšถ๐Ÿพ Person Walking: Medium-Dark Skin Tone U+1F6B6, U+1F3FE +๐Ÿšถ๐Ÿฟ Person Walking: Dark Skin Tone U+1F6B6, U+1F3FF +๐Ÿšถโ€โ™‚๏ธ Man Walking U+1F6B6, U+200D, U+2642, U+FE0F +๐Ÿšถ๐Ÿปโ€โ™‚๏ธ Man Walking: Light Skin Tone U+1F6B6, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿšถ๐Ÿผโ€โ™‚๏ธ Man Walking: Medium-Light Skin Tone U+1F6B6, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿšถ๐Ÿฝโ€โ™‚๏ธ Man Walking: Medium Skin Tone U+1F6B6, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿšถ๐Ÿพโ€โ™‚๏ธ Man Walking: Medium-Dark Skin Tone U+1F6B6, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿšถ๐Ÿฟโ€โ™‚๏ธ Man Walking: Dark Skin Tone U+1F6B6, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿšถโ€โ™€๏ธ Woman Walking U+1F6B6, U+200D, U+2640, U+FE0F +๐Ÿšถ๐Ÿปโ€โ™€๏ธ Woman Walking: Light Skin Tone U+1F6B6, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿšถ๐Ÿผโ€โ™€๏ธ Woman Walking: Medium-Light Skin Tone U+1F6B6, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿšถ๐Ÿฝโ€โ™€๏ธ Woman Walking: Medium Skin Tone U+1F6B6, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿšถ๐Ÿพโ€โ™€๏ธ Woman Walking: Medium-Dark Skin Tone U+1F6B6, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿšถ๐Ÿฟโ€โ™€๏ธ Woman Walking: Dark Skin Tone U+1F6B6, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿง Person Standing U+1F9CD +๐Ÿง๐Ÿป Person Standing: Light Skin Tone U+1F9CD, U+1F3FB +๐Ÿง๐Ÿผ Person Standing: Medium-Light Skin Tone U+1F9CD, U+1F3FC +๐Ÿง๐Ÿฝ Person Standing: Medium Skin Tone U+1F9CD, U+1F3FD +๐Ÿง๐Ÿพ Person Standing: Medium-Dark Skin Tone U+1F9CD, U+1F3FE +๐Ÿง๐Ÿฟ Person Standing: Dark Skin Tone U+1F9CD, U+1F3FF +๐Ÿงโ€โ™‚๏ธ Man Standing U+1F9CD, U+200D, U+2642, U+FE0F +๐Ÿง๐Ÿปโ€โ™‚๏ธ Man Standing: Light Skin Tone U+1F9CD, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿผโ€โ™‚๏ธ Man Standing: Medium-Light Skin Tone U+1F9CD, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿฝโ€โ™‚๏ธ Man Standing: Medium Skin Tone U+1F9CD, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿพโ€โ™‚๏ธ Man Standing: Medium-Dark Skin Tone U+1F9CD, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿง๐Ÿฟโ€โ™‚๏ธ Man Standing: Dark Skin Tone U+1F9CD, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿงโ€โ™€๏ธ Woman Standing U+1F9CD, U+200D, U+2640, U+FE0F +๐Ÿง๐Ÿปโ€โ™€๏ธ Woman Standing: Light Skin Tone U+1F9CD, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿผโ€โ™€๏ธ Woman Standing: Medium-Light Skin Tone U+1F9CD, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿฝโ€โ™€๏ธ Woman Standing: Medium Skin Tone U+1F9CD, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿพโ€โ™€๏ธ Woman Standing: Medium-Dark Skin Tone U+1F9CD, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿง๐Ÿฟโ€โ™€๏ธ Woman Standing: Dark Skin Tone U+1F9CD, U+1F3FF, U+200D, U+2640, + U+FE0F +๐ŸงŽ Person Kneeling U+1F9CE +๐ŸงŽ๐Ÿป Person Kneeling: Light Skin Tone U+1F9CE, U+1F3FB +๐ŸงŽ๐Ÿผ Person Kneeling: Medium-Light Skin Tone U+1F9CE, U+1F3FC +๐ŸงŽ๐Ÿฝ Person Kneeling: Medium Skin Tone U+1F9CE, U+1F3FD +๐ŸงŽ๐Ÿพ Person Kneeling: Medium-Dark Skin Tone U+1F9CE, U+1F3FE +๐ŸงŽ๐Ÿฟ Person Kneeling: Dark Skin Tone U+1F9CE, U+1F3FF +๐ŸงŽโ€โ™‚๏ธ Man Kneeling U+1F9CE, U+200D, U+2642, U+FE0F +๐ŸงŽ๐Ÿปโ€โ™‚๏ธ Man Kneeling: Light Skin Tone U+1F9CE, U+1F3FB, U+200D, U+2642, + U+FE0F +๐ŸงŽ๐Ÿผโ€โ™‚๏ธ Man Kneeling: Medium-Light Skin Tone U+1F9CE, U+1F3FC, U+200D, U+2642, + U+FE0F +๐ŸงŽ๐Ÿฝโ€โ™‚๏ธ Man Kneeling: Medium Skin Tone U+1F9CE, U+1F3FD, U+200D, U+2642, + U+FE0F +๐ŸงŽ๐Ÿพโ€โ™‚๏ธ Man Kneeling: Medium-Dark Skin Tone U+1F9CE, U+1F3FE, U+200D, U+2642, + U+FE0F +๐ŸงŽ๐Ÿฟโ€โ™‚๏ธ Man Kneeling: Dark Skin Tone U+1F9CE, U+1F3FF, U+200D, U+2642, + U+FE0F +๐ŸงŽโ€โ™€๏ธ Woman Kneeling U+1F9CE, U+200D, U+2640, U+FE0F +๐ŸงŽ๐Ÿปโ€โ™€๏ธ Woman Kneeling: Light Skin Tone U+1F9CE, U+1F3FB, U+200D, U+2640, + U+FE0F +๐ŸงŽ๐Ÿผโ€โ™€๏ธ Woman Kneeling: Medium-Light Skin Tone U+1F9CE, U+1F3FC, U+200D, U+2640, + U+FE0F +๐ŸงŽ๐Ÿฝโ€โ™€๏ธ Woman Kneeling: Medium Skin Tone U+1F9CE, U+1F3FD, U+200D, U+2640, + U+FE0F +๐ŸงŽ๐Ÿพโ€โ™€๏ธ Woman Kneeling: Medium-Dark Skin Tone U+1F9CE, U+1F3FE, U+200D, U+2640, + U+FE0F +๐ŸงŽ๐Ÿฟโ€โ™€๏ธ Woman Kneeling: Dark Skin Tone U+1F9CE, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿง‘โ€๐Ÿฆฏ Person with White Cane U+1F9D1, U+200D, U+1F9AF +๐Ÿง‘๐Ÿปโ€๐Ÿฆฏ Person with White Cane: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F9AF +๐Ÿง‘๐Ÿผโ€๐Ÿฆฏ Person with White Cane: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F9AF +Skin Tone +๐Ÿง‘๐Ÿฝโ€๐Ÿฆฏ Person with White Cane: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F9AF +Tone +๐Ÿง‘๐Ÿพโ€๐Ÿฆฏ Person with White Cane: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F9AF +Skin Tone +๐Ÿง‘๐Ÿฟโ€๐Ÿฆฏ Person with White Cane: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F9AF +๐Ÿ‘จโ€๐Ÿฆฏ Man with White Cane U+1F468, U+200D, U+1F9AF +๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฏ Man with White Cane: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F9AF +๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฏ Man with White Cane: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F9AF +Tone +๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฏ Man with White Cane: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F9AF +๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฏ Man with White Cane: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F9AF +Tone +๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฏ Man with White Cane: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F9AF +๐Ÿ‘ฉโ€๐Ÿฆฏ Woman with White Cane U+1F469, U+200D, U+1F9AF +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฏ Woman with White Cane: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F9AF +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฏ Woman with White Cane: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F9AF +Skin Tone +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฏ Woman with White Cane: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F9AF +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฏ Woman with White Cane: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F9AF +Tone +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฏ Woman with White Cane: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F9AF +๐Ÿง‘โ€๐Ÿฆผ Person in Motorized Wheelchair U+1F9D1, U+200D, U+1F9BC +๐Ÿง‘๐Ÿปโ€๐Ÿฆผ Person in Motorized Wheelchair: Light U+1F9D1, U+1F3FB, U+200D, U+1F9BC +Skin Tone +๐Ÿง‘๐Ÿผโ€๐Ÿฆผ Person in Motorized Wheelchair: U+1F9D1, U+1F3FC, U+200D, U+1F9BC +Medium-Light Skin Tone +๐Ÿง‘๐Ÿฝโ€๐Ÿฆผ Person in Motorized Wheelchair: Medium U+1F9D1, U+1F3FD, U+200D, U+1F9BC +Skin Tone +๐Ÿง‘๐Ÿพโ€๐Ÿฆผ Person in Motorized Wheelchair: U+1F9D1, U+1F3FE, U+200D, U+1F9BC +Medium-Dark Skin Tone +๐Ÿง‘๐Ÿฟโ€๐Ÿฆผ Person in Motorized Wheelchair: Dark U+1F9D1, U+1F3FF, U+200D, U+1F9BC +Skin Tone +๐Ÿ‘จโ€๐Ÿฆผ Man in Motorized Wheelchair U+1F468, U+200D, U+1F9BC +๐Ÿ‘จ๐Ÿปโ€๐Ÿฆผ Man in Motorized Wheelchair: Light Skin U+1F468, U+1F3FB, U+200D, U+1F9BC +Tone +๐Ÿ‘จ๐Ÿผโ€๐Ÿฆผ Man in Motorized Wheelchair: U+1F468, U+1F3FC, U+200D, U+1F9BC +Medium-Light Skin Tone +๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆผ Man in Motorized Wheelchair: Medium U+1F468, U+1F3FD, U+200D, U+1F9BC +Skin Tone +๐Ÿ‘จ๐Ÿพโ€๐Ÿฆผ Man in Motorized Wheelchair: U+1F468, U+1F3FE, U+200D, U+1F9BC +Medium-Dark Skin Tone +๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆผ Man in Motorized Wheelchair: Dark Skin U+1F468, U+1F3FF, U+200D, U+1F9BC +Tone +๐Ÿ‘ฉโ€๐Ÿฆผ Woman in Motorized Wheelchair U+1F469, U+200D, U+1F9BC +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆผ Woman in Motorized Wheelchair: Light U+1F469, U+1F3FB, U+200D, U+1F9BC +Skin Tone +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆผ Woman in Motorized Wheelchair: U+1F469, U+1F3FC, U+200D, U+1F9BC +Medium-Light Skin Tone +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆผ Woman in Motorized Wheelchair: Medium U+1F469, U+1F3FD, U+200D, U+1F9BC +Skin Tone +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆผ Woman in Motorized Wheelchair: U+1F469, U+1F3FE, U+200D, U+1F9BC +Medium-Dark Skin Tone +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆผ Woman in Motorized Wheelchair: Dark U+1F469, U+1F3FF, U+200D, U+1F9BC +Skin Tone +๐Ÿง‘โ€๐Ÿฆฝ Person in Manual Wheelchair U+1F9D1, U+200D, U+1F9BD +๐Ÿง‘๐Ÿปโ€๐Ÿฆฝ Person in Manual Wheelchair: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F9BD +Tone +๐Ÿง‘๐Ÿผโ€๐Ÿฆฝ Person in Manual Wheelchair: U+1F9D1, U+1F3FC, U+200D, U+1F9BD +Medium-Light Skin Tone +๐Ÿง‘๐Ÿฝโ€๐Ÿฆฝ Person in Manual Wheelchair: Medium U+1F9D1, U+1F3FD, U+200D, U+1F9BD +Skin Tone +๐Ÿง‘๐Ÿพโ€๐Ÿฆฝ Person in Manual Wheelchair: U+1F9D1, U+1F3FE, U+200D, U+1F9BD +Medium-Dark Skin Tone +๐Ÿง‘๐Ÿฟโ€๐Ÿฆฝ Person in Manual Wheelchair: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F9BD +Tone +๐Ÿ‘จโ€๐Ÿฆฝ Man in Manual Wheelchair U+1F468, U+200D, U+1F9BD +๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฝ Man in Manual Wheelchair: Light Skin U+1F468, U+1F3FB, U+200D, U+1F9BD +Tone +๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฝ Man in Manual Wheelchair: Medium-Light U+1F468, U+1F3FC, U+200D, U+1F9BD +Skin Tone +๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฝ Man in Manual Wheelchair: Medium Skin U+1F468, U+1F3FD, U+200D, U+1F9BD +Tone +๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฝ Man in Manual Wheelchair: Medium-Dark U+1F468, U+1F3FE, U+200D, U+1F9BD +Skin Tone +๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฝ Man in Manual Wheelchair: Dark Skin U+1F468, U+1F3FF, U+200D, U+1F9BD +Tone +๐Ÿ‘ฉโ€๐Ÿฆฝ Woman in Manual Wheelchair U+1F469, U+200D, U+1F9BD +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฝ Woman in Manual Wheelchair: Light Skin U+1F469, U+1F3FB, U+200D, U+1F9BD +Tone +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฝ Woman in Manual Wheelchair: U+1F469, U+1F3FC, U+200D, U+1F9BD +Medium-Light Skin Tone +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฝ Woman in Manual Wheelchair: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F9BD +Tone +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฝ Woman in Manual Wheelchair: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F9BD +Skin Tone +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฝ Woman in Manual Wheelchair: Dark Skin U+1F469, U+1F3FF, U+200D, U+1F9BD +Tone +๐Ÿƒ Person Running U+1F3C3 +๐Ÿƒ๐Ÿป Person Running: Light Skin Tone U+1F3C3, U+1F3FB +๐Ÿƒ๐Ÿผ Person Running: Medium-Light Skin Tone U+1F3C3, U+1F3FC +๐Ÿƒ๐Ÿฝ Person Running: Medium Skin Tone U+1F3C3, U+1F3FD +๐Ÿƒ๐Ÿพ Person Running: Medium-Dark Skin Tone U+1F3C3, U+1F3FE +๐Ÿƒ๐Ÿฟ Person Running: Dark Skin Tone U+1F3C3, U+1F3FF +๐Ÿƒโ€โ™‚๏ธ Man Running U+1F3C3, U+200D, U+2642, U+FE0F +๐Ÿƒ๐Ÿปโ€โ™‚๏ธ Man Running: Light Skin Tone U+1F3C3, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿƒ๐Ÿผโ€โ™‚๏ธ Man Running: Medium-Light Skin Tone U+1F3C3, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿƒ๐Ÿฝโ€โ™‚๏ธ Man Running: Medium Skin Tone U+1F3C3, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿƒ๐Ÿพโ€โ™‚๏ธ Man Running: Medium-Dark Skin Tone U+1F3C3, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿƒ๐Ÿฟโ€โ™‚๏ธ Man Running: Dark Skin Tone U+1F3C3, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿƒโ€โ™€๏ธ Woman Running U+1F3C3, U+200D, U+2640, U+FE0F +๐Ÿƒ๐Ÿปโ€โ™€๏ธ Woman Running: Light Skin Tone U+1F3C3, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿƒ๐Ÿผโ€โ™€๏ธ Woman Running: Medium-Light Skin Tone U+1F3C3, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿƒ๐Ÿฝโ€โ™€๏ธ Woman Running: Medium Skin Tone U+1F3C3, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿƒ๐Ÿพโ€โ™€๏ธ Woman Running: Medium-Dark Skin Tone U+1F3C3, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿƒ๐Ÿฟโ€โ™€๏ธ Woman Running: Dark Skin Tone U+1F3C3, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ’ƒ Woman Dancing U+1F483 +๐Ÿ’ƒ๐Ÿป Woman Dancing: Light Skin Tone U+1F483, U+1F3FB +๐Ÿ’ƒ๐Ÿผ Woman Dancing: Medium-Light Skin Tone U+1F483, U+1F3FC +๐Ÿ’ƒ๐Ÿฝ Woman Dancing: Medium Skin Tone U+1F483, U+1F3FD +๐Ÿ’ƒ๐Ÿพ Woman Dancing: Medium-Dark Skin Tone U+1F483, U+1F3FE +๐Ÿ’ƒ๐Ÿฟ Woman Dancing: Dark Skin Tone U+1F483, U+1F3FF +๐Ÿ•บ Man Dancing U+1F57A +๐Ÿ•บ๐Ÿป Man Dancing: Light Skin Tone U+1F57A, U+1F3FB +๐Ÿ•บ๐Ÿผ Man Dancing: Medium-Light Skin Tone U+1F57A, U+1F3FC +๐Ÿ•บ๐Ÿฝ Man Dancing: Medium Skin Tone U+1F57A, U+1F3FD +๐Ÿ•บ๐Ÿพ Man Dancing: Medium-Dark Skin Tone U+1F57A, U+1F3FE +๐Ÿ•บ๐Ÿฟ Man Dancing: Dark Skin Tone U+1F57A, U+1F3FF +๐Ÿ•ด๏ธ Person in Suit Levitating U+1F574, U+FE0F +๐Ÿ•ด๐Ÿป Person in Suit Levitating: Light Skin U+1F574, U+1F3FB +Tone +๐Ÿ•ด๐Ÿผ Person in Suit Levitating: Medium-Light U+1F574, U+1F3FC +Skin Tone +๐Ÿ•ด๐Ÿฝ Person in Suit Levitating: Medium Skin U+1F574, U+1F3FD +Tone +๐Ÿ•ด๐Ÿพ Person in Suit Levitating: Medium-Dark U+1F574, U+1F3FE +Skin Tone +๐Ÿ•ด๐Ÿฟ Person in Suit Levitating: Dark Skin Tone U+1F574, U+1F3FF +๐Ÿ‘ฏ People with Bunny Ears U+1F46F +๐Ÿ‘ฏโ€โ™‚๏ธ Men with Bunny Ears U+1F46F, U+200D, U+2642, U+FE0F +๐Ÿ‘ฏโ€โ™€๏ธ Women with Bunny Ears U+1F46F, U+200D, U+2640, U+FE0F +๐Ÿง– Person in Steamy Room U+1F9D6 +๐Ÿง–๐Ÿป Person in Steamy Room: Light Skin Tone U+1F9D6, U+1F3FB +๐Ÿง–๐Ÿผ Person in Steamy Room: Medium-Light Skin U+1F9D6, U+1F3FC +Tone +๐Ÿง–๐Ÿฝ Person in Steamy Room: Medium Skin Tone U+1F9D6, U+1F3FD +๐Ÿง–๐Ÿพ Person in Steamy Room: Medium-Dark Skin U+1F9D6, U+1F3FE +Tone +๐Ÿง–๐Ÿฟ Person in Steamy Room: Dark Skin Tone U+1F9D6, U+1F3FF +๐Ÿง–โ€โ™‚๏ธ Man in Steamy Room U+1F9D6, U+200D, U+2642, U+FE0F +๐Ÿง–๐Ÿปโ€โ™‚๏ธ Man in Steamy Room: Light Skin Tone U+1F9D6, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿง–๐Ÿผโ€โ™‚๏ธ Man in Steamy Room: Medium-Light Skin U+1F9D6, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿง–๐Ÿฝโ€โ™‚๏ธ Man in Steamy Room: Medium Skin Tone U+1F9D6, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿง–๐Ÿพโ€โ™‚๏ธ Man in Steamy Room: Medium-Dark Skin U+1F9D6, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿง–๐Ÿฟโ€โ™‚๏ธ Man in Steamy Room: Dark Skin Tone U+1F9D6, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿง–โ€โ™€๏ธ Woman in Steamy Room U+1F9D6, U+200D, U+2640, U+FE0F +๐Ÿง–๐Ÿปโ€โ™€๏ธ Woman in Steamy Room: Light Skin Tone U+1F9D6, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿง–๐Ÿผโ€โ™€๏ธ Woman in Steamy Room: Medium-Light U+1F9D6, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿง–๐Ÿฝโ€โ™€๏ธ Woman in Steamy Room: Medium Skin Tone U+1F9D6, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿง–๐Ÿพโ€โ™€๏ธ Woman in Steamy Room: Medium-Dark Skin U+1F9D6, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿง–๐Ÿฟโ€โ™€๏ธ Woman in Steamy Room: Dark Skin Tone U+1F9D6, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿง— Person Climbing U+1F9D7 +๐Ÿง—๐Ÿป Person Climbing: Light Skin Tone U+1F9D7, U+1F3FB +๐Ÿง—๐Ÿผ Person Climbing: Medium-Light Skin Tone U+1F9D7, U+1F3FC +๐Ÿง—๐Ÿฝ Person Climbing: Medium Skin Tone U+1F9D7, U+1F3FD +๐Ÿง—๐Ÿพ Person Climbing: Medium-Dark Skin Tone U+1F9D7, U+1F3FE +๐Ÿง—๐Ÿฟ Person Climbing: Dark Skin Tone U+1F9D7, U+1F3FF +๐Ÿง—โ€โ™‚๏ธ Man Climbing U+1F9D7, U+200D, U+2642, U+FE0F +๐Ÿง—๐Ÿปโ€โ™‚๏ธ Man Climbing: Light Skin Tone U+1F9D7, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿง—๐Ÿผโ€โ™‚๏ธ Man Climbing: Medium-Light Skin Tone U+1F9D7, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿง—๐Ÿฝโ€โ™‚๏ธ Man Climbing: Medium Skin Tone U+1F9D7, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿง—๐Ÿพโ€โ™‚๏ธ Man Climbing: Medium-Dark Skin Tone U+1F9D7, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿง—๐Ÿฟโ€โ™‚๏ธ Man Climbing: Dark Skin Tone U+1F9D7, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿง—โ€โ™€๏ธ Woman Climbing U+1F9D7, U+200D, U+2640, U+FE0F +๐Ÿง—๐Ÿปโ€โ™€๏ธ Woman Climbing: Light Skin Tone U+1F9D7, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿง—๐Ÿผโ€โ™€๏ธ Woman Climbing: Medium-Light Skin Tone U+1F9D7, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿง—๐Ÿฝโ€โ™€๏ธ Woman Climbing: Medium Skin Tone U+1F9D7, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿง—๐Ÿพโ€โ™€๏ธ Woman Climbing: Medium-Dark Skin Tone U+1F9D7, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿง—๐Ÿฟโ€โ™€๏ธ Woman Climbing: Dark Skin Tone U+1F9D7, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿคบ Person Fencing U+1F93A +๐Ÿ‡ Horse Racing U+1F3C7 +๐Ÿ‡๐Ÿป Horse Racing: Light Skin Tone U+1F3C7, U+1F3FB +๐Ÿ‡๐Ÿผ Horse Racing: Medium-Light Skin Tone U+1F3C7, U+1F3FC +๐Ÿ‡๐Ÿฝ Horse Racing: Medium Skin Tone U+1F3C7, U+1F3FD +๐Ÿ‡๐Ÿพ Horse Racing: Medium-Dark Skin Tone U+1F3C7, U+1F3FE +๐Ÿ‡๐Ÿฟ Horse Racing: Dark Skin Tone U+1F3C7, U+1F3FF +โ›ท๏ธ Skier U+26F7, U+FE0F +๐Ÿ‚ Snowboarder U+1F3C2 +๐Ÿ‚๐Ÿป Snowboarder: Light Skin Tone U+1F3C2, U+1F3FB +๐Ÿ‚๐Ÿผ Snowboarder: Medium-Light Skin Tone U+1F3C2, U+1F3FC +๐Ÿ‚๐Ÿฝ Snowboarder: Medium Skin Tone U+1F3C2, U+1F3FD +๐Ÿ‚๐Ÿพ Snowboarder: Medium-Dark Skin Tone U+1F3C2, U+1F3FE +๐Ÿ‚๐Ÿฟ Snowboarder: Dark Skin Tone U+1F3C2, U+1F3FF +๐ŸŒ๏ธ Person Golfing U+1F3CC, U+FE0F +๐ŸŒ๐Ÿป Person Golfing: Light Skin Tone U+1F3CC, U+1F3FB +๐ŸŒ๐Ÿผ Person Golfing: Medium-Light Skin Tone U+1F3CC, U+1F3FC +๐ŸŒ๐Ÿฝ Person Golfing: Medium Skin Tone U+1F3CC, U+1F3FD +๐ŸŒ๐Ÿพ Person Golfing: Medium-Dark Skin Tone U+1F3CC, U+1F3FE +๐ŸŒ๐Ÿฟ Person Golfing: Dark Skin Tone U+1F3CC, U+1F3FF +๐ŸŒ๏ธโ€โ™‚๏ธ Man Golfing U+1F3CC, U+FE0F, U+200D, U+2642, + U+FE0F +๐ŸŒ๐Ÿปโ€โ™‚๏ธ Man Golfing: Light Skin Tone U+1F3CC, U+1F3FB, U+200D, U+2642, + U+FE0F +๐ŸŒ๐Ÿผโ€โ™‚๏ธ Man Golfing: Medium-Light Skin Tone U+1F3CC, U+1F3FC, U+200D, U+2642, + U+FE0F +๐ŸŒ๐Ÿฝโ€โ™‚๏ธ Man Golfing: Medium Skin Tone U+1F3CC, U+1F3FD, U+200D, U+2642, + U+FE0F +๐ŸŒ๐Ÿพโ€โ™‚๏ธ Man Golfing: Medium-Dark Skin Tone U+1F3CC, U+1F3FE, U+200D, U+2642, + U+FE0F +๐ŸŒ๐Ÿฟโ€โ™‚๏ธ Man Golfing: Dark Skin Tone U+1F3CC, U+1F3FF, U+200D, U+2642, + U+FE0F +๐ŸŒ๏ธโ€โ™€๏ธ Woman Golfing U+1F3CC, U+FE0F, U+200D, U+2640, + U+FE0F +๐ŸŒ๐Ÿปโ€โ™€๏ธ Woman Golfing: Light Skin Tone U+1F3CC, U+1F3FB, U+200D, U+2640, + U+FE0F +๐ŸŒ๐Ÿผโ€โ™€๏ธ Woman Golfing: Medium-Light Skin Tone U+1F3CC, U+1F3FC, U+200D, U+2640, + U+FE0F +๐ŸŒ๐Ÿฝโ€โ™€๏ธ Woman Golfing: Medium Skin Tone U+1F3CC, U+1F3FD, U+200D, U+2640, + U+FE0F +๐ŸŒ๐Ÿพโ€โ™€๏ธ Woman Golfing: Medium-Dark Skin Tone U+1F3CC, U+1F3FE, U+200D, U+2640, + U+FE0F +๐ŸŒ๐Ÿฟโ€โ™€๏ธ Woman Golfing: Dark Skin Tone U+1F3CC, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ„ Person Surfing U+1F3C4 +๐Ÿ„๐Ÿป Person Surfing: Light Skin Tone U+1F3C4, U+1F3FB +๐Ÿ„๐Ÿผ Person Surfing: Medium-Light Skin Tone U+1F3C4, U+1F3FC +๐Ÿ„๐Ÿฝ Person Surfing: Medium Skin Tone U+1F3C4, U+1F3FD +๐Ÿ„๐Ÿพ Person Surfing: Medium-Dark Skin Tone U+1F3C4, U+1F3FE +๐Ÿ„๐Ÿฟ Person Surfing: Dark Skin Tone U+1F3C4, U+1F3FF +๐Ÿ„โ€โ™‚๏ธ Man Surfing U+1F3C4, U+200D, U+2642, U+FE0F +๐Ÿ„๐Ÿปโ€โ™‚๏ธ Man Surfing: Light Skin Tone U+1F3C4, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ„๐Ÿผโ€โ™‚๏ธ Man Surfing: Medium-Light Skin Tone U+1F3C4, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿ„๐Ÿฝโ€โ™‚๏ธ Man Surfing: Medium Skin Tone U+1F3C4, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ„๐Ÿพโ€โ™‚๏ธ Man Surfing: Medium-Dark Skin Tone U+1F3C4, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿ„๐Ÿฟโ€โ™‚๏ธ Man Surfing: Dark Skin Tone U+1F3C4, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ„โ€โ™€๏ธ Woman Surfing U+1F3C4, U+200D, U+2640, U+FE0F +๐Ÿ„๐Ÿปโ€โ™€๏ธ Woman Surfing: Light Skin Tone U+1F3C4, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ„๐Ÿผโ€โ™€๏ธ Woman Surfing: Medium-Light Skin Tone U+1F3C4, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿ„๐Ÿฝโ€โ™€๏ธ Woman Surfing: Medium Skin Tone U+1F3C4, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿ„๐Ÿพโ€โ™€๏ธ Woman Surfing: Medium-Dark Skin Tone U+1F3C4, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿ„๐Ÿฟโ€โ™€๏ธ Woman Surfing: Dark Skin Tone U+1F3C4, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿšฃ Person Rowing Boat U+1F6A3 +๐Ÿšฃ๐Ÿป Person Rowing Boat: Light Skin Tone U+1F6A3, U+1F3FB +๐Ÿšฃ๐Ÿผ Person Rowing Boat: Medium-Light Skin U+1F6A3, U+1F3FC +Tone +๐Ÿšฃ๐Ÿฝ Person Rowing Boat: Medium Skin Tone U+1F6A3, U+1F3FD +๐Ÿšฃ๐Ÿพ Person Rowing Boat: Medium-Dark Skin Tone U+1F6A3, U+1F3FE +๐Ÿšฃ๐Ÿฟ Person Rowing Boat: Dark Skin Tone U+1F6A3, U+1F3FF +๐Ÿšฃโ€โ™‚๏ธ Man Rowing Boat U+1F6A3, U+200D, U+2642, U+FE0F +๐Ÿšฃ๐Ÿปโ€โ™‚๏ธ Man Rowing Boat: Light Skin Tone U+1F6A3, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿšฃ๐Ÿผโ€โ™‚๏ธ Man Rowing Boat: Medium-Light Skin U+1F6A3, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿšฃ๐Ÿฝโ€โ™‚๏ธ Man Rowing Boat: Medium Skin Tone U+1F6A3, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿšฃ๐Ÿพโ€โ™‚๏ธ Man Rowing Boat: Medium-Dark Skin Tone U+1F6A3, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿšฃ๐Ÿฟโ€โ™‚๏ธ Man Rowing Boat: Dark Skin Tone U+1F6A3, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿšฃโ€โ™€๏ธ Woman Rowing Boat U+1F6A3, U+200D, U+2640, U+FE0F +๐Ÿšฃ๐Ÿปโ€โ™€๏ธ Woman Rowing Boat: Light Skin Tone U+1F6A3, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿšฃ๐Ÿผโ€โ™€๏ธ Woman Rowing Boat: Medium-Light Skin U+1F6A3, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿšฃ๐Ÿฝโ€โ™€๏ธ Woman Rowing Boat: Medium Skin Tone U+1F6A3, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿšฃ๐Ÿพโ€โ™€๏ธ Woman Rowing Boat: Medium-Dark Skin U+1F6A3, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿšฃ๐Ÿฟโ€โ™€๏ธ Woman Rowing Boat: Dark Skin Tone U+1F6A3, U+1F3FF, U+200D, U+2640, + U+FE0F +๐ŸŠ Person Swimming U+1F3CA +๐ŸŠ๐Ÿป Person Swimming: Light Skin Tone U+1F3CA, U+1F3FB +๐ŸŠ๐Ÿผ Person Swimming: Medium-Light Skin Tone U+1F3CA, U+1F3FC +๐ŸŠ๐Ÿฝ Person Swimming: Medium Skin Tone U+1F3CA, U+1F3FD +๐ŸŠ๐Ÿพ Person Swimming: Medium-Dark Skin Tone U+1F3CA, U+1F3FE +๐ŸŠ๐Ÿฟ Person Swimming: Dark Skin Tone U+1F3CA, U+1F3FF +๐ŸŠโ€โ™‚๏ธ Man Swimming U+1F3CA, U+200D, U+2642, U+FE0F +๐ŸŠ๐Ÿปโ€โ™‚๏ธ Man Swimming: Light Skin Tone U+1F3CA, U+1F3FB, U+200D, U+2642, + U+FE0F +๐ŸŠ๐Ÿผโ€โ™‚๏ธ Man Swimming: Medium-Light Skin Tone U+1F3CA, U+1F3FC, U+200D, U+2642, + U+FE0F +๐ŸŠ๐Ÿฝโ€โ™‚๏ธ Man Swimming: Medium Skin Tone U+1F3CA, U+1F3FD, U+200D, U+2642, + U+FE0F +๐ŸŠ๐Ÿพโ€โ™‚๏ธ Man Swimming: Medium-Dark Skin Tone U+1F3CA, U+1F3FE, U+200D, U+2642, + U+FE0F +๐ŸŠ๐Ÿฟโ€โ™‚๏ธ Man Swimming: Dark Skin Tone U+1F3CA, U+1F3FF, U+200D, U+2642, + U+FE0F +๐ŸŠโ€โ™€๏ธ Woman Swimming U+1F3CA, U+200D, U+2640, U+FE0F +๐ŸŠ๐Ÿปโ€โ™€๏ธ Woman Swimming: Light Skin Tone U+1F3CA, U+1F3FB, U+200D, U+2640, + U+FE0F +๐ŸŠ๐Ÿผโ€โ™€๏ธ Woman Swimming: Medium-Light Skin Tone U+1F3CA, U+1F3FC, U+200D, U+2640, + U+FE0F +๐ŸŠ๐Ÿฝโ€โ™€๏ธ Woman Swimming: Medium Skin Tone U+1F3CA, U+1F3FD, U+200D, U+2640, + U+FE0F +๐ŸŠ๐Ÿพโ€โ™€๏ธ Woman Swimming: Medium-Dark Skin Tone U+1F3CA, U+1F3FE, U+200D, U+2640, + U+FE0F +๐ŸŠ๐Ÿฟโ€โ™€๏ธ Woman Swimming: Dark Skin Tone U+1F3CA, U+1F3FF, U+200D, U+2640, + U+FE0F +โ›น๏ธ Person Bouncing Ball U+26F9, U+FE0F +โ›น๐Ÿป Person Bouncing Ball: Light Skin Tone U+26F9, U+1F3FB +โ›น๐Ÿผ Person Bouncing Ball: Medium-Light Skin U+26F9, U+1F3FC +Tone +โ›น๐Ÿฝ Person Bouncing Ball: Medium Skin Tone U+26F9, U+1F3FD +โ›น๐Ÿพ Person Bouncing Ball: Medium-Dark Skin U+26F9, U+1F3FE +Tone +โ›น๐Ÿฟ Person Bouncing Ball: Dark Skin Tone U+26F9, U+1F3FF +โ›น๏ธโ€โ™‚๏ธ Man Bouncing Ball U+26F9, U+FE0F, U+200D, U+2642, + U+FE0F +โ›น๐Ÿปโ€โ™‚๏ธ Man Bouncing Ball: Light Skin Tone U+26F9, U+1F3FB, U+200D, U+2642, + U+FE0F +โ›น๐Ÿผโ€โ™‚๏ธ Man Bouncing Ball: Medium-Light Skin U+26F9, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +โ›น๐Ÿฝโ€โ™‚๏ธ Man Bouncing Ball: Medium Skin Tone U+26F9, U+1F3FD, U+200D, U+2642, + U+FE0F +โ›น๐Ÿพโ€โ™‚๏ธ Man Bouncing Ball: Medium-Dark Skin U+26F9, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +โ›น๐Ÿฟโ€โ™‚๏ธ Man Bouncing Ball: Dark Skin Tone U+26F9, U+1F3FF, U+200D, U+2642, + U+FE0F +โ›น๏ธโ€โ™€๏ธ Woman Bouncing Ball U+26F9, U+FE0F, U+200D, U+2640, + U+FE0F +โ›น๐Ÿปโ€โ™€๏ธ Woman Bouncing Ball: Light Skin Tone U+26F9, U+1F3FB, U+200D, U+2640, + U+FE0F +โ›น๐Ÿผโ€โ™€๏ธ Woman Bouncing Ball: Medium-Light Skin U+26F9, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +โ›น๐Ÿฝโ€โ™€๏ธ Woman Bouncing Ball: Medium Skin Tone U+26F9, U+1F3FD, U+200D, U+2640, + U+FE0F +โ›น๐Ÿพโ€โ™€๏ธ Woman Bouncing Ball: Medium-Dark Skin U+26F9, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +โ›น๐Ÿฟโ€โ™€๏ธ Woman Bouncing Ball: Dark Skin Tone U+26F9, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿ‹๏ธ Person Lifting Weights U+1F3CB, U+FE0F +๐Ÿ‹๐Ÿป Person Lifting Weights: Light Skin Tone U+1F3CB, U+1F3FB +๐Ÿ‹๐Ÿผ Person Lifting Weights: Medium-Light Skin U+1F3CB, U+1F3FC +Tone +๐Ÿ‹๐Ÿฝ Person Lifting Weights: Medium Skin Tone U+1F3CB, U+1F3FD +๐Ÿ‹๐Ÿพ Person Lifting Weights: Medium-Dark Skin U+1F3CB, U+1F3FE +Tone +๐Ÿ‹๐Ÿฟ Person Lifting Weights: Dark Skin Tone U+1F3CB, U+1F3FF +๐Ÿ‹๏ธโ€โ™‚๏ธ Man Lifting Weights U+1F3CB, U+FE0F, U+200D, U+2642, + U+FE0F +๐Ÿ‹๐Ÿปโ€โ™‚๏ธ Man Lifting Weights: Light Skin Tone U+1F3CB, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿ‹๐Ÿผโ€โ™‚๏ธ Man Lifting Weights: Medium-Light Skin U+1F3CB, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‹๐Ÿฝโ€โ™‚๏ธ Man Lifting Weights: Medium Skin Tone U+1F3CB, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿ‹๐Ÿพโ€โ™‚๏ธ Man Lifting Weights: Medium-Dark Skin U+1F3CB, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‹๐Ÿฟโ€โ™‚๏ธ Man Lifting Weights: Dark Skin Tone U+1F3CB, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ‹๏ธโ€โ™€๏ธ Woman Lifting Weights U+1F3CB, U+FE0F, U+200D, U+2640, + U+FE0F +๐Ÿ‹๐Ÿปโ€โ™€๏ธ Woman Lifting Weights: Light Skin Tone U+1F3CB, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿ‹๐Ÿผโ€โ™€๏ธ Woman Lifting Weights: Medium-Light U+1F3CB, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ‹๐Ÿฝโ€โ™€๏ธ Woman Lifting Weights: Medium Skin U+1F3CB, U+1F3FD, U+200D, U+2640, +Tone U+FE0F +๐Ÿ‹๐Ÿพโ€โ™€๏ธ Woman Lifting Weights: Medium-Dark U+1F3CB, U+1F3FE, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ‹๐Ÿฟโ€โ™€๏ธ Woman Lifting Weights: Dark Skin Tone U+1F3CB, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿšด Person Biking U+1F6B4 +๐Ÿšด๐Ÿป Person Biking: Light Skin Tone U+1F6B4, U+1F3FB +๐Ÿšด๐Ÿผ Person Biking: Medium-Light Skin Tone U+1F6B4, U+1F3FC +๐Ÿšด๐Ÿฝ Person Biking: Medium Skin Tone U+1F6B4, U+1F3FD +๐Ÿšด๐Ÿพ Person Biking: Medium-Dark Skin Tone U+1F6B4, U+1F3FE +๐Ÿšด๐Ÿฟ Person Biking: Dark Skin Tone U+1F6B4, U+1F3FF +๐Ÿšดโ€โ™‚๏ธ Man Biking U+1F6B4, U+200D, U+2642, U+FE0F +๐Ÿšด๐Ÿปโ€โ™‚๏ธ Man Biking: Light Skin Tone U+1F6B4, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿšด๐Ÿผโ€โ™‚๏ธ Man Biking: Medium-Light Skin Tone U+1F6B4, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿšด๐Ÿฝโ€โ™‚๏ธ Man Biking: Medium Skin Tone U+1F6B4, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿšด๐Ÿพโ€โ™‚๏ธ Man Biking: Medium-Dark Skin Tone U+1F6B4, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿšด๐Ÿฟโ€โ™‚๏ธ Man Biking: Dark Skin Tone U+1F6B4, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿšดโ€โ™€๏ธ Woman Biking U+1F6B4, U+200D, U+2640, U+FE0F +๐Ÿšด๐Ÿปโ€โ™€๏ธ Woman Biking: Light Skin Tone U+1F6B4, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿšด๐Ÿผโ€โ™€๏ธ Woman Biking: Medium-Light Skin Tone U+1F6B4, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿšด๐Ÿฝโ€โ™€๏ธ Woman Biking: Medium Skin Tone U+1F6B4, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿšด๐Ÿพโ€โ™€๏ธ Woman Biking: Medium-Dark Skin Tone U+1F6B4, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿšด๐Ÿฟโ€โ™€๏ธ Woman Biking: Dark Skin Tone U+1F6B4, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿšต Person Mountain Biking U+1F6B5 +๐Ÿšต๐Ÿป Person Mountain Biking: Light Skin Tone U+1F6B5, U+1F3FB +๐Ÿšต๐Ÿผ Person Mountain Biking: Medium-Light Skin U+1F6B5, U+1F3FC +Tone +๐Ÿšต๐Ÿฝ Person Mountain Biking: Medium Skin Tone U+1F6B5, U+1F3FD +๐Ÿšต๐Ÿพ Person Mountain Biking: Medium-Dark Skin U+1F6B5, U+1F3FE +Tone +๐Ÿšต๐Ÿฟ Person Mountain Biking: Dark Skin Tone U+1F6B5, U+1F3FF +๐Ÿšตโ€โ™‚๏ธ Man Mountain Biking U+1F6B5, U+200D, U+2642, U+FE0F +๐Ÿšต๐Ÿปโ€โ™‚๏ธ Man Mountain Biking: Light Skin Tone U+1F6B5, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿšต๐Ÿผโ€โ™‚๏ธ Man Mountain Biking: Medium-Light Skin U+1F6B5, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿšต๐Ÿฝโ€โ™‚๏ธ Man Mountain Biking: Medium Skin Tone U+1F6B5, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿšต๐Ÿพโ€โ™‚๏ธ Man Mountain Biking: Medium-Dark Skin U+1F6B5, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿšต๐Ÿฟโ€โ™‚๏ธ Man Mountain Biking: Dark Skin Tone U+1F6B5, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿšตโ€โ™€๏ธ Woman Mountain Biking U+1F6B5, U+200D, U+2640, U+FE0F +๐Ÿšต๐Ÿปโ€โ™€๏ธ Woman Mountain Biking: Light Skin Tone U+1F6B5, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿšต๐Ÿผโ€โ™€๏ธ Woman Mountain Biking: Medium-Light U+1F6B5, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿšต๐Ÿฝโ€โ™€๏ธ Woman Mountain Biking: Medium Skin U+1F6B5, U+1F3FD, U+200D, U+2640, +Tone U+FE0F +๐Ÿšต๐Ÿพโ€โ™€๏ธ Woman Mountain Biking: Medium-Dark U+1F6B5, U+1F3FE, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿšต๐Ÿฟโ€โ™€๏ธ Woman Mountain Biking: Dark Skin Tone U+1F6B5, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿคธ Person Cartwheeling U+1F938 +๐Ÿคธ๐Ÿป Person Cartwheeling: Light Skin Tone U+1F938, U+1F3FB +๐Ÿคธ๐Ÿผ Person Cartwheeling: Medium-Light Skin U+1F938, U+1F3FC +Tone +๐Ÿคธ๐Ÿฝ Person Cartwheeling: Medium Skin Tone U+1F938, U+1F3FD +๐Ÿคธ๐Ÿพ Person Cartwheeling: Medium-Dark Skin U+1F938, U+1F3FE +Tone +๐Ÿคธ๐Ÿฟ Person Cartwheeling: Dark Skin Tone U+1F938, U+1F3FF +๐Ÿคธโ€โ™‚๏ธ Man Cartwheeling U+1F938, U+200D, U+2642, U+FE0F +๐Ÿคธ๐Ÿปโ€โ™‚๏ธ Man Cartwheeling: Light Skin Tone U+1F938, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿคธ๐Ÿผโ€โ™‚๏ธ Man Cartwheeling: Medium-Light Skin U+1F938, U+1F3FC, U+200D, U+2642, +Tone U+FE0F +๐Ÿคธ๐Ÿฝโ€โ™‚๏ธ Man Cartwheeling: Medium Skin Tone U+1F938, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿคธ๐Ÿพโ€โ™‚๏ธ Man Cartwheeling: Medium-Dark Skin U+1F938, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿคธ๐Ÿฟโ€โ™‚๏ธ Man Cartwheeling: Dark Skin Tone U+1F938, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿคธโ€โ™€๏ธ Woman Cartwheeling U+1F938, U+200D, U+2640, U+FE0F +๐Ÿคธ๐Ÿปโ€โ™€๏ธ Woman Cartwheeling: Light Skin Tone U+1F938, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿคธ๐Ÿผโ€โ™€๏ธ Woman Cartwheeling: Medium-Light Skin U+1F938, U+1F3FC, U+200D, U+2640, +Tone U+FE0F +๐Ÿคธ๐Ÿฝโ€โ™€๏ธ Woman Cartwheeling: Medium Skin Tone U+1F938, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿคธ๐Ÿพโ€โ™€๏ธ Woman Cartwheeling: Medium-Dark Skin U+1F938, U+1F3FE, U+200D, U+2640, +Tone U+FE0F +๐Ÿคธ๐Ÿฟโ€โ™€๏ธ Woman Cartwheeling: Dark Skin Tone U+1F938, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿคผ People Wrestling U+1F93C +๐Ÿคผโ€โ™‚๏ธ Men Wrestling U+1F93C, U+200D, U+2642, U+FE0F +๐Ÿคผโ€โ™€๏ธ Women Wrestling U+1F93C, U+200D, U+2640, U+FE0F +๐Ÿคฝ Person Playing Water Polo U+1F93D +๐Ÿคฝ๐Ÿป Person Playing Water Polo: Light Skin U+1F93D, U+1F3FB +Tone +๐Ÿคฝ๐Ÿผ Person Playing Water Polo: Medium-Light U+1F93D, U+1F3FC +Skin Tone +๐Ÿคฝ๐Ÿฝ Person Playing Water Polo: Medium Skin U+1F93D, U+1F3FD +Tone +๐Ÿ‘ฏ๐Ÿปโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-1-2 U+1F46F, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿคฝ๐Ÿพ Person Playing Water Polo: Medium-Dark U+1F93D, U+1F3FE +Skin Tone +๐Ÿคฝ๐Ÿฟ Person Playing Water Polo: Dark Skin Tone U+1F93D, U+1F3FF +๐Ÿ‘ฏ๐Ÿผโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-3 U+1F46F, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿคฝโ€โ™‚๏ธ Man Playing Water Polo U+1F93D, U+200D, U+2642, U+FE0F +๐Ÿคฝ๐Ÿปโ€โ™‚๏ธ Man Playing Water Polo: Light Skin U+1F93D, U+1F3FB, U+200D, U+2642, +Tone U+FE0F +๐Ÿ‘ฏ๐Ÿฝโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-4 U+1F46F, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿคฝ๐Ÿผโ€โ™‚๏ธ Man Playing Water Polo: Medium-Light U+1F93D, U+1F3FC, U+200D, U+2642, +Skin Tone U+FE0F +๐Ÿ‘ฏ๐Ÿพโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-5 U+1F46F, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿคฝ๐Ÿฝโ€โ™‚๏ธ Man Playing Water Polo: Medium Skin U+1F93D, U+1F3FD, U+200D, U+2642, +Tone U+FE0F +๐Ÿคฝ๐Ÿพโ€โ™‚๏ธ Man Playing Water Polo: Medium-Dark U+1F93D, U+1F3FE, U+200D, U+2642, +Skin Tone U+FE0F +๐Ÿคฝ๐Ÿฟโ€โ™‚๏ธ Man Playing Water Polo: Dark Skin Tone U+1F93D, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿ‘ฏ๐Ÿฟโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-6 U+1F46F, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿคฝโ€โ™€๏ธ Woman Playing Water Polo U+1F93D, U+200D, U+2640, U+FE0F +๐Ÿคฝ๐Ÿปโ€โ™€๏ธ Woman Playing Water Polo: Light Skin U+1F93D, U+1F3FB, U+200D, U+2640, +Tone U+FE0F +๐Ÿคฝ๐Ÿผโ€โ™€๏ธ Woman Playing Water Polo: Medium-Light U+1F93D, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿคฝ๐Ÿฝโ€โ™€๏ธ Woman Playing Water Polo: Medium Skin U+1F93D, U+1F3FD, U+200D, U+2640, +Tone U+FE0F +๐Ÿ‘ฏ๐Ÿปโ€โ™€๏ธ Women With Bunny Ears Partying, U+1F46F, U+1F3FB, U+200D, U+2640, +Type-1-2 U+FE0F +๐Ÿคฝ๐Ÿพโ€โ™€๏ธ Woman Playing Water Polo: Medium-Dark U+1F93D, U+1F3FE, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿ‘ฏ๐Ÿผโ€โ™€๏ธ Women With Bunny Ears Partying, Type-3 U+1F46F, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿคฝ๐Ÿฟโ€โ™€๏ธ Woman Playing Water Polo: Dark Skin U+1F93D, U+1F3FF, U+200D, U+2640, +Tone U+FE0F +๐Ÿคพ Person Playing Handball U+1F93E +๐Ÿ‘ฏ๐Ÿฝโ€โ™€๏ธ Women With Bunny Ears Partying, Type-4 U+1F46F, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿคพ๐Ÿป Person Playing Handball: Light Skin Tone U+1F93E, U+1F3FB +๐Ÿคพ๐Ÿผ Person Playing Handball: Medium-Light U+1F93E, U+1F3FC +Skin Tone +๐Ÿคพ๐Ÿฝ Person Playing Handball: Medium Skin Tone U+1F93E, U+1F3FD +๐Ÿ‘ฏ๐Ÿพโ€โ™€๏ธ Women With Bunny Ears Partying, Type-5 U+1F46F, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿคพ๐Ÿพ Person Playing Handball: Medium-Dark Skin U+1F93E, U+1F3FE +Tone +๐Ÿ‘ฏ๐Ÿฟโ€โ™€๏ธ Women With Bunny Ears Partying, Type-6 U+1F46F, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿคพ๐Ÿฟ Person Playing Handball: Dark Skin Tone U+1F93E, U+1F3FF +๐Ÿคพโ€โ™‚๏ธ Man Playing Handball U+1F93E, U+200D, U+2642, U+FE0F +๐Ÿคพ๐Ÿปโ€โ™‚๏ธ Man Playing Handball: Light Skin Tone U+1F93E, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿคพ๐Ÿผโ€โ™‚๏ธ Man Playing Handball: Medium-Light U+1F93E, U+1F3FC, U+200D, U+2642, +Skin Tone U+FE0F +๐Ÿคพ๐Ÿฝโ€โ™‚๏ธ Man Playing Handball: Medium Skin Tone U+1F93E, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿคพ๐Ÿพโ€โ™‚๏ธ Man Playing Handball: Medium-Dark Skin U+1F93E, U+1F3FE, U+200D, U+2642, +Tone U+FE0F +๐Ÿคพ๐Ÿฟโ€โ™‚๏ธ Man Playing Handball: Dark Skin Tone U+1F93E, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿคพโ€โ™€๏ธ Woman Playing Handball U+1F93E, U+200D, U+2640, U+FE0F +๐Ÿคพ๐Ÿปโ€โ™€๏ธ Woman Playing Handball: Light Skin U+1F93E, U+1F3FB, U+200D, U+2640, +Tone U+FE0F +๐Ÿคพ๐Ÿผโ€โ™€๏ธ Woman Playing Handball: Medium-Light U+1F93E, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿคพ๐Ÿฝโ€โ™€๏ธ Woman Playing Handball: Medium Skin U+1F93E, U+1F3FD, U+200D, U+2640, +Tone U+FE0F +๐Ÿคพ๐Ÿพโ€โ™€๏ธ Woman Playing Handball: Medium-Dark U+1F93E, U+1F3FE, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿคพ๐Ÿฟโ€โ™€๏ธ Woman Playing Handball: Dark Skin Tone U+1F93E, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿคน Person Juggling U+1F939 +๐Ÿคน๐Ÿป Person Juggling: Light Skin Tone U+1F939, U+1F3FB +๐Ÿคน๐Ÿผ Person Juggling: Medium-Light Skin Tone U+1F939, U+1F3FC +๐Ÿคน๐Ÿฝ Person Juggling: Medium Skin Tone U+1F939, U+1F3FD +๐Ÿคน๐Ÿพ Person Juggling: Medium-Dark Skin Tone U+1F939, U+1F3FE +๐Ÿคน๐Ÿฟ Person Juggling: Dark Skin Tone U+1F939, U+1F3FF +๐Ÿคนโ€โ™‚๏ธ Man Juggling U+1F939, U+200D, U+2642, U+FE0F +๐Ÿคน๐Ÿปโ€โ™‚๏ธ Man Juggling: Light Skin Tone U+1F939, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿคน๐Ÿผโ€โ™‚๏ธ Man Juggling: Medium-Light Skin Tone U+1F939, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿคน๐Ÿฝโ€โ™‚๏ธ Man Juggling: Medium Skin Tone U+1F939, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿคน๐Ÿพโ€โ™‚๏ธ Man Juggling: Medium-Dark Skin Tone U+1F939, U+1F3FE, U+200D, U+2642, + U+FE0F +๐Ÿคน๐Ÿฟโ€โ™‚๏ธ Man Juggling: Dark Skin Tone U+1F939, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿคนโ€โ™€๏ธ Woman Juggling U+1F939, U+200D, U+2640, U+FE0F +๐Ÿคน๐Ÿปโ€โ™€๏ธ Woman Juggling: Light Skin Tone U+1F939, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿคน๐Ÿผโ€โ™€๏ธ Woman Juggling: Medium-Light Skin Tone U+1F939, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿคน๐Ÿฝโ€โ™€๏ธ Woman Juggling: Medium Skin Tone U+1F939, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿคน๐Ÿพโ€โ™€๏ธ Woman Juggling: Medium-Dark Skin Tone U+1F939, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿคน๐Ÿฟโ€โ™€๏ธ Woman Juggling: Dark Skin Tone U+1F939, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿง˜ Person in Lotus Position U+1F9D8 +๐Ÿง˜๐Ÿป Person in Lotus Position: Light Skin Tone U+1F9D8, U+1F3FB +๐Ÿง˜๐Ÿผ Person in Lotus Position: Medium-Light U+1F9D8, U+1F3FC +Skin Tone +๐Ÿง˜๐Ÿฝ Person in Lotus Position: Medium Skin U+1F9D8, U+1F3FD +Tone +๐Ÿง˜๐Ÿพ Person in Lotus Position: Medium-Dark U+1F9D8, U+1F3FE +Skin Tone +๐Ÿง˜๐Ÿฟ Person in Lotus Position: Dark Skin Tone U+1F9D8, U+1F3FF +๐Ÿง˜โ€โ™‚๏ธ Man in Lotus Position U+1F9D8, U+200D, U+2642, U+FE0F +๐Ÿง˜๐Ÿปโ€โ™‚๏ธ Man in Lotus Position: Light Skin Tone U+1F9D8, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿง˜๐Ÿผโ€โ™‚๏ธ Man in Lotus Position: Medium-Light U+1F9D8, U+1F3FC, U+200D, U+2642, +Skin Tone U+FE0F +๐Ÿง˜๐Ÿฝโ€โ™‚๏ธ Man in Lotus Position: Medium Skin U+1F9D8, U+1F3FD, U+200D, U+2642, +Tone U+FE0F +๐Ÿง˜๐Ÿพโ€โ™‚๏ธ Man in Lotus Position: Medium-Dark U+1F9D8, U+1F3FE, U+200D, U+2642, +Skin Tone U+FE0F +๐Ÿง˜๐Ÿฟโ€โ™‚๏ธ Man in Lotus Position: Dark Skin Tone U+1F9D8, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿง˜โ€โ™€๏ธ Woman in Lotus Position U+1F9D8, U+200D, U+2640, U+FE0F +๐Ÿง˜๐Ÿปโ€โ™€๏ธ Woman in Lotus Position: Light Skin U+1F9D8, U+1F3FB, U+200D, U+2640, +Tone U+FE0F +๐Ÿง˜๐Ÿผโ€โ™€๏ธ Woman in Lotus Position: Medium-Light U+1F9D8, U+1F3FC, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿง˜๐Ÿฝโ€โ™€๏ธ Woman in Lotus Position: Medium Skin U+1F9D8, U+1F3FD, U+200D, U+2640, +Tone U+FE0F +๐Ÿง˜๐Ÿพโ€โ™€๏ธ Woman in Lotus Position: Medium-Dark U+1F9D8, U+1F3FE, U+200D, U+2640, +Skin Tone U+FE0F +๐Ÿง˜๐Ÿฟโ€โ™€๏ธ Woman in Lotus Position: Dark Skin U+1F9D8, U+1F3FF, U+200D, U+2640, +Tone U+FE0F +๐Ÿ›€ Person Taking Bath U+1F6C0 +๐Ÿ›€๐Ÿป Person Taking Bath: Light Skin Tone U+1F6C0, U+1F3FB +๐Ÿ›€๐Ÿผ Person Taking Bath: Medium-Light Skin U+1F6C0, U+1F3FC +Tone +๐Ÿ›€๐Ÿฝ Person Taking Bath: Medium Skin Tone U+1F6C0, U+1F3FD +๐Ÿ›€๐Ÿพ Person Taking Bath: Medium-Dark Skin Tone U+1F6C0, U+1F3FE +๐Ÿ›€๐Ÿฟ Person Taking Bath: Dark Skin Tone U+1F6C0, U+1F3FF +๐Ÿ›Œ Person in Bed U+1F6CC +๐Ÿ›Œ๐Ÿป Person in Bed: Light Skin Tone U+1F6CC, U+1F3FB +๐Ÿ›Œ๐Ÿผ Person in Bed: Medium-Light Skin Tone U+1F6CC, U+1F3FC +๐Ÿ›Œ๐Ÿฝ Person in Bed: Medium Skin Tone U+1F6CC, U+1F3FD +๐Ÿ›Œ๐Ÿพ Person in Bed: Medium-Dark Skin Tone U+1F6CC, U+1F3FE +๐Ÿ›Œ๐Ÿฟ Person in Bed: Dark Skin Tone U+1F6CC, U+1F3FF +๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ People Holding Hands U+1F9D1, U+200D, U+1F91D, U+200D, + U+1F9D1 +๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, +Tone U+200D, U+1F9D1, U+1F3FB +๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, +Tone, Medium-Light Skin Tone U+200D, U+1F9D1, U+1F3FC +๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, +Tone, Medium Skin Tone U+200D, U+1F9D1, U+1F3FD +๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, +Tone, Medium-Dark Skin Tone U+200D, U+1F9D1, U+1F3FE +๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, +Tone, Dark Skin Tone U+200D, U+1F9D1, U+1F3FF +๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, +Skin Tone, Light Skin Tone U+200D, U+1F9D1, U+1F3FB +๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, +Skin Tone U+200D, U+1F9D1, U+1F3FC +๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, +Skin Tone, Medium Skin Tone U+200D, U+1F9D1, U+1F3FD +๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, +Skin Tone, Medium-Dark Skin Tone U+200D, U+1F9D1, U+1F3FE +๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, +Skin Tone, Dark Skin Tone U+200D, U+1F9D1, U+1F3FF +๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, +Tone, Light Skin Tone U+200D, U+1F9D1, U+1F3FB +๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, +Tone, Medium-Light Skin Tone U+200D, U+1F9D1, U+1F3FC +๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, +Tone U+200D, U+1F9D1, U+1F3FD +๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, +Tone, Medium-Dark Skin Tone U+200D, U+1F9D1, U+1F3FE +๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, +Tone, Dark Skin Tone U+200D, U+1F9D1, U+1F3FF +๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, +Skin Tone, Light Skin Tone U+200D, U+1F9D1, U+1F3FB +๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, +Skin Tone, Medium-Light Skin Tone U+200D, U+1F9D1, U+1F3FC +๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, +Skin Tone, Medium Skin Tone U+200D, U+1F9D1, U+1F3FD +๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, +Skin Tone U+200D, U+1F9D1, U+1F3FE +๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, +Skin Tone, Dark Skin Tone U+200D, U+1F9D1, U+1F3FF +๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F91D, +Tone, Light Skin Tone U+200D, U+1F9D1, U+1F3FB +๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F91D, +Tone, Medium-Light Skin Tone U+200D, U+1F9D1, U+1F3FC +๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F91D, +Tone, Medium Skin Tone U+200D, U+1F9D1, U+1F3FD +๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F91D, +Tone, Medium-Dark Skin Tone U+200D, U+1F9D1, U+1F3FE +๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F91D, + U+200D, U+1F9D1, U+1F3FF +๐Ÿ‘ญ Women Holding Hands U+1F46D +๐Ÿ‘ญ๐Ÿป Women Holding Hands: Light Skin Tone U+1F46D, U+1F3FB +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿผ Women Holding Hands: Light Skin U+1F469, U+1F3FB, U+200D, U+1F91D, +Tone, Medium-Light Skin Tone U+200D, U+1F469, U+1F3FC +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฝ Women Holding Hands: Light Skin U+1F469, U+1F3FB, U+200D, U+1F91D, +Tone, Medium Skin Tone U+200D, U+1F469, U+1F3FD +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿพ Women Holding Hands: Light Skin U+1F469, U+1F3FB, U+200D, U+1F91D, +Tone, Medium-Dark Skin Tone U+200D, U+1F469, U+1F3FE +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฟ Women Holding Hands: Light Skin U+1F469, U+1F3FB, U+200D, U+1F91D, +Tone, Dark Skin Tone U+200D, U+1F469, U+1F3FF +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿป Women Holding Hands: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F91D, +Skin Tone, Light Skin Tone U+200D, U+1F469, U+1F3FB +๐Ÿ‘ญ๐Ÿผ Women Holding Hands: Medium-Light Skin U+1F46D, U+1F3FC +Tone +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฝ Women Holding Hands: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F91D, +Skin Tone, Medium Skin Tone U+200D, U+1F469, U+1F3FD +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿพ Women Holding Hands: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F91D, +Skin Tone, Medium-Dark Skin Tone U+200D, U+1F469, U+1F3FE +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฟ Women Holding Hands: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F91D, +Skin Tone, Dark Skin Tone U+200D, U+1F469, U+1F3FF +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿป Women Holding Hands: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F91D, +Tone, Light Skin Tone U+200D, U+1F469, U+1F3FB +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿผ Women Holding Hands: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F91D, +Tone, Medium-Light Skin Tone U+200D, U+1F469, U+1F3FC +๐Ÿ‘ญ๐Ÿฝ Women Holding Hands: Medium Skin Tone U+1F46D, U+1F3FD +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿพ Women Holding Hands: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F91D, +Tone, Medium-Dark Skin Tone U+200D, U+1F469, U+1F3FE +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฟ Women Holding Hands: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F91D, +Tone, Dark Skin Tone U+200D, U+1F469, U+1F3FF +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿป Women Holding Hands: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F91D, +Skin Tone, Light Skin Tone U+200D, U+1F469, U+1F3FB +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿผ Women Holding Hands: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F91D, +Skin Tone, Medium-Light Skin Tone U+200D, U+1F469, U+1F3FC +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฝ Women Holding Hands: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F91D, +Skin Tone, Medium Skin Tone U+200D, U+1F469, U+1F3FD +๐Ÿ‘ญ๐Ÿพ Women Holding Hands: Medium-Dark Skin U+1F46D, U+1F3FE +Tone +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฟ Women Holding Hands: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F91D, +Skin Tone, Dark Skin Tone U+200D, U+1F469, U+1F3FF +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿป Women Holding Hands: Dark Skin Tone, U+1F469, U+1F3FF, U+200D, U+1F91D, +Light Skin Tone U+200D, U+1F469, U+1F3FB +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿผ Women Holding Hands: Dark Skin Tone, U+1F469, U+1F3FF, U+200D, U+1F91D, +Medium-Light Skin Tone U+200D, U+1F469, U+1F3FC +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฝ Women Holding Hands: Dark Skin Tone, U+1F469, U+1F3FF, U+200D, U+1F91D, +Medium Skin Tone U+200D, U+1F469, U+1F3FD +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿพ Women Holding Hands: Dark Skin Tone, U+1F469, U+1F3FF, U+200D, U+1F91D, +Medium-Dark Skin Tone U+200D, U+1F469, U+1F3FE +๐Ÿ‘ญ๐Ÿฟ Women Holding Hands: Dark Skin Tone U+1F46D, U+1F3FF +๐Ÿ‘ซ Woman and Man Holding Hands U+1F46B +๐Ÿ‘ซ๐Ÿป Woman and Man Holding Hands: Light Skin U+1F46B, U+1F3FB +Tone +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Woman and Man Holding Hands: Light U+1F469, U+1F3FB, U+200D, U+1F91D, +Skin Tone, Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Woman and Man Holding Hands: Light U+1F469, U+1F3FB, U+200D, U+1F91D, +Skin Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Woman and Man Holding Hands: Light U+1F469, U+1F3FB, U+200D, U+1F91D, +Skin Tone, Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE +๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Woman and Man Holding Hands: Light U+1F469, U+1F3FB, U+200D, U+1F91D, +Skin Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Woman and Man Holding Hands: U+1F469, U+1F3FC, U+200D, U+1F91D, +Medium-Light Skin Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB +๐Ÿ‘ซ๐Ÿผ Woman and Man Holding Hands: Medium-Light U+1F46B, U+1F3FC +Skin Tone +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Woman and Man Holding Hands: U+1F469, U+1F3FC, U+200D, U+1F91D, +Medium-Light Skin Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Woman and Man Holding Hands: U+1F469, U+1F3FC, U+200D, U+1F91D, +Medium-Light Skin Tone, Medium-Dark Skin U+200D, U+1F468, U+1F3FE +Tone +๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Woman and Man Holding Hands: U+1F469, U+1F3FC, U+200D, U+1F91D, +Medium-Light Skin Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Woman and Man Holding Hands: Medium U+1F469, U+1F3FD, U+200D, U+1F91D, +Skin Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Woman and Man Holding Hands: Medium U+1F469, U+1F3FD, U+200D, U+1F91D, +Skin Tone, Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC +๐Ÿ‘ซ๐Ÿฝ Woman and Man Holding Hands: Medium Skin U+1F46B, U+1F3FD +Tone +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Woman and Man Holding Hands: Medium U+1F469, U+1F3FD, U+200D, U+1F91D, +Skin Tone, Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE +๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Woman and Man Holding Hands: Medium U+1F469, U+1F3FD, U+200D, U+1F91D, +Skin Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Woman and Man Holding Hands: U+1F469, U+1F3FE, U+200D, U+1F91D, +Medium-Dark Skin Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Woman and Man Holding Hands: U+1F469, U+1F3FE, U+200D, U+1F91D, +Medium-Dark Skin Tone, Medium-Light Skin U+200D, U+1F468, U+1F3FC +Tone +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Woman and Man Holding Hands: U+1F469, U+1F3FE, U+200D, U+1F91D, +Medium-Dark Skin Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD +๐Ÿ‘ซ๐Ÿพ Woman and Man Holding Hands: Medium-Dark U+1F46B, U+1F3FE +Skin Tone +๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Woman and Man Holding Hands: U+1F469, U+1F3FE, U+200D, U+1F91D, +Medium-Dark Skin Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Woman and Man Holding Hands: Dark U+1F469, U+1F3FF, U+200D, U+1F91D, +Skin Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Woman and Man Holding Hands: Dark U+1F469, U+1F3FF, U+200D, U+1F91D, +Skin Tone, Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Woman and Man Holding Hands: Dark U+1F469, U+1F3FF, U+200D, U+1F91D, +Skin Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD +๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Woman and Man Holding Hands: Dark U+1F469, U+1F3FF, U+200D, U+1F91D, +Skin Tone, Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE +๐Ÿ‘ซ๐Ÿฟ Woman and Man Holding Hands: Dark Skin U+1F46B, U+1F3FF +Tone +๐Ÿ‘ฌ Men Holding Hands U+1F46C +๐Ÿ‘ฌ๐Ÿป Men Holding Hands: Light Skin Tone U+1F46C, U+1F3FB +๐Ÿ‘จ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Men Holding Hands: Light Skin Tone, U+1F468, U+1F3FB, U+200D, U+1F91D, +Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC +๐Ÿ‘จ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Men Holding Hands: Light Skin Tone, U+1F468, U+1F3FB, U+200D, U+1F91D, +Medium Skin Tone U+200D, U+1F468, U+1F3FD +๐Ÿ‘จ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Men Holding Hands: Light Skin Tone, U+1F468, U+1F3FB, U+200D, U+1F91D, +Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE +๐Ÿ‘จ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Men Holding Hands: Light Skin Tone, U+1F468, U+1F3FB, U+200D, U+1F91D, +Dark Skin Tone U+200D, U+1F468, U+1F3FF +๐Ÿ‘จ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Men Holding Hands: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F91D, +Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB +๐Ÿ‘ฌ๐Ÿผ Men Holding Hands: Medium-Light Skin Tone U+1F46C, U+1F3FC +๐Ÿ‘จ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Men Holding Hands: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F91D, +Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD +๐Ÿ‘จ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Men Holding Hands: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F91D, +Tone, Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE +๐Ÿ‘จ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Men Holding Hands: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F91D, +Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF +๐Ÿ‘จ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Men Holding Hands: Medium Skin Tone, U+1F468, U+1F3FD, U+200D, U+1F91D, +Light Skin Tone U+200D, U+1F468, U+1F3FB +๐Ÿ‘จ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Men Holding Hands: Medium Skin Tone, U+1F468, U+1F3FD, U+200D, U+1F91D, +Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC +๐Ÿ‘ฌ๐Ÿฝ Men Holding Hands: Medium Skin Tone U+1F46C, U+1F3FD +๐Ÿ‘จ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Men Holding Hands: Medium Skin Tone, U+1F468, U+1F3FD, U+200D, U+1F91D, +Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE +๐Ÿ‘จ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Men Holding Hands: Medium Skin Tone, U+1F468, U+1F3FD, U+200D, U+1F91D, +Dark Skin Tone U+200D, U+1F468, U+1F3FF +๐Ÿ‘จ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Men Holding Hands: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F91D, +Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB +๐Ÿ‘จ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Men Holding Hands: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F91D, +Tone, Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC +๐Ÿ‘จ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Men Holding Hands: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F91D, +Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD +๐Ÿ‘ฌ๐Ÿพ Men Holding Hands: Medium-Dark Skin Tone U+1F46C, U+1F3FE +๐Ÿ‘จ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Men Holding Hands: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F91D, +Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF +๐Ÿ‘จ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Men Holding Hands: Dark Skin Tone, U+1F468, U+1F3FF, U+200D, U+1F91D, +Light Skin Tone U+200D, U+1F468, U+1F3FB +๐Ÿ‘จ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Men Holding Hands: Dark Skin Tone, U+1F468, U+1F3FF, U+200D, U+1F91D, +Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC +๐Ÿ‘จ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Men Holding Hands: Dark Skin Tone, U+1F468, U+1F3FF, U+200D, U+1F91D, +Medium Skin Tone U+200D, U+1F468, U+1F3FD +๐Ÿ‘จ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Men Holding Hands: Dark Skin Tone, U+1F468, U+1F3FF, U+200D, U+1F91D, +Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE +๐Ÿ‘ฌ๐Ÿฟ Men Holding Hands: Dark Skin Tone U+1F46C, U+1F3FF +๐Ÿ’ Kiss U+1F48F +๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ Kiss: Woman, Man U+1F469, U+200D, U+2764, U+FE0F, + U+200D, U+1F48B, U+200D, U+1F468 +๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ Kiss: Man, Man U+1F468, U+200D, U+2764, U+FE0F, + U+200D, U+1F48B, U+200D, U+1F468 +๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ Kiss: Woman, Woman U+1F469, U+200D, U+2764, U+FE0F, + U+200D, U+1F48B, U+200D, U+1F469 +๐Ÿ’‘ Couple with Heart U+1F491 +๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘จ Couple with Heart: Woman, Man U+1F469, U+200D, U+2764, U+FE0F, + U+200D, U+1F468 +๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ Couple with Heart: Man, Man U+1F468, U+200D, U+2764, U+FE0F, + U+200D, U+1F468 +๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ Couple with Heart: Woman, Woman U+1F469, U+200D, U+2764, U+FE0F, + U+200D, U+1F469 +๐Ÿ‘ช Family U+1F46A +๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ Family: Man, Woman, Boy U+1F468, U+200D, U+1F469, U+200D, + U+1F466 +๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง Family: Man, Woman, Girl U+1F468, U+200D, U+1F469, U+200D, + U+1F467 +๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Man, Woman, Girl, Boy U+1F468, U+200D, U+1F469, U+200D, + U+1F467, U+200D, U+1F466 +๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Man, Woman, Boy, Boy U+1F468, U+200D, U+1F469, U+200D, + U+1F466, U+200D, U+1F466 +๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Man, Woman, Girl, Girl U+1F468, U+200D, U+1F469, U+200D, + U+1F467, U+200D, U+1F467 +๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ Family: Man, Man, Boy U+1F468, U+200D, U+1F468, U+200D, + U+1F466 +๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง Family: Man, Man, Girl U+1F468, U+200D, U+1F468, U+200D, + U+1F467 +๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Man, Man, Girl, Boy U+1F468, U+200D, U+1F468, U+200D, + U+1F467, U+200D, U+1F466 +๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Man, Man, Boy, Boy U+1F468, U+200D, U+1F468, U+200D, + U+1F466, U+200D, U+1F466 +๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Man, Man, Girl, Girl U+1F468, U+200D, U+1F468, U+200D, + U+1F467, U+200D, U+1F467 +๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ Family: Woman, Woman, Boy U+1F469, U+200D, U+1F469, U+200D, + U+1F466 +๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง Family: Woman, Woman, Girl U+1F469, U+200D, U+1F469, U+200D, + U+1F467 +๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Woman, Woman, Girl, Boy U+1F469, U+200D, U+1F469, U+200D, + U+1F467, U+200D, U+1F466 +๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Woman, Woman, Boy, Boy U+1F469, U+200D, U+1F469, U+200D, + U+1F466, U+200D, U+1F466 +๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Woman, Woman, Girl, Girl U+1F469, U+200D, U+1F469, U+200D, + U+1F467, U+200D, U+1F467 +๐Ÿ‘จโ€๐Ÿ‘ฆ Family: Man, Boy U+1F468, U+200D, U+1F466 +๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Man, Boy, Boy U+1F468, U+200D, U+1F466, U+200D, + U+1F466 +๐Ÿ‘จโ€๐Ÿ‘ง Family: Man, Girl U+1F468, U+200D, U+1F467 +๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Man, Girl, Boy U+1F468, U+200D, U+1F467, U+200D, + U+1F466 +๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Man, Girl, Girl U+1F468, U+200D, U+1F467, U+200D, + U+1F467 +๐Ÿ‘ฉโ€๐Ÿ‘ฆ Family: Woman, Boy U+1F469, U+200D, U+1F466 +๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Woman, Boy, Boy U+1F469, U+200D, U+1F466, U+200D, + U+1F466 +๐Ÿ‘ฉโ€๐Ÿ‘ง Family: Woman, Girl U+1F469, U+200D, U+1F467 +๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Woman, Girl, Boy U+1F469, U+200D, U+1F467, U+200D, + U+1F466 +๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Woman, Girl, Girl U+1F469, U+200D, U+1F467, U+200D, + U+1F467 +๐Ÿ—ฃ๏ธ Speaking Head U+1F5E3, U+FE0F +๐Ÿ‘ค Bust in Silhouette U+1F464 +๐Ÿ‘ฅ Busts in Silhouette U+1F465 +๐Ÿซ‚ People Hugging U+1FAC2 +๐Ÿ‘ฃ Footprints U+1F463 +๐Ÿป Light Skin Tone U+1F3FB +๐Ÿผ Medium-Light Skin Tone U+1F3FC +๐Ÿฝ Medium Skin Tone U+1F3FD +๐Ÿพ Medium-Dark Skin Tone U+1F3FE +๐Ÿฟ Dark Skin Tone U+1F3FF +๐Ÿฆฐ Red Hair U+1F9B0 +๐Ÿฆฑ Curly Hair U+1F9B1 +๐Ÿฆณ White Hair U+1F9B3 +๐Ÿฆฒ Bald U+1F9B2 +๐Ÿต Monkey Face U+1F435 +๐Ÿ’ Monkey U+1F412 +๐Ÿฆ Gorilla U+1F98D +๐Ÿฆง Orangutan U+1F9A7 +๐Ÿถ Dog Face U+1F436 +๐Ÿ• Dog U+1F415 +๐Ÿฆฎ Guide Dog U+1F9AE +๐Ÿ•โ€๐Ÿฆบ Service Dog U+1F415, U+200D, U+1F9BA +๐Ÿฉ Poodle U+1F429 +๐Ÿบ Wolf U+1F43A +๐ŸฆŠ Fox U+1F98A +๐Ÿฆ Raccoon U+1F99D +๐Ÿฑ Cat Face U+1F431 +๐Ÿˆ Cat U+1F408 +๐Ÿˆโ€โฌ› Black Cat U+1F408, U+200D, U+2B1B +๐Ÿฆ Lion U+1F981 +๐Ÿฏ Tiger Face U+1F42F +๐Ÿ… Tiger U+1F405 +๐Ÿ† Leopard U+1F406 +๐Ÿด Horse Face U+1F434 +๐ŸŽ Horse U+1F40E +๐Ÿฆ„ Unicorn U+1F984 +๐Ÿฆ“ Zebra U+1F993 +๐ŸฆŒ Deer U+1F98C +๐Ÿฆฌ Bison U+1F9AC +๐Ÿฎ Cow Face U+1F42E +๐Ÿ‚ Ox U+1F402 +๐Ÿƒ Water Buffalo U+1F403 +๐Ÿ„ Cow U+1F404 +๐Ÿท Pig Face U+1F437 +๐Ÿ– Pig U+1F416 +๐Ÿ— Boar U+1F417 +๐Ÿฝ Pig Nose U+1F43D +๐Ÿ Ram U+1F40F +๐Ÿ‘ Ewe U+1F411 +๐Ÿ Goat U+1F410 +๐Ÿช Camel U+1F42A +๐Ÿซ Two-Hump Camel U+1F42B +๐Ÿฆ™ Llama U+1F999 +๐Ÿฆ’ Giraffe U+1F992 +๐Ÿ˜ Elephant U+1F418 +๐Ÿฆฃ Mammoth U+1F9A3 +๐Ÿฆ Rhinoceros U+1F98F +๐Ÿฆ› Hippopotamus U+1F99B +๐Ÿญ Mouse Face U+1F42D +๐Ÿ Mouse U+1F401 +๐Ÿ€ Rat U+1F400 +๐Ÿน Hamster U+1F439 +๐Ÿฐ Rabbit Face U+1F430 +๐Ÿ‡ Rabbit U+1F407 +๐Ÿฟ๏ธ Chipmunk U+1F43F, U+FE0F +๐Ÿฆซ Beaver U+1F9AB +๐Ÿฆ” Hedgehog U+1F994 +๐Ÿฆ‡ Bat U+1F987 +๐Ÿป Bear U+1F43B +๐Ÿปโ€โ„๏ธ Polar Bear U+1F43B, U+200D, U+2744, U+FE0F +๐Ÿจ Koala U+1F428 +๐Ÿผ Panda U+1F43C +๐Ÿฆฅ Sloth U+1F9A5 +๐Ÿฆฆ Otter U+1F9A6 +๐Ÿฆจ Skunk U+1F9A8 +๐Ÿฆ˜ Kangaroo U+1F998 +๐Ÿฆก Badger U+1F9A1 +๐Ÿพ Paw Prints U+1F43E +๐Ÿฆƒ Turkey U+1F983 +๐Ÿ” Chicken U+1F414 +๐Ÿ“ Rooster U+1F413 +๐Ÿฃ Hatching Chick U+1F423 +๐Ÿค Baby Chick U+1F424 +๐Ÿฅ Front-Facing Baby Chick U+1F425 +๐Ÿฆ Bird U+1F426 +๐Ÿง Penguin U+1F427 +๐Ÿ•Š๏ธ Dove U+1F54A, U+FE0F +๐Ÿฆ… Eagle U+1F985 +๐Ÿฆ† Duck U+1F986 +๐Ÿฆข Swan U+1F9A2 +๐Ÿฆ‰ Owl U+1F989 +๐Ÿฆค Dodo U+1F9A4 +๐Ÿชถ Feather U+1FAB6 +๐Ÿฆฉ Flamingo U+1F9A9 +๐Ÿฆš Peacock U+1F99A +๐Ÿฆœ Parrot U+1F99C +๐Ÿธ Frog U+1F438 +๐ŸŠ Crocodile U+1F40A +๐Ÿข Turtle U+1F422 +๐ŸฆŽ Lizard U+1F98E +๐Ÿ Snake U+1F40D +๐Ÿฒ Dragon Face U+1F432 +๐Ÿ‰ Dragon U+1F409 +๐Ÿฆ• Sauropod U+1F995 +๐Ÿฆ– T-Rex U+1F996 +๐Ÿณ Spouting Whale U+1F433 +๐Ÿ‹ Whale U+1F40B +๐Ÿฌ Dolphin U+1F42C +๐Ÿฆญ Seal U+1F9AD +๐ŸŸ Fish U+1F41F +๐Ÿ  Tropical Fish U+1F420 +๐Ÿก Blowfish U+1F421 +๐Ÿฆˆ Shark U+1F988 +๐Ÿ™ Octopus U+1F419 +๐Ÿš Spiral Shell U+1F41A +๐ŸŒ Snail U+1F40C +๐Ÿฆ‹ Butterfly U+1F98B +๐Ÿ› Bug U+1F41B +๐Ÿœ Ant U+1F41C +๐Ÿ Honeybee U+1F41D +๐Ÿชฒ Beetle U+1FAB2 +๐Ÿž Lady Beetle U+1F41E +๐Ÿฆ— Cricket U+1F997 +๐Ÿชณ Cockroach U+1FAB3 +๐Ÿ•ท๏ธ Spider U+1F577, U+FE0F +๐Ÿ•ธ๏ธ Spider Web U+1F578, U+FE0F +๐Ÿฆ‚ Scorpion U+1F982 +๐ŸฆŸ Mosquito U+1F99F +๐Ÿชฐ Fly U+1FAB0 +๐Ÿชฑ Worm U+1FAB1 +๐Ÿฆ  Microbe U+1F9A0 +๐Ÿ’ Bouquet U+1F490 +๐ŸŒธ Cherry Blossom U+1F338 +๐Ÿ’ฎ White Flower U+1F4AE +๐Ÿต๏ธ Rosette U+1F3F5, U+FE0F +๐ŸŒน Rose U+1F339 +๐Ÿฅ€ Wilted Flower U+1F940 +๐ŸŒบ Hibiscus U+1F33A +๐ŸŒป Sunflower U+1F33B +๐ŸŒผ Blossom U+1F33C +๐ŸŒท Tulip U+1F337 +๐ŸŒฑ Seedling U+1F331 +๐Ÿชด Potted Plant U+1FAB4 +๐ŸŒฒ Evergreen Tree U+1F332 +๐ŸŒณ Deciduous Tree U+1F333 +๐ŸŒด Palm Tree U+1F334 +๐ŸŒต Cactus U+1F335 +๐ŸŒพ Sheaf of Rice U+1F33E +๐ŸŒฟ Herb U+1F33F +โ˜˜๏ธ Shamrock U+2618, U+FE0F +๐Ÿ€ Four Leaf Clover U+1F340 +๐Ÿ Maple Leaf U+1F341 +๐Ÿ‚ Fallen Leaf U+1F342 +๐Ÿƒ Leaf Fluttering in Wind U+1F343 +๐Ÿ‡ Grapes U+1F347 +๐Ÿˆ Melon U+1F348 +๐Ÿ‰ Watermelon U+1F349 +๐ŸŠ Tangerine U+1F34A +๐Ÿ‹ Lemon U+1F34B +๐ŸŒ Banana U+1F34C +๐Ÿ Pineapple U+1F34D +๐Ÿฅญ Mango U+1F96D +๐ŸŽ Red Apple U+1F34E +๐Ÿ Green Apple U+1F34F +๐Ÿ Pear U+1F350 +๐Ÿคผ๐Ÿป Wrestlers, Type-1-2 U+1F93C, U+1F3FB +๐Ÿ‘ Peach U+1F351 +๐Ÿคผ๐Ÿผ Wrestlers, Type-3 U+1F93C, U+1F3FC +๐Ÿ’ Cherries U+1F352 +๐Ÿคผ๐Ÿฝ Wrestlers, Type-4 U+1F93C, U+1F3FD +๐Ÿ“ Strawberry U+1F353 +๐Ÿคผ๐Ÿพ Wrestlers, Type-5 U+1F93C, U+1F3FE +๐Ÿซ Blueberries U+1FAD0 +๐Ÿคผ๐Ÿฟ Wrestlers, Type-6 U+1F93C, U+1F3FF +๐Ÿฅ Kiwi Fruit U+1F95D +๐Ÿ… Tomato U+1F345 +๐Ÿคผ๐Ÿปโ€โ™‚๏ธ Men Wrestling, Type-1-2 U+1F93C, U+1F3FB, U+200D, U+2642, + U+FE0F +๐Ÿซ’ Olive U+1FAD2 +๐Ÿฅฅ Coconut U+1F965 +๐Ÿฅ‘ Avocado U+1F951 +๐Ÿคผ๐Ÿผโ€โ™‚๏ธ Men Wrestling, Type-3 U+1F93C, U+1F3FC, U+200D, U+2642, + U+FE0F +๐Ÿ† Eggplant U+1F346 +๐Ÿฅ” Potato U+1F954 +๐Ÿคผ๐Ÿฝโ€โ™‚๏ธ Men Wrestling, Type-4 U+1F93C, U+1F3FD, U+200D, U+2642, + U+FE0F +๐Ÿฅ• Carrot U+1F955 +๐Ÿคผ๐Ÿพโ€โ™‚๏ธ Men Wrestling, Type-5 U+1F93C, U+1F3FE, U+200D, U+2642, + U+FE0F +๐ŸŒฝ Ear of Corn U+1F33D +๐ŸŒถ๏ธ Hot Pepper U+1F336, U+FE0F +๐Ÿซ‘ Bell Pepper U+1FAD1 +๐Ÿคผ๐Ÿฟโ€โ™‚๏ธ Men Wrestling, Type-6 U+1F93C, U+1F3FF, U+200D, U+2642, + U+FE0F +๐Ÿฅ’ Cucumber U+1F952 +๐Ÿฅฌ Leafy Green U+1F96C +๐Ÿฅฆ Broccoli U+1F966 +๐Ÿคผ๐Ÿปโ€โ™€๏ธ Women Wrestling, Type-1-2 U+1F93C, U+1F3FB, U+200D, U+2640, + U+FE0F +๐Ÿง„ Garlic U+1F9C4 +๐Ÿง… Onion U+1F9C5 +๐Ÿ„ Mushroom U+1F344 +๐Ÿคผ๐Ÿผโ€โ™€๏ธ Women Wrestling, Type-3 U+1F93C, U+1F3FC, U+200D, U+2640, + U+FE0F +๐Ÿฅœ Peanuts U+1F95C +๐ŸŒฐ Chestnut U+1F330 +๐Ÿคผ๐Ÿฝโ€โ™€๏ธ Women Wrestling, Type-4 U+1F93C, U+1F3FD, U+200D, U+2640, + U+FE0F +๐Ÿž Bread U+1F35E +๐Ÿฅ Croissant U+1F950 +๐Ÿคผ๐Ÿพโ€โ™€๏ธ Women Wrestling, Type-5 U+1F93C, U+1F3FE, U+200D, U+2640, + U+FE0F +๐Ÿฅ– Baguette Bread U+1F956 +๐Ÿซ“ Flatbread U+1FAD3 +๐Ÿคผ๐Ÿฟโ€โ™€๏ธ Women Wrestling, Type-6 U+1F93C, U+1F3FF, U+200D, U+2640, + U+FE0F +๐Ÿฅจ Pretzel U+1F968 +๐Ÿฅฏ Bagel U+1F96F +๐Ÿฅž Pancakes U+1F95E +๐Ÿง‡ Waffle U+1F9C7 +๐Ÿง€ Cheese Wedge U+1F9C0 +๐Ÿ– Meat on Bone U+1F356 +๐Ÿ— Poultry Leg U+1F357 +๐Ÿฅฉ Cut of Meat U+1F969 +๐Ÿฅ“ Bacon U+1F953 +๐Ÿ” Hamburger U+1F354 +๐ŸŸ French Fries U+1F35F +๐Ÿ• Pizza U+1F355 +๐ŸŒญ Hot Dog U+1F32D +๐Ÿฅช Sandwich U+1F96A +๐ŸŒฎ Taco U+1F32E +๐ŸŒฏ Burrito U+1F32F +๐Ÿซ” Tamale U+1FAD4 +๐Ÿฅ™ Stuffed Flatbread U+1F959 +๐Ÿง† Falafel U+1F9C6 +๐Ÿฅš Egg U+1F95A +๐Ÿณ Cooking U+1F373 +๐Ÿฅ˜ Shallow Pan of Food U+1F958 +๐Ÿฒ Pot of Food U+1F372 +๐Ÿซ• Fondue U+1FAD5 +๐Ÿฅฃ Bowl with Spoon U+1F963 +๐Ÿฅ— Green Salad U+1F957 +๐Ÿฟ Popcorn U+1F37F +๐Ÿงˆ Butter U+1F9C8 +๐Ÿง‚ Salt U+1F9C2 +๐Ÿฅซ Canned Food U+1F96B +๐Ÿฑ Bento Box U+1F371 +๐Ÿ˜ Rice Cracker U+1F358 +๐Ÿ™ Rice Ball U+1F359 +๐Ÿš Cooked Rice U+1F35A +๐Ÿ› Curry Rice U+1F35B +๐Ÿœ Steaming Bowl U+1F35C +๐Ÿ Spaghetti U+1F35D +๐Ÿ  Roasted Sweet Potato U+1F360 +๐Ÿข Oden U+1F362 +๐Ÿฃ Sushi U+1F363 +๐Ÿค Fried Shrimp U+1F364 +๐Ÿฅ Fish Cake with Swirl U+1F365 +๐Ÿฅฎ Moon Cake U+1F96E +๐Ÿก Dango U+1F361 +๐ŸฅŸ Dumpling U+1F95F +๐Ÿฅ  Fortune Cookie U+1F960 +๐Ÿฅก Takeout Box U+1F961 +๐Ÿฆ€ Crab U+1F980 +๐Ÿฆž Lobster U+1F99E +๐Ÿฆ Shrimp U+1F990 +๐Ÿฆ‘ Squid U+1F991 +๐Ÿฆช Oyster U+1F9AA +๐Ÿฆ Soft Ice Cream U+1F366 +๐Ÿง Shaved Ice U+1F367 +๐Ÿจ Ice Cream U+1F368 +๐Ÿฉ Doughnut U+1F369 +๐Ÿช Cookie U+1F36A +๐ŸŽ‚ Birthday Cake U+1F382 +๐Ÿฐ Shortcake U+1F370 +๐Ÿง Cupcake U+1F9C1 +๐Ÿฅง Pie U+1F967 +๐Ÿซ Chocolate Bar U+1F36B +๐Ÿฌ Candy U+1F36C +๐Ÿญ Lollipop U+1F36D +๐Ÿฎ Custard U+1F36E +๐Ÿฏ Honey Pot U+1F36F +๐Ÿผ Baby Bottle U+1F37C +๐Ÿฅ› Glass of Milk U+1F95B +โ˜• Hot Beverage U+2615 +๐Ÿซ– Teapot U+1FAD6 +๐Ÿต Teacup Without Handle U+1F375 +๐Ÿถ Sake U+1F376 +๐Ÿพ Bottle with Popping Cork U+1F37E +๐Ÿท Wine Glass U+1F377 +๐Ÿธ Cocktail Glass U+1F378 +๐Ÿน Tropical Drink U+1F379 +๐Ÿบ Beer Mug U+1F37A +๐Ÿป Clinking Beer Mugs U+1F37B +๐Ÿฅ‚ Clinking Glasses U+1F942 +๐Ÿฅƒ Tumbler Glass U+1F943 +๐Ÿฅค Cup with Straw U+1F964 +๐Ÿง‹ Bubble Tea U+1F9CB +๐Ÿงƒ Beverage Box U+1F9C3 +๐Ÿง‰ Mate U+1F9C9 +๐ŸงŠ Ice U+1F9CA +๐Ÿฅข Chopsticks U+1F962 +๐Ÿฝ๏ธ Fork and Knife with Plate U+1F37D, U+FE0F +๐Ÿด Fork and Knife U+1F374 +๐Ÿฅ„ Spoon U+1F944 +๐Ÿ”ช Kitchen Knife U+1F52A +๐Ÿบ Amphora U+1F3FA +๐ŸŒ Globe Showing Europe-Africa U+1F30D +๐ŸŒŽ Globe Showing Americas U+1F30E +๐ŸŒ Globe Showing Asia-Australia U+1F30F +๐ŸŒ Globe with Meridians U+1F310 +๐Ÿ—บ๏ธ World Map U+1F5FA, U+FE0F +๐Ÿ—พ Map of Japan U+1F5FE +๐Ÿงญ Compass U+1F9ED +๐Ÿ”๏ธ Snow-Capped Mountain U+1F3D4, U+FE0F +โ›ฐ๏ธ Mountain U+26F0, U+FE0F +๐ŸŒ‹ Volcano U+1F30B +๐Ÿ—ป Mount Fuji U+1F5FB +๐Ÿ•๏ธ Camping U+1F3D5, U+FE0F +๐Ÿ–๏ธ Beach with Umbrella U+1F3D6, U+FE0F +๐Ÿœ๏ธ Desert U+1F3DC, U+FE0F +๐Ÿ๏ธ Desert Island U+1F3DD, U+FE0F +๐Ÿž๏ธ National Park U+1F3DE, U+FE0F +๐ŸŸ๏ธ Stadium U+1F3DF, U+FE0F +๐Ÿ›๏ธ Classical Building U+1F3DB, U+FE0F +๐Ÿ—๏ธ Building Construction U+1F3D7, U+FE0F +๐Ÿงฑ Brick U+1F9F1 +๐Ÿชจ Rock U+1FAA8 +๐Ÿชต Wood U+1FAB5 +๐Ÿ›– Hut U+1F6D6 +๐Ÿ˜๏ธ Houses U+1F3D8, U+FE0F +๐Ÿš๏ธ Derelict House U+1F3DA, U+FE0F +๐Ÿ  House U+1F3E0 +๐Ÿก House with Garden U+1F3E1 +๐Ÿข Office Building U+1F3E2 +๐Ÿฃ Japanese Post Office U+1F3E3 +๐Ÿค Post Office U+1F3E4 +๐Ÿฅ Hospital U+1F3E5 +๐Ÿฆ Bank U+1F3E6 +๐Ÿจ Hotel U+1F3E8 +๐Ÿฉ Love Hotel U+1F3E9 +๐Ÿช Convenience Store U+1F3EA +๐Ÿซ School U+1F3EB +๐Ÿฌ Department Store U+1F3EC +๐Ÿญ Factory U+1F3ED +๐Ÿฏ Japanese Castle U+1F3EF +๐Ÿฐ Castle U+1F3F0 +๐Ÿ’’ Wedding U+1F492 +๐Ÿ—ผ Tokyo Tower U+1F5FC +๐Ÿ—ฝ Statue of Liberty U+1F5FD +โ›ช Church U+26EA +๐Ÿ•Œ Mosque U+1F54C +๐Ÿ›• Hindu Temple U+1F6D5 +๐Ÿ• Synagogue U+1F54D +โ›ฉ๏ธ Shinto Shrine U+26E9, U+FE0F +๐Ÿ•‹ Kaaba U+1F54B +โ›ฒ Fountain U+26F2 +โ›บ Tent U+26FA +๐ŸŒ Foggy U+1F301 +๐ŸŒƒ Night with Stars U+1F303 +๐Ÿ™๏ธ Cityscape U+1F3D9, U+FE0F +๐ŸŒ„ Sunrise Over Mountains U+1F304 +๐ŸŒ… Sunrise U+1F305 +๐ŸŒ† Cityscape at Dusk U+1F306 +๐ŸŒ‡ Sunset U+1F307 +๐ŸŒ‰ Bridge at Night U+1F309 +โ™จ๏ธ Hot Springs U+2668, U+FE0F +๐ŸŽ  Carousel Horse U+1F3A0 +๐ŸŽก Ferris Wheel U+1F3A1 +๐ŸŽข Roller Coaster U+1F3A2 +๐Ÿ’ˆ Barber Pole U+1F488 +๐ŸŽช Circus Tent U+1F3AA +๐Ÿš‚ Locomotive U+1F682 +๐Ÿšƒ Railway Car U+1F683 +๐Ÿš„ High-Speed Train U+1F684 +๐Ÿš… Bullet Train U+1F685 +๐Ÿš† Train U+1F686 +๐Ÿš‡ Metro U+1F687 +๐Ÿšˆ Light Rail U+1F688 +๐Ÿš‰ Station U+1F689 +๐ŸšŠ Tram U+1F68A +๐Ÿš Monorail U+1F69D +๐Ÿšž Mountain Railway U+1F69E +๐Ÿš‹ Tram Car U+1F68B +๐ŸšŒ Bus U+1F68C +๐Ÿš Oncoming Bus U+1F68D +๐ŸšŽ Trolleybus U+1F68E +๐Ÿš Minibus U+1F690 +๐Ÿš‘ Ambulance U+1F691 +๐Ÿš’ Fire Engine U+1F692 +๐Ÿš“ Police Car U+1F693 +๐Ÿš” Oncoming Police Car U+1F694 +๐Ÿš• Taxi U+1F695 +๐Ÿš– Oncoming Taxi U+1F696 +๐Ÿš— Automobile U+1F697 +๐Ÿš˜ Oncoming Automobile U+1F698 +๐Ÿš™ Sport Utility Vehicle U+1F699 +๐Ÿ›ป Pickup Truck U+1F6FB +๐Ÿšš Delivery Truck U+1F69A +๐Ÿš› Articulated Lorry U+1F69B +๐Ÿšœ Tractor U+1F69C +๐ŸŽ๏ธ Racing Car U+1F3CE, U+FE0F +๐Ÿ๏ธ Motorcycle U+1F3CD, U+FE0F +๐Ÿ›ต Motor Scooter U+1F6F5 +๐Ÿฆฝ Manual Wheelchair U+1F9BD +๐Ÿฆผ Motorized Wheelchair U+1F9BC +๐Ÿ›บ Auto Rickshaw U+1F6FA +๐Ÿšฒ Bicycle U+1F6B2 +๐Ÿ›ด Kick Scooter U+1F6F4 +๐Ÿ›น Skateboard U+1F6F9 +๐Ÿ›ผ Roller Skate U+1F6FC +๐Ÿš Bus Stop U+1F68F +๐Ÿ›ฃ๏ธ Motorway U+1F6E3, U+FE0F +๐Ÿ›ค๏ธ Railway Track U+1F6E4, U+FE0F +๐Ÿ›ข๏ธ Oil Drum U+1F6E2, U+FE0F +โ›ฝ Fuel Pump U+26FD +๐Ÿšจ Police Car Light U+1F6A8 +๐Ÿšฅ Horizontal Traffic Light U+1F6A5 +๐Ÿšฆ Vertical Traffic Light U+1F6A6 +๐Ÿ›‘ Stop Sign U+1F6D1 +๐Ÿšง Construction U+1F6A7 +โš“ Anchor U+2693 +โ›ต Sailboat U+26F5 +๐Ÿ›ถ Canoe U+1F6F6 +๐Ÿšค Speedboat U+1F6A4 +๐Ÿ›ณ๏ธ Passenger Ship U+1F6F3, U+FE0F +โ›ด๏ธ Ferry U+26F4, U+FE0F +๐Ÿ›ฅ๏ธ Motor Boat U+1F6E5, U+FE0F +๐Ÿšข Ship U+1F6A2 +โœˆ๏ธ Airplane U+2708, U+FE0F +๐Ÿ›ฉ๏ธ Small Airplane U+1F6E9, U+FE0F +๐Ÿ›ซ Airplane Departure U+1F6EB +๐Ÿ›ฌ Airplane Arrival U+1F6EC +๐Ÿช‚ Parachute U+1FA82 +๐Ÿ’บ Seat U+1F4BA +๐Ÿš Helicopter U+1F681 +๐ŸšŸ Suspension Railway U+1F69F +๐Ÿš  Mountain Cableway U+1F6A0 +๐Ÿšก Aerial Tramway U+1F6A1 +๐Ÿ›ฐ๏ธ Satellite U+1F6F0, U+FE0F +๐Ÿš€ Rocket U+1F680 +๐Ÿ›ธ Flying Saucer U+1F6F8 +๐Ÿ›Ž๏ธ Bellhop Bell U+1F6CE, U+FE0F +๐Ÿงณ Luggage U+1F9F3 +โŒ› Hourglass Done U+231B +โณ Hourglass Not Done U+23F3 +โŒš Watch U+231A +โฐ Alarm Clock U+23F0 +โฑ๏ธ Stopwatch U+23F1, U+FE0F +โฒ๏ธ Timer Clock U+23F2, U+FE0F +๐Ÿ•ฐ๏ธ Mantelpiece Clock U+1F570, U+FE0F +๐Ÿ•› Twelve Oโ€™Clock U+1F55B +๐Ÿ•ง Twelve-Thirty U+1F567 +๐Ÿ• One Oโ€™Clock U+1F550 +๐Ÿ•œ One-Thirty U+1F55C +๐Ÿ•‘ Two Oโ€™Clock U+1F551 +๐Ÿ• Two-Thirty U+1F55D +๐Ÿ•’ Three Oโ€™Clock U+1F552 +๐Ÿ•ž Three-Thirty U+1F55E +๐Ÿ•“ Four Oโ€™Clock U+1F553 +๐Ÿ•Ÿ Four-Thirty U+1F55F +๐Ÿ•” Five Oโ€™Clock U+1F554 +๐Ÿ•  Five-Thirty U+1F560 +๐Ÿ•• Six Oโ€™Clock U+1F555 +๐Ÿ•ก Six-Thirty U+1F561 +๐Ÿ•– Seven Oโ€™Clock U+1F556 +๐Ÿ•ข Seven-Thirty U+1F562 +๐Ÿ•— Eight Oโ€™Clock U+1F557 +๐Ÿ•ฃ Eight-Thirty U+1F563 +๐Ÿ•˜ Nine Oโ€™Clock U+1F558 +๐Ÿ•ค Nine-Thirty U+1F564 +๐Ÿ•™ Ten Oโ€™Clock U+1F559 +๐Ÿ•ฅ Ten-Thirty U+1F565 +๐Ÿ•š Eleven Oโ€™Clock U+1F55A +๐Ÿ•ฆ Eleven-Thirty U+1F566 +๐ŸŒ‘ New Moon U+1F311 +๐ŸŒ’ Waxing Crescent Moon U+1F312 +๐ŸŒ“ First Quarter Moon U+1F313 +๐ŸŒ” Waxing Gibbous Moon U+1F314 +๐ŸŒ• Full Moon U+1F315 +๐ŸŒ– Waning Gibbous Moon U+1F316 +๐ŸŒ— Last Quarter Moon U+1F317 +๐ŸŒ˜ Waning Crescent Moon U+1F318 +๐ŸŒ™ Crescent Moon U+1F319 +๐ŸŒš New Moon Face U+1F31A +๐ŸŒ› First Quarter Moon Face U+1F31B +๐ŸŒœ Last Quarter Moon Face U+1F31C +๐ŸŒก๏ธ Thermometer U+1F321, U+FE0F +โ˜€๏ธ Sun U+2600, U+FE0F +๐ŸŒ Full Moon Face U+1F31D +๐ŸŒž Sun with Face U+1F31E +๐Ÿช Ringed Planet U+1FA90 +โญ Star U+2B50 +๐ŸŒŸ Glowing Star U+1F31F +๐ŸŒ  Shooting Star U+1F320 +๐ŸŒŒ Milky Way U+1F30C +โ˜๏ธ Cloud U+2601, U+FE0F +โ›… Sun Behind Cloud U+26C5 +โ›ˆ๏ธ Cloud with Lightning and Rain U+26C8, U+FE0F +๐ŸŒค๏ธ Sun Behind Small Cloud U+1F324, U+FE0F +๐ŸŒฅ๏ธ Sun Behind Large Cloud U+1F325, U+FE0F +๐ŸŒฆ๏ธ Sun Behind Rain Cloud U+1F326, U+FE0F +๐ŸŒง๏ธ Cloud with Rain U+1F327, U+FE0F +๐ŸŒจ๏ธ Cloud with Snow U+1F328, U+FE0F +๐ŸŒฉ๏ธ Cloud with Lightning U+1F329, U+FE0F +๐ŸŒช๏ธ Tornado U+1F32A, U+FE0F +๐ŸŒซ๏ธ Fog U+1F32B, U+FE0F +๐ŸŒฌ๏ธ Wind Face U+1F32C, U+FE0F +๐ŸŒ€ Cyclone U+1F300 +๐ŸŒˆ Rainbow U+1F308 +๐ŸŒ‚ Closed Umbrella U+1F302 +โ˜‚๏ธ Umbrella U+2602, U+FE0F +โ˜” Umbrella with Rain Drops U+2614 +โ›ฑ๏ธ Umbrella on Ground U+26F1, U+FE0F +โšก High Voltage U+26A1 +โ„๏ธ Snowflake U+2744, U+FE0F +โ˜ƒ๏ธ Snowman U+2603, U+FE0F +โ›„ Snowman Without Snow U+26C4 +โ˜„๏ธ Comet U+2604, U+FE0F +๐Ÿ”ฅ Fire U+1F525 +๐Ÿ’ง Droplet U+1F4A7 +๐ŸŒŠ Water Wave U+1F30A +๐ŸŽƒ Jack-O-Lantern U+1F383 +๐ŸŽ„ Christmas Tree U+1F384 +๐ŸŽ† Fireworks U+1F386 +๐ŸŽ‡ Sparkler U+1F387 +๐Ÿงจ Firecracker U+1F9E8 +โœจ Sparkles U+2728 +๐ŸŽˆ Balloon U+1F388 +๐ŸŽ‰ Party Popper U+1F389 +๐ŸŽŠ Confetti Ball U+1F38A +๐ŸŽ‹ Tanabata Tree U+1F38B +๐ŸŽ Pine Decoration U+1F38D +๐ŸŽŽ Japanese Dolls U+1F38E +๐ŸŽ Carp Streamer U+1F38F +๐ŸŽ Wind Chime U+1F390 +๐ŸŽ‘ Moon Viewing Ceremony U+1F391 +๐Ÿงง Red Envelope U+1F9E7 +๐ŸŽ€ Ribbon U+1F380 +๐ŸŽ Wrapped Gift U+1F381 +๐ŸŽ—๏ธ Reminder Ribbon U+1F397, U+FE0F +๐ŸŽŸ๏ธ Admission Tickets U+1F39F, U+FE0F +๐ŸŽซ Ticket U+1F3AB +๐ŸŽ–๏ธ Military Medal U+1F396, U+FE0F +๐Ÿ† Trophy U+1F3C6 +๐Ÿ… Sports Medal U+1F3C5 +๐Ÿฅ‡ 1st Place Medal U+1F947 +๐Ÿฅˆ 2nd Place Medal U+1F948 +๐Ÿฅ‰ 3rd Place Medal U+1F949 +โšฝ Soccer Ball U+26BD +โšพ Baseball U+26BE +๐ŸฅŽ Softball U+1F94E +๐Ÿ€ Basketball U+1F3C0 +๐Ÿ Volleyball U+1F3D0 +๐Ÿˆ American Football U+1F3C8 +๐Ÿ‰ Rugby Football U+1F3C9 +๐ŸŽพ Tennis U+1F3BE +๐Ÿฅ Flying Disc U+1F94F +๐ŸŽณ Bowling U+1F3B3 +๐Ÿ Cricket Game U+1F3CF +๐Ÿ‘ Field Hockey U+1F3D1 +๐Ÿ’ Ice Hockey U+1F3D2 +๐Ÿฅ Lacrosse U+1F94D +๐Ÿ“ Ping Pong U+1F3D3 +๐Ÿธ Badminton U+1F3F8 +๐ŸฅŠ Boxing Glove U+1F94A +๐Ÿฅ‹ Martial Arts Uniform U+1F94B +๐Ÿฅ… Goal Net U+1F945 +โ›ณ Flag in Hole U+26F3 +โ›ธ๏ธ Ice Skate U+26F8, U+FE0F +๐ŸŽฃ Fishing Pole U+1F3A3 +๐Ÿคฟ Diving Mask U+1F93F +๐ŸŽฝ Running Shirt U+1F3BD +๐ŸŽฟ Skis U+1F3BF +๐Ÿ›ท Sled U+1F6F7 +๐ŸฅŒ Curling Stone U+1F94C +๐ŸŽฏ Direct Hit U+1F3AF +๐Ÿช€ Yo-Yo U+1FA80 +๐Ÿช Kite U+1FA81 +๐ŸŽฑ Pool 8 Ball U+1F3B1 +๐Ÿ”ฎ Crystal Ball U+1F52E +๐Ÿช„ Magic Wand U+1FA84 +๐Ÿงฟ Nazar Amulet U+1F9FF +๐ŸŽฎ Video Game U+1F3AE +๐Ÿ•น๏ธ Joystick U+1F579, U+FE0F +๐ŸŽฐ Slot Machine U+1F3B0 +๐ŸŽฒ Game Die U+1F3B2 +๐Ÿงฉ Puzzle Piece U+1F9E9 +๐Ÿงธ Teddy Bear U+1F9F8 +๐Ÿช… Piรฑata U+1FA85 +๐Ÿช† Nesting Dolls U+1FA86 +โ™ ๏ธ Spade Suit U+2660, U+FE0F +โ™ฅ๏ธ Heart Suit U+2665, U+FE0F +โ™ฆ๏ธ Diamond Suit U+2666, U+FE0F +โ™ฃ๏ธ Club Suit U+2663, U+FE0F +โ™Ÿ๏ธ Chess Pawn U+265F, U+FE0F +๐Ÿƒ Joker U+1F0CF +๐Ÿ€„ Mahjong Red Dragon U+1F004 +๐ŸŽด Flower Playing Cards U+1F3B4 +๐ŸŽญ Performing Arts U+1F3AD +๐Ÿ–ผ๏ธ Framed Picture U+1F5BC, U+FE0F +๐ŸŽจ Artist Palette U+1F3A8 +๐Ÿงต Thread U+1F9F5 +๐Ÿชก Sewing Needle U+1FAA1 +๐Ÿงถ Yarn U+1F9F6 +๐Ÿชข Knot U+1FAA2 +๐Ÿ‘“ Glasses U+1F453 +๐Ÿ•ถ๏ธ Sunglasses U+1F576, U+FE0F +๐Ÿฅฝ Goggles U+1F97D +๐Ÿฅผ Lab Coat U+1F97C +๐Ÿฆบ Safety Vest U+1F9BA +๐Ÿ‘” Necktie U+1F454 +๐Ÿ‘• T-Shirt U+1F455 +๐Ÿ‘– Jeans U+1F456 +๐Ÿงฃ Scarf U+1F9E3 +๐Ÿงค Gloves U+1F9E4 +๐Ÿงฅ Coat U+1F9E5 +๐Ÿงฆ Socks U+1F9E6 +๐Ÿ‘— Dress U+1F457 +๐Ÿ‘˜ Kimono U+1F458 +๐Ÿฅป Sari U+1F97B +๐Ÿฉฑ One-Piece Swimsuit U+1FA71 +๐Ÿฉฒ Briefs U+1FA72 +๐Ÿฉณ Shorts U+1FA73 +๐Ÿ‘™ Bikini U+1F459 +๐Ÿ‘š Womanโ€™s Clothes U+1F45A +๐Ÿ‘› Purse U+1F45B +๐Ÿ‘œ Handbag U+1F45C +๐Ÿ‘ Clutch Bag U+1F45D +๐Ÿ›๏ธ Shopping Bags U+1F6CD, U+FE0F +๐ŸŽ’ Backpack U+1F392 +๐Ÿฉด Thong Sandal U+1FA74 +๐Ÿ‘ž Manโ€™s Shoe U+1F45E +๐Ÿ‘Ÿ Running Shoe U+1F45F +๐Ÿฅพ Hiking Boot U+1F97E +๐Ÿฅฟ Flat Shoe U+1F97F +๐Ÿ‘  High-Heeled Shoe U+1F460 +๐Ÿ‘ก Womanโ€™s Sandal U+1F461 +๐Ÿฉฐ Ballet Shoes U+1FA70 +๐Ÿ‘ข Womanโ€™s Boot U+1F462 +๐Ÿ‘‘ Crown U+1F451 +๐Ÿ‘’ Womanโ€™s Hat U+1F452 +๐ŸŽฉ Top Hat U+1F3A9 +๐ŸŽ“ Graduation Cap U+1F393 +๐Ÿงข Billed Cap U+1F9E2 +๐Ÿช– Military Helmet U+1FA96 +โ›‘๏ธ Rescue Workerโ€™s Helmet U+26D1, U+FE0F +๐Ÿ“ฟ Prayer Beads U+1F4FF +๐Ÿ’„ Lipstick U+1F484 +๐Ÿ’ Ring U+1F48D +๐Ÿ’Ž Gem Stone U+1F48E +๐Ÿ”‡ Muted Speaker U+1F507 +๐Ÿ”ˆ Speaker Low Volume U+1F508 +๐Ÿ”‰ Speaker Medium Volume U+1F509 +๐Ÿ”Š Speaker High Volume U+1F50A +๐Ÿ“ข Loudspeaker U+1F4E2 +๐Ÿ“ฃ Megaphone U+1F4E3 +๐Ÿ“ฏ Postal Horn U+1F4EF +๐Ÿ”” Bell U+1F514 +๐Ÿ”• Bell with Slash U+1F515 +๐ŸŽผ Musical Score U+1F3BC +๐ŸŽต Musical Note U+1F3B5 +๐ŸŽถ Musical Notes U+1F3B6 +๐ŸŽ™๏ธ Studio Microphone U+1F399, U+FE0F +๐ŸŽš๏ธ Level Slider U+1F39A, U+FE0F +๐ŸŽ›๏ธ Control Knobs U+1F39B, U+FE0F +๐ŸŽค Microphone U+1F3A4 +๐ŸŽง Headphone U+1F3A7 +๐Ÿ“ป Radio U+1F4FB +๐ŸŽท Saxophone U+1F3B7 +๐Ÿช— Accordion U+1FA97 +๐ŸŽธ Guitar U+1F3B8 +๐ŸŽน Musical Keyboard U+1F3B9 +๐ŸŽบ Trumpet U+1F3BA +๐ŸŽป Violin U+1F3BB +๐Ÿช• Banjo U+1FA95 +๐Ÿฅ Drum U+1F941 +๐Ÿช˜ Long Drum U+1FA98 +๐Ÿ“ฑ Mobile Phone U+1F4F1 +๐Ÿ“ฒ Mobile Phone with Arrow U+1F4F2 +โ˜Ž๏ธ Telephone U+260E, U+FE0F +๐Ÿ“ž Telephone Receiver U+1F4DE +๐Ÿ“Ÿ Pager U+1F4DF +๐Ÿ“  Fax Machine U+1F4E0 +๐Ÿ”‹ Battery U+1F50B +๐Ÿ”Œ Electric Plug U+1F50C +๐Ÿ’ป Laptop U+1F4BB +๐Ÿ–ฅ๏ธ Desktop Computer U+1F5A5, U+FE0F +๐Ÿ–จ๏ธ Printer U+1F5A8, U+FE0F +โŒจ๏ธ Keyboard U+2328, U+FE0F +๐Ÿ–ฑ๏ธ Computer Mouse U+1F5B1, U+FE0F +๐Ÿ–ฒ๏ธ Trackball U+1F5B2, U+FE0F +๐Ÿ’ฝ Computer Disk U+1F4BD +๐Ÿ’พ Floppy Disk U+1F4BE +๐Ÿ’ฟ Optical Disk U+1F4BF +๐Ÿ“€ DVD U+1F4C0 +๐Ÿงฎ Abacus U+1F9EE +๐ŸŽฅ Movie Camera U+1F3A5 +๐ŸŽž๏ธ Film Frames U+1F39E, U+FE0F +๐Ÿ“ฝ๏ธ Film Projector U+1F4FD, U+FE0F +๐ŸŽฌ Clapper Board U+1F3AC +๐Ÿ“บ Television U+1F4FA +๐Ÿ“ท Camera U+1F4F7 +๐Ÿ“ธ Camera with Flash U+1F4F8 +๐Ÿ“น Video Camera U+1F4F9 +๐Ÿ“ผ Videocassette U+1F4FC +๐Ÿ” Magnifying Glass Tilted Left U+1F50D +๐Ÿ”Ž Magnifying Glass Tilted Right U+1F50E +๐Ÿ•ฏ๏ธ Candle U+1F56F, U+FE0F +๐Ÿ’ก Light Bulb U+1F4A1 +๐Ÿ”ฆ Flashlight U+1F526 +๐Ÿฎ Red Paper Lantern U+1F3EE +๐Ÿช” Diya Lamp U+1FA94 +๐Ÿ“” Notebook with Decorative Cover U+1F4D4 +๐Ÿ“• Closed Book U+1F4D5 +๐Ÿ“– Open Book U+1F4D6 +๐Ÿ“— Green Book U+1F4D7 +๐Ÿ“˜ Blue Book U+1F4D8 +๐Ÿ“™ Orange Book U+1F4D9 +๐Ÿ“š Books U+1F4DA +๐Ÿ““ Notebook U+1F4D3 +๐Ÿ“’ Ledger U+1F4D2 +๐Ÿ“ƒ Page with Curl U+1F4C3 +๐Ÿ“œ Scroll U+1F4DC +๐Ÿ“„ Page Facing Up U+1F4C4 +๐Ÿ“ฐ Newspaper U+1F4F0 +๐Ÿ—ž๏ธ Rolled-Up Newspaper U+1F5DE, U+FE0F +๐Ÿ“‘ Bookmark Tabs U+1F4D1 +๐Ÿ”– Bookmark U+1F516 +๐Ÿท๏ธ Label U+1F3F7, U+FE0F +๐Ÿ’ฐ Money Bag U+1F4B0 +๐Ÿช™ Coin U+1FA99 +๐Ÿ’ด Yen Banknote U+1F4B4 +๐Ÿ’ต Dollar Banknote U+1F4B5 +๐Ÿ’ถ Euro Banknote U+1F4B6 +๐Ÿ’ท Pound Banknote U+1F4B7 +๐Ÿ’ธ Money with Wings U+1F4B8 +๐Ÿ’ณ Credit Card U+1F4B3 +๐Ÿงพ Receipt U+1F9FE +๐Ÿ’น Chart Increasing with Yen U+1F4B9 +โœ‰๏ธ Envelope U+2709, U+FE0F +๐Ÿ“ง E-Mail U+1F4E7 +๐Ÿ“จ Incoming Envelope U+1F4E8 +๐Ÿ“ฉ Envelope with Arrow U+1F4E9 +๐Ÿ“ค Outbox Tray U+1F4E4 +๐Ÿ“ฅ Inbox Tray U+1F4E5 +๐Ÿ“ฆ Package U+1F4E6 +๐Ÿ“ซ Closed Mailbox with Raised Flag U+1F4EB +๐Ÿ“ช Closed Mailbox with Lowered Flag U+1F4EA +๐Ÿ“ฌ Open Mailbox with Raised Flag U+1F4EC +๐Ÿ“ญ Open Mailbox with Lowered Flag U+1F4ED +๐Ÿ“ฎ Postbox U+1F4EE +๐Ÿ—ณ๏ธ Ballot Box with Ballot U+1F5F3, U+FE0F +โœ๏ธ Pencil U+270F, U+FE0F +โœ’๏ธ Black Nib U+2712, U+FE0F +๐Ÿ–‹๏ธ Fountain Pen U+1F58B, U+FE0F +๐Ÿ–Š๏ธ Pen U+1F58A, U+FE0F +๐Ÿ–Œ๏ธ Paintbrush U+1F58C, U+FE0F +๐Ÿ–๏ธ Crayon U+1F58D, U+FE0F +๐Ÿ“ Memo U+1F4DD +๐Ÿ’ผ Briefcase U+1F4BC +๐Ÿ“ File Folder U+1F4C1 +๐Ÿ“‚ Open File Folder U+1F4C2 +๐Ÿ—‚๏ธ Card Index Dividers U+1F5C2, U+FE0F +๐Ÿ“… Calendar U+1F4C5 +๐Ÿ“† Tear-Off Calendar U+1F4C6 +๐Ÿ—’๏ธ Spiral Notepad U+1F5D2, U+FE0F +๐Ÿ—“๏ธ Spiral Calendar U+1F5D3, U+FE0F +๐Ÿ“‡ Card Index U+1F4C7 +๐Ÿ“ˆ Chart Increasing U+1F4C8 +๐Ÿ“‰ Chart Decreasing U+1F4C9 +๐Ÿ“Š Bar Chart U+1F4CA +๐Ÿ“‹ Clipboard U+1F4CB +๐Ÿ“Œ Pushpin U+1F4CC +๐Ÿ“ Round Pushpin U+1F4CD +๐Ÿ“Ž Paperclip U+1F4CE +๐Ÿ–‡๏ธ Linked Paperclips U+1F587, U+FE0F +๐Ÿ“ Straight Ruler U+1F4CF +๐Ÿ“ Triangular Ruler U+1F4D0 +โœ‚๏ธ Scissors U+2702, U+FE0F +๐Ÿ—ƒ๏ธ Card File Box U+1F5C3, U+FE0F +๐Ÿ—„๏ธ File Cabinet U+1F5C4, U+FE0F +๐Ÿ—‘๏ธ Wastebasket U+1F5D1, U+FE0F +๐Ÿ”’ Locked U+1F512 +๐Ÿ”“ Unlocked U+1F513 +๐Ÿ” Locked with Pen U+1F50F +๐Ÿ” Locked with Key U+1F510 +๐Ÿ”‘ Key U+1F511 +๐Ÿ—๏ธ Old Key U+1F5DD, U+FE0F +๐Ÿ”จ Hammer U+1F528 +๐Ÿช“ Axe U+1FA93 +โ›๏ธ Pick U+26CF, U+FE0F +โš’๏ธ Hammer and Pick U+2692, U+FE0F +๐Ÿ› ๏ธ Hammer and Wrench U+1F6E0, U+FE0F +๐Ÿ—ก๏ธ Dagger U+1F5E1, U+FE0F +โš”๏ธ Crossed Swords U+2694, U+FE0F +๐Ÿ”ซ Pistol U+1F52B +๐Ÿชƒ Boomerang U+1FA83 +๐Ÿน Bow and Arrow U+1F3F9 +๐Ÿ›ก๏ธ Shield U+1F6E1, U+FE0F +๐Ÿชš Carpentry Saw U+1FA9A +๐Ÿ”ง Wrench U+1F527 +๐Ÿช› Screwdriver U+1FA9B +๐Ÿ”ฉ Nut and Bolt U+1F529 +โš™๏ธ Gear U+2699, U+FE0F +๐Ÿ—œ๏ธ Clamp U+1F5DC, U+FE0F +โš–๏ธ Balance Scale U+2696, U+FE0F +๐Ÿฆฏ White Cane U+1F9AF +๐Ÿ”— Link U+1F517 +โ›“๏ธ Chains U+26D3, U+FE0F +๐Ÿช Hook U+1FA9D +๐Ÿงฐ Toolbox U+1F9F0 +๐Ÿงฒ Magnet U+1F9F2 +๐Ÿชœ Ladder U+1FA9C +โš—๏ธ Alembic U+2697, U+FE0F +๐Ÿงช Test Tube U+1F9EA +๐Ÿงซ Petri Dish U+1F9EB +๐Ÿงฌ DNA U+1F9EC +๐Ÿ”ฌ Microscope U+1F52C +๐Ÿ”ญ Telescope U+1F52D +๐Ÿ“ก Satellite Antenna U+1F4E1 +๐Ÿ’‰ Syringe U+1F489 +๐Ÿฉธ Drop of Blood U+1FA78 +๐Ÿ’Š Pill U+1F48A +๐Ÿฉน Adhesive Bandage U+1FA79 +๐Ÿฉบ Stethoscope U+1FA7A +๐Ÿšช Door U+1F6AA +๐Ÿ›— Elevator U+1F6D7 +๐Ÿชž Mirror U+1FA9E +๐ŸชŸ Window U+1FA9F +๐Ÿ›๏ธ Bed U+1F6CF, U+FE0F +๐Ÿ›‹๏ธ Couch and Lamp U+1F6CB, U+FE0F +๐Ÿช‘ Chair U+1FA91 +๐Ÿšฝ Toilet U+1F6BD +๐Ÿช  Plunger U+1FAA0 +๐Ÿšฟ Shower U+1F6BF +๐Ÿ› Bathtub U+1F6C1 +๐Ÿชค Mouse Trap U+1FAA4 +๐Ÿช’ Razor U+1FA92 +๐Ÿงด Lotion Bottle U+1F9F4 +๐Ÿงท Safety Pin U+1F9F7 +๐Ÿงน Broom U+1F9F9 +๐Ÿงบ Basket U+1F9FA +๐Ÿงป Roll of Paper U+1F9FB +๐Ÿชฃ Bucket U+1FAA3 +๐Ÿงผ Soap U+1F9FC +๐Ÿชฅ Toothbrush U+1FAA5 +๐Ÿงฝ Sponge U+1F9FD +๐Ÿงฏ Fire Extinguisher U+1F9EF +๐Ÿ›’ Shopping Cart U+1F6D2 +๐Ÿšฌ Cigarette U+1F6AC +โšฐ๏ธ Coffin U+26B0, U+FE0F +๐Ÿชฆ Headstone U+1FAA6 +โšฑ๏ธ Funeral Urn U+26B1, U+FE0F +๐Ÿ—ฟ Moai U+1F5FF +๐Ÿชง Placard U+1FAA7 +๐Ÿง ATM Sign U+1F3E7 +๐Ÿšฎ Litter in Bin Sign U+1F6AE +๐Ÿšฐ Potable Water U+1F6B0 +โ™ฟ Wheelchair Symbol U+267F +๐Ÿšน Menโ€™s Room U+1F6B9 +๐Ÿšบ Womenโ€™s Room U+1F6BA +๐Ÿšป Restroom U+1F6BB +๐Ÿšผ Baby Symbol U+1F6BC +๐Ÿšพ Water Closet U+1F6BE +๐Ÿ›‚ Passport Control U+1F6C2 +๐Ÿ›ƒ Customs U+1F6C3 +๐Ÿ›„ Baggage Claim U+1F6C4 +๐Ÿ›… Left Luggage U+1F6C5 +โš ๏ธ Warning U+26A0, U+FE0F +๐Ÿšธ Children Crossing U+1F6B8 +โ›” No Entry U+26D4 +๐Ÿšซ Prohibited U+1F6AB +๐Ÿšณ No Bicycles U+1F6B3 +๐Ÿšญ No Smoking U+1F6AD +๐Ÿšฏ No Littering U+1F6AF +๐Ÿšฑ Non-Potable Water U+1F6B1 +๐Ÿšท No Pedestrians U+1F6B7 +๐Ÿ“ต No Mobile Phones U+1F4F5 +๐Ÿ”ž No One Under Eighteen U+1F51E +โ˜ข๏ธ Radioactive U+2622, U+FE0F +โ˜ฃ๏ธ Biohazard U+2623, U+FE0F +โฌ†๏ธ Up Arrow U+2B06, U+FE0F +โ†—๏ธ Up-Right Arrow U+2197, U+FE0F +โžก๏ธ Right Arrow U+27A1, U+FE0F +โ†˜๏ธ Down-Right Arrow U+2198, U+FE0F +โฌ‡๏ธ Down Arrow U+2B07, U+FE0F +โ†™๏ธ Down-Left Arrow U+2199, U+FE0F +โฌ…๏ธ Left Arrow U+2B05, U+FE0F +โ†–๏ธ Up-Left Arrow U+2196, U+FE0F +โ†•๏ธ Up-Down Arrow U+2195, U+FE0F +โ†”๏ธ Left-Right Arrow U+2194, U+FE0F +โ†ฉ๏ธ Right Arrow Curving Left U+21A9, U+FE0F +โ†ช๏ธ Left Arrow Curving Right U+21AA, U+FE0F +โคด๏ธ Right Arrow Curving Up U+2934, U+FE0F +โคต๏ธ Right Arrow Curving Down U+2935, U+FE0F +๐Ÿ”ƒ Clockwise Vertical Arrows U+1F503 +๐Ÿ”„ Counterclockwise Arrows Button U+1F504 +๐Ÿ”™ Back Arrow U+1F519 +๐Ÿ”š End Arrow U+1F51A +๐Ÿ”› On! Arrow U+1F51B +๐Ÿ”œ Soon Arrow U+1F51C +๐Ÿ” Top Arrow U+1F51D +๐Ÿ› Place of Worship U+1F6D0 +โš›๏ธ Atom Symbol U+269B, U+FE0F +๐Ÿ•‰๏ธ Om U+1F549, U+FE0F +โœก๏ธ Star of David U+2721, U+FE0F +โ˜ธ๏ธ Wheel of Dharma U+2638, U+FE0F +โ˜ฏ๏ธ Yin Yang U+262F, U+FE0F +โœ๏ธ Latin Cross U+271D, U+FE0F +โ˜ฆ๏ธ Orthodox Cross U+2626, U+FE0F +โ˜ช๏ธ Star and Crescent U+262A, U+FE0F +โ˜ฎ๏ธ Peace Symbol U+262E, U+FE0F +๐Ÿ•Ž Menorah U+1F54E +๐Ÿ”ฏ Dotted Six-Pointed Star U+1F52F +โ™ˆ Aries U+2648 +โ™‰ Taurus U+2649 +โ™Š Gemini U+264A +โ™‹ Cancer U+264B +โ™Œ Leo U+264C +โ™ Virgo U+264D +โ™Ž Libra U+264E +โ™ Scorpio U+264F +โ™ Sagittarius U+2650 +โ™‘ Capricorn U+2651 +โ™’ Aquarius U+2652 +โ™“ Pisces U+2653 +โ›Ž Ophiuchus U+26CE +๐Ÿ”€ Shuffle Tracks Button U+1F500 +๐Ÿ” Repeat Button U+1F501 +๐Ÿ”‚ Repeat Single Button U+1F502 +โ–ถ๏ธ Play Button U+25B6, U+FE0F +โฉ Fast-Forward Button U+23E9 +โญ๏ธ Next Track Button U+23ED, U+FE0F +โฏ๏ธ Play or Pause Button U+23EF, U+FE0F +โ—€๏ธ Reverse Button U+25C0, U+FE0F +โช Fast Reverse Button U+23EA +โฎ๏ธ Last Track Button U+23EE, U+FE0F +๐Ÿ”ผ Upwards Button U+1F53C +โซ Fast Up Button U+23EB +๐Ÿ”ฝ Downwards Button U+1F53D +โฌ Fast Down Button U+23EC +โธ๏ธ Pause Button U+23F8, U+FE0F +โน๏ธ Stop Button U+23F9, U+FE0F +โบ๏ธ Record Button U+23FA, U+FE0F +โ๏ธ Eject Button U+23CF, U+FE0F +๐ŸŽฆ Cinema U+1F3A6 +๐Ÿ”… Dim Button U+1F505 +๐Ÿ”† Bright Button U+1F506 +๐Ÿ“ถ Antenna Bars U+1F4F6 +๐Ÿ“ณ Vibration Mode U+1F4F3 +๐Ÿ“ด Mobile Phone Off U+1F4F4 +โ™€๏ธ Female Sign U+2640, U+FE0F +โ™‚๏ธ Male Sign U+2642, U+FE0F +โšง๏ธ Transgender Symbol U+26A7, U+FE0F +โœ–๏ธ Multiply U+2716, U+FE0F +โž• Plus U+2795 +โž– Minus U+2796 +โž— Divide U+2797 +โ™พ๏ธ Infinity U+267E, U+FE0F +โ€ผ๏ธ Double Exclamation Mark U+203C, U+FE0F +โ‰๏ธ Exclamation Question Mark U+2049, U+FE0F +โ“ Question Mark U+2753 +โ” White Question Mark U+2754 +โ• White Exclamation Mark U+2755 +โ— Exclamation Mark U+2757 +ใ€ฐ๏ธ Wavy Dash U+3030, U+FE0F +๐Ÿ’ฑ Currency Exchange U+1F4B1 +๐Ÿ’ฒ Heavy Dollar Sign U+1F4B2 +โš•๏ธ Medical Symbol U+2695, U+FE0F +โ™ป๏ธ Recycling Symbol U+267B, U+FE0F +โšœ๏ธ Fleur-de-lis U+269C, U+FE0F +๐Ÿ”ฑ Trident Emblem U+1F531 +๐Ÿ“› Name Badge U+1F4DB +๐Ÿ”ฐ Japanese Symbol for Beginner U+1F530 +โญ• Hollow Red Circle U+2B55 +โœ… Check Mark Button U+2705 +โ˜‘๏ธ Check Box with Check U+2611, U+FE0F +โœ”๏ธ Check Mark U+2714, U+FE0F +โŒ Cross Mark U+274C +โŽ Cross Mark Button U+274E +โžฐ Curly Loop U+27B0 +โžฟ Double Curly Loop U+27BF +ใ€ฝ๏ธ Part Alternation Mark U+303D, U+FE0F +โœณ๏ธ Eight-Spoked Asterisk U+2733, U+FE0F +โœด๏ธ Eight-Pointed Star U+2734, U+FE0F +โ‡๏ธ Sparkle U+2747, U+FE0F +ยฉ๏ธ Copyright U+A9, U+FE0F +ยฎ๏ธ Registered U+AE, U+FE0F +โ„ข๏ธ Trade Mark U+2122, U+FE0F +#๏ธโƒฃ Keycap Number Sign U+23, U+FE0F, U+20E3 +*๏ธโƒฃ Keycap Asterisk U+2A, U+FE0F, U+20E3 +0๏ธโƒฃ Keycap Digit Zero U+30, U+FE0F, U+20E3 +1๏ธโƒฃ Keycap Digit One U+31, U+FE0F, U+20E3 +2๏ธโƒฃ Keycap Digit Two U+32, U+FE0F, U+20E3 +3๏ธโƒฃ Keycap Digit Three U+33, U+FE0F, U+20E3 +4๏ธโƒฃ Keycap Digit Four U+34, U+FE0F, U+20E3 +5๏ธโƒฃ Keycap Digit Five U+35, U+FE0F, U+20E3 +6๏ธโƒฃ Keycap Digit Six U+36, U+FE0F, U+20E3 +7๏ธโƒฃ Keycap Digit Seven U+37, U+FE0F, U+20E3 +8๏ธโƒฃ Keycap Digit Eight U+38, U+FE0F, U+20E3 +9๏ธโƒฃ Keycap Digit Nine U+39, U+FE0F, U+20E3 +๐Ÿ”Ÿ Keycap: 10 U+1F51F +๐Ÿ”  Input Latin Uppercase U+1F520 +๐Ÿ”ก Input Latin Lowercase U+1F521 +๐Ÿ”ข Input Numbers U+1F522 +๐Ÿ”ฃ Input Symbols U+1F523 +๐Ÿ”ค Input Latin Letters U+1F524 +๐Ÿ…ฐ๏ธ A Button (Blood Type) U+1F170, U+FE0F +๐Ÿ†Ž AB Button (Blood Type) U+1F18E +๐Ÿ…ฑ๏ธ B Button (Blood Type) U+1F171, U+FE0F +๐Ÿ†‘ CL Button U+1F191 +๐Ÿ†’ Cool Button U+1F192 +๐Ÿ†“ Free Button U+1F193 +โ„น๏ธ Information U+2139, U+FE0F +๐Ÿ†” ID Button U+1F194 +โ“‚๏ธ Circled M U+24C2, U+FE0F +๐Ÿ†• New Button U+1F195 +๐Ÿ†– NG Button U+1F196 +๐Ÿ…พ๏ธ O Button (Blood Type) U+1F17E, U+FE0F +๐Ÿ†— OK Button U+1F197 +๐Ÿ…ฟ๏ธ P Button U+1F17F, U+FE0F +๐Ÿ†˜ SOS Button U+1F198 +๐Ÿ†™ Up! Button U+1F199 +๐Ÿ†š Vs Button U+1F19A +๐Ÿˆ Japanese โ€œHereโ€ Button U+1F201 +๐Ÿˆ‚๏ธ Japanese โ€œService Chargeโ€ Button U+1F202, U+FE0F +๐Ÿˆท๏ธ Japanese โ€œMonthly Amountโ€ Button U+1F237, U+FE0F +๐Ÿˆถ Japanese โ€œNot Free of Chargeโ€ Button U+1F236 +๐Ÿˆฏ Japanese โ€œReservedโ€ Button U+1F22F +๐Ÿ‰ Japanese โ€œBargainโ€ Button U+1F250 +๐Ÿˆน Japanese โ€œDiscountโ€ Button U+1F239 +๐Ÿˆš Japanese โ€œFree of Chargeโ€ Button U+1F21A +๐Ÿˆฒ Japanese โ€œProhibitedโ€ Button U+1F232 +๐Ÿ‰‘ Japanese โ€œAcceptableโ€ Button U+1F251 +๐Ÿˆธ Japanese โ€œApplicationโ€ Button U+1F238 +๐Ÿˆด Japanese โ€œPassing Gradeโ€ Button U+1F234 +๐Ÿˆณ Japanese โ€œVacancyโ€ Button U+1F233 +ใŠ—๏ธ Japanese โ€œCongratulationsโ€ Button U+3297, U+FE0F +ใŠ™๏ธ Japanese โ€œSecretโ€ Button U+3299, U+FE0F +๐Ÿˆบ Japanese โ€œOpen for Businessโ€ Button U+1F23A +๐Ÿˆต Japanese โ€œNo Vacancyโ€ Button U+1F235 +๐Ÿ”ด Red Circle U+1F534 +๐ŸŸ  Orange Circle U+1F7E0 +๐ŸŸก Yellow Circle U+1F7E1 +๐ŸŸข Green Circle U+1F7E2 +๐Ÿ”ต Blue Circle U+1F535 +๐ŸŸฃ Purple Circle U+1F7E3 +๐ŸŸค Brown Circle U+1F7E4 +โšซ Black Circle U+26AB +โšช White Circle U+26AA +๐ŸŸฅ Red Square U+1F7E5 +๐ŸŸง Orange Square U+1F7E7 +๐ŸŸจ Yellow Square U+1F7E8 +๐ŸŸฉ Green Square U+1F7E9 +๐ŸŸฆ Blue Square U+1F7E6 +๐ŸŸช Purple Square U+1F7EA +๐ŸŸซ Brown Square U+1F7EB +โฌ› Black Large Square U+2B1B +โฌœ White Large Square U+2B1C +โ—ผ๏ธ Black Medium Square U+25FC, U+FE0F +โ—ป๏ธ White Medium Square U+25FB, U+FE0F +โ—พ Black Medium-Small Square U+25FE +โ—ฝ White Medium-Small Square U+25FD +โ–ช๏ธ Black Small Square U+25AA, U+FE0F +โ–ซ๏ธ White Small Square U+25AB, U+FE0F +๐Ÿ”ถ Large Orange Diamond U+1F536 +๐Ÿ”ท Large Blue Diamond U+1F537 +๐Ÿ”ธ Small Orange Diamond U+1F538 +๐Ÿ”น Small Blue Diamond U+1F539 +๐Ÿ”บ Red Triangle Pointed Up U+1F53A +๐Ÿ”ป Red Triangle Pointed Down U+1F53B +๐Ÿ’  Diamond with a Dot U+1F4A0 +๐Ÿ”˜ Radio Button U+1F518 +๐Ÿ”ณ White Square Button U+1F533 +๐Ÿ”ฒ Black Square Button U+1F532 +๐Ÿ Chequered Flag U+1F3C1 +๐Ÿšฉ Triangular Flag U+1F6A9 +๐ŸŽŒ Crossed Flags U+1F38C +๐Ÿด Black Flag U+1F3F4 +๐Ÿณ๏ธ White Flag U+1F3F3, U+FE0F +๐Ÿณ๏ธโ€๐ŸŒˆ Rainbow Flag U+1F3F3, U+FE0F, U+200D, U+1F308 +๐Ÿณ๏ธโ€โšง๏ธ Transgender Flag U+1F3F3, U+FE0F, U+200D, U+26A7, + U+FE0F +๐Ÿดโ€โ˜ ๏ธ Pirate Flag U+1F3F4, U+200D, U+2620, U+FE0F +๐Ÿ‡ฆ๐Ÿ‡จ Flag: Ascension Island U+1F1E6, U+1F1E8 +๐Ÿ‡ฆ๐Ÿ‡ฉ Flag: Andorra U+1F1E6, U+1F1E9 +๐Ÿ‡ฆ๐Ÿ‡ช Flag: United Arab Emirates U+1F1E6, U+1F1EA +๐Ÿ‡ฆ๐Ÿ‡ซ Flag: Afghanistan U+1F1E6, U+1F1EB +๐Ÿ‡ฆ๐Ÿ‡ฌ Flag: Antigua & Barbuda U+1F1E6, U+1F1EC +๐Ÿ‡ฆ๐Ÿ‡ฎ Flag: Anguilla U+1F1E6, U+1F1EE +๐Ÿ‡ฆ๐Ÿ‡ฑ Flag: Albania U+1F1E6, U+1F1F1 +๐Ÿ‡ฆ๐Ÿ‡ฒ Flag: Armenia U+1F1E6, U+1F1F2 +๐Ÿ‡ฆ๐Ÿ‡ด Flag: Angola U+1F1E6, U+1F1F4 +๐Ÿ‡ฆ๐Ÿ‡ถ Flag: Antarctica U+1F1E6, U+1F1F6 +๐Ÿ‡ฆ๐Ÿ‡ท Flag: Argentina U+1F1E6, U+1F1F7 +๐Ÿ‡ฆ๐Ÿ‡ธ Flag: American Samoa U+1F1E6, U+1F1F8 +๐Ÿ‡ฆ๐Ÿ‡น Flag: Austria U+1F1E6, U+1F1F9 +๐Ÿ‡ฆ๐Ÿ‡บ Flag: Australia U+1F1E6, U+1F1FA +๐Ÿ‡ฆ๐Ÿ‡ผ Flag: Aruba U+1F1E6, U+1F1FC +๐Ÿ‡ฆ๐Ÿ‡ฝ Flag: ร…land Islands U+1F1E6, U+1F1FD +๐Ÿ‡ฆ๐Ÿ‡ฟ Flag: Azerbaijan U+1F1E6, U+1F1FF +๐Ÿ‡ง๐Ÿ‡ฆ Flag: Bosnia & Herzegovina U+1F1E7, U+1F1E6 +๐Ÿ‡ง๐Ÿ‡ง Flag: Barbados U+1F1E7, U+1F1E7 +๐Ÿ‡ง๐Ÿ‡ฉ Flag: Bangladesh U+1F1E7, U+1F1E9 +๐Ÿ‡ง๐Ÿ‡ช Flag: Belgium U+1F1E7, U+1F1EA +๐Ÿ‡ง๐Ÿ‡ซ Flag: Burkina Faso U+1F1E7, U+1F1EB +๐Ÿ‡ง๐Ÿ‡ฌ Flag: Bulgaria U+1F1E7, U+1F1EC +๐Ÿ‡ง๐Ÿ‡ญ Flag: Bahrain U+1F1E7, U+1F1ED +๐Ÿ‡ง๐Ÿ‡ฎ Flag: Burundi U+1F1E7, U+1F1EE +๐Ÿ‡ง๐Ÿ‡ฏ Flag: Benin U+1F1E7, U+1F1EF +๐Ÿ‡ง๐Ÿ‡ฑ Flag: St. Barthรฉlemy U+1F1E7, U+1F1F1 +๐Ÿ‡ง๐Ÿ‡ฒ Flag: Bermuda U+1F1E7, U+1F1F2 +๐Ÿ‡ง๐Ÿ‡ณ Flag: Brunei U+1F1E7, U+1F1F3 +๐Ÿ‡ง๐Ÿ‡ด Flag: Bolivia U+1F1E7, U+1F1F4 +๐Ÿ‡ง๐Ÿ‡ถ Flag: Caribbean Netherlands U+1F1E7, U+1F1F6 +๐Ÿ‡ง๐Ÿ‡ท Flag: Brazil U+1F1E7, U+1F1F7 +๐Ÿ‡ง๐Ÿ‡ธ Flag: Bahamas U+1F1E7, U+1F1F8 +๐Ÿ‡ง๐Ÿ‡น Flag: Bhutan U+1F1E7, U+1F1F9 +๐Ÿ‡ง๐Ÿ‡ป Flag: Bouvet Island U+1F1E7, U+1F1FB +๐Ÿ‡ง๐Ÿ‡ผ Flag: Botswana U+1F1E7, U+1F1FC +๐Ÿ‡ง๐Ÿ‡พ Flag: Belarus U+1F1E7, U+1F1FE +๐Ÿ‡ง๐Ÿ‡ฟ Flag: Belize U+1F1E7, U+1F1FF +๐Ÿ‡จ๐Ÿ‡ฆ Flag: Canada U+1F1E8, U+1F1E6 +๐Ÿ‡จ๐Ÿ‡จ Flag: Cocos (Keeling) Islands U+1F1E8, U+1F1E8 +๐Ÿ‡จ๐Ÿ‡ฉ Flag: Congo - Kinshasa U+1F1E8, U+1F1E9 +๐Ÿ‡จ๐Ÿ‡ซ Flag: Central African Republic U+1F1E8, U+1F1EB +๐Ÿ‡จ๐Ÿ‡ฌ Flag: Congo - Brazzaville U+1F1E8, U+1F1EC +๐Ÿ‡จ๐Ÿ‡ญ Flag: Switzerland U+1F1E8, U+1F1ED +๐Ÿ‡จ๐Ÿ‡ฎ Flag: Cรดte dโ€™Ivoire U+1F1E8, U+1F1EE +๐Ÿ‡จ๐Ÿ‡ฐ Flag: Cook Islands U+1F1E8, U+1F1F0 +๐Ÿ‡จ๐Ÿ‡ฑ Flag: Chile U+1F1E8, U+1F1F1 +๐Ÿ‡จ๐Ÿ‡ฒ Flag: Cameroon U+1F1E8, U+1F1F2 +๐Ÿ‡จ๐Ÿ‡ณ Flag: China U+1F1E8, U+1F1F3 +๐Ÿ‡จ๐Ÿ‡ด Flag: Colombia U+1F1E8, U+1F1F4 +๐Ÿ‡จ๐Ÿ‡ต Flag: Clipperton Island U+1F1E8, U+1F1F5 +๐Ÿ‡จ๐Ÿ‡ท Flag: Costa Rica U+1F1E8, U+1F1F7 +๐Ÿ‡จ๐Ÿ‡บ Flag: Cuba U+1F1E8, U+1F1FA +๐Ÿ‡จ๐Ÿ‡ป Flag: Cape Verde U+1F1E8, U+1F1FB +๐Ÿ‡จ๐Ÿ‡ผ Flag: Curaรงao U+1F1E8, U+1F1FC +๐Ÿ‡จ๐Ÿ‡ฝ Flag: Christmas Island U+1F1E8, U+1F1FD +๐Ÿ‡จ๐Ÿ‡พ Flag: Cyprus U+1F1E8, U+1F1FE +๐Ÿ‡จ๐Ÿ‡ฟ Flag: Czechia U+1F1E8, U+1F1FF +๐Ÿ‡ฉ๐Ÿ‡ช Flag: Germany U+1F1E9, U+1F1EA +๐Ÿ‡ฉ๐Ÿ‡ฌ Flag: Diego Garcia U+1F1E9, U+1F1EC +๐Ÿ‡ฉ๐Ÿ‡ฏ Flag: Djibouti U+1F1E9, U+1F1EF +๐Ÿ‡ฉ๐Ÿ‡ฐ Flag: Denmark U+1F1E9, U+1F1F0 +๐Ÿ‡ฉ๐Ÿ‡ฒ Flag: Dominica U+1F1E9, U+1F1F2 +๐Ÿ‡ฉ๐Ÿ‡ด Flag: Dominican Republic U+1F1E9, U+1F1F4 +๐Ÿ‡ฉ๐Ÿ‡ฟ Flag: Algeria U+1F1E9, U+1F1FF +๐Ÿ‡ช๐Ÿ‡ฆ Flag: Ceuta & Melilla U+1F1EA, U+1F1E6 +๐Ÿ‡ช๐Ÿ‡จ Flag: Ecuador U+1F1EA, U+1F1E8 +๐Ÿ‡ช๐Ÿ‡ช Flag: Estonia U+1F1EA, U+1F1EA +๐Ÿ‡ช๐Ÿ‡ฌ Flag: Egypt U+1F1EA, U+1F1EC +๐Ÿ‡ช๐Ÿ‡ญ Flag: Western Sahara U+1F1EA, U+1F1ED +๐Ÿ‡ช๐Ÿ‡ท Flag: Eritrea U+1F1EA, U+1F1F7 +๐Ÿ‡ช๐Ÿ‡ธ Flag: Spain U+1F1EA, U+1F1F8 +๐Ÿ‡ช๐Ÿ‡น Flag: Ethiopia U+1F1EA, U+1F1F9 +๐Ÿ‡ช๐Ÿ‡บ Flag: European Union U+1F1EA, U+1F1FA +๐Ÿ‡ซ๐Ÿ‡ฎ Flag: Finland U+1F1EB, U+1F1EE +๐Ÿ‡ซ๐Ÿ‡ฏ Flag: Fiji U+1F1EB, U+1F1EF +๐Ÿ‡ซ๐Ÿ‡ฐ Flag: Falkland Islands U+1F1EB, U+1F1F0 +๐Ÿ‡ซ๐Ÿ‡ฒ Flag: Micronesia U+1F1EB, U+1F1F2 +๐Ÿ‡ซ๐Ÿ‡ด Flag: Faroe Islands U+1F1EB, U+1F1F4 +๐Ÿ‡ซ๐Ÿ‡ท Flag: France U+1F1EB, U+1F1F7 +๐Ÿ‡ฌ๐Ÿ‡ฆ Flag: Gabon U+1F1EC, U+1F1E6 +๐Ÿ‡ฌ๐Ÿ‡ง Flag: United Kingdom U+1F1EC, U+1F1E7 +๐Ÿ‡ฌ๐Ÿ‡ฉ Flag: Grenada U+1F1EC, U+1F1E9 +๐Ÿ‡ฌ๐Ÿ‡ช Flag: Georgia U+1F1EC, U+1F1EA +๐Ÿ‡ฌ๐Ÿ‡ซ Flag: French Guiana U+1F1EC, U+1F1EB +๐Ÿ‡ฌ๐Ÿ‡ฌ Flag: Guernsey U+1F1EC, U+1F1EC +๐Ÿ‡ฌ๐Ÿ‡ญ Flag: Ghana U+1F1EC, U+1F1ED +๐Ÿ‡ฌ๐Ÿ‡ฎ Flag: Gibraltar U+1F1EC, U+1F1EE +๐Ÿ‡ฌ๐Ÿ‡ฑ Flag: Greenland U+1F1EC, U+1F1F1 +๐Ÿ‡ฌ๐Ÿ‡ฒ Flag: Gambia U+1F1EC, U+1F1F2 +๐Ÿ‡ฌ๐Ÿ‡ณ Flag: Guinea U+1F1EC, U+1F1F3 +๐Ÿ‡ฌ๐Ÿ‡ต Flag: Guadeloupe U+1F1EC, U+1F1F5 +๐Ÿ‡ฌ๐Ÿ‡ถ Flag: Equatorial Guinea U+1F1EC, U+1F1F6 +๐Ÿ‡ฌ๐Ÿ‡ท Flag: Greece U+1F1EC, U+1F1F7 +๐Ÿ‡ฌ๐Ÿ‡ธ Flag: South Georgia & South Sandwich U+1F1EC, U+1F1F8 +Islands +๐Ÿ‡ฌ๐Ÿ‡น Flag: Guatemala U+1F1EC, U+1F1F9 +๐Ÿ‡ฌ๐Ÿ‡บ Flag: Guam U+1F1EC, U+1F1FA +๐Ÿ‡ฌ๐Ÿ‡ผ Flag: Guinea-Bissau U+1F1EC, U+1F1FC +๐Ÿ‡ฌ๐Ÿ‡พ Flag: Guyana U+1F1EC, U+1F1FE +๐Ÿ‡ญ๐Ÿ‡ฐ Flag: Hong Kong SAR China U+1F1ED, U+1F1F0 +๐Ÿ‡ญ๐Ÿ‡ฒ Flag: Heard & McDonald Islands U+1F1ED, U+1F1F2 +๐Ÿ‡ญ๐Ÿ‡ณ Flag: Honduras U+1F1ED, U+1F1F3 +๐Ÿ‡ญ๐Ÿ‡ท Flag: Croatia U+1F1ED, U+1F1F7 +๐Ÿ‡ญ๐Ÿ‡น Flag: Haiti U+1F1ED, U+1F1F9 +๐Ÿ‡ญ๐Ÿ‡บ Flag: Hungary U+1F1ED, U+1F1FA +๐Ÿ‡ฎ๐Ÿ‡จ Flag: Canary Islands U+1F1EE, U+1F1E8 +๐Ÿ‡ฎ๐Ÿ‡ฉ Flag: Indonesia U+1F1EE, U+1F1E9 +๐Ÿ‡ฎ๐Ÿ‡ช Flag: Ireland U+1F1EE, U+1F1EA +๐Ÿ‡ฎ๐Ÿ‡ฑ Flag: Israel U+1F1EE, U+1F1F1 +๐Ÿ‡ฎ๐Ÿ‡ฒ Flag: Isle of Man U+1F1EE, U+1F1F2 +๐Ÿ‡ฎ๐Ÿ‡ณ Flag: India U+1F1EE, U+1F1F3 +๐Ÿ‡ฎ๐Ÿ‡ด Flag: British Indian Ocean Territory U+1F1EE, U+1F1F4 +๐Ÿ‡ฎ๐Ÿ‡ถ Flag: Iraq U+1F1EE, U+1F1F6 +๐Ÿ‡ฎ๐Ÿ‡ท Flag: Iran U+1F1EE, U+1F1F7 +๐Ÿ‡ฎ๐Ÿ‡ธ Flag: Iceland U+1F1EE, U+1F1F8 +๐Ÿ‡ฎ๐Ÿ‡น Flag: Italy U+1F1EE, U+1F1F9 +๐Ÿ‡ฏ๐Ÿ‡ช Flag: Jersey U+1F1EF, U+1F1EA +๐Ÿ‡ฏ๐Ÿ‡ฒ Flag: Jamaica U+1F1EF, U+1F1F2 +๐Ÿ‡ฏ๐Ÿ‡ด Flag: Jordan U+1F1EF, U+1F1F4 +๐Ÿ‡ฏ๐Ÿ‡ต Flag: Japan U+1F1EF, U+1F1F5 +๐Ÿ‡ฐ๐Ÿ‡ช Flag: Kenya U+1F1F0, U+1F1EA +๐Ÿ‡ฐ๐Ÿ‡ฌ Flag: Kyrgyzstan U+1F1F0, U+1F1EC +๐Ÿ‡ฐ๐Ÿ‡ญ Flag: Cambodia U+1F1F0, U+1F1ED +๐Ÿ‡ฐ๐Ÿ‡ฎ Flag: Kiribati U+1F1F0, U+1F1EE +๐Ÿ‡ฐ๐Ÿ‡ฒ Flag: Comoros U+1F1F0, U+1F1F2 +๐Ÿ‡ฐ๐Ÿ‡ณ Flag: St. Kitts & Nevis U+1F1F0, U+1F1F3 +๐Ÿ‡ฐ๐Ÿ‡ต Flag: North Korea U+1F1F0, U+1F1F5 +๐Ÿ‡ฐ๐Ÿ‡ท Flag: South Korea U+1F1F0, U+1F1F7 +๐Ÿ‡ฐ๐Ÿ‡ผ Flag: Kuwait U+1F1F0, U+1F1FC +๐Ÿ‡ฐ๐Ÿ‡พ Flag: Cayman Islands U+1F1F0, U+1F1FE +๐Ÿ‡ฐ๐Ÿ‡ฟ Flag: Kazakhstan U+1F1F0, U+1F1FF +๐Ÿ‡ฑ๐Ÿ‡ฆ Flag: Laos U+1F1F1, U+1F1E6 +๐Ÿ‡ฑ๐Ÿ‡ง Flag: Lebanon U+1F1F1, U+1F1E7 +๐Ÿ‡ฑ๐Ÿ‡จ Flag: St. Lucia U+1F1F1, U+1F1E8 +๐Ÿ‡ฑ๐Ÿ‡ฎ Flag: Liechtenstein U+1F1F1, U+1F1EE +๐Ÿ‡ฑ๐Ÿ‡ฐ Flag: Sri Lanka U+1F1F1, U+1F1F0 +๐Ÿ‡ฑ๐Ÿ‡ท Flag: Liberia U+1F1F1, U+1F1F7 +๐Ÿ‡ฑ๐Ÿ‡ธ Flag: Lesotho U+1F1F1, U+1F1F8 +๐Ÿ‡ฑ๐Ÿ‡น Flag: Lithuania U+1F1F1, U+1F1F9 +๐Ÿ‡ฑ๐Ÿ‡บ Flag: Luxembourg U+1F1F1, U+1F1FA +๐Ÿ‡ฑ๐Ÿ‡ป Flag: Latvia U+1F1F1, U+1F1FB +๐Ÿ‡ฑ๐Ÿ‡พ Flag: Libya U+1F1F1, U+1F1FE +๐Ÿ‡ฒ๐Ÿ‡ฆ Flag: Morocco U+1F1F2, U+1F1E6 +๐Ÿ‡ฒ๐Ÿ‡จ Flag: Monaco U+1F1F2, U+1F1E8 +๐Ÿ‡ฒ๐Ÿ‡ฉ Flag: Moldova U+1F1F2, U+1F1E9 +๐Ÿ‡ฒ๐Ÿ‡ช Flag: Montenegro U+1F1F2, U+1F1EA +๐Ÿ‡ฒ๐Ÿ‡ซ Flag: St. Martin U+1F1F2, U+1F1EB +๐Ÿ‡ฒ๐Ÿ‡ฌ Flag: Madagascar U+1F1F2, U+1F1EC +๐Ÿ‡ฒ๐Ÿ‡ญ Flag: Marshall Islands U+1F1F2, U+1F1ED +๐Ÿ‡ฒ๐Ÿ‡ฐ Flag: North Macedonia U+1F1F2, U+1F1F0 +๐Ÿ‡ฒ๐Ÿ‡ฑ Flag: Mali U+1F1F2, U+1F1F1 +๐Ÿ‡ฒ๐Ÿ‡ฒ Flag: Myanmar (Burma) U+1F1F2, U+1F1F2 +๐Ÿ‡ฒ๐Ÿ‡ณ Flag: Mongolia U+1F1F2, U+1F1F3 +๐Ÿ‡ฒ๐Ÿ‡ด Flag: Macao Sar China U+1F1F2, U+1F1F4 +๐Ÿ‡ฒ๐Ÿ‡ต Flag: Northern Mariana Islands U+1F1F2, U+1F1F5 +๐Ÿ‡ฒ๐Ÿ‡ถ Flag: Martinique U+1F1F2, U+1F1F6 +๐Ÿ‡ฒ๐Ÿ‡ท Flag: Mauritania U+1F1F2, U+1F1F7 +๐Ÿ‡ฒ๐Ÿ‡ธ Flag: Montserrat U+1F1F2, U+1F1F8 +๐Ÿ‡ฒ๐Ÿ‡น Flag: Malta U+1F1F2, U+1F1F9 +๐Ÿ‡ฒ๐Ÿ‡บ Flag: Mauritius U+1F1F2, U+1F1FA +๐Ÿ‡ฒ๐Ÿ‡ป Flag: Maldives U+1F1F2, U+1F1FB +๐Ÿ‡ฒ๐Ÿ‡ผ Flag: Malawi U+1F1F2, U+1F1FC +๐Ÿ‡ฒ๐Ÿ‡ฝ Flag: Mexico U+1F1F2, U+1F1FD +๐Ÿ‡ฒ๐Ÿ‡พ Flag: Malaysia U+1F1F2, U+1F1FE +๐Ÿ‡ฒ๐Ÿ‡ฟ Flag: Mozambique U+1F1F2, U+1F1FF +๐Ÿ‡ณ๐Ÿ‡ฆ Flag: Namibia U+1F1F3, U+1F1E6 +๐Ÿ‡ณ๐Ÿ‡จ Flag: New Caledonia U+1F1F3, U+1F1E8 +๐Ÿ‡ณ๐Ÿ‡ช Flag: Niger U+1F1F3, U+1F1EA +๐Ÿ‡ณ๐Ÿ‡ซ Flag: Norfolk Island U+1F1F3, U+1F1EB +๐Ÿ‡ณ๐Ÿ‡ฌ Flag: Nigeria U+1F1F3, U+1F1EC +๐Ÿ‡ณ๐Ÿ‡ฎ Flag: Nicaragua U+1F1F3, U+1F1EE +๐Ÿ‡ณ๐Ÿ‡ฑ Flag: Netherlands U+1F1F3, U+1F1F1 +๐Ÿ‡ณ๐Ÿ‡ด Flag: Norway U+1F1F3, U+1F1F4 +๐Ÿ‡ณ๐Ÿ‡ต Flag: Nepal U+1F1F3, U+1F1F5 +๐Ÿ‡ณ๐Ÿ‡ท Flag: Nauru U+1F1F3, U+1F1F7 +๐Ÿ‡ณ๐Ÿ‡บ Flag: Niue U+1F1F3, U+1F1FA +๐Ÿ‡ณ๐Ÿ‡ฟ Flag: New Zealand U+1F1F3, U+1F1FF +๐Ÿ‡ด๐Ÿ‡ฒ Flag: Oman U+1F1F4, U+1F1F2 +๐Ÿ‡ต๐Ÿ‡ฆ Flag: Panama U+1F1F5, U+1F1E6 +๐Ÿ‡ต๐Ÿ‡ช Flag: Peru U+1F1F5, U+1F1EA +๐Ÿ‡ต๐Ÿ‡ซ Flag: French Polynesia U+1F1F5, U+1F1EB +๐Ÿ‡ต๐Ÿ‡ฌ Flag: Papua New Guinea U+1F1F5, U+1F1EC +๐Ÿ‡ต๐Ÿ‡ญ Flag: Philippines U+1F1F5, U+1F1ED +๐Ÿ‡ต๐Ÿ‡ฐ Flag: Pakistan U+1F1F5, U+1F1F0 +๐Ÿ‡ต๐Ÿ‡ฑ Flag: Poland U+1F1F5, U+1F1F1 +๐Ÿ‡ต๐Ÿ‡ฒ Flag: St. Pierre & Miquelon U+1F1F5, U+1F1F2 +๐Ÿ‡ต๐Ÿ‡ณ Flag: Pitcairn Islands U+1F1F5, U+1F1F3 +๐Ÿ‡ต๐Ÿ‡ท Flag: Puerto Rico U+1F1F5, U+1F1F7 +๐Ÿ‡ต๐Ÿ‡ธ Flag: Palestinian Territories U+1F1F5, U+1F1F8 +๐Ÿ‡ต๐Ÿ‡น Flag: Portugal U+1F1F5, U+1F1F9 +๐Ÿ‡ต๐Ÿ‡ผ Flag: Palau U+1F1F5, U+1F1FC +๐Ÿ‡ต๐Ÿ‡พ Flag: Paraguay U+1F1F5, U+1F1FE +๐Ÿ‡ถ๐Ÿ‡ฆ Flag: Qatar U+1F1F6, U+1F1E6 +๐Ÿ‡ท๐Ÿ‡ช Flag: Rรฉunion U+1F1F7, U+1F1EA +๐Ÿ‡ท๐Ÿ‡ด Flag: Romania U+1F1F7, U+1F1F4 +๐Ÿ‡ท๐Ÿ‡ธ Flag: Serbia U+1F1F7, U+1F1F8 +๐Ÿ‡ท๐Ÿ‡บ Flag: Russia U+1F1F7, U+1F1FA +๐Ÿ‡ท๐Ÿ‡ผ Flag: Rwanda U+1F1F7, U+1F1FC +๐Ÿ‡ธ๐Ÿ‡ฆ Flag: Saudi Arabia U+1F1F8, U+1F1E6 +๐Ÿ‡ธ๐Ÿ‡ง Flag: Solomon Islands U+1F1F8, U+1F1E7 +๐Ÿ‡ธ๐Ÿ‡จ Flag: Seychelles U+1F1F8, U+1F1E8 +๐Ÿ‡ธ๐Ÿ‡ฉ Flag: Sudan U+1F1F8, U+1F1E9 +๐Ÿ‡ธ๐Ÿ‡ช Flag: Sweden U+1F1F8, U+1F1EA +๐Ÿ‡ธ๐Ÿ‡ฌ Flag: Singapore U+1F1F8, U+1F1EC +๐Ÿ‡ธ๐Ÿ‡ญ Flag: St. Helena U+1F1F8, U+1F1ED +๐Ÿ‡ธ๐Ÿ‡ฎ Flag: Slovenia U+1F1F8, U+1F1EE +๐Ÿ‡ธ๐Ÿ‡ฏ Flag: Svalbard & Jan Mayen U+1F1F8, U+1F1EF +๐Ÿ‡ธ๐Ÿ‡ฐ Flag: Slovakia U+1F1F8, U+1F1F0 +๐Ÿ‡ธ๐Ÿ‡ฑ Flag: Sierra Leone U+1F1F8, U+1F1F1 +๐Ÿ‡ธ๐Ÿ‡ฒ Flag: San Marino U+1F1F8, U+1F1F2 +๐Ÿ‡ธ๐Ÿ‡ณ Flag: Senegal U+1F1F8, U+1F1F3 +๐Ÿ‡ธ๐Ÿ‡ด Flag: Somalia U+1F1F8, U+1F1F4 +๐Ÿ‡ธ๐Ÿ‡ท Flag: Suriname U+1F1F8, U+1F1F7 +๐Ÿ‡ธ๐Ÿ‡ธ Flag: South Sudan U+1F1F8, U+1F1F8 +๐Ÿ‡ธ๐Ÿ‡น Flag: Sรฃo Tomรฉ & Prรญncipe U+1F1F8, U+1F1F9 +๐Ÿ‡ธ๐Ÿ‡ป Flag: El Salvador U+1F1F8, U+1F1FB +๐Ÿ‡ธ๐Ÿ‡ฝ Flag: Sint Maarten U+1F1F8, U+1F1FD +๐Ÿ‡ธ๐Ÿ‡พ Flag: Syria U+1F1F8, U+1F1FE +๐Ÿ‡ธ๐Ÿ‡ฟ Flag: Eswatini U+1F1F8, U+1F1FF +๐Ÿ‡น๐Ÿ‡ฆ Flag: Tristan Da Cunha U+1F1F9, U+1F1E6 +๐Ÿ‡น๐Ÿ‡จ Flag: Turks & Caicos Islands U+1F1F9, U+1F1E8 +๐Ÿ‡น๐Ÿ‡ฉ Flag: Chad U+1F1F9, U+1F1E9 +๐Ÿ‡น๐Ÿ‡ซ Flag: French Southern Territories U+1F1F9, U+1F1EB +๐Ÿ‡น๐Ÿ‡ฌ Flag: Togo U+1F1F9, U+1F1EC +๐Ÿ‡น๐Ÿ‡ญ Flag: Thailand U+1F1F9, U+1F1ED +๐Ÿ‡น๐Ÿ‡ฏ Flag: Tajikistan U+1F1F9, U+1F1EF +๐Ÿ‡น๐Ÿ‡ฐ Flag: Tokelau U+1F1F9, U+1F1F0 +๐Ÿ‡น๐Ÿ‡ฑ Flag: Timor-Leste U+1F1F9, U+1F1F1 +๐Ÿ‡น๐Ÿ‡ฒ Flag: Turkmenistan U+1F1F9, U+1F1F2 +๐Ÿ‡น๐Ÿ‡ณ Flag: Tunisia U+1F1F9, U+1F1F3 +๐Ÿ‡น๐Ÿ‡ด Flag: Tonga U+1F1F9, U+1F1F4 +๐Ÿ‡น๐Ÿ‡ท Flag: Turkey U+1F1F9, U+1F1F7 +๐Ÿ‡น๐Ÿ‡น Flag: Trinidad & Tobago U+1F1F9, U+1F1F9 +๐Ÿ‡น๐Ÿ‡ป Flag: Tuvalu U+1F1F9, U+1F1FB +๐Ÿ‡น๐Ÿ‡ผ Flag: Taiwan U+1F1F9, U+1F1FC +๐Ÿ‡น๐Ÿ‡ฟ Flag: Tanzania U+1F1F9, U+1F1FF +๐Ÿ‡บ๐Ÿ‡ฆ Flag: Ukraine U+1F1FA, U+1F1E6 +๐Ÿ‡บ๐Ÿ‡ฌ Flag: Uganda U+1F1FA, U+1F1EC +๐Ÿ‡บ๐Ÿ‡ฒ Flag: U.S. Outlying Islands U+1F1FA, U+1F1F2 +๐Ÿ‡บ๐Ÿ‡ณ Flag: United Nations U+1F1FA, U+1F1F3 +๐Ÿ‡บ๐Ÿ‡ธ Flag: United States U+1F1FA, U+1F1F8 +๐Ÿ‡บ๐Ÿ‡พ Flag: Uruguay U+1F1FA, U+1F1FE +๐Ÿ‡บ๐Ÿ‡ฟ Flag: Uzbekistan U+1F1FA, U+1F1FF +๐Ÿ‡ป๐Ÿ‡ฆ Flag: Vatican City U+1F1FB, U+1F1E6 +๐Ÿ‡ป๐Ÿ‡จ Flag: St. Vincent & Grenadines U+1F1FB, U+1F1E8 +๐Ÿ‡ป๐Ÿ‡ช Flag: Venezuela U+1F1FB, U+1F1EA +๐Ÿ‡ป๐Ÿ‡ฌ Flag: British Virgin Islands U+1F1FB, U+1F1EC +๐Ÿ‡ป๐Ÿ‡ฎ Flag: U.S. Virgin Islands U+1F1FB, U+1F1EE +๐Ÿ‡ป๐Ÿ‡ณ Flag: Vietnam U+1F1FB, U+1F1F3 +๐Ÿ‡ป๐Ÿ‡บ Flag: Vanuatu U+1F1FB, U+1F1FA +๐Ÿ‡ผ๐Ÿ‡ซ Flag: Wallis & Futuna U+1F1FC, U+1F1EB +๐Ÿ‡ผ๐Ÿ‡ธ Flag: Samoa U+1F1FC, U+1F1F8 +๐Ÿ‡ฝ๐Ÿ‡ฐ Flag: Kosovo U+1F1FD, U+1F1F0 +๐Ÿ‡พ๐Ÿ‡ช Flag: Yemen U+1F1FE, U+1F1EA +๐Ÿ‡พ๐Ÿ‡น Flag: Mayotte U+1F1FE, U+1F1F9 +๐Ÿ‡ฟ๐Ÿ‡ฆ Flag: South Africa U+1F1FF, U+1F1E6 +๐Ÿ‡ฟ๐Ÿ‡ฒ Flag: Zambia U+1F1FF, U+1F1F2 +๐Ÿ‡ฟ๐Ÿ‡ผ Flag: Zimbabwe U+1F1FF, U+1F1FC +๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ Flag: England U+1F3F4, U+E0067, U+E0062, + U+E0065, U+E006E, U+E0067, U+E007F +๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ Flag: Scotland U+1F3F4, U+E0067, U+E0062, + U+E0073, U+E0063, U+E0074, U+E007F +๐Ÿด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ Flag: Wales U+1F3F4, U+E0067, U+E0062, + U+E0077, U+E006C, U+E0073, U+E007F +๐Ÿ‡ฆ Regional Indicator Symbol Letter A U+1F1E6 +๐Ÿ‡ง Regional Indicator Symbol Letter B U+1F1E7 +๐Ÿ‡จ Regional Indicator Symbol Letter C U+1F1E8 +๐Ÿ‡ฉ Regional Indicator Symbol Letter D U+1F1E9 +๐Ÿ‡ช Regional Indicator Symbol Letter E U+1F1EA +๐Ÿ‡ซ Regional Indicator Symbol Letter F U+1F1EB +๐Ÿ‡ฌ Regional Indicator Symbol Letter G U+1F1EC +๐Ÿ‡ญ Regional Indicator Symbol Letter H U+1F1ED +๐Ÿ‡ฎ Regional Indicator Symbol Letter I U+1F1EE +๐Ÿ‡ฏ Regional Indicator Symbol Letter J U+1F1EF +๐Ÿ‡ฐ Regional Indicator Symbol Letter K U+1F1F0 +๐Ÿ‡ฑ Regional Indicator Symbol Letter L U+1F1F1 +๐Ÿ‡ฒ Regional Indicator Symbol Letter M U+1F1F2 +๐Ÿ‡ณ Regional Indicator Symbol Letter N U+1F1F3 +๐Ÿ‡ด Regional Indicator Symbol Letter O U+1F1F4 +๐Ÿ‡ต Regional Indicator Symbol Letter P U+1F1F5 +๐Ÿ‡ถ Regional Indicator Symbol Letter Q U+1F1F6 +๐Ÿ‡ท Regional Indicator Symbol Letter R U+1F1F7 +๐Ÿ‡ธ Regional Indicator Symbol Letter S U+1F1F8 +๐Ÿ‡น Regional Indicator Symbol Letter T U+1F1F9 +๐Ÿ‡บ Regional Indicator Symbol Letter U U+1F1FA +๐Ÿ‡ป Regional Indicator Symbol Letter V U+1F1FB +๐Ÿ‡ผ Regional Indicator Symbol Letter W U+1F1FC +๐Ÿ‡ฝ Regional Indicator Symbol Letter X U+1F1FD +๐Ÿ‡พ Regional Indicator Symbol Letter Y U+1F1FE +๐Ÿ‡ฟ Regional Indicator Symbol Letter Z U+1F1FF +Tag Space U+E0020 +Tag Left Square Bracket U+E005B +Tag Vertical Line U+E007C +4๏ธ Digit Four U+34, U+FE0F +0๏ธ Digit Zero U+30, U+FE0F +Tag Latin Capital Letter G U+E0047 +Tag Digit Eight U+E0038 +Tag Latin Capital Letter N U+E004E +Tag Dollar Sign U+E0024 +*๏ธ Asterisk U+2A, U+FE0F +Tag Right Square Bracket U+E005D +Tag Left Parenthesis U+E0028 +#๏ธ Number Sign U+23, U+FE0F +Tag Digit Two U+E0032 +Tag Latin Capital Letter K U+E004B +Tag Latin Small Letter Y U+E0079 +Tag Tilde U+E007E +Cancel Tag U+E007F +Tag Asterisk U+E002A +Tag Quotation Mark U+E0022 +Tag Colon U+E003A +Tag Digit Zero U+E0030 +๏ธ Variation Selector-16 U+FE0F +Tag Latin Capital Letter X U+E0058 +Tag Reverse Solidus U+E005C +Tag Circumflex Accent U+E005E +Tag Latin Capital Letter Q U+E0051 +Tag Left Curly Bracket U+E007B +Tag Digit Three U+E0033 +Tag Right Parenthesis U+E0029 +Tag Latin Small Letter P U+E0070 +Tag Equals Sign U+E003D +Tag Digit Four U+E0034 +Tag Comma U+E002C +Tag Plus Sign U+E002B +Tag Latin Small Letter J U+E006A +Tag Latin Capital Letter F U+E0046 +Tag Digit Six U+E0036 +Tag Latin Capital Letter P U+E0050 +Tag Latin Small Letter O U+E006F +Tag Latin Capital Letter C U+E0043 +Tag Latin Capital Letter Y U+E0059 +7๏ธ Digit Seven U+37, U+FE0F +Tag Grave Accent U+E0060 +Tag Latin Capital Letter T U+E0054 +โƒฃCombining Enclosing Keycap U+20E3 +Tag Latin Small Letter R U+E0072 +Tag Number Sign U+E0023 +Tag Latin Small Letter H U+E0068 +Tag Latin Small Letter a U+E0061 +Tag Latin Small Letter U U+E0075 +Tag Ampersand U+E0026 +Tag Latin Small Letter T U+E0074 +Tag Latin Small Letter M U+E006D +Tag Latin Capital Letter E U+E0045 +Tag Solidus U+E002F +8๏ธ Digit Eight U+38, U+FE0F +Tag Latin Small Letter X U+E0078 +Tag Latin Small Letter G U+E0067 +Tag Latin Small Letter Z U+E007A +Tag Less-Than Sign U+E003C +Tag Commercial at U+E0040 +Tag Latin Small Letter K U+E006B +Tag Latin Small Letter V U+E0076 +Tag Digit One U+E0031 +Tag Digit Seven U+E0037 +Tag Latin Capital Letter B U+E0042 +Tag Latin Small Letter F U+E0066 +1๏ธ Digit One U+31, U+FE0F +Tag Latin Small Letter D U+E0064 +Tag Latin Small Letter C U+E0063 +Tag Right Curly Bracket U+E007D +5๏ธ Digit Five U+35, U+FE0F +Tag Latin Capital Letter S U+E0053 +Tag Latin Capital Letter V U+E0056 +Tag Digit Five U+E0035 +Tag Full Stop U+E002E +Tag Percent Sign U+E0025 +โ€ Zero Width Joiner U+200D +Tag Latin Small Letter N U+E006E +Tag Hyphen-Minus U+E002D +Tag Latin Small Letter B U+E0062 +Tag Latin Capital Letter R U+E0052 +Tag Digit Nine U+E0039 +Tag Latin Small Letter E U+E0065 +Tag Latin Capital Letter Z U+E005A +Tag Latin Capital Letter I U+E0049 +Tag Latin Capital Letter W U+E0057 +Tag Greater-Than Sign U+E003E +9๏ธ Digit Nine U+39, U+FE0F +Tag Latin Small Letter I U+E0069 +Tag Latin Capital Letter J U+E004A +Tag Latin Small Letter Q U+E0071 +Tag Semicolon U+E003B +2๏ธ Digit Two U+32, U+FE0F +Tag Latin Capital Letter M U+E004D +Tag Low Line U+E005F +Tag Apostrophe U+E0027 +Tag Exclamation Mark U+E0021 +Tag Latin Capital Letter O U+E004F +Tag Latin Small Letter W U+E0077 +Tag Latin Capital Letter U U+E0055 +Tag Latin Capital Letter a U+E0041 +Tag Latin Capital Letter D U+E0044 +Tag Latin Small Letter S U+E0073 +Tag Question Mark U+E003F +6๏ธ Digit Six U+36, U+FE0F +Tag Latin Capital Letter L U+E004C +3๏ธ Digit Three U+33, U+FE0F +Tag Latin Capital Letter H U+E0048 +Tag Latin Small Letter L U+E006C diff --git a/stow/emoji/dot-config/emoji b/stow/emoji/dot-config/emoji deleted file mode 100644 index 2441237..0000000 --- a/stow/emoji/dot-config/emoji +++ /dev/null @@ -1,4267 +0,0 @@ -~ Obtained from https://emojipedia.org/emoji/ on Mon 15 Jun 2020 -๐Ÿ˜€ Grinning Face U+1F600 -๐Ÿ˜ƒ Grinning Face with Big Eyes U+1F603 -๐Ÿ˜„ Grinning Face with Smiling Eyes U+1F604 -๐Ÿ˜ Beaming Face with Smiling Eyes U+1F601 -๐Ÿ˜† Grinning Squinting Face U+1F606 -๐Ÿ˜… Grinning Face with Sweat U+1F605 -๐Ÿคฃ Rolling on the Floor Laughing U+1F923 -๐Ÿ˜‚ Face with Tears of Joy U+1F602 -๐Ÿ™‚ Slightly Smiling Face U+1F642 -๐Ÿ™ƒ Upside-Down Face U+1F643 -๐Ÿ˜‰ Winking Face U+1F609 -๐Ÿ˜Š Smiling Face with Smiling Eyes U+1F60A -๐Ÿ˜‡ Smiling Face with Halo U+1F607 -๐Ÿฅฐ Smiling Face with Hearts U+1F970 -๐Ÿ˜ Smiling Face with Heart-Eyes U+1F60D -๐Ÿคฉ Star-Struck U+1F929 -๐Ÿ˜˜ Face Blowing a Kiss U+1F618 -๐Ÿ˜— Kissing Face U+1F617 -โ˜บ๏ธ Smiling Face U+263A, U+FE0F -๐Ÿ˜š Kissing Face with Closed Eyes U+1F61A -๐Ÿ˜™ Kissing Face with Smiling Eyes U+1F619 -๐Ÿฅฒ Smiling Face with Tear U+1F972 -๐Ÿ˜‹ Face Savoring Food U+1F60B -๐Ÿ˜› Face with Tongue U+1F61B -๐Ÿ˜œ Winking Face with Tongue U+1F61C -๐Ÿคช Zany Face U+1F92A -๐Ÿ˜ Squinting Face with Tongue U+1F61D -๐Ÿค‘ Money-Mouth Face U+1F911 -๐Ÿค— Hugging Face U+1F917 -๐Ÿคญ Face with Hand Over Mouth U+1F92D -๐Ÿคซ Shushing Face U+1F92B -๐Ÿค” Thinking Face U+1F914 -๐Ÿค Zipper-Mouth Face U+1F910 -๐Ÿคจ Face with Raised Eyebrow U+1F928 -๐Ÿ˜ Neutral Face U+1F610 -๐Ÿ˜‘ Expressionless Face U+1F611 -๐Ÿ˜ถ Face Without Mouth U+1F636 -๐Ÿ˜ Smirking Face U+1F60F -๐Ÿ˜’ Unamused Face U+1F612 -๐Ÿ™„ Face with Rolling Eyes U+1F644 -๐Ÿ˜ฌ Grimacing Face U+1F62C -๐Ÿคฅ Lying Face U+1F925 -๐Ÿ˜Œ Relieved Face U+1F60C -๐Ÿ˜” Pensive Face U+1F614 -๐Ÿ˜ช Sleepy Face U+1F62A -๐Ÿคค Drooling Face U+1F924 -๐Ÿ˜ด Sleeping Face U+1F634 -๐Ÿ˜ท Face with Medical Mask U+1F637 -๐Ÿค’ Face with Thermometer U+1F912 -๐Ÿค• Face with Head-Bandage U+1F915 -๐Ÿคข Nauseated Face U+1F922 -๐Ÿคฎ Face Vomiting U+1F92E -๐Ÿคง Sneezing Face U+1F927 -๐Ÿฅต Hot Face U+1F975 -๐Ÿฅถ Cold Face U+1F976 -๐Ÿฅด Woozy Face U+1F974 -๐Ÿ˜ต Dizzy Face U+1F635 -๐Ÿคฏ Exploding Head U+1F92F -๐Ÿค  Cowboy Hat Face U+1F920 -๐Ÿฅณ Partying Face U+1F973 -๐Ÿฅธ Disguised Face U+1F978 -๐Ÿ˜Ž Smiling Face with Sunglasses U+1F60E -๐Ÿค“ Nerd Face U+1F913 -๐Ÿง Face with Monocle U+1F9D0 -๐Ÿ˜• Confused Face U+1F615 -๐Ÿ˜Ÿ Worried Face U+1F61F -๐Ÿ™ Slightly Frowning Face U+1F641 -โ˜น๏ธ Frowning Face U+2639, U+FE0F -๐Ÿ˜ฎ Face with Open Mouth U+1F62E -๐Ÿ˜ฏ Hushed Face U+1F62F -๐Ÿ˜ฒ Astonished Face U+1F632 -๐Ÿ˜ณ Flushed Face U+1F633 -๐Ÿฅบ Pleading Face U+1F97A -๐Ÿ˜ฆ Frowning Face with Open Mouth U+1F626 -๐Ÿ˜ง Anguished Face U+1F627 -๐Ÿ˜จ Fearful Face U+1F628 -๐Ÿ˜ฐ Anxious Face with Sweat U+1F630 -๐Ÿ˜ฅ Sad but Relieved Face U+1F625 -๐Ÿ˜ข Crying Face U+1F622 -๐Ÿ˜ญ Loudly Crying Face U+1F62D -๐Ÿ˜ฑ Face Screaming in Fear U+1F631 -๐Ÿ˜– Confounded Face U+1F616 -๐Ÿ˜ฃ Persevering Face U+1F623 -๐Ÿ˜ž Disappointed Face U+1F61E -๐Ÿ˜“ Downcast Face with Sweat U+1F613 -๐Ÿ˜ฉ Weary Face U+1F629 -๐Ÿ˜ซ Tired Face U+1F62B -๐Ÿฅฑ Yawning Face U+1F971 -๐Ÿ˜ค Face with Steam From Nose U+1F624 -๐Ÿ˜ก Pouting Face U+1F621 -๐Ÿ˜  Angry Face U+1F620 -๐Ÿคฌ Face with Symbols on Mouth U+1F92C -๐Ÿ˜ˆ Smiling Face with Horns U+1F608 -๐Ÿ‘ฟ Angry Face with Horns U+1F47F -๐Ÿ’€ Skull U+1F480 -โ˜ ๏ธ Skull and Crossbones U+2620, U+FE0F -๐Ÿ’ฉ Pile of Poo U+1F4A9 -๐Ÿคก Clown Face U+1F921 -๐Ÿ‘น Ogre U+1F479 -๐Ÿ‘บ Goblin U+1F47A -๐Ÿ‘ป Ghost U+1F47B -๐Ÿ‘ฝ Alien U+1F47D -๐Ÿ‘พ Alien Monster U+1F47E -๐Ÿค– Robot U+1F916 -๐Ÿ˜บ Grinning Cat U+1F63A -๐Ÿ˜ธ Grinning Cat with Smiling Eyes U+1F638 -๐Ÿ˜น Cat with Tears of Joy U+1F639 -๐Ÿ˜ป Smiling Cat with Heart-Eyes U+1F63B -๐Ÿ˜ผ Cat with Wry Smile U+1F63C -๐Ÿ˜ฝ Kissing Cat U+1F63D -๐Ÿ™€ Weary Cat U+1F640 -๐Ÿ˜ฟ Crying Cat U+1F63F -๐Ÿ˜พ Pouting Cat U+1F63E -๐Ÿ™ˆ See-No-Evil Monkey U+1F648 -๐Ÿ™‰ Hear-No-Evil Monkey U+1F649 -๐Ÿ™Š Speak-No-Evil Monkey U+1F64A -๐Ÿ’‹ Kiss Mark U+1F48B -๐Ÿ’Œ Love Letter U+1F48C -๐Ÿ’˜ Heart with Arrow U+1F498 -๐Ÿ’ Heart with Ribbon U+1F49D -๐Ÿ’– Sparkling Heart U+1F496 -๐Ÿ’— Growing Heart U+1F497 -๐Ÿ’“ Beating Heart U+1F493 -๐Ÿ’ž Revolving Hearts U+1F49E -๐Ÿ’• Two Hearts U+1F495 -๐Ÿ’Ÿ Heart Decoration U+1F49F -โฃ๏ธ Heart Exclamation U+2763, U+FE0F -๐Ÿ’” Broken Heart U+1F494 -โค๏ธ Red Heart U+2764, U+FE0F -๐Ÿงก Orange Heart U+1F9E1 -๐Ÿ’› Yellow Heart U+1F49B -๐Ÿ’š Green Heart U+1F49A -๐Ÿ’™ Blue Heart U+1F499 -๐Ÿ’œ Purple Heart U+1F49C -๐ŸคŽ Brown Heart U+1F90E -๐Ÿ–ค Black Heart U+1F5A4 -๐Ÿค White Heart U+1F90D -๐Ÿ’ฏ Hundred Points U+1F4AF -๐Ÿ’ข Anger Symbol U+1F4A2 -๐Ÿ’ฅ Collision U+1F4A5 -๐Ÿ’ซ Dizzy U+1F4AB -๐Ÿ’ฆ Sweat Droplets U+1F4A6 -๐Ÿ’จ Dashing Away U+1F4A8 -๐Ÿ•ณ๏ธ Hole U+1F573, U+FE0F -๐Ÿ’ฃ Bomb U+1F4A3 -๐Ÿ’ฌ Speech Balloon U+1F4AC -๐Ÿ‘๏ธโ€๐Ÿ—จ๏ธ Eye in Speech Bubble U+1F441, U+FE0F, U+200D, U+1F5E8, - U+FE0F -๐Ÿ—จ๏ธ Left Speech Bubble U+1F5E8, U+FE0F -๐Ÿ—ฏ๏ธ Right Anger Bubble U+1F5EF, U+FE0F -๐Ÿ’ญ Thought Balloon U+1F4AD -๐Ÿ’ค Zzz U+1F4A4 -๐Ÿ‘‹ Waving Hand U+1F44B -๐Ÿ‘‹๐Ÿป Waving Hand: Light Skin Tone U+1F44B, U+1F3FB -๐Ÿ‘‹๐Ÿผ Waving Hand: Medium-Light Skin Tone U+1F44B, U+1F3FC -๐Ÿ‘‹๐Ÿฝ Waving Hand: Medium Skin Tone U+1F44B, U+1F3FD -๐Ÿ‘‹๐Ÿพ Waving Hand: Medium-Dark Skin Tone U+1F44B, U+1F3FE -๐Ÿ‘‹๐Ÿฟ Waving Hand: Dark Skin Tone U+1F44B, U+1F3FF -๐Ÿคš Raised Back of Hand U+1F91A -๐Ÿคš๐Ÿป Raised Back of Hand: Light Skin Tone U+1F91A, U+1F3FB -๐Ÿคš๐Ÿผ Raised Back of Hand: Medium-Light Skin U+1F91A, U+1F3FC -Tone -๐Ÿคš๐Ÿฝ Raised Back of Hand: Medium Skin Tone U+1F91A, U+1F3FD -๐Ÿคš๐Ÿพ Raised Back of Hand: Medium-Dark Skin U+1F91A, U+1F3FE -Tone -๐Ÿคš๐Ÿฟ Raised Back of Hand: Dark Skin Tone U+1F91A, U+1F3FF -๐Ÿ–๏ธ Hand with Fingers Splayed U+1F590, U+FE0F -๐Ÿ–๐Ÿป Hand with Fingers Splayed: Light Skin U+1F590, U+1F3FB -Tone -๐Ÿ–๐Ÿผ Hand with Fingers Splayed: Medium-Light U+1F590, U+1F3FC -Skin Tone -๐Ÿ–๐Ÿฝ Hand with Fingers Splayed: Medium Skin U+1F590, U+1F3FD -Tone -๐Ÿ–๐Ÿพ Hand with Fingers Splayed: Medium-Dark U+1F590, U+1F3FE -Skin Tone -๐Ÿ–๐Ÿฟ Hand with Fingers Splayed: Dark Skin Tone U+1F590, U+1F3FF -โœ‹ Raised Hand U+270B -โœ‹๐Ÿป Raised Hand: Light Skin Tone U+270B, U+1F3FB -โœ‹๐Ÿผ Raised Hand: Medium-Light Skin Tone U+270B, U+1F3FC -โœ‹๐Ÿฝ Raised Hand: Medium Skin Tone U+270B, U+1F3FD -โœ‹๐Ÿพ Raised Hand: Medium-Dark Skin Tone U+270B, U+1F3FE -โœ‹๐Ÿฟ Raised Hand: Dark Skin Tone U+270B, U+1F3FF -๐Ÿ–– Vulcan Salute U+1F596 -๐Ÿ––๐Ÿป Vulcan Salute: Light Skin Tone U+1F596, U+1F3FB -๐Ÿ––๐Ÿผ Vulcan Salute: Medium-Light Skin Tone U+1F596, U+1F3FC -๐Ÿ––๐Ÿฝ Vulcan Salute: Medium Skin Tone U+1F596, U+1F3FD -๐Ÿ––๐Ÿพ Vulcan Salute: Medium-Dark Skin Tone U+1F596, U+1F3FE -๐Ÿ––๐Ÿฟ Vulcan Salute: Dark Skin Tone U+1F596, U+1F3FF -๐Ÿ‘Œ OK Hand U+1F44C -๐Ÿ‘Œ๐Ÿป OK Hand: Light Skin Tone U+1F44C, U+1F3FB -๐Ÿ‘Œ๐Ÿผ OK Hand: Medium-Light Skin Tone U+1F44C, U+1F3FC -๐Ÿ‘Œ๐Ÿฝ OK Hand: Medium Skin Tone U+1F44C, U+1F3FD -๐Ÿ‘Œ๐Ÿพ OK Hand: Medium-Dark Skin Tone U+1F44C, U+1F3FE -๐Ÿ‘Œ๐Ÿฟ OK Hand: Dark Skin Tone U+1F44C, U+1F3FF -๐ŸคŒ Pinched Fingers U+1F90C -๐ŸคŒ๐Ÿป Pinched Fingers: Light Skin Tone U+1F90C, U+1F3FB -๐ŸคŒ๐Ÿผ Pinched Fingers: Medium-Light Skin Tone U+1F90C, U+1F3FC -๐ŸคŒ๐Ÿฝ Pinched Fingers: Medium Skin Tone U+1F90C, U+1F3FD -๐ŸคŒ๐Ÿพ Pinched Fingers: Medium-Dark Skin Tone U+1F90C, U+1F3FE -๐ŸคŒ๐Ÿฟ Pinched Fingers: Dark Skin Tone U+1F90C, U+1F3FF -๐Ÿค Pinching Hand U+1F90F -๐Ÿค๐Ÿป Pinching Hand: Light Skin Tone U+1F90F, U+1F3FB -๐Ÿค๐Ÿผ Pinching Hand: Medium-Light Skin Tone U+1F90F, U+1F3FC -๐Ÿค๐Ÿฝ Pinching Hand: Medium Skin Tone U+1F90F, U+1F3FD -๐Ÿค๐Ÿพ Pinching Hand: Medium-Dark Skin Tone U+1F90F, U+1F3FE -๐Ÿค๐Ÿฟ Pinching Hand: Dark Skin Tone U+1F90F, U+1F3FF -โœŒ๏ธ Victory Hand U+270C, U+FE0F -โœŒ๐Ÿป Victory Hand: Light Skin Tone U+270C, U+1F3FB -โœŒ๐Ÿผ Victory Hand: Medium-Light Skin Tone U+270C, U+1F3FC -โœŒ๐Ÿฝ Victory Hand: Medium Skin Tone U+270C, U+1F3FD -โœŒ๐Ÿพ Victory Hand: Medium-Dark Skin Tone U+270C, U+1F3FE -โœŒ๐Ÿฟ Victory Hand: Dark Skin Tone U+270C, U+1F3FF -๐Ÿคž Crossed Fingers U+1F91E -๐Ÿคž๐Ÿป Crossed Fingers: Light Skin Tone U+1F91E, U+1F3FB -๐Ÿคž๐Ÿผ Crossed Fingers: Medium-Light Skin Tone U+1F91E, U+1F3FC -๐Ÿคž๐Ÿฝ Crossed Fingers: Medium Skin Tone U+1F91E, U+1F3FD -๐Ÿคž๐Ÿพ Crossed Fingers: Medium-Dark Skin Tone U+1F91E, U+1F3FE -๐Ÿคž๐Ÿฟ Crossed Fingers: Dark Skin Tone U+1F91E, U+1F3FF -๐ŸคŸ Love-You Gesture U+1F91F -๐ŸคŸ๐Ÿป Love-You Gesture: Light Skin Tone U+1F91F, U+1F3FB -๐ŸคŸ๐Ÿผ Love-You Gesture: Medium-Light Skin Tone U+1F91F, U+1F3FC -๐ŸคŸ๐Ÿฝ Love-You Gesture: Medium Skin Tone U+1F91F, U+1F3FD -๐ŸคŸ๐Ÿพ Love-You Gesture: Medium-Dark Skin Tone U+1F91F, U+1F3FE -๐ŸคŸ๐Ÿฟ Love-You Gesture: Dark Skin Tone U+1F91F, U+1F3FF -๐Ÿค˜ Sign of the Horns U+1F918 -๐Ÿค˜๐Ÿป Sign of the Horns: Light Skin Tone U+1F918, U+1F3FB -๐Ÿค˜๐Ÿผ Sign of the Horns: Medium-Light Skin Tone U+1F918, U+1F3FC -๐Ÿค˜๐Ÿฝ Sign of the Horns: Medium Skin Tone U+1F918, U+1F3FD -๐Ÿค˜๐Ÿพ Sign of the Horns: Medium-Dark Skin Tone U+1F918, U+1F3FE -๐Ÿค˜๐Ÿฟ Sign of the Horns: Dark Skin Tone U+1F918, U+1F3FF -๐Ÿค™ Call Me Hand U+1F919 -๐Ÿค™๐Ÿป Call Me Hand: Light Skin Tone U+1F919, U+1F3FB -๐Ÿค™๐Ÿผ Call Me Hand: Medium-Light Skin Tone U+1F919, U+1F3FC -๐Ÿค™๐Ÿฝ Call Me Hand: Medium Skin Tone U+1F919, U+1F3FD -๐Ÿค™๐Ÿพ Call Me Hand: Medium-Dark Skin Tone U+1F919, U+1F3FE -๐Ÿค™๐Ÿฟ Call Me Hand: Dark Skin Tone U+1F919, U+1F3FF -๐Ÿ‘ˆ Backhand Index Pointing Left U+1F448 -๐Ÿ‘ˆ๐Ÿป Backhand Index Pointing Left: Light Skin U+1F448, U+1F3FB -Tone -๐Ÿ‘ˆ๐Ÿผ Backhand Index Pointing Left: U+1F448, U+1F3FC -Medium-Light Skin Tone -๐Ÿ‘ˆ๐Ÿฝ Backhand Index Pointing Left: Medium Skin U+1F448, U+1F3FD -Tone -๐Ÿ‘ˆ๐Ÿพ Backhand Index Pointing Left: Medium-Dark U+1F448, U+1F3FE -Skin Tone -๐Ÿ‘ˆ๐Ÿฟ Backhand Index Pointing Left: Dark Skin U+1F448, U+1F3FF -Tone -๐Ÿ‘‰ Backhand Index Pointing Right U+1F449 -๐Ÿ‘‰๐Ÿป Backhand Index Pointing Right: Light Skin U+1F449, U+1F3FB -Tone -๐Ÿ‘‰๐Ÿผ Backhand Index Pointing Right: U+1F449, U+1F3FC -Medium-Light Skin Tone -๐Ÿ‘‰๐Ÿฝ Backhand Index Pointing Right: Medium U+1F449, U+1F3FD -Skin Tone -๐Ÿ‘‰๐Ÿพ Backhand Index Pointing Right: U+1F449, U+1F3FE -Medium-Dark Skin Tone -๐Ÿ‘‰๐Ÿฟ Backhand Index Pointing Right: Dark Skin U+1F449, U+1F3FF -Tone -๐Ÿ‘† Backhand Index Pointing Up U+1F446 -๐Ÿ‘†๐Ÿป Backhand Index Pointing Up: Light Skin U+1F446, U+1F3FB -Tone -๐Ÿ‘†๐Ÿผ Backhand Index Pointing Up: Medium-Light U+1F446, U+1F3FC -Skin Tone -๐Ÿ‘†๐Ÿฝ Backhand Index Pointing Up: Medium Skin U+1F446, U+1F3FD -Tone -๐Ÿ‘†๐Ÿพ Backhand Index Pointing Up: Medium-Dark U+1F446, U+1F3FE -Skin Tone -๐Ÿ‘†๐Ÿฟ Backhand Index Pointing Up: Dark Skin U+1F446, U+1F3FF -Tone -๐Ÿ–• Middle Finger U+1F595 -๐Ÿ–•๐Ÿป Middle Finger: Light Skin Tone U+1F595, U+1F3FB -๐Ÿ–•๐Ÿผ Middle Finger: Medium-Light Skin Tone U+1F595, U+1F3FC -๐Ÿ–•๐Ÿฝ Middle Finger: Medium Skin Tone U+1F595, U+1F3FD -๐Ÿ–•๐Ÿพ Middle Finger: Medium-Dark Skin Tone U+1F595, U+1F3FE -๐Ÿ–•๐Ÿฟ Middle Finger: Dark Skin Tone U+1F595, U+1F3FF -๐Ÿ‘‡ Backhand Index Pointing Down U+1F447 -๐Ÿ‘‡๐Ÿป Backhand Index Pointing Down: Light Skin U+1F447, U+1F3FB -Tone -๐Ÿ‘‡๐Ÿผ Backhand Index Pointing Down: U+1F447, U+1F3FC -Medium-Light Skin Tone -๐Ÿ‘‡๐Ÿฝ Backhand Index Pointing Down: Medium Skin U+1F447, U+1F3FD -Tone -๐Ÿ‘‡๐Ÿพ Backhand Index Pointing Down: Medium-Dark U+1F447, U+1F3FE -Skin Tone -๐Ÿ‘‡๐Ÿฟ Backhand Index Pointing Down: Dark Skin U+1F447, U+1F3FF -Tone -โ˜๏ธ Index Pointing Up U+261D, U+FE0F -โ˜๐Ÿป Index Pointing Up: Light Skin Tone U+261D, U+1F3FB -โ˜๐Ÿผ Index Pointing Up: Medium-Light Skin Tone U+261D, U+1F3FC -โ˜๐Ÿฝ Index Pointing Up: Medium Skin Tone U+261D, U+1F3FD -โ˜๐Ÿพ Index Pointing Up: Medium-Dark Skin Tone U+261D, U+1F3FE -โ˜๐Ÿฟ Index Pointing Up: Dark Skin Tone U+261D, U+1F3FF -๐Ÿ‘ Thumbs Up U+1F44D -๐Ÿ‘๐Ÿป Thumbs Up: Light Skin Tone U+1F44D, U+1F3FB -๐Ÿ‘๐Ÿผ Thumbs Up: Medium-Light Skin Tone U+1F44D, U+1F3FC -๐Ÿ‘๐Ÿฝ Thumbs Up: Medium Skin Tone U+1F44D, U+1F3FD -๐Ÿ‘๐Ÿพ Thumbs Up: Medium-Dark Skin Tone U+1F44D, U+1F3FE -๐Ÿ‘๐Ÿฟ Thumbs Up: Dark Skin Tone U+1F44D, U+1F3FF -๐Ÿ‘Ž Thumbs Down U+1F44E -๐Ÿ‘Ž๐Ÿป Thumbs Down: Light Skin Tone U+1F44E, U+1F3FB -๐Ÿ‘Ž๐Ÿผ Thumbs Down: Medium-Light Skin Tone U+1F44E, U+1F3FC -๐Ÿ‘Ž๐Ÿฝ Thumbs Down: Medium Skin Tone U+1F44E, U+1F3FD -๐Ÿ‘Ž๐Ÿพ Thumbs Down: Medium-Dark Skin Tone U+1F44E, U+1F3FE -๐Ÿ‘Ž๐Ÿฟ Thumbs Down: Dark Skin Tone U+1F44E, U+1F3FF -โœŠ Raised Fist U+270A -โœŠ๐Ÿป Raised Fist: Light Skin Tone U+270A, U+1F3FB -โœŠ๐Ÿผ Raised Fist: Medium-Light Skin Tone U+270A, U+1F3FC -โœŠ๐Ÿฝ Raised Fist: Medium Skin Tone U+270A, U+1F3FD -โœŠ๐Ÿพ Raised Fist: Medium-Dark Skin Tone U+270A, U+1F3FE -โœŠ๐Ÿฟ Raised Fist: Dark Skin Tone U+270A, U+1F3FF -๐Ÿ‘Š Oncoming Fist U+1F44A -๐Ÿ‘Š๐Ÿป Oncoming Fist: Light Skin Tone U+1F44A, U+1F3FB -๐Ÿ‘Š๐Ÿผ Oncoming Fist: Medium-Light Skin Tone U+1F44A, U+1F3FC -๐Ÿ‘Š๐Ÿฝ Oncoming Fist: Medium Skin Tone U+1F44A, U+1F3FD -๐Ÿ‘Š๐Ÿพ Oncoming Fist: Medium-Dark Skin Tone U+1F44A, U+1F3FE -๐Ÿ‘Š๐Ÿฟ Oncoming Fist: Dark Skin Tone U+1F44A, U+1F3FF -๐Ÿค› Left-Facing Fist U+1F91B -๐Ÿค›๐Ÿป Left-Facing Fist: Light Skin Tone U+1F91B, U+1F3FB -๐Ÿค›๐Ÿผ Left-Facing Fist: Medium-Light Skin Tone U+1F91B, U+1F3FC -๐Ÿค›๐Ÿฝ Left-Facing Fist: Medium Skin Tone U+1F91B, U+1F3FD -๐Ÿค›๐Ÿพ Left-Facing Fist: Medium-Dark Skin Tone U+1F91B, U+1F3FE -๐Ÿค›๐Ÿฟ Left-Facing Fist: Dark Skin Tone U+1F91B, U+1F3FF -๐Ÿคœ Right-Facing Fist U+1F91C -๐Ÿคœ๐Ÿป Right-Facing Fist: Light Skin Tone U+1F91C, U+1F3FB -๐Ÿคœ๐Ÿผ Right-Facing Fist: Medium-Light Skin Tone U+1F91C, U+1F3FC -๐Ÿคœ๐Ÿฝ Right-Facing Fist: Medium Skin Tone U+1F91C, U+1F3FD -๐Ÿคœ๐Ÿพ Right-Facing Fist: Medium-Dark Skin Tone U+1F91C, U+1F3FE -๐Ÿคœ๐Ÿฟ Right-Facing Fist: Dark Skin Tone U+1F91C, U+1F3FF -๐Ÿ‘ Clapping Hands U+1F44F -๐Ÿ‘๐Ÿป Clapping Hands: Light Skin Tone U+1F44F, U+1F3FB -๐Ÿ‘๐Ÿผ Clapping Hands: Medium-Light Skin Tone U+1F44F, U+1F3FC -๐Ÿ‘๐Ÿฝ Clapping Hands: Medium Skin Tone U+1F44F, U+1F3FD -๐Ÿ‘๐Ÿพ Clapping Hands: Medium-Dark Skin Tone U+1F44F, U+1F3FE -๐Ÿ‘๐Ÿฟ Clapping Hands: Dark Skin Tone U+1F44F, U+1F3FF -๐Ÿ™Œ Raising Hands U+1F64C -๐Ÿ™Œ๐Ÿป Raising Hands: Light Skin Tone U+1F64C, U+1F3FB -๐Ÿ™Œ๐Ÿผ Raising Hands: Medium-Light Skin Tone U+1F64C, U+1F3FC -๐Ÿ™Œ๐Ÿฝ Raising Hands: Medium Skin Tone U+1F64C, U+1F3FD -๐Ÿ™Œ๐Ÿพ Raising Hands: Medium-Dark Skin Tone U+1F64C, U+1F3FE -๐Ÿ™Œ๐Ÿฟ Raising Hands: Dark Skin Tone U+1F64C, U+1F3FF -๐Ÿ‘ Open Hands U+1F450 -๐Ÿ‘๐Ÿป Open Hands: Light Skin Tone U+1F450, U+1F3FB -๐Ÿ‘๐Ÿผ Open Hands: Medium-Light Skin Tone U+1F450, U+1F3FC -๐Ÿ‘๐Ÿฝ Open Hands: Medium Skin Tone U+1F450, U+1F3FD -๐Ÿ‘๐Ÿพ Open Hands: Medium-Dark Skin Tone U+1F450, U+1F3FE -๐Ÿ‘๐Ÿฟ Open Hands: Dark Skin Tone U+1F450, U+1F3FF -๐Ÿคฒ Palms Up Together U+1F932 -๐Ÿคฒ๐Ÿป Palms Up Together: Light Skin Tone U+1F932, U+1F3FB -๐Ÿคฒ๐Ÿผ Palms Up Together: Medium-Light Skin Tone U+1F932, U+1F3FC -๐Ÿคฒ๐Ÿฝ Palms Up Together: Medium Skin Tone U+1F932, U+1F3FD -๐Ÿคฒ๐Ÿพ Palms Up Together: Medium-Dark Skin Tone U+1F932, U+1F3FE -๐Ÿคฒ๐Ÿฟ Palms Up Together: Dark Skin Tone U+1F932, U+1F3FF -๐Ÿค Handshake U+1F91D -๐Ÿ™ Folded Hands U+1F64F -๐Ÿ™๐Ÿป Folded Hands: Light Skin Tone U+1F64F, U+1F3FB -๐Ÿ™๐Ÿผ Folded Hands: Medium-Light Skin Tone U+1F64F, U+1F3FC -๐Ÿ™๐Ÿฝ Folded Hands: Medium Skin Tone U+1F64F, U+1F3FD -๐Ÿ™๐Ÿพ Folded Hands: Medium-Dark Skin Tone U+1F64F, U+1F3FE -๐Ÿ™๐Ÿฟ Folded Hands: Dark Skin Tone U+1F64F, U+1F3FF -โœ๏ธ Writing Hand U+270D, U+FE0F -โœ๐Ÿป Writing Hand: Light Skin Tone U+270D, U+1F3FB -โœ๐Ÿผ Writing Hand: Medium-Light Skin Tone U+270D, U+1F3FC -โœ๐Ÿฝ Writing Hand: Medium Skin Tone U+270D, U+1F3FD -โœ๐Ÿพ Writing Hand: Medium-Dark Skin Tone U+270D, U+1F3FE -โœ๐Ÿฟ Writing Hand: Dark Skin Tone U+270D, U+1F3FF -๐Ÿ’… Nail Polish U+1F485 -๐Ÿ’…๐Ÿป Nail Polish: Light Skin Tone U+1F485, U+1F3FB -๐Ÿ’…๐Ÿผ Nail Polish: Medium-Light Skin Tone U+1F485, U+1F3FC -๐Ÿ’…๐Ÿฝ Nail Polish: Medium Skin Tone U+1F485, U+1F3FD -๐Ÿ’…๐Ÿพ Nail Polish: Medium-Dark Skin Tone U+1F485, U+1F3FE -๐Ÿ’…๐Ÿฟ Nail Polish: Dark Skin Tone U+1F485, U+1F3FF -๐Ÿคณ Selfie U+1F933 -๐Ÿคณ๐Ÿป Selfie: Light Skin Tone U+1F933, U+1F3FB -๐Ÿคณ๐Ÿผ Selfie: Medium-Light Skin Tone U+1F933, U+1F3FC -๐Ÿคณ๐Ÿฝ Selfie: Medium Skin Tone U+1F933, U+1F3FD -๐Ÿคณ๐Ÿพ Selfie: Medium-Dark Skin Tone U+1F933, U+1F3FE -๐Ÿคณ๐Ÿฟ Selfie: Dark Skin Tone U+1F933, U+1F3FF -๐Ÿ’ช Flexed Biceps U+1F4AA -๐Ÿ’ช๐Ÿป Flexed Biceps: Light Skin Tone U+1F4AA, U+1F3FB -๐Ÿ’ช๐Ÿผ Flexed Biceps: Medium-Light Skin Tone U+1F4AA, U+1F3FC -๐Ÿ’ช๐Ÿฝ Flexed Biceps: Medium Skin Tone U+1F4AA, U+1F3FD -๐Ÿ’ช๐Ÿพ Flexed Biceps: Medium-Dark Skin Tone U+1F4AA, U+1F3FE -๐Ÿ’ช๐Ÿฟ Flexed Biceps: Dark Skin Tone U+1F4AA, U+1F3FF -๐Ÿฆพ Mechanical Arm U+1F9BE -๐Ÿฆฟ Mechanical Leg U+1F9BF -๐Ÿฆต Leg U+1F9B5 -๐Ÿฆต๐Ÿป Leg: Light Skin Tone U+1F9B5, U+1F3FB -๐Ÿฆต๐Ÿผ Leg: Medium-Light Skin Tone U+1F9B5, U+1F3FC -๐Ÿฆต๐Ÿฝ Leg: Medium Skin Tone U+1F9B5, U+1F3FD -๐Ÿฆต๐Ÿพ Leg: Medium-Dark Skin Tone U+1F9B5, U+1F3FE -๐Ÿฆต๐Ÿฟ Leg: Dark Skin Tone U+1F9B5, U+1F3FF -๐Ÿฆถ Foot U+1F9B6 -๐Ÿฆถ๐Ÿป Foot: Light Skin Tone U+1F9B6, U+1F3FB -๐Ÿฆถ๐Ÿผ Foot: Medium-Light Skin Tone U+1F9B6, U+1F3FC -๐Ÿฆถ๐Ÿฝ Foot: Medium Skin Tone U+1F9B6, U+1F3FD -๐Ÿฆถ๐Ÿพ Foot: Medium-Dark Skin Tone U+1F9B6, U+1F3FE -๐Ÿฆถ๐Ÿฟ Foot: Dark Skin Tone U+1F9B6, U+1F3FF -๐Ÿ‘‚ Ear U+1F442 -๐Ÿ‘‚๐Ÿป Ear: Light Skin Tone U+1F442, U+1F3FB -๐Ÿ‘‚๐Ÿผ Ear: Medium-Light Skin Tone U+1F442, U+1F3FC -๐Ÿ‘‚๐Ÿฝ Ear: Medium Skin Tone U+1F442, U+1F3FD -๐Ÿ‘‚๐Ÿพ Ear: Medium-Dark Skin Tone U+1F442, U+1F3FE -๐Ÿ‘‚๐Ÿฟ Ear: Dark Skin Tone U+1F442, U+1F3FF -๐Ÿฆป Ear with Hearing Aid U+1F9BB -๐Ÿฆป๐Ÿป Ear with Hearing Aid: Light Skin Tone U+1F9BB, U+1F3FB -๐Ÿฆป๐Ÿผ Ear with Hearing Aid: Medium-Light Skin U+1F9BB, U+1F3FC -Tone -๐Ÿฆป๐Ÿฝ Ear with Hearing Aid: Medium Skin Tone U+1F9BB, U+1F3FD -๐Ÿฆป๐Ÿพ Ear with Hearing Aid: Medium-Dark Skin U+1F9BB, U+1F3FE -Tone -๐Ÿฆป๐Ÿฟ Ear with Hearing Aid: Dark Skin Tone U+1F9BB, U+1F3FF -๐Ÿ‘ƒ Nose U+1F443 -๐Ÿ‘ƒ๐Ÿป Nose: Light Skin Tone U+1F443, U+1F3FB -๐Ÿ‘ƒ๐Ÿผ Nose: Medium-Light Skin Tone U+1F443, U+1F3FC -๐Ÿ‘ƒ๐Ÿฝ Nose: Medium Skin Tone U+1F443, U+1F3FD -๐Ÿ‘ƒ๐Ÿพ Nose: Medium-Dark Skin Tone U+1F443, U+1F3FE -๐Ÿ‘ƒ๐Ÿฟ Nose: Dark Skin Tone U+1F443, U+1F3FF -๐Ÿง  Brain U+1F9E0 -๐Ÿซ€ Anatomical Heart U+1FAC0 -๐Ÿซ Lungs U+1FAC1 -๐Ÿฆท Tooth U+1F9B7 -๐Ÿฆด Bone U+1F9B4 -๐Ÿ‘€ Eyes U+1F440 -๐Ÿ‘๏ธ Eye U+1F441, U+FE0F -๐Ÿ‘… Tongue U+1F445 -๐Ÿ‘„ Mouth U+1F444 -๐Ÿ‘ถ Baby U+1F476 -๐Ÿ‘ถ๐Ÿป Baby: Light Skin Tone U+1F476, U+1F3FB -๐Ÿ‘ถ๐Ÿผ Baby: Medium-Light Skin Tone U+1F476, U+1F3FC -๐Ÿ‘ถ๐Ÿฝ Baby: Medium Skin Tone U+1F476, U+1F3FD -๐Ÿ‘ถ๐Ÿพ Baby: Medium-Dark Skin Tone U+1F476, U+1F3FE -๐Ÿ‘ถ๐Ÿฟ Baby: Dark Skin Tone U+1F476, U+1F3FF -๐Ÿง’ Child U+1F9D2 -๐Ÿง’๐Ÿป Child: Light Skin Tone U+1F9D2, U+1F3FB -๐Ÿง’๐Ÿผ Child: Medium-Light Skin Tone U+1F9D2, U+1F3FC -๐Ÿง’๐Ÿฝ Child: Medium Skin Tone U+1F9D2, U+1F3FD -๐Ÿง’๐Ÿพ Child: Medium-Dark Skin Tone U+1F9D2, U+1F3FE -๐Ÿง’๐Ÿฟ Child: Dark Skin Tone U+1F9D2, U+1F3FF -๐Ÿ‘ฆ Boy U+1F466 -๐Ÿ‘ฆ๐Ÿป Boy: Light Skin Tone U+1F466, U+1F3FB -๐Ÿ‘ฆ๐Ÿผ Boy: Medium-Light Skin Tone U+1F466, U+1F3FC -๐Ÿ‘ฆ๐Ÿฝ Boy: Medium Skin Tone U+1F466, U+1F3FD -๐Ÿ‘ฆ๐Ÿพ Boy: Medium-Dark Skin Tone U+1F466, U+1F3FE -๐Ÿ‘ฆ๐Ÿฟ Boy: Dark Skin Tone U+1F466, U+1F3FF -๐Ÿ‘ง Girl U+1F467 -๐Ÿ‘ง๐Ÿป Girl: Light Skin Tone U+1F467, U+1F3FB -๐Ÿ‘ง๐Ÿผ Girl: Medium-Light Skin Tone U+1F467, U+1F3FC -๐Ÿ‘ง๐Ÿฝ Girl: Medium Skin Tone U+1F467, U+1F3FD -๐Ÿ‘ง๐Ÿพ Girl: Medium-Dark Skin Tone U+1F467, U+1F3FE -๐Ÿ‘ง๐Ÿฟ Girl: Dark Skin Tone U+1F467, U+1F3FF -๐Ÿง‘ Person U+1F9D1 -๐Ÿง‘๐Ÿป Person: Light Skin Tone U+1F9D1, U+1F3FB -๐Ÿง‘๐Ÿผ Person: Medium-Light Skin Tone U+1F9D1, U+1F3FC -๐Ÿง‘๐Ÿฝ Person: Medium Skin Tone U+1F9D1, U+1F3FD -๐Ÿง‘๐Ÿพ Person: Medium-Dark Skin Tone U+1F9D1, U+1F3FE -๐Ÿง‘๐Ÿฟ Person: Dark Skin Tone U+1F9D1, U+1F3FF -๐Ÿ‘ฑ Person: Blond Hair U+1F471 -๐Ÿ‘ฑ๐Ÿป Person: Light Skin Tone, Blond Hair U+1F471, U+1F3FB -๐Ÿ‘ฑ๐Ÿผ Person: Medium-Light Skin Tone, Blond U+1F471, U+1F3FC -Hair -๐Ÿ‘ฑ๐Ÿฝ Person: Medium Skin Tone, Blond Hair U+1F471, U+1F3FD -๐Ÿ‘ฑ๐Ÿพ Person: Medium-Dark Skin Tone, Blond Hair U+1F471, U+1F3FE -๐Ÿ‘ฑ๐Ÿฟ Person: Dark Skin Tone, Blond Hair U+1F471, U+1F3FF -๐Ÿ‘จ Man U+1F468 -๐Ÿ‘จ๐Ÿป Man: Light Skin Tone U+1F468, U+1F3FB -๐Ÿ‘จ๐Ÿผ Man: Medium-Light Skin Tone U+1F468, U+1F3FC -๐Ÿ‘จ๐Ÿฝ Man: Medium Skin Tone U+1F468, U+1F3FD -๐Ÿ‘จ๐Ÿพ Man: Medium-Dark Skin Tone U+1F468, U+1F3FE -๐Ÿ‘จ๐Ÿฟ Man: Dark Skin Tone U+1F468, U+1F3FF -๐Ÿง” Man: Beard U+1F9D4 -๐Ÿง”๐Ÿป Man: Light Skin Tone, Beard U+1F9D4, U+1F3FB -๐Ÿง”๐Ÿผ Man: Medium-Light Skin Tone, Beard U+1F9D4, U+1F3FC -๐Ÿง”๐Ÿฝ Man: Medium Skin Tone, Beard U+1F9D4, U+1F3FD -๐Ÿง”๐Ÿพ Man: Medium-Dark Skin Tone, Beard U+1F9D4, U+1F3FE -๐Ÿง”๐Ÿฟ Man: Dark Skin Tone, Beard U+1F9D4, U+1F3FF -๐Ÿ‘จโ€๐Ÿฆฐ Man: Red Hair U+1F468, U+200D, U+1F9B0 -๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฐ Man: Light Skin Tone, Red Hair U+1F468, U+1F3FB, U+200D, U+1F9B0 -๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฐ Man: Medium-Light Skin Tone, Red Hair U+1F468, U+1F3FC, U+200D, U+1F9B0 -๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฐ Man: Medium Skin Tone, Red Hair U+1F468, U+1F3FD, U+200D, U+1F9B0 -๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฐ Man: Medium-Dark Skin Tone, Red Hair U+1F468, U+1F3FE, U+200D, U+1F9B0 -๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฐ Man: Dark Skin Tone, Red Hair U+1F468, U+1F3FF, U+200D, U+1F9B0 -๐Ÿ‘จโ€๐Ÿฆฑ Man: Curly Hair U+1F468, U+200D, U+1F9B1 -๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฑ Man: Light Skin Tone, Curly Hair U+1F468, U+1F3FB, U+200D, U+1F9B1 -๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฑ Man: Medium-Light Skin Tone, Curly Hair U+1F468, U+1F3FC, U+200D, U+1F9B1 -๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฑ Man: Medium Skin Tone, Curly Hair U+1F468, U+1F3FD, U+200D, U+1F9B1 -๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฑ Man: Medium-Dark Skin Tone, Curly Hair U+1F468, U+1F3FE, U+200D, U+1F9B1 -๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฑ Man: Dark Skin Tone, Curly Hair U+1F468, U+1F3FF, U+200D, U+1F9B1 -๐Ÿ‘จโ€๐Ÿฆณ Man: White Hair U+1F468, U+200D, U+1F9B3 -๐Ÿ‘จ๐Ÿปโ€๐Ÿฆณ Man: Light Skin Tone, White Hair U+1F468, U+1F3FB, U+200D, U+1F9B3 -๐Ÿ‘จ๐Ÿผโ€๐Ÿฆณ Man: Medium-Light Skin Tone, White Hair U+1F468, U+1F3FC, U+200D, U+1F9B3 -๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆณ Man: Medium Skin Tone, White Hair U+1F468, U+1F3FD, U+200D, U+1F9B3 -๐Ÿ‘จ๐Ÿพโ€๐Ÿฆณ Man: Medium-Dark Skin Tone, White Hair U+1F468, U+1F3FE, U+200D, U+1F9B3 -๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆณ Man: Dark Skin Tone, White Hair U+1F468, U+1F3FF, U+200D, U+1F9B3 -๐Ÿ‘จโ€๐Ÿฆฒ Man: Bald U+1F468, U+200D, U+1F9B2 -๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฒ Man: Light Skin Tone, Bald U+1F468, U+1F3FB, U+200D, U+1F9B2 -๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฒ Man: Medium-Light Skin Tone, Bald U+1F468, U+1F3FC, U+200D, U+1F9B2 -๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฒ Man: Medium Skin Tone, Bald U+1F468, U+1F3FD, U+200D, U+1F9B2 -๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฒ Man: Medium-Dark Skin Tone, Bald U+1F468, U+1F3FE, U+200D, U+1F9B2 -๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฒ Man: Dark Skin Tone, Bald U+1F468, U+1F3FF, U+200D, U+1F9B2 -๐Ÿ‘ฉ Woman U+1F469 -๐Ÿ‘ฉ๐Ÿป Woman: Light Skin Tone U+1F469, U+1F3FB -๐Ÿ‘ฉ๐Ÿผ Woman: Medium-Light Skin Tone U+1F469, U+1F3FC -๐Ÿ‘ฉ๐Ÿฝ Woman: Medium Skin Tone U+1F469, U+1F3FD -๐Ÿ‘ฉ๐Ÿพ Woman: Medium-Dark Skin Tone U+1F469, U+1F3FE -๐Ÿ‘ฉ๐Ÿฟ Woman: Dark Skin Tone U+1F469, U+1F3FF -๐Ÿ‘ฉโ€๐Ÿฆฐ Woman: Red Hair U+1F469, U+200D, U+1F9B0 -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฐ Woman: Light Skin Tone, Red Hair U+1F469, U+1F3FB, U+200D, U+1F9B0 -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฐ Woman: Medium-Light Skin Tone, Red Hair U+1F469, U+1F3FC, U+200D, U+1F9B0 -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฐ Woman: Medium Skin Tone, Red Hair U+1F469, U+1F3FD, U+200D, U+1F9B0 -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฐ Woman: Medium-Dark Skin Tone, Red Hair U+1F469, U+1F3FE, U+200D, U+1F9B0 -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฐ Woman: Dark Skin Tone, Red Hair U+1F469, U+1F3FF, U+200D, U+1F9B0 -๐Ÿง‘โ€๐Ÿฆฐ Person: Red Hair U+1F9D1, U+200D, U+1F9B0 -๐Ÿง‘๐Ÿปโ€๐Ÿฆฐ Person: Light Skin Tone, Red Hair U+1F9D1, U+1F3FB, U+200D, U+1F9B0 -๐Ÿง‘๐Ÿผโ€๐Ÿฆฐ Person: Medium-Light Skin Tone, Red U+1F9D1, U+1F3FC, U+200D, U+1F9B0 -Hair -๐Ÿง‘๐Ÿฝโ€๐Ÿฆฐ Person: Medium Skin Tone, Red Hair U+1F9D1, U+1F3FD, U+200D, U+1F9B0 -๐Ÿง‘๐Ÿพโ€๐Ÿฆฐ Person: Medium-Dark Skin Tone, Red Hair U+1F9D1, U+1F3FE, U+200D, U+1F9B0 -๐Ÿง‘๐Ÿฟโ€๐Ÿฆฐ Person: Dark Skin Tone, Red Hair U+1F9D1, U+1F3FF, U+200D, U+1F9B0 -๐Ÿ‘ฉโ€๐Ÿฆฑ Woman: Curly Hair U+1F469, U+200D, U+1F9B1 -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฑ Woman: Light Skin Tone, Curly Hair U+1F469, U+1F3FB, U+200D, U+1F9B1 -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฑ Woman: Medium-Light Skin Tone, Curly U+1F469, U+1F3FC, U+200D, U+1F9B1 -Hair -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฑ Woman: Medium Skin Tone, Curly Hair U+1F469, U+1F3FD, U+200D, U+1F9B1 -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฑ Woman: Medium-Dark Skin Tone, Curly U+1F469, U+1F3FE, U+200D, U+1F9B1 -Hair -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฑ Woman: Dark Skin Tone, Curly Hair U+1F469, U+1F3FF, U+200D, U+1F9B1 -๐Ÿง‘โ€๐Ÿฆฑ Person: Curly Hair U+1F9D1, U+200D, U+1F9B1 -๐Ÿง‘๐Ÿปโ€๐Ÿฆฑ Person: Light Skin Tone, Curly Hair U+1F9D1, U+1F3FB, U+200D, U+1F9B1 -๐Ÿง‘๐Ÿผโ€๐Ÿฆฑ Person: Medium-Light Skin Tone, Curly U+1F9D1, U+1F3FC, U+200D, U+1F9B1 -Hair -๐Ÿง‘๐Ÿฝโ€๐Ÿฆฑ Person: Medium Skin Tone, Curly Hair U+1F9D1, U+1F3FD, U+200D, U+1F9B1 -๐Ÿง‘๐Ÿพโ€๐Ÿฆฑ Person: Medium-Dark Skin Tone, Curly U+1F9D1, U+1F3FE, U+200D, U+1F9B1 -Hair -๐Ÿง‘๐Ÿฟโ€๐Ÿฆฑ Person: Dark Skin Tone, Curly Hair U+1F9D1, U+1F3FF, U+200D, U+1F9B1 -๐Ÿ‘ฉโ€๐Ÿฆณ Woman: White Hair U+1F469, U+200D, U+1F9B3 -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆณ Woman: Light Skin Tone, White Hair U+1F469, U+1F3FB, U+200D, U+1F9B3 -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆณ Woman: Medium-Light Skin Tone, White U+1F469, U+1F3FC, U+200D, U+1F9B3 -Hair -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆณ Woman: Medium Skin Tone, White Hair U+1F469, U+1F3FD, U+200D, U+1F9B3 -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆณ Woman: Medium-Dark Skin Tone, White U+1F469, U+1F3FE, U+200D, U+1F9B3 -Hair -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆณ Woman: Dark Skin Tone, White Hair U+1F469, U+1F3FF, U+200D, U+1F9B3 -๐Ÿง‘โ€๐Ÿฆณ Person: White Hair U+1F9D1, U+200D, U+1F9B3 -๐Ÿง‘๐Ÿปโ€๐Ÿฆณ Person: Light Skin Tone, White Hair U+1F9D1, U+1F3FB, U+200D, U+1F9B3 -๐Ÿง‘๐Ÿผโ€๐Ÿฆณ Person: Medium-Light Skin Tone, White U+1F9D1, U+1F3FC, U+200D, U+1F9B3 -Hair -๐Ÿง‘๐Ÿฝโ€๐Ÿฆณ Person: Medium Skin Tone, White Hair U+1F9D1, U+1F3FD, U+200D, U+1F9B3 -๐Ÿง‘๐Ÿพโ€๐Ÿฆณ Person: Medium-Dark Skin Tone, White U+1F9D1, U+1F3FE, U+200D, U+1F9B3 -Hair -๐Ÿง‘๐Ÿฟโ€๐Ÿฆณ Person: Dark Skin Tone, White Hair U+1F9D1, U+1F3FF, U+200D, U+1F9B3 -๐Ÿ‘ฉโ€๐Ÿฆฒ Woman: Bald U+1F469, U+200D, U+1F9B2 -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฒ Woman: Light Skin Tone, Bald U+1F469, U+1F3FB, U+200D, U+1F9B2 -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฒ Woman: Medium-Light Skin Tone, Bald U+1F469, U+1F3FC, U+200D, U+1F9B2 -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฒ Woman: Medium Skin Tone, Bald U+1F469, U+1F3FD, U+200D, U+1F9B2 -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฒ Woman: Medium-Dark Skin Tone, Bald U+1F469, U+1F3FE, U+200D, U+1F9B2 -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฒ Woman: Dark Skin Tone, Bald U+1F469, U+1F3FF, U+200D, U+1F9B2 -๐Ÿง‘โ€๐Ÿฆฒ Person: Bald U+1F9D1, U+200D, U+1F9B2 -๐Ÿง‘๐Ÿปโ€๐Ÿฆฒ Person: Light Skin Tone, Bald U+1F9D1, U+1F3FB, U+200D, U+1F9B2 -๐Ÿง‘๐Ÿผโ€๐Ÿฆฒ Person: Medium-Light Skin Tone, Bald U+1F9D1, U+1F3FC, U+200D, U+1F9B2 -๐Ÿง‘๐Ÿฝโ€๐Ÿฆฒ Person: Medium Skin Tone, Bald U+1F9D1, U+1F3FD, U+200D, U+1F9B2 -๐Ÿง‘๐Ÿพโ€๐Ÿฆฒ Person: Medium-Dark Skin Tone, Bald U+1F9D1, U+1F3FE, U+200D, U+1F9B2 -๐Ÿง‘๐Ÿฟโ€๐Ÿฆฒ Person: Dark Skin Tone, Bald U+1F9D1, U+1F3FF, U+200D, U+1F9B2 -๐Ÿ‘ฑโ€โ™€๏ธ Woman: Blond Hair U+1F471, U+200D, U+2640, U+FE0F -๐Ÿ‘ฑ๐Ÿปโ€โ™€๏ธ Woman: Light Skin Tone, Blond Hair U+1F471, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฑ๐Ÿผโ€โ™€๏ธ Woman: Medium-Light Skin Tone, Blond U+1F471, U+1F3FC, U+200D, U+2640, -Hair U+FE0F -๐Ÿ‘ฑ๐Ÿฝโ€โ™€๏ธ Woman: Medium Skin Tone, Blond Hair U+1F471, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฑ๐Ÿพโ€โ™€๏ธ Woman: Medium-Dark Skin Tone, Blond U+1F471, U+1F3FE, U+200D, U+2640, -Hair U+FE0F -๐Ÿ‘ฑ๐Ÿฟโ€โ™€๏ธ Woman: Dark Skin Tone, Blond Hair U+1F471, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฑโ€โ™‚๏ธ Man: Blond Hair U+1F471, U+200D, U+2642, U+FE0F -๐Ÿ‘ฑ๐Ÿปโ€โ™‚๏ธ Man: Light Skin Tone, Blond Hair U+1F471, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฑ๐Ÿผโ€โ™‚๏ธ Man: Medium-Light Skin Tone, Blond U+1F471, U+1F3FC, U+200D, U+2642, -Hair U+FE0F -๐Ÿ‘ฑ๐Ÿฝโ€โ™‚๏ธ Man: Medium Skin Tone, Blond Hair U+1F471, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฑ๐Ÿพโ€โ™‚๏ธ Man: Medium-Dark Skin Tone, Blond Hair U+1F471, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฑ๐Ÿฟโ€โ™‚๏ธ Man: Dark Skin Tone, Blond Hair U+1F471, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿง“ Older Person U+1F9D3 -๐Ÿง“๐Ÿป Older Person: Light Skin Tone U+1F9D3, U+1F3FB -๐Ÿง“๐Ÿผ Older Person: Medium-Light Skin Tone U+1F9D3, U+1F3FC -๐Ÿง“๐Ÿฝ Older Person: Medium Skin Tone U+1F9D3, U+1F3FD -๐Ÿง“๐Ÿพ Older Person: Medium-Dark Skin Tone U+1F9D3, U+1F3FE -๐Ÿง“๐Ÿฟ Older Person: Dark Skin Tone U+1F9D3, U+1F3FF -๐Ÿ‘ด Old Man U+1F474 -๐Ÿ‘ด๐Ÿป Old Man: Light Skin Tone U+1F474, U+1F3FB -๐Ÿ‘ด๐Ÿผ Old Man: Medium-Light Skin Tone U+1F474, U+1F3FC -๐Ÿ‘ด๐Ÿฝ Old Man: Medium Skin Tone U+1F474, U+1F3FD -๐Ÿ‘ด๐Ÿพ Old Man: Medium-Dark Skin Tone U+1F474, U+1F3FE -๐Ÿ‘ด๐Ÿฟ Old Man: Dark Skin Tone U+1F474, U+1F3FF -๐Ÿ‘ต Old Woman U+1F475 -๐Ÿ‘ต๐Ÿป Old Woman: Light Skin Tone U+1F475, U+1F3FB -๐Ÿ‘ต๐Ÿผ Old Woman: Medium-Light Skin Tone U+1F475, U+1F3FC -๐Ÿ‘ต๐Ÿฝ Old Woman: Medium Skin Tone U+1F475, U+1F3FD -๐Ÿ‘ต๐Ÿพ Old Woman: Medium-Dark Skin Tone U+1F475, U+1F3FE -๐Ÿ‘ต๐Ÿฟ Old Woman: Dark Skin Tone U+1F475, U+1F3FF -๐Ÿ™ Person Frowning U+1F64D -๐Ÿ™๐Ÿป Person Frowning: Light Skin Tone U+1F64D, U+1F3FB -๐Ÿ™๐Ÿผ Person Frowning: Medium-Light Skin Tone U+1F64D, U+1F3FC -๐Ÿ™๐Ÿฝ Person Frowning: Medium Skin Tone U+1F64D, U+1F3FD -๐Ÿ™๐Ÿพ Person Frowning: Medium-Dark Skin Tone U+1F64D, U+1F3FE -๐Ÿ™๐Ÿฟ Person Frowning: Dark Skin Tone U+1F64D, U+1F3FF -๐Ÿ™โ€โ™‚๏ธ Man Frowning U+1F64D, U+200D, U+2642, U+FE0F -๐Ÿ™๐Ÿปโ€โ™‚๏ธ Man Frowning: Light Skin Tone U+1F64D, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ™๐Ÿผโ€โ™‚๏ธ Man Frowning: Medium-Light Skin Tone U+1F64D, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿ™๐Ÿฝโ€โ™‚๏ธ Man Frowning: Medium Skin Tone U+1F64D, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ™๐Ÿพโ€โ™‚๏ธ Man Frowning: Medium-Dark Skin Tone U+1F64D, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿ™๐Ÿฟโ€โ™‚๏ธ Man Frowning: Dark Skin Tone U+1F64D, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ™โ€โ™€๏ธ Woman Frowning U+1F64D, U+200D, U+2640, U+FE0F -๐Ÿ™๐Ÿปโ€โ™€๏ธ Woman Frowning: Light Skin Tone U+1F64D, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ™๐Ÿผโ€โ™€๏ธ Woman Frowning: Medium-Light Skin Tone U+1F64D, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿ™๐Ÿฝโ€โ™€๏ธ Woman Frowning: Medium Skin Tone U+1F64D, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ™๐Ÿพโ€โ™€๏ธ Woman Frowning: Medium-Dark Skin Tone U+1F64D, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿ™๐Ÿฟโ€โ™€๏ธ Woman Frowning: Dark Skin Tone U+1F64D, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ™Ž Person Pouting U+1F64E -๐Ÿ™Ž๐Ÿป Person Pouting: Light Skin Tone U+1F64E, U+1F3FB -๐Ÿ™Ž๐Ÿผ Person Pouting: Medium-Light Skin Tone U+1F64E, U+1F3FC -๐Ÿ™Ž๐Ÿฝ Person Pouting: Medium Skin Tone U+1F64E, U+1F3FD -๐Ÿ™Ž๐Ÿพ Person Pouting: Medium-Dark Skin Tone U+1F64E, U+1F3FE -๐Ÿ™Ž๐Ÿฟ Person Pouting: Dark Skin Tone U+1F64E, U+1F3FF -๐Ÿ™Žโ€โ™‚๏ธ Man Pouting U+1F64E, U+200D, U+2642, U+FE0F -๐Ÿ™Ž๐Ÿปโ€โ™‚๏ธ Man Pouting: Light Skin Tone U+1F64E, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ™Ž๐Ÿผโ€โ™‚๏ธ Man Pouting: Medium-Light Skin Tone U+1F64E, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿ™Ž๐Ÿฝโ€โ™‚๏ธ Man Pouting: Medium Skin Tone U+1F64E, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ™Ž๐Ÿพโ€โ™‚๏ธ Man Pouting: Medium-Dark Skin Tone U+1F64E, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿ™Ž๐Ÿฟโ€โ™‚๏ธ Man Pouting: Dark Skin Tone U+1F64E, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ™Žโ€โ™€๏ธ Woman Pouting U+1F64E, U+200D, U+2640, U+FE0F -๐Ÿ™Ž๐Ÿปโ€โ™€๏ธ Woman Pouting: Light Skin Tone U+1F64E, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ™Ž๐Ÿผโ€โ™€๏ธ Woman Pouting: Medium-Light Skin Tone U+1F64E, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿ™Ž๐Ÿฝโ€โ™€๏ธ Woman Pouting: Medium Skin Tone U+1F64E, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ™Ž๐Ÿพโ€โ™€๏ธ Woman Pouting: Medium-Dark Skin Tone U+1F64E, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿ™Ž๐Ÿฟโ€โ™€๏ธ Woman Pouting: Dark Skin Tone U+1F64E, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ™… Person Gesturing No U+1F645 -๐Ÿ™…๐Ÿป Person Gesturing No: Light Skin Tone U+1F645, U+1F3FB -๐Ÿ™…๐Ÿผ Person Gesturing No: Medium-Light Skin U+1F645, U+1F3FC -Tone -๐Ÿ™…๐Ÿฝ Person Gesturing No: Medium Skin Tone U+1F645, U+1F3FD -๐Ÿ™…๐Ÿพ Person Gesturing No: Medium-Dark Skin U+1F645, U+1F3FE -Tone -๐Ÿ™…๐Ÿฟ Person Gesturing No: Dark Skin Tone U+1F645, U+1F3FF -๐Ÿ™…โ€โ™‚๏ธ Man Gesturing No U+1F645, U+200D, U+2642, U+FE0F -๐Ÿ™…๐Ÿปโ€โ™‚๏ธ Man Gesturing No: Light Skin Tone U+1F645, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ™…๐Ÿผโ€โ™‚๏ธ Man Gesturing No: Medium-Light Skin U+1F645, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿ™…๐Ÿฝโ€โ™‚๏ธ Man Gesturing No: Medium Skin Tone U+1F645, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ™…๐Ÿพโ€โ™‚๏ธ Man Gesturing No: Medium-Dark Skin U+1F645, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿ™…๐Ÿฟโ€โ™‚๏ธ Man Gesturing No: Dark Skin Tone U+1F645, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ™…โ€โ™€๏ธ Woman Gesturing No U+1F645, U+200D, U+2640, U+FE0F -๐Ÿ™…๐Ÿปโ€โ™€๏ธ Woman Gesturing No: Light Skin Tone U+1F645, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ™…๐Ÿผโ€โ™€๏ธ Woman Gesturing No: Medium-Light Skin U+1F645, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿ™…๐Ÿฝโ€โ™€๏ธ Woman Gesturing No: Medium Skin Tone U+1F645, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ™…๐Ÿพโ€โ™€๏ธ Woman Gesturing No: Medium-Dark Skin U+1F645, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿ™…๐Ÿฟโ€โ™€๏ธ Woman Gesturing No: Dark Skin Tone U+1F645, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ™† Person Gesturing OK U+1F646 -๐Ÿ™†๐Ÿป Person Gesturing OK: Light Skin Tone U+1F646, U+1F3FB -๐Ÿ™†๐Ÿผ Person Gesturing OK: Medium-Light Skin U+1F646, U+1F3FC -Tone -๐Ÿ™†๐Ÿฝ Person Gesturing OK: Medium Skin Tone U+1F646, U+1F3FD -๐Ÿ™†๐Ÿพ Person Gesturing OK: Medium-Dark Skin U+1F646, U+1F3FE -Tone -๐Ÿ™†๐Ÿฟ Person Gesturing OK: Dark Skin Tone U+1F646, U+1F3FF -๐Ÿ™†โ€โ™‚๏ธ Man Gesturing OK U+1F646, U+200D, U+2642, U+FE0F -๐Ÿ™†๐Ÿปโ€โ™‚๏ธ Man Gesturing OK: Light Skin Tone U+1F646, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ™†๐Ÿผโ€โ™‚๏ธ Man Gesturing OK: Medium-Light Skin U+1F646, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿ™†๐Ÿฝโ€โ™‚๏ธ Man Gesturing OK: Medium Skin Tone U+1F646, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ™†๐Ÿพโ€โ™‚๏ธ Man Gesturing OK: Medium-Dark Skin U+1F646, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿ™†๐Ÿฟโ€โ™‚๏ธ Man Gesturing OK: Dark Skin Tone U+1F646, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ™†โ€โ™€๏ธ Woman Gesturing OK U+1F646, U+200D, U+2640, U+FE0F -๐Ÿ™†๐Ÿปโ€โ™€๏ธ Woman Gesturing OK: Light Skin Tone U+1F646, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ™†๐Ÿผโ€โ™€๏ธ Woman Gesturing OK: Medium-Light Skin U+1F646, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿ™†๐Ÿฝโ€โ™€๏ธ Woman Gesturing OK: Medium Skin Tone U+1F646, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ™†๐Ÿพโ€โ™€๏ธ Woman Gesturing OK: Medium-Dark Skin U+1F646, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿ™†๐Ÿฟโ€โ™€๏ธ Woman Gesturing OK: Dark Skin Tone U+1F646, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ’ Person Tipping Hand U+1F481 -๐Ÿ’๐Ÿป Person Tipping Hand: Light Skin Tone U+1F481, U+1F3FB -๐Ÿ’๐Ÿผ Person Tipping Hand: Medium-Light Skin U+1F481, U+1F3FC -Tone -๐Ÿ’๐Ÿฝ Person Tipping Hand: Medium Skin Tone U+1F481, U+1F3FD -๐Ÿ’๐Ÿพ Person Tipping Hand: Medium-Dark Skin U+1F481, U+1F3FE -Tone -๐Ÿ’๐Ÿฟ Person Tipping Hand: Dark Skin Tone U+1F481, U+1F3FF -๐Ÿ’โ€โ™‚๏ธ Man Tipping Hand U+1F481, U+200D, U+2642, U+FE0F -๐Ÿ’๐Ÿปโ€โ™‚๏ธ Man Tipping Hand: Light Skin Tone U+1F481, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ’๐Ÿผโ€โ™‚๏ธ Man Tipping Hand: Medium-Light Skin U+1F481, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿ’๐Ÿฝโ€โ™‚๏ธ Man Tipping Hand: Medium Skin Tone U+1F481, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ’๐Ÿพโ€โ™‚๏ธ Man Tipping Hand: Medium-Dark Skin U+1F481, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿ’๐Ÿฟโ€โ™‚๏ธ Man Tipping Hand: Dark Skin Tone U+1F481, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ’โ€โ™€๏ธ Woman Tipping Hand U+1F481, U+200D, U+2640, U+FE0F -๐Ÿ’๐Ÿปโ€โ™€๏ธ Woman Tipping Hand: Light Skin Tone U+1F481, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ’๐Ÿผโ€โ™€๏ธ Woman Tipping Hand: Medium-Light Skin U+1F481, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿ’๐Ÿฝโ€โ™€๏ธ Woman Tipping Hand: Medium Skin Tone U+1F481, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ’๐Ÿพโ€โ™€๏ธ Woman Tipping Hand: Medium-Dark Skin U+1F481, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿ’๐Ÿฟโ€โ™€๏ธ Woman Tipping Hand: Dark Skin Tone U+1F481, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ™‹ Person Raising Hand U+1F64B -๐Ÿ™‹๐Ÿป Person Raising Hand: Light Skin Tone U+1F64B, U+1F3FB -๐Ÿ™‹๐Ÿผ Person Raising Hand: Medium-Light Skin U+1F64B, U+1F3FC -Tone -๐Ÿ™‹๐Ÿฝ Person Raising Hand: Medium Skin Tone U+1F64B, U+1F3FD -๐Ÿ™‹๐Ÿพ Person Raising Hand: Medium-Dark Skin U+1F64B, U+1F3FE -Tone -๐Ÿ™‹๐Ÿฟ Person Raising Hand: Dark Skin Tone U+1F64B, U+1F3FF -๐Ÿ™‹โ€โ™‚๏ธ Man Raising Hand U+1F64B, U+200D, U+2642, U+FE0F -๐Ÿ™‹๐Ÿปโ€โ™‚๏ธ Man Raising Hand: Light Skin Tone U+1F64B, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ™‹๐Ÿผโ€โ™‚๏ธ Man Raising Hand: Medium-Light Skin U+1F64B, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿ™‹๐Ÿฝโ€โ™‚๏ธ Man Raising Hand: Medium Skin Tone U+1F64B, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ™‹๐Ÿพโ€โ™‚๏ธ Man Raising Hand: Medium-Dark Skin U+1F64B, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿ™‹๐Ÿฟโ€โ™‚๏ธ Man Raising Hand: Dark Skin Tone U+1F64B, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ™‹โ€โ™€๏ธ Woman Raising Hand U+1F64B, U+200D, U+2640, U+FE0F -๐Ÿ™‹๐Ÿปโ€โ™€๏ธ Woman Raising Hand: Light Skin Tone U+1F64B, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ™‹๐Ÿผโ€โ™€๏ธ Woman Raising Hand: Medium-Light Skin U+1F64B, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿ™‹๐Ÿฝโ€โ™€๏ธ Woman Raising Hand: Medium Skin Tone U+1F64B, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ™‹๐Ÿพโ€โ™€๏ธ Woman Raising Hand: Medium-Dark Skin U+1F64B, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿ™‹๐Ÿฟโ€โ™€๏ธ Woman Raising Hand: Dark Skin Tone U+1F64B, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿง Deaf Person U+1F9CF -๐Ÿง๐Ÿป Deaf Person: Light Skin Tone U+1F9CF, U+1F3FB -๐Ÿง๐Ÿผ Deaf Person: Medium-Light Skin Tone U+1F9CF, U+1F3FC -๐Ÿง๐Ÿฝ Deaf Person: Medium Skin Tone U+1F9CF, U+1F3FD -๐Ÿง๐Ÿพ Deaf Person: Medium-Dark Skin Tone U+1F9CF, U+1F3FE -๐Ÿง๐Ÿฟ Deaf Person: Dark Skin Tone U+1F9CF, U+1F3FF -๐Ÿงโ€โ™‚๏ธ Deaf Man U+1F9CF, U+200D, U+2642, U+FE0F -๐Ÿง๐Ÿปโ€โ™‚๏ธ Deaf Man: Light Skin Tone U+1F9CF, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿผโ€โ™‚๏ธ Deaf Man: Medium-Light Skin Tone U+1F9CF, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿฝโ€โ™‚๏ธ Deaf Man: Medium Skin Tone U+1F9CF, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿพโ€โ™‚๏ธ Deaf Man: Medium-Dark Skin Tone U+1F9CF, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿฟโ€โ™‚๏ธ Deaf Man: Dark Skin Tone U+1F9CF, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿงโ€โ™€๏ธ Deaf Woman U+1F9CF, U+200D, U+2640, U+FE0F -๐Ÿง๐Ÿปโ€โ™€๏ธ Deaf Woman: Light Skin Tone U+1F9CF, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿผโ€โ™€๏ธ Deaf Woman: Medium-Light Skin Tone U+1F9CF, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿฝโ€โ™€๏ธ Deaf Woman: Medium Skin Tone U+1F9CF, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿพโ€โ™€๏ธ Deaf Woman: Medium-Dark Skin Tone U+1F9CF, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿฟโ€โ™€๏ธ Deaf Woman: Dark Skin Tone U+1F9CF, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ™‡ Person Bowing U+1F647 -๐Ÿ™‡๐Ÿป Person Bowing: Light Skin Tone U+1F647, U+1F3FB -๐Ÿ™‡๐Ÿผ Person Bowing: Medium-Light Skin Tone U+1F647, U+1F3FC -๐Ÿ™‡๐Ÿฝ Person Bowing: Medium Skin Tone U+1F647, U+1F3FD -๐Ÿ™‡๐Ÿพ Person Bowing: Medium-Dark Skin Tone U+1F647, U+1F3FE -๐Ÿ™‡๐Ÿฟ Person Bowing: Dark Skin Tone U+1F647, U+1F3FF -๐Ÿ™‡โ€โ™‚๏ธ Man Bowing U+1F647, U+200D, U+2642, U+FE0F -๐Ÿ™‡๐Ÿปโ€โ™‚๏ธ Man Bowing: Light Skin Tone U+1F647, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ™‡๐Ÿผโ€โ™‚๏ธ Man Bowing: Medium-Light Skin Tone U+1F647, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿ™‡๐Ÿฝโ€โ™‚๏ธ Man Bowing: Medium Skin Tone U+1F647, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ™‡๐Ÿพโ€โ™‚๏ธ Man Bowing: Medium-Dark Skin Tone U+1F647, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿ™‡๐Ÿฟโ€โ™‚๏ธ Man Bowing: Dark Skin Tone U+1F647, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ™‡โ€โ™€๏ธ Woman Bowing U+1F647, U+200D, U+2640, U+FE0F -๐Ÿ™‡๐Ÿปโ€โ™€๏ธ Woman Bowing: Light Skin Tone U+1F647, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ™‡๐Ÿผโ€โ™€๏ธ Woman Bowing: Medium-Light Skin Tone U+1F647, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿ™‡๐Ÿฝโ€โ™€๏ธ Woman Bowing: Medium Skin Tone U+1F647, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ™‡๐Ÿพโ€โ™€๏ธ Woman Bowing: Medium-Dark Skin Tone U+1F647, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿ™‡๐Ÿฟโ€โ™€๏ธ Woman Bowing: Dark Skin Tone U+1F647, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿคฆ Person Facepalming U+1F926 -๐Ÿคฆ๐Ÿป Person Facepalming: Light Skin Tone U+1F926, U+1F3FB -๐Ÿคฆ๐Ÿผ Person Facepalming: Medium-Light Skin U+1F926, U+1F3FC -Tone -๐Ÿคฆ๐Ÿฝ Person Facepalming: Medium Skin Tone U+1F926, U+1F3FD -๐Ÿคฆ๐Ÿพ Person Facepalming: Medium-Dark Skin Tone U+1F926, U+1F3FE -๐Ÿคฆ๐Ÿฟ Person Facepalming: Dark Skin Tone U+1F926, U+1F3FF -๐Ÿคฆโ€โ™‚๏ธ Man Facepalming U+1F926, U+200D, U+2642, U+FE0F -๐Ÿคฆ๐Ÿปโ€โ™‚๏ธ Man Facepalming: Light Skin Tone U+1F926, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿคฆ๐Ÿผโ€โ™‚๏ธ Man Facepalming: Medium-Light Skin U+1F926, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿคฆ๐Ÿฝโ€โ™‚๏ธ Man Facepalming: Medium Skin Tone U+1F926, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿคฆ๐Ÿพโ€โ™‚๏ธ Man Facepalming: Medium-Dark Skin Tone U+1F926, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿคฆ๐Ÿฟโ€โ™‚๏ธ Man Facepalming: Dark Skin Tone U+1F926, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿคฆโ€โ™€๏ธ Woman Facepalming U+1F926, U+200D, U+2640, U+FE0F -๐Ÿคฆ๐Ÿปโ€โ™€๏ธ Woman Facepalming: Light Skin Tone U+1F926, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿคฆ๐Ÿผโ€โ™€๏ธ Woman Facepalming: Medium-Light Skin U+1F926, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿคฆ๐Ÿฝโ€โ™€๏ธ Woman Facepalming: Medium Skin Tone U+1F926, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿคฆ๐Ÿพโ€โ™€๏ธ Woman Facepalming: Medium-Dark Skin U+1F926, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿคฆ๐Ÿฟโ€โ™€๏ธ Woman Facepalming: Dark Skin Tone U+1F926, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿคท Person Shrugging U+1F937 -๐Ÿคท๐Ÿป Person Shrugging: Light Skin Tone U+1F937, U+1F3FB -๐Ÿคท๐Ÿผ Person Shrugging: Medium-Light Skin Tone U+1F937, U+1F3FC -๐Ÿคท๐Ÿฝ Person Shrugging: Medium Skin Tone U+1F937, U+1F3FD -๐Ÿคท๐Ÿพ Person Shrugging: Medium-Dark Skin Tone U+1F937, U+1F3FE -๐Ÿคท๐Ÿฟ Person Shrugging: Dark Skin Tone U+1F937, U+1F3FF -๐Ÿคทโ€โ™‚๏ธ Man Shrugging U+1F937, U+200D, U+2642, U+FE0F -๐Ÿคท๐Ÿปโ€โ™‚๏ธ Man Shrugging: Light Skin Tone U+1F937, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿคท๐Ÿผโ€โ™‚๏ธ Man Shrugging: Medium-Light Skin Tone U+1F937, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿคท๐Ÿฝโ€โ™‚๏ธ Man Shrugging: Medium Skin Tone U+1F937, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿคท๐Ÿพโ€โ™‚๏ธ Man Shrugging: Medium-Dark Skin Tone U+1F937, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿคท๐Ÿฟโ€โ™‚๏ธ Man Shrugging: Dark Skin Tone U+1F937, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿคทโ€โ™€๏ธ Woman Shrugging U+1F937, U+200D, U+2640, U+FE0F -๐Ÿคท๐Ÿปโ€โ™€๏ธ Woman Shrugging: Light Skin Tone U+1F937, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿคท๐Ÿผโ€โ™€๏ธ Woman Shrugging: Medium-Light Skin U+1F937, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿคท๐Ÿฝโ€โ™€๏ธ Woman Shrugging: Medium Skin Tone U+1F937, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿคท๐Ÿพโ€โ™€๏ธ Woman Shrugging: Medium-Dark Skin Tone U+1F937, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿคท๐Ÿฟโ€โ™€๏ธ Woman Shrugging: Dark Skin Tone U+1F937, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿง‘โ€โš•๏ธ Health Worker U+1F9D1, U+200D, U+2695, U+FE0F -๐Ÿง‘๐Ÿปโ€โš•๏ธ Health Worker: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+2695, - U+FE0F -๐Ÿง‘๐Ÿผโ€โš•๏ธ Health Worker: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+2695, - U+FE0F -๐Ÿง‘๐Ÿฝโ€โš•๏ธ Health Worker: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+2695, - U+FE0F -๐Ÿง‘๐Ÿพโ€โš•๏ธ Health Worker: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+2695, - U+FE0F -๐Ÿง‘๐Ÿฟโ€โš•๏ธ Health Worker: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+2695, - U+FE0F -๐Ÿ‘จโ€โš•๏ธ Man Health Worker U+1F468, U+200D, U+2695, U+FE0F -๐Ÿ‘จ๐Ÿปโ€โš•๏ธ Man Health Worker: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+2695, - U+FE0F -๐Ÿ‘จ๐Ÿผโ€โš•๏ธ Man Health Worker: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+2695, -Tone U+FE0F -๐Ÿ‘จ๐Ÿฝโ€โš•๏ธ Man Health Worker: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+2695, - U+FE0F -๐Ÿ‘จ๐Ÿพโ€โš•๏ธ Man Health Worker: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+2695, -Tone U+FE0F -๐Ÿ‘จ๐Ÿฟโ€โš•๏ธ Man Health Worker: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+2695, - U+FE0F -๐Ÿ‘ฉโ€โš•๏ธ Woman Health Worker U+1F469, U+200D, U+2695, U+FE0F -๐Ÿ‘ฉ๐Ÿปโ€โš•๏ธ Woman Health Worker: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+2695, - U+FE0F -๐Ÿ‘ฉ๐Ÿผโ€โš•๏ธ Woman Health Worker: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+2695, -Tone U+FE0F -๐Ÿ‘ฉ๐Ÿฝโ€โš•๏ธ Woman Health Worker: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+2695, - U+FE0F -๐Ÿ‘ฉ๐Ÿพโ€โš•๏ธ Woman Health Worker: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+2695, -Tone U+FE0F -๐Ÿ‘ฉ๐Ÿฟโ€โš•๏ธ Woman Health Worker: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+2695, - U+FE0F -๐Ÿง‘โ€๐ŸŽ“ Student U+1F9D1, U+200D, U+1F393 -๐Ÿง‘๐Ÿปโ€๐ŸŽ“ Student: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F393 -๐Ÿง‘๐Ÿผโ€๐ŸŽ“ Student: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F393 -๐Ÿง‘๐Ÿฝโ€๐ŸŽ“ Student: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F393 -๐Ÿง‘๐Ÿพโ€๐ŸŽ“ Student: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F393 -๐Ÿง‘๐Ÿฟโ€๐ŸŽ“ Student: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F393 -๐Ÿ‘จโ€๐ŸŽ“ Man Student U+1F468, U+200D, U+1F393 -๐Ÿ‘จ๐Ÿปโ€๐ŸŽ“ Man Student: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F393 -๐Ÿ‘จ๐Ÿผโ€๐ŸŽ“ Man Student: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F393 -๐Ÿ‘จ๐Ÿฝโ€๐ŸŽ“ Man Student: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F393 -๐Ÿ‘จ๐Ÿพโ€๐ŸŽ“ Man Student: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F393 -๐Ÿ‘จ๐Ÿฟโ€๐ŸŽ“ Man Student: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F393 -๐Ÿ‘ฉโ€๐ŸŽ“ Woman Student U+1F469, U+200D, U+1F393 -๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽ“ Woman Student: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F393 -๐Ÿ‘ฉ๐Ÿผโ€๐ŸŽ“ Woman Student: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F393 -๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽ“ Woman Student: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F393 -๐Ÿ‘ฉ๐Ÿพโ€๐ŸŽ“ Woman Student: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F393 -๐Ÿ‘ฉ๐Ÿฟโ€๐ŸŽ“ Woman Student: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F393 -๐Ÿง‘โ€๐Ÿซ Teacher U+1F9D1, U+200D, U+1F3EB -๐Ÿง‘๐Ÿปโ€๐Ÿซ Teacher: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F3EB -๐Ÿง‘๐Ÿผโ€๐Ÿซ Teacher: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F3EB -๐Ÿง‘๐Ÿฝโ€๐Ÿซ Teacher: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F3EB -๐Ÿง‘๐Ÿพโ€๐Ÿซ Teacher: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F3EB -๐Ÿง‘๐Ÿฟโ€๐Ÿซ Teacher: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F3EB -๐Ÿ‘จโ€๐Ÿซ Man Teacher U+1F468, U+200D, U+1F3EB -๐Ÿ‘จ๐Ÿปโ€๐Ÿซ Man Teacher: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F3EB -๐Ÿ‘จ๐Ÿผโ€๐Ÿซ Man Teacher: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F3EB -๐Ÿ‘จ๐Ÿฝโ€๐Ÿซ Man Teacher: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F3EB -๐Ÿ‘จ๐Ÿพโ€๐Ÿซ Man Teacher: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F3EB -๐Ÿ‘จ๐Ÿฟโ€๐Ÿซ Man Teacher: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F3EB -๐Ÿ‘ฉโ€๐Ÿซ Woman Teacher U+1F469, U+200D, U+1F3EB -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿซ Woman Teacher: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F3EB -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿซ Woman Teacher: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F3EB -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿซ Woman Teacher: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F3EB -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿซ Woman Teacher: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F3EB -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿซ Woman Teacher: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F3EB -๐Ÿง‘โ€โš–๏ธ Judge U+1F9D1, U+200D, U+2696, U+FE0F -๐Ÿง‘๐Ÿปโ€โš–๏ธ Judge: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+2696, - U+FE0F -๐Ÿง‘๐Ÿผโ€โš–๏ธ Judge: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+2696, - U+FE0F -๐Ÿง‘๐Ÿฝโ€โš–๏ธ Judge: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+2696, - U+FE0F -๐Ÿง‘๐Ÿพโ€โš–๏ธ Judge: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+2696, - U+FE0F -๐Ÿง‘๐Ÿฟโ€โš–๏ธ Judge: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+2696, - U+FE0F -๐Ÿ‘จโ€โš–๏ธ Man Judge U+1F468, U+200D, U+2696, U+FE0F -๐Ÿ‘จ๐Ÿปโ€โš–๏ธ Man Judge: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+2696, - U+FE0F -๐Ÿ‘จ๐Ÿผโ€โš–๏ธ Man Judge: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+2696, - U+FE0F -๐Ÿ‘จ๐Ÿฝโ€โš–๏ธ Man Judge: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+2696, - U+FE0F -๐Ÿ‘จ๐Ÿพโ€โš–๏ธ Man Judge: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+2696, - U+FE0F -๐Ÿ‘จ๐Ÿฟโ€โš–๏ธ Man Judge: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+2696, - U+FE0F -๐Ÿ‘ฉโ€โš–๏ธ Woman Judge U+1F469, U+200D, U+2696, U+FE0F -๐Ÿ‘ฉ๐Ÿปโ€โš–๏ธ Woman Judge: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+2696, - U+FE0F -๐Ÿ‘ฉ๐Ÿผโ€โš–๏ธ Woman Judge: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+2696, - U+FE0F -๐Ÿ‘ฉ๐Ÿฝโ€โš–๏ธ Woman Judge: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+2696, - U+FE0F -๐Ÿ‘ฉ๐Ÿพโ€โš–๏ธ Woman Judge: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+2696, - U+FE0F -๐Ÿ‘ฉ๐Ÿฟโ€โš–๏ธ Woman Judge: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+2696, - U+FE0F -๐Ÿง‘โ€๐ŸŒพ Farmer U+1F9D1, U+200D, U+1F33E -๐Ÿง‘๐Ÿปโ€๐ŸŒพ Farmer: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F33E -๐Ÿง‘๐Ÿผโ€๐ŸŒพ Farmer: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F33E -๐Ÿง‘๐Ÿฝโ€๐ŸŒพ Farmer: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F33E -๐Ÿง‘๐Ÿพโ€๐ŸŒพ Farmer: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F33E -๐Ÿง‘๐Ÿฟโ€๐ŸŒพ Farmer: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F33E -๐Ÿ‘จโ€๐ŸŒพ Man Farmer U+1F468, U+200D, U+1F33E -๐Ÿ‘จ๐Ÿปโ€๐ŸŒพ Man Farmer: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F33E -๐Ÿ‘จ๐Ÿผโ€๐ŸŒพ Man Farmer: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F33E -๐Ÿ‘จ๐Ÿฝโ€๐ŸŒพ Man Farmer: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F33E -๐Ÿ‘จ๐Ÿพโ€๐ŸŒพ Man Farmer: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F33E -๐Ÿ‘จ๐Ÿฟโ€๐ŸŒพ Man Farmer: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F33E -๐Ÿ‘ฉโ€๐ŸŒพ Woman Farmer U+1F469, U+200D, U+1F33E -๐Ÿ‘ฉ๐Ÿปโ€๐ŸŒพ Woman Farmer: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F33E -๐Ÿ‘ฉ๐Ÿผโ€๐ŸŒพ Woman Farmer: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F33E -๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŒพ Woman Farmer: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F33E -๐Ÿ‘ฉ๐Ÿพโ€๐ŸŒพ Woman Farmer: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F33E -๐Ÿ‘ฉ๐Ÿฟโ€๐ŸŒพ Woman Farmer: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F33E -๐Ÿง‘โ€๐Ÿณ Cook U+1F9D1, U+200D, U+1F373 -๐Ÿง‘๐Ÿปโ€๐Ÿณ Cook: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F373 -๐Ÿง‘๐Ÿผโ€๐Ÿณ Cook: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F373 -๐Ÿง‘๐Ÿฝโ€๐Ÿณ Cook: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F373 -๐Ÿง‘๐Ÿพโ€๐Ÿณ Cook: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F373 -๐Ÿง‘๐Ÿฟโ€๐Ÿณ Cook: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F373 -๐Ÿ‘จโ€๐Ÿณ Man Cook U+1F468, U+200D, U+1F373 -๐Ÿ‘จ๐Ÿปโ€๐Ÿณ Man Cook: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F373 -๐Ÿ‘จ๐Ÿผโ€๐Ÿณ Man Cook: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F373 -๐Ÿ‘จ๐Ÿฝโ€๐Ÿณ Man Cook: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F373 -๐Ÿ‘จ๐Ÿพโ€๐Ÿณ Man Cook: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F373 -๐Ÿ‘จ๐Ÿฟโ€๐Ÿณ Man Cook: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F373 -๐Ÿ‘ฉโ€๐Ÿณ Woman Cook U+1F469, U+200D, U+1F373 -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿณ Woman Cook: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F373 -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿณ Woman Cook: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F373 -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿณ Woman Cook: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F373 -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿณ Woman Cook: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F373 -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿณ Woman Cook: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F373 -๐Ÿง‘โ€๐Ÿ”ง Mechanic U+1F9D1, U+200D, U+1F527 -๐Ÿง‘๐Ÿปโ€๐Ÿ”ง Mechanic: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F527 -๐Ÿง‘๐Ÿผโ€๐Ÿ”ง Mechanic: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F527 -๐Ÿง‘๐Ÿฝโ€๐Ÿ”ง Mechanic: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F527 -๐Ÿง‘๐Ÿพโ€๐Ÿ”ง Mechanic: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F527 -๐Ÿง‘๐Ÿฟโ€๐Ÿ”ง Mechanic: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F527 -๐Ÿ‘จโ€๐Ÿ”ง Man Mechanic U+1F468, U+200D, U+1F527 -๐Ÿ‘จ๐Ÿปโ€๐Ÿ”ง Man Mechanic: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F527 -๐Ÿ‘จ๐Ÿผโ€๐Ÿ”ง Man Mechanic: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F527 -๐Ÿ‘จ๐Ÿฝโ€๐Ÿ”ง Man Mechanic: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F527 -๐Ÿ‘จ๐Ÿพโ€๐Ÿ”ง Man Mechanic: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F527 -๐Ÿ‘จ๐Ÿฟโ€๐Ÿ”ง Man Mechanic: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F527 -๐Ÿ‘ฉโ€๐Ÿ”ง Woman Mechanic U+1F469, U+200D, U+1F527 -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ”ง Woman Mechanic: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F527 -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ”ง Woman Mechanic: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F527 -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ”ง Woman Mechanic: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F527 -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿ”ง Woman Mechanic: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F527 -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ”ง Woman Mechanic: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F527 -๐Ÿง‘โ€๐Ÿญ Factory Worker U+1F9D1, U+200D, U+1F3ED -๐Ÿง‘๐Ÿปโ€๐Ÿญ Factory Worker: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F3ED -๐Ÿง‘๐Ÿผโ€๐Ÿญ Factory Worker: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F3ED -๐Ÿง‘๐Ÿฝโ€๐Ÿญ Factory Worker: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F3ED -๐Ÿง‘๐Ÿพโ€๐Ÿญ Factory Worker: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F3ED -๐Ÿง‘๐Ÿฟโ€๐Ÿญ Factory Worker: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F3ED -๐Ÿ‘จโ€๐Ÿญ Man Factory Worker U+1F468, U+200D, U+1F3ED -๐Ÿ‘จ๐Ÿปโ€๐Ÿญ Man Factory Worker: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F3ED -๐Ÿ‘จ๐Ÿผโ€๐Ÿญ Man Factory Worker: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F3ED -Tone -๐Ÿ‘จ๐Ÿฝโ€๐Ÿญ Man Factory Worker: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F3ED -๐Ÿ‘จ๐Ÿพโ€๐Ÿญ Man Factory Worker: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F3ED -Tone -๐Ÿ‘จ๐Ÿฟโ€๐Ÿญ Man Factory Worker: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F3ED -๐Ÿ‘ฉโ€๐Ÿญ Woman Factory Worker U+1F469, U+200D, U+1F3ED -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿญ Woman Factory Worker: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F3ED -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿญ Woman Factory Worker: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F3ED -Tone -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿญ Woman Factory Worker: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F3ED -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿญ Woman Factory Worker: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F3ED -Tone -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿญ Woman Factory Worker: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F3ED -๐Ÿง‘โ€๐Ÿ’ผ Office Worker U+1F9D1, U+200D, U+1F4BC -๐Ÿง‘๐Ÿปโ€๐Ÿ’ผ Office Worker: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F4BC -๐Ÿง‘๐Ÿผโ€๐Ÿ’ผ Office Worker: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F4BC -๐Ÿง‘๐Ÿฝโ€๐Ÿ’ผ Office Worker: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F4BC -๐Ÿง‘๐Ÿพโ€๐Ÿ’ผ Office Worker: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F4BC -๐Ÿง‘๐Ÿฟโ€๐Ÿ’ผ Office Worker: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F4BC -๐Ÿ‘จโ€๐Ÿ’ผ Man Office Worker U+1F468, U+200D, U+1F4BC -๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ผ Man Office Worker: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F4BC -๐Ÿ‘จ๐Ÿผโ€๐Ÿ’ผ Man Office Worker: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F4BC -Tone -๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ผ Man Office Worker: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F4BC -๐Ÿ‘จ๐Ÿพโ€๐Ÿ’ผ Man Office Worker: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F4BC -Tone -๐Ÿ‘จ๐Ÿฟโ€๐Ÿ’ผ Man Office Worker: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F4BC -๐Ÿ‘ฉโ€๐Ÿ’ผ Woman Office Worker U+1F469, U+200D, U+1F4BC -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ผ Woman Office Worker: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F4BC -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ’ผ Woman Office Worker: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F4BC -Tone -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ผ Woman Office Worker: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F4BC -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿ’ผ Woman Office Worker: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F4BC -Tone -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ’ผ Woman Office Worker: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F4BC -๐Ÿง‘โ€๐Ÿ”ฌ Scientist U+1F9D1, U+200D, U+1F52C -๐Ÿง‘๐Ÿปโ€๐Ÿ”ฌ Scientist: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F52C -๐Ÿง‘๐Ÿผโ€๐Ÿ”ฌ Scientist: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F52C -๐Ÿง‘๐Ÿฝโ€๐Ÿ”ฌ Scientist: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F52C -๐Ÿง‘๐Ÿพโ€๐Ÿ”ฌ Scientist: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F52C -๐Ÿง‘๐Ÿฟโ€๐Ÿ”ฌ Scientist: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F52C -๐Ÿ‘จโ€๐Ÿ”ฌ Man Scientist U+1F468, U+200D, U+1F52C -๐Ÿ‘จ๐Ÿปโ€๐Ÿ”ฌ Man Scientist: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F52C -๐Ÿ‘จ๐Ÿผโ€๐Ÿ”ฌ Man Scientist: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F52C -๐Ÿ‘จ๐Ÿฝโ€๐Ÿ”ฌ Man Scientist: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F52C -๐Ÿ‘จ๐Ÿพโ€๐Ÿ”ฌ Man Scientist: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F52C -๐Ÿ‘จ๐Ÿฟโ€๐Ÿ”ฌ Man Scientist: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F52C -๐Ÿ‘ฉโ€๐Ÿ”ฌ Woman Scientist U+1F469, U+200D, U+1F52C -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ”ฌ Woman Scientist: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F52C -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ”ฌ Woman Scientist: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F52C -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ”ฌ Woman Scientist: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F52C -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿ”ฌ Woman Scientist: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F52C -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ”ฌ Woman Scientist: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F52C -๐Ÿง‘โ€๐Ÿ’ป Technologist U+1F9D1, U+200D, U+1F4BB -๐Ÿง‘๐Ÿปโ€๐Ÿ’ป Technologist: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F4BB -๐Ÿง‘๐Ÿผโ€๐Ÿ’ป Technologist: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F4BB -๐Ÿง‘๐Ÿฝโ€๐Ÿ’ป Technologist: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F4BB -๐Ÿง‘๐Ÿพโ€๐Ÿ’ป Technologist: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F4BB -๐Ÿง‘๐Ÿฟโ€๐Ÿ’ป Technologist: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F4BB -๐Ÿ‘จโ€๐Ÿ’ป Man Technologist U+1F468, U+200D, U+1F4BB -๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Man Technologist: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F4BB -๐Ÿ‘จ๐Ÿผโ€๐Ÿ’ป Man Technologist: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F4BB -Tone -๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ป Man Technologist: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F4BB -๐Ÿ‘จ๐Ÿพโ€๐Ÿ’ป Man Technologist: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F4BB -๐Ÿ‘จ๐Ÿฟโ€๐Ÿ’ป Man Technologist: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F4BB -๐Ÿ‘ฉโ€๐Ÿ’ป Woman Technologist U+1F469, U+200D, U+1F4BB -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป Woman Technologist: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F4BB -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿ’ป Woman Technologist: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F4BB -Tone -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Woman Technologist: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F4BB -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿ’ป Woman Technologist: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F4BB -Tone -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ’ป Woman Technologist: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F4BB -๐Ÿง‘โ€๐ŸŽค Singer U+1F9D1, U+200D, U+1F3A4 -๐Ÿง‘๐Ÿปโ€๐ŸŽค Singer: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F3A4 -๐Ÿง‘๐Ÿผโ€๐ŸŽค Singer: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F3A4 -๐Ÿง‘๐Ÿฝโ€๐ŸŽค Singer: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F3A4 -๐Ÿง‘๐Ÿพโ€๐ŸŽค Singer: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F3A4 -๐Ÿง‘๐Ÿฟโ€๐ŸŽค Singer: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F3A4 -๐Ÿ‘จโ€๐ŸŽค Man Singer U+1F468, U+200D, U+1F3A4 -๐Ÿ‘จ๐Ÿปโ€๐ŸŽค Man Singer: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F3A4 -๐Ÿ‘จ๐Ÿผโ€๐ŸŽค Man Singer: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F3A4 -๐Ÿ‘จ๐Ÿฝโ€๐ŸŽค Man Singer: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F3A4 -๐Ÿ‘จ๐Ÿพโ€๐ŸŽค Man Singer: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F3A4 -๐Ÿ‘จ๐Ÿฟโ€๐ŸŽค Man Singer: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F3A4 -๐Ÿ‘ฉโ€๐ŸŽค Woman Singer U+1F469, U+200D, U+1F3A4 -๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽค Woman Singer: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F3A4 -๐Ÿ‘ฉ๐Ÿผโ€๐ŸŽค Woman Singer: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F3A4 -๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽค Woman Singer: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F3A4 -๐Ÿ‘ฉ๐Ÿพโ€๐ŸŽค Woman Singer: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F3A4 -๐Ÿ‘ฉ๐Ÿฟโ€๐ŸŽค Woman Singer: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F3A4 -๐Ÿง‘โ€๐ŸŽจ Artist U+1F9D1, U+200D, U+1F3A8 -๐Ÿง‘๐Ÿปโ€๐ŸŽจ Artist: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F3A8 -๐Ÿง‘๐Ÿผโ€๐ŸŽจ Artist: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F3A8 -๐Ÿง‘๐Ÿฝโ€๐ŸŽจ Artist: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F3A8 -๐Ÿง‘๐Ÿพโ€๐ŸŽจ Artist: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F3A8 -๐Ÿง‘๐Ÿฟโ€๐ŸŽจ Artist: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F3A8 -๐Ÿ‘จโ€๐ŸŽจ Man Artist U+1F468, U+200D, U+1F3A8 -๐Ÿ‘จ๐Ÿปโ€๐ŸŽจ Man Artist: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F3A8 -๐Ÿ‘จ๐Ÿผโ€๐ŸŽจ Man Artist: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F3A8 -๐Ÿ‘จ๐Ÿฝโ€๐ŸŽจ Man Artist: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F3A8 -๐Ÿ‘จ๐Ÿพโ€๐ŸŽจ Man Artist: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F3A8 -๐Ÿ‘จ๐Ÿฟโ€๐ŸŽจ Man Artist: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F3A8 -๐Ÿ‘ฉโ€๐ŸŽจ Woman Artist U+1F469, U+200D, U+1F3A8 -๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽจ Woman Artist: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F3A8 -๐Ÿ‘ฉ๐Ÿผโ€๐ŸŽจ Woman Artist: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F3A8 -๐Ÿ‘ฉ๐Ÿฝโ€๐ŸŽจ Woman Artist: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F3A8 -๐Ÿ‘ฉ๐Ÿพโ€๐ŸŽจ Woman Artist: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F3A8 -๐Ÿ‘ฉ๐Ÿฟโ€๐ŸŽจ Woman Artist: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F3A8 -๐Ÿง‘โ€โœˆ๏ธ Pilot U+1F9D1, U+200D, U+2708, U+FE0F -๐Ÿง‘๐Ÿปโ€โœˆ๏ธ Pilot: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+2708, - U+FE0F -๐Ÿง‘๐Ÿผโ€โœˆ๏ธ Pilot: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+2708, - U+FE0F -๐Ÿง‘๐Ÿฝโ€โœˆ๏ธ Pilot: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+2708, - U+FE0F -๐Ÿง‘๐Ÿพโ€โœˆ๏ธ Pilot: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+2708, - U+FE0F -๐Ÿง‘๐Ÿฟโ€โœˆ๏ธ Pilot: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+2708, - U+FE0F -๐Ÿ‘จโ€โœˆ๏ธ Man Pilot U+1F468, U+200D, U+2708, U+FE0F -๐Ÿ‘จ๐Ÿปโ€โœˆ๏ธ Man Pilot: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+2708, - U+FE0F -๐Ÿ‘จ๐Ÿผโ€โœˆ๏ธ Man Pilot: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+2708, - U+FE0F -๐Ÿ‘จ๐Ÿฝโ€โœˆ๏ธ Man Pilot: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+2708, - U+FE0F -๐Ÿ‘จ๐Ÿพโ€โœˆ๏ธ Man Pilot: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+2708, - U+FE0F -๐Ÿ‘จ๐Ÿฟโ€โœˆ๏ธ Man Pilot: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+2708, - U+FE0F -๐Ÿ‘ฉโ€โœˆ๏ธ Woman Pilot U+1F469, U+200D, U+2708, U+FE0F -๐Ÿ‘ฉ๐Ÿปโ€โœˆ๏ธ Woman Pilot: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+2708, - U+FE0F -๐Ÿ‘ฉ๐Ÿผโ€โœˆ๏ธ Woman Pilot: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+2708, - U+FE0F -๐Ÿ‘ฉ๐Ÿฝโ€โœˆ๏ธ Woman Pilot: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+2708, - U+FE0F -๐Ÿ‘ฉ๐Ÿพโ€โœˆ๏ธ Woman Pilot: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+2708, - U+FE0F -๐Ÿ‘ฉ๐Ÿฟโ€โœˆ๏ธ Woman Pilot: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+2708, - U+FE0F -๐Ÿง‘โ€๐Ÿš€ Astronaut U+1F9D1, U+200D, U+1F680 -๐Ÿง‘๐Ÿปโ€๐Ÿš€ Astronaut: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F680 -๐Ÿง‘๐Ÿผโ€๐Ÿš€ Astronaut: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F680 -๐Ÿง‘๐Ÿฝโ€๐Ÿš€ Astronaut: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F680 -๐Ÿง‘๐Ÿพโ€๐Ÿš€ Astronaut: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F680 -๐Ÿง‘๐Ÿฟโ€๐Ÿš€ Astronaut: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F680 -๐Ÿ‘จโ€๐Ÿš€ Man Astronaut U+1F468, U+200D, U+1F680 -๐Ÿ‘จ๐Ÿปโ€๐Ÿš€ Man Astronaut: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F680 -๐Ÿ‘จ๐Ÿผโ€๐Ÿš€ Man Astronaut: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F680 -๐Ÿ‘จ๐Ÿฝโ€๐Ÿš€ Man Astronaut: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F680 -๐Ÿ‘จ๐Ÿพโ€๐Ÿš€ Man Astronaut: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F680 -๐Ÿ‘จ๐Ÿฟโ€๐Ÿš€ Man Astronaut: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F680 -๐Ÿ‘ฉโ€๐Ÿš€ Woman Astronaut U+1F469, U+200D, U+1F680 -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿš€ Woman Astronaut: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F680 -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿš€ Woman Astronaut: Medium-Light Skin Tone U+1F469, U+1F3FC, U+200D, U+1F680 -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿš€ Woman Astronaut: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F680 -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿš€ Woman Astronaut: Medium-Dark Skin Tone U+1F469, U+1F3FE, U+200D, U+1F680 -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿš€ Woman Astronaut: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F680 -๐Ÿง‘โ€๐Ÿš’ Firefighter U+1F9D1, U+200D, U+1F692 -๐Ÿง‘๐Ÿปโ€๐Ÿš’ Firefighter: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F692 -๐Ÿง‘๐Ÿผโ€๐Ÿš’ Firefighter: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F692 -๐Ÿง‘๐Ÿฝโ€๐Ÿš’ Firefighter: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F692 -๐Ÿง‘๐Ÿพโ€๐Ÿš’ Firefighter: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F692 -๐Ÿง‘๐Ÿฟโ€๐Ÿš’ Firefighter: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F692 -๐Ÿ‘จโ€๐Ÿš’ Man Firefighter U+1F468, U+200D, U+1F692 -๐Ÿ‘จ๐Ÿปโ€๐Ÿš’ Man Firefighter: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F692 -๐Ÿ‘จ๐Ÿผโ€๐Ÿš’ Man Firefighter: Medium-Light Skin Tone U+1F468, U+1F3FC, U+200D, U+1F692 -๐Ÿ‘จ๐Ÿฝโ€๐Ÿš’ Man Firefighter: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F692 -๐Ÿ‘จ๐Ÿพโ€๐Ÿš’ Man Firefighter: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F692 -๐Ÿ‘จ๐Ÿฟโ€๐Ÿš’ Man Firefighter: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F692 -๐Ÿ‘ฉโ€๐Ÿš’ Woman Firefighter U+1F469, U+200D, U+1F692 -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿš’ Woman Firefighter: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F692 -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿš’ Woman Firefighter: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F692 -Tone -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿš’ Woman Firefighter: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F692 -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿš’ Woman Firefighter: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F692 -Tone -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿš’ Woman Firefighter: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F692 -๐Ÿ‘ฎ Police Officer U+1F46E -๐Ÿ‘ฎ๐Ÿป Police Officer: Light Skin Tone U+1F46E, U+1F3FB -๐Ÿ‘ฎ๐Ÿผ Police Officer: Medium-Light Skin Tone U+1F46E, U+1F3FC -๐Ÿ‘ฎ๐Ÿฝ Police Officer: Medium Skin Tone U+1F46E, U+1F3FD -๐Ÿ‘ฎ๐Ÿพ Police Officer: Medium-Dark Skin Tone U+1F46E, U+1F3FE -๐Ÿ‘ฎ๐Ÿฟ Police Officer: Dark Skin Tone U+1F46E, U+1F3FF -๐Ÿ‘ฎโ€โ™‚๏ธ Man Police Officer U+1F46E, U+200D, U+2642, U+FE0F -๐Ÿ‘ฎ๐Ÿปโ€โ™‚๏ธ Man Police Officer: Light Skin Tone U+1F46E, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฎ๐Ÿผโ€โ™‚๏ธ Man Police Officer: Medium-Light Skin U+1F46E, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‘ฎ๐Ÿฝโ€โ™‚๏ธ Man Police Officer: Medium Skin Tone U+1F46E, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฎ๐Ÿพโ€โ™‚๏ธ Man Police Officer: Medium-Dark Skin U+1F46E, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‘ฎ๐Ÿฟโ€โ™‚๏ธ Man Police Officer: Dark Skin Tone U+1F46E, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฎโ€โ™€๏ธ Woman Police Officer U+1F46E, U+200D, U+2640, U+FE0F -๐Ÿ‘ฎ๐Ÿปโ€โ™€๏ธ Woman Police Officer: Light Skin Tone U+1F46E, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฎ๐Ÿผโ€โ™€๏ธ Woman Police Officer: Medium-Light U+1F46E, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ‘ฎ๐Ÿฝโ€โ™€๏ธ Woman Police Officer: Medium Skin Tone U+1F46E, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฎ๐Ÿพโ€โ™€๏ธ Woman Police Officer: Medium-Dark Skin U+1F46E, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿ‘ฎ๐Ÿฟโ€โ™€๏ธ Woman Police Officer: Dark Skin Tone U+1F46E, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ•ต๏ธ Detective U+1F575, U+FE0F -๐Ÿ•ต๐Ÿป Detective: Light Skin Tone U+1F575, U+1F3FB -๐Ÿ•ต๐Ÿผ Detective: Medium-Light Skin Tone U+1F575, U+1F3FC -๐Ÿ•ต๐Ÿฝ Detective: Medium Skin Tone U+1F575, U+1F3FD -๐Ÿ•ต๐Ÿพ Detective: Medium-Dark Skin Tone U+1F575, U+1F3FE -๐Ÿ•ต๐Ÿฟ Detective: Dark Skin Tone U+1F575, U+1F3FF -๐Ÿ•ต๏ธโ€โ™‚๏ธ Man Detective U+1F575, U+FE0F, U+200D, U+2642, - U+FE0F -๐Ÿ•ต๐Ÿปโ€โ™‚๏ธ Man Detective: Light Skin Tone U+1F575, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ•ต๐Ÿผโ€โ™‚๏ธ Man Detective: Medium-Light Skin Tone U+1F575, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿ•ต๐Ÿฝโ€โ™‚๏ธ Man Detective: Medium Skin Tone U+1F575, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ•ต๐Ÿพโ€โ™‚๏ธ Man Detective: Medium-Dark Skin Tone U+1F575, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿ•ต๐Ÿฟโ€โ™‚๏ธ Man Detective: Dark Skin Tone U+1F575, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ•ต๏ธโ€โ™€๏ธ Woman Detective U+1F575, U+FE0F, U+200D, U+2640, - U+FE0F -๐Ÿ•ต๐Ÿปโ€โ™€๏ธ Woman Detective: Light Skin Tone U+1F575, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ•ต๐Ÿผโ€โ™€๏ธ Woman Detective: Medium-Light Skin U+1F575, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿ•ต๐Ÿฝโ€โ™€๏ธ Woman Detective: Medium Skin Tone U+1F575, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ•ต๐Ÿพโ€โ™€๏ธ Woman Detective: Medium-Dark Skin Tone U+1F575, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿ•ต๐Ÿฟโ€โ™€๏ธ Woman Detective: Dark Skin Tone U+1F575, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ’‚ Guard U+1F482 -๐Ÿ’‚๐Ÿป Guard: Light Skin Tone U+1F482, U+1F3FB -๐Ÿ’‚๐Ÿผ Guard: Medium-Light Skin Tone U+1F482, U+1F3FC -๐Ÿ’‚๐Ÿฝ Guard: Medium Skin Tone U+1F482, U+1F3FD -๐Ÿ’‚๐Ÿพ Guard: Medium-Dark Skin Tone U+1F482, U+1F3FE -๐Ÿ’‚๐Ÿฟ Guard: Dark Skin Tone U+1F482, U+1F3FF -๐Ÿ’‚โ€โ™‚๏ธ Man Guard U+1F482, U+200D, U+2642, U+FE0F -๐Ÿ’‚๐Ÿปโ€โ™‚๏ธ Man Guard: Light Skin Tone U+1F482, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ’‚๐Ÿผโ€โ™‚๏ธ Man Guard: Medium-Light Skin Tone U+1F482, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿ’‚๐Ÿฝโ€โ™‚๏ธ Man Guard: Medium Skin Tone U+1F482, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ’‚๐Ÿพโ€โ™‚๏ธ Man Guard: Medium-Dark Skin Tone U+1F482, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿ’‚๐Ÿฟโ€โ™‚๏ธ Man Guard: Dark Skin Tone U+1F482, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ’‚โ€โ™€๏ธ Woman Guard U+1F482, U+200D, U+2640, U+FE0F -๐Ÿ’‚๐Ÿปโ€โ™€๏ธ Woman Guard: Light Skin Tone U+1F482, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ’‚๐Ÿผโ€โ™€๏ธ Woman Guard: Medium-Light Skin Tone U+1F482, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿ’‚๐Ÿฝโ€โ™€๏ธ Woman Guard: Medium Skin Tone U+1F482, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ’‚๐Ÿพโ€โ™€๏ธ Woman Guard: Medium-Dark Skin Tone U+1F482, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿ’‚๐Ÿฟโ€โ™€๏ธ Woman Guard: Dark Skin Tone U+1F482, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿฅท Ninja U+1F977 -๐Ÿฅท๐Ÿป Ninja: Light Skin Tone U+1F977, U+1F3FB -๐Ÿฅท๐Ÿผ Ninja: Medium-Light Skin Tone U+1F977, U+1F3FC -๐Ÿฅท๐Ÿฝ Ninja: Medium Skin Tone U+1F977, U+1F3FD -๐Ÿฅท๐Ÿพ Ninja: Medium-Dark Skin Tone U+1F977, U+1F3FE -๐Ÿฅท๐Ÿฟ Ninja: Dark Skin Tone U+1F977, U+1F3FF -๐Ÿ‘ท Construction Worker U+1F477 -๐Ÿ‘ท๐Ÿป Construction Worker: Light Skin Tone U+1F477, U+1F3FB -๐Ÿ‘ท๐Ÿผ Construction Worker: Medium-Light Skin U+1F477, U+1F3FC -Tone -๐Ÿ‘ท๐Ÿฝ Construction Worker: Medium Skin Tone U+1F477, U+1F3FD -๐Ÿ‘ท๐Ÿพ Construction Worker: Medium-Dark Skin U+1F477, U+1F3FE -Tone -๐Ÿ‘ท๐Ÿฟ Construction Worker: Dark Skin Tone U+1F477, U+1F3FF -๐Ÿ‘ทโ€โ™‚๏ธ Man Construction Worker U+1F477, U+200D, U+2642, U+FE0F -๐Ÿ‘ท๐Ÿปโ€โ™‚๏ธ Man Construction Worker: Light Skin U+1F477, U+1F3FB, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‘ท๐Ÿผโ€โ™‚๏ธ Man Construction Worker: Medium-Light U+1F477, U+1F3FC, U+200D, U+2642, -Skin Tone U+FE0F -๐Ÿ‘ท๐Ÿฝโ€โ™‚๏ธ Man Construction Worker: Medium Skin U+1F477, U+1F3FD, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‘ท๐Ÿพโ€โ™‚๏ธ Man Construction Worker: Medium-Dark U+1F477, U+1F3FE, U+200D, U+2642, -Skin Tone U+FE0F -๐Ÿ‘ท๐Ÿฟโ€โ™‚๏ธ Man Construction Worker: Dark Skin U+1F477, U+1F3FF, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‘ทโ€โ™€๏ธ Woman Construction Worker U+1F477, U+200D, U+2640, U+FE0F -๐Ÿ‘ท๐Ÿปโ€โ™€๏ธ Woman Construction Worker: Light Skin U+1F477, U+1F3FB, U+200D, U+2640, -Tone U+FE0F -๐Ÿ‘ท๐Ÿผโ€โ™€๏ธ Woman Construction Worker: U+1F477, U+1F3FC, U+200D, U+2640, -Medium-Light Skin Tone U+FE0F -๐Ÿ‘ท๐Ÿฝโ€โ™€๏ธ Woman Construction Worker: Medium Skin U+1F477, U+1F3FD, U+200D, U+2640, -Tone U+FE0F -๐Ÿ‘ท๐Ÿพโ€โ™€๏ธ Woman Construction Worker: Medium-Dark U+1F477, U+1F3FE, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ‘ท๐Ÿฟโ€โ™€๏ธ Woman Construction Worker: Dark Skin U+1F477, U+1F3FF, U+200D, U+2640, -Tone U+FE0F -๐Ÿคด Prince U+1F934 -๐Ÿคด๐Ÿป Prince: Light Skin Tone U+1F934, U+1F3FB -๐Ÿคด๐Ÿผ Prince: Medium-Light Skin Tone U+1F934, U+1F3FC -๐Ÿคด๐Ÿฝ Prince: Medium Skin Tone U+1F934, U+1F3FD -๐Ÿคด๐Ÿพ Prince: Medium-Dark Skin Tone U+1F934, U+1F3FE -๐Ÿคด๐Ÿฟ Prince: Dark Skin Tone U+1F934, U+1F3FF -๐Ÿ‘ธ Princess U+1F478 -๐Ÿ‘ธ๐Ÿป Princess: Light Skin Tone U+1F478, U+1F3FB -๐Ÿ‘ธ๐Ÿผ Princess: Medium-Light Skin Tone U+1F478, U+1F3FC -๐Ÿ‘ธ๐Ÿฝ Princess: Medium Skin Tone U+1F478, U+1F3FD -๐Ÿ‘ธ๐Ÿพ Princess: Medium-Dark Skin Tone U+1F478, U+1F3FE -๐Ÿ‘ธ๐Ÿฟ Princess: Dark Skin Tone U+1F478, U+1F3FF -๐Ÿ‘ณ Person Wearing Turban U+1F473 -๐Ÿ‘ณ๐Ÿป Person Wearing Turban: Light Skin Tone U+1F473, U+1F3FB -๐Ÿ‘ณ๐Ÿผ Person Wearing Turban: Medium-Light Skin U+1F473, U+1F3FC -Tone -๐Ÿ‘ณ๐Ÿฝ Person Wearing Turban: Medium Skin Tone U+1F473, U+1F3FD -๐Ÿ‘ณ๐Ÿพ Person Wearing Turban: Medium-Dark Skin U+1F473, U+1F3FE -Tone -๐Ÿ‘ณ๐Ÿฟ Person Wearing Turban: Dark Skin Tone U+1F473, U+1F3FF -๐Ÿ‘ณโ€โ™‚๏ธ Man Wearing Turban U+1F473, U+200D, U+2642, U+FE0F -๐Ÿ‘ณ๐Ÿปโ€โ™‚๏ธ Man Wearing Turban: Light Skin Tone U+1F473, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ‘ณ๐Ÿผโ€โ™‚๏ธ Man Wearing Turban: Medium-Light Skin U+1F473, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‘ณ๐Ÿฝโ€โ™‚๏ธ Man Wearing Turban: Medium Skin Tone U+1F473, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ‘ณ๐Ÿพโ€โ™‚๏ธ Man Wearing Turban: Medium-Dark Skin U+1F473, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‘ณ๐Ÿฟโ€โ™‚๏ธ Man Wearing Turban: Dark Skin Tone U+1F473, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ‘ณโ€โ™€๏ธ Woman Wearing Turban U+1F473, U+200D, U+2640, U+FE0F -๐Ÿ‘ณ๐Ÿปโ€โ™€๏ธ Woman Wearing Turban: Light Skin Tone U+1F473, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ‘ณ๐Ÿผโ€โ™€๏ธ Woman Wearing Turban: Medium-Light U+1F473, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ‘ณ๐Ÿฝโ€โ™€๏ธ Woman Wearing Turban: Medium Skin Tone U+1F473, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ‘ณ๐Ÿพโ€โ™€๏ธ Woman Wearing Turban: Medium-Dark Skin U+1F473, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿ‘ณ๐Ÿฟโ€โ™€๏ธ Woman Wearing Turban: Dark Skin Tone U+1F473, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฒ Person With Skullcap U+1F472 -๐Ÿ‘ฒ๐Ÿป Person With Skullcap: Light Skin Tone U+1F472, U+1F3FB -๐Ÿ‘ฒ๐Ÿผ Person With Skullcap: Medium-Light Skin U+1F472, U+1F3FC -Tone -๐Ÿ‘ฒ๐Ÿฝ Person With Skullcap: Medium Skin Tone U+1F472, U+1F3FD -๐Ÿ‘ฒ๐Ÿพ Person With Skullcap: Medium-Dark Skin U+1F472, U+1F3FE -Tone -๐Ÿ‘ฒ๐Ÿฟ Person With Skullcap: Dark Skin Tone U+1F472, U+1F3FF -๐Ÿง• Woman with Headscarf U+1F9D5 -๐Ÿง•๐Ÿป Woman with Headscarf: Light Skin Tone U+1F9D5, U+1F3FB -๐Ÿง•๐Ÿผ Woman with Headscarf: Medium-Light Skin U+1F9D5, U+1F3FC -Tone -๐Ÿง•๐Ÿฝ Woman with Headscarf: Medium Skin Tone U+1F9D5, U+1F3FD -๐Ÿง•๐Ÿพ Woman with Headscarf: Medium-Dark Skin U+1F9D5, U+1F3FE -Tone -๐Ÿง•๐Ÿฟ Woman with Headscarf: Dark Skin Tone U+1F9D5, U+1F3FF -๐Ÿคต Person in Tuxedo U+1F935 -๐Ÿคต๐Ÿป Person in Tuxedo: Light Skin Tone U+1F935, U+1F3FB -๐Ÿคต๐Ÿผ Person in Tuxedo: Medium-Light Skin Tone U+1F935, U+1F3FC -๐Ÿคต๐Ÿฝ Person in Tuxedo: Medium Skin Tone U+1F935, U+1F3FD -๐Ÿคต๐Ÿพ Person in Tuxedo: Medium-Dark Skin Tone U+1F935, U+1F3FE -๐Ÿคต๐Ÿฟ Person in Tuxedo: Dark Skin Tone U+1F935, U+1F3FF -๐Ÿคตโ€โ™‚๏ธ Man in Tuxedo U+1F935, U+200D, U+2642, U+FE0F -๐Ÿคต๐Ÿปโ€โ™‚๏ธ Man in Tuxedo: Light Skin Tone U+1F935, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿคต๐Ÿผโ€โ™‚๏ธ Man in Tuxedo: Medium-Light Skin Tone U+1F935, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿคต๐Ÿฝโ€โ™‚๏ธ Man in Tuxedo: Medium Skin Tone U+1F935, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿคต๐Ÿพโ€โ™‚๏ธ Man in Tuxedo: Medium-Dark Skin Tone U+1F935, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿคต๐Ÿฟโ€โ™‚๏ธ Man in Tuxedo: Dark Skin Tone U+1F935, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿคตโ€โ™€๏ธ Woman in Tuxedo U+1F935, U+200D, U+2640, U+FE0F -๐Ÿคต๐Ÿปโ€โ™€๏ธ Woman in Tuxedo: Light Skin Tone U+1F935, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿคต๐Ÿผโ€โ™€๏ธ Woman in Tuxedo: Medium-Light Skin U+1F935, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿคต๐Ÿฝโ€โ™€๏ธ Woman in Tuxedo: Medium Skin Tone U+1F935, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿคต๐Ÿพโ€โ™€๏ธ Woman in Tuxedo: Medium-Dark Skin Tone U+1F935, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿคต๐Ÿฟโ€โ™€๏ธ Woman in Tuxedo: Dark Skin Tone U+1F935, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฐ Person With Veil U+1F470 -๐Ÿ‘ฐ๐Ÿป Person With Veil: Light Skin Tone U+1F470, U+1F3FB -๐Ÿ‘ฐ๐Ÿผ Person With Veil: Medium-Light Skin Tone U+1F470, U+1F3FC -๐Ÿ‘ฐ๐Ÿฝ Person With Veil: Medium Skin Tone U+1F470, U+1F3FD -๐Ÿ‘ฐ๐Ÿพ Person With Veil: Medium-Dark Skin Tone U+1F470, U+1F3FE -๐Ÿ‘ฐ๐Ÿฟ Person With Veil: Dark Skin Tone U+1F470, U+1F3FF -๐Ÿ‘ฐโ€โ™‚๏ธ Man with Veil U+1F470, U+200D, U+2642, U+FE0F -๐Ÿ‘ฐ๐Ÿปโ€โ™‚๏ธ Man with Veil: Light Skin Tone U+1F470, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฐ๐Ÿผโ€โ™‚๏ธ Man with Veil: Medium-Light Skin Tone U+1F470, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฐ๐Ÿฝโ€โ™‚๏ธ Man with Veil: Medium Skin Tone U+1F470, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฐ๐Ÿพโ€โ™‚๏ธ Man with Veil: Medium-Dark Skin Tone U+1F470, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฐ๐Ÿฟโ€โ™‚๏ธ Man with Veil: Dark Skin Tone U+1F470, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฐโ€โ™€๏ธ Woman with Veil U+1F470, U+200D, U+2640, U+FE0F -๐Ÿ‘ฐ๐Ÿปโ€โ™€๏ธ Woman with Veil: Light Skin Tone U+1F470, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฐ๐Ÿผโ€โ™€๏ธ Woman with Veil: Medium-Light Skin U+1F470, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿ‘ฐ๐Ÿฝโ€โ™€๏ธ Woman with Veil: Medium Skin Tone U+1F470, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฐ๐Ÿพโ€โ™€๏ธ Woman with Veil: Medium-Dark Skin Tone U+1F470, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿ‘ฐ๐Ÿฟโ€โ™€๏ธ Woman with Veil: Dark Skin Tone U+1F470, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿคฐ Pregnant Woman U+1F930 -๐Ÿคฐ๐Ÿป Pregnant Woman: Light Skin Tone U+1F930, U+1F3FB -๐Ÿคฐ๐Ÿผ Pregnant Woman: Medium-Light Skin Tone U+1F930, U+1F3FC -๐Ÿคฐ๐Ÿฝ Pregnant Woman: Medium Skin Tone U+1F930, U+1F3FD -๐Ÿคฐ๐Ÿพ Pregnant Woman: Medium-Dark Skin Tone U+1F930, U+1F3FE -๐Ÿคฐ๐Ÿฟ Pregnant Woman: Dark Skin Tone U+1F930, U+1F3FF -๐Ÿคฑ Breast-Feeding U+1F931 -๐Ÿคฑ๐Ÿป Breast-Feeding: Light Skin Tone U+1F931, U+1F3FB -๐Ÿคฑ๐Ÿผ Breast-Feeding: Medium-Light Skin Tone U+1F931, U+1F3FC -๐Ÿคฑ๐Ÿฝ Breast-Feeding: Medium Skin Tone U+1F931, U+1F3FD -๐Ÿคฑ๐Ÿพ Breast-Feeding: Medium-Dark Skin Tone U+1F931, U+1F3FE -๐Ÿคฑ๐Ÿฟ Breast-Feeding: Dark Skin Tone U+1F931, U+1F3FF -๐Ÿ‘ฉโ€๐Ÿผ Woman Feeding Baby U+1F469, U+200D, U+1F37C -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿผ Woman Feeding Baby: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F37C -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿผ Woman Feeding Baby: Medium-Light Skin U+1F469, U+1F3FC, U+200D, U+1F37C -Tone -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿผ Woman Feeding Baby: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F37C -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿผ Woman Feeding Baby: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F37C -Tone -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿผ Woman Feeding Baby: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F37C -๐Ÿ‘จโ€๐Ÿผ Man Feeding Baby U+1F468, U+200D, U+1F37C -๐Ÿ‘จ๐Ÿปโ€๐Ÿผ Man Feeding Baby: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F37C -๐Ÿ‘จ๐Ÿผโ€๐Ÿผ Man Feeding Baby: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F37C -Tone -๐Ÿ‘จ๐Ÿฝโ€๐Ÿผ Man Feeding Baby: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F37C -๐Ÿ‘จ๐Ÿพโ€๐Ÿผ Man Feeding Baby: Medium-Dark Skin Tone U+1F468, U+1F3FE, U+200D, U+1F37C -๐Ÿ‘จ๐Ÿฟโ€๐Ÿผ Man Feeding Baby: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F37C -๐Ÿง‘โ€๐Ÿผ Person Feeding Baby U+1F9D1, U+200D, U+1F37C -๐Ÿง‘๐Ÿปโ€๐Ÿผ Person Feeding Baby: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F37C -๐Ÿง‘๐Ÿผโ€๐Ÿผ Person Feeding Baby: Medium-Light Skin U+1F9D1, U+1F3FC, U+200D, U+1F37C -Tone -๐Ÿง‘๐Ÿฝโ€๐Ÿผ Person Feeding Baby: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F37C -๐Ÿง‘๐Ÿพโ€๐Ÿผ Person Feeding Baby: Medium-Dark Skin U+1F9D1, U+1F3FE, U+200D, U+1F37C -Tone -๐Ÿง‘๐Ÿฟโ€๐Ÿผ Person Feeding Baby: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F37C -๐Ÿ‘ผ Baby Angel U+1F47C -๐Ÿ‘ผ๐Ÿป Baby Angel: Light Skin Tone U+1F47C, U+1F3FB -๐Ÿ‘ผ๐Ÿผ Baby Angel: Medium-Light Skin Tone U+1F47C, U+1F3FC -๐Ÿ‘ผ๐Ÿฝ Baby Angel: Medium Skin Tone U+1F47C, U+1F3FD -๐Ÿ‘ผ๐Ÿพ Baby Angel: Medium-Dark Skin Tone U+1F47C, U+1F3FE -๐Ÿ‘ผ๐Ÿฟ Baby Angel: Dark Skin Tone U+1F47C, U+1F3FF -๐ŸŽ… Santa Claus U+1F385 -๐ŸŽ…๐Ÿป Santa Claus: Light Skin Tone U+1F385, U+1F3FB -๐ŸŽ…๐Ÿผ Santa Claus: Medium-Light Skin Tone U+1F385, U+1F3FC -๐ŸŽ…๐Ÿฝ Santa Claus: Medium Skin Tone U+1F385, U+1F3FD -๐ŸŽ…๐Ÿพ Santa Claus: Medium-Dark Skin Tone U+1F385, U+1F3FE -๐ŸŽ…๐Ÿฟ Santa Claus: Dark Skin Tone U+1F385, U+1F3FF -๐Ÿคถ Mrs. Claus U+1F936 -๐Ÿคถ๐Ÿป Mrs. Claus: Light Skin Tone U+1F936, U+1F3FB -๐Ÿคถ๐Ÿผ Mrs. Claus: Medium-Light Skin Tone U+1F936, U+1F3FC -๐Ÿคถ๐Ÿฝ Mrs. Claus: Medium Skin Tone U+1F936, U+1F3FD -๐Ÿคถ๐Ÿพ Mrs. Claus: Medium-Dark Skin Tone U+1F936, U+1F3FE -๐Ÿคถ๐Ÿฟ Mrs. Claus: Dark Skin Tone U+1F936, U+1F3FF -๐Ÿง‘โ€๐ŸŽ„ Mx Claus U+1F9D1, U+200D, U+1F384 -๐Ÿง‘๐Ÿปโ€๐ŸŽ„ Mx Claus: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F384 -๐Ÿง‘๐Ÿผโ€๐ŸŽ„ Mx Claus: Medium-Light Skin Tone U+1F9D1, U+1F3FC, U+200D, U+1F384 -๐Ÿง‘๐Ÿฝโ€๐ŸŽ„ Mx Claus: Medium Skin Tone U+1F9D1, U+1F3FD, U+200D, U+1F384 -๐Ÿง‘๐Ÿพโ€๐ŸŽ„ Mx Claus: Medium-Dark Skin Tone U+1F9D1, U+1F3FE, U+200D, U+1F384 -๐Ÿง‘๐Ÿฟโ€๐ŸŽ„ Mx Claus: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F384 -๐Ÿฆธ Superhero U+1F9B8 -๐Ÿฆธ๐Ÿป Superhero: Light Skin Tone U+1F9B8, U+1F3FB -๐Ÿฆธ๐Ÿผ Superhero: Medium-Light Skin Tone U+1F9B8, U+1F3FC -๐Ÿฆธ๐Ÿฝ Superhero: Medium Skin Tone U+1F9B8, U+1F3FD -๐Ÿฆธ๐Ÿพ Superhero: Medium-Dark Skin Tone U+1F9B8, U+1F3FE -๐Ÿฆธ๐Ÿฟ Superhero: Dark Skin Tone U+1F9B8, U+1F3FF -๐Ÿฆธโ€โ™‚๏ธ Man Superhero U+1F9B8, U+200D, U+2642, U+FE0F -๐Ÿฆธ๐Ÿปโ€โ™‚๏ธ Man Superhero: Light Skin Tone U+1F9B8, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿฆธ๐Ÿผโ€โ™‚๏ธ Man Superhero: Medium-Light Skin Tone U+1F9B8, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿฆธ๐Ÿฝโ€โ™‚๏ธ Man Superhero: Medium Skin Tone U+1F9B8, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿฆธ๐Ÿพโ€โ™‚๏ธ Man Superhero: Medium-Dark Skin Tone U+1F9B8, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿฆธ๐Ÿฟโ€โ™‚๏ธ Man Superhero: Dark Skin Tone U+1F9B8, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿฆธโ€โ™€๏ธ Woman Superhero U+1F9B8, U+200D, U+2640, U+FE0F -๐Ÿฆธ๐Ÿปโ€โ™€๏ธ Woman Superhero: Light Skin Tone U+1F9B8, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿฆธ๐Ÿผโ€โ™€๏ธ Woman Superhero: Medium-Light Skin U+1F9B8, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿฆธ๐Ÿฝโ€โ™€๏ธ Woman Superhero: Medium Skin Tone U+1F9B8, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿฆธ๐Ÿพโ€โ™€๏ธ Woman Superhero: Medium-Dark Skin Tone U+1F9B8, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿฆธ๐Ÿฟโ€โ™€๏ธ Woman Superhero: Dark Skin Tone U+1F9B8, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿฆน Supervillain U+1F9B9 -๐Ÿฆน๐Ÿป Supervillain: Light Skin Tone U+1F9B9, U+1F3FB -๐Ÿฆน๐Ÿผ Supervillain: Medium-Light Skin Tone U+1F9B9, U+1F3FC -๐Ÿฆน๐Ÿฝ Supervillain: Medium Skin Tone U+1F9B9, U+1F3FD -๐Ÿฆน๐Ÿพ Supervillain: Medium-Dark Skin Tone U+1F9B9, U+1F3FE -๐Ÿฆน๐Ÿฟ Supervillain: Dark Skin Tone U+1F9B9, U+1F3FF -๐Ÿฆนโ€โ™‚๏ธ Man Supervillain U+1F9B9, U+200D, U+2642, U+FE0F -๐Ÿฆน๐Ÿปโ€โ™‚๏ธ Man Supervillain: Light Skin Tone U+1F9B9, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿฆน๐Ÿผโ€โ™‚๏ธ Man Supervillain: Medium-Light Skin U+1F9B9, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿฆน๐Ÿฝโ€โ™‚๏ธ Man Supervillain: Medium Skin Tone U+1F9B9, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿฆน๐Ÿพโ€โ™‚๏ธ Man Supervillain: Medium-Dark Skin U+1F9B9, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿฆน๐Ÿฟโ€โ™‚๏ธ Man Supervillain: Dark Skin Tone U+1F9B9, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿฆนโ€โ™€๏ธ Woman Supervillain U+1F9B9, U+200D, U+2640, U+FE0F -๐Ÿฆน๐Ÿปโ€โ™€๏ธ Woman Supervillain: Light Skin Tone U+1F9B9, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿฆน๐Ÿผโ€โ™€๏ธ Woman Supervillain: Medium-Light Skin U+1F9B9, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿฆน๐Ÿฝโ€โ™€๏ธ Woman Supervillain: Medium Skin Tone U+1F9B9, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿฆน๐Ÿพโ€โ™€๏ธ Woman Supervillain: Medium-Dark Skin U+1F9B9, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿฆน๐Ÿฟโ€โ™€๏ธ Woman Supervillain: Dark Skin Tone U+1F9B9, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿง™ Mage U+1F9D9 -๐Ÿง™๐Ÿป Mage: Light Skin Tone U+1F9D9, U+1F3FB -๐Ÿง™๐Ÿผ Mage: Medium-Light Skin Tone U+1F9D9, U+1F3FC -๐Ÿง™๐Ÿฝ Mage: Medium Skin Tone U+1F9D9, U+1F3FD -๐Ÿง™๐Ÿพ Mage: Medium-Dark Skin Tone U+1F9D9, U+1F3FE -๐Ÿง™๐Ÿฟ Mage: Dark Skin Tone U+1F9D9, U+1F3FF -๐Ÿง™โ€โ™‚๏ธ Man Mage U+1F9D9, U+200D, U+2642, U+FE0F -๐Ÿง™๐Ÿปโ€โ™‚๏ธ Man Mage: Light Skin Tone U+1F9D9, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿง™๐Ÿผโ€โ™‚๏ธ Man Mage: Medium-Light Skin Tone U+1F9D9, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿง™๐Ÿฝโ€โ™‚๏ธ Man Mage: Medium Skin Tone U+1F9D9, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿง™๐Ÿพโ€โ™‚๏ธ Man Mage: Medium-Dark Skin Tone U+1F9D9, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿง™๐Ÿฟโ€โ™‚๏ธ Man Mage: Dark Skin Tone U+1F9D9, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿง™โ€โ™€๏ธ Woman Mage U+1F9D9, U+200D, U+2640, U+FE0F -๐Ÿง™๐Ÿปโ€โ™€๏ธ Woman Mage: Light Skin Tone U+1F9D9, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿง™๐Ÿผโ€โ™€๏ธ Woman Mage: Medium-Light Skin Tone U+1F9D9, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿง™๐Ÿฝโ€โ™€๏ธ Woman Mage: Medium Skin Tone U+1F9D9, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿง™๐Ÿพโ€โ™€๏ธ Woman Mage: Medium-Dark Skin Tone U+1F9D9, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿง™๐Ÿฟโ€โ™€๏ธ Woman Mage: Dark Skin Tone U+1F9D9, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿงš Fairy U+1F9DA -๐Ÿงš๐Ÿป Fairy: Light Skin Tone U+1F9DA, U+1F3FB -๐Ÿงš๐Ÿผ Fairy: Medium-Light Skin Tone U+1F9DA, U+1F3FC -๐Ÿงš๐Ÿฝ Fairy: Medium Skin Tone U+1F9DA, U+1F3FD -๐Ÿงš๐Ÿพ Fairy: Medium-Dark Skin Tone U+1F9DA, U+1F3FE -๐Ÿงš๐Ÿฟ Fairy: Dark Skin Tone U+1F9DA, U+1F3FF -๐Ÿงšโ€โ™‚๏ธ Man Fairy U+1F9DA, U+200D, U+2642, U+FE0F -๐Ÿงš๐Ÿปโ€โ™‚๏ธ Man Fairy: Light Skin Tone U+1F9DA, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿงš๐Ÿผโ€โ™‚๏ธ Man Fairy: Medium-Light Skin Tone U+1F9DA, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿงš๐Ÿฝโ€โ™‚๏ธ Man Fairy: Medium Skin Tone U+1F9DA, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿงš๐Ÿพโ€โ™‚๏ธ Man Fairy: Medium-Dark Skin Tone U+1F9DA, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿงš๐Ÿฟโ€โ™‚๏ธ Man Fairy: Dark Skin Tone U+1F9DA, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿงšโ€โ™€๏ธ Woman Fairy U+1F9DA, U+200D, U+2640, U+FE0F -๐Ÿงš๐Ÿปโ€โ™€๏ธ Woman Fairy: Light Skin Tone U+1F9DA, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿงš๐Ÿผโ€โ™€๏ธ Woman Fairy: Medium-Light Skin Tone U+1F9DA, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿงš๐Ÿฝโ€โ™€๏ธ Woman Fairy: Medium Skin Tone U+1F9DA, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿงš๐Ÿพโ€โ™€๏ธ Woman Fairy: Medium-Dark Skin Tone U+1F9DA, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿงš๐Ÿฟโ€โ™€๏ธ Woman Fairy: Dark Skin Tone U+1F9DA, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿง› Vampire U+1F9DB -๐Ÿง›๐Ÿป Vampire: Light Skin Tone U+1F9DB, U+1F3FB -๐Ÿง›๐Ÿผ Vampire: Medium-Light Skin Tone U+1F9DB, U+1F3FC -๐Ÿง›๐Ÿฝ Vampire: Medium Skin Tone U+1F9DB, U+1F3FD -๐Ÿง›๐Ÿพ Vampire: Medium-Dark Skin Tone U+1F9DB, U+1F3FE -๐Ÿง›๐Ÿฟ Vampire: Dark Skin Tone U+1F9DB, U+1F3FF -๐Ÿง›โ€โ™‚๏ธ Man Vampire U+1F9DB, U+200D, U+2642, U+FE0F -๐Ÿง›๐Ÿปโ€โ™‚๏ธ Man Vampire: Light Skin Tone U+1F9DB, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿง›๐Ÿผโ€โ™‚๏ธ Man Vampire: Medium-Light Skin Tone U+1F9DB, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿง›๐Ÿฝโ€โ™‚๏ธ Man Vampire: Medium Skin Tone U+1F9DB, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿง›๐Ÿพโ€โ™‚๏ธ Man Vampire: Medium-Dark Skin Tone U+1F9DB, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿง›๐Ÿฟโ€โ™‚๏ธ Man Vampire: Dark Skin Tone U+1F9DB, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿง›โ€โ™€๏ธ Woman Vampire U+1F9DB, U+200D, U+2640, U+FE0F -๐Ÿง›๐Ÿปโ€โ™€๏ธ Woman Vampire: Light Skin Tone U+1F9DB, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿง›๐Ÿผโ€โ™€๏ธ Woman Vampire: Medium-Light Skin Tone U+1F9DB, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿง›๐Ÿฝโ€โ™€๏ธ Woman Vampire: Medium Skin Tone U+1F9DB, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿง›๐Ÿพโ€โ™€๏ธ Woman Vampire: Medium-Dark Skin Tone U+1F9DB, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿง›๐Ÿฟโ€โ™€๏ธ Woman Vampire: Dark Skin Tone U+1F9DB, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿงœ Merperson U+1F9DC -๐Ÿงœ๐Ÿป Merperson: Light Skin Tone U+1F9DC, U+1F3FB -๐Ÿงœ๐Ÿผ Merperson: Medium-Light Skin Tone U+1F9DC, U+1F3FC -๐Ÿงœ๐Ÿฝ Merperson: Medium Skin Tone U+1F9DC, U+1F3FD -๐Ÿงœ๐Ÿพ Merperson: Medium-Dark Skin Tone U+1F9DC, U+1F3FE -๐Ÿงœ๐Ÿฟ Merperson: Dark Skin Tone U+1F9DC, U+1F3FF -๐Ÿงœโ€โ™‚๏ธ Merman U+1F9DC, U+200D, U+2642, U+FE0F -๐Ÿงœ๐Ÿปโ€โ™‚๏ธ Merman: Light Skin Tone U+1F9DC, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿงœ๐Ÿผโ€โ™‚๏ธ Merman: Medium-Light Skin Tone U+1F9DC, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿงœ๐Ÿฝโ€โ™‚๏ธ Merman: Medium Skin Tone U+1F9DC, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿงœ๐Ÿพโ€โ™‚๏ธ Merman: Medium-Dark Skin Tone U+1F9DC, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿงœ๐Ÿฟโ€โ™‚๏ธ Merman: Dark Skin Tone U+1F9DC, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿงœโ€โ™€๏ธ Mermaid U+1F9DC, U+200D, U+2640, U+FE0F -๐Ÿงœ๐Ÿปโ€โ™€๏ธ Mermaid: Light Skin Tone U+1F9DC, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿงœ๐Ÿผโ€โ™€๏ธ Mermaid: Medium-Light Skin Tone U+1F9DC, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿงœ๐Ÿฝโ€โ™€๏ธ Mermaid: Medium Skin Tone U+1F9DC, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿงœ๐Ÿพโ€โ™€๏ธ Mermaid: Medium-Dark Skin Tone U+1F9DC, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿงœ๐Ÿฟโ€โ™€๏ธ Mermaid: Dark Skin Tone U+1F9DC, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿง Elf U+1F9DD -๐Ÿง๐Ÿป Elf: Light Skin Tone U+1F9DD, U+1F3FB -๐Ÿง๐Ÿผ Elf: Medium-Light Skin Tone U+1F9DD, U+1F3FC -๐Ÿง๐Ÿฝ Elf: Medium Skin Tone U+1F9DD, U+1F3FD -๐Ÿง๐Ÿพ Elf: Medium-Dark Skin Tone U+1F9DD, U+1F3FE -๐Ÿง๐Ÿฟ Elf: Dark Skin Tone U+1F9DD, U+1F3FF -๐Ÿงโ€โ™‚๏ธ Man Elf U+1F9DD, U+200D, U+2642, U+FE0F -๐Ÿง๐Ÿปโ€โ™‚๏ธ Man Elf: Light Skin Tone U+1F9DD, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿผโ€โ™‚๏ธ Man Elf: Medium-Light Skin Tone U+1F9DD, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿฝโ€โ™‚๏ธ Man Elf: Medium Skin Tone U+1F9DD, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿพโ€โ™‚๏ธ Man Elf: Medium-Dark Skin Tone U+1F9DD, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿฟโ€โ™‚๏ธ Man Elf: Dark Skin Tone U+1F9DD, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿงโ€โ™€๏ธ Woman Elf U+1F9DD, U+200D, U+2640, U+FE0F -๐Ÿง๐Ÿปโ€โ™€๏ธ Woman Elf: Light Skin Tone U+1F9DD, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿผโ€โ™€๏ธ Woman Elf: Medium-Light Skin Tone U+1F9DD, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿฝโ€โ™€๏ธ Woman Elf: Medium Skin Tone U+1F9DD, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿพโ€โ™€๏ธ Woman Elf: Medium-Dark Skin Tone U+1F9DD, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿฟโ€โ™€๏ธ Woman Elf: Dark Skin Tone U+1F9DD, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿงž Genie U+1F9DE -๐Ÿงžโ€โ™‚๏ธ Man Genie U+1F9DE, U+200D, U+2642, U+FE0F -๐Ÿงžโ€โ™€๏ธ Woman Genie U+1F9DE, U+200D, U+2640, U+FE0F -๐ŸงŸ Zombie U+1F9DF -๐ŸงŸโ€โ™‚๏ธ Man Zombie U+1F9DF, U+200D, U+2642, U+FE0F -๐ŸงŸโ€โ™€๏ธ Woman Zombie U+1F9DF, U+200D, U+2640, U+FE0F -๐Ÿ’† Person Getting Massage U+1F486 -๐Ÿ’†๐Ÿป Person Getting Massage: Light Skin Tone U+1F486, U+1F3FB -๐Ÿ’†๐Ÿผ Person Getting Massage: Medium-Light Skin U+1F486, U+1F3FC -Tone -๐Ÿ’†๐Ÿฝ Person Getting Massage: Medium Skin Tone U+1F486, U+1F3FD -๐Ÿ’†๐Ÿพ Person Getting Massage: Medium-Dark Skin U+1F486, U+1F3FE -Tone -๐Ÿ’†๐Ÿฟ Person Getting Massage: Dark Skin Tone U+1F486, U+1F3FF -๐Ÿ’†โ€โ™‚๏ธ Man Getting Massage U+1F486, U+200D, U+2642, U+FE0F -๐Ÿ’†๐Ÿปโ€โ™‚๏ธ Man Getting Massage: Light Skin Tone U+1F486, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ’†๐Ÿผโ€โ™‚๏ธ Man Getting Massage: Medium-Light Skin U+1F486, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿ’†๐Ÿฝโ€โ™‚๏ธ Man Getting Massage: Medium Skin Tone U+1F486, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ’†๐Ÿพโ€โ™‚๏ธ Man Getting Massage: Medium-Dark Skin U+1F486, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿ’†๐Ÿฟโ€โ™‚๏ธ Man Getting Massage: Dark Skin Tone U+1F486, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ’†โ€โ™€๏ธ Woman Getting Massage U+1F486, U+200D, U+2640, U+FE0F -๐Ÿ’†๐Ÿปโ€โ™€๏ธ Woman Getting Massage: Light Skin Tone U+1F486, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ’†๐Ÿผโ€โ™€๏ธ Woman Getting Massage: Medium-Light U+1F486, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ’†๐Ÿฝโ€โ™€๏ธ Woman Getting Massage: Medium Skin U+1F486, U+1F3FD, U+200D, U+2640, -Tone U+FE0F -๐Ÿ’†๐Ÿพโ€โ™€๏ธ Woman Getting Massage: Medium-Dark U+1F486, U+1F3FE, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ’†๐Ÿฟโ€โ™€๏ธ Woman Getting Massage: Dark Skin Tone U+1F486, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ’‡ Person Getting Haircut U+1F487 -๐Ÿ’‡๐Ÿป Person Getting Haircut: Light Skin Tone U+1F487, U+1F3FB -๐Ÿ’‡๐Ÿผ Person Getting Haircut: Medium-Light Skin U+1F487, U+1F3FC -Tone -๐Ÿ’‡๐Ÿฝ Person Getting Haircut: Medium Skin Tone U+1F487, U+1F3FD -๐Ÿ’‡๐Ÿพ Person Getting Haircut: Medium-Dark Skin U+1F487, U+1F3FE -Tone -๐Ÿ’‡๐Ÿฟ Person Getting Haircut: Dark Skin Tone U+1F487, U+1F3FF -๐Ÿ’‡โ€โ™‚๏ธ Man Getting Haircut U+1F487, U+200D, U+2642, U+FE0F -๐Ÿ’‡๐Ÿปโ€โ™‚๏ธ Man Getting Haircut: Light Skin Tone U+1F487, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ’‡๐Ÿผโ€โ™‚๏ธ Man Getting Haircut: Medium-Light Skin U+1F487, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿ’‡๐Ÿฝโ€โ™‚๏ธ Man Getting Haircut: Medium Skin Tone U+1F487, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ’‡๐Ÿพโ€โ™‚๏ธ Man Getting Haircut: Medium-Dark Skin U+1F487, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿ’‡๐Ÿฟโ€โ™‚๏ธ Man Getting Haircut: Dark Skin Tone U+1F487, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ’‡โ€โ™€๏ธ Woman Getting Haircut U+1F487, U+200D, U+2640, U+FE0F -๐Ÿ’‡๐Ÿปโ€โ™€๏ธ Woman Getting Haircut: Light Skin Tone U+1F487, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ’‡๐Ÿผโ€โ™€๏ธ Woman Getting Haircut: Medium-Light U+1F487, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ’‡๐Ÿฝโ€โ™€๏ธ Woman Getting Haircut: Medium Skin U+1F487, U+1F3FD, U+200D, U+2640, -Tone U+FE0F -๐Ÿ’‡๐Ÿพโ€โ™€๏ธ Woman Getting Haircut: Medium-Dark U+1F487, U+1F3FE, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ’‡๐Ÿฟโ€โ™€๏ธ Woman Getting Haircut: Dark Skin Tone U+1F487, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿšถ Person Walking U+1F6B6 -๐Ÿšถ๐Ÿป Person Walking: Light Skin Tone U+1F6B6, U+1F3FB -๐Ÿšถ๐Ÿผ Person Walking: Medium-Light Skin Tone U+1F6B6, U+1F3FC -๐Ÿšถ๐Ÿฝ Person Walking: Medium Skin Tone U+1F6B6, U+1F3FD -๐Ÿšถ๐Ÿพ Person Walking: Medium-Dark Skin Tone U+1F6B6, U+1F3FE -๐Ÿšถ๐Ÿฟ Person Walking: Dark Skin Tone U+1F6B6, U+1F3FF -๐Ÿšถโ€โ™‚๏ธ Man Walking U+1F6B6, U+200D, U+2642, U+FE0F -๐Ÿšถ๐Ÿปโ€โ™‚๏ธ Man Walking: Light Skin Tone U+1F6B6, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿšถ๐Ÿผโ€โ™‚๏ธ Man Walking: Medium-Light Skin Tone U+1F6B6, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿšถ๐Ÿฝโ€โ™‚๏ธ Man Walking: Medium Skin Tone U+1F6B6, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿšถ๐Ÿพโ€โ™‚๏ธ Man Walking: Medium-Dark Skin Tone U+1F6B6, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿšถ๐Ÿฟโ€โ™‚๏ธ Man Walking: Dark Skin Tone U+1F6B6, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿšถโ€โ™€๏ธ Woman Walking U+1F6B6, U+200D, U+2640, U+FE0F -๐Ÿšถ๐Ÿปโ€โ™€๏ธ Woman Walking: Light Skin Tone U+1F6B6, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿšถ๐Ÿผโ€โ™€๏ธ Woman Walking: Medium-Light Skin Tone U+1F6B6, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿšถ๐Ÿฝโ€โ™€๏ธ Woman Walking: Medium Skin Tone U+1F6B6, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿšถ๐Ÿพโ€โ™€๏ธ Woman Walking: Medium-Dark Skin Tone U+1F6B6, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿšถ๐Ÿฟโ€โ™€๏ธ Woman Walking: Dark Skin Tone U+1F6B6, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿง Person Standing U+1F9CD -๐Ÿง๐Ÿป Person Standing: Light Skin Tone U+1F9CD, U+1F3FB -๐Ÿง๐Ÿผ Person Standing: Medium-Light Skin Tone U+1F9CD, U+1F3FC -๐Ÿง๐Ÿฝ Person Standing: Medium Skin Tone U+1F9CD, U+1F3FD -๐Ÿง๐Ÿพ Person Standing: Medium-Dark Skin Tone U+1F9CD, U+1F3FE -๐Ÿง๐Ÿฟ Person Standing: Dark Skin Tone U+1F9CD, U+1F3FF -๐Ÿงโ€โ™‚๏ธ Man Standing U+1F9CD, U+200D, U+2642, U+FE0F -๐Ÿง๐Ÿปโ€โ™‚๏ธ Man Standing: Light Skin Tone U+1F9CD, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿผโ€โ™‚๏ธ Man Standing: Medium-Light Skin Tone U+1F9CD, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿฝโ€โ™‚๏ธ Man Standing: Medium Skin Tone U+1F9CD, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿพโ€โ™‚๏ธ Man Standing: Medium-Dark Skin Tone U+1F9CD, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿง๐Ÿฟโ€โ™‚๏ธ Man Standing: Dark Skin Tone U+1F9CD, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿงโ€โ™€๏ธ Woman Standing U+1F9CD, U+200D, U+2640, U+FE0F -๐Ÿง๐Ÿปโ€โ™€๏ธ Woman Standing: Light Skin Tone U+1F9CD, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿผโ€โ™€๏ธ Woman Standing: Medium-Light Skin Tone U+1F9CD, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿฝโ€โ™€๏ธ Woman Standing: Medium Skin Tone U+1F9CD, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿพโ€โ™€๏ธ Woman Standing: Medium-Dark Skin Tone U+1F9CD, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿง๐Ÿฟโ€โ™€๏ธ Woman Standing: Dark Skin Tone U+1F9CD, U+1F3FF, U+200D, U+2640, - U+FE0F -๐ŸงŽ Person Kneeling U+1F9CE -๐ŸงŽ๐Ÿป Person Kneeling: Light Skin Tone U+1F9CE, U+1F3FB -๐ŸงŽ๐Ÿผ Person Kneeling: Medium-Light Skin Tone U+1F9CE, U+1F3FC -๐ŸงŽ๐Ÿฝ Person Kneeling: Medium Skin Tone U+1F9CE, U+1F3FD -๐ŸงŽ๐Ÿพ Person Kneeling: Medium-Dark Skin Tone U+1F9CE, U+1F3FE -๐ŸงŽ๐Ÿฟ Person Kneeling: Dark Skin Tone U+1F9CE, U+1F3FF -๐ŸงŽโ€โ™‚๏ธ Man Kneeling U+1F9CE, U+200D, U+2642, U+FE0F -๐ŸงŽ๐Ÿปโ€โ™‚๏ธ Man Kneeling: Light Skin Tone U+1F9CE, U+1F3FB, U+200D, U+2642, - U+FE0F -๐ŸงŽ๐Ÿผโ€โ™‚๏ธ Man Kneeling: Medium-Light Skin Tone U+1F9CE, U+1F3FC, U+200D, U+2642, - U+FE0F -๐ŸงŽ๐Ÿฝโ€โ™‚๏ธ Man Kneeling: Medium Skin Tone U+1F9CE, U+1F3FD, U+200D, U+2642, - U+FE0F -๐ŸงŽ๐Ÿพโ€โ™‚๏ธ Man Kneeling: Medium-Dark Skin Tone U+1F9CE, U+1F3FE, U+200D, U+2642, - U+FE0F -๐ŸงŽ๐Ÿฟโ€โ™‚๏ธ Man Kneeling: Dark Skin Tone U+1F9CE, U+1F3FF, U+200D, U+2642, - U+FE0F -๐ŸงŽโ€โ™€๏ธ Woman Kneeling U+1F9CE, U+200D, U+2640, U+FE0F -๐ŸงŽ๐Ÿปโ€โ™€๏ธ Woman Kneeling: Light Skin Tone U+1F9CE, U+1F3FB, U+200D, U+2640, - U+FE0F -๐ŸงŽ๐Ÿผโ€โ™€๏ธ Woman Kneeling: Medium-Light Skin Tone U+1F9CE, U+1F3FC, U+200D, U+2640, - U+FE0F -๐ŸงŽ๐Ÿฝโ€โ™€๏ธ Woman Kneeling: Medium Skin Tone U+1F9CE, U+1F3FD, U+200D, U+2640, - U+FE0F -๐ŸงŽ๐Ÿพโ€โ™€๏ธ Woman Kneeling: Medium-Dark Skin Tone U+1F9CE, U+1F3FE, U+200D, U+2640, - U+FE0F -๐ŸงŽ๐Ÿฟโ€โ™€๏ธ Woman Kneeling: Dark Skin Tone U+1F9CE, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿง‘โ€๐Ÿฆฏ Person with White Cane U+1F9D1, U+200D, U+1F9AF -๐Ÿง‘๐Ÿปโ€๐Ÿฆฏ Person with White Cane: Light Skin Tone U+1F9D1, U+1F3FB, U+200D, U+1F9AF -๐Ÿง‘๐Ÿผโ€๐Ÿฆฏ Person with White Cane: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F9AF -Skin Tone -๐Ÿง‘๐Ÿฝโ€๐Ÿฆฏ Person with White Cane: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F9AF -Tone -๐Ÿง‘๐Ÿพโ€๐Ÿฆฏ Person with White Cane: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F9AF -Skin Tone -๐Ÿง‘๐Ÿฟโ€๐Ÿฆฏ Person with White Cane: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F9AF -๐Ÿ‘จโ€๐Ÿฆฏ Man with White Cane U+1F468, U+200D, U+1F9AF -๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฏ Man with White Cane: Light Skin Tone U+1F468, U+1F3FB, U+200D, U+1F9AF -๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฏ Man with White Cane: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F9AF -Tone -๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฏ Man with White Cane: Medium Skin Tone U+1F468, U+1F3FD, U+200D, U+1F9AF -๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฏ Man with White Cane: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F9AF -Tone -๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฏ Man with White Cane: Dark Skin Tone U+1F468, U+1F3FF, U+200D, U+1F9AF -๐Ÿ‘ฉโ€๐Ÿฆฏ Woman with White Cane U+1F469, U+200D, U+1F9AF -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฏ Woman with White Cane: Light Skin Tone U+1F469, U+1F3FB, U+200D, U+1F9AF -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฏ Woman with White Cane: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F9AF -Skin Tone -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฏ Woman with White Cane: Medium Skin Tone U+1F469, U+1F3FD, U+200D, U+1F9AF -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฏ Woman with White Cane: Medium-Dark Skin U+1F469, U+1F3FE, U+200D, U+1F9AF -Tone -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฏ Woman with White Cane: Dark Skin Tone U+1F469, U+1F3FF, U+200D, U+1F9AF -๐Ÿง‘โ€๐Ÿฆผ Person in Motorized Wheelchair U+1F9D1, U+200D, U+1F9BC -๐Ÿง‘๐Ÿปโ€๐Ÿฆผ Person in Motorized Wheelchair: Light U+1F9D1, U+1F3FB, U+200D, U+1F9BC -Skin Tone -๐Ÿง‘๐Ÿผโ€๐Ÿฆผ Person in Motorized Wheelchair: U+1F9D1, U+1F3FC, U+200D, U+1F9BC -Medium-Light Skin Tone -๐Ÿง‘๐Ÿฝโ€๐Ÿฆผ Person in Motorized Wheelchair: Medium U+1F9D1, U+1F3FD, U+200D, U+1F9BC -Skin Tone -๐Ÿง‘๐Ÿพโ€๐Ÿฆผ Person in Motorized Wheelchair: U+1F9D1, U+1F3FE, U+200D, U+1F9BC -Medium-Dark Skin Tone -๐Ÿง‘๐Ÿฟโ€๐Ÿฆผ Person in Motorized Wheelchair: Dark U+1F9D1, U+1F3FF, U+200D, U+1F9BC -Skin Tone -๐Ÿ‘จโ€๐Ÿฆผ Man in Motorized Wheelchair U+1F468, U+200D, U+1F9BC -๐Ÿ‘จ๐Ÿปโ€๐Ÿฆผ Man in Motorized Wheelchair: Light Skin U+1F468, U+1F3FB, U+200D, U+1F9BC -Tone -๐Ÿ‘จ๐Ÿผโ€๐Ÿฆผ Man in Motorized Wheelchair: U+1F468, U+1F3FC, U+200D, U+1F9BC -Medium-Light Skin Tone -๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆผ Man in Motorized Wheelchair: Medium U+1F468, U+1F3FD, U+200D, U+1F9BC -Skin Tone -๐Ÿ‘จ๐Ÿพโ€๐Ÿฆผ Man in Motorized Wheelchair: U+1F468, U+1F3FE, U+200D, U+1F9BC -Medium-Dark Skin Tone -๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆผ Man in Motorized Wheelchair: Dark Skin U+1F468, U+1F3FF, U+200D, U+1F9BC -Tone -๐Ÿ‘ฉโ€๐Ÿฆผ Woman in Motorized Wheelchair U+1F469, U+200D, U+1F9BC -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆผ Woman in Motorized Wheelchair: Light U+1F469, U+1F3FB, U+200D, U+1F9BC -Skin Tone -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆผ Woman in Motorized Wheelchair: U+1F469, U+1F3FC, U+200D, U+1F9BC -Medium-Light Skin Tone -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆผ Woman in Motorized Wheelchair: Medium U+1F469, U+1F3FD, U+200D, U+1F9BC -Skin Tone -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆผ Woman in Motorized Wheelchair: U+1F469, U+1F3FE, U+200D, U+1F9BC -Medium-Dark Skin Tone -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆผ Woman in Motorized Wheelchair: Dark U+1F469, U+1F3FF, U+200D, U+1F9BC -Skin Tone -๐Ÿง‘โ€๐Ÿฆฝ Person in Manual Wheelchair U+1F9D1, U+200D, U+1F9BD -๐Ÿง‘๐Ÿปโ€๐Ÿฆฝ Person in Manual Wheelchair: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F9BD -Tone -๐Ÿง‘๐Ÿผโ€๐Ÿฆฝ Person in Manual Wheelchair: U+1F9D1, U+1F3FC, U+200D, U+1F9BD -Medium-Light Skin Tone -๐Ÿง‘๐Ÿฝโ€๐Ÿฆฝ Person in Manual Wheelchair: Medium U+1F9D1, U+1F3FD, U+200D, U+1F9BD -Skin Tone -๐Ÿง‘๐Ÿพโ€๐Ÿฆฝ Person in Manual Wheelchair: U+1F9D1, U+1F3FE, U+200D, U+1F9BD -Medium-Dark Skin Tone -๐Ÿง‘๐Ÿฟโ€๐Ÿฆฝ Person in Manual Wheelchair: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F9BD -Tone -๐Ÿ‘จโ€๐Ÿฆฝ Man in Manual Wheelchair U+1F468, U+200D, U+1F9BD -๐Ÿ‘จ๐Ÿปโ€๐Ÿฆฝ Man in Manual Wheelchair: Light Skin U+1F468, U+1F3FB, U+200D, U+1F9BD -Tone -๐Ÿ‘จ๐Ÿผโ€๐Ÿฆฝ Man in Manual Wheelchair: Medium-Light U+1F468, U+1F3FC, U+200D, U+1F9BD -Skin Tone -๐Ÿ‘จ๐Ÿฝโ€๐Ÿฆฝ Man in Manual Wheelchair: Medium Skin U+1F468, U+1F3FD, U+200D, U+1F9BD -Tone -๐Ÿ‘จ๐Ÿพโ€๐Ÿฆฝ Man in Manual Wheelchair: Medium-Dark U+1F468, U+1F3FE, U+200D, U+1F9BD -Skin Tone -๐Ÿ‘จ๐Ÿฟโ€๐Ÿฆฝ Man in Manual Wheelchair: Dark Skin U+1F468, U+1F3FF, U+200D, U+1F9BD -Tone -๐Ÿ‘ฉโ€๐Ÿฆฝ Woman in Manual Wheelchair U+1F469, U+200D, U+1F9BD -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿฆฝ Woman in Manual Wheelchair: Light Skin U+1F469, U+1F3FB, U+200D, U+1F9BD -Tone -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿฆฝ Woman in Manual Wheelchair: U+1F469, U+1F3FC, U+200D, U+1F9BD -Medium-Light Skin Tone -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿฆฝ Woman in Manual Wheelchair: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F9BD -Tone -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿฆฝ Woman in Manual Wheelchair: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F9BD -Skin Tone -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿฆฝ Woman in Manual Wheelchair: Dark Skin U+1F469, U+1F3FF, U+200D, U+1F9BD -Tone -๐Ÿƒ Person Running U+1F3C3 -๐Ÿƒ๐Ÿป Person Running: Light Skin Tone U+1F3C3, U+1F3FB -๐Ÿƒ๐Ÿผ Person Running: Medium-Light Skin Tone U+1F3C3, U+1F3FC -๐Ÿƒ๐Ÿฝ Person Running: Medium Skin Tone U+1F3C3, U+1F3FD -๐Ÿƒ๐Ÿพ Person Running: Medium-Dark Skin Tone U+1F3C3, U+1F3FE -๐Ÿƒ๐Ÿฟ Person Running: Dark Skin Tone U+1F3C3, U+1F3FF -๐Ÿƒโ€โ™‚๏ธ Man Running U+1F3C3, U+200D, U+2642, U+FE0F -๐Ÿƒ๐Ÿปโ€โ™‚๏ธ Man Running: Light Skin Tone U+1F3C3, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿƒ๐Ÿผโ€โ™‚๏ธ Man Running: Medium-Light Skin Tone U+1F3C3, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿƒ๐Ÿฝโ€โ™‚๏ธ Man Running: Medium Skin Tone U+1F3C3, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿƒ๐Ÿพโ€โ™‚๏ธ Man Running: Medium-Dark Skin Tone U+1F3C3, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿƒ๐Ÿฟโ€โ™‚๏ธ Man Running: Dark Skin Tone U+1F3C3, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿƒโ€โ™€๏ธ Woman Running U+1F3C3, U+200D, U+2640, U+FE0F -๐Ÿƒ๐Ÿปโ€โ™€๏ธ Woman Running: Light Skin Tone U+1F3C3, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿƒ๐Ÿผโ€โ™€๏ธ Woman Running: Medium-Light Skin Tone U+1F3C3, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿƒ๐Ÿฝโ€โ™€๏ธ Woman Running: Medium Skin Tone U+1F3C3, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿƒ๐Ÿพโ€โ™€๏ธ Woman Running: Medium-Dark Skin Tone U+1F3C3, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿƒ๐Ÿฟโ€โ™€๏ธ Woman Running: Dark Skin Tone U+1F3C3, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ’ƒ Woman Dancing U+1F483 -๐Ÿ’ƒ๐Ÿป Woman Dancing: Light Skin Tone U+1F483, U+1F3FB -๐Ÿ’ƒ๐Ÿผ Woman Dancing: Medium-Light Skin Tone U+1F483, U+1F3FC -๐Ÿ’ƒ๐Ÿฝ Woman Dancing: Medium Skin Tone U+1F483, U+1F3FD -๐Ÿ’ƒ๐Ÿพ Woman Dancing: Medium-Dark Skin Tone U+1F483, U+1F3FE -๐Ÿ’ƒ๐Ÿฟ Woman Dancing: Dark Skin Tone U+1F483, U+1F3FF -๐Ÿ•บ Man Dancing U+1F57A -๐Ÿ•บ๐Ÿป Man Dancing: Light Skin Tone U+1F57A, U+1F3FB -๐Ÿ•บ๐Ÿผ Man Dancing: Medium-Light Skin Tone U+1F57A, U+1F3FC -๐Ÿ•บ๐Ÿฝ Man Dancing: Medium Skin Tone U+1F57A, U+1F3FD -๐Ÿ•บ๐Ÿพ Man Dancing: Medium-Dark Skin Tone U+1F57A, U+1F3FE -๐Ÿ•บ๐Ÿฟ Man Dancing: Dark Skin Tone U+1F57A, U+1F3FF -๐Ÿ•ด๏ธ Person in Suit Levitating U+1F574, U+FE0F -๐Ÿ•ด๐Ÿป Person in Suit Levitating: Light Skin U+1F574, U+1F3FB -Tone -๐Ÿ•ด๐Ÿผ Person in Suit Levitating: Medium-Light U+1F574, U+1F3FC -Skin Tone -๐Ÿ•ด๐Ÿฝ Person in Suit Levitating: Medium Skin U+1F574, U+1F3FD -Tone -๐Ÿ•ด๐Ÿพ Person in Suit Levitating: Medium-Dark U+1F574, U+1F3FE -Skin Tone -๐Ÿ•ด๐Ÿฟ Person in Suit Levitating: Dark Skin Tone U+1F574, U+1F3FF -๐Ÿ‘ฏ People with Bunny Ears U+1F46F -๐Ÿ‘ฏโ€โ™‚๏ธ Men with Bunny Ears U+1F46F, U+200D, U+2642, U+FE0F -๐Ÿ‘ฏโ€โ™€๏ธ Women with Bunny Ears U+1F46F, U+200D, U+2640, U+FE0F -๐Ÿง– Person in Steamy Room U+1F9D6 -๐Ÿง–๐Ÿป Person in Steamy Room: Light Skin Tone U+1F9D6, U+1F3FB -๐Ÿง–๐Ÿผ Person in Steamy Room: Medium-Light Skin U+1F9D6, U+1F3FC -Tone -๐Ÿง–๐Ÿฝ Person in Steamy Room: Medium Skin Tone U+1F9D6, U+1F3FD -๐Ÿง–๐Ÿพ Person in Steamy Room: Medium-Dark Skin U+1F9D6, U+1F3FE -Tone -๐Ÿง–๐Ÿฟ Person in Steamy Room: Dark Skin Tone U+1F9D6, U+1F3FF -๐Ÿง–โ€โ™‚๏ธ Man in Steamy Room U+1F9D6, U+200D, U+2642, U+FE0F -๐Ÿง–๐Ÿปโ€โ™‚๏ธ Man in Steamy Room: Light Skin Tone U+1F9D6, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿง–๐Ÿผโ€โ™‚๏ธ Man in Steamy Room: Medium-Light Skin U+1F9D6, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿง–๐Ÿฝโ€โ™‚๏ธ Man in Steamy Room: Medium Skin Tone U+1F9D6, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿง–๐Ÿพโ€โ™‚๏ธ Man in Steamy Room: Medium-Dark Skin U+1F9D6, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿง–๐Ÿฟโ€โ™‚๏ธ Man in Steamy Room: Dark Skin Tone U+1F9D6, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿง–โ€โ™€๏ธ Woman in Steamy Room U+1F9D6, U+200D, U+2640, U+FE0F -๐Ÿง–๐Ÿปโ€โ™€๏ธ Woman in Steamy Room: Light Skin Tone U+1F9D6, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿง–๐Ÿผโ€โ™€๏ธ Woman in Steamy Room: Medium-Light U+1F9D6, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿง–๐Ÿฝโ€โ™€๏ธ Woman in Steamy Room: Medium Skin Tone U+1F9D6, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿง–๐Ÿพโ€โ™€๏ธ Woman in Steamy Room: Medium-Dark Skin U+1F9D6, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿง–๐Ÿฟโ€โ™€๏ธ Woman in Steamy Room: Dark Skin Tone U+1F9D6, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿง— Person Climbing U+1F9D7 -๐Ÿง—๐Ÿป Person Climbing: Light Skin Tone U+1F9D7, U+1F3FB -๐Ÿง—๐Ÿผ Person Climbing: Medium-Light Skin Tone U+1F9D7, U+1F3FC -๐Ÿง—๐Ÿฝ Person Climbing: Medium Skin Tone U+1F9D7, U+1F3FD -๐Ÿง—๐Ÿพ Person Climbing: Medium-Dark Skin Tone U+1F9D7, U+1F3FE -๐Ÿง—๐Ÿฟ Person Climbing: Dark Skin Tone U+1F9D7, U+1F3FF -๐Ÿง—โ€โ™‚๏ธ Man Climbing U+1F9D7, U+200D, U+2642, U+FE0F -๐Ÿง—๐Ÿปโ€โ™‚๏ธ Man Climbing: Light Skin Tone U+1F9D7, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿง—๐Ÿผโ€โ™‚๏ธ Man Climbing: Medium-Light Skin Tone U+1F9D7, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿง—๐Ÿฝโ€โ™‚๏ธ Man Climbing: Medium Skin Tone U+1F9D7, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿง—๐Ÿพโ€โ™‚๏ธ Man Climbing: Medium-Dark Skin Tone U+1F9D7, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿง—๐Ÿฟโ€โ™‚๏ธ Man Climbing: Dark Skin Tone U+1F9D7, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿง—โ€โ™€๏ธ Woman Climbing U+1F9D7, U+200D, U+2640, U+FE0F -๐Ÿง—๐Ÿปโ€โ™€๏ธ Woman Climbing: Light Skin Tone U+1F9D7, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿง—๐Ÿผโ€โ™€๏ธ Woman Climbing: Medium-Light Skin Tone U+1F9D7, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿง—๐Ÿฝโ€โ™€๏ธ Woman Climbing: Medium Skin Tone U+1F9D7, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿง—๐Ÿพโ€โ™€๏ธ Woman Climbing: Medium-Dark Skin Tone U+1F9D7, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿง—๐Ÿฟโ€โ™€๏ธ Woman Climbing: Dark Skin Tone U+1F9D7, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿคบ Person Fencing U+1F93A -๐Ÿ‡ Horse Racing U+1F3C7 -๐Ÿ‡๐Ÿป Horse Racing: Light Skin Tone U+1F3C7, U+1F3FB -๐Ÿ‡๐Ÿผ Horse Racing: Medium-Light Skin Tone U+1F3C7, U+1F3FC -๐Ÿ‡๐Ÿฝ Horse Racing: Medium Skin Tone U+1F3C7, U+1F3FD -๐Ÿ‡๐Ÿพ Horse Racing: Medium-Dark Skin Tone U+1F3C7, U+1F3FE -๐Ÿ‡๐Ÿฟ Horse Racing: Dark Skin Tone U+1F3C7, U+1F3FF -โ›ท๏ธ Skier U+26F7, U+FE0F -๐Ÿ‚ Snowboarder U+1F3C2 -๐Ÿ‚๐Ÿป Snowboarder: Light Skin Tone U+1F3C2, U+1F3FB -๐Ÿ‚๐Ÿผ Snowboarder: Medium-Light Skin Tone U+1F3C2, U+1F3FC -๐Ÿ‚๐Ÿฝ Snowboarder: Medium Skin Tone U+1F3C2, U+1F3FD -๐Ÿ‚๐Ÿพ Snowboarder: Medium-Dark Skin Tone U+1F3C2, U+1F3FE -๐Ÿ‚๐Ÿฟ Snowboarder: Dark Skin Tone U+1F3C2, U+1F3FF -๐ŸŒ๏ธ Person Golfing U+1F3CC, U+FE0F -๐ŸŒ๐Ÿป Person Golfing: Light Skin Tone U+1F3CC, U+1F3FB -๐ŸŒ๐Ÿผ Person Golfing: Medium-Light Skin Tone U+1F3CC, U+1F3FC -๐ŸŒ๐Ÿฝ Person Golfing: Medium Skin Tone U+1F3CC, U+1F3FD -๐ŸŒ๐Ÿพ Person Golfing: Medium-Dark Skin Tone U+1F3CC, U+1F3FE -๐ŸŒ๐Ÿฟ Person Golfing: Dark Skin Tone U+1F3CC, U+1F3FF -๐ŸŒ๏ธโ€โ™‚๏ธ Man Golfing U+1F3CC, U+FE0F, U+200D, U+2642, - U+FE0F -๐ŸŒ๐Ÿปโ€โ™‚๏ธ Man Golfing: Light Skin Tone U+1F3CC, U+1F3FB, U+200D, U+2642, - U+FE0F -๐ŸŒ๐Ÿผโ€โ™‚๏ธ Man Golfing: Medium-Light Skin Tone U+1F3CC, U+1F3FC, U+200D, U+2642, - U+FE0F -๐ŸŒ๐Ÿฝโ€โ™‚๏ธ Man Golfing: Medium Skin Tone U+1F3CC, U+1F3FD, U+200D, U+2642, - U+FE0F -๐ŸŒ๐Ÿพโ€โ™‚๏ธ Man Golfing: Medium-Dark Skin Tone U+1F3CC, U+1F3FE, U+200D, U+2642, - U+FE0F -๐ŸŒ๐Ÿฟโ€โ™‚๏ธ Man Golfing: Dark Skin Tone U+1F3CC, U+1F3FF, U+200D, U+2642, - U+FE0F -๐ŸŒ๏ธโ€โ™€๏ธ Woman Golfing U+1F3CC, U+FE0F, U+200D, U+2640, - U+FE0F -๐ŸŒ๐Ÿปโ€โ™€๏ธ Woman Golfing: Light Skin Tone U+1F3CC, U+1F3FB, U+200D, U+2640, - U+FE0F -๐ŸŒ๐Ÿผโ€โ™€๏ธ Woman Golfing: Medium-Light Skin Tone U+1F3CC, U+1F3FC, U+200D, U+2640, - U+FE0F -๐ŸŒ๐Ÿฝโ€โ™€๏ธ Woman Golfing: Medium Skin Tone U+1F3CC, U+1F3FD, U+200D, U+2640, - U+FE0F -๐ŸŒ๐Ÿพโ€โ™€๏ธ Woman Golfing: Medium-Dark Skin Tone U+1F3CC, U+1F3FE, U+200D, U+2640, - U+FE0F -๐ŸŒ๐Ÿฟโ€โ™€๏ธ Woman Golfing: Dark Skin Tone U+1F3CC, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ„ Person Surfing U+1F3C4 -๐Ÿ„๐Ÿป Person Surfing: Light Skin Tone U+1F3C4, U+1F3FB -๐Ÿ„๐Ÿผ Person Surfing: Medium-Light Skin Tone U+1F3C4, U+1F3FC -๐Ÿ„๐Ÿฝ Person Surfing: Medium Skin Tone U+1F3C4, U+1F3FD -๐Ÿ„๐Ÿพ Person Surfing: Medium-Dark Skin Tone U+1F3C4, U+1F3FE -๐Ÿ„๐Ÿฟ Person Surfing: Dark Skin Tone U+1F3C4, U+1F3FF -๐Ÿ„โ€โ™‚๏ธ Man Surfing U+1F3C4, U+200D, U+2642, U+FE0F -๐Ÿ„๐Ÿปโ€โ™‚๏ธ Man Surfing: Light Skin Tone U+1F3C4, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ„๐Ÿผโ€โ™‚๏ธ Man Surfing: Medium-Light Skin Tone U+1F3C4, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿ„๐Ÿฝโ€โ™‚๏ธ Man Surfing: Medium Skin Tone U+1F3C4, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ„๐Ÿพโ€โ™‚๏ธ Man Surfing: Medium-Dark Skin Tone U+1F3C4, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿ„๐Ÿฟโ€โ™‚๏ธ Man Surfing: Dark Skin Tone U+1F3C4, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ„โ€โ™€๏ธ Woman Surfing U+1F3C4, U+200D, U+2640, U+FE0F -๐Ÿ„๐Ÿปโ€โ™€๏ธ Woman Surfing: Light Skin Tone U+1F3C4, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ„๐Ÿผโ€โ™€๏ธ Woman Surfing: Medium-Light Skin Tone U+1F3C4, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿ„๐Ÿฝโ€โ™€๏ธ Woman Surfing: Medium Skin Tone U+1F3C4, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿ„๐Ÿพโ€โ™€๏ธ Woman Surfing: Medium-Dark Skin Tone U+1F3C4, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿ„๐Ÿฟโ€โ™€๏ธ Woman Surfing: Dark Skin Tone U+1F3C4, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿšฃ Person Rowing Boat U+1F6A3 -๐Ÿšฃ๐Ÿป Person Rowing Boat: Light Skin Tone U+1F6A3, U+1F3FB -๐Ÿšฃ๐Ÿผ Person Rowing Boat: Medium-Light Skin U+1F6A3, U+1F3FC -Tone -๐Ÿšฃ๐Ÿฝ Person Rowing Boat: Medium Skin Tone U+1F6A3, U+1F3FD -๐Ÿšฃ๐Ÿพ Person Rowing Boat: Medium-Dark Skin Tone U+1F6A3, U+1F3FE -๐Ÿšฃ๐Ÿฟ Person Rowing Boat: Dark Skin Tone U+1F6A3, U+1F3FF -๐Ÿšฃโ€โ™‚๏ธ Man Rowing Boat U+1F6A3, U+200D, U+2642, U+FE0F -๐Ÿšฃ๐Ÿปโ€โ™‚๏ธ Man Rowing Boat: Light Skin Tone U+1F6A3, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿšฃ๐Ÿผโ€โ™‚๏ธ Man Rowing Boat: Medium-Light Skin U+1F6A3, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿšฃ๐Ÿฝโ€โ™‚๏ธ Man Rowing Boat: Medium Skin Tone U+1F6A3, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿšฃ๐Ÿพโ€โ™‚๏ธ Man Rowing Boat: Medium-Dark Skin Tone U+1F6A3, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿšฃ๐Ÿฟโ€โ™‚๏ธ Man Rowing Boat: Dark Skin Tone U+1F6A3, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿšฃโ€โ™€๏ธ Woman Rowing Boat U+1F6A3, U+200D, U+2640, U+FE0F -๐Ÿšฃ๐Ÿปโ€โ™€๏ธ Woman Rowing Boat: Light Skin Tone U+1F6A3, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿšฃ๐Ÿผโ€โ™€๏ธ Woman Rowing Boat: Medium-Light Skin U+1F6A3, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿšฃ๐Ÿฝโ€โ™€๏ธ Woman Rowing Boat: Medium Skin Tone U+1F6A3, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿšฃ๐Ÿพโ€โ™€๏ธ Woman Rowing Boat: Medium-Dark Skin U+1F6A3, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿšฃ๐Ÿฟโ€โ™€๏ธ Woman Rowing Boat: Dark Skin Tone U+1F6A3, U+1F3FF, U+200D, U+2640, - U+FE0F -๐ŸŠ Person Swimming U+1F3CA -๐ŸŠ๐Ÿป Person Swimming: Light Skin Tone U+1F3CA, U+1F3FB -๐ŸŠ๐Ÿผ Person Swimming: Medium-Light Skin Tone U+1F3CA, U+1F3FC -๐ŸŠ๐Ÿฝ Person Swimming: Medium Skin Tone U+1F3CA, U+1F3FD -๐ŸŠ๐Ÿพ Person Swimming: Medium-Dark Skin Tone U+1F3CA, U+1F3FE -๐ŸŠ๐Ÿฟ Person Swimming: Dark Skin Tone U+1F3CA, U+1F3FF -๐ŸŠโ€โ™‚๏ธ Man Swimming U+1F3CA, U+200D, U+2642, U+FE0F -๐ŸŠ๐Ÿปโ€โ™‚๏ธ Man Swimming: Light Skin Tone U+1F3CA, U+1F3FB, U+200D, U+2642, - U+FE0F -๐ŸŠ๐Ÿผโ€โ™‚๏ธ Man Swimming: Medium-Light Skin Tone U+1F3CA, U+1F3FC, U+200D, U+2642, - U+FE0F -๐ŸŠ๐Ÿฝโ€โ™‚๏ธ Man Swimming: Medium Skin Tone U+1F3CA, U+1F3FD, U+200D, U+2642, - U+FE0F -๐ŸŠ๐Ÿพโ€โ™‚๏ธ Man Swimming: Medium-Dark Skin Tone U+1F3CA, U+1F3FE, U+200D, U+2642, - U+FE0F -๐ŸŠ๐Ÿฟโ€โ™‚๏ธ Man Swimming: Dark Skin Tone U+1F3CA, U+1F3FF, U+200D, U+2642, - U+FE0F -๐ŸŠโ€โ™€๏ธ Woman Swimming U+1F3CA, U+200D, U+2640, U+FE0F -๐ŸŠ๐Ÿปโ€โ™€๏ธ Woman Swimming: Light Skin Tone U+1F3CA, U+1F3FB, U+200D, U+2640, - U+FE0F -๐ŸŠ๐Ÿผโ€โ™€๏ธ Woman Swimming: Medium-Light Skin Tone U+1F3CA, U+1F3FC, U+200D, U+2640, - U+FE0F -๐ŸŠ๐Ÿฝโ€โ™€๏ธ Woman Swimming: Medium Skin Tone U+1F3CA, U+1F3FD, U+200D, U+2640, - U+FE0F -๐ŸŠ๐Ÿพโ€โ™€๏ธ Woman Swimming: Medium-Dark Skin Tone U+1F3CA, U+1F3FE, U+200D, U+2640, - U+FE0F -๐ŸŠ๐Ÿฟโ€โ™€๏ธ Woman Swimming: Dark Skin Tone U+1F3CA, U+1F3FF, U+200D, U+2640, - U+FE0F -โ›น๏ธ Person Bouncing Ball U+26F9, U+FE0F -โ›น๐Ÿป Person Bouncing Ball: Light Skin Tone U+26F9, U+1F3FB -โ›น๐Ÿผ Person Bouncing Ball: Medium-Light Skin U+26F9, U+1F3FC -Tone -โ›น๐Ÿฝ Person Bouncing Ball: Medium Skin Tone U+26F9, U+1F3FD -โ›น๐Ÿพ Person Bouncing Ball: Medium-Dark Skin U+26F9, U+1F3FE -Tone -โ›น๐Ÿฟ Person Bouncing Ball: Dark Skin Tone U+26F9, U+1F3FF -โ›น๏ธโ€โ™‚๏ธ Man Bouncing Ball U+26F9, U+FE0F, U+200D, U+2642, - U+FE0F -โ›น๐Ÿปโ€โ™‚๏ธ Man Bouncing Ball: Light Skin Tone U+26F9, U+1F3FB, U+200D, U+2642, - U+FE0F -โ›น๐Ÿผโ€โ™‚๏ธ Man Bouncing Ball: Medium-Light Skin U+26F9, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -โ›น๐Ÿฝโ€โ™‚๏ธ Man Bouncing Ball: Medium Skin Tone U+26F9, U+1F3FD, U+200D, U+2642, - U+FE0F -โ›น๐Ÿพโ€โ™‚๏ธ Man Bouncing Ball: Medium-Dark Skin U+26F9, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -โ›น๐Ÿฟโ€โ™‚๏ธ Man Bouncing Ball: Dark Skin Tone U+26F9, U+1F3FF, U+200D, U+2642, - U+FE0F -โ›น๏ธโ€โ™€๏ธ Woman Bouncing Ball U+26F9, U+FE0F, U+200D, U+2640, - U+FE0F -โ›น๐Ÿปโ€โ™€๏ธ Woman Bouncing Ball: Light Skin Tone U+26F9, U+1F3FB, U+200D, U+2640, - U+FE0F -โ›น๐Ÿผโ€โ™€๏ธ Woman Bouncing Ball: Medium-Light Skin U+26F9, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -โ›น๐Ÿฝโ€โ™€๏ธ Woman Bouncing Ball: Medium Skin Tone U+26F9, U+1F3FD, U+200D, U+2640, - U+FE0F -โ›น๐Ÿพโ€โ™€๏ธ Woman Bouncing Ball: Medium-Dark Skin U+26F9, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -โ›น๐Ÿฟโ€โ™€๏ธ Woman Bouncing Ball: Dark Skin Tone U+26F9, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿ‹๏ธ Person Lifting Weights U+1F3CB, U+FE0F -๐Ÿ‹๐Ÿป Person Lifting Weights: Light Skin Tone U+1F3CB, U+1F3FB -๐Ÿ‹๐Ÿผ Person Lifting Weights: Medium-Light Skin U+1F3CB, U+1F3FC -Tone -๐Ÿ‹๐Ÿฝ Person Lifting Weights: Medium Skin Tone U+1F3CB, U+1F3FD -๐Ÿ‹๐Ÿพ Person Lifting Weights: Medium-Dark Skin U+1F3CB, U+1F3FE -Tone -๐Ÿ‹๐Ÿฟ Person Lifting Weights: Dark Skin Tone U+1F3CB, U+1F3FF -๐Ÿ‹๏ธโ€โ™‚๏ธ Man Lifting Weights U+1F3CB, U+FE0F, U+200D, U+2642, - U+FE0F -๐Ÿ‹๐Ÿปโ€โ™‚๏ธ Man Lifting Weights: Light Skin Tone U+1F3CB, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿ‹๐Ÿผโ€โ™‚๏ธ Man Lifting Weights: Medium-Light Skin U+1F3CB, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‹๐Ÿฝโ€โ™‚๏ธ Man Lifting Weights: Medium Skin Tone U+1F3CB, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿ‹๐Ÿพโ€โ™‚๏ธ Man Lifting Weights: Medium-Dark Skin U+1F3CB, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‹๐Ÿฟโ€โ™‚๏ธ Man Lifting Weights: Dark Skin Tone U+1F3CB, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ‹๏ธโ€โ™€๏ธ Woman Lifting Weights U+1F3CB, U+FE0F, U+200D, U+2640, - U+FE0F -๐Ÿ‹๐Ÿปโ€โ™€๏ธ Woman Lifting Weights: Light Skin Tone U+1F3CB, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿ‹๐Ÿผโ€โ™€๏ธ Woman Lifting Weights: Medium-Light U+1F3CB, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ‹๐Ÿฝโ€โ™€๏ธ Woman Lifting Weights: Medium Skin U+1F3CB, U+1F3FD, U+200D, U+2640, -Tone U+FE0F -๐Ÿ‹๐Ÿพโ€โ™€๏ธ Woman Lifting Weights: Medium-Dark U+1F3CB, U+1F3FE, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ‹๐Ÿฟโ€โ™€๏ธ Woman Lifting Weights: Dark Skin Tone U+1F3CB, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿšด Person Biking U+1F6B4 -๐Ÿšด๐Ÿป Person Biking: Light Skin Tone U+1F6B4, U+1F3FB -๐Ÿšด๐Ÿผ Person Biking: Medium-Light Skin Tone U+1F6B4, U+1F3FC -๐Ÿšด๐Ÿฝ Person Biking: Medium Skin Tone U+1F6B4, U+1F3FD -๐Ÿšด๐Ÿพ Person Biking: Medium-Dark Skin Tone U+1F6B4, U+1F3FE -๐Ÿšด๐Ÿฟ Person Biking: Dark Skin Tone U+1F6B4, U+1F3FF -๐Ÿšดโ€โ™‚๏ธ Man Biking U+1F6B4, U+200D, U+2642, U+FE0F -๐Ÿšด๐Ÿปโ€โ™‚๏ธ Man Biking: Light Skin Tone U+1F6B4, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿšด๐Ÿผโ€โ™‚๏ธ Man Biking: Medium-Light Skin Tone U+1F6B4, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿšด๐Ÿฝโ€โ™‚๏ธ Man Biking: Medium Skin Tone U+1F6B4, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿšด๐Ÿพโ€โ™‚๏ธ Man Biking: Medium-Dark Skin Tone U+1F6B4, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿšด๐Ÿฟโ€โ™‚๏ธ Man Biking: Dark Skin Tone U+1F6B4, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿšดโ€โ™€๏ธ Woman Biking U+1F6B4, U+200D, U+2640, U+FE0F -๐Ÿšด๐Ÿปโ€โ™€๏ธ Woman Biking: Light Skin Tone U+1F6B4, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿšด๐Ÿผโ€โ™€๏ธ Woman Biking: Medium-Light Skin Tone U+1F6B4, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿšด๐Ÿฝโ€โ™€๏ธ Woman Biking: Medium Skin Tone U+1F6B4, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿšด๐Ÿพโ€โ™€๏ธ Woman Biking: Medium-Dark Skin Tone U+1F6B4, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿšด๐Ÿฟโ€โ™€๏ธ Woman Biking: Dark Skin Tone U+1F6B4, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿšต Person Mountain Biking U+1F6B5 -๐Ÿšต๐Ÿป Person Mountain Biking: Light Skin Tone U+1F6B5, U+1F3FB -๐Ÿšต๐Ÿผ Person Mountain Biking: Medium-Light Skin U+1F6B5, U+1F3FC -Tone -๐Ÿšต๐Ÿฝ Person Mountain Biking: Medium Skin Tone U+1F6B5, U+1F3FD -๐Ÿšต๐Ÿพ Person Mountain Biking: Medium-Dark Skin U+1F6B5, U+1F3FE -Tone -๐Ÿšต๐Ÿฟ Person Mountain Biking: Dark Skin Tone U+1F6B5, U+1F3FF -๐Ÿšตโ€โ™‚๏ธ Man Mountain Biking U+1F6B5, U+200D, U+2642, U+FE0F -๐Ÿšต๐Ÿปโ€โ™‚๏ธ Man Mountain Biking: Light Skin Tone U+1F6B5, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿšต๐Ÿผโ€โ™‚๏ธ Man Mountain Biking: Medium-Light Skin U+1F6B5, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿšต๐Ÿฝโ€โ™‚๏ธ Man Mountain Biking: Medium Skin Tone U+1F6B5, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿšต๐Ÿพโ€โ™‚๏ธ Man Mountain Biking: Medium-Dark Skin U+1F6B5, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿšต๐Ÿฟโ€โ™‚๏ธ Man Mountain Biking: Dark Skin Tone U+1F6B5, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿšตโ€โ™€๏ธ Woman Mountain Biking U+1F6B5, U+200D, U+2640, U+FE0F -๐Ÿšต๐Ÿปโ€โ™€๏ธ Woman Mountain Biking: Light Skin Tone U+1F6B5, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿšต๐Ÿผโ€โ™€๏ธ Woman Mountain Biking: Medium-Light U+1F6B5, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿšต๐Ÿฝโ€โ™€๏ธ Woman Mountain Biking: Medium Skin U+1F6B5, U+1F3FD, U+200D, U+2640, -Tone U+FE0F -๐Ÿšต๐Ÿพโ€โ™€๏ธ Woman Mountain Biking: Medium-Dark U+1F6B5, U+1F3FE, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿšต๐Ÿฟโ€โ™€๏ธ Woman Mountain Biking: Dark Skin Tone U+1F6B5, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿคธ Person Cartwheeling U+1F938 -๐Ÿคธ๐Ÿป Person Cartwheeling: Light Skin Tone U+1F938, U+1F3FB -๐Ÿคธ๐Ÿผ Person Cartwheeling: Medium-Light Skin U+1F938, U+1F3FC -Tone -๐Ÿคธ๐Ÿฝ Person Cartwheeling: Medium Skin Tone U+1F938, U+1F3FD -๐Ÿคธ๐Ÿพ Person Cartwheeling: Medium-Dark Skin U+1F938, U+1F3FE -Tone -๐Ÿคธ๐Ÿฟ Person Cartwheeling: Dark Skin Tone U+1F938, U+1F3FF -๐Ÿคธโ€โ™‚๏ธ Man Cartwheeling U+1F938, U+200D, U+2642, U+FE0F -๐Ÿคธ๐Ÿปโ€โ™‚๏ธ Man Cartwheeling: Light Skin Tone U+1F938, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿคธ๐Ÿผโ€โ™‚๏ธ Man Cartwheeling: Medium-Light Skin U+1F938, U+1F3FC, U+200D, U+2642, -Tone U+FE0F -๐Ÿคธ๐Ÿฝโ€โ™‚๏ธ Man Cartwheeling: Medium Skin Tone U+1F938, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿคธ๐Ÿพโ€โ™‚๏ธ Man Cartwheeling: Medium-Dark Skin U+1F938, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿคธ๐Ÿฟโ€โ™‚๏ธ Man Cartwheeling: Dark Skin Tone U+1F938, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿคธโ€โ™€๏ธ Woman Cartwheeling U+1F938, U+200D, U+2640, U+FE0F -๐Ÿคธ๐Ÿปโ€โ™€๏ธ Woman Cartwheeling: Light Skin Tone U+1F938, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿคธ๐Ÿผโ€โ™€๏ธ Woman Cartwheeling: Medium-Light Skin U+1F938, U+1F3FC, U+200D, U+2640, -Tone U+FE0F -๐Ÿคธ๐Ÿฝโ€โ™€๏ธ Woman Cartwheeling: Medium Skin Tone U+1F938, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿคธ๐Ÿพโ€โ™€๏ธ Woman Cartwheeling: Medium-Dark Skin U+1F938, U+1F3FE, U+200D, U+2640, -Tone U+FE0F -๐Ÿคธ๐Ÿฟโ€โ™€๏ธ Woman Cartwheeling: Dark Skin Tone U+1F938, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿคผ People Wrestling U+1F93C -๐Ÿคผโ€โ™‚๏ธ Men Wrestling U+1F93C, U+200D, U+2642, U+FE0F -๐Ÿคผโ€โ™€๏ธ Women Wrestling U+1F93C, U+200D, U+2640, U+FE0F -๐Ÿคฝ Person Playing Water Polo U+1F93D -๐Ÿคฝ๐Ÿป Person Playing Water Polo: Light Skin U+1F93D, U+1F3FB -Tone -๐Ÿคฝ๐Ÿผ Person Playing Water Polo: Medium-Light U+1F93D, U+1F3FC -Skin Tone -๐Ÿคฝ๐Ÿฝ Person Playing Water Polo: Medium Skin U+1F93D, U+1F3FD -Tone -๐Ÿ‘ฏ๐Ÿปโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-1-2 U+1F46F, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿคฝ๐Ÿพ Person Playing Water Polo: Medium-Dark U+1F93D, U+1F3FE -Skin Tone -๐Ÿคฝ๐Ÿฟ Person Playing Water Polo: Dark Skin Tone U+1F93D, U+1F3FF -๐Ÿ‘ฏ๐Ÿผโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-3 U+1F46F, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿคฝโ€โ™‚๏ธ Man Playing Water Polo U+1F93D, U+200D, U+2642, U+FE0F -๐Ÿคฝ๐Ÿปโ€โ™‚๏ธ Man Playing Water Polo: Light Skin U+1F93D, U+1F3FB, U+200D, U+2642, -Tone U+FE0F -๐Ÿ‘ฏ๐Ÿฝโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-4 U+1F46F, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿคฝ๐Ÿผโ€โ™‚๏ธ Man Playing Water Polo: Medium-Light U+1F93D, U+1F3FC, U+200D, U+2642, -Skin Tone U+FE0F -๐Ÿ‘ฏ๐Ÿพโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-5 U+1F46F, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿคฝ๐Ÿฝโ€โ™‚๏ธ Man Playing Water Polo: Medium Skin U+1F93D, U+1F3FD, U+200D, U+2642, -Tone U+FE0F -๐Ÿคฝ๐Ÿพโ€โ™‚๏ธ Man Playing Water Polo: Medium-Dark U+1F93D, U+1F3FE, U+200D, U+2642, -Skin Tone U+FE0F -๐Ÿคฝ๐Ÿฟโ€โ™‚๏ธ Man Playing Water Polo: Dark Skin Tone U+1F93D, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿ‘ฏ๐Ÿฟโ€โ™‚๏ธ Men With Bunny Ears Partying, Type-6 U+1F46F, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿคฝโ€โ™€๏ธ Woman Playing Water Polo U+1F93D, U+200D, U+2640, U+FE0F -๐Ÿคฝ๐Ÿปโ€โ™€๏ธ Woman Playing Water Polo: Light Skin U+1F93D, U+1F3FB, U+200D, U+2640, -Tone U+FE0F -๐Ÿคฝ๐Ÿผโ€โ™€๏ธ Woman Playing Water Polo: Medium-Light U+1F93D, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿคฝ๐Ÿฝโ€โ™€๏ธ Woman Playing Water Polo: Medium Skin U+1F93D, U+1F3FD, U+200D, U+2640, -Tone U+FE0F -๐Ÿ‘ฏ๐Ÿปโ€โ™€๏ธ Women With Bunny Ears Partying, U+1F46F, U+1F3FB, U+200D, U+2640, -Type-1-2 U+FE0F -๐Ÿคฝ๐Ÿพโ€โ™€๏ธ Woman Playing Water Polo: Medium-Dark U+1F93D, U+1F3FE, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿ‘ฏ๐Ÿผโ€โ™€๏ธ Women With Bunny Ears Partying, Type-3 U+1F46F, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿคฝ๐Ÿฟโ€โ™€๏ธ Woman Playing Water Polo: Dark Skin U+1F93D, U+1F3FF, U+200D, U+2640, -Tone U+FE0F -๐Ÿคพ Person Playing Handball U+1F93E -๐Ÿ‘ฏ๐Ÿฝโ€โ™€๏ธ Women With Bunny Ears Partying, Type-4 U+1F46F, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿคพ๐Ÿป Person Playing Handball: Light Skin Tone U+1F93E, U+1F3FB -๐Ÿคพ๐Ÿผ Person Playing Handball: Medium-Light U+1F93E, U+1F3FC -Skin Tone -๐Ÿคพ๐Ÿฝ Person Playing Handball: Medium Skin Tone U+1F93E, U+1F3FD -๐Ÿ‘ฏ๐Ÿพโ€โ™€๏ธ Women With Bunny Ears Partying, Type-5 U+1F46F, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿคพ๐Ÿพ Person Playing Handball: Medium-Dark Skin U+1F93E, U+1F3FE -Tone -๐Ÿ‘ฏ๐Ÿฟโ€โ™€๏ธ Women With Bunny Ears Partying, Type-6 U+1F46F, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿคพ๐Ÿฟ Person Playing Handball: Dark Skin Tone U+1F93E, U+1F3FF -๐Ÿคพโ€โ™‚๏ธ Man Playing Handball U+1F93E, U+200D, U+2642, U+FE0F -๐Ÿคพ๐Ÿปโ€โ™‚๏ธ Man Playing Handball: Light Skin Tone U+1F93E, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿคพ๐Ÿผโ€โ™‚๏ธ Man Playing Handball: Medium-Light U+1F93E, U+1F3FC, U+200D, U+2642, -Skin Tone U+FE0F -๐Ÿคพ๐Ÿฝโ€โ™‚๏ธ Man Playing Handball: Medium Skin Tone U+1F93E, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿคพ๐Ÿพโ€โ™‚๏ธ Man Playing Handball: Medium-Dark Skin U+1F93E, U+1F3FE, U+200D, U+2642, -Tone U+FE0F -๐Ÿคพ๐Ÿฟโ€โ™‚๏ธ Man Playing Handball: Dark Skin Tone U+1F93E, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿคพโ€โ™€๏ธ Woman Playing Handball U+1F93E, U+200D, U+2640, U+FE0F -๐Ÿคพ๐Ÿปโ€โ™€๏ธ Woman Playing Handball: Light Skin U+1F93E, U+1F3FB, U+200D, U+2640, -Tone U+FE0F -๐Ÿคพ๐Ÿผโ€โ™€๏ธ Woman Playing Handball: Medium-Light U+1F93E, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿคพ๐Ÿฝโ€โ™€๏ธ Woman Playing Handball: Medium Skin U+1F93E, U+1F3FD, U+200D, U+2640, -Tone U+FE0F -๐Ÿคพ๐Ÿพโ€โ™€๏ธ Woman Playing Handball: Medium-Dark U+1F93E, U+1F3FE, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿคพ๐Ÿฟโ€โ™€๏ธ Woman Playing Handball: Dark Skin Tone U+1F93E, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿคน Person Juggling U+1F939 -๐Ÿคน๐Ÿป Person Juggling: Light Skin Tone U+1F939, U+1F3FB -๐Ÿคน๐Ÿผ Person Juggling: Medium-Light Skin Tone U+1F939, U+1F3FC -๐Ÿคน๐Ÿฝ Person Juggling: Medium Skin Tone U+1F939, U+1F3FD -๐Ÿคน๐Ÿพ Person Juggling: Medium-Dark Skin Tone U+1F939, U+1F3FE -๐Ÿคน๐Ÿฟ Person Juggling: Dark Skin Tone U+1F939, U+1F3FF -๐Ÿคนโ€โ™‚๏ธ Man Juggling U+1F939, U+200D, U+2642, U+FE0F -๐Ÿคน๐Ÿปโ€โ™‚๏ธ Man Juggling: Light Skin Tone U+1F939, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿคน๐Ÿผโ€โ™‚๏ธ Man Juggling: Medium-Light Skin Tone U+1F939, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿคน๐Ÿฝโ€โ™‚๏ธ Man Juggling: Medium Skin Tone U+1F939, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿคน๐Ÿพโ€โ™‚๏ธ Man Juggling: Medium-Dark Skin Tone U+1F939, U+1F3FE, U+200D, U+2642, - U+FE0F -๐Ÿคน๐Ÿฟโ€โ™‚๏ธ Man Juggling: Dark Skin Tone U+1F939, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿคนโ€โ™€๏ธ Woman Juggling U+1F939, U+200D, U+2640, U+FE0F -๐Ÿคน๐Ÿปโ€โ™€๏ธ Woman Juggling: Light Skin Tone U+1F939, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿคน๐Ÿผโ€โ™€๏ธ Woman Juggling: Medium-Light Skin Tone U+1F939, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿคน๐Ÿฝโ€โ™€๏ธ Woman Juggling: Medium Skin Tone U+1F939, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿคน๐Ÿพโ€โ™€๏ธ Woman Juggling: Medium-Dark Skin Tone U+1F939, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿคน๐Ÿฟโ€โ™€๏ธ Woman Juggling: Dark Skin Tone U+1F939, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿง˜ Person in Lotus Position U+1F9D8 -๐Ÿง˜๐Ÿป Person in Lotus Position: Light Skin Tone U+1F9D8, U+1F3FB -๐Ÿง˜๐Ÿผ Person in Lotus Position: Medium-Light U+1F9D8, U+1F3FC -Skin Tone -๐Ÿง˜๐Ÿฝ Person in Lotus Position: Medium Skin U+1F9D8, U+1F3FD -Tone -๐Ÿง˜๐Ÿพ Person in Lotus Position: Medium-Dark U+1F9D8, U+1F3FE -Skin Tone -๐Ÿง˜๐Ÿฟ Person in Lotus Position: Dark Skin Tone U+1F9D8, U+1F3FF -๐Ÿง˜โ€โ™‚๏ธ Man in Lotus Position U+1F9D8, U+200D, U+2642, U+FE0F -๐Ÿง˜๐Ÿปโ€โ™‚๏ธ Man in Lotus Position: Light Skin Tone U+1F9D8, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿง˜๐Ÿผโ€โ™‚๏ธ Man in Lotus Position: Medium-Light U+1F9D8, U+1F3FC, U+200D, U+2642, -Skin Tone U+FE0F -๐Ÿง˜๐Ÿฝโ€โ™‚๏ธ Man in Lotus Position: Medium Skin U+1F9D8, U+1F3FD, U+200D, U+2642, -Tone U+FE0F -๐Ÿง˜๐Ÿพโ€โ™‚๏ธ Man in Lotus Position: Medium-Dark U+1F9D8, U+1F3FE, U+200D, U+2642, -Skin Tone U+FE0F -๐Ÿง˜๐Ÿฟโ€โ™‚๏ธ Man in Lotus Position: Dark Skin Tone U+1F9D8, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿง˜โ€โ™€๏ธ Woman in Lotus Position U+1F9D8, U+200D, U+2640, U+FE0F -๐Ÿง˜๐Ÿปโ€โ™€๏ธ Woman in Lotus Position: Light Skin U+1F9D8, U+1F3FB, U+200D, U+2640, -Tone U+FE0F -๐Ÿง˜๐Ÿผโ€โ™€๏ธ Woman in Lotus Position: Medium-Light U+1F9D8, U+1F3FC, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿง˜๐Ÿฝโ€โ™€๏ธ Woman in Lotus Position: Medium Skin U+1F9D8, U+1F3FD, U+200D, U+2640, -Tone U+FE0F -๐Ÿง˜๐Ÿพโ€โ™€๏ธ Woman in Lotus Position: Medium-Dark U+1F9D8, U+1F3FE, U+200D, U+2640, -Skin Tone U+FE0F -๐Ÿง˜๐Ÿฟโ€โ™€๏ธ Woman in Lotus Position: Dark Skin U+1F9D8, U+1F3FF, U+200D, U+2640, -Tone U+FE0F -๐Ÿ›€ Person Taking Bath U+1F6C0 -๐Ÿ›€๐Ÿป Person Taking Bath: Light Skin Tone U+1F6C0, U+1F3FB -๐Ÿ›€๐Ÿผ Person Taking Bath: Medium-Light Skin U+1F6C0, U+1F3FC -Tone -๐Ÿ›€๐Ÿฝ Person Taking Bath: Medium Skin Tone U+1F6C0, U+1F3FD -๐Ÿ›€๐Ÿพ Person Taking Bath: Medium-Dark Skin Tone U+1F6C0, U+1F3FE -๐Ÿ›€๐Ÿฟ Person Taking Bath: Dark Skin Tone U+1F6C0, U+1F3FF -๐Ÿ›Œ Person in Bed U+1F6CC -๐Ÿ›Œ๐Ÿป Person in Bed: Light Skin Tone U+1F6CC, U+1F3FB -๐Ÿ›Œ๐Ÿผ Person in Bed: Medium-Light Skin Tone U+1F6CC, U+1F3FC -๐Ÿ›Œ๐Ÿฝ Person in Bed: Medium Skin Tone U+1F6CC, U+1F3FD -๐Ÿ›Œ๐Ÿพ Person in Bed: Medium-Dark Skin Tone U+1F6CC, U+1F3FE -๐Ÿ›Œ๐Ÿฟ Person in Bed: Dark Skin Tone U+1F6CC, U+1F3FF -๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ People Holding Hands U+1F9D1, U+200D, U+1F91D, U+200D, - U+1F9D1 -๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, -Tone U+200D, U+1F9D1, U+1F3FB -๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, -Tone, Medium-Light Skin Tone U+200D, U+1F9D1, U+1F3FC -๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, -Tone, Medium Skin Tone U+200D, U+1F9D1, U+1F3FD -๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, -Tone, Medium-Dark Skin Tone U+200D, U+1F9D1, U+1F3FE -๐Ÿง‘๐Ÿปโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Light Skin U+1F9D1, U+1F3FB, U+200D, U+1F91D, -Tone, Dark Skin Tone U+200D, U+1F9D1, U+1F3FF -๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, -Skin Tone, Light Skin Tone U+200D, U+1F9D1, U+1F3FB -๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, -Skin Tone U+200D, U+1F9D1, U+1F3FC -๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, -Skin Tone, Medium Skin Tone U+200D, U+1F9D1, U+1F3FD -๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, -Skin Tone, Medium-Dark Skin Tone U+200D, U+1F9D1, U+1F3FE -๐Ÿง‘๐Ÿผโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Medium-Light U+1F9D1, U+1F3FC, U+200D, U+1F91D, -Skin Tone, Dark Skin Tone U+200D, U+1F9D1, U+1F3FF -๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, -Tone, Light Skin Tone U+200D, U+1F9D1, U+1F3FB -๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, -Tone, Medium-Light Skin Tone U+200D, U+1F9D1, U+1F3FC -๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, -Tone U+200D, U+1F9D1, U+1F3FD -๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, -Tone, Medium-Dark Skin Tone U+200D, U+1F9D1, U+1F3FE -๐Ÿง‘๐Ÿฝโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Medium Skin U+1F9D1, U+1F3FD, U+200D, U+1F91D, -Tone, Dark Skin Tone U+200D, U+1F9D1, U+1F3FF -๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, -Skin Tone, Light Skin Tone U+200D, U+1F9D1, U+1F3FB -๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, -Skin Tone, Medium-Light Skin Tone U+200D, U+1F9D1, U+1F3FC -๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, -Skin Tone, Medium Skin Tone U+200D, U+1F9D1, U+1F3FD -๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, -Skin Tone U+200D, U+1F9D1, U+1F3FE -๐Ÿง‘๐Ÿพโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Medium-Dark U+1F9D1, U+1F3FE, U+200D, U+1F91D, -Skin Tone, Dark Skin Tone U+200D, U+1F9D1, U+1F3FF -๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿป People Holding Hands: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F91D, -Tone, Light Skin Tone U+200D, U+1F9D1, U+1F3FB -๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿผ People Holding Hands: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F91D, -Tone, Medium-Light Skin Tone U+200D, U+1F9D1, U+1F3FC -๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿฝ People Holding Hands: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F91D, -Tone, Medium Skin Tone U+200D, U+1F9D1, U+1F3FD -๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿพ People Holding Hands: Dark Skin U+1F9D1, U+1F3FF, U+200D, U+1F91D, -Tone, Medium-Dark Skin Tone U+200D, U+1F9D1, U+1F3FE -๐Ÿง‘๐Ÿฟโ€๐Ÿคโ€๐Ÿง‘๐Ÿฟ People Holding Hands: Dark Skin Tone U+1F9D1, U+1F3FF, U+200D, U+1F91D, - U+200D, U+1F9D1, U+1F3FF -๐Ÿ‘ญ Women Holding Hands U+1F46D -๐Ÿ‘ญ๐Ÿป Women Holding Hands: Light Skin Tone U+1F46D, U+1F3FB -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿผ Women Holding Hands: Light Skin U+1F469, U+1F3FB, U+200D, U+1F91D, -Tone, Medium-Light Skin Tone U+200D, U+1F469, U+1F3FC -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฝ Women Holding Hands: Light Skin U+1F469, U+1F3FB, U+200D, U+1F91D, -Tone, Medium Skin Tone U+200D, U+1F469, U+1F3FD -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿพ Women Holding Hands: Light Skin U+1F469, U+1F3FB, U+200D, U+1F91D, -Tone, Medium-Dark Skin Tone U+200D, U+1F469, U+1F3FE -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฟ Women Holding Hands: Light Skin U+1F469, U+1F3FB, U+200D, U+1F91D, -Tone, Dark Skin Tone U+200D, U+1F469, U+1F3FF -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿป Women Holding Hands: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F91D, -Skin Tone, Light Skin Tone U+200D, U+1F469, U+1F3FB -๐Ÿ‘ญ๐Ÿผ Women Holding Hands: Medium-Light Skin U+1F46D, U+1F3FC -Tone -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฝ Women Holding Hands: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F91D, -Skin Tone, Medium Skin Tone U+200D, U+1F469, U+1F3FD -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿพ Women Holding Hands: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F91D, -Skin Tone, Medium-Dark Skin Tone U+200D, U+1F469, U+1F3FE -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฟ Women Holding Hands: Medium-Light U+1F469, U+1F3FC, U+200D, U+1F91D, -Skin Tone, Dark Skin Tone U+200D, U+1F469, U+1F3FF -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿป Women Holding Hands: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F91D, -Tone, Light Skin Tone U+200D, U+1F469, U+1F3FB -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿผ Women Holding Hands: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F91D, -Tone, Medium-Light Skin Tone U+200D, U+1F469, U+1F3FC -๐Ÿ‘ญ๐Ÿฝ Women Holding Hands: Medium Skin Tone U+1F46D, U+1F3FD -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿพ Women Holding Hands: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F91D, -Tone, Medium-Dark Skin Tone U+200D, U+1F469, U+1F3FE -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฟ Women Holding Hands: Medium Skin U+1F469, U+1F3FD, U+200D, U+1F91D, -Tone, Dark Skin Tone U+200D, U+1F469, U+1F3FF -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿป Women Holding Hands: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F91D, -Skin Tone, Light Skin Tone U+200D, U+1F469, U+1F3FB -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿผ Women Holding Hands: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F91D, -Skin Tone, Medium-Light Skin Tone U+200D, U+1F469, U+1F3FC -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฝ Women Holding Hands: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F91D, -Skin Tone, Medium Skin Tone U+200D, U+1F469, U+1F3FD -๐Ÿ‘ญ๐Ÿพ Women Holding Hands: Medium-Dark Skin U+1F46D, U+1F3FE -Tone -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฟ Women Holding Hands: Medium-Dark U+1F469, U+1F3FE, U+200D, U+1F91D, -Skin Tone, Dark Skin Tone U+200D, U+1F469, U+1F3FF -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿป Women Holding Hands: Dark Skin Tone, U+1F469, U+1F3FF, U+200D, U+1F91D, -Light Skin Tone U+200D, U+1F469, U+1F3FB -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿผ Women Holding Hands: Dark Skin Tone, U+1F469, U+1F3FF, U+200D, U+1F91D, -Medium-Light Skin Tone U+200D, U+1F469, U+1F3FC -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿฝ Women Holding Hands: Dark Skin Tone, U+1F469, U+1F3FF, U+200D, U+1F91D, -Medium Skin Tone U+200D, U+1F469, U+1F3FD -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿพ Women Holding Hands: Dark Skin Tone, U+1F469, U+1F3FF, U+200D, U+1F91D, -Medium-Dark Skin Tone U+200D, U+1F469, U+1F3FE -๐Ÿ‘ญ๐Ÿฟ Women Holding Hands: Dark Skin Tone U+1F46D, U+1F3FF -๐Ÿ‘ซ Woman and Man Holding Hands U+1F46B -๐Ÿ‘ซ๐Ÿป Woman and Man Holding Hands: Light Skin U+1F46B, U+1F3FB -Tone -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Woman and Man Holding Hands: Light U+1F469, U+1F3FB, U+200D, U+1F91D, -Skin Tone, Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Woman and Man Holding Hands: Light U+1F469, U+1F3FB, U+200D, U+1F91D, -Skin Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Woman and Man Holding Hands: Light U+1F469, U+1F3FB, U+200D, U+1F91D, -Skin Tone, Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE -๐Ÿ‘ฉ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Woman and Man Holding Hands: Light U+1F469, U+1F3FB, U+200D, U+1F91D, -Skin Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Woman and Man Holding Hands: U+1F469, U+1F3FC, U+200D, U+1F91D, -Medium-Light Skin Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB -๐Ÿ‘ซ๐Ÿผ Woman and Man Holding Hands: Medium-Light U+1F46B, U+1F3FC -Skin Tone -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Woman and Man Holding Hands: U+1F469, U+1F3FC, U+200D, U+1F91D, -Medium-Light Skin Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Woman and Man Holding Hands: U+1F469, U+1F3FC, U+200D, U+1F91D, -Medium-Light Skin Tone, Medium-Dark Skin U+200D, U+1F468, U+1F3FE -Tone -๐Ÿ‘ฉ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Woman and Man Holding Hands: U+1F469, U+1F3FC, U+200D, U+1F91D, -Medium-Light Skin Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Woman and Man Holding Hands: Medium U+1F469, U+1F3FD, U+200D, U+1F91D, -Skin Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Woman and Man Holding Hands: Medium U+1F469, U+1F3FD, U+200D, U+1F91D, -Skin Tone, Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC -๐Ÿ‘ซ๐Ÿฝ Woman and Man Holding Hands: Medium Skin U+1F46B, U+1F3FD -Tone -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Woman and Man Holding Hands: Medium U+1F469, U+1F3FD, U+200D, U+1F91D, -Skin Tone, Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE -๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Woman and Man Holding Hands: Medium U+1F469, U+1F3FD, U+200D, U+1F91D, -Skin Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Woman and Man Holding Hands: U+1F469, U+1F3FE, U+200D, U+1F91D, -Medium-Dark Skin Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Woman and Man Holding Hands: U+1F469, U+1F3FE, U+200D, U+1F91D, -Medium-Dark Skin Tone, Medium-Light Skin U+200D, U+1F468, U+1F3FC -Tone -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Woman and Man Holding Hands: U+1F469, U+1F3FE, U+200D, U+1F91D, -Medium-Dark Skin Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD -๐Ÿ‘ซ๐Ÿพ Woman and Man Holding Hands: Medium-Dark U+1F46B, U+1F3FE -Skin Tone -๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Woman and Man Holding Hands: U+1F469, U+1F3FE, U+200D, U+1F91D, -Medium-Dark Skin Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Woman and Man Holding Hands: Dark U+1F469, U+1F3FF, U+200D, U+1F91D, -Skin Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Woman and Man Holding Hands: Dark U+1F469, U+1F3FF, U+200D, U+1F91D, -Skin Tone, Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Woman and Man Holding Hands: Dark U+1F469, U+1F3FF, U+200D, U+1F91D, -Skin Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD -๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Woman and Man Holding Hands: Dark U+1F469, U+1F3FF, U+200D, U+1F91D, -Skin Tone, Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE -๐Ÿ‘ซ๐Ÿฟ Woman and Man Holding Hands: Dark Skin U+1F46B, U+1F3FF -Tone -๐Ÿ‘ฌ Men Holding Hands U+1F46C -๐Ÿ‘ฌ๐Ÿป Men Holding Hands: Light Skin Tone U+1F46C, U+1F3FB -๐Ÿ‘จ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Men Holding Hands: Light Skin Tone, U+1F468, U+1F3FB, U+200D, U+1F91D, -Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC -๐Ÿ‘จ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Men Holding Hands: Light Skin Tone, U+1F468, U+1F3FB, U+200D, U+1F91D, -Medium Skin Tone U+200D, U+1F468, U+1F3FD -๐Ÿ‘จ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Men Holding Hands: Light Skin Tone, U+1F468, U+1F3FB, U+200D, U+1F91D, -Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE -๐Ÿ‘จ๐Ÿปโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Men Holding Hands: Light Skin Tone, U+1F468, U+1F3FB, U+200D, U+1F91D, -Dark Skin Tone U+200D, U+1F468, U+1F3FF -๐Ÿ‘จ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Men Holding Hands: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F91D, -Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB -๐Ÿ‘ฌ๐Ÿผ Men Holding Hands: Medium-Light Skin Tone U+1F46C, U+1F3FC -๐Ÿ‘จ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Men Holding Hands: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F91D, -Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD -๐Ÿ‘จ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Men Holding Hands: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F91D, -Tone, Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE -๐Ÿ‘จ๐Ÿผโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Men Holding Hands: Medium-Light Skin U+1F468, U+1F3FC, U+200D, U+1F91D, -Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF -๐Ÿ‘จ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Men Holding Hands: Medium Skin Tone, U+1F468, U+1F3FD, U+200D, U+1F91D, -Light Skin Tone U+200D, U+1F468, U+1F3FB -๐Ÿ‘จ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Men Holding Hands: Medium Skin Tone, U+1F468, U+1F3FD, U+200D, U+1F91D, -Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC -๐Ÿ‘ฌ๐Ÿฝ Men Holding Hands: Medium Skin Tone U+1F46C, U+1F3FD -๐Ÿ‘จ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Men Holding Hands: Medium Skin Tone, U+1F468, U+1F3FD, U+200D, U+1F91D, -Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE -๐Ÿ‘จ๐Ÿฝโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Men Holding Hands: Medium Skin Tone, U+1F468, U+1F3FD, U+200D, U+1F91D, -Dark Skin Tone U+200D, U+1F468, U+1F3FF -๐Ÿ‘จ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Men Holding Hands: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F91D, -Tone, Light Skin Tone U+200D, U+1F468, U+1F3FB -๐Ÿ‘จ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Men Holding Hands: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F91D, -Tone, Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC -๐Ÿ‘จ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Men Holding Hands: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F91D, -Tone, Medium Skin Tone U+200D, U+1F468, U+1F3FD -๐Ÿ‘ฌ๐Ÿพ Men Holding Hands: Medium-Dark Skin Tone U+1F46C, U+1F3FE -๐Ÿ‘จ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฟ Men Holding Hands: Medium-Dark Skin U+1F468, U+1F3FE, U+200D, U+1F91D, -Tone, Dark Skin Tone U+200D, U+1F468, U+1F3FF -๐Ÿ‘จ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿป Men Holding Hands: Dark Skin Tone, U+1F468, U+1F3FF, U+200D, U+1F91D, -Light Skin Tone U+200D, U+1F468, U+1F3FB -๐Ÿ‘จ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿผ Men Holding Hands: Dark Skin Tone, U+1F468, U+1F3FF, U+200D, U+1F91D, -Medium-Light Skin Tone U+200D, U+1F468, U+1F3FC -๐Ÿ‘จ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿฝ Men Holding Hands: Dark Skin Tone, U+1F468, U+1F3FF, U+200D, U+1F91D, -Medium Skin Tone U+200D, U+1F468, U+1F3FD -๐Ÿ‘จ๐Ÿฟโ€๐Ÿคโ€๐Ÿ‘จ๐Ÿพ Men Holding Hands: Dark Skin Tone, U+1F468, U+1F3FF, U+200D, U+1F91D, -Medium-Dark Skin Tone U+200D, U+1F468, U+1F3FE -๐Ÿ‘ฌ๐Ÿฟ Men Holding Hands: Dark Skin Tone U+1F46C, U+1F3FF -๐Ÿ’ Kiss U+1F48F -๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ Kiss: Woman, Man U+1F469, U+200D, U+2764, U+FE0F, - U+200D, U+1F48B, U+200D, U+1F468 -๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ Kiss: Man, Man U+1F468, U+200D, U+2764, U+FE0F, - U+200D, U+1F48B, U+200D, U+1F468 -๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ Kiss: Woman, Woman U+1F469, U+200D, U+2764, U+FE0F, - U+200D, U+1F48B, U+200D, U+1F469 -๐Ÿ’‘ Couple with Heart U+1F491 -๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘จ Couple with Heart: Woman, Man U+1F469, U+200D, U+2764, U+FE0F, - U+200D, U+1F468 -๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ Couple with Heart: Man, Man U+1F468, U+200D, U+2764, U+FE0F, - U+200D, U+1F468 -๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ Couple with Heart: Woman, Woman U+1F469, U+200D, U+2764, U+FE0F, - U+200D, U+1F469 -๐Ÿ‘ช Family U+1F46A -๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ Family: Man, Woman, Boy U+1F468, U+200D, U+1F469, U+200D, - U+1F466 -๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง Family: Man, Woman, Girl U+1F468, U+200D, U+1F469, U+200D, - U+1F467 -๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Man, Woman, Girl, Boy U+1F468, U+200D, U+1F469, U+200D, - U+1F467, U+200D, U+1F466 -๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Man, Woman, Boy, Boy U+1F468, U+200D, U+1F469, U+200D, - U+1F466, U+200D, U+1F466 -๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Man, Woman, Girl, Girl U+1F468, U+200D, U+1F469, U+200D, - U+1F467, U+200D, U+1F467 -๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ Family: Man, Man, Boy U+1F468, U+200D, U+1F468, U+200D, - U+1F466 -๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง Family: Man, Man, Girl U+1F468, U+200D, U+1F468, U+200D, - U+1F467 -๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Man, Man, Girl, Boy U+1F468, U+200D, U+1F468, U+200D, - U+1F467, U+200D, U+1F466 -๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Man, Man, Boy, Boy U+1F468, U+200D, U+1F468, U+200D, - U+1F466, U+200D, U+1F466 -๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Man, Man, Girl, Girl U+1F468, U+200D, U+1F468, U+200D, - U+1F467, U+200D, U+1F467 -๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ Family: Woman, Woman, Boy U+1F469, U+200D, U+1F469, U+200D, - U+1F466 -๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง Family: Woman, Woman, Girl U+1F469, U+200D, U+1F469, U+200D, - U+1F467 -๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Woman, Woman, Girl, Boy U+1F469, U+200D, U+1F469, U+200D, - U+1F467, U+200D, U+1F466 -๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Woman, Woman, Boy, Boy U+1F469, U+200D, U+1F469, U+200D, - U+1F466, U+200D, U+1F466 -๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Woman, Woman, Girl, Girl U+1F469, U+200D, U+1F469, U+200D, - U+1F467, U+200D, U+1F467 -๐Ÿ‘จโ€๐Ÿ‘ฆ Family: Man, Boy U+1F468, U+200D, U+1F466 -๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Man, Boy, Boy U+1F468, U+200D, U+1F466, U+200D, - U+1F466 -๐Ÿ‘จโ€๐Ÿ‘ง Family: Man, Girl U+1F468, U+200D, U+1F467 -๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Man, Girl, Boy U+1F468, U+200D, U+1F467, U+200D, - U+1F466 -๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Man, Girl, Girl U+1F468, U+200D, U+1F467, U+200D, - U+1F467 -๐Ÿ‘ฉโ€๐Ÿ‘ฆ Family: Woman, Boy U+1F469, U+200D, U+1F466 -๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ Family: Woman, Boy, Boy U+1F469, U+200D, U+1F466, U+200D, - U+1F466 -๐Ÿ‘ฉโ€๐Ÿ‘ง Family: Woman, Girl U+1F469, U+200D, U+1F467 -๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Family: Woman, Girl, Boy U+1F469, U+200D, U+1F467, U+200D, - U+1F466 -๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง Family: Woman, Girl, Girl U+1F469, U+200D, U+1F467, U+200D, - U+1F467 -๐Ÿ—ฃ๏ธ Speaking Head U+1F5E3, U+FE0F -๐Ÿ‘ค Bust in Silhouette U+1F464 -๐Ÿ‘ฅ Busts in Silhouette U+1F465 -๐Ÿซ‚ People Hugging U+1FAC2 -๐Ÿ‘ฃ Footprints U+1F463 -๐Ÿป Light Skin Tone U+1F3FB -๐Ÿผ Medium-Light Skin Tone U+1F3FC -๐Ÿฝ Medium Skin Tone U+1F3FD -๐Ÿพ Medium-Dark Skin Tone U+1F3FE -๐Ÿฟ Dark Skin Tone U+1F3FF -๐Ÿฆฐ Red Hair U+1F9B0 -๐Ÿฆฑ Curly Hair U+1F9B1 -๐Ÿฆณ White Hair U+1F9B3 -๐Ÿฆฒ Bald U+1F9B2 -๐Ÿต Monkey Face U+1F435 -๐Ÿ’ Monkey U+1F412 -๐Ÿฆ Gorilla U+1F98D -๐Ÿฆง Orangutan U+1F9A7 -๐Ÿถ Dog Face U+1F436 -๐Ÿ• Dog U+1F415 -๐Ÿฆฎ Guide Dog U+1F9AE -๐Ÿ•โ€๐Ÿฆบ Service Dog U+1F415, U+200D, U+1F9BA -๐Ÿฉ Poodle U+1F429 -๐Ÿบ Wolf U+1F43A -๐ŸฆŠ Fox U+1F98A -๐Ÿฆ Raccoon U+1F99D -๐Ÿฑ Cat Face U+1F431 -๐Ÿˆ Cat U+1F408 -๐Ÿˆโ€โฌ› Black Cat U+1F408, U+200D, U+2B1B -๐Ÿฆ Lion U+1F981 -๐Ÿฏ Tiger Face U+1F42F -๐Ÿ… Tiger U+1F405 -๐Ÿ† Leopard U+1F406 -๐Ÿด Horse Face U+1F434 -๐ŸŽ Horse U+1F40E -๐Ÿฆ„ Unicorn U+1F984 -๐Ÿฆ“ Zebra U+1F993 -๐ŸฆŒ Deer U+1F98C -๐Ÿฆฌ Bison U+1F9AC -๐Ÿฎ Cow Face U+1F42E -๐Ÿ‚ Ox U+1F402 -๐Ÿƒ Water Buffalo U+1F403 -๐Ÿ„ Cow U+1F404 -๐Ÿท Pig Face U+1F437 -๐Ÿ– Pig U+1F416 -๐Ÿ— Boar U+1F417 -๐Ÿฝ Pig Nose U+1F43D -๐Ÿ Ram U+1F40F -๐Ÿ‘ Ewe U+1F411 -๐Ÿ Goat U+1F410 -๐Ÿช Camel U+1F42A -๐Ÿซ Two-Hump Camel U+1F42B -๐Ÿฆ™ Llama U+1F999 -๐Ÿฆ’ Giraffe U+1F992 -๐Ÿ˜ Elephant U+1F418 -๐Ÿฆฃ Mammoth U+1F9A3 -๐Ÿฆ Rhinoceros U+1F98F -๐Ÿฆ› Hippopotamus U+1F99B -๐Ÿญ Mouse Face U+1F42D -๐Ÿ Mouse U+1F401 -๐Ÿ€ Rat U+1F400 -๐Ÿน Hamster U+1F439 -๐Ÿฐ Rabbit Face U+1F430 -๐Ÿ‡ Rabbit U+1F407 -๐Ÿฟ๏ธ Chipmunk U+1F43F, U+FE0F -๐Ÿฆซ Beaver U+1F9AB -๐Ÿฆ” Hedgehog U+1F994 -๐Ÿฆ‡ Bat U+1F987 -๐Ÿป Bear U+1F43B -๐Ÿปโ€โ„๏ธ Polar Bear U+1F43B, U+200D, U+2744, U+FE0F -๐Ÿจ Koala U+1F428 -๐Ÿผ Panda U+1F43C -๐Ÿฆฅ Sloth U+1F9A5 -๐Ÿฆฆ Otter U+1F9A6 -๐Ÿฆจ Skunk U+1F9A8 -๐Ÿฆ˜ Kangaroo U+1F998 -๐Ÿฆก Badger U+1F9A1 -๐Ÿพ Paw Prints U+1F43E -๐Ÿฆƒ Turkey U+1F983 -๐Ÿ” Chicken U+1F414 -๐Ÿ“ Rooster U+1F413 -๐Ÿฃ Hatching Chick U+1F423 -๐Ÿค Baby Chick U+1F424 -๐Ÿฅ Front-Facing Baby Chick U+1F425 -๐Ÿฆ Bird U+1F426 -๐Ÿง Penguin U+1F427 -๐Ÿ•Š๏ธ Dove U+1F54A, U+FE0F -๐Ÿฆ… Eagle U+1F985 -๐Ÿฆ† Duck U+1F986 -๐Ÿฆข Swan U+1F9A2 -๐Ÿฆ‰ Owl U+1F989 -๐Ÿฆค Dodo U+1F9A4 -๐Ÿชถ Feather U+1FAB6 -๐Ÿฆฉ Flamingo U+1F9A9 -๐Ÿฆš Peacock U+1F99A -๐Ÿฆœ Parrot U+1F99C -๐Ÿธ Frog U+1F438 -๐ŸŠ Crocodile U+1F40A -๐Ÿข Turtle U+1F422 -๐ŸฆŽ Lizard U+1F98E -๐Ÿ Snake U+1F40D -๐Ÿฒ Dragon Face U+1F432 -๐Ÿ‰ Dragon U+1F409 -๐Ÿฆ• Sauropod U+1F995 -๐Ÿฆ– T-Rex U+1F996 -๐Ÿณ Spouting Whale U+1F433 -๐Ÿ‹ Whale U+1F40B -๐Ÿฌ Dolphin U+1F42C -๐Ÿฆญ Seal U+1F9AD -๐ŸŸ Fish U+1F41F -๐Ÿ  Tropical Fish U+1F420 -๐Ÿก Blowfish U+1F421 -๐Ÿฆˆ Shark U+1F988 -๐Ÿ™ Octopus U+1F419 -๐Ÿš Spiral Shell U+1F41A -๐ŸŒ Snail U+1F40C -๐Ÿฆ‹ Butterfly U+1F98B -๐Ÿ› Bug U+1F41B -๐Ÿœ Ant U+1F41C -๐Ÿ Honeybee U+1F41D -๐Ÿชฒ Beetle U+1FAB2 -๐Ÿž Lady Beetle U+1F41E -๐Ÿฆ— Cricket U+1F997 -๐Ÿชณ Cockroach U+1FAB3 -๐Ÿ•ท๏ธ Spider U+1F577, U+FE0F -๐Ÿ•ธ๏ธ Spider Web U+1F578, U+FE0F -๐Ÿฆ‚ Scorpion U+1F982 -๐ŸฆŸ Mosquito U+1F99F -๐Ÿชฐ Fly U+1FAB0 -๐Ÿชฑ Worm U+1FAB1 -๐Ÿฆ  Microbe U+1F9A0 -๐Ÿ’ Bouquet U+1F490 -๐ŸŒธ Cherry Blossom U+1F338 -๐Ÿ’ฎ White Flower U+1F4AE -๐Ÿต๏ธ Rosette U+1F3F5, U+FE0F -๐ŸŒน Rose U+1F339 -๐Ÿฅ€ Wilted Flower U+1F940 -๐ŸŒบ Hibiscus U+1F33A -๐ŸŒป Sunflower U+1F33B -๐ŸŒผ Blossom U+1F33C -๐ŸŒท Tulip U+1F337 -๐ŸŒฑ Seedling U+1F331 -๐Ÿชด Potted Plant U+1FAB4 -๐ŸŒฒ Evergreen Tree U+1F332 -๐ŸŒณ Deciduous Tree U+1F333 -๐ŸŒด Palm Tree U+1F334 -๐ŸŒต Cactus U+1F335 -๐ŸŒพ Sheaf of Rice U+1F33E -๐ŸŒฟ Herb U+1F33F -โ˜˜๏ธ Shamrock U+2618, U+FE0F -๐Ÿ€ Four Leaf Clover U+1F340 -๐Ÿ Maple Leaf U+1F341 -๐Ÿ‚ Fallen Leaf U+1F342 -๐Ÿƒ Leaf Fluttering in Wind U+1F343 -๐Ÿ‡ Grapes U+1F347 -๐Ÿˆ Melon U+1F348 -๐Ÿ‰ Watermelon U+1F349 -๐ŸŠ Tangerine U+1F34A -๐Ÿ‹ Lemon U+1F34B -๐ŸŒ Banana U+1F34C -๐Ÿ Pineapple U+1F34D -๐Ÿฅญ Mango U+1F96D -๐ŸŽ Red Apple U+1F34E -๐Ÿ Green Apple U+1F34F -๐Ÿ Pear U+1F350 -๐Ÿคผ๐Ÿป Wrestlers, Type-1-2 U+1F93C, U+1F3FB -๐Ÿ‘ Peach U+1F351 -๐Ÿคผ๐Ÿผ Wrestlers, Type-3 U+1F93C, U+1F3FC -๐Ÿ’ Cherries U+1F352 -๐Ÿคผ๐Ÿฝ Wrestlers, Type-4 U+1F93C, U+1F3FD -๐Ÿ“ Strawberry U+1F353 -๐Ÿคผ๐Ÿพ Wrestlers, Type-5 U+1F93C, U+1F3FE -๐Ÿซ Blueberries U+1FAD0 -๐Ÿคผ๐Ÿฟ Wrestlers, Type-6 U+1F93C, U+1F3FF -๐Ÿฅ Kiwi Fruit U+1F95D -๐Ÿ… Tomato U+1F345 -๐Ÿคผ๐Ÿปโ€โ™‚๏ธ Men Wrestling, Type-1-2 U+1F93C, U+1F3FB, U+200D, U+2642, - U+FE0F -๐Ÿซ’ Olive U+1FAD2 -๐Ÿฅฅ Coconut U+1F965 -๐Ÿฅ‘ Avocado U+1F951 -๐Ÿคผ๐Ÿผโ€โ™‚๏ธ Men Wrestling, Type-3 U+1F93C, U+1F3FC, U+200D, U+2642, - U+FE0F -๐Ÿ† Eggplant U+1F346 -๐Ÿฅ” Potato U+1F954 -๐Ÿคผ๐Ÿฝโ€โ™‚๏ธ Men Wrestling, Type-4 U+1F93C, U+1F3FD, U+200D, U+2642, - U+FE0F -๐Ÿฅ• Carrot U+1F955 -๐Ÿคผ๐Ÿพโ€โ™‚๏ธ Men Wrestling, Type-5 U+1F93C, U+1F3FE, U+200D, U+2642, - U+FE0F -๐ŸŒฝ Ear of Corn U+1F33D -๐ŸŒถ๏ธ Hot Pepper U+1F336, U+FE0F -๐Ÿซ‘ Bell Pepper U+1FAD1 -๐Ÿคผ๐Ÿฟโ€โ™‚๏ธ Men Wrestling, Type-6 U+1F93C, U+1F3FF, U+200D, U+2642, - U+FE0F -๐Ÿฅ’ Cucumber U+1F952 -๐Ÿฅฌ Leafy Green U+1F96C -๐Ÿฅฆ Broccoli U+1F966 -๐Ÿคผ๐Ÿปโ€โ™€๏ธ Women Wrestling, Type-1-2 U+1F93C, U+1F3FB, U+200D, U+2640, - U+FE0F -๐Ÿง„ Garlic U+1F9C4 -๐Ÿง… Onion U+1F9C5 -๐Ÿ„ Mushroom U+1F344 -๐Ÿคผ๐Ÿผโ€โ™€๏ธ Women Wrestling, Type-3 U+1F93C, U+1F3FC, U+200D, U+2640, - U+FE0F -๐Ÿฅœ Peanuts U+1F95C -๐ŸŒฐ Chestnut U+1F330 -๐Ÿคผ๐Ÿฝโ€โ™€๏ธ Women Wrestling, Type-4 U+1F93C, U+1F3FD, U+200D, U+2640, - U+FE0F -๐Ÿž Bread U+1F35E -๐Ÿฅ Croissant U+1F950 -๐Ÿคผ๐Ÿพโ€โ™€๏ธ Women Wrestling, Type-5 U+1F93C, U+1F3FE, U+200D, U+2640, - U+FE0F -๐Ÿฅ– Baguette Bread U+1F956 -๐Ÿซ“ Flatbread U+1FAD3 -๐Ÿคผ๐Ÿฟโ€โ™€๏ธ Women Wrestling, Type-6 U+1F93C, U+1F3FF, U+200D, U+2640, - U+FE0F -๐Ÿฅจ Pretzel U+1F968 -๐Ÿฅฏ Bagel U+1F96F -๐Ÿฅž Pancakes U+1F95E -๐Ÿง‡ Waffle U+1F9C7 -๐Ÿง€ Cheese Wedge U+1F9C0 -๐Ÿ– Meat on Bone U+1F356 -๐Ÿ— Poultry Leg U+1F357 -๐Ÿฅฉ Cut of Meat U+1F969 -๐Ÿฅ“ Bacon U+1F953 -๐Ÿ” Hamburger U+1F354 -๐ŸŸ French Fries U+1F35F -๐Ÿ• Pizza U+1F355 -๐ŸŒญ Hot Dog U+1F32D -๐Ÿฅช Sandwich U+1F96A -๐ŸŒฎ Taco U+1F32E -๐ŸŒฏ Burrito U+1F32F -๐Ÿซ” Tamale U+1FAD4 -๐Ÿฅ™ Stuffed Flatbread U+1F959 -๐Ÿง† Falafel U+1F9C6 -๐Ÿฅš Egg U+1F95A -๐Ÿณ Cooking U+1F373 -๐Ÿฅ˜ Shallow Pan of Food U+1F958 -๐Ÿฒ Pot of Food U+1F372 -๐Ÿซ• Fondue U+1FAD5 -๐Ÿฅฃ Bowl with Spoon U+1F963 -๐Ÿฅ— Green Salad U+1F957 -๐Ÿฟ Popcorn U+1F37F -๐Ÿงˆ Butter U+1F9C8 -๐Ÿง‚ Salt U+1F9C2 -๐Ÿฅซ Canned Food U+1F96B -๐Ÿฑ Bento Box U+1F371 -๐Ÿ˜ Rice Cracker U+1F358 -๐Ÿ™ Rice Ball U+1F359 -๐Ÿš Cooked Rice U+1F35A -๐Ÿ› Curry Rice U+1F35B -๐Ÿœ Steaming Bowl U+1F35C -๐Ÿ Spaghetti U+1F35D -๐Ÿ  Roasted Sweet Potato U+1F360 -๐Ÿข Oden U+1F362 -๐Ÿฃ Sushi U+1F363 -๐Ÿค Fried Shrimp U+1F364 -๐Ÿฅ Fish Cake with Swirl U+1F365 -๐Ÿฅฎ Moon Cake U+1F96E -๐Ÿก Dango U+1F361 -๐ŸฅŸ Dumpling U+1F95F -๐Ÿฅ  Fortune Cookie U+1F960 -๐Ÿฅก Takeout Box U+1F961 -๐Ÿฆ€ Crab U+1F980 -๐Ÿฆž Lobster U+1F99E -๐Ÿฆ Shrimp U+1F990 -๐Ÿฆ‘ Squid U+1F991 -๐Ÿฆช Oyster U+1F9AA -๐Ÿฆ Soft Ice Cream U+1F366 -๐Ÿง Shaved Ice U+1F367 -๐Ÿจ Ice Cream U+1F368 -๐Ÿฉ Doughnut U+1F369 -๐Ÿช Cookie U+1F36A -๐ŸŽ‚ Birthday Cake U+1F382 -๐Ÿฐ Shortcake U+1F370 -๐Ÿง Cupcake U+1F9C1 -๐Ÿฅง Pie U+1F967 -๐Ÿซ Chocolate Bar U+1F36B -๐Ÿฌ Candy U+1F36C -๐Ÿญ Lollipop U+1F36D -๐Ÿฎ Custard U+1F36E -๐Ÿฏ Honey Pot U+1F36F -๐Ÿผ Baby Bottle U+1F37C -๐Ÿฅ› Glass of Milk U+1F95B -โ˜• Hot Beverage U+2615 -๐Ÿซ– Teapot U+1FAD6 -๐Ÿต Teacup Without Handle U+1F375 -๐Ÿถ Sake U+1F376 -๐Ÿพ Bottle with Popping Cork U+1F37E -๐Ÿท Wine Glass U+1F377 -๐Ÿธ Cocktail Glass U+1F378 -๐Ÿน Tropical Drink U+1F379 -๐Ÿบ Beer Mug U+1F37A -๐Ÿป Clinking Beer Mugs U+1F37B -๐Ÿฅ‚ Clinking Glasses U+1F942 -๐Ÿฅƒ Tumbler Glass U+1F943 -๐Ÿฅค Cup with Straw U+1F964 -๐Ÿง‹ Bubble Tea U+1F9CB -๐Ÿงƒ Beverage Box U+1F9C3 -๐Ÿง‰ Mate U+1F9C9 -๐ŸงŠ Ice U+1F9CA -๐Ÿฅข Chopsticks U+1F962 -๐Ÿฝ๏ธ Fork and Knife with Plate U+1F37D, U+FE0F -๐Ÿด Fork and Knife U+1F374 -๐Ÿฅ„ Spoon U+1F944 -๐Ÿ”ช Kitchen Knife U+1F52A -๐Ÿบ Amphora U+1F3FA -๐ŸŒ Globe Showing Europe-Africa U+1F30D -๐ŸŒŽ Globe Showing Americas U+1F30E -๐ŸŒ Globe Showing Asia-Australia U+1F30F -๐ŸŒ Globe with Meridians U+1F310 -๐Ÿ—บ๏ธ World Map U+1F5FA, U+FE0F -๐Ÿ—พ Map of Japan U+1F5FE -๐Ÿงญ Compass U+1F9ED -๐Ÿ”๏ธ Snow-Capped Mountain U+1F3D4, U+FE0F -โ›ฐ๏ธ Mountain U+26F0, U+FE0F -๐ŸŒ‹ Volcano U+1F30B -๐Ÿ—ป Mount Fuji U+1F5FB -๐Ÿ•๏ธ Camping U+1F3D5, U+FE0F -๐Ÿ–๏ธ Beach with Umbrella U+1F3D6, U+FE0F -๐Ÿœ๏ธ Desert U+1F3DC, U+FE0F -๐Ÿ๏ธ Desert Island U+1F3DD, U+FE0F -๐Ÿž๏ธ National Park U+1F3DE, U+FE0F -๐ŸŸ๏ธ Stadium U+1F3DF, U+FE0F -๐Ÿ›๏ธ Classical Building U+1F3DB, U+FE0F -๐Ÿ—๏ธ Building Construction U+1F3D7, U+FE0F -๐Ÿงฑ Brick U+1F9F1 -๐Ÿชจ Rock U+1FAA8 -๐Ÿชต Wood U+1FAB5 -๐Ÿ›– Hut U+1F6D6 -๐Ÿ˜๏ธ Houses U+1F3D8, U+FE0F -๐Ÿš๏ธ Derelict House U+1F3DA, U+FE0F -๐Ÿ  House U+1F3E0 -๐Ÿก House with Garden U+1F3E1 -๐Ÿข Office Building U+1F3E2 -๐Ÿฃ Japanese Post Office U+1F3E3 -๐Ÿค Post Office U+1F3E4 -๐Ÿฅ Hospital U+1F3E5 -๐Ÿฆ Bank U+1F3E6 -๐Ÿจ Hotel U+1F3E8 -๐Ÿฉ Love Hotel U+1F3E9 -๐Ÿช Convenience Store U+1F3EA -๐Ÿซ School U+1F3EB -๐Ÿฌ Department Store U+1F3EC -๐Ÿญ Factory U+1F3ED -๐Ÿฏ Japanese Castle U+1F3EF -๐Ÿฐ Castle U+1F3F0 -๐Ÿ’’ Wedding U+1F492 -๐Ÿ—ผ Tokyo Tower U+1F5FC -๐Ÿ—ฝ Statue of Liberty U+1F5FD -โ›ช Church U+26EA -๐Ÿ•Œ Mosque U+1F54C -๐Ÿ›• Hindu Temple U+1F6D5 -๐Ÿ• Synagogue U+1F54D -โ›ฉ๏ธ Shinto Shrine U+26E9, U+FE0F -๐Ÿ•‹ Kaaba U+1F54B -โ›ฒ Fountain U+26F2 -โ›บ Tent U+26FA -๐ŸŒ Foggy U+1F301 -๐ŸŒƒ Night with Stars U+1F303 -๐Ÿ™๏ธ Cityscape U+1F3D9, U+FE0F -๐ŸŒ„ Sunrise Over Mountains U+1F304 -๐ŸŒ… Sunrise U+1F305 -๐ŸŒ† Cityscape at Dusk U+1F306 -๐ŸŒ‡ Sunset U+1F307 -๐ŸŒ‰ Bridge at Night U+1F309 -โ™จ๏ธ Hot Springs U+2668, U+FE0F -๐ŸŽ  Carousel Horse U+1F3A0 -๐ŸŽก Ferris Wheel U+1F3A1 -๐ŸŽข Roller Coaster U+1F3A2 -๐Ÿ’ˆ Barber Pole U+1F488 -๐ŸŽช Circus Tent U+1F3AA -๐Ÿš‚ Locomotive U+1F682 -๐Ÿšƒ Railway Car U+1F683 -๐Ÿš„ High-Speed Train U+1F684 -๐Ÿš… Bullet Train U+1F685 -๐Ÿš† Train U+1F686 -๐Ÿš‡ Metro U+1F687 -๐Ÿšˆ Light Rail U+1F688 -๐Ÿš‰ Station U+1F689 -๐ŸšŠ Tram U+1F68A -๐Ÿš Monorail U+1F69D -๐Ÿšž Mountain Railway U+1F69E -๐Ÿš‹ Tram Car U+1F68B -๐ŸšŒ Bus U+1F68C -๐Ÿš Oncoming Bus U+1F68D -๐ŸšŽ Trolleybus U+1F68E -๐Ÿš Minibus U+1F690 -๐Ÿš‘ Ambulance U+1F691 -๐Ÿš’ Fire Engine U+1F692 -๐Ÿš“ Police Car U+1F693 -๐Ÿš” Oncoming Police Car U+1F694 -๐Ÿš• Taxi U+1F695 -๐Ÿš– Oncoming Taxi U+1F696 -๐Ÿš— Automobile U+1F697 -๐Ÿš˜ Oncoming Automobile U+1F698 -๐Ÿš™ Sport Utility Vehicle U+1F699 -๐Ÿ›ป Pickup Truck U+1F6FB -๐Ÿšš Delivery Truck U+1F69A -๐Ÿš› Articulated Lorry U+1F69B -๐Ÿšœ Tractor U+1F69C -๐ŸŽ๏ธ Racing Car U+1F3CE, U+FE0F -๐Ÿ๏ธ Motorcycle U+1F3CD, U+FE0F -๐Ÿ›ต Motor Scooter U+1F6F5 -๐Ÿฆฝ Manual Wheelchair U+1F9BD -๐Ÿฆผ Motorized Wheelchair U+1F9BC -๐Ÿ›บ Auto Rickshaw U+1F6FA -๐Ÿšฒ Bicycle U+1F6B2 -๐Ÿ›ด Kick Scooter U+1F6F4 -๐Ÿ›น Skateboard U+1F6F9 -๐Ÿ›ผ Roller Skate U+1F6FC -๐Ÿš Bus Stop U+1F68F -๐Ÿ›ฃ๏ธ Motorway U+1F6E3, U+FE0F -๐Ÿ›ค๏ธ Railway Track U+1F6E4, U+FE0F -๐Ÿ›ข๏ธ Oil Drum U+1F6E2, U+FE0F -โ›ฝ Fuel Pump U+26FD -๐Ÿšจ Police Car Light U+1F6A8 -๐Ÿšฅ Horizontal Traffic Light U+1F6A5 -๐Ÿšฆ Vertical Traffic Light U+1F6A6 -๐Ÿ›‘ Stop Sign U+1F6D1 -๐Ÿšง Construction U+1F6A7 -โš“ Anchor U+2693 -โ›ต Sailboat U+26F5 -๐Ÿ›ถ Canoe U+1F6F6 -๐Ÿšค Speedboat U+1F6A4 -๐Ÿ›ณ๏ธ Passenger Ship U+1F6F3, U+FE0F -โ›ด๏ธ Ferry U+26F4, U+FE0F -๐Ÿ›ฅ๏ธ Motor Boat U+1F6E5, U+FE0F -๐Ÿšข Ship U+1F6A2 -โœˆ๏ธ Airplane U+2708, U+FE0F -๐Ÿ›ฉ๏ธ Small Airplane U+1F6E9, U+FE0F -๐Ÿ›ซ Airplane Departure U+1F6EB -๐Ÿ›ฌ Airplane Arrival U+1F6EC -๐Ÿช‚ Parachute U+1FA82 -๐Ÿ’บ Seat U+1F4BA -๐Ÿš Helicopter U+1F681 -๐ŸšŸ Suspension Railway U+1F69F -๐Ÿš  Mountain Cableway U+1F6A0 -๐Ÿšก Aerial Tramway U+1F6A1 -๐Ÿ›ฐ๏ธ Satellite U+1F6F0, U+FE0F -๐Ÿš€ Rocket U+1F680 -๐Ÿ›ธ Flying Saucer U+1F6F8 -๐Ÿ›Ž๏ธ Bellhop Bell U+1F6CE, U+FE0F -๐Ÿงณ Luggage U+1F9F3 -โŒ› Hourglass Done U+231B -โณ Hourglass Not Done U+23F3 -โŒš Watch U+231A -โฐ Alarm Clock U+23F0 -โฑ๏ธ Stopwatch U+23F1, U+FE0F -โฒ๏ธ Timer Clock U+23F2, U+FE0F -๐Ÿ•ฐ๏ธ Mantelpiece Clock U+1F570, U+FE0F -๐Ÿ•› Twelve Oโ€™Clock U+1F55B -๐Ÿ•ง Twelve-Thirty U+1F567 -๐Ÿ• One Oโ€™Clock U+1F550 -๐Ÿ•œ One-Thirty U+1F55C -๐Ÿ•‘ Two Oโ€™Clock U+1F551 -๐Ÿ• Two-Thirty U+1F55D -๐Ÿ•’ Three Oโ€™Clock U+1F552 -๐Ÿ•ž Three-Thirty U+1F55E -๐Ÿ•“ Four Oโ€™Clock U+1F553 -๐Ÿ•Ÿ Four-Thirty U+1F55F -๐Ÿ•” Five Oโ€™Clock U+1F554 -๐Ÿ•  Five-Thirty U+1F560 -๐Ÿ•• Six Oโ€™Clock U+1F555 -๐Ÿ•ก Six-Thirty U+1F561 -๐Ÿ•– Seven Oโ€™Clock U+1F556 -๐Ÿ•ข Seven-Thirty U+1F562 -๐Ÿ•— Eight Oโ€™Clock U+1F557 -๐Ÿ•ฃ Eight-Thirty U+1F563 -๐Ÿ•˜ Nine Oโ€™Clock U+1F558 -๐Ÿ•ค Nine-Thirty U+1F564 -๐Ÿ•™ Ten Oโ€™Clock U+1F559 -๐Ÿ•ฅ Ten-Thirty U+1F565 -๐Ÿ•š Eleven Oโ€™Clock U+1F55A -๐Ÿ•ฆ Eleven-Thirty U+1F566 -๐ŸŒ‘ New Moon U+1F311 -๐ŸŒ’ Waxing Crescent Moon U+1F312 -๐ŸŒ“ First Quarter Moon U+1F313 -๐ŸŒ” Waxing Gibbous Moon U+1F314 -๐ŸŒ• Full Moon U+1F315 -๐ŸŒ– Waning Gibbous Moon U+1F316 -๐ŸŒ— Last Quarter Moon U+1F317 -๐ŸŒ˜ Waning Crescent Moon U+1F318 -๐ŸŒ™ Crescent Moon U+1F319 -๐ŸŒš New Moon Face U+1F31A -๐ŸŒ› First Quarter Moon Face U+1F31B -๐ŸŒœ Last Quarter Moon Face U+1F31C -๐ŸŒก๏ธ Thermometer U+1F321, U+FE0F -โ˜€๏ธ Sun U+2600, U+FE0F -๐ŸŒ Full Moon Face U+1F31D -๐ŸŒž Sun with Face U+1F31E -๐Ÿช Ringed Planet U+1FA90 -โญ Star U+2B50 -๐ŸŒŸ Glowing Star U+1F31F -๐ŸŒ  Shooting Star U+1F320 -๐ŸŒŒ Milky Way U+1F30C -โ˜๏ธ Cloud U+2601, U+FE0F -โ›… Sun Behind Cloud U+26C5 -โ›ˆ๏ธ Cloud with Lightning and Rain U+26C8, U+FE0F -๐ŸŒค๏ธ Sun Behind Small Cloud U+1F324, U+FE0F -๐ŸŒฅ๏ธ Sun Behind Large Cloud U+1F325, U+FE0F -๐ŸŒฆ๏ธ Sun Behind Rain Cloud U+1F326, U+FE0F -๐ŸŒง๏ธ Cloud with Rain U+1F327, U+FE0F -๐ŸŒจ๏ธ Cloud with Snow U+1F328, U+FE0F -๐ŸŒฉ๏ธ Cloud with Lightning U+1F329, U+FE0F -๐ŸŒช๏ธ Tornado U+1F32A, U+FE0F -๐ŸŒซ๏ธ Fog U+1F32B, U+FE0F -๐ŸŒฌ๏ธ Wind Face U+1F32C, U+FE0F -๐ŸŒ€ Cyclone U+1F300 -๐ŸŒˆ Rainbow U+1F308 -๐ŸŒ‚ Closed Umbrella U+1F302 -โ˜‚๏ธ Umbrella U+2602, U+FE0F -โ˜” Umbrella with Rain Drops U+2614 -โ›ฑ๏ธ Umbrella on Ground U+26F1, U+FE0F -โšก High Voltage U+26A1 -โ„๏ธ Snowflake U+2744, U+FE0F -โ˜ƒ๏ธ Snowman U+2603, U+FE0F -โ›„ Snowman Without Snow U+26C4 -โ˜„๏ธ Comet U+2604, U+FE0F -๐Ÿ”ฅ Fire U+1F525 -๐Ÿ’ง Droplet U+1F4A7 -๐ŸŒŠ Water Wave U+1F30A -๐ŸŽƒ Jack-O-Lantern U+1F383 -๐ŸŽ„ Christmas Tree U+1F384 -๐ŸŽ† Fireworks U+1F386 -๐ŸŽ‡ Sparkler U+1F387 -๐Ÿงจ Firecracker U+1F9E8 -โœจ Sparkles U+2728 -๐ŸŽˆ Balloon U+1F388 -๐ŸŽ‰ Party Popper U+1F389 -๐ŸŽŠ Confetti Ball U+1F38A -๐ŸŽ‹ Tanabata Tree U+1F38B -๐ŸŽ Pine Decoration U+1F38D -๐ŸŽŽ Japanese Dolls U+1F38E -๐ŸŽ Carp Streamer U+1F38F -๐ŸŽ Wind Chime U+1F390 -๐ŸŽ‘ Moon Viewing Ceremony U+1F391 -๐Ÿงง Red Envelope U+1F9E7 -๐ŸŽ€ Ribbon U+1F380 -๐ŸŽ Wrapped Gift U+1F381 -๐ŸŽ—๏ธ Reminder Ribbon U+1F397, U+FE0F -๐ŸŽŸ๏ธ Admission Tickets U+1F39F, U+FE0F -๐ŸŽซ Ticket U+1F3AB -๐ŸŽ–๏ธ Military Medal U+1F396, U+FE0F -๐Ÿ† Trophy U+1F3C6 -๐Ÿ… Sports Medal U+1F3C5 -๐Ÿฅ‡ 1st Place Medal U+1F947 -๐Ÿฅˆ 2nd Place Medal U+1F948 -๐Ÿฅ‰ 3rd Place Medal U+1F949 -โšฝ Soccer Ball U+26BD -โšพ Baseball U+26BE -๐ŸฅŽ Softball U+1F94E -๐Ÿ€ Basketball U+1F3C0 -๐Ÿ Volleyball U+1F3D0 -๐Ÿˆ American Football U+1F3C8 -๐Ÿ‰ Rugby Football U+1F3C9 -๐ŸŽพ Tennis U+1F3BE -๐Ÿฅ Flying Disc U+1F94F -๐ŸŽณ Bowling U+1F3B3 -๐Ÿ Cricket Game U+1F3CF -๐Ÿ‘ Field Hockey U+1F3D1 -๐Ÿ’ Ice Hockey U+1F3D2 -๐Ÿฅ Lacrosse U+1F94D -๐Ÿ“ Ping Pong U+1F3D3 -๐Ÿธ Badminton U+1F3F8 -๐ŸฅŠ Boxing Glove U+1F94A -๐Ÿฅ‹ Martial Arts Uniform U+1F94B -๐Ÿฅ… Goal Net U+1F945 -โ›ณ Flag in Hole U+26F3 -โ›ธ๏ธ Ice Skate U+26F8, U+FE0F -๐ŸŽฃ Fishing Pole U+1F3A3 -๐Ÿคฟ Diving Mask U+1F93F -๐ŸŽฝ Running Shirt U+1F3BD -๐ŸŽฟ Skis U+1F3BF -๐Ÿ›ท Sled U+1F6F7 -๐ŸฅŒ Curling Stone U+1F94C -๐ŸŽฏ Direct Hit U+1F3AF -๐Ÿช€ Yo-Yo U+1FA80 -๐Ÿช Kite U+1FA81 -๐ŸŽฑ Pool 8 Ball U+1F3B1 -๐Ÿ”ฎ Crystal Ball U+1F52E -๐Ÿช„ Magic Wand U+1FA84 -๐Ÿงฟ Nazar Amulet U+1F9FF -๐ŸŽฎ Video Game U+1F3AE -๐Ÿ•น๏ธ Joystick U+1F579, U+FE0F -๐ŸŽฐ Slot Machine U+1F3B0 -๐ŸŽฒ Game Die U+1F3B2 -๐Ÿงฉ Puzzle Piece U+1F9E9 -๐Ÿงธ Teddy Bear U+1F9F8 -๐Ÿช… Piรฑata U+1FA85 -๐Ÿช† Nesting Dolls U+1FA86 -โ™ ๏ธ Spade Suit U+2660, U+FE0F -โ™ฅ๏ธ Heart Suit U+2665, U+FE0F -โ™ฆ๏ธ Diamond Suit U+2666, U+FE0F -โ™ฃ๏ธ Club Suit U+2663, U+FE0F -โ™Ÿ๏ธ Chess Pawn U+265F, U+FE0F -๐Ÿƒ Joker U+1F0CF -๐Ÿ€„ Mahjong Red Dragon U+1F004 -๐ŸŽด Flower Playing Cards U+1F3B4 -๐ŸŽญ Performing Arts U+1F3AD -๐Ÿ–ผ๏ธ Framed Picture U+1F5BC, U+FE0F -๐ŸŽจ Artist Palette U+1F3A8 -๐Ÿงต Thread U+1F9F5 -๐Ÿชก Sewing Needle U+1FAA1 -๐Ÿงถ Yarn U+1F9F6 -๐Ÿชข Knot U+1FAA2 -๐Ÿ‘“ Glasses U+1F453 -๐Ÿ•ถ๏ธ Sunglasses U+1F576, U+FE0F -๐Ÿฅฝ Goggles U+1F97D -๐Ÿฅผ Lab Coat U+1F97C -๐Ÿฆบ Safety Vest U+1F9BA -๐Ÿ‘” Necktie U+1F454 -๐Ÿ‘• T-Shirt U+1F455 -๐Ÿ‘– Jeans U+1F456 -๐Ÿงฃ Scarf U+1F9E3 -๐Ÿงค Gloves U+1F9E4 -๐Ÿงฅ Coat U+1F9E5 -๐Ÿงฆ Socks U+1F9E6 -๐Ÿ‘— Dress U+1F457 -๐Ÿ‘˜ Kimono U+1F458 -๐Ÿฅป Sari U+1F97B -๐Ÿฉฑ One-Piece Swimsuit U+1FA71 -๐Ÿฉฒ Briefs U+1FA72 -๐Ÿฉณ Shorts U+1FA73 -๐Ÿ‘™ Bikini U+1F459 -๐Ÿ‘š Womanโ€™s Clothes U+1F45A -๐Ÿ‘› Purse U+1F45B -๐Ÿ‘œ Handbag U+1F45C -๐Ÿ‘ Clutch Bag U+1F45D -๐Ÿ›๏ธ Shopping Bags U+1F6CD, U+FE0F -๐ŸŽ’ Backpack U+1F392 -๐Ÿฉด Thong Sandal U+1FA74 -๐Ÿ‘ž Manโ€™s Shoe U+1F45E -๐Ÿ‘Ÿ Running Shoe U+1F45F -๐Ÿฅพ Hiking Boot U+1F97E -๐Ÿฅฟ Flat Shoe U+1F97F -๐Ÿ‘  High-Heeled Shoe U+1F460 -๐Ÿ‘ก Womanโ€™s Sandal U+1F461 -๐Ÿฉฐ Ballet Shoes U+1FA70 -๐Ÿ‘ข Womanโ€™s Boot U+1F462 -๐Ÿ‘‘ Crown U+1F451 -๐Ÿ‘’ Womanโ€™s Hat U+1F452 -๐ŸŽฉ Top Hat U+1F3A9 -๐ŸŽ“ Graduation Cap U+1F393 -๐Ÿงข Billed Cap U+1F9E2 -๐Ÿช– Military Helmet U+1FA96 -โ›‘๏ธ Rescue Workerโ€™s Helmet U+26D1, U+FE0F -๐Ÿ“ฟ Prayer Beads U+1F4FF -๐Ÿ’„ Lipstick U+1F484 -๐Ÿ’ Ring U+1F48D -๐Ÿ’Ž Gem Stone U+1F48E -๐Ÿ”‡ Muted Speaker U+1F507 -๐Ÿ”ˆ Speaker Low Volume U+1F508 -๐Ÿ”‰ Speaker Medium Volume U+1F509 -๐Ÿ”Š Speaker High Volume U+1F50A -๐Ÿ“ข Loudspeaker U+1F4E2 -๐Ÿ“ฃ Megaphone U+1F4E3 -๐Ÿ“ฏ Postal Horn U+1F4EF -๐Ÿ”” Bell U+1F514 -๐Ÿ”• Bell with Slash U+1F515 -๐ŸŽผ Musical Score U+1F3BC -๐ŸŽต Musical Note U+1F3B5 -๐ŸŽถ Musical Notes U+1F3B6 -๐ŸŽ™๏ธ Studio Microphone U+1F399, U+FE0F -๐ŸŽš๏ธ Level Slider U+1F39A, U+FE0F -๐ŸŽ›๏ธ Control Knobs U+1F39B, U+FE0F -๐ŸŽค Microphone U+1F3A4 -๐ŸŽง Headphone U+1F3A7 -๐Ÿ“ป Radio U+1F4FB -๐ŸŽท Saxophone U+1F3B7 -๐Ÿช— Accordion U+1FA97 -๐ŸŽธ Guitar U+1F3B8 -๐ŸŽน Musical Keyboard U+1F3B9 -๐ŸŽบ Trumpet U+1F3BA -๐ŸŽป Violin U+1F3BB -๐Ÿช• Banjo U+1FA95 -๐Ÿฅ Drum U+1F941 -๐Ÿช˜ Long Drum U+1FA98 -๐Ÿ“ฑ Mobile Phone U+1F4F1 -๐Ÿ“ฒ Mobile Phone with Arrow U+1F4F2 -โ˜Ž๏ธ Telephone U+260E, U+FE0F -๐Ÿ“ž Telephone Receiver U+1F4DE -๐Ÿ“Ÿ Pager U+1F4DF -๐Ÿ“  Fax Machine U+1F4E0 -๐Ÿ”‹ Battery U+1F50B -๐Ÿ”Œ Electric Plug U+1F50C -๐Ÿ’ป Laptop U+1F4BB -๐Ÿ–ฅ๏ธ Desktop Computer U+1F5A5, U+FE0F -๐Ÿ–จ๏ธ Printer U+1F5A8, U+FE0F -โŒจ๏ธ Keyboard U+2328, U+FE0F -๐Ÿ–ฑ๏ธ Computer Mouse U+1F5B1, U+FE0F -๐Ÿ–ฒ๏ธ Trackball U+1F5B2, U+FE0F -๐Ÿ’ฝ Computer Disk U+1F4BD -๐Ÿ’พ Floppy Disk U+1F4BE -๐Ÿ’ฟ Optical Disk U+1F4BF -๐Ÿ“€ DVD U+1F4C0 -๐Ÿงฎ Abacus U+1F9EE -๐ŸŽฅ Movie Camera U+1F3A5 -๐ŸŽž๏ธ Film Frames U+1F39E, U+FE0F -๐Ÿ“ฝ๏ธ Film Projector U+1F4FD, U+FE0F -๐ŸŽฌ Clapper Board U+1F3AC -๐Ÿ“บ Television U+1F4FA -๐Ÿ“ท Camera U+1F4F7 -๐Ÿ“ธ Camera with Flash U+1F4F8 -๐Ÿ“น Video Camera U+1F4F9 -๐Ÿ“ผ Videocassette U+1F4FC -๐Ÿ” Magnifying Glass Tilted Left U+1F50D -๐Ÿ”Ž Magnifying Glass Tilted Right U+1F50E -๐Ÿ•ฏ๏ธ Candle U+1F56F, U+FE0F -๐Ÿ’ก Light Bulb U+1F4A1 -๐Ÿ”ฆ Flashlight U+1F526 -๐Ÿฎ Red Paper Lantern U+1F3EE -๐Ÿช” Diya Lamp U+1FA94 -๐Ÿ“” Notebook with Decorative Cover U+1F4D4 -๐Ÿ“• Closed Book U+1F4D5 -๐Ÿ“– Open Book U+1F4D6 -๐Ÿ“— Green Book U+1F4D7 -๐Ÿ“˜ Blue Book U+1F4D8 -๐Ÿ“™ Orange Book U+1F4D9 -๐Ÿ“š Books U+1F4DA -๐Ÿ““ Notebook U+1F4D3 -๐Ÿ“’ Ledger U+1F4D2 -๐Ÿ“ƒ Page with Curl U+1F4C3 -๐Ÿ“œ Scroll U+1F4DC -๐Ÿ“„ Page Facing Up U+1F4C4 -๐Ÿ“ฐ Newspaper U+1F4F0 -๐Ÿ—ž๏ธ Rolled-Up Newspaper U+1F5DE, U+FE0F -๐Ÿ“‘ Bookmark Tabs U+1F4D1 -๐Ÿ”– Bookmark U+1F516 -๐Ÿท๏ธ Label U+1F3F7, U+FE0F -๐Ÿ’ฐ Money Bag U+1F4B0 -๐Ÿช™ Coin U+1FA99 -๐Ÿ’ด Yen Banknote U+1F4B4 -๐Ÿ’ต Dollar Banknote U+1F4B5 -๐Ÿ’ถ Euro Banknote U+1F4B6 -๐Ÿ’ท Pound Banknote U+1F4B7 -๐Ÿ’ธ Money with Wings U+1F4B8 -๐Ÿ’ณ Credit Card U+1F4B3 -๐Ÿงพ Receipt U+1F9FE -๐Ÿ’น Chart Increasing with Yen U+1F4B9 -โœ‰๏ธ Envelope U+2709, U+FE0F -๐Ÿ“ง E-Mail U+1F4E7 -๐Ÿ“จ Incoming Envelope U+1F4E8 -๐Ÿ“ฉ Envelope with Arrow U+1F4E9 -๐Ÿ“ค Outbox Tray U+1F4E4 -๐Ÿ“ฅ Inbox Tray U+1F4E5 -๐Ÿ“ฆ Package U+1F4E6 -๐Ÿ“ซ Closed Mailbox with Raised Flag U+1F4EB -๐Ÿ“ช Closed Mailbox with Lowered Flag U+1F4EA -๐Ÿ“ฌ Open Mailbox with Raised Flag U+1F4EC -๐Ÿ“ญ Open Mailbox with Lowered Flag U+1F4ED -๐Ÿ“ฎ Postbox U+1F4EE -๐Ÿ—ณ๏ธ Ballot Box with Ballot U+1F5F3, U+FE0F -โœ๏ธ Pencil U+270F, U+FE0F -โœ’๏ธ Black Nib U+2712, U+FE0F -๐Ÿ–‹๏ธ Fountain Pen U+1F58B, U+FE0F -๐Ÿ–Š๏ธ Pen U+1F58A, U+FE0F -๐Ÿ–Œ๏ธ Paintbrush U+1F58C, U+FE0F -๐Ÿ–๏ธ Crayon U+1F58D, U+FE0F -๐Ÿ“ Memo U+1F4DD -๐Ÿ’ผ Briefcase U+1F4BC -๐Ÿ“ File Folder U+1F4C1 -๐Ÿ“‚ Open File Folder U+1F4C2 -๐Ÿ—‚๏ธ Card Index Dividers U+1F5C2, U+FE0F -๐Ÿ“… Calendar U+1F4C5 -๐Ÿ“† Tear-Off Calendar U+1F4C6 -๐Ÿ—’๏ธ Spiral Notepad U+1F5D2, U+FE0F -๐Ÿ—“๏ธ Spiral Calendar U+1F5D3, U+FE0F -๐Ÿ“‡ Card Index U+1F4C7 -๐Ÿ“ˆ Chart Increasing U+1F4C8 -๐Ÿ“‰ Chart Decreasing U+1F4C9 -๐Ÿ“Š Bar Chart U+1F4CA -๐Ÿ“‹ Clipboard U+1F4CB -๐Ÿ“Œ Pushpin U+1F4CC -๐Ÿ“ Round Pushpin U+1F4CD -๐Ÿ“Ž Paperclip U+1F4CE -๐Ÿ–‡๏ธ Linked Paperclips U+1F587, U+FE0F -๐Ÿ“ Straight Ruler U+1F4CF -๐Ÿ“ Triangular Ruler U+1F4D0 -โœ‚๏ธ Scissors U+2702, U+FE0F -๐Ÿ—ƒ๏ธ Card File Box U+1F5C3, U+FE0F -๐Ÿ—„๏ธ File Cabinet U+1F5C4, U+FE0F -๐Ÿ—‘๏ธ Wastebasket U+1F5D1, U+FE0F -๐Ÿ”’ Locked U+1F512 -๐Ÿ”“ Unlocked U+1F513 -๐Ÿ” Locked with Pen U+1F50F -๐Ÿ” Locked with Key U+1F510 -๐Ÿ”‘ Key U+1F511 -๐Ÿ—๏ธ Old Key U+1F5DD, U+FE0F -๐Ÿ”จ Hammer U+1F528 -๐Ÿช“ Axe U+1FA93 -โ›๏ธ Pick U+26CF, U+FE0F -โš’๏ธ Hammer and Pick U+2692, U+FE0F -๐Ÿ› ๏ธ Hammer and Wrench U+1F6E0, U+FE0F -๐Ÿ—ก๏ธ Dagger U+1F5E1, U+FE0F -โš”๏ธ Crossed Swords U+2694, U+FE0F -๐Ÿ”ซ Pistol U+1F52B -๐Ÿชƒ Boomerang U+1FA83 -๐Ÿน Bow and Arrow U+1F3F9 -๐Ÿ›ก๏ธ Shield U+1F6E1, U+FE0F -๐Ÿชš Carpentry Saw U+1FA9A -๐Ÿ”ง Wrench U+1F527 -๐Ÿช› Screwdriver U+1FA9B -๐Ÿ”ฉ Nut and Bolt U+1F529 -โš™๏ธ Gear U+2699, U+FE0F -๐Ÿ—œ๏ธ Clamp U+1F5DC, U+FE0F -โš–๏ธ Balance Scale U+2696, U+FE0F -๐Ÿฆฏ White Cane U+1F9AF -๐Ÿ”— Link U+1F517 -โ›“๏ธ Chains U+26D3, U+FE0F -๐Ÿช Hook U+1FA9D -๐Ÿงฐ Toolbox U+1F9F0 -๐Ÿงฒ Magnet U+1F9F2 -๐Ÿชœ Ladder U+1FA9C -โš—๏ธ Alembic U+2697, U+FE0F -๐Ÿงช Test Tube U+1F9EA -๐Ÿงซ Petri Dish U+1F9EB -๐Ÿงฌ DNA U+1F9EC -๐Ÿ”ฌ Microscope U+1F52C -๐Ÿ”ญ Telescope U+1F52D -๐Ÿ“ก Satellite Antenna U+1F4E1 -๐Ÿ’‰ Syringe U+1F489 -๐Ÿฉธ Drop of Blood U+1FA78 -๐Ÿ’Š Pill U+1F48A -๐Ÿฉน Adhesive Bandage U+1FA79 -๐Ÿฉบ Stethoscope U+1FA7A -๐Ÿšช Door U+1F6AA -๐Ÿ›— Elevator U+1F6D7 -๐Ÿชž Mirror U+1FA9E -๐ŸชŸ Window U+1FA9F -๐Ÿ›๏ธ Bed U+1F6CF, U+FE0F -๐Ÿ›‹๏ธ Couch and Lamp U+1F6CB, U+FE0F -๐Ÿช‘ Chair U+1FA91 -๐Ÿšฝ Toilet U+1F6BD -๐Ÿช  Plunger U+1FAA0 -๐Ÿšฟ Shower U+1F6BF -๐Ÿ› Bathtub U+1F6C1 -๐Ÿชค Mouse Trap U+1FAA4 -๐Ÿช’ Razor U+1FA92 -๐Ÿงด Lotion Bottle U+1F9F4 -๐Ÿงท Safety Pin U+1F9F7 -๐Ÿงน Broom U+1F9F9 -๐Ÿงบ Basket U+1F9FA -๐Ÿงป Roll of Paper U+1F9FB -๐Ÿชฃ Bucket U+1FAA3 -๐Ÿงผ Soap U+1F9FC -๐Ÿชฅ Toothbrush U+1FAA5 -๐Ÿงฝ Sponge U+1F9FD -๐Ÿงฏ Fire Extinguisher U+1F9EF -๐Ÿ›’ Shopping Cart U+1F6D2 -๐Ÿšฌ Cigarette U+1F6AC -โšฐ๏ธ Coffin U+26B0, U+FE0F -๐Ÿชฆ Headstone U+1FAA6 -โšฑ๏ธ Funeral Urn U+26B1, U+FE0F -๐Ÿ—ฟ Moai U+1F5FF -๐Ÿชง Placard U+1FAA7 -๐Ÿง ATM Sign U+1F3E7 -๐Ÿšฎ Litter in Bin Sign U+1F6AE -๐Ÿšฐ Potable Water U+1F6B0 -โ™ฟ Wheelchair Symbol U+267F -๐Ÿšน Menโ€™s Room U+1F6B9 -๐Ÿšบ Womenโ€™s Room U+1F6BA -๐Ÿšป Restroom U+1F6BB -๐Ÿšผ Baby Symbol U+1F6BC -๐Ÿšพ Water Closet U+1F6BE -๐Ÿ›‚ Passport Control U+1F6C2 -๐Ÿ›ƒ Customs U+1F6C3 -๐Ÿ›„ Baggage Claim U+1F6C4 -๐Ÿ›… Left Luggage U+1F6C5 -โš ๏ธ Warning U+26A0, U+FE0F -๐Ÿšธ Children Crossing U+1F6B8 -โ›” No Entry U+26D4 -๐Ÿšซ Prohibited U+1F6AB -๐Ÿšณ No Bicycles U+1F6B3 -๐Ÿšญ No Smoking U+1F6AD -๐Ÿšฏ No Littering U+1F6AF -๐Ÿšฑ Non-Potable Water U+1F6B1 -๐Ÿšท No Pedestrians U+1F6B7 -๐Ÿ“ต No Mobile Phones U+1F4F5 -๐Ÿ”ž No One Under Eighteen U+1F51E -โ˜ข๏ธ Radioactive U+2622, U+FE0F -โ˜ฃ๏ธ Biohazard U+2623, U+FE0F -โฌ†๏ธ Up Arrow U+2B06, U+FE0F -โ†—๏ธ Up-Right Arrow U+2197, U+FE0F -โžก๏ธ Right Arrow U+27A1, U+FE0F -โ†˜๏ธ Down-Right Arrow U+2198, U+FE0F -โฌ‡๏ธ Down Arrow U+2B07, U+FE0F -โ†™๏ธ Down-Left Arrow U+2199, U+FE0F -โฌ…๏ธ Left Arrow U+2B05, U+FE0F -โ†–๏ธ Up-Left Arrow U+2196, U+FE0F -โ†•๏ธ Up-Down Arrow U+2195, U+FE0F -โ†”๏ธ Left-Right Arrow U+2194, U+FE0F -โ†ฉ๏ธ Right Arrow Curving Left U+21A9, U+FE0F -โ†ช๏ธ Left Arrow Curving Right U+21AA, U+FE0F -โคด๏ธ Right Arrow Curving Up U+2934, U+FE0F -โคต๏ธ Right Arrow Curving Down U+2935, U+FE0F -๐Ÿ”ƒ Clockwise Vertical Arrows U+1F503 -๐Ÿ”„ Counterclockwise Arrows Button U+1F504 -๐Ÿ”™ Back Arrow U+1F519 -๐Ÿ”š End Arrow U+1F51A -๐Ÿ”› On! Arrow U+1F51B -๐Ÿ”œ Soon Arrow U+1F51C -๐Ÿ” Top Arrow U+1F51D -๐Ÿ› Place of Worship U+1F6D0 -โš›๏ธ Atom Symbol U+269B, U+FE0F -๐Ÿ•‰๏ธ Om U+1F549, U+FE0F -โœก๏ธ Star of David U+2721, U+FE0F -โ˜ธ๏ธ Wheel of Dharma U+2638, U+FE0F -โ˜ฏ๏ธ Yin Yang U+262F, U+FE0F -โœ๏ธ Latin Cross U+271D, U+FE0F -โ˜ฆ๏ธ Orthodox Cross U+2626, U+FE0F -โ˜ช๏ธ Star and Crescent U+262A, U+FE0F -โ˜ฎ๏ธ Peace Symbol U+262E, U+FE0F -๐Ÿ•Ž Menorah U+1F54E -๐Ÿ”ฏ Dotted Six-Pointed Star U+1F52F -โ™ˆ Aries U+2648 -โ™‰ Taurus U+2649 -โ™Š Gemini U+264A -โ™‹ Cancer U+264B -โ™Œ Leo U+264C -โ™ Virgo U+264D -โ™Ž Libra U+264E -โ™ Scorpio U+264F -โ™ Sagittarius U+2650 -โ™‘ Capricorn U+2651 -โ™’ Aquarius U+2652 -โ™“ Pisces U+2653 -โ›Ž Ophiuchus U+26CE -๐Ÿ”€ Shuffle Tracks Button U+1F500 -๐Ÿ” Repeat Button U+1F501 -๐Ÿ”‚ Repeat Single Button U+1F502 -โ–ถ๏ธ Play Button U+25B6, U+FE0F -โฉ Fast-Forward Button U+23E9 -โญ๏ธ Next Track Button U+23ED, U+FE0F -โฏ๏ธ Play or Pause Button U+23EF, U+FE0F -โ—€๏ธ Reverse Button U+25C0, U+FE0F -โช Fast Reverse Button U+23EA -โฎ๏ธ Last Track Button U+23EE, U+FE0F -๐Ÿ”ผ Upwards Button U+1F53C -โซ Fast Up Button U+23EB -๐Ÿ”ฝ Downwards Button U+1F53D -โฌ Fast Down Button U+23EC -โธ๏ธ Pause Button U+23F8, U+FE0F -โน๏ธ Stop Button U+23F9, U+FE0F -โบ๏ธ Record Button U+23FA, U+FE0F -โ๏ธ Eject Button U+23CF, U+FE0F -๐ŸŽฆ Cinema U+1F3A6 -๐Ÿ”… Dim Button U+1F505 -๐Ÿ”† Bright Button U+1F506 -๐Ÿ“ถ Antenna Bars U+1F4F6 -๐Ÿ“ณ Vibration Mode U+1F4F3 -๐Ÿ“ด Mobile Phone Off U+1F4F4 -โ™€๏ธ Female Sign U+2640, U+FE0F -โ™‚๏ธ Male Sign U+2642, U+FE0F -โšง๏ธ Transgender Symbol U+26A7, U+FE0F -โœ–๏ธ Multiply U+2716, U+FE0F -โž• Plus U+2795 -โž– Minus U+2796 -โž— Divide U+2797 -โ™พ๏ธ Infinity U+267E, U+FE0F -โ€ผ๏ธ Double Exclamation Mark U+203C, U+FE0F -โ‰๏ธ Exclamation Question Mark U+2049, U+FE0F -โ“ Question Mark U+2753 -โ” White Question Mark U+2754 -โ• White Exclamation Mark U+2755 -โ— Exclamation Mark U+2757 -ใ€ฐ๏ธ Wavy Dash U+3030, U+FE0F -๐Ÿ’ฑ Currency Exchange U+1F4B1 -๐Ÿ’ฒ Heavy Dollar Sign U+1F4B2 -โš•๏ธ Medical Symbol U+2695, U+FE0F -โ™ป๏ธ Recycling Symbol U+267B, U+FE0F -โšœ๏ธ Fleur-de-lis U+269C, U+FE0F -๐Ÿ”ฑ Trident Emblem U+1F531 -๐Ÿ“› Name Badge U+1F4DB -๐Ÿ”ฐ Japanese Symbol for Beginner U+1F530 -โญ• Hollow Red Circle U+2B55 -โœ… Check Mark Button U+2705 -โ˜‘๏ธ Check Box with Check U+2611, U+FE0F -โœ”๏ธ Check Mark U+2714, U+FE0F -โŒ Cross Mark U+274C -โŽ Cross Mark Button U+274E -โžฐ Curly Loop U+27B0 -โžฟ Double Curly Loop U+27BF -ใ€ฝ๏ธ Part Alternation Mark U+303D, U+FE0F -โœณ๏ธ Eight-Spoked Asterisk U+2733, U+FE0F -โœด๏ธ Eight-Pointed Star U+2734, U+FE0F -โ‡๏ธ Sparkle U+2747, U+FE0F -ยฉ๏ธ Copyright U+A9, U+FE0F -ยฎ๏ธ Registered U+AE, U+FE0F -โ„ข๏ธ Trade Mark U+2122, U+FE0F -#๏ธโƒฃ Keycap Number Sign U+23, U+FE0F, U+20E3 -*๏ธโƒฃ Keycap Asterisk U+2A, U+FE0F, U+20E3 -0๏ธโƒฃ Keycap Digit Zero U+30, U+FE0F, U+20E3 -1๏ธโƒฃ Keycap Digit One U+31, U+FE0F, U+20E3 -2๏ธโƒฃ Keycap Digit Two U+32, U+FE0F, U+20E3 -3๏ธโƒฃ Keycap Digit Three U+33, U+FE0F, U+20E3 -4๏ธโƒฃ Keycap Digit Four U+34, U+FE0F, U+20E3 -5๏ธโƒฃ Keycap Digit Five U+35, U+FE0F, U+20E3 -6๏ธโƒฃ Keycap Digit Six U+36, U+FE0F, U+20E3 -7๏ธโƒฃ Keycap Digit Seven U+37, U+FE0F, U+20E3 -8๏ธโƒฃ Keycap Digit Eight U+38, U+FE0F, U+20E3 -9๏ธโƒฃ Keycap Digit Nine U+39, U+FE0F, U+20E3 -๐Ÿ”Ÿ Keycap: 10 U+1F51F -๐Ÿ”  Input Latin Uppercase U+1F520 -๐Ÿ”ก Input Latin Lowercase U+1F521 -๐Ÿ”ข Input Numbers U+1F522 -๐Ÿ”ฃ Input Symbols U+1F523 -๐Ÿ”ค Input Latin Letters U+1F524 -๐Ÿ…ฐ๏ธ A Button (Blood Type) U+1F170, U+FE0F -๐Ÿ†Ž AB Button (Blood Type) U+1F18E -๐Ÿ…ฑ๏ธ B Button (Blood Type) U+1F171, U+FE0F -๐Ÿ†‘ CL Button U+1F191 -๐Ÿ†’ Cool Button U+1F192 -๐Ÿ†“ Free Button U+1F193 -โ„น๏ธ Information U+2139, U+FE0F -๐Ÿ†” ID Button U+1F194 -โ“‚๏ธ Circled M U+24C2, U+FE0F -๐Ÿ†• New Button U+1F195 -๐Ÿ†– NG Button U+1F196 -๐Ÿ…พ๏ธ O Button (Blood Type) U+1F17E, U+FE0F -๐Ÿ†— OK Button U+1F197 -๐Ÿ…ฟ๏ธ P Button U+1F17F, U+FE0F -๐Ÿ†˜ SOS Button U+1F198 -๐Ÿ†™ Up! Button U+1F199 -๐Ÿ†š Vs Button U+1F19A -๐Ÿˆ Japanese โ€œHereโ€ Button U+1F201 -๐Ÿˆ‚๏ธ Japanese โ€œService Chargeโ€ Button U+1F202, U+FE0F -๐Ÿˆท๏ธ Japanese โ€œMonthly Amountโ€ Button U+1F237, U+FE0F -๐Ÿˆถ Japanese โ€œNot Free of Chargeโ€ Button U+1F236 -๐Ÿˆฏ Japanese โ€œReservedโ€ Button U+1F22F -๐Ÿ‰ Japanese โ€œBargainโ€ Button U+1F250 -๐Ÿˆน Japanese โ€œDiscountโ€ Button U+1F239 -๐Ÿˆš Japanese โ€œFree of Chargeโ€ Button U+1F21A -๐Ÿˆฒ Japanese โ€œProhibitedโ€ Button U+1F232 -๐Ÿ‰‘ Japanese โ€œAcceptableโ€ Button U+1F251 -๐Ÿˆธ Japanese โ€œApplicationโ€ Button U+1F238 -๐Ÿˆด Japanese โ€œPassing Gradeโ€ Button U+1F234 -๐Ÿˆณ Japanese โ€œVacancyโ€ Button U+1F233 -ใŠ—๏ธ Japanese โ€œCongratulationsโ€ Button U+3297, U+FE0F -ใŠ™๏ธ Japanese โ€œSecretโ€ Button U+3299, U+FE0F -๐Ÿˆบ Japanese โ€œOpen for Businessโ€ Button U+1F23A -๐Ÿˆต Japanese โ€œNo Vacancyโ€ Button U+1F235 -๐Ÿ”ด Red Circle U+1F534 -๐ŸŸ  Orange Circle U+1F7E0 -๐ŸŸก Yellow Circle U+1F7E1 -๐ŸŸข Green Circle U+1F7E2 -๐Ÿ”ต Blue Circle U+1F535 -๐ŸŸฃ Purple Circle U+1F7E3 -๐ŸŸค Brown Circle U+1F7E4 -โšซ Black Circle U+26AB -โšช White Circle U+26AA -๐ŸŸฅ Red Square U+1F7E5 -๐ŸŸง Orange Square U+1F7E7 -๐ŸŸจ Yellow Square U+1F7E8 -๐ŸŸฉ Green Square U+1F7E9 -๐ŸŸฆ Blue Square U+1F7E6 -๐ŸŸช Purple Square U+1F7EA -๐ŸŸซ Brown Square U+1F7EB -โฌ› Black Large Square U+2B1B -โฌœ White Large Square U+2B1C -โ—ผ๏ธ Black Medium Square U+25FC, U+FE0F -โ—ป๏ธ White Medium Square U+25FB, U+FE0F -โ—พ Black Medium-Small Square U+25FE -โ—ฝ White Medium-Small Square U+25FD -โ–ช๏ธ Black Small Square U+25AA, U+FE0F -โ–ซ๏ธ White Small Square U+25AB, U+FE0F -๐Ÿ”ถ Large Orange Diamond U+1F536 -๐Ÿ”ท Large Blue Diamond U+1F537 -๐Ÿ”ธ Small Orange Diamond U+1F538 -๐Ÿ”น Small Blue Diamond U+1F539 -๐Ÿ”บ Red Triangle Pointed Up U+1F53A -๐Ÿ”ป Red Triangle Pointed Down U+1F53B -๐Ÿ’  Diamond with a Dot U+1F4A0 -๐Ÿ”˜ Radio Button U+1F518 -๐Ÿ”ณ White Square Button U+1F533 -๐Ÿ”ฒ Black Square Button U+1F532 -๐Ÿ Chequered Flag U+1F3C1 -๐Ÿšฉ Triangular Flag U+1F6A9 -๐ŸŽŒ Crossed Flags U+1F38C -๐Ÿด Black Flag U+1F3F4 -๐Ÿณ๏ธ White Flag U+1F3F3, U+FE0F -๐Ÿณ๏ธโ€๐ŸŒˆ Rainbow Flag U+1F3F3, U+FE0F, U+200D, U+1F308 -๐Ÿณ๏ธโ€โšง๏ธ Transgender Flag U+1F3F3, U+FE0F, U+200D, U+26A7, - U+FE0F -๐Ÿดโ€โ˜ ๏ธ Pirate Flag U+1F3F4, U+200D, U+2620, U+FE0F -๐Ÿ‡ฆ๐Ÿ‡จ Flag: Ascension Island U+1F1E6, U+1F1E8 -๐Ÿ‡ฆ๐Ÿ‡ฉ Flag: Andorra U+1F1E6, U+1F1E9 -๐Ÿ‡ฆ๐Ÿ‡ช Flag: United Arab Emirates U+1F1E6, U+1F1EA -๐Ÿ‡ฆ๐Ÿ‡ซ Flag: Afghanistan U+1F1E6, U+1F1EB -๐Ÿ‡ฆ๐Ÿ‡ฌ Flag: Antigua & Barbuda U+1F1E6, U+1F1EC -๐Ÿ‡ฆ๐Ÿ‡ฎ Flag: Anguilla U+1F1E6, U+1F1EE -๐Ÿ‡ฆ๐Ÿ‡ฑ Flag: Albania U+1F1E6, U+1F1F1 -๐Ÿ‡ฆ๐Ÿ‡ฒ Flag: Armenia U+1F1E6, U+1F1F2 -๐Ÿ‡ฆ๐Ÿ‡ด Flag: Angola U+1F1E6, U+1F1F4 -๐Ÿ‡ฆ๐Ÿ‡ถ Flag: Antarctica U+1F1E6, U+1F1F6 -๐Ÿ‡ฆ๐Ÿ‡ท Flag: Argentina U+1F1E6, U+1F1F7 -๐Ÿ‡ฆ๐Ÿ‡ธ Flag: American Samoa U+1F1E6, U+1F1F8 -๐Ÿ‡ฆ๐Ÿ‡น Flag: Austria U+1F1E6, U+1F1F9 -๐Ÿ‡ฆ๐Ÿ‡บ Flag: Australia U+1F1E6, U+1F1FA -๐Ÿ‡ฆ๐Ÿ‡ผ Flag: Aruba U+1F1E6, U+1F1FC -๐Ÿ‡ฆ๐Ÿ‡ฝ Flag: ร…land Islands U+1F1E6, U+1F1FD -๐Ÿ‡ฆ๐Ÿ‡ฟ Flag: Azerbaijan U+1F1E6, U+1F1FF -๐Ÿ‡ง๐Ÿ‡ฆ Flag: Bosnia & Herzegovina U+1F1E7, U+1F1E6 -๐Ÿ‡ง๐Ÿ‡ง Flag: Barbados U+1F1E7, U+1F1E7 -๐Ÿ‡ง๐Ÿ‡ฉ Flag: Bangladesh U+1F1E7, U+1F1E9 -๐Ÿ‡ง๐Ÿ‡ช Flag: Belgium U+1F1E7, U+1F1EA -๐Ÿ‡ง๐Ÿ‡ซ Flag: Burkina Faso U+1F1E7, U+1F1EB -๐Ÿ‡ง๐Ÿ‡ฌ Flag: Bulgaria U+1F1E7, U+1F1EC -๐Ÿ‡ง๐Ÿ‡ญ Flag: Bahrain U+1F1E7, U+1F1ED -๐Ÿ‡ง๐Ÿ‡ฎ Flag: Burundi U+1F1E7, U+1F1EE -๐Ÿ‡ง๐Ÿ‡ฏ Flag: Benin U+1F1E7, U+1F1EF -๐Ÿ‡ง๐Ÿ‡ฑ Flag: St. Barthรฉlemy U+1F1E7, U+1F1F1 -๐Ÿ‡ง๐Ÿ‡ฒ Flag: Bermuda U+1F1E7, U+1F1F2 -๐Ÿ‡ง๐Ÿ‡ณ Flag: Brunei U+1F1E7, U+1F1F3 -๐Ÿ‡ง๐Ÿ‡ด Flag: Bolivia U+1F1E7, U+1F1F4 -๐Ÿ‡ง๐Ÿ‡ถ Flag: Caribbean Netherlands U+1F1E7, U+1F1F6 -๐Ÿ‡ง๐Ÿ‡ท Flag: Brazil U+1F1E7, U+1F1F7 -๐Ÿ‡ง๐Ÿ‡ธ Flag: Bahamas U+1F1E7, U+1F1F8 -๐Ÿ‡ง๐Ÿ‡น Flag: Bhutan U+1F1E7, U+1F1F9 -๐Ÿ‡ง๐Ÿ‡ป Flag: Bouvet Island U+1F1E7, U+1F1FB -๐Ÿ‡ง๐Ÿ‡ผ Flag: Botswana U+1F1E7, U+1F1FC -๐Ÿ‡ง๐Ÿ‡พ Flag: Belarus U+1F1E7, U+1F1FE -๐Ÿ‡ง๐Ÿ‡ฟ Flag: Belize U+1F1E7, U+1F1FF -๐Ÿ‡จ๐Ÿ‡ฆ Flag: Canada U+1F1E8, U+1F1E6 -๐Ÿ‡จ๐Ÿ‡จ Flag: Cocos (Keeling) Islands U+1F1E8, U+1F1E8 -๐Ÿ‡จ๐Ÿ‡ฉ Flag: Congo - Kinshasa U+1F1E8, U+1F1E9 -๐Ÿ‡จ๐Ÿ‡ซ Flag: Central African Republic U+1F1E8, U+1F1EB -๐Ÿ‡จ๐Ÿ‡ฌ Flag: Congo - Brazzaville U+1F1E8, U+1F1EC -๐Ÿ‡จ๐Ÿ‡ญ Flag: Switzerland U+1F1E8, U+1F1ED -๐Ÿ‡จ๐Ÿ‡ฎ Flag: Cรดte dโ€™Ivoire U+1F1E8, U+1F1EE -๐Ÿ‡จ๐Ÿ‡ฐ Flag: Cook Islands U+1F1E8, U+1F1F0 -๐Ÿ‡จ๐Ÿ‡ฑ Flag: Chile U+1F1E8, U+1F1F1 -๐Ÿ‡จ๐Ÿ‡ฒ Flag: Cameroon U+1F1E8, U+1F1F2 -๐Ÿ‡จ๐Ÿ‡ณ Flag: China U+1F1E8, U+1F1F3 -๐Ÿ‡จ๐Ÿ‡ด Flag: Colombia U+1F1E8, U+1F1F4 -๐Ÿ‡จ๐Ÿ‡ต Flag: Clipperton Island U+1F1E8, U+1F1F5 -๐Ÿ‡จ๐Ÿ‡ท Flag: Costa Rica U+1F1E8, U+1F1F7 -๐Ÿ‡จ๐Ÿ‡บ Flag: Cuba U+1F1E8, U+1F1FA -๐Ÿ‡จ๐Ÿ‡ป Flag: Cape Verde U+1F1E8, U+1F1FB -๐Ÿ‡จ๐Ÿ‡ผ Flag: Curaรงao U+1F1E8, U+1F1FC -๐Ÿ‡จ๐Ÿ‡ฝ Flag: Christmas Island U+1F1E8, U+1F1FD -๐Ÿ‡จ๐Ÿ‡พ Flag: Cyprus U+1F1E8, U+1F1FE -๐Ÿ‡จ๐Ÿ‡ฟ Flag: Czechia U+1F1E8, U+1F1FF -๐Ÿ‡ฉ๐Ÿ‡ช Flag: Germany U+1F1E9, U+1F1EA -๐Ÿ‡ฉ๐Ÿ‡ฌ Flag: Diego Garcia U+1F1E9, U+1F1EC -๐Ÿ‡ฉ๐Ÿ‡ฏ Flag: Djibouti U+1F1E9, U+1F1EF -๐Ÿ‡ฉ๐Ÿ‡ฐ Flag: Denmark U+1F1E9, U+1F1F0 -๐Ÿ‡ฉ๐Ÿ‡ฒ Flag: Dominica U+1F1E9, U+1F1F2 -๐Ÿ‡ฉ๐Ÿ‡ด Flag: Dominican Republic U+1F1E9, U+1F1F4 -๐Ÿ‡ฉ๐Ÿ‡ฟ Flag: Algeria U+1F1E9, U+1F1FF -๐Ÿ‡ช๐Ÿ‡ฆ Flag: Ceuta & Melilla U+1F1EA, U+1F1E6 -๐Ÿ‡ช๐Ÿ‡จ Flag: Ecuador U+1F1EA, U+1F1E8 -๐Ÿ‡ช๐Ÿ‡ช Flag: Estonia U+1F1EA, U+1F1EA -๐Ÿ‡ช๐Ÿ‡ฌ Flag: Egypt U+1F1EA, U+1F1EC -๐Ÿ‡ช๐Ÿ‡ญ Flag: Western Sahara U+1F1EA, U+1F1ED -๐Ÿ‡ช๐Ÿ‡ท Flag: Eritrea U+1F1EA, U+1F1F7 -๐Ÿ‡ช๐Ÿ‡ธ Flag: Spain U+1F1EA, U+1F1F8 -๐Ÿ‡ช๐Ÿ‡น Flag: Ethiopia U+1F1EA, U+1F1F9 -๐Ÿ‡ช๐Ÿ‡บ Flag: European Union U+1F1EA, U+1F1FA -๐Ÿ‡ซ๐Ÿ‡ฎ Flag: Finland U+1F1EB, U+1F1EE -๐Ÿ‡ซ๐Ÿ‡ฏ Flag: Fiji U+1F1EB, U+1F1EF -๐Ÿ‡ซ๐Ÿ‡ฐ Flag: Falkland Islands U+1F1EB, U+1F1F0 -๐Ÿ‡ซ๐Ÿ‡ฒ Flag: Micronesia U+1F1EB, U+1F1F2 -๐Ÿ‡ซ๐Ÿ‡ด Flag: Faroe Islands U+1F1EB, U+1F1F4 -๐Ÿ‡ซ๐Ÿ‡ท Flag: France U+1F1EB, U+1F1F7 -๐Ÿ‡ฌ๐Ÿ‡ฆ Flag: Gabon U+1F1EC, U+1F1E6 -๐Ÿ‡ฌ๐Ÿ‡ง Flag: United Kingdom U+1F1EC, U+1F1E7 -๐Ÿ‡ฌ๐Ÿ‡ฉ Flag: Grenada U+1F1EC, U+1F1E9 -๐Ÿ‡ฌ๐Ÿ‡ช Flag: Georgia U+1F1EC, U+1F1EA -๐Ÿ‡ฌ๐Ÿ‡ซ Flag: French Guiana U+1F1EC, U+1F1EB -๐Ÿ‡ฌ๐Ÿ‡ฌ Flag: Guernsey U+1F1EC, U+1F1EC -๐Ÿ‡ฌ๐Ÿ‡ญ Flag: Ghana U+1F1EC, U+1F1ED -๐Ÿ‡ฌ๐Ÿ‡ฎ Flag: Gibraltar U+1F1EC, U+1F1EE -๐Ÿ‡ฌ๐Ÿ‡ฑ Flag: Greenland U+1F1EC, U+1F1F1 -๐Ÿ‡ฌ๐Ÿ‡ฒ Flag: Gambia U+1F1EC, U+1F1F2 -๐Ÿ‡ฌ๐Ÿ‡ณ Flag: Guinea U+1F1EC, U+1F1F3 -๐Ÿ‡ฌ๐Ÿ‡ต Flag: Guadeloupe U+1F1EC, U+1F1F5 -๐Ÿ‡ฌ๐Ÿ‡ถ Flag: Equatorial Guinea U+1F1EC, U+1F1F6 -๐Ÿ‡ฌ๐Ÿ‡ท Flag: Greece U+1F1EC, U+1F1F7 -๐Ÿ‡ฌ๐Ÿ‡ธ Flag: South Georgia & South Sandwich U+1F1EC, U+1F1F8 -Islands -๐Ÿ‡ฌ๐Ÿ‡น Flag: Guatemala U+1F1EC, U+1F1F9 -๐Ÿ‡ฌ๐Ÿ‡บ Flag: Guam U+1F1EC, U+1F1FA -๐Ÿ‡ฌ๐Ÿ‡ผ Flag: Guinea-Bissau U+1F1EC, U+1F1FC -๐Ÿ‡ฌ๐Ÿ‡พ Flag: Guyana U+1F1EC, U+1F1FE -๐Ÿ‡ญ๐Ÿ‡ฐ Flag: Hong Kong SAR China U+1F1ED, U+1F1F0 -๐Ÿ‡ญ๐Ÿ‡ฒ Flag: Heard & McDonald Islands U+1F1ED, U+1F1F2 -๐Ÿ‡ญ๐Ÿ‡ณ Flag: Honduras U+1F1ED, U+1F1F3 -๐Ÿ‡ญ๐Ÿ‡ท Flag: Croatia U+1F1ED, U+1F1F7 -๐Ÿ‡ญ๐Ÿ‡น Flag: Haiti U+1F1ED, U+1F1F9 -๐Ÿ‡ญ๐Ÿ‡บ Flag: Hungary U+1F1ED, U+1F1FA -๐Ÿ‡ฎ๐Ÿ‡จ Flag: Canary Islands U+1F1EE, U+1F1E8 -๐Ÿ‡ฎ๐Ÿ‡ฉ Flag: Indonesia U+1F1EE, U+1F1E9 -๐Ÿ‡ฎ๐Ÿ‡ช Flag: Ireland U+1F1EE, U+1F1EA -๐Ÿ‡ฎ๐Ÿ‡ฑ Flag: Israel U+1F1EE, U+1F1F1 -๐Ÿ‡ฎ๐Ÿ‡ฒ Flag: Isle of Man U+1F1EE, U+1F1F2 -๐Ÿ‡ฎ๐Ÿ‡ณ Flag: India U+1F1EE, U+1F1F3 -๐Ÿ‡ฎ๐Ÿ‡ด Flag: British Indian Ocean Territory U+1F1EE, U+1F1F4 -๐Ÿ‡ฎ๐Ÿ‡ถ Flag: Iraq U+1F1EE, U+1F1F6 -๐Ÿ‡ฎ๐Ÿ‡ท Flag: Iran U+1F1EE, U+1F1F7 -๐Ÿ‡ฎ๐Ÿ‡ธ Flag: Iceland U+1F1EE, U+1F1F8 -๐Ÿ‡ฎ๐Ÿ‡น Flag: Italy U+1F1EE, U+1F1F9 -๐Ÿ‡ฏ๐Ÿ‡ช Flag: Jersey U+1F1EF, U+1F1EA -๐Ÿ‡ฏ๐Ÿ‡ฒ Flag: Jamaica U+1F1EF, U+1F1F2 -๐Ÿ‡ฏ๐Ÿ‡ด Flag: Jordan U+1F1EF, U+1F1F4 -๐Ÿ‡ฏ๐Ÿ‡ต Flag: Japan U+1F1EF, U+1F1F5 -๐Ÿ‡ฐ๐Ÿ‡ช Flag: Kenya U+1F1F0, U+1F1EA -๐Ÿ‡ฐ๐Ÿ‡ฌ Flag: Kyrgyzstan U+1F1F0, U+1F1EC -๐Ÿ‡ฐ๐Ÿ‡ญ Flag: Cambodia U+1F1F0, U+1F1ED -๐Ÿ‡ฐ๐Ÿ‡ฎ Flag: Kiribati U+1F1F0, U+1F1EE -๐Ÿ‡ฐ๐Ÿ‡ฒ Flag: Comoros U+1F1F0, U+1F1F2 -๐Ÿ‡ฐ๐Ÿ‡ณ Flag: St. Kitts & Nevis U+1F1F0, U+1F1F3 -๐Ÿ‡ฐ๐Ÿ‡ต Flag: North Korea U+1F1F0, U+1F1F5 -๐Ÿ‡ฐ๐Ÿ‡ท Flag: South Korea U+1F1F0, U+1F1F7 -๐Ÿ‡ฐ๐Ÿ‡ผ Flag: Kuwait U+1F1F0, U+1F1FC -๐Ÿ‡ฐ๐Ÿ‡พ Flag: Cayman Islands U+1F1F0, U+1F1FE -๐Ÿ‡ฐ๐Ÿ‡ฟ Flag: Kazakhstan U+1F1F0, U+1F1FF -๐Ÿ‡ฑ๐Ÿ‡ฆ Flag: Laos U+1F1F1, U+1F1E6 -๐Ÿ‡ฑ๐Ÿ‡ง Flag: Lebanon U+1F1F1, U+1F1E7 -๐Ÿ‡ฑ๐Ÿ‡จ Flag: St. Lucia U+1F1F1, U+1F1E8 -๐Ÿ‡ฑ๐Ÿ‡ฎ Flag: Liechtenstein U+1F1F1, U+1F1EE -๐Ÿ‡ฑ๐Ÿ‡ฐ Flag: Sri Lanka U+1F1F1, U+1F1F0 -๐Ÿ‡ฑ๐Ÿ‡ท Flag: Liberia U+1F1F1, U+1F1F7 -๐Ÿ‡ฑ๐Ÿ‡ธ Flag: Lesotho U+1F1F1, U+1F1F8 -๐Ÿ‡ฑ๐Ÿ‡น Flag: Lithuania U+1F1F1, U+1F1F9 -๐Ÿ‡ฑ๐Ÿ‡บ Flag: Luxembourg U+1F1F1, U+1F1FA -๐Ÿ‡ฑ๐Ÿ‡ป Flag: Latvia U+1F1F1, U+1F1FB -๐Ÿ‡ฑ๐Ÿ‡พ Flag: Libya U+1F1F1, U+1F1FE -๐Ÿ‡ฒ๐Ÿ‡ฆ Flag: Morocco U+1F1F2, U+1F1E6 -๐Ÿ‡ฒ๐Ÿ‡จ Flag: Monaco U+1F1F2, U+1F1E8 -๐Ÿ‡ฒ๐Ÿ‡ฉ Flag: Moldova U+1F1F2, U+1F1E9 -๐Ÿ‡ฒ๐Ÿ‡ช Flag: Montenegro U+1F1F2, U+1F1EA -๐Ÿ‡ฒ๐Ÿ‡ซ Flag: St. Martin U+1F1F2, U+1F1EB -๐Ÿ‡ฒ๐Ÿ‡ฌ Flag: Madagascar U+1F1F2, U+1F1EC -๐Ÿ‡ฒ๐Ÿ‡ญ Flag: Marshall Islands U+1F1F2, U+1F1ED -๐Ÿ‡ฒ๐Ÿ‡ฐ Flag: North Macedonia U+1F1F2, U+1F1F0 -๐Ÿ‡ฒ๐Ÿ‡ฑ Flag: Mali U+1F1F2, U+1F1F1 -๐Ÿ‡ฒ๐Ÿ‡ฒ Flag: Myanmar (Burma) U+1F1F2, U+1F1F2 -๐Ÿ‡ฒ๐Ÿ‡ณ Flag: Mongolia U+1F1F2, U+1F1F3 -๐Ÿ‡ฒ๐Ÿ‡ด Flag: Macao Sar China U+1F1F2, U+1F1F4 -๐Ÿ‡ฒ๐Ÿ‡ต Flag: Northern Mariana Islands U+1F1F2, U+1F1F5 -๐Ÿ‡ฒ๐Ÿ‡ถ Flag: Martinique U+1F1F2, U+1F1F6 -๐Ÿ‡ฒ๐Ÿ‡ท Flag: Mauritania U+1F1F2, U+1F1F7 -๐Ÿ‡ฒ๐Ÿ‡ธ Flag: Montserrat U+1F1F2, U+1F1F8 -๐Ÿ‡ฒ๐Ÿ‡น Flag: Malta U+1F1F2, U+1F1F9 -๐Ÿ‡ฒ๐Ÿ‡บ Flag: Mauritius U+1F1F2, U+1F1FA -๐Ÿ‡ฒ๐Ÿ‡ป Flag: Maldives U+1F1F2, U+1F1FB -๐Ÿ‡ฒ๐Ÿ‡ผ Flag: Malawi U+1F1F2, U+1F1FC -๐Ÿ‡ฒ๐Ÿ‡ฝ Flag: Mexico U+1F1F2, U+1F1FD -๐Ÿ‡ฒ๐Ÿ‡พ Flag: Malaysia U+1F1F2, U+1F1FE -๐Ÿ‡ฒ๐Ÿ‡ฟ Flag: Mozambique U+1F1F2, U+1F1FF -๐Ÿ‡ณ๐Ÿ‡ฆ Flag: Namibia U+1F1F3, U+1F1E6 -๐Ÿ‡ณ๐Ÿ‡จ Flag: New Caledonia U+1F1F3, U+1F1E8 -๐Ÿ‡ณ๐Ÿ‡ช Flag: Niger U+1F1F3, U+1F1EA -๐Ÿ‡ณ๐Ÿ‡ซ Flag: Norfolk Island U+1F1F3, U+1F1EB -๐Ÿ‡ณ๐Ÿ‡ฌ Flag: Nigeria U+1F1F3, U+1F1EC -๐Ÿ‡ณ๐Ÿ‡ฎ Flag: Nicaragua U+1F1F3, U+1F1EE -๐Ÿ‡ณ๐Ÿ‡ฑ Flag: Netherlands U+1F1F3, U+1F1F1 -๐Ÿ‡ณ๐Ÿ‡ด Flag: Norway U+1F1F3, U+1F1F4 -๐Ÿ‡ณ๐Ÿ‡ต Flag: Nepal U+1F1F3, U+1F1F5 -๐Ÿ‡ณ๐Ÿ‡ท Flag: Nauru U+1F1F3, U+1F1F7 -๐Ÿ‡ณ๐Ÿ‡บ Flag: Niue U+1F1F3, U+1F1FA -๐Ÿ‡ณ๐Ÿ‡ฟ Flag: New Zealand U+1F1F3, U+1F1FF -๐Ÿ‡ด๐Ÿ‡ฒ Flag: Oman U+1F1F4, U+1F1F2 -๐Ÿ‡ต๐Ÿ‡ฆ Flag: Panama U+1F1F5, U+1F1E6 -๐Ÿ‡ต๐Ÿ‡ช Flag: Peru U+1F1F5, U+1F1EA -๐Ÿ‡ต๐Ÿ‡ซ Flag: French Polynesia U+1F1F5, U+1F1EB -๐Ÿ‡ต๐Ÿ‡ฌ Flag: Papua New Guinea U+1F1F5, U+1F1EC -๐Ÿ‡ต๐Ÿ‡ญ Flag: Philippines U+1F1F5, U+1F1ED -๐Ÿ‡ต๐Ÿ‡ฐ Flag: Pakistan U+1F1F5, U+1F1F0 -๐Ÿ‡ต๐Ÿ‡ฑ Flag: Poland U+1F1F5, U+1F1F1 -๐Ÿ‡ต๐Ÿ‡ฒ Flag: St. Pierre & Miquelon U+1F1F5, U+1F1F2 -๐Ÿ‡ต๐Ÿ‡ณ Flag: Pitcairn Islands U+1F1F5, U+1F1F3 -๐Ÿ‡ต๐Ÿ‡ท Flag: Puerto Rico U+1F1F5, U+1F1F7 -๐Ÿ‡ต๐Ÿ‡ธ Flag: Palestinian Territories U+1F1F5, U+1F1F8 -๐Ÿ‡ต๐Ÿ‡น Flag: Portugal U+1F1F5, U+1F1F9 -๐Ÿ‡ต๐Ÿ‡ผ Flag: Palau U+1F1F5, U+1F1FC -๐Ÿ‡ต๐Ÿ‡พ Flag: Paraguay U+1F1F5, U+1F1FE -๐Ÿ‡ถ๐Ÿ‡ฆ Flag: Qatar U+1F1F6, U+1F1E6 -๐Ÿ‡ท๐Ÿ‡ช Flag: Rรฉunion U+1F1F7, U+1F1EA -๐Ÿ‡ท๐Ÿ‡ด Flag: Romania U+1F1F7, U+1F1F4 -๐Ÿ‡ท๐Ÿ‡ธ Flag: Serbia U+1F1F7, U+1F1F8 -๐Ÿ‡ท๐Ÿ‡บ Flag: Russia U+1F1F7, U+1F1FA -๐Ÿ‡ท๐Ÿ‡ผ Flag: Rwanda U+1F1F7, U+1F1FC -๐Ÿ‡ธ๐Ÿ‡ฆ Flag: Saudi Arabia U+1F1F8, U+1F1E6 -๐Ÿ‡ธ๐Ÿ‡ง Flag: Solomon Islands U+1F1F8, U+1F1E7 -๐Ÿ‡ธ๐Ÿ‡จ Flag: Seychelles U+1F1F8, U+1F1E8 -๐Ÿ‡ธ๐Ÿ‡ฉ Flag: Sudan U+1F1F8, U+1F1E9 -๐Ÿ‡ธ๐Ÿ‡ช Flag: Sweden U+1F1F8, U+1F1EA -๐Ÿ‡ธ๐Ÿ‡ฌ Flag: Singapore U+1F1F8, U+1F1EC -๐Ÿ‡ธ๐Ÿ‡ญ Flag: St. Helena U+1F1F8, U+1F1ED -๐Ÿ‡ธ๐Ÿ‡ฎ Flag: Slovenia U+1F1F8, U+1F1EE -๐Ÿ‡ธ๐Ÿ‡ฏ Flag: Svalbard & Jan Mayen U+1F1F8, U+1F1EF -๐Ÿ‡ธ๐Ÿ‡ฐ Flag: Slovakia U+1F1F8, U+1F1F0 -๐Ÿ‡ธ๐Ÿ‡ฑ Flag: Sierra Leone U+1F1F8, U+1F1F1 -๐Ÿ‡ธ๐Ÿ‡ฒ Flag: San Marino U+1F1F8, U+1F1F2 -๐Ÿ‡ธ๐Ÿ‡ณ Flag: Senegal U+1F1F8, U+1F1F3 -๐Ÿ‡ธ๐Ÿ‡ด Flag: Somalia U+1F1F8, U+1F1F4 -๐Ÿ‡ธ๐Ÿ‡ท Flag: Suriname U+1F1F8, U+1F1F7 -๐Ÿ‡ธ๐Ÿ‡ธ Flag: South Sudan U+1F1F8, U+1F1F8 -๐Ÿ‡ธ๐Ÿ‡น Flag: Sรฃo Tomรฉ & Prรญncipe U+1F1F8, U+1F1F9 -๐Ÿ‡ธ๐Ÿ‡ป Flag: El Salvador U+1F1F8, U+1F1FB -๐Ÿ‡ธ๐Ÿ‡ฝ Flag: Sint Maarten U+1F1F8, U+1F1FD -๐Ÿ‡ธ๐Ÿ‡พ Flag: Syria U+1F1F8, U+1F1FE -๐Ÿ‡ธ๐Ÿ‡ฟ Flag: Eswatini U+1F1F8, U+1F1FF -๐Ÿ‡น๐Ÿ‡ฆ Flag: Tristan Da Cunha U+1F1F9, U+1F1E6 -๐Ÿ‡น๐Ÿ‡จ Flag: Turks & Caicos Islands U+1F1F9, U+1F1E8 -๐Ÿ‡น๐Ÿ‡ฉ Flag: Chad U+1F1F9, U+1F1E9 -๐Ÿ‡น๐Ÿ‡ซ Flag: French Southern Territories U+1F1F9, U+1F1EB -๐Ÿ‡น๐Ÿ‡ฌ Flag: Togo U+1F1F9, U+1F1EC -๐Ÿ‡น๐Ÿ‡ญ Flag: Thailand U+1F1F9, U+1F1ED -๐Ÿ‡น๐Ÿ‡ฏ Flag: Tajikistan U+1F1F9, U+1F1EF -๐Ÿ‡น๐Ÿ‡ฐ Flag: Tokelau U+1F1F9, U+1F1F0 -๐Ÿ‡น๐Ÿ‡ฑ Flag: Timor-Leste U+1F1F9, U+1F1F1 -๐Ÿ‡น๐Ÿ‡ฒ Flag: Turkmenistan U+1F1F9, U+1F1F2 -๐Ÿ‡น๐Ÿ‡ณ Flag: Tunisia U+1F1F9, U+1F1F3 -๐Ÿ‡น๐Ÿ‡ด Flag: Tonga U+1F1F9, U+1F1F4 -๐Ÿ‡น๐Ÿ‡ท Flag: Turkey U+1F1F9, U+1F1F7 -๐Ÿ‡น๐Ÿ‡น Flag: Trinidad & Tobago U+1F1F9, U+1F1F9 -๐Ÿ‡น๐Ÿ‡ป Flag: Tuvalu U+1F1F9, U+1F1FB -๐Ÿ‡น๐Ÿ‡ผ Flag: Taiwan U+1F1F9, U+1F1FC -๐Ÿ‡น๐Ÿ‡ฟ Flag: Tanzania U+1F1F9, U+1F1FF -๐Ÿ‡บ๐Ÿ‡ฆ Flag: Ukraine U+1F1FA, U+1F1E6 -๐Ÿ‡บ๐Ÿ‡ฌ Flag: Uganda U+1F1FA, U+1F1EC -๐Ÿ‡บ๐Ÿ‡ฒ Flag: U.S. Outlying Islands U+1F1FA, U+1F1F2 -๐Ÿ‡บ๐Ÿ‡ณ Flag: United Nations U+1F1FA, U+1F1F3 -๐Ÿ‡บ๐Ÿ‡ธ Flag: United States U+1F1FA, U+1F1F8 -๐Ÿ‡บ๐Ÿ‡พ Flag: Uruguay U+1F1FA, U+1F1FE -๐Ÿ‡บ๐Ÿ‡ฟ Flag: Uzbekistan U+1F1FA, U+1F1FF -๐Ÿ‡ป๐Ÿ‡ฆ Flag: Vatican City U+1F1FB, U+1F1E6 -๐Ÿ‡ป๐Ÿ‡จ Flag: St. Vincent & Grenadines U+1F1FB, U+1F1E8 -๐Ÿ‡ป๐Ÿ‡ช Flag: Venezuela U+1F1FB, U+1F1EA -๐Ÿ‡ป๐Ÿ‡ฌ Flag: British Virgin Islands U+1F1FB, U+1F1EC -๐Ÿ‡ป๐Ÿ‡ฎ Flag: U.S. Virgin Islands U+1F1FB, U+1F1EE -๐Ÿ‡ป๐Ÿ‡ณ Flag: Vietnam U+1F1FB, U+1F1F3 -๐Ÿ‡ป๐Ÿ‡บ Flag: Vanuatu U+1F1FB, U+1F1FA -๐Ÿ‡ผ๐Ÿ‡ซ Flag: Wallis & Futuna U+1F1FC, U+1F1EB -๐Ÿ‡ผ๐Ÿ‡ธ Flag: Samoa U+1F1FC, U+1F1F8 -๐Ÿ‡ฝ๐Ÿ‡ฐ Flag: Kosovo U+1F1FD, U+1F1F0 -๐Ÿ‡พ๐Ÿ‡ช Flag: Yemen U+1F1FE, U+1F1EA -๐Ÿ‡พ๐Ÿ‡น Flag: Mayotte U+1F1FE, U+1F1F9 -๐Ÿ‡ฟ๐Ÿ‡ฆ Flag: South Africa U+1F1FF, U+1F1E6 -๐Ÿ‡ฟ๐Ÿ‡ฒ Flag: Zambia U+1F1FF, U+1F1F2 -๐Ÿ‡ฟ๐Ÿ‡ผ Flag: Zimbabwe U+1F1FF, U+1F1FC -๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ Flag: England U+1F3F4, U+E0067, U+E0062, - U+E0065, U+E006E, U+E0067, U+E007F -๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ Flag: Scotland U+1F3F4, U+E0067, U+E0062, - U+E0073, U+E0063, U+E0074, U+E007F -๐Ÿด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ Flag: Wales U+1F3F4, U+E0067, U+E0062, - U+E0077, U+E006C, U+E0073, U+E007F -๐Ÿ‡ฆ Regional Indicator Symbol Letter A U+1F1E6 -๐Ÿ‡ง Regional Indicator Symbol Letter B U+1F1E7 -๐Ÿ‡จ Regional Indicator Symbol Letter C U+1F1E8 -๐Ÿ‡ฉ Regional Indicator Symbol Letter D U+1F1E9 -๐Ÿ‡ช Regional Indicator Symbol Letter E U+1F1EA -๐Ÿ‡ซ Regional Indicator Symbol Letter F U+1F1EB -๐Ÿ‡ฌ Regional Indicator Symbol Letter G U+1F1EC -๐Ÿ‡ญ Regional Indicator Symbol Letter H U+1F1ED -๐Ÿ‡ฎ Regional Indicator Symbol Letter I U+1F1EE -๐Ÿ‡ฏ Regional Indicator Symbol Letter J U+1F1EF -๐Ÿ‡ฐ Regional Indicator Symbol Letter K U+1F1F0 -๐Ÿ‡ฑ Regional Indicator Symbol Letter L U+1F1F1 -๐Ÿ‡ฒ Regional Indicator Symbol Letter M U+1F1F2 -๐Ÿ‡ณ Regional Indicator Symbol Letter N U+1F1F3 -๐Ÿ‡ด Regional Indicator Symbol Letter O U+1F1F4 -๐Ÿ‡ต Regional Indicator Symbol Letter P U+1F1F5 -๐Ÿ‡ถ Regional Indicator Symbol Letter Q U+1F1F6 -๐Ÿ‡ท Regional Indicator Symbol Letter R U+1F1F7 -๐Ÿ‡ธ Regional Indicator Symbol Letter S U+1F1F8 -๐Ÿ‡น Regional Indicator Symbol Letter T U+1F1F9 -๐Ÿ‡บ Regional Indicator Symbol Letter U U+1F1FA -๐Ÿ‡ป Regional Indicator Symbol Letter V U+1F1FB -๐Ÿ‡ผ Regional Indicator Symbol Letter W U+1F1FC -๐Ÿ‡ฝ Regional Indicator Symbol Letter X U+1F1FD -๐Ÿ‡พ Regional Indicator Symbol Letter Y U+1F1FE -๐Ÿ‡ฟ Regional Indicator Symbol Letter Z U+1F1FF -Tag Space U+E0020 -Tag Left Square Bracket U+E005B -Tag Vertical Line U+E007C -4๏ธ Digit Four U+34, U+FE0F -0๏ธ Digit Zero U+30, U+FE0F -Tag Latin Capital Letter G U+E0047 -Tag Digit Eight U+E0038 -Tag Latin Capital Letter N U+E004E -Tag Dollar Sign U+E0024 -*๏ธ Asterisk U+2A, U+FE0F -Tag Right Square Bracket U+E005D -Tag Left Parenthesis U+E0028 -#๏ธ Number Sign U+23, U+FE0F -Tag Digit Two U+E0032 -Tag Latin Capital Letter K U+E004B -Tag Latin Small Letter Y U+E0079 -Tag Tilde U+E007E -Cancel Tag U+E007F -Tag Asterisk U+E002A -Tag Quotation Mark U+E0022 -Tag Colon U+E003A -Tag Digit Zero U+E0030 -๏ธ Variation Selector-16 U+FE0F -Tag Latin Capital Letter X U+E0058 -Tag Reverse Solidus U+E005C -Tag Circumflex Accent U+E005E -Tag Latin Capital Letter Q U+E0051 -Tag Left Curly Bracket U+E007B -Tag Digit Three U+E0033 -Tag Right Parenthesis U+E0029 -Tag Latin Small Letter P U+E0070 -Tag Equals Sign U+E003D -Tag Digit Four U+E0034 -Tag Comma U+E002C -Tag Plus Sign U+E002B -Tag Latin Small Letter J U+E006A -Tag Latin Capital Letter F U+E0046 -Tag Digit Six U+E0036 -Tag Latin Capital Letter P U+E0050 -Tag Latin Small Letter O U+E006F -Tag Latin Capital Letter C U+E0043 -Tag Latin Capital Letter Y U+E0059 -7๏ธ Digit Seven U+37, U+FE0F -Tag Grave Accent U+E0060 -Tag Latin Capital Letter T U+E0054 -โƒฃCombining Enclosing Keycap U+20E3 -Tag Latin Small Letter R U+E0072 -Tag Number Sign U+E0023 -Tag Latin Small Letter H U+E0068 -Tag Latin Small Letter a U+E0061 -Tag Latin Small Letter U U+E0075 -Tag Ampersand U+E0026 -Tag Latin Small Letter T U+E0074 -Tag Latin Small Letter M U+E006D -Tag Latin Capital Letter E U+E0045 -Tag Solidus U+E002F -8๏ธ Digit Eight U+38, U+FE0F -Tag Latin Small Letter X U+E0078 -Tag Latin Small Letter G U+E0067 -Tag Latin Small Letter Z U+E007A -Tag Less-Than Sign U+E003C -Tag Commercial at U+E0040 -Tag Latin Small Letter K U+E006B -Tag Latin Small Letter V U+E0076 -Tag Digit One U+E0031 -Tag Digit Seven U+E0037 -Tag Latin Capital Letter B U+E0042 -Tag Latin Small Letter F U+E0066 -1๏ธ Digit One U+31, U+FE0F -Tag Latin Small Letter D U+E0064 -Tag Latin Small Letter C U+E0063 -Tag Right Curly Bracket U+E007D -5๏ธ Digit Five U+35, U+FE0F -Tag Latin Capital Letter S U+E0053 -Tag Latin Capital Letter V U+E0056 -Tag Digit Five U+E0035 -Tag Full Stop U+E002E -Tag Percent Sign U+E0025 -โ€ Zero Width Joiner U+200D -Tag Latin Small Letter N U+E006E -Tag Hyphen-Minus U+E002D -Tag Latin Small Letter B U+E0062 -Tag Latin Capital Letter R U+E0052 -Tag Digit Nine U+E0039 -Tag Latin Small Letter E U+E0065 -Tag Latin Capital Letter Z U+E005A -Tag Latin Capital Letter I U+E0049 -Tag Latin Capital Letter W U+E0057 -Tag Greater-Than Sign U+E003E -9๏ธ Digit Nine U+39, U+FE0F -Tag Latin Small Letter I U+E0069 -Tag Latin Capital Letter J U+E004A -Tag Latin Small Letter Q U+E0071 -Tag Semicolon U+E003B -2๏ธ Digit Two U+32, U+FE0F -Tag Latin Capital Letter M U+E004D -Tag Low Line U+E005F -Tag Apostrophe U+E0027 -Tag Exclamation Mark U+E0021 -Tag Latin Capital Letter O U+E004F -Tag Latin Small Letter W U+E0077 -Tag Latin Capital Letter U U+E0055 -Tag Latin Capital Letter a U+E0041 -Tag Latin Capital Letter D U+E0044 -Tag Latin Small Letter S U+E0073 -Tag Question Mark U+E003F -6๏ธ Digit Six U+36, U+FE0F -Tag Latin Capital Letter L U+E004C -3๏ธ Digit Three U+33, U+FE0F -Tag Latin Capital Letter H U+E0048 -Tag Latin Small Letter L U+E006C diff --git a/stow/i3/.config/i3/config b/stow/i3/.config/i3/config new file mode 100644 index 0000000..00daed1 --- /dev/null +++ b/stow/i3/.config/i3/config @@ -0,0 +1,279 @@ +# This file has been auto-generated by i3-config-wizard(1). +# It will not be overwritten, so edit it as you like. +# +# Should you change your keyboard layout some time, delete +# this file and re-run i3-config-wizard(1). +# + +# i3 config file (v4) +# +# Please see https://i3wm.org/docs/userguide.html for a complete reference! + +set $mod Mod4 + +# Read from ~/.Xresources +# Last value is color if not able to read it +set_from_resource $black i3wm.color0 #000000 +set_from_resource $black2 i3wm.color8 #3f3f3f +set_from_resource $red i3wm.color1 #ff0000 +set_from_resource $red2 i3wm.color9 #ff7f7f +set_from_resource $green i3wm.color2 #00ff00 +set_from_resource $green2 i3wm.color10 #7fff7f +set_from_resource $yellow i3wm.color3 #ffff00 +set_from_resource $yellow2 i3wm.color11 #ffff7f +set_from_resource $blue i3wm.color4 #0000ff +set_from_resource $blue2 i3wm.color12 #0000ff +set_from_resource $magenta i3wm.color5 #ff00ff +set_from_resource $magenta2 i3wm.color13 #ff7fff +set_from_resource $cyan i3wm.color6 #00ffff +set_from_resource $cyan2 i3wm.color14 #7fffff +set_from_resource $white i3wm.color7 #ffffff +set_from_resource $white2 i3wm.color15 #afafaf + +# Font for window titles. Will also be used by the bar unless a different font +# is used in the bar {} block below. +font pango:monospace 8 + +# This font is widely installed, provides lots of unicode glyphs, right-to-left +# text rendering and scalability on retina/hidpi displays (thanks to pango). +#font pango:DejaVu Sans Mono 8 + +# Before i3 v4.8, we used to recommend this one as the default: +# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 +# The font above is very space-efficient, that is, it looks good, sharp and +# clear in small sizes. However, its unicode glyph coverage is limited, the old +# X core fonts rendering does not support right-to-left and this being a bitmap +# font, it doesnโ€™t scale on retina/hidpi displays. +# +# Use these keys for focus, movement, and resize directions when reaching for +# the arrows is not convenient +set $left h +set $down j +set $up k +set $right l + +# define workspaces names +set $ws1 1:๐Ÿ’ป +set $ws2 2:๐ŸŒ +set $ws3 3:๐Ÿ‘พ +set $ws4 4:๐Ÿงฟ +set $ws5 5:๐Ÿ’ฌ +set $ws6 6:๐ŸŽต +set $ws7 7 +set $ws8 8 +set $ws9 9 +set $ws10 10 +set $wst ๐Ÿ™ˆ + +# use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# kill focused window +bindsym $mod+Shift+q kill + +# change focus +bindsym $mod+$left focus left +bindsym $mod+$down focus down +bindsym $mod+$up focus up +bindsym $mod+$right focus right + +# alternatively, you can use the cursor keys: +bindsym $mod+Left focus left +bindsym $mod+Down focus down +bindsym $mod+Up focus up +bindsym $mod+Right focus right + +# move focused window +bindsym $mod+Shift+$left move left +bindsym $mod+Shift+$down move down +bindsym $mod+Shift+$up move up +bindsym $mod+Shift+$right move right + +# alternatively, you can use the cursor keys: +bindsym $mod+Shift+Left move left +bindsym $mod+Shift+Down move down +bindsym $mod+Shift+Up move up +bindsym $mod+Shift+Right move right + +# navigate workspaces +bindsym $mod+Control+$left workspace prev +bindsym $mod+Control+$right workspace next + +# navigate workspaces with cursor keys: +bindsym $mod+Control+Left workspace prev +bindsym $mod+Control+Right workspace next + +# split in horizontal orientation +bindsym $mod+b split h + +# split in vertical orientation +bindsym $mod+v split v + +# enter fullscreen mode for the focused container +bindsym $mod+f fullscreen toggle + +# toggle bar +#bindsym $mod+Control+b bar mode invisible +#bindsym $mod+Shift+b bar mode dock +bindsym $mod+Shift+b exec toggleBar.sh +# change container layout (stacked, tabbed, toggle split) +bindsym $mod+Control+w layout stacking +bindsym $mod+Shift+w layout tabbed +bindsym $mod+Shift+e layout toggle split + +# toggle tiling / floating +bindsym $mod+Shift+space floating toggle + +# toggle sticky +bindsym $mod+Shift+s sticky toggle + +# modify gaps +bindsym $mod+Shift+g gaps inner current minus 2 +bindsym $mod+g gaps inner current plus 2 +bindsym $mod+Shift+o gaps outer current minus 2 +bindsym $mod+o gaps outer current plus 2 + +# change focus between tiling / floating windows +bindsym $mod+space focus mode_toggle + +# focus the parent container +bindsym $mod+p focus parent + +# focus the child container +bindsym $mod+Shift+p focus child + +# switch to workspace +bindsym $mod+1 workspace $ws1 +bindsym $mod+2 workspace $ws2 +bindsym $mod+3 workspace $ws3 +bindsym $mod+4 workspace $ws4 +bindsym $mod+5 workspace $ws5 +bindsym $mod+6 workspace $ws6 +bindsym $mod+7 workspace $ws7 +bindsym $mod+8 workspace $ws8 +bindsym $mod+9 workspace $ws9 +bindsym $mod+0 workspace $ws10 +bindsym $mod+Control+t workspace $wst + +# move focused container to workspace +bindsym $mod+Shift+1 move container to workspace $ws1 +bindsym $mod+Shift+2 move container to workspace $ws2 +bindsym $mod+Shift+3 move container to workspace $ws3 +bindsym $mod+Shift+4 move container to workspace $ws4 +bindsym $mod+Shift+5 move container to workspace $ws5 +bindsym $mod+Shift+6 move container to workspace $ws6 +bindsym $mod+Shift+7 move container to workspace $ws7 +bindsym $mod+Shift+8 move container to workspace $ws8 +bindsym $mod+Shift+9 move container to workspace $ws9 +bindsym $mod+Shift+0 move container to workspace $ws10 +bindsym $mod+Shift+Control+t move container to workspace $wst + +## Custom ## + +# colors +#class #border #bg #text #indicator #child_border +client.focused $blue2 $black2 $white2 $blue $blue +client.focused_inactive $black2 $black $white $black2 $black2 +client.unfocused $black2 $black $blue2 $black $black +client.urgent $red $black $white $red $red + +# for window config +for_window [class="^.*"] border pixel 4 + +# gaps config +gaps inner 14 +gaps outer 0 + +for_window [title="floating"] floating enable border pixel 1 +for_window [title="noborder"] border none +for_window [title="invisible"] floating enable +for_window [title="invisible"] border none +for_window [title="mpvfloat"] floating enable +for_window [title="mpvfloat"] sticky enable +for_window [title="mpvfloat"] border pixel 1 +for_window [instance="sxivfloat"] floating enable +for_window [instance="sxivfloat"] sticky enable +for_window [instance="sxivfloat"] border pixel 1 +for_window [title="SFML"] floating enable +for_window [title="Firefox"] floating enable + +# edge borders +hide_edge_borders both +#hide_edge_borders none + +# scratchpad +bindsym $mod+minus move scratchpad +bindsym $mod+plus scratchpad show + +# reload the configuration file +bindsym $mod+Control+c reload +# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) +bindsym $mod+Control+r restart +# exit i3 (logs you out of your X session) +#bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" + +# Modes + +# resize window (you can also use the mouse for that) +mode "resize" { +# These bindings trigger as soon as you enter the resize mode + + set $smallSize 1 + set $bigSize 10 + +# Pressing left will shrink the windowโ€™s width. +# Pressing right will grow the windowโ€™s width. +# Pressing up will shrink the windowโ€™s height. +# Pressing down will grow the windowโ€™s height. + bindsym $left resize shrink width $smallSize px or $smallSize ppt + bindsym $down resize grow height $smallSize px or $smallSize ppt + bindsym $up resize shrink height $smallSize px or $smallSize ppt + bindsym $right resize grow width $smallSize px or $smallSize ppt + +# same bindings, but for the arrow keys + bindsym Left resize shrink width $smallSize px or $smallSize ppt + bindsym Down resize grow height $smallSize px or $smallSize ppt + bindsym Up resize shrink height $smallSize px or $smallSize ppt + bindsym Right resize grow width $smallSize px or $smallSize ppt + +# bigger change + bindsym $mod+$left resize shrink width $bigSize px or $bigSize ppt + bindsym $mod+$down resize grow height $bigSize px or $bigSize ppt + bindsym $mod+$up resize shrink height $bigSize px or $bigSize ppt + bindsym $mod+$right resize grow width $bigSize px or $bigSize ppt + + bindsym $mod+Left resize shrink width $bigSize px or $bigSize ppt + bindsym $mod+Down resize grow height $bigSize px or $bigSize ppt + bindsym $mod+Up resize shrink height $bigSize px or $bigSize ppt + bindsym $mod+Right resize grow width $bigSize px or $bigSize ppt + +# back to normal: Enter or Escape + bindsym Return mode "default" + bindsym Escape mode "default" +} + +bindsym $mod+Shift+r mode "resize" + +# Start i3bar to display a workspace bar (plus the system information i3status +# finds out, if available) +bar { + position top + font pango:inconsolata 9 + separator_symbol "ยท" +strip_workspace_numbers yes + colors { + background #000000 + statusline $white2 + separator $white2 + focused_workspace $blue $black $blue + inactive_workspace $black $black $blue + urgent_workspace $magenta $magenta $white2 + } + #status_command i3status + status_command i3blocks +} + +### Init +exec i3-msg "gaps inner current set 0; gaps outer current set 0" +exec $HOME/scripts/xinit.sh + diff --git a/stow/i3/dot-config/i3/config b/stow/i3/dot-config/i3/config deleted file mode 100644 index 00daed1..0000000 --- a/stow/i3/dot-config/i3/config +++ /dev/null @@ -1,279 +0,0 @@ -# This file has been auto-generated by i3-config-wizard(1). -# It will not be overwritten, so edit it as you like. -# -# Should you change your keyboard layout some time, delete -# this file and re-run i3-config-wizard(1). -# - -# i3 config file (v4) -# -# Please see https://i3wm.org/docs/userguide.html for a complete reference! - -set $mod Mod4 - -# Read from ~/.Xresources -# Last value is color if not able to read it -set_from_resource $black i3wm.color0 #000000 -set_from_resource $black2 i3wm.color8 #3f3f3f -set_from_resource $red i3wm.color1 #ff0000 -set_from_resource $red2 i3wm.color9 #ff7f7f -set_from_resource $green i3wm.color2 #00ff00 -set_from_resource $green2 i3wm.color10 #7fff7f -set_from_resource $yellow i3wm.color3 #ffff00 -set_from_resource $yellow2 i3wm.color11 #ffff7f -set_from_resource $blue i3wm.color4 #0000ff -set_from_resource $blue2 i3wm.color12 #0000ff -set_from_resource $magenta i3wm.color5 #ff00ff -set_from_resource $magenta2 i3wm.color13 #ff7fff -set_from_resource $cyan i3wm.color6 #00ffff -set_from_resource $cyan2 i3wm.color14 #7fffff -set_from_resource $white i3wm.color7 #ffffff -set_from_resource $white2 i3wm.color15 #afafaf - -# Font for window titles. Will also be used by the bar unless a different font -# is used in the bar {} block below. -font pango:monospace 8 - -# This font is widely installed, provides lots of unicode glyphs, right-to-left -# text rendering and scalability on retina/hidpi displays (thanks to pango). -#font pango:DejaVu Sans Mono 8 - -# Before i3 v4.8, we used to recommend this one as the default: -# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 -# The font above is very space-efficient, that is, it looks good, sharp and -# clear in small sizes. However, its unicode glyph coverage is limited, the old -# X core fonts rendering does not support right-to-left and this being a bitmap -# font, it doesnโ€™t scale on retina/hidpi displays. -# -# Use these keys for focus, movement, and resize directions when reaching for -# the arrows is not convenient -set $left h -set $down j -set $up k -set $right l - -# define workspaces names -set $ws1 1:๐Ÿ’ป -set $ws2 2:๐ŸŒ -set $ws3 3:๐Ÿ‘พ -set $ws4 4:๐Ÿงฟ -set $ws5 5:๐Ÿ’ฌ -set $ws6 6:๐ŸŽต -set $ws7 7 -set $ws8 8 -set $ws9 9 -set $ws10 10 -set $wst ๐Ÿ™ˆ - -# use Mouse+$mod to drag floating windows to their wanted position -floating_modifier $mod - -# kill focused window -bindsym $mod+Shift+q kill - -# change focus -bindsym $mod+$left focus left -bindsym $mod+$down focus down -bindsym $mod+$up focus up -bindsym $mod+$right focus right - -# alternatively, you can use the cursor keys: -bindsym $mod+Left focus left -bindsym $mod+Down focus down -bindsym $mod+Up focus up -bindsym $mod+Right focus right - -# move focused window -bindsym $mod+Shift+$left move left -bindsym $mod+Shift+$down move down -bindsym $mod+Shift+$up move up -bindsym $mod+Shift+$right move right - -# alternatively, you can use the cursor keys: -bindsym $mod+Shift+Left move left -bindsym $mod+Shift+Down move down -bindsym $mod+Shift+Up move up -bindsym $mod+Shift+Right move right - -# navigate workspaces -bindsym $mod+Control+$left workspace prev -bindsym $mod+Control+$right workspace next - -# navigate workspaces with cursor keys: -bindsym $mod+Control+Left workspace prev -bindsym $mod+Control+Right workspace next - -# split in horizontal orientation -bindsym $mod+b split h - -# split in vertical orientation -bindsym $mod+v split v - -# enter fullscreen mode for the focused container -bindsym $mod+f fullscreen toggle - -# toggle bar -#bindsym $mod+Control+b bar mode invisible -#bindsym $mod+Shift+b bar mode dock -bindsym $mod+Shift+b exec toggleBar.sh -# change container layout (stacked, tabbed, toggle split) -bindsym $mod+Control+w layout stacking -bindsym $mod+Shift+w layout tabbed -bindsym $mod+Shift+e layout toggle split - -# toggle tiling / floating -bindsym $mod+Shift+space floating toggle - -# toggle sticky -bindsym $mod+Shift+s sticky toggle - -# modify gaps -bindsym $mod+Shift+g gaps inner current minus 2 -bindsym $mod+g gaps inner current plus 2 -bindsym $mod+Shift+o gaps outer current minus 2 -bindsym $mod+o gaps outer current plus 2 - -# change focus between tiling / floating windows -bindsym $mod+space focus mode_toggle - -# focus the parent container -bindsym $mod+p focus parent - -# focus the child container -bindsym $mod+Shift+p focus child - -# switch to workspace -bindsym $mod+1 workspace $ws1 -bindsym $mod+2 workspace $ws2 -bindsym $mod+3 workspace $ws3 -bindsym $mod+4 workspace $ws4 -bindsym $mod+5 workspace $ws5 -bindsym $mod+6 workspace $ws6 -bindsym $mod+7 workspace $ws7 -bindsym $mod+8 workspace $ws8 -bindsym $mod+9 workspace $ws9 -bindsym $mod+0 workspace $ws10 -bindsym $mod+Control+t workspace $wst - -# move focused container to workspace -bindsym $mod+Shift+1 move container to workspace $ws1 -bindsym $mod+Shift+2 move container to workspace $ws2 -bindsym $mod+Shift+3 move container to workspace $ws3 -bindsym $mod+Shift+4 move container to workspace $ws4 -bindsym $mod+Shift+5 move container to workspace $ws5 -bindsym $mod+Shift+6 move container to workspace $ws6 -bindsym $mod+Shift+7 move container to workspace $ws7 -bindsym $mod+Shift+8 move container to workspace $ws8 -bindsym $mod+Shift+9 move container to workspace $ws9 -bindsym $mod+Shift+0 move container to workspace $ws10 -bindsym $mod+Shift+Control+t move container to workspace $wst - -## Custom ## - -# colors -#class #border #bg #text #indicator #child_border -client.focused $blue2 $black2 $white2 $blue $blue -client.focused_inactive $black2 $black $white $black2 $black2 -client.unfocused $black2 $black $blue2 $black $black -client.urgent $red $black $white $red $red - -# for window config -for_window [class="^.*"] border pixel 4 - -# gaps config -gaps inner 14 -gaps outer 0 - -for_window [title="floating"] floating enable border pixel 1 -for_window [title="noborder"] border none -for_window [title="invisible"] floating enable -for_window [title="invisible"] border none -for_window [title="mpvfloat"] floating enable -for_window [title="mpvfloat"] sticky enable -for_window [title="mpvfloat"] border pixel 1 -for_window [instance="sxivfloat"] floating enable -for_window [instance="sxivfloat"] sticky enable -for_window [instance="sxivfloat"] border pixel 1 -for_window [title="SFML"] floating enable -for_window [title="Firefox"] floating enable - -# edge borders -hide_edge_borders both -#hide_edge_borders none - -# scratchpad -bindsym $mod+minus move scratchpad -bindsym $mod+plus scratchpad show - -# reload the configuration file -bindsym $mod+Control+c reload -# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) -bindsym $mod+Control+r restart -# exit i3 (logs you out of your X session) -#bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" - -# Modes - -# resize window (you can also use the mouse for that) -mode "resize" { -# These bindings trigger as soon as you enter the resize mode - - set $smallSize 1 - set $bigSize 10 - -# Pressing left will shrink the windowโ€™s width. -# Pressing right will grow the windowโ€™s width. -# Pressing up will shrink the windowโ€™s height. -# Pressing down will grow the windowโ€™s height. - bindsym $left resize shrink width $smallSize px or $smallSize ppt - bindsym $down resize grow height $smallSize px or $smallSize ppt - bindsym $up resize shrink height $smallSize px or $smallSize ppt - bindsym $right resize grow width $smallSize px or $smallSize ppt - -# same bindings, but for the arrow keys - bindsym Left resize shrink width $smallSize px or $smallSize ppt - bindsym Down resize grow height $smallSize px or $smallSize ppt - bindsym Up resize shrink height $smallSize px or $smallSize ppt - bindsym Right resize grow width $smallSize px or $smallSize ppt - -# bigger change - bindsym $mod+$left resize shrink width $bigSize px or $bigSize ppt - bindsym $mod+$down resize grow height $bigSize px or $bigSize ppt - bindsym $mod+$up resize shrink height $bigSize px or $bigSize ppt - bindsym $mod+$right resize grow width $bigSize px or $bigSize ppt - - bindsym $mod+Left resize shrink width $bigSize px or $bigSize ppt - bindsym $mod+Down resize grow height $bigSize px or $bigSize ppt - bindsym $mod+Up resize shrink height $bigSize px or $bigSize ppt - bindsym $mod+Right resize grow width $bigSize px or $bigSize ppt - -# back to normal: Enter or Escape - bindsym Return mode "default" - bindsym Escape mode "default" -} - -bindsym $mod+Shift+r mode "resize" - -# Start i3bar to display a workspace bar (plus the system information i3status -# finds out, if available) -bar { - position top - font pango:inconsolata 9 - separator_symbol "ยท" -strip_workspace_numbers yes - colors { - background #000000 - statusline $white2 - separator $white2 - focused_workspace $blue $black $blue - inactive_workspace $black $black $blue - urgent_workspace $magenta $magenta $white2 - } - #status_command i3status - status_command i3blocks -} - -### Init -exec i3-msg "gaps inner current set 0; gaps outer current set 0" -exec $HOME/scripts/xinit.sh - diff --git a/stow/i3blocks/.config/i3blocks/config b/stow/i3blocks/.config/i3blocks/config new file mode 100644 index 0000000..17d9fee --- /dev/null +++ b/stow/i3blocks/.config/i3blocks/config @@ -0,0 +1,101 @@ +markup=pango +#separator_block_width=0 + +#[emojis] +#command=shufEmoji.sh 1 +#interval=once + +#[corona] +#command=~/scripts/i3blocks/i3corona.sh +#interval=once + +[weather] +command=~/scripts/i3blocks/i3weather.sh +interval=once + +[moon] +command=~/scripts/i3blocks/i3moon.sh +interval=once + +#[fortune] +#color=#ffffff +#color=#bceebc +##background=#6da48e +#command=echo "๐Ÿฅ  $(fortune -n 55 -s | sed 's/\n/ \/ /g')" +#interval=once + +[screenRec] +command=~/scripts/i3blocks/i3rec.sh +interval=once +signal=13 + +[music] +color=#a5acff +command=~/scripts/i3blocks/i3music.sh +interval=2 +signal=12 + +[vol] +#background=#bceebc +#color=#000000 +command=~/scripts/i3blocks/i3vol.sh +interval=once +signal=10 + +[brightness] +#background=#ffff7d +#color=#000000 +command=~/scripts/i3blocks/i3brightness.sh +interval=once +signal=11 + +[battery] +command=~/scripts/i3blocks/i3battery.sh BAT1 +interval=20 + +[mail] +command=~/scripts/i3blocks/i3mailbox.sh +interval=once +signal=15 + +[internet] +#background=#009e60 +command=~/scripts/i3blocks/i3internet.sh +interval=2 + +[cpu] +label=๐ŸŒก๏ธ +command=~/scripts/i3blocks/i3cpu.sh +interval=20 + +[mem] +label=๐Ÿค” +command=~/scripts/i3blocks/i3mem.sh +interval=30 + +[disk] +label=๐Ÿ’ฝ +command=~/scripts/i3blocks/i3disk.sh +interval=30 + +[flags] +command=~/scripts/i3blocks/i3flags.sh +interval=30 + +[litter] +label=๐Ÿšฎ +command=[ -z "$(ls $HOME/litter)" ] && echo "โœ…" || du -sh $HOME/litter | cut -d' ' -f1 +interval=once +signal=14 + +[appointments] +label=๐Ÿ“† +command=~/scripts/i3blocks/i3calcurse.sh +interval=once + +[date] +#color=#000000 +#background=#eb87ff +color=#eb87ff +command=~/scripts/i3blocks/i3date.sh +interval=1 diff --git a/stow/i3blocks/dot-config/i3blocks/config b/stow/i3blocks/dot-config/i3blocks/config deleted file mode 100644 index 17d9fee..0000000 --- a/stow/i3blocks/dot-config/i3blocks/config +++ /dev/null @@ -1,101 +0,0 @@ -markup=pango -#separator_block_width=0 - -#[emojis] -#command=shufEmoji.sh 1 -#interval=once - -#[corona] -#command=~/scripts/i3blocks/i3corona.sh -#interval=once - -[weather] -command=~/scripts/i3blocks/i3weather.sh -interval=once - -[moon] -command=~/scripts/i3blocks/i3moon.sh -interval=once - -#[fortune] -#color=#ffffff -#color=#bceebc -##background=#6da48e -#command=echo "๐Ÿฅ  $(fortune -n 55 -s | sed 's/\n/ \/ /g')" -#interval=once - -[screenRec] -command=~/scripts/i3blocks/i3rec.sh -interval=once -signal=13 - -[music] -color=#a5acff -command=~/scripts/i3blocks/i3music.sh -interval=2 -signal=12 - -[vol] -#background=#bceebc -#color=#000000 -command=~/scripts/i3blocks/i3vol.sh -interval=once -signal=10 - -[brightness] -#background=#ffff7d -#color=#000000 -command=~/scripts/i3blocks/i3brightness.sh -interval=once -signal=11 - -[battery] -command=~/scripts/i3blocks/i3battery.sh BAT1 -interval=20 - -[mail] -command=~/scripts/i3blocks/i3mailbox.sh -interval=once -signal=15 - -[internet] -#background=#009e60 -command=~/scripts/i3blocks/i3internet.sh -interval=2 - -[cpu] -label=๐ŸŒก๏ธ -command=~/scripts/i3blocks/i3cpu.sh -interval=20 - -[mem] -label=๐Ÿค” -command=~/scripts/i3blocks/i3mem.sh -interval=30 - -[disk] -label=๐Ÿ’ฝ -command=~/scripts/i3blocks/i3disk.sh -interval=30 - -[flags] -command=~/scripts/i3blocks/i3flags.sh -interval=30 - -[litter] -label=๐Ÿšฎ -command=[ -z "$(ls $HOME/litter)" ] && echo "โœ…" || du -sh $HOME/litter | cut -d' ' -f1 -interval=once -signal=14 - -[appointments] -label=๐Ÿ“† -command=~/scripts/i3blocks/i3calcurse.sh -interval=once - -[date] -#color=#000000 -#background=#eb87ff -color=#eb87ff -command=~/scripts/i3blocks/i3date.sh -interval=1 diff --git a/stow/mpv/.config/mpv/input.conf b/stow/mpv/.config/mpv/input.conf new file mode 100644 index 0000000..3acfb6c --- /dev/null +++ b/stow/mpv/.config/mpv/input.conf @@ -0,0 +1,213 @@ +# mpv keybindings +# +# Location of user-defined bindings: ~/.config/mpv/input.conf +# +# Lines starting with # are comments. Use SHARP to assign the # key. +# Copy this file and uncomment and edit the bindings you want to change. +# +# List of commands and further details: DOCS/man/input.rst +# List of special keys: --input-keylist +# Keybindings testing mode: mpv --input-test --force-window --idle +# +# Use 'ignore' to unbind a key fully (e.g. 'ctrl+a ignore'). +# +# Strings need to be quoted and escaped: +# KEY show-text "This is a single backslash: \\ and a quote: \" !" +# +# You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with +# the modifiers Shift, Ctrl, Alt and Meta (may not work on the terminal). +# +# The default keybindings are hardcoded into the mpv binary. +# You can disable them completely with: --no-input-default-bindings + +# Developer note: +# On compilation, this file is baked into the mpv binary, and all lines are +# uncommented (unless '#' is followed by a space) - thus this file defines the +# default key bindings. + +# If this is enabled, treat all the following bindings as default. +#default-bindings start + +#MOUSE_BTN0 ignore # don't do anything +#MOUSE_BTN0_DBL cycle fullscreen # toggle fullscreen on/off +#MOUSE_BTN2 cycle pause # toggle pause on/off +#MOUSE_BTN3 seek 10 +#MOUSE_BTN4 seek -10 +#MOUSE_BTN5 add volume -2 +#MOUSE_BTN6 add volume 2 + +# Mouse wheels, touchpad or other input devices that have axes +# if the input devices supports precise scrolling it will also scale the +# numeric value accordingly +#AXIS_UP seek 10 +#AXIS_DOWN seek -10 +#AXIS_LEFT seek 5 +#AXIS_RIGHT seek -5 + +## Seek units are in seconds, but note that these are limited by keyframes +#RIGHT seek 5 +#LEFT seek -5 +#UP seek 60 +#DOWN seek -60 +# Do smaller, always exact (non-keyframe-limited), seeks with shift. +# Don't show them on the OSD (no-osd). +#Shift+RIGHT no-osd seek 1 exact +#Shift+LEFT no-osd seek -1 exact +#Shift+UP no-osd seek 5 exact +#Shift+DOWN no-osd seek -5 exact +# Skip to previous/next subtitle (subject to some restrictions; see manpage) +#Ctrl+LEFT no-osd sub-seek -1 +#Ctrl+RIGHT no-osd sub-seek 1 +#PGUP add chapter 1 # skip to next chapter +#PGDWN add chapter -1 # skip to previous chapter +#Shift+PGUP seek 600 +#Shift+PGDWN seek -600 +#[ multiply speed 0.9091 # scale playback speed +#] multiply speed 1.1 +#{ multiply speed 0.5 +#} multiply speed 2.0 +#BS set speed 1.0 # reset speed to normal +#q quit +#Q quit-watch-later +#q {encode} quit 4 +#ESC set fullscreen no +#ESC {encode} quit 4 +#p cycle pause # toggle pause/playback mode +#. frame-step # advance one frame and pause +#, frame-back-step # go back by one frame and pause +#SPACE cycle pause +#> playlist-next # skip to next file +#ENTER playlist-next # skip to next file +#< playlist-prev # skip to previous file +#O no-osd cycle-values osd-level 3 1 # cycle through OSD mode +#o show-progress +#P show-progress +#I show-text "${filename}" # display filename in osd +#z add sub-delay -0.1 # subtract 100 ms delay from subs +#x add sub-delay +0.1 # add +#ctrl++ add audio-delay 0.100 # this changes audio/video sync +#ctrl+- add audio-delay -0.100 +#9 add volume -2 +#/ add volume -2 +#0 add volume 2 +#* add volume 2 +#m cycle mute +#1 add contrast -1 +#2 add contrast 1 +#3 add brightness -1 +#4 add brightness 1 +#5 add gamma -1 +#6 add gamma 1 +#7 add saturation -1 +#8 add saturation 1 +#Alt+0 set window-scale 0.5 +#Alt+1 set window-scale 1.0 +#Alt+2 set window-scale 2.0 +# toggle deinterlacer (automatically inserts or removes required filter) +#d cycle deinterlace +#r add sub-pos -1 # move subtitles up +#t add sub-pos +1 # down +#v cycle sub-visibility +# stretch SSA/ASS subtitles with anamorphic videos to match historical +#V cycle sub-ass-vsfilter-aspect-compat +# switch between applying no style overrides to SSA/ASS subtitles, and +# overriding them almost completely with the normal subtitle style +#u cycle-values sub-ass-style-override "force" "no" +#j cycle sub # cycle through subtitles +#J cycle sub down # ...backwards +#SHARP cycle audio # switch audio streams +#_ cycle video +#T cycle ontop # toggle video window ontop of other windows +#f cycle fullscreen # toggle fullscreen +#s screenshot # take a screenshot +#S screenshot video # ...without subtitles +#Ctrl+s screenshot window # ...with subtitles and OSD, and scaled +#Alt+s screenshot each-frame # automatically screenshot every frame +#w add panscan -0.1 # zoom out with -panscan 0 -fs +#e add panscan +0.1 # in +# cycle video aspect ratios; "-1" is the container aspect +#A cycle-values video-aspect "16:9" "4:3" "2.35:1" "-1" +#POWER quit +#PLAY cycle pause +#PAUSE cycle pause +#PLAYPAUSE cycle pause +#STOP quit +#FORWARD seek 60 +#REWIND seek -60 +#NEXT playlist-next +#PREV playlist-prev +#VOLUME_UP add volume 2 +#VOLUME_DOWN add volume -2 +#MUTE cycle mute +#CLOSE_WIN quit +#CLOSE_WIN {encode} quit 4 +#E cycle edition # next edition +#l ab-loop # Set/clear A-B loop points +#L cycle-values loop "inf" "no" # toggle infinite looping +#ctrl+c quit 4 + +# Apple Remote section +#AR_PLAY cycle pause +#AR_PLAY_HOLD quit +#AR_CENTER cycle pause +#AR_CENTER_HOLD quit +#AR_NEXT seek 10 +#AR_NEXT_HOLD seek 120 +#AR_PREV seek -10 +#AR_PREV_HOLD seek -120 +#AR_MENU show-progress +#AR_MENU_HOLD cycle mute +#AR_VUP add volume 2 +#AR_VUP_HOLD add chapter 1 +#AR_VDOWN add volume -2 +#AR_VDOWN_HOLD add chapter -1 + +# For tv:// +#h cycle tv-channel -1 # previous channel +#k cycle tv-channel +1 # next channel + +# For dvb:// +#H cycle dvb-channel-name -1 # previous channel +#K cycle dvb-channel-name +1 # next channel + +# +# Legacy bindings (may or may not be removed in the future) +# +#! add chapter -1 # skip to previous chapter +#@ add chapter 1 # next + +# +# Not assigned by default +# (not an exhaustive list of unbound commands) +# + +B add sub-scale +0.1 # increase subtitle font size +b add sub-scale -0.1 # decrease subtitle font size +# ? sub-step -1 # immediately display next subtitle +# ? sub-step +1 # previous +# ? cycle angle # switch DVD/Bluray angle +# ? add balance -0.1 # adjust audio balance in favor of left +# ? add balance 0.1 # right +# ? cycle sub-forced-only # toggle DVD forced subs +# ? cycle program # cycle transport stream programs +# ? stop # stop playback (quit or enter idle mode) + +l seek 5 +h seek -5 +j seek -60 +k seek 60 +Shift+l no-osd seek 1 exact +Shift+h no-osd seek -1 exact +Shift+k no-osd seek 5 exact +Shift+j no-osd seek -5 exact +Ctrl+h no-osd sub-seek -1 +Ctrl+l no-osd sub-seek 1 +Alt+j cycle sub +Alt+J cycle sub down +Alt+l ab-loop # Set/clear A-B loop points +Alt+L cycle-values loop "inf" "no" # toggle infinite looping +i show-text "${media-title}" +I show-text "${filename}" # display filename in osd +c show-text "${chapter-list}" +M show-text "${metadata}" +p show-text "${video-params}" diff --git a/stow/mpv/.config/mpv/mpv.conf b/stow/mpv/.config/mpv/mpv.conf new file mode 100644 index 0000000..9e5391f --- /dev/null +++ b/stow/mpv/.config/mpv/mpv.conf @@ -0,0 +1,21 @@ +# vim: syntax=config + +# OSD +osd-level=1 +osd-font='Linux Libertine' +osd-font-size=45 +osd-color='#FF00B0B0' +osd-bar-w=80 +osd-bar-h=1.5 +osd-bar-align-x=0 +osd-bar-align-y=0.8 + +# Subtitles +sub-border-size=8 + +# Terminal +term-osd-bar +msg-color + +# OSC +osc=no diff --git a/stow/mpv/.config/mpv/scripts-opts/mpv_thumbnail_script.conf b/stow/mpv/.config/mpv/scripts-opts/mpv_thumbnail_script.conf new file mode 100644 index 0000000..7380feb --- /dev/null +++ b/stow/mpv/.config/mpv/scripts-opts/mpv_thumbnail_script.conf @@ -0,0 +1,70 @@ +# The thumbnail cache directory. +# On Windows this defaults to %TEMP%\mpv_thumbs_cache, +# and on other platforms to /tmp/mpv_thumbs_cache. +# The directory will be created automatically, but must be writeable! +# Use absolute paths, and take note that environment variables like %TEMP% are unsupported (despite the default)! +cache_directory=/tmp/my_mpv_thumbnails +# THIS IS NOT A WINDOWS PATH. COMMENT IT OUT OR ADJUST IT YOURSELF. + +# Whether to generate thumbnails automatically on video load, without a keypress +# Defaults to yes +autogenerate=yes + +# Only automatically thumbnail videos shorter than this (in seconds) +# You will have to press T (or your own keybind) to enable the thumbnail previews +# Set to 0 to disable the check, ie. thumbnail videos no matter how long they are +# Defaults to 3600 (one hour) +autogenerate_max_duration=3600 + +# Use mpv to generate thumbnail even if ffmpeg is found in PATH +# ffmpeg is slightly faster than mpv but lacks support for ordered chapters in MKVs, +# which can break the resulting thumbnails. You have been warned. +# Defaults to yes (don't use ffmpeg) +prefer_mpv=yes + +# Explicitly disable subtitles on the mpv sub-calls +# mpv can and will by default render subtitles into the thumbnails. +# If this is not what you wish, set mpv_no_sub to yes +# Defaults to no +mpv_no_sub=no + +# Enable to disable the built-in keybind ("T") to add your own, see after the block +disable_keybinds=no + +# The maximum dimensions of the thumbnails, in pixels +# Defaults to 200 and 200 +thumbnail_width=200 +thumbnail_height=200 + +# The thumbnail count target +# (This will result in a thumbnail every ~10 seconds for a 25 minute video) +thumbnail_count=150 + +# The above target count will be adjusted by the minimum and +# maximum time difference between thumbnails. +# The thumbnail_count will be used to calculate a target separation, +# and min/max_delta will be used to constrict it. + +# In other words, thumbnails will be: +# - at least min_delta seconds apart (limiting the amount) +# - at most max_delta seconds apart (raising the amount if needed) +# Defaults to 5 and 90, values are seconds +min_delta=5 +max_delta=90 +# 120 seconds aka 2 minutes will add more thumbnails only when the video is over 5 hours long! + +# Below are overrides for remote urls (you generally want less thumbnails, because it's slow!) +# Thumbnailing network paths will be done with mpv (leveraging youtube-dl) + +# Allow thumbnailing network paths (naive check for "://") +# Defaults to no +thumbnail_network=yes +# Override thumbnail count, min/max delta, as above +remote_thumbnail_count=60 +remote_min_delta=15 +remote_max_delta=120 + +# Try to grab the raw stream and disable ytdl for the mpv subcalls +# Much faster than passing the url to ytdl again, but may cause problems with some sites +# Defaults to yes +remote_direct_stream=yes diff --git a/stow/mpv/.config/mpv/scripts-opts/youtube-quality.conf b/stow/mpv/.config/mpv/scripts-opts/youtube-quality.conf new file mode 100644 index 0000000..9c1a8c9 --- /dev/null +++ b/stow/mpv/.config/mpv/scripts-opts/youtube-quality.conf @@ -0,0 +1,41 @@ +# KEY BINDINGS + +# invoke or dismiss the quality menu +toggle_menu_binding=ctrl+f +# move the menu cursor up +up_binding=UP +# move the menu cursor down +down_binding=DOWN +# select menu entry +select_binding=ENTER + +# formatting / cursors +selected_and_active=โ–ถ - +selected_and_inactive=โ— - +unselected_and_active=โ–ท - +unselected_and_inactive=โ—‹ - + +# font size scales by window, if false requires larger font and padding sizes +scale_playlist_by_window=no + +# playlist ass style overrides inside curly brackets, \keyvalue is one field, extra \ for escape in lua +# example {\\fnUbuntu\\fs10\\b0\\bord1} equals: font=Ubuntu, size=10, bold=no, border=1 +# read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags +# undeclared tags will use default osd settings +# these styles will be used for the whole playlist. More specific styling will need to be hacked in +# +# (a monospaced font is recommended but not required) +style_ass_tags={\\fnmonospace} + +# paddings for top left corner +text_padding_x=5 +text_padding_y=5 + +# how many seconds until the quality menu times out +menu_timeout=10 + +#use youtube-dl to fetch a list of available formats (overrides quality_strings) +fetch_formats=yes + +# list of ytdl-format strings to choose from +quality_strings=[ {"4320p" : "bestvideo[height<=?4320p]+bestaudio/best"}, {"2160p" : "bestvideo[height<=?2160]+bestaudio/best"}, {"1440p" : "bestvideo[height<=?1440]+bestaudio/best"}, {"1080p" : "bestvideo[height<=?1080]+bestaudio/best"}, {"720p" : "bestvideo[height<=?720]+bestaudio/best"}, {"480p" : "bestvideo[height<=?480]+bestaudio/best"}, {"360p" : "bestvideo[height<=?360]+bestaudio/best"}, {"240p" : "bestvideo[height<=?240]+bestaudio/best"}, {"144p" : "bestvideo[height<=?144]+bestaudio/best"} ] diff --git a/stow/mpv/.config/mpv/scripts/mpv-splice.lua b/stow/mpv/.config/mpv/scripts/mpv-splice.lua new file mode 100644 index 0000000..b121dc4 --- /dev/null +++ b/stow/mpv/.config/mpv/scripts/mpv-splice.lua @@ -0,0 +1,328 @@ +-- ----------------------------------------------------------------------------- +-- +-- MPV Splice +-- URL: https://github.com/pvpscript/mpv-video-splice +-- +-- Requires: ffmpeg +-- +-- Description: +-- +-- This script provides the hability to create video slices by grabbing two +-- timestamps, which generate a slice from timestamp A[i] to timestamp B[i], +-- e.g.: +-- -> Slice 1: 00:10:34.25 -> 00:15:00.00. +-- -> Slice 2: 00:23:00.84 -> 00:24:10.00. +-- ... +-- -> Slice n: 01:44:22.47 -> 01:56:00.00. +-- +-- Then, all the slices from 1 to n are joined together, creating a new +-- video. +-- +-- The output file will appear at the directory that the mpv command was ran, +-- or in the environment variable set for it (see Environment variables below) +-- +-- Note: This script prevents the mpv player from closing when the video ends, +-- so that the slices don't get lost. Keep this in mind if there's the option +-- 'keep-open=no' in the current config file. +-- +-- Note: This script will also silence the terminal, so the script messages +-- can be seen more clearly. +-- +-- ----------------------------------------------------------------------------- +-- +-- +-- Usage: +-- +-- In the video screen, press Alt + T to grab the first timestamp and then +-- press Alt + T again to get the second timestamp. This process will generate +-- a time range, which represents a video slice. Repeat this process to create +-- more slices. +-- +-- To see all the slices made, press Alt + P. All of the slices will appear +-- in the terminal in order of creation, with their corresponding timestamps. +-- Incomplete slices will show up as 'Slice N in progress', where N is the +-- slice number. +-- +-- To reset an incomplete slice, press Alt + R. If the first part of a slice +-- was created at the wrong time, this will reset the current slice. +-- +-- To delete a whole slice, start the slice deletion mode by pressing Alt + D. +-- When in this mode, it's possible to press Alt + NUM, where NUM is any +-- number between 0 inclusive and 9 inclusive. For each Alt + NUM pressed, a +-- number will be concatenated to make the final number referring to the slice +-- to be removed, then press Alt + D again to stop the slicing deletion mode +-- and delete the slice corresponding to the formed number. +-- +-- Example 1: Deleting slice number 3 +-- -> Alt + D # Start slice deletion mode +-- -> Alt + 3 # Concatenate number 3 +-- -> Alt + D # Exit slice deletion mode +-- +-- Example 2> Deleting slice number 76 +-- -> Alt + D # Start slice deletion mode +-- -> Alt + 7 # Concatenate number 7 +-- -> Alt + 6 # Concatenate number 6 +-- -> Alt + D # Exit slice deletion mode +-- +-- To fire up ffmpeg, which will slice up the video and concatenate the slices +-- together, press Alt + C. It's important that there are at least one +-- slice, otherwise no video will be created. +-- +-- Note: No cut will be made unless the user presses Alt + C. +-- Also, the original video file won't be affected by the cutting. +-- +-- +-- ----------------------------------------------------------------------------- +-- +-- +-- Log level: +-- +-- Everytime a timestamp is grabbed, a text will appear on the screen showing +-- the selected time. +-- When Alt + P is pressed, besides showing the slices in the terminal, +-- it will also show on the screen the total number of cuts (or slices) +-- that were made. +-- When the actual cutting and joining process begins, a message will be shown +-- on the screen and the terminal telling that it began. When the process ends, +-- a message will appear on the screen and the terminal displaying the full path +-- of the generated video. It will also appear a message in the terminal telling +-- that the process ended. +-- +-- Note: Every message that appears on the terminal has the log level of 'info'. +-- +-- +-- ----------------------------------------------------------------------------- +-- +-- +-- Environment Variables: +-- +-- This script uses environment variables to allow the user to +-- set the temporary location of the video cuts and for setting the location for +-- the resulting video. +-- +-- To set the temporary directory, set the variable MPV_SPLICE_TEMP; +-- e.g.: export MPV_SPLICE_TEMP="$HOME/temporary_location" +-- +-- To set the video output directory, set the variable MPV_SPLICE_OUTPUT; +-- e.g.: export MPV_SPLICE_OUTPUT="$HOME/output_location" +-- +-- Make sure the directories set in the variables really exist, or else the +-- script might fail. +-- +-- ----------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- +-- Importing the mpv libraries + +local mp = require 'mp' +local msg = require 'mp.msg' + +-------------------------------------------------------------------------------- +-- Default variables + +local default_tmp_location = "/tmp" +local default_output_location = mp.get_property("working-directory") + +-------------------------------------------------------------------------------- + +local concat_name = "concat.txt" + +local ffmpeg = "ffmpeg -hide_banner -loglevel warning" + +local tmp_location = os.getenv("MPV_SPLICE_TEMP") + and os.getenv("MPV_SPLICE_TEMP") + or default_tmp_location +local output_location = os.getenv("MPV_SPLICE_OUTPUT") + and os.getenv("MPV_SPLICE_OUTPUT") + or default_output_location + +local times = {} +local start_time = nil +local remove_val = "" + +local exit_time = 0 + +-------------------------------------------------------------------------------- + +function notify(duration, ...) + local args = {...} + local text = "" + + for i, v in ipairs(args) do + text = text .. tostring(v) + end + + msg.info(text) + mp.command(string.format("show-text \"%s\" %d 1", + text, duration)) +end + +local function get_time() + local time_in_secs = mp.get_property_number('time-pos') + + local hours = math.floor(time_in_secs / 3600) + local mins = math.floor((time_in_secs - hours * 3600) / 60) + local secs = time_in_secs - hours * 3600 - mins * 60 + + local fmt_time = string.format('%02d:%02d:%05.2f', hours, mins, secs) + + return fmt_time +end + +function put_time() + local time = get_time() + local message = "" + + if not start_time then + start_time = time + message = "[START TIMESTAMP]" + else + --times[#times+1] = { + table.insert(times, { + t_start = start_time, + t_end = time + }) + start_time = nil + + message = "[END TIMESTAMP]" + end + + notify(2000, message, ": ", time) +end + +function show_times() + notify(2000, "Total cuts: ", #times) + + for i, obj in ipairs(times) do + msg.info("Slice", i, ": ", obj.t_start, " -> ", obj.t_end) + end + if start_time then + notify(2000, "Slice ", #times+1, " in progress.") + end +end + +function reset_current_slice() + if start_time then + notify(2000, "Slice ", #times+1, " reseted.") + + start_time = nil + end +end + +function delete_slice() + if remove_val == "" then + notify(2000, "Entered slice deletion mode.") + + -- Add shortcut keys to the interval {0..9}. + for i=0,9,1 do + mp.add_key_binding("Alt+" .. i, "num_key_" .. i, + function() + remove_val = remove_val .. i + notify(1000, "Slice to remove: " + .. remove_val) + end + ) + end + else + -- Remove previously added shortcut keys. + for i=0,9,1 do + mp.remove_key_binding("num_key_" .. i) + end + + remove_num = tonumber(remove_val) + if #times >= remove_num and remove_num > 0 then + table.remove(times, remove_num) + notify(2000, "Removed slice ", remove_num) + end + + remove_val = "" + + msg.info("Exited slice deletion mode.") + end +end + +function prevent_quit(name) + if start_time then + if os.time() - exit_time <= 2 then + mp.command(name) + else + exit_time = os.time() + end + notify(3000, "Slice has been marked. Press again to quit") + else + mp.command(name) + end +end + +function process_video() + local alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + local rnd_size = 10 + + local pieces = {} + + -- Better seed randomization + math.randomseed(os.time()) + math.random(); math.random(); math.random() + + if times[#times] then + local tmp_dir = io.popen(string.format("mktemp -d -p %s", + tmp_location)):read("*l") + local input_file = mp.get_property("path") + local ext = string.gmatch(input_file, ".*%.(.*)$")() + + local rnd_str = "" + for i=1,rnd_size,1 do + local rnd_index = math.floor(math.random() * #alphabet + 0.5) + rnd_str = rnd_str .. alphabet:sub(rnd_index, rnd_index) + end + + local output_file = string.format("%s/%s_%s_cut.%s", + output_location, + mp.get_property("filename/no-ext"), + rnd_str, ext) + + local cat_file_name = string.format("%s/%s", tmp_dir, "concat.txt") + local cat_file_ptr = io.open(cat_file_name, "w") + + notify(2000, "Process started!") + + for i, obj in ipairs(times) do + local path = string.format("%s/%s_%d.%s", + tmp_dir, rnd_str, i, ext) + cat_file_ptr:write(string.format("file '%s'\n", path)) + os.execute(string.format("%s -ss %s -i \"%s\" -to %s " .. + "-c copy -copyts -avoid_negative_ts make_zero \"%s\"", + ffmpeg, obj.t_start, input_file, obj.t_end, + path)) + end + + cat_file_ptr:close() + + cmd = string.format("%s -f concat -safe 0 -i \"%s\" " .. + "-c copy \"%s\"", + ffmpeg, cat_file_name, output_file) + os.execute(cmd) + + notify(10000, "File saved as: ", output_file) + msg.info("Process ended!") + + os.execute(string.format("rm -rf %s", tmp_dir)) + msg.info("Temporary directory removed!") + end +end + +mp.set_property("keep-open", "yes") -- Prevent mpv from exiting when the video ends +mp.set_property("quiet", "yes") -- Silence terminal. + +mp.add_key_binding('q', "quit", function() + prevent_quit("quit") +end) +mp.add_key_binding('Shift+q', "quit-watch-later", function() + prevent_quit("quit-watch-later") +end) + +mp.add_key_binding('Alt+t', "put_time", put_time) +mp.add_key_binding('Alt+p', "show_times", show_times) +mp.add_key_binding('Alt+c', "process_video", process_video) +mp.add_key_binding('Alt+r', "reset_current_slice", reset_current_slice) +mp.add_key_binding('Alt+d', "delete_slice", delete_slice) diff --git a/stow/mpv/.config/mpv/scripts/mpv_thumbnail_script_client_osc.lua b/stow/mpv/.config/mpv/scripts/mpv_thumbnail_script_client_osc.lua new file mode 100644 index 0000000..e822846 --- /dev/null +++ b/stow/mpv/.config/mpv/scripts/mpv_thumbnail_script_client_osc.lua @@ -0,0 +1,3886 @@ +--[[ + Copyright (C) 2017 AMM + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +]]-- +--[[ + mpv_thumbnail_script.lua 0.4.2 - commit a2de250 (branch master) + https://github.com/TheAMM/mpv_thumbnail_script + Built on 2018-02-07 20:36:55 +]]-- +local assdraw = require 'mp.assdraw' +local msg = require 'mp.msg' +local opt = require 'mp.options' +local utils = require 'mp.utils' + +-- Determine platform -- +ON_WINDOWS = (package.config:sub(1,1) ~= '/') + +-- Some helper functions needed to parse the options -- +function isempty(v) return (v == false) or (v == nil) or (v == "") or (v == 0) or (type(v) == "table" and next(v) == nil) end + +function divmod (a, b) + return math.floor(a / b), a % b +end + +-- Better modulo +function bmod( i, N ) + return (i % N + N) % N +end + +function join_paths(...) + local sep = ON_WINDOWS and "\\" or "/" + local result = ""; + for i, p in pairs({...}) do + if p ~= "" then + if is_absolute_path(p) then + result = p + else + result = (result ~= "") and (result:gsub("[\\"..sep.."]*$", "") .. sep .. p) or p + end + end + end + return result:gsub("[\\"..sep.."]*$", "") +end + +-- /some/path/file.ext -> /some/path, file.ext +function split_path( path ) + local sep = ON_WINDOWS and "\\" or "/" + local first_index, last_index = path:find('^.*' .. sep) + + if last_index == nil then + return "", path + else + local dir = path:sub(0, last_index-1) + local file = path:sub(last_index+1, -1) + + return dir, file + end +end + +function is_absolute_path( path ) + local tmp, is_win = path:gsub("^[A-Z]:\\", "") + local tmp, is_unix = path:gsub("^/", "") + return (is_win > 0) or (is_unix > 0) +end + +function Set(source) + local set = {} + for _, l in ipairs(source) do set[l] = true end + return set +end + +--------------------------- +-- More helper functions -- +--------------------------- + +-- Removes all keys from a table, without destroying the reference to it +function clear_table(target) + for key, value in pairs(target) do + target[key] = nil + end +end +function shallow_copy(target) + local copy = {} + for k, v in pairs(target) do + copy[k] = v + end + return copy +end + +-- Rounds to given decimals. eg. round_dec(3.145, 0) => 3 +function round_dec(num, idp) + local mult = 10^(idp or 0) + return math.floor(num * mult + 0.5) / mult +end + +function file_exists(name) + local f = io.open(name, "rb") + if f ~= nil then + local ok, err, code = f:read(1) + io.close(f) + return code == nil + else + return false + end +end + +function path_exists(name) + local f = io.open(name, "rb") + if f ~= nil then + io.close(f) + return true + else + return false + end +end + +function create_directories(path) + local cmd + if ON_WINDOWS then + cmd = { args = {"cmd", "/c", "mkdir", path} } + else + cmd = { args = {"mkdir", "-p", path} } + end + utils.subprocess(cmd) +end + +-- Find an executable in PATH or CWD with the given name +function find_executable(name) + local delim = ON_WINDOWS and ";" or ":" + + local pwd = os.getenv("PWD") or utils.getcwd() + local path = os.getenv("PATH") + + local env_path = pwd .. delim .. path -- Check CWD first + + local result, filename + for path_dir in env_path:gmatch("[^"..delim.."]+") do + filename = join_paths(path_dir, name) + if file_exists(filename) then + result = filename + break + end + end + + return result +end + +local ExecutableFinder = { path_cache = {} } +-- Searches for an executable and caches the result if any +function ExecutableFinder:get_executable_path( name, raw_name ) + name = ON_WINDOWS and not raw_name and (name .. ".exe") or name + + if self.path_cache[name] == nil then + self.path_cache[name] = find_executable(name) or false + end + return self.path_cache[name] +end + +-- Format seconds to HH.MM.SS.sss +function format_time(seconds, sep, decimals) + decimals = decimals == nil and 3 or decimals + sep = sep and sep or "." + local s = seconds + local h, s = divmod(s, 60*60) + local m, s = divmod(s, 60) + + local second_format = string.format("%%0%d.%df", 2+(decimals > 0 and decimals+1 or 0), decimals) + + return string.format("%02d"..sep.."%02d"..sep..second_format, h, m, s) +end + +-- Format seconds to 1h 2m 3.4s +function format_time_hms(seconds, sep, decimals, force_full) + decimals = decimals == nil and 1 or decimals + sep = sep ~= nil and sep or " " + + local s = seconds + local h, s = divmod(s, 60*60) + local m, s = divmod(s, 60) + + if force_full or h > 0 then + return string.format("%dh"..sep.."%dm"..sep.."%." .. tostring(decimals) .. "fs", h, m, s) + elseif m > 0 then + return string.format("%dm"..sep.."%." .. tostring(decimals) .. "fs", m, s) + else + return string.format("%." .. tostring(decimals) .. "fs", s) + end +end + +-- Writes text on OSD and console +function log_info(txt, timeout) + timeout = timeout or 1.5 + msg.info(txt) + mp.osd_message(txt, timeout) +end + +-- Join table items, ala ({"a", "b", "c"}, "=", "-", ", ") => "=a-, =b-, =c-" +function join_table(source, before, after, sep) + before = before or "" + after = after or "" + sep = sep or ", " + local result = "" + for i, v in pairs(source) do + if not isempty(v) then + local part = before .. v .. after + if i == 1 then + result = part + else + result = result .. sep .. part + end + end + end + return result +end + +function wrap(s, char) + char = char or "'" + return char .. s .. char +end +-- Wraps given string into 'string' and escapes any 's in it +function escape_and_wrap(s, char, replacement) + char = char or "'" + replacement = replacement or "\\" .. char + return wrap(string.gsub(s, char, replacement), char) +end +-- Escapes single quotes in a string and wraps the input in single quotes +function escape_single_bash(s) + return escape_and_wrap(s, "'", "'\\''") +end + +-- Returns (a .. b) if b is not empty or nil +function joined_or_nil(a, b) + return not isempty(b) and (a .. b) or nil +end + +-- Put items from one table into another +function extend_table(target, source) + for i, v in pairs(source) do + table.insert(target, v) + end +end + +-- Creates a handle and filename for a temporary random file (in current directory) +function create_temporary_file(base, mode, suffix) + local handle, filename + suffix = suffix or "" + while true do + filename = base .. tostring(math.random(1, 5000)) .. suffix + handle = io.open(filename, "r") + if not handle then + handle = io.open(filename, mode) + break + end + io.close(handle) + end + return handle, filename +end + + +function get_processor_count() + local proc_count + + if ON_WINDOWS then + proc_count = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) + else + local cpuinfo_handle = io.open("/proc/cpuinfo") + if cpuinfo_handle ~= nil then + local cpuinfo_contents = cpuinfo_handle:read("*a") + local _, replace_count = cpuinfo_contents:gsub('processor', '') + proc_count = replace_count + end + end + + if proc_count and proc_count > 0 then + return proc_count + else + return nil + end +end + +function substitute_values(string, values) + local substitutor = function(match) + if match == "%" then + return "%" + else + -- nil is discarded by gsub + return values[match] + end + end + + local substituted = string:gsub('%%(.)', substitutor) + return substituted +end + +-- ASS HELPERS -- +function round_rect_top( ass, x0, y0, x1, y1, r ) + local c = 0.551915024494 * r -- circle approximation + ass:move_to(x0 + r, y0) + ass:line_to(x1 - r, y0) -- top line + if r > 0 then + ass:bezier_curve(x1 - r + c, y0, x1, y0 + r - c, x1, y0 + r) -- top right corner + end + ass:line_to(x1, y1) -- right line + ass:line_to(x0, y1) -- bottom line + ass:line_to(x0, y0 + r) -- left line + if r > 0 then + ass:bezier_curve(x0, y0 + r - c, x0 + r - c, y0, x0 + r, y0) -- top left corner + end +end + +function round_rect(ass, x0, y0, x1, y1, rtl, rtr, rbr, rbl) + local c = 0.551915024494 + ass:move_to(x0 + rtl, y0) + ass:line_to(x1 - rtr, y0) -- top line + if rtr > 0 then + ass:bezier_curve(x1 - rtr + rtr*c, y0, x1, y0 + rtr - rtr*c, x1, y0 + rtr) -- top right corner + end + ass:line_to(x1, y1 - rbr) -- right line + if rbr > 0 then + ass:bezier_curve(x1, y1 - rbr + rbr*c, x1 - rbr + rbr*c, y1, x1 - rbr, y1) -- bottom right corner + end + ass:line_to(x0 + rbl, y1) -- bottom line + if rbl > 0 then + ass:bezier_curve(x0 + rbl - rbl*c, y1, x0, y1 - rbl + rbl*c, x0, y1 - rbl) -- bottom left corner + end + ass:line_to(x0, y0 + rtl) -- left line + if rtl > 0 then + ass:bezier_curve(x0, y0 + rtl - rtl*c, x0 + rtl - rtl*c, y0, x0 + rtl, y0) -- top left corner + end +end +-- $Revision: 1.5 $ +-- $Date: 2014-09-10 16:54:25 $ + +-- This module was originally taken from http://cube3d.de/uploads/Main/sha1.txt. + +------------------------------------------------------------------------------- +-- SHA-1 secure hash computation, and HMAC-SHA1 signature computation, +-- in pure Lua (tested on Lua 5.1) +-- License: MIT +-- +-- Usage: +-- local hashAsHex = sha1.hex(message) -- returns a hex string +-- local hashAsData = sha1.bin(message) -- returns raw bytes +-- +-- local hmacAsHex = sha1.hmacHex(key, message) -- hex string +-- local hmacAsData = sha1.hmacBin(key, message) -- raw bytes +-- +-- +-- Pass sha1.hex() a string, and it returns a hash as a 40-character hex string. +-- For example, the call +-- +-- local hash = sha1.hex("iNTERFACEWARE") +-- +-- puts the 40-character string +-- +-- "e76705ffb88a291a0d2f9710a5471936791b4819" +-- +-- into the variable 'hash' +-- +-- Pass sha1.hmacHex() a key and a message, and it returns the signature as a +-- 40-byte hex string. +-- +-- +-- The two "bin" versions do the same, but return the 20-byte string of raw +-- data that the 40-byte hex strings represent. +-- +------------------------------------------------------------------------------- +-- +-- Description +-- Due to the lack of bitwise operations in 5.1, this version uses numbers to +-- represents the 32bit words that we combine with binary operations. The basic +-- operations of byte based "xor", "or", "and" are all cached in a combination +-- table (several 64k large tables are built on startup, which +-- consumes some memory and time). The caching can be switched off through +-- setting the local cfg_caching variable to false. +-- For all binary operations, the 32 bit numbers are split into 8 bit values +-- that are combined and then merged again. +-- +-- Algorithm: http://www.itl.nist.gov/fipspubs/fip180-1.htm +-- +------------------------------------------------------------------------------- + +local sha1 = (function() +local sha1 = {} + +-- set this to false if you don't want to build several 64k sized tables when +-- loading this file (takes a while but grants a boost of factor 13) +local cfg_caching = false +-- local storing of global functions (minor speedup) +local floor,modf = math.floor,math.modf +local char,format,rep = string.char,string.format,string.rep + +-- merge 4 bytes to an 32 bit word +local function bytes_to_w32 (a,b,c,d) return a*0x1000000+b*0x10000+c*0x100+d end +-- split a 32 bit word into four 8 bit numbers +local function w32_to_bytes (i) + return floor(i/0x1000000)%0x100,floor(i/0x10000)%0x100,floor(i/0x100)%0x100,i%0x100 +end + +-- shift the bits of a 32 bit word. Don't use negative values for "bits" +local function w32_rot (bits,a) + local b2 = 2^(32-bits) + local a,b = modf(a/b2) + return a+b*b2*(2^(bits)) +end + +-- caching function for functions that accept 2 arguments, both of values between +-- 0 and 255. The function to be cached is passed, all values are calculated +-- during loading and a function is returned that returns the cached values (only) +local function cache2arg (fn) + if not cfg_caching then return fn end + local lut = {} + for i=0,0xffff do + local a,b = floor(i/0x100),i%0x100 + lut[i] = fn(a,b) + end + return function (a,b) + return lut[a*0x100+b] + end +end + +-- splits an 8-bit number into 8 bits, returning all 8 bits as booleans +local function byte_to_bits (b) + local b = function (n) + local b = floor(b/n) + return b%2==1 + end + return b(1),b(2),b(4),b(8),b(16),b(32),b(64),b(128) +end + +-- builds an 8bit number from 8 booleans +local function bits_to_byte (a,b,c,d,e,f,g,h) + local function n(b,x) return b and x or 0 end + return n(a,1)+n(b,2)+n(c,4)+n(d,8)+n(e,16)+n(f,32)+n(g,64)+n(h,128) +end + +-- debug function for visualizing bits in a string +local function bits_to_string (a,b,c,d,e,f,g,h) + local function x(b) return b and "1" or "0" end + return ("%s%s%s%s %s%s%s%s"):format(x(a),x(b),x(c),x(d),x(e),x(f),x(g),x(h)) +end + +-- debug function for converting a 8-bit number as bit string +local function byte_to_bit_string (b) + return bits_to_string(byte_to_bits(b)) +end + +-- debug function for converting a 32 bit number as bit string +local function w32_to_bit_string(a) + if type(a) == "string" then return a end + local aa,ab,ac,ad = w32_to_bytes(a) + local s = byte_to_bit_string + return ("%s %s %s %s"):format(s(aa):reverse(),s(ab):reverse(),s(ac):reverse(),s(ad):reverse()):reverse() +end + +-- bitwise "and" function for 2 8bit number +local band = cache2arg (function(a,b) + local A,B,C,D,E,F,G,H = byte_to_bits(b) + local a,b,c,d,e,f,g,h = byte_to_bits(a) + return bits_to_byte( + A and a, B and b, C and c, D and d, + E and e, F and f, G and g, H and h) + end) + +-- bitwise "or" function for 2 8bit numbers +local bor = cache2arg(function(a,b) + local A,B,C,D,E,F,G,H = byte_to_bits(b) + local a,b,c,d,e,f,g,h = byte_to_bits(a) + return bits_to_byte( + A or a, B or b, C or c, D or d, + E or e, F or f, G or g, H or h) + end) + +-- bitwise "xor" function for 2 8bit numbers +local bxor = cache2arg(function(a,b) + local A,B,C,D,E,F,G,H = byte_to_bits(b) + local a,b,c,d,e,f,g,h = byte_to_bits(a) + return bits_to_byte( + A ~= a, B ~= b, C ~= c, D ~= d, + E ~= e, F ~= f, G ~= g, H ~= h) + end) + +-- bitwise complement for one 8bit number +local function bnot (x) + return 255-(x % 256) +end + +-- creates a function to combine to 32bit numbers using an 8bit combination function +local function w32_comb(fn) + return function (a,b) + local aa,ab,ac,ad = w32_to_bytes(a) + local ba,bb,bc,bd = w32_to_bytes(b) + return bytes_to_w32(fn(aa,ba),fn(ab,bb),fn(ac,bc),fn(ad,bd)) + end +end + +-- create functions for and, xor and or, all for 2 32bit numbers +local w32_and = w32_comb(band) +local w32_xor = w32_comb(bxor) +local w32_or = w32_comb(bor) + +-- xor function that may receive a variable number of arguments +local function w32_xor_n (a,...) + local aa,ab,ac,ad = w32_to_bytes(a) + for i=1,select('#',...) do + local ba,bb,bc,bd = w32_to_bytes(select(i,...)) + aa,ab,ac,ad = bxor(aa,ba),bxor(ab,bb),bxor(ac,bc),bxor(ad,bd) + end + return bytes_to_w32(aa,ab,ac,ad) +end + +-- combining 3 32bit numbers through binary "or" operation +local function w32_or3 (a,b,c) + local aa,ab,ac,ad = w32_to_bytes(a) + local ba,bb,bc,bd = w32_to_bytes(b) + local ca,cb,cc,cd = w32_to_bytes(c) + return bytes_to_w32( + bor(aa,bor(ba,ca)), bor(ab,bor(bb,cb)), bor(ac,bor(bc,cc)), bor(ad,bor(bd,cd)) + ) +end + +-- binary complement for 32bit numbers +local function w32_not (a) + return 4294967295-(a % 4294967296) +end + +-- adding 2 32bit numbers, cutting off the remainder on 33th bit +local function w32_add (a,b) return (a+b) % 4294967296 end + +-- adding n 32bit numbers, cutting off the remainder (again) +local function w32_add_n (a,...) + for i=1,select('#',...) do + a = (a+select(i,...)) % 4294967296 + end + return a +end +-- converting the number to a hexadecimal string +local function w32_to_hexstring (w) return format("%08x",w) end + +-- calculating the SHA1 for some text +function sha1.hex(msg) + local H0,H1,H2,H3,H4 = 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0 + local msg_len_in_bits = #msg * 8 + + local first_append = char(0x80) -- append a '1' bit plus seven '0' bits + + local non_zero_message_bytes = #msg +1 +8 -- the +1 is the appended bit 1, the +8 are for the final appended length + local current_mod = non_zero_message_bytes % 64 + local second_append = current_mod>0 and rep(char(0), 64 - current_mod) or "" + + -- now to append the length as a 64-bit number. + local B1, R1 = modf(msg_len_in_bits / 0x01000000) + local B2, R2 = modf( 0x01000000 * R1 / 0x00010000) + local B3, R3 = modf( 0x00010000 * R2 / 0x00000100) + local B4 = 0x00000100 * R3 + + local L64 = char( 0) .. char( 0) .. char( 0) .. char( 0) -- high 32 bits + .. char(B1) .. char(B2) .. char(B3) .. char(B4) -- low 32 bits + + msg = msg .. first_append .. second_append .. L64 + + assert(#msg % 64 == 0) + + local chunks = #msg / 64 + + local W = { } + local start, A, B, C, D, E, f, K, TEMP + local chunk = 0 + + while chunk < chunks do + -- + -- break chunk up into W[0] through W[15] + -- + start,chunk = chunk * 64 + 1,chunk + 1 + + for t = 0, 15 do + W[t] = bytes_to_w32(msg:byte(start, start + 3)) + start = start + 4 + end + + -- + -- build W[16] through W[79] + -- + for t = 16, 79 do + -- For t = 16 to 79 let Wt = S1(Wt-3 XOR Wt-8 XOR Wt-14 XOR Wt-16). + W[t] = w32_rot(1, w32_xor_n(W[t-3], W[t-8], W[t-14], W[t-16])) + end + + A,B,C,D,E = H0,H1,H2,H3,H4 + + for t = 0, 79 do + if t <= 19 then + -- (B AND C) OR ((NOT B) AND D) + f = w32_or(w32_and(B, C), w32_and(w32_not(B), D)) + K = 0x5A827999 + elseif t <= 39 then + -- B XOR C XOR D + f = w32_xor_n(B, C, D) + K = 0x6ED9EBA1 + elseif t <= 59 then + -- (B AND C) OR (B AND D) OR (C AND D + f = w32_or3(w32_and(B, C), w32_and(B, D), w32_and(C, D)) + K = 0x8F1BBCDC + else + -- B XOR C XOR D + f = w32_xor_n(B, C, D) + K = 0xCA62C1D6 + end + + -- TEMP = S5(A) + ft(B,C,D) + E + Wt + Kt; + A,B,C,D,E = w32_add_n(w32_rot(5, A), f, E, W[t], K), + A, w32_rot(30, B), C, D + end + -- Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E. + H0,H1,H2,H3,H4 = w32_add(H0, A),w32_add(H1, B),w32_add(H2, C),w32_add(H3, D),w32_add(H4, E) + end + local f = w32_to_hexstring + return f(H0) .. f(H1) .. f(H2) .. f(H3) .. f(H4) +end + +local function hex_to_binary(hex) + return hex:gsub('..', function(hexval) + return string.char(tonumber(hexval, 16)) + end) +end + +function sha1.bin(msg) + return hex_to_binary(sha1.hex(msg)) +end + +local xor_with_0x5c = {} +local xor_with_0x36 = {} +-- building the lookuptables ahead of time (instead of littering the source code +-- with precalculated values) +for i=0,0xff do + xor_with_0x5c[char(i)] = char(bxor(i,0x5c)) + xor_with_0x36[char(i)] = char(bxor(i,0x36)) +end + +local blocksize = 64 -- 512 bits + +function sha1.hmacHex(key, text) + assert(type(key) == 'string', "key passed to hmacHex should be a string") + assert(type(text) == 'string', "text passed to hmacHex should be a string") + + if #key > blocksize then + key = sha1.bin(key) + end + + local key_xord_with_0x36 = key:gsub('.', xor_with_0x36) .. string.rep(string.char(0x36), blocksize - #key) + local key_xord_with_0x5c = key:gsub('.', xor_with_0x5c) .. string.rep(string.char(0x5c), blocksize - #key) + + return sha1.hex(key_xord_with_0x5c .. sha1.bin(key_xord_with_0x36 .. text)) +end + +function sha1.hmacBin(key, text) + return hex_to_binary(sha1.hmacHex(key, text)) +end + +return sha1 +end)() + +local SCRIPT_NAME = "mpv_thumbnail_script" + +local default_cache_base = ON_WINDOWS and os.getenv("TEMP") or "/tmp/" + +local thumbnailer_options = { + -- The thumbnail directory + cache_directory = join_paths(default_cache_base, "mpv_thumbs_cache"), + + ------------------------ + -- Generation options -- + ------------------------ + + -- Automatically generate the thumbnails on video load, without a keypress + autogenerate = true, + + -- Only automatically thumbnail videos shorter than this (seconds) + autogenerate_max_duration = 3600, -- 1 hour + + -- SHA1-sum filenames over this length + -- It's nice to know what files the thumbnails are (hence directory names) + -- but long URLs may approach filesystem limits. + hash_filename_length = 128, + + -- Use mpv to generate thumbnail even if ffmpeg is found in PATH + -- ffmpeg does not handle ordered chapters (MKVs which rely on other MKVs)! + -- mpv is a bit slower, but has better support overall (eg. subtitles in the previews) + prefer_mpv = true, + + -- Explicitly disable subtitles on the mpv sub-calls + mpv_no_sub = false, + -- Add a "--no-config" to the mpv sub-call arguments + mpv_no_config = false, + -- Add a "--profile=" to the mpv sub-call arguments + -- Use "" to disable + mpv_profile = "", + -- Output debug logs to .log, ala //000000.bgra.log + -- The logs are removed after successful encodes, unless you set mpv_keep_logs below + mpv_logs = true, + -- Keep all mpv logs, even the succesfull ones + mpv_keep_logs = false, + + -- Disable the built-in keybind ("T") to add your own + disable_keybinds = false, + + --------------------- + -- Display options -- + --------------------- + + -- Move the thumbnail up or down + -- For example: + -- topbar/bottombar: 24 + -- rest: 0 + vertical_offset = 24, + + -- Adjust background padding + -- Examples: + -- topbar: 0, 10, 10, 10 + -- bottombar: 10, 0, 10, 10 + -- slimbox/box: 10, 10, 10, 10 + pad_top = 10, + pad_bot = 0, + pad_left = 10, + pad_right = 10, + + -- If true, pad values are screen-pixels. If false, video-pixels. + pad_in_screenspace = true, + -- Calculate pad into the offset + offset_by_pad = true, + + -- Background color in BBGGRR + background_color = "000000", + -- Alpha: 0 - fully opaque, 255 - transparent + background_alpha = 80, + + -- Keep thumbnail on the screen near left or right side + constrain_to_screen = true, + + -- Do not display the thumbnailing progress + hide_progress = false, + + ----------------------- + -- Thumbnail options -- + ----------------------- + + -- The maximum dimensions of the thumbnails (pixels) + thumbnail_width = 200, + thumbnail_height = 200, + + -- The thumbnail count target + -- (This will result in a thumbnail every ~10 seconds for a 25 minute video) + thumbnail_count = 150, + + -- The above target count will be adjusted by the minimum and + -- maximum time difference between thumbnails. + -- The thumbnail_count will be used to calculate a target separation, + -- and min/max_delta will be used to constrict it. + + -- In other words, thumbnails will be: + -- at least min_delta seconds apart (limiting the amount) + -- at most max_delta seconds apart (raising the amount if needed) + min_delta = 5, + -- 120 seconds aka 2 minutes will add more thumbnails when the video is over 5 hours! + max_delta = 90, + + + -- Overrides for remote urls (you generally want less thumbnails!) + -- Thumbnailing network paths will be done with mpv + + -- Allow thumbnailing network paths (naive check for "://") + thumbnail_network = false, + -- Override thumbnail count, min/max delta + remote_thumbnail_count = 60, + remote_min_delta = 15, + remote_max_delta = 120, + + -- Try to grab the raw stream and disable ytdl for the mpv subcalls + -- Much faster than passing the url to ytdl again, but may cause problems with some sites + remote_direct_stream = true, +} + +read_options(thumbnailer_options, SCRIPT_NAME) +local Thumbnailer = { + cache_directory = thumbnailer_options.cache_directory, + + state = { + ready = false, + available = false, + enabled = false, + + thumbnail_template = nil, + + thumbnail_delta = nil, + thumbnail_count = 0, + + thumbnail_size = nil, + + finished_thumbnails = 0, + + -- List of thumbnail states (from 1 to thumbnail_count) + -- ready: 1 + -- in progress: 0 + -- not ready: -1 + thumbnails = {}, + + worker_input_path = nil, + -- Extra options for the workers + worker_extra = {}, + }, + -- Set in register_client + worker_register_timeout = nil, + -- A timer used to wait for more workers in case we have none + worker_wait_timer = nil, + workers = {} +} + +function Thumbnailer:clear_state() + clear_table(self.state) + self.state.ready = false + self.state.available = false + self.state.finished_thumbnails = 0 + self.state.thumbnails = {} + self.state.worker_extra = {} +end + + +function Thumbnailer:on_file_loaded() + self:clear_state() +end + +function Thumbnailer:on_thumb_ready(index) + self.state.thumbnails[index] = 1 + + -- Full recount instead of a naive increment (let's be safe!) + self.state.finished_thumbnails = 0 + for i, v in pairs(self.state.thumbnails) do + if v > 0 then + self.state.finished_thumbnails = self.state.finished_thumbnails + 1 + end + end +end + +function Thumbnailer:on_thumb_progress(index) + self.state.thumbnails[index] = math.max(self.state.thumbnails[index], 0) +end + +function Thumbnailer:on_start_file() + -- Clear state when a new file is being loaded + self:clear_state() +end + +function Thumbnailer:on_video_change(params) + -- Gather a new state when we get proper video-dec-params and our state is empty + if params ~= nil then + if not self.state.ready then + self:update_state() + end + end +end + + +function Thumbnailer:update_state() + msg.debug("Gathering video/thumbnail state") + + self.state.thumbnail_delta = self:get_delta() + self.state.thumbnail_count = self:get_thumbnail_count(self.state.thumbnail_delta) + + -- Prefill individual thumbnail states + for i = 1, self.state.thumbnail_count do + self.state.thumbnails[i] = -1 + end + + self.state.thumbnail_template, self.state.thumbnail_directory = self:get_thumbnail_template() + self.state.thumbnail_size = self:get_thumbnail_size() + + self.state.ready = true + + local file_path = mp.get_property_native("path") + self.state.is_remote = file_path:find("://") ~= nil + + self.state.available = false + + -- Make sure the file has video (and not just albumart) + local track_list = mp.get_property_native("track-list") + local has_video = false + for i, track in pairs(track_list) do + if track.type == "video" and not track.external and not track.albumart then + has_video = true + break + end + end + + if has_video and self.state.thumbnail_delta ~= nil and self.state.thumbnail_size ~= nil and self.state.thumbnail_count > 0 then + self.state.available = true + end + + msg.debug("Thumbnailer.state:", utils.to_string(self.state)) + +end + + +function Thumbnailer:get_thumbnail_template() + local file_path = mp.get_property_native("path") + local is_remote = file_path:find("://") ~= nil + + local filename = mp.get_property_native("filename/no-ext") + local filesize = mp.get_property_native("file-size", 0) + + if is_remote then + filesize = 0 + end + + filename = filename:gsub('[^a-zA-Z0-9_.%-\' ]', '') + -- Hash overly long filenames (most likely URLs) + if #filename > thumbnailer_options.hash_filename_length then + filename = sha1.hex(filename) + end + + local file_key = ("%s-%d"):format(filename, filesize) + + local thumbnail_directory = join_paths(self.cache_directory, file_key) + local file_template = join_paths(thumbnail_directory, "%06d.bgra") + return file_template, thumbnail_directory +end + + +function Thumbnailer:get_thumbnail_size() + local video_dec_params = mp.get_property_native("video-dec-params") + local video_width = video_dec_params.dw + local video_height = video_dec_params.dh + if not (video_width and video_height) then + return nil + end + + local w, h + if video_width > video_height then + w = thumbnailer_options.thumbnail_width + h = math.floor(video_height * (w / video_width)) + else + h = thumbnailer_options.thumbnail_height + w = math.floor(video_width * (h / video_height)) + end + return { w=w, h=h } +end + + +function Thumbnailer:get_delta() + local file_path = mp.get_property_native("path") + local file_duration = mp.get_property_native("duration") + local is_seekable = mp.get_property_native("seekable") + + -- Naive url check + local is_remote = file_path:find("://") ~= nil + + local remote_and_disallowed = is_remote + if is_remote and thumbnailer_options.thumbnail_network then + remote_and_disallowed = false + end + + if remote_and_disallowed or not is_seekable or not file_duration then + -- Not a local path (or remote thumbnails allowed), not seekable or lacks duration + return nil + end + + local thumbnail_count = thumbnailer_options.thumbnail_count + local min_delta = thumbnailer_options.min_delta + local max_delta = thumbnailer_options.max_delta + + if is_remote then + thumbnail_count = thumbnailer_options.remote_thumbnail_count + min_delta = thumbnailer_options.remote_min_delta + max_delta = thumbnailer_options.remote_max_delta + end + + local target_delta = (file_duration / thumbnail_count) + local delta = math.max(min_delta, math.min(max_delta, target_delta)) + + return delta +end + + +function Thumbnailer:get_thumbnail_count(delta) + if delta == nil then + return 0 + end + local file_duration = mp.get_property_native("duration") + + return math.ceil(file_duration / delta) +end + +function Thumbnailer:get_closest(thumbnail_index) + -- Given a 1-based index, find the closest available thumbnail and return it's 1-based index + + -- Check the direct thumbnail index first + if self.state.thumbnails[thumbnail_index] > 0 then + return thumbnail_index + end + + local min_distance = self.state.thumbnail_count + 1 + local closest = nil + + -- Naive, inefficient, lazy. But functional. + for index, value in pairs(self.state.thumbnails) do + local distance = math.abs(index - thumbnail_index) + if distance < min_distance and value > 0 then + min_distance = distance + closest = index + end + end + return closest +end + +function Thumbnailer:get_thumbnail_index(time_position) + -- Returns a 1-based thumbnail index for the given timestamp (between 1 and thumbnail_count, inclusive) + if self.state.thumbnail_delta and (self.state.thumbnail_count and self.state.thumbnail_count > 0) then + return math.min(math.floor(time_position / self.state.thumbnail_delta) + 1, self.state.thumbnail_count) + else + return nil + end +end + +function Thumbnailer:get_thumbnail_path(time_position) + -- Given a timestamp, return: + -- the closest available thumbnail path (if any) + -- the 1-based thumbnail index calculated from the timestamp + -- the 1-based thumbnail index of the closest available (and used) thumbnail + -- OR nil if thumbnails are not available. + + local thumbnail_index = self:get_thumbnail_index(time_position) + if not thumbnail_index then return nil end + + local closest = self:get_closest(thumbnail_index) + + if closest ~= nil then + return self.state.thumbnail_template:format(closest-1), thumbnail_index, closest + else + return nil, thumbnail_index, nil + end +end + +function Thumbnailer:register_client() + self.worker_register_timeout = mp.get_time() + 2 + + mp.register_script_message("mpv_thumbnail_script-ready", function(index, path) + self:on_thumb_ready(tonumber(index), path) + end) + mp.register_script_message("mpv_thumbnail_script-progress", function(index, path) + self:on_thumb_progress(tonumber(index), path) + end) + + mp.register_script_message("mpv_thumbnail_script-worker", function(worker_name) + if not self.workers[worker_name] then + msg.debug("Registered worker", worker_name) + self.workers[worker_name] = true + mp.commandv("script-message-to", worker_name, "mpv_thumbnail_script-slaved") + end + end) + + -- Notify workers to generate thumbnails when video loads/changes + -- This will be executed after the on_video_change (because it's registered after it) + mp.observe_property("video-dec-params", "native", function() + local duration = mp.get_property_native("duration") + local max_duration = thumbnailer_options.autogenerate_max_duration + + if self.state.available and thumbnailer_options.autogenerate then + -- Notify if autogenerate is on and video is not too long + if duration < max_duration or max_duration == 0 then + self:start_worker_jobs() + end + end + end) + + local thumb_script_key = not thumbnailer_options.disable_keybinds and "T" or nil + mp.add_key_binding(thumb_script_key, "generate-thumbnails", function() + if self.state.available then + mp.osd_message("Started thumbnailer jobs") + self:start_worker_jobs() + else + mp.osd_message("Thumbnailing unavailabe") + end + end) +end + +function Thumbnailer:_create_thumbnail_job_order() + -- Returns a list of 1-based thumbnail indices in a job order + local used_frames = {} + local work_frames = {} + + -- Pick frames in increasing frequency. + -- This way we can do a quick few passes over the video and then fill in the gaps. + for x = 6, 0, -1 do + local nth = (2^x) + + for thi = 1, self.state.thumbnail_count, nth do + if not used_frames[thi] then + table.insert(work_frames, thi) + used_frames[thi] = true + end + end + end + return work_frames +end + +function Thumbnailer:prepare_source_path() + local file_path = mp.get_property_native("path") + + if self.state.is_remote and thumbnailer_options.remote_direct_stream then + -- Use the direct stream (possibly) provided by ytdl + -- This skips ytdl on the sub-calls, making the thumbnailing faster + -- Works well on YouTube, rest not really tested + file_path = mp.get_property_native("stream-path") + + -- edl:// urls can get LONG. In which case, save the path (URL) + -- to a temporary file and use that instead. + local playlist_filename = join_paths(self.state.thumbnail_directory, "playlist.txt") + + if #file_path > 8000 then + -- Path is too long for a playlist - just pass the original URL to + -- workers and allow ytdl + self.state.worker_extra.enable_ytdl = true + file_path = mp.get_property_native("path") + msg.warn("Falling back to original URL and ytdl due to LONG source path. This will be slow.") + + elseif #file_path > 1024 then + local playlist_file = io.open(playlist_filename, "wb") + if not playlist_file then + msg.error(("Tried to write a playlist to %s but couldn't!"):format(playlist_file)) + return false + end + + playlist_file:write(file_path .. "\n") + playlist_file:close() + + file_path = "--playlist=" .. playlist_filename + msg.warn("Using playlist workaround due to long source path") + end + end + + self.state.worker_input_path = file_path + return true +end + +function Thumbnailer:start_worker_jobs() + -- Create directory for the thumbnails, if needed + local l, err = utils.readdir(self.state.thumbnail_directory) + if err then + msg.debug("Creating thumbnail directory", self.state.thumbnail_directory) + create_directories(self.state.thumbnail_directory) + end + + -- Try to prepare the source path for workers, and bail if unable to do so + if not self:prepare_source_path() then + return + end + + local worker_list = {} + for worker_name in pairs(self.workers) do table.insert(worker_list, worker_name) end + + local worker_count = #worker_list + + -- In case we have a worker timer created already, clear it + -- (For example, if the video-dec-params change in quick succession or the user pressed T, etc) + if self.worker_wait_timer then + self.worker_wait_timer:stop() + end + + if worker_count == 0 then + local now = mp.get_time() + if mp.get_time() > self.worker_register_timeout then + -- Workers have had their time to register but we have none! + local err = "No thumbnail workers found. Make sure you are not missing a script!" + msg.error(err) + mp.osd_message(err, 3) + + else + -- We may be too early. Delay the work start a bit to try again. + msg.warn("No workers found. Waiting a bit more for them.") + -- Wait at least half a second + local wait_time = math.max(self.worker_register_timeout - now, 0.5) + self.worker_wait_timer = mp.add_timeout(wait_time, function() self:start_worker_jobs() end) + end + + else + -- We have at least one worker. This may not be all of them, but they have had + -- their time to register; we've done our best waiting for them. + self.state.enabled = true + + msg.debug( ("Splitting %d thumbnails amongst %d worker(s)"):format(self.state.thumbnail_count, worker_count) ) + + local frame_job_order = self:_create_thumbnail_job_order() + local worker_jobs = {} + for i = 1, worker_count do worker_jobs[worker_list[i]] = {} end + + -- Split frames amongst the workers + for i, thumbnail_index in ipairs(frame_job_order) do + local worker_id = worker_list[ ((i-1) % worker_count) + 1 ] + table.insert(worker_jobs[worker_id], thumbnail_index) + end + + local state_json_string = utils.format_json(self.state) + msg.debug("Giving workers state:", state_json_string) + + for worker_name, worker_frames in pairs(worker_jobs) do + if #worker_frames > 0 then + local frames_json_string = utils.format_json(worker_frames) + msg.debug("Assigning job to", worker_name, frames_json_string) + mp.commandv("script-message-to", worker_name, "mpv_thumbnail_script-job", state_json_string, frames_json_string) + end + end + end +end + +mp.register_event("start-file", function() Thumbnailer:on_start_file() end) +mp.observe_property("video-dec-params", "native", function(name, params) Thumbnailer:on_video_change(params) end) +--[[ +This is mpv's original player/lua/osc.lua patched to display thumbnails + +Sections are denoted with -- mpv_thumbnail_script.lua -- +Current osc.lua version: 97816bbef0f97cfda7abdbe560707481d5f68ccd +]]-- + +local assdraw = require 'mp.assdraw' +local msg = require 'mp.msg' +local opt = require 'mp.options' +local utils = require 'mp.utils' + + +-- +-- Parameters +-- + +-- default user option values +-- do not touch, change them in osc.conf +local user_opts = { + showwindowed = true, -- show OSC when windowed? + showfullscreen = true, -- show OSC when fullscreen? + scalewindowed = 1, -- scaling of the controller when windowed + scalefullscreen = 1, -- scaling of the controller when fullscreen + scaleforcedwindow = 2, -- scaling when rendered on a forced window + vidscale = true, -- scale the controller with the video? + valign = 0.8, -- vertical alignment, -1 (top) to 1 (bottom) + halign = 0, -- horizontal alignment, -1 (left) to 1 (right) + barmargin = 0, -- vertical margin of top/bottombar + boxalpha = 80, -- alpha of the background box, + -- 0 (opaque) to 255 (fully transparent) + hidetimeout = 500, -- duration in ms until the OSC hides if no + -- mouse movement. enforced non-negative for the + -- user, but internally negative is "always-on". + fadeduration = 200, -- duration of fade out in ms, 0 = no fade + deadzonesize = 0.5, -- size of deadzone + minmousemove = 0, -- minimum amount of pixels the mouse has to + -- move between ticks to make the OSC show up + iamaprogrammer = false, -- use native mpv values and disable OSC + -- internal track list management (and some + -- functions that depend on it) + layout = "bottombar", + seekbarstyle = "bar", -- slider (diamond marker), knob (circle + -- marker with guide), or bar (fill) + title = "${media-title}", -- string compatible with property-expansion + -- to be shown as OSC title + tooltipborder = 1, -- border of tooltip in bottom/topbar + timetotal = false, -- display total time instead of remaining time? + timems = false, -- display timecodes with milliseconds? + seekranges = true, -- display seek ranges? + visibility = "auto", -- only used at init to set visibility_mode(...) + boxmaxchars = 80, -- title crop threshold for box layout +} + +-- read_options may modify hidetimeout, so save the original default value in +-- case the user set hidetimeout < 0 and we need the default instead. +local hidetimeout_def = user_opts.hidetimeout +-- read options from config and command-line +opt.read_options(user_opts, "osc") +if user_opts.hidetimeout < 0 then + user_opts.hidetimeout = hidetimeout_def + msg.warn("hidetimeout cannot be negative. Using " .. user_opts.hidetimeout) +end + + +-- mpv_thumbnail_script.lua -- + +-- Patch in msg.trace +if not msg.trace then + msg.trace = function(...) return mp.log("trace", ...) end +end + +-- Patch in utils.format_bytes_humanized +if not utils.format_bytes_humanized then + utils.format_bytes_humanized = function(b) + local d = {"Bytes", "KiB", "MiB", "GiB", "TiB", "PiB"} + local i = 1 + while b >= 1024 do + b = b / 1024 + i = i + 1 + end + return string.format("%0.2f %s", b, d[i] and d[i] or "*1024^" .. (i-1)) + end +end + +Thumbnailer:register_client() + +function get_thumbnail_y_offset(thumb_size, msy) + local layout = user_opts.layout + local offset = 0 + + if layout == "bottombar" then + offset = 15 --+ margin + elseif layout == "topbar" then + offset = -(thumb_size.h * msy + 15) + elseif layout == "box" then + offset = 15 + elseif layout == "slimbox" then + offset = 12 + end + + return offset / msy +end + + +local osc_thumb_state = { + visible = false, + overlay_id = 1, + + last_path = nil, + last_x = nil, + last_y = nil, +} + +function hide_thumbnail() + osc_thumb_state.visible = false + osc_thumb_state.last_path = nil + mp.command_native({ "overlay-remove", osc_thumb_state.overlay_id }) +end + +function display_thumbnail(pos, value, ass) + -- If thumbnails are not available, bail + if not (Thumbnailer.state.enabled and Thumbnailer.state.available) then + return + end + + local duration = mp.get_property_number("duration", nil) + if not ((duration == nil) or (value == nil)) then + target_position = duration * (value / 100) + + local msx, msy = get_virt_scale_factor() + local osd_w, osd_h = mp.get_osd_size() + + local thumb_size = Thumbnailer.state.thumbnail_size + local thumb_path, thumb_index, closest_index = Thumbnailer:get_thumbnail_path(target_position) + + local thumbs_ready = Thumbnailer.state.finished_thumbnails + local thumbs_total = Thumbnailer.state.thumbnail_count + local perc = math.floor((thumbs_ready / thumbs_total) * 100) + + local display_progress = thumbs_ready ~= thumbs_total and not thumbnailer_options.hide_progress + + local vertical_offset = thumbnailer_options.vertical_offset + local padding = thumbnailer_options.background_padding + + local pad = { + l = thumbnailer_options.pad_left, r = thumbnailer_options.pad_right, + t = thumbnailer_options.pad_top, b = thumbnailer_options.pad_bot + } + if thumbnailer_options.pad_in_screenspace then + pad.l = pad.l * msx + pad.r = pad.r * msx + pad.t = pad.t * msy + pad.b = pad.b * msy + end + + if thumbnailer_options.offset_by_pad then + vertical_offset = vertical_offset + (user_opts.layout == "topbar" and pad.t or pad.b) + end + + local ass_w = thumb_size.w * msx + local ass_h = thumb_size.h * msy + local y_offset = get_thumbnail_y_offset(thumb_size, 1) + + -- Constrain thumbnail display to window + -- (ie. don't let it go off-screen left/right) + if thumbnailer_options.constrain_to_screen and osd_w > (ass_w + pad.l + pad.r)/msx then + local padded_left = (pad.l + (ass_w / 2)) + local padded_right = (pad.r + (ass_w / 2)) + if pos.x - padded_left < 0 then + pos.x = padded_left + elseif pos.x + padded_right > osd_w*msx then + pos.x = osd_w*msx - padded_right + end + end + + local text_h = 30 * msy + local bg_h = ass_h + (display_progress and text_h or 0) + local bg_left = pos.x - ass_w/2 + local framegraph_h = 10 * msy + + local bg_top = nil + local text_top = nil + local framegraph_top = nil + + if user_opts.layout == "topbar" then + bg_top = pos.y - ( y_offset + thumb_size.h ) + vertical_offset + text_top = bg_top + ass_h + framegraph_h + framegraph_top = bg_top + ass_h + vertical_offset = -vertical_offset + else + bg_top = pos.y - y_offset - bg_h - vertical_offset + text_top = bg_top + framegraph_top = bg_top + 20 * msy + end + + if display_progress then + if user_opts.layout == "topbar" then + pad.b = math.max(0, pad.b - 30) + else + pad.t = math.max(0, pad.t - 30) + end + end + + + + -- Draw background + ass:new_event() + ass:pos(bg_left, bg_top) + ass:append(("{\\bord0\\1c&H%s&\\1a&H%X&}"):format(thumbnailer_options.background_color, thumbnailer_options.background_alpha)) + ass:draw_start() + ass:rect_cw(-pad.l, -pad.t, ass_w+pad.r, bg_h+pad.b) + ass:draw_stop() + + if display_progress then + + ass:new_event() + ass:pos(pos.x, text_top) + ass:an(8) + -- Scale text to correct size + ass:append(("{\\fs20\\bord0\\fscx%f\\fscy%f}"):format(100*msx, 100*msy)) + ass:append(("%d%% - %d/%d"):format(perc, thumbs_ready, thumbs_total)) + + -- Draw the generation progress + local block_w = thumb_size.w * (Thumbnailer.state.thumbnail_delta / duration) * msy + local block_max_x = thumb_size.w * msy + + -- Draw finished thumbnail blocks (white) + ass:new_event() + ass:pos(bg_left, framegraph_top) + ass:append(("{\\bord0\\1c&HFFFFFF&\\1a&H%X&"):format(0)) + ass:draw_start(2) + for i, v in pairs(Thumbnailer.state.thumbnails) do + if i ~= closest_index and v > 0 then + ass:rect_cw((i-1)*block_w, 0, math.min(block_max_x, i*block_w), framegraph_h) + end + end + ass:draw_stop() + + -- Draw in-progress thumbnail blocks (grayish green) + ass:new_event() + ass:pos(bg_left, framegraph_top) + ass:append(("{\\bord0\\1c&H44AA44&\\1a&H%X&"):format(0)) + ass:draw_start(2) + for i, v in pairs(Thumbnailer.state.thumbnails) do + if i ~= closest_index and v == 0 then + ass:rect_cw((i-1)*block_w, 0, math.min(block_max_x, i*block_w), framegraph_h) + end + end + ass:draw_stop() + + if closest_index ~= nil then + ass:new_event() + ass:pos(bg_left, framegraph_top) + ass:append(("{\\bord0\\1c&H4444FF&\\1a&H%X&"):format(0)) + ass:draw_start(2) + ass:rect_cw((closest_index-1)*block_w, 0, math.min(block_max_x, closest_index*block_w), framegraph_h) + ass:draw_stop() + end + end + + if thumb_path then + local overlay_y_offset = get_thumbnail_y_offset(thumb_size, msy) + + local thumb_x = math.floor(pos.x / msx - thumb_size.w/2) + local thumb_y = math.floor(pos.y / msy - thumb_size.h - overlay_y_offset - vertical_offset/msy) + + osc_thumb_state.visible = true + if not (osc_thumb_state.last_path == thumb_path and osc_thumb_state.last_x == thumb_x and osc_thumb_state.last_y == thumb_y) then + local overlay_add_args = { + "overlay-add", osc_thumb_state.overlay_id, + thumb_x, thumb_y, + thumb_path, + 0, + "bgra", + thumb_size.w, thumb_size.h, + 4 * thumb_size.w + } + mp.command_native(overlay_add_args) + + osc_thumb_state.last_path = thumb_path + osc_thumb_state.last_x = thumb_x + osc_thumb_state.last_y = thumb_y + end + end + end +end + +-- // mpv_thumbnail_script.lua // -- + + +local osc_param = { -- calculated by osc_init() + playresy = 0, -- canvas size Y + playresx = 0, -- canvas size X + display_aspect = 1, + unscaled_y = 0, + areas = {}, +} + +local osc_styles = { + bigButtons = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs50\\fnmpv-osd-symbols}", + smallButtonsL = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs19\\fnmpv-osd-symbols}", + smallButtonsLlabel = "{\\fscx105\\fscy105\\fn" .. mp.get_property("options/osd-font") .. "}", + smallButtonsR = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs30\\fnmpv-osd-symbols}", + topButtons = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs12\\fnmpv-osd-symbols}", + + elementDown = "{\\1c&H999999}", + timecodes = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs20}", + vidtitle = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs12\\q2}", + box = "{\\rDefault\\blur0\\bord1\\1c&H000000\\3c&HFFFFFF}", + + topButtonsBar = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs18\\fnmpv-osd-symbols}", + smallButtonsBar = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs28\\fnmpv-osd-symbols}", + timecodesBar = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs27}", + timePosBar = "{\\blur0\\bord".. user_opts.tooltipborder .."\\1c&HFFFFFF\\3c&H000000\\fs30}", + vidtitleBar = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs18\\q2}", +} + +-- internal states, do not touch +local state = { + showtime, -- time of last invocation (last mouse move) + osc_visible = false, + anistart, -- time when the animation started + anitype, -- current type of animation + animation, -- current animation alpha + mouse_down_counter = 0, -- used for softrepeat + active_element = nil, -- nil = none, 0 = background, 1+ = see elements[] + active_event_source = nil, -- the "button" that issued the current event + rightTC_trem = not user_opts.timetotal, -- if the right timecode should display total or remaining time + tc_ms = user_opts.timems, -- Should the timecodes display their time with milliseconds + mp_screen_sizeX, mp_screen_sizeY, -- last screen-resolution, to detect resolution changes to issue reINITs + initREQ = false, -- is a re-init request pending? + last_mouseX, last_mouseY, -- last mouse position, to detect significant mouse movement + message_text, + message_timeout, + fullscreen = false, + timer = nil, + cache_idle = false, + idle = false, + enabled = true, + input_enabled = true, + showhide_enabled = false, +} + + + + +-- +-- Helperfunctions +-- + +-- scale factor for translating between real and virtual ASS coordinates +function get_virt_scale_factor() + local w, h = mp.get_osd_size() + if w <= 0 or h <= 0 then + return 0, 0 + end + return osc_param.playresx / w, osc_param.playresy / h +end + +-- return mouse position in virtual ASS coordinates (playresx/y) +function get_virt_mouse_pos() + local sx, sy = get_virt_scale_factor() + local x, y = mp.get_mouse_pos() + return x * sx, y * sy +end + +function set_virt_mouse_area(x0, y0, x1, y1, name) + local sx, sy = get_virt_scale_factor() + mp.set_mouse_area(x0 / sx, y0 / sy, x1 / sx, y1 / sy, name) +end + +function scale_value(x0, x1, y0, y1, val) + local m = (y1 - y0) / (x1 - x0) + local b = y0 - (m * x0) + return (m * val) + b +end + +-- returns hitbox spanning coordinates (top left, bottom right corner) +-- according to alignment +function get_hitbox_coords(x, y, an, w, h) + + local alignments = { + [1] = function () return x, y-h, x+w, y end, + [2] = function () return x-(w/2), y-h, x+(w/2), y end, + [3] = function () return x-w, y-h, x, y end, + + [4] = function () return x, y-(h/2), x+w, y+(h/2) end, + [5] = function () return x-(w/2), y-(h/2), x+(w/2), y+(h/2) end, + [6] = function () return x-w, y-(h/2), x, y+(h/2) end, + + [7] = function () return x, y, x+w, y+h end, + [8] = function () return x-(w/2), y, x+(w/2), y+h end, + [9] = function () return x-w, y, x, y+h end, + } + + return alignments[an]() +end + +function get_hitbox_coords_geo(geometry) + return get_hitbox_coords(geometry.x, geometry.y, geometry.an, + geometry.w, geometry.h) +end + +function get_element_hitbox(element) + return element.hitbox.x1, element.hitbox.y1, + element.hitbox.x2, element.hitbox.y2 +end + +function mouse_hit(element) + return mouse_hit_coords(get_element_hitbox(element)) +end + +function mouse_hit_coords(bX1, bY1, bX2, bY2) + local mX, mY = get_virt_mouse_pos() + return (mX >= bX1 and mX <= bX2 and mY >= bY1 and mY <= bY2) +end + +function limit_range(min, max, val) + if val > max then + val = max + elseif val < min then + val = min + end + return val +end + +-- translate value into element coordinates +function get_slider_ele_pos_for(element, val) + + local ele_pos = scale_value( + element.slider.min.value, element.slider.max.value, + element.slider.min.ele_pos, element.slider.max.ele_pos, + val) + + return limit_range( + element.slider.min.ele_pos, element.slider.max.ele_pos, + ele_pos) +end + +-- translates global (mouse) coordinates to value +function get_slider_value_at(element, glob_pos) + + local val = scale_value( + element.slider.min.glob_pos, element.slider.max.glob_pos, + element.slider.min.value, element.slider.max.value, + glob_pos) + + return limit_range( + element.slider.min.value, element.slider.max.value, + val) +end + +-- get value at current mouse position +function get_slider_value(element) + return get_slider_value_at(element, get_virt_mouse_pos()) +end + +function countone(val) + if not (user_opts.iamaprogrammer) then + val = val + 1 + end + return val +end + +-- align: -1 .. +1 +-- frame: size of the containing area +-- obj: size of the object that should be positioned inside the area +-- margin: min. distance from object to frame (as long as -1 <= align <= +1) +function get_align(align, frame, obj, margin) + return (frame / 2) + (((frame / 2) - margin - (obj / 2)) * align) +end + +-- multiplies two alpha values, formular can probably be improved +function mult_alpha(alphaA, alphaB) + return 255 - (((1-(alphaA/255)) * (1-(alphaB/255))) * 255) +end + +function add_area(name, x1, y1, x2, y2) + -- create area if needed + if (osc_param.areas[name] == nil) then + osc_param.areas[name] = {} + end + table.insert(osc_param.areas[name], {x1=x1, y1=y1, x2=x2, y2=y2}) +end + + +-- +-- Tracklist Management +-- + +local nicetypes = {video = "Video", audio = "Audio", sub = "Subtitle"} + +-- updates the OSC internal playlists, should be run each time the track-layout changes +function update_tracklist() + local tracktable = mp.get_property_native("track-list", {}) + + -- by osc_id + tracks_osc = {} + tracks_osc.video, tracks_osc.audio, tracks_osc.sub = {}, {}, {} + -- by mpv_id + tracks_mpv = {} + tracks_mpv.video, tracks_mpv.audio, tracks_mpv.sub = {}, {}, {} + for n = 1, #tracktable do + if not (tracktable[n].type == "unknown") then + local type = tracktable[n].type + local mpv_id = tonumber(tracktable[n].id) + + -- by osc_id + table.insert(tracks_osc[type], tracktable[n]) + + -- by mpv_id + tracks_mpv[type][mpv_id] = tracktable[n] + tracks_mpv[type][mpv_id].osc_id = #tracks_osc[type] + end + end +end + +-- return a nice list of tracks of the given type (video, audio, sub) +function get_tracklist(type) + local msg = "Available " .. nicetypes[type] .. " Tracks: " + if #tracks_osc[type] == 0 then + msg = msg .. "none" + else + for n = 1, #tracks_osc[type] do + local track = tracks_osc[type][n] + local lang, title, selected = "unknown", "", "โ—‹" + if not(track.lang == nil) then lang = track.lang end + if not(track.title == nil) then title = track.title end + if (track.id == tonumber(mp.get_property(type))) then + selected = "โ—" + end + msg = msg.."\n"..selected.." "..n..": ["..lang.."] "..title + end + end + return msg +end + +-- relatively change the track of given by tracks + --(+1 -> next, -1 -> previous) +function set_track(type, next) + local current_track_mpv, current_track_osc + if (mp.get_property(type) == "no") then + current_track_osc = 0 + else + current_track_mpv = tonumber(mp.get_property(type)) + current_track_osc = tracks_mpv[type][current_track_mpv].osc_id + end + local new_track_osc = (current_track_osc + next) % (#tracks_osc[type] + 1) + local new_track_mpv + if new_track_osc == 0 then + new_track_mpv = "no" + else + new_track_mpv = tracks_osc[type][new_track_osc].id + end + + mp.commandv("set", type, new_track_mpv) + + if (new_track_osc == 0) then + show_message(nicetypes[type] .. " Track: none") + else + show_message(nicetypes[type] .. " Track: " + .. new_track_osc .. "/" .. #tracks_osc[type] + .. " [".. (tracks_osc[type][new_track_osc].lang or "unknown") .."] " + .. (tracks_osc[type][new_track_osc].title or "")) + end +end + +-- get the currently selected track of , OSC-style counted +function get_track(type) + local track = mp.get_property(type) + if track ~= "no" and track ~= nil then + local tr = tracks_mpv[type][tonumber(track)] + if tr then + return tr.osc_id + end + end + return 0 +end + + +-- +-- Element Management +-- + +local elements = {} + +function prepare_elements() + + -- remove elements without layout or invisble + local elements2 = {} + for n, element in pairs(elements) do + if not (element.layout == nil) and (element.visible) then + table.insert(elements2, element) + end + end + elements = elements2 + + function elem_compare (a, b) + return a.layout.layer < b.layout.layer + end + + table.sort(elements, elem_compare) + + + for _,element in pairs(elements) do + + local elem_geo = element.layout.geometry + + -- Calculate the hitbox + local bX1, bY1, bX2, bY2 = get_hitbox_coords_geo(elem_geo) + element.hitbox = {x1 = bX1, y1 = bY1, x2 = bX2, y2 = bY2} + + local style_ass = assdraw.ass_new() + + -- prepare static elements + style_ass:append("{}") -- hack to troll new_event into inserting a \n + style_ass:new_event() + style_ass:pos(elem_geo.x, elem_geo.y) + style_ass:an(elem_geo.an) + style_ass:append(element.layout.style) + + element.style_ass = style_ass + + local static_ass = assdraw.ass_new() + + + if (element.type == "box") then + --draw box + static_ass:draw_start() + static_ass:round_rect_cw(0, 0, elem_geo.w, elem_geo.h, + element.layout.box.radius) + static_ass:draw_stop() + + + elseif (element.type == "slider") then + --draw static slider parts + + local slider_lo = element.layout.slider + -- offset between element outline and drag-area + local foV = slider_lo.border + slider_lo.gap + + -- calculate positions of min and max points + if (slider_lo.stype == "slider") or + (slider_lo.stype == "knob") then + element.slider.min.ele_pos = elem_geo.h / 2 + element.slider.max.ele_pos = elem_geo.w - (elem_geo.h / 2) + + elseif (slider_lo.stype == "bar") then + element.slider.min.ele_pos = + slider_lo.border + slider_lo.gap + element.slider.max.ele_pos = + elem_geo.w - (slider_lo.border + slider_lo.gap) + end + + element.slider.min.glob_pos = + element.hitbox.x1 + element.slider.min.ele_pos + element.slider.max.glob_pos = + element.hitbox.x1 + element.slider.max.ele_pos + + -- -- -- + + static_ass:draw_start() + + -- the box + static_ass:rect_cw(0, 0, elem_geo.w, elem_geo.h); + + -- the "hole" + static_ass:rect_ccw(slider_lo.border, slider_lo.border, + elem_geo.w - slider_lo.border, elem_geo.h - slider_lo.border) + + -- marker nibbles + if not (element.slider.markerF == nil) and (slider_lo.gap > 0) then + local markers = element.slider.markerF() + for _,marker in pairs(markers) do + if (marker > element.slider.min.value) and + (marker < element.slider.max.value) then + + local s = get_slider_ele_pos_for(element, marker) + + if (slider_lo.gap > 1) then -- draw triangles + + local a = slider_lo.gap / 0.5 --0.866 + + --top + if (slider_lo.nibbles_top) then + static_ass:move_to(s - (a/2), slider_lo.border) + static_ass:line_to(s + (a/2), slider_lo.border) + static_ass:line_to(s, foV) + end + + --bottom + if (slider_lo.nibbles_bottom) then + static_ass:move_to(s - (a/2), + elem_geo.h - slider_lo.border) + static_ass:line_to(s, + elem_geo.h - foV) + static_ass:line_to(s + (a/2), + elem_geo.h - slider_lo.border) + end + + else -- draw 2x1px nibbles + + --top + if (slider_lo.nibbles_top) then + static_ass:rect_cw(s - 1, slider_lo.border, + s + 1, slider_lo.border + slider_lo.gap); + end + + --bottom + if (slider_lo.nibbles_bottom) then + static_ass:rect_cw(s - 1, + elem_geo.h -slider_lo.border -slider_lo.gap, + s + 1, elem_geo.h - slider_lo.border); + end + end + end + end + end + end + + element.static_ass = static_ass + + + -- if the element is supposed to be disabled, + -- style it accordingly and kill the eventresponders + if not (element.enabled) then + element.layout.alpha[1] = 136 + element.eventresponder = nil + end + end +end + + +-- +-- Element Rendering +-- + +function render_elements(master_ass) + + for n=1, #elements do + local element = elements[n] + + local style_ass = assdraw.ass_new() + style_ass:merge(element.style_ass) + + --alpha + local ar = element.layout.alpha + if not (state.animation == nil) then + ar = {} + for ai, av in pairs(element.layout.alpha) do + ar[ai] = mult_alpha(av, state.animation) + end + end + + style_ass:append(string.format("{\\1a&H%X&\\2a&H%X&\\3a&H%X&\\4a&H%X&}", + ar[1], ar[2], ar[3], ar[4])) + + if element.eventresponder and (state.active_element == n) then + + -- run render event functions + if not (element.eventresponder.render == nil) then + element.eventresponder.render(element) + end + + if mouse_hit(element) then + -- mouse down styling + if (element.styledown) then + style_ass:append(osc_styles.elementDown) + end + + if (element.softrepeat) and (state.mouse_down_counter >= 15 + and state.mouse_down_counter % 5 == 0) then + + element.eventresponder[state.active_event_source.."_down"](element) + end + state.mouse_down_counter = state.mouse_down_counter + 1 + end + + end + + local elem_ass = assdraw.ass_new() + + elem_ass:merge(style_ass) + + if not (element.type == "button") then + elem_ass:merge(element.static_ass) + end + + if (element.type == "slider") then + + local slider_lo = element.layout.slider + local elem_geo = element.layout.geometry + local s_min = element.slider.min.value + local s_max = element.slider.max.value + + -- draw pos marker + local pos = element.slider.posF() + + if not (pos == nil) then + + local foV = slider_lo.border + slider_lo.gap + local foH = 0 + if (slider_lo.stype == "slider") or + (slider_lo.stype == "knob") then + foH = elem_geo.h / 2 + elseif (slider_lo.stype == "bar") then + foH = slider_lo.border + slider_lo.gap + end + + local xp = get_slider_ele_pos_for(element, pos) + + -- the filling + local innerH = elem_geo.h - (2*foV) + + if (slider_lo.stype == "bar") then + elem_ass:rect_cw(foH, foV, xp, elem_geo.h - foV) + elseif (slider_lo.stype == "slider") then + elem_ass:move_to(xp, foV) + elem_ass:line_to(xp+(innerH/2), (innerH/2)+foV) + elem_ass:line_to(xp, (innerH)+foV) + elem_ass:line_to(xp-(innerH/2), (innerH/2)+foV) + elseif (slider_lo.stype == "knob") then + elem_ass:rect_cw(xp, (9*innerH/20) + foV, + elem_geo.w - foH, (11*innerH/20) + foV) + elem_ass:rect_cw(foH, (3*innerH/8) + foV, + xp, (5*innerH/8) + foV) + elem_ass:round_rect_cw(xp - innerH/2, foV, + xp + innerH/2, foV + innerH, innerH/2.0) + end + end + + -- seek ranges + local seekRanges = element.slider.seekRangesF() + if not (seekRanges == nil) then + for _,range in pairs(seekRanges) do + local pstart = get_slider_ele_pos_for(element, range["start"]) + local pend = get_slider_ele_pos_for(element, range["end"]) + elem_ass:rect_ccw(pstart, (elem_geo.h/2)-1, pend, (elem_geo.h/2) + 1) + end + end + + elem_ass:draw_stop() + + -- add tooltip + if not (element.slider.tooltipF == nil) then + + if mouse_hit(element) then + local sliderpos = get_slider_value(element) + local tooltiplabel = element.slider.tooltipF(sliderpos) + + local an = slider_lo.tooltip_an + + local ty + + if (an == 2) then + ty = element.hitbox.y1 - slider_lo.border + else + ty = element.hitbox.y1 + elem_geo.h/2 + end + + local tx = get_virt_mouse_pos() + if (slider_lo.adjust_tooltip) then + if (an == 2) then + if (sliderpos < (s_min + 3)) then + an = an - 1 + elseif (sliderpos > (s_max - 3)) then + an = an + 1 + end + elseif (sliderpos > (s_max-s_min)/2) then + an = an + 1 + tx = tx - 5 + else + an = an - 1 + tx = tx + 10 + end + end + + -- tooltip label + elem_ass:new_event() + elem_ass:pos(tx, ty) + elem_ass:an(an) + elem_ass:append(slider_lo.tooltip_style) + + --alpha + local ar = slider_lo.alpha + if not (state.animation == nil) then + ar = {} + for ai, av in pairs(slider_lo.alpha) do + ar[ai] = mult_alpha(av, state.animation) + end + end + elem_ass:append(string.format("{\\1a&H%X&\\2a&H%X&\\3a&H%X&\\4a&H%X&}", + ar[1], ar[2], ar[3], ar[4])) + + elem_ass:append(tooltiplabel) + + -- mpv_thumbnail_script.lua -- + display_thumbnail({x=get_virt_mouse_pos(), y=ty, a=an}, sliderpos, elem_ass) + -- // mpv_thumbnail_script.lua // -- + + end + end + + elseif (element.type == "button") then + + local buttontext + if type(element.content) == "function" then + buttontext = element.content() -- function objects + elseif not (element.content == nil) then + buttontext = element.content -- text objects + end + + local maxchars = element.layout.button.maxchars + if not (maxchars == nil) and (#buttontext > maxchars) then + local max_ratio = 1.25 -- up to 25% more chars while shrinking + local limit = math.max(0, math.floor(maxchars * max_ratio) - 3) + if (#buttontext > limit) then + while (#buttontext > limit) do + buttontext = buttontext:gsub(".[\128-\191]*$", "") + end + buttontext = buttontext .. "..." + end + local _, nchars2 = buttontext:gsub(".[\128-\191]*", "") + local stretch = (maxchars/#buttontext)*100 + buttontext = string.format("{\\fscx%f}", + (maxchars/#buttontext)*100) .. buttontext + end + + elem_ass:append(buttontext) + end + + master_ass:merge(elem_ass) + end +end + +-- +-- Message display +-- + +-- pos is 1 based +function limited_list(prop, pos) + local proplist = mp.get_property_native(prop, {}) + local count = #proplist + if count == 0 then + return count, proplist + end + + local fs = tonumber(mp.get_property('options/osd-font-size')) + local max = math.ceil(osc_param.unscaled_y*0.75 / fs) + if max % 2 == 0 then + max = max - 1 + end + local delta = math.ceil(max / 2) - 1 + local begi = math.max(math.min(pos - delta, count - max + 1), 1) + local endi = math.min(begi + max - 1, count) + + local reslist = {} + for i=begi, endi do + local item = proplist[i] + item.current = (i == pos) and true or nil + table.insert(reslist, item) + end + return count, reslist +end + +function get_playlist() + local pos = mp.get_property_number('playlist-pos', 0) + 1 + local count, limlist = limited_list('playlist', pos) + if count == 0 then + return 'Empty playlist.' + end + + local message = string.format('Playlist [%d/%d]:\n', pos, count) + for i, v in ipairs(limlist) do + local title = v.title + local _, filename = utils.split_path(v.filename) + if title == nil then + title = filename + end + message = string.format('%s %s %s\n', message, + (v.current and 'โ—' or 'โ—‹'), title) + end + return message +end + +function get_chapterlist() + local pos = mp.get_property_number('chapter', 0) + 1 + local count, limlist = limited_list('chapter-list', pos) + if count == 0 then + return 'No chapters.' + end + + local message = string.format('Chapters [%d/%d]:\n', pos, count) + for i, v in ipairs(limlist) do + local time = mp.format_time(v.time) + local title = v.title + if title == nil then + title = string.format('Chapter %02d', i) + end + message = string.format('%s[%s] %s %s\n', message, time, + (v.current and 'โ—' or 'โ—‹'), title) + end + return message +end + +function show_message(text, duration) + + --print("text: "..text.." duration: " .. duration) + if duration == nil then + duration = tonumber(mp.get_property("options/osd-duration")) / 1000 + elseif not type(duration) == "number" then + print("duration: " .. duration) + end + + -- cut the text short, otherwise the following functions + -- may slow down massively on huge input + text = string.sub(text, 0, 4000) + + -- replace actual linebreaks with ASS linebreaks + text = string.gsub(text, "\n", "\\N") + + state.message_text = text + state.message_timeout = mp.get_time() + duration +end + +function render_message(ass) + if not(state.message_timeout == nil) and not(state.message_text == nil) + and state.message_timeout > mp.get_time() then + local _, lines = string.gsub(state.message_text, "\\N", "") + + local fontsize = tonumber(mp.get_property("options/osd-font-size")) + local outline = tonumber(mp.get_property("options/osd-border-size")) + local maxlines = math.ceil(osc_param.unscaled_y*0.75 / fontsize) + local counterscale = osc_param.playresy / osc_param.unscaled_y + + fontsize = fontsize * counterscale / math.max(0.65 + math.min(lines/maxlines, 1), 1) + outline = outline * counterscale / math.max(0.75 + math.min(lines/maxlines, 1)/2, 1) + + local style = "{\\bord" .. outline .. "\\fs" .. fontsize .. "}" + + + ass:new_event() + ass:append(style .. state.message_text) + else + state.message_text = nil + state.message_timeout = nil + end +end + +-- +-- Initialisation and Layout +-- + +function new_element(name, type) + elements[name] = {} + elements[name].type = type + + -- add default stuff + elements[name].eventresponder = {} + elements[name].visible = true + elements[name].enabled = true + elements[name].softrepeat = false + elements[name].styledown = (type == "button") + elements[name].state = {} + + if (type == "slider") then + elements[name].slider = {min = {value = 0}, max = {value = 100}} + end + + + return elements[name] +end + +function add_layout(name) + if not (elements[name] == nil) then + -- new layout + elements[name].layout = {} + + -- set layout defaults + elements[name].layout.layer = 50 + elements[name].layout.alpha = {[1] = 0, [2] = 255, [3] = 255, [4] = 255} + + if (elements[name].type == "button") then + elements[name].layout.button = { + maxchars = nil, + } + elseif (elements[name].type == "slider") then + -- slider defaults + elements[name].layout.slider = { + border = 1, + gap = 1, + nibbles_top = true, + nibbles_bottom = true, + stype = "slider", + adjust_tooltip = true, + tooltip_style = "", + tooltip_an = 2, + alpha = {[1] = 0, [2] = 255, [3] = 88, [4] = 255}, + } + elseif (elements[name].type == "box") then + elements[name].layout.box = {radius = 0} + end + + return elements[name].layout + else + msg.error("Can't add_layout to element \""..name.."\", doesn't exist.") + end +end + +-- +-- Layouts +-- + +local layouts = {} + +-- Classic box layout +layouts["box"] = function () + + local osc_geo = { + w = 550, -- width + h = 138, -- height + r = 10, -- corner-radius + p = 15, -- padding + } + + -- make sure the OSC actually fits into the video + if (osc_param.playresx < (osc_geo.w + (2 * osc_geo.p))) then + osc_param.playresy = (osc_geo.w+(2*osc_geo.p))/osc_param.display_aspect + osc_param.playresx = osc_param.playresy * osc_param.display_aspect + end + + -- position of the controller according to video aspect and valignment + local posX = math.floor(get_align(user_opts.halign, osc_param.playresx, + osc_geo.w, 0)) + local posY = math.floor(get_align(user_opts.valign, osc_param.playresy, + osc_geo.h, 0)) + + -- position offset for contents aligned at the borders of the box + local pos_offsetX = (osc_geo.w - (2*osc_geo.p)) / 2 + local pos_offsetY = (osc_geo.h - (2*osc_geo.p)) / 2 + + osc_param.areas = {} -- delete areas + + -- area for active mouse input + add_area("input", get_hitbox_coords(posX, posY, 5, osc_geo.w, osc_geo.h)) + + -- area for show/hide + local sh_area_y0, sh_area_y1 + if user_opts.valign > 0 then + -- deadzone above OSC + sh_area_y0 = get_align(-1 + (2*user_opts.deadzonesize), + posY - (osc_geo.h / 2), 0, 0) + sh_area_y1 = osc_param.playresy + else + -- deadzone below OSC + sh_area_y0 = 0 + sh_area_y1 = (posY + (osc_geo.h / 2)) + + get_align(1 - (2*user_opts.deadzonesize), + osc_param.playresy - (posY + (osc_geo.h / 2)), 0, 0) + end + add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1) + + -- fetch values + local osc_w, osc_h, osc_r, osc_p = + osc_geo.w, osc_geo.h, osc_geo.r, osc_geo.p + + local lo + + -- + -- Background box + -- + + new_element("bgbox", "box") + lo = add_layout("bgbox") + + lo.geometry = {x = posX, y = posY, an = 5, w = osc_w, h = osc_h} + lo.layer = 10 + lo.style = osc_styles.box + lo.alpha[1] = user_opts.boxalpha + lo.alpha[3] = user_opts.boxalpha + lo.box.radius = osc_r + + -- + -- Title row + -- + + local titlerowY = posY - pos_offsetY - 10 + + lo = add_layout("title") + lo.geometry = {x = posX, y = titlerowY, an = 8, w = 496, h = 12} + lo.style = osc_styles.vidtitle + lo.button.maxchars = user_opts.boxmaxchars + + lo = add_layout("pl_prev") + lo.geometry = + {x = (posX - pos_offsetX), y = titlerowY, an = 7, w = 12, h = 12} + lo.style = osc_styles.topButtons + + lo = add_layout("pl_next") + lo.geometry = + {x = (posX + pos_offsetX), y = titlerowY, an = 9, w = 12, h = 12} + lo.style = osc_styles.topButtons + + -- + -- Big buttons + -- + + local bigbtnrowY = posY - pos_offsetY + 35 + local bigbtndist = 60 + + lo = add_layout("playpause") + lo.geometry = + {x = posX, y = bigbtnrowY, an = 5, w = 40, h = 40} + lo.style = osc_styles.bigButtons + + lo = add_layout("skipback") + lo.geometry = + {x = posX - bigbtndist, y = bigbtnrowY, an = 5, w = 40, h = 40} + lo.style = osc_styles.bigButtons + + lo = add_layout("skipfrwd") + lo.geometry = + {x = posX + bigbtndist, y = bigbtnrowY, an = 5, w = 40, h = 40} + lo.style = osc_styles.bigButtons + + lo = add_layout("ch_prev") + lo.geometry = + {x = posX - (bigbtndist * 2), y = bigbtnrowY, an = 5, w = 40, h = 40} + lo.style = osc_styles.bigButtons + + lo = add_layout("ch_next") + lo.geometry = + {x = posX + (bigbtndist * 2), y = bigbtnrowY, an = 5, w = 40, h = 40} + lo.style = osc_styles.bigButtons + + lo = add_layout("cy_audio") + lo.geometry = + {x = posX - pos_offsetX, y = bigbtnrowY, an = 1, w = 70, h = 18} + lo.style = osc_styles.smallButtonsL + + lo = add_layout("cy_sub") + lo.geometry = + {x = posX - pos_offsetX, y = bigbtnrowY, an = 7, w = 70, h = 18} + lo.style = osc_styles.smallButtonsL + + lo = add_layout("tog_fs") + lo.geometry = + {x = posX+pos_offsetX - 25, y = bigbtnrowY, an = 4, w = 25, h = 25} + lo.style = osc_styles.smallButtonsR + + lo = add_layout("volume") + lo.geometry = + {x = posX+pos_offsetX - (25 * 2) - osc_geo.p, + y = bigbtnrowY, an = 4, w = 25, h = 25} + lo.style = osc_styles.smallButtonsR + + -- + -- Seekbar + -- + + lo = add_layout("seekbar") + lo.geometry = + {x = posX, y = posY+pos_offsetY-22, an = 2, w = pos_offsetX*2, h = 15} + lo.style = osc_styles.timecodes + lo.slider.tooltip_style = osc_styles.vidtitle + lo.slider.stype = user_opts["seekbarstyle"] + if lo.slider.stype == "knob" then + lo.slider.border = 0 + end + + -- + -- Timecodes + Cache + -- + + local bottomrowY = posY + pos_offsetY - 5 + + lo = add_layout("tc_left") + lo.geometry = + {x = posX - pos_offsetX, y = bottomrowY, an = 4, w = 110, h = 18} + lo.style = osc_styles.timecodes + + lo = add_layout("tc_right") + lo.geometry = + {x = posX + pos_offsetX, y = bottomrowY, an = 6, w = 110, h = 18} + lo.style = osc_styles.timecodes + + lo = add_layout("cache") + lo.geometry = + {x = posX, y = bottomrowY, an = 5, w = 110, h = 18} + lo.style = osc_styles.timecodes + +end + +-- slim box layout +layouts["slimbox"] = function () + + local osc_geo = { + w = 660, -- width + h = 70, -- height + r = 10, -- corner-radius + } + + -- make sure the OSC actually fits into the video + if (osc_param.playresx < (osc_geo.w)) then + osc_param.playresy = (osc_geo.w)/osc_param.display_aspect + osc_param.playresx = osc_param.playresy * osc_param.display_aspect + end + + -- position of the controller according to video aspect and valignment + local posX = math.floor(get_align(user_opts.halign, osc_param.playresx, + osc_geo.w, 0)) + local posY = math.floor(get_align(user_opts.valign, osc_param.playresy, + osc_geo.h, 0)) + + osc_param.areas = {} -- delete areas + + -- area for active mouse input + add_area("input", get_hitbox_coords(posX, posY, 5, osc_geo.w, osc_geo.h)) + + -- area for show/hide + local sh_area_y0, sh_area_y1 + if user_opts.valign > 0 then + -- deadzone above OSC + sh_area_y0 = get_align(-1 + (2*user_opts.deadzonesize), + posY - (osc_geo.h / 2), 0, 0) + sh_area_y1 = osc_param.playresy + else + -- deadzone below OSC + sh_area_y0 = 0 + sh_area_y1 = (posY + (osc_geo.h / 2)) + + get_align(1 - (2*user_opts.deadzonesize), + osc_param.playresy - (posY + (osc_geo.h / 2)), 0, 0) + end + add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1) + + local lo + + local tc_w, ele_h, inner_w = 100, 20, osc_geo.w - 100 + + -- styles + local styles = { + box = "{\\rDefault\\blur0\\bord1\\1c&H000000\\3c&HFFFFFF}", + timecodes = "{\\1c&HFFFFFF\\3c&H000000\\fs20\\bord2\\blur1}", + tooltip = "{\\1c&HFFFFFF\\3c&H000000\\fs12\\bord1\\blur0.5}", + } + + + new_element("bgbox", "box") + lo = add_layout("bgbox") + + lo.geometry = {x = posX, y = posY - 1, an = 2, w = inner_w, h = ele_h} + lo.layer = 10 + lo.style = osc_styles.box + lo.alpha[1] = user_opts.boxalpha + lo.alpha[3] = 0 + if not (user_opts["seekbarstyle"] == "bar") then + lo.box.radius = osc_geo.r + end + + + lo = add_layout("seekbar") + lo.geometry = + {x = posX, y = posY - 1, an = 2, w = inner_w, h = ele_h} + lo.style = osc_styles.timecodes + lo.slider.border = 0 + lo.slider.gap = 1.5 + lo.slider.tooltip_style = styles.tooltip + lo.slider.stype = user_opts["seekbarstyle"] + lo.slider.adjust_tooltip = false + + -- + -- Timecodes + -- + + lo = add_layout("tc_left") + lo.geometry = + {x = posX - (inner_w/2) + osc_geo.r, y = posY + 1, + an = 7, w = tc_w, h = ele_h} + lo.style = styles.timecodes + lo.alpha[3] = user_opts.boxalpha + + lo = add_layout("tc_right") + lo.geometry = + {x = posX + (inner_w/2) - osc_geo.r, y = posY + 1, + an = 9, w = tc_w, h = ele_h} + lo.style = styles.timecodes + lo.alpha[3] = user_opts.boxalpha + + -- Cache + + lo = add_layout("cache") + lo.geometry = + {x = posX, y = posY + 1, + an = 8, w = tc_w, h = ele_h} + lo.style = styles.timecodes + lo.alpha[3] = user_opts.boxalpha + + +end + +layouts["bottombar"] = function() + local osc_geo = { + x = -2, + y = osc_param.playresy - 54 - user_opts.barmargin, + an = 7, + w = osc_param.playresx + 4, + h = 56, + } + + local padX = 9 + local padY = 3 + local buttonW = 27 + local tcW = (state.tc_ms) and 170 or 110 + local tsW = 90 + local minW = (buttonW + padX)*5 + (tcW + padX)*4 + (tsW + padX)*2 + + if ((osc_param.display_aspect > 0) and (osc_param.playresx < minW)) then + osc_param.playresy = minW / osc_param.display_aspect + osc_param.playresx = osc_param.playresy * osc_param.display_aspect + osc_geo.y = osc_param.playresy - 54 - user_opts.barmargin + osc_geo.w = osc_param.playresx + 4 + end + + local line1 = osc_geo.y + 9 + padY + local line2 = osc_geo.y + 36 + padY + + osc_param.areas = {} + + add_area("input", get_hitbox_coords(osc_geo.x, osc_geo.y, osc_geo.an, + osc_geo.w, osc_geo.h)) + + local sh_area_y0, sh_area_y1 + sh_area_y0 = get_align(-1 + (2*user_opts.deadzonesize), + osc_geo.y - (osc_geo.h / 2), 0, 0) + sh_area_y1 = osc_param.playresy - user_opts.barmargin + add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1) + + local lo, geo + + -- Background bar + new_element("bgbox", "box") + lo = add_layout("bgbox") + + lo.geometry = osc_geo + lo.layer = 10 + lo.style = osc_styles.box + lo.alpha[1] = user_opts.boxalpha + + + -- Playlist prev/next + geo = { x = osc_geo.x + padX, y = line1, + an = 4, w = 18, h = 18 - padY } + lo = add_layout("pl_prev") + lo.geometry = geo + lo.style = osc_styles.topButtonsBar + + geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("pl_next") + lo.geometry = geo + lo.style = osc_styles.topButtonsBar + + local t_l = geo.x + geo.w + padX + + -- Cache + geo = { x = osc_geo.x + osc_geo.w - padX, y = geo.y, + an = 6, w = 150, h = geo.h } + lo = add_layout("cache") + lo.geometry = geo + lo.style = osc_styles.vidtitleBar + + local t_r = geo.x - geo.w - padX*2 + + -- Title + geo = { x = t_l, y = geo.y, an = 4, + w = t_r - t_l, h = geo.h } + lo = add_layout("title") + lo.geometry = geo + lo.style = string.format("%s{\\clip(%f,%f,%f,%f)}", + osc_styles.vidtitleBar, + geo.x, geo.y-geo.h, geo.w, geo.y+geo.h) + + + -- Playback control buttons + geo = { x = osc_geo.x + padX, y = line2, an = 4, + w = buttonW, h = 36 - padY*2} + lo = add_layout("playpause") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("ch_prev") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("ch_next") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + -- Left timecode + geo = { x = geo.x + geo.w + padX + tcW, y = geo.y, an = 6, + w = tcW, h = geo.h } + lo = add_layout("tc_left") + lo.geometry = geo + lo.style = osc_styles.timecodesBar + + local sb_l = geo.x + padX + + -- Fullscreen button + geo = { x = osc_geo.x + osc_geo.w - buttonW - padX, y = geo.y, an = 4, + w = buttonW, h = geo.h } + lo = add_layout("tog_fs") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + -- Volume + geo = { x = geo.x - geo.w - padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("volume") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + -- Track selection buttons + geo = { x = geo.x - tsW - padX, y = geo.y, an = geo.an, w = tsW, h = geo.h } + lo = add_layout("cy_sub") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + geo = { x = geo.x - geo.w - padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("cy_audio") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + + -- Right timecode + geo = { x = geo.x - padX - tcW - 10, y = geo.y, an = geo.an, + w = tcW, h = geo.h } + lo = add_layout("tc_right") + lo.geometry = geo + lo.style = osc_styles.timecodesBar + + local sb_r = geo.x - padX + + + -- Seekbar + geo = { x = sb_l, y = geo.y, an = geo.an, + w = math.max(0, sb_r - sb_l), h = geo.h } + new_element("bgbar1", "box") + lo = add_layout("bgbar1") + + lo.geometry = geo + lo.layer = 15 + lo.style = osc_styles.timecodesBar + lo.alpha[1] = + math.min(255, user_opts.boxalpha + (255 - user_opts.boxalpha)*0.8) + + lo = add_layout("seekbar") + lo.geometry = geo + lo.style = osc_styles.timecodes + lo.slider.border = 0 + lo.slider.gap = 2 + lo.slider.tooltip_style = osc_styles.timePosBar + lo.slider.tooltip_an = 5 + lo.slider.stype = user_opts["seekbarstyle"] +end + +layouts["topbar"] = function() + local osc_geo = { + x = -2, + y = 54 + user_opts.barmargin, + an = 1, + w = osc_param.playresx + 4, + h = 56, + } + + local padX = 9 + local padY = 3 + local buttonW = 27 + local tcW = (state.tc_ms) and 170 or 110 + local tsW = 90 + local minW = (buttonW + padX)*5 + (tcW + padX)*4 + (tsW + padX)*2 + + if ((osc_param.display_aspect > 0) and (osc_param.playresx < minW)) then + osc_param.playresy = minW / osc_param.display_aspect + osc_param.playresx = osc_param.playresy * osc_param.display_aspect + osc_geo.y = 54 + user_opts.barmargin + osc_geo.w = osc_param.playresx + 4 + end + + local line1 = osc_geo.y - 36 - padY + local line2 = osc_geo.y - 9 - padY + + osc_param.areas = {} + + add_area("input", get_hitbox_coords(osc_geo.x, osc_geo.y, osc_geo.an, + osc_geo.w, osc_geo.h)) + + local sh_area_y0, sh_area_y1 + sh_area_y0 = user_opts.barmargin + sh_area_y1 = (osc_geo.y + (osc_geo.h / 2)) + + get_align(1 - (2*user_opts.deadzonesize), + osc_param.playresy - (osc_geo.y + (osc_geo.h / 2)), 0, 0) + add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1) + + local lo, geo + + -- Background bar + new_element("bgbox", "box") + lo = add_layout("bgbox") + + lo.geometry = osc_geo + lo.layer = 10 + lo.style = osc_styles.box + lo.alpha[1] = user_opts.boxalpha + + + -- Playback control buttons + geo = { x = osc_geo.x + padX, y = line1, an = 4, + w = buttonW, h = 36 - padY*2 } + lo = add_layout("playpause") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("ch_prev") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("ch_next") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + + -- Left timecode + geo = { x = geo.x + geo.w + padX + tcW, y = geo.y, an = 6, + w = tcW, h = geo.h } + lo = add_layout("tc_left") + lo.geometry = geo + lo.style = osc_styles.timecodesBar + + local sb_l = geo.x + padX + + -- Fullscreen button + geo = { x = osc_geo.x + osc_geo.w - buttonW - padX, y = geo.y, an = 4, + w = buttonW, h = geo.h } + lo = add_layout("tog_fs") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + -- Volume + geo = { x = geo.x - geo.w - padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("volume") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + -- Track selection buttons + geo = { x = geo.x - tsW - padX, y = geo.y, an = geo.an, w = tsW, h = geo.h } + lo = add_layout("cy_sub") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + geo = { x = geo.x - geo.w - padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("cy_audio") + lo.geometry = geo + lo.style = osc_styles.smallButtonsBar + + + -- Right timecode + geo = { x = geo.x - geo.w - padX - tcW - 10, y = geo.y, an = 4, + w = tcW, h = geo.h } + lo = add_layout("tc_right") + lo.geometry = geo + lo.style = osc_styles.timecodesBar + + local sb_r = geo.x - padX + + + -- Seekbar + geo = { x = sb_l, y = user_opts.barmargin, an = 7, + w = math.max(0, sb_r - sb_l), h = geo.h } + new_element("bgbar1", "box") + lo = add_layout("bgbar1") + + lo.geometry = geo + lo.layer = 15 + lo.style = osc_styles.timecodesBar + lo.alpha[1] = + math.min(255, user_opts.boxalpha + (255 - user_opts.boxalpha)*0.8) + + lo = add_layout("seekbar") + lo.geometry = geo + lo.style = osc_styles.timecodesBar + lo.slider.border = 0 + lo.slider.gap = 2 + lo.slider.tooltip_style = osc_styles.timePosBar + lo.slider.stype = user_opts["seekbarstyle"] + lo.slider.tooltip_an = 5 + + + -- Playlist prev/next + geo = { x = osc_geo.x + padX, y = line2, an = 4, w = 18, h = 18 - padY } + lo = add_layout("pl_prev") + lo.geometry = geo + lo.style = osc_styles.topButtonsBar + + geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } + lo = add_layout("pl_next") + lo.geometry = geo + lo.style = osc_styles.topButtonsBar + + local t_l = geo.x + geo.w + padX + + -- Cache + geo = { x = osc_geo.x + osc_geo.w - padX, y = geo.y, + an = 6, w = 150, h = geo.h } + lo = add_layout("cache") + lo.geometry = geo + lo.style = osc_styles.vidtitleBar + + local t_r = geo.x - geo.w - padX*2 + + -- Title + geo = { x = t_l, y = geo.y, an = 4, + w = t_r - t_l, h = geo.h } + lo = add_layout("title") + lo.geometry = geo + lo.style = string.format("%s{\\clip(%f,%f,%f,%f)}", + osc_styles.vidtitleBar, + geo.x, geo.y-geo.h, geo.w, geo.y+geo.h) +end + +-- Validate string type user options +function validate_user_opts() + if layouts[user_opts.layout] == nil then + msg.warn("Invalid setting \""..user_opts.layout.."\" for layout") + user_opts.layout = "box" + end + + if user_opts.seekbarstyle ~= "slider" and + user_opts.seekbarstyle ~= "bar" and + user_opts.seekbarstyle ~= "knob" then + msg.warn("Invalid setting \"" .. user_opts.seekbarstyle + .. "\" for seekbarstyle") + user_opts.seekbarstyle = "slider" + end +end + + +-- OSC INIT +function osc_init() + msg.debug("osc_init") + + -- set canvas resolution according to display aspect and scaling setting + local baseResY = 720 + local display_w, display_h, display_aspect = mp.get_osd_size() + local scale = 1 + + if (mp.get_property("video") == "no") then -- dummy/forced window + scale = user_opts.scaleforcedwindow + elseif state.fullscreen then + scale = user_opts.scalefullscreen + else + scale = user_opts.scalewindowed + end + + if user_opts.vidscale then + osc_param.unscaled_y = baseResY + else + osc_param.unscaled_y = display_h + end + osc_param.playresy = osc_param.unscaled_y / scale + if (display_aspect > 0) then + osc_param.display_aspect = display_aspect + end + osc_param.playresx = osc_param.playresy * osc_param.display_aspect + + + + + + elements = {} + + -- some often needed stuff + local pl_count = mp.get_property_number("playlist-count", 0) + local have_pl = (pl_count > 1) + local pl_pos = mp.get_property_number("playlist-pos", 0) + 1 + local have_ch = (mp.get_property_number("chapters", 0) > 0) + local loop = mp.get_property("loop-playlist", "no") + + local ne + + -- title + ne = new_element("title", "button") + + ne.content = function () + local title = mp.command_native({"expand-text", user_opts.title}) + -- escape ASS, and strip newlines and trailing slashes + title = title:gsub("\\n", " "):gsub("\\$", ""):gsub("{","\\{") + return not (title == "") and title or "mpv" + end + + ne.eventresponder["mbtn_left_up"] = function () + local title = mp.get_property_osd("media-title") + if (have_pl) then + title = string.format("[%d/%d] %s", countone(pl_pos - 1), + pl_count, title) + end + show_message(title) + end + + ne.eventresponder["mbtn_right_up"] = + function () show_message(mp.get_property_osd("filename")) end + + -- playlist buttons + + -- prev + ne = new_element("pl_prev", "button") + + ne.content = "\238\132\144" + ne.enabled = (pl_pos > 1) or (loop ~= "no") + ne.eventresponder["mbtn_left_up"] = + function () + mp.commandv("playlist-prev", "weak") + show_message(get_playlist(), 3) + end + ne.eventresponder["shift+mbtn_left_up"] = + function () show_message(get_playlist(), 3) end + ne.eventresponder["mbtn_right_up"] = + function () show_message(get_playlist(), 3) end + + --next + ne = new_element("pl_next", "button") + + ne.content = "\238\132\129" + ne.enabled = (have_pl and (pl_pos < pl_count)) or (loop ~= "no") + ne.eventresponder["mbtn_left_up"] = + function () + mp.commandv("playlist-next", "weak") + show_message(get_playlist(), 3) + end + ne.eventresponder["shift+mbtn_left_up"] = + function () show_message(get_playlist(), 3) end + ne.eventresponder["mbtn_right_up"] = + function () show_message(get_playlist(), 3) end + + + -- big buttons + + --playpause + ne = new_element("playpause", "button") + + ne.content = function () + if mp.get_property("pause") == "yes" then + return ("\238\132\129") + else + return ("\238\128\130") + end + end + ne.eventresponder["mbtn_left_up"] = + function () mp.commandv("cycle", "pause") end + + --skipback + ne = new_element("skipback", "button") + + ne.softrepeat = true + ne.content = "\238\128\132" + ne.eventresponder["mbtn_left_down"] = + function () mp.commandv("seek", -5, "relative", "keyframes") end + ne.eventresponder["shift+mbtn_left_down"] = + function () mp.commandv("frame-back-step") end + ne.eventresponder["mbtn_right_down"] = + function () mp.commandv("seek", -30, "relative", "keyframes") end + + --skipfrwd + ne = new_element("skipfrwd", "button") + + ne.softrepeat = true + ne.content = "\238\128\133" + ne.eventresponder["mbtn_left_down"] = + function () mp.commandv("seek", 10, "relative", "keyframes") end + ne.eventresponder["shift+mbtn_left_down"] = + function () mp.commandv("frame-step") end + ne.eventresponder["mbtn_right_down"] = + function () mp.commandv("seek", 60, "relative", "keyframes") end + + --ch_prev + ne = new_element("ch_prev", "button") + + ne.enabled = have_ch + ne.content = "\238\132\132" + ne.eventresponder["mbtn_left_up"] = + function () + mp.commandv("add", "chapter", -1) + show_message(get_chapterlist(), 3) + end + ne.eventresponder["shift+mbtn_left_up"] = + function () show_message(get_chapterlist(), 3) end + ne.eventresponder["mbtn_right_up"] = + function () show_message(get_chapterlist(), 3) end + + --ch_next + ne = new_element("ch_next", "button") + + ne.enabled = have_ch + ne.content = "\238\132\133" + ne.eventresponder["mbtn_left_up"] = + function () + mp.commandv("add", "chapter", 1) + show_message(get_chapterlist(), 3) + end + ne.eventresponder["shift+mbtn_left_up"] = + function () show_message(get_chapterlist(), 3) end + ne.eventresponder["mbtn_right_up"] = + function () show_message(get_chapterlist(), 3) end + + -- + update_tracklist() + + --cy_audio + ne = new_element("cy_audio", "button") + + ne.enabled = (#tracks_osc.audio > 0) + ne.content = function () + local aid = "โ€“" + if not (get_track("audio") == 0) then + aid = get_track("audio") + end + return ("\238\132\134" .. osc_styles.smallButtonsLlabel + .. " " .. aid .. "/" .. #tracks_osc.audio) + end + ne.eventresponder["mbtn_left_up"] = + function () set_track("audio", 1) end + ne.eventresponder["mbtn_right_up"] = + function () set_track("audio", -1) end + ne.eventresponder["shift+mbtn_left_down"] = + function () show_message(get_tracklist("audio"), 2) end + + --cy_sub + ne = new_element("cy_sub", "button") + + ne.enabled = (#tracks_osc.sub > 0) + ne.content = function () + local sid = "โ€“" + if not (get_track("sub") == 0) then + sid = get_track("sub") + end + return ("\238\132\135" .. osc_styles.smallButtonsLlabel + .. " " .. sid .. "/" .. #tracks_osc.sub) + end + ne.eventresponder["mbtn_left_up"] = + function () set_track("sub", 1) end + ne.eventresponder["mbtn_right_up"] = + function () set_track("sub", -1) end + ne.eventresponder["shift+mbtn_left_down"] = + function () show_message(get_tracklist("sub"), 2) end + + --tog_fs + ne = new_element("tog_fs", "button") + ne.content = function () + if (state.fullscreen) then + return ("\238\132\137") + else + return ("\238\132\136") + end + end + ne.eventresponder["mbtn_left_up"] = + function () mp.commandv("cycle", "fullscreen") end + + + --seekbar + ne = new_element("seekbar", "slider") + + ne.enabled = not (mp.get_property("percent-pos") == nil) + ne.slider.markerF = function () + local duration = mp.get_property_number("duration", nil) + if not (duration == nil) then + local chapters = mp.get_property_native("chapter-list", {}) + local markers = {} + for n = 1, #chapters do + markers[n] = (chapters[n].time / duration * 100) + end + return markers + else + return {} + end + end + ne.slider.posF = + function () return mp.get_property_number("percent-pos", nil) end + ne.slider.tooltipF = function (pos) + local duration = mp.get_property_number("duration", nil) + if not ((duration == nil) or (pos == nil)) then + possec = duration * (pos / 100) + return mp.format_time(possec) + else + return "" + end + end + ne.slider.seekRangesF = function() + if not (user_opts.seekranges) then + return nil + end + local cache_state = mp.get_property_native("demuxer-cache-state", nil) + if not cache_state then + return nil + end + local duration = mp.get_property_number("duration", nil) + if (duration == nil) or duration <= 0 then + return nil + end + local ranges = cache_state["seekable-ranges"] + for _, range in pairs(ranges) do + range["start"] = 100 * range["start"] / duration + range["end"] = 100 * range["end"] / duration + end + return ranges + end + ne.eventresponder["mouse_move"] = --keyframe seeking when mouse is dragged + function (element) + -- mouse move events may pile up during seeking and may still get + -- sent when the user is done seeking, so we need to throw away + -- identical seeks + local seekto = get_slider_value(element) + if (element.state.lastseek == nil) or + (not (element.state.lastseek == seekto)) then + mp.commandv("seek", seekto, + "absolute-percent", "keyframes") + element.state.lastseek = seekto + end + + end + ne.eventresponder["mbtn_left_down"] = --exact seeks on single clicks + function (element) mp.commandv("seek", get_slider_value(element), + "absolute-percent", "exact") end + ne.eventresponder["reset"] = + function (element) element.state.lastseek = nil end + + + -- tc_left (current pos) + ne = new_element("tc_left", "button") + + ne.content = function () + if (state.tc_ms) then + return (mp.get_property_osd("playback-time/full")) + else + return (mp.get_property_osd("playback-time")) + end + end + ne.eventresponder["mbtn_left_up"] = function () + state.tc_ms = not state.tc_ms + request_init() + end + + -- tc_right (total/remaining time) + ne = new_element("tc_right", "button") + + ne.visible = (mp.get_property_number("duration", 0) > 0) + ne.content = function () + if (state.rightTC_trem) then + if state.tc_ms then + return ("-"..mp.get_property_osd("playtime-remaining/full")) + else + return ("-"..mp.get_property_osd("playtime-remaining")) + end + else + if state.tc_ms then + return (mp.get_property_osd("duration/full")) + else + return (mp.get_property_osd("duration")) + end + end + end + ne.eventresponder["mbtn_left_up"] = + function () state.rightTC_trem = not state.rightTC_trem end + + -- cache + ne = new_element("cache", "button") + + ne.content = function () + local dmx_cache = mp.get_property_number("demuxer-cache-duration") + local cache_used = mp.get_property_number("cache-used") + local dmx_cache_state = mp.get_property_native("demuxer-cache-state", {}) + local is_network = mp.get_property_native("demuxer-via-network") + local show_cache = cache_used and not dmx_cache_state["eof"] + if dmx_cache then + dmx_cache = string.format("%3.0fs", dmx_cache) + end + if dmx_cache_state["fw-bytes"] then + cache_used = (cache_used or 0)*1024 + dmx_cache_state["fw-bytes"] + end + if (is_network and dmx_cache) or show_cache then + -- Only show dmx-cache-duration by itself if it's a network file. + -- Cache can be forced even for local files, so always show that. + return string.format("Cache: %s%s%s", + (dmx_cache and dmx_cache or ""), + ((dmx_cache and show_cache) and " | " or ""), + (show_cache and + utils.format_bytes_humanized(cache_used) or "")) + else + return "" + end + end + + -- volume + ne = new_element("volume", "button") + + ne.content = function() + local volume = mp.get_property_number("volume", 0) + local mute = mp.get_property_native("mute") + local volicon = {"\238\132\139", "\238\132\140", + "\238\132\141", "\238\132\142"} + if volume == 0 or mute then + return "\238\132\138" + else + return volicon[math.min(4,math.ceil(volume / (100/3)))] + end + end + ne.eventresponder["mbtn_left_up"] = + function () mp.commandv("cycle", "mute") end + + ne.eventresponder["wheel_up_press"] = + function () mp.commandv("osd-auto", "add", "volume", 5) end + ne.eventresponder["wheel_down_press"] = + function () mp.commandv("osd-auto", "add", "volume", -5) end + + + -- load layout + layouts[user_opts.layout]() + + --do something with the elements + prepare_elements() + +end + + + +-- +-- Other important stuff +-- + + +function show_osc() + -- show when disabled can happen (e.g. mouse_move) due to async/delayed unbinding + if not state.enabled then return end + + msg.trace("show_osc") + --remember last time of invocation (mouse move) + state.showtime = mp.get_time() + + osc_visible(true) + + if (user_opts.fadeduration > 0) then + state.anitype = nil + end +end + +function hide_osc() + msg.trace("hide_osc") + if not state.enabled then + -- typically hide happens at render() from tick(), but now tick() is + -- no-op and won't render again to remove the osc, so do that manually. + state.osc_visible = false + timer_stop() + render_wipe() + elseif (user_opts.fadeduration > 0) then + if not(state.osc_visible == false) then + state.anitype = "out" + control_timer() + end + else + osc_visible(false) + end +end + +function osc_visible(visible) + state.osc_visible = visible + control_timer() +end + +function pause_state(name, enabled) + state.paused = enabled + control_timer() +end + +function cache_state(name, idle) + state.cache_idle = idle + control_timer() +end + +function control_timer() + if (state.paused) and (state.osc_visible) and + ( not(state.cache_idle) or not (state.anitype == nil) ) then + + timer_start() + else + timer_stop() + end +end + +function timer_start() + if not (state.timer_active) then + msg.trace("timer start") + + if (state.timer == nil) then + -- create new timer + state.timer = mp.add_periodic_timer(0.03, tick) + else + -- resume existing one + state.timer:resume() + end + + state.timer_active = true + end +end + +function timer_stop() + if (state.timer_active) then + msg.trace("timer stop") + + if not (state.timer == nil) then + -- kill timer + state.timer:kill() + end + + state.timer_active = false + end +end + + + +function mouse_leave() + if user_opts.hidetimeout >= 0 then + hide_osc() + end + -- reset mouse position + state.last_mouseX, state.last_mouseY = nil, nil +end + +function request_init() + state.initREQ = true +end + +function render_wipe() + msg.trace("render_wipe()") + mp.set_osd_ass(0, 0, "{}") +end + +function render() + msg.trace("rendering") + local current_screen_sizeX, current_screen_sizeY, aspect = mp.get_osd_size() + local mouseX, mouseY = get_virt_mouse_pos() + local now = mp.get_time() + + -- check if display changed, if so request reinit + if not (state.mp_screen_sizeX == current_screen_sizeX + and state.mp_screen_sizeY == current_screen_sizeY) then + + request_init() + + state.mp_screen_sizeX = current_screen_sizeX + state.mp_screen_sizeY = current_screen_sizeY + end + + -- init management + if state.initREQ then + osc_init() + state.initREQ = false + + -- store initial mouse position + if (state.last_mouseX == nil or state.last_mouseY == nil) + and not (mouseX == nil or mouseY == nil) then + + state.last_mouseX, state.last_mouseY = mouseX, mouseY + end + end + + + -- fade animation + if not(state.anitype == nil) then + + if (state.anistart == nil) then + state.anistart = now + end + + if (now < state.anistart + (user_opts.fadeduration/1000)) then + + if (state.anitype == "in") then --fade in + osc_visible(true) + state.animation = scale_value(state.anistart, + (state.anistart + (user_opts.fadeduration/1000)), + 255, 0, now) + elseif (state.anitype == "out") then --fade out + state.animation = scale_value(state.anistart, + (state.anistart + (user_opts.fadeduration/1000)), + 0, 255, now) + end + + else + if (state.anitype == "out") then + osc_visible(false) + end + state.anistart = nil + state.animation = nil + state.anitype = nil + end + else + state.anistart = nil + state.animation = nil + state.anitype = nil + end + + --mouse show/hide area + for k,cords in pairs(osc_param.areas["showhide"]) do + set_virt_mouse_area(cords.x1, cords.y1, cords.x2, cords.y2, "showhide") + end + do_enable_keybindings() + + --mouse input area + local mouse_over_osc = false + + for _,cords in ipairs(osc_param.areas["input"]) do + if state.osc_visible then -- activate only when OSC is actually visible + set_virt_mouse_area(cords.x1, cords.y1, cords.x2, cords.y2, "input") + end + if state.osc_visible ~= state.input_enabled then + if state.osc_visible then + mp.enable_key_bindings("input") + else + mp.disable_key_bindings("input") + end + state.input_enabled = state.osc_visible + end + + if (mouse_hit_coords(cords.x1, cords.y1, cords.x2, cords.y2)) then + mouse_over_osc = true + end + end + + -- autohide + if not (state.showtime == nil) and (user_opts.hidetimeout >= 0) + and (state.showtime + (user_opts.hidetimeout/1000) < now) + and (state.active_element == nil) and not (mouse_over_osc) then + + hide_osc() + end + + + -- actual rendering + local ass = assdraw.ass_new() + + -- Messages + render_message(ass) + + -- mpv_thumbnail_script.lua -- + local thumb_was_visible = osc_thumb_state.visible + osc_thumb_state.visible = false + -- // mpv_thumbnail_script.lua // -- + + -- actual OSC + if state.osc_visible then + render_elements(ass) + end + + -- mpv_thumbnail_script.lua -- + if not osc_thumb_state.visible and thumb_was_visible then + hide_thumbnail() + end + -- // mpv_thumbnail_script.lua // -- + + -- submit + mp.set_osd_ass(osc_param.playresy * osc_param.display_aspect, + osc_param.playresy, ass.text) + + + + +end + +-- +-- Eventhandling +-- + +local function element_has_action(element, action) + return element and element.eventresponder and + element.eventresponder[action] +end + +function process_event(source, what) + local action = string.format("%s%s", source, + what and ("_" .. what) or "") + + if what == "down" or what == "press" then + + for n = 1, #elements do + + if mouse_hit(elements[n]) and + elements[n].eventresponder and + (elements[n].eventresponder[source .. "_up"] or + elements[n].eventresponder[action]) then + + if what == "down" then + state.active_element = n + state.active_event_source = source + end + -- fire the down or press event if the element has one + if element_has_action(elements[n], action) then + elements[n].eventresponder[action](elements[n]) + end + + end + end + + elseif what == "up" then + + if elements[state.active_element] then + local n = state.active_element + + if n == 0 then + --click on background (does not work) + elseif element_has_action(elements[n], action) and + mouse_hit(elements[n]) then + + elements[n].eventresponder[action](elements[n]) + end + + --reset active element + if element_has_action(elements[n], "reset") then + elements[n].eventresponder["reset"](elements[n]) + end + + end + state.active_element = nil + state.mouse_down_counter = 0 + + elseif source == "mouse_move" then + + local mouseX, mouseY = get_virt_mouse_pos() + if (user_opts.minmousemove == 0) or + (not ((state.last_mouseX == nil) or (state.last_mouseY == nil)) and + ((math.abs(mouseX - state.last_mouseX) >= user_opts.minmousemove) + or (math.abs(mouseY - state.last_mouseY) >= user_opts.minmousemove) + ) + ) then + show_osc() + end + state.last_mouseX, state.last_mouseY = mouseX, mouseY + + local n = state.active_element + if element_has_action(elements[n], action) then + elements[n].eventresponder[action](elements[n]) + end + tick() + end +end + +-- called by mpv on every frame +function tick() + if (not state.enabled) then return end + + if (state.idle) then + + -- render idle message + msg.trace("idle message") + local icon_x, icon_y = 320 - 26, 140 + + local ass = assdraw.ass_new() + ass:new_event() + ass:pos(icon_x, icon_y) + ass:append("{\\rDefault\\an7\\c&H430142&\\1a&H00&\\bord0\\shad0\\p6}m 1605 828 b 1605 1175 1324 1456 977 1456 631 1456 349 1175 349 828 349 482 631 200 977 200 1324 200 1605 482 1605 828{\\p0}") + ass:new_event() + ass:pos(icon_x, icon_y) + ass:append("{\\rDefault\\an7\\c&HDDDBDD&\\1a&H00&\\bord0\\shad0\\p6}m 1296 910 b 1296 1131 1117 1310 897 1310 676 1310 497 1131 497 910 497 689 676 511 897 511 1117 511 1296 689 1296 910{\\p0}") + ass:new_event() + ass:pos(icon_x, icon_y) + ass:append("{\\rDefault\\an7\\c&H691F69&\\1a&H00&\\bord0\\shad0\\p6}m 762 1113 l 762 708 b 881 776 1000 843 1119 911 1000 978 881 1046 762 1113{\\p0}") + ass:new_event() + ass:pos(icon_x, icon_y) + ass:append("{\\rDefault\\an7\\c&H682167&\\1a&H00&\\bord0\\shad0\\p6}m 925 42 b 463 42 87 418 87 880 87 1343 463 1718 925 1718 1388 1718 1763 1343 1763 880 1763 418 1388 42 925 42 m 925 42 m 977 200 b 1324 200 1605 482 1605 828 1605 1175 1324 1456 977 1456 631 1456 349 1175 349 828 349 482 631 200 977 200{\\p0}") + ass:new_event() + ass:pos(icon_x, icon_y) + ass:append("{\\rDefault\\an7\\c&H753074&\\1a&H00&\\bord0\\shad0\\p6}m 977 198 b 630 198 348 480 348 828 348 1176 630 1458 977 1458 1325 1458 1607 1176 1607 828 1607 480 1325 198 977 198 m 977 198 m 977 202 b 1323 202 1604 483 1604 828 1604 1174 1323 1454 977 1454 632 1454 351 1174 351 828 351 483 632 202 977 202{\\p0}") + ass:new_event() + ass:pos(icon_x, icon_y) + ass:append("{\\rDefault\\an7\\c&HE5E5E5&\\1a&H00&\\bord0\\shad0\\p6}m 895 10 b 401 10 0 410 0 905 0 1399 401 1800 895 1800 1390 1800 1790 1399 1790 905 1790 410 1390 10 895 10 m 895 10 m 925 42 b 1388 42 1763 418 1763 880 1763 1343 1388 1718 925 1718 463 1718 87 1343 87 880 87 418 463 42 925 42{\\p0}") + ass:new_event() + ass:pos(320, icon_y+65) + ass:an(8) + ass:append("Drop files or URLs to play here.") + mp.set_osd_ass(640, 360, ass.text) + + if state.showhide_enabled then + mp.disable_key_bindings("showhide") + state.showhide_enabled = false + end + + + elseif (state.fullscreen and user_opts.showfullscreen) + or (not state.fullscreen and user_opts.showwindowed) then + + -- render the OSC + render() + else + -- Flush OSD + mp.set_osd_ass(osc_param.playresy, osc_param.playresy, "") + end +end + +function do_enable_keybindings() + if state.enabled then + if not state.showhide_enabled then + mp.enable_key_bindings("showhide", "allow-vo-dragging+allow-hide-cursor") + end + state.showhide_enabled = true + end +end + +function enable_osc(enable) + state.enabled = enable + if enable then + do_enable_keybindings() + else + hide_osc() -- acts immediately when state.enabled == false + if state.showhide_enabled then + mp.disable_key_bindings("showhide") + end + state.showhide_enabled = false + end +end + +-- mpv_thumbnail_script.lua -- + +local builtin_osc_enabled = mp.get_property_native('osc') +if builtin_osc_enabled then + local err = "You must disable the built-in OSC with osc=no in your configuration!" + mp.osd_message(err, 5) + msg.error(err) + + -- This may break, but since we can, let's try to just disable the builtin OSC. + mp.set_property_native('osc', false) +end + +-- // mpv_thumbnail_script.lua // -- + + +validate_user_opts() + +mp.register_event("start-file", request_init) +mp.register_event("tracks-changed", request_init) +mp.observe_property("playlist", nil, request_init) + +mp.register_script_message("osc-message", show_message) +mp.register_script_message("osc-chapterlist", function(dur) + show_message(get_chapterlist(), dur) +end) +mp.register_script_message("osc-playlist", function(dur) + show_message(get_playlist(), dur) +end) +mp.register_script_message("osc-tracklist", function(dur) + local msg = {} + for k,v in pairs(nicetypes) do + table.insert(msg, get_tracklist(k)) + end + show_message(table.concat(msg, '\n\n'), dur) +end) + +mp.observe_property("fullscreen", "bool", + function(name, val) + state.fullscreen = val + request_init() + end +) +mp.observe_property("idle-active", "bool", + function(name, val) + state.idle = val + tick() + end +) +mp.observe_property("pause", "bool", pause_state) +mp.observe_property("cache-idle", "bool", cache_state) +mp.observe_property("vo-configured", "bool", function(name, val) + if val then + mp.register_event("tick", tick) + else + mp.unregister_event(tick) + end +end) + +-- mouse show/hide bindings +mp.set_key_bindings({ + {"mouse_move", function(e) process_event("mouse_move", nil) end}, + {"mouse_leave", mouse_leave}, +}, "showhide", "force") +do_enable_keybindings() + +--mouse input bindings +mp.set_key_bindings({ + {"mbtn_left", function(e) process_event("mbtn_left", "up") end, + function(e) process_event("mbtn_left", "down") end}, + {"shift+mbtn_left", function(e) process_event("shift+mbtn_left", "up") end, + function(e) process_event("shift+mbtn_left", "down") end}, + {"mbtn_right", function(e) process_event("mbtn_right", "up") end, + function(e) process_event("mbtn_right", "down") end}, + {"wheel_up", function(e) process_event("wheel_up", "press") end}, + {"wheel_down", function(e) process_event("wheel_down", "press") end}, + {"mbtn_left_dbl", "ignore"}, + {"shift+mbtn_left_dbl", "ignore"}, + {"mbtn_right_dbl", "ignore"}, +}, "input", "force") +mp.enable_key_bindings("input") + + +user_opts.hidetimeout_orig = user_opts.hidetimeout + +function always_on(val) + if val then + user_opts.hidetimeout = -1 -- disable autohide + if state.enabled then show_osc() end + else + user_opts.hidetimeout = user_opts.hidetimeout_orig + if state.enabled then hide_osc() end + end +end + +-- mode can be auto/always/never/cycle +-- the modes only affect internal variables and not stored on its own. +function visibility_mode(mode, no_osd) + if mode == "cycle" then + if not state.enabled then + mode = "auto" + elseif user_opts.hidetimeout >= 0 then + mode = "always" + else + mode = "never" + end + end + + if mode == "auto" then + always_on(false) + enable_osc(true) + elseif mode == "always" then + enable_osc(true) + always_on(true) + elseif mode == "never" then + enable_osc(false) + else + msg.warn("Ignoring unknown visibility mode '" .. mode .. "'") + return + end + + if not no_osd and tonumber(mp.get_property("osd-level")) >= 1 then + mp.osd_message("OSC visibility: " .. mode) + end +end + +visibility_mode(user_opts.visibility, true) +mp.register_script_message("osc-visibility", visibility_mode) +mp.add_key_binding(nil, "visibility", function() visibility_mode("cycle") end) + +set_virt_mouse_area(0, 0, 0, 0, "input") diff --git a/stow/mpv/.config/mpv/scripts/mpv_thumbnail_script_server.lua b/stow/mpv/.config/mpv/scripts/mpv_thumbnail_script_server.lua new file mode 100644 index 0000000..21a34d8 --- /dev/null +++ b/stow/mpv/.config/mpv/scripts/mpv_thumbnail_script_server.lua @@ -0,0 +1,736 @@ +--[[ + Copyright (C) 2017 AMM + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +]]-- +--[[ + mpv_thumbnail_script.lua 0.4.2 - commit a2de250 (branch master) + https://github.com/TheAMM/mpv_thumbnail_script + Built on 2018-02-07 20:36:54 +]]-- +local assdraw = require 'mp.assdraw' +local msg = require 'mp.msg' +local opt = require 'mp.options' +local utils = require 'mp.utils' + +-- Determine platform -- +ON_WINDOWS = (package.config:sub(1,1) ~= '/') + +-- Some helper functions needed to parse the options -- +function isempty(v) return (v == false) or (v == nil) or (v == "") or (v == 0) or (type(v) == "table" and next(v) == nil) end + +function divmod (a, b) + return math.floor(a / b), a % b +end + +-- Better modulo +function bmod( i, N ) + return (i % N + N) % N +end + +function join_paths(...) + local sep = ON_WINDOWS and "\\" or "/" + local result = ""; + for i, p in pairs({...}) do + if p ~= "" then + if is_absolute_path(p) then + result = p + else + result = (result ~= "") and (result:gsub("[\\"..sep.."]*$", "") .. sep .. p) or p + end + end + end + return result:gsub("[\\"..sep.."]*$", "") +end + +-- /some/path/file.ext -> /some/path, file.ext +function split_path( path ) + local sep = ON_WINDOWS and "\\" or "/" + local first_index, last_index = path:find('^.*' .. sep) + + if last_index == nil then + return "", path + else + local dir = path:sub(0, last_index-1) + local file = path:sub(last_index+1, -1) + + return dir, file + end +end + +function is_absolute_path( path ) + local tmp, is_win = path:gsub("^[A-Z]:\\", "") + local tmp, is_unix = path:gsub("^/", "") + return (is_win > 0) or (is_unix > 0) +end + +function Set(source) + local set = {} + for _, l in ipairs(source) do set[l] = true end + return set +end + +--------------------------- +-- More helper functions -- +--------------------------- + +-- Removes all keys from a table, without destroying the reference to it +function clear_table(target) + for key, value in pairs(target) do + target[key] = nil + end +end +function shallow_copy(target) + local copy = {} + for k, v in pairs(target) do + copy[k] = v + end + return copy +end + +-- Rounds to given decimals. eg. round_dec(3.145, 0) => 3 +function round_dec(num, idp) + local mult = 10^(idp or 0) + return math.floor(num * mult + 0.5) / mult +end + +function file_exists(name) + local f = io.open(name, "rb") + if f ~= nil then + local ok, err, code = f:read(1) + io.close(f) + return code == nil + else + return false + end +end + +function path_exists(name) + local f = io.open(name, "rb") + if f ~= nil then + io.close(f) + return true + else + return false + end +end + +function create_directories(path) + local cmd + if ON_WINDOWS then + cmd = { args = {"cmd", "/c", "mkdir", path} } + else + cmd = { args = {"mkdir", "-p", path} } + end + utils.subprocess(cmd) +end + +-- Find an executable in PATH or CWD with the given name +function find_executable(name) + local delim = ON_WINDOWS and ";" or ":" + + local pwd = os.getenv("PWD") or utils.getcwd() + local path = os.getenv("PATH") + + local env_path = pwd .. delim .. path -- Check CWD first + + local result, filename + for path_dir in env_path:gmatch("[^"..delim.."]+") do + filename = join_paths(path_dir, name) + if file_exists(filename) then + result = filename + break + end + end + + return result +end + +local ExecutableFinder = { path_cache = {} } +-- Searches for an executable and caches the result if any +function ExecutableFinder:get_executable_path( name, raw_name ) + name = ON_WINDOWS and not raw_name and (name .. ".exe") or name + + if self.path_cache[name] == nil then + self.path_cache[name] = find_executable(name) or false + end + return self.path_cache[name] +end + +-- Format seconds to HH.MM.SS.sss +function format_time(seconds, sep, decimals) + decimals = decimals == nil and 3 or decimals + sep = sep and sep or "." + local s = seconds + local h, s = divmod(s, 60*60) + local m, s = divmod(s, 60) + + local second_format = string.format("%%0%d.%df", 2+(decimals > 0 and decimals+1 or 0), decimals) + + return string.format("%02d"..sep.."%02d"..sep..second_format, h, m, s) +end + +-- Format seconds to 1h 2m 3.4s +function format_time_hms(seconds, sep, decimals, force_full) + decimals = decimals == nil and 1 or decimals + sep = sep ~= nil and sep or " " + + local s = seconds + local h, s = divmod(s, 60*60) + local m, s = divmod(s, 60) + + if force_full or h > 0 then + return string.format("%dh"..sep.."%dm"..sep.."%." .. tostring(decimals) .. "fs", h, m, s) + elseif m > 0 then + return string.format("%dm"..sep.."%." .. tostring(decimals) .. "fs", m, s) + else + return string.format("%." .. tostring(decimals) .. "fs", s) + end +end + +-- Writes text on OSD and console +function log_info(txt, timeout) + timeout = timeout or 1.5 + msg.info(txt) + mp.osd_message(txt, timeout) +end + +-- Join table items, ala ({"a", "b", "c"}, "=", "-", ", ") => "=a-, =b-, =c-" +function join_table(source, before, after, sep) + before = before or "" + after = after or "" + sep = sep or ", " + local result = "" + for i, v in pairs(source) do + if not isempty(v) then + local part = before .. v .. after + if i == 1 then + result = part + else + result = result .. sep .. part + end + end + end + return result +end + +function wrap(s, char) + char = char or "'" + return char .. s .. char +end +-- Wraps given string into 'string' and escapes any 's in it +function escape_and_wrap(s, char, replacement) + char = char or "'" + replacement = replacement or "\\" .. char + return wrap(string.gsub(s, char, replacement), char) +end +-- Escapes single quotes in a string and wraps the input in single quotes +function escape_single_bash(s) + return escape_and_wrap(s, "'", "'\\''") +end + +-- Returns (a .. b) if b is not empty or nil +function joined_or_nil(a, b) + return not isempty(b) and (a .. b) or nil +end + +-- Put items from one table into another +function extend_table(target, source) + for i, v in pairs(source) do + table.insert(target, v) + end +end + +-- Creates a handle and filename for a temporary random file (in current directory) +function create_temporary_file(base, mode, suffix) + local handle, filename + suffix = suffix or "" + while true do + filename = base .. tostring(math.random(1, 5000)) .. suffix + handle = io.open(filename, "r") + if not handle then + handle = io.open(filename, mode) + break + end + io.close(handle) + end + return handle, filename +end + + +function get_processor_count() + local proc_count + + if ON_WINDOWS then + proc_count = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) + else + local cpuinfo_handle = io.open("/proc/cpuinfo") + if cpuinfo_handle ~= nil then + local cpuinfo_contents = cpuinfo_handle:read("*a") + local _, replace_count = cpuinfo_contents:gsub('processor', '') + proc_count = replace_count + end + end + + if proc_count and proc_count > 0 then + return proc_count + else + return nil + end +end + +function substitute_values(string, values) + local substitutor = function(match) + if match == "%" then + return "%" + else + -- nil is discarded by gsub + return values[match] + end + end + + local substituted = string:gsub('%%(.)', substitutor) + return substituted +end + +-- ASS HELPERS -- +function round_rect_top( ass, x0, y0, x1, y1, r ) + local c = 0.551915024494 * r -- circle approximation + ass:move_to(x0 + r, y0) + ass:line_to(x1 - r, y0) -- top line + if r > 0 then + ass:bezier_curve(x1 - r + c, y0, x1, y0 + r - c, x1, y0 + r) -- top right corner + end + ass:line_to(x1, y1) -- right line + ass:line_to(x0, y1) -- bottom line + ass:line_to(x0, y0 + r) -- left line + if r > 0 then + ass:bezier_curve(x0, y0 + r - c, x0 + r - c, y0, x0 + r, y0) -- top left corner + end +end + +function round_rect(ass, x0, y0, x1, y1, rtl, rtr, rbr, rbl) + local c = 0.551915024494 + ass:move_to(x0 + rtl, y0) + ass:line_to(x1 - rtr, y0) -- top line + if rtr > 0 then + ass:bezier_curve(x1 - rtr + rtr*c, y0, x1, y0 + rtr - rtr*c, x1, y0 + rtr) -- top right corner + end + ass:line_to(x1, y1 - rbr) -- right line + if rbr > 0 then + ass:bezier_curve(x1, y1 - rbr + rbr*c, x1 - rbr + rbr*c, y1, x1 - rbr, y1) -- bottom right corner + end + ass:line_to(x0 + rbl, y1) -- bottom line + if rbl > 0 then + ass:bezier_curve(x0 + rbl - rbl*c, y1, x0, y1 - rbl + rbl*c, x0, y1 - rbl) -- bottom left corner + end + ass:line_to(x0, y0 + rtl) -- left line + if rtl > 0 then + ass:bezier_curve(x0, y0 + rtl - rtl*c, x0 + rtl - rtl*c, y0, x0 + rtl, y0) -- top left corner + end +end +local SCRIPT_NAME = "mpv_thumbnail_script" + +local default_cache_base = ON_WINDOWS and os.getenv("TEMP") or "/tmp/" + +local thumbnailer_options = { + -- The thumbnail directory + cache_directory = join_paths(default_cache_base, "mpv_thumbs_cache"), + + ------------------------ + -- Generation options -- + ------------------------ + + -- Automatically generate the thumbnails on video load, without a keypress + autogenerate = true, + + -- Only automatically thumbnail videos shorter than this (seconds) + autogenerate_max_duration = 3600, -- 1 hour + + -- SHA1-sum filenames over this length + -- It's nice to know what files the thumbnails are (hence directory names) + -- but long URLs may approach filesystem limits. + hash_filename_length = 128, + + -- Use mpv to generate thumbnail even if ffmpeg is found in PATH + -- ffmpeg does not handle ordered chapters (MKVs which rely on other MKVs)! + -- mpv is a bit slower, but has better support overall (eg. subtitles in the previews) + prefer_mpv = true, + + -- Explicitly disable subtitles on the mpv sub-calls + mpv_no_sub = false, + -- Add a "--no-config" to the mpv sub-call arguments + mpv_no_config = false, + -- Add a "--profile=" to the mpv sub-call arguments + -- Use "" to disable + mpv_profile = "", + -- Output debug logs to .log, ala //000000.bgra.log + -- The logs are removed after successful encodes, unless you set mpv_keep_logs below + mpv_logs = true, + -- Keep all mpv logs, even the succesfull ones + mpv_keep_logs = false, + + -- Disable the built-in keybind ("T") to add your own + disable_keybinds = false, + + --------------------- + -- Display options -- + --------------------- + + -- Move the thumbnail up or down + -- For example: + -- topbar/bottombar: 24 + -- rest: 0 + vertical_offset = 24, + + -- Adjust background padding + -- Examples: + -- topbar: 0, 10, 10, 10 + -- bottombar: 10, 0, 10, 10 + -- slimbox/box: 10, 10, 10, 10 + pad_top = 10, + pad_bot = 0, + pad_left = 10, + pad_right = 10, + + -- If true, pad values are screen-pixels. If false, video-pixels. + pad_in_screenspace = true, + -- Calculate pad into the offset + offset_by_pad = true, + + -- Background color in BBGGRR + background_color = "000000", + -- Alpha: 0 - fully opaque, 255 - transparent + background_alpha = 80, + + -- Keep thumbnail on the screen near left or right side + constrain_to_screen = true, + + -- Do not display the thumbnailing progress + hide_progress = false, + + ----------------------- + -- Thumbnail options -- + ----------------------- + + -- The maximum dimensions of the thumbnails (pixels) + thumbnail_width = 200, + thumbnail_height = 200, + + -- The thumbnail count target + -- (This will result in a thumbnail every ~10 seconds for a 25 minute video) + thumbnail_count = 150, + + -- The above target count will be adjusted by the minimum and + -- maximum time difference between thumbnails. + -- The thumbnail_count will be used to calculate a target separation, + -- and min/max_delta will be used to constrict it. + + -- In other words, thumbnails will be: + -- at least min_delta seconds apart (limiting the amount) + -- at most max_delta seconds apart (raising the amount if needed) + min_delta = 5, + -- 120 seconds aka 2 minutes will add more thumbnails when the video is over 5 hours! + max_delta = 90, + + + -- Overrides for remote urls (you generally want less thumbnails!) + -- Thumbnailing network paths will be done with mpv + + -- Allow thumbnailing network paths (naive check for "://") + thumbnail_network = false, + -- Override thumbnail count, min/max delta + remote_thumbnail_count = 60, + remote_min_delta = 15, + remote_max_delta = 120, + + -- Try to grab the raw stream and disable ytdl for the mpv subcalls + -- Much faster than passing the url to ytdl again, but may cause problems with some sites + remote_direct_stream = true, +} + +read_options(thumbnailer_options, SCRIPT_NAME) +function skip_nil(tbl) + local n = {} + for k, v in pairs(tbl) do + table.insert(n, v) + end + return n +end + +function create_thumbnail_mpv(file_path, timestamp, size, output_path, options) + options = options or {} + + local ytdl_disabled = not options.enable_ytdl and (mp.get_property_native("ytdl") == false + or thumbnailer_options.remote_direct_stream) + + local header_fields_arg = nil + local header_fields = mp.get_property_native("http-header-fields") + if #header_fields > 0 then + -- We can't escape the headers, mpv won't parse "--http-header-fields='Name: value'" properly + header_fields_arg = "--http-header-fields=" .. table.concat(header_fields, ",") + end + + local profile_arg = nil + if thumbnailer_options.mpv_profile ~= "" then + profile_arg = "--profile=" .. thumbnailer_options.mpv_profile + end + + local log_arg = "--log-file=" .. output_path .. ".log" + + local mpv_command = skip_nil({ + "mpv", + -- Hide console output + "--msg-level=all=no", + + -- Disable ytdl + (ytdl_disabled and "--no-ytdl" or nil), + -- Pass HTTP headers from current instance + header_fields_arg, + -- Pass User-Agent and Referer - should do no harm even with ytdl active + "--user-agent=" .. mp.get_property_native("user-agent"), + "--referrer=" .. mp.get_property_native("referrer"), + -- Disable hardware decoding + "--hwdec=no", + + -- Insert --no-config, --profile=... and --log-file if enabled + (thumbnailer_options.mpv_no_config and "--no-config" or nil), + profile_arg, + (thumbnailer_options.mpv_logs and log_arg or nil), + + file_path, + + "--start=" .. tostring(timestamp), + "--frames=1", + "--hr-seek=yes", + "--no-audio", + -- Optionally disable subtitles + (thumbnailer_options.mpv_no_sub and "--no-sub" or nil), + + ("--vf=scale=%d:%d"):format(size.w, size.h), + "--vf-add=format=bgra", + "--of=rawvideo", + "--ovc=rawvideo", + ("--o=%s"):format(output_path) + }) + return utils.subprocess({args=mpv_command}) +end + + +function create_thumbnail_ffmpeg(file_path, timestamp, size, output_path) + local ffmpeg_command = { + "ffmpeg", + "-loglevel", "quiet", + "-noaccurate_seek", + "-ss", format_time(timestamp, ":"), + "-i", file_path, + + "-frames:v", "1", + "-an", + + "-vf", ("scale=%d:%d"):format(size.w, size.h), + "-c:v", "rawvideo", + "-pix_fmt", "bgra", + "-f", "rawvideo", + + "-y", output_path + } + return utils.subprocess({args=ffmpeg_command}) +end + + +function check_output(ret, output_path, is_mpv) + local log_path = output_path .. ".log" + local success = true + + if ret.killed_by_us then + return nil + else + if ret.error or ret.status ~= 0 then + msg.error("Thumbnailing command failed!") + msg.error("mpv process error:", ret.error) + msg.error("Process stdout:", ret.stdout) + if is_mpv then + msg.error("Debug log:", log_path) + end + + success = false + end + + if not file_exists(output_path) then + msg.error("Output file missing!", output_path) + success = false + end + end + + if is_mpv and not thumbnailer_options.mpv_keep_logs then + -- Remove successful debug logs + if success and file_exists(log_path) then + os.remove(log_path) + end + end + + return success +end + + +function do_worker_job(state_json_string, frames_json_string) + msg.debug("Handling given job") + local thumb_state, err = utils.parse_json(state_json_string) + if err then + msg.error("Failed to parse state JSON") + return + end + + local thumbnail_indexes, err = utils.parse_json(frames_json_string) + if err then + msg.error("Failed to parse thumbnail frame indexes") + return + end + + local thumbnail_func = create_thumbnail_mpv + if not thumbnailer_options.prefer_mpv then + if ExecutableFinder:get_executable_path("ffmpeg") then + thumbnail_func = create_thumbnail_ffmpeg + else + msg.warn("Could not find ffmpeg in PATH! Falling back on mpv.") + end + end + + local file_duration = mp.get_property_native("duration") + local file_path = thumb_state.worker_input_path + + if thumb_state.is_remote then + if (thumbnail_func == create_thumbnail_ffmpeg) then + msg.warn("Thumbnailing remote path, falling back on mpv.") + end + thumbnail_func = create_thumbnail_mpv + end + + local generate_thumbnail_for_index = function(thumbnail_index) + -- Given a 1-based thumbnail index, generate a thumbnail for it based on the thumbnailer state + local thumb_idx = thumbnail_index - 1 + msg.debug("Starting work on thumbnail", thumb_idx) + + local thumbnail_path = thumb_state.thumbnail_template:format(thumb_idx) + -- Grab the "middle" of the thumbnail duration instead of the very start, and leave some margin in the end + local timestamp = math.min(file_duration - 0.25, (thumb_idx + 0.5) * thumb_state.thumbnail_delta) + + mp.commandv("script-message", "mpv_thumbnail_script-progress", tostring(thumbnail_index)) + + -- The expected size (raw BGRA image) + local thumbnail_raw_size = (thumb_state.thumbnail_size.w * thumb_state.thumbnail_size.h * 4) + + local need_thumbnail_generation = false + + -- Check if the thumbnail already exists and is the correct size + local thumbnail_file = io.open(thumbnail_path, "rb") + if thumbnail_file == nil then + need_thumbnail_generation = true + else + local existing_thumbnail_filesize = thumbnail_file:seek("end") + if existing_thumbnail_filesize ~= thumbnail_raw_size then + -- Size doesn't match, so (re)generate + msg.warn("Thumbnail", thumb_idx, "did not match expected size, regenerating") + need_thumbnail_generation = true + end + thumbnail_file:close() + end + + if need_thumbnail_generation then + local ret = thumbnail_func(file_path, timestamp, thumb_state.thumbnail_size, thumbnail_path, thumb_state.worker_extra) + local success = check_output(ret, thumbnail_path, thumbnail_func == create_thumbnail_mpv) + + if success == nil then + -- Killed by us, changing files, ignore + msg.debug("Changing files, subprocess killed") + return true + elseif not success then + -- Real failure + mp.osd_message("Thumbnailing failed, check console for details", 3.5) + return true + end + else + msg.debug("Thumbnail", thumb_idx, "already done!") + end + + -- Verify thumbnail size + -- Sometimes ffmpeg will output an empty file when seeking to a "bad" section (usually the end) + thumbnail_file = io.open(thumbnail_path, "rb") + + -- Bail if we can't read the file (it should really exist by now, we checked this in check_output!) + if thumbnail_file == nil then + msg.error("Thumbnail suddenly disappeared!") + return true + end + + -- Check the size of the generated file + local thumbnail_file_size = thumbnail_file:seek("end") + thumbnail_file:close() + + -- Check if the file is big enough + local missing_bytes = math.max(0, thumbnail_raw_size - thumbnail_file_size) + if missing_bytes > 0 then + msg.warn(("Thumbnail missing %d bytes (expected %d, had %d), padding %s"):format( + missing_bytes, thumbnail_raw_size, thumbnail_file_size, thumbnail_path + )) + -- Pad the file if it's missing content (eg. ffmpeg seek to file end) + thumbnail_file = io.open(thumbnail_path, "ab") + thumbnail_file:write(string.rep(string.char(0), missing_bytes)) + thumbnail_file:close() + end + + msg.debug("Finished work on thumbnail", thumb_idx) + mp.commandv("script-message", "mpv_thumbnail_script-ready", tostring(thumbnail_index), thumbnail_path) + end + + msg.debug(("Generating %d thumbnails @ %dx%d for %q"):format( + #thumbnail_indexes, + thumb_state.thumbnail_size.w, + thumb_state.thumbnail_size.h, + file_path)) + + for i, thumbnail_index in ipairs(thumbnail_indexes) do + local bail = generate_thumbnail_for_index(thumbnail_index) + if bail then return end + end + +end + +-- Set up listeners and keybinds + +-- Job listener +mp.register_script_message("mpv_thumbnail_script-job", do_worker_job) + + +-- Register this worker with the master script +local register_timer = nil +local register_timeout = mp.get_time() + 1.5 + +local register_function = function() + if mp.get_time() > register_timeout and register_timer then + msg.error("Thumbnail worker registering timed out") + register_timer:stop() + else + msg.debug("Announcing self to master...") + mp.commandv("script-message", "mpv_thumbnail_script-worker", mp.get_script_name()) + end +end + +register_timer = mp.add_periodic_timer(0.1, register_function) + +mp.register_script_message("mpv_thumbnail_script-slaved", function() + msg.debug("Successfully registered with master") + register_timer:stop() +end) diff --git a/stow/mpv/.config/mpv/scripts/youtube-quality.lua b/stow/mpv/.config/mpv/scripts/youtube-quality.lua new file mode 100644 index 0000000..b587f37 --- /dev/null +++ b/stow/mpv/.config/mpv/scripts/youtube-quality.lua @@ -0,0 +1,275 @@ +-- youtube-quality.lua +-- +-- Change youtube video quality on the fly. +-- +-- Diplays a menu that lets you switch to different ytdl-format settings while +-- you're in the middle of a video (just like you were using the web player). +-- +-- Bound to ctrl-f by default. + +local mp = require 'mp' +local utils = require 'mp.utils' +local msg = require 'mp.msg' +local assdraw = require 'mp.assdraw' + +local opts = { + --key bindings + toggle_menu_binding = "ctrl+f", + up_binding = "UP", + down_binding = "DOWN", + select_binding = "ENTER", + + --formatting / cursors + selected_and_active = "โ–ถ - ", + selected_and_inactive = "โ— - ", + unselected_and_active = "โ–ท - ", + unselected_and_inactive = "โ—‹ - ", + + --font size scales by window, if false requires larger font and padding sizes + scale_playlist_by_window=false, + + --playlist ass style overrides inside curly brackets, \keyvalue is one field, extra \ for escape in lua + --example {\\fnUbuntu\\fs10\\b0\\bord1} equals: font=Ubuntu, size=10, bold=no, border=1 + --read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags + --undeclared tags will use default osd settings + --these styles will be used for the whole playlist. More specific styling will need to be hacked in + -- + --(a monospaced font is recommended but not required) + style_ass_tags = "{\\fnmonospace}", + + --paddings for top left corner + text_padding_x = 5, + text_padding_y = 5, + + --other + menu_timeout = 10, + + --use youtube-dl to fetch a list of available formats (overrides quality_strings) + fetch_formats = true, + + --default menu entries + quality_strings=[[ + [ + {"4320p" : "bestvideo[height<=?4320p]+bestaudio/best"}, + {"2160p" : "bestvideo[height<=?2160]+bestaudio/best"}, + {"1440p" : "bestvideo[height<=?1440]+bestaudio/best"}, + {"1080p" : "bestvideo[height<=?1080]+bestaudio/best"}, + {"720p" : "bestvideo[height<=?720]+bestaudio/best"}, + {"480p" : "bestvideo[height<=?480]+bestaudio/best"}, + {"360p" : "bestvideo[height<=?360]+bestaudio/best"}, + {"240p" : "bestvideo[height<=?240]+bestaudio/best"}, + {"144p" : "bestvideo[height<=?144]+bestaudio/best"} + ] + ]], +} +(require 'mp.options').read_options(opts, "youtube-quality") +opts.quality_strings = utils.parse_json(opts.quality_strings) + +local destroyer = nil + + +function show_menu() + local selected = 1 + local active = 0 + local current_ytdl_format = mp.get_property("ytdl-format") + msg.verbose("current ytdl-format: "..current_ytdl_format) + local num_options = 0 + local options = {} + + + if opts.fetch_formats then + options, num_options = download_formats() + end + + if next(options) == nil then + for i,v in ipairs(opts.quality_strings) do + num_options = num_options + 1 + for k,v2 in pairs(v) do + options[i] = {label = k, format=v2} + if v2 == current_ytdl_format then + active = i + selected = active + end + end + end + end + + --set the cursor to the currently format + for i,v in ipairs(options) do + if v.format == current_ytdl_format then + active = i + selected = active + break + end + end + + function selected_move(amt) + selected = selected + amt + if selected < 1 then selected = num_options + elseif selected > num_options then selected = 1 end + timeout:kill() + timeout:resume() + draw_menu() + end + function choose_prefix(i) + if i == selected and i == active then return opts.selected_and_active + elseif i == selected then return opts.selected_and_inactive end + + if i ~= selected and i == active then return opts.unselected_and_active + elseif i ~= selected then return opts.unselected_and_inactive end + return "> " --shouldn't get here. + end + + function draw_menu() + local ass = assdraw.ass_new() + + ass:pos(opts.text_padding_x, opts.text_padding_y) + ass:append(opts.style_ass_tags) + + for i,v in ipairs(options) do + ass:append(choose_prefix(i)..v.label.."\\N") + end + + local w, h = mp.get_osd_size() + if opts.scale_playlist_by_window then w,h = 0, 0 end + mp.set_osd_ass(w, h, ass.text) + end + + function destroy() + timeout:kill() + mp.set_osd_ass(0,0,"") + mp.remove_key_binding("move_up") + mp.remove_key_binding("move_down") + mp.remove_key_binding("select") + mp.remove_key_binding("escape") + destroyer = nil + end + timeout = mp.add_periodic_timer(opts.menu_timeout, destroy) + destroyer = destroy + + mp.add_forced_key_binding(opts.up_binding, "move_up", function() selected_move(-1) end, {repeatable=true}) + mp.add_forced_key_binding(opts.down_binding, "move_down", function() selected_move(1) end, {repeatable=true}) + mp.add_forced_key_binding(opts.select_binding, "select", function() + destroy() + mp.set_property("ytdl-format", options[selected].format) + reload_resume() + end) + mp.add_forced_key_binding(opts.toggle_menu_binding, "escape", destroy) + + draw_menu() + return +end + +local ytdl = { + path = "youtube-dl", + searched = false, + blacklisted = {} +} + +format_cache={} +function download_formats() + local function exec(args) + local ret = utils.subprocess({args = args}) + return ret.status, ret.stdout, ret + end + + local function table_size(t) + s = 0 + for i,v in ipairs(t) do + s = s+1 + end + return s + end + + local url = mp.get_property("path") + + url = string.gsub(url, "ytdl://", "") -- Strip possible ytdl:// prefix. + + -- don't fetch the format list if we already have it + if format_cache[url] ~= nil then + local res = format_cache[url] + return res, table_size(res) + end + mp.osd_message("fetching available formats with youtube-dl...", 60) + + if not (ytdl.searched) then + local ytdl_mcd = mp.find_config_file("youtube-dl") + if not (ytdl_mcd == nil) then + msg.verbose("found youtube-dl at: " .. ytdl_mcd) + ytdl.path = ytdl_mcd + end + ytdl.searched = true + end + + local command = {ytdl.path, "--no-warnings", "--no-playlist", "-J"} + table.insert(command, url) + local es, json, result = exec(command) + + if (es < 0) or (json == nil) or (json == "") then + mp.osd_message("fetching formats failed...", 1) + msg.error("failed to get format list: " .. err) + return {}, 0 + end + + local json, err = utils.parse_json(json) + + if (json == nil) then + mp.osd_message("fetching formats failed...", 1) + msg.error("failed to parse JSON data: " .. err) + return {}, 0 + end + + res = {} + msg.verbose("youtube-dl succeeded!") + for i,v in ipairs(json.formats) do + if v.vcodec ~= "none" then + local fps = v.fps and v.fps.."fps" or "" + local resolution = string.format("%sx%s", v.width, v.height) + local l = string.format("%-9s %-5s (%-4s / %s)", resolution, fps, v.ext, v.vcodec) + local f = string.format("%s+bestaudio/best", v.format_id) + table.insert(res, {label=l, format=f, width=v.width }) + end + end + + table.sort(res, function(a, b) return a.width > b.width end) + + mp.osd_message("", 0) + format_cache[url] = res + return res, table_size(res) +end + + +-- register script message to show menu +mp.register_script_message("toggle-quality-menu", +function() + if destroyer ~= nil then + destroyer() + else + show_menu() + end +end) + +-- keybind to launch menu +mp.add_key_binding(opts.toggle_menu_binding, "quality-menu", show_menu) + +-- special thanks to reload.lua (https://github.com/4e6/mpv-reload/) +function reload_resume() + local playlist_pos = mp.get_property_number("playlist-pos") + local reload_duration = mp.get_property_native("duration") + local time_pos = mp.get_property("time-pos") + + mp.set_property_number("playlist-pos", playlist_pos) + + -- Tries to determine live stream vs. pre-recordered VOD. VOD has non-zero + -- duration property. When reloading VOD, to keep the current time position + -- we should provide offset from the start. Stream doesn't have fixed start. + -- Decent choice would be to reload stream from it's current 'live' positon. + -- That's the reason we don't pass the offset when reloading streams. + if reload_duration and reload_duration > 0 then + local function seeker() + mp.commandv("seek", time_pos, "absolute") + mp.unregister_event(seeker) + end + mp.register_event("file-loaded", seeker) + end +end diff --git a/stow/mpv/dot-config/mpv/input.conf b/stow/mpv/dot-config/mpv/input.conf deleted file mode 100644 index 3acfb6c..0000000 --- a/stow/mpv/dot-config/mpv/input.conf +++ /dev/null @@ -1,213 +0,0 @@ -# mpv keybindings -# -# Location of user-defined bindings: ~/.config/mpv/input.conf -# -# Lines starting with # are comments. Use SHARP to assign the # key. -# Copy this file and uncomment and edit the bindings you want to change. -# -# List of commands and further details: DOCS/man/input.rst -# List of special keys: --input-keylist -# Keybindings testing mode: mpv --input-test --force-window --idle -# -# Use 'ignore' to unbind a key fully (e.g. 'ctrl+a ignore'). -# -# Strings need to be quoted and escaped: -# KEY show-text "This is a single backslash: \\ and a quote: \" !" -# -# You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with -# the modifiers Shift, Ctrl, Alt and Meta (may not work on the terminal). -# -# The default keybindings are hardcoded into the mpv binary. -# You can disable them completely with: --no-input-default-bindings - -# Developer note: -# On compilation, this file is baked into the mpv binary, and all lines are -# uncommented (unless '#' is followed by a space) - thus this file defines the -# default key bindings. - -# If this is enabled, treat all the following bindings as default. -#default-bindings start - -#MOUSE_BTN0 ignore # don't do anything -#MOUSE_BTN0_DBL cycle fullscreen # toggle fullscreen on/off -#MOUSE_BTN2 cycle pause # toggle pause on/off -#MOUSE_BTN3 seek 10 -#MOUSE_BTN4 seek -10 -#MOUSE_BTN5 add volume -2 -#MOUSE_BTN6 add volume 2 - -# Mouse wheels, touchpad or other input devices that have axes -# if the input devices supports precise scrolling it will also scale the -# numeric value accordingly -#AXIS_UP seek 10 -#AXIS_DOWN seek -10 -#AXIS_LEFT seek 5 -#AXIS_RIGHT seek -5 - -## Seek units are in seconds, but note that these are limited by keyframes -#RIGHT seek 5 -#LEFT seek -5 -#UP seek 60 -#DOWN seek -60 -# Do smaller, always exact (non-keyframe-limited), seeks with shift. -# Don't show them on the OSD (no-osd). -#Shift+RIGHT no-osd seek 1 exact -#Shift+LEFT no-osd seek -1 exact -#Shift+UP no-osd seek 5 exact -#Shift+DOWN no-osd seek -5 exact -# Skip to previous/next subtitle (subject to some restrictions; see manpage) -#Ctrl+LEFT no-osd sub-seek -1 -#Ctrl+RIGHT no-osd sub-seek 1 -#PGUP add chapter 1 # skip to next chapter -#PGDWN add chapter -1 # skip to previous chapter -#Shift+PGUP seek 600 -#Shift+PGDWN seek -600 -#[ multiply speed 0.9091 # scale playback speed -#] multiply speed 1.1 -#{ multiply speed 0.5 -#} multiply speed 2.0 -#BS set speed 1.0 # reset speed to normal -#q quit -#Q quit-watch-later -#q {encode} quit 4 -#ESC set fullscreen no -#ESC {encode} quit 4 -#p cycle pause # toggle pause/playback mode -#. frame-step # advance one frame and pause -#, frame-back-step # go back by one frame and pause -#SPACE cycle pause -#> playlist-next # skip to next file -#ENTER playlist-next # skip to next file -#< playlist-prev # skip to previous file -#O no-osd cycle-values osd-level 3 1 # cycle through OSD mode -#o show-progress -#P show-progress -#I show-text "${filename}" # display filename in osd -#z add sub-delay -0.1 # subtract 100 ms delay from subs -#x add sub-delay +0.1 # add -#ctrl++ add audio-delay 0.100 # this changes audio/video sync -#ctrl+- add audio-delay -0.100 -#9 add volume -2 -#/ add volume -2 -#0 add volume 2 -#* add volume 2 -#m cycle mute -#1 add contrast -1 -#2 add contrast 1 -#3 add brightness -1 -#4 add brightness 1 -#5 add gamma -1 -#6 add gamma 1 -#7 add saturation -1 -#8 add saturation 1 -#Alt+0 set window-scale 0.5 -#Alt+1 set window-scale 1.0 -#Alt+2 set window-scale 2.0 -# toggle deinterlacer (automatically inserts or removes required filter) -#d cycle deinterlace -#r add sub-pos -1 # move subtitles up -#t add sub-pos +1 # down -#v cycle sub-visibility -# stretch SSA/ASS subtitles with anamorphic videos to match historical -#V cycle sub-ass-vsfilter-aspect-compat -# switch between applying no style overrides to SSA/ASS subtitles, and -# overriding them almost completely with the normal subtitle style -#u cycle-values sub-ass-style-override "force" "no" -#j cycle sub # cycle through subtitles -#J cycle sub down # ...backwards -#SHARP cycle audio # switch audio streams -#_ cycle video -#T cycle ontop # toggle video window ontop of other windows -#f cycle fullscreen # toggle fullscreen -#s screenshot # take a screenshot -#S screenshot video # ...without subtitles -#Ctrl+s screenshot window # ...with subtitles and OSD, and scaled -#Alt+s screenshot each-frame # automatically screenshot every frame -#w add panscan -0.1 # zoom out with -panscan 0 -fs -#e add panscan +0.1 # in -# cycle video aspect ratios; "-1" is the container aspect -#A cycle-values video-aspect "16:9" "4:3" "2.35:1" "-1" -#POWER quit -#PLAY cycle pause -#PAUSE cycle pause -#PLAYPAUSE cycle pause -#STOP quit -#FORWARD seek 60 -#REWIND seek -60 -#NEXT playlist-next -#PREV playlist-prev -#VOLUME_UP add volume 2 -#VOLUME_DOWN add volume -2 -#MUTE cycle mute -#CLOSE_WIN quit -#CLOSE_WIN {encode} quit 4 -#E cycle edition # next edition -#l ab-loop # Set/clear A-B loop points -#L cycle-values loop "inf" "no" # toggle infinite looping -#ctrl+c quit 4 - -# Apple Remote section -#AR_PLAY cycle pause -#AR_PLAY_HOLD quit -#AR_CENTER cycle pause -#AR_CENTER_HOLD quit -#AR_NEXT seek 10 -#AR_NEXT_HOLD seek 120 -#AR_PREV seek -10 -#AR_PREV_HOLD seek -120 -#AR_MENU show-progress -#AR_MENU_HOLD cycle mute -#AR_VUP add volume 2 -#AR_VUP_HOLD add chapter 1 -#AR_VDOWN add volume -2 -#AR_VDOWN_HOLD add chapter -1 - -# For tv:// -#h cycle tv-channel -1 # previous channel -#k cycle tv-channel +1 # next channel - -# For dvb:// -#H cycle dvb-channel-name -1 # previous channel -#K cycle dvb-channel-name +1 # next channel - -# -# Legacy bindings (may or may not be removed in the future) -# -#! add chapter -1 # skip to previous chapter -#@ add chapter 1 # next - -# -# Not assigned by default -# (not an exhaustive list of unbound commands) -# - -B add sub-scale +0.1 # increase subtitle font size -b add sub-scale -0.1 # decrease subtitle font size -# ? sub-step -1 # immediately display next subtitle -# ? sub-step +1 # previous -# ? cycle angle # switch DVD/Bluray angle -# ? add balance -0.1 # adjust audio balance in favor of left -# ? add balance 0.1 # right -# ? cycle sub-forced-only # toggle DVD forced subs -# ? cycle program # cycle transport stream programs -# ? stop # stop playback (quit or enter idle mode) - -l seek 5 -h seek -5 -j seek -60 -k seek 60 -Shift+l no-osd seek 1 exact -Shift+h no-osd seek -1 exact -Shift+k no-osd seek 5 exact -Shift+j no-osd seek -5 exact -Ctrl+h no-osd sub-seek -1 -Ctrl+l no-osd sub-seek 1 -Alt+j cycle sub -Alt+J cycle sub down -Alt+l ab-loop # Set/clear A-B loop points -Alt+L cycle-values loop "inf" "no" # toggle infinite looping -i show-text "${media-title}" -I show-text "${filename}" # display filename in osd -c show-text "${chapter-list}" -M show-text "${metadata}" -p show-text "${video-params}" diff --git a/stow/mpv/dot-config/mpv/mpv.conf b/stow/mpv/dot-config/mpv/mpv.conf deleted file mode 100644 index 9e5391f..0000000 --- a/stow/mpv/dot-config/mpv/mpv.conf +++ /dev/null @@ -1,21 +0,0 @@ -# vim: syntax=config - -# OSD -osd-level=1 -osd-font='Linux Libertine' -osd-font-size=45 -osd-color='#FF00B0B0' -osd-bar-w=80 -osd-bar-h=1.5 -osd-bar-align-x=0 -osd-bar-align-y=0.8 - -# Subtitles -sub-border-size=8 - -# Terminal -term-osd-bar -msg-color - -# OSC -osc=no diff --git a/stow/mpv/dot-config/mpv/scripts-opts/mpv_thumbnail_script.conf b/stow/mpv/dot-config/mpv/scripts-opts/mpv_thumbnail_script.conf deleted file mode 100644 index 7380feb..0000000 --- a/stow/mpv/dot-config/mpv/scripts-opts/mpv_thumbnail_script.conf +++ /dev/null @@ -1,70 +0,0 @@ -# The thumbnail cache directory. -# On Windows this defaults to %TEMP%\mpv_thumbs_cache, -# and on other platforms to /tmp/mpv_thumbs_cache. -# The directory will be created automatically, but must be writeable! -# Use absolute paths, and take note that environment variables like %TEMP% are unsupported (despite the default)! -cache_directory=/tmp/my_mpv_thumbnails -# THIS IS NOT A WINDOWS PATH. COMMENT IT OUT OR ADJUST IT YOURSELF. - -# Whether to generate thumbnails automatically on video load, without a keypress -# Defaults to yes -autogenerate=yes - -# Only automatically thumbnail videos shorter than this (in seconds) -# You will have to press T (or your own keybind) to enable the thumbnail previews -# Set to 0 to disable the check, ie. thumbnail videos no matter how long they are -# Defaults to 3600 (one hour) -autogenerate_max_duration=3600 - -# Use mpv to generate thumbnail even if ffmpeg is found in PATH -# ffmpeg is slightly faster than mpv but lacks support for ordered chapters in MKVs, -# which can break the resulting thumbnails. You have been warned. -# Defaults to yes (don't use ffmpeg) -prefer_mpv=yes - -# Explicitly disable subtitles on the mpv sub-calls -# mpv can and will by default render subtitles into the thumbnails. -# If this is not what you wish, set mpv_no_sub to yes -# Defaults to no -mpv_no_sub=no - -# Enable to disable the built-in keybind ("T") to add your own, see after the block -disable_keybinds=no - -# The maximum dimensions of the thumbnails, in pixels -# Defaults to 200 and 200 -thumbnail_width=200 -thumbnail_height=200 - -# The thumbnail count target -# (This will result in a thumbnail every ~10 seconds for a 25 minute video) -thumbnail_count=150 - -# The above target count will be adjusted by the minimum and -# maximum time difference between thumbnails. -# The thumbnail_count will be used to calculate a target separation, -# and min/max_delta will be used to constrict it. - -# In other words, thumbnails will be: -# - at least min_delta seconds apart (limiting the amount) -# - at most max_delta seconds apart (raising the amount if needed) -# Defaults to 5 and 90, values are seconds -min_delta=5 -max_delta=90 -# 120 seconds aka 2 minutes will add more thumbnails only when the video is over 5 hours long! - -# Below are overrides for remote urls (you generally want less thumbnails, because it's slow!) -# Thumbnailing network paths will be done with mpv (leveraging youtube-dl) - -# Allow thumbnailing network paths (naive check for "://") -# Defaults to no -thumbnail_network=yes -# Override thumbnail count, min/max delta, as above -remote_thumbnail_count=60 -remote_min_delta=15 -remote_max_delta=120 - -# Try to grab the raw stream and disable ytdl for the mpv subcalls -# Much faster than passing the url to ytdl again, but may cause problems with some sites -# Defaults to yes -remote_direct_stream=yes diff --git a/stow/mpv/dot-config/mpv/scripts-opts/youtube-quality.conf b/stow/mpv/dot-config/mpv/scripts-opts/youtube-quality.conf deleted file mode 100644 index 9c1a8c9..0000000 --- a/stow/mpv/dot-config/mpv/scripts-opts/youtube-quality.conf +++ /dev/null @@ -1,41 +0,0 @@ -# KEY BINDINGS - -# invoke or dismiss the quality menu -toggle_menu_binding=ctrl+f -# move the menu cursor up -up_binding=UP -# move the menu cursor down -down_binding=DOWN -# select menu entry -select_binding=ENTER - -# formatting / cursors -selected_and_active=โ–ถ - -selected_and_inactive=โ— - -unselected_and_active=โ–ท - -unselected_and_inactive=โ—‹ - - -# font size scales by window, if false requires larger font and padding sizes -scale_playlist_by_window=no - -# playlist ass style overrides inside curly brackets, \keyvalue is one field, extra \ for escape in lua -# example {\\fnUbuntu\\fs10\\b0\\bord1} equals: font=Ubuntu, size=10, bold=no, border=1 -# read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags -# undeclared tags will use default osd settings -# these styles will be used for the whole playlist. More specific styling will need to be hacked in -# -# (a monospaced font is recommended but not required) -style_ass_tags={\\fnmonospace} - -# paddings for top left corner -text_padding_x=5 -text_padding_y=5 - -# how many seconds until the quality menu times out -menu_timeout=10 - -#use youtube-dl to fetch a list of available formats (overrides quality_strings) -fetch_formats=yes - -# list of ytdl-format strings to choose from -quality_strings=[ {"4320p" : "bestvideo[height<=?4320p]+bestaudio/best"}, {"2160p" : "bestvideo[height<=?2160]+bestaudio/best"}, {"1440p" : "bestvideo[height<=?1440]+bestaudio/best"}, {"1080p" : "bestvideo[height<=?1080]+bestaudio/best"}, {"720p" : "bestvideo[height<=?720]+bestaudio/best"}, {"480p" : "bestvideo[height<=?480]+bestaudio/best"}, {"360p" : "bestvideo[height<=?360]+bestaudio/best"}, {"240p" : "bestvideo[height<=?240]+bestaudio/best"}, {"144p" : "bestvideo[height<=?144]+bestaudio/best"} ] diff --git a/stow/mpv/dot-config/mpv/scripts/mpv-splice.lua b/stow/mpv/dot-config/mpv/scripts/mpv-splice.lua deleted file mode 100644 index b121dc4..0000000 --- a/stow/mpv/dot-config/mpv/scripts/mpv-splice.lua +++ /dev/null @@ -1,328 +0,0 @@ --- ----------------------------------------------------------------------------- --- --- MPV Splice --- URL: https://github.com/pvpscript/mpv-video-splice --- --- Requires: ffmpeg --- --- Description: --- --- This script provides the hability to create video slices by grabbing two --- timestamps, which generate a slice from timestamp A[i] to timestamp B[i], --- e.g.: --- -> Slice 1: 00:10:34.25 -> 00:15:00.00. --- -> Slice 2: 00:23:00.84 -> 00:24:10.00. --- ... --- -> Slice n: 01:44:22.47 -> 01:56:00.00. --- --- Then, all the slices from 1 to n are joined together, creating a new --- video. --- --- The output file will appear at the directory that the mpv command was ran, --- or in the environment variable set for it (see Environment variables below) --- --- Note: This script prevents the mpv player from closing when the video ends, --- so that the slices don't get lost. Keep this in mind if there's the option --- 'keep-open=no' in the current config file. --- --- Note: This script will also silence the terminal, so the script messages --- can be seen more clearly. --- --- ----------------------------------------------------------------------------- --- --- --- Usage: --- --- In the video screen, press Alt + T to grab the first timestamp and then --- press Alt + T again to get the second timestamp. This process will generate --- a time range, which represents a video slice. Repeat this process to create --- more slices. --- --- To see all the slices made, press Alt + P. All of the slices will appear --- in the terminal in order of creation, with their corresponding timestamps. --- Incomplete slices will show up as 'Slice N in progress', where N is the --- slice number. --- --- To reset an incomplete slice, press Alt + R. If the first part of a slice --- was created at the wrong time, this will reset the current slice. --- --- To delete a whole slice, start the slice deletion mode by pressing Alt + D. --- When in this mode, it's possible to press Alt + NUM, where NUM is any --- number between 0 inclusive and 9 inclusive. For each Alt + NUM pressed, a --- number will be concatenated to make the final number referring to the slice --- to be removed, then press Alt + D again to stop the slicing deletion mode --- and delete the slice corresponding to the formed number. --- --- Example 1: Deleting slice number 3 --- -> Alt + D # Start slice deletion mode --- -> Alt + 3 # Concatenate number 3 --- -> Alt + D # Exit slice deletion mode --- --- Example 2> Deleting slice number 76 --- -> Alt + D # Start slice deletion mode --- -> Alt + 7 # Concatenate number 7 --- -> Alt + 6 # Concatenate number 6 --- -> Alt + D # Exit slice deletion mode --- --- To fire up ffmpeg, which will slice up the video and concatenate the slices --- together, press Alt + C. It's important that there are at least one --- slice, otherwise no video will be created. --- --- Note: No cut will be made unless the user presses Alt + C. --- Also, the original video file won't be affected by the cutting. --- --- --- ----------------------------------------------------------------------------- --- --- --- Log level: --- --- Everytime a timestamp is grabbed, a text will appear on the screen showing --- the selected time. --- When Alt + P is pressed, besides showing the slices in the terminal, --- it will also show on the screen the total number of cuts (or slices) --- that were made. --- When the actual cutting and joining process begins, a message will be shown --- on the screen and the terminal telling that it began. When the process ends, --- a message will appear on the screen and the terminal displaying the full path --- of the generated video. It will also appear a message in the terminal telling --- that the process ended. --- --- Note: Every message that appears on the terminal has the log level of 'info'. --- --- --- ----------------------------------------------------------------------------- --- --- --- Environment Variables: --- --- This script uses environment variables to allow the user to --- set the temporary location of the video cuts and for setting the location for --- the resulting video. --- --- To set the temporary directory, set the variable MPV_SPLICE_TEMP; --- e.g.: export MPV_SPLICE_TEMP="$HOME/temporary_location" --- --- To set the video output directory, set the variable MPV_SPLICE_OUTPUT; --- e.g.: export MPV_SPLICE_OUTPUT="$HOME/output_location" --- --- Make sure the directories set in the variables really exist, or else the --- script might fail. --- --- ----------------------------------------------------------------------------- - --------------------------------------------------------------------------------- --- Importing the mpv libraries - -local mp = require 'mp' -local msg = require 'mp.msg' - --------------------------------------------------------------------------------- --- Default variables - -local default_tmp_location = "/tmp" -local default_output_location = mp.get_property("working-directory") - --------------------------------------------------------------------------------- - -local concat_name = "concat.txt" - -local ffmpeg = "ffmpeg -hide_banner -loglevel warning" - -local tmp_location = os.getenv("MPV_SPLICE_TEMP") - and os.getenv("MPV_SPLICE_TEMP") - or default_tmp_location -local output_location = os.getenv("MPV_SPLICE_OUTPUT") - and os.getenv("MPV_SPLICE_OUTPUT") - or default_output_location - -local times = {} -local start_time = nil -local remove_val = "" - -local exit_time = 0 - --------------------------------------------------------------------------------- - -function notify(duration, ...) - local args = {...} - local text = "" - - for i, v in ipairs(args) do - text = text .. tostring(v) - end - - msg.info(text) - mp.command(string.format("show-text \"%s\" %d 1", - text, duration)) -end - -local function get_time() - local time_in_secs = mp.get_property_number('time-pos') - - local hours = math.floor(time_in_secs / 3600) - local mins = math.floor((time_in_secs - hours * 3600) / 60) - local secs = time_in_secs - hours * 3600 - mins * 60 - - local fmt_time = string.format('%02d:%02d:%05.2f', hours, mins, secs) - - return fmt_time -end - -function put_time() - local time = get_time() - local message = "" - - if not start_time then - start_time = time - message = "[START TIMESTAMP]" - else - --times[#times+1] = { - table.insert(times, { - t_start = start_time, - t_end = time - }) - start_time = nil - - message = "[END TIMESTAMP]" - end - - notify(2000, message, ": ", time) -end - -function show_times() - notify(2000, "Total cuts: ", #times) - - for i, obj in ipairs(times) do - msg.info("Slice", i, ": ", obj.t_start, " -> ", obj.t_end) - end - if start_time then - notify(2000, "Slice ", #times+1, " in progress.") - end -end - -function reset_current_slice() - if start_time then - notify(2000, "Slice ", #times+1, " reseted.") - - start_time = nil - end -end - -function delete_slice() - if remove_val == "" then - notify(2000, "Entered slice deletion mode.") - - -- Add shortcut keys to the interval {0..9}. - for i=0,9,1 do - mp.add_key_binding("Alt+" .. i, "num_key_" .. i, - function() - remove_val = remove_val .. i - notify(1000, "Slice to remove: " - .. remove_val) - end - ) - end - else - -- Remove previously added shortcut keys. - for i=0,9,1 do - mp.remove_key_binding("num_key_" .. i) - end - - remove_num = tonumber(remove_val) - if #times >= remove_num and remove_num > 0 then - table.remove(times, remove_num) - notify(2000, "Removed slice ", remove_num) - end - - remove_val = "" - - msg.info("Exited slice deletion mode.") - end -end - -function prevent_quit(name) - if start_time then - if os.time() - exit_time <= 2 then - mp.command(name) - else - exit_time = os.time() - end - notify(3000, "Slice has been marked. Press again to quit") - else - mp.command(name) - end -end - -function process_video() - local alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - local rnd_size = 10 - - local pieces = {} - - -- Better seed randomization - math.randomseed(os.time()) - math.random(); math.random(); math.random() - - if times[#times] then - local tmp_dir = io.popen(string.format("mktemp -d -p %s", - tmp_location)):read("*l") - local input_file = mp.get_property("path") - local ext = string.gmatch(input_file, ".*%.(.*)$")() - - local rnd_str = "" - for i=1,rnd_size,1 do - local rnd_index = math.floor(math.random() * #alphabet + 0.5) - rnd_str = rnd_str .. alphabet:sub(rnd_index, rnd_index) - end - - local output_file = string.format("%s/%s_%s_cut.%s", - output_location, - mp.get_property("filename/no-ext"), - rnd_str, ext) - - local cat_file_name = string.format("%s/%s", tmp_dir, "concat.txt") - local cat_file_ptr = io.open(cat_file_name, "w") - - notify(2000, "Process started!") - - for i, obj in ipairs(times) do - local path = string.format("%s/%s_%d.%s", - tmp_dir, rnd_str, i, ext) - cat_file_ptr:write(string.format("file '%s'\n", path)) - os.execute(string.format("%s -ss %s -i \"%s\" -to %s " .. - "-c copy -copyts -avoid_negative_ts make_zero \"%s\"", - ffmpeg, obj.t_start, input_file, obj.t_end, - path)) - end - - cat_file_ptr:close() - - cmd = string.format("%s -f concat -safe 0 -i \"%s\" " .. - "-c copy \"%s\"", - ffmpeg, cat_file_name, output_file) - os.execute(cmd) - - notify(10000, "File saved as: ", output_file) - msg.info("Process ended!") - - os.execute(string.format("rm -rf %s", tmp_dir)) - msg.info("Temporary directory removed!") - end -end - -mp.set_property("keep-open", "yes") -- Prevent mpv from exiting when the video ends -mp.set_property("quiet", "yes") -- Silence terminal. - -mp.add_key_binding('q', "quit", function() - prevent_quit("quit") -end) -mp.add_key_binding('Shift+q', "quit-watch-later", function() - prevent_quit("quit-watch-later") -end) - -mp.add_key_binding('Alt+t', "put_time", put_time) -mp.add_key_binding('Alt+p', "show_times", show_times) -mp.add_key_binding('Alt+c', "process_video", process_video) -mp.add_key_binding('Alt+r', "reset_current_slice", reset_current_slice) -mp.add_key_binding('Alt+d', "delete_slice", delete_slice) diff --git a/stow/mpv/dot-config/mpv/scripts/mpv_thumbnail_script_client_osc.lua b/stow/mpv/dot-config/mpv/scripts/mpv_thumbnail_script_client_osc.lua deleted file mode 100644 index e822846..0000000 --- a/stow/mpv/dot-config/mpv/scripts/mpv_thumbnail_script_client_osc.lua +++ /dev/null @@ -1,3886 +0,0 @@ ---[[ - Copyright (C) 2017 AMM - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -]]-- ---[[ - mpv_thumbnail_script.lua 0.4.2 - commit a2de250 (branch master) - https://github.com/TheAMM/mpv_thumbnail_script - Built on 2018-02-07 20:36:55 -]]-- -local assdraw = require 'mp.assdraw' -local msg = require 'mp.msg' -local opt = require 'mp.options' -local utils = require 'mp.utils' - --- Determine platform -- -ON_WINDOWS = (package.config:sub(1,1) ~= '/') - --- Some helper functions needed to parse the options -- -function isempty(v) return (v == false) or (v == nil) or (v == "") or (v == 0) or (type(v) == "table" and next(v) == nil) end - -function divmod (a, b) - return math.floor(a / b), a % b -end - --- Better modulo -function bmod( i, N ) - return (i % N + N) % N -end - -function join_paths(...) - local sep = ON_WINDOWS and "\\" or "/" - local result = ""; - for i, p in pairs({...}) do - if p ~= "" then - if is_absolute_path(p) then - result = p - else - result = (result ~= "") and (result:gsub("[\\"..sep.."]*$", "") .. sep .. p) or p - end - end - end - return result:gsub("[\\"..sep.."]*$", "") -end - --- /some/path/file.ext -> /some/path, file.ext -function split_path( path ) - local sep = ON_WINDOWS and "\\" or "/" - local first_index, last_index = path:find('^.*' .. sep) - - if last_index == nil then - return "", path - else - local dir = path:sub(0, last_index-1) - local file = path:sub(last_index+1, -1) - - return dir, file - end -end - -function is_absolute_path( path ) - local tmp, is_win = path:gsub("^[A-Z]:\\", "") - local tmp, is_unix = path:gsub("^/", "") - return (is_win > 0) or (is_unix > 0) -end - -function Set(source) - local set = {} - for _, l in ipairs(source) do set[l] = true end - return set -end - ---------------------------- --- More helper functions -- ---------------------------- - --- Removes all keys from a table, without destroying the reference to it -function clear_table(target) - for key, value in pairs(target) do - target[key] = nil - end -end -function shallow_copy(target) - local copy = {} - for k, v in pairs(target) do - copy[k] = v - end - return copy -end - --- Rounds to given decimals. eg. round_dec(3.145, 0) => 3 -function round_dec(num, idp) - local mult = 10^(idp or 0) - return math.floor(num * mult + 0.5) / mult -end - -function file_exists(name) - local f = io.open(name, "rb") - if f ~= nil then - local ok, err, code = f:read(1) - io.close(f) - return code == nil - else - return false - end -end - -function path_exists(name) - local f = io.open(name, "rb") - if f ~= nil then - io.close(f) - return true - else - return false - end -end - -function create_directories(path) - local cmd - if ON_WINDOWS then - cmd = { args = {"cmd", "/c", "mkdir", path} } - else - cmd = { args = {"mkdir", "-p", path} } - end - utils.subprocess(cmd) -end - --- Find an executable in PATH or CWD with the given name -function find_executable(name) - local delim = ON_WINDOWS and ";" or ":" - - local pwd = os.getenv("PWD") or utils.getcwd() - local path = os.getenv("PATH") - - local env_path = pwd .. delim .. path -- Check CWD first - - local result, filename - for path_dir in env_path:gmatch("[^"..delim.."]+") do - filename = join_paths(path_dir, name) - if file_exists(filename) then - result = filename - break - end - end - - return result -end - -local ExecutableFinder = { path_cache = {} } --- Searches for an executable and caches the result if any -function ExecutableFinder:get_executable_path( name, raw_name ) - name = ON_WINDOWS and not raw_name and (name .. ".exe") or name - - if self.path_cache[name] == nil then - self.path_cache[name] = find_executable(name) or false - end - return self.path_cache[name] -end - --- Format seconds to HH.MM.SS.sss -function format_time(seconds, sep, decimals) - decimals = decimals == nil and 3 or decimals - sep = sep and sep or "." - local s = seconds - local h, s = divmod(s, 60*60) - local m, s = divmod(s, 60) - - local second_format = string.format("%%0%d.%df", 2+(decimals > 0 and decimals+1 or 0), decimals) - - return string.format("%02d"..sep.."%02d"..sep..second_format, h, m, s) -end - --- Format seconds to 1h 2m 3.4s -function format_time_hms(seconds, sep, decimals, force_full) - decimals = decimals == nil and 1 or decimals - sep = sep ~= nil and sep or " " - - local s = seconds - local h, s = divmod(s, 60*60) - local m, s = divmod(s, 60) - - if force_full or h > 0 then - return string.format("%dh"..sep.."%dm"..sep.."%." .. tostring(decimals) .. "fs", h, m, s) - elseif m > 0 then - return string.format("%dm"..sep.."%." .. tostring(decimals) .. "fs", m, s) - else - return string.format("%." .. tostring(decimals) .. "fs", s) - end -end - --- Writes text on OSD and console -function log_info(txt, timeout) - timeout = timeout or 1.5 - msg.info(txt) - mp.osd_message(txt, timeout) -end - --- Join table items, ala ({"a", "b", "c"}, "=", "-", ", ") => "=a-, =b-, =c-" -function join_table(source, before, after, sep) - before = before or "" - after = after or "" - sep = sep or ", " - local result = "" - for i, v in pairs(source) do - if not isempty(v) then - local part = before .. v .. after - if i == 1 then - result = part - else - result = result .. sep .. part - end - end - end - return result -end - -function wrap(s, char) - char = char or "'" - return char .. s .. char -end --- Wraps given string into 'string' and escapes any 's in it -function escape_and_wrap(s, char, replacement) - char = char or "'" - replacement = replacement or "\\" .. char - return wrap(string.gsub(s, char, replacement), char) -end --- Escapes single quotes in a string and wraps the input in single quotes -function escape_single_bash(s) - return escape_and_wrap(s, "'", "'\\''") -end - --- Returns (a .. b) if b is not empty or nil -function joined_or_nil(a, b) - return not isempty(b) and (a .. b) or nil -end - --- Put items from one table into another -function extend_table(target, source) - for i, v in pairs(source) do - table.insert(target, v) - end -end - --- Creates a handle and filename for a temporary random file (in current directory) -function create_temporary_file(base, mode, suffix) - local handle, filename - suffix = suffix or "" - while true do - filename = base .. tostring(math.random(1, 5000)) .. suffix - handle = io.open(filename, "r") - if not handle then - handle = io.open(filename, mode) - break - end - io.close(handle) - end - return handle, filename -end - - -function get_processor_count() - local proc_count - - if ON_WINDOWS then - proc_count = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) - else - local cpuinfo_handle = io.open("/proc/cpuinfo") - if cpuinfo_handle ~= nil then - local cpuinfo_contents = cpuinfo_handle:read("*a") - local _, replace_count = cpuinfo_contents:gsub('processor', '') - proc_count = replace_count - end - end - - if proc_count and proc_count > 0 then - return proc_count - else - return nil - end -end - -function substitute_values(string, values) - local substitutor = function(match) - if match == "%" then - return "%" - else - -- nil is discarded by gsub - return values[match] - end - end - - local substituted = string:gsub('%%(.)', substitutor) - return substituted -end - --- ASS HELPERS -- -function round_rect_top( ass, x0, y0, x1, y1, r ) - local c = 0.551915024494 * r -- circle approximation - ass:move_to(x0 + r, y0) - ass:line_to(x1 - r, y0) -- top line - if r > 0 then - ass:bezier_curve(x1 - r + c, y0, x1, y0 + r - c, x1, y0 + r) -- top right corner - end - ass:line_to(x1, y1) -- right line - ass:line_to(x0, y1) -- bottom line - ass:line_to(x0, y0 + r) -- left line - if r > 0 then - ass:bezier_curve(x0, y0 + r - c, x0 + r - c, y0, x0 + r, y0) -- top left corner - end -end - -function round_rect(ass, x0, y0, x1, y1, rtl, rtr, rbr, rbl) - local c = 0.551915024494 - ass:move_to(x0 + rtl, y0) - ass:line_to(x1 - rtr, y0) -- top line - if rtr > 0 then - ass:bezier_curve(x1 - rtr + rtr*c, y0, x1, y0 + rtr - rtr*c, x1, y0 + rtr) -- top right corner - end - ass:line_to(x1, y1 - rbr) -- right line - if rbr > 0 then - ass:bezier_curve(x1, y1 - rbr + rbr*c, x1 - rbr + rbr*c, y1, x1 - rbr, y1) -- bottom right corner - end - ass:line_to(x0 + rbl, y1) -- bottom line - if rbl > 0 then - ass:bezier_curve(x0 + rbl - rbl*c, y1, x0, y1 - rbl + rbl*c, x0, y1 - rbl) -- bottom left corner - end - ass:line_to(x0, y0 + rtl) -- left line - if rtl > 0 then - ass:bezier_curve(x0, y0 + rtl - rtl*c, x0 + rtl - rtl*c, y0, x0 + rtl, y0) -- top left corner - end -end --- $Revision: 1.5 $ --- $Date: 2014-09-10 16:54:25 $ - --- This module was originally taken from http://cube3d.de/uploads/Main/sha1.txt. - -------------------------------------------------------------------------------- --- SHA-1 secure hash computation, and HMAC-SHA1 signature computation, --- in pure Lua (tested on Lua 5.1) --- License: MIT --- --- Usage: --- local hashAsHex = sha1.hex(message) -- returns a hex string --- local hashAsData = sha1.bin(message) -- returns raw bytes --- --- local hmacAsHex = sha1.hmacHex(key, message) -- hex string --- local hmacAsData = sha1.hmacBin(key, message) -- raw bytes --- --- --- Pass sha1.hex() a string, and it returns a hash as a 40-character hex string. --- For example, the call --- --- local hash = sha1.hex("iNTERFACEWARE") --- --- puts the 40-character string --- --- "e76705ffb88a291a0d2f9710a5471936791b4819" --- --- into the variable 'hash' --- --- Pass sha1.hmacHex() a key and a message, and it returns the signature as a --- 40-byte hex string. --- --- --- The two "bin" versions do the same, but return the 20-byte string of raw --- data that the 40-byte hex strings represent. --- -------------------------------------------------------------------------------- --- --- Description --- Due to the lack of bitwise operations in 5.1, this version uses numbers to --- represents the 32bit words that we combine with binary operations. The basic --- operations of byte based "xor", "or", "and" are all cached in a combination --- table (several 64k large tables are built on startup, which --- consumes some memory and time). The caching can be switched off through --- setting the local cfg_caching variable to false. --- For all binary operations, the 32 bit numbers are split into 8 bit values --- that are combined and then merged again. --- --- Algorithm: http://www.itl.nist.gov/fipspubs/fip180-1.htm --- -------------------------------------------------------------------------------- - -local sha1 = (function() -local sha1 = {} - --- set this to false if you don't want to build several 64k sized tables when --- loading this file (takes a while but grants a boost of factor 13) -local cfg_caching = false --- local storing of global functions (minor speedup) -local floor,modf = math.floor,math.modf -local char,format,rep = string.char,string.format,string.rep - --- merge 4 bytes to an 32 bit word -local function bytes_to_w32 (a,b,c,d) return a*0x1000000+b*0x10000+c*0x100+d end --- split a 32 bit word into four 8 bit numbers -local function w32_to_bytes (i) - return floor(i/0x1000000)%0x100,floor(i/0x10000)%0x100,floor(i/0x100)%0x100,i%0x100 -end - --- shift the bits of a 32 bit word. Don't use negative values for "bits" -local function w32_rot (bits,a) - local b2 = 2^(32-bits) - local a,b = modf(a/b2) - return a+b*b2*(2^(bits)) -end - --- caching function for functions that accept 2 arguments, both of values between --- 0 and 255. The function to be cached is passed, all values are calculated --- during loading and a function is returned that returns the cached values (only) -local function cache2arg (fn) - if not cfg_caching then return fn end - local lut = {} - for i=0,0xffff do - local a,b = floor(i/0x100),i%0x100 - lut[i] = fn(a,b) - end - return function (a,b) - return lut[a*0x100+b] - end -end - --- splits an 8-bit number into 8 bits, returning all 8 bits as booleans -local function byte_to_bits (b) - local b = function (n) - local b = floor(b/n) - return b%2==1 - end - return b(1),b(2),b(4),b(8),b(16),b(32),b(64),b(128) -end - --- builds an 8bit number from 8 booleans -local function bits_to_byte (a,b,c,d,e,f,g,h) - local function n(b,x) return b and x or 0 end - return n(a,1)+n(b,2)+n(c,4)+n(d,8)+n(e,16)+n(f,32)+n(g,64)+n(h,128) -end - --- debug function for visualizing bits in a string -local function bits_to_string (a,b,c,d,e,f,g,h) - local function x(b) return b and "1" or "0" end - return ("%s%s%s%s %s%s%s%s"):format(x(a),x(b),x(c),x(d),x(e),x(f),x(g),x(h)) -end - --- debug function for converting a 8-bit number as bit string -local function byte_to_bit_string (b) - return bits_to_string(byte_to_bits(b)) -end - --- debug function for converting a 32 bit number as bit string -local function w32_to_bit_string(a) - if type(a) == "string" then return a end - local aa,ab,ac,ad = w32_to_bytes(a) - local s = byte_to_bit_string - return ("%s %s %s %s"):format(s(aa):reverse(),s(ab):reverse(),s(ac):reverse(),s(ad):reverse()):reverse() -end - --- bitwise "and" function for 2 8bit number -local band = cache2arg (function(a,b) - local A,B,C,D,E,F,G,H = byte_to_bits(b) - local a,b,c,d,e,f,g,h = byte_to_bits(a) - return bits_to_byte( - A and a, B and b, C and c, D and d, - E and e, F and f, G and g, H and h) - end) - --- bitwise "or" function for 2 8bit numbers -local bor = cache2arg(function(a,b) - local A,B,C,D,E,F,G,H = byte_to_bits(b) - local a,b,c,d,e,f,g,h = byte_to_bits(a) - return bits_to_byte( - A or a, B or b, C or c, D or d, - E or e, F or f, G or g, H or h) - end) - --- bitwise "xor" function for 2 8bit numbers -local bxor = cache2arg(function(a,b) - local A,B,C,D,E,F,G,H = byte_to_bits(b) - local a,b,c,d,e,f,g,h = byte_to_bits(a) - return bits_to_byte( - A ~= a, B ~= b, C ~= c, D ~= d, - E ~= e, F ~= f, G ~= g, H ~= h) - end) - --- bitwise complement for one 8bit number -local function bnot (x) - return 255-(x % 256) -end - --- creates a function to combine to 32bit numbers using an 8bit combination function -local function w32_comb(fn) - return function (a,b) - local aa,ab,ac,ad = w32_to_bytes(a) - local ba,bb,bc,bd = w32_to_bytes(b) - return bytes_to_w32(fn(aa,ba),fn(ab,bb),fn(ac,bc),fn(ad,bd)) - end -end - --- create functions for and, xor and or, all for 2 32bit numbers -local w32_and = w32_comb(band) -local w32_xor = w32_comb(bxor) -local w32_or = w32_comb(bor) - --- xor function that may receive a variable number of arguments -local function w32_xor_n (a,...) - local aa,ab,ac,ad = w32_to_bytes(a) - for i=1,select('#',...) do - local ba,bb,bc,bd = w32_to_bytes(select(i,...)) - aa,ab,ac,ad = bxor(aa,ba),bxor(ab,bb),bxor(ac,bc),bxor(ad,bd) - end - return bytes_to_w32(aa,ab,ac,ad) -end - --- combining 3 32bit numbers through binary "or" operation -local function w32_or3 (a,b,c) - local aa,ab,ac,ad = w32_to_bytes(a) - local ba,bb,bc,bd = w32_to_bytes(b) - local ca,cb,cc,cd = w32_to_bytes(c) - return bytes_to_w32( - bor(aa,bor(ba,ca)), bor(ab,bor(bb,cb)), bor(ac,bor(bc,cc)), bor(ad,bor(bd,cd)) - ) -end - --- binary complement for 32bit numbers -local function w32_not (a) - return 4294967295-(a % 4294967296) -end - --- adding 2 32bit numbers, cutting off the remainder on 33th bit -local function w32_add (a,b) return (a+b) % 4294967296 end - --- adding n 32bit numbers, cutting off the remainder (again) -local function w32_add_n (a,...) - for i=1,select('#',...) do - a = (a+select(i,...)) % 4294967296 - end - return a -end --- converting the number to a hexadecimal string -local function w32_to_hexstring (w) return format("%08x",w) end - --- calculating the SHA1 for some text -function sha1.hex(msg) - local H0,H1,H2,H3,H4 = 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0 - local msg_len_in_bits = #msg * 8 - - local first_append = char(0x80) -- append a '1' bit plus seven '0' bits - - local non_zero_message_bytes = #msg +1 +8 -- the +1 is the appended bit 1, the +8 are for the final appended length - local current_mod = non_zero_message_bytes % 64 - local second_append = current_mod>0 and rep(char(0), 64 - current_mod) or "" - - -- now to append the length as a 64-bit number. - local B1, R1 = modf(msg_len_in_bits / 0x01000000) - local B2, R2 = modf( 0x01000000 * R1 / 0x00010000) - local B3, R3 = modf( 0x00010000 * R2 / 0x00000100) - local B4 = 0x00000100 * R3 - - local L64 = char( 0) .. char( 0) .. char( 0) .. char( 0) -- high 32 bits - .. char(B1) .. char(B2) .. char(B3) .. char(B4) -- low 32 bits - - msg = msg .. first_append .. second_append .. L64 - - assert(#msg % 64 == 0) - - local chunks = #msg / 64 - - local W = { } - local start, A, B, C, D, E, f, K, TEMP - local chunk = 0 - - while chunk < chunks do - -- - -- break chunk up into W[0] through W[15] - -- - start,chunk = chunk * 64 + 1,chunk + 1 - - for t = 0, 15 do - W[t] = bytes_to_w32(msg:byte(start, start + 3)) - start = start + 4 - end - - -- - -- build W[16] through W[79] - -- - for t = 16, 79 do - -- For t = 16 to 79 let Wt = S1(Wt-3 XOR Wt-8 XOR Wt-14 XOR Wt-16). - W[t] = w32_rot(1, w32_xor_n(W[t-3], W[t-8], W[t-14], W[t-16])) - end - - A,B,C,D,E = H0,H1,H2,H3,H4 - - for t = 0, 79 do - if t <= 19 then - -- (B AND C) OR ((NOT B) AND D) - f = w32_or(w32_and(B, C), w32_and(w32_not(B), D)) - K = 0x5A827999 - elseif t <= 39 then - -- B XOR C XOR D - f = w32_xor_n(B, C, D) - K = 0x6ED9EBA1 - elseif t <= 59 then - -- (B AND C) OR (B AND D) OR (C AND D - f = w32_or3(w32_and(B, C), w32_and(B, D), w32_and(C, D)) - K = 0x8F1BBCDC - else - -- B XOR C XOR D - f = w32_xor_n(B, C, D) - K = 0xCA62C1D6 - end - - -- TEMP = S5(A) + ft(B,C,D) + E + Wt + Kt; - A,B,C,D,E = w32_add_n(w32_rot(5, A), f, E, W[t], K), - A, w32_rot(30, B), C, D - end - -- Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E. - H0,H1,H2,H3,H4 = w32_add(H0, A),w32_add(H1, B),w32_add(H2, C),w32_add(H3, D),w32_add(H4, E) - end - local f = w32_to_hexstring - return f(H0) .. f(H1) .. f(H2) .. f(H3) .. f(H4) -end - -local function hex_to_binary(hex) - return hex:gsub('..', function(hexval) - return string.char(tonumber(hexval, 16)) - end) -end - -function sha1.bin(msg) - return hex_to_binary(sha1.hex(msg)) -end - -local xor_with_0x5c = {} -local xor_with_0x36 = {} --- building the lookuptables ahead of time (instead of littering the source code --- with precalculated values) -for i=0,0xff do - xor_with_0x5c[char(i)] = char(bxor(i,0x5c)) - xor_with_0x36[char(i)] = char(bxor(i,0x36)) -end - -local blocksize = 64 -- 512 bits - -function sha1.hmacHex(key, text) - assert(type(key) == 'string', "key passed to hmacHex should be a string") - assert(type(text) == 'string', "text passed to hmacHex should be a string") - - if #key > blocksize then - key = sha1.bin(key) - end - - local key_xord_with_0x36 = key:gsub('.', xor_with_0x36) .. string.rep(string.char(0x36), blocksize - #key) - local key_xord_with_0x5c = key:gsub('.', xor_with_0x5c) .. string.rep(string.char(0x5c), blocksize - #key) - - return sha1.hex(key_xord_with_0x5c .. sha1.bin(key_xord_with_0x36 .. text)) -end - -function sha1.hmacBin(key, text) - return hex_to_binary(sha1.hmacHex(key, text)) -end - -return sha1 -end)() - -local SCRIPT_NAME = "mpv_thumbnail_script" - -local default_cache_base = ON_WINDOWS and os.getenv("TEMP") or "/tmp/" - -local thumbnailer_options = { - -- The thumbnail directory - cache_directory = join_paths(default_cache_base, "mpv_thumbs_cache"), - - ------------------------ - -- Generation options -- - ------------------------ - - -- Automatically generate the thumbnails on video load, without a keypress - autogenerate = true, - - -- Only automatically thumbnail videos shorter than this (seconds) - autogenerate_max_duration = 3600, -- 1 hour - - -- SHA1-sum filenames over this length - -- It's nice to know what files the thumbnails are (hence directory names) - -- but long URLs may approach filesystem limits. - hash_filename_length = 128, - - -- Use mpv to generate thumbnail even if ffmpeg is found in PATH - -- ffmpeg does not handle ordered chapters (MKVs which rely on other MKVs)! - -- mpv is a bit slower, but has better support overall (eg. subtitles in the previews) - prefer_mpv = true, - - -- Explicitly disable subtitles on the mpv sub-calls - mpv_no_sub = false, - -- Add a "--no-config" to the mpv sub-call arguments - mpv_no_config = false, - -- Add a "--profile=" to the mpv sub-call arguments - -- Use "" to disable - mpv_profile = "", - -- Output debug logs to .log, ala //000000.bgra.log - -- The logs are removed after successful encodes, unless you set mpv_keep_logs below - mpv_logs = true, - -- Keep all mpv logs, even the succesfull ones - mpv_keep_logs = false, - - -- Disable the built-in keybind ("T") to add your own - disable_keybinds = false, - - --------------------- - -- Display options -- - --------------------- - - -- Move the thumbnail up or down - -- For example: - -- topbar/bottombar: 24 - -- rest: 0 - vertical_offset = 24, - - -- Adjust background padding - -- Examples: - -- topbar: 0, 10, 10, 10 - -- bottombar: 10, 0, 10, 10 - -- slimbox/box: 10, 10, 10, 10 - pad_top = 10, - pad_bot = 0, - pad_left = 10, - pad_right = 10, - - -- If true, pad values are screen-pixels. If false, video-pixels. - pad_in_screenspace = true, - -- Calculate pad into the offset - offset_by_pad = true, - - -- Background color in BBGGRR - background_color = "000000", - -- Alpha: 0 - fully opaque, 255 - transparent - background_alpha = 80, - - -- Keep thumbnail on the screen near left or right side - constrain_to_screen = true, - - -- Do not display the thumbnailing progress - hide_progress = false, - - ----------------------- - -- Thumbnail options -- - ----------------------- - - -- The maximum dimensions of the thumbnails (pixels) - thumbnail_width = 200, - thumbnail_height = 200, - - -- The thumbnail count target - -- (This will result in a thumbnail every ~10 seconds for a 25 minute video) - thumbnail_count = 150, - - -- The above target count will be adjusted by the minimum and - -- maximum time difference between thumbnails. - -- The thumbnail_count will be used to calculate a target separation, - -- and min/max_delta will be used to constrict it. - - -- In other words, thumbnails will be: - -- at least min_delta seconds apart (limiting the amount) - -- at most max_delta seconds apart (raising the amount if needed) - min_delta = 5, - -- 120 seconds aka 2 minutes will add more thumbnails when the video is over 5 hours! - max_delta = 90, - - - -- Overrides for remote urls (you generally want less thumbnails!) - -- Thumbnailing network paths will be done with mpv - - -- Allow thumbnailing network paths (naive check for "://") - thumbnail_network = false, - -- Override thumbnail count, min/max delta - remote_thumbnail_count = 60, - remote_min_delta = 15, - remote_max_delta = 120, - - -- Try to grab the raw stream and disable ytdl for the mpv subcalls - -- Much faster than passing the url to ytdl again, but may cause problems with some sites - remote_direct_stream = true, -} - -read_options(thumbnailer_options, SCRIPT_NAME) -local Thumbnailer = { - cache_directory = thumbnailer_options.cache_directory, - - state = { - ready = false, - available = false, - enabled = false, - - thumbnail_template = nil, - - thumbnail_delta = nil, - thumbnail_count = 0, - - thumbnail_size = nil, - - finished_thumbnails = 0, - - -- List of thumbnail states (from 1 to thumbnail_count) - -- ready: 1 - -- in progress: 0 - -- not ready: -1 - thumbnails = {}, - - worker_input_path = nil, - -- Extra options for the workers - worker_extra = {}, - }, - -- Set in register_client - worker_register_timeout = nil, - -- A timer used to wait for more workers in case we have none - worker_wait_timer = nil, - workers = {} -} - -function Thumbnailer:clear_state() - clear_table(self.state) - self.state.ready = false - self.state.available = false - self.state.finished_thumbnails = 0 - self.state.thumbnails = {} - self.state.worker_extra = {} -end - - -function Thumbnailer:on_file_loaded() - self:clear_state() -end - -function Thumbnailer:on_thumb_ready(index) - self.state.thumbnails[index] = 1 - - -- Full recount instead of a naive increment (let's be safe!) - self.state.finished_thumbnails = 0 - for i, v in pairs(self.state.thumbnails) do - if v > 0 then - self.state.finished_thumbnails = self.state.finished_thumbnails + 1 - end - end -end - -function Thumbnailer:on_thumb_progress(index) - self.state.thumbnails[index] = math.max(self.state.thumbnails[index], 0) -end - -function Thumbnailer:on_start_file() - -- Clear state when a new file is being loaded - self:clear_state() -end - -function Thumbnailer:on_video_change(params) - -- Gather a new state when we get proper video-dec-params and our state is empty - if params ~= nil then - if not self.state.ready then - self:update_state() - end - end -end - - -function Thumbnailer:update_state() - msg.debug("Gathering video/thumbnail state") - - self.state.thumbnail_delta = self:get_delta() - self.state.thumbnail_count = self:get_thumbnail_count(self.state.thumbnail_delta) - - -- Prefill individual thumbnail states - for i = 1, self.state.thumbnail_count do - self.state.thumbnails[i] = -1 - end - - self.state.thumbnail_template, self.state.thumbnail_directory = self:get_thumbnail_template() - self.state.thumbnail_size = self:get_thumbnail_size() - - self.state.ready = true - - local file_path = mp.get_property_native("path") - self.state.is_remote = file_path:find("://") ~= nil - - self.state.available = false - - -- Make sure the file has video (and not just albumart) - local track_list = mp.get_property_native("track-list") - local has_video = false - for i, track in pairs(track_list) do - if track.type == "video" and not track.external and not track.albumart then - has_video = true - break - end - end - - if has_video and self.state.thumbnail_delta ~= nil and self.state.thumbnail_size ~= nil and self.state.thumbnail_count > 0 then - self.state.available = true - end - - msg.debug("Thumbnailer.state:", utils.to_string(self.state)) - -end - - -function Thumbnailer:get_thumbnail_template() - local file_path = mp.get_property_native("path") - local is_remote = file_path:find("://") ~= nil - - local filename = mp.get_property_native("filename/no-ext") - local filesize = mp.get_property_native("file-size", 0) - - if is_remote then - filesize = 0 - end - - filename = filename:gsub('[^a-zA-Z0-9_.%-\' ]', '') - -- Hash overly long filenames (most likely URLs) - if #filename > thumbnailer_options.hash_filename_length then - filename = sha1.hex(filename) - end - - local file_key = ("%s-%d"):format(filename, filesize) - - local thumbnail_directory = join_paths(self.cache_directory, file_key) - local file_template = join_paths(thumbnail_directory, "%06d.bgra") - return file_template, thumbnail_directory -end - - -function Thumbnailer:get_thumbnail_size() - local video_dec_params = mp.get_property_native("video-dec-params") - local video_width = video_dec_params.dw - local video_height = video_dec_params.dh - if not (video_width and video_height) then - return nil - end - - local w, h - if video_width > video_height then - w = thumbnailer_options.thumbnail_width - h = math.floor(video_height * (w / video_width)) - else - h = thumbnailer_options.thumbnail_height - w = math.floor(video_width * (h / video_height)) - end - return { w=w, h=h } -end - - -function Thumbnailer:get_delta() - local file_path = mp.get_property_native("path") - local file_duration = mp.get_property_native("duration") - local is_seekable = mp.get_property_native("seekable") - - -- Naive url check - local is_remote = file_path:find("://") ~= nil - - local remote_and_disallowed = is_remote - if is_remote and thumbnailer_options.thumbnail_network then - remote_and_disallowed = false - end - - if remote_and_disallowed or not is_seekable or not file_duration then - -- Not a local path (or remote thumbnails allowed), not seekable or lacks duration - return nil - end - - local thumbnail_count = thumbnailer_options.thumbnail_count - local min_delta = thumbnailer_options.min_delta - local max_delta = thumbnailer_options.max_delta - - if is_remote then - thumbnail_count = thumbnailer_options.remote_thumbnail_count - min_delta = thumbnailer_options.remote_min_delta - max_delta = thumbnailer_options.remote_max_delta - end - - local target_delta = (file_duration / thumbnail_count) - local delta = math.max(min_delta, math.min(max_delta, target_delta)) - - return delta -end - - -function Thumbnailer:get_thumbnail_count(delta) - if delta == nil then - return 0 - end - local file_duration = mp.get_property_native("duration") - - return math.ceil(file_duration / delta) -end - -function Thumbnailer:get_closest(thumbnail_index) - -- Given a 1-based index, find the closest available thumbnail and return it's 1-based index - - -- Check the direct thumbnail index first - if self.state.thumbnails[thumbnail_index] > 0 then - return thumbnail_index - end - - local min_distance = self.state.thumbnail_count + 1 - local closest = nil - - -- Naive, inefficient, lazy. But functional. - for index, value in pairs(self.state.thumbnails) do - local distance = math.abs(index - thumbnail_index) - if distance < min_distance and value > 0 then - min_distance = distance - closest = index - end - end - return closest -end - -function Thumbnailer:get_thumbnail_index(time_position) - -- Returns a 1-based thumbnail index for the given timestamp (between 1 and thumbnail_count, inclusive) - if self.state.thumbnail_delta and (self.state.thumbnail_count and self.state.thumbnail_count > 0) then - return math.min(math.floor(time_position / self.state.thumbnail_delta) + 1, self.state.thumbnail_count) - else - return nil - end -end - -function Thumbnailer:get_thumbnail_path(time_position) - -- Given a timestamp, return: - -- the closest available thumbnail path (if any) - -- the 1-based thumbnail index calculated from the timestamp - -- the 1-based thumbnail index of the closest available (and used) thumbnail - -- OR nil if thumbnails are not available. - - local thumbnail_index = self:get_thumbnail_index(time_position) - if not thumbnail_index then return nil end - - local closest = self:get_closest(thumbnail_index) - - if closest ~= nil then - return self.state.thumbnail_template:format(closest-1), thumbnail_index, closest - else - return nil, thumbnail_index, nil - end -end - -function Thumbnailer:register_client() - self.worker_register_timeout = mp.get_time() + 2 - - mp.register_script_message("mpv_thumbnail_script-ready", function(index, path) - self:on_thumb_ready(tonumber(index), path) - end) - mp.register_script_message("mpv_thumbnail_script-progress", function(index, path) - self:on_thumb_progress(tonumber(index), path) - end) - - mp.register_script_message("mpv_thumbnail_script-worker", function(worker_name) - if not self.workers[worker_name] then - msg.debug("Registered worker", worker_name) - self.workers[worker_name] = true - mp.commandv("script-message-to", worker_name, "mpv_thumbnail_script-slaved") - end - end) - - -- Notify workers to generate thumbnails when video loads/changes - -- This will be executed after the on_video_change (because it's registered after it) - mp.observe_property("video-dec-params", "native", function() - local duration = mp.get_property_native("duration") - local max_duration = thumbnailer_options.autogenerate_max_duration - - if self.state.available and thumbnailer_options.autogenerate then - -- Notify if autogenerate is on and video is not too long - if duration < max_duration or max_duration == 0 then - self:start_worker_jobs() - end - end - end) - - local thumb_script_key = not thumbnailer_options.disable_keybinds and "T" or nil - mp.add_key_binding(thumb_script_key, "generate-thumbnails", function() - if self.state.available then - mp.osd_message("Started thumbnailer jobs") - self:start_worker_jobs() - else - mp.osd_message("Thumbnailing unavailabe") - end - end) -end - -function Thumbnailer:_create_thumbnail_job_order() - -- Returns a list of 1-based thumbnail indices in a job order - local used_frames = {} - local work_frames = {} - - -- Pick frames in increasing frequency. - -- This way we can do a quick few passes over the video and then fill in the gaps. - for x = 6, 0, -1 do - local nth = (2^x) - - for thi = 1, self.state.thumbnail_count, nth do - if not used_frames[thi] then - table.insert(work_frames, thi) - used_frames[thi] = true - end - end - end - return work_frames -end - -function Thumbnailer:prepare_source_path() - local file_path = mp.get_property_native("path") - - if self.state.is_remote and thumbnailer_options.remote_direct_stream then - -- Use the direct stream (possibly) provided by ytdl - -- This skips ytdl on the sub-calls, making the thumbnailing faster - -- Works well on YouTube, rest not really tested - file_path = mp.get_property_native("stream-path") - - -- edl:// urls can get LONG. In which case, save the path (URL) - -- to a temporary file and use that instead. - local playlist_filename = join_paths(self.state.thumbnail_directory, "playlist.txt") - - if #file_path > 8000 then - -- Path is too long for a playlist - just pass the original URL to - -- workers and allow ytdl - self.state.worker_extra.enable_ytdl = true - file_path = mp.get_property_native("path") - msg.warn("Falling back to original URL and ytdl due to LONG source path. This will be slow.") - - elseif #file_path > 1024 then - local playlist_file = io.open(playlist_filename, "wb") - if not playlist_file then - msg.error(("Tried to write a playlist to %s but couldn't!"):format(playlist_file)) - return false - end - - playlist_file:write(file_path .. "\n") - playlist_file:close() - - file_path = "--playlist=" .. playlist_filename - msg.warn("Using playlist workaround due to long source path") - end - end - - self.state.worker_input_path = file_path - return true -end - -function Thumbnailer:start_worker_jobs() - -- Create directory for the thumbnails, if needed - local l, err = utils.readdir(self.state.thumbnail_directory) - if err then - msg.debug("Creating thumbnail directory", self.state.thumbnail_directory) - create_directories(self.state.thumbnail_directory) - end - - -- Try to prepare the source path for workers, and bail if unable to do so - if not self:prepare_source_path() then - return - end - - local worker_list = {} - for worker_name in pairs(self.workers) do table.insert(worker_list, worker_name) end - - local worker_count = #worker_list - - -- In case we have a worker timer created already, clear it - -- (For example, if the video-dec-params change in quick succession or the user pressed T, etc) - if self.worker_wait_timer then - self.worker_wait_timer:stop() - end - - if worker_count == 0 then - local now = mp.get_time() - if mp.get_time() > self.worker_register_timeout then - -- Workers have had their time to register but we have none! - local err = "No thumbnail workers found. Make sure you are not missing a script!" - msg.error(err) - mp.osd_message(err, 3) - - else - -- We may be too early. Delay the work start a bit to try again. - msg.warn("No workers found. Waiting a bit more for them.") - -- Wait at least half a second - local wait_time = math.max(self.worker_register_timeout - now, 0.5) - self.worker_wait_timer = mp.add_timeout(wait_time, function() self:start_worker_jobs() end) - end - - else - -- We have at least one worker. This may not be all of them, but they have had - -- their time to register; we've done our best waiting for them. - self.state.enabled = true - - msg.debug( ("Splitting %d thumbnails amongst %d worker(s)"):format(self.state.thumbnail_count, worker_count) ) - - local frame_job_order = self:_create_thumbnail_job_order() - local worker_jobs = {} - for i = 1, worker_count do worker_jobs[worker_list[i]] = {} end - - -- Split frames amongst the workers - for i, thumbnail_index in ipairs(frame_job_order) do - local worker_id = worker_list[ ((i-1) % worker_count) + 1 ] - table.insert(worker_jobs[worker_id], thumbnail_index) - end - - local state_json_string = utils.format_json(self.state) - msg.debug("Giving workers state:", state_json_string) - - for worker_name, worker_frames in pairs(worker_jobs) do - if #worker_frames > 0 then - local frames_json_string = utils.format_json(worker_frames) - msg.debug("Assigning job to", worker_name, frames_json_string) - mp.commandv("script-message-to", worker_name, "mpv_thumbnail_script-job", state_json_string, frames_json_string) - end - end - end -end - -mp.register_event("start-file", function() Thumbnailer:on_start_file() end) -mp.observe_property("video-dec-params", "native", function(name, params) Thumbnailer:on_video_change(params) end) ---[[ -This is mpv's original player/lua/osc.lua patched to display thumbnails - -Sections are denoted with -- mpv_thumbnail_script.lua -- -Current osc.lua version: 97816bbef0f97cfda7abdbe560707481d5f68ccd -]]-- - -local assdraw = require 'mp.assdraw' -local msg = require 'mp.msg' -local opt = require 'mp.options' -local utils = require 'mp.utils' - - --- --- Parameters --- - --- default user option values --- do not touch, change them in osc.conf -local user_opts = { - showwindowed = true, -- show OSC when windowed? - showfullscreen = true, -- show OSC when fullscreen? - scalewindowed = 1, -- scaling of the controller when windowed - scalefullscreen = 1, -- scaling of the controller when fullscreen - scaleforcedwindow = 2, -- scaling when rendered on a forced window - vidscale = true, -- scale the controller with the video? - valign = 0.8, -- vertical alignment, -1 (top) to 1 (bottom) - halign = 0, -- horizontal alignment, -1 (left) to 1 (right) - barmargin = 0, -- vertical margin of top/bottombar - boxalpha = 80, -- alpha of the background box, - -- 0 (opaque) to 255 (fully transparent) - hidetimeout = 500, -- duration in ms until the OSC hides if no - -- mouse movement. enforced non-negative for the - -- user, but internally negative is "always-on". - fadeduration = 200, -- duration of fade out in ms, 0 = no fade - deadzonesize = 0.5, -- size of deadzone - minmousemove = 0, -- minimum amount of pixels the mouse has to - -- move between ticks to make the OSC show up - iamaprogrammer = false, -- use native mpv values and disable OSC - -- internal track list management (and some - -- functions that depend on it) - layout = "bottombar", - seekbarstyle = "bar", -- slider (diamond marker), knob (circle - -- marker with guide), or bar (fill) - title = "${media-title}", -- string compatible with property-expansion - -- to be shown as OSC title - tooltipborder = 1, -- border of tooltip in bottom/topbar - timetotal = false, -- display total time instead of remaining time? - timems = false, -- display timecodes with milliseconds? - seekranges = true, -- display seek ranges? - visibility = "auto", -- only used at init to set visibility_mode(...) - boxmaxchars = 80, -- title crop threshold for box layout -} - --- read_options may modify hidetimeout, so save the original default value in --- case the user set hidetimeout < 0 and we need the default instead. -local hidetimeout_def = user_opts.hidetimeout --- read options from config and command-line -opt.read_options(user_opts, "osc") -if user_opts.hidetimeout < 0 then - user_opts.hidetimeout = hidetimeout_def - msg.warn("hidetimeout cannot be negative. Using " .. user_opts.hidetimeout) -end - - --- mpv_thumbnail_script.lua -- - --- Patch in msg.trace -if not msg.trace then - msg.trace = function(...) return mp.log("trace", ...) end -end - --- Patch in utils.format_bytes_humanized -if not utils.format_bytes_humanized then - utils.format_bytes_humanized = function(b) - local d = {"Bytes", "KiB", "MiB", "GiB", "TiB", "PiB"} - local i = 1 - while b >= 1024 do - b = b / 1024 - i = i + 1 - end - return string.format("%0.2f %s", b, d[i] and d[i] or "*1024^" .. (i-1)) - end -end - -Thumbnailer:register_client() - -function get_thumbnail_y_offset(thumb_size, msy) - local layout = user_opts.layout - local offset = 0 - - if layout == "bottombar" then - offset = 15 --+ margin - elseif layout == "topbar" then - offset = -(thumb_size.h * msy + 15) - elseif layout == "box" then - offset = 15 - elseif layout == "slimbox" then - offset = 12 - end - - return offset / msy -end - - -local osc_thumb_state = { - visible = false, - overlay_id = 1, - - last_path = nil, - last_x = nil, - last_y = nil, -} - -function hide_thumbnail() - osc_thumb_state.visible = false - osc_thumb_state.last_path = nil - mp.command_native({ "overlay-remove", osc_thumb_state.overlay_id }) -end - -function display_thumbnail(pos, value, ass) - -- If thumbnails are not available, bail - if not (Thumbnailer.state.enabled and Thumbnailer.state.available) then - return - end - - local duration = mp.get_property_number("duration", nil) - if not ((duration == nil) or (value == nil)) then - target_position = duration * (value / 100) - - local msx, msy = get_virt_scale_factor() - local osd_w, osd_h = mp.get_osd_size() - - local thumb_size = Thumbnailer.state.thumbnail_size - local thumb_path, thumb_index, closest_index = Thumbnailer:get_thumbnail_path(target_position) - - local thumbs_ready = Thumbnailer.state.finished_thumbnails - local thumbs_total = Thumbnailer.state.thumbnail_count - local perc = math.floor((thumbs_ready / thumbs_total) * 100) - - local display_progress = thumbs_ready ~= thumbs_total and not thumbnailer_options.hide_progress - - local vertical_offset = thumbnailer_options.vertical_offset - local padding = thumbnailer_options.background_padding - - local pad = { - l = thumbnailer_options.pad_left, r = thumbnailer_options.pad_right, - t = thumbnailer_options.pad_top, b = thumbnailer_options.pad_bot - } - if thumbnailer_options.pad_in_screenspace then - pad.l = pad.l * msx - pad.r = pad.r * msx - pad.t = pad.t * msy - pad.b = pad.b * msy - end - - if thumbnailer_options.offset_by_pad then - vertical_offset = vertical_offset + (user_opts.layout == "topbar" and pad.t or pad.b) - end - - local ass_w = thumb_size.w * msx - local ass_h = thumb_size.h * msy - local y_offset = get_thumbnail_y_offset(thumb_size, 1) - - -- Constrain thumbnail display to window - -- (ie. don't let it go off-screen left/right) - if thumbnailer_options.constrain_to_screen and osd_w > (ass_w + pad.l + pad.r)/msx then - local padded_left = (pad.l + (ass_w / 2)) - local padded_right = (pad.r + (ass_w / 2)) - if pos.x - padded_left < 0 then - pos.x = padded_left - elseif pos.x + padded_right > osd_w*msx then - pos.x = osd_w*msx - padded_right - end - end - - local text_h = 30 * msy - local bg_h = ass_h + (display_progress and text_h or 0) - local bg_left = pos.x - ass_w/2 - local framegraph_h = 10 * msy - - local bg_top = nil - local text_top = nil - local framegraph_top = nil - - if user_opts.layout == "topbar" then - bg_top = pos.y - ( y_offset + thumb_size.h ) + vertical_offset - text_top = bg_top + ass_h + framegraph_h - framegraph_top = bg_top + ass_h - vertical_offset = -vertical_offset - else - bg_top = pos.y - y_offset - bg_h - vertical_offset - text_top = bg_top - framegraph_top = bg_top + 20 * msy - end - - if display_progress then - if user_opts.layout == "topbar" then - pad.b = math.max(0, pad.b - 30) - else - pad.t = math.max(0, pad.t - 30) - end - end - - - - -- Draw background - ass:new_event() - ass:pos(bg_left, bg_top) - ass:append(("{\\bord0\\1c&H%s&\\1a&H%X&}"):format(thumbnailer_options.background_color, thumbnailer_options.background_alpha)) - ass:draw_start() - ass:rect_cw(-pad.l, -pad.t, ass_w+pad.r, bg_h+pad.b) - ass:draw_stop() - - if display_progress then - - ass:new_event() - ass:pos(pos.x, text_top) - ass:an(8) - -- Scale text to correct size - ass:append(("{\\fs20\\bord0\\fscx%f\\fscy%f}"):format(100*msx, 100*msy)) - ass:append(("%d%% - %d/%d"):format(perc, thumbs_ready, thumbs_total)) - - -- Draw the generation progress - local block_w = thumb_size.w * (Thumbnailer.state.thumbnail_delta / duration) * msy - local block_max_x = thumb_size.w * msy - - -- Draw finished thumbnail blocks (white) - ass:new_event() - ass:pos(bg_left, framegraph_top) - ass:append(("{\\bord0\\1c&HFFFFFF&\\1a&H%X&"):format(0)) - ass:draw_start(2) - for i, v in pairs(Thumbnailer.state.thumbnails) do - if i ~= closest_index and v > 0 then - ass:rect_cw((i-1)*block_w, 0, math.min(block_max_x, i*block_w), framegraph_h) - end - end - ass:draw_stop() - - -- Draw in-progress thumbnail blocks (grayish green) - ass:new_event() - ass:pos(bg_left, framegraph_top) - ass:append(("{\\bord0\\1c&H44AA44&\\1a&H%X&"):format(0)) - ass:draw_start(2) - for i, v in pairs(Thumbnailer.state.thumbnails) do - if i ~= closest_index and v == 0 then - ass:rect_cw((i-1)*block_w, 0, math.min(block_max_x, i*block_w), framegraph_h) - end - end - ass:draw_stop() - - if closest_index ~= nil then - ass:new_event() - ass:pos(bg_left, framegraph_top) - ass:append(("{\\bord0\\1c&H4444FF&\\1a&H%X&"):format(0)) - ass:draw_start(2) - ass:rect_cw((closest_index-1)*block_w, 0, math.min(block_max_x, closest_index*block_w), framegraph_h) - ass:draw_stop() - end - end - - if thumb_path then - local overlay_y_offset = get_thumbnail_y_offset(thumb_size, msy) - - local thumb_x = math.floor(pos.x / msx - thumb_size.w/2) - local thumb_y = math.floor(pos.y / msy - thumb_size.h - overlay_y_offset - vertical_offset/msy) - - osc_thumb_state.visible = true - if not (osc_thumb_state.last_path == thumb_path and osc_thumb_state.last_x == thumb_x and osc_thumb_state.last_y == thumb_y) then - local overlay_add_args = { - "overlay-add", osc_thumb_state.overlay_id, - thumb_x, thumb_y, - thumb_path, - 0, - "bgra", - thumb_size.w, thumb_size.h, - 4 * thumb_size.w - } - mp.command_native(overlay_add_args) - - osc_thumb_state.last_path = thumb_path - osc_thumb_state.last_x = thumb_x - osc_thumb_state.last_y = thumb_y - end - end - end -end - --- // mpv_thumbnail_script.lua // -- - - -local osc_param = { -- calculated by osc_init() - playresy = 0, -- canvas size Y - playresx = 0, -- canvas size X - display_aspect = 1, - unscaled_y = 0, - areas = {}, -} - -local osc_styles = { - bigButtons = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs50\\fnmpv-osd-symbols}", - smallButtonsL = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs19\\fnmpv-osd-symbols}", - smallButtonsLlabel = "{\\fscx105\\fscy105\\fn" .. mp.get_property("options/osd-font") .. "}", - smallButtonsR = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs30\\fnmpv-osd-symbols}", - topButtons = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs12\\fnmpv-osd-symbols}", - - elementDown = "{\\1c&H999999}", - timecodes = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs20}", - vidtitle = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs12\\q2}", - box = "{\\rDefault\\blur0\\bord1\\1c&H000000\\3c&HFFFFFF}", - - topButtonsBar = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs18\\fnmpv-osd-symbols}", - smallButtonsBar = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs28\\fnmpv-osd-symbols}", - timecodesBar = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs27}", - timePosBar = "{\\blur0\\bord".. user_opts.tooltipborder .."\\1c&HFFFFFF\\3c&H000000\\fs30}", - vidtitleBar = "{\\blur0\\bord0\\1c&HFFFFFF\\3c&HFFFFFF\\fs18\\q2}", -} - --- internal states, do not touch -local state = { - showtime, -- time of last invocation (last mouse move) - osc_visible = false, - anistart, -- time when the animation started - anitype, -- current type of animation - animation, -- current animation alpha - mouse_down_counter = 0, -- used for softrepeat - active_element = nil, -- nil = none, 0 = background, 1+ = see elements[] - active_event_source = nil, -- the "button" that issued the current event - rightTC_trem = not user_opts.timetotal, -- if the right timecode should display total or remaining time - tc_ms = user_opts.timems, -- Should the timecodes display their time with milliseconds - mp_screen_sizeX, mp_screen_sizeY, -- last screen-resolution, to detect resolution changes to issue reINITs - initREQ = false, -- is a re-init request pending? - last_mouseX, last_mouseY, -- last mouse position, to detect significant mouse movement - message_text, - message_timeout, - fullscreen = false, - timer = nil, - cache_idle = false, - idle = false, - enabled = true, - input_enabled = true, - showhide_enabled = false, -} - - - - --- --- Helperfunctions --- - --- scale factor for translating between real and virtual ASS coordinates -function get_virt_scale_factor() - local w, h = mp.get_osd_size() - if w <= 0 or h <= 0 then - return 0, 0 - end - return osc_param.playresx / w, osc_param.playresy / h -end - --- return mouse position in virtual ASS coordinates (playresx/y) -function get_virt_mouse_pos() - local sx, sy = get_virt_scale_factor() - local x, y = mp.get_mouse_pos() - return x * sx, y * sy -end - -function set_virt_mouse_area(x0, y0, x1, y1, name) - local sx, sy = get_virt_scale_factor() - mp.set_mouse_area(x0 / sx, y0 / sy, x1 / sx, y1 / sy, name) -end - -function scale_value(x0, x1, y0, y1, val) - local m = (y1 - y0) / (x1 - x0) - local b = y0 - (m * x0) - return (m * val) + b -end - --- returns hitbox spanning coordinates (top left, bottom right corner) --- according to alignment -function get_hitbox_coords(x, y, an, w, h) - - local alignments = { - [1] = function () return x, y-h, x+w, y end, - [2] = function () return x-(w/2), y-h, x+(w/2), y end, - [3] = function () return x-w, y-h, x, y end, - - [4] = function () return x, y-(h/2), x+w, y+(h/2) end, - [5] = function () return x-(w/2), y-(h/2), x+(w/2), y+(h/2) end, - [6] = function () return x-w, y-(h/2), x, y+(h/2) end, - - [7] = function () return x, y, x+w, y+h end, - [8] = function () return x-(w/2), y, x+(w/2), y+h end, - [9] = function () return x-w, y, x, y+h end, - } - - return alignments[an]() -end - -function get_hitbox_coords_geo(geometry) - return get_hitbox_coords(geometry.x, geometry.y, geometry.an, - geometry.w, geometry.h) -end - -function get_element_hitbox(element) - return element.hitbox.x1, element.hitbox.y1, - element.hitbox.x2, element.hitbox.y2 -end - -function mouse_hit(element) - return mouse_hit_coords(get_element_hitbox(element)) -end - -function mouse_hit_coords(bX1, bY1, bX2, bY2) - local mX, mY = get_virt_mouse_pos() - return (mX >= bX1 and mX <= bX2 and mY >= bY1 and mY <= bY2) -end - -function limit_range(min, max, val) - if val > max then - val = max - elseif val < min then - val = min - end - return val -end - --- translate value into element coordinates -function get_slider_ele_pos_for(element, val) - - local ele_pos = scale_value( - element.slider.min.value, element.slider.max.value, - element.slider.min.ele_pos, element.slider.max.ele_pos, - val) - - return limit_range( - element.slider.min.ele_pos, element.slider.max.ele_pos, - ele_pos) -end - --- translates global (mouse) coordinates to value -function get_slider_value_at(element, glob_pos) - - local val = scale_value( - element.slider.min.glob_pos, element.slider.max.glob_pos, - element.slider.min.value, element.slider.max.value, - glob_pos) - - return limit_range( - element.slider.min.value, element.slider.max.value, - val) -end - --- get value at current mouse position -function get_slider_value(element) - return get_slider_value_at(element, get_virt_mouse_pos()) -end - -function countone(val) - if not (user_opts.iamaprogrammer) then - val = val + 1 - end - return val -end - --- align: -1 .. +1 --- frame: size of the containing area --- obj: size of the object that should be positioned inside the area --- margin: min. distance from object to frame (as long as -1 <= align <= +1) -function get_align(align, frame, obj, margin) - return (frame / 2) + (((frame / 2) - margin - (obj / 2)) * align) -end - --- multiplies two alpha values, formular can probably be improved -function mult_alpha(alphaA, alphaB) - return 255 - (((1-(alphaA/255)) * (1-(alphaB/255))) * 255) -end - -function add_area(name, x1, y1, x2, y2) - -- create area if needed - if (osc_param.areas[name] == nil) then - osc_param.areas[name] = {} - end - table.insert(osc_param.areas[name], {x1=x1, y1=y1, x2=x2, y2=y2}) -end - - --- --- Tracklist Management --- - -local nicetypes = {video = "Video", audio = "Audio", sub = "Subtitle"} - --- updates the OSC internal playlists, should be run each time the track-layout changes -function update_tracklist() - local tracktable = mp.get_property_native("track-list", {}) - - -- by osc_id - tracks_osc = {} - tracks_osc.video, tracks_osc.audio, tracks_osc.sub = {}, {}, {} - -- by mpv_id - tracks_mpv = {} - tracks_mpv.video, tracks_mpv.audio, tracks_mpv.sub = {}, {}, {} - for n = 1, #tracktable do - if not (tracktable[n].type == "unknown") then - local type = tracktable[n].type - local mpv_id = tonumber(tracktable[n].id) - - -- by osc_id - table.insert(tracks_osc[type], tracktable[n]) - - -- by mpv_id - tracks_mpv[type][mpv_id] = tracktable[n] - tracks_mpv[type][mpv_id].osc_id = #tracks_osc[type] - end - end -end - --- return a nice list of tracks of the given type (video, audio, sub) -function get_tracklist(type) - local msg = "Available " .. nicetypes[type] .. " Tracks: " - if #tracks_osc[type] == 0 then - msg = msg .. "none" - else - for n = 1, #tracks_osc[type] do - local track = tracks_osc[type][n] - local lang, title, selected = "unknown", "", "โ—‹" - if not(track.lang == nil) then lang = track.lang end - if not(track.title == nil) then title = track.title end - if (track.id == tonumber(mp.get_property(type))) then - selected = "โ—" - end - msg = msg.."\n"..selected.." "..n..": ["..lang.."] "..title - end - end - return msg -end - --- relatively change the track of given by tracks - --(+1 -> next, -1 -> previous) -function set_track(type, next) - local current_track_mpv, current_track_osc - if (mp.get_property(type) == "no") then - current_track_osc = 0 - else - current_track_mpv = tonumber(mp.get_property(type)) - current_track_osc = tracks_mpv[type][current_track_mpv].osc_id - end - local new_track_osc = (current_track_osc + next) % (#tracks_osc[type] + 1) - local new_track_mpv - if new_track_osc == 0 then - new_track_mpv = "no" - else - new_track_mpv = tracks_osc[type][new_track_osc].id - end - - mp.commandv("set", type, new_track_mpv) - - if (new_track_osc == 0) then - show_message(nicetypes[type] .. " Track: none") - else - show_message(nicetypes[type] .. " Track: " - .. new_track_osc .. "/" .. #tracks_osc[type] - .. " [".. (tracks_osc[type][new_track_osc].lang or "unknown") .."] " - .. (tracks_osc[type][new_track_osc].title or "")) - end -end - --- get the currently selected track of , OSC-style counted -function get_track(type) - local track = mp.get_property(type) - if track ~= "no" and track ~= nil then - local tr = tracks_mpv[type][tonumber(track)] - if tr then - return tr.osc_id - end - end - return 0 -end - - --- --- Element Management --- - -local elements = {} - -function prepare_elements() - - -- remove elements without layout or invisble - local elements2 = {} - for n, element in pairs(elements) do - if not (element.layout == nil) and (element.visible) then - table.insert(elements2, element) - end - end - elements = elements2 - - function elem_compare (a, b) - return a.layout.layer < b.layout.layer - end - - table.sort(elements, elem_compare) - - - for _,element in pairs(elements) do - - local elem_geo = element.layout.geometry - - -- Calculate the hitbox - local bX1, bY1, bX2, bY2 = get_hitbox_coords_geo(elem_geo) - element.hitbox = {x1 = bX1, y1 = bY1, x2 = bX2, y2 = bY2} - - local style_ass = assdraw.ass_new() - - -- prepare static elements - style_ass:append("{}") -- hack to troll new_event into inserting a \n - style_ass:new_event() - style_ass:pos(elem_geo.x, elem_geo.y) - style_ass:an(elem_geo.an) - style_ass:append(element.layout.style) - - element.style_ass = style_ass - - local static_ass = assdraw.ass_new() - - - if (element.type == "box") then - --draw box - static_ass:draw_start() - static_ass:round_rect_cw(0, 0, elem_geo.w, elem_geo.h, - element.layout.box.radius) - static_ass:draw_stop() - - - elseif (element.type == "slider") then - --draw static slider parts - - local slider_lo = element.layout.slider - -- offset between element outline and drag-area - local foV = slider_lo.border + slider_lo.gap - - -- calculate positions of min and max points - if (slider_lo.stype == "slider") or - (slider_lo.stype == "knob") then - element.slider.min.ele_pos = elem_geo.h / 2 - element.slider.max.ele_pos = elem_geo.w - (elem_geo.h / 2) - - elseif (slider_lo.stype == "bar") then - element.slider.min.ele_pos = - slider_lo.border + slider_lo.gap - element.slider.max.ele_pos = - elem_geo.w - (slider_lo.border + slider_lo.gap) - end - - element.slider.min.glob_pos = - element.hitbox.x1 + element.slider.min.ele_pos - element.slider.max.glob_pos = - element.hitbox.x1 + element.slider.max.ele_pos - - -- -- -- - - static_ass:draw_start() - - -- the box - static_ass:rect_cw(0, 0, elem_geo.w, elem_geo.h); - - -- the "hole" - static_ass:rect_ccw(slider_lo.border, slider_lo.border, - elem_geo.w - slider_lo.border, elem_geo.h - slider_lo.border) - - -- marker nibbles - if not (element.slider.markerF == nil) and (slider_lo.gap > 0) then - local markers = element.slider.markerF() - for _,marker in pairs(markers) do - if (marker > element.slider.min.value) and - (marker < element.slider.max.value) then - - local s = get_slider_ele_pos_for(element, marker) - - if (slider_lo.gap > 1) then -- draw triangles - - local a = slider_lo.gap / 0.5 --0.866 - - --top - if (slider_lo.nibbles_top) then - static_ass:move_to(s - (a/2), slider_lo.border) - static_ass:line_to(s + (a/2), slider_lo.border) - static_ass:line_to(s, foV) - end - - --bottom - if (slider_lo.nibbles_bottom) then - static_ass:move_to(s - (a/2), - elem_geo.h - slider_lo.border) - static_ass:line_to(s, - elem_geo.h - foV) - static_ass:line_to(s + (a/2), - elem_geo.h - slider_lo.border) - end - - else -- draw 2x1px nibbles - - --top - if (slider_lo.nibbles_top) then - static_ass:rect_cw(s - 1, slider_lo.border, - s + 1, slider_lo.border + slider_lo.gap); - end - - --bottom - if (slider_lo.nibbles_bottom) then - static_ass:rect_cw(s - 1, - elem_geo.h -slider_lo.border -slider_lo.gap, - s + 1, elem_geo.h - slider_lo.border); - end - end - end - end - end - end - - element.static_ass = static_ass - - - -- if the element is supposed to be disabled, - -- style it accordingly and kill the eventresponders - if not (element.enabled) then - element.layout.alpha[1] = 136 - element.eventresponder = nil - end - end -end - - --- --- Element Rendering --- - -function render_elements(master_ass) - - for n=1, #elements do - local element = elements[n] - - local style_ass = assdraw.ass_new() - style_ass:merge(element.style_ass) - - --alpha - local ar = element.layout.alpha - if not (state.animation == nil) then - ar = {} - for ai, av in pairs(element.layout.alpha) do - ar[ai] = mult_alpha(av, state.animation) - end - end - - style_ass:append(string.format("{\\1a&H%X&\\2a&H%X&\\3a&H%X&\\4a&H%X&}", - ar[1], ar[2], ar[3], ar[4])) - - if element.eventresponder and (state.active_element == n) then - - -- run render event functions - if not (element.eventresponder.render == nil) then - element.eventresponder.render(element) - end - - if mouse_hit(element) then - -- mouse down styling - if (element.styledown) then - style_ass:append(osc_styles.elementDown) - end - - if (element.softrepeat) and (state.mouse_down_counter >= 15 - and state.mouse_down_counter % 5 == 0) then - - element.eventresponder[state.active_event_source.."_down"](element) - end - state.mouse_down_counter = state.mouse_down_counter + 1 - end - - end - - local elem_ass = assdraw.ass_new() - - elem_ass:merge(style_ass) - - if not (element.type == "button") then - elem_ass:merge(element.static_ass) - end - - if (element.type == "slider") then - - local slider_lo = element.layout.slider - local elem_geo = element.layout.geometry - local s_min = element.slider.min.value - local s_max = element.slider.max.value - - -- draw pos marker - local pos = element.slider.posF() - - if not (pos == nil) then - - local foV = slider_lo.border + slider_lo.gap - local foH = 0 - if (slider_lo.stype == "slider") or - (slider_lo.stype == "knob") then - foH = elem_geo.h / 2 - elseif (slider_lo.stype == "bar") then - foH = slider_lo.border + slider_lo.gap - end - - local xp = get_slider_ele_pos_for(element, pos) - - -- the filling - local innerH = elem_geo.h - (2*foV) - - if (slider_lo.stype == "bar") then - elem_ass:rect_cw(foH, foV, xp, elem_geo.h - foV) - elseif (slider_lo.stype == "slider") then - elem_ass:move_to(xp, foV) - elem_ass:line_to(xp+(innerH/2), (innerH/2)+foV) - elem_ass:line_to(xp, (innerH)+foV) - elem_ass:line_to(xp-(innerH/2), (innerH/2)+foV) - elseif (slider_lo.stype == "knob") then - elem_ass:rect_cw(xp, (9*innerH/20) + foV, - elem_geo.w - foH, (11*innerH/20) + foV) - elem_ass:rect_cw(foH, (3*innerH/8) + foV, - xp, (5*innerH/8) + foV) - elem_ass:round_rect_cw(xp - innerH/2, foV, - xp + innerH/2, foV + innerH, innerH/2.0) - end - end - - -- seek ranges - local seekRanges = element.slider.seekRangesF() - if not (seekRanges == nil) then - for _,range in pairs(seekRanges) do - local pstart = get_slider_ele_pos_for(element, range["start"]) - local pend = get_slider_ele_pos_for(element, range["end"]) - elem_ass:rect_ccw(pstart, (elem_geo.h/2)-1, pend, (elem_geo.h/2) + 1) - end - end - - elem_ass:draw_stop() - - -- add tooltip - if not (element.slider.tooltipF == nil) then - - if mouse_hit(element) then - local sliderpos = get_slider_value(element) - local tooltiplabel = element.slider.tooltipF(sliderpos) - - local an = slider_lo.tooltip_an - - local ty - - if (an == 2) then - ty = element.hitbox.y1 - slider_lo.border - else - ty = element.hitbox.y1 + elem_geo.h/2 - end - - local tx = get_virt_mouse_pos() - if (slider_lo.adjust_tooltip) then - if (an == 2) then - if (sliderpos < (s_min + 3)) then - an = an - 1 - elseif (sliderpos > (s_max - 3)) then - an = an + 1 - end - elseif (sliderpos > (s_max-s_min)/2) then - an = an + 1 - tx = tx - 5 - else - an = an - 1 - tx = tx + 10 - end - end - - -- tooltip label - elem_ass:new_event() - elem_ass:pos(tx, ty) - elem_ass:an(an) - elem_ass:append(slider_lo.tooltip_style) - - --alpha - local ar = slider_lo.alpha - if not (state.animation == nil) then - ar = {} - for ai, av in pairs(slider_lo.alpha) do - ar[ai] = mult_alpha(av, state.animation) - end - end - elem_ass:append(string.format("{\\1a&H%X&\\2a&H%X&\\3a&H%X&\\4a&H%X&}", - ar[1], ar[2], ar[3], ar[4])) - - elem_ass:append(tooltiplabel) - - -- mpv_thumbnail_script.lua -- - display_thumbnail({x=get_virt_mouse_pos(), y=ty, a=an}, sliderpos, elem_ass) - -- // mpv_thumbnail_script.lua // -- - - end - end - - elseif (element.type == "button") then - - local buttontext - if type(element.content) == "function" then - buttontext = element.content() -- function objects - elseif not (element.content == nil) then - buttontext = element.content -- text objects - end - - local maxchars = element.layout.button.maxchars - if not (maxchars == nil) and (#buttontext > maxchars) then - local max_ratio = 1.25 -- up to 25% more chars while shrinking - local limit = math.max(0, math.floor(maxchars * max_ratio) - 3) - if (#buttontext > limit) then - while (#buttontext > limit) do - buttontext = buttontext:gsub(".[\128-\191]*$", "") - end - buttontext = buttontext .. "..." - end - local _, nchars2 = buttontext:gsub(".[\128-\191]*", "") - local stretch = (maxchars/#buttontext)*100 - buttontext = string.format("{\\fscx%f}", - (maxchars/#buttontext)*100) .. buttontext - end - - elem_ass:append(buttontext) - end - - master_ass:merge(elem_ass) - end -end - --- --- Message display --- - --- pos is 1 based -function limited_list(prop, pos) - local proplist = mp.get_property_native(prop, {}) - local count = #proplist - if count == 0 then - return count, proplist - end - - local fs = tonumber(mp.get_property('options/osd-font-size')) - local max = math.ceil(osc_param.unscaled_y*0.75 / fs) - if max % 2 == 0 then - max = max - 1 - end - local delta = math.ceil(max / 2) - 1 - local begi = math.max(math.min(pos - delta, count - max + 1), 1) - local endi = math.min(begi + max - 1, count) - - local reslist = {} - for i=begi, endi do - local item = proplist[i] - item.current = (i == pos) and true or nil - table.insert(reslist, item) - end - return count, reslist -end - -function get_playlist() - local pos = mp.get_property_number('playlist-pos', 0) + 1 - local count, limlist = limited_list('playlist', pos) - if count == 0 then - return 'Empty playlist.' - end - - local message = string.format('Playlist [%d/%d]:\n', pos, count) - for i, v in ipairs(limlist) do - local title = v.title - local _, filename = utils.split_path(v.filename) - if title == nil then - title = filename - end - message = string.format('%s %s %s\n', message, - (v.current and 'โ—' or 'โ—‹'), title) - end - return message -end - -function get_chapterlist() - local pos = mp.get_property_number('chapter', 0) + 1 - local count, limlist = limited_list('chapter-list', pos) - if count == 0 then - return 'No chapters.' - end - - local message = string.format('Chapters [%d/%d]:\n', pos, count) - for i, v in ipairs(limlist) do - local time = mp.format_time(v.time) - local title = v.title - if title == nil then - title = string.format('Chapter %02d', i) - end - message = string.format('%s[%s] %s %s\n', message, time, - (v.current and 'โ—' or 'โ—‹'), title) - end - return message -end - -function show_message(text, duration) - - --print("text: "..text.." duration: " .. duration) - if duration == nil then - duration = tonumber(mp.get_property("options/osd-duration")) / 1000 - elseif not type(duration) == "number" then - print("duration: " .. duration) - end - - -- cut the text short, otherwise the following functions - -- may slow down massively on huge input - text = string.sub(text, 0, 4000) - - -- replace actual linebreaks with ASS linebreaks - text = string.gsub(text, "\n", "\\N") - - state.message_text = text - state.message_timeout = mp.get_time() + duration -end - -function render_message(ass) - if not(state.message_timeout == nil) and not(state.message_text == nil) - and state.message_timeout > mp.get_time() then - local _, lines = string.gsub(state.message_text, "\\N", "") - - local fontsize = tonumber(mp.get_property("options/osd-font-size")) - local outline = tonumber(mp.get_property("options/osd-border-size")) - local maxlines = math.ceil(osc_param.unscaled_y*0.75 / fontsize) - local counterscale = osc_param.playresy / osc_param.unscaled_y - - fontsize = fontsize * counterscale / math.max(0.65 + math.min(lines/maxlines, 1), 1) - outline = outline * counterscale / math.max(0.75 + math.min(lines/maxlines, 1)/2, 1) - - local style = "{\\bord" .. outline .. "\\fs" .. fontsize .. "}" - - - ass:new_event() - ass:append(style .. state.message_text) - else - state.message_text = nil - state.message_timeout = nil - end -end - --- --- Initialisation and Layout --- - -function new_element(name, type) - elements[name] = {} - elements[name].type = type - - -- add default stuff - elements[name].eventresponder = {} - elements[name].visible = true - elements[name].enabled = true - elements[name].softrepeat = false - elements[name].styledown = (type == "button") - elements[name].state = {} - - if (type == "slider") then - elements[name].slider = {min = {value = 0}, max = {value = 100}} - end - - - return elements[name] -end - -function add_layout(name) - if not (elements[name] == nil) then - -- new layout - elements[name].layout = {} - - -- set layout defaults - elements[name].layout.layer = 50 - elements[name].layout.alpha = {[1] = 0, [2] = 255, [3] = 255, [4] = 255} - - if (elements[name].type == "button") then - elements[name].layout.button = { - maxchars = nil, - } - elseif (elements[name].type == "slider") then - -- slider defaults - elements[name].layout.slider = { - border = 1, - gap = 1, - nibbles_top = true, - nibbles_bottom = true, - stype = "slider", - adjust_tooltip = true, - tooltip_style = "", - tooltip_an = 2, - alpha = {[1] = 0, [2] = 255, [3] = 88, [4] = 255}, - } - elseif (elements[name].type == "box") then - elements[name].layout.box = {radius = 0} - end - - return elements[name].layout - else - msg.error("Can't add_layout to element \""..name.."\", doesn't exist.") - end -end - --- --- Layouts --- - -local layouts = {} - --- Classic box layout -layouts["box"] = function () - - local osc_geo = { - w = 550, -- width - h = 138, -- height - r = 10, -- corner-radius - p = 15, -- padding - } - - -- make sure the OSC actually fits into the video - if (osc_param.playresx < (osc_geo.w + (2 * osc_geo.p))) then - osc_param.playresy = (osc_geo.w+(2*osc_geo.p))/osc_param.display_aspect - osc_param.playresx = osc_param.playresy * osc_param.display_aspect - end - - -- position of the controller according to video aspect and valignment - local posX = math.floor(get_align(user_opts.halign, osc_param.playresx, - osc_geo.w, 0)) - local posY = math.floor(get_align(user_opts.valign, osc_param.playresy, - osc_geo.h, 0)) - - -- position offset for contents aligned at the borders of the box - local pos_offsetX = (osc_geo.w - (2*osc_geo.p)) / 2 - local pos_offsetY = (osc_geo.h - (2*osc_geo.p)) / 2 - - osc_param.areas = {} -- delete areas - - -- area for active mouse input - add_area("input", get_hitbox_coords(posX, posY, 5, osc_geo.w, osc_geo.h)) - - -- area for show/hide - local sh_area_y0, sh_area_y1 - if user_opts.valign > 0 then - -- deadzone above OSC - sh_area_y0 = get_align(-1 + (2*user_opts.deadzonesize), - posY - (osc_geo.h / 2), 0, 0) - sh_area_y1 = osc_param.playresy - else - -- deadzone below OSC - sh_area_y0 = 0 - sh_area_y1 = (posY + (osc_geo.h / 2)) + - get_align(1 - (2*user_opts.deadzonesize), - osc_param.playresy - (posY + (osc_geo.h / 2)), 0, 0) - end - add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1) - - -- fetch values - local osc_w, osc_h, osc_r, osc_p = - osc_geo.w, osc_geo.h, osc_geo.r, osc_geo.p - - local lo - - -- - -- Background box - -- - - new_element("bgbox", "box") - lo = add_layout("bgbox") - - lo.geometry = {x = posX, y = posY, an = 5, w = osc_w, h = osc_h} - lo.layer = 10 - lo.style = osc_styles.box - lo.alpha[1] = user_opts.boxalpha - lo.alpha[3] = user_opts.boxalpha - lo.box.radius = osc_r - - -- - -- Title row - -- - - local titlerowY = posY - pos_offsetY - 10 - - lo = add_layout("title") - lo.geometry = {x = posX, y = titlerowY, an = 8, w = 496, h = 12} - lo.style = osc_styles.vidtitle - lo.button.maxchars = user_opts.boxmaxchars - - lo = add_layout("pl_prev") - lo.geometry = - {x = (posX - pos_offsetX), y = titlerowY, an = 7, w = 12, h = 12} - lo.style = osc_styles.topButtons - - lo = add_layout("pl_next") - lo.geometry = - {x = (posX + pos_offsetX), y = titlerowY, an = 9, w = 12, h = 12} - lo.style = osc_styles.topButtons - - -- - -- Big buttons - -- - - local bigbtnrowY = posY - pos_offsetY + 35 - local bigbtndist = 60 - - lo = add_layout("playpause") - lo.geometry = - {x = posX, y = bigbtnrowY, an = 5, w = 40, h = 40} - lo.style = osc_styles.bigButtons - - lo = add_layout("skipback") - lo.geometry = - {x = posX - bigbtndist, y = bigbtnrowY, an = 5, w = 40, h = 40} - lo.style = osc_styles.bigButtons - - lo = add_layout("skipfrwd") - lo.geometry = - {x = posX + bigbtndist, y = bigbtnrowY, an = 5, w = 40, h = 40} - lo.style = osc_styles.bigButtons - - lo = add_layout("ch_prev") - lo.geometry = - {x = posX - (bigbtndist * 2), y = bigbtnrowY, an = 5, w = 40, h = 40} - lo.style = osc_styles.bigButtons - - lo = add_layout("ch_next") - lo.geometry = - {x = posX + (bigbtndist * 2), y = bigbtnrowY, an = 5, w = 40, h = 40} - lo.style = osc_styles.bigButtons - - lo = add_layout("cy_audio") - lo.geometry = - {x = posX - pos_offsetX, y = bigbtnrowY, an = 1, w = 70, h = 18} - lo.style = osc_styles.smallButtonsL - - lo = add_layout("cy_sub") - lo.geometry = - {x = posX - pos_offsetX, y = bigbtnrowY, an = 7, w = 70, h = 18} - lo.style = osc_styles.smallButtonsL - - lo = add_layout("tog_fs") - lo.geometry = - {x = posX+pos_offsetX - 25, y = bigbtnrowY, an = 4, w = 25, h = 25} - lo.style = osc_styles.smallButtonsR - - lo = add_layout("volume") - lo.geometry = - {x = posX+pos_offsetX - (25 * 2) - osc_geo.p, - y = bigbtnrowY, an = 4, w = 25, h = 25} - lo.style = osc_styles.smallButtonsR - - -- - -- Seekbar - -- - - lo = add_layout("seekbar") - lo.geometry = - {x = posX, y = posY+pos_offsetY-22, an = 2, w = pos_offsetX*2, h = 15} - lo.style = osc_styles.timecodes - lo.slider.tooltip_style = osc_styles.vidtitle - lo.slider.stype = user_opts["seekbarstyle"] - if lo.slider.stype == "knob" then - lo.slider.border = 0 - end - - -- - -- Timecodes + Cache - -- - - local bottomrowY = posY + pos_offsetY - 5 - - lo = add_layout("tc_left") - lo.geometry = - {x = posX - pos_offsetX, y = bottomrowY, an = 4, w = 110, h = 18} - lo.style = osc_styles.timecodes - - lo = add_layout("tc_right") - lo.geometry = - {x = posX + pos_offsetX, y = bottomrowY, an = 6, w = 110, h = 18} - lo.style = osc_styles.timecodes - - lo = add_layout("cache") - lo.geometry = - {x = posX, y = bottomrowY, an = 5, w = 110, h = 18} - lo.style = osc_styles.timecodes - -end - --- slim box layout -layouts["slimbox"] = function () - - local osc_geo = { - w = 660, -- width - h = 70, -- height - r = 10, -- corner-radius - } - - -- make sure the OSC actually fits into the video - if (osc_param.playresx < (osc_geo.w)) then - osc_param.playresy = (osc_geo.w)/osc_param.display_aspect - osc_param.playresx = osc_param.playresy * osc_param.display_aspect - end - - -- position of the controller according to video aspect and valignment - local posX = math.floor(get_align(user_opts.halign, osc_param.playresx, - osc_geo.w, 0)) - local posY = math.floor(get_align(user_opts.valign, osc_param.playresy, - osc_geo.h, 0)) - - osc_param.areas = {} -- delete areas - - -- area for active mouse input - add_area("input", get_hitbox_coords(posX, posY, 5, osc_geo.w, osc_geo.h)) - - -- area for show/hide - local sh_area_y0, sh_area_y1 - if user_opts.valign > 0 then - -- deadzone above OSC - sh_area_y0 = get_align(-1 + (2*user_opts.deadzonesize), - posY - (osc_geo.h / 2), 0, 0) - sh_area_y1 = osc_param.playresy - else - -- deadzone below OSC - sh_area_y0 = 0 - sh_area_y1 = (posY + (osc_geo.h / 2)) + - get_align(1 - (2*user_opts.deadzonesize), - osc_param.playresy - (posY + (osc_geo.h / 2)), 0, 0) - end - add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1) - - local lo - - local tc_w, ele_h, inner_w = 100, 20, osc_geo.w - 100 - - -- styles - local styles = { - box = "{\\rDefault\\blur0\\bord1\\1c&H000000\\3c&HFFFFFF}", - timecodes = "{\\1c&HFFFFFF\\3c&H000000\\fs20\\bord2\\blur1}", - tooltip = "{\\1c&HFFFFFF\\3c&H000000\\fs12\\bord1\\blur0.5}", - } - - - new_element("bgbox", "box") - lo = add_layout("bgbox") - - lo.geometry = {x = posX, y = posY - 1, an = 2, w = inner_w, h = ele_h} - lo.layer = 10 - lo.style = osc_styles.box - lo.alpha[1] = user_opts.boxalpha - lo.alpha[3] = 0 - if not (user_opts["seekbarstyle"] == "bar") then - lo.box.radius = osc_geo.r - end - - - lo = add_layout("seekbar") - lo.geometry = - {x = posX, y = posY - 1, an = 2, w = inner_w, h = ele_h} - lo.style = osc_styles.timecodes - lo.slider.border = 0 - lo.slider.gap = 1.5 - lo.slider.tooltip_style = styles.tooltip - lo.slider.stype = user_opts["seekbarstyle"] - lo.slider.adjust_tooltip = false - - -- - -- Timecodes - -- - - lo = add_layout("tc_left") - lo.geometry = - {x = posX - (inner_w/2) + osc_geo.r, y = posY + 1, - an = 7, w = tc_w, h = ele_h} - lo.style = styles.timecodes - lo.alpha[3] = user_opts.boxalpha - - lo = add_layout("tc_right") - lo.geometry = - {x = posX + (inner_w/2) - osc_geo.r, y = posY + 1, - an = 9, w = tc_w, h = ele_h} - lo.style = styles.timecodes - lo.alpha[3] = user_opts.boxalpha - - -- Cache - - lo = add_layout("cache") - lo.geometry = - {x = posX, y = posY + 1, - an = 8, w = tc_w, h = ele_h} - lo.style = styles.timecodes - lo.alpha[3] = user_opts.boxalpha - - -end - -layouts["bottombar"] = function() - local osc_geo = { - x = -2, - y = osc_param.playresy - 54 - user_opts.barmargin, - an = 7, - w = osc_param.playresx + 4, - h = 56, - } - - local padX = 9 - local padY = 3 - local buttonW = 27 - local tcW = (state.tc_ms) and 170 or 110 - local tsW = 90 - local minW = (buttonW + padX)*5 + (tcW + padX)*4 + (tsW + padX)*2 - - if ((osc_param.display_aspect > 0) and (osc_param.playresx < minW)) then - osc_param.playresy = minW / osc_param.display_aspect - osc_param.playresx = osc_param.playresy * osc_param.display_aspect - osc_geo.y = osc_param.playresy - 54 - user_opts.barmargin - osc_geo.w = osc_param.playresx + 4 - end - - local line1 = osc_geo.y + 9 + padY - local line2 = osc_geo.y + 36 + padY - - osc_param.areas = {} - - add_area("input", get_hitbox_coords(osc_geo.x, osc_geo.y, osc_geo.an, - osc_geo.w, osc_geo.h)) - - local sh_area_y0, sh_area_y1 - sh_area_y0 = get_align(-1 + (2*user_opts.deadzonesize), - osc_geo.y - (osc_geo.h / 2), 0, 0) - sh_area_y1 = osc_param.playresy - user_opts.barmargin - add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1) - - local lo, geo - - -- Background bar - new_element("bgbox", "box") - lo = add_layout("bgbox") - - lo.geometry = osc_geo - lo.layer = 10 - lo.style = osc_styles.box - lo.alpha[1] = user_opts.boxalpha - - - -- Playlist prev/next - geo = { x = osc_geo.x + padX, y = line1, - an = 4, w = 18, h = 18 - padY } - lo = add_layout("pl_prev") - lo.geometry = geo - lo.style = osc_styles.topButtonsBar - - geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("pl_next") - lo.geometry = geo - lo.style = osc_styles.topButtonsBar - - local t_l = geo.x + geo.w + padX - - -- Cache - geo = { x = osc_geo.x + osc_geo.w - padX, y = geo.y, - an = 6, w = 150, h = geo.h } - lo = add_layout("cache") - lo.geometry = geo - lo.style = osc_styles.vidtitleBar - - local t_r = geo.x - geo.w - padX*2 - - -- Title - geo = { x = t_l, y = geo.y, an = 4, - w = t_r - t_l, h = geo.h } - lo = add_layout("title") - lo.geometry = geo - lo.style = string.format("%s{\\clip(%f,%f,%f,%f)}", - osc_styles.vidtitleBar, - geo.x, geo.y-geo.h, geo.w, geo.y+geo.h) - - - -- Playback control buttons - geo = { x = osc_geo.x + padX, y = line2, an = 4, - w = buttonW, h = 36 - padY*2} - lo = add_layout("playpause") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("ch_prev") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("ch_next") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - -- Left timecode - geo = { x = geo.x + geo.w + padX + tcW, y = geo.y, an = 6, - w = tcW, h = geo.h } - lo = add_layout("tc_left") - lo.geometry = geo - lo.style = osc_styles.timecodesBar - - local sb_l = geo.x + padX - - -- Fullscreen button - geo = { x = osc_geo.x + osc_geo.w - buttonW - padX, y = geo.y, an = 4, - w = buttonW, h = geo.h } - lo = add_layout("tog_fs") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - -- Volume - geo = { x = geo.x - geo.w - padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("volume") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - -- Track selection buttons - geo = { x = geo.x - tsW - padX, y = geo.y, an = geo.an, w = tsW, h = geo.h } - lo = add_layout("cy_sub") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - geo = { x = geo.x - geo.w - padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("cy_audio") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - - -- Right timecode - geo = { x = geo.x - padX - tcW - 10, y = geo.y, an = geo.an, - w = tcW, h = geo.h } - lo = add_layout("tc_right") - lo.geometry = geo - lo.style = osc_styles.timecodesBar - - local sb_r = geo.x - padX - - - -- Seekbar - geo = { x = sb_l, y = geo.y, an = geo.an, - w = math.max(0, sb_r - sb_l), h = geo.h } - new_element("bgbar1", "box") - lo = add_layout("bgbar1") - - lo.geometry = geo - lo.layer = 15 - lo.style = osc_styles.timecodesBar - lo.alpha[1] = - math.min(255, user_opts.boxalpha + (255 - user_opts.boxalpha)*0.8) - - lo = add_layout("seekbar") - lo.geometry = geo - lo.style = osc_styles.timecodes - lo.slider.border = 0 - lo.slider.gap = 2 - lo.slider.tooltip_style = osc_styles.timePosBar - lo.slider.tooltip_an = 5 - lo.slider.stype = user_opts["seekbarstyle"] -end - -layouts["topbar"] = function() - local osc_geo = { - x = -2, - y = 54 + user_opts.barmargin, - an = 1, - w = osc_param.playresx + 4, - h = 56, - } - - local padX = 9 - local padY = 3 - local buttonW = 27 - local tcW = (state.tc_ms) and 170 or 110 - local tsW = 90 - local minW = (buttonW + padX)*5 + (tcW + padX)*4 + (tsW + padX)*2 - - if ((osc_param.display_aspect > 0) and (osc_param.playresx < minW)) then - osc_param.playresy = minW / osc_param.display_aspect - osc_param.playresx = osc_param.playresy * osc_param.display_aspect - osc_geo.y = 54 + user_opts.barmargin - osc_geo.w = osc_param.playresx + 4 - end - - local line1 = osc_geo.y - 36 - padY - local line2 = osc_geo.y - 9 - padY - - osc_param.areas = {} - - add_area("input", get_hitbox_coords(osc_geo.x, osc_geo.y, osc_geo.an, - osc_geo.w, osc_geo.h)) - - local sh_area_y0, sh_area_y1 - sh_area_y0 = user_opts.barmargin - sh_area_y1 = (osc_geo.y + (osc_geo.h / 2)) + - get_align(1 - (2*user_opts.deadzonesize), - osc_param.playresy - (osc_geo.y + (osc_geo.h / 2)), 0, 0) - add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1) - - local lo, geo - - -- Background bar - new_element("bgbox", "box") - lo = add_layout("bgbox") - - lo.geometry = osc_geo - lo.layer = 10 - lo.style = osc_styles.box - lo.alpha[1] = user_opts.boxalpha - - - -- Playback control buttons - geo = { x = osc_geo.x + padX, y = line1, an = 4, - w = buttonW, h = 36 - padY*2 } - lo = add_layout("playpause") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("ch_prev") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("ch_next") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - - -- Left timecode - geo = { x = geo.x + geo.w + padX + tcW, y = geo.y, an = 6, - w = tcW, h = geo.h } - lo = add_layout("tc_left") - lo.geometry = geo - lo.style = osc_styles.timecodesBar - - local sb_l = geo.x + padX - - -- Fullscreen button - geo = { x = osc_geo.x + osc_geo.w - buttonW - padX, y = geo.y, an = 4, - w = buttonW, h = geo.h } - lo = add_layout("tog_fs") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - -- Volume - geo = { x = geo.x - geo.w - padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("volume") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - -- Track selection buttons - geo = { x = geo.x - tsW - padX, y = geo.y, an = geo.an, w = tsW, h = geo.h } - lo = add_layout("cy_sub") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - geo = { x = geo.x - geo.w - padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("cy_audio") - lo.geometry = geo - lo.style = osc_styles.smallButtonsBar - - - -- Right timecode - geo = { x = geo.x - geo.w - padX - tcW - 10, y = geo.y, an = 4, - w = tcW, h = geo.h } - lo = add_layout("tc_right") - lo.geometry = geo - lo.style = osc_styles.timecodesBar - - local sb_r = geo.x - padX - - - -- Seekbar - geo = { x = sb_l, y = user_opts.barmargin, an = 7, - w = math.max(0, sb_r - sb_l), h = geo.h } - new_element("bgbar1", "box") - lo = add_layout("bgbar1") - - lo.geometry = geo - lo.layer = 15 - lo.style = osc_styles.timecodesBar - lo.alpha[1] = - math.min(255, user_opts.boxalpha + (255 - user_opts.boxalpha)*0.8) - - lo = add_layout("seekbar") - lo.geometry = geo - lo.style = osc_styles.timecodesBar - lo.slider.border = 0 - lo.slider.gap = 2 - lo.slider.tooltip_style = osc_styles.timePosBar - lo.slider.stype = user_opts["seekbarstyle"] - lo.slider.tooltip_an = 5 - - - -- Playlist prev/next - geo = { x = osc_geo.x + padX, y = line2, an = 4, w = 18, h = 18 - padY } - lo = add_layout("pl_prev") - lo.geometry = geo - lo.style = osc_styles.topButtonsBar - - geo = { x = geo.x + geo.w + padX, y = geo.y, an = geo.an, w = geo.w, h = geo.h } - lo = add_layout("pl_next") - lo.geometry = geo - lo.style = osc_styles.topButtonsBar - - local t_l = geo.x + geo.w + padX - - -- Cache - geo = { x = osc_geo.x + osc_geo.w - padX, y = geo.y, - an = 6, w = 150, h = geo.h } - lo = add_layout("cache") - lo.geometry = geo - lo.style = osc_styles.vidtitleBar - - local t_r = geo.x - geo.w - padX*2 - - -- Title - geo = { x = t_l, y = geo.y, an = 4, - w = t_r - t_l, h = geo.h } - lo = add_layout("title") - lo.geometry = geo - lo.style = string.format("%s{\\clip(%f,%f,%f,%f)}", - osc_styles.vidtitleBar, - geo.x, geo.y-geo.h, geo.w, geo.y+geo.h) -end - --- Validate string type user options -function validate_user_opts() - if layouts[user_opts.layout] == nil then - msg.warn("Invalid setting \""..user_opts.layout.."\" for layout") - user_opts.layout = "box" - end - - if user_opts.seekbarstyle ~= "slider" and - user_opts.seekbarstyle ~= "bar" and - user_opts.seekbarstyle ~= "knob" then - msg.warn("Invalid setting \"" .. user_opts.seekbarstyle - .. "\" for seekbarstyle") - user_opts.seekbarstyle = "slider" - end -end - - --- OSC INIT -function osc_init() - msg.debug("osc_init") - - -- set canvas resolution according to display aspect and scaling setting - local baseResY = 720 - local display_w, display_h, display_aspect = mp.get_osd_size() - local scale = 1 - - if (mp.get_property("video") == "no") then -- dummy/forced window - scale = user_opts.scaleforcedwindow - elseif state.fullscreen then - scale = user_opts.scalefullscreen - else - scale = user_opts.scalewindowed - end - - if user_opts.vidscale then - osc_param.unscaled_y = baseResY - else - osc_param.unscaled_y = display_h - end - osc_param.playresy = osc_param.unscaled_y / scale - if (display_aspect > 0) then - osc_param.display_aspect = display_aspect - end - osc_param.playresx = osc_param.playresy * osc_param.display_aspect - - - - - - elements = {} - - -- some often needed stuff - local pl_count = mp.get_property_number("playlist-count", 0) - local have_pl = (pl_count > 1) - local pl_pos = mp.get_property_number("playlist-pos", 0) + 1 - local have_ch = (mp.get_property_number("chapters", 0) > 0) - local loop = mp.get_property("loop-playlist", "no") - - local ne - - -- title - ne = new_element("title", "button") - - ne.content = function () - local title = mp.command_native({"expand-text", user_opts.title}) - -- escape ASS, and strip newlines and trailing slashes - title = title:gsub("\\n", " "):gsub("\\$", ""):gsub("{","\\{") - return not (title == "") and title or "mpv" - end - - ne.eventresponder["mbtn_left_up"] = function () - local title = mp.get_property_osd("media-title") - if (have_pl) then - title = string.format("[%d/%d] %s", countone(pl_pos - 1), - pl_count, title) - end - show_message(title) - end - - ne.eventresponder["mbtn_right_up"] = - function () show_message(mp.get_property_osd("filename")) end - - -- playlist buttons - - -- prev - ne = new_element("pl_prev", "button") - - ne.content = "\238\132\144" - ne.enabled = (pl_pos > 1) or (loop ~= "no") - ne.eventresponder["mbtn_left_up"] = - function () - mp.commandv("playlist-prev", "weak") - show_message(get_playlist(), 3) - end - ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_playlist(), 3) end - ne.eventresponder["mbtn_right_up"] = - function () show_message(get_playlist(), 3) end - - --next - ne = new_element("pl_next", "button") - - ne.content = "\238\132\129" - ne.enabled = (have_pl and (pl_pos < pl_count)) or (loop ~= "no") - ne.eventresponder["mbtn_left_up"] = - function () - mp.commandv("playlist-next", "weak") - show_message(get_playlist(), 3) - end - ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_playlist(), 3) end - ne.eventresponder["mbtn_right_up"] = - function () show_message(get_playlist(), 3) end - - - -- big buttons - - --playpause - ne = new_element("playpause", "button") - - ne.content = function () - if mp.get_property("pause") == "yes" then - return ("\238\132\129") - else - return ("\238\128\130") - end - end - ne.eventresponder["mbtn_left_up"] = - function () mp.commandv("cycle", "pause") end - - --skipback - ne = new_element("skipback", "button") - - ne.softrepeat = true - ne.content = "\238\128\132" - ne.eventresponder["mbtn_left_down"] = - function () mp.commandv("seek", -5, "relative", "keyframes") end - ne.eventresponder["shift+mbtn_left_down"] = - function () mp.commandv("frame-back-step") end - ne.eventresponder["mbtn_right_down"] = - function () mp.commandv("seek", -30, "relative", "keyframes") end - - --skipfrwd - ne = new_element("skipfrwd", "button") - - ne.softrepeat = true - ne.content = "\238\128\133" - ne.eventresponder["mbtn_left_down"] = - function () mp.commandv("seek", 10, "relative", "keyframes") end - ne.eventresponder["shift+mbtn_left_down"] = - function () mp.commandv("frame-step") end - ne.eventresponder["mbtn_right_down"] = - function () mp.commandv("seek", 60, "relative", "keyframes") end - - --ch_prev - ne = new_element("ch_prev", "button") - - ne.enabled = have_ch - ne.content = "\238\132\132" - ne.eventresponder["mbtn_left_up"] = - function () - mp.commandv("add", "chapter", -1) - show_message(get_chapterlist(), 3) - end - ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_chapterlist(), 3) end - ne.eventresponder["mbtn_right_up"] = - function () show_message(get_chapterlist(), 3) end - - --ch_next - ne = new_element("ch_next", "button") - - ne.enabled = have_ch - ne.content = "\238\132\133" - ne.eventresponder["mbtn_left_up"] = - function () - mp.commandv("add", "chapter", 1) - show_message(get_chapterlist(), 3) - end - ne.eventresponder["shift+mbtn_left_up"] = - function () show_message(get_chapterlist(), 3) end - ne.eventresponder["mbtn_right_up"] = - function () show_message(get_chapterlist(), 3) end - - -- - update_tracklist() - - --cy_audio - ne = new_element("cy_audio", "button") - - ne.enabled = (#tracks_osc.audio > 0) - ne.content = function () - local aid = "โ€“" - if not (get_track("audio") == 0) then - aid = get_track("audio") - end - return ("\238\132\134" .. osc_styles.smallButtonsLlabel - .. " " .. aid .. "/" .. #tracks_osc.audio) - end - ne.eventresponder["mbtn_left_up"] = - function () set_track("audio", 1) end - ne.eventresponder["mbtn_right_up"] = - function () set_track("audio", -1) end - ne.eventresponder["shift+mbtn_left_down"] = - function () show_message(get_tracklist("audio"), 2) end - - --cy_sub - ne = new_element("cy_sub", "button") - - ne.enabled = (#tracks_osc.sub > 0) - ne.content = function () - local sid = "โ€“" - if not (get_track("sub") == 0) then - sid = get_track("sub") - end - return ("\238\132\135" .. osc_styles.smallButtonsLlabel - .. " " .. sid .. "/" .. #tracks_osc.sub) - end - ne.eventresponder["mbtn_left_up"] = - function () set_track("sub", 1) end - ne.eventresponder["mbtn_right_up"] = - function () set_track("sub", -1) end - ne.eventresponder["shift+mbtn_left_down"] = - function () show_message(get_tracklist("sub"), 2) end - - --tog_fs - ne = new_element("tog_fs", "button") - ne.content = function () - if (state.fullscreen) then - return ("\238\132\137") - else - return ("\238\132\136") - end - end - ne.eventresponder["mbtn_left_up"] = - function () mp.commandv("cycle", "fullscreen") end - - - --seekbar - ne = new_element("seekbar", "slider") - - ne.enabled = not (mp.get_property("percent-pos") == nil) - ne.slider.markerF = function () - local duration = mp.get_property_number("duration", nil) - if not (duration == nil) then - local chapters = mp.get_property_native("chapter-list", {}) - local markers = {} - for n = 1, #chapters do - markers[n] = (chapters[n].time / duration * 100) - end - return markers - else - return {} - end - end - ne.slider.posF = - function () return mp.get_property_number("percent-pos", nil) end - ne.slider.tooltipF = function (pos) - local duration = mp.get_property_number("duration", nil) - if not ((duration == nil) or (pos == nil)) then - possec = duration * (pos / 100) - return mp.format_time(possec) - else - return "" - end - end - ne.slider.seekRangesF = function() - if not (user_opts.seekranges) then - return nil - end - local cache_state = mp.get_property_native("demuxer-cache-state", nil) - if not cache_state then - return nil - end - local duration = mp.get_property_number("duration", nil) - if (duration == nil) or duration <= 0 then - return nil - end - local ranges = cache_state["seekable-ranges"] - for _, range in pairs(ranges) do - range["start"] = 100 * range["start"] / duration - range["end"] = 100 * range["end"] / duration - end - return ranges - end - ne.eventresponder["mouse_move"] = --keyframe seeking when mouse is dragged - function (element) - -- mouse move events may pile up during seeking and may still get - -- sent when the user is done seeking, so we need to throw away - -- identical seeks - local seekto = get_slider_value(element) - if (element.state.lastseek == nil) or - (not (element.state.lastseek == seekto)) then - mp.commandv("seek", seekto, - "absolute-percent", "keyframes") - element.state.lastseek = seekto - end - - end - ne.eventresponder["mbtn_left_down"] = --exact seeks on single clicks - function (element) mp.commandv("seek", get_slider_value(element), - "absolute-percent", "exact") end - ne.eventresponder["reset"] = - function (element) element.state.lastseek = nil end - - - -- tc_left (current pos) - ne = new_element("tc_left", "button") - - ne.content = function () - if (state.tc_ms) then - return (mp.get_property_osd("playback-time/full")) - else - return (mp.get_property_osd("playback-time")) - end - end - ne.eventresponder["mbtn_left_up"] = function () - state.tc_ms = not state.tc_ms - request_init() - end - - -- tc_right (total/remaining time) - ne = new_element("tc_right", "button") - - ne.visible = (mp.get_property_number("duration", 0) > 0) - ne.content = function () - if (state.rightTC_trem) then - if state.tc_ms then - return ("-"..mp.get_property_osd("playtime-remaining/full")) - else - return ("-"..mp.get_property_osd("playtime-remaining")) - end - else - if state.tc_ms then - return (mp.get_property_osd("duration/full")) - else - return (mp.get_property_osd("duration")) - end - end - end - ne.eventresponder["mbtn_left_up"] = - function () state.rightTC_trem = not state.rightTC_trem end - - -- cache - ne = new_element("cache", "button") - - ne.content = function () - local dmx_cache = mp.get_property_number("demuxer-cache-duration") - local cache_used = mp.get_property_number("cache-used") - local dmx_cache_state = mp.get_property_native("demuxer-cache-state", {}) - local is_network = mp.get_property_native("demuxer-via-network") - local show_cache = cache_used and not dmx_cache_state["eof"] - if dmx_cache then - dmx_cache = string.format("%3.0fs", dmx_cache) - end - if dmx_cache_state["fw-bytes"] then - cache_used = (cache_used or 0)*1024 + dmx_cache_state["fw-bytes"] - end - if (is_network and dmx_cache) or show_cache then - -- Only show dmx-cache-duration by itself if it's a network file. - -- Cache can be forced even for local files, so always show that. - return string.format("Cache: %s%s%s", - (dmx_cache and dmx_cache or ""), - ((dmx_cache and show_cache) and " | " or ""), - (show_cache and - utils.format_bytes_humanized(cache_used) or "")) - else - return "" - end - end - - -- volume - ne = new_element("volume", "button") - - ne.content = function() - local volume = mp.get_property_number("volume", 0) - local mute = mp.get_property_native("mute") - local volicon = {"\238\132\139", "\238\132\140", - "\238\132\141", "\238\132\142"} - if volume == 0 or mute then - return "\238\132\138" - else - return volicon[math.min(4,math.ceil(volume / (100/3)))] - end - end - ne.eventresponder["mbtn_left_up"] = - function () mp.commandv("cycle", "mute") end - - ne.eventresponder["wheel_up_press"] = - function () mp.commandv("osd-auto", "add", "volume", 5) end - ne.eventresponder["wheel_down_press"] = - function () mp.commandv("osd-auto", "add", "volume", -5) end - - - -- load layout - layouts[user_opts.layout]() - - --do something with the elements - prepare_elements() - -end - - - --- --- Other important stuff --- - - -function show_osc() - -- show when disabled can happen (e.g. mouse_move) due to async/delayed unbinding - if not state.enabled then return end - - msg.trace("show_osc") - --remember last time of invocation (mouse move) - state.showtime = mp.get_time() - - osc_visible(true) - - if (user_opts.fadeduration > 0) then - state.anitype = nil - end -end - -function hide_osc() - msg.trace("hide_osc") - if not state.enabled then - -- typically hide happens at render() from tick(), but now tick() is - -- no-op and won't render again to remove the osc, so do that manually. - state.osc_visible = false - timer_stop() - render_wipe() - elseif (user_opts.fadeduration > 0) then - if not(state.osc_visible == false) then - state.anitype = "out" - control_timer() - end - else - osc_visible(false) - end -end - -function osc_visible(visible) - state.osc_visible = visible - control_timer() -end - -function pause_state(name, enabled) - state.paused = enabled - control_timer() -end - -function cache_state(name, idle) - state.cache_idle = idle - control_timer() -end - -function control_timer() - if (state.paused) and (state.osc_visible) and - ( not(state.cache_idle) or not (state.anitype == nil) ) then - - timer_start() - else - timer_stop() - end -end - -function timer_start() - if not (state.timer_active) then - msg.trace("timer start") - - if (state.timer == nil) then - -- create new timer - state.timer = mp.add_periodic_timer(0.03, tick) - else - -- resume existing one - state.timer:resume() - end - - state.timer_active = true - end -end - -function timer_stop() - if (state.timer_active) then - msg.trace("timer stop") - - if not (state.timer == nil) then - -- kill timer - state.timer:kill() - end - - state.timer_active = false - end -end - - - -function mouse_leave() - if user_opts.hidetimeout >= 0 then - hide_osc() - end - -- reset mouse position - state.last_mouseX, state.last_mouseY = nil, nil -end - -function request_init() - state.initREQ = true -end - -function render_wipe() - msg.trace("render_wipe()") - mp.set_osd_ass(0, 0, "{}") -end - -function render() - msg.trace("rendering") - local current_screen_sizeX, current_screen_sizeY, aspect = mp.get_osd_size() - local mouseX, mouseY = get_virt_mouse_pos() - local now = mp.get_time() - - -- check if display changed, if so request reinit - if not (state.mp_screen_sizeX == current_screen_sizeX - and state.mp_screen_sizeY == current_screen_sizeY) then - - request_init() - - state.mp_screen_sizeX = current_screen_sizeX - state.mp_screen_sizeY = current_screen_sizeY - end - - -- init management - if state.initREQ then - osc_init() - state.initREQ = false - - -- store initial mouse position - if (state.last_mouseX == nil or state.last_mouseY == nil) - and not (mouseX == nil or mouseY == nil) then - - state.last_mouseX, state.last_mouseY = mouseX, mouseY - end - end - - - -- fade animation - if not(state.anitype == nil) then - - if (state.anistart == nil) then - state.anistart = now - end - - if (now < state.anistart + (user_opts.fadeduration/1000)) then - - if (state.anitype == "in") then --fade in - osc_visible(true) - state.animation = scale_value(state.anistart, - (state.anistart + (user_opts.fadeduration/1000)), - 255, 0, now) - elseif (state.anitype == "out") then --fade out - state.animation = scale_value(state.anistart, - (state.anistart + (user_opts.fadeduration/1000)), - 0, 255, now) - end - - else - if (state.anitype == "out") then - osc_visible(false) - end - state.anistart = nil - state.animation = nil - state.anitype = nil - end - else - state.anistart = nil - state.animation = nil - state.anitype = nil - end - - --mouse show/hide area - for k,cords in pairs(osc_param.areas["showhide"]) do - set_virt_mouse_area(cords.x1, cords.y1, cords.x2, cords.y2, "showhide") - end - do_enable_keybindings() - - --mouse input area - local mouse_over_osc = false - - for _,cords in ipairs(osc_param.areas["input"]) do - if state.osc_visible then -- activate only when OSC is actually visible - set_virt_mouse_area(cords.x1, cords.y1, cords.x2, cords.y2, "input") - end - if state.osc_visible ~= state.input_enabled then - if state.osc_visible then - mp.enable_key_bindings("input") - else - mp.disable_key_bindings("input") - end - state.input_enabled = state.osc_visible - end - - if (mouse_hit_coords(cords.x1, cords.y1, cords.x2, cords.y2)) then - mouse_over_osc = true - end - end - - -- autohide - if not (state.showtime == nil) and (user_opts.hidetimeout >= 0) - and (state.showtime + (user_opts.hidetimeout/1000) < now) - and (state.active_element == nil) and not (mouse_over_osc) then - - hide_osc() - end - - - -- actual rendering - local ass = assdraw.ass_new() - - -- Messages - render_message(ass) - - -- mpv_thumbnail_script.lua -- - local thumb_was_visible = osc_thumb_state.visible - osc_thumb_state.visible = false - -- // mpv_thumbnail_script.lua // -- - - -- actual OSC - if state.osc_visible then - render_elements(ass) - end - - -- mpv_thumbnail_script.lua -- - if not osc_thumb_state.visible and thumb_was_visible then - hide_thumbnail() - end - -- // mpv_thumbnail_script.lua // -- - - -- submit - mp.set_osd_ass(osc_param.playresy * osc_param.display_aspect, - osc_param.playresy, ass.text) - - - - -end - --- --- Eventhandling --- - -local function element_has_action(element, action) - return element and element.eventresponder and - element.eventresponder[action] -end - -function process_event(source, what) - local action = string.format("%s%s", source, - what and ("_" .. what) or "") - - if what == "down" or what == "press" then - - for n = 1, #elements do - - if mouse_hit(elements[n]) and - elements[n].eventresponder and - (elements[n].eventresponder[source .. "_up"] or - elements[n].eventresponder[action]) then - - if what == "down" then - state.active_element = n - state.active_event_source = source - end - -- fire the down or press event if the element has one - if element_has_action(elements[n], action) then - elements[n].eventresponder[action](elements[n]) - end - - end - end - - elseif what == "up" then - - if elements[state.active_element] then - local n = state.active_element - - if n == 0 then - --click on background (does not work) - elseif element_has_action(elements[n], action) and - mouse_hit(elements[n]) then - - elements[n].eventresponder[action](elements[n]) - end - - --reset active element - if element_has_action(elements[n], "reset") then - elements[n].eventresponder["reset"](elements[n]) - end - - end - state.active_element = nil - state.mouse_down_counter = 0 - - elseif source == "mouse_move" then - - local mouseX, mouseY = get_virt_mouse_pos() - if (user_opts.minmousemove == 0) or - (not ((state.last_mouseX == nil) or (state.last_mouseY == nil)) and - ((math.abs(mouseX - state.last_mouseX) >= user_opts.minmousemove) - or (math.abs(mouseY - state.last_mouseY) >= user_opts.minmousemove) - ) - ) then - show_osc() - end - state.last_mouseX, state.last_mouseY = mouseX, mouseY - - local n = state.active_element - if element_has_action(elements[n], action) then - elements[n].eventresponder[action](elements[n]) - end - tick() - end -end - --- called by mpv on every frame -function tick() - if (not state.enabled) then return end - - if (state.idle) then - - -- render idle message - msg.trace("idle message") - local icon_x, icon_y = 320 - 26, 140 - - local ass = assdraw.ass_new() - ass:new_event() - ass:pos(icon_x, icon_y) - ass:append("{\\rDefault\\an7\\c&H430142&\\1a&H00&\\bord0\\shad0\\p6}m 1605 828 b 1605 1175 1324 1456 977 1456 631 1456 349 1175 349 828 349 482 631 200 977 200 1324 200 1605 482 1605 828{\\p0}") - ass:new_event() - ass:pos(icon_x, icon_y) - ass:append("{\\rDefault\\an7\\c&HDDDBDD&\\1a&H00&\\bord0\\shad0\\p6}m 1296 910 b 1296 1131 1117 1310 897 1310 676 1310 497 1131 497 910 497 689 676 511 897 511 1117 511 1296 689 1296 910{\\p0}") - ass:new_event() - ass:pos(icon_x, icon_y) - ass:append("{\\rDefault\\an7\\c&H691F69&\\1a&H00&\\bord0\\shad0\\p6}m 762 1113 l 762 708 b 881 776 1000 843 1119 911 1000 978 881 1046 762 1113{\\p0}") - ass:new_event() - ass:pos(icon_x, icon_y) - ass:append("{\\rDefault\\an7\\c&H682167&\\1a&H00&\\bord0\\shad0\\p6}m 925 42 b 463 42 87 418 87 880 87 1343 463 1718 925 1718 1388 1718 1763 1343 1763 880 1763 418 1388 42 925 42 m 925 42 m 977 200 b 1324 200 1605 482 1605 828 1605 1175 1324 1456 977 1456 631 1456 349 1175 349 828 349 482 631 200 977 200{\\p0}") - ass:new_event() - ass:pos(icon_x, icon_y) - ass:append("{\\rDefault\\an7\\c&H753074&\\1a&H00&\\bord0\\shad0\\p6}m 977 198 b 630 198 348 480 348 828 348 1176 630 1458 977 1458 1325 1458 1607 1176 1607 828 1607 480 1325 198 977 198 m 977 198 m 977 202 b 1323 202 1604 483 1604 828 1604 1174 1323 1454 977 1454 632 1454 351 1174 351 828 351 483 632 202 977 202{\\p0}") - ass:new_event() - ass:pos(icon_x, icon_y) - ass:append("{\\rDefault\\an7\\c&HE5E5E5&\\1a&H00&\\bord0\\shad0\\p6}m 895 10 b 401 10 0 410 0 905 0 1399 401 1800 895 1800 1390 1800 1790 1399 1790 905 1790 410 1390 10 895 10 m 895 10 m 925 42 b 1388 42 1763 418 1763 880 1763 1343 1388 1718 925 1718 463 1718 87 1343 87 880 87 418 463 42 925 42{\\p0}") - ass:new_event() - ass:pos(320, icon_y+65) - ass:an(8) - ass:append("Drop files or URLs to play here.") - mp.set_osd_ass(640, 360, ass.text) - - if state.showhide_enabled then - mp.disable_key_bindings("showhide") - state.showhide_enabled = false - end - - - elseif (state.fullscreen and user_opts.showfullscreen) - or (not state.fullscreen and user_opts.showwindowed) then - - -- render the OSC - render() - else - -- Flush OSD - mp.set_osd_ass(osc_param.playresy, osc_param.playresy, "") - end -end - -function do_enable_keybindings() - if state.enabled then - if not state.showhide_enabled then - mp.enable_key_bindings("showhide", "allow-vo-dragging+allow-hide-cursor") - end - state.showhide_enabled = true - end -end - -function enable_osc(enable) - state.enabled = enable - if enable then - do_enable_keybindings() - else - hide_osc() -- acts immediately when state.enabled == false - if state.showhide_enabled then - mp.disable_key_bindings("showhide") - end - state.showhide_enabled = false - end -end - --- mpv_thumbnail_script.lua -- - -local builtin_osc_enabled = mp.get_property_native('osc') -if builtin_osc_enabled then - local err = "You must disable the built-in OSC with osc=no in your configuration!" - mp.osd_message(err, 5) - msg.error(err) - - -- This may break, but since we can, let's try to just disable the builtin OSC. - mp.set_property_native('osc', false) -end - --- // mpv_thumbnail_script.lua // -- - - -validate_user_opts() - -mp.register_event("start-file", request_init) -mp.register_event("tracks-changed", request_init) -mp.observe_property("playlist", nil, request_init) - -mp.register_script_message("osc-message", show_message) -mp.register_script_message("osc-chapterlist", function(dur) - show_message(get_chapterlist(), dur) -end) -mp.register_script_message("osc-playlist", function(dur) - show_message(get_playlist(), dur) -end) -mp.register_script_message("osc-tracklist", function(dur) - local msg = {} - for k,v in pairs(nicetypes) do - table.insert(msg, get_tracklist(k)) - end - show_message(table.concat(msg, '\n\n'), dur) -end) - -mp.observe_property("fullscreen", "bool", - function(name, val) - state.fullscreen = val - request_init() - end -) -mp.observe_property("idle-active", "bool", - function(name, val) - state.idle = val - tick() - end -) -mp.observe_property("pause", "bool", pause_state) -mp.observe_property("cache-idle", "bool", cache_state) -mp.observe_property("vo-configured", "bool", function(name, val) - if val then - mp.register_event("tick", tick) - else - mp.unregister_event(tick) - end -end) - --- mouse show/hide bindings -mp.set_key_bindings({ - {"mouse_move", function(e) process_event("mouse_move", nil) end}, - {"mouse_leave", mouse_leave}, -}, "showhide", "force") -do_enable_keybindings() - ---mouse input bindings -mp.set_key_bindings({ - {"mbtn_left", function(e) process_event("mbtn_left", "up") end, - function(e) process_event("mbtn_left", "down") end}, - {"shift+mbtn_left", function(e) process_event("shift+mbtn_left", "up") end, - function(e) process_event("shift+mbtn_left", "down") end}, - {"mbtn_right", function(e) process_event("mbtn_right", "up") end, - function(e) process_event("mbtn_right", "down") end}, - {"wheel_up", function(e) process_event("wheel_up", "press") end}, - {"wheel_down", function(e) process_event("wheel_down", "press") end}, - {"mbtn_left_dbl", "ignore"}, - {"shift+mbtn_left_dbl", "ignore"}, - {"mbtn_right_dbl", "ignore"}, -}, "input", "force") -mp.enable_key_bindings("input") - - -user_opts.hidetimeout_orig = user_opts.hidetimeout - -function always_on(val) - if val then - user_opts.hidetimeout = -1 -- disable autohide - if state.enabled then show_osc() end - else - user_opts.hidetimeout = user_opts.hidetimeout_orig - if state.enabled then hide_osc() end - end -end - --- mode can be auto/always/never/cycle --- the modes only affect internal variables and not stored on its own. -function visibility_mode(mode, no_osd) - if mode == "cycle" then - if not state.enabled then - mode = "auto" - elseif user_opts.hidetimeout >= 0 then - mode = "always" - else - mode = "never" - end - end - - if mode == "auto" then - always_on(false) - enable_osc(true) - elseif mode == "always" then - enable_osc(true) - always_on(true) - elseif mode == "never" then - enable_osc(false) - else - msg.warn("Ignoring unknown visibility mode '" .. mode .. "'") - return - end - - if not no_osd and tonumber(mp.get_property("osd-level")) >= 1 then - mp.osd_message("OSC visibility: " .. mode) - end -end - -visibility_mode(user_opts.visibility, true) -mp.register_script_message("osc-visibility", visibility_mode) -mp.add_key_binding(nil, "visibility", function() visibility_mode("cycle") end) - -set_virt_mouse_area(0, 0, 0, 0, "input") diff --git a/stow/mpv/dot-config/mpv/scripts/mpv_thumbnail_script_server.lua b/stow/mpv/dot-config/mpv/scripts/mpv_thumbnail_script_server.lua deleted file mode 100644 index 21a34d8..0000000 --- a/stow/mpv/dot-config/mpv/scripts/mpv_thumbnail_script_server.lua +++ /dev/null @@ -1,736 +0,0 @@ ---[[ - Copyright (C) 2017 AMM - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -]]-- ---[[ - mpv_thumbnail_script.lua 0.4.2 - commit a2de250 (branch master) - https://github.com/TheAMM/mpv_thumbnail_script - Built on 2018-02-07 20:36:54 -]]-- -local assdraw = require 'mp.assdraw' -local msg = require 'mp.msg' -local opt = require 'mp.options' -local utils = require 'mp.utils' - --- Determine platform -- -ON_WINDOWS = (package.config:sub(1,1) ~= '/') - --- Some helper functions needed to parse the options -- -function isempty(v) return (v == false) or (v == nil) or (v == "") or (v == 0) or (type(v) == "table" and next(v) == nil) end - -function divmod (a, b) - return math.floor(a / b), a % b -end - --- Better modulo -function bmod( i, N ) - return (i % N + N) % N -end - -function join_paths(...) - local sep = ON_WINDOWS and "\\" or "/" - local result = ""; - for i, p in pairs({...}) do - if p ~= "" then - if is_absolute_path(p) then - result = p - else - result = (result ~= "") and (result:gsub("[\\"..sep.."]*$", "") .. sep .. p) or p - end - end - end - return result:gsub("[\\"..sep.."]*$", "") -end - --- /some/path/file.ext -> /some/path, file.ext -function split_path( path ) - local sep = ON_WINDOWS and "\\" or "/" - local first_index, last_index = path:find('^.*' .. sep) - - if last_index == nil then - return "", path - else - local dir = path:sub(0, last_index-1) - local file = path:sub(last_index+1, -1) - - return dir, file - end -end - -function is_absolute_path( path ) - local tmp, is_win = path:gsub("^[A-Z]:\\", "") - local tmp, is_unix = path:gsub("^/", "") - return (is_win > 0) or (is_unix > 0) -end - -function Set(source) - local set = {} - for _, l in ipairs(source) do set[l] = true end - return set -end - ---------------------------- --- More helper functions -- ---------------------------- - --- Removes all keys from a table, without destroying the reference to it -function clear_table(target) - for key, value in pairs(target) do - target[key] = nil - end -end -function shallow_copy(target) - local copy = {} - for k, v in pairs(target) do - copy[k] = v - end - return copy -end - --- Rounds to given decimals. eg. round_dec(3.145, 0) => 3 -function round_dec(num, idp) - local mult = 10^(idp or 0) - return math.floor(num * mult + 0.5) / mult -end - -function file_exists(name) - local f = io.open(name, "rb") - if f ~= nil then - local ok, err, code = f:read(1) - io.close(f) - return code == nil - else - return false - end -end - -function path_exists(name) - local f = io.open(name, "rb") - if f ~= nil then - io.close(f) - return true - else - return false - end -end - -function create_directories(path) - local cmd - if ON_WINDOWS then - cmd = { args = {"cmd", "/c", "mkdir", path} } - else - cmd = { args = {"mkdir", "-p", path} } - end - utils.subprocess(cmd) -end - --- Find an executable in PATH or CWD with the given name -function find_executable(name) - local delim = ON_WINDOWS and ";" or ":" - - local pwd = os.getenv("PWD") or utils.getcwd() - local path = os.getenv("PATH") - - local env_path = pwd .. delim .. path -- Check CWD first - - local result, filename - for path_dir in env_path:gmatch("[^"..delim.."]+") do - filename = join_paths(path_dir, name) - if file_exists(filename) then - result = filename - break - end - end - - return result -end - -local ExecutableFinder = { path_cache = {} } --- Searches for an executable and caches the result if any -function ExecutableFinder:get_executable_path( name, raw_name ) - name = ON_WINDOWS and not raw_name and (name .. ".exe") or name - - if self.path_cache[name] == nil then - self.path_cache[name] = find_executable(name) or false - end - return self.path_cache[name] -end - --- Format seconds to HH.MM.SS.sss -function format_time(seconds, sep, decimals) - decimals = decimals == nil and 3 or decimals - sep = sep and sep or "." - local s = seconds - local h, s = divmod(s, 60*60) - local m, s = divmod(s, 60) - - local second_format = string.format("%%0%d.%df", 2+(decimals > 0 and decimals+1 or 0), decimals) - - return string.format("%02d"..sep.."%02d"..sep..second_format, h, m, s) -end - --- Format seconds to 1h 2m 3.4s -function format_time_hms(seconds, sep, decimals, force_full) - decimals = decimals == nil and 1 or decimals - sep = sep ~= nil and sep or " " - - local s = seconds - local h, s = divmod(s, 60*60) - local m, s = divmod(s, 60) - - if force_full or h > 0 then - return string.format("%dh"..sep.."%dm"..sep.."%." .. tostring(decimals) .. "fs", h, m, s) - elseif m > 0 then - return string.format("%dm"..sep.."%." .. tostring(decimals) .. "fs", m, s) - else - return string.format("%." .. tostring(decimals) .. "fs", s) - end -end - --- Writes text on OSD and console -function log_info(txt, timeout) - timeout = timeout or 1.5 - msg.info(txt) - mp.osd_message(txt, timeout) -end - --- Join table items, ala ({"a", "b", "c"}, "=", "-", ", ") => "=a-, =b-, =c-" -function join_table(source, before, after, sep) - before = before or "" - after = after or "" - sep = sep or ", " - local result = "" - for i, v in pairs(source) do - if not isempty(v) then - local part = before .. v .. after - if i == 1 then - result = part - else - result = result .. sep .. part - end - end - end - return result -end - -function wrap(s, char) - char = char or "'" - return char .. s .. char -end --- Wraps given string into 'string' and escapes any 's in it -function escape_and_wrap(s, char, replacement) - char = char or "'" - replacement = replacement or "\\" .. char - return wrap(string.gsub(s, char, replacement), char) -end --- Escapes single quotes in a string and wraps the input in single quotes -function escape_single_bash(s) - return escape_and_wrap(s, "'", "'\\''") -end - --- Returns (a .. b) if b is not empty or nil -function joined_or_nil(a, b) - return not isempty(b) and (a .. b) or nil -end - --- Put items from one table into another -function extend_table(target, source) - for i, v in pairs(source) do - table.insert(target, v) - end -end - --- Creates a handle and filename for a temporary random file (in current directory) -function create_temporary_file(base, mode, suffix) - local handle, filename - suffix = suffix or "" - while true do - filename = base .. tostring(math.random(1, 5000)) .. suffix - handle = io.open(filename, "r") - if not handle then - handle = io.open(filename, mode) - break - end - io.close(handle) - end - return handle, filename -end - - -function get_processor_count() - local proc_count - - if ON_WINDOWS then - proc_count = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) - else - local cpuinfo_handle = io.open("/proc/cpuinfo") - if cpuinfo_handle ~= nil then - local cpuinfo_contents = cpuinfo_handle:read("*a") - local _, replace_count = cpuinfo_contents:gsub('processor', '') - proc_count = replace_count - end - end - - if proc_count and proc_count > 0 then - return proc_count - else - return nil - end -end - -function substitute_values(string, values) - local substitutor = function(match) - if match == "%" then - return "%" - else - -- nil is discarded by gsub - return values[match] - end - end - - local substituted = string:gsub('%%(.)', substitutor) - return substituted -end - --- ASS HELPERS -- -function round_rect_top( ass, x0, y0, x1, y1, r ) - local c = 0.551915024494 * r -- circle approximation - ass:move_to(x0 + r, y0) - ass:line_to(x1 - r, y0) -- top line - if r > 0 then - ass:bezier_curve(x1 - r + c, y0, x1, y0 + r - c, x1, y0 + r) -- top right corner - end - ass:line_to(x1, y1) -- right line - ass:line_to(x0, y1) -- bottom line - ass:line_to(x0, y0 + r) -- left line - if r > 0 then - ass:bezier_curve(x0, y0 + r - c, x0 + r - c, y0, x0 + r, y0) -- top left corner - end -end - -function round_rect(ass, x0, y0, x1, y1, rtl, rtr, rbr, rbl) - local c = 0.551915024494 - ass:move_to(x0 + rtl, y0) - ass:line_to(x1 - rtr, y0) -- top line - if rtr > 0 then - ass:bezier_curve(x1 - rtr + rtr*c, y0, x1, y0 + rtr - rtr*c, x1, y0 + rtr) -- top right corner - end - ass:line_to(x1, y1 - rbr) -- right line - if rbr > 0 then - ass:bezier_curve(x1, y1 - rbr + rbr*c, x1 - rbr + rbr*c, y1, x1 - rbr, y1) -- bottom right corner - end - ass:line_to(x0 + rbl, y1) -- bottom line - if rbl > 0 then - ass:bezier_curve(x0 + rbl - rbl*c, y1, x0, y1 - rbl + rbl*c, x0, y1 - rbl) -- bottom left corner - end - ass:line_to(x0, y0 + rtl) -- left line - if rtl > 0 then - ass:bezier_curve(x0, y0 + rtl - rtl*c, x0 + rtl - rtl*c, y0, x0 + rtl, y0) -- top left corner - end -end -local SCRIPT_NAME = "mpv_thumbnail_script" - -local default_cache_base = ON_WINDOWS and os.getenv("TEMP") or "/tmp/" - -local thumbnailer_options = { - -- The thumbnail directory - cache_directory = join_paths(default_cache_base, "mpv_thumbs_cache"), - - ------------------------ - -- Generation options -- - ------------------------ - - -- Automatically generate the thumbnails on video load, without a keypress - autogenerate = true, - - -- Only automatically thumbnail videos shorter than this (seconds) - autogenerate_max_duration = 3600, -- 1 hour - - -- SHA1-sum filenames over this length - -- It's nice to know what files the thumbnails are (hence directory names) - -- but long URLs may approach filesystem limits. - hash_filename_length = 128, - - -- Use mpv to generate thumbnail even if ffmpeg is found in PATH - -- ffmpeg does not handle ordered chapters (MKVs which rely on other MKVs)! - -- mpv is a bit slower, but has better support overall (eg. subtitles in the previews) - prefer_mpv = true, - - -- Explicitly disable subtitles on the mpv sub-calls - mpv_no_sub = false, - -- Add a "--no-config" to the mpv sub-call arguments - mpv_no_config = false, - -- Add a "--profile=" to the mpv sub-call arguments - -- Use "" to disable - mpv_profile = "", - -- Output debug logs to .log, ala //000000.bgra.log - -- The logs are removed after successful encodes, unless you set mpv_keep_logs below - mpv_logs = true, - -- Keep all mpv logs, even the succesfull ones - mpv_keep_logs = false, - - -- Disable the built-in keybind ("T") to add your own - disable_keybinds = false, - - --------------------- - -- Display options -- - --------------------- - - -- Move the thumbnail up or down - -- For example: - -- topbar/bottombar: 24 - -- rest: 0 - vertical_offset = 24, - - -- Adjust background padding - -- Examples: - -- topbar: 0, 10, 10, 10 - -- bottombar: 10, 0, 10, 10 - -- slimbox/box: 10, 10, 10, 10 - pad_top = 10, - pad_bot = 0, - pad_left = 10, - pad_right = 10, - - -- If true, pad values are screen-pixels. If false, video-pixels. - pad_in_screenspace = true, - -- Calculate pad into the offset - offset_by_pad = true, - - -- Background color in BBGGRR - background_color = "000000", - -- Alpha: 0 - fully opaque, 255 - transparent - background_alpha = 80, - - -- Keep thumbnail on the screen near left or right side - constrain_to_screen = true, - - -- Do not display the thumbnailing progress - hide_progress = false, - - ----------------------- - -- Thumbnail options -- - ----------------------- - - -- The maximum dimensions of the thumbnails (pixels) - thumbnail_width = 200, - thumbnail_height = 200, - - -- The thumbnail count target - -- (This will result in a thumbnail every ~10 seconds for a 25 minute video) - thumbnail_count = 150, - - -- The above target count will be adjusted by the minimum and - -- maximum time difference between thumbnails. - -- The thumbnail_count will be used to calculate a target separation, - -- and min/max_delta will be used to constrict it. - - -- In other words, thumbnails will be: - -- at least min_delta seconds apart (limiting the amount) - -- at most max_delta seconds apart (raising the amount if needed) - min_delta = 5, - -- 120 seconds aka 2 minutes will add more thumbnails when the video is over 5 hours! - max_delta = 90, - - - -- Overrides for remote urls (you generally want less thumbnails!) - -- Thumbnailing network paths will be done with mpv - - -- Allow thumbnailing network paths (naive check for "://") - thumbnail_network = false, - -- Override thumbnail count, min/max delta - remote_thumbnail_count = 60, - remote_min_delta = 15, - remote_max_delta = 120, - - -- Try to grab the raw stream and disable ytdl for the mpv subcalls - -- Much faster than passing the url to ytdl again, but may cause problems with some sites - remote_direct_stream = true, -} - -read_options(thumbnailer_options, SCRIPT_NAME) -function skip_nil(tbl) - local n = {} - for k, v in pairs(tbl) do - table.insert(n, v) - end - return n -end - -function create_thumbnail_mpv(file_path, timestamp, size, output_path, options) - options = options or {} - - local ytdl_disabled = not options.enable_ytdl and (mp.get_property_native("ytdl") == false - or thumbnailer_options.remote_direct_stream) - - local header_fields_arg = nil - local header_fields = mp.get_property_native("http-header-fields") - if #header_fields > 0 then - -- We can't escape the headers, mpv won't parse "--http-header-fields='Name: value'" properly - header_fields_arg = "--http-header-fields=" .. table.concat(header_fields, ",") - end - - local profile_arg = nil - if thumbnailer_options.mpv_profile ~= "" then - profile_arg = "--profile=" .. thumbnailer_options.mpv_profile - end - - local log_arg = "--log-file=" .. output_path .. ".log" - - local mpv_command = skip_nil({ - "mpv", - -- Hide console output - "--msg-level=all=no", - - -- Disable ytdl - (ytdl_disabled and "--no-ytdl" or nil), - -- Pass HTTP headers from current instance - header_fields_arg, - -- Pass User-Agent and Referer - should do no harm even with ytdl active - "--user-agent=" .. mp.get_property_native("user-agent"), - "--referrer=" .. mp.get_property_native("referrer"), - -- Disable hardware decoding - "--hwdec=no", - - -- Insert --no-config, --profile=... and --log-file if enabled - (thumbnailer_options.mpv_no_config and "--no-config" or nil), - profile_arg, - (thumbnailer_options.mpv_logs and log_arg or nil), - - file_path, - - "--start=" .. tostring(timestamp), - "--frames=1", - "--hr-seek=yes", - "--no-audio", - -- Optionally disable subtitles - (thumbnailer_options.mpv_no_sub and "--no-sub" or nil), - - ("--vf=scale=%d:%d"):format(size.w, size.h), - "--vf-add=format=bgra", - "--of=rawvideo", - "--ovc=rawvideo", - ("--o=%s"):format(output_path) - }) - return utils.subprocess({args=mpv_command}) -end - - -function create_thumbnail_ffmpeg(file_path, timestamp, size, output_path) - local ffmpeg_command = { - "ffmpeg", - "-loglevel", "quiet", - "-noaccurate_seek", - "-ss", format_time(timestamp, ":"), - "-i", file_path, - - "-frames:v", "1", - "-an", - - "-vf", ("scale=%d:%d"):format(size.w, size.h), - "-c:v", "rawvideo", - "-pix_fmt", "bgra", - "-f", "rawvideo", - - "-y", output_path - } - return utils.subprocess({args=ffmpeg_command}) -end - - -function check_output(ret, output_path, is_mpv) - local log_path = output_path .. ".log" - local success = true - - if ret.killed_by_us then - return nil - else - if ret.error or ret.status ~= 0 then - msg.error("Thumbnailing command failed!") - msg.error("mpv process error:", ret.error) - msg.error("Process stdout:", ret.stdout) - if is_mpv then - msg.error("Debug log:", log_path) - end - - success = false - end - - if not file_exists(output_path) then - msg.error("Output file missing!", output_path) - success = false - end - end - - if is_mpv and not thumbnailer_options.mpv_keep_logs then - -- Remove successful debug logs - if success and file_exists(log_path) then - os.remove(log_path) - end - end - - return success -end - - -function do_worker_job(state_json_string, frames_json_string) - msg.debug("Handling given job") - local thumb_state, err = utils.parse_json(state_json_string) - if err then - msg.error("Failed to parse state JSON") - return - end - - local thumbnail_indexes, err = utils.parse_json(frames_json_string) - if err then - msg.error("Failed to parse thumbnail frame indexes") - return - end - - local thumbnail_func = create_thumbnail_mpv - if not thumbnailer_options.prefer_mpv then - if ExecutableFinder:get_executable_path("ffmpeg") then - thumbnail_func = create_thumbnail_ffmpeg - else - msg.warn("Could not find ffmpeg in PATH! Falling back on mpv.") - end - end - - local file_duration = mp.get_property_native("duration") - local file_path = thumb_state.worker_input_path - - if thumb_state.is_remote then - if (thumbnail_func == create_thumbnail_ffmpeg) then - msg.warn("Thumbnailing remote path, falling back on mpv.") - end - thumbnail_func = create_thumbnail_mpv - end - - local generate_thumbnail_for_index = function(thumbnail_index) - -- Given a 1-based thumbnail index, generate a thumbnail for it based on the thumbnailer state - local thumb_idx = thumbnail_index - 1 - msg.debug("Starting work on thumbnail", thumb_idx) - - local thumbnail_path = thumb_state.thumbnail_template:format(thumb_idx) - -- Grab the "middle" of the thumbnail duration instead of the very start, and leave some margin in the end - local timestamp = math.min(file_duration - 0.25, (thumb_idx + 0.5) * thumb_state.thumbnail_delta) - - mp.commandv("script-message", "mpv_thumbnail_script-progress", tostring(thumbnail_index)) - - -- The expected size (raw BGRA image) - local thumbnail_raw_size = (thumb_state.thumbnail_size.w * thumb_state.thumbnail_size.h * 4) - - local need_thumbnail_generation = false - - -- Check if the thumbnail already exists and is the correct size - local thumbnail_file = io.open(thumbnail_path, "rb") - if thumbnail_file == nil then - need_thumbnail_generation = true - else - local existing_thumbnail_filesize = thumbnail_file:seek("end") - if existing_thumbnail_filesize ~= thumbnail_raw_size then - -- Size doesn't match, so (re)generate - msg.warn("Thumbnail", thumb_idx, "did not match expected size, regenerating") - need_thumbnail_generation = true - end - thumbnail_file:close() - end - - if need_thumbnail_generation then - local ret = thumbnail_func(file_path, timestamp, thumb_state.thumbnail_size, thumbnail_path, thumb_state.worker_extra) - local success = check_output(ret, thumbnail_path, thumbnail_func == create_thumbnail_mpv) - - if success == nil then - -- Killed by us, changing files, ignore - msg.debug("Changing files, subprocess killed") - return true - elseif not success then - -- Real failure - mp.osd_message("Thumbnailing failed, check console for details", 3.5) - return true - end - else - msg.debug("Thumbnail", thumb_idx, "already done!") - end - - -- Verify thumbnail size - -- Sometimes ffmpeg will output an empty file when seeking to a "bad" section (usually the end) - thumbnail_file = io.open(thumbnail_path, "rb") - - -- Bail if we can't read the file (it should really exist by now, we checked this in check_output!) - if thumbnail_file == nil then - msg.error("Thumbnail suddenly disappeared!") - return true - end - - -- Check the size of the generated file - local thumbnail_file_size = thumbnail_file:seek("end") - thumbnail_file:close() - - -- Check if the file is big enough - local missing_bytes = math.max(0, thumbnail_raw_size - thumbnail_file_size) - if missing_bytes > 0 then - msg.warn(("Thumbnail missing %d bytes (expected %d, had %d), padding %s"):format( - missing_bytes, thumbnail_raw_size, thumbnail_file_size, thumbnail_path - )) - -- Pad the file if it's missing content (eg. ffmpeg seek to file end) - thumbnail_file = io.open(thumbnail_path, "ab") - thumbnail_file:write(string.rep(string.char(0), missing_bytes)) - thumbnail_file:close() - end - - msg.debug("Finished work on thumbnail", thumb_idx) - mp.commandv("script-message", "mpv_thumbnail_script-ready", tostring(thumbnail_index), thumbnail_path) - end - - msg.debug(("Generating %d thumbnails @ %dx%d for %q"):format( - #thumbnail_indexes, - thumb_state.thumbnail_size.w, - thumb_state.thumbnail_size.h, - file_path)) - - for i, thumbnail_index in ipairs(thumbnail_indexes) do - local bail = generate_thumbnail_for_index(thumbnail_index) - if bail then return end - end - -end - --- Set up listeners and keybinds - --- Job listener -mp.register_script_message("mpv_thumbnail_script-job", do_worker_job) - - --- Register this worker with the master script -local register_timer = nil -local register_timeout = mp.get_time() + 1.5 - -local register_function = function() - if mp.get_time() > register_timeout and register_timer then - msg.error("Thumbnail worker registering timed out") - register_timer:stop() - else - msg.debug("Announcing self to master...") - mp.commandv("script-message", "mpv_thumbnail_script-worker", mp.get_script_name()) - end -end - -register_timer = mp.add_periodic_timer(0.1, register_function) - -mp.register_script_message("mpv_thumbnail_script-slaved", function() - msg.debug("Successfully registered with master") - register_timer:stop() -end) diff --git a/stow/mpv/dot-config/mpv/scripts/youtube-quality.lua b/stow/mpv/dot-config/mpv/scripts/youtube-quality.lua deleted file mode 100644 index b587f37..0000000 --- a/stow/mpv/dot-config/mpv/scripts/youtube-quality.lua +++ /dev/null @@ -1,275 +0,0 @@ --- youtube-quality.lua --- --- Change youtube video quality on the fly. --- --- Diplays a menu that lets you switch to different ytdl-format settings while --- you're in the middle of a video (just like you were using the web player). --- --- Bound to ctrl-f by default. - -local mp = require 'mp' -local utils = require 'mp.utils' -local msg = require 'mp.msg' -local assdraw = require 'mp.assdraw' - -local opts = { - --key bindings - toggle_menu_binding = "ctrl+f", - up_binding = "UP", - down_binding = "DOWN", - select_binding = "ENTER", - - --formatting / cursors - selected_and_active = "โ–ถ - ", - selected_and_inactive = "โ— - ", - unselected_and_active = "โ–ท - ", - unselected_and_inactive = "โ—‹ - ", - - --font size scales by window, if false requires larger font and padding sizes - scale_playlist_by_window=false, - - --playlist ass style overrides inside curly brackets, \keyvalue is one field, extra \ for escape in lua - --example {\\fnUbuntu\\fs10\\b0\\bord1} equals: font=Ubuntu, size=10, bold=no, border=1 - --read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags - --undeclared tags will use default osd settings - --these styles will be used for the whole playlist. More specific styling will need to be hacked in - -- - --(a monospaced font is recommended but not required) - style_ass_tags = "{\\fnmonospace}", - - --paddings for top left corner - text_padding_x = 5, - text_padding_y = 5, - - --other - menu_timeout = 10, - - --use youtube-dl to fetch a list of available formats (overrides quality_strings) - fetch_formats = true, - - --default menu entries - quality_strings=[[ - [ - {"4320p" : "bestvideo[height<=?4320p]+bestaudio/best"}, - {"2160p" : "bestvideo[height<=?2160]+bestaudio/best"}, - {"1440p" : "bestvideo[height<=?1440]+bestaudio/best"}, - {"1080p" : "bestvideo[height<=?1080]+bestaudio/best"}, - {"720p" : "bestvideo[height<=?720]+bestaudio/best"}, - {"480p" : "bestvideo[height<=?480]+bestaudio/best"}, - {"360p" : "bestvideo[height<=?360]+bestaudio/best"}, - {"240p" : "bestvideo[height<=?240]+bestaudio/best"}, - {"144p" : "bestvideo[height<=?144]+bestaudio/best"} - ] - ]], -} -(require 'mp.options').read_options(opts, "youtube-quality") -opts.quality_strings = utils.parse_json(opts.quality_strings) - -local destroyer = nil - - -function show_menu() - local selected = 1 - local active = 0 - local current_ytdl_format = mp.get_property("ytdl-format") - msg.verbose("current ytdl-format: "..current_ytdl_format) - local num_options = 0 - local options = {} - - - if opts.fetch_formats then - options, num_options = download_formats() - end - - if next(options) == nil then - for i,v in ipairs(opts.quality_strings) do - num_options = num_options + 1 - for k,v2 in pairs(v) do - options[i] = {label = k, format=v2} - if v2 == current_ytdl_format then - active = i - selected = active - end - end - end - end - - --set the cursor to the currently format - for i,v in ipairs(options) do - if v.format == current_ytdl_format then - active = i - selected = active - break - end - end - - function selected_move(amt) - selected = selected + amt - if selected < 1 then selected = num_options - elseif selected > num_options then selected = 1 end - timeout:kill() - timeout:resume() - draw_menu() - end - function choose_prefix(i) - if i == selected and i == active then return opts.selected_and_active - elseif i == selected then return opts.selected_and_inactive end - - if i ~= selected and i == active then return opts.unselected_and_active - elseif i ~= selected then return opts.unselected_and_inactive end - return "> " --shouldn't get here. - end - - function draw_menu() - local ass = assdraw.ass_new() - - ass:pos(opts.text_padding_x, opts.text_padding_y) - ass:append(opts.style_ass_tags) - - for i,v in ipairs(options) do - ass:append(choose_prefix(i)..v.label.."\\N") - end - - local w, h = mp.get_osd_size() - if opts.scale_playlist_by_window then w,h = 0, 0 end - mp.set_osd_ass(w, h, ass.text) - end - - function destroy() - timeout:kill() - mp.set_osd_ass(0,0,"") - mp.remove_key_binding("move_up") - mp.remove_key_binding("move_down") - mp.remove_key_binding("select") - mp.remove_key_binding("escape") - destroyer = nil - end - timeout = mp.add_periodic_timer(opts.menu_timeout, destroy) - destroyer = destroy - - mp.add_forced_key_binding(opts.up_binding, "move_up", function() selected_move(-1) end, {repeatable=true}) - mp.add_forced_key_binding(opts.down_binding, "move_down", function() selected_move(1) end, {repeatable=true}) - mp.add_forced_key_binding(opts.select_binding, "select", function() - destroy() - mp.set_property("ytdl-format", options[selected].format) - reload_resume() - end) - mp.add_forced_key_binding(opts.toggle_menu_binding, "escape", destroy) - - draw_menu() - return -end - -local ytdl = { - path = "youtube-dl", - searched = false, - blacklisted = {} -} - -format_cache={} -function download_formats() - local function exec(args) - local ret = utils.subprocess({args = args}) - return ret.status, ret.stdout, ret - end - - local function table_size(t) - s = 0 - for i,v in ipairs(t) do - s = s+1 - end - return s - end - - local url = mp.get_property("path") - - url = string.gsub(url, "ytdl://", "") -- Strip possible ytdl:// prefix. - - -- don't fetch the format list if we already have it - if format_cache[url] ~= nil then - local res = format_cache[url] - return res, table_size(res) - end - mp.osd_message("fetching available formats with youtube-dl...", 60) - - if not (ytdl.searched) then - local ytdl_mcd = mp.find_config_file("youtube-dl") - if not (ytdl_mcd == nil) then - msg.verbose("found youtube-dl at: " .. ytdl_mcd) - ytdl.path = ytdl_mcd - end - ytdl.searched = true - end - - local command = {ytdl.path, "--no-warnings", "--no-playlist", "-J"} - table.insert(command, url) - local es, json, result = exec(command) - - if (es < 0) or (json == nil) or (json == "") then - mp.osd_message("fetching formats failed...", 1) - msg.error("failed to get format list: " .. err) - return {}, 0 - end - - local json, err = utils.parse_json(json) - - if (json == nil) then - mp.osd_message("fetching formats failed...", 1) - msg.error("failed to parse JSON data: " .. err) - return {}, 0 - end - - res = {} - msg.verbose("youtube-dl succeeded!") - for i,v in ipairs(json.formats) do - if v.vcodec ~= "none" then - local fps = v.fps and v.fps.."fps" or "" - local resolution = string.format("%sx%s", v.width, v.height) - local l = string.format("%-9s %-5s (%-4s / %s)", resolution, fps, v.ext, v.vcodec) - local f = string.format("%s+bestaudio/best", v.format_id) - table.insert(res, {label=l, format=f, width=v.width }) - end - end - - table.sort(res, function(a, b) return a.width > b.width end) - - mp.osd_message("", 0) - format_cache[url] = res - return res, table_size(res) -end - - --- register script message to show menu -mp.register_script_message("toggle-quality-menu", -function() - if destroyer ~= nil then - destroyer() - else - show_menu() - end -end) - --- keybind to launch menu -mp.add_key_binding(opts.toggle_menu_binding, "quality-menu", show_menu) - --- special thanks to reload.lua (https://github.com/4e6/mpv-reload/) -function reload_resume() - local playlist_pos = mp.get_property_number("playlist-pos") - local reload_duration = mp.get_property_native("duration") - local time_pos = mp.get_property("time-pos") - - mp.set_property_number("playlist-pos", playlist_pos) - - -- Tries to determine live stream vs. pre-recordered VOD. VOD has non-zero - -- duration property. When reloading VOD, to keep the current time position - -- we should provide offset from the start. Stream doesn't have fixed start. - -- Decent choice would be to reload stream from it's current 'live' positon. - -- That's the reason we don't pass the offset when reloading streams. - if reload_duration and reload_duration > 0 then - local function seeker() - mp.commandv("seek", time_pos, "absolute") - mp.unregister_event(seeker) - end - mp.register_event("file-loaded", seeker) - end -end diff --git a/stow/neofetch/.config/neofetch/config.conf b/stow/neofetch/.config/neofetch/config.conf new file mode 100644 index 0000000..41e77d4 --- /dev/null +++ b/stow/neofetch/.config/neofetch/config.conf @@ -0,0 +1,764 @@ +# See this wiki page for more info: +# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info +print_info() { + info title + info underline + + info "OS" distro + info "Host" model + info "Kernel" kernel + info "Uptime" uptime + info "Packages" packages + info "Shell" shell + info "Resolution" resolution + info "DE" de + info "WM" wm + info "WM Theme" wm_theme + info "Theme" theme + info "Icons" icons + info "Terminal" term + info "Terminal Font" term_font + info "CPU" cpu + info "GPU" gpu + info "Memory" memory + + # info "GPU Driver" gpu_driver # Linux/macOS only + # info "CPU Usage" cpu_usage + # info "Disk" disk + # info "Battery" battery + # info "Font" font + # info "Song" song + # [[ "$player" ]] && prin "Music Player" "$player" + # info "Local IP" local_ip + # info "Public IP" public_ip + # info "Users" users + # info "Locale" locale # This only works on glibc systems. + + info cols +} + + +# Kernel + + +# Shorten the output of the kernel function. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --kernel_shorthand +# Supports: Everything except *BSDs (except PacBSD and PC-BSD) +# +# Example: +# on: '4.8.9-1-ARCH' +# off: 'Linux 4.8.9-1-ARCH' +kernel_shorthand="on" + + +# Distro + + +# Shorten the output of the distro function +# +# Default: 'off' +# Values: 'on', 'tiny', 'off' +# Flag: --distro_shorthand +# Supports: Everything except Windows and Haiku +distro_shorthand="off" + +# Show/Hide OS Architecture. +# Show 'x86_64', 'x86' and etc in 'Distro:' output. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --os_arch +# +# Example: +# on: 'Arch Linux x86_64' +# off: 'Arch Linux' +os_arch="on" + + +# Uptime + + +# Shorten the output of the uptime function +# +# Default: 'on' +# Values: 'on', 'tiny', 'off' +# Flag: --uptime_shorthand +# +# Example: +# on: '2 days, 10 hours, 3 mins' +# tiny: '2d 10h 3m' +# off: '2 days, 10 hours, 3 minutes' +uptime_shorthand="on" + + +# Memory + + +# Show memory pecentage in output. +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --memory_percent +# +# Example: +# on: '1801MiB / 7881MiB (22%)' +# off: '1801MiB / 7881MiB' +memory_percent="off" + + +# Packages + + +# Show/Hide Package Manager names. +# +# Default: 'tiny' +# Values: 'on', 'tiny' 'off' +# Flag: --package_managers +# +# Example: +# on: '998 (pacman), 8 (flatpak), 4 (snap)' +# tiny: '908 (pacman, flatpak, snap)' +# off: '908' +package_managers="on" + + +# Shell + + +# Show the path to $SHELL +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --shell_path +# +# Example: +# on: '/bin/bash' +# off: 'bash' +shell_path="off" + +# Show $SHELL version +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --shell_version +# +# Example: +# on: 'bash 4.4.5' +# off: 'bash' +shell_version="on" + + +# CPU + + +# CPU speed type +# +# Default: 'bios_limit' +# Values: 'scaling_cur_freq', 'scaling_min_freq', 'scaling_max_freq', 'bios_limit'. +# Flag: --speed_type +# Supports: Linux with 'cpufreq' +# NOTE: Any file in '/sys/devices/system/cpu/cpu0/cpufreq' can be used as a value. +speed_type="bios_limit" + +# CPU speed shorthand +# +# Default: 'off' +# Values: 'on', 'off'. +# Flag: --speed_shorthand +# NOTE: This flag is not supported in systems with CPU speed less than 1 GHz +# +# Example: +# on: 'i7-6500U (4) @ 3.1GHz' +# off: 'i7-6500U (4) @ 3.100GHz' +speed_shorthand="off" + +# Enable/Disable CPU brand in output. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --cpu_brand +# +# Example: +# on: 'Intel i7-6500U' +# off: 'i7-6500U (4)' +cpu_brand="on" + +# CPU Speed +# Hide/Show CPU speed. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --cpu_speed +# +# Example: +# on: 'Intel i7-6500U (4) @ 3.1GHz' +# off: 'Intel i7-6500U (4)' +cpu_speed="on" + +# CPU Cores +# Display CPU cores in output +# +# Default: 'logical' +# Values: 'logical', 'physical', 'off' +# Flag: --cpu_cores +# Support: 'physical' doesn't work on BSD. +# +# Example: +# logical: 'Intel i7-6500U (4) @ 3.1GHz' (All virtual cores) +# physical: 'Intel i7-6500U (2) @ 3.1GHz' (All physical cores) +# off: 'Intel i7-6500U @ 3.1GHz' +cpu_cores="logical" + +# CPU Temperature +# Hide/Show CPU temperature. +# Note the temperature is added to the regular CPU function. +# +# Default: 'off' +# Values: 'C', 'F', 'off' +# Flag: --cpu_temp +# Supports: Linux, BSD +# NOTE: For FreeBSD and NetBSD-based systems, you'll need to enable +# coretemp kernel module. This only supports newer Intel processors. +# +# Example: +# C: 'Intel i7-6500U (4) @ 3.1GHz [27.2ยฐC]' +# F: 'Intel i7-6500U (4) @ 3.1GHz [82.0ยฐF]' +# off: 'Intel i7-6500U (4) @ 3.1GHz' +cpu_temp="off" + + +# GPU + + +# Enable/Disable GPU Brand +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --gpu_brand +# +# Example: +# on: 'AMD HD 7950' +# off: 'HD 7950' +gpu_brand="on" + +# Which GPU to display +# +# Default: 'all' +# Values: 'all', 'dedicated', 'integrated' +# Flag: --gpu_type +# Supports: Linux +# +# Example: +# all: +# GPU1: AMD HD 7950 +# GPU2: Intel Integrated Graphics +# +# dedicated: +# GPU1: AMD HD 7950 +# +# integrated: +# GPU1: Intel Integrated Graphics +gpu_type="all" + + +# Resolution + + +# Display refresh rate next to each monitor +# Default: 'off' +# Values: 'on', 'off' +# Flag: --refresh_rate +# Supports: Doesn't work on Windows. +# +# Example: +# on: '1920x1080 @ 60Hz' +# off: '1920x1080' +refresh_rate="off" + + +# Gtk Theme / Icons / Font + + +# Shorten output of GTK Theme / Icons / Font +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --gtk_shorthand +# +# Example: +# on: 'Numix, Adwaita' +# off: 'Numix [GTK2], Adwaita [GTK3]' +gtk_shorthand="off" + + +# Enable/Disable gtk2 Theme / Icons / Font +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --gtk2 +# +# Example: +# on: 'Numix [GTK2], Adwaita [GTK3]' +# off: 'Adwaita [GTK3]' +gtk2="on" + +# Enable/Disable gtk3 Theme / Icons / Font +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --gtk3 +# +# Example: +# on: 'Numix [GTK2], Adwaita [GTK3]' +# off: 'Numix [GTK2]' +gtk3="on" + + +# IP Address + + +# Website to ping for the public IP +# +# Default: 'http://ident.me' +# Values: 'url' +# Flag: --ip_host +public_ip_host="http://ident.me" + +# Public IP timeout. +# +# Default: '2' +# Values: 'int' +# Flag: --ip_timeout +public_ip_timeout=2 + + +# Disk + + +# Which disks to display. +# The values can be any /dev/sdXX, mount point or directory. +# NOTE: By default we only show the disk info for '/'. +# +# Default: '/' +# Values: '/', '/dev/sdXX', '/path/to/drive'. +# Flag: --disk_show +# +# Example: +# disk_show=('/' '/dev/sdb1'): +# 'Disk (/): 74G / 118G (66%)' +# 'Disk (/mnt/Videos): 823G / 893G (93%)' +# +# disk_show=('/'): +# 'Disk (/): 74G / 118G (66%)' +# +disk_show=('/') + +# Disk subtitle. +# What to append to the Disk subtitle. +# +# Default: 'mount' +# Values: 'mount', 'name', 'dir' +# Flag: --disk_subtitle +# +# Example: +# name: 'Disk (/dev/sda1): 74G / 118G (66%)' +# 'Disk (/dev/sdb2): 74G / 118G (66%)' +# +# mount: 'Disk (/): 74G / 118G (66%)' +# 'Disk (/mnt/Local Disk): 74G / 118G (66%)' +# 'Disk (/mnt/Videos): 74G / 118G (66%)' +# +# dir: 'Disk (/): 74G / 118G (66%)' +# 'Disk (Local Disk): 74G / 118G (66%)' +# 'Disk (Videos): 74G / 118G (66%)' +disk_subtitle="mount" + + +# Song + + +# Manually specify a music player. +# +# Default: 'auto' +# Values: 'auto', 'player-name' +# Flag: --music_player +# +# Available values for 'player-name': +# +# amarok +# audacious +# banshee +# bluemindo +# clementine +# cmus +# deadbeef +# deepin-music +# dragon +# elisa +# exaile +# gnome-music +# gmusicbrowser +# gogglesmm +# guayadeque +# iTunes +# juk +# lollypop +# mocp +# mopidy +# mpd +# netease-cloud-music +# pogo +# pragha +# qmmp +# quodlibet +# rhythmbox +# sayonara +# smplayer +# spotify +# strawberry +# tomahawk +# vlc +# xmms2d +# xnoise +# yarock +music_player="auto" + +# Format to display song information. +# +# Default: '%artist% - %album% - %title%' +# Values: '%artist%', '%album%', '%title%' +# Flag: --song_format +# +# Example: +# default: 'Song: Jet - Get Born - Sgt Major' +song_format="%artist% - %album% - %title%" + +# Print the Artist, Album and Title on separate lines +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --song_shorthand +# +# Example: +# on: 'Artist: The Fratellis' +# 'Album: Costello Music' +# 'Song: Chelsea Dagger' +# +# off: 'Song: The Fratellis - Costello Music - Chelsea Dagger' +song_shorthand="off" + +# 'mpc' arguments (specify a host, password etc). +# +# Default: '' +# Example: mpc_args=(-h HOST -P PASSWORD) +mpc_args=() + + +# Text Colors + + +# Text Colors +# +# Default: 'distro' +# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num' +# Flag: --colors +# +# Each number represents a different part of the text in +# this order: 'title', '@', 'underline', 'subtitle', 'colon', 'info' +# +# Example: +# colors=(distro) - Text is colored based on Distro colors. +# colors=(4 6 1 8 8 6) - Text is colored in the order above. +colors=(distro) + + +# Text Options + + +# Toggle bold text +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --bold +bold="on" + +# Enable/Disable Underline +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --underline +underline_enabled="on" + +# Underline character +# +# Default: '-' +# Values: 'string' +# Flag: --underline_char +underline_char="-" + + +# Info Separator +# Replace the default separator with the specified string. +# +# Default: ':' +# Flag: --separator +# +# Example: +# separator="->": 'Shell-> bash' +# separator=" =": 'WM = dwm' +separator=":" + + +# Color Blocks + + +# Color block range +# The range of colors to print. +# +# Default: '0', '15' +# Values: 'num' +# Flag: --block_range +# +# Example: +# +# Display colors 0-7 in the blocks. (8 colors) +# neofetch --block_range 0 7 +# +# Display colors 0-15 in the blocks. (16 colors) +# neofetch --block_range 0 15 +block_range=(0 15) + +# Toggle color blocks +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --color_blocks +color_blocks="on" + +# Color block width in spaces +# +# Default: '3' +# Values: 'num' +# Flag: --block_width +block_width=3 + +# Color block height in lines +# +# Default: '1' +# Values: 'num' +# Flag: --block_height +block_height=1 + + +# Progress Bars + + +# Bar characters +# +# Default: '-', '=' +# Values: 'string', 'string' +# Flag: --bar_char +# +# Example: +# neofetch --bar_char 'elapsed' 'total' +# neofetch --bar_char '-' '=' +bar_char_elapsed="-" +bar_char_total="=" + +# Toggle Bar border +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --bar_border +bar_border="on" + +# Progress bar length in spaces +# Number of chars long to make the progress bars. +# +# Default: '15' +# Values: 'num' +# Flag: --bar_length +bar_length=15 + +# Progress bar colors +# When set to distro, uses your distro's logo colors. +# +# Default: 'distro', 'distro' +# Values: 'distro', 'num' +# Flag: --bar_colors +# +# Example: +# neofetch --bar_colors 3 4 +# neofetch --bar_colors distro 5 +bar_color_elapsed="distro" +bar_color_total="distro" + + +# Info display +# Display a bar with the info. +# +# Default: 'off' +# Values: 'bar', 'infobar', 'barinfo', 'off' +# Flags: --cpu_display +# --memory_display +# --battery_display +# --disk_display +# +# Example: +# bar: '[---=======]' +# infobar: 'info [---=======]' +# barinfo: '[---=======] info' +# off: 'info' +cpu_display="off" +memory_display="off" +battery_display="off" +disk_display="off" + + +# Backend Settings + + +# Image backend. +# +# Default: 'ascii' +# Values: 'ascii', 'caca', 'chafa', 'jp2a', 'iterm2', 'off', +# 'termpix', 'pixterm', 'tycat', 'w3m', 'kitty' +# Flag: --backend +image_backend="ascii" + +# Image Source +# +# Which image or ascii file to display. +# +# Default: 'auto' +# Values: 'auto', 'ascii', 'wallpaper', '/path/to/img', '/path/to/ascii', '/path/to/dir/' +# 'command output (neofetch --ascii "$(fortune | cowsay -W 30)")' +# Flag: --source +# +# NOTE: 'auto' will pick the best image source for whatever image backend is used. +# In ascii mode, distro ascii art will be used and in an image mode, your +# wallpaper will be used. +image_source="auto" + + +# Ascii Options + + +# Ascii distro +# Which distro's ascii art to display. +# +# Default: 'auto' +# Values: 'auto', 'distro_name' +# Flag: --ascii_distro +# +# NOTE: Arch and Ubuntu have 'old' logo variants. +# Change this to 'arch_old' or 'ubuntu_old' to use the old logos. +# NOTE: Ubuntu has flavor variants. +# Change this to 'Lubuntu', 'Xubuntu', 'Ubuntu-GNOME' or 'Ubuntu-Budgie' to use the flavors. +# NOTE: Arch, Crux and Gentoo have a smaller logo variant. +# Change this to 'arch_small', 'crux_small' or 'gentoo_small' to use the small logos. +ascii_distro="auto" + +# Ascii Colors +# +# Default: 'distro' +# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num' +# Flag: --ascii_colors +# +# Example: +# ascii_colors=(distro) - Ascii is colored based on Distro colors. +# ascii_colors=(4 6 1 8 8 6) - Ascii is colored using these colors. +ascii_colors=(distro) + +# Bold ascii logo +# Whether or not to bold the ascii logo. +# +# Default: 'on' +# Values: 'on', 'off' +# Flag: --ascii_bold +ascii_bold="on" + + +# Image Options + + +# Image loop +# Setting this to on will make neofetch redraw the image constantly until +# Ctrl+C is pressed. This fixes display issues in some terminal emulators. +# +# Default: 'off' +# Values: 'on', 'off' +# Flag: --loop +image_loop="off" + +# Thumbnail directory +# +# Default: '~/.cache/thumbnails/neofetch' +# Values: 'dir' +thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch" + +# Crop mode +# +# Default: 'normal' +# Values: 'normal', 'fit', 'fill' +# Flag: --crop_mode +# +# See this wiki page to learn about the fit and fill options. +# https://github.com/dylanaraps/neofetch/wiki/What-is-Waifu-Crop%3F +crop_mode="normal" + +# Crop offset +# Note: Only affects 'normal' crop mode. +# +# Default: 'center' +# Values: 'northwest', 'north', 'northeast', 'west', 'center' +# 'east', 'southwest', 'south', 'southeast' +# Flag: --crop_offset +crop_offset="center" + +# Image size +# The image is half the terminal width by default. +# +# Default: 'auto' +# Values: 'auto', '00px', '00%', 'none' +# Flags: --image_size +# --size +image_size="auto" + +# Gap between image and text +# +# Default: '3' +# Values: 'num', '-num' +# Flag: --gap +gap=3 + +# Image offsets +# Only works with the w3m backend. +# +# Default: '0' +# Values: 'px' +# Flags: --xoffset +# --yoffset +yoffset=0 +xoffset=0 + +# Image background color +# Only works with the w3m backend. +# +# Default: '' +# Values: 'color', 'blue' +# Flag: --bg_color +background_color= + + +# Misc Options + +# Stdout mode +# Turn off all colors and disables image backend (ASCII/Image). +# Useful for piping into another command. +# Default: 'off' +# Values: 'on', 'off' +stdout="off" diff --git a/stow/neofetch/.config/neofetch/neofetchLogin.conf b/stow/neofetch/.config/neofetch/neofetchLogin.conf new file mode 100644 index 0000000..7750481 --- /dev/null +++ b/stow/neofetch/.config/neofetch/neofetchLogin.conf @@ -0,0 +1,63 @@ +# See this wiki page for more info: +# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info +print_info() { + info underline + info title + info underline + + info "OS" distro + info "Kernel" kernel + info "Shell" shell + info "Resolution" resolution + info "Memory" memory + info "Disk" disk + info "Battery" battery + info "Uptime" uptime +} + + + + +ascii_bold="off" +#ascii_colors=(4 4) +#ascii_distro="auto" +ascii_colors=(3) +ascii_distro="gnu" +background_color= +bar_border="on" +bar_char_elapsed="-" +bar_char_total="=" +bar_color_elapsed="distro" +bar_color_total="distro" +bar_length=15 +battery_display="off" +bold="on" +colors=(6 5 4 4 5 6) +cpu_display="off" +crop_mode="normal" +crop_offset="center" +disk_display="on" +disk_show=('/' '/home') +disk_subtitle="mount" +distro_shorthand="off" +gap=3 +image_backend="ascii" +image_loop="off" +image_size="auto" +image_source="auto" +kernel_shorthand="off" +memory_display="off" +memory_percent="on" +os_arch="on" +refresh_rate="off" +separator=":" +shell_path="off" +shell_version="on" +speed_type="bios_limit" +stdout="off" +thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch" +underline_char="-" +underline_enabled="on" +uptime_shorthand="on" +xoffset=10 +yoffset=0 diff --git a/stow/neofetch/dot-config/neofetch/config.conf b/stow/neofetch/dot-config/neofetch/config.conf deleted file mode 100644 index 41e77d4..0000000 --- a/stow/neofetch/dot-config/neofetch/config.conf +++ /dev/null @@ -1,764 +0,0 @@ -# See this wiki page for more info: -# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info -print_info() { - info title - info underline - - info "OS" distro - info "Host" model - info "Kernel" kernel - info "Uptime" uptime - info "Packages" packages - info "Shell" shell - info "Resolution" resolution - info "DE" de - info "WM" wm - info "WM Theme" wm_theme - info "Theme" theme - info "Icons" icons - info "Terminal" term - info "Terminal Font" term_font - info "CPU" cpu - info "GPU" gpu - info "Memory" memory - - # info "GPU Driver" gpu_driver # Linux/macOS only - # info "CPU Usage" cpu_usage - # info "Disk" disk - # info "Battery" battery - # info "Font" font - # info "Song" song - # [[ "$player" ]] && prin "Music Player" "$player" - # info "Local IP" local_ip - # info "Public IP" public_ip - # info "Users" users - # info "Locale" locale # This only works on glibc systems. - - info cols -} - - -# Kernel - - -# Shorten the output of the kernel function. -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --kernel_shorthand -# Supports: Everything except *BSDs (except PacBSD and PC-BSD) -# -# Example: -# on: '4.8.9-1-ARCH' -# off: 'Linux 4.8.9-1-ARCH' -kernel_shorthand="on" - - -# Distro - - -# Shorten the output of the distro function -# -# Default: 'off' -# Values: 'on', 'tiny', 'off' -# Flag: --distro_shorthand -# Supports: Everything except Windows and Haiku -distro_shorthand="off" - -# Show/Hide OS Architecture. -# Show 'x86_64', 'x86' and etc in 'Distro:' output. -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --os_arch -# -# Example: -# on: 'Arch Linux x86_64' -# off: 'Arch Linux' -os_arch="on" - - -# Uptime - - -# Shorten the output of the uptime function -# -# Default: 'on' -# Values: 'on', 'tiny', 'off' -# Flag: --uptime_shorthand -# -# Example: -# on: '2 days, 10 hours, 3 mins' -# tiny: '2d 10h 3m' -# off: '2 days, 10 hours, 3 minutes' -uptime_shorthand="on" - - -# Memory - - -# Show memory pecentage in output. -# -# Default: 'off' -# Values: 'on', 'off' -# Flag: --memory_percent -# -# Example: -# on: '1801MiB / 7881MiB (22%)' -# off: '1801MiB / 7881MiB' -memory_percent="off" - - -# Packages - - -# Show/Hide Package Manager names. -# -# Default: 'tiny' -# Values: 'on', 'tiny' 'off' -# Flag: --package_managers -# -# Example: -# on: '998 (pacman), 8 (flatpak), 4 (snap)' -# tiny: '908 (pacman, flatpak, snap)' -# off: '908' -package_managers="on" - - -# Shell - - -# Show the path to $SHELL -# -# Default: 'off' -# Values: 'on', 'off' -# Flag: --shell_path -# -# Example: -# on: '/bin/bash' -# off: 'bash' -shell_path="off" - -# Show $SHELL version -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --shell_version -# -# Example: -# on: 'bash 4.4.5' -# off: 'bash' -shell_version="on" - - -# CPU - - -# CPU speed type -# -# Default: 'bios_limit' -# Values: 'scaling_cur_freq', 'scaling_min_freq', 'scaling_max_freq', 'bios_limit'. -# Flag: --speed_type -# Supports: Linux with 'cpufreq' -# NOTE: Any file in '/sys/devices/system/cpu/cpu0/cpufreq' can be used as a value. -speed_type="bios_limit" - -# CPU speed shorthand -# -# Default: 'off' -# Values: 'on', 'off'. -# Flag: --speed_shorthand -# NOTE: This flag is not supported in systems with CPU speed less than 1 GHz -# -# Example: -# on: 'i7-6500U (4) @ 3.1GHz' -# off: 'i7-6500U (4) @ 3.100GHz' -speed_shorthand="off" - -# Enable/Disable CPU brand in output. -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --cpu_brand -# -# Example: -# on: 'Intel i7-6500U' -# off: 'i7-6500U (4)' -cpu_brand="on" - -# CPU Speed -# Hide/Show CPU speed. -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --cpu_speed -# -# Example: -# on: 'Intel i7-6500U (4) @ 3.1GHz' -# off: 'Intel i7-6500U (4)' -cpu_speed="on" - -# CPU Cores -# Display CPU cores in output -# -# Default: 'logical' -# Values: 'logical', 'physical', 'off' -# Flag: --cpu_cores -# Support: 'physical' doesn't work on BSD. -# -# Example: -# logical: 'Intel i7-6500U (4) @ 3.1GHz' (All virtual cores) -# physical: 'Intel i7-6500U (2) @ 3.1GHz' (All physical cores) -# off: 'Intel i7-6500U @ 3.1GHz' -cpu_cores="logical" - -# CPU Temperature -# Hide/Show CPU temperature. -# Note the temperature is added to the regular CPU function. -# -# Default: 'off' -# Values: 'C', 'F', 'off' -# Flag: --cpu_temp -# Supports: Linux, BSD -# NOTE: For FreeBSD and NetBSD-based systems, you'll need to enable -# coretemp kernel module. This only supports newer Intel processors. -# -# Example: -# C: 'Intel i7-6500U (4) @ 3.1GHz [27.2ยฐC]' -# F: 'Intel i7-6500U (4) @ 3.1GHz [82.0ยฐF]' -# off: 'Intel i7-6500U (4) @ 3.1GHz' -cpu_temp="off" - - -# GPU - - -# Enable/Disable GPU Brand -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --gpu_brand -# -# Example: -# on: 'AMD HD 7950' -# off: 'HD 7950' -gpu_brand="on" - -# Which GPU to display -# -# Default: 'all' -# Values: 'all', 'dedicated', 'integrated' -# Flag: --gpu_type -# Supports: Linux -# -# Example: -# all: -# GPU1: AMD HD 7950 -# GPU2: Intel Integrated Graphics -# -# dedicated: -# GPU1: AMD HD 7950 -# -# integrated: -# GPU1: Intel Integrated Graphics -gpu_type="all" - - -# Resolution - - -# Display refresh rate next to each monitor -# Default: 'off' -# Values: 'on', 'off' -# Flag: --refresh_rate -# Supports: Doesn't work on Windows. -# -# Example: -# on: '1920x1080 @ 60Hz' -# off: '1920x1080' -refresh_rate="off" - - -# Gtk Theme / Icons / Font - - -# Shorten output of GTK Theme / Icons / Font -# -# Default: 'off' -# Values: 'on', 'off' -# Flag: --gtk_shorthand -# -# Example: -# on: 'Numix, Adwaita' -# off: 'Numix [GTK2], Adwaita [GTK3]' -gtk_shorthand="off" - - -# Enable/Disable gtk2 Theme / Icons / Font -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --gtk2 -# -# Example: -# on: 'Numix [GTK2], Adwaita [GTK3]' -# off: 'Adwaita [GTK3]' -gtk2="on" - -# Enable/Disable gtk3 Theme / Icons / Font -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --gtk3 -# -# Example: -# on: 'Numix [GTK2], Adwaita [GTK3]' -# off: 'Numix [GTK2]' -gtk3="on" - - -# IP Address - - -# Website to ping for the public IP -# -# Default: 'http://ident.me' -# Values: 'url' -# Flag: --ip_host -public_ip_host="http://ident.me" - -# Public IP timeout. -# -# Default: '2' -# Values: 'int' -# Flag: --ip_timeout -public_ip_timeout=2 - - -# Disk - - -# Which disks to display. -# The values can be any /dev/sdXX, mount point or directory. -# NOTE: By default we only show the disk info for '/'. -# -# Default: '/' -# Values: '/', '/dev/sdXX', '/path/to/drive'. -# Flag: --disk_show -# -# Example: -# disk_show=('/' '/dev/sdb1'): -# 'Disk (/): 74G / 118G (66%)' -# 'Disk (/mnt/Videos): 823G / 893G (93%)' -# -# disk_show=('/'): -# 'Disk (/): 74G / 118G (66%)' -# -disk_show=('/') - -# Disk subtitle. -# What to append to the Disk subtitle. -# -# Default: 'mount' -# Values: 'mount', 'name', 'dir' -# Flag: --disk_subtitle -# -# Example: -# name: 'Disk (/dev/sda1): 74G / 118G (66%)' -# 'Disk (/dev/sdb2): 74G / 118G (66%)' -# -# mount: 'Disk (/): 74G / 118G (66%)' -# 'Disk (/mnt/Local Disk): 74G / 118G (66%)' -# 'Disk (/mnt/Videos): 74G / 118G (66%)' -# -# dir: 'Disk (/): 74G / 118G (66%)' -# 'Disk (Local Disk): 74G / 118G (66%)' -# 'Disk (Videos): 74G / 118G (66%)' -disk_subtitle="mount" - - -# Song - - -# Manually specify a music player. -# -# Default: 'auto' -# Values: 'auto', 'player-name' -# Flag: --music_player -# -# Available values for 'player-name': -# -# amarok -# audacious -# banshee -# bluemindo -# clementine -# cmus -# deadbeef -# deepin-music -# dragon -# elisa -# exaile -# gnome-music -# gmusicbrowser -# gogglesmm -# guayadeque -# iTunes -# juk -# lollypop -# mocp -# mopidy -# mpd -# netease-cloud-music -# pogo -# pragha -# qmmp -# quodlibet -# rhythmbox -# sayonara -# smplayer -# spotify -# strawberry -# tomahawk -# vlc -# xmms2d -# xnoise -# yarock -music_player="auto" - -# Format to display song information. -# -# Default: '%artist% - %album% - %title%' -# Values: '%artist%', '%album%', '%title%' -# Flag: --song_format -# -# Example: -# default: 'Song: Jet - Get Born - Sgt Major' -song_format="%artist% - %album% - %title%" - -# Print the Artist, Album and Title on separate lines -# -# Default: 'off' -# Values: 'on', 'off' -# Flag: --song_shorthand -# -# Example: -# on: 'Artist: The Fratellis' -# 'Album: Costello Music' -# 'Song: Chelsea Dagger' -# -# off: 'Song: The Fratellis - Costello Music - Chelsea Dagger' -song_shorthand="off" - -# 'mpc' arguments (specify a host, password etc). -# -# Default: '' -# Example: mpc_args=(-h HOST -P PASSWORD) -mpc_args=() - - -# Text Colors - - -# Text Colors -# -# Default: 'distro' -# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num' -# Flag: --colors -# -# Each number represents a different part of the text in -# this order: 'title', '@', 'underline', 'subtitle', 'colon', 'info' -# -# Example: -# colors=(distro) - Text is colored based on Distro colors. -# colors=(4 6 1 8 8 6) - Text is colored in the order above. -colors=(distro) - - -# Text Options - - -# Toggle bold text -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --bold -bold="on" - -# Enable/Disable Underline -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --underline -underline_enabled="on" - -# Underline character -# -# Default: '-' -# Values: 'string' -# Flag: --underline_char -underline_char="-" - - -# Info Separator -# Replace the default separator with the specified string. -# -# Default: ':' -# Flag: --separator -# -# Example: -# separator="->": 'Shell-> bash' -# separator=" =": 'WM = dwm' -separator=":" - - -# Color Blocks - - -# Color block range -# The range of colors to print. -# -# Default: '0', '15' -# Values: 'num' -# Flag: --block_range -# -# Example: -# -# Display colors 0-7 in the blocks. (8 colors) -# neofetch --block_range 0 7 -# -# Display colors 0-15 in the blocks. (16 colors) -# neofetch --block_range 0 15 -block_range=(0 15) - -# Toggle color blocks -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --color_blocks -color_blocks="on" - -# Color block width in spaces -# -# Default: '3' -# Values: 'num' -# Flag: --block_width -block_width=3 - -# Color block height in lines -# -# Default: '1' -# Values: 'num' -# Flag: --block_height -block_height=1 - - -# Progress Bars - - -# Bar characters -# -# Default: '-', '=' -# Values: 'string', 'string' -# Flag: --bar_char -# -# Example: -# neofetch --bar_char 'elapsed' 'total' -# neofetch --bar_char '-' '=' -bar_char_elapsed="-" -bar_char_total="=" - -# Toggle Bar border -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --bar_border -bar_border="on" - -# Progress bar length in spaces -# Number of chars long to make the progress bars. -# -# Default: '15' -# Values: 'num' -# Flag: --bar_length -bar_length=15 - -# Progress bar colors -# When set to distro, uses your distro's logo colors. -# -# Default: 'distro', 'distro' -# Values: 'distro', 'num' -# Flag: --bar_colors -# -# Example: -# neofetch --bar_colors 3 4 -# neofetch --bar_colors distro 5 -bar_color_elapsed="distro" -bar_color_total="distro" - - -# Info display -# Display a bar with the info. -# -# Default: 'off' -# Values: 'bar', 'infobar', 'barinfo', 'off' -# Flags: --cpu_display -# --memory_display -# --battery_display -# --disk_display -# -# Example: -# bar: '[---=======]' -# infobar: 'info [---=======]' -# barinfo: '[---=======] info' -# off: 'info' -cpu_display="off" -memory_display="off" -battery_display="off" -disk_display="off" - - -# Backend Settings - - -# Image backend. -# -# Default: 'ascii' -# Values: 'ascii', 'caca', 'chafa', 'jp2a', 'iterm2', 'off', -# 'termpix', 'pixterm', 'tycat', 'w3m', 'kitty' -# Flag: --backend -image_backend="ascii" - -# Image Source -# -# Which image or ascii file to display. -# -# Default: 'auto' -# Values: 'auto', 'ascii', 'wallpaper', '/path/to/img', '/path/to/ascii', '/path/to/dir/' -# 'command output (neofetch --ascii "$(fortune | cowsay -W 30)")' -# Flag: --source -# -# NOTE: 'auto' will pick the best image source for whatever image backend is used. -# In ascii mode, distro ascii art will be used and in an image mode, your -# wallpaper will be used. -image_source="auto" - - -# Ascii Options - - -# Ascii distro -# Which distro's ascii art to display. -# -# Default: 'auto' -# Values: 'auto', 'distro_name' -# Flag: --ascii_distro -# -# NOTE: Arch and Ubuntu have 'old' logo variants. -# Change this to 'arch_old' or 'ubuntu_old' to use the old logos. -# NOTE: Ubuntu has flavor variants. -# Change this to 'Lubuntu', 'Xubuntu', 'Ubuntu-GNOME' or 'Ubuntu-Budgie' to use the flavors. -# NOTE: Arch, Crux and Gentoo have a smaller logo variant. -# Change this to 'arch_small', 'crux_small' or 'gentoo_small' to use the small logos. -ascii_distro="auto" - -# Ascii Colors -# -# Default: 'distro' -# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num' -# Flag: --ascii_colors -# -# Example: -# ascii_colors=(distro) - Ascii is colored based on Distro colors. -# ascii_colors=(4 6 1 8 8 6) - Ascii is colored using these colors. -ascii_colors=(distro) - -# Bold ascii logo -# Whether or not to bold the ascii logo. -# -# Default: 'on' -# Values: 'on', 'off' -# Flag: --ascii_bold -ascii_bold="on" - - -# Image Options - - -# Image loop -# Setting this to on will make neofetch redraw the image constantly until -# Ctrl+C is pressed. This fixes display issues in some terminal emulators. -# -# Default: 'off' -# Values: 'on', 'off' -# Flag: --loop -image_loop="off" - -# Thumbnail directory -# -# Default: '~/.cache/thumbnails/neofetch' -# Values: 'dir' -thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch" - -# Crop mode -# -# Default: 'normal' -# Values: 'normal', 'fit', 'fill' -# Flag: --crop_mode -# -# See this wiki page to learn about the fit and fill options. -# https://github.com/dylanaraps/neofetch/wiki/What-is-Waifu-Crop%3F -crop_mode="normal" - -# Crop offset -# Note: Only affects 'normal' crop mode. -# -# Default: 'center' -# Values: 'northwest', 'north', 'northeast', 'west', 'center' -# 'east', 'southwest', 'south', 'southeast' -# Flag: --crop_offset -crop_offset="center" - -# Image size -# The image is half the terminal width by default. -# -# Default: 'auto' -# Values: 'auto', '00px', '00%', 'none' -# Flags: --image_size -# --size -image_size="auto" - -# Gap between image and text -# -# Default: '3' -# Values: 'num', '-num' -# Flag: --gap -gap=3 - -# Image offsets -# Only works with the w3m backend. -# -# Default: '0' -# Values: 'px' -# Flags: --xoffset -# --yoffset -yoffset=0 -xoffset=0 - -# Image background color -# Only works with the w3m backend. -# -# Default: '' -# Values: 'color', 'blue' -# Flag: --bg_color -background_color= - - -# Misc Options - -# Stdout mode -# Turn off all colors and disables image backend (ASCII/Image). -# Useful for piping into another command. -# Default: 'off' -# Values: 'on', 'off' -stdout="off" diff --git a/stow/neofetch/dot-config/neofetch/neofetchLogin.conf b/stow/neofetch/dot-config/neofetch/neofetchLogin.conf deleted file mode 100644 index 7750481..0000000 --- a/stow/neofetch/dot-config/neofetch/neofetchLogin.conf +++ /dev/null @@ -1,63 +0,0 @@ -# See this wiki page for more info: -# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info -print_info() { - info underline - info title - info underline - - info "OS" distro - info "Kernel" kernel - info "Shell" shell - info "Resolution" resolution - info "Memory" memory - info "Disk" disk - info "Battery" battery - info "Uptime" uptime -} - - - - -ascii_bold="off" -#ascii_colors=(4 4) -#ascii_distro="auto" -ascii_colors=(3) -ascii_distro="gnu" -background_color= -bar_border="on" -bar_char_elapsed="-" -bar_char_total="=" -bar_color_elapsed="distro" -bar_color_total="distro" -bar_length=15 -battery_display="off" -bold="on" -colors=(6 5 4 4 5 6) -cpu_display="off" -crop_mode="normal" -crop_offset="center" -disk_display="on" -disk_show=('/' '/home') -disk_subtitle="mount" -distro_shorthand="off" -gap=3 -image_backend="ascii" -image_loop="off" -image_size="auto" -image_source="auto" -kernel_shorthand="off" -memory_display="off" -memory_percent="on" -os_arch="on" -refresh_rate="off" -separator=":" -shell_path="off" -shell_version="on" -speed_type="bios_limit" -stdout="off" -thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch" -underline_char="-" -underline_enabled="on" -uptime_shorthand="on" -xoffset=10 -yoffset=0 diff --git a/stow/newsboat/.config/newsboat/config b/stow/newsboat/.config/newsboat/config new file mode 100644 index 0000000..b789f5a --- /dev/null +++ b/stow/newsboat/.config/newsboat/config @@ -0,0 +1,11 @@ +bind-key l open +bind-key l show-urls article +bind-key h quit +bind-key j down +bind-key k up +bind-key J next-feed +bind-key K prev-feed +bind-key g home +bind-key G end + +external-url-viewer urlview diff --git a/stow/newsboat/dot-config/newsboat/config b/stow/newsboat/dot-config/newsboat/config deleted file mode 100644 index b789f5a..0000000 --- a/stow/newsboat/dot-config/newsboat/config +++ /dev/null @@ -1,11 +0,0 @@ -bind-key l open -bind-key l show-urls article -bind-key h quit -bind-key j down -bind-key k up -bind-key J next-feed -bind-key K prev-feed -bind-key g home -bind-key G end - -external-url-viewer urlview diff --git a/stow/nvim/.config/nvim/init.vim b/stow/nvim/.config/nvim/init.vim new file mode 100644 index 0000000..f182e5b --- /dev/null +++ b/stow/nvim/.config/nvim/init.vim @@ -0,0 +1,3 @@ +set runtimepath^=~/.vim runtimepath+=~/.vim/after +let &packpath = &runtimepath +source ~/.vimrc diff --git a/stow/nvim/dot-config/nvim/init.vim b/stow/nvim/dot-config/nvim/init.vim deleted file mode 100644 index f182e5b..0000000 --- a/stow/nvim/dot-config/nvim/init.vim +++ /dev/null @@ -1,3 +0,0 @@ -set runtimepath^=~/.vim runtimepath+=~/.vim/after -let &packpath = &runtimepath -source ~/.vimrc diff --git a/stow/pandoc/.config/pandoc/luascripts/diagram-generator.lua b/stow/pandoc/.config/pandoc/luascripts/diagram-generator.lua new file mode 100644 index 0000000..4d69ba3 --- /dev/null +++ b/stow/pandoc/.config/pandoc/luascripts/diagram-generator.lua @@ -0,0 +1,299 @@ +--[[ + This Lua filter is used to create images with or without captions from + code blocks. Currently PlantUML, GraphViz, Tikz, and Python can be + processed. For further details, see README.md. + + Thanks to @floriandd2ba and @jgm for the initial implementation of + the PlantUML filter, which I used as a template. Thanks also @muxueqz + for the code to generate a GraphViz image. +]] + +-- The PlantUML path. If set, uses the environment variable PLANTUML or the +-- value "plantuml.jar" (local PlantUML version). In order to define a +-- PlantUML version per pandoc document, use the meta data to define the key +-- "plantumlPath". +local plantumlPath = os.getenv("PLANTUML") or "plantuml.jar" + +-- The Inkscape path. In order to define an Inkscape version per pandoc +-- document, use the meta data to define the key "inkscapePath". +local inkscapePath = os.getenv("INKSCAPE") or "inkscape" + +-- The Python path. In order to define a Python version per pandoc document, +-- use the meta data to define the key "pythonPath". +local pythonPath = os.getenv("PYTHON") + +-- The Python environment's activate script. Can be set on a per document +-- basis by using the meta data key "activatePythonPath". +local pythonActivatePath = os.getenv("PYTHON_ACTIVATE") + +-- The Java path. In order to define a Java version per pandoc document, +-- use the meta data to define the key "javaPath". +local javaPath = os.getenv("JAVA_HOME") +if javaPath then + javaPath = javaPath .. package.config:sub(1,1) .. "bin" + .. package.config:sub(1,1) .. "java" +else + javaPath = "java" +end + +-- The dot (Graphviz) path. In order to define a dot version per pandoc +-- document, use the meta data to define the key "dotPath". +local dotPath = os.getenv("DOT") or "dot" + +-- The pdflatex path. In order to define a pdflatex version per pandoc +-- document, use the meta data to define the key "pdflatexPath". +local pdflatexPath = os.getenv("PDFLATEX") or "pdflatex" + +-- The default format is SVG i.e. vector graphics: +local filetype = "svg" +local mimetype = "image/svg+xml" + +-- Check for output formats that potentially cannot use SVG +-- vector graphics. In these cases, we use a different format +-- such as PNG: +if FORMAT == "docx" then + filetype = "png" + mimetype = "image/png" +elseif FORMAT == "pptx" then + filetype = "png" + mimetype = "image/png" +elseif FORMAT == "rtf" then + filetype = "png" + mimetype = "image/png" +end + +-- Execute the meta data table to determine the paths. This function +-- must be called first to get the desired path. If one of these +-- meta options was set, it gets used instead of the corresponding +-- environment variable: +function Meta(meta) + plantumlPath = meta.plantumlPath or plantumlPath + inkscapePath = meta.inkscapePath or inkscapePath + pythonPath = meta.pythonPath or pythonPath + pythonActivatePath = meta.activatePythonPath or pythonActivatePath + javaPath = meta.javaPath or javaPath + dotPath = meta.dotPath or dotPath + pdflatexPath = meta.pdflatexPath or pdflatexPath +end + +-- Call plantuml.jar with some parameters (cf. PlantUML help): +local function plantuml(puml, filetype) + local final = pandoc.pipe(javaPath, {"-jar", plantumlPath, "-t" .. filetype, "-pipe", "-charset", "UTF8"}, puml) + return final +end + +-- Call dot (GraphViz) in order to generate the image +-- (thanks @muxueqz for this code): +local function graphviz(code, filetype) + local final = pandoc.pipe(dotPath, {"-T" .. filetype}, code) + return final +end + +-- Compile LaTeX with Tikz code to an image: +local function tikz2image(src, filetype, additionalPackages) + + -- Define file names: + local outfile = string.format("./tmp-latex/file.%s", filetype) + local tmp = "./tmp-latex/file" + local tmpDir = "./tmp-latex/" + + -- Ensure, that the tmp directory exists: + os.execute("mkdir -p tmp-latex") + + -- Build and write the LaTeX document: + local f = io.open(tmp .. ".tex", 'w') + f:write("\\documentclass{standalone}\n\\usepackage{tikz}\n") + + -- Any additional package(s) are desired? + if additionalPackages then + f:write(additionalPackages) + end + + f:write("\\begin{document}\n") + f:write(src) + f:write("\n\\end{document}\n") + f:close() + + -- Execute the LaTeX compiler: + pandoc.pipe(pdflatexPath, {'-output-directory', tmpDir, tmp}, '') + + -- Build the basic Inkscape command for the conversion: + local baseCommand = " --without-gui --file=" .. tmp .. ".pdf" + local knownFormat = false + + if filetype == "png" then + + -- Append the subcommands to convert into a PNG file: + baseCommand = baseCommand .. " --export-png=" + .. tmp .. ".png --export-dpi=300" + knownFormat = true + + elseif filetype == "svg" then + + -- Append the subcommands to convert into a SVG file: + baseCommand = baseCommand .. " --export-plain-svg=" .. tmp .. ".svg" + knownFormat = true + + end + + -- Unfortunately, continuation is only possible, if we know the actual + -- format: + if not knownFormat then + error(string.format("Don't know how to convert pdf to %s.", filetype)) + end + + local imgData = nil + + -- We know the desired format. Thus, execute Inkscape: + os.execute("\"" .. inkscapePath .. "\"" .. baseCommand) + + -- Try to open the image: + local r = io.open(tmp .. "." .. filetype, 'rb') + + -- Read the image, if available: + if r then + imgData = r:read("*all") + r:close() + end + + -- Delete the image tmp file: + os.remove(outfile) + + -- Remove the temporary files: + os.remove(tmp .. ".tex") + os.remove(tmp .. ".pdf") + os.remove(tmp .. ".log") + os.remove(tmp .. ".aux") + + return imgData +end + +-- Run Python to generate an image: +local function py2image(code, filetype) + + -- Define the temp files: + local outfile = string.format('%s.%s', os.tmpname(), filetype) + local pyfile = os.tmpname() + + -- Replace the desired destination's file type in the Python code: + local extendedCode = string.gsub(code, "%$FORMAT%$", filetype) + + -- Replace the desired destination's path in the Python code: + extendedCode = string.gsub(extendedCode, "%$DESTINATION%$", outfile) + + -- Write the Python code: + local f = io.open(pyfile, 'w') + f:write(extendedCode) + f:close() + + -- Execute Python in the desired environment: + local pycmd = pythonPath .. ' ' .. pyfile + local command = pythonActivatePath + and pythonActivatePath .. ' && ' .. pycmd + or pycmd + os.execute(command) + + -- Try to open the written image: + local r = io.open(outfile, 'rb') + local imgData = nil + + -- When the image exist, read it: + if r then + imgData = r:read("*all") + r:close() + else + io.stderr:write(string.format("File '%s' could not be opened", outfile)) + error 'Could not create image from python code.' + end + + -- Delete the tmp files: + os.remove(pyfile) + os.remove(outfile) + + return imgData +end + +-- Executes each document's code block to find matching code blocks: +function CodeBlock(block) + + -- Predefine a potential image: + local fname = nil + + -- Using a table with all known generators i.e. converters: + local converters = { + plantuml = plantuml, + graphviz = graphviz, + tikz = tikz2image, + py2image = py2image, + } + + -- Check if a converter exists for this block. If not, return the block + -- unchanged. + local img_converter = converters[block.classes[1]] + if not img_converter then + return nil + end + + -- Call the correct converter which belongs to the used class: + local success, img = pcall(img_converter, block.text, + filetype, block.attributes["additionalPackages"] or nil) + + -- Was ok? + if success and img then + -- Hash the figure name and content: + fname = pandoc.sha1(img) .. "." .. filetype + + -- Store the data in the media bag: + pandoc.mediabag.insert(fname, mimetype, img) + + else + + -- an error occured; img contains the error message + io.stderr:write(tostring(img)) + io.stderr:write('\n') + error 'Image conversion failed. Aborting.' + + end + + -- Case: This code block was an image e.g. PlantUML or dot/Graphviz, etc.: + if fname then + + -- Define the default caption: + local caption = {} + local enableCaption = nil + + -- If the user defines a caption, use it: + if block.attributes["caption"] then + caption = pandoc.read(block.attributes.caption).blocks[1].content + + -- This is pandoc's current hack to enforce a caption: + enableCaption = "fig:" + end + + -- Create a new image for the document's structure. Attach the user's + -- caption. Also use a hack (fig:) to enforce pandoc to create a + -- figure i.e. attach a caption to the image. + local imgObj = pandoc.Image(caption, fname, enableCaption) + + -- Now, transfer the attribute "name" from the code block to the new + -- image block. It might gets used by the figure numbering lua filter. + -- If the figure numbering gets not used, this additional attribute + -- gets ignored as well. + if block.attributes["name"] then + imgObj.attributes["name"] = block.attributes["name"] + end + + -- Finally, put the image inside an empty paragraph. By returning the + -- resulting paragraph object, the source code block gets replaced by + -- the image: + return pandoc.Para{ imgObj } + end +end + +-- Normally, pandoc will run the function in the built-in order Inlines -> +-- Blocks -> Meta -> Pandoc. We instead want Meta -> Blocks. Thus, we must +-- define our custom order: +return { + {Meta = Meta}, + {CodeBlock = CodeBlock}, +} diff --git a/stow/pandoc/dot-config/pandoc/luascripts/diagram-generator.lua b/stow/pandoc/dot-config/pandoc/luascripts/diagram-generator.lua deleted file mode 100644 index 4d69ba3..0000000 --- a/stow/pandoc/dot-config/pandoc/luascripts/diagram-generator.lua +++ /dev/null @@ -1,299 +0,0 @@ ---[[ - This Lua filter is used to create images with or without captions from - code blocks. Currently PlantUML, GraphViz, Tikz, and Python can be - processed. For further details, see README.md. - - Thanks to @floriandd2ba and @jgm for the initial implementation of - the PlantUML filter, which I used as a template. Thanks also @muxueqz - for the code to generate a GraphViz image. -]] - --- The PlantUML path. If set, uses the environment variable PLANTUML or the --- value "plantuml.jar" (local PlantUML version). In order to define a --- PlantUML version per pandoc document, use the meta data to define the key --- "plantumlPath". -local plantumlPath = os.getenv("PLANTUML") or "plantuml.jar" - --- The Inkscape path. In order to define an Inkscape version per pandoc --- document, use the meta data to define the key "inkscapePath". -local inkscapePath = os.getenv("INKSCAPE") or "inkscape" - --- The Python path. In order to define a Python version per pandoc document, --- use the meta data to define the key "pythonPath". -local pythonPath = os.getenv("PYTHON") - --- The Python environment's activate script. Can be set on a per document --- basis by using the meta data key "activatePythonPath". -local pythonActivatePath = os.getenv("PYTHON_ACTIVATE") - --- The Java path. In order to define a Java version per pandoc document, --- use the meta data to define the key "javaPath". -local javaPath = os.getenv("JAVA_HOME") -if javaPath then - javaPath = javaPath .. package.config:sub(1,1) .. "bin" - .. package.config:sub(1,1) .. "java" -else - javaPath = "java" -end - --- The dot (Graphviz) path. In order to define a dot version per pandoc --- document, use the meta data to define the key "dotPath". -local dotPath = os.getenv("DOT") or "dot" - --- The pdflatex path. In order to define a pdflatex version per pandoc --- document, use the meta data to define the key "pdflatexPath". -local pdflatexPath = os.getenv("PDFLATEX") or "pdflatex" - --- The default format is SVG i.e. vector graphics: -local filetype = "svg" -local mimetype = "image/svg+xml" - --- Check for output formats that potentially cannot use SVG --- vector graphics. In these cases, we use a different format --- such as PNG: -if FORMAT == "docx" then - filetype = "png" - mimetype = "image/png" -elseif FORMAT == "pptx" then - filetype = "png" - mimetype = "image/png" -elseif FORMAT == "rtf" then - filetype = "png" - mimetype = "image/png" -end - --- Execute the meta data table to determine the paths. This function --- must be called first to get the desired path. If one of these --- meta options was set, it gets used instead of the corresponding --- environment variable: -function Meta(meta) - plantumlPath = meta.plantumlPath or plantumlPath - inkscapePath = meta.inkscapePath or inkscapePath - pythonPath = meta.pythonPath or pythonPath - pythonActivatePath = meta.activatePythonPath or pythonActivatePath - javaPath = meta.javaPath or javaPath - dotPath = meta.dotPath or dotPath - pdflatexPath = meta.pdflatexPath or pdflatexPath -end - --- Call plantuml.jar with some parameters (cf. PlantUML help): -local function plantuml(puml, filetype) - local final = pandoc.pipe(javaPath, {"-jar", plantumlPath, "-t" .. filetype, "-pipe", "-charset", "UTF8"}, puml) - return final -end - --- Call dot (GraphViz) in order to generate the image --- (thanks @muxueqz for this code): -local function graphviz(code, filetype) - local final = pandoc.pipe(dotPath, {"-T" .. filetype}, code) - return final -end - --- Compile LaTeX with Tikz code to an image: -local function tikz2image(src, filetype, additionalPackages) - - -- Define file names: - local outfile = string.format("./tmp-latex/file.%s", filetype) - local tmp = "./tmp-latex/file" - local tmpDir = "./tmp-latex/" - - -- Ensure, that the tmp directory exists: - os.execute("mkdir -p tmp-latex") - - -- Build and write the LaTeX document: - local f = io.open(tmp .. ".tex", 'w') - f:write("\\documentclass{standalone}\n\\usepackage{tikz}\n") - - -- Any additional package(s) are desired? - if additionalPackages then - f:write(additionalPackages) - end - - f:write("\\begin{document}\n") - f:write(src) - f:write("\n\\end{document}\n") - f:close() - - -- Execute the LaTeX compiler: - pandoc.pipe(pdflatexPath, {'-output-directory', tmpDir, tmp}, '') - - -- Build the basic Inkscape command for the conversion: - local baseCommand = " --without-gui --file=" .. tmp .. ".pdf" - local knownFormat = false - - if filetype == "png" then - - -- Append the subcommands to convert into a PNG file: - baseCommand = baseCommand .. " --export-png=" - .. tmp .. ".png --export-dpi=300" - knownFormat = true - - elseif filetype == "svg" then - - -- Append the subcommands to convert into a SVG file: - baseCommand = baseCommand .. " --export-plain-svg=" .. tmp .. ".svg" - knownFormat = true - - end - - -- Unfortunately, continuation is only possible, if we know the actual - -- format: - if not knownFormat then - error(string.format("Don't know how to convert pdf to %s.", filetype)) - end - - local imgData = nil - - -- We know the desired format. Thus, execute Inkscape: - os.execute("\"" .. inkscapePath .. "\"" .. baseCommand) - - -- Try to open the image: - local r = io.open(tmp .. "." .. filetype, 'rb') - - -- Read the image, if available: - if r then - imgData = r:read("*all") - r:close() - end - - -- Delete the image tmp file: - os.remove(outfile) - - -- Remove the temporary files: - os.remove(tmp .. ".tex") - os.remove(tmp .. ".pdf") - os.remove(tmp .. ".log") - os.remove(tmp .. ".aux") - - return imgData -end - --- Run Python to generate an image: -local function py2image(code, filetype) - - -- Define the temp files: - local outfile = string.format('%s.%s', os.tmpname(), filetype) - local pyfile = os.tmpname() - - -- Replace the desired destination's file type in the Python code: - local extendedCode = string.gsub(code, "%$FORMAT%$", filetype) - - -- Replace the desired destination's path in the Python code: - extendedCode = string.gsub(extendedCode, "%$DESTINATION%$", outfile) - - -- Write the Python code: - local f = io.open(pyfile, 'w') - f:write(extendedCode) - f:close() - - -- Execute Python in the desired environment: - local pycmd = pythonPath .. ' ' .. pyfile - local command = pythonActivatePath - and pythonActivatePath .. ' && ' .. pycmd - or pycmd - os.execute(command) - - -- Try to open the written image: - local r = io.open(outfile, 'rb') - local imgData = nil - - -- When the image exist, read it: - if r then - imgData = r:read("*all") - r:close() - else - io.stderr:write(string.format("File '%s' could not be opened", outfile)) - error 'Could not create image from python code.' - end - - -- Delete the tmp files: - os.remove(pyfile) - os.remove(outfile) - - return imgData -end - --- Executes each document's code block to find matching code blocks: -function CodeBlock(block) - - -- Predefine a potential image: - local fname = nil - - -- Using a table with all known generators i.e. converters: - local converters = { - plantuml = plantuml, - graphviz = graphviz, - tikz = tikz2image, - py2image = py2image, - } - - -- Check if a converter exists for this block. If not, return the block - -- unchanged. - local img_converter = converters[block.classes[1]] - if not img_converter then - return nil - end - - -- Call the correct converter which belongs to the used class: - local success, img = pcall(img_converter, block.text, - filetype, block.attributes["additionalPackages"] or nil) - - -- Was ok? - if success and img then - -- Hash the figure name and content: - fname = pandoc.sha1(img) .. "." .. filetype - - -- Store the data in the media bag: - pandoc.mediabag.insert(fname, mimetype, img) - - else - - -- an error occured; img contains the error message - io.stderr:write(tostring(img)) - io.stderr:write('\n') - error 'Image conversion failed. Aborting.' - - end - - -- Case: This code block was an image e.g. PlantUML or dot/Graphviz, etc.: - if fname then - - -- Define the default caption: - local caption = {} - local enableCaption = nil - - -- If the user defines a caption, use it: - if block.attributes["caption"] then - caption = pandoc.read(block.attributes.caption).blocks[1].content - - -- This is pandoc's current hack to enforce a caption: - enableCaption = "fig:" - end - - -- Create a new image for the document's structure. Attach the user's - -- caption. Also use a hack (fig:) to enforce pandoc to create a - -- figure i.e. attach a caption to the image. - local imgObj = pandoc.Image(caption, fname, enableCaption) - - -- Now, transfer the attribute "name" from the code block to the new - -- image block. It might gets used by the figure numbering lua filter. - -- If the figure numbering gets not used, this additional attribute - -- gets ignored as well. - if block.attributes["name"] then - imgObj.attributes["name"] = block.attributes["name"] - end - - -- Finally, put the image inside an empty paragraph. By returning the - -- resulting paragraph object, the source code block gets replaced by - -- the image: - return pandoc.Para{ imgObj } - end -end - --- Normally, pandoc will run the function in the built-in order Inlines -> --- Blocks -> Meta -> Pandoc. We instead want Meta -> Blocks. Thus, we must --- define our custom order: -return { - {Meta = Meta}, - {CodeBlock = CodeBlock}, -} diff --git a/stow/picom/.config/picom/picom.conf b/stow/picom/.config/picom/picom.conf new file mode 100644 index 0000000..2f4dfc7 --- /dev/null +++ b/stow/picom/.config/picom/picom.conf @@ -0,0 +1,502 @@ +################################# +# Animations # +################################# +# requires https://github.com/jonaburg/picom +# (These are also the default values) +transition-length = 200 +transition-pow-x = 0.5 +transition-pow-y = 0.5 +transition-pow-w = 0.5 +transition-pow-h = 0.5 +size-transition = true + + +################################# +# Corners # +################################# +# requires: https://github.com/sdhand/compton or https://github.com/jonaburg/picom +corner-radius = 0; +rounded-corners-exclude = [ + #"window_type = 'normal'", + "class_g = 'awesome'", + #"class_g = 'URxvt'", + "class_g = 'i3bar'", + "class_g = 'dwm'", + "class_g = 'XTerm'", + "class_g = 'kitty'", + "class_g = 'Alacritty'", + "class_g = 'Polybar'", + "class_g = 'code-oss'", + #"class_g = 'TelegramDesktop'", + "class_g = 'firefox'", + "class_g = 'Thunderbird'" +]; +round-borders = 0; +round-borders-exclude = [ + #"class_g = 'TelegramDesktop'", +]; + +################################# +# Shadows # +################################# + + +# Enabled client-side shadows on windows. Note desktop windows +# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow, +# unless explicitly requested using the wintypes option. +# +# shadow = false +shadow = true; + +# The blur radius for shadows, in pixels. (defaults to 12) +# shadow-radius = 12 +shadow-radius = 12; + +# The opacity of shadows. (0.0 - 1.0, defaults to 0.75) +# shadow-opacity = .75 + +# The left offset for shadows, in pixels. (defaults to -15) +# shadow-offset-x = -15 +shadow-offset-x = -7; + +# The top offset for shadows, in pixels. (defaults to -15) +# shadow-offset-y = -15 +shadow-offset-y = -7; + +# Avoid drawing shadows on dock/panel windows. This option is deprecated, +# you should use the *wintypes* option in your config file instead. +# +# no-dock-shadow = false + +# Don't draw shadows on drag-and-drop windows. This option is deprecated, +# you should use the *wintypes* option in your config file instead. +# +# no-dnd-shadow = false + +# Red color value of shadow (0.0 - 1.0, defaults to 0). +# shadow-red = 0 + +# Green color value of shadow (0.0 - 1.0, defaults to 0). +# shadow-green = 0 + +# Blue color value of shadow (0.0 - 1.0, defaults to 0). +# shadow-blue = 0 + +# Do not paint shadows on shaped windows. Note shaped windows +# here means windows setting its shape through X Shape extension. +# Those using ARGB background is beyond our control. +# Deprecated, use +# shadow-exclude = 'bounding_shaped' +# or +# shadow-exclude = 'bounding_shaped && !rounded_corners' +# instead. +# +# shadow-ignore-shaped = '' + +# Specify a list of conditions of windows that should have no shadow. +# +# examples: +# shadow-exclude = "n:e:Notification"; +# +# shadow-exclude = [] +shadow-exclude = [ + "name = 'Notification'", + "class_g = 'Conky'", + "class_g ?= 'Notify-osd'", + "class_g = 'Cairo-clock'", + "class_g = 'slop'", + "class_g = 'Polybar'", + "_GTK_FRAME_EXTENTS@:c" +]; + +# Specify a X geometry that describes the region in which shadow should not +# be painted in, such as a dock window region. Use +# shadow-exclude-reg = "x10+0+0" +# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on. +# +# shadow-exclude-reg = "" + +# Crop shadow of a window fully on a particular Xinerama screen to the screen. +# xinerama-shadow-crop = false + + +################################# +# Fading # +################################# + + +# Fade windows in/out when opening/closing and when opacity changes, +# unless no-fading-openclose is used. +# fading = false +fading = true; + +# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028) +# fade-in-step = 0.028 +fade-in-step = 0.03; + +# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03) +# fade-out-step = 0.03 +fade-out-step = 0.03; + +# The time between steps in fade step, in milliseconds. (> 0, defaults to 10) +# fade-delta = 10 + +# Specify a list of conditions of windows that should not be faded. +# don't need this, we disable fading for all normal windows with wintypes: {} +fade-exclude = [ + "class_g = 'slop'" # maim +] + +# Do not fade on window open/close. +# no-fading-openclose = false + +# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc. +# no-fading-destroyed-argb = false + + +################################# +# Transparency / Opacity # +################################# + +# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0) +# inactive-opacity = 1 +inactive-opacity = 0.8; + +# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default) +# frame-opacity = 1.0 +frame-opacity = 0.7; + +# Default opacity for dropdown menus and popup menus. (0.0 - 1.0, defaults to 1.0) +# menu-opacity = 1.0 +# menu-opacity is depreciated use dropdown-menu and popup-menu instead. + +#If using these 2 below change their values in line 510 & 511 aswell +popup_menu = { opacity = 0.8; } +dropdown_menu = { opacity = 0.8; } + + +# Let inactive opacity set by -i override the '_NET_WM_OPACITY' values of windows. +# inactive-opacity-override = true +inactive-opacity-override = false; + +# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0) +active-opacity = 1.0; + +# Dim inactive windows. (0.0 - 1.0, defaults to 0.0) +# inactive-dim = 0.0 + +# Specify a list of conditions of windows that should always be considered focused. +# focus-exclude = [] +focus-exclude = [ + "class_g = 'Cairo-clock'", + "class_g = 'Bar'", # lemonbar + "class_g = 'slop'" # maim +]; + +# Use fixed inactive dim value, instead of adjusting according to window opacity. +# inactive-dim-fixed = 1.0 + +# Specify a list of opacity rules, in the format `PERCENT:PATTERN`, +# like `50:name *= "Firefox"`. picom-trans is recommended over this. +# Note we don't make any guarantee about possible conflicts with other +# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows. +# example: +# opacity-rule = [ "80:class_g = 'URxvt'" ]; +# +# opacity-rule = [] +opacity-rule = [ + "90:class_g = 'URxvt' && !focused", + "80:class_g = 'dmenu'" +]; + + +################################# +# Background-Blurring # +################################# + + +# Parameters for background blurring, see the *BLUR* section for more information. +# blur-method = +# blur-size = 12 +# +# blur-deviation = false + +# Blur background of semi-transparent / ARGB windows. +# Bad in performance, with driver-dependent behavior. +# The name of the switch may change without prior notifications. +# +# blur-background = true; + +# Blur background of windows when the window frame is not opaque. +# Implies: +# blur-background +# Bad in performance, with driver-dependent behavior. The name may change. +# +# blur-background-frame = false; + + +# Use fixed blur strength rather than adjusting according to window opacity. +# blur-background-fixed = false; + + +# Specify the blur convolution kernel, with the following format: +# example: +# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; +# +# blur-kern = '' +# blur-kern = "3x3box"; + +blur: { + # requires: https://github.com/ibhagwan/picom + method = "kawase"; + #method = "kernel"; + strength = 3; + # deviation = 1.0; + # kernel = "11x11gaussian"; + background = false; + background-frame = false; + background-fixed = false; + kern = "3x3box"; +} + +# Exclude conditions for background blur. +blur-background-exclude = [ + #"window_type = 'dock'", + #"window_type = 'desktop'", + #"class_g = 'URxvt'", + # + # prevents picom from blurring the background + # when taking selection screenshot with `main` + # https://github.com/naelstrof/maim/issues/130 + "class_g = 'slop'", + "_GTK_FRAME_EXTENTS@:c" +]; + + +################################# +# General Settings # +################################# + +# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers. +# daemon = false + +# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`. +# `xrender` is the default one. +# +experimental-backends = true; +backend = "glx"; +#backend = "xrender"; + + +# Enable/disable VSync. +# vsync = false +vsync = true + +# Enable remote control via D-Bus. See the *D-BUS API* section below for more details. +# dbus = false + +# Try to detect WM windows (a non-override-redirect window with no +# child that has 'WM_STATE') and mark them as active. +# +# mark-wmwin-focused = false +mark-wmwin-focused = true; + +# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused. +# mark-ovredir-focused = false +mark-ovredir-focused = true; + +# Try to detect windows with rounded corners and don't consider them +# shaped windows. The accuracy is not very high, unfortunately. +# +# detect-rounded-corners = false +detect-rounded-corners = true; + +# Detect '_NET_WM_OPACITY' on client windows, useful for window managers +# not passing '_NET_WM_OPACITY' of client windows to frame windows. +# +# detect-client-opacity = false +detect-client-opacity = true; + +# Specify refresh rate of the screen. If not specified or 0, picom will +# try detecting this with X RandR extension. +# +# refresh-rate = 60 +refresh-rate = 0 + +# Limit picom to repaint at most once every 1 / 'refresh_rate' second to +# boost performance. This should not be used with +# vsync drm/opengl/opengl-oml +# as they essentially does sw-opti's job already, +# unless you wish to specify a lower refresh rate than the actual value. +# +# sw-opti = + +# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window, +# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy, +# provided that the WM supports it. +# +# use-ewmh-active-win = false + +# Unredirect all windows if a full-screen opaque window is detected, +# to maximize performance for full-screen windows. Known to cause flickering +# when redirecting/unredirecting windows. paint-on-overlay may make the flickering less obvious. +# +# unredir-if-possible = false + +# Delay before unredirecting the window, in milliseconds. Defaults to 0. +# unredir-if-possible-delay = 0 + +# Conditions of windows that shouldn't be considered full-screen for unredirecting screen. +# unredir-if-possible-exclude = [] + +# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows +# in the same group focused at the same time. +# +# detect-transient = false +detect-transient = true + +# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same +# group focused at the same time. 'WM_TRANSIENT_FOR' has higher priority if +# detect-transient is enabled, too. +# +# detect-client-leader = false +detect-client-leader = true + +# Resize damaged region by a specific number of pixels. +# A positive value enlarges it while a negative one shrinks it. +# If the value is positive, those additional pixels will not be actually painted +# to screen, only used in blur calculation, and such. (Due to technical limitations, +# with use-damage, those pixels will still be incorrectly painted to screen.) +# Primarily used to fix the line corruption issues of blur, +# in which case you should use the blur radius value here +# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`, +# with a 5x5 one you use `--resize-damage 2`, and so on). +# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly. +# +# resize-damage = 1 + +# Specify a list of conditions of windows that should be painted with inverted color. +# Resource-hogging, and is not well tested. +# +# invert-color-include = [] + +# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer. +# Might cause incorrect opacity when rendering transparent content (but never +# practically happened) and may not work with blur-background. +# My tests show a 15% performance boost. Recommended. +# +# glx-no-stencil = false + +# GLX backend: Avoid rebinding pixmap on window damage. +# Probably could improve performance on rapid window content changes, +# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.). +# Recommended if it works. +# +# glx-no-rebind-pixmap = false + +# Disable the use of damage information. +# This cause the whole screen to be redrawn everytime, instead of the part of the screen +# has actually changed. Potentially degrades the performance, but might fix some artifacts. +# The opposing option is use-damage +# +# no-use-damage = false +#use-damage = true (Causing Weird Black semi opaque rectangles when terminal is opened) +#Changing use-damage to false fixes the problem +use-damage = false + +# Use X Sync fence to sync clients' draw calls, to make sure all draw +# calls are finished before picom starts drawing. Needed on nvidia-drivers +# with GLX backend for some users. +# +# xrender-sync-fence = false + +# GLX backend: Use specified GLSL fragment shader for rendering window contents. +# See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl` +# in the source tree for examples. +# +# glx-fshader-win = '' + +# Force all windows to be painted with blending. Useful if you +# have a glx-fshader-win that could turn opaque pixels transparent. +# +# force-win-blend = false + +# Do not use EWMH to detect fullscreen windows. +# Reverts to checking if a window is fullscreen based only on its size and coordinates. +# +# no-ewmh-fullscreen = false + +# Dimming bright windows so their brightness doesn't exceed this set value. +# Brightness of a window is estimated by averaging all pixels in the window, +# so this could comes with a performance hit. +# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0) +# +# max-brightness = 1.0 + +# Make transparent windows clip other windows like non-transparent windows do, +# instead of blending on top of them. +# +# transparent-clipping = false + +# Set the log level. Possible values are: +# "trace", "debug", "info", "warn", "error" +# in increasing level of importance. Case doesn't matter. +# If using the "TRACE" log level, it's better to log into a file +# using *--log-file*, since it can generate a huge stream of logs. +# +# log-level = "debug" +log-level = "info"; + +# Set the log file. +# If *--log-file* is never specified, logs will be written to stderr. +# Otherwise, logs will to written to the given file, though some of the early +# logs might still be written to the stderr. +# When setting this option from the config file, it is recommended to use an absolute path. +# +# log-file = '/path/to/your/log/file' + +# Show all X errors (for debugging) +# show-all-xerrors = false + +# Write process ID to a file. +# write-pid-path = '/path/to/your/log/file' + +# Window type settings +# +# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard: +# "unknown", "desktop", "dock", "toolbar", "menu", "utility", +# "splash", "dialog", "normal", "dropdown_menu", "popup_menu", +# "tooltip", "notification", "combo", and "dnd". +# +# Following per window-type options are available: :: +# +# fade, shadow::: +# Controls window-type-specific shadow and fade settings. +# +# opacity::: +# Controls default opacity of the window type. +# +# focus::: +# Controls whether the window of this type is to be always considered focused. +# (By default, all window types except "normal" and "dialog" has this on.) +# +# full-shadow::: +# Controls whether shadow is drawn under the parts of the window that you +# normally won't be able to see. Useful when the window has parts of it +# transparent, and you want shadows in those areas. +# +# redir-ignore::: +# Controls whether this type of windows should cause screen to become +# redirected again after been unredirected. If you have unredir-if-possible +# set, and doesn't want certain window to cause unnecessary screen redirection, +# you can set this to `true`. +# +wintypes: +{ + normal = { fade = false; shadow = false; } + tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; }; + dock = { shadow = false; } + dnd = { shadow = false; } + popup_menu = { opacity = 0.8; } + dropdown_menu = { opacity = 0.8; } +}; diff --git a/stow/picom/.config/picom/picom.jonaburg.sample.conf b/stow/picom/.config/picom/picom.jonaburg.sample.conf new file mode 100644 index 0000000..ee3fbbe --- /dev/null +++ b/stow/picom/.config/picom/picom.jonaburg.sample.conf @@ -0,0 +1,512 @@ +################################# +# Animations # +################################# +# requires https://github.com/jonaburg/picom +# (These are also the default values) +transition-length = 300 +transition-pow-x = 0.1 +transition-pow-y = 0.1 +transition-pow-w = 0.1 +transition-pow-h = 0.1 +size-transition = true + + +################################# +# Corners # +################################# +# requires: https://github.com/sdhand/compton or https://github.com/jonaburg/picom +corner-radius = 10.0; +rounded-corners-exclude = [ + #"window_type = 'normal'", + "class_g = 'awesome'", + "class_g = 'URxvt'", + "class_g = 'XTerm'", + "class_g = 'kitty'", + "class_g = 'Alacritty'", + "class_g = 'Polybar'", + "class_g = 'code-oss'", + #"class_g = 'TelegramDesktop'", + "class_g = 'firefox'", + "class_g = 'Thunderbird'" +]; +round-borders = 1; +round-borders-exclude = [ + #"class_g = 'TelegramDesktop'", +]; + +################################# +# Shadows # +################################# + + +# Enabled client-side shadows on windows. Note desktop windows +# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow, +# unless explicitly requested using the wintypes option. +# +# shadow = false +shadow = false; + +# The blur radius for shadows, in pixels. (defaults to 12) +# shadow-radius = 12 +shadow-radius = 7; + +# The opacity of shadows. (0.0 - 1.0, defaults to 0.75) +# shadow-opacity = .75 + +# The left offset for shadows, in pixels. (defaults to -15) +# shadow-offset-x = -15 +shadow-offset-x = -7; + +# The top offset for shadows, in pixels. (defaults to -15) +# shadow-offset-y = -15 +shadow-offset-y = -7; + +# Avoid drawing shadows on dock/panel windows. This option is deprecated, +# you should use the *wintypes* option in your config file instead. +# +# no-dock-shadow = false + +# Don't draw shadows on drag-and-drop windows. This option is deprecated, +# you should use the *wintypes* option in your config file instead. +# +# no-dnd-shadow = false + +# Red color value of shadow (0.0 - 1.0, defaults to 0). +# shadow-red = 0 + +# Green color value of shadow (0.0 - 1.0, defaults to 0). +# shadow-green = 0 + +# Blue color value of shadow (0.0 - 1.0, defaults to 0). +# shadow-blue = 0 + +# Do not paint shadows on shaped windows. Note shaped windows +# here means windows setting its shape through X Shape extension. +# Those using ARGB background is beyond our control. +# Deprecated, use +# shadow-exclude = 'bounding_shaped' +# or +# shadow-exclude = 'bounding_shaped && !rounded_corners' +# instead. +# +# shadow-ignore-shaped = '' + +# Specify a list of conditions of windows that should have no shadow. +# +# examples: +# shadow-exclude = "n:e:Notification"; +# +# shadow-exclude = [] +shadow-exclude = [ + "name = 'Notification'", + "class_g = 'Conky'", + "class_g ?= 'Notify-osd'", + "class_g = 'Cairo-clock'", + "class_g = 'slop'", + "class_g = 'Polybar'", + "_GTK_FRAME_EXTENTS@:c" +]; + +# Specify a X geometry that describes the region in which shadow should not +# be painted in, such as a dock window region. Use +# shadow-exclude-reg = "x10+0+0" +# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on. +# +# shadow-exclude-reg = "" + +# Crop shadow of a window fully on a particular Xinerama screen to the screen. +# xinerama-shadow-crop = false + + +################################# +# Fading # +################################# + + +# Fade windows in/out when opening/closing and when opacity changes, +# unless no-fading-openclose is used. +# fading = false +fading = true; + +# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028) +# fade-in-step = 0.028 +fade-in-step = 0.03; + +# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03) +# fade-out-step = 0.03 +fade-out-step = 0.03; + +# The time between steps in fade step, in milliseconds. (> 0, defaults to 10) +# fade-delta = 10 + +# Specify a list of conditions of windows that should not be faded. +# don't need this, we disable fading for all normal windows with wintypes: {} +fade-exclude = [ + "class_g = 'slop'" # maim +] + +# Do not fade on window open/close. +# no-fading-openclose = false + +# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc. +# no-fading-destroyed-argb = false + + +################################# +# Transparency / Opacity # +################################# + + +# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0) +# inactive-opacity = 1 +inactive-opacity = 0.8; + +# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default) +# frame-opacity = 1.0 +frame-opacity = 0.7; + +# Default opacity for dropdown menus and popup menus. (0.0 - 1.0, defaults to 1.0) +# menu-opacity = 1.0 +# menu-opacity is depreciated use dropdown-menu and popup-menu instead. + +#If using these 2 below change their values in line 510 & 511 aswell +popup_menu = { opacity = 0.8; } +dropdown_menu = { opacity = 0.8; } + + +# Let inactive opacity set by -i override the '_NET_WM_OPACITY' values of windows. +# inactive-opacity-override = true +inactive-opacity-override = false; + +# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0) +active-opacity = 1.0; + +# Dim inactive windows. (0.0 - 1.0, defaults to 0.0) +# inactive-dim = 0.0 + +# Specify a list of conditions of windows that should always be considered focused. +# focus-exclude = [] +focus-exclude = [ + "class_g = 'Cairo-clock'", + "class_g = 'Bar'", # lemonbar + "class_g = 'slop'" # maim +]; + +# Use fixed inactive dim value, instead of adjusting according to window opacity. +# inactive-dim-fixed = 1.0 + +# Specify a list of opacity rules, in the format `PERCENT:PATTERN`, +# like `50:name *= "Firefox"`. picom-trans is recommended over this. +# Note we don't make any guarantee about possible conflicts with other +# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows. +# example: +# opacity-rule = [ "80:class_g = 'URxvt'" ]; +# +# opacity-rule = [] +opacity-rule = [ + "80:class_g = 'Bar'", # lemonbar + "100:class_g = 'slop'", # maim + "100:class_g = 'XTerm'", + "100:class_g = 'URxvt'", + "100:class_g = 'kitty'", + "100:class_g = 'Alacritty'", + "80:class_g = 'Polybar'", + "100:class_g = 'code-oss'", + "100:class_g = 'Meld'", + "70:class_g = 'TelegramDesktop'", + "90:class_g = 'Joplin'", + "100:class_g = 'firefox'", + "100:class_g = 'Thunderbird'" +]; + + +################################# +# Background-Blurring # +################################# + + +# Parameters for background blurring, see the *BLUR* section for more information. +# blur-method = +# blur-size = 12 +# +# blur-deviation = false + +# Blur background of semi-transparent / ARGB windows. +# Bad in performance, with driver-dependent behavior. +# The name of the switch may change without prior notifications. +# +# blur-background = true; + +# Blur background of windows when the window frame is not opaque. +# Implies: +# blur-background +# Bad in performance, with driver-dependent behavior. The name may change. +# +# blur-background-frame = false; + + +# Use fixed blur strength rather than adjusting according to window opacity. +# blur-background-fixed = false; + + +# Specify the blur convolution kernel, with the following format: +# example: +# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; +# +# blur-kern = '' +# blur-kern = "3x3box"; + +blur: { + # requires: https://github.com/ibhagwan/picom + method = "kawase"; + #method = "kernel"; + strength = 7; + # deviation = 1.0; + # kernel = "11x11gaussian"; + background = false; + background-frame = false; + background-fixed = false; + kern = "3x3box"; +} + +# Exclude conditions for background blur. +blur-background-exclude = [ + #"window_type = 'dock'", + #"window_type = 'desktop'", + #"class_g = 'URxvt'", + # + # prevents picom from blurring the background + # when taking selection screenshot with `main` + # https://github.com/naelstrof/maim/issues/130 + "class_g = 'slop'", + "_GTK_FRAME_EXTENTS@:c" +]; + + +################################# +# General Settings # +################################# + +# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers. +# daemon = false + +# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`. +# `xrender` is the default one. +# +experimental-backends = true; +backend = "glx"; +#backend = "xrender"; + + +# Enable/disable VSync. +# vsync = false +vsync = true + +# Enable remote control via D-Bus. See the *D-BUS API* section below for more details. +# dbus = false + +# Try to detect WM windows (a non-override-redirect window with no +# child that has 'WM_STATE') and mark them as active. +# +# mark-wmwin-focused = false +mark-wmwin-focused = true; + +# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused. +# mark-ovredir-focused = false +mark-ovredir-focused = true; + +# Try to detect windows with rounded corners and don't consider them +# shaped windows. The accuracy is not very high, unfortunately. +# +# detect-rounded-corners = false +detect-rounded-corners = true; + +# Detect '_NET_WM_OPACITY' on client windows, useful for window managers +# not passing '_NET_WM_OPACITY' of client windows to frame windows. +# +# detect-client-opacity = false +detect-client-opacity = true; + +# Specify refresh rate of the screen. If not specified or 0, picom will +# try detecting this with X RandR extension. +# +# refresh-rate = 60 +refresh-rate = 0 + +# Limit picom to repaint at most once every 1 / 'refresh_rate' second to +# boost performance. This should not be used with +# vsync drm/opengl/opengl-oml +# as they essentially does sw-opti's job already, +# unless you wish to specify a lower refresh rate than the actual value. +# +# sw-opti = + +# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window, +# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy, +# provided that the WM supports it. +# +# use-ewmh-active-win = false + +# Unredirect all windows if a full-screen opaque window is detected, +# to maximize performance for full-screen windows. Known to cause flickering +# when redirecting/unredirecting windows. paint-on-overlay may make the flickering less obvious. +# +# unredir-if-possible = false + +# Delay before unredirecting the window, in milliseconds. Defaults to 0. +# unredir-if-possible-delay = 0 + +# Conditions of windows that shouldn't be considered full-screen for unredirecting screen. +# unredir-if-possible-exclude = [] + +# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows +# in the same group focused at the same time. +# +# detect-transient = false +detect-transient = true + +# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same +# group focused at the same time. 'WM_TRANSIENT_FOR' has higher priority if +# detect-transient is enabled, too. +# +# detect-client-leader = false +detect-client-leader = true + +# Resize damaged region by a specific number of pixels. +# A positive value enlarges it while a negative one shrinks it. +# If the value is positive, those additional pixels will not be actually painted +# to screen, only used in blur calculation, and such. (Due to technical limitations, +# with use-damage, those pixels will still be incorrectly painted to screen.) +# Primarily used to fix the line corruption issues of blur, +# in which case you should use the blur radius value here +# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`, +# with a 5x5 one you use `--resize-damage 2`, and so on). +# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly. +# +# resize-damage = 1 + +# Specify a list of conditions of windows that should be painted with inverted color. +# Resource-hogging, and is not well tested. +# +# invert-color-include = [] + +# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer. +# Might cause incorrect opacity when rendering transparent content (but never +# practically happened) and may not work with blur-background. +# My tests show a 15% performance boost. Recommended. +# +# glx-no-stencil = false + +# GLX backend: Avoid rebinding pixmap on window damage. +# Probably could improve performance on rapid window content changes, +# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.). +# Recommended if it works. +# +# glx-no-rebind-pixmap = false + +# Disable the use of damage information. +# This cause the whole screen to be redrawn everytime, instead of the part of the screen +# has actually changed. Potentially degrades the performance, but might fix some artifacts. +# The opposing option is use-damage +# +# no-use-damage = false +#use-damage = true (Causing Weird Black semi opaque rectangles when terminal is opened) +#Changing use-damage to false fixes the problem +use-damage = false + +# Use X Sync fence to sync clients' draw calls, to make sure all draw +# calls are finished before picom starts drawing. Needed on nvidia-drivers +# with GLX backend for some users. +# +# xrender-sync-fence = false + +# GLX backend: Use specified GLSL fragment shader for rendering window contents. +# See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl` +# in the source tree for examples. +# +# glx-fshader-win = '' + +# Force all windows to be painted with blending. Useful if you +# have a glx-fshader-win that could turn opaque pixels transparent. +# +# force-win-blend = false + +# Do not use EWMH to detect fullscreen windows. +# Reverts to checking if a window is fullscreen based only on its size and coordinates. +# +# no-ewmh-fullscreen = false + +# Dimming bright windows so their brightness doesn't exceed this set value. +# Brightness of a window is estimated by averaging all pixels in the window, +# so this could comes with a performance hit. +# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0) +# +# max-brightness = 1.0 + +# Make transparent windows clip other windows like non-transparent windows do, +# instead of blending on top of them. +# +# transparent-clipping = false + +# Set the log level. Possible values are: +# "trace", "debug", "info", "warn", "error" +# in increasing level of importance. Case doesn't matter. +# If using the "TRACE" log level, it's better to log into a file +# using *--log-file*, since it can generate a huge stream of logs. +# +# log-level = "debug" +log-level = "info"; + +# Set the log file. +# If *--log-file* is never specified, logs will be written to stderr. +# Otherwise, logs will to written to the given file, though some of the early +# logs might still be written to the stderr. +# When setting this option from the config file, it is recommended to use an absolute path. +# +# log-file = '/path/to/your/log/file' + +# Show all X errors (for debugging) +# show-all-xerrors = false + +# Write process ID to a file. +# write-pid-path = '/path/to/your/log/file' + +# Window type settings +# +# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard: +# "unknown", "desktop", "dock", "toolbar", "menu", "utility", +# "splash", "dialog", "normal", "dropdown_menu", "popup_menu", +# "tooltip", "notification", "combo", and "dnd". +# +# Following per window-type options are available: :: +# +# fade, shadow::: +# Controls window-type-specific shadow and fade settings. +# +# opacity::: +# Controls default opacity of the window type. +# +# focus::: +# Controls whether the window of this type is to be always considered focused. +# (By default, all window types except "normal" and "dialog" has this on.) +# +# full-shadow::: +# Controls whether shadow is drawn under the parts of the window that you +# normally won't be able to see. Useful when the window has parts of it +# transparent, and you want shadows in those areas. +# +# redir-ignore::: +# Controls whether this type of windows should cause screen to become +# redirected again after been unredirected. If you have unredir-if-possible +# set, and doesn't want certain window to cause unnecessary screen redirection, +# you can set this to `true`. +# +wintypes: +{ + normal = { fade = false; shadow = false; } + tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; }; + dock = { shadow = false; } + dnd = { shadow = false; } + popup_menu = { opacity = 0.8; } + dropdown_menu = { opacity = 0.8; } +}; diff --git a/stow/picom/.config/picom/picom.upstream.conf b/stow/picom/.config/picom/picom.upstream.conf new file mode 100644 index 0000000..19c0d1b --- /dev/null +++ b/stow/picom/.config/picom/picom.upstream.conf @@ -0,0 +1,235 @@ +# Thank you code_nomad: http://9m.no/๊ชฏ้ตž +# and Arch Wiki contributors: https://wiki.archlinux.org/index.php/Compton + +################################# +# +# Backend +# +################################# + +# Backend to use: "xrender" or "glx". +# GLX backend is typically much faster but depends on a sane driver. +backend = "glx"; + +################################# +# +# GLX backend +# +################################# + +glx-no-stencil = true; + +# GLX backend: Copy unmodified regions from front buffer instead of redrawing them all. +# My tests with nvidia-drivers show a 10% decrease in performance when the whole screen is modified, +# but a 20% increase when only 1/4 is. +# My tests on nouveau show terrible slowdown. +glx-copy-from-front = false; + +# GLX backend: Use MESA_copy_sub_buffer to do partial screen update. +# My tests on nouveau shows a 200% performance boost when only 1/4 of the screen is updated. +# May break VSync and is not available on some drivers. +# Overrides --glx-copy-from-front. +# glx-use-copysubbuffermesa = true; + +# GLX backend: Avoid rebinding pixmap on window damage. +# Probably could improve performance on rapid window content changes, but is known to break things on some drivers (LLVMpipe). +# Recommended if it works. +# glx-no-rebind-pixmap = true; + +# GLX backend: GLX buffer swap method we assume. +# Could be undefined (0), copy (1), exchange (2), 3-6, or buffer-age (-1). +# undefined is the slowest and the safest, and the default value. +# copy is fastest, but may fail on some drivers, +# 2-6 are gradually slower but safer (6 is still faster than 0). +# Usually, double buffer means 2, triple buffer means 3. +# buffer-age means auto-detect using GLX_EXT_buffer_age, supported by some drivers. +# Useless with --glx-use-copysubbuffermesa. +# Partially breaks --resize-damage. +# Defaults to undefined. +#glx-swap-method = "undefined"; + +################################# +# +# Shadows +# +################################# + +# Enabled client-side shadows on windows. +shadow = true; +# The blur radius for shadows. (default 12) +shadow-radius = 10; +# The left offset for shadows. (default -15) +shadow-offset-x = 0.25; +# The top offset for shadows. (default -15) +shadow-offset-y = 0.25; +# The translucency for shadows. (default .75) +shadow-opacity = 0.25; + +# Set if you want different colour shadows +# shadow-red = 0.0; +# shadow-green = 0.0; +# shadow-blue = 0.0; + +# The shadow exclude options are helpful if you have shadows enabled. Due to the way picom draws its shadows, certain applications will have visual glitches +# (most applications are fine, only apps that do weird things with xshapes or argb are affected). +# This list includes all the affected apps I found in my testing. The "! name~=''" part excludes shadows on any "Unknown" windows, this prevents a visual glitch with the XFWM alt tab switcher. +shadow-exclude = [ + "! name~=''", + "name *= 'dunst'", + "name *= 'i3bar'", + "name = 'Notification'", + "name = 'Plank'", + "name = 'Docky'", + "name = 'Kupfer'", + "name = 'xfce4-notifyd'", + "name *= 'VLC'", + "name *= 'picom'", + "name *= 'Chromium'", + "name *= 'Chrome'", + "class_g = 'Firefox' && argb", + "class_g = 'Conky'", + "class_g = 'Kupfer'", + "class_g = 'Synapse'", + "class_g ?= 'Notify-osd'", + "class_g ?= 'Cairo-dock'", + "class_g ?= 'Xfce4-notifyd'", + "class_g ?= 'Xfce4-power-manager'", + "_GTK_FRAME_EXTENTS@:c", + "_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'" +]; +# Avoid drawing shadow on all shaped windows (see also: --detect-rounded-corners) +shadow-ignore-shaped = false; + +################################# +# +# Opacity +# +################################# + +#inactive-opacity = 0.8; +active-opacity = 1; +frame-opacity = 1; +inactive-opacity-override = false; + +# Dim inactive windows. (0.0 - 1.0) +inactive-dim = 0.1; +# Do not let dimness adjust based on window opacity. +# inactive-dim-fixed = true; +# Blur background of transparent windows. Bad performance with X Render backend. GLX backend is preferred. +# blur-background = true; +# Blur background of opaque windows with transparent frames as well. +# blur-background-frame = true; +# Do not let blur radius adjust based on window opacity. +blur-background-fixed = false; +blur-background-exclude = [ + "window_type = 'dock'", + "window_type = 'desktop'" +]; + +opacity-rule = [ + "70:class_g = 'URxvt' && !focused", + "95:class_g = 'URxvt' && focused", + "80:class_g = 'dmenu'" + #"80:_NET_WM_NAME@:s = 'rofi'" +]; + +################################# +# +# Fading +# +################################# + +# Fade windows during opacity changes. +fading = true; +# The time between steps in a fade in milliseconds. (default 10). +fade-delta = 2.8; +# Opacity change between steps while fading in. (default 0.028). +fade-in-step = 0.03; +# Opacity change between steps while fading out. (default 0.03). +fade-out-step = 0.03; +# Fade windows in/out when opening/closing +no-fading-openclose = false; + +# Specify a list of conditions of windows that should not be faded. +fade-exclude = [ ]; + +################################# +# +# Other +# +################################# + +# Try to detect WM windows and mark them as active. +mark-wmwin-focused = true; +# Mark all non-WM but override-redirect windows active (e.g. menus). +mark-ovredir-focused = true; +# Use EWMH _NET_WM_ACTIVE_WINDOW to determine which window is focused instead of using FocusIn/Out events. +# Usually more reliable but depends on a EWMH-compliant WM. +use-ewmh-active-win = true; +# Detect rounded corners and treat them as rectangular when --shadow-ignore-shaped is on. +detect-rounded-corners = true; + +# Detect _NET_WM_OPACITY on client windows, useful for window managers not passing _NET_WM_OPACITY of client windows to frame windows. +# This prevents opacity being ignored for some apps. +# For example without this enabled my xfce4-notifyd is 100% opacity no matter what. +detect-client-opacity = true; + +# Specify refresh rate of the screen. +# If not specified or 0, picom will try detecting this with X RandR extension. +refresh-rate = 0; + +# Vertical synchronization: match the refresh rate of the monitor +vsync = true; + +# Enable DBE painting mode, intended to use with VSync to (hopefully) eliminate tearing. +# Reported to have no effect, though. +dbe = false; + +# Limit picom to repaint at most once every 1 / refresh_rate second to boost performance. +# This should not be used with --vsync drm/opengl/opengl-oml as they essentially does --sw-opti's job already, +# unless you wish to specify a lower refresh rate than the actual value. +#sw-opti = true; + +# Unredirect all windows if a full-screen opaque window is detected, to maximize performance for full-screen windows, like games. +# Known to cause flickering when redirecting/unredirecting windows. +unredir-if-possible = false; + +# Specify a list of conditions of windows that should always be considered focused. +focus-exclude = [ "_NET_WM_NAME@:s = 'rofi'" ]; + +# Use WM_TRANSIENT_FOR to group windows, and consider windows in the same group focused at the same time. +detect-transient = false; +# Use WM_CLIENT_LEADER to group windows, and consider windows in the same group focused at the same time. +# WM_TRANSIENT_FOR has higher priority if --detect-transient is enabled, too. +detect-client-leader = false; + +################################# +# +# Window type settings +# +################################# + +wintypes: +{ + tooltip = + { + # fade: Fade the particular type of windows. + fade = true; + # shadow: Give those windows shadow + shadow = false; + # opacity: Default opacity for the type of windows. + opacity = 0.85; + # focus: Whether to always consider windows of this type focused. + focus = true; + }; +}; + +###################### +# +# XSync +# See: https://github.com/yshui/picom/commit/b18d46bcbdc35a3b5620d817dd46fbc76485c20d +# +###################### + +# Use X Sync fence to sync clients' draw calls. Needed on nvidia-drivers with GLX backend for some users. +xrender-sync-fence = true; diff --git a/stow/picom/dot-config/picom/picom.conf b/stow/picom/dot-config/picom/picom.conf deleted file mode 100644 index 2f4dfc7..0000000 --- a/stow/picom/dot-config/picom/picom.conf +++ /dev/null @@ -1,502 +0,0 @@ -################################# -# Animations # -################################# -# requires https://github.com/jonaburg/picom -# (These are also the default values) -transition-length = 200 -transition-pow-x = 0.5 -transition-pow-y = 0.5 -transition-pow-w = 0.5 -transition-pow-h = 0.5 -size-transition = true - - -################################# -# Corners # -################################# -# requires: https://github.com/sdhand/compton or https://github.com/jonaburg/picom -corner-radius = 0; -rounded-corners-exclude = [ - #"window_type = 'normal'", - "class_g = 'awesome'", - #"class_g = 'URxvt'", - "class_g = 'i3bar'", - "class_g = 'dwm'", - "class_g = 'XTerm'", - "class_g = 'kitty'", - "class_g = 'Alacritty'", - "class_g = 'Polybar'", - "class_g = 'code-oss'", - #"class_g = 'TelegramDesktop'", - "class_g = 'firefox'", - "class_g = 'Thunderbird'" -]; -round-borders = 0; -round-borders-exclude = [ - #"class_g = 'TelegramDesktop'", -]; - -################################# -# Shadows # -################################# - - -# Enabled client-side shadows on windows. Note desktop windows -# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow, -# unless explicitly requested using the wintypes option. -# -# shadow = false -shadow = true; - -# The blur radius for shadows, in pixels. (defaults to 12) -# shadow-radius = 12 -shadow-radius = 12; - -# The opacity of shadows. (0.0 - 1.0, defaults to 0.75) -# shadow-opacity = .75 - -# The left offset for shadows, in pixels. (defaults to -15) -# shadow-offset-x = -15 -shadow-offset-x = -7; - -# The top offset for shadows, in pixels. (defaults to -15) -# shadow-offset-y = -15 -shadow-offset-y = -7; - -# Avoid drawing shadows on dock/panel windows. This option is deprecated, -# you should use the *wintypes* option in your config file instead. -# -# no-dock-shadow = false - -# Don't draw shadows on drag-and-drop windows. This option is deprecated, -# you should use the *wintypes* option in your config file instead. -# -# no-dnd-shadow = false - -# Red color value of shadow (0.0 - 1.0, defaults to 0). -# shadow-red = 0 - -# Green color value of shadow (0.0 - 1.0, defaults to 0). -# shadow-green = 0 - -# Blue color value of shadow (0.0 - 1.0, defaults to 0). -# shadow-blue = 0 - -# Do not paint shadows on shaped windows. Note shaped windows -# here means windows setting its shape through X Shape extension. -# Those using ARGB background is beyond our control. -# Deprecated, use -# shadow-exclude = 'bounding_shaped' -# or -# shadow-exclude = 'bounding_shaped && !rounded_corners' -# instead. -# -# shadow-ignore-shaped = '' - -# Specify a list of conditions of windows that should have no shadow. -# -# examples: -# shadow-exclude = "n:e:Notification"; -# -# shadow-exclude = [] -shadow-exclude = [ - "name = 'Notification'", - "class_g = 'Conky'", - "class_g ?= 'Notify-osd'", - "class_g = 'Cairo-clock'", - "class_g = 'slop'", - "class_g = 'Polybar'", - "_GTK_FRAME_EXTENTS@:c" -]; - -# Specify a X geometry that describes the region in which shadow should not -# be painted in, such as a dock window region. Use -# shadow-exclude-reg = "x10+0+0" -# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on. -# -# shadow-exclude-reg = "" - -# Crop shadow of a window fully on a particular Xinerama screen to the screen. -# xinerama-shadow-crop = false - - -################################# -# Fading # -################################# - - -# Fade windows in/out when opening/closing and when opacity changes, -# unless no-fading-openclose is used. -# fading = false -fading = true; - -# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028) -# fade-in-step = 0.028 -fade-in-step = 0.03; - -# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03) -# fade-out-step = 0.03 -fade-out-step = 0.03; - -# The time between steps in fade step, in milliseconds. (> 0, defaults to 10) -# fade-delta = 10 - -# Specify a list of conditions of windows that should not be faded. -# don't need this, we disable fading for all normal windows with wintypes: {} -fade-exclude = [ - "class_g = 'slop'" # maim -] - -# Do not fade on window open/close. -# no-fading-openclose = false - -# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc. -# no-fading-destroyed-argb = false - - -################################# -# Transparency / Opacity # -################################# - -# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0) -# inactive-opacity = 1 -inactive-opacity = 0.8; - -# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default) -# frame-opacity = 1.0 -frame-opacity = 0.7; - -# Default opacity for dropdown menus and popup menus. (0.0 - 1.0, defaults to 1.0) -# menu-opacity = 1.0 -# menu-opacity is depreciated use dropdown-menu and popup-menu instead. - -#If using these 2 below change their values in line 510 & 511 aswell -popup_menu = { opacity = 0.8; } -dropdown_menu = { opacity = 0.8; } - - -# Let inactive opacity set by -i override the '_NET_WM_OPACITY' values of windows. -# inactive-opacity-override = true -inactive-opacity-override = false; - -# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0) -active-opacity = 1.0; - -# Dim inactive windows. (0.0 - 1.0, defaults to 0.0) -# inactive-dim = 0.0 - -# Specify a list of conditions of windows that should always be considered focused. -# focus-exclude = [] -focus-exclude = [ - "class_g = 'Cairo-clock'", - "class_g = 'Bar'", # lemonbar - "class_g = 'slop'" # maim -]; - -# Use fixed inactive dim value, instead of adjusting according to window opacity. -# inactive-dim-fixed = 1.0 - -# Specify a list of opacity rules, in the format `PERCENT:PATTERN`, -# like `50:name *= "Firefox"`. picom-trans is recommended over this. -# Note we don't make any guarantee about possible conflicts with other -# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows. -# example: -# opacity-rule = [ "80:class_g = 'URxvt'" ]; -# -# opacity-rule = [] -opacity-rule = [ - "90:class_g = 'URxvt' && !focused", - "80:class_g = 'dmenu'" -]; - - -################################# -# Background-Blurring # -################################# - - -# Parameters for background blurring, see the *BLUR* section for more information. -# blur-method = -# blur-size = 12 -# -# blur-deviation = false - -# Blur background of semi-transparent / ARGB windows. -# Bad in performance, with driver-dependent behavior. -# The name of the switch may change without prior notifications. -# -# blur-background = true; - -# Blur background of windows when the window frame is not opaque. -# Implies: -# blur-background -# Bad in performance, with driver-dependent behavior. The name may change. -# -# blur-background-frame = false; - - -# Use fixed blur strength rather than adjusting according to window opacity. -# blur-background-fixed = false; - - -# Specify the blur convolution kernel, with the following format: -# example: -# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; -# -# blur-kern = '' -# blur-kern = "3x3box"; - -blur: { - # requires: https://github.com/ibhagwan/picom - method = "kawase"; - #method = "kernel"; - strength = 3; - # deviation = 1.0; - # kernel = "11x11gaussian"; - background = false; - background-frame = false; - background-fixed = false; - kern = "3x3box"; -} - -# Exclude conditions for background blur. -blur-background-exclude = [ - #"window_type = 'dock'", - #"window_type = 'desktop'", - #"class_g = 'URxvt'", - # - # prevents picom from blurring the background - # when taking selection screenshot with `main` - # https://github.com/naelstrof/maim/issues/130 - "class_g = 'slop'", - "_GTK_FRAME_EXTENTS@:c" -]; - - -################################# -# General Settings # -################################# - -# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers. -# daemon = false - -# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`. -# `xrender` is the default one. -# -experimental-backends = true; -backend = "glx"; -#backend = "xrender"; - - -# Enable/disable VSync. -# vsync = false -vsync = true - -# Enable remote control via D-Bus. See the *D-BUS API* section below for more details. -# dbus = false - -# Try to detect WM windows (a non-override-redirect window with no -# child that has 'WM_STATE') and mark them as active. -# -# mark-wmwin-focused = false -mark-wmwin-focused = true; - -# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused. -# mark-ovredir-focused = false -mark-ovredir-focused = true; - -# Try to detect windows with rounded corners and don't consider them -# shaped windows. The accuracy is not very high, unfortunately. -# -# detect-rounded-corners = false -detect-rounded-corners = true; - -# Detect '_NET_WM_OPACITY' on client windows, useful for window managers -# not passing '_NET_WM_OPACITY' of client windows to frame windows. -# -# detect-client-opacity = false -detect-client-opacity = true; - -# Specify refresh rate of the screen. If not specified or 0, picom will -# try detecting this with X RandR extension. -# -# refresh-rate = 60 -refresh-rate = 0 - -# Limit picom to repaint at most once every 1 / 'refresh_rate' second to -# boost performance. This should not be used with -# vsync drm/opengl/opengl-oml -# as they essentially does sw-opti's job already, -# unless you wish to specify a lower refresh rate than the actual value. -# -# sw-opti = - -# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window, -# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy, -# provided that the WM supports it. -# -# use-ewmh-active-win = false - -# Unredirect all windows if a full-screen opaque window is detected, -# to maximize performance for full-screen windows. Known to cause flickering -# when redirecting/unredirecting windows. paint-on-overlay may make the flickering less obvious. -# -# unredir-if-possible = false - -# Delay before unredirecting the window, in milliseconds. Defaults to 0. -# unredir-if-possible-delay = 0 - -# Conditions of windows that shouldn't be considered full-screen for unredirecting screen. -# unredir-if-possible-exclude = [] - -# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows -# in the same group focused at the same time. -# -# detect-transient = false -detect-transient = true - -# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same -# group focused at the same time. 'WM_TRANSIENT_FOR' has higher priority if -# detect-transient is enabled, too. -# -# detect-client-leader = false -detect-client-leader = true - -# Resize damaged region by a specific number of pixels. -# A positive value enlarges it while a negative one shrinks it. -# If the value is positive, those additional pixels will not be actually painted -# to screen, only used in blur calculation, and such. (Due to technical limitations, -# with use-damage, those pixels will still be incorrectly painted to screen.) -# Primarily used to fix the line corruption issues of blur, -# in which case you should use the blur radius value here -# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`, -# with a 5x5 one you use `--resize-damage 2`, and so on). -# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly. -# -# resize-damage = 1 - -# Specify a list of conditions of windows that should be painted with inverted color. -# Resource-hogging, and is not well tested. -# -# invert-color-include = [] - -# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer. -# Might cause incorrect opacity when rendering transparent content (but never -# practically happened) and may not work with blur-background. -# My tests show a 15% performance boost. Recommended. -# -# glx-no-stencil = false - -# GLX backend: Avoid rebinding pixmap on window damage. -# Probably could improve performance on rapid window content changes, -# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.). -# Recommended if it works. -# -# glx-no-rebind-pixmap = false - -# Disable the use of damage information. -# This cause the whole screen to be redrawn everytime, instead of the part of the screen -# has actually changed. Potentially degrades the performance, but might fix some artifacts. -# The opposing option is use-damage -# -# no-use-damage = false -#use-damage = true (Causing Weird Black semi opaque rectangles when terminal is opened) -#Changing use-damage to false fixes the problem -use-damage = false - -# Use X Sync fence to sync clients' draw calls, to make sure all draw -# calls are finished before picom starts drawing. Needed on nvidia-drivers -# with GLX backend for some users. -# -# xrender-sync-fence = false - -# GLX backend: Use specified GLSL fragment shader for rendering window contents. -# See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl` -# in the source tree for examples. -# -# glx-fshader-win = '' - -# Force all windows to be painted with blending. Useful if you -# have a glx-fshader-win that could turn opaque pixels transparent. -# -# force-win-blend = false - -# Do not use EWMH to detect fullscreen windows. -# Reverts to checking if a window is fullscreen based only on its size and coordinates. -# -# no-ewmh-fullscreen = false - -# Dimming bright windows so their brightness doesn't exceed this set value. -# Brightness of a window is estimated by averaging all pixels in the window, -# so this could comes with a performance hit. -# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0) -# -# max-brightness = 1.0 - -# Make transparent windows clip other windows like non-transparent windows do, -# instead of blending on top of them. -# -# transparent-clipping = false - -# Set the log level. Possible values are: -# "trace", "debug", "info", "warn", "error" -# in increasing level of importance. Case doesn't matter. -# If using the "TRACE" log level, it's better to log into a file -# using *--log-file*, since it can generate a huge stream of logs. -# -# log-level = "debug" -log-level = "info"; - -# Set the log file. -# If *--log-file* is never specified, logs will be written to stderr. -# Otherwise, logs will to written to the given file, though some of the early -# logs might still be written to the stderr. -# When setting this option from the config file, it is recommended to use an absolute path. -# -# log-file = '/path/to/your/log/file' - -# Show all X errors (for debugging) -# show-all-xerrors = false - -# Write process ID to a file. -# write-pid-path = '/path/to/your/log/file' - -# Window type settings -# -# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard: -# "unknown", "desktop", "dock", "toolbar", "menu", "utility", -# "splash", "dialog", "normal", "dropdown_menu", "popup_menu", -# "tooltip", "notification", "combo", and "dnd". -# -# Following per window-type options are available: :: -# -# fade, shadow::: -# Controls window-type-specific shadow and fade settings. -# -# opacity::: -# Controls default opacity of the window type. -# -# focus::: -# Controls whether the window of this type is to be always considered focused. -# (By default, all window types except "normal" and "dialog" has this on.) -# -# full-shadow::: -# Controls whether shadow is drawn under the parts of the window that you -# normally won't be able to see. Useful when the window has parts of it -# transparent, and you want shadows in those areas. -# -# redir-ignore::: -# Controls whether this type of windows should cause screen to become -# redirected again after been unredirected. If you have unredir-if-possible -# set, and doesn't want certain window to cause unnecessary screen redirection, -# you can set this to `true`. -# -wintypes: -{ - normal = { fade = false; shadow = false; } - tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; }; - dock = { shadow = false; } - dnd = { shadow = false; } - popup_menu = { opacity = 0.8; } - dropdown_menu = { opacity = 0.8; } -}; diff --git a/stow/picom/dot-config/picom/picom.jonaburg.sample.conf b/stow/picom/dot-config/picom/picom.jonaburg.sample.conf deleted file mode 100644 index ee3fbbe..0000000 --- a/stow/picom/dot-config/picom/picom.jonaburg.sample.conf +++ /dev/null @@ -1,512 +0,0 @@ -################################# -# Animations # -################################# -# requires https://github.com/jonaburg/picom -# (These are also the default values) -transition-length = 300 -transition-pow-x = 0.1 -transition-pow-y = 0.1 -transition-pow-w = 0.1 -transition-pow-h = 0.1 -size-transition = true - - -################################# -# Corners # -################################# -# requires: https://github.com/sdhand/compton or https://github.com/jonaburg/picom -corner-radius = 10.0; -rounded-corners-exclude = [ - #"window_type = 'normal'", - "class_g = 'awesome'", - "class_g = 'URxvt'", - "class_g = 'XTerm'", - "class_g = 'kitty'", - "class_g = 'Alacritty'", - "class_g = 'Polybar'", - "class_g = 'code-oss'", - #"class_g = 'TelegramDesktop'", - "class_g = 'firefox'", - "class_g = 'Thunderbird'" -]; -round-borders = 1; -round-borders-exclude = [ - #"class_g = 'TelegramDesktop'", -]; - -################################# -# Shadows # -################################# - - -# Enabled client-side shadows on windows. Note desktop windows -# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow, -# unless explicitly requested using the wintypes option. -# -# shadow = false -shadow = false; - -# The blur radius for shadows, in pixels. (defaults to 12) -# shadow-radius = 12 -shadow-radius = 7; - -# The opacity of shadows. (0.0 - 1.0, defaults to 0.75) -# shadow-opacity = .75 - -# The left offset for shadows, in pixels. (defaults to -15) -# shadow-offset-x = -15 -shadow-offset-x = -7; - -# The top offset for shadows, in pixels. (defaults to -15) -# shadow-offset-y = -15 -shadow-offset-y = -7; - -# Avoid drawing shadows on dock/panel windows. This option is deprecated, -# you should use the *wintypes* option in your config file instead. -# -# no-dock-shadow = false - -# Don't draw shadows on drag-and-drop windows. This option is deprecated, -# you should use the *wintypes* option in your config file instead. -# -# no-dnd-shadow = false - -# Red color value of shadow (0.0 - 1.0, defaults to 0). -# shadow-red = 0 - -# Green color value of shadow (0.0 - 1.0, defaults to 0). -# shadow-green = 0 - -# Blue color value of shadow (0.0 - 1.0, defaults to 0). -# shadow-blue = 0 - -# Do not paint shadows on shaped windows. Note shaped windows -# here means windows setting its shape through X Shape extension. -# Those using ARGB background is beyond our control. -# Deprecated, use -# shadow-exclude = 'bounding_shaped' -# or -# shadow-exclude = 'bounding_shaped && !rounded_corners' -# instead. -# -# shadow-ignore-shaped = '' - -# Specify a list of conditions of windows that should have no shadow. -# -# examples: -# shadow-exclude = "n:e:Notification"; -# -# shadow-exclude = [] -shadow-exclude = [ - "name = 'Notification'", - "class_g = 'Conky'", - "class_g ?= 'Notify-osd'", - "class_g = 'Cairo-clock'", - "class_g = 'slop'", - "class_g = 'Polybar'", - "_GTK_FRAME_EXTENTS@:c" -]; - -# Specify a X geometry that describes the region in which shadow should not -# be painted in, such as a dock window region. Use -# shadow-exclude-reg = "x10+0+0" -# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on. -# -# shadow-exclude-reg = "" - -# Crop shadow of a window fully on a particular Xinerama screen to the screen. -# xinerama-shadow-crop = false - - -################################# -# Fading # -################################# - - -# Fade windows in/out when opening/closing and when opacity changes, -# unless no-fading-openclose is used. -# fading = false -fading = true; - -# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028) -# fade-in-step = 0.028 -fade-in-step = 0.03; - -# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03) -# fade-out-step = 0.03 -fade-out-step = 0.03; - -# The time between steps in fade step, in milliseconds. (> 0, defaults to 10) -# fade-delta = 10 - -# Specify a list of conditions of windows that should not be faded. -# don't need this, we disable fading for all normal windows with wintypes: {} -fade-exclude = [ - "class_g = 'slop'" # maim -] - -# Do not fade on window open/close. -# no-fading-openclose = false - -# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc. -# no-fading-destroyed-argb = false - - -################################# -# Transparency / Opacity # -################################# - - -# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0) -# inactive-opacity = 1 -inactive-opacity = 0.8; - -# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default) -# frame-opacity = 1.0 -frame-opacity = 0.7; - -# Default opacity for dropdown menus and popup menus. (0.0 - 1.0, defaults to 1.0) -# menu-opacity = 1.0 -# menu-opacity is depreciated use dropdown-menu and popup-menu instead. - -#If using these 2 below change their values in line 510 & 511 aswell -popup_menu = { opacity = 0.8; } -dropdown_menu = { opacity = 0.8; } - - -# Let inactive opacity set by -i override the '_NET_WM_OPACITY' values of windows. -# inactive-opacity-override = true -inactive-opacity-override = false; - -# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0) -active-opacity = 1.0; - -# Dim inactive windows. (0.0 - 1.0, defaults to 0.0) -# inactive-dim = 0.0 - -# Specify a list of conditions of windows that should always be considered focused. -# focus-exclude = [] -focus-exclude = [ - "class_g = 'Cairo-clock'", - "class_g = 'Bar'", # lemonbar - "class_g = 'slop'" # maim -]; - -# Use fixed inactive dim value, instead of adjusting according to window opacity. -# inactive-dim-fixed = 1.0 - -# Specify a list of opacity rules, in the format `PERCENT:PATTERN`, -# like `50:name *= "Firefox"`. picom-trans is recommended over this. -# Note we don't make any guarantee about possible conflicts with other -# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows. -# example: -# opacity-rule = [ "80:class_g = 'URxvt'" ]; -# -# opacity-rule = [] -opacity-rule = [ - "80:class_g = 'Bar'", # lemonbar - "100:class_g = 'slop'", # maim - "100:class_g = 'XTerm'", - "100:class_g = 'URxvt'", - "100:class_g = 'kitty'", - "100:class_g = 'Alacritty'", - "80:class_g = 'Polybar'", - "100:class_g = 'code-oss'", - "100:class_g = 'Meld'", - "70:class_g = 'TelegramDesktop'", - "90:class_g = 'Joplin'", - "100:class_g = 'firefox'", - "100:class_g = 'Thunderbird'" -]; - - -################################# -# Background-Blurring # -################################# - - -# Parameters for background blurring, see the *BLUR* section for more information. -# blur-method = -# blur-size = 12 -# -# blur-deviation = false - -# Blur background of semi-transparent / ARGB windows. -# Bad in performance, with driver-dependent behavior. -# The name of the switch may change without prior notifications. -# -# blur-background = true; - -# Blur background of windows when the window frame is not opaque. -# Implies: -# blur-background -# Bad in performance, with driver-dependent behavior. The name may change. -# -# blur-background-frame = false; - - -# Use fixed blur strength rather than adjusting according to window opacity. -# blur-background-fixed = false; - - -# Specify the blur convolution kernel, with the following format: -# example: -# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; -# -# blur-kern = '' -# blur-kern = "3x3box"; - -blur: { - # requires: https://github.com/ibhagwan/picom - method = "kawase"; - #method = "kernel"; - strength = 7; - # deviation = 1.0; - # kernel = "11x11gaussian"; - background = false; - background-frame = false; - background-fixed = false; - kern = "3x3box"; -} - -# Exclude conditions for background blur. -blur-background-exclude = [ - #"window_type = 'dock'", - #"window_type = 'desktop'", - #"class_g = 'URxvt'", - # - # prevents picom from blurring the background - # when taking selection screenshot with `main` - # https://github.com/naelstrof/maim/issues/130 - "class_g = 'slop'", - "_GTK_FRAME_EXTENTS@:c" -]; - - -################################# -# General Settings # -################################# - -# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers. -# daemon = false - -# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`. -# `xrender` is the default one. -# -experimental-backends = true; -backend = "glx"; -#backend = "xrender"; - - -# Enable/disable VSync. -# vsync = false -vsync = true - -# Enable remote control via D-Bus. See the *D-BUS API* section below for more details. -# dbus = false - -# Try to detect WM windows (a non-override-redirect window with no -# child that has 'WM_STATE') and mark them as active. -# -# mark-wmwin-focused = false -mark-wmwin-focused = true; - -# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused. -# mark-ovredir-focused = false -mark-ovredir-focused = true; - -# Try to detect windows with rounded corners and don't consider them -# shaped windows. The accuracy is not very high, unfortunately. -# -# detect-rounded-corners = false -detect-rounded-corners = true; - -# Detect '_NET_WM_OPACITY' on client windows, useful for window managers -# not passing '_NET_WM_OPACITY' of client windows to frame windows. -# -# detect-client-opacity = false -detect-client-opacity = true; - -# Specify refresh rate of the screen. If not specified or 0, picom will -# try detecting this with X RandR extension. -# -# refresh-rate = 60 -refresh-rate = 0 - -# Limit picom to repaint at most once every 1 / 'refresh_rate' second to -# boost performance. This should not be used with -# vsync drm/opengl/opengl-oml -# as they essentially does sw-opti's job already, -# unless you wish to specify a lower refresh rate than the actual value. -# -# sw-opti = - -# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window, -# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy, -# provided that the WM supports it. -# -# use-ewmh-active-win = false - -# Unredirect all windows if a full-screen opaque window is detected, -# to maximize performance for full-screen windows. Known to cause flickering -# when redirecting/unredirecting windows. paint-on-overlay may make the flickering less obvious. -# -# unredir-if-possible = false - -# Delay before unredirecting the window, in milliseconds. Defaults to 0. -# unredir-if-possible-delay = 0 - -# Conditions of windows that shouldn't be considered full-screen for unredirecting screen. -# unredir-if-possible-exclude = [] - -# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows -# in the same group focused at the same time. -# -# detect-transient = false -detect-transient = true - -# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same -# group focused at the same time. 'WM_TRANSIENT_FOR' has higher priority if -# detect-transient is enabled, too. -# -# detect-client-leader = false -detect-client-leader = true - -# Resize damaged region by a specific number of pixels. -# A positive value enlarges it while a negative one shrinks it. -# If the value is positive, those additional pixels will not be actually painted -# to screen, only used in blur calculation, and such. (Due to technical limitations, -# with use-damage, those pixels will still be incorrectly painted to screen.) -# Primarily used to fix the line corruption issues of blur, -# in which case you should use the blur radius value here -# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`, -# with a 5x5 one you use `--resize-damage 2`, and so on). -# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly. -# -# resize-damage = 1 - -# Specify a list of conditions of windows that should be painted with inverted color. -# Resource-hogging, and is not well tested. -# -# invert-color-include = [] - -# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer. -# Might cause incorrect opacity when rendering transparent content (but never -# practically happened) and may not work with blur-background. -# My tests show a 15% performance boost. Recommended. -# -# glx-no-stencil = false - -# GLX backend: Avoid rebinding pixmap on window damage. -# Probably could improve performance on rapid window content changes, -# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.). -# Recommended if it works. -# -# glx-no-rebind-pixmap = false - -# Disable the use of damage information. -# This cause the whole screen to be redrawn everytime, instead of the part of the screen -# has actually changed. Potentially degrades the performance, but might fix some artifacts. -# The opposing option is use-damage -# -# no-use-damage = false -#use-damage = true (Causing Weird Black semi opaque rectangles when terminal is opened) -#Changing use-damage to false fixes the problem -use-damage = false - -# Use X Sync fence to sync clients' draw calls, to make sure all draw -# calls are finished before picom starts drawing. Needed on nvidia-drivers -# with GLX backend for some users. -# -# xrender-sync-fence = false - -# GLX backend: Use specified GLSL fragment shader for rendering window contents. -# See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl` -# in the source tree for examples. -# -# glx-fshader-win = '' - -# Force all windows to be painted with blending. Useful if you -# have a glx-fshader-win that could turn opaque pixels transparent. -# -# force-win-blend = false - -# Do not use EWMH to detect fullscreen windows. -# Reverts to checking if a window is fullscreen based only on its size and coordinates. -# -# no-ewmh-fullscreen = false - -# Dimming bright windows so their brightness doesn't exceed this set value. -# Brightness of a window is estimated by averaging all pixels in the window, -# so this could comes with a performance hit. -# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0) -# -# max-brightness = 1.0 - -# Make transparent windows clip other windows like non-transparent windows do, -# instead of blending on top of them. -# -# transparent-clipping = false - -# Set the log level. Possible values are: -# "trace", "debug", "info", "warn", "error" -# in increasing level of importance. Case doesn't matter. -# If using the "TRACE" log level, it's better to log into a file -# using *--log-file*, since it can generate a huge stream of logs. -# -# log-level = "debug" -log-level = "info"; - -# Set the log file. -# If *--log-file* is never specified, logs will be written to stderr. -# Otherwise, logs will to written to the given file, though some of the early -# logs might still be written to the stderr. -# When setting this option from the config file, it is recommended to use an absolute path. -# -# log-file = '/path/to/your/log/file' - -# Show all X errors (for debugging) -# show-all-xerrors = false - -# Write process ID to a file. -# write-pid-path = '/path/to/your/log/file' - -# Window type settings -# -# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard: -# "unknown", "desktop", "dock", "toolbar", "menu", "utility", -# "splash", "dialog", "normal", "dropdown_menu", "popup_menu", -# "tooltip", "notification", "combo", and "dnd". -# -# Following per window-type options are available: :: -# -# fade, shadow::: -# Controls window-type-specific shadow and fade settings. -# -# opacity::: -# Controls default opacity of the window type. -# -# focus::: -# Controls whether the window of this type is to be always considered focused. -# (By default, all window types except "normal" and "dialog" has this on.) -# -# full-shadow::: -# Controls whether shadow is drawn under the parts of the window that you -# normally won't be able to see. Useful when the window has parts of it -# transparent, and you want shadows in those areas. -# -# redir-ignore::: -# Controls whether this type of windows should cause screen to become -# redirected again after been unredirected. If you have unredir-if-possible -# set, and doesn't want certain window to cause unnecessary screen redirection, -# you can set this to `true`. -# -wintypes: -{ - normal = { fade = false; shadow = false; } - tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; }; - dock = { shadow = false; } - dnd = { shadow = false; } - popup_menu = { opacity = 0.8; } - dropdown_menu = { opacity = 0.8; } -}; diff --git a/stow/picom/dot-config/picom/picom.upstream.conf b/stow/picom/dot-config/picom/picom.upstream.conf deleted file mode 100644 index 19c0d1b..0000000 --- a/stow/picom/dot-config/picom/picom.upstream.conf +++ /dev/null @@ -1,235 +0,0 @@ -# Thank you code_nomad: http://9m.no/๊ชฏ้ตž -# and Arch Wiki contributors: https://wiki.archlinux.org/index.php/Compton - -################################# -# -# Backend -# -################################# - -# Backend to use: "xrender" or "glx". -# GLX backend is typically much faster but depends on a sane driver. -backend = "glx"; - -################################# -# -# GLX backend -# -################################# - -glx-no-stencil = true; - -# GLX backend: Copy unmodified regions from front buffer instead of redrawing them all. -# My tests with nvidia-drivers show a 10% decrease in performance when the whole screen is modified, -# but a 20% increase when only 1/4 is. -# My tests on nouveau show terrible slowdown. -glx-copy-from-front = false; - -# GLX backend: Use MESA_copy_sub_buffer to do partial screen update. -# My tests on nouveau shows a 200% performance boost when only 1/4 of the screen is updated. -# May break VSync and is not available on some drivers. -# Overrides --glx-copy-from-front. -# glx-use-copysubbuffermesa = true; - -# GLX backend: Avoid rebinding pixmap on window damage. -# Probably could improve performance on rapid window content changes, but is known to break things on some drivers (LLVMpipe). -# Recommended if it works. -# glx-no-rebind-pixmap = true; - -# GLX backend: GLX buffer swap method we assume. -# Could be undefined (0), copy (1), exchange (2), 3-6, or buffer-age (-1). -# undefined is the slowest and the safest, and the default value. -# copy is fastest, but may fail on some drivers, -# 2-6 are gradually slower but safer (6 is still faster than 0). -# Usually, double buffer means 2, triple buffer means 3. -# buffer-age means auto-detect using GLX_EXT_buffer_age, supported by some drivers. -# Useless with --glx-use-copysubbuffermesa. -# Partially breaks --resize-damage. -# Defaults to undefined. -#glx-swap-method = "undefined"; - -################################# -# -# Shadows -# -################################# - -# Enabled client-side shadows on windows. -shadow = true; -# The blur radius for shadows. (default 12) -shadow-radius = 10; -# The left offset for shadows. (default -15) -shadow-offset-x = 0.25; -# The top offset for shadows. (default -15) -shadow-offset-y = 0.25; -# The translucency for shadows. (default .75) -shadow-opacity = 0.25; - -# Set if you want different colour shadows -# shadow-red = 0.0; -# shadow-green = 0.0; -# shadow-blue = 0.0; - -# The shadow exclude options are helpful if you have shadows enabled. Due to the way picom draws its shadows, certain applications will have visual glitches -# (most applications are fine, only apps that do weird things with xshapes or argb are affected). -# This list includes all the affected apps I found in my testing. The "! name~=''" part excludes shadows on any "Unknown" windows, this prevents a visual glitch with the XFWM alt tab switcher. -shadow-exclude = [ - "! name~=''", - "name *= 'dunst'", - "name *= 'i3bar'", - "name = 'Notification'", - "name = 'Plank'", - "name = 'Docky'", - "name = 'Kupfer'", - "name = 'xfce4-notifyd'", - "name *= 'VLC'", - "name *= 'picom'", - "name *= 'Chromium'", - "name *= 'Chrome'", - "class_g = 'Firefox' && argb", - "class_g = 'Conky'", - "class_g = 'Kupfer'", - "class_g = 'Synapse'", - "class_g ?= 'Notify-osd'", - "class_g ?= 'Cairo-dock'", - "class_g ?= 'Xfce4-notifyd'", - "class_g ?= 'Xfce4-power-manager'", - "_GTK_FRAME_EXTENTS@:c", - "_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'" -]; -# Avoid drawing shadow on all shaped windows (see also: --detect-rounded-corners) -shadow-ignore-shaped = false; - -################################# -# -# Opacity -# -################################# - -#inactive-opacity = 0.8; -active-opacity = 1; -frame-opacity = 1; -inactive-opacity-override = false; - -# Dim inactive windows. (0.0 - 1.0) -inactive-dim = 0.1; -# Do not let dimness adjust based on window opacity. -# inactive-dim-fixed = true; -# Blur background of transparent windows. Bad performance with X Render backend. GLX backend is preferred. -# blur-background = true; -# Blur background of opaque windows with transparent frames as well. -# blur-background-frame = true; -# Do not let blur radius adjust based on window opacity. -blur-background-fixed = false; -blur-background-exclude = [ - "window_type = 'dock'", - "window_type = 'desktop'" -]; - -opacity-rule = [ - "70:class_g = 'URxvt' && !focused", - "95:class_g = 'URxvt' && focused", - "80:class_g = 'dmenu'" - #"80:_NET_WM_NAME@:s = 'rofi'" -]; - -################################# -# -# Fading -# -################################# - -# Fade windows during opacity changes. -fading = true; -# The time between steps in a fade in milliseconds. (default 10). -fade-delta = 2.8; -# Opacity change between steps while fading in. (default 0.028). -fade-in-step = 0.03; -# Opacity change between steps while fading out. (default 0.03). -fade-out-step = 0.03; -# Fade windows in/out when opening/closing -no-fading-openclose = false; - -# Specify a list of conditions of windows that should not be faded. -fade-exclude = [ ]; - -################################# -# -# Other -# -################################# - -# Try to detect WM windows and mark them as active. -mark-wmwin-focused = true; -# Mark all non-WM but override-redirect windows active (e.g. menus). -mark-ovredir-focused = true; -# Use EWMH _NET_WM_ACTIVE_WINDOW to determine which window is focused instead of using FocusIn/Out events. -# Usually more reliable but depends on a EWMH-compliant WM. -use-ewmh-active-win = true; -# Detect rounded corners and treat them as rectangular when --shadow-ignore-shaped is on. -detect-rounded-corners = true; - -# Detect _NET_WM_OPACITY on client windows, useful for window managers not passing _NET_WM_OPACITY of client windows to frame windows. -# This prevents opacity being ignored for some apps. -# For example without this enabled my xfce4-notifyd is 100% opacity no matter what. -detect-client-opacity = true; - -# Specify refresh rate of the screen. -# If not specified or 0, picom will try detecting this with X RandR extension. -refresh-rate = 0; - -# Vertical synchronization: match the refresh rate of the monitor -vsync = true; - -# Enable DBE painting mode, intended to use with VSync to (hopefully) eliminate tearing. -# Reported to have no effect, though. -dbe = false; - -# Limit picom to repaint at most once every 1 / refresh_rate second to boost performance. -# This should not be used with --vsync drm/opengl/opengl-oml as they essentially does --sw-opti's job already, -# unless you wish to specify a lower refresh rate than the actual value. -#sw-opti = true; - -# Unredirect all windows if a full-screen opaque window is detected, to maximize performance for full-screen windows, like games. -# Known to cause flickering when redirecting/unredirecting windows. -unredir-if-possible = false; - -# Specify a list of conditions of windows that should always be considered focused. -focus-exclude = [ "_NET_WM_NAME@:s = 'rofi'" ]; - -# Use WM_TRANSIENT_FOR to group windows, and consider windows in the same group focused at the same time. -detect-transient = false; -# Use WM_CLIENT_LEADER to group windows, and consider windows in the same group focused at the same time. -# WM_TRANSIENT_FOR has higher priority if --detect-transient is enabled, too. -detect-client-leader = false; - -################################# -# -# Window type settings -# -################################# - -wintypes: -{ - tooltip = - { - # fade: Fade the particular type of windows. - fade = true; - # shadow: Give those windows shadow - shadow = false; - # opacity: Default opacity for the type of windows. - opacity = 0.85; - # focus: Whether to always consider windows of this type focused. - focus = true; - }; -}; - -###################### -# -# XSync -# See: https://github.com/yshui/picom/commit/b18d46bcbdc35a3b5620d817dd46fbc76485c20d -# -###################### - -# Use X Sync fence to sync clients' draw calls. Needed on nvidia-drivers with GLX backend for some users. -xrender-sync-fence = true; diff --git a/stow/qutebrowser/.config/qutebrowser/config.py b/stow/qutebrowser/.config/qutebrowser/config.py new file mode 100644 index 0000000..433a9cc --- /dev/null +++ b/stow/qutebrowser/.config/qutebrowser/config.py @@ -0,0 +1,1729 @@ +import dracula.draw + +## Autogenerated config.py +## Documentation: +## qute://help/configuring.html +## qute://help/settings.html + +## This is here so configs done via the GUI are still loaded. +## Remove it to not load settings done via the GUI. +config.load_autoconfig() + +## Aliases for commands. The keys of the given dictionary are the +## aliases, while the values are the commands they map to. +## Type: Dict +# c.aliases = {'w': 'session-save', 'q': 'quit', 'wq': 'quit --save'} + +## Time interval (in milliseconds) between auto-saves of +## config/cookies/etc. +## Type: Int +# c.auto_save.interval = 15000 + +## Always restore open sites when qutebrowser is reopened. +## Type: Bool +# c.auto_save.session = False + +## Backend to use to display websites. qutebrowser supports two different +## web rendering engines / backends, QtWebKit and QtWebEngine. QtWebKit +## was discontinued by the Qt project with Qt 5.6, but picked up as a +## well maintained fork: https://github.com/annulen/webkit/wiki - +## qutebrowser only supports the fork. QtWebEngine is Qt's official +## successor to QtWebKit. It's slightly more resource hungry than +## QtWebKit and has a couple of missing features in qutebrowser, but is +## generally the preferred choice. +## Type: String +## Valid values: +## - webengine: Use QtWebEngine (based on Chromium). +## - webkit: Use QtWebKit (based on WebKit, similar to Safari). +# c.backend = 'webengine' + +## This setting can be used to map keys to other keys. When the key used +## as dictionary-key is pressed, the binding for the key used as +## dictionary-value is invoked instead. This is useful for global +## remappings of keys, for example to map Ctrl-[ to Escape. Note that +## when a key is bound (via `bindings.default` or `bindings.commands`), +## the mapping is ignored. +## Type: Dict +# c.bindings.key_mappings = {'': '', '': '', '': '', '': '', '': '', '': '', '': '', '': ''} + +## Background color of the completion widget category headers. +## Type: QssColor +# c.colors.completion.category.bg = 'qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #888888, stop:1 #505050)' + +## Bottom border color of the completion widget category headers. +## Type: QssColor +# c.colors.completion.category.border.bottom = 'black' + +## Top border color of the completion widget category headers. +## Type: QssColor +# c.colors.completion.category.border.top = 'black' + +## Foreground color of completion widget category headers. +## Type: QtColor +# c.colors.completion.category.fg = 'white' + +## Background color of the completion widget for even rows. +## Type: QssColor +# c.colors.completion.even.bg = '#333333' + +## Text color of the completion widget. May be a single color to use for +## all columns or a list of three colors, one for each column. +## Type: List of QtColor, or QtColor +# c.colors.completion.fg = ['white', 'white', 'white'] + +## Background color of the selected completion item. +## Type: QssColor +# c.colors.completion.item.selected.bg = '#e8c000' + +## Bottom border color of the selected completion item. +## Type: QssColor +# c.colors.completion.item.selected.border.bottom = '#bbbb00' + +## Top border color of the completion widget category headers. +## Type: QssColor +# c.colors.completion.item.selected.border.top = '#bbbb00' + +## Foreground color of the selected completion item. +## Type: QtColor +# c.colors.completion.item.selected.fg = 'black' + +## Foreground color of the matched text in the completion. +## Type: QssColor +# c.colors.completion.match.fg = '#ff4444' + +## Background color of the completion widget for odd rows. +## Type: QssColor +# c.colors.completion.odd.bg = '#444444' + +## Color of the scrollbar in the completion view. +## Type: QssColor +# c.colors.completion.scrollbar.bg = '#333333' + +## Color of the scrollbar handle in the completion view. +## Type: QssColor +# c.colors.completion.scrollbar.fg = 'white' + +## Background color for the download bar. +## Type: QssColor +# c.colors.downloads.bar.bg = 'black' + +## Background color for downloads with errors. +## Type: QtColor +# c.colors.downloads.error.bg = 'red' + +## Foreground color for downloads with errors. +## Type: QtColor +# c.colors.downloads.error.fg = 'white' + +## Color gradient start for download backgrounds. +## Type: QtColor +# c.colors.downloads.start.bg = '#0000aa' + +## Color gradient start for download text. +## Type: QtColor +# c.colors.downloads.start.fg = 'white' + +## Color gradient stop for download backgrounds. +## Type: QtColor +# c.colors.downloads.stop.bg = '#00aa00' + +## Color gradient end for download text. +## Type: QtColor +# c.colors.downloads.stop.fg = 'white' + +## Color gradient interpolation system for download backgrounds. +## Type: ColorSystem +## Valid values: +## - rgb: Interpolate in the RGB color system. +## - hsv: Interpolate in the HSV color system. +## - hsl: Interpolate in the HSL color system. +## - none: Don't show a gradient. +# c.colors.downloads.system.bg = 'rgb' + +## Color gradient interpolation system for download text. +## Type: ColorSystem +## Valid values: +## - rgb: Interpolate in the RGB color system. +## - hsv: Interpolate in the HSV color system. +## - hsl: Interpolate in the HSL color system. +## - none: Don't show a gradient. +# c.colors.downloads.system.fg = 'rgb' + +## Background color for hints. Note that you can use a `rgba(...)` value +## for transparency. +## Type: QssColor +# c.colors.hints.bg = 'qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 247, 133, 0.8), stop:1 rgba(255, 197, 66, 0.8))' +c.colors.hints.bg = 'qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0, 0, 255, 0.8), stop:1 rgba(255, 0, 255, 0.8))' + +## Font color for hints. +## Type: QssColor +# c.colors.hints.fg = 'black' +c.colors.hints.fg = 'white' + +## Font color for the matched part of hints. +## Type: QssColor +# c.colors.hints.match.fg = 'green' +c.colors.hints.match.fg = 'yellow' + +## Background color of the keyhint widget. +## Type: QssColor +# c.colors.keyhint.bg = 'rgba(0, 0, 0, 80%)' + +## Text color for the keyhint widget. +## Type: QssColor +# c.colors.keyhint.fg = '#FFFFFF' + +## Highlight color for keys to complete the current keychain. +## Type: QssColor +# c.colors.keyhint.suffix.fg = '#FFFF00' + +## Background color of an error message. +## Type: QssColor +# c.colors.messages.error.bg = 'red' + +## Border color of an error message. +## Type: QssColor +# c.colors.messages.error.border = '#bb0000' + +## Foreground color of an error message. +## Type: QssColor +# c.colors.messages.error.fg = 'white' + +## Background color of an info message. +## Type: QssColor +# c.colors.messages.info.bg = 'black' + +## Border color of an info message. +## Type: QssColor +# c.colors.messages.info.border = '#333333' + +## Foreground color of an info message. +## Type: QssColor +# c.colors.messages.info.fg = 'white' + +## Background color of a warning message. +## Type: QssColor +# c.colors.messages.warning.bg = 'darkorange' + +## Border color of a warning message. +## Type: QssColor +# c.colors.messages.warning.border = '#d47300' + +## Foreground color of a warning message. +## Type: QssColor +# c.colors.messages.warning.fg = 'white' + +## Background color for prompts. +## Type: QssColor +# c.colors.prompts.bg = '#444444' + +## Border used around UI elements in prompts. +## Type: String +# c.colors.prompts.border = '1px solid gray' + +## Foreground color for prompts. +## Type: QssColor +# c.colors.prompts.fg = 'white' + +## Background color for the selected item in filename prompts. +## Type: QssColor +# c.colors.prompts.selected.bg = 'grey' + +## Background color of the statusbar in caret mode. +## Type: QssColor +# c.colors.statusbar.caret.bg = 'purple' + +## Foreground color of the statusbar in caret mode. +## Type: QssColor +# c.colors.statusbar.caret.fg = 'white' + +## Background color of the statusbar in caret mode with a selection. +## Type: QssColor +# c.colors.statusbar.caret.selection.bg = '#a12dff' + +## Foreground color of the statusbar in caret mode with a selection. +## Type: QssColor +# c.colors.statusbar.caret.selection.fg = 'white' + +## Background color of the statusbar in command mode. +## Type: QssColor +# c.colors.statusbar.command.bg = 'black' + +## Foreground color of the statusbar in command mode. +## Type: QssColor +# c.colors.statusbar.command.fg = 'white' + +## Background color of the statusbar in private browsing + command mode. +## Type: QssColor +# c.colors.statusbar.command.private.bg = 'grey' + +## Foreground color of the statusbar in private browsing + command mode. +## Type: QssColor +# c.colors.statusbar.command.private.fg = 'white' + +## Background color of the statusbar in insert mode. +## Type: QssColor +# c.colors.statusbar.insert.bg = 'darkgreen' +c.colors.statusbar.insert.bg = '#3fff00' #Harlequin + +## Foreground color of the statusbar in insert mode. +## Type: QssColor +# c.colors.statusbar.insert.fg = 'white' +c.colors.statusbar.insert.fg = 'black' + +## Background color of the statusbar. +## Type: QssColor +# c.colors.statusbar.normal.bg = 'black' + +## Foreground color of the statusbar. +## Type: QssColor +# c.colors.statusbar.normal.fg = 'white' + +## Background color of the statusbar in passthrough mode. +## Type: QssColor +# c.colors.statusbar.passthrough.bg = 'darkblue' +c.colors.statusbar.passthrough.bg = '#3f00ff' + +## Foreground color of the statusbar in passthrough mode. +## Type: QssColor +# c.colors.statusbar.passthrough.fg = 'white' + +## Background color of the statusbar in private browsing mode. +## Type: QssColor +# c.colors.statusbar.private.bg = '#666666' + +## Foreground color of the statusbar in private browsing mode. +## Type: QssColor +# c.colors.statusbar.private.fg = 'white' + +## Background color of the progress bar. +## Type: QssColor +# c.colors.statusbar.progress.bg = 'white' + +## Foreground color of the URL in the statusbar on error. +## Type: QssColor +# c.colors.statusbar.url.error.fg = 'orange' + +## Default foreground color of the URL in the statusbar. +## Type: QssColor +# c.colors.statusbar.url.fg = 'white' + +## Foreground color of the URL in the statusbar for hovered links. +## Type: QssColor +# c.colors.statusbar.url.hover.fg = 'aqua' + +## Foreground color of the URL in the statusbar on successful load +## (http). +## Type: QssColor +# c.colors.statusbar.url.success.http.fg = 'white' + +## Foreground color of the URL in the statusbar on successful load +## (https). +## Type: QssColor +# c.colors.statusbar.url.success.https.fg = 'lime' +c.colors.statusbar.url.success.https.fg = 'white' + +## Foreground color of the URL in the statusbar when there's a warning. +## Type: QssColor +# c.colors.statusbar.url.warn.fg = 'yellow' + +## Background color of the tab bar. +## Type: QtColor +# c.colors.tabs.bar.bg = '#555555' + +## Background color of unselected even tabs. +## Type: QtColor +# c.colors.tabs.even.bg = 'darkgrey' +c.colors.tabs.even.bg = 'black' + +## Foreground color of unselected even tabs. +## Type: QtColor +# c.colors.tabs.even.fg = 'white' +c.colors.tabs.even.fg = '#9F9F9F' + +## Color for the tab indicator on errors. +## Type: QtColor +# c.colors.tabs.indicator.error = '#ff0000' + +## Color gradient start for the tab indicator. +## Type: QtColor +# c.colors.tabs.indicator.start = '#0000aa' + +## Color gradient end for the tab indicator. +## Type: QtColor +# c.colors.tabs.indicator.stop = '#00aa00' + +## Color gradient interpolation system for the tab indicator. +## Type: ColorSystem +## Valid values: +## - rgb: Interpolate in the RGB color system. +## - hsv: Interpolate in the HSV color system. +## - hsl: Interpolate in the HSL color system. +## - none: Don't show a gradient. +# c.colors.tabs.indicator.system = 'rgb' + +## Background color of unselected odd tabs. +## Type: QtColor +# c.colors.tabs.odd.bg = 'grey' +#c.colors.tabs.odd.bg = '#5F5F5F' +c.colors.tabs.odd.bg = 'black' + +## Foreground color of unselected odd tabs. +## Type: QtColor +# c.colors.tabs.odd.fg = 'white' +c.colors.tabs.odd.fg = '#9F9F9F' + +## Background color of selected even tabs. +## Type: QtColor +# c.colors.tabs.selected.even.bg = 'black' + +## Foreground color of selected even tabs. +## Type: QtColor +# c.colors.tabs.selected.even.fg = 'white' + +## Background color of selected odd tabs. +## Type: QtColor +# c.colors.tabs.selected.odd.bg = 'black' + +## Foreground color of selected odd tabs. +## Type: QtColor +# c.colors.tabs.selected.odd.fg = 'white' + +## Background color for webpages if unset (or empty to use the theme's +## color). +## Type: QtColor +# c.colors.webpage.bg = 'white' + +## Number of commands to save in the command history. 0: no history / -1: +## unlimited +## Type: Int +# c.completion.cmd_history_max_items = 100 + +## Delay (in milliseconds) before updating completions after typing a +## character. +## Type: Int +# c.completion.delay = 0 + +## Height (in pixels or as percentage of the window) of the completion. +## Type: PercOrInt +# c.completion.height = '50%' +c.completion.height = '30%' + +## Minimum amount of characters needed to update completions. +## Type: Int +# c.completion.min_chars = 1 + +## Move on to the next part when there's only one possible completion +## left. +## Type: Bool +# c.completion.quick = True + +## Padding (in pixels) of the scrollbar handle in the completion window. +## Type: Int +# c.completion.scrollbar.padding = 2 + +## Width (in pixels) of the scrollbar in the completion window. +## Type: Int +# c.completion.scrollbar.width = 12 + +## When to show the autocompletion window. +## Type: String +## Valid values: +## - always: Whenever a completion is available. +## - auto: Whenever a completion is requested. +## - never: Never. +# c.completion.show = 'always' + +## Shrink the completion to be smaller than the configured size if there +## are no scrollbars. +## Type: Bool +# c.completion.shrink = False + +## Format of timestamps (e.g. for the history completion). +## Type: TimestampTemplate +# c.completion.timestamp_format = '%Y-%m-%d' + +## Execute the best-matching command on a partial match. +## Type: Bool +# c.completion.use_best_match = False + +## Number of URLs to show in the web history. 0: no history / -1: +## unlimited +## Type: Int +# c.completion.web_history_max_items = -1 + +## Require a confirmation before quitting the application. +## Type: ConfirmQuit +## Valid values: +## - always: Always show a confirmation. +## - multiple-tabs: Show a confirmation if multiple tabs are opened. +## - downloads: Show a confirmation if downloads are running +## - never: Never show a confirmation. +# c.confirm_quit = ['never'] + +## Enable support for the HTML 5 web application cache feature. An +## application cache acts like an HTTP cache in some sense. For documents +## that use the application cache via JavaScript, the loader engine will +## first ask the application cache for the contents, before hitting the +## network. +## Type: Bool +# c.content.cache.appcache = True + +## Maximum number of pages to hold in the global memory page cache. The +## page cache allows for a nicer user experience when navigating forth or +## back to pages in the forward/back history, by pausing and resuming up +## to _n_ pages. For more information about the feature, please refer to: +## http://webkit.org/blog/427/webkit-page-cache-i-the-basics/ +## Type: Int +# c.content.cache.maximum_pages = 0 + +## Size (in bytes) of the HTTP network cache. Null to use the default +## value. With QtWebEngine, the maximum supported value is 2147483647 (~2 +## GB). +## Type: Int +# c.content.cache.size = None + +## Which cookies to accept. +## Type: String +## Valid values: +## - all: Accept all cookies. +## - no-3rdparty: Accept cookies from the same origin only. +## - no-unknown-3rdparty: Accept cookies from the same origin only, unless a cookie is already set for the domain. +## - never: Don't accept cookies at all. +# c.content.cookies.accept = 'no-3rdparty' + +## Store cookies. Note this option needs a restart with QtWebEngine on Qt +## < 5.9. +## Type: Bool +# c.content.cookies.store = True + +## Default encoding to use for websites. The encoding must be a string +## describing an encoding such as _utf-8_, _iso-8859-1_, etc. +## Type: String +# c.content.default_encoding = 'iso-8859-1' + +## Enable extra tools for Web developers. This needs to be enabled for +## `:inspector` to work and also adds an _Inspect_ entry to the context +## menu. For QtWebEngine, see `--enable-webengine-inspector` in +## `qutebrowser --help` instead. +## Type: Bool +# c.content.developer_extras = False +#c.content.developer_extras = True + +## Try to pre-fetch DNS entries to speed up browsing. +## Type: Bool +# c.content.dns_prefetch = True + +## Expand each subframe to its contents. This will flatten all the frames +## to become one scrollable page. +## Type: Bool +# c.content.frame_flattening = False + +## Allow websites to request geolocations. +## Type: BoolAsk +## Valid values: +## - true +## - false +## - ask +# c.content.geolocation = 'ask' + +## Value to send in the `Accept-Language` header. +## Type: String +# c.content.headers.accept_language = 'en-US,en' + +## Custom headers for qutebrowser HTTP requests. +## Type: Dict +# c.content.headers.custom = {} + +## Value to send in the `DNT` header. When this is set to true, +## qutebrowser asks websites to not track your identity. If set to null, +## the DNT header is not sent at all. +## Type: Bool +# c.content.headers.do_not_track = True + +## When to send the Referer header. The Referer header tells websites +## from which website you were coming from when visting them. +## Type: String +## Valid values: +## - always: Always send the Referer. +## - never: Never send the Referer. This is not recommended, as some sites may break. +## - same-domain: Only send the Referer for the same domain. This will still protect your privacy, but shouldn't break any sites. +# c.content.headers.referer = 'same-domain' + +## User agent to send. Unset to send the default. +## Type: String +# c.content.headers.user_agent = None + +## Enable host blocking. +## Type: Bool +# c.content.host_blocking.enabled = True + +## List of URLs of lists which contain hosts to block. The file can be +## in one of the following formats: - An `/etc/hosts`-like file - One +## host per line - A zip-file of any of the above, with either only one +## file, or a file named `hosts` (with any extension). +## Type: List of Url +# c.content.host_blocking.lists = ['https://www.malwaredomainlist.com/hostslist/hosts.txt', 'http://someonewhocares.org/hosts/hosts', 'http://winhelp2002.mvps.org/hosts.zip', 'http://malwaredomains.lehigh.edu/files/justdomains.zip', 'https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&mimetype=plaintext'] + +## List of domains that should always be loaded, despite being ad- +## blocked. Domains may contain * and ? wildcards and are otherwise +## required to exactly match the requested domain. Local domains are +## always exempt from hostblocking. +## Type: List of String +# c.content.host_blocking.whitelist = ['piwik.org'] + +## Enable hyperlink auditing (``). +## Type: Bool +# c.content.hyperlink_auditing = False + +## Load images automatically in web pages. +## Type: Bool +# c.content.images = True + +## Show javascript alerts. +## Type: Bool +# c.content.javascript.alert = True + +## Allow JavaScript to read from or write to the clipboard. With +## QtWebEngine, writing the clipboard as response to a user interaction +## is always allowed. +## Type: Bool +# c.content.javascript.can_access_clipboard = False + +## Allow JavaScript to close tabs. +## Type: Bool +# c.content.javascript.can_close_tabs = False + +## Allow JavaScript to open new tabs without user interaction. +## Type: Bool +# c.content.javascript.can_open_tabs_automatically = False + +## Enable JavaScript. +## Type: Bool +# c.content.javascript.enabled = True + +## Log levels to use for JavaScript console logging messages. When a +## JavaScript message with the level given in the dictionary key is +## logged, the corresponding dictionary value selects the qutebrowser +## logger to use. On QtWebKit, the "unknown" setting is always used. +## Type: Dict +# c.content.javascript.log = {'unknown': 'debug', 'info': 'debug', 'warning': 'debug', 'error': 'debug'} + +## Use the standard JavaScript modal dialog for `alert()` and +## `confirm()`. +## Type: Bool +# c.content.javascript.modal_dialog = False + +## Show javascript prompts. +## Type: Bool +# c.content.javascript.prompt = True + +## Allow locally loaded documents to access other local URLs. +## Type: Bool +# c.content.local_content_can_access_file_urls = True + +## Allow locally loaded documents to access remote URLs. +## Type: Bool +# c.content.local_content_can_access_remote_urls = False + +## Enable support for HTML 5 local storage and Web SQL. +## Type: Bool +# c.content.local_storage = True + +## Allow websites to record audio/video. +## Type: BoolAsk +## Valid values: +## - true +## - false +## - ask +# c.content.media_capture = 'ask' + +## Netrc-file for HTTP authentication. If unset, `~/.netrc` is used. +## Type: File +# c.content.netrc_file = None + +## Allow websites to show notifications. +## Type: BoolAsk +## Valid values: +## - true +## - false +## - ask +# c.content.notifications = 'ask' + +## Allow pdf.js to view PDF files in the browser. Note that the files can +## still be downloaded by clicking the download button in the pdf.js +## viewer. +## Type: Bool +# c.content.pdfjs = False + +## Enable plugins in Web pages. +## Type: Bool +# c.content.plugins = False + +## Draw the background color and images also when the page is printed. +## Type: Bool +# c.content.print_element_backgrounds = True + +## Open new windows in private browsing mode which does not record +## visited pages. +## Type: Bool +# c.content.private_browsing = False + +## Proxy to use. In addition to the listed values, you can use a +## `socks://...` or `http://...` URL. +## Type: Proxy +## Valid values: +## - system: Use the system wide proxy. +## - none: Don't use any proxy +# c.content.proxy = 'system' + +## Send DNS requests over the configured proxy. +## Type: Bool +# c.content.proxy_dns_requests = True + +## Validate SSL handshakes. +## Type: BoolAsk +## Valid values: +## - true +## - false +## - ask +# c.content.ssl_strict = 'ask' + +## List of user stylesheet filenames to use. +## Type: List of File, or File +# c.content.user_stylesheets = [] + +## Enable WebGL. +## Type: Bool +# c.content.webgl = True + +## Limit fullscreen to the browser window (does not expand to fill the +## screen). +## Type: Bool +c.content.fullscreen.window = True + +## Monitor load requests for cross-site scripting attempts. Suspicious +## scripts will be blocked and reported in the inspector's JavaScript +## console. Enabling this feature might have an impact on performance. +## Type: Bool +# c.content.xss_auditing = False + +## Directory to save downloads to. If unset, a sensible OS-specific +## default is used. +## Type: Directory +# c.downloads.location.directory = None +c.downloads.location.directory = "~/downloads" + +## Prompt the user for the download location. If set to false, +## `downloads.location.directory` will be used. +## Type: Bool +# c.downloads.location.prompt = True + +## Remember the last used download directory. +## Type: Bool +# c.downloads.location.remember = True + +## What to display in the download filename input. +## Type: String +## Valid values: +## - path: Show only the download path. +## - filename: Show only download filename. +## - both: Show download path and filename. +# c.downloads.location.suggestion = 'path' + +## Default program used to open downloads. If null, the default internal +## handler is used. Any `{}` in the string will be expanded to the +## filename, else the filename will be appended. +## Type: String +# c.downloads.open_dispatcher = None +c.downloads.open_dispatcher = "rifle" + +## Where to show the downloaded files. +## Type: VerticalPosition +## Valid values: +## - top +## - bottom +# c.downloads.position = 'top' + +## Duration (in milliseconds) to wait before removing finished downloads. +## If set to -1, downloads are never removed. +## Type: Int +# c.downloads.remove_finished = -1 + +## Editor (and arguments) to use for the `open-editor` command. The +## following placeholders are defined: * `{file}`: Filename of the file +## to be edited. * `{line}`: Line in which the caret is found in the +## text. * `{column}`: Column in which the caret is found in the text. * +## `{line0}`: Same as `{line}`, but starting from index 0. * `{column0}`: +## Same as `{column}`, but starting from index 0. +## Type: ShellCommand +# c.editor.command = ['gvim', '-f', '{file}', '-c', 'normal {line}G{column0}l'] +c.editor.command = ['urxvt', '-title', '"floating"', '-e', 'nvim', '{file}'] + +## Encoding to use for the editor. +## Type: Encoding +# c.editor.encoding = 'utf-8' + +## Font used in the completion categories. +## Type: Font +# c.fonts.completion.category = 'bold 10pt monospace' +c.fonts.completion.category = 'bold 10pt serif' + +## Font used in the completion widget. +## Type: Font +# c.fonts.completion.entry = '10pt monospace' +c.fonts.completion.entry = '10pt serif' + +## Font used for the debugging console. +## Type: QtFont +# c.fonts.debug_console = '10pt monospace' +c.fonts.debug_console = '10pt serif' + +## Font used for the downloadbar. +## Type: Font +# c.fonts.downloads = '10pt monospace' +c.fonts.downloads = '10pt serif' + +## Font used for the hints. +## Type: Font +# c.fonts.hints = 'bold 10pt monospace' +c.fonts.hints = 'bold 10pt Inconsolata' + +## Font used in the keyhint widget. +## Type: Font +# c.fonts.keyhint = '10pt monospace' +c.fonts.keyhint = '10pt serif' + +## Font used for error messages. +## Type: Font +# c.fonts.messages.error = '10pt monospace' +c.fonts.messages.error = '10pt serif' + +## Font used for info messages. +## Type: Font +# c.fonts.messages.info = '10pt monospace' +c.fonts.messages.info = '10pt serif' + +## Font used for warning messages. +## Type: Font +# c.fonts.messages.warning = '10pt monospace' +c.fonts.messages.warning = '10pt serif' + +## Default monospace fonts. Whenever "monospace" is used in a font +## setting, it's replaced with the fonts listed here. +## Type: Font +# c.fonts.monospace = '"xos4 Terminus", Terminus, Monospace, "DejaVu Sans Mono", Monaco, "Bitstream Vera Sans Mono", "Andale Mono", "Courier New", Courier, "Liberation Mono", monospace, Fixed, Consolas, Terminal' + +## Font used for prompts. +## Type: Font +# c.fonts.prompts = '10pt sans-serif' + +## Font used in the statusbar. +## Type: Font +# c.fonts.statusbar = '10pt monospace' +c.fonts.statusbar = '10pt Linux Libertine' + +## Font used in the tab bar. +## Type: QtFont +# c.fonts.tabs = '10pt monospace' +# No longer exists (Thu 16 Jul 2020 01:39:46 AM CEST) +c.fonts.tabs.selected = '10pt serif' +c.fonts.tabs.unselected = '10pt serif' + +## Font family for cursive fonts. +## Type: FontFamily +# c.fonts.web.family.cursive = '' + +## Font family for fantasy fonts. +## Type: FontFamily +# c.fonts.web.family.fantasy = '' + +## Font family for fixed fonts. +## Type: FontFamily +# c.fonts.web.family.fixed = '' + +## Font family for sans-serif fonts. +## Type: FontFamily +# c.fonts.web.family.sans_serif = '' + +## Font family for serif fonts. +## Type: FontFamily +# c.fonts.web.family.serif = '' + +## Font family for standard fonts. +## Type: FontFamily +# c.fonts.web.family.standard = '' + +## Default font size (in pixels) for regular text. +## Type: Int +# c.fonts.web.size.default = 16 + +## Default font size (in pixels) for fixed-pitch text. +## Type: Int +# c.fonts.web.size.default_fixed = 13 + +## Hard minimum font size (in pixels). +## Type: Int +# c.fonts.web.size.minimum = 0 + +## Minimum logical font size (in pixels) that is applied when zooming +## out. +## Type: Int +# c.fonts.web.size.minimum_logical = 6 + +## When a hint can be automatically followed without pressing Enter. +## Type: String +## Valid values: +## - always: Auto-follow whenever there is only a single hint on a page. +## - unique-match: Auto-follow whenever there is a unique non-empty match in either the hint string (word mode) or filter (number mode). +## - full-match: Follow the hint when the user typed the whole hint (letter, word or number mode) or the element's text (only in number mode). +## - never: The user will always need to press Enter to follow a hint. +# c.hints.auto_follow = 'unique-match' + +## Duration (in milliseconds) to ignore normal-mode key bindings after a +## successful auto-follow. +## Type: Int +# c.hints.auto_follow_timeout = 0 + +## CSS border value for hints. +## Type: String +# c.hints.border = '1px solid #E3BE23' +c.hints.border = '1px solid #000000' + +## Characters used for hint strings. +## Type: UniqueCharString +# c.hints.chars = 'asdfghjkl' +c.hints.chars = 'asdfjklรฑ' + +## Dictionary file to be used by the word hints. +## Type: File +# c.hints.dictionary = '/usr/share/dict/words' + +## Which implementation to use to find elements to hint. +## Type: String +## Valid values: +## - javascript: Better but slower +## - python: Slightly worse but faster +# c.hints.find_implementation = 'python' +c.hints.find_implementation = 'javascript' + +## Hide unmatched hints in rapid mode. +## Type: Bool +# c.hints.hide_unmatched_rapid_hints = True + +## Minimum number of characters used for hint strings. +## Type: Int +# c.hints.min_chars = 1 +c.hints.min_chars = 2 + +## Mode to use for hints. +## Type: String +## Valid values: +## - number: Use numeric hints. (In this mode you can also type letters from the hinted element to filter and reduce the number of elements that are hinted.) +## - letter: Use the characters in the `hints.chars` setting. +## - word: Use hints words based on the html elements and the extra words. +# c.hints.mode = 'letter' +c.hints.mode = 'letter' + +## Comma-separated list of regular expressions to use for 'next' links. +## Type: List of Regex +# c.hints.next_regexes = ['\\bnext\\b', '\\bmore\\b', '\\bnewer\\b', '\\b[>โ†’โ‰ซ]\\b', '\\b(>>|ยป)\\b', '\\bcontinue\\b'] + +## Comma-separated list of regular expressions to use for 'prev' links. +## Type: List of Regex +# c.hints.prev_regexes = ['\\bprev(ious)?\\b', '\\bback\\b', '\\bolder\\b', '\\b[<โ†โ‰ช]\\b', '\\b(<<|ยซ)\\b'] + +## Scatter hint key chains (like Vimium) or not (like dwb). Ignored for +## number hints. +## Type: Bool +# c.hints.scatter = True + +## Make characters in hint strings uppercase. +## Type: Bool +# c.hints.uppercase = False + +## Maximum time (in minutes) between two history items for them to be +## considered being from the same browsing session. Items with less time +## between them are grouped when being displayed in `:history`. Use -1 to +## disable separation. +## Type: Int +# c.history_gap_interval = 30 + +## Which unbound keys to forward to the webview in normal mode. +## Type: String +## Valid values: +## - all: Forward all unbound keys. +## - auto: Forward unbound non-alphanumeric keys. +## - none: Don't forward any keys. +# c.input.forward_unbound_keys = 'auto' + +## Leave insert mode if a non-editable element is clicked. +## Type: Bool +# c.input.insert_mode.auto_leave = True + +## Automatically enter insert mode if an editable element is focused +## after loading the page. +## Type: Bool +# c.input.insert_mode.auto_load = False +c.input.insert_mode.auto_load = True + +## Switch to insert mode when clicking flash and other plugins. +## Type: Bool +# c.input.insert_mode.plugins = False + +## Include hyperlinks in the keyboard focus chain when tabbing. +## Type: Bool +# c.input.links_included_in_focus_chain = True + +## Timeout (in milliseconds) for partially typed key bindings. If the +## current input forms only partial matches, the keystring will be +## cleared after this time. +## Type: Int +# c.input.partial_timeout = 5000 + +## Enable Opera-like mouse rocker gestures. This disables the context +## menu. +## Type: Bool +# c.input.rocker_gestures = False + +## Enable spatial navigation. Spatial navigation consists in the ability +## to navigate between focusable elements in a Web page, such as +## hyperlinks and form controls, by using Left, Right, Up and Down arrow +## keys. For example, if the user presses the Right key, heuristics +## determine whether there is an element he might be trying to reach +## towards the right and which element he probably wants. +## Type: Bool +# c.input.spatial_navigation = False + +## Keychains that shouldn't be shown in the keyhint dialog. Globs are +## supported, so `;*` will blacklist all keychains starting with `;`. Use +## `*` to disable keyhints. +## Type: List of String +# c.keyhint.blacklist = [] + +## Time (in milliseconds) from pressing a key to seeing the keyhint +## dialog. +## Type: Int +# c.keyhint.delay = 500 + +## Rounding radius (in pixels) for the edges of the keyhint dialog. +## Type: Int +# c.keyhint.radius = 6 + +## Duration (in milliseconds) to show messages in the statusbar for. Set +## to 0 to never clear messages. +## Type: Int +# c.messages.timeout = 2000 + +## How to open links in an existing instance if a new one is launched. +## This happens when e.g. opening a link from a terminal. See +## `new_instance_open_target_window` to customize in which window the +## link is opened in. +## Type: String +## Valid values: +## - tab: Open a new tab in the existing window and activate the window. +## - tab-bg: Open a new background tab in the existing window and activate the window. +## - tab-silent: Open a new tab in the existing window without activating the window. +## - tab-bg-silent: Open a new background tab in the existing window without activating the window. +## - window: Open in a new window. +# c.new_instance_open_target = 'tab' +c.new_instance_open_target = 'window' + +## Which window to choose when opening links as new tabs. When +## `new_instance_open_target` is not set to `window`, this is ignored. +## Type: String +## Valid values: +## - first-opened: Open new tabs in the first (oldest) opened window. +## - last-opened: Open new tabs in the last (newest) opened window. +## - last-focused: Open new tabs in the most recently focused window. +## - last-visible: Open new tabs in the most recently visible window. +# c.new_instance_open_target_window = 'last-focused' + +## Show a filebrowser in upload/download prompts. +## Type: Bool +# c.prompt.filebrowser = True + +## Rounding radius (in pixels) for the edges of prompts. +## Type: Int +# c.prompt.radius = 8 + +## Additional arguments to pass to Qt, without leading `--`. With +## QtWebEngine, some Chromium arguments (see +## https://peter.sh/experiments/chromium-command-line-switches/ for a +## list) will work. +## Type: List of String +# c.qt.args = [] + +## Force a Qt platform to use. This sets the `QT_QPA_PLATFORM` +## environment variable and is useful to force using the XCB plugin when +## running QtWebEngine on Wayland. +## Type: String +# c.qt.force_platform = None + +## Force software rendering for QtWebEngine. This is needed for +## QtWebEngine to work with Nouveau drivers. +## Type: Bool +# c.qt.force_software_rendering = False + +## Turn on Qt HighDPI scaling. This is equivalent to setting +## QT_AUTO_SCREEN_SCALE_FACTOR=1 in the environment. It's off by default +## as it can cause issues with some bitmap fonts. As an alternative to +## this, it's possible to set font sizes and the `zoom.default` setting. +## Type: Bool +# c.qt.highdpi = False + +## Show a scrollbar. +## Type: Bool +# c.scrolling.bar = False + +## Enable smooth scrolling for web pages. Note smooth scrolling does not +## work with the `:scroll-px` command. +## Type: Bool +# c.scrolling.smooth = False + +## When to find text on a page case-insensitively. +## Type: String +## Valid values: +## - always: Search case-insensitively. +## - never: Search case-sensitively. +## - smart: Search case-sensitively if there are capital characters. +# c.search.ignore_case = 'smart' + +## Find text on a page incrementally, renewing the search for each typed +## character. +## Type: Bool +# c.search.incremental = True + +## Name of the session to save by default. If this is set to null, the +## session which was last loaded is saved. +## Type: SessionName +# c.session.default_name = None + +## Load a restored tab as soon as it takes focus. +## Type: Bool +# c.session.lazy_restore = False + +## Languages to use for spell checking. You can check for available +## languages and install dictionaries using scripts/dictcli.py. Run the +## script with -h/--help for instructions. +## Type: List of String +## Valid values: +## - af-ZA: Afrikaans (South Africa) +## - bg-BG: Bulgarian (Bulgaria) +## - ca-ES: Catalan (Spain) +## - cs-CZ: Czech (Czech Republic) +## - da-DK: Danish (Denmark) +## - de-DE: German (Germany) +## - el-GR: Greek (Greece) +## - en-AU: English (Australia) +## - en-CA: English (Canada) +## - en-GB: English (United Kingdom) +## - en-US: English (United States) +## - es-ES: Spanish (Spain) +## - et-EE: Estonian (Estonia) +## - fa-IR: Farsi (Iran) +## - fo-FO: Faroese (Faroe Islands) +## - fr-FR: French (France) +## - he-IL: Hebrew (Israel) +## - hi-IN: Hindi (India) +## - hr-HR: Croatian (Croatia) +## - hu-HU: Hungarian (Hungary) +## - id-ID: Indonesian (Indonesia) +## - it-IT: Italian (Italy) +## - ko: Korean +## - lt-LT: Lithuanian (Lithuania) +## - lv-LV: Latvian (Latvia) +## - nb-NO: Norwegian (Norway) +## - nl-NL: Dutch (Netherlands) +## - pl-PL: Polish (Poland) +## - pt-BR: Portuguese (Brazil) +## - pt-PT: Portuguese (Portugal) +## - ro-RO: Romanian (Romania) +## - ru-RU: Russian (Russia) +## - sh: Serbo-Croatian +## - sk-SK: Slovak (Slovakia) +## - sl-SI: Slovenian (Slovenia) +## - sq: Albanian +## - sr: Serbian +## - sv-SE: Swedish (Sweden) +## - ta-IN: Tamil (India) +## - tg-TG: Tajik (Tajikistan) +## - tr-TR: Turkish (Turkey) +## - uk-UA: Ukrainian (Ukraine) +## - vi-VN: Vietnamese (Viet Nam) +# c.spellcheck.languages = [] + +## Hide the statusbar unless a message is shown. +## Type: Bool +# c.statusbar.hide = False +# No longer exists (Thu 16 Jul 2020 01:39:46 AM CEST) +c.statusbar.show = "in-mode" + +## Padding (in pixels) for the statusbar. +## Type: Padding +# c.statusbar.padding = {'top': 1, 'bottom': 1, 'left': 0, 'right': 0} + +## Position of the status bar. +## Type: VerticalPosition +## Valid values: +## - top +## - bottom +# c.statusbar.position = 'bottom' + +## Open new tabs (middleclick/ctrl+click) in the background. +## Type: Bool +# c.tabs.background = False + +## Mouse button with which to close tabs. +## Type: String +## Valid values: +## - right: Close tabs on right-click. +## - middle: Close tabs on middle-click. +## - none: Don't close tabs using the mouse. +# c.tabs.close_mouse_button = 'middle' + +## How to behave when the close mouse button is pressed on the tab bar. +## Type: String +## Valid values: +## - new-tab: Open a new tab. +## - close-current: Close the current tab. +## - close-last: Close the last tab. +## - ignore: Don't do anything. +# c.tabs.close_mouse_button_on_bar = 'new-tab' + +## Scaling factor for favicons in the tab bar. The tab size is unchanged, +## so big favicons also require extra `tabs.padding`. +## Type: Float +# c.tabs.favicons.scale = 1.0 + +## Show favicons in the tab bar. +## Type: Bool +# c.tabs.favicons.show = True + +## Padding (in pixels) for tab indicators. +## Type: Padding +# c.tabs.indicator.padding = {'top': 2, 'bottom': 2, 'left': 0, 'right': 4} + +## Width (in pixels) of the progress indicator (0 to disable). +## Type: Int +# c.tabs.indicator.width = 3 + +## How to behave when the last tab is closed. +## Type: String +## Valid values: +## - ignore: Don't do anything. +## - blank: Load a blank page. +## - startpage: Load the start page. +## - default-page: Load the default page. +## - close: Close the window. +# c.tabs.last_close = 'ignore' +c.tabs.last_close = 'close' + +## Switch between tabs using the mouse wheel. +## Type: Bool +# c.tabs.mousewheel_switching = True + +## Position of new tabs opened from another tab. +## Type: NewTabPosition +## Valid values: +## - prev: Before the current tab. +## - next: After the current tab. +## - first: At the beginning. +## - last: At the end. +# c.tabs.new_position.related = 'next' + +## Position of new tabs which aren't opened from another tab. +## Type: NewTabPosition +## Valid values: +## - prev: Before the current tab. +## - next: After the current tab. +## - first: At the beginning. +## - last: At the end. +# c.tabs.new_position.unrelated = 'last' + +## Padding (in pixels) around text for tabs. +## Type: Padding +# c.tabs.padding = {'top': 0, 'bottom': 0, 'left': 5, 'right': 5} + +## Stay in insert/passthrough mode when switching tabs. +## Type: Bool +# c.tabs.persist_mode_on_change = False + +## Shrink pinned tabs down to their contents. +## Type: Bool +# c.tabs.pinned.shrink = True + +## Position of the tab bar. +## Type: Position +## Valid values: +## - top +## - bottom +## - left +## - right +# c.tabs.position = 'top' + +## Which tab to select when the focused tab is removed. +## Type: SelectOnRemove +## Valid values: +## - prev: Select the tab which came before the closed one (left in horizontal, above in vertical). +## - next: Select the tab which came after the closed one (right in horizontal, below in vertical). +## - last-used: Select the previously selected tab. +# c.tabs.select_on_remove = 'next' + +## When to show the tab bar. +## Type: String +## Valid values: +## - always: Always show the tab bar. +## - never: Always hide the tab bar. +## - multiple: Hide the tab bar if only one tab is open. +## - switching: Show the tab bar when switching tabs. +# c.tabs.show = 'always' +c.tabs.show = 'multiple' + +## Duration (in milliseconds) to show the tab bar before hiding it when +## tabs.show is set to 'switching'. +## Type: Int +# c.tabs.show_switching_delay = 800 + +## Open a new window for every tab. +## Type: Bool +# c.tabs.tabs_are_windows = False + +## Alignment of the text inside of tabs. +## Type: TextAlignment +## Valid values: +## - left +## - right +## - center +# c.tabs.title.alignment = 'left' + +## Format to use for the tab title. The following placeholders are +## defined: * `{perc}`: Percentage as a string like `[10%]`. * +## `{perc_raw}`: Raw percentage, e.g. `10`. * `{title}`: Title of the +## current web page. * `{title_sep}`: The string ` - ` if a title is set, +## empty otherwise. * `{index}`: Index of this tab. * `{id}`: Internal +## tab ID of this tab. * `{scroll_pos}`: Page scroll position. * +## `{host}`: Host of the current web page. * `{backend}`: Either +## ''webkit'' or ''webengine'' * `{private}`: Indicates when private mode +## is enabled. * `{current_url}`: URL of the current web page. * +## `{protocol}`: Protocol (http/https/...) of the current web page. +## Type: FormatString +# c.tabs.title.format = '{index}: {title}' + +## Format to use for the tab title for pinned tabs. The same placeholders +## like for `tabs.title.format` are defined. +## Type: FormatString +# c.tabs.title.format_pinned = '{index}' + +## Width (in pixels or as percentage of the window) of the tab bar if +## it's vertical. +## Type: PercOrInt +# c.tabs.width = '20%' + +## Wrap when changing tabs. +## Type: Bool +# c.tabs.wrap = True + +## What search to start when something else than a URL is entered. +## Type: String +## Valid values: +## - naive: Use simple/naive check. +## - dns: Use DNS requests (might be slow!). +## - never: Never search automatically. +# c.url.auto_search = 'naive' + +## Page to open if :open -t/-b/-w is used without URL. Use `about:blank` +## for a blank page. +## Type: FuzzyUrl +# c.url.default_page = 'https://start.duckduckgo.com/' +c.url.default_page = '/home/taamas/.mainpage/index.html' + +## URL segments where `:navigate increment/decrement` will search for a +## number. +## Type: FlagList +## Valid values: +## - host +## - path +## - query +## - anchor +# c.url.incdec_segments = ['path', 'query'] + +## Search engines which can be used via the address bar. Maps a search +## engine name (such as `DEFAULT`, or `ddg`) to a URL with a `{}` +## placeholder. The placeholder will be replaced by the search term, use +## `{{` and `}}` for literal `{`/`}` signs. The search engine named +## `DEFAULT` is used when `url.auto_search` is turned on and something +## else than a URL was entered to be opened. Other search engines can be +## used by prepending the search engine name to the search term, e.g. +## `:open google qutebrowser`. +## Type: Dict +c.url.searchengines = { + 'DEFAULT': 'https://duckduckgo.com/?q={}', #duckduckgo + 'ddg': 'https://duckduckgo.com/?q={}', #duckduckgo + 's': 'https://search.disroot.org/search?q={}', #Disroot SearX + 'y': 'https://www.youtube.com/results?search_query={}', #youtube + 'tw': 'https://twitter.com/{}', #twitter + 'w': 'https://en.wikipedia.org/?search={}', #wikipedia + 'we': 'https://es.wikipedia.org/?search={}', #wikipedia(ES) + 'aw': 'https://wiki.archlinux.org/?search={}', #archWiki + 'sf': 'https://scryfall.com/search?q={}', #scryfall + 'mkm': 'https://www.cardmarket.com/en/Magic/Products/Search?searchString={}', #mkm + 'gi': 'https://game-icons.net/search.html?q={}', #game-icons + 'bc': 'https://bandcamp.com/search?q={}', #bancamp + 'mdd': 'https://www.megadede.com/search/{}', #megadede + 'gh': 'https://www.github.com/search?q={}', #github + 'ghu': 'https://github.com/search?q={}&type=Users', #github users + 'ep': 'https://emojipedia.org/search/?q={}', #emojipedia + 'rae': 'https://dle.rae.es/?w={}', #rae + 'maps': 'https://www.google.com/maps/place/{}', #google maps + 'im': 'https://imagemagick.org/script/search.php?q={}', # ImageMagick + 'mc': 'https://minecraft.gamepedia.com/{}', # Minecraft wiki + 'mb': 'https://musicbrainz.org/search?query={}&type=artist&method=indexed', # MusicBrainz (Artist) + 'df': 'https://dwarffortresswiki.org/index.php/DF2014:{}', # Dwarf Fortress Wiki + 'sl': 'https://senseis.xmp.net/?{}', # Sensei's Library + 'sls': 'https://senseis.xmp.net/?search={}&searchtype=title', # Sensei's Library search + 'bs': 'https://bsaber.com/?s={}', # Beast Saber + 'bp': 'https://bulbapedia.bulbagarden.net/wiki/{}', # Bulbapedia + 'bpm': 'https://bulbapedia.bulbagarden.net/wiki/{}#Learnset', # Bulbapedia (Learnset) + 'bpe': 'https://bulbapedia.bulbagarden.net/wiki/{}#Evolution', # Bulbapedia (Evolution) + 'sg': 'https://www.smogon.com/dex/ss/pokemon/{}', # Smogon + 'tex': 'https://www.ctan.org/search?phrase={}', # CTAN + 'keys': 'https://keys.openpgp.org/search?q={}', # openPGP keys + 'fl': 'https://fallenlondon.wiki/w/index.php?search={}' # Fallen London wiki +} + +## Page(s) to open at the start. +## Type: List of FuzzyUrl, or FuzzyUrl +# c.url.start_pages = ['https://start.duckduckgo.com'] +c.url.start_pages = ['file:///home/taamas/.mainpage/index.html'] + +## URL parameters to strip with `:yank url`. +## Type: List of String +# c.url.yank_ignored_parameters = ['ref', 'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'] + +## Hide the window decoration when using wayland. +## Type: Bool +# c.window.hide_wayland_decoration = False + +## Format to use for the window title. The same placeholders like for +## `tabs.title.format` are defined. +## Type: FormatString +# c.window.title_format = '{perc}{title}{title_sep}qutebrowser' + +## Default zoom level. +## Type: Perc +# c.zoom.default = '100%' + +## Available zoom levels. +## Type: List of Perc +# c.zoom.levels = ['25%', '33%', '50%', '67%', '75%', '90%', '100%', '110%', '125%', '150%', '175%', '200%', '250%', '300%', '400%', '500%'] + +## Number of zoom increments to divide the mouse wheel movements to. +## Type: Int +# c.zoom.mouse_divider = 512 + +## Apply the zoom factor on a frame only to the text or to all content. +## Type: Bool +# c.zoom.text_only = False + +## Bindings for normal mode +# config.bind("'", 'enter-mode jump_mark') +# config.bind('+', 'zoom-in') +# config.bind('-', 'zoom-out') +# config.bind('.', 'repeat-command') +# config.bind('/', 'set-cmd-text /') +# config.bind(':', 'set-cmd-text :') +# config.bind(';I', 'hint images tab') +# config.bind(';O', 'hint links fill :open -t -r {hint-url}') +# config.bind(';R', 'hint --rapid links window') +# config.bind(';Y', 'hint links yank-primary') +# config.bind(';b', 'hint all tab-bg') +# config.bind(';f', 'hint all tab-fg') +# config.bind(';h', 'hint all hover') +# config.bind(';i', 'hint images') +# config.bind(';o', 'hint links fill :open {hint-url}') +# config.bind(';r', 'hint --rapid links tab-bg') +# config.bind(';t', 'hint inputs') +# config.bind(';y', 'hint links yank') +# config.bind('', 'tab-focus 1') +# config.bind('', 'tab-focus 2') +# config.bind('', 'tab-focus 3') +# config.bind('', 'tab-focus 4') +# config.bind('', 'tab-focus 5') +# config.bind('', 'tab-focus 6') +# config.bind('', 'tab-focus 7') +# config.bind('', 'tab-focus 8') +# config.bind('', 'tab-focus -1') +# config.bind('', 'navigate increment') +# config.bind('', 'print') +# config.bind('', 'scroll-page 0 -1') +# config.bind('', 'scroll-page 0 0.5') +# config.bind('', 'reload -f') +# config.bind('', 'scroll-page 0 1') +# config.bind('', 'open -w') +# config.bind('', 'tab-next') +# config.bind('', 'tab-prev') +# config.bind('', 'quit') +# config.bind('', 'follow-selected -t') +# config.bind('', 'open -p') +# config.bind('', 'undo') +# config.bind('', 'close') +# config.bind('', 'open -t') +# config.bind('', 'tab-focus last') +# config.bind('', 'scroll-page 0 -0.5') +# config.bind('', 'enter-mode passthrough') +# config.bind('', 'tab-close') +# config.bind('', 'navigate decrement') +# config.bind('', 'tab-focus last') +# config.bind('', 'home') +# config.bind('', 'tab-pin') +# config.bind('', 'stop') +# config.bind('', 'clear-keychain ;; search ;; fullscreen --leave') +# config.bind('', 'fullscreen') +# config.bind('', 'reload') +# config.bind('', 'follow-selected') +# config.bind('', 'back') +# config.bind('', 'forward') +# config.bind('=', 'zoom') +# config.bind('?', 'set-cmd-text ?') +# config.bind('@', 'run-macro') +# config.bind('B', 'set-cmd-text -s :quickmark-load -t') +# config.bind('D', 'tab-close -o') +config.unbind('D') +# config.bind('F', 'hint all tab') +# config.bind('G', 'scroll-to-perc') +# config.bind('H', 'back') +# config.bind('J', 'tab-next') +# config.bind('K', 'tab-prev') +# config.bind('L', 'forward') +# config.bind('M', 'bookmark-add') +# config.bind('N', 'search-prev') +# config.bind('O', 'set-cmd-text -s :open -t') +# config.bind('PP', 'open -t -- {primary}') +# config.bind('Pp', 'open -t -- {clipboard}') +# config.bind('R', 'reload -f') +# config.bind('Sb', 'open qute://bookmarks#bookmarks') +# config.bind('Sh', 'open qute://history') +# config.bind('Sq', 'open qute://bookmarks') +# config.bind('Ss', 'open qute://settings') +# config.bind('T', 'tab-focus') +# config.bind('ZQ', 'quit') +# config.bind('ZZ', 'quit --save') +# config.bind('[[', 'navigate prev') +# config.bind(']]', 'navigate next') +# config.bind('`', 'enter-mode set_mark') +# config.bind('ad', 'download-cancel') +# config.bind('b', 'set-cmd-text -s :quickmark-load') +# config.bind('cd', 'download-clear') +# config.bind('co', 'tab-only') +# config.bind('d', 'tab-close') +config.bind('d', 'scroll-page 0 0.5') +config.bind('u', 'scroll-page 0 -0.5') +config.bind('q', 'tab-close') +# config.bind('f', 'hint') +# config.bind('g$', 'tab-focus -1') +# config.bind('g0', 'tab-focus 1') +# config.bind('gB', 'set-cmd-text -s :bookmark-load -t') +# config.bind('gC', 'tab-clone') +# config.bind('gO', 'set-cmd-text :open -t -r {url:pretty}') +# config.bind('gU', 'navigate up -t') +# config.bind('g^', 'tab-focus 1') +# config.bind('ga', 'open -t') +# config.bind('gb', 'set-cmd-text -s :bookmark-load') +# config.bind('gd', 'download') +# config.bind('gf', 'view-source') +# config.bind('gg', 'scroll-to-perc 0') +# config.bind('gl', 'tab-move -') +# config.bind('gm', 'tab-move') +# config.bind('go', 'set-cmd-text :open {url:pretty}') +# config.bind('gr', 'tab-move +') +# config.bind('gt', 'set-cmd-text -s :buffer') +# config.bind('gu', 'navigate up') +# config.bind('h', 'scroll left') +# config.bind('i', 'enter-mode insert') +# config.bind('j', 'scroll down') +# config.bind('k', 'scroll up') +# config.bind('l', 'scroll right') +# config.bind('m', 'quickmark-save') +# config.bind('n', 'search-next') +# config.bind('o', 'set-cmd-text -s :open') +# config.bind('pP', 'open -- {primary}') +# config.bind('pp', 'open -- {clipboard}') +# config.bind('q', 'record-macro') +config.bind('Q', 'record-macro') +# config.bind('r', 'reload') +# config.bind('sf', 'save') +# config.bind('sk', 'set-cmd-text -s :bind') +# config.bind('sl', 'set-cmd-text -s :set -t') +# config.bind('ss', 'set-cmd-text -s :set') +# config.bind('th', 'back -t') +# config.bind('tl', 'forward -t') +# config.bind('u', 'undo') +config.bind('U', 'undo') +# config.bind('v', 'enter-mode caret') +# config.bind('wB', 'set-cmd-text -s :bookmark-load -w') +# config.bind('wO', 'set-cmd-text :open -w {url:pretty}') +# config.bind('wP', 'open -w -- {primary}') +# config.bind('wb', 'set-cmd-text -s :quickmark-load -w') +# config.bind('wf', 'hint all window') +# config.bind('wh', 'back -w') +# config.bind('wi', 'inspector') +# config.bind('wl', 'forward -w') +# config.bind('wo', 'set-cmd-text -s :open -w') +# config.bind('wp', 'open -w -- {clipboard}') +# config.bind('xO', 'set-cmd-text :open -b -r {url:pretty}') +# config.bind('xo', 'set-cmd-text -s :open -b') +# config.bind('yD', 'yank domain -s') +# config.bind('yP', 'yank pretty-url -s') +# config.bind('yT', 'yank title -s') +# config.bind('yY', 'yank -s') +# config.bind('yd', 'yank domain') +# config.bind('yp', 'yank pretty-url') +# config.bind('yt', 'yank title') +# config.bind('yy', 'yank') +# config.bind('{{', 'navigate prev -t') +# config.bind('}}', 'navigate next -t') + +## Custom normal mode bindings +# open url with mpv +config.bind(',v', 'spawn mpv {url}') +config.bind(',fv', 'hint links spawn mpv {hint-url}') +config.bind(',Fv', 'hint all spawn mpv {hint-url}') +config.bind(',V', 'spawn /home/taamas/scripts/floats/mpvFloat.sh {url}') +config.bind(',fV', 'hint links spawn mpvFloat.sh {hint-url}') +config.bind(',FV', 'hint all spawn mpvFloat.sh {hint-url}') +#download url's video +config.bind(',d', 'spawn youtube-dl --all-subs --embed-subs -o ~/downloads/videos/%(title)s.%(ext)s {url}') +# same as previous, but showing urxvt +config.bind(',D', 'spawn /home/taamas/scripts/floats/youtube-dlFloat.sh {url}') +# two same commands, using hints instead than current url +config.bind(',fd', 'hint links spawn youtube-dl.sh {hint-url}') +config.bind(',Fd', 'hint all spawn youtube-dl.sh {hint-url}') +config.bind(',fD', 'hint links spawn /home/taamas/scripts/floats/youtube-dlFloat.sh {hint-url}') +config.bind(',FD', 'hint all spawn /home/taamas/scripts/floats/youtube-dlFloat.sh {hint-url}') +# download url's audio in mp3 in ~/music/qutebrowser +config.bind(',a', 'spawn youtube-dl -o ~/music/qutebrowser/%(title)s.%(ext)s -x --audio-format mp3 --embed-thumbnail {url}') +# same as previous, but showing urxvt +config.bind(',A', 'spawn /home/taamas/scripts/floats/youtube-dlFloatAudio.sh {url}') +# two same commands, using hints instead than current url +config.bind(',fa', 'hint links spawn /home/taamas/scripts/floats/youtube-dlAudio.sh {hint-url}') +config.bind(',Fa', 'hint all spawn /home/taamas/scripts/floats/youtube-dlAudio.sh {hint-url}') +config.bind(',fA', 'hint links spawn /home/taamas/scripts/floats/youtube-dlFloatAudio.sh {hint-url}') +config.bind(',FA', 'hint all spawn /home/taamas/scripts/floats/youtube-dlFloatAudio.sh {hint-url}') +# open images with corresponding script +config.bind(',i', 'spawn showURLimage.sh {url}') +config.bind(',fi', 'hint images spawn showURLimage.sh {hint-url}') +config.bind(',fI', 'hint all spawn showURLimage.sh {hint-url}') +# ripme bulk image downloading +config.bind(',rm', 'spawn ripme.sh {url}') +config.bind(',frm', 'hint links spawn ripme.sh {hint-url}') + +## Bindings for caret mode +# config.bind('$', 'move-to-end-of-line', mode='caret') +# config.bind('0', 'move-to-start-of-line', mode='caret') +# config.bind('', 'drop-selection', mode='caret') +# config.bind('', 'leave-mode', mode='caret') +# config.bind('', 'yank selection', mode='caret') +# config.bind('', 'toggle-selection', mode='caret') +# config.bind('G', 'move-to-end-of-document', mode='caret') +# config.bind('H', 'scroll left', mode='caret') +# config.bind('J', 'scroll down', mode='caret') +# config.bind('K', 'scroll up', mode='caret') +# config.bind('L', 'scroll right', mode='caret') +# config.bind('Y', 'yank selection -s', mode='caret') +# config.bind('[', 'move-to-start-of-prev-block', mode='caret') +# config.bind(']', 'move-to-start-of-next-block', mode='caret') +# config.bind('b', 'move-to-prev-word', mode='caret') +# config.bind('c', 'enter-mode normal', mode='caret') +# config.bind('e', 'move-to-end-of-word', mode='caret') +# config.bind('gg', 'move-to-start-of-document', mode='caret') +# config.bind('h', 'move-to-prev-char', mode='caret') +# config.bind('j', 'move-to-next-line', mode='caret') +# config.bind('k', 'move-to-prev-line', mode='caret') +# config.bind('l', 'move-to-next-char', mode='caret') +# config.bind('v', 'toggle-selection', mode='caret') +# config.bind('w', 'move-to-next-word', mode='caret') +# config.bind('y', 'yank selection', mode='caret') +# config.bind('{', 'move-to-end-of-prev-block', mode='caret') +# config.bind('}', 'move-to-end-of-next-block', mode='caret') + +## Bindings for command mode +# config.bind('', 'rl-backward-word', mode='command') +# config.bind('', 'rl-backward-kill-word', mode='command') +# config.bind('', 'rl-kill-word', mode='command') +# config.bind('', 'rl-forward-word', mode='command') +# config.bind('', 'rl-delete-char', mode='command') +# config.bind('', 'rl-beginning-of-line', mode='command') +# config.bind('', 'rl-backward-char', mode='command') +# config.bind('', 'completion-item-yank', mode='command') +# config.bind('', 'completion-item-del', mode='command') +# config.bind('', 'rl-end-of-line', mode='command') +# config.bind('', 'rl-forward-char', mode='command') +# config.bind('', 'rl-backward-delete-char', mode='command') +# config.bind('', 'rl-kill-line', mode='command') +# config.bind('', 'command-history-next', mode='command') +# config.bind('', 'command-history-prev', mode='command') +# config.bind('', 'command-accept --rapid', mode='command') +# config.bind('', 'completion-item-yank --sel', mode='command') +# config.bind('', 'completion-item-focus prev-category', mode='command') +# config.bind('', 'completion-item-focus next-category', mode='command') +# config.bind('', 'rl-unix-line-discard', mode='command') +# config.bind('', 'rl-unix-word-rubout', mode='command') +# config.bind('', 'rl-yank', mode='command') +# config.bind('', 'completion-item-focus --history next', mode='command') +# config.bind('', 'leave-mode', mode='command') +# config.bind('', 'command-accept', mode='command') +# config.bind('', 'completion-item-del', mode='command') +# config.bind('', 'completion-item-focus prev', mode='command') +# config.bind('', 'completion-item-focus next', mode='command') +# config.bind('', 'completion-item-focus --history prev', mode='command') + +## Bindings for hint mode +# config.bind('', 'hint all tab-bg', mode='hint') +# config.bind('', 'hint links', mode='hint') +# config.bind('', 'hint --rapid links tab-bg', mode='hint') +# config.bind('', 'leave-mode', mode='hint') +# config.bind('', 'follow-hint', mode='hint') + +## Bindings for insert mode +# config.bind('', 'open-editor', mode='insert') +# config.bind('', 'leave-mode', mode='insert') +# config.bind('', 'insert-text {primary}', mode='insert') + +## Bindings for passthrough mode +# config.bind('', 'leave-mode', mode='passthrough') + +## Bindings for prompt mode +# config.bind('', 'rl-backward-word', mode='prompt') +# config.bind('', 'rl-backward-kill-word', mode='prompt') +# config.bind('', 'rl-kill-word', mode='prompt') +# config.bind('', 'rl-forward-word', mode='prompt') +# config.bind('', 'rl-delete-char', mode='prompt') +# config.bind('', 'rl-beginning-of-line', mode='prompt') +# config.bind('', 'rl-backward-char', mode='prompt') +# config.bind('', 'rl-end-of-line', mode='prompt') +# config.bind('', 'rl-forward-char', mode='prompt') +# config.bind('', 'rl-backward-delete-char', mode='prompt') +# config.bind('', 'rl-kill-line', mode='prompt') +# config.bind('', 'rl-unix-line-discard', mode='prompt') +# config.bind('', 'rl-unix-word-rubout', mode='prompt') +# config.bind('', 'prompt-open-download', mode='prompt') +# config.bind('', 'rl-yank', mode='prompt') +# config.bind('', 'prompt-item-focus next', mode='prompt') +# config.bind('', 'leave-mode', mode='prompt') +# config.bind('', 'prompt-accept', mode='prompt') +# config.bind('', 'prompt-item-focus prev', mode='prompt') +# config.bind('', 'prompt-item-focus next', mode='prompt') +# config.bind('', 'prompt-item-focus prev', mode='prompt') +# config.bind('n', 'prompt-accept no', mode='prompt') +# config.bind('y', 'prompt-accept yes', mode='prompt') + +## Bindings for register mode +# config.bind('', 'leave-mode', mode='register') + +dracula.draw.blood(c, { + 'spacing': { + 'vertical': 3, + 'horizontal': 8 + } +}) diff --git a/stow/qutebrowser/dot-config/qutebrowser/config.py b/stow/qutebrowser/dot-config/qutebrowser/config.py deleted file mode 100644 index 433a9cc..0000000 --- a/stow/qutebrowser/dot-config/qutebrowser/config.py +++ /dev/null @@ -1,1729 +0,0 @@ -import dracula.draw - -## Autogenerated config.py -## Documentation: -## qute://help/configuring.html -## qute://help/settings.html - -## This is here so configs done via the GUI are still loaded. -## Remove it to not load settings done via the GUI. -config.load_autoconfig() - -## Aliases for commands. The keys of the given dictionary are the -## aliases, while the values are the commands they map to. -## Type: Dict -# c.aliases = {'w': 'session-save', 'q': 'quit', 'wq': 'quit --save'} - -## Time interval (in milliseconds) between auto-saves of -## config/cookies/etc. -## Type: Int -# c.auto_save.interval = 15000 - -## Always restore open sites when qutebrowser is reopened. -## Type: Bool -# c.auto_save.session = False - -## Backend to use to display websites. qutebrowser supports two different -## web rendering engines / backends, QtWebKit and QtWebEngine. QtWebKit -## was discontinued by the Qt project with Qt 5.6, but picked up as a -## well maintained fork: https://github.com/annulen/webkit/wiki - -## qutebrowser only supports the fork. QtWebEngine is Qt's official -## successor to QtWebKit. It's slightly more resource hungry than -## QtWebKit and has a couple of missing features in qutebrowser, but is -## generally the preferred choice. -## Type: String -## Valid values: -## - webengine: Use QtWebEngine (based on Chromium). -## - webkit: Use QtWebKit (based on WebKit, similar to Safari). -# c.backend = 'webengine' - -## This setting can be used to map keys to other keys. When the key used -## as dictionary-key is pressed, the binding for the key used as -## dictionary-value is invoked instead. This is useful for global -## remappings of keys, for example to map Ctrl-[ to Escape. Note that -## when a key is bound (via `bindings.default` or `bindings.commands`), -## the mapping is ignored. -## Type: Dict -# c.bindings.key_mappings = {'': '', '': '', '': '', '': '', '': '', '': '', '': '', '': ''} - -## Background color of the completion widget category headers. -## Type: QssColor -# c.colors.completion.category.bg = 'qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #888888, stop:1 #505050)' - -## Bottom border color of the completion widget category headers. -## Type: QssColor -# c.colors.completion.category.border.bottom = 'black' - -## Top border color of the completion widget category headers. -## Type: QssColor -# c.colors.completion.category.border.top = 'black' - -## Foreground color of completion widget category headers. -## Type: QtColor -# c.colors.completion.category.fg = 'white' - -## Background color of the completion widget for even rows. -## Type: QssColor -# c.colors.completion.even.bg = '#333333' - -## Text color of the completion widget. May be a single color to use for -## all columns or a list of three colors, one for each column. -## Type: List of QtColor, or QtColor -# c.colors.completion.fg = ['white', 'white', 'white'] - -## Background color of the selected completion item. -## Type: QssColor -# c.colors.completion.item.selected.bg = '#e8c000' - -## Bottom border color of the selected completion item. -## Type: QssColor -# c.colors.completion.item.selected.border.bottom = '#bbbb00' - -## Top border color of the completion widget category headers. -## Type: QssColor -# c.colors.completion.item.selected.border.top = '#bbbb00' - -## Foreground color of the selected completion item. -## Type: QtColor -# c.colors.completion.item.selected.fg = 'black' - -## Foreground color of the matched text in the completion. -## Type: QssColor -# c.colors.completion.match.fg = '#ff4444' - -## Background color of the completion widget for odd rows. -## Type: QssColor -# c.colors.completion.odd.bg = '#444444' - -## Color of the scrollbar in the completion view. -## Type: QssColor -# c.colors.completion.scrollbar.bg = '#333333' - -## Color of the scrollbar handle in the completion view. -## Type: QssColor -# c.colors.completion.scrollbar.fg = 'white' - -## Background color for the download bar. -## Type: QssColor -# c.colors.downloads.bar.bg = 'black' - -## Background color for downloads with errors. -## Type: QtColor -# c.colors.downloads.error.bg = 'red' - -## Foreground color for downloads with errors. -## Type: QtColor -# c.colors.downloads.error.fg = 'white' - -## Color gradient start for download backgrounds. -## Type: QtColor -# c.colors.downloads.start.bg = '#0000aa' - -## Color gradient start for download text. -## Type: QtColor -# c.colors.downloads.start.fg = 'white' - -## Color gradient stop for download backgrounds. -## Type: QtColor -# c.colors.downloads.stop.bg = '#00aa00' - -## Color gradient end for download text. -## Type: QtColor -# c.colors.downloads.stop.fg = 'white' - -## Color gradient interpolation system for download backgrounds. -## Type: ColorSystem -## Valid values: -## - rgb: Interpolate in the RGB color system. -## - hsv: Interpolate in the HSV color system. -## - hsl: Interpolate in the HSL color system. -## - none: Don't show a gradient. -# c.colors.downloads.system.bg = 'rgb' - -## Color gradient interpolation system for download text. -## Type: ColorSystem -## Valid values: -## - rgb: Interpolate in the RGB color system. -## - hsv: Interpolate in the HSV color system. -## - hsl: Interpolate in the HSL color system. -## - none: Don't show a gradient. -# c.colors.downloads.system.fg = 'rgb' - -## Background color for hints. Note that you can use a `rgba(...)` value -## for transparency. -## Type: QssColor -# c.colors.hints.bg = 'qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 247, 133, 0.8), stop:1 rgba(255, 197, 66, 0.8))' -c.colors.hints.bg = 'qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0, 0, 255, 0.8), stop:1 rgba(255, 0, 255, 0.8))' - -## Font color for hints. -## Type: QssColor -# c.colors.hints.fg = 'black' -c.colors.hints.fg = 'white' - -## Font color for the matched part of hints. -## Type: QssColor -# c.colors.hints.match.fg = 'green' -c.colors.hints.match.fg = 'yellow' - -## Background color of the keyhint widget. -## Type: QssColor -# c.colors.keyhint.bg = 'rgba(0, 0, 0, 80%)' - -## Text color for the keyhint widget. -## Type: QssColor -# c.colors.keyhint.fg = '#FFFFFF' - -## Highlight color for keys to complete the current keychain. -## Type: QssColor -# c.colors.keyhint.suffix.fg = '#FFFF00' - -## Background color of an error message. -## Type: QssColor -# c.colors.messages.error.bg = 'red' - -## Border color of an error message. -## Type: QssColor -# c.colors.messages.error.border = '#bb0000' - -## Foreground color of an error message. -## Type: QssColor -# c.colors.messages.error.fg = 'white' - -## Background color of an info message. -## Type: QssColor -# c.colors.messages.info.bg = 'black' - -## Border color of an info message. -## Type: QssColor -# c.colors.messages.info.border = '#333333' - -## Foreground color of an info message. -## Type: QssColor -# c.colors.messages.info.fg = 'white' - -## Background color of a warning message. -## Type: QssColor -# c.colors.messages.warning.bg = 'darkorange' - -## Border color of a warning message. -## Type: QssColor -# c.colors.messages.warning.border = '#d47300' - -## Foreground color of a warning message. -## Type: QssColor -# c.colors.messages.warning.fg = 'white' - -## Background color for prompts. -## Type: QssColor -# c.colors.prompts.bg = '#444444' - -## Border used around UI elements in prompts. -## Type: String -# c.colors.prompts.border = '1px solid gray' - -## Foreground color for prompts. -## Type: QssColor -# c.colors.prompts.fg = 'white' - -## Background color for the selected item in filename prompts. -## Type: QssColor -# c.colors.prompts.selected.bg = 'grey' - -## Background color of the statusbar in caret mode. -## Type: QssColor -# c.colors.statusbar.caret.bg = 'purple' - -## Foreground color of the statusbar in caret mode. -## Type: QssColor -# c.colors.statusbar.caret.fg = 'white' - -## Background color of the statusbar in caret mode with a selection. -## Type: QssColor -# c.colors.statusbar.caret.selection.bg = '#a12dff' - -## Foreground color of the statusbar in caret mode with a selection. -## Type: QssColor -# c.colors.statusbar.caret.selection.fg = 'white' - -## Background color of the statusbar in command mode. -## Type: QssColor -# c.colors.statusbar.command.bg = 'black' - -## Foreground color of the statusbar in command mode. -## Type: QssColor -# c.colors.statusbar.command.fg = 'white' - -## Background color of the statusbar in private browsing + command mode. -## Type: QssColor -# c.colors.statusbar.command.private.bg = 'grey' - -## Foreground color of the statusbar in private browsing + command mode. -## Type: QssColor -# c.colors.statusbar.command.private.fg = 'white' - -## Background color of the statusbar in insert mode. -## Type: QssColor -# c.colors.statusbar.insert.bg = 'darkgreen' -c.colors.statusbar.insert.bg = '#3fff00' #Harlequin - -## Foreground color of the statusbar in insert mode. -## Type: QssColor -# c.colors.statusbar.insert.fg = 'white' -c.colors.statusbar.insert.fg = 'black' - -## Background color of the statusbar. -## Type: QssColor -# c.colors.statusbar.normal.bg = 'black' - -## Foreground color of the statusbar. -## Type: QssColor -# c.colors.statusbar.normal.fg = 'white' - -## Background color of the statusbar in passthrough mode. -## Type: QssColor -# c.colors.statusbar.passthrough.bg = 'darkblue' -c.colors.statusbar.passthrough.bg = '#3f00ff' - -## Foreground color of the statusbar in passthrough mode. -## Type: QssColor -# c.colors.statusbar.passthrough.fg = 'white' - -## Background color of the statusbar in private browsing mode. -## Type: QssColor -# c.colors.statusbar.private.bg = '#666666' - -## Foreground color of the statusbar in private browsing mode. -## Type: QssColor -# c.colors.statusbar.private.fg = 'white' - -## Background color of the progress bar. -## Type: QssColor -# c.colors.statusbar.progress.bg = 'white' - -## Foreground color of the URL in the statusbar on error. -## Type: QssColor -# c.colors.statusbar.url.error.fg = 'orange' - -## Default foreground color of the URL in the statusbar. -## Type: QssColor -# c.colors.statusbar.url.fg = 'white' - -## Foreground color of the URL in the statusbar for hovered links. -## Type: QssColor -# c.colors.statusbar.url.hover.fg = 'aqua' - -## Foreground color of the URL in the statusbar on successful load -## (http). -## Type: QssColor -# c.colors.statusbar.url.success.http.fg = 'white' - -## Foreground color of the URL in the statusbar on successful load -## (https). -## Type: QssColor -# c.colors.statusbar.url.success.https.fg = 'lime' -c.colors.statusbar.url.success.https.fg = 'white' - -## Foreground color of the URL in the statusbar when there's a warning. -## Type: QssColor -# c.colors.statusbar.url.warn.fg = 'yellow' - -## Background color of the tab bar. -## Type: QtColor -# c.colors.tabs.bar.bg = '#555555' - -## Background color of unselected even tabs. -## Type: QtColor -# c.colors.tabs.even.bg = 'darkgrey' -c.colors.tabs.even.bg = 'black' - -## Foreground color of unselected even tabs. -## Type: QtColor -# c.colors.tabs.even.fg = 'white' -c.colors.tabs.even.fg = '#9F9F9F' - -## Color for the tab indicator on errors. -## Type: QtColor -# c.colors.tabs.indicator.error = '#ff0000' - -## Color gradient start for the tab indicator. -## Type: QtColor -# c.colors.tabs.indicator.start = '#0000aa' - -## Color gradient end for the tab indicator. -## Type: QtColor -# c.colors.tabs.indicator.stop = '#00aa00' - -## Color gradient interpolation system for the tab indicator. -## Type: ColorSystem -## Valid values: -## - rgb: Interpolate in the RGB color system. -## - hsv: Interpolate in the HSV color system. -## - hsl: Interpolate in the HSL color system. -## - none: Don't show a gradient. -# c.colors.tabs.indicator.system = 'rgb' - -## Background color of unselected odd tabs. -## Type: QtColor -# c.colors.tabs.odd.bg = 'grey' -#c.colors.tabs.odd.bg = '#5F5F5F' -c.colors.tabs.odd.bg = 'black' - -## Foreground color of unselected odd tabs. -## Type: QtColor -# c.colors.tabs.odd.fg = 'white' -c.colors.tabs.odd.fg = '#9F9F9F' - -## Background color of selected even tabs. -## Type: QtColor -# c.colors.tabs.selected.even.bg = 'black' - -## Foreground color of selected even tabs. -## Type: QtColor -# c.colors.tabs.selected.even.fg = 'white' - -## Background color of selected odd tabs. -## Type: QtColor -# c.colors.tabs.selected.odd.bg = 'black' - -## Foreground color of selected odd tabs. -## Type: QtColor -# c.colors.tabs.selected.odd.fg = 'white' - -## Background color for webpages if unset (or empty to use the theme's -## color). -## Type: QtColor -# c.colors.webpage.bg = 'white' - -## Number of commands to save in the command history. 0: no history / -1: -## unlimited -## Type: Int -# c.completion.cmd_history_max_items = 100 - -## Delay (in milliseconds) before updating completions after typing a -## character. -## Type: Int -# c.completion.delay = 0 - -## Height (in pixels or as percentage of the window) of the completion. -## Type: PercOrInt -# c.completion.height = '50%' -c.completion.height = '30%' - -## Minimum amount of characters needed to update completions. -## Type: Int -# c.completion.min_chars = 1 - -## Move on to the next part when there's only one possible completion -## left. -## Type: Bool -# c.completion.quick = True - -## Padding (in pixels) of the scrollbar handle in the completion window. -## Type: Int -# c.completion.scrollbar.padding = 2 - -## Width (in pixels) of the scrollbar in the completion window. -## Type: Int -# c.completion.scrollbar.width = 12 - -## When to show the autocompletion window. -## Type: String -## Valid values: -## - always: Whenever a completion is available. -## - auto: Whenever a completion is requested. -## - never: Never. -# c.completion.show = 'always' - -## Shrink the completion to be smaller than the configured size if there -## are no scrollbars. -## Type: Bool -# c.completion.shrink = False - -## Format of timestamps (e.g. for the history completion). -## Type: TimestampTemplate -# c.completion.timestamp_format = '%Y-%m-%d' - -## Execute the best-matching command on a partial match. -## Type: Bool -# c.completion.use_best_match = False - -## Number of URLs to show in the web history. 0: no history / -1: -## unlimited -## Type: Int -# c.completion.web_history_max_items = -1 - -## Require a confirmation before quitting the application. -## Type: ConfirmQuit -## Valid values: -## - always: Always show a confirmation. -## - multiple-tabs: Show a confirmation if multiple tabs are opened. -## - downloads: Show a confirmation if downloads are running -## - never: Never show a confirmation. -# c.confirm_quit = ['never'] - -## Enable support for the HTML 5 web application cache feature. An -## application cache acts like an HTTP cache in some sense. For documents -## that use the application cache via JavaScript, the loader engine will -## first ask the application cache for the contents, before hitting the -## network. -## Type: Bool -# c.content.cache.appcache = True - -## Maximum number of pages to hold in the global memory page cache. The -## page cache allows for a nicer user experience when navigating forth or -## back to pages in the forward/back history, by pausing and resuming up -## to _n_ pages. For more information about the feature, please refer to: -## http://webkit.org/blog/427/webkit-page-cache-i-the-basics/ -## Type: Int -# c.content.cache.maximum_pages = 0 - -## Size (in bytes) of the HTTP network cache. Null to use the default -## value. With QtWebEngine, the maximum supported value is 2147483647 (~2 -## GB). -## Type: Int -# c.content.cache.size = None - -## Which cookies to accept. -## Type: String -## Valid values: -## - all: Accept all cookies. -## - no-3rdparty: Accept cookies from the same origin only. -## - no-unknown-3rdparty: Accept cookies from the same origin only, unless a cookie is already set for the domain. -## - never: Don't accept cookies at all. -# c.content.cookies.accept = 'no-3rdparty' - -## Store cookies. Note this option needs a restart with QtWebEngine on Qt -## < 5.9. -## Type: Bool -# c.content.cookies.store = True - -## Default encoding to use for websites. The encoding must be a string -## describing an encoding such as _utf-8_, _iso-8859-1_, etc. -## Type: String -# c.content.default_encoding = 'iso-8859-1' - -## Enable extra tools for Web developers. This needs to be enabled for -## `:inspector` to work and also adds an _Inspect_ entry to the context -## menu. For QtWebEngine, see `--enable-webengine-inspector` in -## `qutebrowser --help` instead. -## Type: Bool -# c.content.developer_extras = False -#c.content.developer_extras = True - -## Try to pre-fetch DNS entries to speed up browsing. -## Type: Bool -# c.content.dns_prefetch = True - -## Expand each subframe to its contents. This will flatten all the frames -## to become one scrollable page. -## Type: Bool -# c.content.frame_flattening = False - -## Allow websites to request geolocations. -## Type: BoolAsk -## Valid values: -## - true -## - false -## - ask -# c.content.geolocation = 'ask' - -## Value to send in the `Accept-Language` header. -## Type: String -# c.content.headers.accept_language = 'en-US,en' - -## Custom headers for qutebrowser HTTP requests. -## Type: Dict -# c.content.headers.custom = {} - -## Value to send in the `DNT` header. When this is set to true, -## qutebrowser asks websites to not track your identity. If set to null, -## the DNT header is not sent at all. -## Type: Bool -# c.content.headers.do_not_track = True - -## When to send the Referer header. The Referer header tells websites -## from which website you were coming from when visting them. -## Type: String -## Valid values: -## - always: Always send the Referer. -## - never: Never send the Referer. This is not recommended, as some sites may break. -## - same-domain: Only send the Referer for the same domain. This will still protect your privacy, but shouldn't break any sites. -# c.content.headers.referer = 'same-domain' - -## User agent to send. Unset to send the default. -## Type: String -# c.content.headers.user_agent = None - -## Enable host blocking. -## Type: Bool -# c.content.host_blocking.enabled = True - -## List of URLs of lists which contain hosts to block. The file can be -## in one of the following formats: - An `/etc/hosts`-like file - One -## host per line - A zip-file of any of the above, with either only one -## file, or a file named `hosts` (with any extension). -## Type: List of Url -# c.content.host_blocking.lists = ['https://www.malwaredomainlist.com/hostslist/hosts.txt', 'http://someonewhocares.org/hosts/hosts', 'http://winhelp2002.mvps.org/hosts.zip', 'http://malwaredomains.lehigh.edu/files/justdomains.zip', 'https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&mimetype=plaintext'] - -## List of domains that should always be loaded, despite being ad- -## blocked. Domains may contain * and ? wildcards and are otherwise -## required to exactly match the requested domain. Local domains are -## always exempt from hostblocking. -## Type: List of String -# c.content.host_blocking.whitelist = ['piwik.org'] - -## Enable hyperlink auditing (``). -## Type: Bool -# c.content.hyperlink_auditing = False - -## Load images automatically in web pages. -## Type: Bool -# c.content.images = True - -## Show javascript alerts. -## Type: Bool -# c.content.javascript.alert = True - -## Allow JavaScript to read from or write to the clipboard. With -## QtWebEngine, writing the clipboard as response to a user interaction -## is always allowed. -## Type: Bool -# c.content.javascript.can_access_clipboard = False - -## Allow JavaScript to close tabs. -## Type: Bool -# c.content.javascript.can_close_tabs = False - -## Allow JavaScript to open new tabs without user interaction. -## Type: Bool -# c.content.javascript.can_open_tabs_automatically = False - -## Enable JavaScript. -## Type: Bool -# c.content.javascript.enabled = True - -## Log levels to use for JavaScript console logging messages. When a -## JavaScript message with the level given in the dictionary key is -## logged, the corresponding dictionary value selects the qutebrowser -## logger to use. On QtWebKit, the "unknown" setting is always used. -## Type: Dict -# c.content.javascript.log = {'unknown': 'debug', 'info': 'debug', 'warning': 'debug', 'error': 'debug'} - -## Use the standard JavaScript modal dialog for `alert()` and -## `confirm()`. -## Type: Bool -# c.content.javascript.modal_dialog = False - -## Show javascript prompts. -## Type: Bool -# c.content.javascript.prompt = True - -## Allow locally loaded documents to access other local URLs. -## Type: Bool -# c.content.local_content_can_access_file_urls = True - -## Allow locally loaded documents to access remote URLs. -## Type: Bool -# c.content.local_content_can_access_remote_urls = False - -## Enable support for HTML 5 local storage and Web SQL. -## Type: Bool -# c.content.local_storage = True - -## Allow websites to record audio/video. -## Type: BoolAsk -## Valid values: -## - true -## - false -## - ask -# c.content.media_capture = 'ask' - -## Netrc-file for HTTP authentication. If unset, `~/.netrc` is used. -## Type: File -# c.content.netrc_file = None - -## Allow websites to show notifications. -## Type: BoolAsk -## Valid values: -## - true -## - false -## - ask -# c.content.notifications = 'ask' - -## Allow pdf.js to view PDF files in the browser. Note that the files can -## still be downloaded by clicking the download button in the pdf.js -## viewer. -## Type: Bool -# c.content.pdfjs = False - -## Enable plugins in Web pages. -## Type: Bool -# c.content.plugins = False - -## Draw the background color and images also when the page is printed. -## Type: Bool -# c.content.print_element_backgrounds = True - -## Open new windows in private browsing mode which does not record -## visited pages. -## Type: Bool -# c.content.private_browsing = False - -## Proxy to use. In addition to the listed values, you can use a -## `socks://...` or `http://...` URL. -## Type: Proxy -## Valid values: -## - system: Use the system wide proxy. -## - none: Don't use any proxy -# c.content.proxy = 'system' - -## Send DNS requests over the configured proxy. -## Type: Bool -# c.content.proxy_dns_requests = True - -## Validate SSL handshakes. -## Type: BoolAsk -## Valid values: -## - true -## - false -## - ask -# c.content.ssl_strict = 'ask' - -## List of user stylesheet filenames to use. -## Type: List of File, or File -# c.content.user_stylesheets = [] - -## Enable WebGL. -## Type: Bool -# c.content.webgl = True - -## Limit fullscreen to the browser window (does not expand to fill the -## screen). -## Type: Bool -c.content.fullscreen.window = True - -## Monitor load requests for cross-site scripting attempts. Suspicious -## scripts will be blocked and reported in the inspector's JavaScript -## console. Enabling this feature might have an impact on performance. -## Type: Bool -# c.content.xss_auditing = False - -## Directory to save downloads to. If unset, a sensible OS-specific -## default is used. -## Type: Directory -# c.downloads.location.directory = None -c.downloads.location.directory = "~/downloads" - -## Prompt the user for the download location. If set to false, -## `downloads.location.directory` will be used. -## Type: Bool -# c.downloads.location.prompt = True - -## Remember the last used download directory. -## Type: Bool -# c.downloads.location.remember = True - -## What to display in the download filename input. -## Type: String -## Valid values: -## - path: Show only the download path. -## - filename: Show only download filename. -## - both: Show download path and filename. -# c.downloads.location.suggestion = 'path' - -## Default program used to open downloads. If null, the default internal -## handler is used. Any `{}` in the string will be expanded to the -## filename, else the filename will be appended. -## Type: String -# c.downloads.open_dispatcher = None -c.downloads.open_dispatcher = "rifle" - -## Where to show the downloaded files. -## Type: VerticalPosition -## Valid values: -## - top -## - bottom -# c.downloads.position = 'top' - -## Duration (in milliseconds) to wait before removing finished downloads. -## If set to -1, downloads are never removed. -## Type: Int -# c.downloads.remove_finished = -1 - -## Editor (and arguments) to use for the `open-editor` command. The -## following placeholders are defined: * `{file}`: Filename of the file -## to be edited. * `{line}`: Line in which the caret is found in the -## text. * `{column}`: Column in which the caret is found in the text. * -## `{line0}`: Same as `{line}`, but starting from index 0. * `{column0}`: -## Same as `{column}`, but starting from index 0. -## Type: ShellCommand -# c.editor.command = ['gvim', '-f', '{file}', '-c', 'normal {line}G{column0}l'] -c.editor.command = ['urxvt', '-title', '"floating"', '-e', 'nvim', '{file}'] - -## Encoding to use for the editor. -## Type: Encoding -# c.editor.encoding = 'utf-8' - -## Font used in the completion categories. -## Type: Font -# c.fonts.completion.category = 'bold 10pt monospace' -c.fonts.completion.category = 'bold 10pt serif' - -## Font used in the completion widget. -## Type: Font -# c.fonts.completion.entry = '10pt monospace' -c.fonts.completion.entry = '10pt serif' - -## Font used for the debugging console. -## Type: QtFont -# c.fonts.debug_console = '10pt monospace' -c.fonts.debug_console = '10pt serif' - -## Font used for the downloadbar. -## Type: Font -# c.fonts.downloads = '10pt monospace' -c.fonts.downloads = '10pt serif' - -## Font used for the hints. -## Type: Font -# c.fonts.hints = 'bold 10pt monospace' -c.fonts.hints = 'bold 10pt Inconsolata' - -## Font used in the keyhint widget. -## Type: Font -# c.fonts.keyhint = '10pt monospace' -c.fonts.keyhint = '10pt serif' - -## Font used for error messages. -## Type: Font -# c.fonts.messages.error = '10pt monospace' -c.fonts.messages.error = '10pt serif' - -## Font used for info messages. -## Type: Font -# c.fonts.messages.info = '10pt monospace' -c.fonts.messages.info = '10pt serif' - -## Font used for warning messages. -## Type: Font -# c.fonts.messages.warning = '10pt monospace' -c.fonts.messages.warning = '10pt serif' - -## Default monospace fonts. Whenever "monospace" is used in a font -## setting, it's replaced with the fonts listed here. -## Type: Font -# c.fonts.monospace = '"xos4 Terminus", Terminus, Monospace, "DejaVu Sans Mono", Monaco, "Bitstream Vera Sans Mono", "Andale Mono", "Courier New", Courier, "Liberation Mono", monospace, Fixed, Consolas, Terminal' - -## Font used for prompts. -## Type: Font -# c.fonts.prompts = '10pt sans-serif' - -## Font used in the statusbar. -## Type: Font -# c.fonts.statusbar = '10pt monospace' -c.fonts.statusbar = '10pt Linux Libertine' - -## Font used in the tab bar. -## Type: QtFont -# c.fonts.tabs = '10pt monospace' -# No longer exists (Thu 16 Jul 2020 01:39:46 AM CEST) -c.fonts.tabs.selected = '10pt serif' -c.fonts.tabs.unselected = '10pt serif' - -## Font family for cursive fonts. -## Type: FontFamily -# c.fonts.web.family.cursive = '' - -## Font family for fantasy fonts. -## Type: FontFamily -# c.fonts.web.family.fantasy = '' - -## Font family for fixed fonts. -## Type: FontFamily -# c.fonts.web.family.fixed = '' - -## Font family for sans-serif fonts. -## Type: FontFamily -# c.fonts.web.family.sans_serif = '' - -## Font family for serif fonts. -## Type: FontFamily -# c.fonts.web.family.serif = '' - -## Font family for standard fonts. -## Type: FontFamily -# c.fonts.web.family.standard = '' - -## Default font size (in pixels) for regular text. -## Type: Int -# c.fonts.web.size.default = 16 - -## Default font size (in pixels) for fixed-pitch text. -## Type: Int -# c.fonts.web.size.default_fixed = 13 - -## Hard minimum font size (in pixels). -## Type: Int -# c.fonts.web.size.minimum = 0 - -## Minimum logical font size (in pixels) that is applied when zooming -## out. -## Type: Int -# c.fonts.web.size.minimum_logical = 6 - -## When a hint can be automatically followed without pressing Enter. -## Type: String -## Valid values: -## - always: Auto-follow whenever there is only a single hint on a page. -## - unique-match: Auto-follow whenever there is a unique non-empty match in either the hint string (word mode) or filter (number mode). -## - full-match: Follow the hint when the user typed the whole hint (letter, word or number mode) or the element's text (only in number mode). -## - never: The user will always need to press Enter to follow a hint. -# c.hints.auto_follow = 'unique-match' - -## Duration (in milliseconds) to ignore normal-mode key bindings after a -## successful auto-follow. -## Type: Int -# c.hints.auto_follow_timeout = 0 - -## CSS border value for hints. -## Type: String -# c.hints.border = '1px solid #E3BE23' -c.hints.border = '1px solid #000000' - -## Characters used for hint strings. -## Type: UniqueCharString -# c.hints.chars = 'asdfghjkl' -c.hints.chars = 'asdfjklรฑ' - -## Dictionary file to be used by the word hints. -## Type: File -# c.hints.dictionary = '/usr/share/dict/words' - -## Which implementation to use to find elements to hint. -## Type: String -## Valid values: -## - javascript: Better but slower -## - python: Slightly worse but faster -# c.hints.find_implementation = 'python' -c.hints.find_implementation = 'javascript' - -## Hide unmatched hints in rapid mode. -## Type: Bool -# c.hints.hide_unmatched_rapid_hints = True - -## Minimum number of characters used for hint strings. -## Type: Int -# c.hints.min_chars = 1 -c.hints.min_chars = 2 - -## Mode to use for hints. -## Type: String -## Valid values: -## - number: Use numeric hints. (In this mode you can also type letters from the hinted element to filter and reduce the number of elements that are hinted.) -## - letter: Use the characters in the `hints.chars` setting. -## - word: Use hints words based on the html elements and the extra words. -# c.hints.mode = 'letter' -c.hints.mode = 'letter' - -## Comma-separated list of regular expressions to use for 'next' links. -## Type: List of Regex -# c.hints.next_regexes = ['\\bnext\\b', '\\bmore\\b', '\\bnewer\\b', '\\b[>โ†’โ‰ซ]\\b', '\\b(>>|ยป)\\b', '\\bcontinue\\b'] - -## Comma-separated list of regular expressions to use for 'prev' links. -## Type: List of Regex -# c.hints.prev_regexes = ['\\bprev(ious)?\\b', '\\bback\\b', '\\bolder\\b', '\\b[<โ†โ‰ช]\\b', '\\b(<<|ยซ)\\b'] - -## Scatter hint key chains (like Vimium) or not (like dwb). Ignored for -## number hints. -## Type: Bool -# c.hints.scatter = True - -## Make characters in hint strings uppercase. -## Type: Bool -# c.hints.uppercase = False - -## Maximum time (in minutes) between two history items for them to be -## considered being from the same browsing session. Items with less time -## between them are grouped when being displayed in `:history`. Use -1 to -## disable separation. -## Type: Int -# c.history_gap_interval = 30 - -## Which unbound keys to forward to the webview in normal mode. -## Type: String -## Valid values: -## - all: Forward all unbound keys. -## - auto: Forward unbound non-alphanumeric keys. -## - none: Don't forward any keys. -# c.input.forward_unbound_keys = 'auto' - -## Leave insert mode if a non-editable element is clicked. -## Type: Bool -# c.input.insert_mode.auto_leave = True - -## Automatically enter insert mode if an editable element is focused -## after loading the page. -## Type: Bool -# c.input.insert_mode.auto_load = False -c.input.insert_mode.auto_load = True - -## Switch to insert mode when clicking flash and other plugins. -## Type: Bool -# c.input.insert_mode.plugins = False - -## Include hyperlinks in the keyboard focus chain when tabbing. -## Type: Bool -# c.input.links_included_in_focus_chain = True - -## Timeout (in milliseconds) for partially typed key bindings. If the -## current input forms only partial matches, the keystring will be -## cleared after this time. -## Type: Int -# c.input.partial_timeout = 5000 - -## Enable Opera-like mouse rocker gestures. This disables the context -## menu. -## Type: Bool -# c.input.rocker_gestures = False - -## Enable spatial navigation. Spatial navigation consists in the ability -## to navigate between focusable elements in a Web page, such as -## hyperlinks and form controls, by using Left, Right, Up and Down arrow -## keys. For example, if the user presses the Right key, heuristics -## determine whether there is an element he might be trying to reach -## towards the right and which element he probably wants. -## Type: Bool -# c.input.spatial_navigation = False - -## Keychains that shouldn't be shown in the keyhint dialog. Globs are -## supported, so `;*` will blacklist all keychains starting with `;`. Use -## `*` to disable keyhints. -## Type: List of String -# c.keyhint.blacklist = [] - -## Time (in milliseconds) from pressing a key to seeing the keyhint -## dialog. -## Type: Int -# c.keyhint.delay = 500 - -## Rounding radius (in pixels) for the edges of the keyhint dialog. -## Type: Int -# c.keyhint.radius = 6 - -## Duration (in milliseconds) to show messages in the statusbar for. Set -## to 0 to never clear messages. -## Type: Int -# c.messages.timeout = 2000 - -## How to open links in an existing instance if a new one is launched. -## This happens when e.g. opening a link from a terminal. See -## `new_instance_open_target_window` to customize in which window the -## link is opened in. -## Type: String -## Valid values: -## - tab: Open a new tab in the existing window and activate the window. -## - tab-bg: Open a new background tab in the existing window and activate the window. -## - tab-silent: Open a new tab in the existing window without activating the window. -## - tab-bg-silent: Open a new background tab in the existing window without activating the window. -## - window: Open in a new window. -# c.new_instance_open_target = 'tab' -c.new_instance_open_target = 'window' - -## Which window to choose when opening links as new tabs. When -## `new_instance_open_target` is not set to `window`, this is ignored. -## Type: String -## Valid values: -## - first-opened: Open new tabs in the first (oldest) opened window. -## - last-opened: Open new tabs in the last (newest) opened window. -## - last-focused: Open new tabs in the most recently focused window. -## - last-visible: Open new tabs in the most recently visible window. -# c.new_instance_open_target_window = 'last-focused' - -## Show a filebrowser in upload/download prompts. -## Type: Bool -# c.prompt.filebrowser = True - -## Rounding radius (in pixels) for the edges of prompts. -## Type: Int -# c.prompt.radius = 8 - -## Additional arguments to pass to Qt, without leading `--`. With -## QtWebEngine, some Chromium arguments (see -## https://peter.sh/experiments/chromium-command-line-switches/ for a -## list) will work. -## Type: List of String -# c.qt.args = [] - -## Force a Qt platform to use. This sets the `QT_QPA_PLATFORM` -## environment variable and is useful to force using the XCB plugin when -## running QtWebEngine on Wayland. -## Type: String -# c.qt.force_platform = None - -## Force software rendering for QtWebEngine. This is needed for -## QtWebEngine to work with Nouveau drivers. -## Type: Bool -# c.qt.force_software_rendering = False - -## Turn on Qt HighDPI scaling. This is equivalent to setting -## QT_AUTO_SCREEN_SCALE_FACTOR=1 in the environment. It's off by default -## as it can cause issues with some bitmap fonts. As an alternative to -## this, it's possible to set font sizes and the `zoom.default` setting. -## Type: Bool -# c.qt.highdpi = False - -## Show a scrollbar. -## Type: Bool -# c.scrolling.bar = False - -## Enable smooth scrolling for web pages. Note smooth scrolling does not -## work with the `:scroll-px` command. -## Type: Bool -# c.scrolling.smooth = False - -## When to find text on a page case-insensitively. -## Type: String -## Valid values: -## - always: Search case-insensitively. -## - never: Search case-sensitively. -## - smart: Search case-sensitively if there are capital characters. -# c.search.ignore_case = 'smart' - -## Find text on a page incrementally, renewing the search for each typed -## character. -## Type: Bool -# c.search.incremental = True - -## Name of the session to save by default. If this is set to null, the -## session which was last loaded is saved. -## Type: SessionName -# c.session.default_name = None - -## Load a restored tab as soon as it takes focus. -## Type: Bool -# c.session.lazy_restore = False - -## Languages to use for spell checking. You can check for available -## languages and install dictionaries using scripts/dictcli.py. Run the -## script with -h/--help for instructions. -## Type: List of String -## Valid values: -## - af-ZA: Afrikaans (South Africa) -## - bg-BG: Bulgarian (Bulgaria) -## - ca-ES: Catalan (Spain) -## - cs-CZ: Czech (Czech Republic) -## - da-DK: Danish (Denmark) -## - de-DE: German (Germany) -## - el-GR: Greek (Greece) -## - en-AU: English (Australia) -## - en-CA: English (Canada) -## - en-GB: English (United Kingdom) -## - en-US: English (United States) -## - es-ES: Spanish (Spain) -## - et-EE: Estonian (Estonia) -## - fa-IR: Farsi (Iran) -## - fo-FO: Faroese (Faroe Islands) -## - fr-FR: French (France) -## - he-IL: Hebrew (Israel) -## - hi-IN: Hindi (India) -## - hr-HR: Croatian (Croatia) -## - hu-HU: Hungarian (Hungary) -## - id-ID: Indonesian (Indonesia) -## - it-IT: Italian (Italy) -## - ko: Korean -## - lt-LT: Lithuanian (Lithuania) -## - lv-LV: Latvian (Latvia) -## - nb-NO: Norwegian (Norway) -## - nl-NL: Dutch (Netherlands) -## - pl-PL: Polish (Poland) -## - pt-BR: Portuguese (Brazil) -## - pt-PT: Portuguese (Portugal) -## - ro-RO: Romanian (Romania) -## - ru-RU: Russian (Russia) -## - sh: Serbo-Croatian -## - sk-SK: Slovak (Slovakia) -## - sl-SI: Slovenian (Slovenia) -## - sq: Albanian -## - sr: Serbian -## - sv-SE: Swedish (Sweden) -## - ta-IN: Tamil (India) -## - tg-TG: Tajik (Tajikistan) -## - tr-TR: Turkish (Turkey) -## - uk-UA: Ukrainian (Ukraine) -## - vi-VN: Vietnamese (Viet Nam) -# c.spellcheck.languages = [] - -## Hide the statusbar unless a message is shown. -## Type: Bool -# c.statusbar.hide = False -# No longer exists (Thu 16 Jul 2020 01:39:46 AM CEST) -c.statusbar.show = "in-mode" - -## Padding (in pixels) for the statusbar. -## Type: Padding -# c.statusbar.padding = {'top': 1, 'bottom': 1, 'left': 0, 'right': 0} - -## Position of the status bar. -## Type: VerticalPosition -## Valid values: -## - top -## - bottom -# c.statusbar.position = 'bottom' - -## Open new tabs (middleclick/ctrl+click) in the background. -## Type: Bool -# c.tabs.background = False - -## Mouse button with which to close tabs. -## Type: String -## Valid values: -## - right: Close tabs on right-click. -## - middle: Close tabs on middle-click. -## - none: Don't close tabs using the mouse. -# c.tabs.close_mouse_button = 'middle' - -## How to behave when the close mouse button is pressed on the tab bar. -## Type: String -## Valid values: -## - new-tab: Open a new tab. -## - close-current: Close the current tab. -## - close-last: Close the last tab. -## - ignore: Don't do anything. -# c.tabs.close_mouse_button_on_bar = 'new-tab' - -## Scaling factor for favicons in the tab bar. The tab size is unchanged, -## so big favicons also require extra `tabs.padding`. -## Type: Float -# c.tabs.favicons.scale = 1.0 - -## Show favicons in the tab bar. -## Type: Bool -# c.tabs.favicons.show = True - -## Padding (in pixels) for tab indicators. -## Type: Padding -# c.tabs.indicator.padding = {'top': 2, 'bottom': 2, 'left': 0, 'right': 4} - -## Width (in pixels) of the progress indicator (0 to disable). -## Type: Int -# c.tabs.indicator.width = 3 - -## How to behave when the last tab is closed. -## Type: String -## Valid values: -## - ignore: Don't do anything. -## - blank: Load a blank page. -## - startpage: Load the start page. -## - default-page: Load the default page. -## - close: Close the window. -# c.tabs.last_close = 'ignore' -c.tabs.last_close = 'close' - -## Switch between tabs using the mouse wheel. -## Type: Bool -# c.tabs.mousewheel_switching = True - -## Position of new tabs opened from another tab. -## Type: NewTabPosition -## Valid values: -## - prev: Before the current tab. -## - next: After the current tab. -## - first: At the beginning. -## - last: At the end. -# c.tabs.new_position.related = 'next' - -## Position of new tabs which aren't opened from another tab. -## Type: NewTabPosition -## Valid values: -## - prev: Before the current tab. -## - next: After the current tab. -## - first: At the beginning. -## - last: At the end. -# c.tabs.new_position.unrelated = 'last' - -## Padding (in pixels) around text for tabs. -## Type: Padding -# c.tabs.padding = {'top': 0, 'bottom': 0, 'left': 5, 'right': 5} - -## Stay in insert/passthrough mode when switching tabs. -## Type: Bool -# c.tabs.persist_mode_on_change = False - -## Shrink pinned tabs down to their contents. -## Type: Bool -# c.tabs.pinned.shrink = True - -## Position of the tab bar. -## Type: Position -## Valid values: -## - top -## - bottom -## - left -## - right -# c.tabs.position = 'top' - -## Which tab to select when the focused tab is removed. -## Type: SelectOnRemove -## Valid values: -## - prev: Select the tab which came before the closed one (left in horizontal, above in vertical). -## - next: Select the tab which came after the closed one (right in horizontal, below in vertical). -## - last-used: Select the previously selected tab. -# c.tabs.select_on_remove = 'next' - -## When to show the tab bar. -## Type: String -## Valid values: -## - always: Always show the tab bar. -## - never: Always hide the tab bar. -## - multiple: Hide the tab bar if only one tab is open. -## - switching: Show the tab bar when switching tabs. -# c.tabs.show = 'always' -c.tabs.show = 'multiple' - -## Duration (in milliseconds) to show the tab bar before hiding it when -## tabs.show is set to 'switching'. -## Type: Int -# c.tabs.show_switching_delay = 800 - -## Open a new window for every tab. -## Type: Bool -# c.tabs.tabs_are_windows = False - -## Alignment of the text inside of tabs. -## Type: TextAlignment -## Valid values: -## - left -## - right -## - center -# c.tabs.title.alignment = 'left' - -## Format to use for the tab title. The following placeholders are -## defined: * `{perc}`: Percentage as a string like `[10%]`. * -## `{perc_raw}`: Raw percentage, e.g. `10`. * `{title}`: Title of the -## current web page. * `{title_sep}`: The string ` - ` if a title is set, -## empty otherwise. * `{index}`: Index of this tab. * `{id}`: Internal -## tab ID of this tab. * `{scroll_pos}`: Page scroll position. * -## `{host}`: Host of the current web page. * `{backend}`: Either -## ''webkit'' or ''webengine'' * `{private}`: Indicates when private mode -## is enabled. * `{current_url}`: URL of the current web page. * -## `{protocol}`: Protocol (http/https/...) of the current web page. -## Type: FormatString -# c.tabs.title.format = '{index}: {title}' - -## Format to use for the tab title for pinned tabs. The same placeholders -## like for `tabs.title.format` are defined. -## Type: FormatString -# c.tabs.title.format_pinned = '{index}' - -## Width (in pixels or as percentage of the window) of the tab bar if -## it's vertical. -## Type: PercOrInt -# c.tabs.width = '20%' - -## Wrap when changing tabs. -## Type: Bool -# c.tabs.wrap = True - -## What search to start when something else than a URL is entered. -## Type: String -## Valid values: -## - naive: Use simple/naive check. -## - dns: Use DNS requests (might be slow!). -## - never: Never search automatically. -# c.url.auto_search = 'naive' - -## Page to open if :open -t/-b/-w is used without URL. Use `about:blank` -## for a blank page. -## Type: FuzzyUrl -# c.url.default_page = 'https://start.duckduckgo.com/' -c.url.default_page = '/home/taamas/.mainpage/index.html' - -## URL segments where `:navigate increment/decrement` will search for a -## number. -## Type: FlagList -## Valid values: -## - host -## - path -## - query -## - anchor -# c.url.incdec_segments = ['path', 'query'] - -## Search engines which can be used via the address bar. Maps a search -## engine name (such as `DEFAULT`, or `ddg`) to a URL with a `{}` -## placeholder. The placeholder will be replaced by the search term, use -## `{{` and `}}` for literal `{`/`}` signs. The search engine named -## `DEFAULT` is used when `url.auto_search` is turned on and something -## else than a URL was entered to be opened. Other search engines can be -## used by prepending the search engine name to the search term, e.g. -## `:open google qutebrowser`. -## Type: Dict -c.url.searchengines = { - 'DEFAULT': 'https://duckduckgo.com/?q={}', #duckduckgo - 'ddg': 'https://duckduckgo.com/?q={}', #duckduckgo - 's': 'https://search.disroot.org/search?q={}', #Disroot SearX - 'y': 'https://www.youtube.com/results?search_query={}', #youtube - 'tw': 'https://twitter.com/{}', #twitter - 'w': 'https://en.wikipedia.org/?search={}', #wikipedia - 'we': 'https://es.wikipedia.org/?search={}', #wikipedia(ES) - 'aw': 'https://wiki.archlinux.org/?search={}', #archWiki - 'sf': 'https://scryfall.com/search?q={}', #scryfall - 'mkm': 'https://www.cardmarket.com/en/Magic/Products/Search?searchString={}', #mkm - 'gi': 'https://game-icons.net/search.html?q={}', #game-icons - 'bc': 'https://bandcamp.com/search?q={}', #bancamp - 'mdd': 'https://www.megadede.com/search/{}', #megadede - 'gh': 'https://www.github.com/search?q={}', #github - 'ghu': 'https://github.com/search?q={}&type=Users', #github users - 'ep': 'https://emojipedia.org/search/?q={}', #emojipedia - 'rae': 'https://dle.rae.es/?w={}', #rae - 'maps': 'https://www.google.com/maps/place/{}', #google maps - 'im': 'https://imagemagick.org/script/search.php?q={}', # ImageMagick - 'mc': 'https://minecraft.gamepedia.com/{}', # Minecraft wiki - 'mb': 'https://musicbrainz.org/search?query={}&type=artist&method=indexed', # MusicBrainz (Artist) - 'df': 'https://dwarffortresswiki.org/index.php/DF2014:{}', # Dwarf Fortress Wiki - 'sl': 'https://senseis.xmp.net/?{}', # Sensei's Library - 'sls': 'https://senseis.xmp.net/?search={}&searchtype=title', # Sensei's Library search - 'bs': 'https://bsaber.com/?s={}', # Beast Saber - 'bp': 'https://bulbapedia.bulbagarden.net/wiki/{}', # Bulbapedia - 'bpm': 'https://bulbapedia.bulbagarden.net/wiki/{}#Learnset', # Bulbapedia (Learnset) - 'bpe': 'https://bulbapedia.bulbagarden.net/wiki/{}#Evolution', # Bulbapedia (Evolution) - 'sg': 'https://www.smogon.com/dex/ss/pokemon/{}', # Smogon - 'tex': 'https://www.ctan.org/search?phrase={}', # CTAN - 'keys': 'https://keys.openpgp.org/search?q={}', # openPGP keys - 'fl': 'https://fallenlondon.wiki/w/index.php?search={}' # Fallen London wiki -} - -## Page(s) to open at the start. -## Type: List of FuzzyUrl, or FuzzyUrl -# c.url.start_pages = ['https://start.duckduckgo.com'] -c.url.start_pages = ['file:///home/taamas/.mainpage/index.html'] - -## URL parameters to strip with `:yank url`. -## Type: List of String -# c.url.yank_ignored_parameters = ['ref', 'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'] - -## Hide the window decoration when using wayland. -## Type: Bool -# c.window.hide_wayland_decoration = False - -## Format to use for the window title. The same placeholders like for -## `tabs.title.format` are defined. -## Type: FormatString -# c.window.title_format = '{perc}{title}{title_sep}qutebrowser' - -## Default zoom level. -## Type: Perc -# c.zoom.default = '100%' - -## Available zoom levels. -## Type: List of Perc -# c.zoom.levels = ['25%', '33%', '50%', '67%', '75%', '90%', '100%', '110%', '125%', '150%', '175%', '200%', '250%', '300%', '400%', '500%'] - -## Number of zoom increments to divide the mouse wheel movements to. -## Type: Int -# c.zoom.mouse_divider = 512 - -## Apply the zoom factor on a frame only to the text or to all content. -## Type: Bool -# c.zoom.text_only = False - -## Bindings for normal mode -# config.bind("'", 'enter-mode jump_mark') -# config.bind('+', 'zoom-in') -# config.bind('-', 'zoom-out') -# config.bind('.', 'repeat-command') -# config.bind('/', 'set-cmd-text /') -# config.bind(':', 'set-cmd-text :') -# config.bind(';I', 'hint images tab') -# config.bind(';O', 'hint links fill :open -t -r {hint-url}') -# config.bind(';R', 'hint --rapid links window') -# config.bind(';Y', 'hint links yank-primary') -# config.bind(';b', 'hint all tab-bg') -# config.bind(';f', 'hint all tab-fg') -# config.bind(';h', 'hint all hover') -# config.bind(';i', 'hint images') -# config.bind(';o', 'hint links fill :open {hint-url}') -# config.bind(';r', 'hint --rapid links tab-bg') -# config.bind(';t', 'hint inputs') -# config.bind(';y', 'hint links yank') -# config.bind('', 'tab-focus 1') -# config.bind('', 'tab-focus 2') -# config.bind('', 'tab-focus 3') -# config.bind('', 'tab-focus 4') -# config.bind('', 'tab-focus 5') -# config.bind('', 'tab-focus 6') -# config.bind('', 'tab-focus 7') -# config.bind('', 'tab-focus 8') -# config.bind('', 'tab-focus -1') -# config.bind('', 'navigate increment') -# config.bind('', 'print') -# config.bind('', 'scroll-page 0 -1') -# config.bind('', 'scroll-page 0 0.5') -# config.bind('', 'reload -f') -# config.bind('', 'scroll-page 0 1') -# config.bind('', 'open -w') -# config.bind('', 'tab-next') -# config.bind('', 'tab-prev') -# config.bind('', 'quit') -# config.bind('', 'follow-selected -t') -# config.bind('', 'open -p') -# config.bind('', 'undo') -# config.bind('', 'close') -# config.bind('', 'open -t') -# config.bind('', 'tab-focus last') -# config.bind('', 'scroll-page 0 -0.5') -# config.bind('', 'enter-mode passthrough') -# config.bind('', 'tab-close') -# config.bind('', 'navigate decrement') -# config.bind('', 'tab-focus last') -# config.bind('', 'home') -# config.bind('', 'tab-pin') -# config.bind('', 'stop') -# config.bind('', 'clear-keychain ;; search ;; fullscreen --leave') -# config.bind('', 'fullscreen') -# config.bind('', 'reload') -# config.bind('', 'follow-selected') -# config.bind('', 'back') -# config.bind('', 'forward') -# config.bind('=', 'zoom') -# config.bind('?', 'set-cmd-text ?') -# config.bind('@', 'run-macro') -# config.bind('B', 'set-cmd-text -s :quickmark-load -t') -# config.bind('D', 'tab-close -o') -config.unbind('D') -# config.bind('F', 'hint all tab') -# config.bind('G', 'scroll-to-perc') -# config.bind('H', 'back') -# config.bind('J', 'tab-next') -# config.bind('K', 'tab-prev') -# config.bind('L', 'forward') -# config.bind('M', 'bookmark-add') -# config.bind('N', 'search-prev') -# config.bind('O', 'set-cmd-text -s :open -t') -# config.bind('PP', 'open -t -- {primary}') -# config.bind('Pp', 'open -t -- {clipboard}') -# config.bind('R', 'reload -f') -# config.bind('Sb', 'open qute://bookmarks#bookmarks') -# config.bind('Sh', 'open qute://history') -# config.bind('Sq', 'open qute://bookmarks') -# config.bind('Ss', 'open qute://settings') -# config.bind('T', 'tab-focus') -# config.bind('ZQ', 'quit') -# config.bind('ZZ', 'quit --save') -# config.bind('[[', 'navigate prev') -# config.bind(']]', 'navigate next') -# config.bind('`', 'enter-mode set_mark') -# config.bind('ad', 'download-cancel') -# config.bind('b', 'set-cmd-text -s :quickmark-load') -# config.bind('cd', 'download-clear') -# config.bind('co', 'tab-only') -# config.bind('d', 'tab-close') -config.bind('d', 'scroll-page 0 0.5') -config.bind('u', 'scroll-page 0 -0.5') -config.bind('q', 'tab-close') -# config.bind('f', 'hint') -# config.bind('g$', 'tab-focus -1') -# config.bind('g0', 'tab-focus 1') -# config.bind('gB', 'set-cmd-text -s :bookmark-load -t') -# config.bind('gC', 'tab-clone') -# config.bind('gO', 'set-cmd-text :open -t -r {url:pretty}') -# config.bind('gU', 'navigate up -t') -# config.bind('g^', 'tab-focus 1') -# config.bind('ga', 'open -t') -# config.bind('gb', 'set-cmd-text -s :bookmark-load') -# config.bind('gd', 'download') -# config.bind('gf', 'view-source') -# config.bind('gg', 'scroll-to-perc 0') -# config.bind('gl', 'tab-move -') -# config.bind('gm', 'tab-move') -# config.bind('go', 'set-cmd-text :open {url:pretty}') -# config.bind('gr', 'tab-move +') -# config.bind('gt', 'set-cmd-text -s :buffer') -# config.bind('gu', 'navigate up') -# config.bind('h', 'scroll left') -# config.bind('i', 'enter-mode insert') -# config.bind('j', 'scroll down') -# config.bind('k', 'scroll up') -# config.bind('l', 'scroll right') -# config.bind('m', 'quickmark-save') -# config.bind('n', 'search-next') -# config.bind('o', 'set-cmd-text -s :open') -# config.bind('pP', 'open -- {primary}') -# config.bind('pp', 'open -- {clipboard}') -# config.bind('q', 'record-macro') -config.bind('Q', 'record-macro') -# config.bind('r', 'reload') -# config.bind('sf', 'save') -# config.bind('sk', 'set-cmd-text -s :bind') -# config.bind('sl', 'set-cmd-text -s :set -t') -# config.bind('ss', 'set-cmd-text -s :set') -# config.bind('th', 'back -t') -# config.bind('tl', 'forward -t') -# config.bind('u', 'undo') -config.bind('U', 'undo') -# config.bind('v', 'enter-mode caret') -# config.bind('wB', 'set-cmd-text -s :bookmark-load -w') -# config.bind('wO', 'set-cmd-text :open -w {url:pretty}') -# config.bind('wP', 'open -w -- {primary}') -# config.bind('wb', 'set-cmd-text -s :quickmark-load -w') -# config.bind('wf', 'hint all window') -# config.bind('wh', 'back -w') -# config.bind('wi', 'inspector') -# config.bind('wl', 'forward -w') -# config.bind('wo', 'set-cmd-text -s :open -w') -# config.bind('wp', 'open -w -- {clipboard}') -# config.bind('xO', 'set-cmd-text :open -b -r {url:pretty}') -# config.bind('xo', 'set-cmd-text -s :open -b') -# config.bind('yD', 'yank domain -s') -# config.bind('yP', 'yank pretty-url -s') -# config.bind('yT', 'yank title -s') -# config.bind('yY', 'yank -s') -# config.bind('yd', 'yank domain') -# config.bind('yp', 'yank pretty-url') -# config.bind('yt', 'yank title') -# config.bind('yy', 'yank') -# config.bind('{{', 'navigate prev -t') -# config.bind('}}', 'navigate next -t') - -## Custom normal mode bindings -# open url with mpv -config.bind(',v', 'spawn mpv {url}') -config.bind(',fv', 'hint links spawn mpv {hint-url}') -config.bind(',Fv', 'hint all spawn mpv {hint-url}') -config.bind(',V', 'spawn /home/taamas/scripts/floats/mpvFloat.sh {url}') -config.bind(',fV', 'hint links spawn mpvFloat.sh {hint-url}') -config.bind(',FV', 'hint all spawn mpvFloat.sh {hint-url}') -#download url's video -config.bind(',d', 'spawn youtube-dl --all-subs --embed-subs -o ~/downloads/videos/%(title)s.%(ext)s {url}') -# same as previous, but showing urxvt -config.bind(',D', 'spawn /home/taamas/scripts/floats/youtube-dlFloat.sh {url}') -# two same commands, using hints instead than current url -config.bind(',fd', 'hint links spawn youtube-dl.sh {hint-url}') -config.bind(',Fd', 'hint all spawn youtube-dl.sh {hint-url}') -config.bind(',fD', 'hint links spawn /home/taamas/scripts/floats/youtube-dlFloat.sh {hint-url}') -config.bind(',FD', 'hint all spawn /home/taamas/scripts/floats/youtube-dlFloat.sh {hint-url}') -# download url's audio in mp3 in ~/music/qutebrowser -config.bind(',a', 'spawn youtube-dl -o ~/music/qutebrowser/%(title)s.%(ext)s -x --audio-format mp3 --embed-thumbnail {url}') -# same as previous, but showing urxvt -config.bind(',A', 'spawn /home/taamas/scripts/floats/youtube-dlFloatAudio.sh {url}') -# two same commands, using hints instead than current url -config.bind(',fa', 'hint links spawn /home/taamas/scripts/floats/youtube-dlAudio.sh {hint-url}') -config.bind(',Fa', 'hint all spawn /home/taamas/scripts/floats/youtube-dlAudio.sh {hint-url}') -config.bind(',fA', 'hint links spawn /home/taamas/scripts/floats/youtube-dlFloatAudio.sh {hint-url}') -config.bind(',FA', 'hint all spawn /home/taamas/scripts/floats/youtube-dlFloatAudio.sh {hint-url}') -# open images with corresponding script -config.bind(',i', 'spawn showURLimage.sh {url}') -config.bind(',fi', 'hint images spawn showURLimage.sh {hint-url}') -config.bind(',fI', 'hint all spawn showURLimage.sh {hint-url}') -# ripme bulk image downloading -config.bind(',rm', 'spawn ripme.sh {url}') -config.bind(',frm', 'hint links spawn ripme.sh {hint-url}') - -## Bindings for caret mode -# config.bind('$', 'move-to-end-of-line', mode='caret') -# config.bind('0', 'move-to-start-of-line', mode='caret') -# config.bind('', 'drop-selection', mode='caret') -# config.bind('', 'leave-mode', mode='caret') -# config.bind('', 'yank selection', mode='caret') -# config.bind('', 'toggle-selection', mode='caret') -# config.bind('G', 'move-to-end-of-document', mode='caret') -# config.bind('H', 'scroll left', mode='caret') -# config.bind('J', 'scroll down', mode='caret') -# config.bind('K', 'scroll up', mode='caret') -# config.bind('L', 'scroll right', mode='caret') -# config.bind('Y', 'yank selection -s', mode='caret') -# config.bind('[', 'move-to-start-of-prev-block', mode='caret') -# config.bind(']', 'move-to-start-of-next-block', mode='caret') -# config.bind('b', 'move-to-prev-word', mode='caret') -# config.bind('c', 'enter-mode normal', mode='caret') -# config.bind('e', 'move-to-end-of-word', mode='caret') -# config.bind('gg', 'move-to-start-of-document', mode='caret') -# config.bind('h', 'move-to-prev-char', mode='caret') -# config.bind('j', 'move-to-next-line', mode='caret') -# config.bind('k', 'move-to-prev-line', mode='caret') -# config.bind('l', 'move-to-next-char', mode='caret') -# config.bind('v', 'toggle-selection', mode='caret') -# config.bind('w', 'move-to-next-word', mode='caret') -# config.bind('y', 'yank selection', mode='caret') -# config.bind('{', 'move-to-end-of-prev-block', mode='caret') -# config.bind('}', 'move-to-end-of-next-block', mode='caret') - -## Bindings for command mode -# config.bind('', 'rl-backward-word', mode='command') -# config.bind('', 'rl-backward-kill-word', mode='command') -# config.bind('', 'rl-kill-word', mode='command') -# config.bind('', 'rl-forward-word', mode='command') -# config.bind('', 'rl-delete-char', mode='command') -# config.bind('', 'rl-beginning-of-line', mode='command') -# config.bind('', 'rl-backward-char', mode='command') -# config.bind('', 'completion-item-yank', mode='command') -# config.bind('', 'completion-item-del', mode='command') -# config.bind('', 'rl-end-of-line', mode='command') -# config.bind('', 'rl-forward-char', mode='command') -# config.bind('', 'rl-backward-delete-char', mode='command') -# config.bind('', 'rl-kill-line', mode='command') -# config.bind('', 'command-history-next', mode='command') -# config.bind('', 'command-history-prev', mode='command') -# config.bind('', 'command-accept --rapid', mode='command') -# config.bind('', 'completion-item-yank --sel', mode='command') -# config.bind('', 'completion-item-focus prev-category', mode='command') -# config.bind('', 'completion-item-focus next-category', mode='command') -# config.bind('', 'rl-unix-line-discard', mode='command') -# config.bind('', 'rl-unix-word-rubout', mode='command') -# config.bind('', 'rl-yank', mode='command') -# config.bind('', 'completion-item-focus --history next', mode='command') -# config.bind('', 'leave-mode', mode='command') -# config.bind('', 'command-accept', mode='command') -# config.bind('', 'completion-item-del', mode='command') -# config.bind('', 'completion-item-focus prev', mode='command') -# config.bind('', 'completion-item-focus next', mode='command') -# config.bind('', 'completion-item-focus --history prev', mode='command') - -## Bindings for hint mode -# config.bind('', 'hint all tab-bg', mode='hint') -# config.bind('', 'hint links', mode='hint') -# config.bind('', 'hint --rapid links tab-bg', mode='hint') -# config.bind('', 'leave-mode', mode='hint') -# config.bind('', 'follow-hint', mode='hint') - -## Bindings for insert mode -# config.bind('', 'open-editor', mode='insert') -# config.bind('', 'leave-mode', mode='insert') -# config.bind('', 'insert-text {primary}', mode='insert') - -## Bindings for passthrough mode -# config.bind('', 'leave-mode', mode='passthrough') - -## Bindings for prompt mode -# config.bind('', 'rl-backward-word', mode='prompt') -# config.bind('', 'rl-backward-kill-word', mode='prompt') -# config.bind('', 'rl-kill-word', mode='prompt') -# config.bind('', 'rl-forward-word', mode='prompt') -# config.bind('', 'rl-delete-char', mode='prompt') -# config.bind('', 'rl-beginning-of-line', mode='prompt') -# config.bind('', 'rl-backward-char', mode='prompt') -# config.bind('', 'rl-end-of-line', mode='prompt') -# config.bind('', 'rl-forward-char', mode='prompt') -# config.bind('', 'rl-backward-delete-char', mode='prompt') -# config.bind('', 'rl-kill-line', mode='prompt') -# config.bind('', 'rl-unix-line-discard', mode='prompt') -# config.bind('', 'rl-unix-word-rubout', mode='prompt') -# config.bind('', 'prompt-open-download', mode='prompt') -# config.bind('', 'rl-yank', mode='prompt') -# config.bind('', 'prompt-item-focus next', mode='prompt') -# config.bind('', 'leave-mode', mode='prompt') -# config.bind('', 'prompt-accept', mode='prompt') -# config.bind('', 'prompt-item-focus prev', mode='prompt') -# config.bind('', 'prompt-item-focus next', mode='prompt') -# config.bind('', 'prompt-item-focus prev', mode='prompt') -# config.bind('n', 'prompt-accept no', mode='prompt') -# config.bind('y', 'prompt-accept yes', mode='prompt') - -## Bindings for register mode -# config.bind('', 'leave-mode', mode='register') - -dracula.draw.blood(c, { - 'spacing': { - 'vertical': 3, - 'horizontal': 8 - } -}) diff --git a/stow/ranger/.config/ranger/rc.conf b/stow/ranger/.config/ranger/rc.conf new file mode 100644 index 0000000..4fe51db --- /dev/null +++ b/stow/ranger/.config/ranger/rc.conf @@ -0,0 +1,640 @@ +# =================================================================== +# This file contains the default startup commands for ranger. +# To change them, it is recommended to create the file +# ~/.config/ranger/rc.conf and add your custom commands there. +# +# If you copy this whole file there, you may want to set the environment +# variable RANGER_LOAD_DEFAULT_RC to FALSE to avoid loading it twice. +# +# The purpose of this file is mainly to define keybindings and settings. +# For running more complex python code, please create a plugin in "plugins/" or +# a command in "commands.py". +# +# Each line is a command that will be run before the user interface +# is initialized. As a result, you can not use commands which rely +# on the UI such as :delete or :mark. +# =================================================================== + +# =================================================================== +# == Options +# =================================================================== + +# Which viewmode should be used? Possible values are: +# miller: Use miller columns which show multiple levels of the hierarchy +# multipane: Midnight-commander like multipane view showing all tabs next +# to each other +set viewmode miller +#set viewmode multipane + +# How many columns are there, and what are their relative widths? +set column_ratios 1,3,4 + +# Which files should be hidden? (regular expression) +set hidden_filter ^\.|\.(?:pyc|pyo|bak|swp)$|^lost\+found$|^__(py)?cache__$ + +# Show hidden files? You can toggle this by typing 'zh' +set show_hidden false + +# Ask for a confirmation when running the "delete" command? +# Valid values are "always", "never", "multiple" (default) +# With "multiple", ranger will ask only if you delete multiple files at once. +set confirm_on_delete multiple + +# Which script is used to generate file previews? +# ranger ships with scope.sh, a script that calls external programs (see +# README.md for dependencies) to preview images, archives, etc. +set preview_script ~/.config/ranger/scope.sh + +# Use the external preview script or display simple plain text or image previews? +set use_preview_script true + +# Automatically count files in the directory, even before entering them? +set automatically_count_files true + +# Open all images in this directory when running certain image viewers +# like feh or sxiv? You can still open selected files by marking them. +set open_all_images true + +# Be aware of version control systems and display information. +set vcs_aware true + +# State of the three backends git, hg, bzr. The possible states are +# disabled, local (only show local info), enabled (show local and remote +# information). +set vcs_backend_git enabled +set vcs_backend_hg disabled +set vcs_backend_bzr disabled + +# Use one of the supported image preview protocols +# set preview_images false +set preview_images true + +# Set the preview image method. Supported methods: +# +# * w3m (default): +# Preview images in full color with the external command "w3mimgpreview"? +# This requires the console web browser "w3m" and a supported terminal. +# It has been successfully tested with "xterm" and "urxvt" without tmux. +# +# * iterm2: +# Preview images in full color using iTerm2 image previews +# (http://iterm2.com/images.html). This requires using iTerm2 compiled +# with image preview support. +# +# * urxvt: +# Preview images in full color using urxvt image backgrounds. This +# requires using urxvt compiled with pixbuf support. +# +# * urxvt-full: +# The same as urxvt but utilizing not only the preview pane but the +# whole terminal window. +set preview_images_method w3m + +# Use a unicode "..." character to mark cut-off filenames? +set unicode_ellipsis false + +# Show dotfiles in the bookmark preview box? +set show_hidden_bookmarks true + +# Which colorscheme to use? These colorschemes are available by default: +# default, jungle, snow, solarized +set colorscheme default + +# Preview files on the rightmost column? +# And collapse (shrink) the last column if there is nothing to preview? +set preview_files true +set preview_directories true +set collapse_preview true + +# Save the console history on exit? +set save_console_history true + +# Draw the status bar on top of the browser window (default: bottom) +set status_bar_on_top false + +# Draw a progress bar in the status bar which displays the average state of all +# currently running tasks which support progress bars? +set draw_progress_bar_in_status_bar true + +# Draw borders around columns? +set draw_borders true + +# Display the directory name in tabs? +set dirname_in_tabs false + +# Enable the mouse support? +set mouse_enabled true + +# Display the file size in the main column or status bar? +set display_size_in_main_column true +set display_size_in_status_bar true + +# Display files tags in all columns or only in main column? +set display_tags_in_all_columns true + +# Set a title for the window? +set update_title true + +# Set the title to "ranger" in the tmux program? +set update_tmux_title true + +# Shorten the title if it gets long? The number defines how many +# directories are displayed at once, 0 turns off this feature. +set shorten_title 3 + +# Abbreviate $HOME with ~ in the titlebar (first line) of ranger? +set tilde_in_titlebar true + +# How many directory-changes or console-commands should be kept in history? +set max_history_size 20 +set max_console_history_size 50 + +# Try to keep so much space between the top/bottom border when scrolling: +set scroll_offset 8 + +# Flush the input after each key hit? (Noticeable when ranger lags) +set flushinput true + +# Padding on the right when there's no preview? +# This allows you to click into the space to run the file. +set padding_right false + +# Save bookmarks (used with mX and `X) instantly? +# This helps to synchronize bookmarks between multiple ranger +# instances but leads to *slight* performance loss. +# When false, bookmarks are saved when ranger is exited. +set autosave_bookmarks true + +# You can display the "real" cumulative size of directories by using the +# command :get_cumulative_size or typing "dc". The size is expensive to +# calculate and will not be updated automatically. You can choose +# to update it automatically though by turning on this option: +set autoupdate_cumulative_size false + +# Turning this on makes sense for screen readers: +set show_cursor false + +# One of: size, natural, basename, atime, ctime, mtime, type, random +set sort natural + +# Additional sorting options +set sort_reverse false +set sort_case_insensitive true +set sort_directories_first true +set sort_unicode false + +# Enable this if key combinations with the Alt Key don't work for you. +# (Especially on xterm) +set xterm_alt_key false + +# Whether to include bookmarks in cd command +set cd_bookmarks true + +# Avoid previewing files larger than this size, in bytes. Use a value of 0 to +# disable this feature. +set preview_max_size 0 + +# Add the highlighted file to the path in the titlebar +set show_selection_in_titlebar true + +# The delay that ranger idly waits for user input, in milliseconds, with a +# resolution of 100ms. Lower delay reduces lag between directory updates but +# increases CPU load. +set idle_delay 2000 + +# When the metadata manager module looks for metadata, should it only look for +# a ".metadata.json" file in the current directory, or do a deep search and +# check all directories above the current one as well? +set metadata_deep_search false + +# Clear all existing filters when leaving a directory +set clear_filters_on_dir_change false + +# Disable displaying line numbers in main column +set line_numbers false + +# =================================================================== +# == Local Options +# =================================================================== +# You can set local options that only affect a single directory. + +# Examples: +setlocal path=~/downloads sort mtime +setlocal path=~/downloads sort_reverse True +setlocal path=~/downloads/videos sort mtime +setlocal path=~/downloads/videos sort_reverse True +setlocal path=~/downloads/audios sort mtime +setlocal path=~/downloads/audios sort_reverse True +setlocal path=~/scp sort mtime +setlocal path=~/scp sort_reverse True + +# =================================================================== +# == Command Aliases in the Console +# =================================================================== + +alias e edit +alias q quit +alias q! quitall +alias qa quitall +alias qall quitall +alias setl setlocal + +alias filter scout -prt +alias find scout -aeit +alias mark scout -mr +alias unmark scout -Mr +alias search scout -rs +alias search_inc scout -rts +alias travel scout -aefiklst + +# =================================================================== +# == Define keys for the browser +# =================================================================== + +# Custom +map ,b bulkrename +map ,d shell rm.sh %s +map ,s shell tmux split-window -p 60 -c %d & +map ,S shell tmux new-window -a -n shell -c %d & +map ,e shell tmux new-window -a -n $EDITOR "$EDITOR %s" +map ,w shell setBG.sh %f & +map ,W console shell ~/scripts/floats/floatBgBrowser.sh %d/ & +map ,p shell asPDF.sh %f +map ,P shell lowriter --convert-to pdf %f +map ,um shell sudo umount %p +map ,z shell zip -r %f.zip %s +map ,uz shell 7z x %f +map ,ur shell unrar x %f +map ,ut shell tar -xvzf %f +map ,m shell move.sh %s +map ,c shell copy.sh %s +map ,C shell scp.sh %s +#map ,g shell cd $(selectPathFzf.sh) + +# Basic +map Q quit! +map q quit +copymap q ZZ ZQ + +map R reload_cwd +map reset +map redraw_window +map abort +map change_mode normal +map ~ set viewmode! + +map i display_file +map ? help +map W display_log +map w taskview_open +map S shell $SHELL + +map : console +map ; console +map ! console shell%space +map @ console -p6 shell %%s +map # console shell -p%space +map s console shell%space +map r chain draw_possible_programs; console open_with%space +map f console find%space +map cd console cd%space + +# Change the line mode +map Mf linemode filename +map Mi linemode fileinfo +map Mm linemode mtime +map Mp linemode permissions +map Ms linemode sizemtime +map Mt linemode metatitle + +# Tagging / Marking +map t tag_toggle +map ut tag_remove +map " tag_toggle tag=%any +map mark_files toggle=True +map v mark_files all=True toggle=True +map uv mark_files all=True val=False +map V toggle_visual_mode +map uV toggle_visual_mode reverse=True + +# For the nostalgics: Midnight Commander bindings +map help +map display_file +map edit +map copy +map cut +map console mkdir%space +map console delete +map exit + +# In case you work on a keyboard with dvorak layout +map move up=1 +map move down=1 +map move left=1 +map move right=1 +map move to=0 +map move to=-1 +map move down=1 pages=True +map move up=1 pages=True +map move right=1 +#map console delete +map console touch%space + +# VIM-like +copymap k +copymap j +copymap h +copymap l +copymap gg +copymap G +copymap +copymap + +map J move down=0.5 pages=True +map K move up=0.5 pages=True +copymap J +copymap K + +# Jumping around +map H history_go -1 +map L history_go 1 +map ] move_parent 1 +map [ move_parent -1 +map } traverse + +map gh cd ~ +map ge cd /etc +map gu cd /usr +map gd cd /dev +map gl cd -r . +map gL cd -r %f +map go cd /opt +map gv cd /var +map gm cd /media +map gM cd /mnt +map gs cd /srv +map gr cd / +map gR eval fm.cd(ranger.RANGERDIR) +map g/ cd / +map g? cd /usr/share/doc/ranger + +# External Programs +map E edit +map du shell -p du --max-depth=1 -h --apparent-size +map dU shell -p du --max-depth=1 -h --apparent-size | sort -rh +map yp shell -f echo -n %d/%f | xsel -i; xsel -o | xsel -i -b +map yd shell -f echo -n %d | xsel -i; xsel -o | xsel -i -b +map yn shell -f echo -n %f | xsel -i; xsel -o | xsel -i -b + +# Filesystem Operations +map = chmod + +map cw console rename%space +map a rename_append +map A eval fm.open_console('rename ' + fm.thisfile.relative_path.replace("%", "%%")) +map I eval fm.open_console('rename ' + fm.thisfile.relative_path.replace("%", "%%"), position=7) + +map pp paste +map po paste overwrite=True +map pP paste append=True +map pO paste overwrite=True append=True +map pl paste_symlink relative=False +map pL paste_symlink relative=True +map phl paste_hardlink +map pht paste_hardlinked_subtree + +map dD console delete + +map dd cut +map ud uncut +map da cut mode=add +map dr cut mode=remove +map dt cut mode=toggle + +map yy copy +map uy uncut +map ya copy mode=add +map yr copy mode=remove +map yt copy mode=toggle + +# Temporary workarounds +map dgg eval fm.cut(dirarg=dict(to=0), narg=quantifier) +map dG eval fm.cut(dirarg=dict(to=-1), narg=quantifier) +map dj eval fm.cut(dirarg=dict(down=1), narg=quantifier) +map dk eval fm.cut(dirarg=dict(up=1), narg=quantifier) +map ygg eval fm.copy(dirarg=dict(to=0), narg=quantifier) +map yG eval fm.copy(dirarg=dict(to=-1), narg=quantifier) +map yj eval fm.copy(dirarg=dict(down=1), narg=quantifier) +map yk eval fm.copy(dirarg=dict(up=1), narg=quantifier) + +# Searching +map / console search%space +map n search_next +map N search_next forward=False +map ct search_next order=tag +map cs search_next order=size +map ci search_next order=mimetype +map cc search_next order=ctime +map cm search_next order=mtime +map ca search_next order=atime + +# Tabs +map tab_new ~ +map tab_close +map tab_move 1 +map tab_move -1 +map tab_move 1 +map tab_move -1 +map gt tab_move 1 +map gT tab_move -1 +map gn tab_new ~ +map gc tab_close +map uq tab_restore +map tab_open 1 +map tab_open 2 +map tab_open 3 +map tab_open 4 +map tab_open 5 +map tab_open 6 +map tab_open 7 +map tab_open 8 +map tab_open 9 + +# Sorting +map or set sort_reverse! +map oz set sort=random +map os chain set sort=size; set sort_reverse=False +map ob chain set sort=basename; set sort_reverse=False +map on chain set sort=natural; set sort_reverse=False +map om chain set sort=mtime; set sort_reverse=False +map oc chain set sort=ctime; set sort_reverse=False +map oa chain set sort=atime; set sort_reverse=False +map ot chain set sort=type; set sort_reverse=False +map oe chain set sort=extension; set sort_reverse=False + +map oS chain set sort=size; set sort_reverse=True +map oB chain set sort=basename; set sort_reverse=True +map oN chain set sort=natural; set sort_reverse=True +map oM chain set sort=mtime; set sort_reverse=True +map oC chain set sort=ctime; set sort_reverse=True +map oA chain set sort=atime; set sort_reverse=True +map oT chain set sort=type; set sort_reverse=True +map oE chain set sort=extension; set sort_reverse=True + +map dc get_cumulative_size + +# Settings +map zc set collapse_preview! +map zd set sort_directories_first! +map zh set show_hidden! +map set show_hidden! +map zI set flushinput! +map zi set preview_images! +map zm set mouse_enabled! +map zp set preview_files! +map zP set preview_directories! +map zs set sort_case_insensitive! +map zu set autoupdate_cumulative_size! +map zv set use_preview_script! +map zf console filter%space + +# Bookmarks +map ` enter_bookmark %any +map ' enter_bookmark %any +map m set_bookmark %any +map um unset_bookmark %any + +map m draw_bookmarks +copymap m um ` ' + +# Generate all the chmod bindings with some python help: +eval for arg in "rwxXst": cmd("map +u{0} shell -f chmod u+{0} %s".format(arg)) +eval for arg in "rwxXst": cmd("map +g{0} shell -f chmod g+{0} %s".format(arg)) +eval for arg in "rwxXst": cmd("map +o{0} shell -f chmod o+{0} %s".format(arg)) +eval for arg in "rwxXst": cmd("map +a{0} shell -f chmod a+{0} %s".format(arg)) +eval for arg in "rwxXst": cmd("map +{0} shell -f chmod u+{0} %s".format(arg)) + +eval for arg in "rwxXst": cmd("map -u{0} shell -f chmod u-{0} %s".format(arg)) +eval for arg in "rwxXst": cmd("map -g{0} shell -f chmod g-{0} %s".format(arg)) +eval for arg in "rwxXst": cmd("map -o{0} shell -f chmod o-{0} %s".format(arg)) +eval for arg in "rwxXst": cmd("map -a{0} shell -f chmod a-{0} %s".format(arg)) +eval for arg in "rwxXst": cmd("map -{0} shell -f chmod u-{0} %s".format(arg)) + +# =================================================================== +# == Define keys for the console +# =================================================================== +# Note: Unmapped keys are passed directly to the console. + +# Basic +cmap eval fm.ui.console.tab() +cmap eval fm.ui.console.tab(-1) +cmap eval fm.ui.console.close() +cmap eval fm.ui.console.execute() +cmap redraw_window + +copycmap +copycmap + +# Move around +cmap eval fm.ui.console.history_move(-1) +cmap eval fm.ui.console.history_move(1) +cmap eval fm.ui.console.move(left=1) +cmap eval fm.ui.console.move(right=1) +cmap eval fm.ui.console.move(right=0, absolute=True) +cmap eval fm.ui.console.move(right=-1, absolute=True) +cmap eval fm.ui.console.move_word(left=1) +cmap eval fm.ui.console.move_word(right=1) + +# Line Editing +cmap eval fm.ui.console.delete(-1) +cmap eval fm.ui.console.delete(0) +cmap eval fm.ui.console.delete_word() +cmap eval fm.ui.console.delete_word(backward=False) +cmap eval fm.ui.console.delete_rest(1) +cmap eval fm.ui.console.delete_rest(-1) +cmap eval fm.ui.console.paste() + +# And of course the emacs way +copycmap +copycmap +copycmap +copycmap +copycmap +copycmap +copycmap +copycmap + +# Note: There are multiple ways to express backspaces. (code 263) +# and (code 127). To be sure, use both. +copycmap + +# This special expression allows typing in numerals: +cmap false + +# =================================================================== +# == Pager Keybindings +# =================================================================== + +# Movement +pmap pager_move down=1 +pmap pager_move up=1 +pmap pager_move left=4 +pmap pager_move right=4 +pmap pager_move to=0 +pmap pager_move to=-1 +pmap pager_move down=1.0 pages=True +pmap pager_move up=1.0 pages=True +pmap pager_move down=0.5 pages=True +pmap pager_move up=0.5 pages=True + +copypmap k +copypmap j +copypmap h +copypmap l +copypmap g +copypmap G +copypmap d +copypmap u +copypmap n f +copypmap p b + +# Basic +pmap redraw_window +pmap pager_close +copypmap q Q i +pmap E edit_file + +# =================================================================== +# == Taskview Keybindings +# =================================================================== + +# Movement +tmap taskview_move up=1 +tmap taskview_move down=1 +tmap taskview_move to=0 +tmap taskview_move to=-1 +tmap taskview_move down=1.0 pages=True +tmap taskview_move up=1.0 pages=True +tmap taskview_move down=0.5 pages=True +tmap taskview_move up=0.5 pages=True + +copytmap k +copytmap j +copytmap g +copytmap G +copytmap u +copytmap n f +copytmap p b + +# Changing priority and deleting tasks +tmap J eval -q fm.ui.taskview.task_move(-1) +tmap K eval -q fm.ui.taskview.task_move(0) +tmap dd eval -q fm.ui.taskview.task_remove() +tmap eval -q fm.ui.taskview.task_move(-1) +tmap eval -q fm.ui.taskview.task_move(0) +tmap eval -q fm.ui.taskview.task_remove() + +# Basic +tmap redraw_window +tmap taskview_close +copytmap q Q w diff --git a/stow/ranger/.config/ranger/rifle.conf b/stow/ranger/.config/ranger/rifle.conf new file mode 100644 index 0000000..35a10a0 --- /dev/null +++ b/stow/ranger/.config/ranger/rifle.conf @@ -0,0 +1,226 @@ +# vim: ft=cfg +# +# This is the configuration file of "rifle", ranger's file executor/opener. +# Each line consists of conditions and a command. For each line the conditions +# are checked and if they are met, the respective command is run. +# +# Syntax: +# , , ... = command +# +# The command can contain these environment variables: +# $1-$9 | The n-th selected file +# $@ | All selected files +# +# If you use the special command "ask", rifle will ask you what program to run. +# +# Prefixing a condition with "!" will negate its result. +# These conditions are currently supported: +# match | The regexp matches $1 +# ext | The regexp matches the extension of $1 +# mime | The regexp matches the mime type of $1 +# name | The regexp matches the basename of $1 +# path | The regexp matches the absolute path of $1 +# has | The program is installed (i.e. located in $PATH) +# env | The environment variable "variable" is non-empty +# file | $1 is a file +# directory | $1 is a directory +# number | change the number of this command to n +# terminal | stdin, stderr and stdout are connected to a terminal +# X | $DISPLAY is not empty (i.e. Xorg runs) +# +# There are also pseudo-conditions which have a "side effect": +# flag | Change how the program is run. See below. +# label <++><++>?""a +inoremap himg <++><++>?""a + +" Misc +" Comment a line +nnoremap hc I0 +" Uncomment a line +nnoremap hC 05x/-->3x0 diff --git a/stow/vim/.vim/ftplugin/html/snips/template.txt b/stow/vim/.vim/ftplugin/html/snips/template.txt new file mode 100644 index 0000000..38d9f26 --- /dev/null +++ b/stow/vim/.vim/ftplugin/html/snips/template.txt @@ -0,0 +1,12 @@ + + + + <+++> + + + + + <++> + + + diff --git a/stow/vim/.vim/ftplugin/java/java.vim b/stow/vim/.vim/ftplugin/java/java.vim new file mode 100644 index 0000000..2595b32 --- /dev/null +++ b/stow/vim/.vim/ftplugin/java/java.vim @@ -0,0 +1,14 @@ +" ~/.vim/ftplugin/java.vim +" Java-specific vim configuration + +call matchadd('ColorColumn', '\%131v', 100) + +let g:syntastic_java_checkers = [] + +nnoremap gt :YcmCompleter GoTo +nnoremap gr :YcmCompleter GoToReferences +nnoremap fi :YcmCompleter FixIt +nnoremap rr :YcmCompleter RefactorRename +nnoremap e :YcmDiags +nnoremap R :!./run.sh + diff --git a/stow/vim/.vim/ftplugin/javascript/javascript.vim b/stow/vim/.vim/ftplugin/javascript/javascript.vim new file mode 100644 index 0000000..4935410 --- /dev/null +++ b/stow/vim/.vim/ftplugin/javascript/javascript.vim @@ -0,0 +1,38 @@ +" ~/.vim/ftplugin/javascript/javascript.vim +" JavaScript-specific vim configuration +" +" Syntastic linters: jslint + +" JSLint arguments +" let g:syntastic_javascript_jslint_args = "--browser --indent" + +" ALE +let b:ale_linters = ['eslint'] + +" Tabs are expanded to 4 spaces +setlocal tabstop=4 shiftwidth=4 expandtab +" Show existing tabs (they can be deleted with :retab) +setlocal list + +" Column marker: 110 characters +call matchadd('ColorColumn', '\%111v', 100) +setlocal textwidth=110 + +" Mappings + +let mapleader = " " + +nnoremap C :sp ~/.vim/ftplugin/javascript/javascript.vim + +nnoremap gd :YcmCompleter GoTo +nnoremap gr :YcmCompleter GoToReferences +nnoremap gh :YcmCompleter GetType +nnoremap gD :YcmCompleter GetDoc +nnoremap gR :YcmCompleter RefactorRename +nnoremap fi :YcmCompleter FixIt +nnoremap e :YcmDiags + +let mapleader = "," + +inoremap if if (<+++>) {<++>} <++>?<+++>cf> +inoremap else else {<+++>}<++>?<+++>cf> diff --git a/stow/vim/.vim/ftplugin/plantuml/plantuml.vim b/stow/vim/.vim/ftplugin/plantuml/plantuml.vim new file mode 100644 index 0000000..5bab6a2 --- /dev/null +++ b/stow/vim/.vim/ftplugin/plantuml/plantuml.vim @@ -0,0 +1,20 @@ +" ~/.vim/ftplugin/plantuml/plantuml.vim +" PlantUML-specific vim configuration + +" Tabs hate: tabs are expanded to 4 spaces +setlocal tabstop=4 shiftwidth=4 expandtab +" Show existing tabs (they can be deleted with :retab) +setlocal list + +" Column marker: 80 characters +call matchadd('ColorColumn', '\%81v', 100) +setlocal textwidth=80 + +let mapleader = " " + +nnoremap temp :-1r ~/.vim/ftplugin/plantuml/snips/template.txtGdd?<+++>cf> + +nnoremap C :sp ~/.vim/ftplugin/plantuml/plantuml.vim + +nnoremap c :w:!compilePlantUML.sh "%" +nnoremap o :w:!compilePlantUML.sh -o "%" diff --git a/stow/vim/.vim/ftplugin/plantuml/snips/template.txt b/stow/vim/.vim/ftplugin/plantuml/snips/template.txt new file mode 100644 index 0000000..f649539 --- /dev/null +++ b/stow/vim/.vim/ftplugin/plantuml/snips/template.txt @@ -0,0 +1,9 @@ +@startuml + +class <+++> { + <++> +} + +<++> + +@enduml diff --git a/stow/vim/.vim/ftplugin/python/python.vim b/stow/vim/.vim/ftplugin/python/python.vim new file mode 100644 index 0000000..358f902 --- /dev/null +++ b/stow/vim/.vim/ftplugin/python/python.vim @@ -0,0 +1,34 @@ +" ~/.vim/ftplugin/python/python.vim +" Python-specific vim configuration + +" Tabs are expanded to 4 spaces +setlocal tabstop=4 shiftwidth=4 expandtab +" Show existing tabs (they can be deleted with :retab) +setlocal list + +" Column marker: 90 characters +call matchadd('ColorColumn', '\%91v', 100) +setlocal textwidth=90 + +let b:ale_python_pylint_options = '-d invalid-name' + +" Mappings + +let mapleader = " " + +nnoremap C :sp ~/.vim/ftplugin/python/python.vim +nnoremap x :! ./% +nnoremap X :! ./% + +nnoremap gd :YcmCompleter GoTo +nnoremap gr :YcmCompleter GoToReferences +nnoremap gR :YcmCompleter RefactorRename +nnoremap gd :YcmCompleter GetDoc +nnoremap gT :YcmCompleter GetType + +nnoremap db :!tmux split-window -l '40\%' 'python -mฬ€ pdb %' + +let mapleader = "," + +inoremap temp :-1r ~/.vim/ftplugin/python/snips/templateGdd?<+++>cf> +inoremap class :-1r ~/.vim/ftplugin/python/snips/classGdd?<+++>cf> diff --git a/stow/vim/.vim/ftplugin/python/snips/class b/stow/vim/.vim/ftplugin/python/snips/class new file mode 100644 index 0000000..0febf0c --- /dev/null +++ b/stow/vim/.vim/ftplugin/python/snips/class @@ -0,0 +1,3 @@ +class <+++>: + def __init__(<++>): + self.<++> = <++> diff --git a/stow/vim/.vim/ftplugin/python/snips/template b/stow/vim/.vim/ftplugin/python/snips/template new file mode 100644 index 0000000..d10fa4a --- /dev/null +++ b/stow/vim/.vim/ftplugin/python/snips/template @@ -0,0 +1,5 @@ +#!/usr/bin/python + +"""<+++>""" + +<++> diff --git a/stow/vim/.vim/ftplugin/sent/sent.vim b/stow/vim/.vim/ftplugin/sent/sent.vim new file mode 100644 index 0000000..c9cc974 --- /dev/null +++ b/stow/vim/.vim/ftplugin/sent/sent.vim @@ -0,0 +1,19 @@ +" ~/.vim/ftplugin/sent/sent.vim +" Vim configuration for writing sent presentations + +" Tabs hate: tabs are expanded to 4 spaces +setlocal tabstop=4 shiftwidth=4 expandtab +" Show existing tabs (they can be deleted with :retab) +setlocal list + +call matchadd('ColorColumn', '\%41v', 100) +setlocal textwidth=40 + +setlocal spell + +let mapleader = " " + +nnoremap C :sp ~/.vim/ftplugin/sent/sent.vim + +nnoremap c :w:!killall sent :!sent % & +nnoremap o :w:!sent % & diff --git a/stow/vim/.vim/ftplugin/sh/sh.vim b/stow/vim/.vim/ftplugin/sh/sh.vim new file mode 100644 index 0000000..3eb4da5 --- /dev/null +++ b/stow/vim/.vim/ftplugin/sh/sh.vim @@ -0,0 +1,16 @@ +" ~/.vim/ftplugin/sh.vim +" Bourne shell scripts specific vim configuration +" +" Linters: sh, shellcheck + +call matchadd('ColorColumn', '\%111v', 100) +setlocal textwidth=110 + +nnoremap C :sp ~/.vim/ftplugin/sh/sh.vim +nnoremap +x :!chmod 744 % +nnoremap x :w:!./% +nnoremap e :Errors + +inoremap sh #!/bin/sh +inoremap if if <+++>; then<++>fi<++>?<+++>cf> +"inoremap if :read ~/.vim/ftplugin/sh/snippets/if.txtkdd/<+++>cf> diff --git a/stow/vim/.vim/ftplugin/sh/snippets/if.txt b/stow/vim/.vim/ftplugin/sh/snippets/if.txt new file mode 100644 index 0000000..9f6bb88 --- /dev/null +++ b/stow/vim/.vim/ftplugin/sh/snippets/if.txt @@ -0,0 +1,3 @@ +if <+++>; then + <++> +fi<++> diff --git a/stow/vim/.vim/ftplugin/tex/snips/template.txt b/stow/vim/.vim/ftplugin/tex/snips/template.txt new file mode 100644 index 0000000..1f4bd46 --- /dev/null +++ b/stow/vim/.vim/ftplugin/tex/snips/template.txt @@ -0,0 +1,30 @@ +\documentclass{article} + +\usepackage{geometry} +\usepackage{graphicx} +\usepackage{booktabs} + +\geometry{left=4.5cm,top=2cm,bottom=2cm,right=4.5cm} + +\renewcommand{\contentsname}{Contenidos} +\renewcommand{\figurename}{Figura} + +\begin{document} + +\frenchspacing + +\title{<+++>} + +\author{<++>} + +\date{} + +\maketitle + +\tableofcontents + +\section{<++>} + +<++> + +\end{document} diff --git a/stow/vim/.vim/ftplugin/tex/tex.vim b/stow/vim/.vim/ftplugin/tex/tex.vim new file mode 100644 index 0000000..87f3c88 --- /dev/null +++ b/stow/vim/.vim/ftplugin/tex/tex.vim @@ -0,0 +1,45 @@ +" ~/.vim/ftplugin/tex.vim +" LaTeX-specific vim configuration + +" Syntastic linters: chktex, lacheck, proselint + +call matchadd('ColorColumn', '\%91v', 100) +setlocal textwidth=80 + +let mapleader = " " + +nnoremap C :sp ~/.vim/ftplugin/tex/tex.vim +nnoremap e :Errors +" proselint not enabled by default (it's slow) +"nnoremap sp :SyntasticCheck proselint + +nnoremap c :w:!toPDF.sh % +nnoremap o :w:!toPDF.sh -o % +nnoremap O :w:!toPDF.sh -o % +nnoremap m :w:!make +nnoremap M :w:!make + +nnoremap temp :-1r ~/.vim/ftplugin/tex/snips/template.txt/<+++>cf> + +let mapleader = "," + +inoremap ldocclass \documentclass{}o<++>k$i +inoremap lpckg \usepackage{}o<++>k$i +inoremap lbdoc \begin{document}o\end{document}kkI +inoremap lauthor \author{}o<++>k$i +inoremap ltitle \title{}o<++>k$i +inoremap lsection \section{}o<++>k$i +inoremap lssection \subsection{}o<++>k$i +inoremap lsssection \subsubsection{}o<++>k$i +inoremap lssssection \paragraph{}o<++>k$i +inoremap lsssssection \subparagraph{}o<++>k$i +inoremap lb \textbf{}<++>F}i +inoremap li \textit{}<++>F}i +inoremap lemph \emph{}<++>F}i +inoremap llabel \label{}<++>F}i +inoremap lref ~\ref{}<++>F}i +inoremap lenumerate \begin{enumerate}o\end{enumerate}kkI\itemI<++>k<$a +inoremap litemize \begin{itemize}o\end{itemize}kkI\itemI<++>k<$a +inoremap litem \item<++>k$a +inoremap limage \begin{figure}[h]\begin{center}\includegraphics[width=\textwidth]{}\caption{<++>}\end{center}\end{figure}<++>4k$i +inoremap ltable \begin{table}[h]\makebox[\linewidth]{\centering\centering\begin{tabular}{ccxxx}\toprule<++>&<++>\\\midrule<++>&<++>\\\bottomrule\end{tabular}}\end{table}<++>?xxxcw diff --git a/stow/vim/.vim/ftplugin/text/text.vim b/stow/vim/.vim/ftplugin/text/text.vim new file mode 100644 index 0000000..c370a74 --- /dev/null +++ b/stow/vim/.vim/ftplugin/text/text.vim @@ -0,0 +1,20 @@ +" ~/.vim/ftplugin/text/text.vim +" Plain text files vim configuration +" +" Syntastic linter: proselint + +" Tabs hate: tabs are expanded to 2 spaces +setlocal tabstop=2 shiftwidth=2 expandtab +" Show existing tabs (they can be deleted with :retab) +setlocal list + +let mapleader = " " + +call matchadd('ColorColumn', '\%101v', 100) +setlocal textwidth=100 + +nnoremap C :sp ~/.vim/ftplugin/text/text.vim + +" Proselint is slow to act +nnoremap sp :SyntasticCheck proselint +nnoremap e :Errors diff --git a/stow/vim/.vim/ftplugin/typescript/typescript.vim b/stow/vim/.vim/ftplugin/typescript/typescript.vim new file mode 100644 index 0000000..7c91032 --- /dev/null +++ b/stow/vim/.vim/ftplugin/typescript/typescript.vim @@ -0,0 +1,33 @@ +" ~/.vim/ftplugin/typescript/typescript.vim +" TypeScript-specific vim configuration + +" ALE +let b:ale_linters = ['eslint'] + +" Tabs are expanded to 4 spaces +setlocal tabstop=4 shiftwidth=4 expandtab +" Show existing tabs (they can be deleted with :retab) +setlocal list + +" Column marker: 110 characters +call matchadd('ColorColumn', '\%111v', 100) +setlocal textwidth=110 + +" Mappings + +let mapleader = " " + +nnoremap C :sp ~/.vim/ftplugin/typescript/typescript.vim + +nnoremap gd :YcmCompleter GoTo +nnoremap gr :YcmCompleter GoToReferences +nnoremap gh :YcmCompleter GetType +nnoremap gD :YcmCompleter GetDoc +nnoremap gR :YcmCompleter RefactorRename +nnoremap fi :YcmCompleter FixIt +nnoremap e :YcmDiags + +let mapleader = "," + +inoremap if if (<+++>) {<++>} <++>?<+++>cf> +inoremap else else {<+++>}<++>?<+++>cf> diff --git a/stow/vim/.vim/ftplugin/vimwiki/snips/plantUml.txt b/stow/vim/.vim/ftplugin/vimwiki/snips/plantUml.txt new file mode 100644 index 0000000..4a016eb --- /dev/null +++ b/stow/vim/.vim/ftplugin/vimwiki/snips/plantUml.txt @@ -0,0 +1,5 @@ +```{.plantuml caption="<+++>"} +@startuml +<++> +@enduml +``` diff --git a/stow/vim/.vim/ftplugin/vimwiki/snips/template.txt b/stow/vim/.vim/ftplugin/vimwiki/snips/template.txt new file mode 100644 index 0000000..f6b16a8 --- /dev/null +++ b/stow/vim/.vim/ftplugin/vimwiki/snips/template.txt @@ -0,0 +1,15 @@ +--- +header-includes: + - \usepackage[margin=1.5in]{geometry} + +title: "Title" +author: +- รรฑigo Gutiรฉrrez Fernรกndez + + \ + + UO238186 +date: "10/04/2020" +--- + +# Introducciรณn diff --git a/stow/vim/.vim/ftplugin/vimwiki/vimwiki.vim b/stow/vim/.vim/ftplugin/vimwiki/vimwiki.vim new file mode 100644 index 0000000..c361600 --- /dev/null +++ b/stow/vim/.vim/ftplugin/vimwiki/vimwiki.vim @@ -0,0 +1,39 @@ +" ~/.vim/ftplugin/vimwiki.vim +" vimwiki-specific vim configuration +" +" Syntastic linter: mdl, proselint, textlint + +"let g:syntastic_vimwiki_checkers = ['markdown/mdl'] + +" Tabs hate: tabs are expanded to 2 spaces +setlocal tabstop=2 shiftwidth=2 expandtab +" Show existing tabs (they can be deleted with :retab) +setlocal list + +" Text width +match ColorColumn /\%81v/ +setlocal textwidth=80 +setlocal linebreak + +" Syntax highlighting colors +highlight Title ctermfg=blue +highlight TitleHash ctermfg=cyan +match TitleHash /^##*/ + +setlocal conceallevel=1 + +let mapleader = " " + +nnoremap C :sp ~/.vim/ftplugin/vimwiki/vimwiki.vim +nnoremap e :Errors + +nnoremap tt :r ~/.vim/ftplugin/vimwiki/snips/template.txt +nnoremap tp :r ~/.vim/ftplugin/vimwiki/snips/plantUml.txt/<+++>cf> + +nnoremap c :w:!toPDF.sh "%" +nnoremap o :w:!toPDF.sh -o "%" + +let mapleader = "," + +inoremap h < l >>A diff --git a/stow/vim/.vim/plugin/SWTC.vim b/stow/vim/.vim/plugin/SWTC.vim new file mode 100644 index 0000000..9459e92 --- /dev/null +++ b/stow/vim/.vim/plugin/SWTC.vim @@ -0,0 +1,339 @@ +" Vim global plugin for Star Wars crawls +" Maintainer: Damian Conway +" License: This file is placed in the public domain. + +"###################################################################### +"## ## +"## To use: ## +"## ## +"## :SWTC ## +"## ## +"## See file 'intro.swtc' for the crawl-specification syntax ## +"## ## +"###################################################################### + + +" If already loaded, we're done... +if exists("loaded_SWcrawl") + finish +endif +let loaded_SWcrawl = 1 + +" Preserve external compatibility options, then enable full vim compatibility... +let s:save_cpo = &cpo +set cpo&vim + +" Set up the actual colon command... +command! -nargs=1 -complete=file SWTC call SWcrawl() + + +" Implementation.... + +let s:CRAWL_SPEED = 1 "(lines per second) +let s:STAR_DENSITY = 50 "(pixels per star, i.e. 1 star per STAR_DENSITY pixels) +let s:STARFIELD_HEIGHT = 2 "(screens deep) + +let s:LOGO_LINE1 = '^\s*\[\zs.*\ze\]\s*$' +let s:LOGO_LINE2 = '^\s*\[\[\zs.*\ze\]\]\s*$' +let s:LOGO_LINE3 = '^\s*\[\[\[\zs.*\ze\]\]\]\s*$' +let s:LOGO_LINE4 = '^\s*\[\[\[\[\zs.*\ze\]\]\]\]\s*$' +let s:CENTRED_CRAWL_LINE = '^\s*[>]\s*\zs.\{-}\ze\s*[<]\s*$' +let s:CRAWL_LINE = '^\s*[|]\s*\zs.\{-}\ze\s*[|]\s*$' +let s:PREFACE_LINE = '^\s*\zs.\{-}\ze\s*$' + +highlight SWC_PREFACE ctermfg=cyan +highlight SWC_FADE_LIGHT ctermfg=cyan +highlight SWC_FADE_DARK ctermfg=blue +highlight SWC_LOGO ctermfg=yellow cterm=bold +highlight SWC_CRAWL ctermfg=yellow +highlight SWC_STAR ctermfg=white +highlight SWC_BLACK ctermfg=black ctermbg=black + +let s:PREFACE_POS = { 'x': 10, 'y': 5 } + +function! SWcrawl (textsource) + " Load preface, logo, and text to be crawled... + let preface = [] + let logo1 = [] + let logo2 = [] + let logo3 = [] + let logo4 = [] + let crawl = [] + let centred = [] + let max_crawl_width = 0 + for nextline in readfile(a:textsource) + " Ignore blank lines... + if nextline =~ '^\s*$' + continue + + " Lines in [...] are logo components... + elseif nextline =~ s:LOGO_LINE4 + let logo4 += [ matchstr(nextline, s:LOGO_LINE4) ] + elseif nextline =~ s:LOGO_LINE3 + let logo3 += [ matchstr(nextline, s:LOGO_LINE3) ] + elseif nextline =~ s:LOGO_LINE2 + let logo2 += [ matchstr(nextline, s:LOGO_LINE2) ] + elseif nextline =~ s:LOGO_LINE1 + let logo1 += [ matchstr(nextline, s:LOGO_LINE1) ] + + " Lines in |...| are crawl components... + elseif nextline =~ s:CRAWL_LINE + let next_crawl = matchstr(nextline, s:CRAWL_LINE) + if strlen(next_crawl) > max_crawl_width + let max_crawl_width = strlen(substitute(next_crawl,'\s\+',' ','g')) + endif + let crawl += [ next_crawl ] + let centred += [ 0 ] + + " Lines in >...< are centred crawl components... + elseif nextline =~ s:CENTRED_CRAWL_LINE + let next_crawl = matchstr(nextline, s:CENTRED_CRAWL_LINE) + if strlen(next_crawl) > max_crawl_width + let max_crawl_width = strlen(substitute(next_crawl,'\s\+',' ','g')) + endif + let crawl += [ next_crawl ] + let centred += [ 1 ] + + " Anything else is preface... + else + let preface += [ substitute(matchstr(nextline, s:PREFACE_LINE), "^\s*", repeat(" ",s:PREFACE_POS.x), '') ] + + endif + endfor + + " Ensure all logos available... + let logo1 = len(logo1) ? logo1 : ["YOUR", "LOGO", "HERE"] + let logo2 = len(logo2) ? logo2 : copy(logo1) + let logo3 = len(logo3) ? logo3 : copy(logo2) + let logo4 = len(logo4) ? logo4 : copy(logo3) + + " Save current buffer for final transition effect... + let original_buffer = getline(1,'$') + + " Switch to a new buffer... + let prev_matches = getmatches() + enew! + let b:WIN = { 'x' : winwidth(0), 'y' : winheight(0) } + call setline(1, repeat([""], b:WIN.y + 1)) + + " And hide annoyances... + set lcs= + let old_rulerformat = &rulerformat + let &rulerformat="%#SWC_BLACK#%l" + echo "" + + " Generate starfield... + let stars = SWC_gen_stars() + + " Clear screen... + call setline(1, repeat([""], s:STARFIELD_HEIGHT * b:WIN.y) + original_buffer) + redraw + sleep 2 + + " Start with preface... + call matchadd('SWC_PREFACE', '.', 100) + call setline(s:PREFACE_POS.y, preface) + echo "" + redraw + sleep 5 + + " Clean up... + call clearmatches() + call setline(s:PREFACE_POS.y, repeat([""], len(preface))) + echo "" + redraw + sleep 1 + + " Then show logo receding at centre of screen... + call clearmatches() + call matchadd('SWC_BLACK', '*', 102) + call matchadd('SWC_STAR', '\s\zs[.]\ze\s', 101) + call matchadd('SWC_LOGO', '.', 100) + call SWC_draw_logo(logo1) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 3 + + " Push it away... + call setline(1, repeat([""], b:WIN.y)) + call SWC_draw_logo(logo2) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 500m + + call setline(1, repeat([""], b:WIN.y)) + call SWC_draw_logo(logo3) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 500m + + call setline(1, repeat([""], b:WIN.y)) + call SWC_draw_logo(logo4) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 500m + + + " Clean up... + call clearmatches() + call matchadd('SWC_STAR', '\s\zs[.]\ze\s', 101) + call setline(1, repeat([""], b:WIN.y)) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 2 + + " Run crawl... + call clearmatches() + call matchadd('SWC_CRAWL', '.', 100) + call matchadd('SWC_STAR', '\s\zs[.]\ze\s', 101) + for offset_from_bottom in range(1, len(crawl) + b:WIN.y) + let crawl_line = offset_from_bottom < b:WIN.y ? 0 : offset_from_bottom - b:WIN.y + 1 + for screen_line in range(1, b:WIN.y) + if screen_line >= b:WIN.y - offset_from_bottom && crawl_line < len(crawl) + let padded_line = SWC_pad(crawl[crawl_line], screen_line, centred[crawl_line], max_crawl_width) + call setline(screen_line, padded_line) + let crawl_line += 1 + else + call setline(screen_line, "") + endif + endfor + call SWC_paint_stars(stars) + echo "" + redraw + exec 'sleep ' . s:trunc(1000/s:CRAWL_SPEED) . 'm' + if getchar(0) || offset_from_bottom > len(crawl) && padded_line !~ '\S' + break + endif + endfor + + " Pan starfield down... + call matchadd('SWC_FADE_DARK', '[^.]', 200) + sleep 200m + for offset_from_top in range(1, s:STARFIELD_HEIGHT * b:WIN.y) + 1delete + redraw + exec 'sleep ' . (200 - 2 * offset_from_top) . 'm' + endfor + sleep 200m + + + " Switch back to previous buffer and restore normal highlighting... + edit! # + call setmatches(prev_matches) + let &rulerformat = old_rulerformat + redraw + +endfunction + +function s:trunc (n) + return str2nr(string( a:n )) +endfunction + +function! SWC_draw_logo (logo) + let logo = copy(a:logo) + + " Find centre for logo... + let logo_width = 0 + for line in logo + if strlen(line) > logo_width + let logo_width = strlen(line) + endif + endfor + let logo_pos_x = (b:WIN.x - logo_width) / 2 + let logo_pos_y = (b:WIN.y - len(logo)) / 2 + + " Move logo to centre... + call map(logo, "repeat(' ', logo_pos_x) . v:val") + + " Draw logo + call setline(logo_pos_y, logo) + +endfunction + +function! SWC_pad (text, y_pos, centred, max_text_width) + + " Does this need padding??? + let words = split(a:text, '\s\+') + if len(words) < 1 + return a:text + endif + + " How many unpadded characters are there??? + let unpadded_width = 0 + for word in words + let unpadded_width += strlen(word) + endfor + + " How much padding is needed??? + let rel_y = (2.0 * a:y_pos / b:WIN.y) - 1.0 + let stretched_width = s:trunc( a:max_text_width + rel_y * (b:WIN.x - a:max_text_width) ) + let required_padding = max([ 0, stretched_width - unpadded_width ]) + let indent = (b:WIN.x - stretched_width) / 2 + let gap_count = len(words) - 1 + + " Is this a last line??? + let tight = a:centred || strlen(a:text) < 0.9 * a:max_text_width + + " Insert padding... + if a:y_pos >= b:WIN.y/2 + let min_padding_needed_for = gap_count + if tight + let min_pad_per_gap = max([ 1, s:trunc(rel_y * 6.0) ]) + else + let min_pad_per_gap = max([ 1, required_padding / gap_count ]) + let leftover_padding = required_padding - gap_count * min_pad_per_gap + let min_padding_needed_for = min([ gap_count, gap_count - leftover_padding ]) + endif + let padded_text = join(words[0 : min_padding_needed_for], repeat(" ", min_pad_per_gap)) + \ . repeat(" ", min_pad_per_gap+1) + \ . join(words[min_padding_needed_for+1 : -1], repeat(" ", min_pad_per_gap+1)) + let padded_text = substitute(padded_text, '\s*$', '', '') + + " Or remove chars (in the distance)... + elseif a:text =~ '\S' +" let delta = s:trunc( 8.0 * (b:WIN.y/2 - a:y_pos) ) +" let greeked_len = max([ 0, strlen(substitute(a:text, '^\s*\|\s*$', '', 'g')) - delta ]) + let greeked_len = tight ? stretched_width * (unpadded_width + gap_count) / a:max_text_width : stretched_width + let padded_text = repeat('~', greeked_len) + + " Or ignore it... + else + let padded_text = "" + + endif + + " Indent to centre... + let padded_text = substitute(padded_text, '\s*$', '', '') + let max_ever_padding = b:WIN.x - a:max_text_width + let indent = a:centred ? (b:WIN.x - strlen(padded_text))/2 + \ : indent + return repeat(" ", indent) . padded_text +endfunction + +function! SWC_gen_stars () + let star_count = b:WIN.x * s:STARFIELD_HEIGHT * b:WIN.y / s:STAR_DENSITY + let stars = [] + for n in range(star_count) + let x = RandomNumber(b:WIN.x) + 1 + let y = RandomNumber(s:STARFIELD_HEIGHT * b:WIN.y) + 1 + let stars += [{'y':y,'x':x}] + endfor + return stars +endfunction + +function! SWC_paint_stars (stars) + let max_x = b:WIN.x + for star in a:stars + let line = strpart(getline(star.y) . repeat(" ", max_x), 0, max_x) + let line = substitute(line, '\s\zs\%'.(star.x-1).'c\s\ze\s', '.', '') + call setline(star.y, line) + endfor +endfunction + +" Restore previous external compatibility options +let &cpo = s:save_cpo diff --git a/stow/vim/.vim/plugin/dragvisuals.vim b/stow/vim/.vim/plugin/dragvisuals.vim new file mode 100644 index 0000000..12c4f5d --- /dev/null +++ b/stow/vim/.vim/plugin/dragvisuals.vim @@ -0,0 +1,345 @@ +" Vim global plugin for dragging virtual blocks +" Last change: Tue Jul 24 07:19:35 EST 2012 +" Maintainer: Damian Conway +" License: This file is placed in the public domain. + +"######################################################################### +"## ## +"## Add the following (uncommented) to your .vimrc... ## +"## ## +"## runtime plugin/dragvisuals.vim ## +"## ## +"## vmap DVB_Drag('left') ## +"## vmap DVB_Drag('right') ## +"## vmap DVB_Drag('down') ## +"## vmap DVB_Drag('up') ## +"## vmap D DVB_Duplicate() ## +"## ## +"## " Remove any introduced trailing whitespace after moving... ## +"## let g:DVB_TrimWS = 1 ## +"## ## +"## Or, if you use the arrow keys for normal motions, choose ## +"## four other keys for block dragging. For example: ## +"## ## +"## vmap h DVB_Drag('left') ## +"## vmap l DVB_Drag('right') ## +"## vmap j DVB_Drag('down') ## +"## vmap k DVB_Drag('up') ## +"## ## +"## Or: ## +"## ## +"## vmap DVB_Drag('left') ## +"## vmap DVB_Drag('right') ## +"## vmap DVB_Drag('down') ## +"## vmap DVB_Drag('up') ## +"## ## +"## Or even: ## +"## ## +"## vmap DVB_Drag('left') ## +"## vmap DVB_Drag('right') ## +"## vmap DVB_Drag('down') ## +"## vmap DVB_Drag('up') ## +"## ## +"######################################################################### + + +" If already loaded, we're done... +if exists("loaded_dragvirtualblocks") + finish +endif +let loaded_dragvirtualblocks = 1 + +" Preserve external compatibility options, then enable full vim compatibility... +let s:save_cpo = &cpo +set cpo&vim + +"====[ Implementation ]==================================== + +" Toggle this to stop trimming on drags... +if !exists('g:DVB_TrimWS') + let g:DVB_TrimWS = 1 +endif + +function! DVB_Drag (dir) + " No-op in Visual mode... + if mode() ==# 'v' + return "\gv" + + " Do Visual Line drag indirectly via temporary nmap + " (to ensure we have access to block position data)... + elseif mode() ==# 'V' + " Set up a temporary convenience... + exec "nnoremap M \Drag_Lines('".a:dir."')" + + " Return instructions to implement the move and reset selection... + return '"vyM' + + " Otherwise do Visual Block drag indirectly via temporary nmap + " (to ensure we have access to block position data)... + else + " Set up a temporary convenience... + exec "nnoremap M \Drag_Block('".a:dir."')" + + " Return instructions to implement the move and reset selection... + return '"vyM' + endif +endfunction + +" Duplicate selected block and place to the right... +function! DVB_Duplicate () + exec "nnoremap M \DuplicateBlock()" + return '"vyM' +endfunction + +function! s:DuplicateBlock () + nunmap M + " Locate block boundaries... + let [buf_left, line_left, col_left, offset_left ] = getpos("'<") + let [buf_right, line_right, col_right, offset_right] = getpos("'>") + + " Identify special '$' blocks... + let dollar_block = 0 + let start_col = min([col_left+offset_left, col_right+offset_right]) + let end_col = max([col_left+offset_left, col_right+offset_right]) + let visual_width = end_col - start_col + 1 + for visual_line in split(getreg("v"),"\n") + if strlen(visual_line) > visual_width + let dollar_block = 1 + let visual_width = strlen(visual_line) + endif + endfor + let square_up = (dollar_block ? (start_col+visual_width-2).'|' : '') + + set virtualedit=all + return 'gv'.square_up.'yPgv' + \. (visual_width-dollar_block) . 'lo' . (visual_width-dollar_block) . 'l' + \. "y:set virtualedit=block\gv" + \. (dollar_block ? 'o$' : '') +endfunction + + +" Kludge to hide change reporting inside implementation... +let s:NO_REPORT = ":let b:DVB_report=&report\:let &report=1000000000\" +let s:PREV_REPORT = ":let &report = b:DVB_report\" + + +" Drag in specified direction in Visual Line mode... +function! s:Drag_Lines (dir) + " Clean up the temporary convenience... + nunmap M + + " Locate block being shifted... + let [buf_left, line_left, col_left, offset_left ] = getpos("'<") + let [buf_right, line_right, col_right, offset_right] = getpos("'>") + + " Drag entire lines left if possible... + if a:dir == 'left' + " Are all lines indented at least one space??? + let lines = getline(line_left, line_right) + let all_indented = match(lines, '^[^ ]') == -1 + nohlsearch + + " If can't trim one space from start of each line, be a no-op... + if !all_indented + return 'gv' + + " Otherwise drag left by removing one space from start of each line... + else + return s:NO_REPORT + \ . "gv:s/^ //\" + \ . s:PREV_REPORT + \ . "gv" + endif + + " To drag entire lines right, add a space in column 1... + elseif a:dir == 'right' + return s:NO_REPORT + \ . "gv:s/^/ /\:nohlsearch\" + \ . s:PREV_REPORT + \ . "gv" + + " To drag entire lines upwards... + elseif a:dir == 'up' + let EOF = line('$') + + " Can't drag up if at first line... + if line_left == 1 || line_right == 1 + return 'gv' + + " Needs special handling at EOF (because cursor moves up on delete)... + elseif line_left == EOF || line_right == EOF + let height = line_right - line_left + let select_extra = height ? height . 'j' : "" + return s:NO_REPORT + \ . 'gvxP' + \ . s:PREV_REPORT + \ . 'V' . select_extra + + " Otherwise just cut-move-paste-reselect... + else + let height = line_right - line_left + let select_extra = height ? height . 'j' : "" + return s:NO_REPORT + \ . 'gvxkP' + \ . s:PREV_REPORT + \ . 'V' . select_extra + endif + + " To drag entire lines downwards... + elseif a:dir == 'down' + let EOF = line('$') + + " This is how much extra we're going to have to reselect... + let height = line_right - line_left + let select_extra = height ? height . 'j' : "" + + " Needs special handling at EOF (to push selection down into new space)... + if line_left == EOF || line_right == EOF + return "O\gv" + + " Otherwise, just cut-move-paste-reselect... + else + return s:NO_REPORT + \ . 'gvxp' + \ . s:PREV_REPORT + \ . 'V' . select_extra + endif + + endif +endfunction + +" Drag in specified direction in Visual Block mode... +function! s:Drag_Block (dir) + " Clean up the temporary convenience... + nunmap M + + " Locate block being shifted... + let [buf_left, line_left, col_left, offset_left ] = getpos("'<") + let [buf_right, line_right, col_right, offset_right] = getpos("'>") + + " Identify special '$' blocks... + let dollar_block = 0 + let start_col = min([col_left+offset_left, col_right+offset_right]) + let end_col = max([col_left+offset_left, col_right+offset_right]) + let visual_width = end_col - start_col + 1 + for visual_line in split(getreg("v"),"\n") + if strlen(visual_line) > visual_width + let dollar_block = 1 + let visual_width = strlen(visual_line) + endif + endfor + let square_up = (dollar_block ? (start_col+visual_width-2).'|' : '') + + " Drag left... + if a:dir == 'left' + "Can't drag left at left margin... + if col_left == 1 || col_right == 1 + return 'gv' + + " Otherwise reposition one column left (and optionally trim any whitespace)... + elseif g:DVB_TrimWS + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " Are we moving past other text??? + let square_up_final = "" + if dollar_block + let lines = getline(line_left, line_right) + if match(lines, '^.\{'.(start_col-2).'}\S') >= 0 + let dollar_block = 0 + let square_up_final = (start_col+visual_width-3).'|' + endif + endif + + let vcol = start_col - 2 + return 'gv'.square_up.'xhP' + \ . s:NO_REPORT + \ . "gvhoho:s/\\s*$//\gv\" + \ . ':set virtualedit=' . prev_ve . "\" + \ . s:PREV_REPORT + \ . ":nohlsearch\gv" + \ . (dollar_block ? '$' : square_up_final ) + else + return 'gv'.square_up.'xhPgvhoho' + endif + + " Drag right... + elseif a:dir == 'right' + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " Reposition block one column to the right... + if g:DVB_TrimWS + let vcol = start_col + return 'gv'.square_up.'xp' + \ . s:NO_REPORT + \ . "gvlolo" + \ . ":s/\\s*$//\gv\" + \ . ':set virtualedit=' . prev_ve . "\" + \ . s:PREV_REPORT + \ . (dollar_block ? 'gv$' : 'gv') + else + return 'gv'.square_up.'xp:set virtualedit=' . prev_ve . "\gvlolo" + endif + + " Drag upwards... + elseif a:dir == 'up' + " Can't drag upwards at top margin... + if line_left == 1 || line_right == 1 + return 'gv' + endif + + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " If trimming whitespace, jump to just below block to do it... + if g:DVB_TrimWS + let height = line_right - line_left + 1 + return 'gv'.square_up.'xkPgvkoko"vy' + \ . height + \ . 'j:s/\s*$//' + \ . "\:nohlsearch\:set virtualedit=" + \ . prev_ve + \ . "\gv" + \ . (dollar_block ? '$' : '') + + " Otherwise just move and reselect... + else + return 'gv'.square_up.'xkPgvkoko"vy:set virtualedit=' + \ . prev_ve + \ . "\gv" + \ . (dollar_block ? '$' : '') + endif + + " Drag downwards... + elseif a:dir == 'down' + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " If trimming whitespace, move to just above block to do it... + if g:DVB_TrimWS + return 'gv'.square_up.'xjPgvjojo"vyk:s/\s*$//' + \ . "\:nohlsearch\:set virtualedit=" + \ . prev_ve + \ . "\gv" + \ . (dollar_block ? '$' : '') + + " Otherwise just move and reselect... + else + return 'gv'.square_up.'xjPgvjojo"vy' + \ . "\:set virtualedit=" + \ . prev_ve + \ . "\gv" + \ . (dollar_block ? '$' : '') + endif + endif +endfunction + + +" Restore previous external compatibility options +let &cpo = s:save_cpo + diff --git a/stow/vim/.vim/plugin/rng.vim b/stow/vim/.vim/plugin/rng.vim new file mode 100644 index 0000000..51c9991 --- /dev/null +++ b/stow/vim/.vim/plugin/rng.vim @@ -0,0 +1,83 @@ +" George Marsaglia's Multiply-with-carry Random Number Generator {{{ +" Modified to work within Vim's semantics +let s:m_w = 1 + getpid() +let s:m_z = localtime() + +" not sure of the wisdom of generating a full 32-bit RN here +" and then using abs() on the sucker. Feedback welcome. +function! RandomNumber(...) + if a:0 == 0 + let s:m_z = (36969 * and(s:m_z, 0xffff)) + (s:m_z / 65536) + let s:m_w = (18000 * and(s:m_w, 0xffff)) + (s:m_w / 65536) + return (s:m_z * 65536) + s:m_w " 32-bit result + elseif a:0 == 1 " We return a number in [0, a:1] or [a:1, 0] + return a:1 < 0 ? RandomNumber(a:1,0) : RandomNumber(0,a:1) + else " if a:2 >= 2 + return abs(RandomNumber()) % (abs(a:2 - a:1) + 1) + a:1 + endif +endfunction +" end RNG }}} + +" RandomChar(base, cap) +" base : the lowest char number desired +" cap : the highest char number desired +" Defaults to ASCII characters in the range +" 33-126 (!-~) +" But it's capable of much wider character tables +function! RandomChar(...) + let base = 33 + let cap = 126 + if a:0 > 0 + let base = a:1 + endif + if a:0 > 1 + let cap = a:2 + endif + return nr2char(RandomNumber(base, cap)) +endfunction + +function! RandomCharsInSet(length, set) + let from = join(map(range(len(a:set)), 'nr2char(char2nr("a")+v:val)'), '') + let to = join(a:set, '') + return map(RandomChars(a:length, 97, 96+len(a:set)), 'tr(v:val, from, to)') +endfunction + +function! RandomChars(length, ...) + let args = [] + if a:0 > 0 + if type(a:1) == type([]) + let args = a:1 + else + let args = a:000 + endif + endif + return map(repeat([0], a:length), 'call("RandomChar", args)') +endfunction + +function! RandomString(length, ...) + let args = [] + if a:0 > 0 + if type(a:1) == type([]) + let args = a:1 + else + let args = a:000 + endif + endif + return join(call('RandomChars', [a:length, args]), '') +endfunction + +let s:chars = '! " # $ % & '' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~' +let s:charlist = split(s:chars, ' ') + +function! RandomCharFromRegex(regex, ...) + let charlist = a:0 ? split(a:1, '\zs') : copy(s:charlist) + call filter(charlist, 'v:val =~ a:regex') + return charlist[RandomNumber(0, len(charlist) - 1)] +endfunction + +function! RandomStringFromRegex(regex, lenght, ...) + let charlist = a:0 ? split(a:1, '\zs') : copy(s:charlist) + call filter(charlist, 'v:val =~ a:regex') + let len = len(charlist) - 1 + return join(map(range(a:lenght), 'charlist[RandomNumber(0, len)]'), '') +endfunction diff --git a/stow/vim/.vimrc b/stow/vim/.vimrc new file mode 100644 index 0000000..9520648 --- /dev/null +++ b/stow/vim/.vimrc @@ -0,0 +1,280 @@ +" _ +" __ _(_)_ __ ___ _ __ ___ +" \ \ / / | '_ ` _ \| '__/ __| +" \ V /| | | | | | | | | (__ +" \_/ |_|_| |_| |_|_| \___| +" + +let mapleader = "," + +call plug#begin('~/.vim/plugged') "Update with PlugInstall +Plug 'PotatoesMaster/i3-vim-syntax' +Plug 'junegunn/goyo.vim' +Plug 'junegunn/fzf.vim' +Plug 'junegunn/limelight.vim' +Plug 'arcticicestudio/nord-vim' +Plug 'tpope/vim-surround' +Plug 'tpope/vim-repeat' +Plug 'vimwiki/vimwiki' +Plug 'vim-airline/vim-airline' +Plug 'psliwka/vim-smoothie' +"Plug 'vim-syntastic/syntastic' +Plug 'dense-analysis/ale' +"Plug 'Shougo/deoplete.nvim', {'do': ':UpdateRemotePlugins' } +"Plug 'Shougo/deoplete-clangx' +"Plug 'neoclide/coc.nvim', {'branch': 'release'} +Plug 'Valloric/YouCompleteMe' +"Plug 'OmniSharp/omnisharp-vim' +Plug 'dylanaraps/wal.vim' +"Plug 'ThePrimeagen/vim-be-good' +call plug#end() + +" Basic settings +set nocompatible +set encoding=utf-8 +set number relativenumber +set tabstop=4 +set shiftwidth=4 +set scrolloff=2 +set wildmode=longest,list,full +set splitbelow +set splitright +set vb " No bell +" Searching +set ignorecase +set wrapscan +set incsearch +set nohlsearch + +" Filetypes +filetype indent plugin on +au BufRead,BufNewFile *.pu,*.puml,*.pumlc set filetype=plantuml +au BufRead,BufNewFile *.g set filetype=antlr3 +au BufRead,BufNewFile *.g4 set filetype=antlr4 +au BufRead,BufNewFile *.sent set filetype=sent +let g:tex_flavor = "latex" + +" hlnext: Highlighting searches +nnoremap n n:call HLNext(0.1) +nnoremap N N:call HLNext(0.1) +function! HLNext(blinktime) + set invcursorline + redraw + exec 'sleep'.float2nr(a:blinktime*1000).'m' + set invcursorline + redraw +endfunction + +" dragvisuals: dragging visual blocks +vmap DVB_Drag('left') +vmap DVB_Drag('right') +vmap DVB_Drag('down') +vmap DVB_Drag('up') +vmap D DVB_Duplicate() + +" Showing tabs +"exec "set listchars=tab:\uBB\uBB,trail:\uB7,nbsp:~" +exec "set listchars=tab:\uBBยท,trail:\uB7,nbsp:~" +nnoremap l :set list! + +" For deoplete + +"let g:deoplete#enable_at_startup = 1 +" +"call deoplete#custom#option({ +"\ 'auto_complete': v:true, +"\ 'auto_complete_delay': 0, +"\ 'smart_case': v:true, +"\ }) +" +"call deoplete#custom#option('sources', { +"\ '_': ['ale'], +"\}) + +" For CoC +"inoremap coc#refresh() + +" For YouCompleteMe +let g:ycm_auto_trigger = 1 +let g:ycm_autoclose_preview_window_after_insertion = 1 + +" For syntastic +"set statusline+=%#warningmsg# +"set statusline+=%{SyntasticStatuslineFlag()} +"set statusline+=%* +"let g:syntastic_cs_checkers = ['code_checker'] +"let g:syntastic_enable_signs = 1 +"let g:syntastic_aggregate_errors = 1 +"let g:syntastic_always_populate_loc_list = 1 +"let g:syntastic_auto_loc_list = 2 +"let g:syntastic_check_on_open = 1 +"let g:syntastic_check_on_wq = 0 + +" For omnisharp +"let g:OmniSharp_server_stdio = 1 +"let g:OmniSharp_server_path = '/home/taamas/repos/omnisharp-roslyn/artifacts/scripts/OmniSharp.Stdio' +"let g:OmniSharp_selector_ui = 'fzf' + +" For cursor shape with tmux +if exists('$TMUX') + let &t_SI = "\Ptmux;\\e[5 q\\\" + let &t_EI = "\Ptmux;\\e[2 q\\\" +else + let &t_SI = "\e[5 q" + let &t_EI = "\e[2 q" +endif + +"if empty($TMUX) +" let &t_SI = "\]50;CursorShape=1\x7" " Vertical bar in insert mode +" let &t_EI = "\]50;CursorShape=0\x7" " Block in normal mode +"else +" let &t_SI = "\Ptmux;\\]50;CursorShape=1\x7\\\" +" let &t_EI = "\Ptmux;\\]50;CursorShape=0\x7\\\" +"endif + +"if &term =~ '^screen' +" " tmux will send xterm-style keys when its xterm-keys option is on +" execute "set =\e[1;*A" +" execute "set =\e[1;*B" +" execute "set =\e[1;*C" +" execute "set =\e[1;*D" +"endif + +" For vim-airline +if !exists('g:airline_symbols') + let g:airline_symbols = {} +endif +let g:airline_left_sep='' +let g:airline_right_sep='' +let g:airline_symbols.linenr = '๐Ÿ”ƒ' +let g:airline_symbols.maxlinenr = 'โ†ฉ' + +" For vimwiki +" filetype plugin on +let g:vimwiki_ext2syntax = {'.md': 'markdown', '.markdown': 'markdown', '.mdown': 'markdown'} +let g:vimwiki_list = [{'path': '~/docs/vimwiki/', 'syntax': 'markdown', 'ext': '.md'}, + \ {'path': '~/docs/notas/', 'syntax': 'markdown', 'ext': '.md'}, + \ {'path': '~/games/dungeonesYDragones/tarkba/vimwiki/', 'syntax': 'markdown', 'ext': '.md'}, + \ {'path': '~/games/dungeonesYDragones/creaciones/vimwiki/', 'syntax': 'markdown', 'ext': '.md'}] + +" Vertical split character +set fillchars+=vert:โ–ˆ + +" Shortcuts for split navigation +map h +map j +map k +map l +map < +map + +map - +map > +map 10< +map 5+ +map 5- +map 10> + +" Shortcuts for opening netrw +nnoremap f :40Vexplore +nnoremap F :40Lexplore + +" FZF +nnoremap :Files + +" Moving -here- +nnoremap h :cd %:h + +nnoremap :tabnew +"nnoremap gt "Can't be set without also remapping +"nnoremap gT + +nnoremap vrc :80vsp ~/.vimrc +nnoremap S :!tmux split-window -l '40\%' + +nnoremap / /grtfjx + +""" Color +colorscheme nord + +" Syntax +syntax enable +syntax on + +" Line number color +highlight LineNr ctermfg=12 +highlight LineNr cterm=NONE +highlight CursorLineNr ctermfg=5 +highlight CursorLineNr cterm=underline + +" Completion color +highlight Pmenu ctermbg=blue ctermfg=black +highlight PmenuSel ctermbg=darkblue ctermfg=white + +" Panel border color +"highlight VertSplit ctermbg=black ctermfg=darkblue + +" Symbol pairs match color +highlight MatchParen ctermbg=cyan ctermfg=black + +" Errors colors +highlight Error ctermbg=red ctermfg=black +highlight SpellBad ctermbg=red ctermfg=black + +" Comments colors +highlight Comment ctermfg=green + +" Line size marking +highlight ColorColumn ctermbg=darkblue ctermfg=black +"Redjail Bomb (thx Damian Conway!) +"highlight ColorColumn ctermbg=red ctermfg=blue +"exec 'set colorcolumn='.join(range(2,80,3), ',') + +"Clean trailing whitespaces on save +autocmd BufWritePre * %s/\s\+$//e + +" Autoupdate ~/.Xresources +autocmd BufWritePost ~/.Xresources !xrdb % + +" Generate ~/.mainpage/urls on ~/.config/qutebrowser save +autocmd BufWritePost ~/.config/qutebrowser/config.py !grep -e \'.*\':\ \'.*{}.*\' "$HOME/.config/qutebrowser/config.py" | grep -v DEFAULT | sed 's/,//; s/^\ *//' > ~/.mainpage/urls + +""" Remaps """ + +nnoremap Y y$ +nnoremap ss :set spell! +nnoremap sl :set spelllang= +nnoremap sL :setlocal spelllang= +nnoremap e :Errors +nnoremap x :w:! ./% +inoremap w :w +inoremap /<++>cf> +nnoremap p "+p +nnoremap y "+yy +vnoremap y "+y +nnoremap d "+dd +vnoremap d "+d + +" For Goyo +function! s:goyo_enter() + silent !tmux set status off +endfunction + +function! s:goyo_leave() + silent !tmux set status on +endfunction + +autocmd! User GoyoEnter nested call goyo_enter() +autocmd! User GoyoLeave nested call goyo_leave() + +let g:goyo_linenr = 1 +nnoremap G :Goyo \| set linebreak:e + +" For LimeLight +let g:limelight_conceal_ctermfg = 7 + +"" git +nnoremap gs :!git status +"nnoremap gpull :!git pull +nnoremap ga :!git add % +nnoremap gp :!git push +nnoremap gc :!git commit -m " diff --git a/stow/vim/dot-vim/autoload/plug.vim b/stow/vim/dot-vim/autoload/plug.vim deleted file mode 100644 index 9c296ac..0000000 --- a/stow/vim/dot-vim/autoload/plug.vim +++ /dev/null @@ -1,2788 +0,0 @@ -" vim-plug: Vim plugin manager -" ============================ -" -" Download plug.vim and put it in ~/.vim/autoload -" -" curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ -" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim -" -" Edit your .vimrc -" -" call plug#begin('~/.vim/plugged') -" -" " Make sure you use single quotes -" -" " Shorthand notation; fetches https://github.com/junegunn/vim-easy-align -" Plug 'junegunn/vim-easy-align' -" -" " Any valid git URL is allowed -" Plug 'https://github.com/junegunn/vim-github-dashboard.git' -" -" " Multiple Plug commands can be written in a single line using | separators -" Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets' -" -" " On-demand loading -" Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' } -" Plug 'tpope/vim-fireplace', { 'for': 'clojure' } -" -" " Using a non-default branch -" Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' } -" -" " Using a tagged release; wildcard allowed (requires git 1.9.2 or above) -" Plug 'fatih/vim-go', { 'tag': '*' } -" -" " Plugin options -" Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' } -" -" " Plugin outside ~/.vim/plugged with post-update hook -" Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' } -" -" " Unmanaged plugin (manually installed and updated) -" Plug '~/my-prototype-plugin' -" -" " Initialize plugin system -" call plug#end() -" -" Then reload .vimrc and :PlugInstall to install plugins. -" -" Plug options: -" -"| Option | Description | -"| ----------------------- | ------------------------------------------------ | -"| `branch`/`tag`/`commit` | Branch/tag/commit of the repository to use | -"| `rtp` | Subdirectory that contains Vim plugin | -"| `dir` | Custom directory for the plugin | -"| `as` | Use different name for the plugin | -"| `do` | Post-update hook (string or funcref) | -"| `on` | On-demand loading: Commands or ``-mappings | -"| `for` | On-demand loading: File types | -"| `frozen` | Do not update unless explicitly specified | -" -" More information: https://github.com/junegunn/vim-plug -" -" -" Copyright (c) 2017 Junegunn Choi -" -" MIT License -" -" Permission is hereby granted, free of charge, to any person obtaining -" a copy of this software and associated documentation files (the -" "Software"), to deal in the Software without restriction, including -" without limitation the rights to use, copy, modify, merge, publish, -" distribute, sublicense, and/or sell copies of the Software, and to -" permit persons to whom the Software is furnished to do so, subject to -" the following conditions: -" -" The above copyright notice and this permission notice shall be -" included in all copies or substantial portions of the Software. -" -" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -if exists('g:loaded_plug') - finish -endif -let g:loaded_plug = 1 - -let s:cpo_save = &cpo -set cpo&vim - -let s:plug_src = 'https://github.com/junegunn/vim-plug.git' -let s:plug_tab = get(s:, 'plug_tab', -1) -let s:plug_buf = get(s:, 'plug_buf', -1) -let s:mac_gui = has('gui_macvim') && has('gui_running') -let s:is_win = has('win32') -let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win) -let s:vim8 = has('patch-8.0.0039') && exists('*job_start') -if s:is_win && &shellslash - set noshellslash - let s:me = resolve(expand(':p')) - set shellslash -else - let s:me = resolve(expand(':p')) -endif -let s:base_spec = { 'branch': '', 'frozen': 0 } -let s:TYPE = { -\ 'string': type(''), -\ 'list': type([]), -\ 'dict': type({}), -\ 'funcref': type(function('call')) -\ } -let s:loaded = get(s:, 'loaded', {}) -let s:triggers = get(s:, 'triggers', {}) - -function! s:isabsolute(dir) abort - return a:dir =~# '^/' || (has('win32') && a:dir =~? '^\%(\\\|[A-Z]:\)') -endfunction - -function! s:git_dir(dir) abort - let gitdir = s:trim(a:dir) . '/.git' - if isdirectory(gitdir) - return gitdir - endif - if !filereadable(gitdir) - return '' - endif - let gitdir = matchstr(get(readfile(gitdir), 0, ''), '^gitdir: \zs.*') - if len(gitdir) && !s:isabsolute(gitdir) - let gitdir = a:dir . '/' . gitdir - endif - return isdirectory(gitdir) ? gitdir : '' -endfunction - -function! s:git_origin_url(dir) abort - let gitdir = s:git_dir(a:dir) - let config = gitdir . '/config' - if empty(gitdir) || !filereadable(config) - return '' - endif - return matchstr(join(readfile(config)), '\[remote "origin"\].\{-}url\s*=\s*\zs\S*\ze') -endfunction - -function! s:git_revision(dir) abort - let gitdir = s:git_dir(a:dir) - let head = gitdir . '/HEAD' - if empty(gitdir) || !filereadable(head) - return '' - endif - - let line = get(readfile(head), 0, '') - let ref = matchstr(line, '^ref: \zs.*') - if empty(ref) - return line - endif - - if filereadable(gitdir . '/' . ref) - return get(readfile(gitdir . '/' . ref), 0, '') - endif - - if filereadable(gitdir . '/packed-refs') - for line in readfile(gitdir . '/packed-refs') - if line =~# ' ' . ref - return matchstr(line, '^[0-9a-f]*') - endif - endfor - endif - - return '' -endfunction - -function! s:git_local_branch(dir) abort - let gitdir = s:git_dir(a:dir) - let head = gitdir . '/HEAD' - if empty(gitdir) || !filereadable(head) - return '' - endif - let branch = matchstr(get(readfile(head), 0, ''), '^ref: refs/heads/\zs.*') - return len(branch) ? branch : 'HEAD' -endfunction - -function! s:git_origin_branch(spec) - if len(a:spec.branch) - return a:spec.branch - endif - - " The file may not be present if this is a local repository - let gitdir = s:git_dir(a:spec.dir) - let origin_head = gitdir.'/refs/remotes/origin/HEAD' - if len(gitdir) && filereadable(origin_head) - return matchstr(get(readfile(origin_head), 0, ''), - \ '^ref: refs/remotes/origin/\zs.*') - endif - - " The command may not return the name of a branch in detached HEAD state - let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir)) - return v:shell_error ? '' : result[-1] -endfunction - -if s:is_win - function! s:plug_call(fn, ...) - let shellslash = &shellslash - try - set noshellslash - return call(a:fn, a:000) - finally - let &shellslash = shellslash - endtry - endfunction -else - function! s:plug_call(fn, ...) - return call(a:fn, a:000) - endfunction -endif - -function! s:plug_getcwd() - return s:plug_call('getcwd') -endfunction - -function! s:plug_fnamemodify(fname, mods) - return s:plug_call('fnamemodify', a:fname, a:mods) -endfunction - -function! s:plug_expand(fmt) - return s:plug_call('expand', a:fmt, 1) -endfunction - -function! s:plug_tempname() - return s:plug_call('tempname') -endfunction - -function! plug#begin(...) - if a:0 > 0 - let s:plug_home_org = a:1 - let home = s:path(s:plug_fnamemodify(s:plug_expand(a:1), ':p')) - elseif exists('g:plug_home') - let home = s:path(g:plug_home) - elseif !empty(&rtp) - let home = s:path(split(&rtp, ',')[0]) . '/plugged' - else - return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.') - endif - if s:plug_fnamemodify(home, ':t') ==# 'plugin' && s:plug_fnamemodify(home, ':h') ==# s:first_rtp - return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.') - endif - - let g:plug_home = home - let g:plugs = {} - let g:plugs_order = [] - let s:triggers = {} - - call s:define_commands() - return 1 -endfunction - -function! s:define_commands() - command! -nargs=+ -bar Plug call plug#() - if !executable('git') - return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.') - endif - if has('win32') - \ && &shellslash - \ && (&shell =~# 'cmd\(\.exe\)\?$' || &shell =~# 'powershell\(\.exe\)\?$') - return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.') - endif - if !has('nvim') - \ && (has('win32') || has('win32unix')) - \ && !has('multi_byte') - return s:err('Vim needs +multi_byte feature on Windows to run shell commands. Enable +iconv for best results.') - endif - command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(0, []) - command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(0, []) - command! -nargs=0 -bar -bang PlugClean call s:clean(0) - command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif - command! -nargs=0 -bar PlugStatus call s:status() - command! -nargs=0 -bar PlugDiff call s:diff() - command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(0, ) -endfunction - -function! s:to_a(v) - return type(a:v) == s:TYPE.list ? a:v : [a:v] -endfunction - -function! s:to_s(v) - return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n" -endfunction - -function! s:glob(from, pattern) - return s:lines(globpath(a:from, a:pattern)) -endfunction - -function! s:source(from, ...) - let found = 0 - for pattern in a:000 - for vim in s:glob(a:from, pattern) - execute 'source' s:esc(vim) - let found = 1 - endfor - endfor - return found -endfunction - -function! s:assoc(dict, key, val) - let a:dict[a:key] = add(get(a:dict, a:key, []), a:val) -endfunction - -function! s:ask(message, ...) - call inputsave() - echohl WarningMsg - let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) ')) - echohl None - call inputrestore() - echo "\r" - return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0 -endfunction - -function! s:ask_no_interrupt(...) - try - return call('s:ask', a:000) - catch - return 0 - endtry -endfunction - -function! s:lazy(plug, opt) - return has_key(a:plug, a:opt) && - \ (empty(s:to_a(a:plug[a:opt])) || - \ !isdirectory(a:plug.dir) || - \ len(s:glob(s:rtp(a:plug), 'plugin')) || - \ len(s:glob(s:rtp(a:plug), 'after/plugin'))) -endfunction - -function! plug#end() - if !exists('g:plugs') - return s:err('plug#end() called without calling plug#begin() first') - endif - - if exists('#PlugLOD') - augroup PlugLOD - autocmd! - augroup END - augroup! PlugLOD - endif - let lod = { 'ft': {}, 'map': {}, 'cmd': {} } - - if exists('g:did_load_filetypes') - filetype off - endif - for name in g:plugs_order - if !has_key(g:plugs, name) - continue - endif - let plug = g:plugs[name] - if get(s:loaded, name, 0) || !s:lazy(plug, 'on') && !s:lazy(plug, 'for') - let s:loaded[name] = 1 - continue - endif - - if has_key(plug, 'on') - let s:triggers[name] = { 'map': [], 'cmd': [] } - for cmd in s:to_a(plug.on) - if cmd =~? '^.\+' - if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i')) - call s:assoc(lod.map, cmd, name) - endif - call add(s:triggers[name].map, cmd) - elseif cmd =~# '^[A-Z]' - let cmd = substitute(cmd, '!*$', '', '') - if exists(':'.cmd) != 2 - call s:assoc(lod.cmd, cmd, name) - endif - call add(s:triggers[name].cmd, cmd) - else - call s:err('Invalid `on` option: '.cmd. - \ '. Should start with an uppercase letter or ``.') - endif - endfor - endif - - if has_key(plug, 'for') - let types = s:to_a(plug.for) - if !empty(types) - augroup filetypedetect - call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim') - augroup END - endif - for type in types - call s:assoc(lod.ft, type, name) - endfor - endif - endfor - - for [cmd, names] in items(lod.cmd) - execute printf( - \ 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "", , , , %s)', - \ cmd, string(cmd), string(names)) - endfor - - for [map, names] in items(lod.map) - for [mode, map_prefix, key_prefix] in - \ [['i', '', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']] - execute printf( - \ '%snoremap %s %s:call lod_map(%s, %s, %s, "%s")', - \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix) - endfor - endfor - - for [ft, names] in items(lod.ft) - augroup PlugLOD - execute printf('autocmd FileType %s call lod_ft(%s, %s)', - \ ft, string(ft), string(names)) - augroup END - endfor - - call s:reorg_rtp() - filetype plugin indent on - if has('vim_starting') - if has('syntax') && !exists('g:syntax_on') - syntax enable - end - else - call s:reload_plugins() - endif -endfunction - -function! s:loaded_names() - return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)') -endfunction - -function! s:load_plugin(spec) - call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim') -endfunction - -function! s:reload_plugins() - for name in s:loaded_names() - call s:load_plugin(g:plugs[name]) - endfor -endfunction - -function! s:trim(str) - return substitute(a:str, '[\/]\+$', '', '') -endfunction - -function! s:version_requirement(val, min) - for idx in range(0, len(a:min) - 1) - let v = get(a:val, idx, 0) - if v < a:min[idx] | return 0 - elseif v > a:min[idx] | return 1 - endif - endfor - return 1 -endfunction - -function! s:git_version_requirement(...) - if !exists('s:git_version') - let s:git_version = map(split(split(s:system(['git', '--version']))[2], '\.'), 'str2nr(v:val)') - endif - return s:version_requirement(s:git_version, a:000) -endfunction - -function! s:progress_opt(base) - return a:base && !s:is_win && - \ s:git_version_requirement(1, 7, 1) ? '--progress' : '' -endfunction - -function! s:rtp(spec) - return s:path(a:spec.dir . get(a:spec, 'rtp', '')) -endfunction - -if s:is_win - function! s:path(path) - return s:trim(substitute(a:path, '/', '\', 'g')) - endfunction - - function! s:dirpath(path) - return s:path(a:path) . '\' - endfunction - - function! s:is_local_plug(repo) - return a:repo =~? '^[a-z]:\|^[%~]' - endfunction - - " Copied from fzf - function! s:wrap_cmds(cmds) - let cmds = [ - \ '@echo off', - \ 'setlocal enabledelayedexpansion'] - \ + (type(a:cmds) == type([]) ? a:cmds : [a:cmds]) - \ + ['endlocal'] - if has('iconv') - if !exists('s:codepage') - let s:codepage = libcallnr('kernel32.dll', 'GetACP', 0) - endif - return map(cmds, printf('iconv(v:val."\r", "%s", "cp%d")', &encoding, s:codepage)) - endif - return map(cmds, 'v:val."\r"') - endfunction - - function! s:batchfile(cmd) - let batchfile = s:plug_tempname().'.bat' - call writefile(s:wrap_cmds(a:cmd), batchfile) - let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0}) - if &shell =~# 'powershell\(\.exe\)\?$' - let cmd = '& ' . cmd - endif - return [batchfile, cmd] - endfunction -else - function! s:path(path) - return s:trim(a:path) - endfunction - - function! s:dirpath(path) - return substitute(a:path, '[/\\]*$', '/', '') - endfunction - - function! s:is_local_plug(repo) - return a:repo[0] =~ '[/$~]' - endfunction -endif - -function! s:err(msg) - echohl ErrorMsg - echom '[vim-plug] '.a:msg - echohl None -endfunction - -function! s:warn(cmd, msg) - echohl WarningMsg - execute a:cmd 'a:msg' - echohl None -endfunction - -function! s:esc(path) - return escape(a:path, ' ') -endfunction - -function! s:escrtp(path) - return escape(a:path, ' ,') -endfunction - -function! s:remove_rtp() - for name in s:loaded_names() - let rtp = s:rtp(g:plugs[name]) - execute 'set rtp-='.s:escrtp(rtp) - let after = globpath(rtp, 'after') - if isdirectory(after) - execute 'set rtp-='.s:escrtp(after) - endif - endfor -endfunction - -function! s:reorg_rtp() - if !empty(s:first_rtp) - execute 'set rtp-='.s:first_rtp - execute 'set rtp-='.s:last_rtp - endif - - " &rtp is modified from outside - if exists('s:prtp') && s:prtp !=# &rtp - call s:remove_rtp() - unlet! s:middle - endif - - let s:middle = get(s:, 'middle', &rtp) - let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])') - let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)') - let rtp = join(map(rtps, 'escape(v:val, ",")'), ',') - \ . ','.s:middle.',' - \ . join(map(afters, 'escape(v:val, ",")'), ',') - let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g') - let s:prtp = &rtp - - if !empty(s:first_rtp) - execute 'set rtp^='.s:first_rtp - execute 'set rtp+='.s:last_rtp - endif -endfunction - -function! s:doautocmd(...) - if exists('#'.join(a:000, '#')) - execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '' : '') join(a:000) - endif -endfunction - -function! s:dobufread(names) - for name in a:names - let path = s:rtp(g:plugs[name]) - for dir in ['ftdetect', 'ftplugin', 'after/ftdetect', 'after/ftplugin'] - if len(finddir(dir, path)) - if exists('#BufRead') - doautocmd BufRead - endif - return - endif - endfor - endfor -endfunction - -function! plug#load(...) - if a:0 == 0 - return s:err('Argument missing: plugin name(s) required') - endif - if !exists('g:plugs') - return s:err('plug#begin was not called') - endif - let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000 - let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)') - if !empty(unknowns) - let s = len(unknowns) > 1 ? 's' : '' - return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', '))) - end - let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)') - if !empty(unloaded) - for name in unloaded - call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) - endfor - call s:dobufread(unloaded) - return 1 - end - return 0 -endfunction - -function! s:remove_triggers(name) - if !has_key(s:triggers, a:name) - return - endif - for cmd in s:triggers[a:name].cmd - execute 'silent! delc' cmd - endfor - for map in s:triggers[a:name].map - execute 'silent! unmap' map - execute 'silent! iunmap' map - endfor - call remove(s:triggers, a:name) -endfunction - -function! s:lod(names, types, ...) - for name in a:names - call s:remove_triggers(name) - let s:loaded[name] = 1 - endfor - call s:reorg_rtp() - - for name in a:names - let rtp = s:rtp(g:plugs[name]) - for dir in a:types - call s:source(rtp, dir.'/**/*.vim') - endfor - if a:0 - if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2)) - execute 'runtime' a:1 - endif - call s:source(rtp, a:2) - endif - call s:doautocmd('User', name) - endfor -endfunction - -function! s:lod_ft(pat, names) - let syn = 'syntax/'.a:pat.'.vim' - call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn) - execute 'autocmd! PlugLOD FileType' a:pat - call s:doautocmd('filetypeplugin', 'FileType') - call s:doautocmd('filetypeindent', 'FileType') -endfunction - -function! s:lod_cmd(cmd, bang, l1, l2, args, names) - call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) - call s:dobufread(a:names) - execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args) -endfunction - -function! s:lod_map(map, names, with_prefix, prefix) - call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) - call s:dobufread(a:names) - let extra = '' - while 1 - let c = getchar(0) - if c == 0 - break - endif - let extra .= nr2char(c) - endwhile - - if a:with_prefix - let prefix = v:count ? v:count : '' - let prefix .= '"'.v:register.a:prefix - if mode(1) == 'no' - if v:operator == 'c' - let prefix = "\" . prefix - endif - let prefix .= v:operator - endif - call feedkeys(prefix, 'n') - endif - call feedkeys(substitute(a:map, '^', "\", '') . extra) -endfunction - -function! plug#(repo, ...) - if a:0 > 1 - return s:err('Invalid number of arguments (1..2)') - endif - - try - let repo = s:trim(a:repo) - let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec - let name = get(opts, 'as', s:plug_fnamemodify(repo, ':t:s?\.git$??')) - let spec = extend(s:infer_properties(name, repo), opts) - if !has_key(g:plugs, name) - call add(g:plugs_order, name) - endif - let g:plugs[name] = spec - let s:loaded[name] = get(s:loaded, name, 0) - catch - return s:err(repo . ' ' . v:exception) - endtry -endfunction - -function! s:parse_options(arg) - let opts = copy(s:base_spec) - let type = type(a:arg) - let opt_errfmt = 'Invalid argument for "%s" option of :Plug (expected: %s)' - if type == s:TYPE.string - if empty(a:arg) - throw printf(opt_errfmt, 'tag', 'string') - endif - let opts.tag = a:arg - elseif type == s:TYPE.dict - for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as'] - if has_key(a:arg, opt) - \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt])) - throw printf(opt_errfmt, opt, 'string') - endif - endfor - for opt in ['on', 'for'] - if has_key(a:arg, opt) - \ && type(a:arg[opt]) != s:TYPE.list - \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt])) - throw printf(opt_errfmt, opt, 'string or list') - endif - endfor - if has_key(a:arg, 'do') - \ && type(a:arg.do) != s:TYPE.funcref - \ && (type(a:arg.do) != s:TYPE.string || empty(a:arg.do)) - throw printf(opt_errfmt, 'do', 'string or funcref') - endif - call extend(opts, a:arg) - if has_key(opts, 'dir') - let opts.dir = s:dirpath(s:plug_expand(opts.dir)) - endif - else - throw 'Invalid argument type (expected: string or dictionary)' - endif - return opts -endfunction - -function! s:infer_properties(name, repo) - let repo = a:repo - if s:is_local_plug(repo) - return { 'dir': s:dirpath(s:plug_expand(repo)) } - else - if repo =~ ':' - let uri = repo - else - if repo !~ '/' - throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo) - endif - let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git') - let uri = printf(fmt, repo) - endif - return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri } - endif -endfunction - -function! s:install(force, names) - call s:update_impl(0, a:force, a:names) -endfunction - -function! s:update(force, names) - call s:update_impl(1, a:force, a:names) -endfunction - -function! plug#helptags() - if !exists('g:plugs') - return s:err('plug#begin was not called') - endif - for spec in values(g:plugs) - let docd = join([s:rtp(spec), 'doc'], '/') - if isdirectory(docd) - silent! execute 'helptags' s:esc(docd) - endif - endfor - return 1 -endfunction - -function! s:syntax() - syntax clear - syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber - syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX - syn match plugNumber /[0-9]\+[0-9.]*/ contained - syn match plugBracket /[[\]]/ contained - syn match plugX /x/ contained - syn match plugDash /^-\{1}\ / - syn match plugPlus /^+/ - syn match plugStar /^*/ - syn match plugMessage /\(^- \)\@<=.*/ - syn match plugName /\(^- \)\@<=[^ ]*:/ - syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/ - syn match plugTag /(tag: [^)]\+)/ - syn match plugInstall /\(^+ \)\@<=[^:]*/ - syn match plugUpdate /\(^* \)\@<=[^:]*/ - syn match plugCommit /^ \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag - syn match plugEdge /^ \X\+$/ - syn match plugEdge /^ \X*/ contained nextgroup=plugSha - syn match plugSha /[0-9a-f]\{7,9}/ contained - syn match plugRelDate /([^)]*)$/ contained - syn match plugNotLoaded /(not loaded)$/ - syn match plugError /^x.*/ - syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/ - syn match plugH2 /^.*:\n-\+$/ - syn match plugH2 /^-\{2,}/ - syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean - hi def link plug1 Title - hi def link plug2 Repeat - hi def link plugH2 Type - hi def link plugX Exception - hi def link plugBracket Structure - hi def link plugNumber Number - - hi def link plugDash Special - hi def link plugPlus Constant - hi def link plugStar Boolean - - hi def link plugMessage Function - hi def link plugName Label - hi def link plugInstall Function - hi def link plugUpdate Type - - hi def link plugError Error - hi def link plugDeleted Ignore - hi def link plugRelDate Comment - hi def link plugEdge PreProc - hi def link plugSha Identifier - hi def link plugTag Constant - - hi def link plugNotLoaded Comment -endfunction - -function! s:lpad(str, len) - return a:str . repeat(' ', a:len - len(a:str)) -endfunction - -function! s:lines(msg) - return split(a:msg, "[\r\n]") -endfunction - -function! s:lastline(msg) - return get(s:lines(a:msg), -1, '') -endfunction - -function! s:new_window() - execute get(g:, 'plug_window', 'vertical topleft new') -endfunction - -function! s:plug_window_exists() - let buflist = tabpagebuflist(s:plug_tab) - return !empty(buflist) && index(buflist, s:plug_buf) >= 0 -endfunction - -function! s:switch_in() - if !s:plug_window_exists() - return 0 - endif - - if winbufnr(0) != s:plug_buf - let s:pos = [tabpagenr(), winnr(), winsaveview()] - execute 'normal!' s:plug_tab.'gt' - let winnr = bufwinnr(s:plug_buf) - execute winnr.'wincmd w' - call add(s:pos, winsaveview()) - else - let s:pos = [winsaveview()] - endif - - setlocal modifiable - return 1 -endfunction - -function! s:switch_out(...) - call winrestview(s:pos[-1]) - setlocal nomodifiable - if a:0 > 0 - execute a:1 - endif - - if len(s:pos) > 1 - execute 'normal!' s:pos[0].'gt' - execute s:pos[1] 'wincmd w' - call winrestview(s:pos[2]) - endif -endfunction - -function! s:finish_bindings() - nnoremap R :call retry() - nnoremap D :PlugDiff - nnoremap S :PlugStatus - nnoremap U :call status_update() - xnoremap U :call status_update() - nnoremap ]] :silent! call section('') - nnoremap [[ :silent! call section('b') -endfunction - -function! s:prepare(...) - if empty(s:plug_getcwd()) - throw 'Invalid current working directory. Cannot proceed.' - endif - - for evar in ['$GIT_DIR', '$GIT_WORK_TREE'] - if exists(evar) - throw evar.' detected. Cannot proceed.' - endif - endfor - - call s:job_abort() - if s:switch_in() - if b:plug_preview == 1 - pc - endif - enew - else - call s:new_window() - endif - - nnoremap q :if b:plug_preview==1pcendifbd - if a:0 == 0 - call s:finish_bindings() - endif - let b:plug_preview = -1 - let s:plug_tab = tabpagenr() - let s:plug_buf = winbufnr(0) - call s:assign_name() - - for k in ['', 'L', 'o', 'X', 'd', 'dd'] - execute 'silent! unmap ' k - endfor - setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell - if exists('+colorcolumn') - setlocal colorcolumn= - endif - setf vim-plug - if exists('g:syntax_on') - call s:syntax() - endif -endfunction - -function! s:assign_name() - " Assign buffer name - let prefix = '[Plugins]' - let name = prefix - let idx = 2 - while bufexists(name) - let name = printf('%s (%s)', prefix, idx) - let idx = idx + 1 - endwhile - silent! execute 'f' fnameescape(name) -endfunction - -function! s:chsh(swap) - let prev = [&shell, &shellcmdflag, &shellredir] - if !s:is_win - set shell=sh - endif - if a:swap - if &shell =~# 'powershell\(\.exe\)\?$' || &shell =~# 'pwsh$' - let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s' - elseif &shell =~# 'sh' || &shell =~# 'cmd\(\.exe\)\?$' - set shellredir=>%s\ 2>&1 - endif - endif - return prev -endfunction - -function! s:bang(cmd, ...) - let batchfile = '' - try - let [sh, shellcmdflag, shrd] = s:chsh(a:0) - " FIXME: Escaping is incomplete. We could use shellescape with eval, - " but it won't work on Windows. - let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd - if s:is_win - let [batchfile, cmd] = s:batchfile(cmd) - endif - let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%') - execute "normal! :execute g:_plug_bang\\" - finally - unlet g:_plug_bang - let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] - if s:is_win && filereadable(batchfile) - call delete(batchfile) - endif - endtry - return v:shell_error ? 'Exit status: ' . v:shell_error : '' -endfunction - -function! s:regress_bar() - let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '') - call s:progress_bar(2, bar, len(bar)) -endfunction - -function! s:is_updated(dir) - return !empty(s:system_chomp(['git', 'log', '--pretty=format:%h', 'HEAD...HEAD@{1}'], a:dir)) -endfunction - -function! s:do(pull, force, todo) - for [name, spec] in items(a:todo) - if !isdirectory(spec.dir) - continue - endif - let installed = has_key(s:update.new, name) - let updated = installed ? 0 : - \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir)) - if a:force || installed || updated - execute 'cd' s:esc(spec.dir) - call append(3, '- Post-update hook for '. name .' ... ') - let error = '' - let type = type(spec.do) - if type == s:TYPE.string - if spec.do[0] == ':' - if !get(s:loaded, name, 0) - let s:loaded[name] = 1 - call s:reorg_rtp() - endif - call s:load_plugin(spec) - try - execute spec.do[1:] - catch - let error = v:exception - endtry - if !s:plug_window_exists() - cd - - throw 'Warning: vim-plug was terminated by the post-update hook of '.name - endif - else - let error = s:bang(spec.do) - endif - elseif type == s:TYPE.funcref - try - call s:load_plugin(spec) - let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged') - call spec.do({ 'name': name, 'status': status, 'force': a:force }) - catch - let error = v:exception - endtry - else - let error = 'Invalid hook type' - endif - call s:switch_in() - call setline(4, empty(error) ? (getline(4) . 'OK') - \ : ('x' . getline(4)[1:] . error)) - if !empty(error) - call add(s:update.errors, name) - call s:regress_bar() - endif - cd - - endif - endfor -endfunction - -function! s:hash_match(a, b) - return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0 -endfunction - -function! s:checkout(spec) - let sha = a:spec.commit - let output = s:git_revision(a:spec.dir) - if !empty(output) && !s:hash_match(sha, s:lines(output)[0]) - let credential_helper = s:git_version_requirement(2) ? '-c credential.helper= ' : '' - let output = s:system( - \ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir) - endif - return output -endfunction - -function! s:finish(pull) - let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen')) - if new_frozen - let s = new_frozen > 1 ? 's' : '' - call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s)) - endif - call append(3, '- Finishing ... ') | 4 - redraw - call plug#helptags() - call plug#end() - call setline(4, getline(4) . 'Done!') - redraw - let msgs = [] - if !empty(s:update.errors) - call add(msgs, "Press 'R' to retry.") - endif - if a:pull && len(s:update.new) < len(filter(getline(5, '$'), - \ "v:val =~ '^- ' && v:val !~# 'Already up.to.date'")) - call add(msgs, "Press 'D' to see the updated changes.") - endif - echo join(msgs, ' ') - call s:finish_bindings() -endfunction - -function! s:retry() - if empty(s:update.errors) - return - endif - echo - call s:update_impl(s:update.pull, s:update.force, - \ extend(copy(s:update.errors), [s:update.threads])) -endfunction - -function! s:is_managed(name) - return has_key(g:plugs[a:name], 'uri') -endfunction - -function! s:names(...) - return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)')) -endfunction - -function! s:check_ruby() - silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'") - if !exists('g:plug_ruby') - redraw! - return s:warn('echom', 'Warning: Ruby interface is broken') - endif - let ruby_version = split(g:plug_ruby, '\.') - unlet g:plug_ruby - return s:version_requirement(ruby_version, [1, 8, 7]) -endfunction - -function! s:update_impl(pull, force, args) abort - let sync = index(a:args, '--sync') >= 0 || has('vim_starting') - let args = filter(copy(a:args), 'v:val != "--sync"') - let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ? - \ remove(args, -1) : get(g:, 'plug_threads', 16) - - let managed = filter(copy(g:plugs), 's:is_managed(v:key)') - let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') : - \ filter(managed, 'index(args, v:key) >= 0') - - if empty(todo) - return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install')) - endif - - if !s:is_win && s:git_version_requirement(2, 3) - let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : '' - let $GIT_TERMINAL_PROMPT = 0 - for plug in values(todo) - let plug.uri = substitute(plug.uri, - \ '^https://git::@github\.com', 'https://github.com', '') - endfor - endif - - if !isdirectory(g:plug_home) - try - call mkdir(g:plug_home, 'p') - catch - return s:err(printf('Invalid plug directory: %s. '. - \ 'Try to call plug#begin with a valid directory', g:plug_home)) - endtry - endif - - if has('nvim') && !exists('*jobwait') && threads > 1 - call s:warn('echom', '[vim-plug] Update Neovim for parallel installer') - endif - - let use_job = s:nvim || s:vim8 - let python = (has('python') || has('python3')) && !use_job - let ruby = has('ruby') && !use_job && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && threads > 1 && s:check_ruby() - - let s:update = { - \ 'start': reltime(), - \ 'all': todo, - \ 'todo': copy(todo), - \ 'errors': [], - \ 'pull': a:pull, - \ 'force': a:force, - \ 'new': {}, - \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1, - \ 'bar': '', - \ 'fin': 0 - \ } - - call s:prepare(1) - call append(0, ['', '']) - normal! 2G - silent! redraw - - let s:clone_opt = [] - if get(g:, 'plug_shallow', 1) - call extend(s:clone_opt, ['--depth', '1']) - if s:git_version_requirement(1, 7, 10) - call add(s:clone_opt, '--no-single-branch') - endif - endif - - if has('win32unix') || has('wsl') - call extend(s:clone_opt, ['-c', 'core.eol=lf', '-c', 'core.autocrlf=input']) - endif - - let s:submodule_opt = s:git_version_requirement(2, 8) ? ' --jobs='.threads : '' - - " Python version requirement (>= 2.7) - if python && !has('python3') && !ruby && !use_job && s:update.threads > 1 - redir => pyv - silent python import platform; print platform.python_version() - redir END - let python = s:version_requirement( - \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6]) - endif - - if (python || ruby) && s:update.threads > 1 - try - let imd = &imd - if s:mac_gui - set noimd - endif - if ruby - call s:update_ruby() - else - call s:update_python() - endif - catch - let lines = getline(4, '$') - let printed = {} - silent! 4,$d _ - for line in lines - let name = s:extract_name(line, '.', '') - if empty(name) || !has_key(printed, name) - call append('$', line) - if !empty(name) - let printed[name] = 1 - if line[0] == 'x' && index(s:update.errors, name) < 0 - call add(s:update.errors, name) - end - endif - endif - endfor - finally - let &imd = imd - call s:update_finish() - endtry - else - call s:update_vim() - while use_job && sync - sleep 100m - if s:update.fin - break - endif - endwhile - endif -endfunction - -function! s:log4(name, msg) - call setline(4, printf('- %s (%s)', a:msg, a:name)) - redraw -endfunction - -function! s:update_finish() - if exists('s:git_terminal_prompt') - let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt - endif - if s:switch_in() - call append(3, '- Updating ...') | 4 - for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))')) - let [pos, _] = s:logpos(name) - if !pos - continue - endif - if has_key(spec, 'commit') - call s:log4(name, 'Checking out '.spec.commit) - let out = s:checkout(spec) - elseif has_key(spec, 'tag') - let tag = spec.tag - if tag =~ '\*' - let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir)) - if !v:shell_error && !empty(tags) - let tag = tags[0] - call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag)) - call append(3, '') - endif - endif - call s:log4(name, 'Checking out '.tag) - let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir) - else - let branch = s:git_origin_branch(spec) - call s:log4(name, 'Merging origin/'.s:esc(branch)) - let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1' - \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir) - endif - if !v:shell_error && filereadable(spec.dir.'/.gitmodules') && - \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir)) - call s:log4(name, 'Updating submodules. This may take a while.') - let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir) - endif - let msg = s:format_message(v:shell_error ? 'x': '-', name, out) - if v:shell_error - call add(s:update.errors, name) - call s:regress_bar() - silent execute pos 'd _' - call append(4, msg) | 4 - elseif !empty(out) - call setline(pos, msg[0]) - endif - redraw - endfor - silent 4 d _ - try - call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")')) - catch - call s:warn('echom', v:exception) - call s:warn('echo', '') - return - endtry - call s:finish(s:update.pull) - call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.') - call s:switch_out('normal! gg') - endif -endfunction - -function! s:job_abort() - if (!s:nvim && !s:vim8) || !exists('s:jobs') - return - endif - - for [name, j] in items(s:jobs) - if s:nvim - silent! call jobstop(j.jobid) - elseif s:vim8 - silent! call job_stop(j.jobid) - endif - if j.new - call s:rm_rf(g:plugs[name].dir) - endif - endfor - let s:jobs = {} -endfunction - -function! s:last_non_empty_line(lines) - let len = len(a:lines) - for idx in range(len) - let line = a:lines[len-idx-1] - if !empty(line) - return line - endif - endfor - return '' -endfunction - -function! s:job_out_cb(self, data) abort - let self = a:self - let data = remove(self.lines, -1) . a:data - let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]') - call extend(self.lines, lines) - " To reduce the number of buffer updates - let self.tick = get(self, 'tick', -1) + 1 - if !self.running || self.tick % len(s:jobs) == 0 - let bullet = self.running ? (self.new ? '+' : '*') : (self.error ? 'x' : '-') - let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines) - call s:log(bullet, self.name, result) - endif -endfunction - -function! s:job_exit_cb(self, data) abort - let a:self.running = 0 - let a:self.error = a:data != 0 - call s:reap(a:self.name) - call s:tick() -endfunction - -function! s:job_cb(fn, job, ch, data) - if !s:plug_window_exists() " plug window closed - return s:job_abort() - endif - call call(a:fn, [a:job, a:data]) -endfunction - -function! s:nvim_cb(job_id, data, event) dict abort - return (a:event == 'stdout' || a:event == 'stderr') ? - \ s:job_cb('s:job_out_cb', self, 0, join(a:data, "\n")) : - \ s:job_cb('s:job_exit_cb', self, 0, a:data) -endfunction - -function! s:spawn(name, cmd, opts) - let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''], - \ 'new': get(a:opts, 'new', 0) } - let s:jobs[a:name] = job - - if s:nvim - if has_key(a:opts, 'dir') - let job.cwd = a:opts.dir - endif - let argv = a:cmd - call extend(job, { - \ 'on_stdout': function('s:nvim_cb'), - \ 'on_stderr': function('s:nvim_cb'), - \ 'on_exit': function('s:nvim_cb'), - \ }) - let jid = s:plug_call('jobstart', argv, job) - if jid > 0 - let job.jobid = jid - else - let job.running = 0 - let job.error = 1 - let job.lines = [jid < 0 ? argv[0].' is not executable' : - \ 'Invalid arguments (or job table is full)'] - endif - elseif s:vim8 - let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"script": 0})')) - if has_key(a:opts, 'dir') - let cmd = s:with_cd(cmd, a:opts.dir, 0) - endif - let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd] - let jid = job_start(s:is_win ? join(argv, ' ') : argv, { - \ 'out_cb': function('s:job_cb', ['s:job_out_cb', job]), - \ 'err_cb': function('s:job_cb', ['s:job_out_cb', job]), - \ 'exit_cb': function('s:job_cb', ['s:job_exit_cb', job]), - \ 'err_mode': 'raw', - \ 'out_mode': 'raw' - \}) - if job_status(jid) == 'run' - let job.jobid = jid - else - let job.running = 0 - let job.error = 1 - let job.lines = ['Failed to start job'] - endif - else - let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd])) - let job.error = v:shell_error != 0 - let job.running = 0 - endif -endfunction - -function! s:reap(name) - let job = s:jobs[a:name] - if job.error - call add(s:update.errors, a:name) - elseif get(job, 'new', 0) - let s:update.new[a:name] = 1 - endif - let s:update.bar .= job.error ? 'x' : '=' - - let bullet = job.error ? 'x' : '-' - let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines) - call s:log(bullet, a:name, empty(result) ? 'OK' : result) - call s:bar() - - call remove(s:jobs, a:name) -endfunction - -function! s:bar() - if s:switch_in() - let total = len(s:update.all) - call setline(1, (s:update.pull ? 'Updating' : 'Installing'). - \ ' plugins ('.len(s:update.bar).'/'.total.')') - call s:progress_bar(2, s:update.bar, total) - call s:switch_out() - endif -endfunction - -function! s:logpos(name) - let max = line('$') - for i in range(4, max > 4 ? max : 4) - if getline(i) =~# '^[-+x*] '.a:name.':' - for j in range(i + 1, max > 5 ? max : 5) - if getline(j) !~ '^ ' - return [i, j - 1] - endif - endfor - return [i, i] - endif - endfor - return [0, 0] -endfunction - -function! s:log(bullet, name, lines) - if s:switch_in() - let [b, e] = s:logpos(a:name) - if b > 0 - silent execute printf('%d,%d d _', b, e) - if b > winheight('.') - let b = 4 - endif - else - let b = 4 - endif - " FIXME For some reason, nomodifiable is set after :d in vim8 - setlocal modifiable - call append(b - 1, s:format_message(a:bullet, a:name, a:lines)) - call s:switch_out() - endif -endfunction - -function! s:update_vim() - let s:jobs = {} - - call s:bar() - call s:tick() -endfunction - -function! s:tick() - let pull = s:update.pull - let prog = s:progress_opt(s:nvim || s:vim8) -while 1 " Without TCO, Vim stack is bound to explode - if empty(s:update.todo) - if empty(s:jobs) && !s:update.fin - call s:update_finish() - let s:update.fin = 1 - endif - return - endif - - let name = keys(s:update.todo)[0] - let spec = remove(s:update.todo, name) - let new = empty(globpath(spec.dir, '.git', 1)) - - call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...') - redraw - - let has_tag = has_key(spec, 'tag') - if !new - let [error, _] = s:git_validate(spec, 0) - if empty(error) - if pull - let cmd = s:git_version_requirement(2) ? ['git', '-c', 'credential.helper=', 'fetch'] : ['git', 'fetch'] - if has_tag && !empty(globpath(spec.dir, '.git/shallow')) - call extend(cmd, ['--depth', '99999999']) - endif - if !empty(prog) - call add(cmd, prog) - endif - call s:spawn(name, cmd, { 'dir': spec.dir }) - else - let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 } - endif - else - let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 } - endif - else - let cmd = ['git', 'clone'] - if !has_tag - call extend(cmd, s:clone_opt) - endif - if !empty(prog) - call add(cmd, prog) - endif - call s:spawn(name, extend(cmd, [spec.uri, s:trim(spec.dir)]), { 'new': 1 }) - endif - - if !s:jobs[name].running - call s:reap(name) - endif - if len(s:jobs) >= s:update.threads - break - endif -endwhile -endfunction - -function! s:update_python() -let py_exe = has('python') ? 'python' : 'python3' -execute py_exe "<< EOF" -import datetime -import functools -import os -try: - import queue -except ImportError: - import Queue as queue -import random -import re -import shutil -import signal -import subprocess -import tempfile -import threading as thr -import time -import traceback -import vim - -G_NVIM = vim.eval("has('nvim')") == '1' -G_PULL = vim.eval('s:update.pull') == '1' -G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1 -G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)')) -G_CLONE_OPT = ' '.join(vim.eval('s:clone_opt')) -G_PROGRESS = vim.eval('s:progress_opt(1)') -G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads')) -G_STOP = thr.Event() -G_IS_WIN = vim.eval('s:is_win') == '1' - -class PlugError(Exception): - def __init__(self, msg): - self.msg = msg -class CmdTimedOut(PlugError): - pass -class CmdFailed(PlugError): - pass -class InvalidURI(PlugError): - pass -class Action(object): - INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-'] - -class Buffer(object): - def __init__(self, lock, num_plugs, is_pull): - self.bar = '' - self.event = 'Updating' if is_pull else 'Installing' - self.lock = lock - self.maxy = int(vim.eval('winheight(".")')) - self.num_plugs = num_plugs - - def __where(self, name): - """ Find first line with name in current buffer. Return line num. """ - found, lnum = False, 0 - matcher = re.compile('^[-+x*] {0}:'.format(name)) - for line in vim.current.buffer: - if matcher.search(line) is not None: - found = True - break - lnum += 1 - - if not found: - lnum = -1 - return lnum - - def header(self): - curbuf = vim.current.buffer - curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs) - - num_spaces = self.num_plugs - len(self.bar) - curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ') - - with self.lock: - vim.command('normal! 2G') - vim.command('redraw') - - def write(self, action, name, lines): - first, rest = lines[0], lines[1:] - msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)] - msg.extend([' ' + line for line in rest]) - - try: - if action == Action.ERROR: - self.bar += 'x' - vim.command("call add(s:update.errors, '{0}')".format(name)) - elif action == Action.DONE: - self.bar += '=' - - curbuf = vim.current.buffer - lnum = self.__where(name) - if lnum != -1: # Found matching line num - del curbuf[lnum] - if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]): - lnum = 3 - else: - lnum = 3 - curbuf.append(msg, lnum) - - self.header() - except vim.error: - pass - -class Command(object): - CD = 'cd /d' if G_IS_WIN else 'cd' - - def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None): - self.cmd = cmd - if cmd_dir: - self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd) - self.timeout = timeout - self.callback = cb if cb else (lambda msg: None) - self.clean = clean if clean else (lambda: None) - self.proc = None - - @property - def alive(self): - """ Returns true only if command still running. """ - return self.proc and self.proc.poll() is None - - def execute(self, ntries=3): - """ Execute the command with ntries if CmdTimedOut. - Returns the output of the command if no Exception. - """ - attempt, finished, limit = 0, False, self.timeout - - while not finished: - try: - attempt += 1 - result = self.try_command() - finished = True - return result - except CmdTimedOut: - if attempt != ntries: - self.notify_retry() - self.timeout += limit - else: - raise - - def notify_retry(self): - """ Retry required for command, notify user. """ - for count in range(3, 0, -1): - if G_STOP.is_set(): - raise KeyboardInterrupt - msg = 'Timeout. Will retry in {0} second{1} ...'.format( - count, 's' if count != 1 else '') - self.callback([msg]) - time.sleep(1) - self.callback(['Retrying ...']) - - def try_command(self): - """ Execute a cmd & poll for callback. Returns list of output. - Raises CmdFailed -> return code for Popen isn't 0 - Raises CmdTimedOut -> command exceeded timeout without new output - """ - first_line = True - - try: - tfile = tempfile.NamedTemporaryFile(mode='w+b') - preexec_fn = not G_IS_WIN and os.setsid or None - self.proc = subprocess.Popen(self.cmd, stdout=tfile, - stderr=subprocess.STDOUT, - stdin=subprocess.PIPE, shell=True, - preexec_fn=preexec_fn) - thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,)) - thrd.start() - - thread_not_started = True - while thread_not_started: - try: - thrd.join(0.1) - thread_not_started = False - except RuntimeError: - pass - - while self.alive: - if G_STOP.is_set(): - raise KeyboardInterrupt - - if first_line or random.random() < G_LOG_PROB: - first_line = False - line = '' if G_IS_WIN else nonblock_read(tfile.name) - if line: - self.callback([line]) - - time_diff = time.time() - os.path.getmtime(tfile.name) - if time_diff > self.timeout: - raise CmdTimedOut(['Timeout!']) - - thrd.join(0.5) - - tfile.seek(0) - result = [line.decode('utf-8', 'replace').rstrip() for line in tfile] - - if self.proc.returncode != 0: - raise CmdFailed([''] + result) - - return result - except: - self.terminate() - raise - - def terminate(self): - """ Terminate process and cleanup. """ - if self.alive: - if G_IS_WIN: - os.kill(self.proc.pid, signal.SIGINT) - else: - os.killpg(self.proc.pid, signal.SIGTERM) - self.clean() - -class Plugin(object): - def __init__(self, name, args, buf_q, lock): - self.name = name - self.args = args - self.buf_q = buf_q - self.lock = lock - self.tag = args.get('tag', 0) - - def manage(self): - try: - if os.path.exists(self.args['dir']): - self.update() - else: - self.install() - with self.lock: - thread_vim_command("let s:update.new['{0}'] = 1".format(self.name)) - except PlugError as exc: - self.write(Action.ERROR, self.name, exc.msg) - except KeyboardInterrupt: - G_STOP.set() - self.write(Action.ERROR, self.name, ['Interrupted!']) - except: - # Any exception except those above print stack trace - msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip()) - self.write(Action.ERROR, self.name, msg.split('\n')) - raise - - def install(self): - target = self.args['dir'] - if target[-1] == '\\': - target = target[0:-1] - - def clean(target): - def _clean(): - try: - shutil.rmtree(target) - except OSError: - pass - return _clean - - self.write(Action.INSTALL, self.name, ['Installing ...']) - callback = functools.partial(self.write, Action.INSTALL, self.name) - cmd = 'git clone {0} {1} {2} {3} 2>&1'.format( - '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'], - esc(target)) - com = Command(cmd, None, G_TIMEOUT, callback, clean(target)) - result = com.execute(G_RETRIES) - self.write(Action.DONE, self.name, result[-1:]) - - def repo_uri(self): - cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url' - command = Command(cmd, self.args['dir'], G_TIMEOUT,) - result = command.execute(G_RETRIES) - return result[-1] - - def update(self): - actual_uri = self.repo_uri() - expect_uri = self.args['uri'] - regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$') - ma = regex.match(actual_uri) - mb = regex.match(expect_uri) - if ma is None or mb is None or ma.groups() != mb.groups(): - msg = ['', - 'Invalid URI: {0}'.format(actual_uri), - 'Expected {0}'.format(expect_uri), - 'PlugClean required.'] - raise InvalidURI(msg) - - if G_PULL: - self.write(Action.UPDATE, self.name, ['Updating ...']) - callback = functools.partial(self.write, Action.UPDATE, self.name) - fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else '' - cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS) - com = Command(cmd, self.args['dir'], G_TIMEOUT, callback) - result = com.execute(G_RETRIES) - self.write(Action.DONE, self.name, result[-1:]) - else: - self.write(Action.DONE, self.name, ['Already installed']) - - def write(self, action, name, msg): - self.buf_q.put((action, name, msg)) - -class PlugThread(thr.Thread): - def __init__(self, tname, args): - super(PlugThread, self).__init__() - self.tname = tname - self.args = args - - def run(self): - thr.current_thread().name = self.tname - buf_q, work_q, lock = self.args - - try: - while not G_STOP.is_set(): - name, args = work_q.get_nowait() - plug = Plugin(name, args, buf_q, lock) - plug.manage() - work_q.task_done() - except queue.Empty: - pass - -class RefreshThread(thr.Thread): - def __init__(self, lock): - super(RefreshThread, self).__init__() - self.lock = lock - self.running = True - - def run(self): - while self.running: - with self.lock: - thread_vim_command('noautocmd normal! a') - time.sleep(0.33) - - def stop(self): - self.running = False - -if G_NVIM: - def thread_vim_command(cmd): - vim.session.threadsafe_call(lambda: vim.command(cmd)) -else: - def thread_vim_command(cmd): - vim.command(cmd) - -def esc(name): - return '"' + name.replace('"', '\"') + '"' - -def nonblock_read(fname): - """ Read a file with nonblock flag. Return the last line. """ - fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK) - buf = os.read(fread, 100000).decode('utf-8', 'replace') - os.close(fread) - - line = buf.rstrip('\r\n') - left = max(line.rfind('\r'), line.rfind('\n')) - if left != -1: - left += 1 - line = line[left:] - - return line - -def main(): - thr.current_thread().name = 'main' - nthreads = int(vim.eval('s:update.threads')) - plugs = vim.eval('s:update.todo') - mac_gui = vim.eval('s:mac_gui') == '1' - - lock = thr.Lock() - buf = Buffer(lock, len(plugs), G_PULL) - buf_q, work_q = queue.Queue(), queue.Queue() - for work in plugs.items(): - work_q.put(work) - - start_cnt = thr.active_count() - for num in range(nthreads): - tname = 'PlugT-{0:02}'.format(num) - thread = PlugThread(tname, (buf_q, work_q, lock)) - thread.start() - if mac_gui: - rthread = RefreshThread(lock) - rthread.start() - - while not buf_q.empty() or thr.active_count() != start_cnt: - try: - action, name, msg = buf_q.get(True, 0.25) - buf.write(action, name, ['OK'] if not msg else msg) - buf_q.task_done() - except queue.Empty: - pass - except KeyboardInterrupt: - G_STOP.set() - - if mac_gui: - rthread.stop() - rthread.join() - -main() -EOF -endfunction - -function! s:update_ruby() - ruby << EOF - module PlugStream - SEP = ["\r", "\n", nil] - def get_line - buffer = '' - loop do - char = readchar rescue return - if SEP.include? char.chr - buffer << $/ - break - else - buffer << char - end - end - buffer - end - end unless defined?(PlugStream) - - def esc arg - %["#{arg.gsub('"', '\"')}"] - end - - def killall pid - pids = [pid] - if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM - pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil } - else - unless `which pgrep 2> /dev/null`.empty? - children = pids - until children.empty? - children = children.map { |pid| - `pgrep -P #{pid}`.lines.map { |l| l.chomp } - }.flatten - pids += children - end - end - pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil } - end - end - - def compare_git_uri a, b - regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$} - regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1) - end - - require 'thread' - require 'fileutils' - require 'timeout' - running = true - iswin = VIM::evaluate('s:is_win').to_i == 1 - pull = VIM::evaluate('s:update.pull').to_i == 1 - base = VIM::evaluate('g:plug_home') - all = VIM::evaluate('s:update.todo') - limit = VIM::evaluate('get(g:, "plug_timeout", 60)') - tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1 - nthr = VIM::evaluate('s:update.threads').to_i - maxy = VIM::evaluate('winheight(".")').to_i - vim7 = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/ - cd = iswin ? 'cd /d' : 'cd' - tot = VIM::evaluate('len(s:update.todo)') || 0 - bar = '' - skip = 'Already installed' - mtx = Mutex.new - take1 = proc { mtx.synchronize { running && all.shift } } - logh = proc { - cnt = bar.length - $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})" - $curbuf[2] = '[' + bar.ljust(tot) + ']' - VIM::command('normal! 2G') - VIM::command('redraw') - } - where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } } - log = proc { |name, result, type| - mtx.synchronize do - ing = ![true, false].include?(type) - bar += type ? '=' : 'x' unless ing - b = case type - when :install then '+' when :update then '*' - when true, nil then '-' else - VIM::command("call add(s:update.errors, '#{name}')") - 'x' - end - result = - if type || type.nil? - ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"] - elsif result =~ /^Interrupted|^Timeout/ - ["#{b} #{name}: #{result}"] - else - ["#{b} #{name}"] + result.lines.map { |l| " " << l } - end - if lnum = where.call(name) - $curbuf.delete lnum - lnum = 4 if ing && lnum > maxy - end - result.each_with_index do |line, offset| - $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp) - end - logh.call - end - } - bt = proc { |cmd, name, type, cleanup| - tried = timeout = 0 - begin - tried += 1 - timeout += limit - fd = nil - data = '' - if iswin - Timeout::timeout(timeout) do - tmp = VIM::evaluate('tempname()') - system("(#{cmd}) > #{tmp}") - data = File.read(tmp).chomp - File.unlink tmp rescue nil - end - else - fd = IO.popen(cmd).extend(PlugStream) - first_line = true - log_prob = 1.0 / nthr - while line = Timeout::timeout(timeout) { fd.get_line } - data << line - log.call name, line.chomp, type if name && (first_line || rand < log_prob) - first_line = false - end - fd.close - end - [$? == 0, data.chomp] - rescue Timeout::Error, Interrupt => e - if fd && !fd.closed? - killall fd.pid - fd.close - end - cleanup.call if cleanup - if e.is_a?(Timeout::Error) && tried < tries - 3.downto(1) do |countdown| - s = countdown > 1 ? 's' : '' - log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type - sleep 1 - end - log.call name, 'Retrying ...', type - retry - end - [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"] - end - } - main = Thread.current - threads = [] - watcher = Thread.new { - if vim7 - while VIM::evaluate('getchar(1)') - sleep 0.1 - end - else - require 'io/console' # >= Ruby 1.9 - nil until IO.console.getch == 3.chr - end - mtx.synchronize do - running = false - threads.each { |t| t.raise Interrupt } unless vim7 - end - threads.each { |t| t.join rescue nil } - main.kill - } - refresh = Thread.new { - while true - mtx.synchronize do - break unless running - VIM::command('noautocmd normal! a') - end - sleep 0.2 - end - } if VIM::evaluate('s:mac_gui') == 1 - - clone_opt = VIM::evaluate('s:clone_opt').join(' ') - progress = VIM::evaluate('s:progress_opt(1)') - nthr.times do - mtx.synchronize do - threads << Thread.new { - while pair = take1.call - name = pair.first - dir, uri, tag = pair.last.values_at *%w[dir uri tag] - exists = File.directory? dir - ok, result = - if exists - chdir = "#{cd} #{iswin ? dir : esc(dir)}" - ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil - current_uri = data.lines.to_a.last - if !ret - if data =~ /^Interrupted|^Timeout/ - [false, data] - else - [false, [data.chomp, "PlugClean required."].join($/)] - end - elsif !compare_git_uri(current_uri, uri) - [false, ["Invalid URI: #{current_uri}", - "Expected: #{uri}", - "PlugClean required."].join($/)] - else - if pull - log.call name, 'Updating ...', :update - fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : '' - bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil - else - [true, skip] - end - end - else - d = esc dir.sub(%r{[\\/]+$}, '') - log.call name, 'Installing ...', :install - bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc { - FileUtils.rm_rf dir - } - end - mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok - log.call name, result, ok - end - } if running - end - end - threads.each { |t| t.join rescue nil } - logh.call - refresh.kill if refresh - watcher.kill -EOF -endfunction - -function! s:shellesc_cmd(arg, script) - let escaped = substitute('"'.a:arg.'"', '[&|<>()@^!"]', '^&', 'g') - return substitute(escaped, '%', (a:script ? '%' : '^') . '&', 'g') -endfunction - -function! s:shellesc_ps1(arg) - return "'".substitute(escape(a:arg, '\"'), "'", "''", 'g')."'" -endfunction - -function! s:shellesc_sh(arg) - return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'" -endfunction - -" Escape the shell argument based on the shell. -" Vim and Neovim's shellescape() are insufficient. -" 1. shellslash determines whether to use single/double quotes. -" Double-quote escaping is fragile for cmd.exe. -" 2. It does not work for powershell. -" 3. It does not work for *sh shells if the command is executed -" via cmd.exe (ie. cmd.exe /c sh -c command command_args) -" 4. It does not support batchfile syntax. -" -" Accepts an optional dictionary with the following keys: -" - shell: same as Vim/Neovim 'shell' option. -" If unset, fallback to 'cmd.exe' on Windows or 'sh'. -" - script: If truthy and shell is cmd.exe, escape for batchfile syntax. -function! plug#shellescape(arg, ...) - if a:arg =~# '^[A-Za-z0-9_/:.-]\+$' - return a:arg - endif - let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {} - let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh') - let script = get(opts, 'script', 1) - if shell =~# 'cmd\(\.exe\)\?$' - return s:shellesc_cmd(a:arg, script) - elseif shell =~# 'powershell\(\.exe\)\?$' || shell =~# 'pwsh$' - return s:shellesc_ps1(a:arg) - endif - return s:shellesc_sh(a:arg) -endfunction - -function! s:glob_dir(path) - return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)') -endfunction - -function! s:progress_bar(line, bar, total) - call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']') -endfunction - -function! s:compare_git_uri(a, b) - " See `git help clone' - " https:// [user@] github.com[:port] / junegunn/vim-plug [.git] - " [git@] github.com[:port] : junegunn/vim-plug [.git] - " file:// / junegunn/vim-plug [/] - " / junegunn/vim-plug [/] - let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$' - let ma = matchlist(a:a, pat) - let mb = matchlist(a:b, pat) - return ma[1:2] ==# mb[1:2] -endfunction - -function! s:format_message(bullet, name, message) - if a:bullet != 'x' - return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))] - else - let lines = map(s:lines(a:message), '" ".v:val') - return extend([printf('x %s:', a:name)], lines) - endif -endfunction - -function! s:with_cd(cmd, dir, ...) - let script = a:0 > 0 ? a:1 : 1 - return printf('cd%s %s && %s', s:is_win ? ' /d' : '', plug#shellescape(a:dir, {'script': script}), a:cmd) -endfunction - -function! s:system(cmd, ...) - let batchfile = '' - try - let [sh, shellcmdflag, shrd] = s:chsh(1) - if type(a:cmd) == s:TYPE.list - " Neovim's system() supports list argument to bypass the shell - " but it cannot set the working directory for the command. - " Assume that the command does not rely on the shell. - if has('nvim') && a:0 == 0 - return system(a:cmd) - endif - let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})')) - if &shell =~# 'powershell\(\.exe\)\?$' - let cmd = '& ' . cmd - endif - else - let cmd = a:cmd - endif - if a:0 > 0 - let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list) - endif - if s:is_win && type(a:cmd) != s:TYPE.list - let [batchfile, cmd] = s:batchfile(cmd) - endif - return system(cmd) - finally - let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] - if s:is_win && filereadable(batchfile) - call delete(batchfile) - endif - endtry -endfunction - -function! s:system_chomp(...) - let ret = call('s:system', a:000) - return v:shell_error ? '' : substitute(ret, '\n$', '', '') -endfunction - -function! s:git_validate(spec, check_branch) - let err = '' - if isdirectory(a:spec.dir) - let result = [s:git_local_branch(a:spec.dir), s:git_origin_url(a:spec.dir)] - let remote = result[-1] - if empty(remote) - let err = join([remote, 'PlugClean required.'], "\n") - elseif !s:compare_git_uri(remote, a:spec.uri) - let err = join(['Invalid URI: '.remote, - \ 'Expected: '.a:spec.uri, - \ 'PlugClean required.'], "\n") - elseif a:check_branch && has_key(a:spec, 'commit') - let sha = s:git_revision(a:spec.dir) - if empty(sha) - let err = join(add(result, 'PlugClean required.'), "\n") - elseif !s:hash_match(sha, a:spec.commit) - let err = join([printf('Invalid HEAD (expected: %s, actual: %s)', - \ a:spec.commit[:6], sha[:6]), - \ 'PlugUpdate required.'], "\n") - endif - elseif a:check_branch - let current_branch = result[0] - " Check tag - let origin_branch = s:git_origin_branch(a:spec) - if has_key(a:spec, 'tag') - let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir) - if a:spec.tag !=# tag && a:spec.tag !~ '\*' - let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.', - \ (empty(tag) ? 'N/A' : tag), a:spec.tag) - endif - " Check branch - elseif origin_branch !=# current_branch - let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.', - \ current_branch, origin_branch) - endif - if empty(err) - let [ahead, behind] = split(s:lastline(s:system([ - \ 'git', 'rev-list', '--count', '--left-right', - \ printf('HEAD...origin/%s', origin_branch) - \ ], a:spec.dir)), '\t') - if !v:shell_error && ahead - if behind - " Only mention PlugClean if diverged, otherwise it's likely to be - " pushable (and probably not that messed up). - let err = printf( - \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n" - \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', origin_branch, ahead, behind) - else - let err = printf("Ahead of origin/%s by %d commit(s).\n" - \ .'Cannot update until local changes are pushed.', - \ origin_branch, ahead) - endif - endif - endif - endif - else - let err = 'Not found' - endif - return [err, err =~# 'PlugClean'] -endfunction - -function! s:rm_rf(dir) - if isdirectory(a:dir) - return s:system(s:is_win - \ ? 'rmdir /S /Q '.plug#shellescape(a:dir) - \ : ['rm', '-rf', a:dir]) - endif -endfunction - -function! s:clean(force) - call s:prepare() - call append(0, 'Searching for invalid plugins in '.g:plug_home) - call append(1, '') - - " List of valid directories - let dirs = [] - let errs = {} - let [cnt, total] = [0, len(g:plugs)] - for [name, spec] in items(g:plugs) - if !s:is_managed(name) - call add(dirs, spec.dir) - else - let [err, clean] = s:git_validate(spec, 1) - if clean - let errs[spec.dir] = s:lines(err)[0] - else - call add(dirs, spec.dir) - endif - endif - let cnt += 1 - call s:progress_bar(2, repeat('=', cnt), total) - normal! 2G - redraw - endfor - - let allowed = {} - for dir in dirs - let allowed[s:dirpath(s:plug_fnamemodify(dir, ':h:h'))] = 1 - let allowed[dir] = 1 - for child in s:glob_dir(dir) - let allowed[child] = 1 - endfor - endfor - - let todo = [] - let found = sort(s:glob_dir(g:plug_home)) - while !empty(found) - let f = remove(found, 0) - if !has_key(allowed, f) && isdirectory(f) - call add(todo, f) - call append(line('$'), '- ' . f) - if has_key(errs, f) - call append(line('$'), ' ' . errs[f]) - endif - let found = filter(found, 'stridx(v:val, f) != 0') - end - endwhile - - 4 - redraw - if empty(todo) - call append(line('$'), 'Already clean.') - else - let s:clean_count = 0 - call append(3, ['Directories to delete:', '']) - redraw! - if a:force || s:ask_no_interrupt('Delete all directories?') - call s:delete([6, line('$')], 1) - else - call setline(4, 'Cancelled.') - nnoremap d :set opfunc=delete_opg@ - nmap dd d_ - xnoremap d :call delete_op(visualmode(), 1) - echo 'Delete the lines (d{motion}) to delete the corresponding directories' - endif - endif - 4 - setlocal nomodifiable -endfunction - -function! s:delete_op(type, ...) - call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0) -endfunction - -function! s:delete(range, force) - let [l1, l2] = a:range - let force = a:force - let err_count = 0 - while l1 <= l2 - let line = getline(l1) - if line =~ '^- ' && isdirectory(line[2:]) - execute l1 - redraw! - let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1) - let force = force || answer > 1 - if answer - let err = s:rm_rf(line[2:]) - setlocal modifiable - if empty(err) - call setline(l1, '~'.line[1:]) - let s:clean_count += 1 - else - delete _ - call append(l1 - 1, s:format_message('x', line[1:], err)) - let l2 += len(s:lines(err)) - let err_count += 1 - endif - let msg = printf('Removed %d directories.', s:clean_count) - if err_count > 0 - let msg .= printf(' Failed to remove %d directories.', err_count) - endif - call setline(4, msg) - setlocal nomodifiable - endif - endif - let l1 += 1 - endwhile -endfunction - -function! s:upgrade() - echo 'Downloading the latest version of vim-plug' - redraw - let tmp = s:plug_tempname() - let new = tmp . '/plug.vim' - - try - let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp]) - if v:shell_error - return s:err('Error upgrading vim-plug: '. out) - endif - - if readfile(s:me) ==# readfile(new) - echo 'vim-plug is already up-to-date' - return 0 - else - call rename(s:me, s:me . '.old') - call rename(new, s:me) - unlet g:loaded_plug - echo 'vim-plug has been upgraded' - return 1 - endif - finally - silent! call s:rm_rf(tmp) - endtry -endfunction - -function! s:upgrade_specs() - for spec in values(g:plugs) - let spec.frozen = get(spec, 'frozen', 0) - endfor -endfunction - -function! s:status() - call s:prepare() - call append(0, 'Checking plugins') - call append(1, '') - - let ecnt = 0 - let unloaded = 0 - let [cnt, total] = [0, len(g:plugs)] - for [name, spec] in items(g:plugs) - let is_dir = isdirectory(spec.dir) - if has_key(spec, 'uri') - if is_dir - let [err, _] = s:git_validate(spec, 1) - let [valid, msg] = [empty(err), empty(err) ? 'OK' : err] - else - let [valid, msg] = [0, 'Not found. Try PlugInstall.'] - endif - else - if is_dir - let [valid, msg] = [1, 'OK'] - else - let [valid, msg] = [0, 'Not found.'] - endif - endif - let cnt += 1 - let ecnt += !valid - " `s:loaded` entry can be missing if PlugUpgraded - if is_dir && get(s:loaded, name, -1) == 0 - let unloaded = 1 - let msg .= ' (not loaded)' - endif - call s:progress_bar(2, repeat('=', cnt), total) - call append(3, s:format_message(valid ? '-' : 'x', name, msg)) - normal! 2G - redraw - endfor - call setline(1, 'Finished. '.ecnt.' error(s).') - normal! gg - setlocal nomodifiable - if unloaded - echo "Press 'L' on each line to load plugin, or 'U' to update" - nnoremap L :call status_load(line('.')) - xnoremap L :call status_load(line('.')) - end -endfunction - -function! s:extract_name(str, prefix, suffix) - return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$') -endfunction - -function! s:status_load(lnum) - let line = getline(a:lnum) - let name = s:extract_name(line, '-', '(not loaded)') - if !empty(name) - call plug#load(name) - setlocal modifiable - call setline(a:lnum, substitute(line, ' (not loaded)$', '', '')) - setlocal nomodifiable - endif -endfunction - -function! s:status_update() range - let lines = getline(a:firstline, a:lastline) - let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)') - if !empty(names) - echo - execute 'PlugUpdate' join(names) - endif -endfunction - -function! s:is_preview_window_open() - silent! wincmd P - if &previewwindow - wincmd p - return 1 - endif -endfunction - -function! s:find_name(lnum) - for lnum in reverse(range(1, a:lnum)) - let line = getline(lnum) - if empty(line) - return '' - endif - let name = s:extract_name(line, '-', '') - if !empty(name) - return name - endif - endfor - return '' -endfunction - -function! s:preview_commit() - if b:plug_preview < 0 - let b:plug_preview = !s:is_preview_window_open() - endif - - let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7,9}') - if empty(sha) - return - endif - - let name = s:find_name(line('.')) - if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir) - return - endif - - if exists('g:plug_pwindow') && !s:is_preview_window_open() - execute g:plug_pwindow - execute 'e' sha - else - execute 'pedit' sha - wincmd P - endif - setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable - let batchfile = '' - try - let [sh, shellcmdflag, shrd] = s:chsh(1) - let cmd = 'cd '.plug#shellescape(g:plugs[name].dir).' && git show --no-color --pretty=medium '.sha - if s:is_win - let [batchfile, cmd] = s:batchfile(cmd) - endif - execute 'silent %!' cmd - finally - let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] - if s:is_win && filereadable(batchfile) - call delete(batchfile) - endif - endtry - setlocal nomodifiable - nnoremap q :q - wincmd p -endfunction - -function! s:section(flags) - call search('\(^[x-] \)\@<=[^:]\+:', a:flags) -endfunction - -function! s:format_git_log(line) - let indent = ' ' - let tokens = split(a:line, nr2char(1)) - if len(tokens) != 5 - return indent.substitute(a:line, '\s*$', '', '') - endif - let [graph, sha, refs, subject, date] = tokens - let tag = matchstr(refs, 'tag: [^,)]\+') - let tag = empty(tag) ? ' ' : ' ('.tag.') ' - return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date) -endfunction - -function! s:append_ul(lnum, text) - call append(a:lnum, ['', a:text, repeat('-', len(a:text))]) -endfunction - -function! s:diff() - call s:prepare() - call append(0, ['Collecting changes ...', '']) - let cnts = [0, 0] - let bar = '' - let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)') - call s:progress_bar(2, bar, len(total)) - for origin in [1, 0] - let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))')))) - if empty(plugs) - continue - endif - call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:') - for [k, v] in plugs - let branch = s:git_origin_branch(v) - if len(branch) - let range = origin ? '..origin/'.branch : 'HEAD@{1}..' - let cmd = ['git', 'log', '--graph', '--color=never'] - if s:git_version_requirement(2, 10, 0) - call add(cmd, '--no-show-signature') - endif - call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range]) - if has_key(v, 'rtp') - call extend(cmd, ['--', v.rtp]) - endif - let diff = s:system_chomp(cmd, v.dir) - if !empty(diff) - let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' - call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) - let cnts[origin] += 1 - endif - endif - let bar .= '=' - call s:progress_bar(2, bar, len(total)) - normal! 2G - redraw - endfor - if !cnts[origin] - call append(5, ['', 'N/A']) - endif - endfor - call setline(1, printf('%d plugin(s) updated.', cnts[0]) - \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : '')) - - if cnts[0] || cnts[1] - nnoremap (plug-preview) :silent! call preview_commit() - if empty(maparg("\", 'n')) - nmap (plug-preview) - endif - if empty(maparg('o', 'n')) - nmap o (plug-preview) - endif - endif - if cnts[0] - nnoremap X :call revert() - echo "Press 'X' on each block to revert the update" - endif - normal! gg - setlocal nomodifiable -endfunction - -function! s:revert() - if search('^Pending updates', 'bnW') - return - endif - - let name = s:find_name(line('.')) - if empty(name) || !has_key(g:plugs, name) || - \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y' - return - endif - - call s:system('git reset --hard HEAD@{1} && git checkout '.plug#shellescape(g:plugs[name].branch).' --', g:plugs[name].dir) - setlocal modifiable - normal! "_dap - setlocal nomodifiable - echo 'Reverted' -endfunction - -function! s:snapshot(force, ...) abort - call s:prepare() - setf vim - call append(0, ['" Generated by vim-plug', - \ '" '.strftime("%c"), - \ '" :source this file in vim to restore the snapshot', - \ '" or execute: vim -S snapshot.vim', - \ '', '', 'PlugUpdate!']) - 1 - let anchor = line('$') - 3 - let names = sort(keys(filter(copy(g:plugs), - \'has_key(v:val, "uri") && !has_key(v:val, "commit") && isdirectory(v:val.dir)'))) - for name in reverse(names) - let sha = s:git_revision(g:plugs[name].dir) - if !empty(sha) - call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha)) - redraw - endif - endfor - - if a:0 > 0 - let fn = s:plug_expand(a:1) - if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?')) - return - endif - call writefile(getline(1, '$'), fn) - echo 'Saved as '.a:1 - silent execute 'e' s:esc(fn) - setf vim - endif -endfunction - -function! s:split_rtp() - return split(&rtp, '\\\@`-mappings | -"| `for` | On-demand loading: File types | -"| `frozen` | Do not update unless explicitly specified | -" -" More information: https://github.com/junegunn/vim-plug -" -" -" Copyright (c) 2017 Junegunn Choi -" -" MIT License -" -" Permission is hereby granted, free of charge, to any person obtaining -" a copy of this software and associated documentation files (the -" "Software"), to deal in the Software without restriction, including -" without limitation the rights to use, copy, modify, merge, publish, -" distribute, sublicense, and/or sell copies of the Software, and to -" permit persons to whom the Software is furnished to do so, subject to -" the following conditions: -" -" The above copyright notice and this permission notice shall be -" included in all copies or substantial portions of the Software. -" -" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -if exists('g:loaded_plug') - finish -endif -let g:loaded_plug = 1 - -let s:cpo_save = &cpo -set cpo&vim - -let s:plug_src = 'https://github.com/junegunn/vim-plug.git' -let s:plug_tab = get(s:, 'plug_tab', -1) -let s:plug_buf = get(s:, 'plug_buf', -1) -let s:mac_gui = has('gui_macvim') && has('gui_running') -let s:is_win = has('win32') -let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win) -let s:vim8 = has('patch-8.0.0039') && exists('*job_start') -if s:is_win && &shellslash - set noshellslash - let s:me = resolve(expand(':p')) - set shellslash -else - let s:me = resolve(expand(':p')) -endif -let s:base_spec = { 'branch': '', 'frozen': 0 } -let s:TYPE = { -\ 'string': type(''), -\ 'list': type([]), -\ 'dict': type({}), -\ 'funcref': type(function('call')) -\ } -let s:loaded = get(s:, 'loaded', {}) -let s:triggers = get(s:, 'triggers', {}) - -function! s:isabsolute(dir) abort - return a:dir =~# '^/' || (has('win32') && a:dir =~? '^\%(\\\|[A-Z]:\)') -endfunction - -function! s:git_dir(dir) abort - let gitdir = s:trim(a:dir) . '/.git' - if isdirectory(gitdir) - return gitdir - endif - if !filereadable(gitdir) - return '' - endif - let gitdir = matchstr(get(readfile(gitdir), 0, ''), '^gitdir: \zs.*') - if len(gitdir) && !s:isabsolute(gitdir) - let gitdir = a:dir . '/' . gitdir - endif - return isdirectory(gitdir) ? gitdir : '' -endfunction - -function! s:git_origin_url(dir) abort - let gitdir = s:git_dir(a:dir) - let config = gitdir . '/config' - if empty(gitdir) || !filereadable(config) - return '' - endif - return matchstr(join(readfile(config)), '\[remote "origin"\].\{-}url\s*=\s*\zs\S*\ze') -endfunction - -function! s:git_revision(dir) abort - let gitdir = s:git_dir(a:dir) - let head = gitdir . '/HEAD' - if empty(gitdir) || !filereadable(head) - return '' - endif - - let line = get(readfile(head), 0, '') - let ref = matchstr(line, '^ref: \zs.*') - if empty(ref) - return line - endif - - if filereadable(gitdir . '/' . ref) - return get(readfile(gitdir . '/' . ref), 0, '') - endif - - if filereadable(gitdir . '/packed-refs') - for line in readfile(gitdir . '/packed-refs') - if line =~# ' ' . ref - return matchstr(line, '^[0-9a-f]*') - endif - endfor - endif - - return '' -endfunction - -function! s:git_local_branch(dir) abort - let gitdir = s:git_dir(a:dir) - let head = gitdir . '/HEAD' - if empty(gitdir) || !filereadable(head) - return '' - endif - let branch = matchstr(get(readfile(head), 0, ''), '^ref: refs/heads/\zs.*') - return len(branch) ? branch : 'HEAD' -endfunction - -function! s:git_origin_branch(spec) - if len(a:spec.branch) - return a:spec.branch - endif - - " The file may not be present if this is a local repository - let gitdir = s:git_dir(a:spec.dir) - let origin_head = gitdir.'/refs/remotes/origin/HEAD' - if len(gitdir) && filereadable(origin_head) - return matchstr(get(readfile(origin_head), 0, ''), - \ '^ref: refs/remotes/origin/\zs.*') - endif - - " The command may not return the name of a branch in detached HEAD state - let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir)) - return v:shell_error ? '' : result[-1] -endfunction - -if s:is_win - function! s:plug_call(fn, ...) - let shellslash = &shellslash - try - set noshellslash - return call(a:fn, a:000) - finally - let &shellslash = shellslash - endtry - endfunction -else - function! s:plug_call(fn, ...) - return call(a:fn, a:000) - endfunction -endif - -function! s:plug_getcwd() - return s:plug_call('getcwd') -endfunction - -function! s:plug_fnamemodify(fname, mods) - return s:plug_call('fnamemodify', a:fname, a:mods) -endfunction - -function! s:plug_expand(fmt) - return s:plug_call('expand', a:fmt, 1) -endfunction - -function! s:plug_tempname() - return s:plug_call('tempname') -endfunction - -function! plug#begin(...) - if a:0 > 0 - let s:plug_home_org = a:1 - let home = s:path(s:plug_fnamemodify(s:plug_expand(a:1), ':p')) - elseif exists('g:plug_home') - let home = s:path(g:plug_home) - elseif !empty(&rtp) - let home = s:path(split(&rtp, ',')[0]) . '/plugged' - else - return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.') - endif - if s:plug_fnamemodify(home, ':t') ==# 'plugin' && s:plug_fnamemodify(home, ':h') ==# s:first_rtp - return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.') - endif - - let g:plug_home = home - let g:plugs = {} - let g:plugs_order = [] - let s:triggers = {} - - call s:define_commands() - return 1 -endfunction - -function! s:define_commands() - command! -nargs=+ -bar Plug call plug#() - if !executable('git') - return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.') - endif - if has('win32') - \ && &shellslash - \ && (&shell =~# 'cmd\(\.exe\)\?$' || &shell =~# 'powershell\(\.exe\)\?$') - return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.') - endif - if !has('nvim') - \ && (has('win32') || has('win32unix')) - \ && !has('multi_byte') - return s:err('Vim needs +multi_byte feature on Windows to run shell commands. Enable +iconv for best results.') - endif - command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(0, []) - command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(0, []) - command! -nargs=0 -bar -bang PlugClean call s:clean(0) - command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif - command! -nargs=0 -bar PlugStatus call s:status() - command! -nargs=0 -bar PlugDiff call s:diff() - command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(0, ) -endfunction - -function! s:to_a(v) - return type(a:v) == s:TYPE.list ? a:v : [a:v] -endfunction - -function! s:to_s(v) - return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n" -endfunction - -function! s:glob(from, pattern) - return s:lines(globpath(a:from, a:pattern)) -endfunction - -function! s:source(from, ...) - let found = 0 - for pattern in a:000 - for vim in s:glob(a:from, pattern) - execute 'source' s:esc(vim) - let found = 1 - endfor - endfor - return found -endfunction - -function! s:assoc(dict, key, val) - let a:dict[a:key] = add(get(a:dict, a:key, []), a:val) -endfunction - -function! s:ask(message, ...) - call inputsave() - echohl WarningMsg - let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) ')) - echohl None - call inputrestore() - echo "\r" - return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0 -endfunction - -function! s:ask_no_interrupt(...) - try - return call('s:ask', a:000) - catch - return 0 - endtry -endfunction - -function! s:lazy(plug, opt) - return has_key(a:plug, a:opt) && - \ (empty(s:to_a(a:plug[a:opt])) || - \ !isdirectory(a:plug.dir) || - \ len(s:glob(s:rtp(a:plug), 'plugin')) || - \ len(s:glob(s:rtp(a:plug), 'after/plugin'))) -endfunction - -function! plug#end() - if !exists('g:plugs') - return s:err('plug#end() called without calling plug#begin() first') - endif - - if exists('#PlugLOD') - augroup PlugLOD - autocmd! - augroup END - augroup! PlugLOD - endif - let lod = { 'ft': {}, 'map': {}, 'cmd': {} } - - if exists('g:did_load_filetypes') - filetype off - endif - for name in g:plugs_order - if !has_key(g:plugs, name) - continue - endif - let plug = g:plugs[name] - if get(s:loaded, name, 0) || !s:lazy(plug, 'on') && !s:lazy(plug, 'for') - let s:loaded[name] = 1 - continue - endif - - if has_key(plug, 'on') - let s:triggers[name] = { 'map': [], 'cmd': [] } - for cmd in s:to_a(plug.on) - if cmd =~? '^.\+' - if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i')) - call s:assoc(lod.map, cmd, name) - endif - call add(s:triggers[name].map, cmd) - elseif cmd =~# '^[A-Z]' - let cmd = substitute(cmd, '!*$', '', '') - if exists(':'.cmd) != 2 - call s:assoc(lod.cmd, cmd, name) - endif - call add(s:triggers[name].cmd, cmd) - else - call s:err('Invalid `on` option: '.cmd. - \ '. Should start with an uppercase letter or ``.') - endif - endfor - endif - - if has_key(plug, 'for') - let types = s:to_a(plug.for) - if !empty(types) - augroup filetypedetect - call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim') - augroup END - endif - for type in types - call s:assoc(lod.ft, type, name) - endfor - endif - endfor - - for [cmd, names] in items(lod.cmd) - execute printf( - \ 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "", , , , %s)', - \ cmd, string(cmd), string(names)) - endfor - - for [map, names] in items(lod.map) - for [mode, map_prefix, key_prefix] in - \ [['i', '', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']] - execute printf( - \ '%snoremap %s %s:call lod_map(%s, %s, %s, "%s")', - \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix) - endfor - endfor - - for [ft, names] in items(lod.ft) - augroup PlugLOD - execute printf('autocmd FileType %s call lod_ft(%s, %s)', - \ ft, string(ft), string(names)) - augroup END - endfor - - call s:reorg_rtp() - filetype plugin indent on - if has('vim_starting') - if has('syntax') && !exists('g:syntax_on') - syntax enable - end - else - call s:reload_plugins() - endif -endfunction - -function! s:loaded_names() - return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)') -endfunction - -function! s:load_plugin(spec) - call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim') -endfunction - -function! s:reload_plugins() - for name in s:loaded_names() - call s:load_plugin(g:plugs[name]) - endfor -endfunction - -function! s:trim(str) - return substitute(a:str, '[\/]\+$', '', '') -endfunction - -function! s:version_requirement(val, min) - for idx in range(0, len(a:min) - 1) - let v = get(a:val, idx, 0) - if v < a:min[idx] | return 0 - elseif v > a:min[idx] | return 1 - endif - endfor - return 1 -endfunction - -function! s:git_version_requirement(...) - if !exists('s:git_version') - let s:git_version = map(split(split(s:system(['git', '--version']))[2], '\.'), 'str2nr(v:val)') - endif - return s:version_requirement(s:git_version, a:000) -endfunction - -function! s:progress_opt(base) - return a:base && !s:is_win && - \ s:git_version_requirement(1, 7, 1) ? '--progress' : '' -endfunction - -function! s:rtp(spec) - return s:path(a:spec.dir . get(a:spec, 'rtp', '')) -endfunction - -if s:is_win - function! s:path(path) - return s:trim(substitute(a:path, '/', '\', 'g')) - endfunction - - function! s:dirpath(path) - return s:path(a:path) . '\' - endfunction - - function! s:is_local_plug(repo) - return a:repo =~? '^[a-z]:\|^[%~]' - endfunction - - " Copied from fzf - function! s:wrap_cmds(cmds) - let cmds = [ - \ '@echo off', - \ 'setlocal enabledelayedexpansion'] - \ + (type(a:cmds) == type([]) ? a:cmds : [a:cmds]) - \ + ['endlocal'] - if has('iconv') - if !exists('s:codepage') - let s:codepage = libcallnr('kernel32.dll', 'GetACP', 0) - endif - return map(cmds, printf('iconv(v:val."\r", "%s", "cp%d")', &encoding, s:codepage)) - endif - return map(cmds, 'v:val."\r"') - endfunction - - function! s:batchfile(cmd) - let batchfile = s:plug_tempname().'.bat' - call writefile(s:wrap_cmds(a:cmd), batchfile) - let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0}) - if &shell =~# 'powershell\(\.exe\)\?$' - let cmd = '& ' . cmd - endif - return [batchfile, cmd] - endfunction -else - function! s:path(path) - return s:trim(a:path) - endfunction - - function! s:dirpath(path) - return substitute(a:path, '[/\\]*$', '/', '') - endfunction - - function! s:is_local_plug(repo) - return a:repo[0] =~ '[/$~]' - endfunction -endif - -function! s:err(msg) - echohl ErrorMsg - echom '[vim-plug] '.a:msg - echohl None -endfunction - -function! s:warn(cmd, msg) - echohl WarningMsg - execute a:cmd 'a:msg' - echohl None -endfunction - -function! s:esc(path) - return escape(a:path, ' ') -endfunction - -function! s:escrtp(path) - return escape(a:path, ' ,') -endfunction - -function! s:remove_rtp() - for name in s:loaded_names() - let rtp = s:rtp(g:plugs[name]) - execute 'set rtp-='.s:escrtp(rtp) - let after = globpath(rtp, 'after') - if isdirectory(after) - execute 'set rtp-='.s:escrtp(after) - endif - endfor -endfunction - -function! s:reorg_rtp() - if !empty(s:first_rtp) - execute 'set rtp-='.s:first_rtp - execute 'set rtp-='.s:last_rtp - endif - - " &rtp is modified from outside - if exists('s:prtp') && s:prtp !=# &rtp - call s:remove_rtp() - unlet! s:middle - endif - - let s:middle = get(s:, 'middle', &rtp) - let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])') - let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)') - let rtp = join(map(rtps, 'escape(v:val, ",")'), ',') - \ . ','.s:middle.',' - \ . join(map(afters, 'escape(v:val, ",")'), ',') - let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g') - let s:prtp = &rtp - - if !empty(s:first_rtp) - execute 'set rtp^='.s:first_rtp - execute 'set rtp+='.s:last_rtp - endif -endfunction - -function! s:doautocmd(...) - if exists('#'.join(a:000, '#')) - execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '' : '') join(a:000) - endif -endfunction - -function! s:dobufread(names) - for name in a:names - let path = s:rtp(g:plugs[name]) - for dir in ['ftdetect', 'ftplugin', 'after/ftdetect', 'after/ftplugin'] - if len(finddir(dir, path)) - if exists('#BufRead') - doautocmd BufRead - endif - return - endif - endfor - endfor -endfunction - -function! plug#load(...) - if a:0 == 0 - return s:err('Argument missing: plugin name(s) required') - endif - if !exists('g:plugs') - return s:err('plug#begin was not called') - endif - let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000 - let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)') - if !empty(unknowns) - let s = len(unknowns) > 1 ? 's' : '' - return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', '))) - end - let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)') - if !empty(unloaded) - for name in unloaded - call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) - endfor - call s:dobufread(unloaded) - return 1 - end - return 0 -endfunction - -function! s:remove_triggers(name) - if !has_key(s:triggers, a:name) - return - endif - for cmd in s:triggers[a:name].cmd - execute 'silent! delc' cmd - endfor - for map in s:triggers[a:name].map - execute 'silent! unmap' map - execute 'silent! iunmap' map - endfor - call remove(s:triggers, a:name) -endfunction - -function! s:lod(names, types, ...) - for name in a:names - call s:remove_triggers(name) - let s:loaded[name] = 1 - endfor - call s:reorg_rtp() - - for name in a:names - let rtp = s:rtp(g:plugs[name]) - for dir in a:types - call s:source(rtp, dir.'/**/*.vim') - endfor - if a:0 - if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2)) - execute 'runtime' a:1 - endif - call s:source(rtp, a:2) - endif - call s:doautocmd('User', name) - endfor -endfunction - -function! s:lod_ft(pat, names) - let syn = 'syntax/'.a:pat.'.vim' - call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn) - execute 'autocmd! PlugLOD FileType' a:pat - call s:doautocmd('filetypeplugin', 'FileType') - call s:doautocmd('filetypeindent', 'FileType') -endfunction - -function! s:lod_cmd(cmd, bang, l1, l2, args, names) - call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) - call s:dobufread(a:names) - execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args) -endfunction - -function! s:lod_map(map, names, with_prefix, prefix) - call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) - call s:dobufread(a:names) - let extra = '' - while 1 - let c = getchar(0) - if c == 0 - break - endif - let extra .= nr2char(c) - endwhile - - if a:with_prefix - let prefix = v:count ? v:count : '' - let prefix .= '"'.v:register.a:prefix - if mode(1) == 'no' - if v:operator == 'c' - let prefix = "\" . prefix - endif - let prefix .= v:operator - endif - call feedkeys(prefix, 'n') - endif - call feedkeys(substitute(a:map, '^', "\", '') . extra) -endfunction - -function! plug#(repo, ...) - if a:0 > 1 - return s:err('Invalid number of arguments (1..2)') - endif - - try - let repo = s:trim(a:repo) - let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec - let name = get(opts, 'as', s:plug_fnamemodify(repo, ':t:s?\.git$??')) - let spec = extend(s:infer_properties(name, repo), opts) - if !has_key(g:plugs, name) - call add(g:plugs_order, name) - endif - let g:plugs[name] = spec - let s:loaded[name] = get(s:loaded, name, 0) - catch - return s:err(repo . ' ' . v:exception) - endtry -endfunction - -function! s:parse_options(arg) - let opts = copy(s:base_spec) - let type = type(a:arg) - let opt_errfmt = 'Invalid argument for "%s" option of :Plug (expected: %s)' - if type == s:TYPE.string - if empty(a:arg) - throw printf(opt_errfmt, 'tag', 'string') - endif - let opts.tag = a:arg - elseif type == s:TYPE.dict - for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as'] - if has_key(a:arg, opt) - \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt])) - throw printf(opt_errfmt, opt, 'string') - endif - endfor - for opt in ['on', 'for'] - if has_key(a:arg, opt) - \ && type(a:arg[opt]) != s:TYPE.list - \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt])) - throw printf(opt_errfmt, opt, 'string or list') - endif - endfor - if has_key(a:arg, 'do') - \ && type(a:arg.do) != s:TYPE.funcref - \ && (type(a:arg.do) != s:TYPE.string || empty(a:arg.do)) - throw printf(opt_errfmt, 'do', 'string or funcref') - endif - call extend(opts, a:arg) - if has_key(opts, 'dir') - let opts.dir = s:dirpath(s:plug_expand(opts.dir)) - endif - else - throw 'Invalid argument type (expected: string or dictionary)' - endif - return opts -endfunction - -function! s:infer_properties(name, repo) - let repo = a:repo - if s:is_local_plug(repo) - return { 'dir': s:dirpath(s:plug_expand(repo)) } - else - if repo =~ ':' - let uri = repo - else - if repo !~ '/' - throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo) - endif - let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git') - let uri = printf(fmt, repo) - endif - return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri } - endif -endfunction - -function! s:install(force, names) - call s:update_impl(0, a:force, a:names) -endfunction - -function! s:update(force, names) - call s:update_impl(1, a:force, a:names) -endfunction - -function! plug#helptags() - if !exists('g:plugs') - return s:err('plug#begin was not called') - endif - for spec in values(g:plugs) - let docd = join([s:rtp(spec), 'doc'], '/') - if isdirectory(docd) - silent! execute 'helptags' s:esc(docd) - endif - endfor - return 1 -endfunction - -function! s:syntax() - syntax clear - syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber - syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX - syn match plugNumber /[0-9]\+[0-9.]*/ contained - syn match plugBracket /[[\]]/ contained - syn match plugX /x/ contained - syn match plugDash /^-\{1}\ / - syn match plugPlus /^+/ - syn match plugStar /^*/ - syn match plugMessage /\(^- \)\@<=.*/ - syn match plugName /\(^- \)\@<=[^ ]*:/ - syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/ - syn match plugTag /(tag: [^)]\+)/ - syn match plugInstall /\(^+ \)\@<=[^:]*/ - syn match plugUpdate /\(^* \)\@<=[^:]*/ - syn match plugCommit /^ \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag - syn match plugEdge /^ \X\+$/ - syn match plugEdge /^ \X*/ contained nextgroup=plugSha - syn match plugSha /[0-9a-f]\{7,9}/ contained - syn match plugRelDate /([^)]*)$/ contained - syn match plugNotLoaded /(not loaded)$/ - syn match plugError /^x.*/ - syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/ - syn match plugH2 /^.*:\n-\+$/ - syn match plugH2 /^-\{2,}/ - syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean - hi def link plug1 Title - hi def link plug2 Repeat - hi def link plugH2 Type - hi def link plugX Exception - hi def link plugBracket Structure - hi def link plugNumber Number - - hi def link plugDash Special - hi def link plugPlus Constant - hi def link plugStar Boolean - - hi def link plugMessage Function - hi def link plugName Label - hi def link plugInstall Function - hi def link plugUpdate Type - - hi def link plugError Error - hi def link plugDeleted Ignore - hi def link plugRelDate Comment - hi def link plugEdge PreProc - hi def link plugSha Identifier - hi def link plugTag Constant - - hi def link plugNotLoaded Comment -endfunction - -function! s:lpad(str, len) - return a:str . repeat(' ', a:len - len(a:str)) -endfunction - -function! s:lines(msg) - return split(a:msg, "[\r\n]") -endfunction - -function! s:lastline(msg) - return get(s:lines(a:msg), -1, '') -endfunction - -function! s:new_window() - execute get(g:, 'plug_window', 'vertical topleft new') -endfunction - -function! s:plug_window_exists() - let buflist = tabpagebuflist(s:plug_tab) - return !empty(buflist) && index(buflist, s:plug_buf) >= 0 -endfunction - -function! s:switch_in() - if !s:plug_window_exists() - return 0 - endif - - if winbufnr(0) != s:plug_buf - let s:pos = [tabpagenr(), winnr(), winsaveview()] - execute 'normal!' s:plug_tab.'gt' - let winnr = bufwinnr(s:plug_buf) - execute winnr.'wincmd w' - call add(s:pos, winsaveview()) - else - let s:pos = [winsaveview()] - endif - - setlocal modifiable - return 1 -endfunction - -function! s:switch_out(...) - call winrestview(s:pos[-1]) - setlocal nomodifiable - if a:0 > 0 - execute a:1 - endif - - if len(s:pos) > 1 - execute 'normal!' s:pos[0].'gt' - execute s:pos[1] 'wincmd w' - call winrestview(s:pos[2]) - endif -endfunction - -function! s:finish_bindings() - nnoremap R :call retry() - nnoremap D :PlugDiff - nnoremap S :PlugStatus - nnoremap U :call status_update() - xnoremap U :call status_update() - nnoremap ]] :silent! call section('') - nnoremap [[ :silent! call section('b') -endfunction - -function! s:prepare(...) - if empty(s:plug_getcwd()) - throw 'Invalid current working directory. Cannot proceed.' - endif - - for evar in ['$GIT_DIR', '$GIT_WORK_TREE'] - if exists(evar) - throw evar.' detected. Cannot proceed.' - endif - endfor - - call s:job_abort() - if s:switch_in() - if b:plug_preview == 1 - pc - endif - enew - else - call s:new_window() - endif - - nnoremap q :if b:plug_preview==1pcendifbd - if a:0 == 0 - call s:finish_bindings() - endif - let b:plug_preview = -1 - let s:plug_tab = tabpagenr() - let s:plug_buf = winbufnr(0) - call s:assign_name() - - for k in ['', 'L', 'o', 'X', 'd', 'dd'] - execute 'silent! unmap ' k - endfor - setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell - if exists('+colorcolumn') - setlocal colorcolumn= - endif - setf vim-plug - if exists('g:syntax_on') - call s:syntax() - endif -endfunction - -function! s:assign_name() - " Assign buffer name - let prefix = '[Plugins]' - let name = prefix - let idx = 2 - while bufexists(name) - let name = printf('%s (%s)', prefix, idx) - let idx = idx + 1 - endwhile - silent! execute 'f' fnameescape(name) -endfunction - -function! s:chsh(swap) - let prev = [&shell, &shellcmdflag, &shellredir] - if !s:is_win - set shell=sh - endif - if a:swap - if &shell =~# 'powershell\(\.exe\)\?$' || &shell =~# 'pwsh$' - let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s' - elseif &shell =~# 'sh' || &shell =~# 'cmd\(\.exe\)\?$' - set shellredir=>%s\ 2>&1 - endif - endif - return prev -endfunction - -function! s:bang(cmd, ...) - let batchfile = '' - try - let [sh, shellcmdflag, shrd] = s:chsh(a:0) - " FIXME: Escaping is incomplete. We could use shellescape with eval, - " but it won't work on Windows. - let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd - if s:is_win - let [batchfile, cmd] = s:batchfile(cmd) - endif - let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%') - execute "normal! :execute g:_plug_bang\\" - finally - unlet g:_plug_bang - let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] - if s:is_win && filereadable(batchfile) - call delete(batchfile) - endif - endtry - return v:shell_error ? 'Exit status: ' . v:shell_error : '' -endfunction - -function! s:regress_bar() - let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '') - call s:progress_bar(2, bar, len(bar)) -endfunction - -function! s:is_updated(dir) - return !empty(s:system_chomp(['git', 'log', '--pretty=format:%h', 'HEAD...HEAD@{1}'], a:dir)) -endfunction - -function! s:do(pull, force, todo) - for [name, spec] in items(a:todo) - if !isdirectory(spec.dir) - continue - endif - let installed = has_key(s:update.new, name) - let updated = installed ? 0 : - \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir)) - if a:force || installed || updated - execute 'cd' s:esc(spec.dir) - call append(3, '- Post-update hook for '. name .' ... ') - let error = '' - let type = type(spec.do) - if type == s:TYPE.string - if spec.do[0] == ':' - if !get(s:loaded, name, 0) - let s:loaded[name] = 1 - call s:reorg_rtp() - endif - call s:load_plugin(spec) - try - execute spec.do[1:] - catch - let error = v:exception - endtry - if !s:plug_window_exists() - cd - - throw 'Warning: vim-plug was terminated by the post-update hook of '.name - endif - else - let error = s:bang(spec.do) - endif - elseif type == s:TYPE.funcref - try - call s:load_plugin(spec) - let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged') - call spec.do({ 'name': name, 'status': status, 'force': a:force }) - catch - let error = v:exception - endtry - else - let error = 'Invalid hook type' - endif - call s:switch_in() - call setline(4, empty(error) ? (getline(4) . 'OK') - \ : ('x' . getline(4)[1:] . error)) - if !empty(error) - call add(s:update.errors, name) - call s:regress_bar() - endif - cd - - endif - endfor -endfunction - -function! s:hash_match(a, b) - return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0 -endfunction - -function! s:checkout(spec) - let sha = a:spec.commit - let output = s:git_revision(a:spec.dir) - if !empty(output) && !s:hash_match(sha, s:lines(output)[0]) - let credential_helper = s:git_version_requirement(2) ? '-c credential.helper= ' : '' - let output = s:system( - \ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir) - endif - return output -endfunction - -function! s:finish(pull) - let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen')) - if new_frozen - let s = new_frozen > 1 ? 's' : '' - call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s)) - endif - call append(3, '- Finishing ... ') | 4 - redraw - call plug#helptags() - call plug#end() - call setline(4, getline(4) . 'Done!') - redraw - let msgs = [] - if !empty(s:update.errors) - call add(msgs, "Press 'R' to retry.") - endif - if a:pull && len(s:update.new) < len(filter(getline(5, '$'), - \ "v:val =~ '^- ' && v:val !~# 'Already up.to.date'")) - call add(msgs, "Press 'D' to see the updated changes.") - endif - echo join(msgs, ' ') - call s:finish_bindings() -endfunction - -function! s:retry() - if empty(s:update.errors) - return - endif - echo - call s:update_impl(s:update.pull, s:update.force, - \ extend(copy(s:update.errors), [s:update.threads])) -endfunction - -function! s:is_managed(name) - return has_key(g:plugs[a:name], 'uri') -endfunction - -function! s:names(...) - return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)')) -endfunction - -function! s:check_ruby() - silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'") - if !exists('g:plug_ruby') - redraw! - return s:warn('echom', 'Warning: Ruby interface is broken') - endif - let ruby_version = split(g:plug_ruby, '\.') - unlet g:plug_ruby - return s:version_requirement(ruby_version, [1, 8, 7]) -endfunction - -function! s:update_impl(pull, force, args) abort - let sync = index(a:args, '--sync') >= 0 || has('vim_starting') - let args = filter(copy(a:args), 'v:val != "--sync"') - let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ? - \ remove(args, -1) : get(g:, 'plug_threads', 16) - - let managed = filter(copy(g:plugs), 's:is_managed(v:key)') - let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') : - \ filter(managed, 'index(args, v:key) >= 0') - - if empty(todo) - return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install')) - endif - - if !s:is_win && s:git_version_requirement(2, 3) - let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : '' - let $GIT_TERMINAL_PROMPT = 0 - for plug in values(todo) - let plug.uri = substitute(plug.uri, - \ '^https://git::@github\.com', 'https://github.com', '') - endfor - endif - - if !isdirectory(g:plug_home) - try - call mkdir(g:plug_home, 'p') - catch - return s:err(printf('Invalid plug directory: %s. '. - \ 'Try to call plug#begin with a valid directory', g:plug_home)) - endtry - endif - - if has('nvim') && !exists('*jobwait') && threads > 1 - call s:warn('echom', '[vim-plug] Update Neovim for parallel installer') - endif - - let use_job = s:nvim || s:vim8 - let python = (has('python') || has('python3')) && !use_job - let ruby = has('ruby') && !use_job && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && threads > 1 && s:check_ruby() - - let s:update = { - \ 'start': reltime(), - \ 'all': todo, - \ 'todo': copy(todo), - \ 'errors': [], - \ 'pull': a:pull, - \ 'force': a:force, - \ 'new': {}, - \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1, - \ 'bar': '', - \ 'fin': 0 - \ } - - call s:prepare(1) - call append(0, ['', '']) - normal! 2G - silent! redraw - - let s:clone_opt = [] - if get(g:, 'plug_shallow', 1) - call extend(s:clone_opt, ['--depth', '1']) - if s:git_version_requirement(1, 7, 10) - call add(s:clone_opt, '--no-single-branch') - endif - endif - - if has('win32unix') || has('wsl') - call extend(s:clone_opt, ['-c', 'core.eol=lf', '-c', 'core.autocrlf=input']) - endif - - let s:submodule_opt = s:git_version_requirement(2, 8) ? ' --jobs='.threads : '' - - " Python version requirement (>= 2.7) - if python && !has('python3') && !ruby && !use_job && s:update.threads > 1 - redir => pyv - silent python import platform; print platform.python_version() - redir END - let python = s:version_requirement( - \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6]) - endif - - if (python || ruby) && s:update.threads > 1 - try - let imd = &imd - if s:mac_gui - set noimd - endif - if ruby - call s:update_ruby() - else - call s:update_python() - endif - catch - let lines = getline(4, '$') - let printed = {} - silent! 4,$d _ - for line in lines - let name = s:extract_name(line, '.', '') - if empty(name) || !has_key(printed, name) - call append('$', line) - if !empty(name) - let printed[name] = 1 - if line[0] == 'x' && index(s:update.errors, name) < 0 - call add(s:update.errors, name) - end - endif - endif - endfor - finally - let &imd = imd - call s:update_finish() - endtry - else - call s:update_vim() - while use_job && sync - sleep 100m - if s:update.fin - break - endif - endwhile - endif -endfunction - -function! s:log4(name, msg) - call setline(4, printf('- %s (%s)', a:msg, a:name)) - redraw -endfunction - -function! s:update_finish() - if exists('s:git_terminal_prompt') - let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt - endif - if s:switch_in() - call append(3, '- Updating ...') | 4 - for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))')) - let [pos, _] = s:logpos(name) - if !pos - continue - endif - if has_key(spec, 'commit') - call s:log4(name, 'Checking out '.spec.commit) - let out = s:checkout(spec) - elseif has_key(spec, 'tag') - let tag = spec.tag - if tag =~ '\*' - let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir)) - if !v:shell_error && !empty(tags) - let tag = tags[0] - call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag)) - call append(3, '') - endif - endif - call s:log4(name, 'Checking out '.tag) - let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir) - else - let branch = s:git_origin_branch(spec) - call s:log4(name, 'Merging origin/'.s:esc(branch)) - let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1' - \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir) - endif - if !v:shell_error && filereadable(spec.dir.'/.gitmodules') && - \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir)) - call s:log4(name, 'Updating submodules. This may take a while.') - let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir) - endif - let msg = s:format_message(v:shell_error ? 'x': '-', name, out) - if v:shell_error - call add(s:update.errors, name) - call s:regress_bar() - silent execute pos 'd _' - call append(4, msg) | 4 - elseif !empty(out) - call setline(pos, msg[0]) - endif - redraw - endfor - silent 4 d _ - try - call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")')) - catch - call s:warn('echom', v:exception) - call s:warn('echo', '') - return - endtry - call s:finish(s:update.pull) - call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.') - call s:switch_out('normal! gg') - endif -endfunction - -function! s:job_abort() - if (!s:nvim && !s:vim8) || !exists('s:jobs') - return - endif - - for [name, j] in items(s:jobs) - if s:nvim - silent! call jobstop(j.jobid) - elseif s:vim8 - silent! call job_stop(j.jobid) - endif - if j.new - call s:rm_rf(g:plugs[name].dir) - endif - endfor - let s:jobs = {} -endfunction - -function! s:last_non_empty_line(lines) - let len = len(a:lines) - for idx in range(len) - let line = a:lines[len-idx-1] - if !empty(line) - return line - endif - endfor - return '' -endfunction - -function! s:job_out_cb(self, data) abort - let self = a:self - let data = remove(self.lines, -1) . a:data - let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]') - call extend(self.lines, lines) - " To reduce the number of buffer updates - let self.tick = get(self, 'tick', -1) + 1 - if !self.running || self.tick % len(s:jobs) == 0 - let bullet = self.running ? (self.new ? '+' : '*') : (self.error ? 'x' : '-') - let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines) - call s:log(bullet, self.name, result) - endif -endfunction - -function! s:job_exit_cb(self, data) abort - let a:self.running = 0 - let a:self.error = a:data != 0 - call s:reap(a:self.name) - call s:tick() -endfunction - -function! s:job_cb(fn, job, ch, data) - if !s:plug_window_exists() " plug window closed - return s:job_abort() - endif - call call(a:fn, [a:job, a:data]) -endfunction - -function! s:nvim_cb(job_id, data, event) dict abort - return (a:event == 'stdout' || a:event == 'stderr') ? - \ s:job_cb('s:job_out_cb', self, 0, join(a:data, "\n")) : - \ s:job_cb('s:job_exit_cb', self, 0, a:data) -endfunction - -function! s:spawn(name, cmd, opts) - let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''], - \ 'new': get(a:opts, 'new', 0) } - let s:jobs[a:name] = job - - if s:nvim - if has_key(a:opts, 'dir') - let job.cwd = a:opts.dir - endif - let argv = a:cmd - call extend(job, { - \ 'on_stdout': function('s:nvim_cb'), - \ 'on_stderr': function('s:nvim_cb'), - \ 'on_exit': function('s:nvim_cb'), - \ }) - let jid = s:plug_call('jobstart', argv, job) - if jid > 0 - let job.jobid = jid - else - let job.running = 0 - let job.error = 1 - let job.lines = [jid < 0 ? argv[0].' is not executable' : - \ 'Invalid arguments (or job table is full)'] - endif - elseif s:vim8 - let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"script": 0})')) - if has_key(a:opts, 'dir') - let cmd = s:with_cd(cmd, a:opts.dir, 0) - endif - let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd] - let jid = job_start(s:is_win ? join(argv, ' ') : argv, { - \ 'out_cb': function('s:job_cb', ['s:job_out_cb', job]), - \ 'err_cb': function('s:job_cb', ['s:job_out_cb', job]), - \ 'exit_cb': function('s:job_cb', ['s:job_exit_cb', job]), - \ 'err_mode': 'raw', - \ 'out_mode': 'raw' - \}) - if job_status(jid) == 'run' - let job.jobid = jid - else - let job.running = 0 - let job.error = 1 - let job.lines = ['Failed to start job'] - endif - else - let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd])) - let job.error = v:shell_error != 0 - let job.running = 0 - endif -endfunction - -function! s:reap(name) - let job = s:jobs[a:name] - if job.error - call add(s:update.errors, a:name) - elseif get(job, 'new', 0) - let s:update.new[a:name] = 1 - endif - let s:update.bar .= job.error ? 'x' : '=' - - let bullet = job.error ? 'x' : '-' - let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines) - call s:log(bullet, a:name, empty(result) ? 'OK' : result) - call s:bar() - - call remove(s:jobs, a:name) -endfunction - -function! s:bar() - if s:switch_in() - let total = len(s:update.all) - call setline(1, (s:update.pull ? 'Updating' : 'Installing'). - \ ' plugins ('.len(s:update.bar).'/'.total.')') - call s:progress_bar(2, s:update.bar, total) - call s:switch_out() - endif -endfunction - -function! s:logpos(name) - let max = line('$') - for i in range(4, max > 4 ? max : 4) - if getline(i) =~# '^[-+x*] '.a:name.':' - for j in range(i + 1, max > 5 ? max : 5) - if getline(j) !~ '^ ' - return [i, j - 1] - endif - endfor - return [i, i] - endif - endfor - return [0, 0] -endfunction - -function! s:log(bullet, name, lines) - if s:switch_in() - let [b, e] = s:logpos(a:name) - if b > 0 - silent execute printf('%d,%d d _', b, e) - if b > winheight('.') - let b = 4 - endif - else - let b = 4 - endif - " FIXME For some reason, nomodifiable is set after :d in vim8 - setlocal modifiable - call append(b - 1, s:format_message(a:bullet, a:name, a:lines)) - call s:switch_out() - endif -endfunction - -function! s:update_vim() - let s:jobs = {} - - call s:bar() - call s:tick() -endfunction - -function! s:tick() - let pull = s:update.pull - let prog = s:progress_opt(s:nvim || s:vim8) -while 1 " Without TCO, Vim stack is bound to explode - if empty(s:update.todo) - if empty(s:jobs) && !s:update.fin - call s:update_finish() - let s:update.fin = 1 - endif - return - endif - - let name = keys(s:update.todo)[0] - let spec = remove(s:update.todo, name) - let new = empty(globpath(spec.dir, '.git', 1)) - - call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...') - redraw - - let has_tag = has_key(spec, 'tag') - if !new - let [error, _] = s:git_validate(spec, 0) - if empty(error) - if pull - let cmd = ['git', 'fetch'] - if has_tag && !empty(globpath(spec.dir, '.git/shallow')) - call extend(cmd, ['--depth', '99999999']) - endif - if !empty(prog) - call add(cmd, prog) - endif - call s:spawn(name, cmd, { 'dir': spec.dir }) - else - let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 } - endif - else - let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 } - endif - else - let cmd = ['git', 'clone'] - if !has_tag - call extend(cmd, s:clone_opt) - endif - if !empty(prog) - call add(cmd, prog) - endif - call s:spawn(name, extend(cmd, [spec.uri, s:trim(spec.dir)]), { 'new': 1 }) - endif - - if !s:jobs[name].running - call s:reap(name) - endif - if len(s:jobs) >= s:update.threads - break - endif -endwhile -endfunction - -function! s:update_python() -let py_exe = has('python') ? 'python' : 'python3' -execute py_exe "<< EOF" -import datetime -import functools -import os -try: - import queue -except ImportError: - import Queue as queue -import random -import re -import shutil -import signal -import subprocess -import tempfile -import threading as thr -import time -import traceback -import vim - -G_NVIM = vim.eval("has('nvim')") == '1' -G_PULL = vim.eval('s:update.pull') == '1' -G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1 -G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)')) -G_CLONE_OPT = ' '.join(vim.eval('s:clone_opt')) -G_PROGRESS = vim.eval('s:progress_opt(1)') -G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads')) -G_STOP = thr.Event() -G_IS_WIN = vim.eval('s:is_win') == '1' - -class PlugError(Exception): - def __init__(self, msg): - self.msg = msg -class CmdTimedOut(PlugError): - pass -class CmdFailed(PlugError): - pass -class InvalidURI(PlugError): - pass -class Action(object): - INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-'] - -class Buffer(object): - def __init__(self, lock, num_plugs, is_pull): - self.bar = '' - self.event = 'Updating' if is_pull else 'Installing' - self.lock = lock - self.maxy = int(vim.eval('winheight(".")')) - self.num_plugs = num_plugs - - def __where(self, name): - """ Find first line with name in current buffer. Return line num. """ - found, lnum = False, 0 - matcher = re.compile('^[-+x*] {0}:'.format(name)) - for line in vim.current.buffer: - if matcher.search(line) is not None: - found = True - break - lnum += 1 - - if not found: - lnum = -1 - return lnum - - def header(self): - curbuf = vim.current.buffer - curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs) - - num_spaces = self.num_plugs - len(self.bar) - curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ') - - with self.lock: - vim.command('normal! 2G') - vim.command('redraw') - - def write(self, action, name, lines): - first, rest = lines[0], lines[1:] - msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)] - msg.extend([' ' + line for line in rest]) - - try: - if action == Action.ERROR: - self.bar += 'x' - vim.command("call add(s:update.errors, '{0}')".format(name)) - elif action == Action.DONE: - self.bar += '=' - - curbuf = vim.current.buffer - lnum = self.__where(name) - if lnum != -1: # Found matching line num - del curbuf[lnum] - if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]): - lnum = 3 - else: - lnum = 3 - curbuf.append(msg, lnum) - - self.header() - except vim.error: - pass - -class Command(object): - CD = 'cd /d' if G_IS_WIN else 'cd' - - def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None): - self.cmd = cmd - if cmd_dir: - self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd) - self.timeout = timeout - self.callback = cb if cb else (lambda msg: None) - self.clean = clean if clean else (lambda: None) - self.proc = None - - @property - def alive(self): - """ Returns true only if command still running. """ - return self.proc and self.proc.poll() is None - - def execute(self, ntries=3): - """ Execute the command with ntries if CmdTimedOut. - Returns the output of the command if no Exception. - """ - attempt, finished, limit = 0, False, self.timeout - - while not finished: - try: - attempt += 1 - result = self.try_command() - finished = True - return result - except CmdTimedOut: - if attempt != ntries: - self.notify_retry() - self.timeout += limit - else: - raise - - def notify_retry(self): - """ Retry required for command, notify user. """ - for count in range(3, 0, -1): - if G_STOP.is_set(): - raise KeyboardInterrupt - msg = 'Timeout. Will retry in {0} second{1} ...'.format( - count, 's' if count != 1 else '') - self.callback([msg]) - time.sleep(1) - self.callback(['Retrying ...']) - - def try_command(self): - """ Execute a cmd & poll for callback. Returns list of output. - Raises CmdFailed -> return code for Popen isn't 0 - Raises CmdTimedOut -> command exceeded timeout without new output - """ - first_line = True - - try: - tfile = tempfile.NamedTemporaryFile(mode='w+b') - preexec_fn = not G_IS_WIN and os.setsid or None - self.proc = subprocess.Popen(self.cmd, stdout=tfile, - stderr=subprocess.STDOUT, - stdin=subprocess.PIPE, shell=True, - preexec_fn=preexec_fn) - thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,)) - thrd.start() - - thread_not_started = True - while thread_not_started: - try: - thrd.join(0.1) - thread_not_started = False - except RuntimeError: - pass - - while self.alive: - if G_STOP.is_set(): - raise KeyboardInterrupt - - if first_line or random.random() < G_LOG_PROB: - first_line = False - line = '' if G_IS_WIN else nonblock_read(tfile.name) - if line: - self.callback([line]) - - time_diff = time.time() - os.path.getmtime(tfile.name) - if time_diff > self.timeout: - raise CmdTimedOut(['Timeout!']) - - thrd.join(0.5) - - tfile.seek(0) - result = [line.decode('utf-8', 'replace').rstrip() for line in tfile] - - if self.proc.returncode != 0: - raise CmdFailed([''] + result) - - return result - except: - self.terminate() - raise - - def terminate(self): - """ Terminate process and cleanup. """ - if self.alive: - if G_IS_WIN: - os.kill(self.proc.pid, signal.SIGINT) - else: - os.killpg(self.proc.pid, signal.SIGTERM) - self.clean() - -class Plugin(object): - def __init__(self, name, args, buf_q, lock): - self.name = name - self.args = args - self.buf_q = buf_q - self.lock = lock - self.tag = args.get('tag', 0) - - def manage(self): - try: - if os.path.exists(self.args['dir']): - self.update() - else: - self.install() - with self.lock: - thread_vim_command("let s:update.new['{0}'] = 1".format(self.name)) - except PlugError as exc: - self.write(Action.ERROR, self.name, exc.msg) - except KeyboardInterrupt: - G_STOP.set() - self.write(Action.ERROR, self.name, ['Interrupted!']) - except: - # Any exception except those above print stack trace - msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip()) - self.write(Action.ERROR, self.name, msg.split('\n')) - raise - - def install(self): - target = self.args['dir'] - if target[-1] == '\\': - target = target[0:-1] - - def clean(target): - def _clean(): - try: - shutil.rmtree(target) - except OSError: - pass - return _clean - - self.write(Action.INSTALL, self.name, ['Installing ...']) - callback = functools.partial(self.write, Action.INSTALL, self.name) - cmd = 'git clone {0} {1} {2} {3} 2>&1'.format( - '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'], - esc(target)) - com = Command(cmd, None, G_TIMEOUT, callback, clean(target)) - result = com.execute(G_RETRIES) - self.write(Action.DONE, self.name, result[-1:]) - - def repo_uri(self): - cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url' - command = Command(cmd, self.args['dir'], G_TIMEOUT,) - result = command.execute(G_RETRIES) - return result[-1] - - def update(self): - actual_uri = self.repo_uri() - expect_uri = self.args['uri'] - regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$') - ma = regex.match(actual_uri) - mb = regex.match(expect_uri) - if ma is None or mb is None or ma.groups() != mb.groups(): - msg = ['', - 'Invalid URI: {0}'.format(actual_uri), - 'Expected {0}'.format(expect_uri), - 'PlugClean required.'] - raise InvalidURI(msg) - - if G_PULL: - self.write(Action.UPDATE, self.name, ['Updating ...']) - callback = functools.partial(self.write, Action.UPDATE, self.name) - fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else '' - cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS) - com = Command(cmd, self.args['dir'], G_TIMEOUT, callback) - result = com.execute(G_RETRIES) - self.write(Action.DONE, self.name, result[-1:]) - else: - self.write(Action.DONE, self.name, ['Already installed']) - - def write(self, action, name, msg): - self.buf_q.put((action, name, msg)) - -class PlugThread(thr.Thread): - def __init__(self, tname, args): - super(PlugThread, self).__init__() - self.tname = tname - self.args = args - - def run(self): - thr.current_thread().name = self.tname - buf_q, work_q, lock = self.args - - try: - while not G_STOP.is_set(): - name, args = work_q.get_nowait() - plug = Plugin(name, args, buf_q, lock) - plug.manage() - work_q.task_done() - except queue.Empty: - pass - -class RefreshThread(thr.Thread): - def __init__(self, lock): - super(RefreshThread, self).__init__() - self.lock = lock - self.running = True - - def run(self): - while self.running: - with self.lock: - thread_vim_command('noautocmd normal! a') - time.sleep(0.33) - - def stop(self): - self.running = False - -if G_NVIM: - def thread_vim_command(cmd): - vim.session.threadsafe_call(lambda: vim.command(cmd)) -else: - def thread_vim_command(cmd): - vim.command(cmd) - -def esc(name): - return '"' + name.replace('"', '\"') + '"' - -def nonblock_read(fname): - """ Read a file with nonblock flag. Return the last line. """ - fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK) - buf = os.read(fread, 100000).decode('utf-8', 'replace') - os.close(fread) - - line = buf.rstrip('\r\n') - left = max(line.rfind('\r'), line.rfind('\n')) - if left != -1: - left += 1 - line = line[left:] - - return line - -def main(): - thr.current_thread().name = 'main' - nthreads = int(vim.eval('s:update.threads')) - plugs = vim.eval('s:update.todo') - mac_gui = vim.eval('s:mac_gui') == '1' - - lock = thr.Lock() - buf = Buffer(lock, len(plugs), G_PULL) - buf_q, work_q = queue.Queue(), queue.Queue() - for work in plugs.items(): - work_q.put(work) - - start_cnt = thr.active_count() - for num in range(nthreads): - tname = 'PlugT-{0:02}'.format(num) - thread = PlugThread(tname, (buf_q, work_q, lock)) - thread.start() - if mac_gui: - rthread = RefreshThread(lock) - rthread.start() - - while not buf_q.empty() or thr.active_count() != start_cnt: - try: - action, name, msg = buf_q.get(True, 0.25) - buf.write(action, name, ['OK'] if not msg else msg) - buf_q.task_done() - except queue.Empty: - pass - except KeyboardInterrupt: - G_STOP.set() - - if mac_gui: - rthread.stop() - rthread.join() - -main() -EOF -endfunction - -function! s:update_ruby() - ruby << EOF - module PlugStream - SEP = ["\r", "\n", nil] - def get_line - buffer = '' - loop do - char = readchar rescue return - if SEP.include? char.chr - buffer << $/ - break - else - buffer << char - end - end - buffer - end - end unless defined?(PlugStream) - - def esc arg - %["#{arg.gsub('"', '\"')}"] - end - - def killall pid - pids = [pid] - if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM - pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil } - else - unless `which pgrep 2> /dev/null`.empty? - children = pids - until children.empty? - children = children.map { |pid| - `pgrep -P #{pid}`.lines.map { |l| l.chomp } - }.flatten - pids += children - end - end - pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil } - end - end - - def compare_git_uri a, b - regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$} - regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1) - end - - require 'thread' - require 'fileutils' - require 'timeout' - running = true - iswin = VIM::evaluate('s:is_win').to_i == 1 - pull = VIM::evaluate('s:update.pull').to_i == 1 - base = VIM::evaluate('g:plug_home') - all = VIM::evaluate('s:update.todo') - limit = VIM::evaluate('get(g:, "plug_timeout", 60)') - tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1 - nthr = VIM::evaluate('s:update.threads').to_i - maxy = VIM::evaluate('winheight(".")').to_i - vim7 = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/ - cd = iswin ? 'cd /d' : 'cd' - tot = VIM::evaluate('len(s:update.todo)') || 0 - bar = '' - skip = 'Already installed' - mtx = Mutex.new - take1 = proc { mtx.synchronize { running && all.shift } } - logh = proc { - cnt = bar.length - $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})" - $curbuf[2] = '[' + bar.ljust(tot) + ']' - VIM::command('normal! 2G') - VIM::command('redraw') - } - where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } } - log = proc { |name, result, type| - mtx.synchronize do - ing = ![true, false].include?(type) - bar += type ? '=' : 'x' unless ing - b = case type - when :install then '+' when :update then '*' - when true, nil then '-' else - VIM::command("call add(s:update.errors, '#{name}')") - 'x' - end - result = - if type || type.nil? - ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"] - elsif result =~ /^Interrupted|^Timeout/ - ["#{b} #{name}: #{result}"] - else - ["#{b} #{name}"] + result.lines.map { |l| " " << l } - end - if lnum = where.call(name) - $curbuf.delete lnum - lnum = 4 if ing && lnum > maxy - end - result.each_with_index do |line, offset| - $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp) - end - logh.call - end - } - bt = proc { |cmd, name, type, cleanup| - tried = timeout = 0 - begin - tried += 1 - timeout += limit - fd = nil - data = '' - if iswin - Timeout::timeout(timeout) do - tmp = VIM::evaluate('tempname()') - system("(#{cmd}) > #{tmp}") - data = File.read(tmp).chomp - File.unlink tmp rescue nil - end - else - fd = IO.popen(cmd).extend(PlugStream) - first_line = true - log_prob = 1.0 / nthr - while line = Timeout::timeout(timeout) { fd.get_line } - data << line - log.call name, line.chomp, type if name && (first_line || rand < log_prob) - first_line = false - end - fd.close - end - [$? == 0, data.chomp] - rescue Timeout::Error, Interrupt => e - if fd && !fd.closed? - killall fd.pid - fd.close - end - cleanup.call if cleanup - if e.is_a?(Timeout::Error) && tried < tries - 3.downto(1) do |countdown| - s = countdown > 1 ? 's' : '' - log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type - sleep 1 - end - log.call name, 'Retrying ...', type - retry - end - [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"] - end - } - main = Thread.current - threads = [] - watcher = Thread.new { - if vim7 - while VIM::evaluate('getchar(1)') - sleep 0.1 - end - else - require 'io/console' # >= Ruby 1.9 - nil until IO.console.getch == 3.chr - end - mtx.synchronize do - running = false - threads.each { |t| t.raise Interrupt } unless vim7 - end - threads.each { |t| t.join rescue nil } - main.kill - } - refresh = Thread.new { - while true - mtx.synchronize do - break unless running - VIM::command('noautocmd normal! a') - end - sleep 0.2 - end - } if VIM::evaluate('s:mac_gui') == 1 - - clone_opt = VIM::evaluate('s:clone_opt').join(' ') - progress = VIM::evaluate('s:progress_opt(1)') - nthr.times do - mtx.synchronize do - threads << Thread.new { - while pair = take1.call - name = pair.first - dir, uri, tag = pair.last.values_at *%w[dir uri tag] - exists = File.directory? dir - ok, result = - if exists - chdir = "#{cd} #{iswin ? dir : esc(dir)}" - ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil - current_uri = data.lines.to_a.last - if !ret - if data =~ /^Interrupted|^Timeout/ - [false, data] - else - [false, [data.chomp, "PlugClean required."].join($/)] - end - elsif !compare_git_uri(current_uri, uri) - [false, ["Invalid URI: #{current_uri}", - "Expected: #{uri}", - "PlugClean required."].join($/)] - else - if pull - log.call name, 'Updating ...', :update - fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : '' - bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil - else - [true, skip] - end - end - else - d = esc dir.sub(%r{[\\/]+$}, '') - log.call name, 'Installing ...', :install - bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc { - FileUtils.rm_rf dir - } - end - mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok - log.call name, result, ok - end - } if running - end - end - threads.each { |t| t.join rescue nil } - logh.call - refresh.kill if refresh - watcher.kill -EOF -endfunction - -function! s:shellesc_cmd(arg, script) - let escaped = substitute('"'.a:arg.'"', '[&|<>()@^!"]', '^&', 'g') - return substitute(escaped, '%', (a:script ? '%' : '^') . '&', 'g') -endfunction - -function! s:shellesc_ps1(arg) - return "'".substitute(escape(a:arg, '\"'), "'", "''", 'g')."'" -endfunction - -function! s:shellesc_sh(arg) - return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'" -endfunction - -" Escape the shell argument based on the shell. -" Vim and Neovim's shellescape() are insufficient. -" 1. shellslash determines whether to use single/double quotes. -" Double-quote escaping is fragile for cmd.exe. -" 2. It does not work for powershell. -" 3. It does not work for *sh shells if the command is executed -" via cmd.exe (ie. cmd.exe /c sh -c command command_args) -" 4. It does not support batchfile syntax. -" -" Accepts an optional dictionary with the following keys: -" - shell: same as Vim/Neovim 'shell' option. -" If unset, fallback to 'cmd.exe' on Windows or 'sh'. -" - script: If truthy and shell is cmd.exe, escape for batchfile syntax. -function! plug#shellescape(arg, ...) - if a:arg =~# '^[A-Za-z0-9_/:.-]\+$' - return a:arg - endif - let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {} - let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh') - let script = get(opts, 'script', 1) - if shell =~# 'cmd\(\.exe\)\?$' - return s:shellesc_cmd(a:arg, script) - elseif shell =~# 'powershell\(\.exe\)\?$' || shell =~# 'pwsh$' - return s:shellesc_ps1(a:arg) - endif - return s:shellesc_sh(a:arg) -endfunction - -function! s:glob_dir(path) - return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)') -endfunction - -function! s:progress_bar(line, bar, total) - call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']') -endfunction - -function! s:compare_git_uri(a, b) - " See `git help clone' - " https:// [user@] github.com[:port] / junegunn/vim-plug [.git] - " [git@] github.com[:port] : junegunn/vim-plug [.git] - " file:// / junegunn/vim-plug [/] - " / junegunn/vim-plug [/] - let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$' - let ma = matchlist(a:a, pat) - let mb = matchlist(a:b, pat) - return ma[1:2] ==# mb[1:2] -endfunction - -function! s:format_message(bullet, name, message) - if a:bullet != 'x' - return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))] - else - let lines = map(s:lines(a:message), '" ".v:val') - return extend([printf('x %s:', a:name)], lines) - endif -endfunction - -function! s:with_cd(cmd, dir, ...) - let script = a:0 > 0 ? a:1 : 1 - return printf('cd%s %s && %s', s:is_win ? ' /d' : '', plug#shellescape(a:dir, {'script': script}), a:cmd) -endfunction - -function! s:system(cmd, ...) - let batchfile = '' - try - let [sh, shellcmdflag, shrd] = s:chsh(1) - if type(a:cmd) == s:TYPE.list - " Neovim's system() supports list argument to bypass the shell - " but it cannot set the working directory for the command. - " Assume that the command does not rely on the shell. - if has('nvim') && a:0 == 0 - return system(a:cmd) - endif - let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})')) - if &shell =~# 'powershell\(\.exe\)\?$' - let cmd = '& ' . cmd - endif - else - let cmd = a:cmd - endif - if a:0 > 0 - let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list) - endif - if s:is_win && type(a:cmd) != s:TYPE.list - let [batchfile, cmd] = s:batchfile(cmd) - endif - return system(cmd) - finally - let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] - if s:is_win && filereadable(batchfile) - call delete(batchfile) - endif - endtry -endfunction - -function! s:system_chomp(...) - let ret = call('s:system', a:000) - return v:shell_error ? '' : substitute(ret, '\n$', '', '') -endfunction - -function! s:git_validate(spec, check_branch) - let err = '' - if isdirectory(a:spec.dir) - let result = [s:git_local_branch(a:spec.dir), s:git_origin_url(a:spec.dir)] - let remote = result[-1] - if empty(remote) - let err = join([remote, 'PlugClean required.'], "\n") - elseif !s:compare_git_uri(remote, a:spec.uri) - let err = join(['Invalid URI: '.remote, - \ 'Expected: '.a:spec.uri, - \ 'PlugClean required.'], "\n") - elseif a:check_branch && has_key(a:spec, 'commit') - let sha = s:git_revision(a:spec.dir) - if empty(sha) - let err = join(add(result, 'PlugClean required.'), "\n") - elseif !s:hash_match(sha, a:spec.commit) - let err = join([printf('Invalid HEAD (expected: %s, actual: %s)', - \ a:spec.commit[:6], sha[:6]), - \ 'PlugUpdate required.'], "\n") - endif - elseif a:check_branch - let current_branch = result[0] - " Check tag - let origin_branch = s:git_origin_branch(a:spec) - if has_key(a:spec, 'tag') - let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir) - if a:spec.tag !=# tag && a:spec.tag !~ '\*' - let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.', - \ (empty(tag) ? 'N/A' : tag), a:spec.tag) - endif - " Check branch - elseif origin_branch !=# current_branch - let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.', - \ current_branch, origin_branch) - endif - if empty(err) - let [ahead, behind] = split(s:lastline(s:system([ - \ 'git', 'rev-list', '--count', '--left-right', - \ printf('HEAD...origin/%s', origin_branch) - \ ], a:spec.dir)), '\t') - if !v:shell_error && ahead - if behind - " Only mention PlugClean if diverged, otherwise it's likely to be - " pushable (and probably not that messed up). - let err = printf( - \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n" - \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', origin_branch, ahead, behind) - else - let err = printf("Ahead of origin/%s by %d commit(s).\n" - \ .'Cannot update until local changes are pushed.', - \ origin_branch, ahead) - endif - endif - endif - endif - else - let err = 'Not found' - endif - return [err, err =~# 'PlugClean'] -endfunction - -function! s:rm_rf(dir) - if isdirectory(a:dir) - return s:system(s:is_win - \ ? 'rmdir /S /Q '.plug#shellescape(a:dir) - \ : ['rm', '-rf', a:dir]) - endif -endfunction - -function! s:clean(force) - call s:prepare() - call append(0, 'Searching for invalid plugins in '.g:plug_home) - call append(1, '') - - " List of valid directories - let dirs = [] - let errs = {} - let [cnt, total] = [0, len(g:plugs)] - for [name, spec] in items(g:plugs) - if !s:is_managed(name) - call add(dirs, spec.dir) - else - let [err, clean] = s:git_validate(spec, 1) - if clean - let errs[spec.dir] = s:lines(err)[0] - else - call add(dirs, spec.dir) - endif - endif - let cnt += 1 - call s:progress_bar(2, repeat('=', cnt), total) - normal! 2G - redraw - endfor - - let allowed = {} - for dir in dirs - let allowed[s:dirpath(s:plug_fnamemodify(dir, ':h:h'))] = 1 - let allowed[dir] = 1 - for child in s:glob_dir(dir) - let allowed[child] = 1 - endfor - endfor - - let todo = [] - let found = sort(s:glob_dir(g:plug_home)) - while !empty(found) - let f = remove(found, 0) - if !has_key(allowed, f) && isdirectory(f) - call add(todo, f) - call append(line('$'), '- ' . f) - if has_key(errs, f) - call append(line('$'), ' ' . errs[f]) - endif - let found = filter(found, 'stridx(v:val, f) != 0') - end - endwhile - - 4 - redraw - if empty(todo) - call append(line('$'), 'Already clean.') - else - let s:clean_count = 0 - call append(3, ['Directories to delete:', '']) - redraw! - if a:force || s:ask_no_interrupt('Delete all directories?') - call s:delete([6, line('$')], 1) - else - call setline(4, 'Cancelled.') - nnoremap d :set opfunc=delete_opg@ - nmap dd d_ - xnoremap d :call delete_op(visualmode(), 1) - echo 'Delete the lines (d{motion}) to delete the corresponding directories' - endif - endif - 4 - setlocal nomodifiable -endfunction - -function! s:delete_op(type, ...) - call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0) -endfunction - -function! s:delete(range, force) - let [l1, l2] = a:range - let force = a:force - let err_count = 0 - while l1 <= l2 - let line = getline(l1) - if line =~ '^- ' && isdirectory(line[2:]) - execute l1 - redraw! - let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1) - let force = force || answer > 1 - if answer - let err = s:rm_rf(line[2:]) - setlocal modifiable - if empty(err) - call setline(l1, '~'.line[1:]) - let s:clean_count += 1 - else - delete _ - call append(l1 - 1, s:format_message('x', line[1:], err)) - let l2 += len(s:lines(err)) - let err_count += 1 - endif - let msg = printf('Removed %d directories.', s:clean_count) - if err_count > 0 - let msg .= printf(' Failed to remove %d directories.', err_count) - endif - call setline(4, msg) - setlocal nomodifiable - endif - endif - let l1 += 1 - endwhile -endfunction - -function! s:upgrade() - echo 'Downloading the latest version of vim-plug' - redraw - let tmp = s:plug_tempname() - let new = tmp . '/plug.vim' - - try - let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp]) - if v:shell_error - return s:err('Error upgrading vim-plug: '. out) - endif - - if readfile(s:me) ==# readfile(new) - echo 'vim-plug is already up-to-date' - return 0 - else - call rename(s:me, s:me . '.old') - call rename(new, s:me) - unlet g:loaded_plug - echo 'vim-plug has been upgraded' - return 1 - endif - finally - silent! call s:rm_rf(tmp) - endtry -endfunction - -function! s:upgrade_specs() - for spec in values(g:plugs) - let spec.frozen = get(spec, 'frozen', 0) - endfor -endfunction - -function! s:status() - call s:prepare() - call append(0, 'Checking plugins') - call append(1, '') - - let ecnt = 0 - let unloaded = 0 - let [cnt, total] = [0, len(g:plugs)] - for [name, spec] in items(g:plugs) - let is_dir = isdirectory(spec.dir) - if has_key(spec, 'uri') - if is_dir - let [err, _] = s:git_validate(spec, 1) - let [valid, msg] = [empty(err), empty(err) ? 'OK' : err] - else - let [valid, msg] = [0, 'Not found. Try PlugInstall.'] - endif - else - if is_dir - let [valid, msg] = [1, 'OK'] - else - let [valid, msg] = [0, 'Not found.'] - endif - endif - let cnt += 1 - let ecnt += !valid - " `s:loaded` entry can be missing if PlugUpgraded - if is_dir && get(s:loaded, name, -1) == 0 - let unloaded = 1 - let msg .= ' (not loaded)' - endif - call s:progress_bar(2, repeat('=', cnt), total) - call append(3, s:format_message(valid ? '-' : 'x', name, msg)) - normal! 2G - redraw - endfor - call setline(1, 'Finished. '.ecnt.' error(s).') - normal! gg - setlocal nomodifiable - if unloaded - echo "Press 'L' on each line to load plugin, or 'U' to update" - nnoremap L :call status_load(line('.')) - xnoremap L :call status_load(line('.')) - end -endfunction - -function! s:extract_name(str, prefix, suffix) - return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$') -endfunction - -function! s:status_load(lnum) - let line = getline(a:lnum) - let name = s:extract_name(line, '-', '(not loaded)') - if !empty(name) - call plug#load(name) - setlocal modifiable - call setline(a:lnum, substitute(line, ' (not loaded)$', '', '')) - setlocal nomodifiable - endif -endfunction - -function! s:status_update() range - let lines = getline(a:firstline, a:lastline) - let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)') - if !empty(names) - echo - execute 'PlugUpdate' join(names) - endif -endfunction - -function! s:is_preview_window_open() - silent! wincmd P - if &previewwindow - wincmd p - return 1 - endif -endfunction - -function! s:find_name(lnum) - for lnum in reverse(range(1, a:lnum)) - let line = getline(lnum) - if empty(line) - return '' - endif - let name = s:extract_name(line, '-', '') - if !empty(name) - return name - endif - endfor - return '' -endfunction - -function! s:preview_commit() - if b:plug_preview < 0 - let b:plug_preview = !s:is_preview_window_open() - endif - - let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7,9}') - if empty(sha) - return - endif - - let name = s:find_name(line('.')) - if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir) - return - endif - - if exists('g:plug_pwindow') && !s:is_preview_window_open() - execute g:plug_pwindow - execute 'e' sha - else - execute 'pedit' sha - wincmd P - endif - setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable - let batchfile = '' - try - let [sh, shellcmdflag, shrd] = s:chsh(1) - let cmd = 'cd '.plug#shellescape(g:plugs[name].dir).' && git show --no-color --pretty=medium '.sha - if s:is_win - let [batchfile, cmd] = s:batchfile(cmd) - endif - execute 'silent %!' cmd - finally - let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] - if s:is_win && filereadable(batchfile) - call delete(batchfile) - endif - endtry - setlocal nomodifiable - nnoremap q :q - wincmd p -endfunction - -function! s:section(flags) - call search('\(^[x-] \)\@<=[^:]\+:', a:flags) -endfunction - -function! s:format_git_log(line) - let indent = ' ' - let tokens = split(a:line, nr2char(1)) - if len(tokens) != 5 - return indent.substitute(a:line, '\s*$', '', '') - endif - let [graph, sha, refs, subject, date] = tokens - let tag = matchstr(refs, 'tag: [^,)]\+') - let tag = empty(tag) ? ' ' : ' ('.tag.') ' - return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date) -endfunction - -function! s:append_ul(lnum, text) - call append(a:lnum, ['', a:text, repeat('-', len(a:text))]) -endfunction - -function! s:diff() - call s:prepare() - call append(0, ['Collecting changes ...', '']) - let cnts = [0, 0] - let bar = '' - let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)') - call s:progress_bar(2, bar, len(total)) - for origin in [1, 0] - let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))')))) - if empty(plugs) - continue - endif - call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:') - for [k, v] in plugs - let branch = s:git_origin_branch(v) - if len(branch) - let range = origin ? '..origin/'.branch : 'HEAD@{1}..' - let cmd = ['git', 'log', '--graph', '--color=never'] - if s:git_version_requirement(2, 10, 0) - call add(cmd, '--no-show-signature') - endif - call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range]) - if has_key(v, 'rtp') - call extend(cmd, ['--', v.rtp]) - endif - let diff = s:system_chomp(cmd, v.dir) - if !empty(diff) - let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' - call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) - let cnts[origin] += 1 - endif - endif - let bar .= '=' - call s:progress_bar(2, bar, len(total)) - normal! 2G - redraw - endfor - if !cnts[origin] - call append(5, ['', 'N/A']) - endif - endfor - call setline(1, printf('%d plugin(s) updated.', cnts[0]) - \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : '')) - - if cnts[0] || cnts[1] - nnoremap (plug-preview) :silent! call preview_commit() - if empty(maparg("\", 'n')) - nmap (plug-preview) - endif - if empty(maparg('o', 'n')) - nmap o (plug-preview) - endif - endif - if cnts[0] - nnoremap X :call revert() - echo "Press 'X' on each block to revert the update" - endif - normal! gg - setlocal nomodifiable -endfunction - -function! s:revert() - if search('^Pending updates', 'bnW') - return - endif - - let name = s:find_name(line('.')) - if empty(name) || !has_key(g:plugs, name) || - \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y' - return - endif - - call s:system('git reset --hard HEAD@{1} && git checkout '.plug#shellescape(g:plugs[name].branch).' --', g:plugs[name].dir) - setlocal modifiable - normal! "_dap - setlocal nomodifiable - echo 'Reverted' -endfunction - -function! s:snapshot(force, ...) abort - call s:prepare() - setf vim - call append(0, ['" Generated by vim-plug', - \ '" '.strftime("%c"), - \ '" :source this file in vim to restore the snapshot', - \ '" or execute: vim -S snapshot.vim', - \ '', '', 'PlugUpdate!']) - 1 - let anchor = line('$') - 3 - let names = sort(keys(filter(copy(g:plugs), - \'has_key(v:val, "uri") && !has_key(v:val, "commit") && isdirectory(v:val.dir)'))) - for name in reverse(names) - let sha = s:git_revision(g:plugs[name].dir) - if !empty(sha) - call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha)) - redraw - endif - endfor - - if a:0 > 0 - let fn = s:plug_expand(a:1) - if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?')) - return - endif - call writefile(getline(1, '$'), fn) - echo 'Saved as '.a:1 - silent execute 'e' s:esc(fn) - setf vim - endif -endfunction - -function! s:split_rtp() - return split(&rtp, '\\\@ -" Based on: xoria256.vim 1.1 by Dmitriy Y. Zotikov (xio) -" -" Should work in recent 256 color terminals. 88-color terms like urxvt are -" unsupported. -" -" Don't forget to install 'ncurses-term' and set TERM to xterm-256color or -" similar value. -" -" Color numbers (0-255) see: -" http://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html - - - -" Bla-bla ---------------------------------------------------------------------- - -if &t_Co != 256 && ! has("gui_running") - echomsg "" - echomsg "err: please use GUI or a 256-color terminal (so that t_Co=256 can be set)" - echomsg "" - finish -endif - -set background=dark - -hi clear - -if exists("syntax_on") - syntax reset -endif - -let colors_name = "burnttoast256" - - -" The real part ---------------------------------------------------------------- - -"" General colors -hi Normal ctermfg=252 guifg=#d0d0d0 ctermbg=16 guibg=#000000 cterm=none gui=none -hi ColorColumn ctermbg=233 guibg=#121212 -hi CursorColumn ctermbg=238 guibg=#444444 -hi Cursor ctermbg=214 guibg=#ffaf00 -hi CursorLine cterm=none gui=none -hi CursorLineNr ctermfg=7 guifg=#c0c0c0 ctermbg=233 guibg=#121212 cterm=bold gui=bold -hi FoldColumn ctermfg=248 guifg=#a8a8a8 ctermbg=bg guibg=bg -hi Folded ctermfg=255 guifg=#eeeeee ctermbg=60 guibg=#5f5f87 -hi IncSearch ctermfg=0 guifg=#000000 ctermbg=223 guibg=#ffd7af cterm=none gui=none -hi LineNr ctermfg=8 guifg=#808080 ctermbg=233 guibg=#121212 -hi NonText ctermfg=237 guifg=#3a3a3a -hi Pmenu ctermfg=15 guifg=#ffffff ctermbg=234 guibg=#1c1c1c -hi PmenuSbar ctermbg=243 guibg=#767676 -hi PmenuSel ctermfg=146 guifg=#afafd7 ctermbg=232 guibg=#080808 cterm=bold gui=bold -hi PmenuThumb ctermbg=252 guibg=#d0d0d0 -hi Search ctermfg=0 guifg=#000000 ctermbg=149 guibg=#afd75f -hi SignColumn ctermfg=248 guifg=#a8a8a8 -hi SpecialKey ctermfg=237 guifg=#3a3a3a -hi StatusLine ctermbg=239 guibg=#4e4e4e cterm=bold gui=bold -hi StatusLineNC ctermbg=237 guibg=#3a3a3a cterm=none gui=none -hi TabLine ctermfg=fg guifg=fg ctermbg=242 guibg=#6c6c6c cterm=underline gui=underline -hi TabLineFill ctermfg=fg guifg=fg ctermbg=242 guibg=#6c6c6c cterm=underline gui=underline -hi VertSplit ctermfg=237 guifg=#3a3a3a ctermbg=237 guibg=#3a3a3a cterm=none gui=none -hi Visual ctermfg=24 guifg=#005f87 ctermbg=153 guibg=#afd7ff -hi VIsualNOS ctermfg=24 guifg=#005f87 ctermbg=153 guibg=#afd7ff cterm=none gui=none -hi WildMenu ctermfg=0 guifg=#000000 ctermbg=184 guibg=#d7d700 cterm=bold gui=bold - -"" Syntax highlighting -hi Comment ctermfg=36 guifg=#00af87 -hi Constant ctermfg=222 guifg=#ffd787 -hi Error ctermfg=9 guifg=#ff0000 ctermbg=52 guibg=#5f0000 cterm=none gui=none -hi ErrorMsg ctermfg=9 guifg=#ff0000 ctermbg=52 guibg=#5f0000 -hi Function ctermfg=134 guifg=#af5fd7 -hi Identifier ctermfg=134 guifg=#af5fd7 cterm=none gui=none -hi Ignore ctermfg=238 guifg=#444444 -hi MatchParen ctermfg=188 guifg=#d7d7d7 ctermbg=68 guibg=#5f87d7 cterm=bold gui=bold -hi Number ctermfg=180 guifg=#d7af87 -hi PreProc ctermfg=150 guifg=#afd787 -hi Special ctermfg=132 guifg=#af5f87 -hi Statement ctermfg=75 guifg=#5fafff cterm=none gui=none -hi String ctermfg=217 guifg=#ffafaf -hi Todo ctermfg=0 guifg=#000000 ctermbg=36 guibg=#00af87 -hi Type ctermfg=146 guifg=#afafd7 cterm=none gui=none -hi Underlined ctermfg=39 guifg=#00afff cterm=underline gui=underline - -"" Python highlighting -hi pythonFunctionCall ctermfg=210 guifg=#ff8787 -"hi pythonStrFormatting Special -"hi pythonStrFormat Special -"hi pythonStrTemplate Special - -"" Special -""" .diff -hi diffAdded ctermfg=150 guifg=#afd787 -hi diffRemoved ctermfg=174 guifg=#d78787 -""" vimdiff -hi DiffAdd ctermbg=22 guibg=#005f00 -hi DiffDelete ctermfg=9 guifg=#ff0000 ctermbg=52 guibg=#5f0000 cterm=none gui=none -hi DiffChange ctermbg=235 guibg=#262626 cterm=none gui=none -hi DiffText ctermbg=17 guibg=#00005f cterm=none gui=none - -"" To highlight lines that are too long -hi OverLength ctermbg=130 guibg=#af5f00 - -"" Spelling and compiling errors -hi SpellBad ctermbg=52 guibg=#5f0000 - -"" Colors for unit testing. -hi RedBar ctermbg=52 guibg=#5f0000 -hi GreenBar ctermbg=22 guibg=#005f00 - -" For indentation -hi IndentGuidesOdd ctermbg=235 guibg=#262626 ctermfg=237 guifg=#3a3a3a -hi IndentGuidesEven ctermbg=233 guibg=#121212 ctermfg=237 guifg=#3a3a3a - diff --git a/stow/vim/dot-vim/colors/nord.vim b/stow/vim/dot-vim/colors/nord.vim deleted file mode 100644 index 6b00afb..0000000 --- a/stow/vim/dot-vim/colors/nord.vim +++ /dev/null @@ -1,764 +0,0 @@ -" Copyright (C) 2016-present Arctic Ice Studio -" Copyright (C) 2016-present Sven Greb - -" Project: Nord Vim -" Repository: https://github.com/arcticicestudio/nord-vim -" License: MIT - -if version > 580 - hi clear - if exists("syntax_on") - syntax reset - endif -endif - -let g:colors_name = "nord" -let s:nord_vim_version="0.15.0" -set background=dark - -let s:nord0_gui = "#2E3440" -let s:nord1_gui = "#3B4252" -let s:nord2_gui = "#434C5E" -let s:nord3_gui = "#4C566A" -let s:nord3_gui_bright = "#616E88" -let s:nord4_gui = "#D8DEE9" -let s:nord5_gui = "#E5E9F0" -let s:nord6_gui = "#ECEFF4" -let s:nord7_gui = "#8FBCBB" -let s:nord8_gui = "#88C0D0" -let s:nord9_gui = "#81A1C1" -let s:nord10_gui = "#5E81AC" -let s:nord11_gui = "#BF616A" -let s:nord12_gui = "#D08770" -let s:nord13_gui = "#EBCB8B" -let s:nord14_gui = "#A3BE8C" -let s:nord15_gui = "#B48EAD" - -let s:nord1_term = "0" -let s:nord3_term = "8" -let s:nord5_term = "7" -let s:nord6_term = "15" -let s:nord7_term = "14" -let s:nord8_term = "6" -let s:nord9_term = "4" -let s:nord10_term = "12" -let s:nord11_term = "1" -let s:nord12_term = "11" -let s:nord13_term = "3" -let s:nord14_term = "2" -let s:nord15_term = "5" - -let s:nord3_gui_brightened = [ - \ s:nord3_gui, - \ "#4e586d", - \ "#505b70", - \ "#525d73", - \ "#556076", - \ "#576279", - \ "#59647c", - \ "#5b677f", - \ "#5d6982", - \ "#5f6c85", - \ "#616e88", - \ "#63718b", - \ "#66738e", - \ "#687591", - \ "#6a7894", - \ "#6d7a96", - \ "#6f7d98", - \ "#72809a", - \ "#75829c", - \ "#78859e", - \ "#7b88a1", -\ ] - -if !exists("g:nord_bold") - let g:nord_bold = 1 -endif - -let s:bold = "bold," -if g:nord_bold == 0 - let s:bold = "" -endif - -if !exists("g:nord_italic") - if has("gui_running") || $TERM_ITALICS == "true" - let g:nord_italic = 1 - else - let g:nord_italic = 0 - endif -endif - -let s:italic = "italic," -if g:nord_italic == 0 - let s:italic = "" -endif - -let s:underline = "underline," -if ! get(g:, "nord_underline", 1) - let s:underline = "NONE," -endif - -let s:italicize_comments = "" -if exists("g:nord_italic_comments") - if g:nord_italic_comments == 1 - let s:italicize_comments = s:italic - endif -endif - -if !exists('g:nord_uniform_status_lines') - let g:nord_uniform_status_lines = 0 -endif - -function! s:logWarning(msg) - echohl WarningMsg - echomsg 'nord: warning: ' . a:msg - echohl None -endfunction - -if exists("g:nord_comment_brightness") - call s:logWarning('Variable g:nord_comment_brightness has been deprecated and will be removed in version 1.0.0!' . - \' The comment color brightness has been increased by 10% by default.' . - \' Please see https://github.com/arcticicestudio/nord-vim/issues/145 for more details.') - let g:nord_comment_brightness = 10 -endif - -if !exists("g:nord_uniform_diff_background") - let g:nord_uniform_diff_background = 0 -endif - -if !exists("g:nord_cursor_line_number_background") - let g:nord_cursor_line_number_background = 0 -endif - -if !exists("g:nord_bold_vertical_split_line") - let g:nord_bold_vertical_split_line = 0 -endif - -function! s:hi(group, guifg, guibg, ctermfg, ctermbg, attr, guisp) - if a:guifg != "" - exec "hi " . a:group . " guifg=" . a:guifg - endif - if a:guibg != "" - exec "hi " . a:group . " guibg=" . a:guibg - endif - if a:ctermfg != "" - exec "hi " . a:group . " ctermfg=" . a:ctermfg - endif - if a:ctermbg != "" - exec "hi " . a:group . " ctermbg=" . a:ctermbg - endif - if a:attr != "" - exec "hi " . a:group . " gui=" . a:attr . " cterm=" . substitute(a:attr, "undercurl", s:underline, "") - endif - if a:guisp != "" - exec "hi " . a:group . " guisp=" . a:guisp - endif -endfunction - -"+---------------+ -"+ UI Components + -"+---------------+ -"+--- Attributes ---+ -call s:hi("Bold", "", "", "", "", s:bold, "") -call s:hi("Italic", "", "", "", "", s:italic, "") -call s:hi("Underline", "", "", "", "", s:underline, "") - -"+--- Editor ---+ -call s:hi("ColorColumn", "", s:nord1_gui, "NONE", s:nord1_term, "", "") -call s:hi("Cursor", s:nord0_gui, s:nord4_gui, "", "NONE", "", "") -call s:hi("CursorLine", "", s:nord1_gui, "NONE", s:nord1_term, "NONE", "") -call s:hi("Error", s:nord4_gui, s:nord11_gui, "", s:nord11_term, "", "") -call s:hi("iCursor", s:nord0_gui, s:nord4_gui, "", "NONE", "", "") -call s:hi("LineNr", s:nord3_gui, "NONE", s:nord3_term, "NONE", "", "") -call s:hi("MatchParen", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, "", "") -call s:hi("NonText", s:nord2_gui, "", s:nord3_term, "", "", "") -call s:hi("Normal", s:nord4_gui, s:nord0_gui, "NONE", "NONE", "", "") -call s:hi("PMenu", s:nord4_gui, s:nord2_gui, "NONE", s:nord1_term, "NONE", "") -call s:hi("PmenuSbar", s:nord4_gui, s:nord2_gui, "NONE", s:nord1_term, "", "") -call s:hi("PMenuSel", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, "", "") -call s:hi("PmenuThumb", s:nord8_gui, s:nord3_gui, "NONE", s:nord3_term, "", "") -call s:hi("SpecialKey", s:nord3_gui, "", s:nord3_term, "", "", "") -call s:hi("SpellBad", s:nord11_gui, s:nord0_gui, s:nord11_term, "NONE", "undercurl", s:nord11_gui) -call s:hi("SpellCap", s:nord13_gui, s:nord0_gui, s:nord13_term, "NONE", "undercurl", s:nord13_gui) -call s:hi("SpellLocal", s:nord5_gui, s:nord0_gui, s:nord5_term, "NONE", "undercurl", s:nord5_gui) -call s:hi("SpellRare", s:nord6_gui, s:nord0_gui, s:nord6_term, "NONE", "undercurl", s:nord6_gui) -call s:hi("Visual", "", s:nord2_gui, "", s:nord1_term, "", "") -call s:hi("VisualNOS", "", s:nord2_gui, "", s:nord1_term, "", "") -"+- Neovim Support -+ -call s:hi("healthError", s:nord11_gui, s:nord1_gui, s:nord11_term, s:nord1_term, "", "") -call s:hi("healthSuccess", s:nord14_gui, s:nord1_gui, s:nord14_term, s:nord1_term, "", "") -call s:hi("healthWarning", s:nord13_gui, s:nord1_gui, s:nord13_term, s:nord1_term, "", "") -call s:hi("TermCursorNC", "", s:nord1_gui, "", s:nord1_term, "", "") - -"+- Vim 8 Terminal Colors -+ -if has('terminal') - let g:terminal_ansi_colors = [s:nord1_gui, s:nord11_gui, s:nord14_gui, s:nord13_gui, s:nord9_gui, s:nord15_gui, s:nord8_gui, s:nord5_gui, s:nord3_gui, s:nord11_gui, s:nord14_gui, s:nord13_gui, s:nord9_gui, s:nord15_gui, s:nord7_gui, s:nord6_gui] -endif - -"+- Neovim Terminal Colors -+ -if has('nvim') - let g:terminal_color_0 = s:nord1_gui - let g:terminal_color_1 = s:nord11_gui - let g:terminal_color_2 = s:nord14_gui - let g:terminal_color_3 = s:nord13_gui - let g:terminal_color_4 = s:nord9_gui - let g:terminal_color_5 = s:nord15_gui - let g:terminal_color_6 = s:nord8_gui - let g:terminal_color_7 = s:nord5_gui - let g:terminal_color_8 = s:nord3_gui - let g:terminal_color_9 = s:nord11_gui - let g:terminal_color_10 = s:nord14_gui - let g:terminal_color_11 = s:nord13_gui - let g:terminal_color_12 = s:nord9_gui - let g:terminal_color_13 = s:nord15_gui - let g:terminal_color_14 = s:nord7_gui - let g:terminal_color_15 = s:nord6_gui -endif - -"+--- Gutter ---+ -call s:hi("CursorColumn", "", s:nord1_gui, "NONE", s:nord1_term, "", "") -if g:nord_cursor_line_number_background == 0 - call s:hi("CursorLineNr", s:nord4_gui, "", "NONE", "", "NONE", "") -else - call s:hi("CursorLineNr", s:nord4_gui, s:nord1_gui, "NONE", s:nord1_term, "NONE", "") -endif -call s:hi("Folded", s:nord3_gui, s:nord1_gui, s:nord3_term, s:nord1_term, s:bold, "") -call s:hi("FoldColumn", s:nord3_gui, s:nord0_gui, s:nord3_term, "NONE", "", "") -call s:hi("SignColumn", s:nord1_gui, s:nord0_gui, s:nord1_term, "NONE", "", "") - -"+--- Navigation ---+ -call s:hi("Directory", s:nord8_gui, "", s:nord8_term, "NONE", "", "") - -"+--- Prompt/Status ---+ -call s:hi("EndOfBuffer", s:nord1_gui, "", s:nord1_term, "NONE", "", "") -call s:hi("ErrorMsg", s:nord4_gui, s:nord11_gui, "NONE", s:nord11_term, "", "") -call s:hi("ModeMsg", s:nord4_gui, "", "", "", "", "") -call s:hi("MoreMsg", s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("Question", s:nord4_gui, "", "NONE", "", "", "") -if g:nord_uniform_status_lines == 0 - call s:hi("StatusLine", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, "NONE", "") - call s:hi("StatusLineNC", s:nord4_gui, s:nord1_gui, "NONE", s:nord1_term, "NONE", "") - call s:hi("StatusLineTerm", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, "NONE", "") - call s:hi("StatusLineTermNC", s:nord4_gui, s:nord1_gui, "NONE", s:nord1_term, "NONE", "") -else - call s:hi("StatusLine", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, "NONE", "") - call s:hi("StatusLineNC", s:nord4_gui, s:nord3_gui, "NONE", s:nord3_term, "NONE", "") - call s:hi("StatusLineTerm", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, "NONE", "") - call s:hi("StatusLineTermNC", s:nord4_gui, s:nord3_gui, "NONE", s:nord3_term, "NONE", "") -endif -call s:hi("WarningMsg", s:nord0_gui, s:nord13_gui, s:nord1_term, s:nord13_term, "", "") -call s:hi("WildMenu", s:nord8_gui, s:nord1_gui, s:nord8_term, s:nord1_term, "", "") - -"+--- Search ---+ -call s:hi("IncSearch", s:nord6_gui, s:nord10_gui, s:nord6_term, s:nord10_term, s:underline, "") -call s:hi("Search", s:nord1_gui, s:nord8_gui, s:nord1_term, s:nord8_term, "NONE", "") - -"+--- Tabs ---+ -call s:hi("TabLine", s:nord4_gui, s:nord1_gui, "NONE", s:nord1_term, "NONE", "") -call s:hi("TabLineFill", s:nord4_gui, s:nord1_gui, "NONE", s:nord1_term, "NONE", "") -call s:hi("TabLineSel", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, "NONE", "") - -"+--- Window ---+ -call s:hi("Title", s:nord4_gui, "", "NONE", "", "NONE", "") - -if g:nord_bold_vertical_split_line == 0 - call s:hi("VertSplit", s:nord2_gui, s:nord0_gui, s:nord3_term, "NONE", "NONE", "") -else - call s:hi("VertSplit", s:nord2_gui, s:nord1_gui, s:nord3_term, s:nord1_term, "NONE", "") -endif - -"+----------------------+ -"+ Language Base Groups + -"+----------------------+ -call s:hi("Boolean", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("Character", s:nord14_gui, "", s:nord14_term, "", "", "") -call s:hi("Comment", s:nord3_gui_bright, "", s:nord3_term, "", s:italicize_comments, "") -call s:hi("Conditional", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("Constant", s:nord4_gui, "", "NONE", "", "", "") -call s:hi("Define", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("Delimiter", s:nord6_gui, "", s:nord6_term, "", "", "") -call s:hi("Exception", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("Float", s:nord15_gui, "", s:nord15_term, "", "", "") -call s:hi("Function", s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("Identifier", s:nord4_gui, "", "NONE", "", "NONE", "") -call s:hi("Include", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("Keyword", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("Label", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("Number", s:nord15_gui, "", s:nord15_term, "", "", "") -call s:hi("Operator", s:nord9_gui, "", s:nord9_term, "", "NONE", "") -call s:hi("PreProc", s:nord9_gui, "", s:nord9_term, "", "NONE", "") -call s:hi("Repeat", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("Special", s:nord4_gui, "", "NONE", "", "", "") -call s:hi("SpecialChar", s:nord13_gui, "", s:nord13_term, "", "", "") -call s:hi("SpecialComment", s:nord8_gui, "", s:nord8_term, "", s:italicize_comments, "") -call s:hi("Statement", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("StorageClass", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("String", s:nord14_gui, "", s:nord14_term, "", "", "") -call s:hi("Structure", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("Tag", s:nord4_gui, "", "", "", "", "") -call s:hi("Todo", s:nord13_gui, "NONE", s:nord13_term, "NONE", "", "") -call s:hi("Type", s:nord9_gui, "", s:nord9_term, "", "NONE", "") -call s:hi("Typedef", s:nord9_gui, "", s:nord9_term, "", "", "") -hi! link Macro Define -hi! link PreCondit PreProc - -"+-----------+ -"+ Languages + -"+-----------+ -call s:hi("asciidocAttributeEntry", s:nord10_gui, "", s:nord10_term, "", "", "") -call s:hi("asciidocAttributeList", s:nord10_gui, "", s:nord10_term, "", "", "") -call s:hi("asciidocAttributeRef", s:nord10_gui, "", s:nord10_term, "", "", "") -call s:hi("asciidocHLabel", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("asciidocListingBlock", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("asciidocMacroAttributes", s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("asciidocOneLineTitle", s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("asciidocPassthroughBlock", s:nord9_gui, "", s:nord9_term, "", "", "") -call s:hi("asciidocQuotedMonospaced", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("asciidocTriplePlusPassthrough", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link asciidocAdmonition Keyword -hi! link asciidocAttributeRef markdownH1 -hi! link asciidocBackslash Keyword -hi! link asciidocMacro Keyword -hi! link asciidocQuotedBold Bold -hi! link asciidocQuotedEmphasized Italic -hi! link asciidocQuotedMonospaced2 asciidocQuotedMonospaced -hi! link asciidocQuotedUnconstrainedBold asciidocQuotedBold -hi! link asciidocQuotedUnconstrainedEmphasized asciidocQuotedEmphasized -hi! link asciidocURL markdownLinkText - -call s:hi("awkCharClass", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("awkPatterns", s:nord9_gui, "", s:nord9_term, "", s:bold, "") -hi! link awkArrayElement Identifier -hi! link awkBoolLogic Keyword -hi! link awkBrktRegExp SpecialChar -hi! link awkComma Delimiter -hi! link awkExpression Keyword -hi! link awkFieldVars Identifier -hi! link awkLineSkip Keyword -hi! link awkOperator Operator -hi! link awkRegExp SpecialChar -hi! link awkSearch Keyword -hi! link awkSemicolon Delimiter -hi! link awkSpecialCharacter SpecialChar -hi! link awkSpecialPrintf SpecialChar -hi! link awkVariables Identifier - -call s:hi("cIncluded", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link cOperator Operator -hi! link cPreCondit PreCondit - -call s:hi("cmakeGeneratorExpression", s:nord10_gui, "", s:nord10_term, "", "", "") - -hi! link csPreCondit PreCondit -hi! link csType Type -hi! link csXmlTag SpecialComment - -call s:hi("cssAttributeSelector", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("cssDefinition", s:nord7_gui, "", s:nord7_term, "", "NONE", "") -call s:hi("cssIdentifier", s:nord7_gui, "", s:nord7_term, "", s:underline, "") -call s:hi("cssStringQ", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link cssAttr Keyword -hi! link cssBraces Delimiter -hi! link cssClassName cssDefinition -hi! link cssColor Number -hi! link cssProp cssDefinition -hi! link cssPseudoClass cssDefinition -hi! link cssPseudoClassId cssPseudoClass -hi! link cssVendor Keyword - -call s:hi("dosiniHeader", s:nord8_gui, "", s:nord8_term, "", "", "") -hi! link dosiniLabel Type - -call s:hi("dtBooleanKey", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("dtExecKey", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("dtLocaleKey", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("dtNumericKey", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("dtTypeKey", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link dtDelim Delimiter -hi! link dtLocaleValue Keyword -hi! link dtTypeValue Keyword - -if g:nord_uniform_diff_background == 0 - call s:hi("DiffAdd", s:nord14_gui, s:nord0_gui, s:nord14_term, "NONE", "inverse", "") - call s:hi("DiffChange", s:nord13_gui, s:nord0_gui, s:nord13_term, "NONE", "inverse", "") - call s:hi("DiffDelete", s:nord11_gui, s:nord0_gui, s:nord11_term, "NONE", "inverse", "") - call s:hi("DiffText", s:nord9_gui, s:nord0_gui, s:nord9_term, "NONE", "inverse", "") -else - call s:hi("DiffAdd", s:nord14_gui, s:nord1_gui, s:nord14_term, s:nord1_term, "", "") - call s:hi("DiffChange", s:nord13_gui, s:nord1_gui, s:nord13_term, s:nord1_term, "", "") - call s:hi("DiffDelete", s:nord11_gui, s:nord1_gui, s:nord11_term, s:nord1_term, "", "") - call s:hi("DiffText", s:nord9_gui, s:nord1_gui, s:nord9_term, s:nord1_term, "", "") -endif -" Legacy groups for official git.vim and diff.vim syntax -hi! link diffAdded DiffAdd -hi! link diffChanged DiffChange -hi! link diffRemoved DiffDelete - -call s:hi("gitconfigVariable", s:nord7_gui, "", s:nord7_term, "", "", "") - -call s:hi("goBuiltins", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link goConstants Keyword - -call s:hi("helpBar", s:nord3_gui, "", s:nord3_term, "", "", "") -call s:hi("helpHyperTextJump", s:nord8_gui, "", s:nord8_term, "", s:underline, "") - -call s:hi("htmlArg", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("htmlLink", s:nord4_gui, "", "", "", "NONE", "NONE") -hi! link htmlBold Bold -hi! link htmlEndTag htmlTag -hi! link htmlItalic Italic -hi! link htmlH1 markdownH1 -hi! link htmlH2 markdownH1 -hi! link htmlH3 markdownH1 -hi! link htmlH4 markdownH1 -hi! link htmlH5 markdownH1 -hi! link htmlH6 markdownH1 -hi! link htmlSpecialChar SpecialChar -hi! link htmlTag Keyword -hi! link htmlTagN htmlTag - -call s:hi("javaDocTags", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link javaCommentTitle Comment -hi! link javaScriptBraces Delimiter -hi! link javaScriptIdentifier Keyword -hi! link javaScriptNumber Number - -call s:hi("jsonKeyword", s:nord7_gui, "", s:nord7_term, "", "", "") - -call s:hi("lessClass", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link lessAmpersand Keyword -hi! link lessCssAttribute Delimiter -hi! link lessFunction Function -hi! link cssSelectorOp Keyword - -hi! link lispAtomBarSymbol SpecialChar -hi! link lispAtomList SpecialChar -hi! link lispAtomMark Keyword -hi! link lispBarSymbol SpecialChar -hi! link lispFunc Function - -hi! link luaFunc Function - -call s:hi("markdownBlockquote", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("markdownCode", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("markdownCodeDelimiter", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("markdownFootnote", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("markdownId", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("markdownIdDeclaration", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("markdownH1", s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("markdownLinkText", s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("markdownUrl", s:nord4_gui, "", "NONE", "", "NONE", "") -hi! link markdownBold Bold -hi! link markdownBoldDelimiter Keyword -hi! link markdownFootnoteDefinition markdownFootnote -hi! link markdownH2 markdownH1 -hi! link markdownH3 markdownH1 -hi! link markdownH4 markdownH1 -hi! link markdownH5 markdownH1 -hi! link markdownH6 markdownH1 -hi! link markdownIdDelimiter Keyword -hi! link markdownItalic Italic -hi! link markdownItalicDelimiter Keyword -hi! link markdownLinkDelimiter Keyword -hi! link markdownLinkTextDelimiter Keyword -hi! link markdownListMarker Keyword -hi! link markdownRule Keyword -hi! link markdownHeadingDelimiter Keyword - -call s:hi("perlPackageDecl", s:nord7_gui, "", s:nord7_term, "", "", "") - -call s:hi("phpClasses", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("phpDocTags", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link phpDocCustomTags phpDocTags -hi! link phpMemberSelector Keyword - -call s:hi("podCmdText", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("podVerbatimLine", s:nord4_gui, "", "NONE", "", "", "") -hi! link podFormat Keyword - -hi! link pythonBuiltin Type -hi! link pythonEscape SpecialChar - -call s:hi("rubyConstant", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("rubySymbol", s:nord6_gui, "", s:nord6_term, "", s:bold, "") -hi! link rubyAttribute Identifier -hi! link rubyBlockParameterList Operator -hi! link rubyInterpolationDelimiter Keyword -hi! link rubyKeywordAsMethod Function -hi! link rubyLocalVariableOrMethod Function -hi! link rubyPseudoVariable Keyword -hi! link rubyRegexp SpecialChar - -call s:hi("rustAttribute", s:nord10_gui, "", s:nord10_term, "", "", "") -call s:hi("rustEnum", s:nord7_gui, "", s:nord7_term, "", s:bold, "") -call s:hi("rustMacro", s:nord8_gui, "", s:nord8_term, "", s:bold, "") -call s:hi("rustModPath", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("rustPanic", s:nord9_gui, "", s:nord9_term, "", s:bold, "") -call s:hi("rustTrait", s:nord7_gui, "", s:nord7_term, "", s:italic, "") -hi! link rustCommentLineDoc Comment -hi! link rustDerive rustAttribute -hi! link rustEnumVariant rustEnum -hi! link rustEscape SpecialChar -hi! link rustQuestionMark Keyword - -call s:hi("sassClass", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("sassId", s:nord7_gui, "", s:nord7_term, "", s:underline, "") -hi! link sassAmpersand Keyword -hi! link sassClassChar Delimiter -hi! link sassControl Keyword -hi! link sassControlLine Keyword -hi! link sassExtend Keyword -hi! link sassFor Keyword -hi! link sassFunctionDecl Keyword -hi! link sassFunctionName Function -hi! link sassidChar sassId -hi! link sassInclude SpecialChar -hi! link sassMixinName Function -hi! link sassMixing SpecialChar -hi! link sassReturn Keyword - -hi! link shCmdParenRegion Delimiter -hi! link shCmdSubRegion Delimiter -hi! link shDerefSimple Identifier -hi! link shDerefVar Identifier - -hi! link sqlKeyword Keyword -hi! link sqlSpecial Keyword - -call s:hi("vimAugroup", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("vimMapRhs", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("vimNotation", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link vimFunc Function -hi! link vimFunction Function -hi! link vimUserFunc Function - -call s:hi("xmlAttrib", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("xmlCdataStart", s:nord3_gui_bright, "", s:nord3_term, "", s:bold, "") -call s:hi("xmlNamespace", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link xmlAttribPunct Delimiter -hi! link xmlCdata Comment -hi! link xmlCdataCdata xmlCdataStart -hi! link xmlCdataEnd xmlCdataStart -hi! link xmlEndTag xmlTagName -hi! link xmlProcessingDelim Keyword -hi! link xmlTagName Keyword - -call s:hi("yamlBlockMappingKey", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link yamlBool Keyword -hi! link yamlDocumentStart Keyword - -"+----------------+ -"+ Plugin Support + -"+----------------+ -"+--- UI ---+ -" ALE -" > w0rp/ale -call s:hi("ALEWarningSign", s:nord13_gui, "", s:nord13_term, "", "", "") -call s:hi("ALEErrorSign" , s:nord11_gui, "", s:nord11_term, "", "", "") -call s:hi("ALEWarning" , s:nord13_gui, "", s:nord13_term, "", "undercurl", "") -call s:hi("ALEError" , s:nord11_gui, "", s:nord11_term, "", "undercurl", "") - -" Coc -" > neoclide/coc -call s:hi("CocWarningSign", s:nord13_gui, "", s:nord13_term, "", "", "") -call s:hi("CocErrorSign" , s:nord11_gui, "", s:nord11_term, "", "", "") -call s:hi("CocInfoSign" , s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("CocHintSign" , s:nord10_gui, "", s:nord10_term, "", "", "") - -" Nvim LSP -" > neovim/nvim-lsp -call s:hi("LSPDiagnosticsWarning", s:nord13_gui, "", s:nord13_term, "", "", "") -call s:hi("LSPDiagnosticsError" , s:nord11_gui, "", s:nord11_term, "", "", "") -call s:hi("LSPDiagnosticsInformation" , s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("LSPDiagnosticsHint" , s:nord10_gui, "", s:nord10_term, "", "", "") - -" GitGutter -" > airblade/vim-gitgutter -call s:hi("GitGutterAdd", s:nord14_gui, "", s:nord14_term, "", "", "") -call s:hi("GitGutterChange", s:nord13_gui, "", s:nord13_term, "", "", "") -call s:hi("GitGutterChangeDelete", s:nord11_gui, "", s:nord11_term, "", "", "") -call s:hi("GitGutterDelete", s:nord11_gui, "", s:nord11_term, "", "", "") - -" Signify -" > mhinz/vim-signify -call s:hi("SignifySignAdd", s:nord14_gui, "", s:nord14_term, "", "", "") -call s:hi("SignifySignChange", s:nord13_gui, "", s:nord13_term, "", "", "") -call s:hi("SignifySignChangeDelete", s:nord11_gui, "", s:nord11_term, "", "", "") -call s:hi("SignifySignDelete", s:nord11_gui, "", s:nord11_term, "", "", "") - -" fugitive.vim -" > tpope/vim-fugitive -call s:hi("gitcommitDiscardedFile", s:nord11_gui, "", s:nord11_term, "", "", "") -call s:hi("gitcommitUntrackedFile", s:nord11_gui, "", s:nord11_term, "", "", "") -call s:hi("gitcommitSelectedFile", s:nord14_gui, "", s:nord14_term, "", "", "") - -" davidhalter/jedi-vim -call s:hi("jediFunction", s:nord4_gui, s:nord3_gui, "", s:nord3_term, "", "") -call s:hi("jediFat", s:nord8_gui, s:nord3_gui, s:nord8_term, s:nord3_term, s:underline.s:bold, "") - -" NERDTree -" > scrooloose/nerdtree -call s:hi("NERDTreeExecFile", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link NERDTreeDirSlash Keyword -hi! link NERDTreeHelp Comment - -" CtrlP -" > ctrlpvim/ctrlp.vim -hi! link CtrlPMatch Keyword -hi! link CtrlPBufferHid Normal - -" vim-clap -" > liuchengxu/vim-clap -call s:hi("ClapDir", s:nord4_gui, "", "", "", "", "") -call s:hi("ClapDisplay", s:nord4_gui, s:nord1_gui, "", s:nord1_term, "", "") -call s:hi("ClapFile", s:nord4_gui, "", "", "NONE", "", "") -call s:hi("ClapMatches", s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("ClapNoMatchesFound", s:nord13_gui, "", s:nord13_term, "", "", "") -call s:hi("ClapSelected", s:nord7_gui, "", s:nord7_term, "", s:bold, "") -call s:hi("ClapSelectedSign", s:nord9_gui, "", s:nord9_term, "", "", "") - -let s:clap_matches = [ - \ [s:nord8_gui, s:nord8_term] , - \ [s:nord9_gui, s:nord9_term] , - \ [s:nord10_gui, s:nord10_term] , - \ ] -for s:nord_clap_match_i in range(1,12) - let clap_match_color = s:clap_matches[s:nord_clap_match_i % len(s:clap_matches) - 1] - call s:hi("ClapMatches" . s:nord_clap_match_i, clap_match_color[0], "", clap_match_color[1], "", "", "") - call s:hi("ClapFuzzyMatches" . s:nord_clap_match_i, clap_match_color[0], "", clap_match_color[1], "", "", "") -endfor -unlet s:nord_clap_match_i - -hi! link ClapCurrentSelection PmenuSel -hi! link ClapCurrentSelectionSign ClapSelectedSign -hi! link ClapInput Pmenu -hi! link ClapPreview Pmenu -hi! link ClapProviderAbout ClapDisplay -hi! link ClapProviderColon Type -hi! link ClapProviderId Type - -" vim-plug -" > junegunn/vim-plug -call s:hi("plugDeleted", s:nord11_gui, "", "", s:nord11_term, "", "") - -" vim-signature -" > kshenoy/vim-signature -call s:hi("SignatureMarkText", s:nord8_gui, "", s:nord8_term, "", "", "") - -" vim-startify -" > mhinz/vim-startify -call s:hi("StartifyFile", s:nord6_gui, "", s:nord6_term, "", "", "") -call s:hi("StartifyFooter", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("StartifyHeader", s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("StartifyNumber", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("StartifyPath", s:nord8_gui, "", s:nord8_term, "", "", "") -hi! link StartifyBracket Delimiter -hi! link StartifySlash Normal -hi! link StartifySpecial Comment - -"+--- Languages ---+ -" Haskell -" > neovimhaskell/haskell-vim -call s:hi("haskellPreProc", s:nord10_gui, "", s:nord10_term, "", "", "") -call s:hi("haskellType", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link haskellPragma haskellPreProc - -" JavaScript -" > pangloss/vim-javascript -call s:hi("jsGlobalNodeObjects", s:nord8_gui, "", s:nord8_term, "", s:italic, "") -hi! link jsBrackets Delimiter -hi! link jsFuncCall Function -hi! link jsFuncParens Delimiter -hi! link jsThis Keyword -hi! link jsNoise Delimiter -hi! link jsPrototype Keyword -hi! link jsRegexpString SpecialChar - -" TypeScript -" > HerringtonDarkholme/yats.vim -call s:hi("typescriptBOMWindowMethod", s:nord8_gui, "", s:nord8_term, "", s:italic, "") -call s:hi("typescriptClassName", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("typescriptDecorator", s:nord12_gui, "", s:nord12_term, "", "", "") -call s:hi("typescriptInterfaceName", s:nord7_gui, "", s:nord7_term, "", s:bold, "") -call s:hi("typescriptRegexpString", s:nord13_gui, "", s:nord13_term, "", "", "") -" TypeScript JSX - call s:hi("tsxAttrib", s:nord7_gui, "", s:nord7_term, "", "", "") -hi! link typescriptOperator Operator -hi! link typescriptBinaryOp Operator -hi! link typescriptAssign Operator -hi! link typescriptMember Identifier -hi! link typescriptDOMStorageMethod Identifier -hi! link typescriptArrowFuncArg Identifier -hi! link typescriptGlobal typescriptClassName -hi! link typescriptBOMWindowProp Function -hi! link typescriptArrowFuncDef Function -hi! link typescriptAliasDeclaration Function -hi! link typescriptPredefinedType Type -hi! link typescriptTypeReference typescriptClassName -hi! link typescriptTypeAnnotation Structure -hi! link typescriptDocNamedParamType SpecialComment -hi! link typescriptDocNotation Keyword -hi! link typescriptDocTags Keyword -hi! link typescriptImport Keyword -hi! link typescriptExport Keyword -hi! link typescriptTry Keyword -hi! link typescriptVariable Keyword -hi! link typescriptBraces Normal -hi! link typescriptObjectLabel Normal -hi! link typescriptCall Normal -hi! link typescriptClassHeritage typescriptClassName -hi! link typescriptFuncTypeArrow Structure -hi! link typescriptMemberOptionality Structure -hi! link typescriptNodeGlobal typescriptGlobal -hi! link typescriptTypeBrackets Structure -hi! link tsxEqual Operator -hi! link tsxIntrinsicTagName htmlTag -hi! link tsxTagName tsxIntrinsicTagName - -" Markdown -" > plasticboy/vim-markdown -call s:hi("mkdCode", s:nord7_gui, "", s:nord7_term, "", "", "") -call s:hi("mkdFootnote", s:nord8_gui, "", s:nord8_term, "", "", "") -call s:hi("mkdRule", s:nord10_gui, "", s:nord10_term, "", "", "") -call s:hi("mkdLineBreak", s:nord9_gui, "", s:nord9_term, "", "", "") -hi! link mkdBold Bold -hi! link mkdItalic Italic -hi! link mkdString Keyword -hi! link mkdCodeStart mkdCode -hi! link mkdCodeEnd mkdCode -hi! link mkdBlockquote Comment -hi! link mkdListItem Keyword -hi! link mkdListItemLine Normal -hi! link mkdFootnotes mkdFootnote -hi! link mkdLink markdownLinkText -hi! link mkdURL markdownUrl -hi! link mkdInlineURL mkdURL -hi! link mkdID Identifier -hi! link mkdLinkDef mkdLink -hi! link mkdLinkDefTarget mkdURL -hi! link mkdLinkTitle mkdInlineURL -hi! link mkdDelimiter Keyword - -" Vimwiki -" > vimwiki/vimwiki -if !exists("g:vimwiki_hl_headers") || g:vimwiki_hl_headers == 0 - for s:i in range(1,6) - call s:hi("VimwikiHeader".s:i, s:nord8_gui, "", s:nord8_term, "", s:bold, "") - endfor -else - let s:vimwiki_hcolor_guifg = [s:nord7_gui, s:nord8_gui, s:nord9_gui, s:nord10_gui, s:nord14_gui, s:nord15_gui] - let s:vimwiki_hcolor_ctermfg = [s:nord7_term, s:nord8_term, s:nord9_term, s:nord10_term, s:nord14_term, s:nord15_term] - for s:i in range(1,6) - call s:hi("VimwikiHeader".s:i, s:vimwiki_hcolor_guifg[s:i-1] , "", s:vimwiki_hcolor_ctermfg[s:i-1], "", s:bold, "") - endfor -endif - -call s:hi("VimwikiLink", s:nord8_gui, "", s:nord8_term, "", s:underline, "") -hi! link VimwikiHeaderChar markdownHeadingDelimiter -hi! link VimwikiHR Keyword -hi! link VimwikiList markdownListMarker - -" YAML -" > stephpy/vim-yaml -call s:hi("yamlKey", s:nord7_gui, "", s:nord7_term, "", "", "") diff --git a/stow/vim/dot-vim/ftplugin/antlr/antlr3.vim b/stow/vim/dot-vim/ftplugin/antlr/antlr3.vim deleted file mode 100644 index 10e24e5..0000000 --- a/stow/vim/dot-vim/ftplugin/antlr/antlr3.vim +++ /dev/null @@ -1,91 +0,0 @@ -" vim: ts=8 -" Vim syntax file -" Language: ANTLRv3 -" Maintainer: J๖rn Horstmann (updated by Davyd Madeley) -" Last Change: 2008-11-21 - -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") - finish -endif - -syn keyword antlrKeyword grammar lexer parser tree header members options fragment returns throws scope init - -syn match antlrCharacter '\\\(r\|n\|t\|f\|b\|"\|\'\|\\\|u\x\{4}\)' contained display - -syn match antlrToken "\<[A-Z_][a-zA-Z_0-9]\+\>" -syn match antlrRule "[a-z][a-zA-Z_0-9]\+" -syn match antlrScopeVariable '$\k\+::\k\+' - -syn match antlrOperator "[:;@.]" -syn match antlrOperator "[()]" -syn match antlrOperator "[?+*~|!]" -syn match antlrOperator "[->=^]" - -syn match antlrBrace "[{}]" -syn match antlrBrace "[\[\]]" -syn region antlrAction matchgroup=antlrBrace start="[{\[]" end="[}\]]" contains=antlrVariable,antlrLiteral,antlrComment -syn match antlrVariable contained "$[a-zA-Z][a-zA-Z_0-9]*" - -syn region antlrLiteral start=+'+ end=+'+ contains=antlrCharacter -syn region antlrLiteral start=+"+ end=+"+ contains=antlrCharacter - -syn region antlrComment start="/\*" end="\*/" -syn match antlrComment "//.*$" - -" Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 - if version < 508 - let did_antlr_syntax_inits = 1 - command -nargs=+ HiLink hi link - else - command -nargs=+ HiLink hi def link - endif - - HiLink antlrLiteral String - hi def antlrVariable term=bold cterm=bold gui=bold - HiLink antlrBrace Operator - HiLink antlrCharacter Special - HiLink antlrComment Comment - HiLink antlrOperator Operator - HiLink antlrKeyword Keyword - HiLink antlrToken PreProc - HiLink antlrScopeVariable Identifier - HiLink antlrRule Type - - delcommand HiLink -endif - -" try to figure out the target language -let target_languages = [] -" can we figure out from the file name -let extensions = split(expand('%:t'), '\.') -if len(extensions) >= 3 - " great.. the target language was provided via file name - call add(target_languages, tolower(extensions[-2])) -else - " no multiple extensions... have to figure out from the content - let buffer = join(getline(1, line('$')), "\n") - let antlr_options = matchstr(buffer, '\m\(\_s\|;\)options\_s\+{\_.\{-\}}') - call substitute(antlr_options, '\mlanguage\_s*=\_s*''\?\(.\{-\}\)''\?\_s*;', '\=add(target_languages, tolower(submatch(1)))', 'g') -endif -if exists('target_languages[-1]') - " the last defined target language takes precendece - let lang=target_languages[-1] - let syntax_file = findfile('syntax/' . lang . '.vim', &rtp, 1) - if syntax_file != '' - " if a valid syntax file was found only - let b:current_syntax = '' - unlet b:current_syntax - let region_name = '@' . lang . 'Language' - exe 'syntax include ' . region_name . ' ' . syntax_file - exe 'syntax region ' . lang . ' start="{" end="}" keepend contains=' . region_name - endif -endif - -let b:current_syntax = "antlr3" diff --git a/stow/vim/dot-vim/ftplugin/antlr/antlr4.vim b/stow/vim/dot-vim/ftplugin/antlr/antlr4.vim deleted file mode 100644 index 456076c..0000000 --- a/stow/vim/dot-vim/ftplugin/antlr/antlr4.vim +++ /dev/null @@ -1,76 +0,0 @@ -" vim: ts=8 -" Vim syntax file -" Language: ANTLRv4 -" Maintainer: J๖rn Horstmann (updated by Dylon Edwards) -" Last Change: 2015-12-15 - -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syntax clear -elseif exists("b:current_syntax") - finish -endif - -syn keyword antlrKeyword import fragment lexer parser grammar returns locals throws catch finally mode options tokens header members init after channels mode protected public private - -syn keyword antlrReserved rule - -syn match antlrCharacter '\\\(r\|n\|t\|f\|b\|"\|\'\|\\\|u\x\{4}\)' contained display - -syn match antlrToken "\<[A-Z_][a-zA-Z_0-9]\+\>" -syn match antlrRule "[a-z][a-zA-Z_0-9]\+" -syn match antlrScopeVariable '$\k\+::\k\+' - -syn match antlrOperator "[:;@.]" -syn match antlrOperator "[()]" -syn match antlrOperator "[?+*~|!]" -syn match antlrOperator "[->=^]" - -syn match antlrBlock "[{}]" -syn region antlrAction matchgroup=antlrBlock start="{" end="}" contains=antlrVariable,antlrAction -syn match antlrVariable contained "$[a-zA-Z][a-zA-Z_0-9]*" - -syn include @JAVA syntax/java.vim -syn region ANTLR4EmbeddedJavaAction matchgroup=antlrBlock start="{" end="}" contains=@JAVA,antlrVariable containedin=antlrAction - -syn keyword antlrOperations pushMode popMode skip channel - -syn match antlrBrace "[\[\]]" -syn region antlrCharClass matchgroup=antlrBrace start="\[" end="\]" contains=antlrCharacter - -syn region antlrLiteral start=+'+ end=+'+ contains=antlrCharacter -syn region antlrLiteral start=+"+ end=+"+ contains=antlrCharacter - -syn region antlrComment start="/\*" end="\*/" -syn match antlrComment "//.*$" - -" Define the default highlighting. -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlighting yet -if version >= 508 - if version < 508 - let did_antlr_syntax_inits = 1 - command -nargs=+ HiLink hi link - else - command -nargs=+ HiLink hi def link - endif - - HiLink antlrReserved Error - HiLink antlrOperations Identifier - HiLink antlrLiteral String - hi def antlrVariable term=bold cterm=bold gui=bold - HiLink antlrBrace Operator - HiLink antlrBlock Operator - HiLink antlrCharacter Special - HiLink antlrComment Comment - HiLink antlrOperator Operator - HiLink antlrKeyword Keyword - HiLink antlrToken PreProc - HiLink antlrScopeVariable Identifier - HiLink antlrRule Type - - delcommand HiLink -endif - -let b:current_syntax = "antlr4" diff --git a/stow/vim/dot-vim/ftplugin/asciidoc/asciidoc.vim b/stow/vim/dot-vim/ftplugin/asciidoc/asciidoc.vim deleted file mode 100644 index b94b875..0000000 --- a/stow/vim/dot-vim/ftplugin/asciidoc/asciidoc.vim +++ /dev/null @@ -1,19 +0,0 @@ -" ~/.vim/ftplugin/asciidoc/asciidoc.vim -" asciidoc vim configuration -" -" Syntastic linter: proselint - -" Tabs hate: tabs are expanded to 2 spaces -setlocal tabstop=2 shiftwidth=2 expandtab -" Show existing tabs (they can be deleted with :retab) -setlocal list - -" Column marker: 80 characters -" call matchadd('ColorColumn', '\%81v', 100) -setlocal textwidth=80 - -nnoremap C :sp ~/.vim/ftplugin/asciidoc/asciidoc.vim - -" Proselint is slow to act -nnoremap sp :SyntasticCheck proselint -nnoremap e :Errors diff --git a/stow/vim/dot-vim/ftplugin/cpp/cpp.vim b/stow/vim/dot-vim/ftplugin/cpp/cpp.vim deleted file mode 100644 index e2072c1..0000000 --- a/stow/vim/dot-vim/ftplugin/cpp/cpp.vim +++ /dev/null @@ -1,28 +0,0 @@ -" ~/.vim/ftplugin/cpp/cpp.vim -" C++-specific vim configuration - -let mapleader = " " - -" Column marker: 80 characters -match ColorColumn /\%81v/ -setlocal textwidth=80 - -nnoremap C :sp ~/.vim/ftplugin/cpp/cpp.vim -nnoremap E :Errors - -nnoremap c :w:!g++ "%"; ./a.out - -nnoremap gd :YcmCompleter GoTo -nnoremap gr :YcmCompleter GoToReferences -nnoremap gh :YcmCompleter GetType -nnoremap gD :YcmCompleter GetDoc -nnoremap gR :YcmCompleter RefactorRename -nnoremap fi :YcmCompleter FixIt -nnoremap e :YcmDiags - -nnoremap temp :-1r ~/.vim/ftplugin/cpp/snips/template.txtGdd?<+++>cf> - -let mapleader = "," - -inoremap if if (<+++>) {<++>}?<+++>cf> -inoremap for for (<+++>; <++>; <++>) {<++>}?<+++>cf> diff --git a/stow/vim/dot-vim/ftplugin/cpp/snips/template.txt b/stow/vim/dot-vim/ftplugin/cpp/snips/template.txt deleted file mode 100644 index 90ef863..0000000 --- a/stow/vim/dot-vim/ftplugin/cpp/snips/template.txt +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main() { - <+++> - return 0; -} diff --git a/stow/vim/dot-vim/ftplugin/css/css.vim b/stow/vim/dot-vim/ftplugin/css/css.vim deleted file mode 100644 index 695243c..0000000 --- a/stow/vim/dot-vim/ftplugin/css/css.vim +++ /dev/null @@ -1,20 +0,0 @@ -" ~/.vim/ftplugin/css/css.vim -" CSS-specific vim configuration -" -" Syntastic linters: csslint, prettycss, sstylelint - -"let g:syntastic_css_csslint_args = "--ignore=order-alphabetical,ids" - -setlocal textwidth=80 -call matchadd('ColorColumn', '\%81v', 100) - -" Tabs are expanded to 2 spaces -setlocal tabstop=2 shiftwidth=2 expandtab -" Don't show existing tabs -setlocal nolist - -" Mappings -nnoremap C :sp ~/.vim/ftplugin/css/css.vim -nnoremap e :Errors -nnoremap s vi{!sort - diff --git a/stow/vim/dot-vim/ftplugin/html/html.vim b/stow/vim/dot-vim/ftplugin/html/html.vim deleted file mode 100644 index 41890b4..0000000 --- a/stow/vim/dot-vim/ftplugin/html/html.vim +++ /dev/null @@ -1,78 +0,0 @@ -" ~/.vim/ftplugin/html/html.vim -" HTML-specific vim configuration -" -" Syntastic linter: tidy - -" Tabs are expanded to 2 spaces -setlocal tabstop=2 shiftwidth=2 expandtab -" Show existing tabs (they can be deleted with :retab) -setlocal list - -" Column marker: 100 characters -call matchadd('ColorColumn', '\%101v', 100) -setlocal textwidth=100 - -let mapleader = " " - -nnoremap o :!$BROWSER % & -nnoremap f :!firefox --new-window % & -nnoremap C :sp ~/.vim/ftplugin/html/html.vim -nnoremap e :Errors - -nnoremap temp :-1r ~/.vim/ftplugin/html/snips/template.txtGdd?<+++>cf> - -let mapleader = "," - -" Layout elements -inoremap hheader
<++>kki -inoremap hnav <++>kki -inoremap hsection
<++>kki -inoremap harticle
<++>kki -inoremap hfooter
<++>kki -inoremap haside <++>kki -inoremap hdiv
<++>
<++>?""a - -" Headers and paragraphs -inoremap hh1

<++>?i -inoremap hh2

<++>?i -inoremap hh3

<++>?i -inoremap hh4

<++>?i -inoremap hh5
<++>?i -inoremap hh6
<++>?i -inoremap hp

<++>?

i - -" Text formatting -inoremap hb <++>?i -inoremap hi <++>?i -inoremap hem <++>?i -inoremap hcode <++>?i -inoremap hsub <++>?i -inoremap hsup <++>?i -inoremap hcite <++>?i - -" Tables -inoremap htable <++><++>
<++>
<++>?""a -inoremap htr <++>kki -inoremap hth <++>?i -inoremap htd <++>?i - -" Lists -inoremap hul
  • <++>
<++>?i -inoremap hol
  1. <++>
<++>?i -inoremap hli
  • <++>?i - -" Forms -inoremap hform
    <++>3ki -inoremap hfs
    <++>kki -inoremap hlegend <++>?i -inoremap hlabel <++>?i - -" Media -inoremap ha
    <++><++>?""a -inoremap himg <++><++>?""a - -" Misc -" Comment a line -nnoremap hc I0 -" Uncomment a line -nnoremap hC 05x/-->3x0 diff --git a/stow/vim/dot-vim/ftplugin/html/snips/template.txt b/stow/vim/dot-vim/ftplugin/html/snips/template.txt deleted file mode 100644 index 38d9f26..0000000 --- a/stow/vim/dot-vim/ftplugin/html/snips/template.txt +++ /dev/null @@ -1,12 +0,0 @@ - - - - <+++> - - - - - <++> - - - diff --git a/stow/vim/dot-vim/ftplugin/java/java.vim b/stow/vim/dot-vim/ftplugin/java/java.vim deleted file mode 100644 index 2595b32..0000000 --- a/stow/vim/dot-vim/ftplugin/java/java.vim +++ /dev/null @@ -1,14 +0,0 @@ -" ~/.vim/ftplugin/java.vim -" Java-specific vim configuration - -call matchadd('ColorColumn', '\%131v', 100) - -let g:syntastic_java_checkers = [] - -nnoremap gt :YcmCompleter GoTo -nnoremap gr :YcmCompleter GoToReferences -nnoremap fi :YcmCompleter FixIt -nnoremap rr :YcmCompleter RefactorRename -nnoremap e :YcmDiags -nnoremap R :!./run.sh - diff --git a/stow/vim/dot-vim/ftplugin/javascript/javascript.vim b/stow/vim/dot-vim/ftplugin/javascript/javascript.vim deleted file mode 100644 index 4935410..0000000 --- a/stow/vim/dot-vim/ftplugin/javascript/javascript.vim +++ /dev/null @@ -1,38 +0,0 @@ -" ~/.vim/ftplugin/javascript/javascript.vim -" JavaScript-specific vim configuration -" -" Syntastic linters: jslint - -" JSLint arguments -" let g:syntastic_javascript_jslint_args = "--browser --indent" - -" ALE -let b:ale_linters = ['eslint'] - -" Tabs are expanded to 4 spaces -setlocal tabstop=4 shiftwidth=4 expandtab -" Show existing tabs (they can be deleted with :retab) -setlocal list - -" Column marker: 110 characters -call matchadd('ColorColumn', '\%111v', 100) -setlocal textwidth=110 - -" Mappings - -let mapleader = " " - -nnoremap C :sp ~/.vim/ftplugin/javascript/javascript.vim - -nnoremap gd :YcmCompleter GoTo -nnoremap gr :YcmCompleter GoToReferences -nnoremap gh :YcmCompleter GetType -nnoremap gD :YcmCompleter GetDoc -nnoremap gR :YcmCompleter RefactorRename -nnoremap fi :YcmCompleter FixIt -nnoremap e :YcmDiags - -let mapleader = "," - -inoremap if if (<+++>) {<++>} <++>?<+++>cf> -inoremap else else {<+++>}<++>?<+++>cf> diff --git a/stow/vim/dot-vim/ftplugin/plantuml/plantuml.vim b/stow/vim/dot-vim/ftplugin/plantuml/plantuml.vim deleted file mode 100644 index 5bab6a2..0000000 --- a/stow/vim/dot-vim/ftplugin/plantuml/plantuml.vim +++ /dev/null @@ -1,20 +0,0 @@ -" ~/.vim/ftplugin/plantuml/plantuml.vim -" PlantUML-specific vim configuration - -" Tabs hate: tabs are expanded to 4 spaces -setlocal tabstop=4 shiftwidth=4 expandtab -" Show existing tabs (they can be deleted with :retab) -setlocal list - -" Column marker: 80 characters -call matchadd('ColorColumn', '\%81v', 100) -setlocal textwidth=80 - -let mapleader = " " - -nnoremap temp :-1r ~/.vim/ftplugin/plantuml/snips/template.txtGdd?<+++>cf> - -nnoremap C :sp ~/.vim/ftplugin/plantuml/plantuml.vim - -nnoremap c :w:!compilePlantUML.sh "%" -nnoremap o :w:!compilePlantUML.sh -o "%" diff --git a/stow/vim/dot-vim/ftplugin/plantuml/snips/template.txt b/stow/vim/dot-vim/ftplugin/plantuml/snips/template.txt deleted file mode 100644 index f649539..0000000 --- a/stow/vim/dot-vim/ftplugin/plantuml/snips/template.txt +++ /dev/null @@ -1,9 +0,0 @@ -@startuml - -class <+++> { - <++> -} - -<++> - -@enduml diff --git a/stow/vim/dot-vim/ftplugin/python/python.vim b/stow/vim/dot-vim/ftplugin/python/python.vim deleted file mode 100644 index 358f902..0000000 --- a/stow/vim/dot-vim/ftplugin/python/python.vim +++ /dev/null @@ -1,34 +0,0 @@ -" ~/.vim/ftplugin/python/python.vim -" Python-specific vim configuration - -" Tabs are expanded to 4 spaces -setlocal tabstop=4 shiftwidth=4 expandtab -" Show existing tabs (they can be deleted with :retab) -setlocal list - -" Column marker: 90 characters -call matchadd('ColorColumn', '\%91v', 100) -setlocal textwidth=90 - -let b:ale_python_pylint_options = '-d invalid-name' - -" Mappings - -let mapleader = " " - -nnoremap C :sp ~/.vim/ftplugin/python/python.vim -nnoremap x :! ./% -nnoremap X :! ./% - -nnoremap gd :YcmCompleter GoTo -nnoremap gr :YcmCompleter GoToReferences -nnoremap gR :YcmCompleter RefactorRename -nnoremap gd :YcmCompleter GetDoc -nnoremap gT :YcmCompleter GetType - -nnoremap db :!tmux split-window -l '40\%' 'python -mฬ€ pdb %' - -let mapleader = "," - -inoremap temp :-1r ~/.vim/ftplugin/python/snips/templateGdd?<+++>cf> -inoremap class :-1r ~/.vim/ftplugin/python/snips/classGdd?<+++>cf> diff --git a/stow/vim/dot-vim/ftplugin/python/snips/class b/stow/vim/dot-vim/ftplugin/python/snips/class deleted file mode 100644 index 0febf0c..0000000 --- a/stow/vim/dot-vim/ftplugin/python/snips/class +++ /dev/null @@ -1,3 +0,0 @@ -class <+++>: - def __init__(<++>): - self.<++> = <++> diff --git a/stow/vim/dot-vim/ftplugin/python/snips/template b/stow/vim/dot-vim/ftplugin/python/snips/template deleted file mode 100644 index d10fa4a..0000000 --- a/stow/vim/dot-vim/ftplugin/python/snips/template +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/python - -"""<+++>""" - -<++> diff --git a/stow/vim/dot-vim/ftplugin/sent/sent.vim b/stow/vim/dot-vim/ftplugin/sent/sent.vim deleted file mode 100644 index c9cc974..0000000 --- a/stow/vim/dot-vim/ftplugin/sent/sent.vim +++ /dev/null @@ -1,19 +0,0 @@ -" ~/.vim/ftplugin/sent/sent.vim -" Vim configuration for writing sent presentations - -" Tabs hate: tabs are expanded to 4 spaces -setlocal tabstop=4 shiftwidth=4 expandtab -" Show existing tabs (they can be deleted with :retab) -setlocal list - -call matchadd('ColorColumn', '\%41v', 100) -setlocal textwidth=40 - -setlocal spell - -let mapleader = " " - -nnoremap C :sp ~/.vim/ftplugin/sent/sent.vim - -nnoremap c :w:!killall sent :!sent % & -nnoremap o :w:!sent % & diff --git a/stow/vim/dot-vim/ftplugin/sh/sh.vim b/stow/vim/dot-vim/ftplugin/sh/sh.vim deleted file mode 100644 index 3eb4da5..0000000 --- a/stow/vim/dot-vim/ftplugin/sh/sh.vim +++ /dev/null @@ -1,16 +0,0 @@ -" ~/.vim/ftplugin/sh.vim -" Bourne shell scripts specific vim configuration -" -" Linters: sh, shellcheck - -call matchadd('ColorColumn', '\%111v', 100) -setlocal textwidth=110 - -nnoremap C :sp ~/.vim/ftplugin/sh/sh.vim -nnoremap +x :!chmod 744 % -nnoremap x :w:!./% -nnoremap e :Errors - -inoremap sh #!/bin/sh -inoremap if if <+++>; then<++>fi<++>?<+++>cf> -"inoremap if :read ~/.vim/ftplugin/sh/snippets/if.txtkdd/<+++>cf> diff --git a/stow/vim/dot-vim/ftplugin/sh/snippets/if.txt b/stow/vim/dot-vim/ftplugin/sh/snippets/if.txt deleted file mode 100644 index 9f6bb88..0000000 --- a/stow/vim/dot-vim/ftplugin/sh/snippets/if.txt +++ /dev/null @@ -1,3 +0,0 @@ -if <+++>; then - <++> -fi<++> diff --git a/stow/vim/dot-vim/ftplugin/tex/snips/template.txt b/stow/vim/dot-vim/ftplugin/tex/snips/template.txt deleted file mode 100644 index 1f4bd46..0000000 --- a/stow/vim/dot-vim/ftplugin/tex/snips/template.txt +++ /dev/null @@ -1,30 +0,0 @@ -\documentclass{article} - -\usepackage{geometry} -\usepackage{graphicx} -\usepackage{booktabs} - -\geometry{left=4.5cm,top=2cm,bottom=2cm,right=4.5cm} - -\renewcommand{\contentsname}{Contenidos} -\renewcommand{\figurename}{Figura} - -\begin{document} - -\frenchspacing - -\title{<+++>} - -\author{<++>} - -\date{} - -\maketitle - -\tableofcontents - -\section{<++>} - -<++> - -\end{document} diff --git a/stow/vim/dot-vim/ftplugin/tex/tex.vim b/stow/vim/dot-vim/ftplugin/tex/tex.vim deleted file mode 100644 index 87f3c88..0000000 --- a/stow/vim/dot-vim/ftplugin/tex/tex.vim +++ /dev/null @@ -1,45 +0,0 @@ -" ~/.vim/ftplugin/tex.vim -" LaTeX-specific vim configuration - -" Syntastic linters: chktex, lacheck, proselint - -call matchadd('ColorColumn', '\%91v', 100) -setlocal textwidth=80 - -let mapleader = " " - -nnoremap C :sp ~/.vim/ftplugin/tex/tex.vim -nnoremap e :Errors -" proselint not enabled by default (it's slow) -"nnoremap sp :SyntasticCheck proselint - -nnoremap c :w:!toPDF.sh % -nnoremap o :w:!toPDF.sh -o % -nnoremap O :w:!toPDF.sh -o % -nnoremap m :w:!make -nnoremap M :w:!make - -nnoremap temp :-1r ~/.vim/ftplugin/tex/snips/template.txt/<+++>cf> - -let mapleader = "," - -inoremap ldocclass \documentclass{}o<++>k$i -inoremap lpckg \usepackage{}o<++>k$i -inoremap lbdoc \begin{document}o\end{document}kkI -inoremap lauthor \author{}o<++>k$i -inoremap ltitle \title{}o<++>k$i -inoremap lsection \section{}o<++>k$i -inoremap lssection \subsection{}o<++>k$i -inoremap lsssection \subsubsection{}o<++>k$i -inoremap lssssection \paragraph{}o<++>k$i -inoremap lsssssection \subparagraph{}o<++>k$i -inoremap lb \textbf{}<++>F}i -inoremap li \textit{}<++>F}i -inoremap lemph \emph{}<++>F}i -inoremap llabel \label{}<++>F}i -inoremap lref ~\ref{}<++>F}i -inoremap lenumerate \begin{enumerate}o\end{enumerate}kkI\itemI<++>k<$a -inoremap litemize \begin{itemize}o\end{itemize}kkI\itemI<++>k<$a -inoremap litem \item<++>k$a -inoremap limage \begin{figure}[h]\begin{center}\includegraphics[width=\textwidth]{}\caption{<++>}\end{center}\end{figure}<++>4k$i -inoremap ltable \begin{table}[h]\makebox[\linewidth]{\centering\centering\begin{tabular}{ccxxx}\toprule<++>&<++>\\\midrule<++>&<++>\\\bottomrule\end{tabular}}\end{table}<++>?xxxcw diff --git a/stow/vim/dot-vim/ftplugin/text/text.vim b/stow/vim/dot-vim/ftplugin/text/text.vim deleted file mode 100644 index c370a74..0000000 --- a/stow/vim/dot-vim/ftplugin/text/text.vim +++ /dev/null @@ -1,20 +0,0 @@ -" ~/.vim/ftplugin/text/text.vim -" Plain text files vim configuration -" -" Syntastic linter: proselint - -" Tabs hate: tabs are expanded to 2 spaces -setlocal tabstop=2 shiftwidth=2 expandtab -" Show existing tabs (they can be deleted with :retab) -setlocal list - -let mapleader = " " - -call matchadd('ColorColumn', '\%101v', 100) -setlocal textwidth=100 - -nnoremap C :sp ~/.vim/ftplugin/text/text.vim - -" Proselint is slow to act -nnoremap sp :SyntasticCheck proselint -nnoremap e :Errors diff --git a/stow/vim/dot-vim/ftplugin/typescript/typescript.vim b/stow/vim/dot-vim/ftplugin/typescript/typescript.vim deleted file mode 100644 index 7c91032..0000000 --- a/stow/vim/dot-vim/ftplugin/typescript/typescript.vim +++ /dev/null @@ -1,33 +0,0 @@ -" ~/.vim/ftplugin/typescript/typescript.vim -" TypeScript-specific vim configuration - -" ALE -let b:ale_linters = ['eslint'] - -" Tabs are expanded to 4 spaces -setlocal tabstop=4 shiftwidth=4 expandtab -" Show existing tabs (they can be deleted with :retab) -setlocal list - -" Column marker: 110 characters -call matchadd('ColorColumn', '\%111v', 100) -setlocal textwidth=110 - -" Mappings - -let mapleader = " " - -nnoremap C :sp ~/.vim/ftplugin/typescript/typescript.vim - -nnoremap gd :YcmCompleter GoTo -nnoremap gr :YcmCompleter GoToReferences -nnoremap gh :YcmCompleter GetType -nnoremap gD :YcmCompleter GetDoc -nnoremap gR :YcmCompleter RefactorRename -nnoremap fi :YcmCompleter FixIt -nnoremap e :YcmDiags - -let mapleader = "," - -inoremap if if (<+++>) {<++>} <++>?<+++>cf> -inoremap else else {<+++>}<++>?<+++>cf> diff --git a/stow/vim/dot-vim/ftplugin/vimwiki/snips/plantUml.txt b/stow/vim/dot-vim/ftplugin/vimwiki/snips/plantUml.txt deleted file mode 100644 index 4a016eb..0000000 --- a/stow/vim/dot-vim/ftplugin/vimwiki/snips/plantUml.txt +++ /dev/null @@ -1,5 +0,0 @@ -```{.plantuml caption="<+++>"} -@startuml -<++> -@enduml -``` diff --git a/stow/vim/dot-vim/ftplugin/vimwiki/snips/template.txt b/stow/vim/dot-vim/ftplugin/vimwiki/snips/template.txt deleted file mode 100644 index f6b16a8..0000000 --- a/stow/vim/dot-vim/ftplugin/vimwiki/snips/template.txt +++ /dev/null @@ -1,15 +0,0 @@ ---- -header-includes: - - \usepackage[margin=1.5in]{geometry} - -title: "Title" -author: -- รรฑigo Gutiรฉrrez Fernรกndez - - \ - - UO238186 -date: "10/04/2020" ---- - -# Introducciรณn diff --git a/stow/vim/dot-vim/ftplugin/vimwiki/vimwiki.vim b/stow/vim/dot-vim/ftplugin/vimwiki/vimwiki.vim deleted file mode 100644 index c361600..0000000 --- a/stow/vim/dot-vim/ftplugin/vimwiki/vimwiki.vim +++ /dev/null @@ -1,39 +0,0 @@ -" ~/.vim/ftplugin/vimwiki.vim -" vimwiki-specific vim configuration -" -" Syntastic linter: mdl, proselint, textlint - -"let g:syntastic_vimwiki_checkers = ['markdown/mdl'] - -" Tabs hate: tabs are expanded to 2 spaces -setlocal tabstop=2 shiftwidth=2 expandtab -" Show existing tabs (they can be deleted with :retab) -setlocal list - -" Text width -match ColorColumn /\%81v/ -setlocal textwidth=80 -setlocal linebreak - -" Syntax highlighting colors -highlight Title ctermfg=blue -highlight TitleHash ctermfg=cyan -match TitleHash /^##*/ - -setlocal conceallevel=1 - -let mapleader = " " - -nnoremap C :sp ~/.vim/ftplugin/vimwiki/vimwiki.vim -nnoremap e :Errors - -nnoremap tt :r ~/.vim/ftplugin/vimwiki/snips/template.txt -nnoremap tp :r ~/.vim/ftplugin/vimwiki/snips/plantUml.txt/<+++>cf> - -nnoremap c :w:!toPDF.sh "%" -nnoremap o :w:!toPDF.sh -o "%" - -let mapleader = "," - -inoremap h < l >>A diff --git a/stow/vim/dot-vim/plugin/SWTC.vim b/stow/vim/dot-vim/plugin/SWTC.vim deleted file mode 100644 index 9459e92..0000000 --- a/stow/vim/dot-vim/plugin/SWTC.vim +++ /dev/null @@ -1,339 +0,0 @@ -" Vim global plugin for Star Wars crawls -" Maintainer: Damian Conway -" License: This file is placed in the public domain. - -"###################################################################### -"## ## -"## To use: ## -"## ## -"## :SWTC ## -"## ## -"## See file 'intro.swtc' for the crawl-specification syntax ## -"## ## -"###################################################################### - - -" If already loaded, we're done... -if exists("loaded_SWcrawl") - finish -endif -let loaded_SWcrawl = 1 - -" Preserve external compatibility options, then enable full vim compatibility... -let s:save_cpo = &cpo -set cpo&vim - -" Set up the actual colon command... -command! -nargs=1 -complete=file SWTC call SWcrawl() - - -" Implementation.... - -let s:CRAWL_SPEED = 1 "(lines per second) -let s:STAR_DENSITY = 50 "(pixels per star, i.e. 1 star per STAR_DENSITY pixels) -let s:STARFIELD_HEIGHT = 2 "(screens deep) - -let s:LOGO_LINE1 = '^\s*\[\zs.*\ze\]\s*$' -let s:LOGO_LINE2 = '^\s*\[\[\zs.*\ze\]\]\s*$' -let s:LOGO_LINE3 = '^\s*\[\[\[\zs.*\ze\]\]\]\s*$' -let s:LOGO_LINE4 = '^\s*\[\[\[\[\zs.*\ze\]\]\]\]\s*$' -let s:CENTRED_CRAWL_LINE = '^\s*[>]\s*\zs.\{-}\ze\s*[<]\s*$' -let s:CRAWL_LINE = '^\s*[|]\s*\zs.\{-}\ze\s*[|]\s*$' -let s:PREFACE_LINE = '^\s*\zs.\{-}\ze\s*$' - -highlight SWC_PREFACE ctermfg=cyan -highlight SWC_FADE_LIGHT ctermfg=cyan -highlight SWC_FADE_DARK ctermfg=blue -highlight SWC_LOGO ctermfg=yellow cterm=bold -highlight SWC_CRAWL ctermfg=yellow -highlight SWC_STAR ctermfg=white -highlight SWC_BLACK ctermfg=black ctermbg=black - -let s:PREFACE_POS = { 'x': 10, 'y': 5 } - -function! SWcrawl (textsource) - " Load preface, logo, and text to be crawled... - let preface = [] - let logo1 = [] - let logo2 = [] - let logo3 = [] - let logo4 = [] - let crawl = [] - let centred = [] - let max_crawl_width = 0 - for nextline in readfile(a:textsource) - " Ignore blank lines... - if nextline =~ '^\s*$' - continue - - " Lines in [...] are logo components... - elseif nextline =~ s:LOGO_LINE4 - let logo4 += [ matchstr(nextline, s:LOGO_LINE4) ] - elseif nextline =~ s:LOGO_LINE3 - let logo3 += [ matchstr(nextline, s:LOGO_LINE3) ] - elseif nextline =~ s:LOGO_LINE2 - let logo2 += [ matchstr(nextline, s:LOGO_LINE2) ] - elseif nextline =~ s:LOGO_LINE1 - let logo1 += [ matchstr(nextline, s:LOGO_LINE1) ] - - " Lines in |...| are crawl components... - elseif nextline =~ s:CRAWL_LINE - let next_crawl = matchstr(nextline, s:CRAWL_LINE) - if strlen(next_crawl) > max_crawl_width - let max_crawl_width = strlen(substitute(next_crawl,'\s\+',' ','g')) - endif - let crawl += [ next_crawl ] - let centred += [ 0 ] - - " Lines in >...< are centred crawl components... - elseif nextline =~ s:CENTRED_CRAWL_LINE - let next_crawl = matchstr(nextline, s:CENTRED_CRAWL_LINE) - if strlen(next_crawl) > max_crawl_width - let max_crawl_width = strlen(substitute(next_crawl,'\s\+',' ','g')) - endif - let crawl += [ next_crawl ] - let centred += [ 1 ] - - " Anything else is preface... - else - let preface += [ substitute(matchstr(nextline, s:PREFACE_LINE), "^\s*", repeat(" ",s:PREFACE_POS.x), '') ] - - endif - endfor - - " Ensure all logos available... - let logo1 = len(logo1) ? logo1 : ["YOUR", "LOGO", "HERE"] - let logo2 = len(logo2) ? logo2 : copy(logo1) - let logo3 = len(logo3) ? logo3 : copy(logo2) - let logo4 = len(logo4) ? logo4 : copy(logo3) - - " Save current buffer for final transition effect... - let original_buffer = getline(1,'$') - - " Switch to a new buffer... - let prev_matches = getmatches() - enew! - let b:WIN = { 'x' : winwidth(0), 'y' : winheight(0) } - call setline(1, repeat([""], b:WIN.y + 1)) - - " And hide annoyances... - set lcs= - let old_rulerformat = &rulerformat - let &rulerformat="%#SWC_BLACK#%l" - echo "" - - " Generate starfield... - let stars = SWC_gen_stars() - - " Clear screen... - call setline(1, repeat([""], s:STARFIELD_HEIGHT * b:WIN.y) + original_buffer) - redraw - sleep 2 - - " Start with preface... - call matchadd('SWC_PREFACE', '.', 100) - call setline(s:PREFACE_POS.y, preface) - echo "" - redraw - sleep 5 - - " Clean up... - call clearmatches() - call setline(s:PREFACE_POS.y, repeat([""], len(preface))) - echo "" - redraw - sleep 1 - - " Then show logo receding at centre of screen... - call clearmatches() - call matchadd('SWC_BLACK', '*', 102) - call matchadd('SWC_STAR', '\s\zs[.]\ze\s', 101) - call matchadd('SWC_LOGO', '.', 100) - call SWC_draw_logo(logo1) - call SWC_paint_stars(stars) - echo "" - redraw - sleep 3 - - " Push it away... - call setline(1, repeat([""], b:WIN.y)) - call SWC_draw_logo(logo2) - call SWC_paint_stars(stars) - echo "" - redraw - sleep 500m - - call setline(1, repeat([""], b:WIN.y)) - call SWC_draw_logo(logo3) - call SWC_paint_stars(stars) - echo "" - redraw - sleep 500m - - call setline(1, repeat([""], b:WIN.y)) - call SWC_draw_logo(logo4) - call SWC_paint_stars(stars) - echo "" - redraw - sleep 500m - - - " Clean up... - call clearmatches() - call matchadd('SWC_STAR', '\s\zs[.]\ze\s', 101) - call setline(1, repeat([""], b:WIN.y)) - call SWC_paint_stars(stars) - echo "" - redraw - sleep 2 - - " Run crawl... - call clearmatches() - call matchadd('SWC_CRAWL', '.', 100) - call matchadd('SWC_STAR', '\s\zs[.]\ze\s', 101) - for offset_from_bottom in range(1, len(crawl) + b:WIN.y) - let crawl_line = offset_from_bottom < b:WIN.y ? 0 : offset_from_bottom - b:WIN.y + 1 - for screen_line in range(1, b:WIN.y) - if screen_line >= b:WIN.y - offset_from_bottom && crawl_line < len(crawl) - let padded_line = SWC_pad(crawl[crawl_line], screen_line, centred[crawl_line], max_crawl_width) - call setline(screen_line, padded_line) - let crawl_line += 1 - else - call setline(screen_line, "") - endif - endfor - call SWC_paint_stars(stars) - echo "" - redraw - exec 'sleep ' . s:trunc(1000/s:CRAWL_SPEED) . 'm' - if getchar(0) || offset_from_bottom > len(crawl) && padded_line !~ '\S' - break - endif - endfor - - " Pan starfield down... - call matchadd('SWC_FADE_DARK', '[^.]', 200) - sleep 200m - for offset_from_top in range(1, s:STARFIELD_HEIGHT * b:WIN.y) - 1delete - redraw - exec 'sleep ' . (200 - 2 * offset_from_top) . 'm' - endfor - sleep 200m - - - " Switch back to previous buffer and restore normal highlighting... - edit! # - call setmatches(prev_matches) - let &rulerformat = old_rulerformat - redraw - -endfunction - -function s:trunc (n) - return str2nr(string( a:n )) -endfunction - -function! SWC_draw_logo (logo) - let logo = copy(a:logo) - - " Find centre for logo... - let logo_width = 0 - for line in logo - if strlen(line) > logo_width - let logo_width = strlen(line) - endif - endfor - let logo_pos_x = (b:WIN.x - logo_width) / 2 - let logo_pos_y = (b:WIN.y - len(logo)) / 2 - - " Move logo to centre... - call map(logo, "repeat(' ', logo_pos_x) . v:val") - - " Draw logo - call setline(logo_pos_y, logo) - -endfunction - -function! SWC_pad (text, y_pos, centred, max_text_width) - - " Does this need padding??? - let words = split(a:text, '\s\+') - if len(words) < 1 - return a:text - endif - - " How many unpadded characters are there??? - let unpadded_width = 0 - for word in words - let unpadded_width += strlen(word) - endfor - - " How much padding is needed??? - let rel_y = (2.0 * a:y_pos / b:WIN.y) - 1.0 - let stretched_width = s:trunc( a:max_text_width + rel_y * (b:WIN.x - a:max_text_width) ) - let required_padding = max([ 0, stretched_width - unpadded_width ]) - let indent = (b:WIN.x - stretched_width) / 2 - let gap_count = len(words) - 1 - - " Is this a last line??? - let tight = a:centred || strlen(a:text) < 0.9 * a:max_text_width - - " Insert padding... - if a:y_pos >= b:WIN.y/2 - let min_padding_needed_for = gap_count - if tight - let min_pad_per_gap = max([ 1, s:trunc(rel_y * 6.0) ]) - else - let min_pad_per_gap = max([ 1, required_padding / gap_count ]) - let leftover_padding = required_padding - gap_count * min_pad_per_gap - let min_padding_needed_for = min([ gap_count, gap_count - leftover_padding ]) - endif - let padded_text = join(words[0 : min_padding_needed_for], repeat(" ", min_pad_per_gap)) - \ . repeat(" ", min_pad_per_gap+1) - \ . join(words[min_padding_needed_for+1 : -1], repeat(" ", min_pad_per_gap+1)) - let padded_text = substitute(padded_text, '\s*$', '', '') - - " Or remove chars (in the distance)... - elseif a:text =~ '\S' -" let delta = s:trunc( 8.0 * (b:WIN.y/2 - a:y_pos) ) -" let greeked_len = max([ 0, strlen(substitute(a:text, '^\s*\|\s*$', '', 'g')) - delta ]) - let greeked_len = tight ? stretched_width * (unpadded_width + gap_count) / a:max_text_width : stretched_width - let padded_text = repeat('~', greeked_len) - - " Or ignore it... - else - let padded_text = "" - - endif - - " Indent to centre... - let padded_text = substitute(padded_text, '\s*$', '', '') - let max_ever_padding = b:WIN.x - a:max_text_width - let indent = a:centred ? (b:WIN.x - strlen(padded_text))/2 - \ : indent - return repeat(" ", indent) . padded_text -endfunction - -function! SWC_gen_stars () - let star_count = b:WIN.x * s:STARFIELD_HEIGHT * b:WIN.y / s:STAR_DENSITY - let stars = [] - for n in range(star_count) - let x = RandomNumber(b:WIN.x) + 1 - let y = RandomNumber(s:STARFIELD_HEIGHT * b:WIN.y) + 1 - let stars += [{'y':y,'x':x}] - endfor - return stars -endfunction - -function! SWC_paint_stars (stars) - let max_x = b:WIN.x - for star in a:stars - let line = strpart(getline(star.y) . repeat(" ", max_x), 0, max_x) - let line = substitute(line, '\s\zs\%'.(star.x-1).'c\s\ze\s', '.', '') - call setline(star.y, line) - endfor -endfunction - -" Restore previous external compatibility options -let &cpo = s:save_cpo diff --git a/stow/vim/dot-vim/plugin/dragvisuals.vim b/stow/vim/dot-vim/plugin/dragvisuals.vim deleted file mode 100644 index 12c4f5d..0000000 --- a/stow/vim/dot-vim/plugin/dragvisuals.vim +++ /dev/null @@ -1,345 +0,0 @@ -" Vim global plugin for dragging virtual blocks -" Last change: Tue Jul 24 07:19:35 EST 2012 -" Maintainer: Damian Conway -" License: This file is placed in the public domain. - -"######################################################################### -"## ## -"## Add the following (uncommented) to your .vimrc... ## -"## ## -"## runtime plugin/dragvisuals.vim ## -"## ## -"## vmap DVB_Drag('left') ## -"## vmap DVB_Drag('right') ## -"## vmap DVB_Drag('down') ## -"## vmap DVB_Drag('up') ## -"## vmap D DVB_Duplicate() ## -"## ## -"## " Remove any introduced trailing whitespace after moving... ## -"## let g:DVB_TrimWS = 1 ## -"## ## -"## Or, if you use the arrow keys for normal motions, choose ## -"## four other keys for block dragging. For example: ## -"## ## -"## vmap h DVB_Drag('left') ## -"## vmap l DVB_Drag('right') ## -"## vmap j DVB_Drag('down') ## -"## vmap k DVB_Drag('up') ## -"## ## -"## Or: ## -"## ## -"## vmap DVB_Drag('left') ## -"## vmap DVB_Drag('right') ## -"## vmap DVB_Drag('down') ## -"## vmap DVB_Drag('up') ## -"## ## -"## Or even: ## -"## ## -"## vmap DVB_Drag('left') ## -"## vmap DVB_Drag('right') ## -"## vmap DVB_Drag('down') ## -"## vmap DVB_Drag('up') ## -"## ## -"######################################################################### - - -" If already loaded, we're done... -if exists("loaded_dragvirtualblocks") - finish -endif -let loaded_dragvirtualblocks = 1 - -" Preserve external compatibility options, then enable full vim compatibility... -let s:save_cpo = &cpo -set cpo&vim - -"====[ Implementation ]==================================== - -" Toggle this to stop trimming on drags... -if !exists('g:DVB_TrimWS') - let g:DVB_TrimWS = 1 -endif - -function! DVB_Drag (dir) - " No-op in Visual mode... - if mode() ==# 'v' - return "\gv" - - " Do Visual Line drag indirectly via temporary nmap - " (to ensure we have access to block position data)... - elseif mode() ==# 'V' - " Set up a temporary convenience... - exec "nnoremap M \Drag_Lines('".a:dir."')" - - " Return instructions to implement the move and reset selection... - return '"vyM' - - " Otherwise do Visual Block drag indirectly via temporary nmap - " (to ensure we have access to block position data)... - else - " Set up a temporary convenience... - exec "nnoremap M \Drag_Block('".a:dir."')" - - " Return instructions to implement the move and reset selection... - return '"vyM' - endif -endfunction - -" Duplicate selected block and place to the right... -function! DVB_Duplicate () - exec "nnoremap M \DuplicateBlock()" - return '"vyM' -endfunction - -function! s:DuplicateBlock () - nunmap M - " Locate block boundaries... - let [buf_left, line_left, col_left, offset_left ] = getpos("'<") - let [buf_right, line_right, col_right, offset_right] = getpos("'>") - - " Identify special '$' blocks... - let dollar_block = 0 - let start_col = min([col_left+offset_left, col_right+offset_right]) - let end_col = max([col_left+offset_left, col_right+offset_right]) - let visual_width = end_col - start_col + 1 - for visual_line in split(getreg("v"),"\n") - if strlen(visual_line) > visual_width - let dollar_block = 1 - let visual_width = strlen(visual_line) - endif - endfor - let square_up = (dollar_block ? (start_col+visual_width-2).'|' : '') - - set virtualedit=all - return 'gv'.square_up.'yPgv' - \. (visual_width-dollar_block) . 'lo' . (visual_width-dollar_block) . 'l' - \. "y:set virtualedit=block\gv" - \. (dollar_block ? 'o$' : '') -endfunction - - -" Kludge to hide change reporting inside implementation... -let s:NO_REPORT = ":let b:DVB_report=&report\:let &report=1000000000\" -let s:PREV_REPORT = ":let &report = b:DVB_report\" - - -" Drag in specified direction in Visual Line mode... -function! s:Drag_Lines (dir) - " Clean up the temporary convenience... - nunmap M - - " Locate block being shifted... - let [buf_left, line_left, col_left, offset_left ] = getpos("'<") - let [buf_right, line_right, col_right, offset_right] = getpos("'>") - - " Drag entire lines left if possible... - if a:dir == 'left' - " Are all lines indented at least one space??? - let lines = getline(line_left, line_right) - let all_indented = match(lines, '^[^ ]') == -1 - nohlsearch - - " If can't trim one space from start of each line, be a no-op... - if !all_indented - return 'gv' - - " Otherwise drag left by removing one space from start of each line... - else - return s:NO_REPORT - \ . "gv:s/^ //\" - \ . s:PREV_REPORT - \ . "gv" - endif - - " To drag entire lines right, add a space in column 1... - elseif a:dir == 'right' - return s:NO_REPORT - \ . "gv:s/^/ /\:nohlsearch\" - \ . s:PREV_REPORT - \ . "gv" - - " To drag entire lines upwards... - elseif a:dir == 'up' - let EOF = line('$') - - " Can't drag up if at first line... - if line_left == 1 || line_right == 1 - return 'gv' - - " Needs special handling at EOF (because cursor moves up on delete)... - elseif line_left == EOF || line_right == EOF - let height = line_right - line_left - let select_extra = height ? height . 'j' : "" - return s:NO_REPORT - \ . 'gvxP' - \ . s:PREV_REPORT - \ . 'V' . select_extra - - " Otherwise just cut-move-paste-reselect... - else - let height = line_right - line_left - let select_extra = height ? height . 'j' : "" - return s:NO_REPORT - \ . 'gvxkP' - \ . s:PREV_REPORT - \ . 'V' . select_extra - endif - - " To drag entire lines downwards... - elseif a:dir == 'down' - let EOF = line('$') - - " This is how much extra we're going to have to reselect... - let height = line_right - line_left - let select_extra = height ? height . 'j' : "" - - " Needs special handling at EOF (to push selection down into new space)... - if line_left == EOF || line_right == EOF - return "O\gv" - - " Otherwise, just cut-move-paste-reselect... - else - return s:NO_REPORT - \ . 'gvxp' - \ . s:PREV_REPORT - \ . 'V' . select_extra - endif - - endif -endfunction - -" Drag in specified direction in Visual Block mode... -function! s:Drag_Block (dir) - " Clean up the temporary convenience... - nunmap M - - " Locate block being shifted... - let [buf_left, line_left, col_left, offset_left ] = getpos("'<") - let [buf_right, line_right, col_right, offset_right] = getpos("'>") - - " Identify special '$' blocks... - let dollar_block = 0 - let start_col = min([col_left+offset_left, col_right+offset_right]) - let end_col = max([col_left+offset_left, col_right+offset_right]) - let visual_width = end_col - start_col + 1 - for visual_line in split(getreg("v"),"\n") - if strlen(visual_line) > visual_width - let dollar_block = 1 - let visual_width = strlen(visual_line) - endif - endfor - let square_up = (dollar_block ? (start_col+visual_width-2).'|' : '') - - " Drag left... - if a:dir == 'left' - "Can't drag left at left margin... - if col_left == 1 || col_right == 1 - return 'gv' - - " Otherwise reposition one column left (and optionally trim any whitespace)... - elseif g:DVB_TrimWS - " May need to be able to temporarily step past EOL... - let prev_ve = &virtualedit - set virtualedit=all - - " Are we moving past other text??? - let square_up_final = "" - if dollar_block - let lines = getline(line_left, line_right) - if match(lines, '^.\{'.(start_col-2).'}\S') >= 0 - let dollar_block = 0 - let square_up_final = (start_col+visual_width-3).'|' - endif - endif - - let vcol = start_col - 2 - return 'gv'.square_up.'xhP' - \ . s:NO_REPORT - \ . "gvhoho:s/\\s*$//\gv\" - \ . ':set virtualedit=' . prev_ve . "\" - \ . s:PREV_REPORT - \ . ":nohlsearch\gv" - \ . (dollar_block ? '$' : square_up_final ) - else - return 'gv'.square_up.'xhPgvhoho' - endif - - " Drag right... - elseif a:dir == 'right' - " May need to be able to temporarily step past EOL... - let prev_ve = &virtualedit - set virtualedit=all - - " Reposition block one column to the right... - if g:DVB_TrimWS - let vcol = start_col - return 'gv'.square_up.'xp' - \ . s:NO_REPORT - \ . "gvlolo" - \ . ":s/\\s*$//\gv\" - \ . ':set virtualedit=' . prev_ve . "\" - \ . s:PREV_REPORT - \ . (dollar_block ? 'gv$' : 'gv') - else - return 'gv'.square_up.'xp:set virtualedit=' . prev_ve . "\gvlolo" - endif - - " Drag upwards... - elseif a:dir == 'up' - " Can't drag upwards at top margin... - if line_left == 1 || line_right == 1 - return 'gv' - endif - - " May need to be able to temporarily step past EOL... - let prev_ve = &virtualedit - set virtualedit=all - - " If trimming whitespace, jump to just below block to do it... - if g:DVB_TrimWS - let height = line_right - line_left + 1 - return 'gv'.square_up.'xkPgvkoko"vy' - \ . height - \ . 'j:s/\s*$//' - \ . "\:nohlsearch\:set virtualedit=" - \ . prev_ve - \ . "\gv" - \ . (dollar_block ? '$' : '') - - " Otherwise just move and reselect... - else - return 'gv'.square_up.'xkPgvkoko"vy:set virtualedit=' - \ . prev_ve - \ . "\gv" - \ . (dollar_block ? '$' : '') - endif - - " Drag downwards... - elseif a:dir == 'down' - " May need to be able to temporarily step past EOL... - let prev_ve = &virtualedit - set virtualedit=all - - " If trimming whitespace, move to just above block to do it... - if g:DVB_TrimWS - return 'gv'.square_up.'xjPgvjojo"vyk:s/\s*$//' - \ . "\:nohlsearch\:set virtualedit=" - \ . prev_ve - \ . "\gv" - \ . (dollar_block ? '$' : '') - - " Otherwise just move and reselect... - else - return 'gv'.square_up.'xjPgvjojo"vy' - \ . "\:set virtualedit=" - \ . prev_ve - \ . "\gv" - \ . (dollar_block ? '$' : '') - endif - endif -endfunction - - -" Restore previous external compatibility options -let &cpo = s:save_cpo - diff --git a/stow/vim/dot-vim/plugin/rng.vim b/stow/vim/dot-vim/plugin/rng.vim deleted file mode 100644 index 51c9991..0000000 --- a/stow/vim/dot-vim/plugin/rng.vim +++ /dev/null @@ -1,83 +0,0 @@ -" George Marsaglia's Multiply-with-carry Random Number Generator {{{ -" Modified to work within Vim's semantics -let s:m_w = 1 + getpid() -let s:m_z = localtime() - -" not sure of the wisdom of generating a full 32-bit RN here -" and then using abs() on the sucker. Feedback welcome. -function! RandomNumber(...) - if a:0 == 0 - let s:m_z = (36969 * and(s:m_z, 0xffff)) + (s:m_z / 65536) - let s:m_w = (18000 * and(s:m_w, 0xffff)) + (s:m_w / 65536) - return (s:m_z * 65536) + s:m_w " 32-bit result - elseif a:0 == 1 " We return a number in [0, a:1] or [a:1, 0] - return a:1 < 0 ? RandomNumber(a:1,0) : RandomNumber(0,a:1) - else " if a:2 >= 2 - return abs(RandomNumber()) % (abs(a:2 - a:1) + 1) + a:1 - endif -endfunction -" end RNG }}} - -" RandomChar(base, cap) -" base : the lowest char number desired -" cap : the highest char number desired -" Defaults to ASCII characters in the range -" 33-126 (!-~) -" But it's capable of much wider character tables -function! RandomChar(...) - let base = 33 - let cap = 126 - if a:0 > 0 - let base = a:1 - endif - if a:0 > 1 - let cap = a:2 - endif - return nr2char(RandomNumber(base, cap)) -endfunction - -function! RandomCharsInSet(length, set) - let from = join(map(range(len(a:set)), 'nr2char(char2nr("a")+v:val)'), '') - let to = join(a:set, '') - return map(RandomChars(a:length, 97, 96+len(a:set)), 'tr(v:val, from, to)') -endfunction - -function! RandomChars(length, ...) - let args = [] - if a:0 > 0 - if type(a:1) == type([]) - let args = a:1 - else - let args = a:000 - endif - endif - return map(repeat([0], a:length), 'call("RandomChar", args)') -endfunction - -function! RandomString(length, ...) - let args = [] - if a:0 > 0 - if type(a:1) == type([]) - let args = a:1 - else - let args = a:000 - endif - endif - return join(call('RandomChars', [a:length, args]), '') -endfunction - -let s:chars = '! " # $ % & '' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~' -let s:charlist = split(s:chars, ' ') - -function! RandomCharFromRegex(regex, ...) - let charlist = a:0 ? split(a:1, '\zs') : copy(s:charlist) - call filter(charlist, 'v:val =~ a:regex') - return charlist[RandomNumber(0, len(charlist) - 1)] -endfunction - -function! RandomStringFromRegex(regex, lenght, ...) - let charlist = a:0 ? split(a:1, '\zs') : copy(s:charlist) - call filter(charlist, 'v:val =~ a:regex') - let len = len(charlist) - 1 - return join(map(range(a:lenght), 'charlist[RandomNumber(0, len)]'), '') -endfunction diff --git a/stow/vim/dot-vimrc b/stow/vim/dot-vimrc deleted file mode 100644 index 9520648..0000000 --- a/stow/vim/dot-vimrc +++ /dev/null @@ -1,280 +0,0 @@ -" _ -" __ _(_)_ __ ___ _ __ ___ -" \ \ / / | '_ ` _ \| '__/ __| -" \ V /| | | | | | | | | (__ -" \_/ |_|_| |_| |_|_| \___| -" - -let mapleader = "," - -call plug#begin('~/.vim/plugged') "Update with PlugInstall -Plug 'PotatoesMaster/i3-vim-syntax' -Plug 'junegunn/goyo.vim' -Plug 'junegunn/fzf.vim' -Plug 'junegunn/limelight.vim' -Plug 'arcticicestudio/nord-vim' -Plug 'tpope/vim-surround' -Plug 'tpope/vim-repeat' -Plug 'vimwiki/vimwiki' -Plug 'vim-airline/vim-airline' -Plug 'psliwka/vim-smoothie' -"Plug 'vim-syntastic/syntastic' -Plug 'dense-analysis/ale' -"Plug 'Shougo/deoplete.nvim', {'do': ':UpdateRemotePlugins' } -"Plug 'Shougo/deoplete-clangx' -"Plug 'neoclide/coc.nvim', {'branch': 'release'} -Plug 'Valloric/YouCompleteMe' -"Plug 'OmniSharp/omnisharp-vim' -Plug 'dylanaraps/wal.vim' -"Plug 'ThePrimeagen/vim-be-good' -call plug#end() - -" Basic settings -set nocompatible -set encoding=utf-8 -set number relativenumber -set tabstop=4 -set shiftwidth=4 -set scrolloff=2 -set wildmode=longest,list,full -set splitbelow -set splitright -set vb " No bell -" Searching -set ignorecase -set wrapscan -set incsearch -set nohlsearch - -" Filetypes -filetype indent plugin on -au BufRead,BufNewFile *.pu,*.puml,*.pumlc set filetype=plantuml -au BufRead,BufNewFile *.g set filetype=antlr3 -au BufRead,BufNewFile *.g4 set filetype=antlr4 -au BufRead,BufNewFile *.sent set filetype=sent -let g:tex_flavor = "latex" - -" hlnext: Highlighting searches -nnoremap n n:call HLNext(0.1) -nnoremap N N:call HLNext(0.1) -function! HLNext(blinktime) - set invcursorline - redraw - exec 'sleep'.float2nr(a:blinktime*1000).'m' - set invcursorline - redraw -endfunction - -" dragvisuals: dragging visual blocks -vmap DVB_Drag('left') -vmap DVB_Drag('right') -vmap DVB_Drag('down') -vmap DVB_Drag('up') -vmap D DVB_Duplicate() - -" Showing tabs -"exec "set listchars=tab:\uBB\uBB,trail:\uB7,nbsp:~" -exec "set listchars=tab:\uBBยท,trail:\uB7,nbsp:~" -nnoremap l :set list! - -" For deoplete - -"let g:deoplete#enable_at_startup = 1 -" -"call deoplete#custom#option({ -"\ 'auto_complete': v:true, -"\ 'auto_complete_delay': 0, -"\ 'smart_case': v:true, -"\ }) -" -"call deoplete#custom#option('sources', { -"\ '_': ['ale'], -"\}) - -" For CoC -"inoremap coc#refresh() - -" For YouCompleteMe -let g:ycm_auto_trigger = 1 -let g:ycm_autoclose_preview_window_after_insertion = 1 - -" For syntastic -"set statusline+=%#warningmsg# -"set statusline+=%{SyntasticStatuslineFlag()} -"set statusline+=%* -"let g:syntastic_cs_checkers = ['code_checker'] -"let g:syntastic_enable_signs = 1 -"let g:syntastic_aggregate_errors = 1 -"let g:syntastic_always_populate_loc_list = 1 -"let g:syntastic_auto_loc_list = 2 -"let g:syntastic_check_on_open = 1 -"let g:syntastic_check_on_wq = 0 - -" For omnisharp -"let g:OmniSharp_server_stdio = 1 -"let g:OmniSharp_server_path = '/home/taamas/repos/omnisharp-roslyn/artifacts/scripts/OmniSharp.Stdio' -"let g:OmniSharp_selector_ui = 'fzf' - -" For cursor shape with tmux -if exists('$TMUX') - let &t_SI = "\Ptmux;\\e[5 q\\\" - let &t_EI = "\Ptmux;\\e[2 q\\\" -else - let &t_SI = "\e[5 q" - let &t_EI = "\e[2 q" -endif - -"if empty($TMUX) -" let &t_SI = "\]50;CursorShape=1\x7" " Vertical bar in insert mode -" let &t_EI = "\]50;CursorShape=0\x7" " Block in normal mode -"else -" let &t_SI = "\Ptmux;\\]50;CursorShape=1\x7\\\" -" let &t_EI = "\Ptmux;\\]50;CursorShape=0\x7\\\" -"endif - -"if &term =~ '^screen' -" " tmux will send xterm-style keys when its xterm-keys option is on -" execute "set =\e[1;*A" -" execute "set =\e[1;*B" -" execute "set =\e[1;*C" -" execute "set =\e[1;*D" -"endif - -" For vim-airline -if !exists('g:airline_symbols') - let g:airline_symbols = {} -endif -let g:airline_left_sep='' -let g:airline_right_sep='' -let g:airline_symbols.linenr = '๐Ÿ”ƒ' -let g:airline_symbols.maxlinenr = 'โ†ฉ' - -" For vimwiki -" filetype plugin on -let g:vimwiki_ext2syntax = {'.md': 'markdown', '.markdown': 'markdown', '.mdown': 'markdown'} -let g:vimwiki_list = [{'path': '~/docs/vimwiki/', 'syntax': 'markdown', 'ext': '.md'}, - \ {'path': '~/docs/notas/', 'syntax': 'markdown', 'ext': '.md'}, - \ {'path': '~/games/dungeonesYDragones/tarkba/vimwiki/', 'syntax': 'markdown', 'ext': '.md'}, - \ {'path': '~/games/dungeonesYDragones/creaciones/vimwiki/', 'syntax': 'markdown', 'ext': '.md'}] - -" Vertical split character -set fillchars+=vert:โ–ˆ - -" Shortcuts for split navigation -map h -map j -map k -map l -map < -map + -map - -map > -map 10< -map 5+ -map 5- -map 10> - -" Shortcuts for opening netrw -nnoremap f :40Vexplore -nnoremap F :40Lexplore - -" FZF -nnoremap :Files - -" Moving -here- -nnoremap h :cd %:h - -nnoremap :tabnew -"nnoremap gt "Can't be set without also remapping -"nnoremap gT - -nnoremap vrc :80vsp ~/.vimrc -nnoremap S :!tmux split-window -l '40\%' - -nnoremap / /grtfjx - -""" Color -colorscheme nord - -" Syntax -syntax enable -syntax on - -" Line number color -highlight LineNr ctermfg=12 -highlight LineNr cterm=NONE -highlight CursorLineNr ctermfg=5 -highlight CursorLineNr cterm=underline - -" Completion color -highlight Pmenu ctermbg=blue ctermfg=black -highlight PmenuSel ctermbg=darkblue ctermfg=white - -" Panel border color -"highlight VertSplit ctermbg=black ctermfg=darkblue - -" Symbol pairs match color -highlight MatchParen ctermbg=cyan ctermfg=black - -" Errors colors -highlight Error ctermbg=red ctermfg=black -highlight SpellBad ctermbg=red ctermfg=black - -" Comments colors -highlight Comment ctermfg=green - -" Line size marking -highlight ColorColumn ctermbg=darkblue ctermfg=black -"Redjail Bomb (thx Damian Conway!) -"highlight ColorColumn ctermbg=red ctermfg=blue -"exec 'set colorcolumn='.join(range(2,80,3), ',') - -"Clean trailing whitespaces on save -autocmd BufWritePre * %s/\s\+$//e - -" Autoupdate ~/.Xresources -autocmd BufWritePost ~/.Xresources !xrdb % - -" Generate ~/.mainpage/urls on ~/.config/qutebrowser save -autocmd BufWritePost ~/.config/qutebrowser/config.py !grep -e \'.*\':\ \'.*{}.*\' "$HOME/.config/qutebrowser/config.py" | grep -v DEFAULT | sed 's/,//; s/^\ *//' > ~/.mainpage/urls - -""" Remaps """ - -nnoremap Y y$ -nnoremap ss :set spell! -nnoremap sl :set spelllang= -nnoremap sL :setlocal spelllang= -nnoremap e :Errors -nnoremap x :w:! ./% -inoremap w :w -inoremap /<++>cf> -nnoremap p "+p -nnoremap y "+yy -vnoremap y "+y -nnoremap d "+dd -vnoremap d "+d - -" For Goyo -function! s:goyo_enter() - silent !tmux set status off -endfunction - -function! s:goyo_leave() - silent !tmux set status on -endfunction - -autocmd! User GoyoEnter nested call goyo_enter() -autocmd! User GoyoLeave nested call goyo_leave() - -let g:goyo_linenr = 1 -nnoremap G :Goyo \| set linebreak:e - -" For LimeLight -let g:limelight_conceal_ctermfg = 7 - -"" git -nnoremap gs :!git status -"nnoremap gpull :!git pull -nnoremap ga :!git add % -nnoremap gp :!git push -nnoremap gc :!git commit -m " diff --git a/stow/vis/.config/vis/colors/basic_colors b/stow/vis/.config/vis/colors/basic_colors new file mode 100644 index 0000000..4be5fa4 --- /dev/null +++ b/stow/vis/.config/vis/colors/basic_colors @@ -0,0 +1,15 @@ +4 +12 +6 +14 +2 +10 +11 +3 +5 +1 +13 +9 +7 +15 +0 diff --git a/stow/vis/.config/vis/colors/rainbow b/stow/vis/.config/vis/colors/rainbow new file mode 100644 index 0000000..13714c5 --- /dev/null +++ b/stow/vis/.config/vis/colors/rainbow @@ -0,0 +1,30 @@ +#1F80F3 +#08ADD8 +#06B3D4 +#01D7AF +#01DBA9 +#0DF47E +#26FE53 +#2CFF4B +#4FF829 +#58F522 +#83DE0B +#8FD506 +#ADBB01 +#BEAA01 +#D78C07 +#E27C0D +#F65525 +#F94C2B +#FE2A4D +#FE2456 +#F20B81 +#D901AC +#D501B2 +#B007D6 +#AA09DA +#7C21F4 +#6D2DF9 +#5541FE +#3E58FE +#2A70F9 diff --git a/stow/vis/.config/vis/config b/stow/vis/.config/vis/config new file mode 100644 index 0000000..a68497a --- /dev/null +++ b/stow/vis/.config/vis/config @@ -0,0 +1,91 @@ +##Refresh rate of the visualizers. A really high refresh rate may cause screen tearing. Default is 20. +#visualizer.fps=20 + +##Sets the audio sources to use. Currently available ones are "mpd" and "alsa"Sets the audio sources to use. +##Currently available ones are "mpd", "pulse" and "alsa". Defaults to "mpd". +#audio.sources=pulse + +##vis tries to find the correct pulseaudio sink, however this will not work on all systems. +##If pulse audio is not working with vis try switching the audio source. A list can be found by running the +##command pacmd list-sinks | grep -e 'name:' -e 'index' +#audio.pulse.source=0 + +##Defaults to "/tmp/mpd.fifo" +#mpd.fifo.path=/tmp/mpd.fifo + +##If set to false the visualizers will use mono mode instead of stereo. Some visualizers will +##behave differently when mono is enabled. For example, spectrum show two sets of bars. +#audio.stereo.enabled=false + +##Specifies how often the visualizer will change in seconds. 0 means do not rotate. Default is 0. +#visualizer.rotation.secs=10 + +##Configures the samples rate and the cutoff frequencies. +#audio.sampling.frequency=44100 +#audio.low.cutoff.frequency=30 +#audio.high.cutoff.frequency=22050 + +##Applies scaling factor to both lorenz and ellipse visualizers. This is useful when the system audio is set +#to a low volume. +#visualizer.scaling.multiplier=1.0 + +##Configures the visualizers and the order they are in. Available visualizers are spectrum,lorenz,ellipse. +##Defaults to spectrum,ellipse,lorenz +#visualizers=spectrum,ellipse,lorenz + + +##Configures what character the spectrum visualizer will use. Specifying a space (e.g " ") means the +##background will be colored instead of the character. Defaults to " ". +#visualizer.spectrum.character=# + +##Spectrum bar width. Defaults to 2. +#visualizer.spectrum.bar.width=2 + +##The amount of space between each bar in the spectrum visualizer. Defaults to 1. It's possible to set this to +##zero to have no space between bars +#visualizer.spectrum.bar.spacing=1 + +##Available smoothing options are monstercat, sgs, none. +#visualizer.spectrum.smoothing.mode=sgs + +##This configures the falloff effect on the spectrum visualizer. Available falloff options are fill,top,none. +##Defaults to "fill" +#visualizer.spectrum.falloff.mode=fill + +##Configures how fast the falloff character falls. This is an exponential falloff so values usually look +##best 0.9+ and small changes in this value can have a large effect. Defaults to 0.95 +#visualizer.spectrum.falloff.weight=0.95 + +##Margins in percent of total screen for spectrum visualizer. All margins default to 0 +#visualizer.spectrum.top.margin=0.30 +#visualizer.spectrum.bottom.margin=0.10 +#visualizer.spectrum.right.margin=0.10 +#visualizer.spectrum.left.margin=0.10 + +##Reverses the direction of the spectrum so that high freqs are first and low freqs last. Defaults to false. +#visualizer.spectrum.reversed=false + +##This configures the sgs smoothing effect on the spectrum visualizer. More points spreads out the smoothing +##effect and increasing passes runs the smoother multiple times on reach run. Defaults are points=3 and passes=1 +#visualizer.sgs.smoothing.points=3 +#visualizer.sgs.smoothing.passes=1 + + +##Configures what character the ellipse visualizer will use. Specifying a space (e.g " ") means the +##background will be colored instead of the character. Defaults to "โ–ˆ". +#visualizer.ellipse.character=# + +##The radius of each color ring in the ellipse visualizer. Defaults to 2. +#visualizer.ellipse.radius=2 + + +##Configures what character the lorenz visualizer will use. Specifying a space (e.g " ") means the +##background will be colored instead of the character. Defaults to "โ–ˆ". +#visualizer.lorenz.character=# + + +##Turns off overriding the user's terminal colors. This is true by default. +#colors.override.terminal=false + +##Specifies the color scheme. The color scheme must be in ~/.config/vis/colors/ directory. The default scheme is "colors". +#colors.scheme=rainbow diff --git a/stow/vis/dot-config/vis/colors/basic_colors b/stow/vis/dot-config/vis/colors/basic_colors deleted file mode 100644 index 4be5fa4..0000000 --- a/stow/vis/dot-config/vis/colors/basic_colors +++ /dev/null @@ -1,15 +0,0 @@ -4 -12 -6 -14 -2 -10 -11 -3 -5 -1 -13 -9 -7 -15 -0 diff --git a/stow/vis/dot-config/vis/colors/rainbow b/stow/vis/dot-config/vis/colors/rainbow deleted file mode 100644 index 13714c5..0000000 --- a/stow/vis/dot-config/vis/colors/rainbow +++ /dev/null @@ -1,30 +0,0 @@ -#1F80F3 -#08ADD8 -#06B3D4 -#01D7AF -#01DBA9 -#0DF47E -#26FE53 -#2CFF4B -#4FF829 -#58F522 -#83DE0B -#8FD506 -#ADBB01 -#BEAA01 -#D78C07 -#E27C0D -#F65525 -#F94C2B -#FE2A4D -#FE2456 -#F20B81 -#D901AC -#D501B2 -#B007D6 -#AA09DA -#7C21F4 -#6D2DF9 -#5541FE -#3E58FE -#2A70F9 diff --git a/stow/vis/dot-config/vis/config b/stow/vis/dot-config/vis/config deleted file mode 100644 index a68497a..0000000 --- a/stow/vis/dot-config/vis/config +++ /dev/null @@ -1,91 +0,0 @@ -##Refresh rate of the visualizers. A really high refresh rate may cause screen tearing. Default is 20. -#visualizer.fps=20 - -##Sets the audio sources to use. Currently available ones are "mpd" and "alsa"Sets the audio sources to use. -##Currently available ones are "mpd", "pulse" and "alsa". Defaults to "mpd". -#audio.sources=pulse - -##vis tries to find the correct pulseaudio sink, however this will not work on all systems. -##If pulse audio is not working with vis try switching the audio source. A list can be found by running the -##command pacmd list-sinks | grep -e 'name:' -e 'index' -#audio.pulse.source=0 - -##Defaults to "/tmp/mpd.fifo" -#mpd.fifo.path=/tmp/mpd.fifo - -##If set to false the visualizers will use mono mode instead of stereo. Some visualizers will -##behave differently when mono is enabled. For example, spectrum show two sets of bars. -#audio.stereo.enabled=false - -##Specifies how often the visualizer will change in seconds. 0 means do not rotate. Default is 0. -#visualizer.rotation.secs=10 - -##Configures the samples rate and the cutoff frequencies. -#audio.sampling.frequency=44100 -#audio.low.cutoff.frequency=30 -#audio.high.cutoff.frequency=22050 - -##Applies scaling factor to both lorenz and ellipse visualizers. This is useful when the system audio is set -#to a low volume. -#visualizer.scaling.multiplier=1.0 - -##Configures the visualizers and the order they are in. Available visualizers are spectrum,lorenz,ellipse. -##Defaults to spectrum,ellipse,lorenz -#visualizers=spectrum,ellipse,lorenz - - -##Configures what character the spectrum visualizer will use. Specifying a space (e.g " ") means the -##background will be colored instead of the character. Defaults to " ". -#visualizer.spectrum.character=# - -##Spectrum bar width. Defaults to 2. -#visualizer.spectrum.bar.width=2 - -##The amount of space between each bar in the spectrum visualizer. Defaults to 1. It's possible to set this to -##zero to have no space between bars -#visualizer.spectrum.bar.spacing=1 - -##Available smoothing options are monstercat, sgs, none. -#visualizer.spectrum.smoothing.mode=sgs - -##This configures the falloff effect on the spectrum visualizer. Available falloff options are fill,top,none. -##Defaults to "fill" -#visualizer.spectrum.falloff.mode=fill - -##Configures how fast the falloff character falls. This is an exponential falloff so values usually look -##best 0.9+ and small changes in this value can have a large effect. Defaults to 0.95 -#visualizer.spectrum.falloff.weight=0.95 - -##Margins in percent of total screen for spectrum visualizer. All margins default to 0 -#visualizer.spectrum.top.margin=0.30 -#visualizer.spectrum.bottom.margin=0.10 -#visualizer.spectrum.right.margin=0.10 -#visualizer.spectrum.left.margin=0.10 - -##Reverses the direction of the spectrum so that high freqs are first and low freqs last. Defaults to false. -#visualizer.spectrum.reversed=false - -##This configures the sgs smoothing effect on the spectrum visualizer. More points spreads out the smoothing -##effect and increasing passes runs the smoother multiple times on reach run. Defaults are points=3 and passes=1 -#visualizer.sgs.smoothing.points=3 -#visualizer.sgs.smoothing.passes=1 - - -##Configures what character the ellipse visualizer will use. Specifying a space (e.g " ") means the -##background will be colored instead of the character. Defaults to "โ–ˆ". -#visualizer.ellipse.character=# - -##The radius of each color ring in the ellipse visualizer. Defaults to 2. -#visualizer.ellipse.radius=2 - - -##Configures what character the lorenz visualizer will use. Specifying a space (e.g " ") means the -##background will be colored instead of the character. Defaults to "โ–ˆ". -#visualizer.lorenz.character=# - - -##Turns off overriding the user's terminal colors. This is true by default. -#colors.override.terminal=false - -##Specifies the color scheme. The color scheme must be in ~/.config/vis/colors/ directory. The default scheme is "colors". -#colors.scheme=rainbow diff --git a/stow/zathura/.config/zathura/zathurarc b/stow/zathura/.config/zathura/zathurarc new file mode 100644 index 0000000..78e873b --- /dev/null +++ b/stow/zathura/.config/zathura/zathurarc @@ -0,0 +1,58 @@ +set page-padding 1 +set selection-clipboard clipboard +set statusbar-home-tilde true +set guioptions shv + +# Colors + +# Outside the document +set default-bg "#000000" + +# Status bar +set statusbar-bg "#1d2021" +set statusbar-fg "#fbf1c7" +set font "mononoki 10" + +# Document light and dark colors +set recolor false # recolor at start +set recolor-keephue false + +#set recolor-lightcolor "#232f40" +set recolor-lightcolor "#1d2021" + +# Solarized +# Dark +#set recolor-darkcolor "#fdf6e3" #base3 (lighest) +set recolor-darkcolor "#eee8d5" #base2 +#set recolor-darkcolor "#93a1a1" #base1 +#set recolor-darkcolor "#2aa198" #cyan +#set recolor-darkcolor "#268bd2" #blue +#set recolor-lightcolor "#073642" #base02 +#set recolor-lightcolor "#002b36" #base03 (darkest) +# Light +#set recolor-darkcolor "#002b36" #base03 (darkest) +#set recolor-lightcolor "#fdf6e3" #base3 (lighest) + +# based on custom dmenu +#set recolor-darkcolor "#ffffff" +#set recolor-lightcolor "#093145" + +# Keep images color +set recolor-reverse-video false +# Use same hue when recoloring +set recolor-keephue false + +map u scroll half-up +map d scroll half-down +map D toggle_page_mode +map b toggle_statusbar +map r reload +map R rotate +map p print +map Y exec 'echo "%" | xsel -bi; dunstify "%"' +map I exec '/home/taamas/scripts/pdfs/pdfSxiv.sh "%"' +#map y feedkeys "d" +#map P change_mode presentation + +#map x exec 'scp "%" taamas@93.156.110.0:~/pdfs' +#map X exec 'scp "%" taamas@93.156.110.0:/srv/http/files' diff --git a/stow/zathura/dot-config/zathura/zathurarc b/stow/zathura/dot-config/zathura/zathurarc deleted file mode 100644 index 78e873b..0000000 --- a/stow/zathura/dot-config/zathura/zathurarc +++ /dev/null @@ -1,58 +0,0 @@ -set page-padding 1 -set selection-clipboard clipboard -set statusbar-home-tilde true -set guioptions shv - -# Colors - -# Outside the document -set default-bg "#000000" - -# Status bar -set statusbar-bg "#1d2021" -set statusbar-fg "#fbf1c7" -set font "mononoki 10" - -# Document light and dark colors -set recolor false # recolor at start -set recolor-keephue false - -#set recolor-lightcolor "#232f40" -set recolor-lightcolor "#1d2021" - -# Solarized -# Dark -#set recolor-darkcolor "#fdf6e3" #base3 (lighest) -set recolor-darkcolor "#eee8d5" #base2 -#set recolor-darkcolor "#93a1a1" #base1 -#set recolor-darkcolor "#2aa198" #cyan -#set recolor-darkcolor "#268bd2" #blue -#set recolor-lightcolor "#073642" #base02 -#set recolor-lightcolor "#002b36" #base03 (darkest) -# Light -#set recolor-darkcolor "#002b36" #base03 (darkest) -#set recolor-lightcolor "#fdf6e3" #base3 (lighest) - -# based on custom dmenu -#set recolor-darkcolor "#ffffff" -#set recolor-lightcolor "#093145" - -# Keep images color -set recolor-reverse-video false -# Use same hue when recoloring -set recolor-keephue false - -map u scroll half-up -map d scroll half-down -map D toggle_page_mode -map b toggle_statusbar -map r reload -map R rotate -map p print -map Y exec 'echo "%" | xsel -bi; dunstify "%"' -map I exec '/home/taamas/scripts/pdfs/pdfSxiv.sh "%"' -#map y feedkeys "d" -#map P change_mode presentation - -#map x exec 'scp "%" taamas@93.156.110.0:~/pdfs' -#map X exec 'scp "%" taamas@93.156.110.0:/srv/http/files' -- cgit v1.2.1