From 03cc854bfc3fa9a27449d2a2eeb6c665dc1bb89d5e71bfe5beb909d554e971c2 Mon Sep 17 00:00:00 2001 From: Philipp Date: Wed, 19 Jun 2024 00:06:56 +0200 Subject: [PATCH] First commit --- README.md | 23 + alacritty/.config/alacritty/alacritty.toml | 15 + alacritty/.config/alacritty/dracula.toml | 76 + nvim/.config/nvim/init.vim | 44 + .../nerdtree/.github/ISSUE_TEMPLATE/bug.md | 46 + .../.github/ISSUE_TEMPLATE/feature_request.md | 8 + .../.github/ISSUE_TEMPLATE/question.md | 13 + .../nerdtree/.github/PULL_REQUEST_TEMPLATE.md | 7 + .../nerdtree/.github/workflows/vint.yml | 15 + nvim/.vim/plugged/nerdtree/.gitignore | 3 + nvim/.vim/plugged/nerdtree/.vintrc.yaml | 5 + nvim/.vim/plugged/nerdtree/CHANGELOG.md | 343 + nvim/.vim/plugged/nerdtree/LICENCE | 13 + nvim/.vim/plugged/nerdtree/README.markdown | 261 + nvim/.vim/plugged/nerdtree/_config.yml | 1 + .../plugged/nerdtree/autoload/nerdtree.vim | 315 + .../nerdtree/autoload/nerdtree/ui_glue.vim | 756 + nvim/.vim/plugged/nerdtree/doc/NERDTree.txt | 1587 ++ .../nerdtree/lib/nerdtree/bookmark.vim | 365 + .../plugged/nerdtree/lib/nerdtree/creator.vim | 438 + .../plugged/nerdtree/lib/nerdtree/event.vim | 13 + .../nerdtree/lib/nerdtree/flag_set.vim | 58 + .../plugged/nerdtree/lib/nerdtree/key_map.vim | 164 + .../nerdtree/lib/nerdtree/menu_controller.vim | 211 + .../nerdtree/lib/nerdtree/menu_item.vim | 118 + .../nerdtree/lib/nerdtree/nerdtree.vim | 209 + .../nerdtree/lib/nerdtree/notifier.vim | 35 + .../plugged/nerdtree/lib/nerdtree/opener.vim | 326 + .../plugged/nerdtree/lib/nerdtree/path.vim | 867 + .../nerdtree/lib/nerdtree/tree_dir_node.vim | 720 + .../nerdtree/lib/nerdtree/tree_file_node.vim | 349 + .../.vim/plugged/nerdtree/lib/nerdtree/ui.vim | 558 + .../nerdtree_plugin/exec_menuitem.vim | 40 + .../nerdtree/nerdtree_plugin/fs_menu.vim | 557 + .../plugged/nerdtree/nerdtree_plugin/vcs.vim | 47 + .../plugged/nerdtree/plugin/NERD_tree.vim | 240 + nvim/.vim/plugged/nerdtree/screenshot.png | Bin 0 -> 87896 bytes .../.vim/plugged/nerdtree/syntax/nerdtree.vim | 97 + .../vim-devicons/.github/ISSUE_TEMPLATE.md | 24 + .../.github/PULL_REQUEST_TEMPLATE.md | 15 + .../vim-devicons/.github/workflows/ci.yml | 42 + .../vim-devicons/.github/workflows/vint.yml | 32 + nvim/.vim/plugged/vim-devicons/.gitignore | 5 + nvim/.vim/plugged/vim-devicons/CHANGELOG.md | 249 + .../plugged/vim-devicons/CODE_OF_CONDUCT.md | 76 + .../.vim/plugged/vim-devicons/CONTRIBUTING.md | 18 + nvim/.vim/plugged/vim-devicons/DEVELOPER.md | 68 + nvim/.vim/plugged/vim-devicons/LICENSE | 22 + nvim/.vim/plugged/vim-devicons/README.md | 107 + .../tabline/formatters/webdevicons.vim | 14 + .../autoload/devicons/plugins/ctrlp.vim | 30 + .../autoload/devicons/plugins/denite.vim | 10 + .../autoload/devicons/plugins/flagship.vim | 15 + .../autoload/devicons/plugins/startify.vim | 6 + .../autoload/devicons/plugins/unite.vim | 37 + .../autoload/devicons/plugins/vimfiler.vim | 8 + .../autoload/vimfiler/columns/devicons.vim | 80 + .../plugged/vim-devicons/doc/webdevicons.txt | 1078 + .../nerdtree_plugin/webdevicons.vim | 389 + .../vim-devicons/plugin/webdevicons.vim | 703 + .../pythonx/vim_devicons/__init__.py | 2 + .../vim_devicons/powerline/__init__.py | 2 + .../vim_devicons/powerline/segments.py | 28 + .../filter/devicons_denite_converter.py | 31 + nvim/.vim/plugged/vim-devicons/test/.themisrc | 1 + .../vim-devicons/test/default_setting.vim | 39 + .../plugged/vim-devicons/test/fileformat.vim | 29 + .../plugged/vim-devicons/test/filetype.vim | 344 + .../plugged/vim/.github/issue_template.md | 45 + .../vim/.github/pull_request_template.md | 5 + nvim/.vim/plugged/vim/.gitignore | 1 + nvim/.vim/plugged/vim/INSTALL.md | 108 + nvim/.vim/plugged/vim/LICENSE | 21 + nvim/.vim/plugged/vim/README.md | 34 + .../.vim/plugged/vim/after/plugin/dracula.vim | 238 + nvim/.vim/plugged/vim/after/syntax/css.vim | 15 + .../plugged/vim/after/syntax/gitcommit.vim | 12 + nvim/.vim/plugged/vim/after/syntax/html.vim | 9 + .../plugged/vim/after/syntax/javascript.vim | 45 + .../vim/after/syntax/javascriptreact.vim | 1 + nvim/.vim/plugged/vim/after/syntax/json.vim | 6 + nvim/.vim/plugged/vim/after/syntax/lua.vim | 22 + .../plugged/vim/after/syntax/markdown.vim | 50 + nvim/.vim/plugged/vim/after/syntax/ocaml.vim | 7 + nvim/.vim/plugged/vim/after/syntax/perl.vim | 38 + nvim/.vim/plugged/vim/after/syntax/php.vim | 10 + .../plugged/vim/after/syntax/plantuml.vim | 13 + .../plugged/vim/after/syntax/purescript.vim | 9 + nvim/.vim/plugged/vim/after/syntax/python.vim | 11 + nvim/.vim/plugged/vim/after/syntax/rst.vim | 26 + nvim/.vim/plugged/vim/after/syntax/ruby.vim | 16 + nvim/.vim/plugged/vim/after/syntax/rust.vim | 5 + nvim/.vim/plugged/vim/after/syntax/sass.vim | 12 + nvim/.vim/plugged/vim/after/syntax/sh.vim | 8 + nvim/.vim/plugged/vim/after/syntax/tex.vim | 16 + .../plugged/vim/after/syntax/typescript.vim | 57 + .../vim/after/syntax/typescriptreact.vim | 22 + nvim/.vim/plugged/vim/after/syntax/vim.vim | 14 + nvim/.vim/plugged/vim/after/syntax/xml.vim | 13 + nvim/.vim/plugged/vim/after/syntax/yaml.vim | 12 + .../vim/autoload/airline/themes/dracula.vim | 160 + nvim/.vim/plugged/vim/autoload/dracula.vim | 57 + .../lightline/colorscheme/dracula.vim | 42 + nvim/.vim/plugged/vim/colors/dracula.vim | 378 + nvim/.vim/plugged/vim/doc/dracula.txt | 173 + nvim/.vim/plugged/vim/dracula-pro.png | Bin 0 -> 339197 bytes nvim/.vim/plugged/vim/screenshot.png | Bin 0 -> 336007 bytes plasma/.config/gtkrc-2.0 | 5 + plasma/.config/kded5rc | 2 + plasma/.config/kdeglobals | 125 + plasma/.config/kglobalshortcutsrc | 259 + plasma/.config/kwinoutputconfig.json | 167 + plasma/.config/kwinrc | 26 + plasma/.config/plasma-localerc | 9 + .../plasma-org.kde.plasma.desktop-appletsrc | 220 + plasma/.config/plasmanotifyrc | 5 + plasma/.config/plasmaparc | 0 plasma/.config/plasmashellrc | 9 + plasma/.config/spectaclerc | 12 + zsh/.oh-my-zsh/.editorconfig | 11 + zsh/.oh-my-zsh/.github/CODEOWNERS | 14 + zsh/.oh-my-zsh/.github/FUNDING.yml | 2 + .../.github/ISSUE_TEMPLATE/bug_report.yml | 68 + .../.github/ISSUE_TEMPLATE/bug_report_omz.yml | 77 + .../.github/ISSUE_TEMPLATE/config.yml | 8 + .../ISSUE_TEMPLATE/feature_request.yml | 37 + .../.github/PULL_REQUEST_TEMPLATE.md | 20 + zsh/.oh-my-zsh/.github/dependabot.yml | 12 + zsh/.oh-my-zsh/.github/dependencies.yml | 46 + .../.github/workflows/dependencies.yml | 36 + .../workflows/dependencies/requirements.txt | 7 + .../.github/workflows/dependencies/updater.py | 598 + .../.github/workflows/installer.yml | 56 + .../.github/workflows/installer/.gitignore | 1 + .../.github/workflows/installer/.vercelignore | 2 + .../.github/workflows/installer/vercel.json | 23 + zsh/.oh-my-zsh/.github/workflows/main.yml | 38 + zsh/.oh-my-zsh/.github/workflows/project.yml | 146 + zsh/.oh-my-zsh/.gitignore | 12 + zsh/.oh-my-zsh/.gitpod.Dockerfile | 5 + zsh/.oh-my-zsh/.gitpod.yml | 9 + zsh/.oh-my-zsh/.prettierrc | 4 + zsh/.oh-my-zsh/CODE_OF_CONDUCT.md | 76 + zsh/.oh-my-zsh/CONTRIBUTING.md | 245 + zsh/.oh-my-zsh/LICENSE.txt | 21 + zsh/.oh-my-zsh/README.md | 489 + zsh/.oh-my-zsh/SECURITY.md | 23 + zsh/.oh-my-zsh/lib/async_prompt.zsh | 144 + zsh/.oh-my-zsh/lib/bzr.zsh | 10 + zsh/.oh-my-zsh/lib/cli.zsh | 839 + zsh/.oh-my-zsh/lib/clipboard.zsh | 107 + zsh/.oh-my-zsh/lib/compfix.zsh | 44 + zsh/.oh-my-zsh/lib/completion.zsh | 78 + zsh/.oh-my-zsh/lib/correction.zsh | 10 + zsh/.oh-my-zsh/lib/diagnostics.zsh | 353 + zsh/.oh-my-zsh/lib/directories.zsh | 40 + zsh/.oh-my-zsh/lib/functions.zsh | 267 + zsh/.oh-my-zsh/lib/git.zsh | 334 + zsh/.oh-my-zsh/lib/grep.zsh | 41 + zsh/.oh-my-zsh/lib/history.zsh | 41 + zsh/.oh-my-zsh/lib/key-bindings.zsh | 145 + zsh/.oh-my-zsh/lib/misc.zsh | 38 + zsh/.oh-my-zsh/lib/nvm.zsh | 6 + zsh/.oh-my-zsh/lib/prompt_info_functions.zsh | 44 + zsh/.oh-my-zsh/lib/spectrum.zsh | 38 + zsh/.oh-my-zsh/lib/termsupport.zsh | 163 + zsh/.oh-my-zsh/lib/tests/cli.test.zsh | 169 + zsh/.oh-my-zsh/lib/theme-and-appearance.zsh | 81 + zsh/.oh-my-zsh/lib/vcs_info.zsh | 53 + zsh/.oh-my-zsh/oh-my-zsh.sh | 238 + .../plugins/1password/1password.plugin.zsh | 9 + zsh/.oh-my-zsh/plugins/1password/README.md | 40 + zsh/.oh-my-zsh/plugins/1password/_opswd | 19 + zsh/.oh-my-zsh/plugins/1password/opswd | 90 + zsh/.oh-my-zsh/plugins/adb/README.md | 8 + zsh/.oh-my-zsh/plugins/adb/_adb | 67 + zsh/.oh-my-zsh/plugins/ag/README.md | 13 + zsh/.oh-my-zsh/plugins/ag/_ag | 66 + .../plugins/alias-finder/.zunit.yml | 9 + zsh/.oh-my-zsh/plugins/alias-finder/README.md | 33 + .../alias-finder/alias-finder.plugin.zsh | 62 + .../alias-finder/tests/_output/.gitkeep | 0 .../alias-finder/tests/_support/.gitkeep | 0 .../alias-finder/tests/_support/bootstrap | 2 + .../plugins/alias-finder/tests/test_run.sh | 107 + zsh/.oh-my-zsh/plugins/aliases/.gitignore | 1 + zsh/.oh-my-zsh/plugins/aliases/README.md | 28 + .../plugins/aliases/aliases.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/aliases/cheatsheet.py | 69 + zsh/.oh-my-zsh/plugins/aliases/termcolor.py | 168 + zsh/.oh-my-zsh/plugins/ansible/README.md | 33 + .../plugins/ansible/ansible.plugin.zsh | 28 + zsh/.oh-my-zsh/plugins/ant/README.md | 12 + zsh/.oh-my-zsh/plugins/ant/_ant | 22 + zsh/.oh-my-zsh/plugins/ant/ant.plugin.zsh | 2 + .../plugins/apache2-macports/README.md | 21 + .../apache2-macports.plugin.zsh | 6 + zsh/.oh-my-zsh/plugins/arcanist/README.md | 43 + .../plugins/arcanist/arcanist.plugin.zsh | 39 + zsh/.oh-my-zsh/plugins/archlinux/README.md | 184 + .../plugins/archlinux/archlinux.plugin.zsh | 203 + zsh/.oh-my-zsh/plugins/argocd/README.md | 20 + .../plugins/argocd/argocd.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/asdf/README.md | 30 + zsh/.oh-my-zsh/plugins/asdf/asdf.plugin.zsh | 30 + zsh/.oh-my-zsh/plugins/autoenv/README.md | 20 + .../plugins/autoenv/autoenv.plugin.zsh | 80 + zsh/.oh-my-zsh/plugins/autojump/README.md | 11 + .../plugins/autojump/autojump.plugin.zsh | 40 + zsh/.oh-my-zsh/plugins/autopep8/README.md | 8 + zsh/.oh-my-zsh/plugins/autopep8/_autopep8 | 32 + zsh/.oh-my-zsh/plugins/aws/README.md | 98 + zsh/.oh-my-zsh/plugins/aws/aws.plugin.zsh | 338 + zsh/.oh-my-zsh/plugins/azure/README.md | 49 + zsh/.oh-my-zsh/plugins/azure/azure.plugin.zsh | 60 + zsh/.oh-my-zsh/plugins/battery/README.md | 29 + .../plugins/battery/battery.plugin.zsh | 306 + zsh/.oh-my-zsh/plugins/bazel/README.md | 22 + zsh/.oh-my-zsh/plugins/bazel/_bazel | 341 + zsh/.oh-my-zsh/plugins/bazel/bazel.plugin.zsh | 5 + zsh/.oh-my-zsh/plugins/bbedit/README.md | 20 + .../plugins/bbedit/bbedit.plugin.zsh | 21 + zsh/.oh-my-zsh/plugins/bedtools/README.md | 5 + zsh/.oh-my-zsh/plugins/bedtools/_bedtools | 64 + zsh/.oh-my-zsh/plugins/bgnotify/README.md | 63 + .../plugins/bgnotify/bgnotify.plugin.zsh | 141 + zsh/.oh-my-zsh/plugins/bower/README.md | 17 + zsh/.oh-my-zsh/plugins/bower/_bower | 58 + zsh/.oh-my-zsh/plugins/bower/bower.plugin.zsh | 84 + zsh/.oh-my-zsh/plugins/branch/README.md | 49 + .../plugins/branch/branch.plugin.zsh | 35 + zsh/.oh-my-zsh/plugins/brew/README.md | 43 + zsh/.oh-my-zsh/plugins/brew/brew.plugin.zsh | 60 + zsh/.oh-my-zsh/plugins/bridgetown/README.md | 26 + .../plugins/bridgetown/bridgetown.plugin.zsh | 12 + zsh/.oh-my-zsh/plugins/bun/README.md | 20 + zsh/.oh-my-zsh/plugins/bun/bun.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/bundler/README.md | 74 + zsh/.oh-my-zsh/plugins/bundler/_bundler | 105 + .../plugins/bundler/bundler.plugin.zsh | 127 + zsh/.oh-my-zsh/plugins/cabal/README.md | 9 + zsh/.oh-my-zsh/plugins/cabal/cabal.plugin.zsh | 93 + zsh/.oh-my-zsh/plugins/cake/README.md | 15 + zsh/.oh-my-zsh/plugins/cake/cake.plugin.zsh | 33 + zsh/.oh-my-zsh/plugins/cakephp3/README.md | 16 + .../plugins/cakephp3/cakephp3.plugin.zsh | 38 + zsh/.oh-my-zsh/plugins/capistrano/README.md | 14 + zsh/.oh-my-zsh/plugins/capistrano/_capistrano | 49 + .../plugins/capistrano/capistrano.plugin.zsh | 11 + zsh/.oh-my-zsh/plugins/cask/README.md | 15 + zsh/.oh-my-zsh/plugins/cask/cask.plugin.zsh | 26 + zsh/.oh-my-zsh/plugins/catimg/README.md | 23 + .../plugins/catimg/catimg.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/catimg/catimg.sh | 88 + zsh/.oh-my-zsh/plugins/catimg/colors.png | Bin 0 -> 353 bytes zsh/.oh-my-zsh/plugins/celery/README.md | 9 + zsh/.oh-my-zsh/plugins/celery/_celery | 129 + zsh/.oh-my-zsh/plugins/charm/README.md | 9 + zsh/.oh-my-zsh/plugins/charm/charm.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/chruby/README.md | 21 + .../plugins/chruby/chruby.plugin.zsh | 94 + zsh/.oh-my-zsh/plugins/chucknorris/.gitignore | 1 + zsh/.oh-my-zsh/plugins/chucknorris/README.md | 38 + .../chucknorris/chucknorris.plugin.zsh | 24 + .../plugins/chucknorris/fortunes/chucknorris | 568 + zsh/.oh-my-zsh/plugins/cloudfoundry/README.md | 58 + .../cloudfoundry/cloudfoundry.plugin.zsh | 34 + zsh/.oh-my-zsh/plugins/codeclimate/README.md | 8 + .../plugins/codeclimate/_codeclimate | 82 + zsh/.oh-my-zsh/plugins/coffee/README.md | 31 + zsh/.oh-my-zsh/plugins/coffee/_coffee | 81 + .../plugins/coffee/coffee.plugin.zsh | 16 + zsh/.oh-my-zsh/plugins/colemak/.gitignore | 1 + zsh/.oh-my-zsh/plugins/colemak/README.md | 48 + zsh/.oh-my-zsh/plugins/colemak/colemak-less | 6 + .../plugins/colemak/colemak.plugin.zsh | 38 + .../plugins/colored-man-pages/README.md | 32 + .../colored-man-pages.plugin.zsh | 54 + .../plugins/colored-man-pages/nroff | 12 + zsh/.oh-my-zsh/plugins/colorize/README.md | 56 + .../plugins/colorize/colorize.plugin.zsh | 114 + .../plugins/command-not-found/README.md | 34 + .../command-not-found.plugin.zsh | 70 + .../plugins/common-aliases/README.md | 130 + .../common-aliases/common-aliases.plugin.zsh | 90 + zsh/.oh-my-zsh/plugins/compleat/README.md | 9 + .../plugins/compleat/compleat.plugin.zsh | 20 + zsh/.oh-my-zsh/plugins/composer/README.md | 35 + .../plugins/composer/composer.plugin.zsh | 76 + zsh/.oh-my-zsh/plugins/copybuffer/README.md | 11 + .../plugins/copybuffer/copybuffer.plugin.zsh | 16 + zsh/.oh-my-zsh/plugins/copyfile/README.md | 11 + .../plugins/copyfile/copyfile.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/copypath/README.md | 15 + .../plugins/copypath/copypath.plugin.zsh | 15 + zsh/.oh-my-zsh/plugins/cp/README.md | 32 + zsh/.oh-my-zsh/plugins/cp/cp.plugin.zsh | 4 + zsh/.oh-my-zsh/plugins/cpanm/README.md | 9 + zsh/.oh-my-zsh/plugins/cpanm/_cpanm | 64 + zsh/.oh-my-zsh/plugins/dash/README.md | 28 + zsh/.oh-my-zsh/plugins/dash/dash.plugin.zsh | 84 + zsh/.oh-my-zsh/plugins/dbt/README.md | 29 + zsh/.oh-my-zsh/plugins/dbt/dbt.plugin.zsh | 23 + zsh/.oh-my-zsh/plugins/debian/README.md | 92 + .../plugins/debian/debian.plugin.zsh | 227 + zsh/.oh-my-zsh/plugins/deno/README.md | 20 + zsh/.oh-my-zsh/plugins/deno/deno.plugin.zsh | 28 + zsh/.oh-my-zsh/plugins/dircycle/README.md | 78 + .../plugins/dircycle/dircycle.plugin.zsh | 54 + zsh/.oh-my-zsh/plugins/direnv/README.md | 15 + .../plugins/direnv/direnv.plugin.zsh | 16 + zsh/.oh-my-zsh/plugins/dirhistory/README.md | 62 + .../plugins/dirhistory/dirhistory.plugin.zsh | 225 + zsh/.oh-my-zsh/plugins/dirpersist/README.md | 10 + .../plugins/dirpersist/dirpersist.plugin.zsh | 21 + zsh/.oh-my-zsh/plugins/dnf/README.md | 32 + zsh/.oh-my-zsh/plugins/dnf/dnf.plugin.zsh | 19 + zsh/.oh-my-zsh/plugins/dnote/README.md | 51 + zsh/.oh-my-zsh/plugins/dnote/_dnote | 39 + .../plugins/docker-compose/README.md | 34 + .../plugins/docker-compose/_docker-compose | 421 + .../docker-compose/docker-compose.plugin.zsh | 24 + .../plugins/docker-machine/README.md | 19 + .../plugins/docker-machine/_docker-machine | 359 + .../docker-machine/docker-machine.plugin.zsh | 33 + zsh/.oh-my-zsh/plugins/docker/README.md | 80 + .../plugins/docker/completions/_docker | 3126 +++ .../plugins/docker/docker.plugin.zsh | 64 + zsh/.oh-my-zsh/plugins/doctl/README.md | 9 + zsh/.oh-my-zsh/plugins/doctl/doctl.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/dotenv/README.md | 92 + .../plugins/dotenv/dotenv.plugin.zsh | 67 + zsh/.oh-my-zsh/plugins/dotnet/README.md | 25 + .../plugins/dotnet/dotnet.plugin.zsh | 26 + zsh/.oh-my-zsh/plugins/droplr/README.md | 19 + .../plugins/droplr/droplr.plugin.zsh | 15 + zsh/.oh-my-zsh/plugins/drush/README.md | 66 + .../plugins/drush/drush.complete.sh | 50 + zsh/.oh-my-zsh/plugins/drush/drush.plugin.zsh | 107 + zsh/.oh-my-zsh/plugins/eecms/README.md | 11 + zsh/.oh-my-zsh/plugins/eecms/eecms.plugin.zsh | 20 + zsh/.oh-my-zsh/plugins/emacs/README.md | 30 + zsh/.oh-my-zsh/plugins/emacs/emacs.plugin.zsh | 68 + zsh/.oh-my-zsh/plugins/emacs/emacsclient.sh | 38 + zsh/.oh-my-zsh/plugins/ember-cli/README.md | 33 + zsh/.oh-my-zsh/plugins/ember-cli/_ember-cli | 189 + .../plugins/ember-cli/ember-cli.plugin.zsh | 12 + zsh/.oh-my-zsh/plugins/emoji-clock/README.md | 14 + .../emoji-clock/emoji-clock.plugin.zsh | 33 + zsh/.oh-my-zsh/plugins/emoji/README.md | 127 + .../plugins/emoji/emoji-char-definitions.zsh | 7274 ++++++ zsh/.oh-my-zsh/plugins/emoji/emoji-data.txt | 4122 +++ zsh/.oh-my-zsh/plugins/emoji/emoji.plugin.zsh | 110 + zsh/.oh-my-zsh/plugins/emoji/gemoji_db.json | 21538 ++++++++++++++++ zsh/.oh-my-zsh/plugins/emoji/update_emoji.py | 213 + zsh/.oh-my-zsh/plugins/emotty/README.md | 39 + .../plugins/emotty/emotty.plugin.zsh | 55 + .../plugins/emotty/emotty_emoji_set.zsh | 24 + .../plugins/emotty/emotty_floral_set.zsh | 18 + .../plugins/emotty/emotty_love_set.zsh | 34 + .../plugins/emotty/emotty_nature_set.zsh | 58 + .../plugins/emotty/emotty_stellar_set.zsh | 25 + .../plugins/emotty/emotty_zodiac_set.zsh | 29 + zsh/.oh-my-zsh/plugins/encode64/README.md | 73 + .../plugins/encode64/encode64.plugin.zsh | 27 + zsh/.oh-my-zsh/plugins/extract/README.md | 65 + zsh/.oh-my-zsh/plugins/extract/_extract | 7 + .../plugins/extract/extract.plugin.zsh | 137 + zsh/.oh-my-zsh/plugins/eza/README.md | 111 + zsh/.oh-my-zsh/plugins/eza/eza.plugin.zsh | 65 + zsh/.oh-my-zsh/plugins/fabric/README.md | 9 + zsh/.oh-my-zsh/plugins/fabric/_fab | 69 + .../plugins/fabric/fabric.plugin.zsh | 0 zsh/.oh-my-zsh/plugins/fancy-ctrl-z/README.md | 14 + .../fancy-ctrl-z/fancy-ctrl-z.plugin.zsh | 12 + zsh/.oh-my-zsh/plugins/fasd/README.md | 21 + zsh/.oh-my-zsh/plugins/fasd/fasd.plugin.zsh | 16 + zsh/.oh-my-zsh/plugins/fastfile/README.md | 85 + .../plugins/fastfile/fastfile.plugin.zsh | 128 + zsh/.oh-my-zsh/plugins/fbterm/README.md | 10 + .../plugins/fbterm/fbterm.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/fd/README.md | 9 + zsh/.oh-my-zsh/plugins/fd/_fd | 273 + zsh/.oh-my-zsh/plugins/fig/README.md | 9 + zsh/.oh-my-zsh/plugins/fig/fig.plugin.zsh | 13 + zsh/.oh-my-zsh/plugins/firewalld/README.md | 22 + .../plugins/firewalld/firewalld.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/flutter/README.md | 28 + .../plugins/flutter/flutter.plugin.zsh | 29 + zsh/.oh-my-zsh/plugins/fluxcd/README.md | 9 + .../plugins/fluxcd/fluxcd.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/fnm/README.md | 9 + zsh/.oh-my-zsh/plugins/fnm/fnm.plugin.zsh | 13 + zsh/.oh-my-zsh/plugins/forklift/README.md | 23 + .../plugins/forklift/forklift.plugin.zsh | 128 + zsh/.oh-my-zsh/plugins/fossil/README.md | 7 + zsh/.oh-my-zsh/plugins/fossil/_fossil | 32 + .../plugins/fossil/fossil.plugin.zsh | 56 + .../plugins/frontend-search/README.md | 85 + .../plugins/frontend-search/_frontend | 161 + .../frontend-search.plugin.zsh | 119 + zsh/.oh-my-zsh/plugins/fzf/README.md | 52 + zsh/.oh-my-zsh/plugins/fzf/fzf.plugin.zsh | 274 + zsh/.oh-my-zsh/plugins/gas/README.md | 10 + zsh/.oh-my-zsh/plugins/gas/_gas | 39 + zsh/.oh-my-zsh/plugins/gatsby/README.md | 7 + zsh/.oh-my-zsh/plugins/gatsby/_gatsby | 24 + zsh/.oh-my-zsh/plugins/gcloud/README.md | 24 + .../plugins/gcloud/gcloud.plugin.zsh | 52 + zsh/.oh-my-zsh/plugins/geeknote/README.md | 10 + zsh/.oh-my-zsh/plugins/geeknote/_geeknote | 157 + .../plugins/geeknote/geeknote.plugin.zsh | 2 + zsh/.oh-my-zsh/plugins/gem/README.md | 17 + zsh/.oh-my-zsh/plugins/gem/_gem | 72 + zsh/.oh-my-zsh/plugins/gem/gem.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/genpass/README.md | 66 + zsh/.oh-my-zsh/plugins/genpass/genpass-apple | 79 + zsh/.oh-my-zsh/plugins/genpass/genpass-monkey | 32 + zsh/.oh-my-zsh/plugins/genpass/genpass-xkcd | 68 + .../plugins/genpass/genpass.plugin.zsh | 1 + zsh/.oh-my-zsh/plugins/gh/README.md | 23 + zsh/.oh-my-zsh/plugins/gh/gh.plugin.zsh | 14 + .../plugins/git-auto-fetch/README.md | 50 + .../git-auto-fetch/git-auto-fetch.plugin.zsh | 65 + zsh/.oh-my-zsh/plugins/git-commit/README.md | 47 + .../plugins/git-commit/git-commit.plugin.zsh | 58 + .../plugins/git-escape-magic/README.md | 16 + .../plugins/git-escape-magic/git-escape-magic | 135 + .../git-escape-magic.plugin.zsh | 9 + zsh/.oh-my-zsh/plugins/git-extras/README.md | 17 + .../plugins/git-extras/git-extras.plugin.zsh | 418 + zsh/.oh-my-zsh/plugins/git-flow-avh/README.md | 19 + .../git-flow-avh/git-flow-avh.plugin.zsh | 526 + zsh/.oh-my-zsh/plugins/git-flow/README.md | 40 + zsh/.oh-my-zsh/plugins/git-flow/_git-flow | 327 + .../plugins/git-flow/git-flow.plugin.zsh | 32 + zsh/.oh-my-zsh/plugins/git-hubflow/README.md | 24 + .../git-hubflow/git-hubflow.plugin.zsh | 333 + zsh/.oh-my-zsh/plugins/git-lfs/README.md | 24 + .../plugins/git-lfs/git-lfs.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/git-prompt/README.md | 72 + .../plugins/git-prompt/git-prompt.plugin.zsh | 113 + .../plugins/git-prompt/gitstatus.py | 103 + zsh/.oh-my-zsh/plugins/git/README.md | 283 + zsh/.oh-my-zsh/plugins/git/git.plugin.zsh | 423 + zsh/.oh-my-zsh/plugins/gitfast/README.md | 9 + zsh/.oh-my-zsh/plugins/gitfast/_git | 286 + .../plugins/gitfast/git-completion.bash | 3560 +++ zsh/.oh-my-zsh/plugins/gitfast/git-prompt.sh | 594 + .../plugins/gitfast/gitfast.plugin.zsh | 11 + zsh/.oh-my-zsh/plugins/github/README.md | 45 + zsh/.oh-my-zsh/plugins/github/_hub | 174 + .../plugins/github/github.plugin.zsh | 77 + zsh/.oh-my-zsh/plugins/gitignore/README.md | 17 + .../plugins/gitignore/gitignore.plugin.zsh | 12 + zsh/.oh-my-zsh/plugins/glassfish/README.md | 9 + zsh/.oh-my-zsh/plugins/glassfish/_asadmin | 1150 + .../plugins/glassfish/glassfish.plugin.zsh | 0 zsh/.oh-my-zsh/plugins/globalias/README.md | 79 + .../plugins/globalias/globalias.plugin.zsh | 23 + zsh/.oh-my-zsh/plugins/gnu-utils/README.md | 38 + .../plugins/gnu-utils/gnu-utils.plugin.zsh | 74 + zsh/.oh-my-zsh/plugins/golang/README.md | 41 + zsh/.oh-my-zsh/plugins/golang/_golang | 249 + .../plugins/golang/golang.plugin.zsh | 38 + .../plugins/golang/templates/package.txt | 29 + .../plugins/golang/templates/search.txt | 0 zsh/.oh-my-zsh/plugins/gpg-agent/README.md | 9 + .../plugins/gpg-agent/gpg-agent.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/gradle/LICENSE | 19 + zsh/.oh-my-zsh/plugins/gradle/README.md | 30 + zsh/.oh-my-zsh/plugins/gradle/_gradle | 408 + .../plugins/gradle/gradle.plugin.zsh | 26 + zsh/.oh-my-zsh/plugins/grails/README.md | 16 + .../plugins/grails/grails.plugin.zsh | 60 + zsh/.oh-my-zsh/plugins/grc/README.md | 15 + zsh/.oh-my-zsh/plugins/grc/grc.plugin.zsh | 19 + zsh/.oh-my-zsh/plugins/grunt/README.md | 37 + zsh/.oh-my-zsh/plugins/grunt/grunt.plugin.zsh | 255 + zsh/.oh-my-zsh/plugins/gulp/README.md | 8 + zsh/.oh-my-zsh/plugins/gulp/gulp.plugin.zsh | 29 + zsh/.oh-my-zsh/plugins/hanami/README.md | 45 + .../plugins/hanami/hanami.plugin.zsh | 19 + zsh/.oh-my-zsh/plugins/hasura/README.md | 9 + .../plugins/hasura/hasura.plugin.zsh | 13 + zsh/.oh-my-zsh/plugins/helm/README.md | 19 + zsh/.oh-my-zsh/plugins/helm/helm.plugin.zsh | 19 + zsh/.oh-my-zsh/plugins/heroku-alias/README.md | 127 + .../plugins/heroku-alias/heroku.alias.sh | 92 + zsh/.oh-my-zsh/plugins/heroku/README.md | 9 + .../plugins/heroku/heroku.plugin.zsh | 9 + .../history-substring-search/README.md | 251 + .../dependencies/OMZ-README.md | 15 + .../history-substring-search.plugin.zsh | 19 + .../history-substring-search.zsh | 846 + zsh/.oh-my-zsh/plugins/history/README.md | 18 + .../plugins/history/history.plugin.zsh | 4 + zsh/.oh-my-zsh/plugins/hitchhiker/.gitignore | 1 + zsh/.oh-my-zsh/plugins/hitchhiker/README.md | 44 + .../plugins/hitchhiker/fortunes/hitchhiker | 275 + .../plugins/hitchhiker/hitchhiker.plugin.zsh | 28 + zsh/.oh-my-zsh/plugins/hitokoto/README.md | 15 + .../plugins/hitokoto/hitokoto.plugin.zsh | 18 + zsh/.oh-my-zsh/plugins/homestead/README.md | 9 + .../plugins/homestead/homestead.plugin.zsh | 10 + zsh/.oh-my-zsh/plugins/httpie/README.md | 14 + zsh/.oh-my-zsh/plugins/httpie/_httpie | 181 + zsh/.oh-my-zsh/plugins/invoke/README.md | 10 + .../plugins/invoke/invoke.plugin.zsh | 5 + zsh/.oh-my-zsh/plugins/ionic/README.md | 30 + zsh/.oh-my-zsh/plugins/ionic/ionic.plugin.zsh | 15 + zsh/.oh-my-zsh/plugins/ipfs/LICENSE | 22 + zsh/.oh-my-zsh/plugins/ipfs/README.md | 17 + zsh/.oh-my-zsh/plugins/ipfs/_ipfs | 791 + zsh/.oh-my-zsh/plugins/isodate/README.md | 22 + .../plugins/isodate/isodate.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/istioctl/README.md | 9 + .../plugins/istioctl/istioctl.plugin.zsh | 4 + zsh/.oh-my-zsh/plugins/iterm2/README.md | 41 + .../plugins/iterm2/iterm2.plugin.zsh | 79 + .../iterm2/iterm2_shell_integration.zsh | 178 + zsh/.oh-my-zsh/plugins/iterm2/update | 4 + zsh/.oh-my-zsh/plugins/jake-node/README.md | 9 + .../plugins/jake-node/jake-node.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/jenv/README.md | 27 + zsh/.oh-my-zsh/plugins/jenv/jenv.plugin.zsh | 36 + zsh/.oh-my-zsh/plugins/jfrog/README.md | 11 + zsh/.oh-my-zsh/plugins/jfrog/jfrog.plugin.zsh | 11 + zsh/.oh-my-zsh/plugins/jhbuild/README.md | 34 + .../plugins/jhbuild/jhbuild.plugin.zsh | 32 + zsh/.oh-my-zsh/plugins/jira/README.md | 84 + zsh/.oh-my-zsh/plugins/jira/_jira | 26 + zsh/.oh-my-zsh/plugins/jira/jira.plugin.zsh | 172 + zsh/.oh-my-zsh/plugins/jruby/README.md | 21 + zsh/.oh-my-zsh/plugins/jruby/jruby.plugin.zsh | 4 + zsh/.oh-my-zsh/plugins/jsontools/README.md | 79 + .../plugins/jsontools/jsontools.plugin.zsh | 113 + zsh/.oh-my-zsh/plugins/juju/README.md | 132 + zsh/.oh-my-zsh/plugins/juju/juju.plugin.zsh | 202 + zsh/.oh-my-zsh/plugins/jump/README.md | 31 + zsh/.oh-my-zsh/plugins/jump/jump.plugin.zsh | 60 + zsh/.oh-my-zsh/plugins/kate/README.md | 20 + zsh/.oh-my-zsh/plugins/kate/kate.plugin.zsh | 9 + zsh/.oh-my-zsh/plugins/keychain/README.md | 45 + .../plugins/keychain/keychain.plugin.zsh | 32 + zsh/.oh-my-zsh/plugins/kind/README.md | 22 + zsh/.oh-my-zsh/plugins/kind/kind.plugin.zsh | 23 + zsh/.oh-my-zsh/plugins/kitchen/README.md | 9 + zsh/.oh-my-zsh/plugins/kitchen/_kitchen | 85 + zsh/.oh-my-zsh/plugins/kitty/README.md | 23 + zsh/.oh-my-zsh/plugins/kitty/kitty.plugin.zsh | 16 + zsh/.oh-my-zsh/plugins/kn/README.md | 17 + zsh/.oh-my-zsh/plugins/kn/kn.plugin.zsh | 8 + zsh/.oh-my-zsh/plugins/knife/README.md | 25 + zsh/.oh-my-zsh/plugins/knife/_knife | 257 + zsh/.oh-my-zsh/plugins/knife_ssh/README.md | 14 + .../plugins/knife_ssh/knife_ssh.plugin.zsh | 18 + zsh/.oh-my-zsh/plugins/kops/README.md | 12 + zsh/.oh-my-zsh/plugins/kops/kops.plugin.zsh | 3 + zsh/.oh-my-zsh/plugins/kube-ps1/README.md | 242 + .../plugins/kube-ps1/kube-ps1.plugin.zsh | 399 + zsh/.oh-my-zsh/plugins/kubectl/README.md | 137 + .../plugins/kubectl/kubectl.plugin.zsh | 190 + zsh/.oh-my-zsh/plugins/kubectx/README.md | 26 + .../plugins/kubectx/kubectx.plugin.zsh | 13 + zsh/.oh-my-zsh/plugins/kubectx/prod.png | Bin 0 -> 3834 bytes zsh/.oh-my-zsh/plugins/kubectx/stage.png | Bin 0 -> 3829 bytes zsh/.oh-my-zsh/plugins/lando/LICENSE | 21 + zsh/.oh-my-zsh/plugins/lando/README.md | 56 + zsh/.oh-my-zsh/plugins/lando/lando.plugin.zsh | 52 + zsh/.oh-my-zsh/plugins/laravel/README.md | 62 + zsh/.oh-my-zsh/plugins/laravel/_artisan | 40 + .../plugins/laravel/laravel.plugin.zsh | 46 + zsh/.oh-my-zsh/plugins/laravel4/README.md | 18 + .../plugins/laravel4/laravel4.plugin.zsh | 20 + zsh/.oh-my-zsh/plugins/laravel5/README.md | 18 + .../plugins/laravel5/laravel5.plugin.zsh | 19 + .../plugins/last-working-dir/README.md | 33 + .../last-working-dir.plugin.zsh | 28 + zsh/.oh-my-zsh/plugins/lein/README.md | 9 + zsh/.oh-my-zsh/plugins/lein/_lein | 69 + zsh/.oh-my-zsh/plugins/lighthouse/README.md | 29 + .../plugins/lighthouse/lighthouse.plugin.zsh | 12 + zsh/.oh-my-zsh/plugins/lol/README.md | 71 + zsh/.oh-my-zsh/plugins/lol/lol.plugin.zsh | 51 + zsh/.oh-my-zsh/plugins/lpass/README.md | 13 + zsh/.oh-my-zsh/plugins/lpass/_lpass | 169 + zsh/.oh-my-zsh/plugins/lxd/README.md | 9 + zsh/.oh-my-zsh/plugins/lxd/lxd.plugin.zsh | 26 + zsh/.oh-my-zsh/plugins/macos/README.md | 69 + zsh/.oh-my-zsh/plugins/macos/_security | 90 + zsh/.oh-my-zsh/plugins/macos/macos.plugin.zsh | 298 + zsh/.oh-my-zsh/plugins/macos/music | 170 + zsh/.oh-my-zsh/plugins/macos/spotify | 479 + zsh/.oh-my-zsh/plugins/macports/README.md | 47 + zsh/.oh-my-zsh/plugins/macports/_port | 92 + .../plugins/macports/macports.plugin.zsh | 44 + zsh/.oh-my-zsh/plugins/magic-enter/README.md | 17 + .../magic-enter/magic-enter.plugin.zsh | 38 + zsh/.oh-my-zsh/plugins/man/README.md | 13 + zsh/.oh-my-zsh/plugins/man/man.plugin.zsh | 37 + zsh/.oh-my-zsh/plugins/marked2/README.md | 13 + .../plugins/marked2/marked2.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/marktext/README.md | 17 + .../plugins/marktext/marktext.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/mercurial/README.md | 69 + .../plugins/mercurial/mercurial.plugin.zsh | 118 + zsh/.oh-my-zsh/plugins/meteor/README.md | 46 + zsh/.oh-my-zsh/plugins/meteor/_meteor | 67 + .../plugins/meteor/meteor.plugin.zsh | 33 + zsh/.oh-my-zsh/plugins/microk8s/README.md | 24 + .../plugins/microk8s/microk8s.plugin.zsh | 82 + zsh/.oh-my-zsh/plugins/minikube/README.md | 9 + .../plugins/minikube/minikube.plugin.zsh | 13 + zsh/.oh-my-zsh/plugins/mise/README.md | 32 + zsh/.oh-my-zsh/plugins/mise/mise.plugin.zsh | 26 + zsh/.oh-my-zsh/plugins/mix-fast/README.md | 28 + .../plugins/mix-fast/mix-fast.plugin.zsh | 30 + zsh/.oh-my-zsh/plugins/mix/README.md | 19 + zsh/.oh-my-zsh/plugins/mix/_mix | 156 + zsh/.oh-my-zsh/plugins/mongo-atlas/README.md | 10 + .../mongo-atlas/mongo-atlas.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/mongocli/README.md | 19 + .../plugins/mongocli/mongocli.plugin.zsh | 4 + zsh/.oh-my-zsh/plugins/mosh/README.md | 9 + zsh/.oh-my-zsh/plugins/mosh/mosh.plugin.zsh | 2 + zsh/.oh-my-zsh/plugins/multipass/README.md | 22 + zsh/.oh-my-zsh/plugins/multipass/_multipass | 73 + .../plugins/multipass/multipass.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/mvn/README.md | 61 + zsh/.oh-my-zsh/plugins/mvn/mvn.plugin.zsh | 344 + .../plugins/mysql-macports/README.md | 20 + .../mysql-macports/mysql-macports.plugin.zsh | 8 + zsh/.oh-my-zsh/plugins/n98-magerun/README.md | 21 + .../n98-magerun/n98-magerun.plugin.zsh | 42 + zsh/.oh-my-zsh/plugins/nanoc/README.md | 20 + zsh/.oh-my-zsh/plugins/nanoc/_nanoc | 92 + zsh/.oh-my-zsh/plugins/nanoc/nanoc.plugin.zsh | 6 + zsh/.oh-my-zsh/plugins/nats/README.md | 14 + zsh/.oh-my-zsh/plugins/nats/nats.plugin.zsh | 23 + zsh/.oh-my-zsh/plugins/ng/README.md | 10 + zsh/.oh-my-zsh/plugins/ng/_ng | 56 + zsh/.oh-my-zsh/plugins/nmap/README.md | 27 + zsh/.oh-my-zsh/plugins/nmap/nmap.plugin.zsh | 32 + zsh/.oh-my-zsh/plugins/node/README.md | 19 + zsh/.oh-my-zsh/plugins/node/node.plugin.zsh | 6 + zsh/.oh-my-zsh/plugins/nodenv/README.md | 20 + .../plugins/nodenv/nodenv.plugin.zsh | 43 + zsh/.oh-my-zsh/plugins/nomad/README.md | 15 + zsh/.oh-my-zsh/plugins/nomad/_nomad | 153 + zsh/.oh-my-zsh/plugins/npm/README.md | 50 + zsh/.oh-my-zsh/plugins/npm/npm.plugin.zsh | 117 + zsh/.oh-my-zsh/plugins/nvm/README.md | 57 + zsh/.oh-my-zsh/plugins/nvm/nvm.plugin.zsh | 97 + zsh/.oh-my-zsh/plugins/oc/README.md | 13 + zsh/.oh-my-zsh/plugins/oc/oc.plugin.zsh | 8 + zsh/.oh-my-zsh/plugins/octozen/README.md | 12 + .../plugins/octozen/octozen.plugin.zsh | 11 + zsh/.oh-my-zsh/plugins/operator-sdk/README.md | 11 + .../operator-sdk/operator-sdk.plugin.zsh | 4 + zsh/.oh-my-zsh/plugins/otp/README.md | 22 + zsh/.oh-my-zsh/plugins/otp/otp.plugin.zsh | 45 + zsh/.oh-my-zsh/plugins/pass/README.md | 22 + zsh/.oh-my-zsh/plugins/pass/_pass | 147 + zsh/.oh-my-zsh/plugins/paver/README.md | 12 + zsh/.oh-my-zsh/plugins/paver/paver.plugin.zsh | 16 + zsh/.oh-my-zsh/plugins/pep8/README.md | 8 + zsh/.oh-my-zsh/plugins/pep8/_pep8 | 34 + .../plugins/per-directory-history/README.md | 50 + .../per-directory-history.plugin.zsh | 1 + .../per-directory-history.zsh | 178 + zsh/.oh-my-zsh/plugins/percol/README.md | 23 + .../plugins/percol/percol.plugin.zsh | 25 + zsh/.oh-my-zsh/plugins/perl/README.md | 37 + zsh/.oh-my-zsh/plugins/perl/perl.plugin.zsh | 56 + zsh/.oh-my-zsh/plugins/perms/README.md | 25 + zsh/.oh-my-zsh/plugins/perms/perms.plugin.zsh | 87 + zsh/.oh-my-zsh/plugins/phing/README.md | 9 + zsh/.oh-my-zsh/plugins/phing/phing.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/pip/README.md | 36 + zsh/.oh-my-zsh/plugins/pip/_pip | 100 + zsh/.oh-my-zsh/plugins/pip/pip.plugin.zsh | 135 + zsh/.oh-my-zsh/plugins/pipenv/README.md | 42 + .../plugins/pipenv/pipenv.plugin.zsh | 55 + zsh/.oh-my-zsh/plugins/pj/README.md | 45 + zsh/.oh-my-zsh/plugins/pj/pj.plugin.zsh | 34 + zsh/.oh-my-zsh/plugins/please/README.md | 26 + .../plugins/please/please.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/pm2/README.md | 19 + zsh/.oh-my-zsh/plugins/pm2/_pm2 | 168 + zsh/.oh-my-zsh/plugins/pm2/pm2.plugin.zsh | 6 + zsh/.oh-my-zsh/plugins/pod/README.md | 10 + zsh/.oh-my-zsh/plugins/pod/_pod | 682 + zsh/.oh-my-zsh/plugins/podman/README.md | 47 + .../plugins/podman/podman.plugin.zsh | 47 + zsh/.oh-my-zsh/plugins/poetry-env/README.md | 10 + .../plugins/poetry-env/poetry-env.plugin.zsh | 27 + zsh/.oh-my-zsh/plugins/poetry/README.md | 42 + .../plugins/poetry/poetry.plugin.zsh | 42 + zsh/.oh-my-zsh/plugins/postgres/README.md | 22 + .../plugins/postgres/postgres.plugin.zsh | 13 + zsh/.oh-my-zsh/plugins/pow/README.md | 21 + zsh/.oh-my-zsh/plugins/pow/pow.plugin.zsh | 85 + zsh/.oh-my-zsh/plugins/powder/README.md | 8 + zsh/.oh-my-zsh/plugins/powder/_powder | 4 + zsh/.oh-my-zsh/plugins/powify/README.md | 10 + zsh/.oh-my-zsh/plugins/powify/_powify | 55 + zsh/.oh-my-zsh/plugins/pre-commit/README.md | 19 + .../plugins/pre-commit/pre-commit.plugin.zsh | 8 + zsh/.oh-my-zsh/plugins/procs/README.md | 9 + zsh/.oh-my-zsh/plugins/procs/procs.plugin.zsh | 13 + zsh/.oh-my-zsh/plugins/profiles/README.md | 25 + .../plugins/profiles/profiles.plugin.zsh | 12 + zsh/.oh-my-zsh/plugins/pyenv/README.md | 32 + zsh/.oh-my-zsh/plugins/pyenv/pyenv.plugin.zsh | 98 + zsh/.oh-my-zsh/plugins/pylint/README.md | 16 + zsh/.oh-my-zsh/plugins/pylint/_pylint | 31 + .../plugins/pylint/pylint.plugin.zsh | 1 + zsh/.oh-my-zsh/plugins/python/README.md | 40 + .../plugins/python/python.plugin.zsh | 107 + zsh/.oh-my-zsh/plugins/qodana/README.md | 20 + .../plugins/qodana/qodana.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/qrcode/README.md | 8 + .../plugins/qrcode/qrcode.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/rails/README.md | 122 + zsh/.oh-my-zsh/plugins/rails/_rails | 538 + zsh/.oh-my-zsh/plugins/rails/rails.plugin.zsh | 120 + zsh/.oh-my-zsh/plugins/rake-fast/README.md | 35 + .../plugins/rake-fast/rake-fast.plugin.zsh | 79 + zsh/.oh-my-zsh/plugins/rake/README.md | 41 + zsh/.oh-my-zsh/plugins/rake/rake.plugin.zsh | 9 + zsh/.oh-my-zsh/plugins/rand-quote/README.md | 15 + .../plugins/rand-quote/rand-quote.plugin.zsh | 23 + zsh/.oh-my-zsh/plugins/rbenv/README.md | 26 + zsh/.oh-my-zsh/plugins/rbenv/rbenv.plugin.zsh | 68 + zsh/.oh-my-zsh/plugins/rbfu/README.md | 18 + zsh/.oh-my-zsh/plugins/rbfu/rbfu.plugin.zsh | 49 + zsh/.oh-my-zsh/plugins/rbw/README.md | 22 + zsh/.oh-my-zsh/plugins/rbw/rbw.plugin.zsh | 43 + zsh/.oh-my-zsh/plugins/react-native/README.md | 92 + .../plugins/react-native/_react-native | 32 + .../react-native/react-native.plugin.zsh | 79 + zsh/.oh-my-zsh/plugins/rebar/README.md | 9 + zsh/.oh-my-zsh/plugins/rebar/_rebar | 79 + zsh/.oh-my-zsh/plugins/redis-cli/README.md | 15 + zsh/.oh-my-zsh/plugins/redis-cli/_redis-cli | 142 + zsh/.oh-my-zsh/plugins/repo/README.md | 25 + zsh/.oh-my-zsh/plugins/repo/_repo | 279 + zsh/.oh-my-zsh/plugins/repo/repo.plugin.zsh | 10 + zsh/.oh-my-zsh/plugins/ripgrep/README.md | 9 + zsh/.oh-my-zsh/plugins/ripgrep/_ripgrep | 640 + zsh/.oh-my-zsh/plugins/ros/README.md | 10 + zsh/.oh-my-zsh/plugins/ros/_ros | 64 + zsh/.oh-my-zsh/plugins/rsync/README.md | 16 + zsh/.oh-my-zsh/plugins/rsync/rsync.plugin.zsh | 4 + zsh/.oh-my-zsh/plugins/rtx/rtx.plugin.zsh | 2 + zsh/.oh-my-zsh/plugins/ruby/README.md | 33 + zsh/.oh-my-zsh/plugins/ruby/ruby.plugin.zsh | 26 + zsh/.oh-my-zsh/plugins/rust/README.md | 9 + zsh/.oh-my-zsh/plugins/rust/_rustc | 228 + zsh/.oh-my-zsh/plugins/rust/rust.plugin.zsh | 26 + zsh/.oh-my-zsh/plugins/rvm/README.md | 37 + zsh/.oh-my-zsh/plugins/rvm/rvm.plugin.zsh | 56 + zsh/.oh-my-zsh/plugins/safe-paste/README.md | 9 + .../plugins/safe-paste/safe-paste.plugin.zsh | 100 + zsh/.oh-my-zsh/plugins/salt/README.md | 5 + zsh/.oh-my-zsh/plugins/salt/_salt | 279 + zsh/.oh-my-zsh/plugins/samtools/README.md | 5 + zsh/.oh-my-zsh/plugins/samtools/_samtools | 40 + zsh/.oh-my-zsh/plugins/sbt/README.md | 32 + zsh/.oh-my-zsh/plugins/sbt/_sbt | 56 + zsh/.oh-my-zsh/plugins/sbt/sbt.plugin.zsh | 25 + zsh/.oh-my-zsh/plugins/scala/README.md | 16 + zsh/.oh-my-zsh/plugins/scala/_scala | 249 + zsh/.oh-my-zsh/plugins/scd/README.md | 159 + zsh/.oh-my-zsh/plugins/scd/_scd | 60 + zsh/.oh-my-zsh/plugins/scd/scd | 533 + zsh/.oh-my-zsh/plugins/scd/scd.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/screen/README.md | 10 + .../plugins/screen/screen.plugin.zsh | 54 + zsh/.oh-my-zsh/plugins/scw/README.md | 7 + zsh/.oh-my-zsh/plugins/scw/_scw | 333 + zsh/.oh-my-zsh/plugins/sdk/README.md | 14 + zsh/.oh-my-zsh/plugins/sdk/sdk.plugin.zsh | 58 + zsh/.oh-my-zsh/plugins/sfdx/README.md | 11 + zsh/.oh-my-zsh/plugins/sfdx/_sfdx | 1110 + zsh/.oh-my-zsh/plugins/sfffe/README.md | 17 + zsh/.oh-my-zsh/plugins/sfffe/sfffe.plugin.zsh | 28 + .../plugins/shell-proxy/.editorconfig | 3 + zsh/.oh-my-zsh/plugins/shell-proxy/README.md | 67 + zsh/.oh-my-zsh/plugins/shell-proxy/proxy.py | 91 + .../shell-proxy/shell-proxy.plugin.zsh | 44 + .../plugins/shell-proxy/ssh-agent.py | 16 + .../plugins/shell-proxy/ssh-proxy.py | 37 + zsh/.oh-my-zsh/plugins/shrink-path/README.md | 116 + .../shrink-path/shrink-path.plugin.zsh | 182 + zsh/.oh-my-zsh/plugins/sigstore/README.md | 13 + .../plugins/sigstore/sigstore.plugin.zsh | 22 + zsh/.oh-my-zsh/plugins/singlechar/README.md | 118 + .../plugins/singlechar/singlechar.plugin.zsh | 123 + zsh/.oh-my-zsh/plugins/skaffold/README.md | 9 + .../plugins/skaffold/skaffold.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/snap/README.md | 18 + zsh/.oh-my-zsh/plugins/snap/snap.plugin.zsh | 10 + zsh/.oh-my-zsh/plugins/spring/README.md | 25 + zsh/.oh-my-zsh/plugins/spring/_spring | 29 + zsh/.oh-my-zsh/plugins/sprunge/README.md | 38 + .../plugins/sprunge/sprunge.plugin.zsh | 52 + zsh/.oh-my-zsh/plugins/ssh-agent/README.md | 133 + .../plugins/ssh-agent/ssh-agent.plugin.zsh | 115 + zsh/.oh-my-zsh/plugins/ssh/ssh.plugin.zsh | 53 + zsh/.oh-my-zsh/plugins/stack/README.md | 9 + zsh/.oh-my-zsh/plugins/stack/stack.plugin.zsh | 4 + zsh/.oh-my-zsh/plugins/starship/README.md | 21 + .../plugins/starship/starship.plugin.zsh | 8 + zsh/.oh-my-zsh/plugins/stripe/README.md | 9 + .../plugins/stripe/stripe.plugin.zsh | 13 + .../plugins/sublime-merge/README.md | 17 + .../sublime-merge/sublime-merge.plugin.zsh | 55 + zsh/.oh-my-zsh/plugins/sublime/README.md | 37 + .../plugins/sublime/sublime.plugin.zsh | 124 + zsh/.oh-my-zsh/plugins/sudo/README.md | 75 + zsh/.oh-my-zsh/plugins/sudo/sudo.plugin.zsh | 108 + zsh/.oh-my-zsh/plugins/supervisor/README.md | 13 + .../plugins/supervisor/_supervisorctl | 143 + .../plugins/supervisor/_supervisord | 33 + .../plugins/supervisor/supervisor.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/suse/README.md | 96 + zsh/.oh-my-zsh/plugins/suse/suse.plugin.zsh | 59 + zsh/.oh-my-zsh/plugins/svcat/README.md | 9 + zsh/.oh-my-zsh/plugins/svcat/svcat.plugin.zsh | 6 + .../plugins/svn-fast-info/README.md | 56 + .../svn-fast-info/svn-fast-info.plugin.zsh | 74 + zsh/.oh-my-zsh/plugins/svn/README.md | 67 + zsh/.oh-my-zsh/plugins/svn/svn.plugin.zsh | 89 + zsh/.oh-my-zsh/plugins/swiftpm/README.md | 22 + zsh/.oh-my-zsh/plugins/swiftpm/_swift | 844 + .../plugins/swiftpm/swiftpm.plugin.zsh | 8 + zsh/.oh-my-zsh/plugins/symfony/README.md | 9 + .../plugins/symfony/symfony.plugin.zsh | 13 + zsh/.oh-my-zsh/plugins/symfony2/README.md | 28 + .../plugins/symfony2/symfony2.plugin.zsh | 34 + zsh/.oh-my-zsh/plugins/symfony6/README.md | 9 + .../plugins/symfony6/symfony6.plugin.zsh | 82 + zsh/.oh-my-zsh/plugins/systemadmin/README.md | 51 + .../systemadmin/systemadmin.plugin.zsh | 187 + zsh/.oh-my-zsh/plugins/systemd/README.md | 98 + .../plugins/systemd/systemd.plugin.zsh | 121 + zsh/.oh-my-zsh/plugins/taskwarrior/README.md | 18 + zsh/.oh-my-zsh/plugins/taskwarrior/_task | 285 + .../taskwarrior/taskwarrior.plugin.zsh | 7 + zsh/.oh-my-zsh/plugins/term_tab/README.md | 18 + .../plugins/term_tab/term_tab.plugin.zsh | 42 + zsh/.oh-my-zsh/plugins/terminitor/README.md | 9 + zsh/.oh-my-zsh/plugins/terminitor/_terminitor | 38 + zsh/.oh-my-zsh/plugins/terraform/README.md | 52 + zsh/.oh-my-zsh/plugins/terraform/_terraform | 545 + .../plugins/terraform/terraform.plugin.zsh | 30 + zsh/.oh-my-zsh/plugins/textastic/README.md | 15 + .../plugins/textastic/textastic.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/textmate/README.md | 17 + .../plugins/textmate/textmate.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/thefuck/README.md | 13 + .../plugins/thefuck/thefuck.plugin.zsh | 21 + zsh/.oh-my-zsh/plugins/themes/README.md | 18 + .../plugins/themes/themes.plugin.zsh | 35 + zsh/.oh-my-zsh/plugins/thor/README.md | 10 + zsh/.oh-my-zsh/plugins/thor/_thor | 4 + zsh/.oh-my-zsh/plugins/tig/README.md | 16 + zsh/.oh-my-zsh/plugins/tig/tig.plugin.zsh | 5 + zsh/.oh-my-zsh/plugins/timer/README.md | 18 + zsh/.oh-my-zsh/plugins/timer/timer.plugin.zsh | 35 + zsh/.oh-my-zsh/plugins/tldr/README.md | 15 + zsh/.oh-my-zsh/plugins/tldr/tldr.plugin.zsh | 19 + zsh/.oh-my-zsh/plugins/tmux-cssh/README.md | 10 + zsh/.oh-my-zsh/plugins/tmux-cssh/_tmux-cssh | 25 + zsh/.oh-my-zsh/plugins/tmux/README.md | 46 + zsh/.oh-my-zsh/plugins/tmux/tmux.extra.conf | 2 + zsh/.oh-my-zsh/plugins/tmux/tmux.only.conf | 1 + zsh/.oh-my-zsh/plugins/tmux/tmux.plugin.zsh | 185 + zsh/.oh-my-zsh/plugins/tmuxinator/README.md | 19 + zsh/.oh-my-zsh/plugins/tmuxinator/_tmuxinator | 23 + .../plugins/tmuxinator/tmuxinator.plugin.zsh | 5 + zsh/.oh-my-zsh/plugins/toolbox/README.md | 26 + .../plugins/toolbox/toolbox.plugin.zsh | 6 + zsh/.oh-my-zsh/plugins/torrent/README.md | 13 + .../plugins/torrent/torrent.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/transfer/README.md | 41 + .../plugins/transfer/transfer.plugin.zsh | 97 + zsh/.oh-my-zsh/plugins/tugboat/README.md | 12 + zsh/.oh-my-zsh/plugins/tugboat/_tugboat | 106 + zsh/.oh-my-zsh/plugins/ubuntu/README.md | 61 + .../plugins/ubuntu/ubuntu.plugin.zsh | 127 + zsh/.oh-my-zsh/plugins/ufw/README.md | 18 + zsh/.oh-my-zsh/plugins/ufw/_ufw | 115 + .../plugins/universalarchive/README.md | 46 + .../universalarchive/_universalarchive | 6 + .../universalarchive.plugin.zsh | 70 + zsh/.oh-my-zsh/plugins/urltools/README.md | 29 + .../plugins/urltools/urltools.plugin.zsh | 42 + .../plugins/vagrant-prompt/README.md | 6 + .../vagrant-prompt/vagrant-prompt.plugin.zsh | 33 + zsh/.oh-my-zsh/plugins/vagrant/README.md | 40 + zsh/.oh-my-zsh/plugins/vagrant/_vagrant | 133 + .../plugins/vagrant/vagrant.plugin.zsh | 33 + zsh/.oh-my-zsh/plugins/vault/README.md | 15 + zsh/.oh-my-zsh/plugins/vault/_vault | 400 + zsh/.oh-my-zsh/plugins/vi-mode/README.md | 176 + .../plugins/vi-mode/vi-mode.plugin.zsh | 176 + .../plugins/vim-interaction/README.md | 82 + .../vim-interaction.plugin.zsh | 69 + zsh/.oh-my-zsh/plugins/virtualenv/README.md | 15 + .../plugins/virtualenv/virtualenv.plugin.zsh | 7 + .../plugins/virtualenvwrapper/README.md | 38 + .../virtualenvwrapper.plugin.zsh | 92 + zsh/.oh-my-zsh/plugins/volta/README.md | 11 + zsh/.oh-my-zsh/plugins/volta/volta.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/vscode/README.md | 85 + .../plugins/vscode/vscode.plugin.zsh | 50 + zsh/.oh-my-zsh/plugins/vundle/README.md | 19 + .../plugins/vundle/vundle.plugin.zsh | 27 + zsh/.oh-my-zsh/plugins/wakeonlan/README.md | 43 + zsh/.oh-my-zsh/plugins/wakeonlan/_wake | 4 + .../plugins/wakeonlan/wakeonlan.plugin.zsh | 14 + zsh/.oh-my-zsh/plugins/watson/README.md | 9 + zsh/.oh-my-zsh/plugins/watson/_watson | 34 + zsh/.oh-my-zsh/plugins/wd/LICENSE | 21 + zsh/.oh-my-zsh/plugins/wd/README.md | 303 + zsh/.oh-my-zsh/plugins/wd/_wd.sh | 102 + zsh/.oh-my-zsh/plugins/wd/wd.plugin.zsh | 21 + zsh/.oh-my-zsh/plugins/wd/wd.sh | 589 + zsh/.oh-my-zsh/plugins/web-search/README.md | 84 + .../plugins/web-search/web-search.plugin.zsh | 102 + zsh/.oh-my-zsh/plugins/wp-cli/README.md | 109 + .../plugins/wp-cli/wp-cli.plugin.zsh | 123 + zsh/.oh-my-zsh/plugins/xcode/README.md | 88 + zsh/.oh-my-zsh/plugins/xcode/_xcselv | 19 + zsh/.oh-my-zsh/plugins/xcode/xcode.plugin.zsh | 208 + zsh/.oh-my-zsh/plugins/yarn/README.md | 74 + zsh/.oh-my-zsh/plugins/yarn/_yarn | 502 + zsh/.oh-my-zsh/plugins/yarn/yarn.plugin.zsh | 64 + zsh/.oh-my-zsh/plugins/yii/README.md | 15 + zsh/.oh-my-zsh/plugins/yii/yii.plugin.zsh | 17 + zsh/.oh-my-zsh/plugins/yii2/README.md | 7 + zsh/.oh-my-zsh/plugins/yii2/yii2.plugin.zsh | 29 + zsh/.oh-my-zsh/plugins/yum/README.md | 27 + zsh/.oh-my-zsh/plugins/yum/yum.plugin.zsh | 16 + zsh/.oh-my-zsh/plugins/z/LICENSE | 21 + zsh/.oh-my-zsh/plugins/z/MANUAL.md | 366 + zsh/.oh-my-zsh/plugins/z/README.md | 24 + zsh/.oh-my-zsh/plugins/z/_z | 82 + zsh/.oh-my-zsh/plugins/z/img/demo.gif | Bin 0 -> 1271520 bytes zsh/.oh-my-zsh/plugins/z/img/mit_license.svg | 1 + .../plugins/z/img/zsh_4.3.11_plus.svg | 1 + zsh/.oh-my-zsh/plugins/z/z.plugin.zsh | 1014 + zsh/.oh-my-zsh/plugins/zbell/README.md | 33 + zsh/.oh-my-zsh/plugins/zbell/zbell.plugin.zsh | 96 + zsh/.oh-my-zsh/plugins/zeus/README.md | 50 + zsh/.oh-my-zsh/plugins/zeus/_zeus | 98 + zsh/.oh-my-zsh/plugins/zeus/zeus.plugin.zsh | 70 + zsh/.oh-my-zsh/plugins/zoxide/README.md | 17 + .../plugins/zoxide/zoxide.plugin.zsh | 5 + .../plugins/zsh-interactive-cd/LICENSE | 375 + .../plugins/zsh-interactive-cd/README.md | 15 + .../plugins/zsh-interactive-cd/demo.gif | Bin 0 -> 1497944 bytes .../zsh-interactive-cd.plugin.zsh | 180 + .../.config/znt/n-aliases.conf | 33 + .../.config/znt/n-cd.conf | 68 + .../.config/znt/n-env.conf | 38 + .../.config/znt/n-functions.conf | 41 + .../.config/znt/n-history.conf | 43 + .../.config/znt/n-kill.conf | 46 + .../.config/znt/n-list.conf | 55 + .../.config/znt/n-options.conf | 34 + .../.config/znt/n-panelize.conf | 34 + .../plugins/zsh-navigation-tools/LICENSE | 700 + .../plugins/zsh-navigation-tools/Makefile | 35 + .../plugins/zsh-navigation-tools/NEWS | 17 + .../plugins/zsh-navigation-tools/README.md | 259 + .../plugins/zsh-navigation-tools/_n-kill | 41 + .../doc/generate_single_file | 35 + .../doc/img/n-history2.png | Bin 0 -> 108316 bytes .../zsh-navigation-tools/doc/install.sh | 70 + .../zsh-navigation-tools/doc/n-preview | 224 + .../zsh-navigation-tools/doc/znt-tmux.zsh | 50 + .../plugins/zsh-navigation-tools/n-aliases | 47 + .../plugins/zsh-navigation-tools/n-cd | 71 + .../plugins/zsh-navigation-tools/n-env | 47 + .../plugins/zsh-navigation-tools/n-functions | 54 + .../plugins/zsh-navigation-tools/n-help | 135 + .../plugins/zsh-navigation-tools/n-history | 371 + .../plugins/zsh-navigation-tools/n-kill | 96 + .../plugins/zsh-navigation-tools/n-list | 517 + .../plugins/zsh-navigation-tools/n-list-draw | 133 + .../plugins/zsh-navigation-tools/n-list-input | 377 + .../plugins/zsh-navigation-tools/n-options | 84 + .../plugins/zsh-navigation-tools/n-panelize | 68 + .../zsh-navigation-tools/znt-cd-widget | 8 + .../zsh-navigation-tools/znt-history-widget | 22 + .../zsh-navigation-tools/znt-kill-widget | 8 + .../zsh-navigation-tools/znt-usetty-wrapper | 40 + .../zsh-navigation-tools.plugin.zsh | 77 + zsh/.oh-my-zsh/templates/zshrc.zsh-template | 101 + zsh/.oh-my-zsh/themes/3den.zsh-theme | 7 + zsh/.oh-my-zsh/themes/Soliah.zsh-theme | 85 + zsh/.oh-my-zsh/themes/adben.zsh-theme | 118 + zsh/.oh-my-zsh/themes/af-magic.zsh-theme | 47 + zsh/.oh-my-zsh/themes/afowler.zsh-theme | 10 + zsh/.oh-my-zsh/themes/agnoster.zsh-theme | 271 + zsh/.oh-my-zsh/themes/alanpeabody.zsh-theme | 24 + zsh/.oh-my-zsh/themes/amuse.zsh-theme | 24 + zsh/.oh-my-zsh/themes/apple.zsh-theme | 24 + zsh/.oh-my-zsh/themes/arrow.zsh-theme | 14 + zsh/.oh-my-zsh/themes/aussiegeek.zsh-theme | 8 + zsh/.oh-my-zsh/themes/avit.zsh-theme | 90 + zsh/.oh-my-zsh/themes/awesomepanda.zsh-theme | 16 + zsh/.oh-my-zsh/themes/bira.zsh-theme | 37 + zsh/.oh-my-zsh/themes/blinks.zsh-theme | 30 + zsh/.oh-my-zsh/themes/bureau.zsh-theme | 133 + zsh/.oh-my-zsh/themes/candy-kingdom.zsh-theme | 34 + zsh/.oh-my-zsh/themes/candy.zsh-theme | 7 + zsh/.oh-my-zsh/themes/clean.zsh-theme | 14 + zsh/.oh-my-zsh/themes/cloud.zsh-theme | 10 + zsh/.oh-my-zsh/themes/crcandy.zsh-theme | 8 + zsh/.oh-my-zsh/themes/crunch.zsh-theme | 39 + zsh/.oh-my-zsh/themes/cypher.zsh-theme | 4 + zsh/.oh-my-zsh/themes/dallas.zsh-theme | 27 + zsh/.oh-my-zsh/themes/darkblood.zsh-theme | 9 + zsh/.oh-my-zsh/themes/daveverwer.zsh-theme | 7 + zsh/.oh-my-zsh/themes/dieter.zsh-theme | 56 + zsh/.oh-my-zsh/themes/dogenpunk.zsh-theme | 77 + zsh/.oh-my-zsh/themes/dpoggi.zsh-theme | 14 + zsh/.oh-my-zsh/themes/dst.zsh-theme | 16 + zsh/.oh-my-zsh/themes/dstufft.zsh-theme | 19 + zsh/.oh-my-zsh/themes/duellj.zsh-theme | 7 + zsh/.oh-my-zsh/themes/eastwood.zsh-theme | 23 + zsh/.oh-my-zsh/themes/edvardm.zsh-theme | 6 + zsh/.oh-my-zsh/themes/emotty.zsh-theme | 113 + zsh/.oh-my-zsh/themes/essembeh.zsh-theme | 50 + zsh/.oh-my-zsh/themes/evan.zsh-theme | 2 + zsh/.oh-my-zsh/themes/fino-time.zsh-theme | 38 + zsh/.oh-my-zsh/themes/fino.zsh-theme | 47 + zsh/.oh-my-zsh/themes/fishy.zsh-theme | 36 + zsh/.oh-my-zsh/themes/flazz.zsh-theme | 19 + zsh/.oh-my-zsh/themes/fletcherm.zsh-theme | 12 + zsh/.oh-my-zsh/themes/fox.zsh-theme | 9 + zsh/.oh-my-zsh/themes/frisk.zsh-theme | 12 + zsh/.oh-my-zsh/themes/frontcube.zsh-theme | 13 + zsh/.oh-my-zsh/themes/funky.zsh-theme | 14 + zsh/.oh-my-zsh/themes/fwalch.zsh-theme | 6 + zsh/.oh-my-zsh/themes/gallifrey.zsh-theme | 11 + zsh/.oh-my-zsh/themes/gallois.zsh-theme | 140 + .../themes/garyblessington.zsh-theme | 6 + zsh/.oh-my-zsh/themes/gentoo.zsh-theme | 30 + zsh/.oh-my-zsh/themes/geoffgarside.zsh-theme | 5 + zsh/.oh-my-zsh/themes/gianu.zsh-theme | 6 + zsh/.oh-my-zsh/themes/gnzh.zsh-theme | 43 + zsh/.oh-my-zsh/themes/gozilla.zsh-theme | 15 + zsh/.oh-my-zsh/themes/half-life.zsh-theme | 97 + zsh/.oh-my-zsh/themes/humza.zsh-theme | 26 + zsh/.oh-my-zsh/themes/imajes.zsh-theme | 5 + zsh/.oh-my-zsh/themes/intheloop.zsh-theme | 23 + zsh/.oh-my-zsh/themes/itchy.zsh-theme | 18 + zsh/.oh-my-zsh/themes/jaischeema.zsh-theme | 12 + zsh/.oh-my-zsh/themes/jbergantine.zsh-theme | 6 + zsh/.oh-my-zsh/themes/jispwoso.zsh-theme | 10 + zsh/.oh-my-zsh/themes/jnrowe.zsh-theme | 37 + zsh/.oh-my-zsh/themes/jonathan.zsh-theme | 124 + zsh/.oh-my-zsh/themes/josh.zsh-theme | 43 + zsh/.oh-my-zsh/themes/jreese.zsh-theme | 14 + zsh/.oh-my-zsh/themes/jtriley.zsh-theme | 2 + zsh/.oh-my-zsh/themes/juanghurtado.zsh-theme | 41 + zsh/.oh-my-zsh/themes/junkfood.zsh-theme | 30 + zsh/.oh-my-zsh/themes/kafeitu.zsh-theme | 6 + zsh/.oh-my-zsh/themes/kardan.zsh-theme | 12 + zsh/.oh-my-zsh/themes/kennethreitz.zsh-theme | 15 + zsh/.oh-my-zsh/themes/kiwi.zsh-theme | 10 + zsh/.oh-my-zsh/themes/kolo.zsh-theme | 24 + zsh/.oh-my-zsh/themes/kphoen.zsh-theme | 43 + zsh/.oh-my-zsh/themes/lambda.zsh-theme | 4 + zsh/.oh-my-zsh/themes/linuxonly.zsh-theme | 58 + zsh/.oh-my-zsh/themes/lukerandall.zsh-theme | 24 + zsh/.oh-my-zsh/themes/macovsky-ruby.zsh-theme | 1 + zsh/.oh-my-zsh/themes/macovsky.zsh-theme | 12 + zsh/.oh-my-zsh/themes/maran.zsh-theme | 6 + zsh/.oh-my-zsh/themes/mgutz.zsh-theme | 6 + zsh/.oh-my-zsh/themes/mh.zsh-theme | 24 + .../themes/michelebologna.zsh-theme | 78 + zsh/.oh-my-zsh/themes/mikeh.zsh-theme | 21 + zsh/.oh-my-zsh/themes/miloshadzic.zsh-theme | 8 + zsh/.oh-my-zsh/themes/minimal.zsh-theme | 26 + zsh/.oh-my-zsh/themes/mira.zsh-theme | 23 + zsh/.oh-my-zsh/themes/mlh.zsh-theme | 105 + zsh/.oh-my-zsh/themes/mortalscumbag.zsh-theme | 71 + zsh/.oh-my-zsh/themes/mrtazz.zsh-theme | 7 + zsh/.oh-my-zsh/themes/murilasso.zsh-theme | 14 + zsh/.oh-my-zsh/themes/muse.zsh-theme | 16 + zsh/.oh-my-zsh/themes/nanotech.zsh-theme | 7 + zsh/.oh-my-zsh/themes/nebirhos.zsh-theme | 21 + zsh/.oh-my-zsh/themes/nicoulaj.zsh-theme | 43 + zsh/.oh-my-zsh/themes/norm.zsh-theme | 7 + zsh/.oh-my-zsh/themes/obraun.zsh-theme | 10 + zsh/.oh-my-zsh/themes/oldgallois.zsh-theme | 24 + zsh/.oh-my-zsh/themes/peepcode.zsh-theme | 47 + zsh/.oh-my-zsh/themes/philips.zsh-theme | 14 + zsh/.oh-my-zsh/themes/pmcgee.zsh-theme | 16 + .../themes/pygmalion-virtualenv.zsh-theme | 54 + zsh/.oh-my-zsh/themes/pygmalion.zsh-theme | 32 + zsh/.oh-my-zsh/themes/random.zsh-theme | 47 + zsh/.oh-my-zsh/themes/re5et.zsh-theme | 15 + zsh/.oh-my-zsh/themes/refined.zsh-theme | 108 + zsh/.oh-my-zsh/themes/rgm.zsh-theme | 8 + zsh/.oh-my-zsh/themes/risto.zsh-theme | 6 + zsh/.oh-my-zsh/themes/rixius.zsh-theme | 21 + zsh/.oh-my-zsh/themes/rkj-repos.zsh-theme | 35 + zsh/.oh-my-zsh/themes/rkj.zsh-theme | 9 + zsh/.oh-my-zsh/themes/robbyrussell.zsh-theme | 7 + zsh/.oh-my-zsh/themes/sammy.zsh-theme | 6 + zsh/.oh-my-zsh/themes/simonoff.zsh-theme | 99 + zsh/.oh-my-zsh/themes/simple.zsh-theme | 6 + zsh/.oh-my-zsh/themes/skaro.zsh-theme | 7 + zsh/.oh-my-zsh/themes/smt.zsh-theme | 83 + zsh/.oh-my-zsh/themes/sonicradish.zsh-theme | 37 + zsh/.oh-my-zsh/themes/sorin.zsh-theme | 42 + zsh/.oh-my-zsh/themes/sporty_256.zsh-theme | 13 + zsh/.oh-my-zsh/themes/steeef.zsh-theme | 103 + zsh/.oh-my-zsh/themes/strug.zsh-theme | 25 + zsh/.oh-my-zsh/themes/sunaku.zsh-theme | 25 + zsh/.oh-my-zsh/themes/sunrise.zsh-theme | 93 + zsh/.oh-my-zsh/themes/superjarin.zsh-theme | 18 + zsh/.oh-my-zsh/themes/suvash.zsh-theme | 21 + .../themes/takashiyoshida.zsh-theme | 27 + zsh/.oh-my-zsh/themes/terminalparty.zsh-theme | 8 + zsh/.oh-my-zsh/themes/theunraveler.zsh-theme | 16 + zsh/.oh-my-zsh/themes/tjkirch.zsh-theme | 15 + zsh/.oh-my-zsh/themes/tjkirch_mod.zsh-theme | 13 + zsh/.oh-my-zsh/themes/tonotdo.zsh-theme | 12 + zsh/.oh-my-zsh/themes/trapd00r.zsh-theme | 132 + zsh/.oh-my-zsh/themes/wedisagree.zsh-theme | 109 + zsh/.oh-my-zsh/themes/wezm+.zsh-theme | 7 + zsh/.oh-my-zsh/themes/wezm.zsh-theme | 7 + zsh/.oh-my-zsh/themes/wuffers.zsh-theme | 5 + .../themes/xiong-chiamiov-plus.zsh-theme | 6 + .../themes/xiong-chiamiov.zsh-theme | 6 + zsh/.oh-my-zsh/themes/ys.zsh-theme | 80 + zsh/.oh-my-zsh/themes/zhann.zsh-theme | 25 + zsh/.oh-my-zsh/tools/changelog.sh | 579 + zsh/.oh-my-zsh/tools/check_for_upgrade.sh | 297 + zsh/.oh-my-zsh/tools/install.sh | 556 + zsh/.oh-my-zsh/tools/require_tool.sh | 161 + zsh/.oh-my-zsh/tools/theme_chooser.sh | 98 + zsh/.oh-my-zsh/tools/uninstall.sh | 41 + zsh/.oh-my-zsh/tools/upgrade.sh | 295 + zsh/.zshrc | 110 + 1154 files changed, 124499 insertions(+) create mode 100644 README.md create mode 100644 alacritty/.config/alacritty/alacritty.toml create mode 100644 alacritty/.config/alacritty/dracula.toml create mode 100644 nvim/.config/nvim/init.vim create mode 100644 nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/bug.md create mode 100644 nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/question.md create mode 100644 nvim/.vim/plugged/nerdtree/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 nvim/.vim/plugged/nerdtree/.github/workflows/vint.yml create mode 100644 nvim/.vim/plugged/nerdtree/.gitignore create mode 100644 nvim/.vim/plugged/nerdtree/.vintrc.yaml create mode 100644 nvim/.vim/plugged/nerdtree/CHANGELOG.md create mode 100644 nvim/.vim/plugged/nerdtree/LICENCE create mode 100644 nvim/.vim/plugged/nerdtree/README.markdown create mode 100644 nvim/.vim/plugged/nerdtree/_config.yml create mode 100644 nvim/.vim/plugged/nerdtree/autoload/nerdtree.vim create mode 100644 nvim/.vim/plugged/nerdtree/autoload/nerdtree/ui_glue.vim create mode 100644 nvim/.vim/plugged/nerdtree/doc/NERDTree.txt create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/bookmark.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/creator.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/event.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/flag_set.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/key_map.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/menu_controller.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/menu_item.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/nerdtree.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/notifier.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/opener.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/path.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/tree_dir_node.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/tree_file_node.vim create mode 100644 nvim/.vim/plugged/nerdtree/lib/nerdtree/ui.vim create mode 100644 nvim/.vim/plugged/nerdtree/nerdtree_plugin/exec_menuitem.vim create mode 100644 nvim/.vim/plugged/nerdtree/nerdtree_plugin/fs_menu.vim create mode 100644 nvim/.vim/plugged/nerdtree/nerdtree_plugin/vcs.vim create mode 100644 nvim/.vim/plugged/nerdtree/plugin/NERD_tree.vim create mode 100644 nvim/.vim/plugged/nerdtree/screenshot.png create mode 100644 nvim/.vim/plugged/nerdtree/syntax/nerdtree.vim create mode 100644 nvim/.vim/plugged/vim-devicons/.github/ISSUE_TEMPLATE.md create mode 100644 nvim/.vim/plugged/vim-devicons/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 nvim/.vim/plugged/vim-devicons/.github/workflows/ci.yml create mode 100644 nvim/.vim/plugged/vim-devicons/.github/workflows/vint.yml create mode 100644 nvim/.vim/plugged/vim-devicons/.gitignore create mode 100644 nvim/.vim/plugged/vim-devicons/CHANGELOG.md create mode 100644 nvim/.vim/plugged/vim-devicons/CODE_OF_CONDUCT.md create mode 100644 nvim/.vim/plugged/vim-devicons/CONTRIBUTING.md create mode 100644 nvim/.vim/plugged/vim-devicons/DEVELOPER.md create mode 100644 nvim/.vim/plugged/vim-devicons/LICENSE create mode 100644 nvim/.vim/plugged/vim-devicons/README.md create mode 100644 nvim/.vim/plugged/vim-devicons/autoload/airline/extensions/tabline/formatters/webdevicons.vim create mode 100644 nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/ctrlp.vim create mode 100644 nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/denite.vim create mode 100644 nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/flagship.vim create mode 100644 nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/startify.vim create mode 100644 nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/unite.vim create mode 100644 nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/vimfiler.vim create mode 100644 nvim/.vim/plugged/vim-devicons/autoload/vimfiler/columns/devicons.vim create mode 100644 nvim/.vim/plugged/vim-devicons/doc/webdevicons.txt create mode 100644 nvim/.vim/plugged/vim-devicons/nerdtree_plugin/webdevicons.vim create mode 100644 nvim/.vim/plugged/vim-devicons/plugin/webdevicons.vim create mode 100644 nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/__init__.py create mode 100644 nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/powerline/__init__.py create mode 100644 nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/powerline/segments.py create mode 100644 nvim/.vim/plugged/vim-devicons/rplugin/python3/denite/filter/devicons_denite_converter.py create mode 100644 nvim/.vim/plugged/vim-devicons/test/.themisrc create mode 100644 nvim/.vim/plugged/vim-devicons/test/default_setting.vim create mode 100644 nvim/.vim/plugged/vim-devicons/test/fileformat.vim create mode 100644 nvim/.vim/plugged/vim-devicons/test/filetype.vim create mode 100644 nvim/.vim/plugged/vim/.github/issue_template.md create mode 100644 nvim/.vim/plugged/vim/.github/pull_request_template.md create mode 100644 nvim/.vim/plugged/vim/.gitignore create mode 100644 nvim/.vim/plugged/vim/INSTALL.md create mode 100644 nvim/.vim/plugged/vim/LICENSE create mode 100644 nvim/.vim/plugged/vim/README.md create mode 100644 nvim/.vim/plugged/vim/after/plugin/dracula.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/css.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/gitcommit.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/html.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/javascript.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/javascriptreact.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/json.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/lua.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/markdown.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/ocaml.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/perl.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/php.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/plantuml.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/purescript.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/python.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/rst.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/ruby.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/rust.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/sass.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/sh.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/tex.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/typescript.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/typescriptreact.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/vim.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/xml.vim create mode 100644 nvim/.vim/plugged/vim/after/syntax/yaml.vim create mode 100644 nvim/.vim/plugged/vim/autoload/airline/themes/dracula.vim create mode 100644 nvim/.vim/plugged/vim/autoload/dracula.vim create mode 100644 nvim/.vim/plugged/vim/autoload/lightline/colorscheme/dracula.vim create mode 100644 nvim/.vim/plugged/vim/colors/dracula.vim create mode 100644 nvim/.vim/plugged/vim/doc/dracula.txt create mode 100644 nvim/.vim/plugged/vim/dracula-pro.png create mode 100644 nvim/.vim/plugged/vim/screenshot.png create mode 100644 plasma/.config/gtkrc-2.0 create mode 100644 plasma/.config/kded5rc create mode 100644 plasma/.config/kdeglobals create mode 100644 plasma/.config/kglobalshortcutsrc create mode 100644 plasma/.config/kwinoutputconfig.json create mode 100644 plasma/.config/kwinrc create mode 100644 plasma/.config/plasma-localerc create mode 100644 plasma/.config/plasma-org.kde.plasma.desktop-appletsrc create mode 100644 plasma/.config/plasmanotifyrc create mode 100644 plasma/.config/plasmaparc create mode 100644 plasma/.config/plasmashellrc create mode 100644 plasma/.config/spectaclerc create mode 100644 zsh/.oh-my-zsh/.editorconfig create mode 100644 zsh/.oh-my-zsh/.github/CODEOWNERS create mode 100644 zsh/.oh-my-zsh/.github/FUNDING.yml create mode 100644 zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/bug_report_omz.yml create mode 100644 zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/config.yml create mode 100644 zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 zsh/.oh-my-zsh/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 zsh/.oh-my-zsh/.github/dependabot.yml create mode 100644 zsh/.oh-my-zsh/.github/dependencies.yml create mode 100644 zsh/.oh-my-zsh/.github/workflows/dependencies.yml create mode 100644 zsh/.oh-my-zsh/.github/workflows/dependencies/requirements.txt create mode 100644 zsh/.oh-my-zsh/.github/workflows/dependencies/updater.py create mode 100644 zsh/.oh-my-zsh/.github/workflows/installer.yml create mode 100644 zsh/.oh-my-zsh/.github/workflows/installer/.gitignore create mode 100644 zsh/.oh-my-zsh/.github/workflows/installer/.vercelignore create mode 100644 zsh/.oh-my-zsh/.github/workflows/installer/vercel.json create mode 100644 zsh/.oh-my-zsh/.github/workflows/main.yml create mode 100644 zsh/.oh-my-zsh/.github/workflows/project.yml create mode 100644 zsh/.oh-my-zsh/.gitignore create mode 100644 zsh/.oh-my-zsh/.gitpod.Dockerfile create mode 100644 zsh/.oh-my-zsh/.gitpod.yml create mode 100644 zsh/.oh-my-zsh/.prettierrc create mode 100644 zsh/.oh-my-zsh/CODE_OF_CONDUCT.md create mode 100644 zsh/.oh-my-zsh/CONTRIBUTING.md create mode 100644 zsh/.oh-my-zsh/LICENSE.txt create mode 100644 zsh/.oh-my-zsh/README.md create mode 100644 zsh/.oh-my-zsh/SECURITY.md create mode 100644 zsh/.oh-my-zsh/lib/async_prompt.zsh create mode 100644 zsh/.oh-my-zsh/lib/bzr.zsh create mode 100644 zsh/.oh-my-zsh/lib/cli.zsh create mode 100644 zsh/.oh-my-zsh/lib/clipboard.zsh create mode 100644 zsh/.oh-my-zsh/lib/compfix.zsh create mode 100644 zsh/.oh-my-zsh/lib/completion.zsh create mode 100644 zsh/.oh-my-zsh/lib/correction.zsh create mode 100644 zsh/.oh-my-zsh/lib/diagnostics.zsh create mode 100644 zsh/.oh-my-zsh/lib/directories.zsh create mode 100644 zsh/.oh-my-zsh/lib/functions.zsh create mode 100644 zsh/.oh-my-zsh/lib/git.zsh create mode 100644 zsh/.oh-my-zsh/lib/grep.zsh create mode 100644 zsh/.oh-my-zsh/lib/history.zsh create mode 100644 zsh/.oh-my-zsh/lib/key-bindings.zsh create mode 100644 zsh/.oh-my-zsh/lib/misc.zsh create mode 100644 zsh/.oh-my-zsh/lib/nvm.zsh create mode 100644 zsh/.oh-my-zsh/lib/prompt_info_functions.zsh create mode 100644 zsh/.oh-my-zsh/lib/spectrum.zsh create mode 100644 zsh/.oh-my-zsh/lib/termsupport.zsh create mode 100644 zsh/.oh-my-zsh/lib/tests/cli.test.zsh create mode 100644 zsh/.oh-my-zsh/lib/theme-and-appearance.zsh create mode 100644 zsh/.oh-my-zsh/lib/vcs_info.zsh create mode 100644 zsh/.oh-my-zsh/oh-my-zsh.sh create mode 100644 zsh/.oh-my-zsh/plugins/1password/1password.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/1password/README.md create mode 100644 zsh/.oh-my-zsh/plugins/1password/_opswd create mode 100644 zsh/.oh-my-zsh/plugins/1password/opswd create mode 100644 zsh/.oh-my-zsh/plugins/adb/README.md create mode 100644 zsh/.oh-my-zsh/plugins/adb/_adb create mode 100644 zsh/.oh-my-zsh/plugins/ag/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ag/_ag create mode 100644 zsh/.oh-my-zsh/plugins/alias-finder/.zunit.yml create mode 100644 zsh/.oh-my-zsh/plugins/alias-finder/README.md create mode 100644 zsh/.oh-my-zsh/plugins/alias-finder/alias-finder.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/alias-finder/tests/_output/.gitkeep create mode 100644 zsh/.oh-my-zsh/plugins/alias-finder/tests/_support/.gitkeep create mode 100644 zsh/.oh-my-zsh/plugins/alias-finder/tests/_support/bootstrap create mode 100644 zsh/.oh-my-zsh/plugins/alias-finder/tests/test_run.sh create mode 100644 zsh/.oh-my-zsh/plugins/aliases/.gitignore create mode 100644 zsh/.oh-my-zsh/plugins/aliases/README.md create mode 100644 zsh/.oh-my-zsh/plugins/aliases/aliases.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/aliases/cheatsheet.py create mode 100644 zsh/.oh-my-zsh/plugins/aliases/termcolor.py create mode 100644 zsh/.oh-my-zsh/plugins/ansible/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ansible/ansible.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/ant/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ant/_ant create mode 100644 zsh/.oh-my-zsh/plugins/ant/ant.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/apache2-macports/README.md create mode 100644 zsh/.oh-my-zsh/plugins/apache2-macports/apache2-macports.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/arcanist/README.md create mode 100644 zsh/.oh-my-zsh/plugins/arcanist/arcanist.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/archlinux/README.md create mode 100644 zsh/.oh-my-zsh/plugins/archlinux/archlinux.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/argocd/README.md create mode 100644 zsh/.oh-my-zsh/plugins/argocd/argocd.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/asdf/README.md create mode 100644 zsh/.oh-my-zsh/plugins/asdf/asdf.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/autoenv/README.md create mode 100644 zsh/.oh-my-zsh/plugins/autoenv/autoenv.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/autojump/README.md create mode 100644 zsh/.oh-my-zsh/plugins/autojump/autojump.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/autopep8/README.md create mode 100644 zsh/.oh-my-zsh/plugins/autopep8/_autopep8 create mode 100644 zsh/.oh-my-zsh/plugins/aws/README.md create mode 100644 zsh/.oh-my-zsh/plugins/aws/aws.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/azure/README.md create mode 100644 zsh/.oh-my-zsh/plugins/azure/azure.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/battery/README.md create mode 100644 zsh/.oh-my-zsh/plugins/battery/battery.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/bazel/README.md create mode 100644 zsh/.oh-my-zsh/plugins/bazel/_bazel create mode 100644 zsh/.oh-my-zsh/plugins/bazel/bazel.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/bbedit/README.md create mode 100644 zsh/.oh-my-zsh/plugins/bbedit/bbedit.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/bedtools/README.md create mode 100644 zsh/.oh-my-zsh/plugins/bedtools/_bedtools create mode 100644 zsh/.oh-my-zsh/plugins/bgnotify/README.md create mode 100644 zsh/.oh-my-zsh/plugins/bgnotify/bgnotify.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/bower/README.md create mode 100644 zsh/.oh-my-zsh/plugins/bower/_bower create mode 100644 zsh/.oh-my-zsh/plugins/bower/bower.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/branch/README.md create mode 100644 zsh/.oh-my-zsh/plugins/branch/branch.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/brew/README.md create mode 100644 zsh/.oh-my-zsh/plugins/brew/brew.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/bridgetown/README.md create mode 100644 zsh/.oh-my-zsh/plugins/bridgetown/bridgetown.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/bun/README.md create mode 100644 zsh/.oh-my-zsh/plugins/bun/bun.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/bundler/README.md create mode 100644 zsh/.oh-my-zsh/plugins/bundler/_bundler create mode 100644 zsh/.oh-my-zsh/plugins/bundler/bundler.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/cabal/README.md create mode 100644 zsh/.oh-my-zsh/plugins/cabal/cabal.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/cake/README.md create mode 100644 zsh/.oh-my-zsh/plugins/cake/cake.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/cakephp3/README.md create mode 100644 zsh/.oh-my-zsh/plugins/cakephp3/cakephp3.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/capistrano/README.md create mode 100644 zsh/.oh-my-zsh/plugins/capistrano/_capistrano create mode 100644 zsh/.oh-my-zsh/plugins/capistrano/capistrano.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/cask/README.md create mode 100644 zsh/.oh-my-zsh/plugins/cask/cask.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/catimg/README.md create mode 100644 zsh/.oh-my-zsh/plugins/catimg/catimg.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/catimg/catimg.sh create mode 100644 zsh/.oh-my-zsh/plugins/catimg/colors.png create mode 100644 zsh/.oh-my-zsh/plugins/celery/README.md create mode 100644 zsh/.oh-my-zsh/plugins/celery/_celery create mode 100644 zsh/.oh-my-zsh/plugins/charm/README.md create mode 100644 zsh/.oh-my-zsh/plugins/charm/charm.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/chruby/README.md create mode 100644 zsh/.oh-my-zsh/plugins/chruby/chruby.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/chucknorris/.gitignore create mode 100644 zsh/.oh-my-zsh/plugins/chucknorris/README.md create mode 100644 zsh/.oh-my-zsh/plugins/chucknorris/chucknorris.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/chucknorris/fortunes/chucknorris create mode 100644 zsh/.oh-my-zsh/plugins/cloudfoundry/README.md create mode 100644 zsh/.oh-my-zsh/plugins/cloudfoundry/cloudfoundry.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/codeclimate/README.md create mode 100644 zsh/.oh-my-zsh/plugins/codeclimate/_codeclimate create mode 100644 zsh/.oh-my-zsh/plugins/coffee/README.md create mode 100644 zsh/.oh-my-zsh/plugins/coffee/_coffee create mode 100644 zsh/.oh-my-zsh/plugins/coffee/coffee.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/colemak/.gitignore create mode 100644 zsh/.oh-my-zsh/plugins/colemak/README.md create mode 100644 zsh/.oh-my-zsh/plugins/colemak/colemak-less create mode 100644 zsh/.oh-my-zsh/plugins/colemak/colemak.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/colored-man-pages/README.md create mode 100644 zsh/.oh-my-zsh/plugins/colored-man-pages/colored-man-pages.plugin.zsh create mode 100755 zsh/.oh-my-zsh/plugins/colored-man-pages/nroff create mode 100644 zsh/.oh-my-zsh/plugins/colorize/README.md create mode 100644 zsh/.oh-my-zsh/plugins/colorize/colorize.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/command-not-found/README.md create mode 100644 zsh/.oh-my-zsh/plugins/command-not-found/command-not-found.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/common-aliases/README.md create mode 100644 zsh/.oh-my-zsh/plugins/common-aliases/common-aliases.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/compleat/README.md create mode 100644 zsh/.oh-my-zsh/plugins/compleat/compleat.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/composer/README.md create mode 100644 zsh/.oh-my-zsh/plugins/composer/composer.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/copybuffer/README.md create mode 100644 zsh/.oh-my-zsh/plugins/copybuffer/copybuffer.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/copyfile/README.md create mode 100644 zsh/.oh-my-zsh/plugins/copyfile/copyfile.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/copypath/README.md create mode 100644 zsh/.oh-my-zsh/plugins/copypath/copypath.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/cp/README.md create mode 100644 zsh/.oh-my-zsh/plugins/cp/cp.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/cpanm/README.md create mode 100644 zsh/.oh-my-zsh/plugins/cpanm/_cpanm create mode 100644 zsh/.oh-my-zsh/plugins/dash/README.md create mode 100644 zsh/.oh-my-zsh/plugins/dash/dash.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/dbt/README.md create mode 100644 zsh/.oh-my-zsh/plugins/dbt/dbt.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/debian/README.md create mode 100644 zsh/.oh-my-zsh/plugins/debian/debian.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/deno/README.md create mode 100644 zsh/.oh-my-zsh/plugins/deno/deno.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/dircycle/README.md create mode 100644 zsh/.oh-my-zsh/plugins/dircycle/dircycle.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/direnv/README.md create mode 100644 zsh/.oh-my-zsh/plugins/direnv/direnv.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/dirhistory/README.md create mode 100644 zsh/.oh-my-zsh/plugins/dirhistory/dirhistory.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/dirpersist/README.md create mode 100644 zsh/.oh-my-zsh/plugins/dirpersist/dirpersist.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/dnf/README.md create mode 100644 zsh/.oh-my-zsh/plugins/dnf/dnf.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/dnote/README.md create mode 100644 zsh/.oh-my-zsh/plugins/dnote/_dnote create mode 100644 zsh/.oh-my-zsh/plugins/docker-compose/README.md create mode 100644 zsh/.oh-my-zsh/plugins/docker-compose/_docker-compose create mode 100644 zsh/.oh-my-zsh/plugins/docker-compose/docker-compose.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/docker-machine/README.md create mode 100644 zsh/.oh-my-zsh/plugins/docker-machine/_docker-machine create mode 100644 zsh/.oh-my-zsh/plugins/docker-machine/docker-machine.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/docker/README.md create mode 100644 zsh/.oh-my-zsh/plugins/docker/completions/_docker create mode 100644 zsh/.oh-my-zsh/plugins/docker/docker.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/doctl/README.md create mode 100644 zsh/.oh-my-zsh/plugins/doctl/doctl.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/dotenv/README.md create mode 100644 zsh/.oh-my-zsh/plugins/dotenv/dotenv.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/dotnet/README.md create mode 100644 zsh/.oh-my-zsh/plugins/dotnet/dotnet.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/droplr/README.md create mode 100644 zsh/.oh-my-zsh/plugins/droplr/droplr.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/drush/README.md create mode 100644 zsh/.oh-my-zsh/plugins/drush/drush.complete.sh create mode 100644 zsh/.oh-my-zsh/plugins/drush/drush.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/eecms/README.md create mode 100644 zsh/.oh-my-zsh/plugins/eecms/eecms.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emacs/README.md create mode 100644 zsh/.oh-my-zsh/plugins/emacs/emacs.plugin.zsh create mode 100755 zsh/.oh-my-zsh/plugins/emacs/emacsclient.sh create mode 100644 zsh/.oh-my-zsh/plugins/ember-cli/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ember-cli/_ember-cli create mode 100644 zsh/.oh-my-zsh/plugins/ember-cli/ember-cli.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emoji-clock/README.md create mode 100644 zsh/.oh-my-zsh/plugins/emoji-clock/emoji-clock.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emoji/README.md create mode 100644 zsh/.oh-my-zsh/plugins/emoji/emoji-char-definitions.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emoji/emoji-data.txt create mode 100644 zsh/.oh-my-zsh/plugins/emoji/emoji.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emoji/gemoji_db.json create mode 100644 zsh/.oh-my-zsh/plugins/emoji/update_emoji.py create mode 100644 zsh/.oh-my-zsh/plugins/emotty/README.md create mode 100644 zsh/.oh-my-zsh/plugins/emotty/emotty.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emotty/emotty_emoji_set.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emotty/emotty_floral_set.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emotty/emotty_love_set.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emotty/emotty_nature_set.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emotty/emotty_stellar_set.zsh create mode 100644 zsh/.oh-my-zsh/plugins/emotty/emotty_zodiac_set.zsh create mode 100644 zsh/.oh-my-zsh/plugins/encode64/README.md create mode 100644 zsh/.oh-my-zsh/plugins/encode64/encode64.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/extract/README.md create mode 100644 zsh/.oh-my-zsh/plugins/extract/_extract create mode 100644 zsh/.oh-my-zsh/plugins/extract/extract.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/eza/README.md create mode 100644 zsh/.oh-my-zsh/plugins/eza/eza.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fabric/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fabric/_fab create mode 100644 zsh/.oh-my-zsh/plugins/fabric/fabric.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fancy-ctrl-z/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fancy-ctrl-z/fancy-ctrl-z.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fasd/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fasd/fasd.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fastfile/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fastfile/fastfile.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fbterm/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fbterm/fbterm.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fd/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fd/_fd create mode 100644 zsh/.oh-my-zsh/plugins/fig/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fig/fig.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/firewalld/README.md create mode 100644 zsh/.oh-my-zsh/plugins/firewalld/firewalld.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/flutter/README.md create mode 100644 zsh/.oh-my-zsh/plugins/flutter/flutter.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fluxcd/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fluxcd/fluxcd.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fnm/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fnm/fnm.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/forklift/README.md create mode 100644 zsh/.oh-my-zsh/plugins/forklift/forklift.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fossil/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fossil/_fossil create mode 100644 zsh/.oh-my-zsh/plugins/fossil/fossil.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/frontend-search/README.md create mode 100644 zsh/.oh-my-zsh/plugins/frontend-search/_frontend create mode 100644 zsh/.oh-my-zsh/plugins/frontend-search/frontend-search.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/fzf/README.md create mode 100644 zsh/.oh-my-zsh/plugins/fzf/fzf.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/gas/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gas/_gas create mode 100644 zsh/.oh-my-zsh/plugins/gatsby/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gatsby/_gatsby create mode 100644 zsh/.oh-my-zsh/plugins/gcloud/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gcloud/gcloud.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/geeknote/README.md create mode 100644 zsh/.oh-my-zsh/plugins/geeknote/_geeknote create mode 100644 zsh/.oh-my-zsh/plugins/geeknote/geeknote.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/gem/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gem/_gem create mode 100644 zsh/.oh-my-zsh/plugins/gem/gem.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/genpass/README.md create mode 100755 zsh/.oh-my-zsh/plugins/genpass/genpass-apple create mode 100755 zsh/.oh-my-zsh/plugins/genpass/genpass-monkey create mode 100755 zsh/.oh-my-zsh/plugins/genpass/genpass-xkcd create mode 100644 zsh/.oh-my-zsh/plugins/genpass/genpass.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/gh/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gh/gh.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-auto-fetch/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git-auto-fetch/git-auto-fetch.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-commit/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git-commit/git-commit.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-escape-magic/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git-escape-magic/git-escape-magic create mode 100644 zsh/.oh-my-zsh/plugins/git-escape-magic/git-escape-magic.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-extras/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git-extras/git-extras.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-flow-avh/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git-flow-avh/git-flow-avh.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-flow/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git-flow/_git-flow create mode 100644 zsh/.oh-my-zsh/plugins/git-flow/git-flow.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-hubflow/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git-hubflow/git-hubflow.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-lfs/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git-lfs/git-lfs.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-prompt/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git-prompt/git-prompt.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/git-prompt/gitstatus.py create mode 100644 zsh/.oh-my-zsh/plugins/git/README.md create mode 100644 zsh/.oh-my-zsh/plugins/git/git.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/gitfast/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gitfast/_git create mode 100644 zsh/.oh-my-zsh/plugins/gitfast/git-completion.bash create mode 100644 zsh/.oh-my-zsh/plugins/gitfast/git-prompt.sh create mode 100644 zsh/.oh-my-zsh/plugins/gitfast/gitfast.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/github/README.md create mode 100644 zsh/.oh-my-zsh/plugins/github/_hub create mode 100644 zsh/.oh-my-zsh/plugins/github/github.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/gitignore/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gitignore/gitignore.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/glassfish/README.md create mode 100644 zsh/.oh-my-zsh/plugins/glassfish/_asadmin create mode 100644 zsh/.oh-my-zsh/plugins/glassfish/glassfish.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/globalias/README.md create mode 100644 zsh/.oh-my-zsh/plugins/globalias/globalias.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/gnu-utils/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gnu-utils/gnu-utils.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/golang/README.md create mode 100644 zsh/.oh-my-zsh/plugins/golang/_golang create mode 100644 zsh/.oh-my-zsh/plugins/golang/golang.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/golang/templates/package.txt create mode 100644 zsh/.oh-my-zsh/plugins/golang/templates/search.txt create mode 100644 zsh/.oh-my-zsh/plugins/gpg-agent/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gpg-agent/gpg-agent.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/gradle/LICENSE create mode 100644 zsh/.oh-my-zsh/plugins/gradle/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gradle/_gradle create mode 100644 zsh/.oh-my-zsh/plugins/gradle/gradle.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/grails/README.md create mode 100644 zsh/.oh-my-zsh/plugins/grails/grails.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/grc/README.md create mode 100644 zsh/.oh-my-zsh/plugins/grc/grc.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/grunt/README.md create mode 100644 zsh/.oh-my-zsh/plugins/grunt/grunt.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/gulp/README.md create mode 100644 zsh/.oh-my-zsh/plugins/gulp/gulp.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/hanami/README.md create mode 100644 zsh/.oh-my-zsh/plugins/hanami/hanami.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/hasura/README.md create mode 100644 zsh/.oh-my-zsh/plugins/hasura/hasura.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/helm/README.md create mode 100644 zsh/.oh-my-zsh/plugins/helm/helm.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/heroku-alias/README.md create mode 100644 zsh/.oh-my-zsh/plugins/heroku-alias/heroku.alias.sh create mode 100644 zsh/.oh-my-zsh/plugins/heroku/README.md create mode 100644 zsh/.oh-my-zsh/plugins/heroku/heroku.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/history-substring-search/README.md create mode 100644 zsh/.oh-my-zsh/plugins/history-substring-search/dependencies/OMZ-README.md create mode 100644 zsh/.oh-my-zsh/plugins/history-substring-search/history-substring-search.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/history-substring-search/history-substring-search.zsh create mode 100644 zsh/.oh-my-zsh/plugins/history/README.md create mode 100644 zsh/.oh-my-zsh/plugins/history/history.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/hitchhiker/.gitignore create mode 100644 zsh/.oh-my-zsh/plugins/hitchhiker/README.md create mode 100644 zsh/.oh-my-zsh/plugins/hitchhiker/fortunes/hitchhiker create mode 100644 zsh/.oh-my-zsh/plugins/hitchhiker/hitchhiker.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/hitokoto/README.md create mode 100644 zsh/.oh-my-zsh/plugins/hitokoto/hitokoto.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/homestead/README.md create mode 100644 zsh/.oh-my-zsh/plugins/homestead/homestead.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/httpie/README.md create mode 100644 zsh/.oh-my-zsh/plugins/httpie/_httpie create mode 100644 zsh/.oh-my-zsh/plugins/invoke/README.md create mode 100644 zsh/.oh-my-zsh/plugins/invoke/invoke.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/ionic/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ionic/ionic.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/ipfs/LICENSE create mode 100644 zsh/.oh-my-zsh/plugins/ipfs/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ipfs/_ipfs create mode 100644 zsh/.oh-my-zsh/plugins/isodate/README.md create mode 100644 zsh/.oh-my-zsh/plugins/isodate/isodate.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/istioctl/README.md create mode 100644 zsh/.oh-my-zsh/plugins/istioctl/istioctl.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/iterm2/README.md create mode 100644 zsh/.oh-my-zsh/plugins/iterm2/iterm2.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/iterm2/iterm2_shell_integration.zsh create mode 100755 zsh/.oh-my-zsh/plugins/iterm2/update create mode 100644 zsh/.oh-my-zsh/plugins/jake-node/README.md create mode 100644 zsh/.oh-my-zsh/plugins/jake-node/jake-node.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/jenv/README.md create mode 100644 zsh/.oh-my-zsh/plugins/jenv/jenv.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/jfrog/README.md create mode 100644 zsh/.oh-my-zsh/plugins/jfrog/jfrog.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/jhbuild/README.md create mode 100644 zsh/.oh-my-zsh/plugins/jhbuild/jhbuild.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/jira/README.md create mode 100644 zsh/.oh-my-zsh/plugins/jira/_jira create mode 100644 zsh/.oh-my-zsh/plugins/jira/jira.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/jruby/README.md create mode 100644 zsh/.oh-my-zsh/plugins/jruby/jruby.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/jsontools/README.md create mode 100644 zsh/.oh-my-zsh/plugins/jsontools/jsontools.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/juju/README.md create mode 100644 zsh/.oh-my-zsh/plugins/juju/juju.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/jump/README.md create mode 100644 zsh/.oh-my-zsh/plugins/jump/jump.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/kate/README.md create mode 100644 zsh/.oh-my-zsh/plugins/kate/kate.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/keychain/README.md create mode 100644 zsh/.oh-my-zsh/plugins/keychain/keychain.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/kind/README.md create mode 100644 zsh/.oh-my-zsh/plugins/kind/kind.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/kitchen/README.md create mode 100644 zsh/.oh-my-zsh/plugins/kitchen/_kitchen create mode 100644 zsh/.oh-my-zsh/plugins/kitty/README.md create mode 100644 zsh/.oh-my-zsh/plugins/kitty/kitty.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/kn/README.md create mode 100644 zsh/.oh-my-zsh/plugins/kn/kn.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/knife/README.md create mode 100644 zsh/.oh-my-zsh/plugins/knife/_knife create mode 100644 zsh/.oh-my-zsh/plugins/knife_ssh/README.md create mode 100644 zsh/.oh-my-zsh/plugins/knife_ssh/knife_ssh.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/kops/README.md create mode 100644 zsh/.oh-my-zsh/plugins/kops/kops.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/kube-ps1/README.md create mode 100644 zsh/.oh-my-zsh/plugins/kube-ps1/kube-ps1.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/kubectl/README.md create mode 100644 zsh/.oh-my-zsh/plugins/kubectl/kubectl.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/kubectx/README.md create mode 100644 zsh/.oh-my-zsh/plugins/kubectx/kubectx.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/kubectx/prod.png create mode 100644 zsh/.oh-my-zsh/plugins/kubectx/stage.png create mode 100644 zsh/.oh-my-zsh/plugins/lando/LICENSE create mode 100644 zsh/.oh-my-zsh/plugins/lando/README.md create mode 100644 zsh/.oh-my-zsh/plugins/lando/lando.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/laravel/README.md create mode 100644 zsh/.oh-my-zsh/plugins/laravel/_artisan create mode 100644 zsh/.oh-my-zsh/plugins/laravel/laravel.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/laravel4/README.md create mode 100644 zsh/.oh-my-zsh/plugins/laravel4/laravel4.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/laravel5/README.md create mode 100644 zsh/.oh-my-zsh/plugins/laravel5/laravel5.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/last-working-dir/README.md create mode 100644 zsh/.oh-my-zsh/plugins/last-working-dir/last-working-dir.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/lein/README.md create mode 100644 zsh/.oh-my-zsh/plugins/lein/_lein create mode 100644 zsh/.oh-my-zsh/plugins/lighthouse/README.md create mode 100644 zsh/.oh-my-zsh/plugins/lighthouse/lighthouse.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/lol/README.md create mode 100644 zsh/.oh-my-zsh/plugins/lol/lol.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/lpass/README.md create mode 100644 zsh/.oh-my-zsh/plugins/lpass/_lpass create mode 100644 zsh/.oh-my-zsh/plugins/lxd/README.md create mode 100644 zsh/.oh-my-zsh/plugins/lxd/lxd.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/macos/README.md create mode 100644 zsh/.oh-my-zsh/plugins/macos/_security create mode 100644 zsh/.oh-my-zsh/plugins/macos/macos.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/macos/music create mode 100644 zsh/.oh-my-zsh/plugins/macos/spotify create mode 100644 zsh/.oh-my-zsh/plugins/macports/README.md create mode 100644 zsh/.oh-my-zsh/plugins/macports/_port create mode 100644 zsh/.oh-my-zsh/plugins/macports/macports.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/magic-enter/README.md create mode 100644 zsh/.oh-my-zsh/plugins/magic-enter/magic-enter.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/man/README.md create mode 100644 zsh/.oh-my-zsh/plugins/man/man.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/marked2/README.md create mode 100644 zsh/.oh-my-zsh/plugins/marked2/marked2.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/marktext/README.md create mode 100644 zsh/.oh-my-zsh/plugins/marktext/marktext.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/mercurial/README.md create mode 100644 zsh/.oh-my-zsh/plugins/mercurial/mercurial.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/meteor/README.md create mode 100644 zsh/.oh-my-zsh/plugins/meteor/_meteor create mode 100644 zsh/.oh-my-zsh/plugins/meteor/meteor.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/microk8s/README.md create mode 100644 zsh/.oh-my-zsh/plugins/microk8s/microk8s.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/minikube/README.md create mode 100644 zsh/.oh-my-zsh/plugins/minikube/minikube.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/mise/README.md create mode 100644 zsh/.oh-my-zsh/plugins/mise/mise.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/mix-fast/README.md create mode 100644 zsh/.oh-my-zsh/plugins/mix-fast/mix-fast.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/mix/README.md create mode 100644 zsh/.oh-my-zsh/plugins/mix/_mix create mode 100644 zsh/.oh-my-zsh/plugins/mongo-atlas/README.md create mode 100644 zsh/.oh-my-zsh/plugins/mongo-atlas/mongo-atlas.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/mongocli/README.md create mode 100644 zsh/.oh-my-zsh/plugins/mongocli/mongocli.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/mosh/README.md create mode 100644 zsh/.oh-my-zsh/plugins/mosh/mosh.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/multipass/README.md create mode 100644 zsh/.oh-my-zsh/plugins/multipass/_multipass create mode 100644 zsh/.oh-my-zsh/plugins/multipass/multipass.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/mvn/README.md create mode 100644 zsh/.oh-my-zsh/plugins/mvn/mvn.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/mysql-macports/README.md create mode 100644 zsh/.oh-my-zsh/plugins/mysql-macports/mysql-macports.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/n98-magerun/README.md create mode 100644 zsh/.oh-my-zsh/plugins/n98-magerun/n98-magerun.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/nanoc/README.md create mode 100644 zsh/.oh-my-zsh/plugins/nanoc/_nanoc create mode 100644 zsh/.oh-my-zsh/plugins/nanoc/nanoc.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/nats/README.md create mode 100644 zsh/.oh-my-zsh/plugins/nats/nats.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/ng/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ng/_ng create mode 100644 zsh/.oh-my-zsh/plugins/nmap/README.md create mode 100644 zsh/.oh-my-zsh/plugins/nmap/nmap.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/node/README.md create mode 100644 zsh/.oh-my-zsh/plugins/node/node.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/nodenv/README.md create mode 100644 zsh/.oh-my-zsh/plugins/nodenv/nodenv.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/nomad/README.md create mode 100644 zsh/.oh-my-zsh/plugins/nomad/_nomad create mode 100644 zsh/.oh-my-zsh/plugins/npm/README.md create mode 100644 zsh/.oh-my-zsh/plugins/npm/npm.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/nvm/README.md create mode 100644 zsh/.oh-my-zsh/plugins/nvm/nvm.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/oc/README.md create mode 100644 zsh/.oh-my-zsh/plugins/oc/oc.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/octozen/README.md create mode 100644 zsh/.oh-my-zsh/plugins/octozen/octozen.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/operator-sdk/README.md create mode 100644 zsh/.oh-my-zsh/plugins/operator-sdk/operator-sdk.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/otp/README.md create mode 100644 zsh/.oh-my-zsh/plugins/otp/otp.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pass/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pass/_pass create mode 100644 zsh/.oh-my-zsh/plugins/paver/README.md create mode 100644 zsh/.oh-my-zsh/plugins/paver/paver.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pep8/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pep8/_pep8 create mode 100644 zsh/.oh-my-zsh/plugins/per-directory-history/README.md create mode 120000 zsh/.oh-my-zsh/plugins/per-directory-history/per-directory-history.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/per-directory-history/per-directory-history.zsh create mode 100644 zsh/.oh-my-zsh/plugins/percol/README.md create mode 100644 zsh/.oh-my-zsh/plugins/percol/percol.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/perl/README.md create mode 100644 zsh/.oh-my-zsh/plugins/perl/perl.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/perms/README.md create mode 100644 zsh/.oh-my-zsh/plugins/perms/perms.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/phing/README.md create mode 100644 zsh/.oh-my-zsh/plugins/phing/phing.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pip/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pip/_pip create mode 100644 zsh/.oh-my-zsh/plugins/pip/pip.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pipenv/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pipenv/pipenv.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pj/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pj/pj.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/please/README.md create mode 100644 zsh/.oh-my-zsh/plugins/please/please.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pm2/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pm2/_pm2 create mode 100644 zsh/.oh-my-zsh/plugins/pm2/pm2.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pod/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pod/_pod create mode 100644 zsh/.oh-my-zsh/plugins/podman/README.md create mode 100644 zsh/.oh-my-zsh/plugins/podman/podman.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/poetry-env/README.md create mode 100644 zsh/.oh-my-zsh/plugins/poetry-env/poetry-env.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/poetry/README.md create mode 100644 zsh/.oh-my-zsh/plugins/poetry/poetry.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/postgres/README.md create mode 100644 zsh/.oh-my-zsh/plugins/postgres/postgres.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pow/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pow/pow.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/powder/README.md create mode 100644 zsh/.oh-my-zsh/plugins/powder/_powder create mode 100644 zsh/.oh-my-zsh/plugins/powify/README.md create mode 100644 zsh/.oh-my-zsh/plugins/powify/_powify create mode 100644 zsh/.oh-my-zsh/plugins/pre-commit/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pre-commit/pre-commit.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/procs/README.md create mode 100644 zsh/.oh-my-zsh/plugins/procs/procs.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/profiles/README.md create mode 100644 zsh/.oh-my-zsh/plugins/profiles/profiles.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pyenv/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pyenv/pyenv.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/pylint/README.md create mode 100644 zsh/.oh-my-zsh/plugins/pylint/_pylint create mode 100644 zsh/.oh-my-zsh/plugins/pylint/pylint.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/python/README.md create mode 100644 zsh/.oh-my-zsh/plugins/python/python.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/qodana/README.md create mode 100644 zsh/.oh-my-zsh/plugins/qodana/qodana.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/qrcode/README.md create mode 100644 zsh/.oh-my-zsh/plugins/qrcode/qrcode.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rails/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rails/_rails create mode 100644 zsh/.oh-my-zsh/plugins/rails/rails.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rake-fast/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rake-fast/rake-fast.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rake/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rake/rake.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rand-quote/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rand-quote/rand-quote.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rbenv/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rbenv/rbenv.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rbfu/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rbfu/rbfu.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rbw/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rbw/rbw.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/react-native/README.md create mode 100644 zsh/.oh-my-zsh/plugins/react-native/_react-native create mode 100644 zsh/.oh-my-zsh/plugins/react-native/react-native.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rebar/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rebar/_rebar create mode 100644 zsh/.oh-my-zsh/plugins/redis-cli/README.md create mode 100644 zsh/.oh-my-zsh/plugins/redis-cli/_redis-cli create mode 100644 zsh/.oh-my-zsh/plugins/repo/README.md create mode 100644 zsh/.oh-my-zsh/plugins/repo/_repo create mode 100644 zsh/.oh-my-zsh/plugins/repo/repo.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/ripgrep/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ripgrep/_ripgrep create mode 100644 zsh/.oh-my-zsh/plugins/ros/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ros/_ros create mode 100644 zsh/.oh-my-zsh/plugins/rsync/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rsync/rsync.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rtx/rtx.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/ruby/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ruby/ruby.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rust/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rust/_rustc create mode 100644 zsh/.oh-my-zsh/plugins/rust/rust.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/rvm/README.md create mode 100644 zsh/.oh-my-zsh/plugins/rvm/rvm.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/safe-paste/README.md create mode 100644 zsh/.oh-my-zsh/plugins/safe-paste/safe-paste.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/salt/README.md create mode 100644 zsh/.oh-my-zsh/plugins/salt/_salt create mode 100644 zsh/.oh-my-zsh/plugins/samtools/README.md create mode 100644 zsh/.oh-my-zsh/plugins/samtools/_samtools create mode 100644 zsh/.oh-my-zsh/plugins/sbt/README.md create mode 100644 zsh/.oh-my-zsh/plugins/sbt/_sbt create mode 100644 zsh/.oh-my-zsh/plugins/sbt/sbt.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/scala/README.md create mode 100644 zsh/.oh-my-zsh/plugins/scala/_scala create mode 100644 zsh/.oh-my-zsh/plugins/scd/README.md create mode 100644 zsh/.oh-my-zsh/plugins/scd/_scd create mode 100755 zsh/.oh-my-zsh/plugins/scd/scd create mode 100644 zsh/.oh-my-zsh/plugins/scd/scd.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/screen/README.md create mode 100644 zsh/.oh-my-zsh/plugins/screen/screen.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/scw/README.md create mode 100644 zsh/.oh-my-zsh/plugins/scw/_scw create mode 100644 zsh/.oh-my-zsh/plugins/sdk/README.md create mode 100644 zsh/.oh-my-zsh/plugins/sdk/sdk.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/sfdx/README.md create mode 100644 zsh/.oh-my-zsh/plugins/sfdx/_sfdx create mode 100644 zsh/.oh-my-zsh/plugins/sfffe/README.md create mode 100644 zsh/.oh-my-zsh/plugins/sfffe/sfffe.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/shell-proxy/.editorconfig create mode 100644 zsh/.oh-my-zsh/plugins/shell-proxy/README.md create mode 100755 zsh/.oh-my-zsh/plugins/shell-proxy/proxy.py create mode 100644 zsh/.oh-my-zsh/plugins/shell-proxy/shell-proxy.plugin.zsh create mode 100755 zsh/.oh-my-zsh/plugins/shell-proxy/ssh-agent.py create mode 100755 zsh/.oh-my-zsh/plugins/shell-proxy/ssh-proxy.py create mode 100644 zsh/.oh-my-zsh/plugins/shrink-path/README.md create mode 100644 zsh/.oh-my-zsh/plugins/shrink-path/shrink-path.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/sigstore/README.md create mode 100644 zsh/.oh-my-zsh/plugins/sigstore/sigstore.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/singlechar/README.md create mode 100644 zsh/.oh-my-zsh/plugins/singlechar/singlechar.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/skaffold/README.md create mode 100644 zsh/.oh-my-zsh/plugins/skaffold/skaffold.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/snap/README.md create mode 100644 zsh/.oh-my-zsh/plugins/snap/snap.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/spring/README.md create mode 100644 zsh/.oh-my-zsh/plugins/spring/_spring create mode 100644 zsh/.oh-my-zsh/plugins/sprunge/README.md create mode 100644 zsh/.oh-my-zsh/plugins/sprunge/sprunge.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/ssh-agent/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ssh-agent/ssh-agent.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/ssh/ssh.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/stack/README.md create mode 100644 zsh/.oh-my-zsh/plugins/stack/stack.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/starship/README.md create mode 100644 zsh/.oh-my-zsh/plugins/starship/starship.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/stripe/README.md create mode 100644 zsh/.oh-my-zsh/plugins/stripe/stripe.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/sublime-merge/README.md create mode 100644 zsh/.oh-my-zsh/plugins/sublime-merge/sublime-merge.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/sublime/README.md create mode 100644 zsh/.oh-my-zsh/plugins/sublime/sublime.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/sudo/README.md create mode 100644 zsh/.oh-my-zsh/plugins/sudo/sudo.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/supervisor/README.md create mode 100644 zsh/.oh-my-zsh/plugins/supervisor/_supervisorctl create mode 100644 zsh/.oh-my-zsh/plugins/supervisor/_supervisord create mode 100644 zsh/.oh-my-zsh/plugins/supervisor/supervisor.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/suse/README.md create mode 100644 zsh/.oh-my-zsh/plugins/suse/suse.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/svcat/README.md create mode 100644 zsh/.oh-my-zsh/plugins/svcat/svcat.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/svn-fast-info/README.md create mode 100644 zsh/.oh-my-zsh/plugins/svn-fast-info/svn-fast-info.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/svn/README.md create mode 100644 zsh/.oh-my-zsh/plugins/svn/svn.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/swiftpm/README.md create mode 100644 zsh/.oh-my-zsh/plugins/swiftpm/_swift create mode 100644 zsh/.oh-my-zsh/plugins/swiftpm/swiftpm.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/symfony/README.md create mode 100644 zsh/.oh-my-zsh/plugins/symfony/symfony.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/symfony2/README.md create mode 100644 zsh/.oh-my-zsh/plugins/symfony2/symfony2.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/symfony6/README.md create mode 100644 zsh/.oh-my-zsh/plugins/symfony6/symfony6.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/systemadmin/README.md create mode 100644 zsh/.oh-my-zsh/plugins/systemadmin/systemadmin.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/systemd/README.md create mode 100644 zsh/.oh-my-zsh/plugins/systemd/systemd.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/taskwarrior/README.md create mode 100644 zsh/.oh-my-zsh/plugins/taskwarrior/_task create mode 100644 zsh/.oh-my-zsh/plugins/taskwarrior/taskwarrior.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/term_tab/README.md create mode 100644 zsh/.oh-my-zsh/plugins/term_tab/term_tab.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/terminitor/README.md create mode 100644 zsh/.oh-my-zsh/plugins/terminitor/_terminitor create mode 100644 zsh/.oh-my-zsh/plugins/terraform/README.md create mode 100644 zsh/.oh-my-zsh/plugins/terraform/_terraform create mode 100644 zsh/.oh-my-zsh/plugins/terraform/terraform.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/textastic/README.md create mode 100644 zsh/.oh-my-zsh/plugins/textastic/textastic.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/textmate/README.md create mode 100644 zsh/.oh-my-zsh/plugins/textmate/textmate.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/thefuck/README.md create mode 100644 zsh/.oh-my-zsh/plugins/thefuck/thefuck.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/themes/README.md create mode 100644 zsh/.oh-my-zsh/plugins/themes/themes.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/thor/README.md create mode 100644 zsh/.oh-my-zsh/plugins/thor/_thor create mode 100644 zsh/.oh-my-zsh/plugins/tig/README.md create mode 100644 zsh/.oh-my-zsh/plugins/tig/tig.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/timer/README.md create mode 100644 zsh/.oh-my-zsh/plugins/timer/timer.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/tldr/README.md create mode 100644 zsh/.oh-my-zsh/plugins/tldr/tldr.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/tmux-cssh/README.md create mode 100644 zsh/.oh-my-zsh/plugins/tmux-cssh/_tmux-cssh create mode 100644 zsh/.oh-my-zsh/plugins/tmux/README.md create mode 100644 zsh/.oh-my-zsh/plugins/tmux/tmux.extra.conf create mode 100644 zsh/.oh-my-zsh/plugins/tmux/tmux.only.conf create mode 100644 zsh/.oh-my-zsh/plugins/tmux/tmux.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/tmuxinator/README.md create mode 100644 zsh/.oh-my-zsh/plugins/tmuxinator/_tmuxinator create mode 100644 zsh/.oh-my-zsh/plugins/tmuxinator/tmuxinator.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/toolbox/README.md create mode 100644 zsh/.oh-my-zsh/plugins/toolbox/toolbox.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/torrent/README.md create mode 100644 zsh/.oh-my-zsh/plugins/torrent/torrent.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/transfer/README.md create mode 100644 zsh/.oh-my-zsh/plugins/transfer/transfer.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/tugboat/README.md create mode 100644 zsh/.oh-my-zsh/plugins/tugboat/_tugboat create mode 100644 zsh/.oh-my-zsh/plugins/ubuntu/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ubuntu/ubuntu.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/ufw/README.md create mode 100644 zsh/.oh-my-zsh/plugins/ufw/_ufw create mode 100644 zsh/.oh-my-zsh/plugins/universalarchive/README.md create mode 100644 zsh/.oh-my-zsh/plugins/universalarchive/_universalarchive create mode 100644 zsh/.oh-my-zsh/plugins/universalarchive/universalarchive.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/urltools/README.md create mode 100644 zsh/.oh-my-zsh/plugins/urltools/urltools.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/vagrant-prompt/README.md create mode 100644 zsh/.oh-my-zsh/plugins/vagrant-prompt/vagrant-prompt.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/vagrant/README.md create mode 100644 zsh/.oh-my-zsh/plugins/vagrant/_vagrant create mode 100644 zsh/.oh-my-zsh/plugins/vagrant/vagrant.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/vault/README.md create mode 100644 zsh/.oh-my-zsh/plugins/vault/_vault create mode 100644 zsh/.oh-my-zsh/plugins/vi-mode/README.md create mode 100644 zsh/.oh-my-zsh/plugins/vi-mode/vi-mode.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/vim-interaction/README.md create mode 100644 zsh/.oh-my-zsh/plugins/vim-interaction/vim-interaction.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/virtualenv/README.md create mode 100644 zsh/.oh-my-zsh/plugins/virtualenv/virtualenv.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/virtualenvwrapper/README.md create mode 100644 zsh/.oh-my-zsh/plugins/virtualenvwrapper/virtualenvwrapper.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/volta/README.md create mode 100644 zsh/.oh-my-zsh/plugins/volta/volta.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/vscode/README.md create mode 100644 zsh/.oh-my-zsh/plugins/vscode/vscode.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/vundle/README.md create mode 100644 zsh/.oh-my-zsh/plugins/vundle/vundle.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/wakeonlan/README.md create mode 100644 zsh/.oh-my-zsh/plugins/wakeonlan/_wake create mode 100644 zsh/.oh-my-zsh/plugins/wakeonlan/wakeonlan.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/watson/README.md create mode 100644 zsh/.oh-my-zsh/plugins/watson/_watson create mode 100644 zsh/.oh-my-zsh/plugins/wd/LICENSE create mode 100644 zsh/.oh-my-zsh/plugins/wd/README.md create mode 100644 zsh/.oh-my-zsh/plugins/wd/_wd.sh create mode 100644 zsh/.oh-my-zsh/plugins/wd/wd.plugin.zsh create mode 100755 zsh/.oh-my-zsh/plugins/wd/wd.sh create mode 100644 zsh/.oh-my-zsh/plugins/web-search/README.md create mode 100644 zsh/.oh-my-zsh/plugins/web-search/web-search.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/wp-cli/README.md create mode 100644 zsh/.oh-my-zsh/plugins/wp-cli/wp-cli.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/xcode/README.md create mode 100644 zsh/.oh-my-zsh/plugins/xcode/_xcselv create mode 100644 zsh/.oh-my-zsh/plugins/xcode/xcode.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/yarn/README.md create mode 100644 zsh/.oh-my-zsh/plugins/yarn/_yarn create mode 100644 zsh/.oh-my-zsh/plugins/yarn/yarn.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/yii/README.md create mode 100644 zsh/.oh-my-zsh/plugins/yii/yii.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/yii2/README.md create mode 100644 zsh/.oh-my-zsh/plugins/yii2/yii2.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/yum/README.md create mode 100644 zsh/.oh-my-zsh/plugins/yum/yum.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/z/LICENSE create mode 100644 zsh/.oh-my-zsh/plugins/z/MANUAL.md create mode 100644 zsh/.oh-my-zsh/plugins/z/README.md create mode 100644 zsh/.oh-my-zsh/plugins/z/_z create mode 100644 zsh/.oh-my-zsh/plugins/z/img/demo.gif create mode 100644 zsh/.oh-my-zsh/plugins/z/img/mit_license.svg create mode 100644 zsh/.oh-my-zsh/plugins/z/img/zsh_4.3.11_plus.svg create mode 100644 zsh/.oh-my-zsh/plugins/z/z.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/zbell/README.md create mode 100644 zsh/.oh-my-zsh/plugins/zbell/zbell.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/zeus/README.md create mode 100644 zsh/.oh-my-zsh/plugins/zeus/_zeus create mode 100644 zsh/.oh-my-zsh/plugins/zeus/zeus.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/zoxide/README.md create mode 100644 zsh/.oh-my-zsh/plugins/zoxide/zoxide.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/zsh-interactive-cd/LICENSE create mode 100644 zsh/.oh-my-zsh/plugins/zsh-interactive-cd/README.md create mode 100644 zsh/.oh-my-zsh/plugins/zsh-interactive-cd/demo.gif create mode 100644 zsh/.oh-my-zsh/plugins/zsh-interactive-cd/zsh-interactive-cd.plugin.zsh create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/.config/znt/n-aliases.conf create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/.config/znt/n-cd.conf create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/.config/znt/n-env.conf create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/.config/znt/n-functions.conf create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/.config/znt/n-history.conf create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/.config/znt/n-kill.conf create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/.config/znt/n-list.conf create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/.config/znt/n-options.conf create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/.config/znt/n-panelize.conf create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/LICENSE create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/Makefile create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/NEWS create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/README.md create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/_n-kill create mode 100755 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/doc/generate_single_file create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/doc/img/n-history2.png create mode 100755 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/doc/install.sh create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/doc/n-preview create mode 100755 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/doc/znt-tmux.zsh create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-aliases create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-cd create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-env create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-functions create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-help create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-history create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-kill create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-list create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-list-draw create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-list-input create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-options create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/n-panelize create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/znt-cd-widget create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/znt-history-widget create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/znt-kill-widget create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/znt-usetty-wrapper create mode 100644 zsh/.oh-my-zsh/plugins/zsh-navigation-tools/zsh-navigation-tools.plugin.zsh create mode 100644 zsh/.oh-my-zsh/templates/zshrc.zsh-template create mode 100644 zsh/.oh-my-zsh/themes/3den.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/Soliah.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/adben.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/af-magic.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/afowler.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/agnoster.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/alanpeabody.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/amuse.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/apple.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/arrow.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/aussiegeek.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/avit.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/awesomepanda.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/bira.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/blinks.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/bureau.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/candy-kingdom.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/candy.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/clean.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/cloud.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/crcandy.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/crunch.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/cypher.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/dallas.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/darkblood.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/daveverwer.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/dieter.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/dogenpunk.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/dpoggi.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/dst.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/dstufft.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/duellj.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/eastwood.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/edvardm.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/emotty.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/essembeh.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/evan.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/fino-time.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/fino.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/fishy.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/flazz.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/fletcherm.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/fox.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/frisk.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/frontcube.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/funky.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/fwalch.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/gallifrey.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/gallois.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/garyblessington.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/gentoo.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/geoffgarside.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/gianu.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/gnzh.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/gozilla.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/half-life.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/humza.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/imajes.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/intheloop.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/itchy.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/jaischeema.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/jbergantine.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/jispwoso.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/jnrowe.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/jonathan.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/josh.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/jreese.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/jtriley.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/juanghurtado.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/junkfood.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/kafeitu.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/kardan.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/kennethreitz.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/kiwi.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/kolo.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/kphoen.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/lambda.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/linuxonly.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/lukerandall.zsh-theme create mode 120000 zsh/.oh-my-zsh/themes/macovsky-ruby.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/macovsky.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/maran.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/mgutz.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/mh.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/michelebologna.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/mikeh.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/miloshadzic.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/minimal.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/mira.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/mlh.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/mortalscumbag.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/mrtazz.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/murilasso.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/muse.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/nanotech.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/nebirhos.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/nicoulaj.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/norm.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/obraun.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/oldgallois.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/peepcode.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/philips.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/pmcgee.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/pygmalion-virtualenv.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/pygmalion.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/random.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/re5et.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/refined.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/rgm.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/risto.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/rixius.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/rkj-repos.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/rkj.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/robbyrussell.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/sammy.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/simonoff.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/simple.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/skaro.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/smt.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/sonicradish.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/sorin.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/sporty_256.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/steeef.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/strug.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/sunaku.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/sunrise.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/superjarin.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/suvash.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/takashiyoshida.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/terminalparty.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/theunraveler.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/tjkirch.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/tjkirch_mod.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/tonotdo.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/trapd00r.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/wedisagree.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/wezm+.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/wezm.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/wuffers.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/xiong-chiamiov-plus.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/xiong-chiamiov.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/ys.zsh-theme create mode 100644 zsh/.oh-my-zsh/themes/zhann.zsh-theme create mode 100755 zsh/.oh-my-zsh/tools/changelog.sh create mode 100644 zsh/.oh-my-zsh/tools/check_for_upgrade.sh create mode 100755 zsh/.oh-my-zsh/tools/install.sh create mode 100755 zsh/.oh-my-zsh/tools/require_tool.sh create mode 100755 zsh/.oh-my-zsh/tools/theme_chooser.sh create mode 100644 zsh/.oh-my-zsh/tools/uninstall.sh create mode 100755 zsh/.oh-my-zsh/tools/upgrade.sh create mode 100644 zsh/.zshrc diff --git a/README.md b/README.md new file mode 100644 index 0000000..bc3cd03 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +#Dotfiles from [Spaenny](https://spenny.tf) + +> All needed Dotfiles to get my system back to a usable state + +## Install +###Requirements + +You will need atleast following packages for it to work + +`paru -S nvim alacritty plasma-meta zsh fzf stow` + +### Getting started + +For stow to restore the old state you have to run following command. +`git clone https://git.snrd.eu/Spaenny/dotfiles.git && cd dotfiles` +`stow alacritty nvim plasma zsh` + +If you just wanna restore one application config you can do so by executing it via package name. +`stow nvim` +This would just restore the nvim config files. + + +WARNING: This will instantly apply my Dotfiles to your machine, for further information how todo this step by step checkout. diff --git a/alacritty/.config/alacritty/alacritty.toml b/alacritty/.config/alacritty/alacritty.toml new file mode 100644 index 0000000..a339657 --- /dev/null +++ b/alacritty/.config/alacritty/alacritty.toml @@ -0,0 +1,15 @@ +# Import our style +import = ["~/.config/alacritty/dracula.toml"] + +# Lets setup copying to system clipboard +[selection] +save_to_clipboard = true + +# Change our cursor to a line +[cursor] +style.shape = "Beam" +style.blinking = "On" + +# We want something different for vim +vi_mode_style.shape = "Block" +vi_mode_style.blinking = "Off" diff --git a/alacritty/.config/alacritty/dracula.toml b/alacritty/.config/alacritty/dracula.toml new file mode 100644 index 0000000..687cce6 --- /dev/null +++ b/alacritty/.config/alacritty/dracula.toml @@ -0,0 +1,76 @@ +# Dracula theme for Alacritty +# https://draculatheme.com/alacritty +# +# Color palette +# https://spec.draculatheme.com +# +# Instructions +# https://github.com/alacritty/alacritty/blob/master/extra/man/alacritty.5.scd + +[colors.primary] + +background = "#282a36" +foreground = "#f8f8f2" +bright_foreground = "#ffffff" + +[colors.cursor] + +text = "#282a36" +cursor = "#f8f8f2" + +[colors.vi_mode_cursor] + +text = "CellBackground" +cursor = "CellForeground" + +[colors.selection] + +text = "CellForeground" +background = "#44475a" + +[colors.normal] + +black = "#21222c" +red = "#ff5555" +green = "#50fa7b" +yellow = "#f1fa8c" +blue = "#bd93f9" +magenta = "#ff79c6" +cyan = "#8be9fd" +white = "#f8f8f2" + +[colors.bright] + +black = "#6272a4" +red = "#ff6e6e" +green = "#69ff94" +yellow = "#ffffa5" +blue = "#d6acff" +magenta = "#ff92df" +cyan = "#a4ffff" +white = "#ffffff" + +[colors.search.matches] + +foreground = "#44475a" +background = "#50fa7b" + +[colors.search.focused_match] + +foreground = "#44475a" +background = "#ffb86c" + +[colors.footer_bar] + +background = "#282a36" +foreground = "#f8f8f2" + +[colors.hints.start] + +foreground = "#282a36" +background = "#f1fa8c" + +[colors.hints.end] + +foreground = "#f1fa8c" +background = "#282a36" diff --git a/nvim/.config/nvim/init.vim b/nvim/.config/nvim/init.vim new file mode 100644 index 0000000..451be46 --- /dev/null +++ b/nvim/.config/nvim/init.vim @@ -0,0 +1,44 @@ +" Get us some plugins +call plug#begin("~/.vim/plugged") +" Plugin Section +Plug 'dracula/vim' +Plug 'ryanoasis/vim-devicons' +Plug 'scrooloose/nerdtree' +call plug#end() + + +" Show matching +set showmatch + +" case insensitive +set ignorecase + +" Enable middle mouse click pasting +set mouse=v + +" Highlight our search +set hlsearch + +" Set columns for tab stop +set tabstop=4 + +" convert tabs to white spaces +set expandtab + +" indent a new line the same amount as the line just typed +set autoindent + +" show line numbers +set number + +" enable syntax highlighting +syntax on + +" use system clipboard +set clipboard=unnamedplus + +" highlight current cursorline +set cursorline + +" disable creating swap file +set noswapfile diff --git a/nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/bug.md b/nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 0000000..f40e5c8 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,46 @@ +--- +name: "Bug Report" +about: "NERDTree is misbehaving? Tell us about it." +labels: bug +--- + + +#### Self-Diagnosis +Before creating an issue, take some time to search these resources for an answer. It's possible that someone else has already seen and solved your issue. +- [old NERDTree issues](https://github.com/preservim/nerdtree/issues?q=is%3Aissue) +- NERDTree documentation - `:h NERDTree` +- [NERDTree Wiki](https://github.com/preservim/nerdtree/wiki) +- Other resources: , , etc. + +#### Environment +- Operating System: +- Vim/Neovim version `:version`: +- NERDTree version, found on first line of quickhelp `?`: +- Are you using any of these NERDTree-dependent plugins? + - [ ] [Xuyuanp/nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin) + - [ ] [ryanoasis/vim-devicons](https://github.com/ryanoasis/vim-devicons) + - [ ] [tiagofumo/vim-nerdtree-syntax-highlight](https://github.com/tiagofumo/vim-nerdtree-syntax-highlight) + - [ ] [scrooloose/nerdtree-project-plugin](https://github.com/scrooloose/nerdtree-project-plugin) + - [ ] [PhilRunninger/nerdtree-buffer-ops](https://github.com/PhilRunninger/nerdtree-buffer-ops) + - [ ] [PhilRunninger/nerdtree-visual-selection](https://github.com/PhilRunninger/nerdtree-visual-selection) + - [ ] [jistr/vim-nerdtree-tabs](https://github.com/jistr/vim-nerdtree-tabs) + - [ ] Others (specify): +- Provide a minimal **.vimrc** file that will reproduce the issue. +```vim +``` + +#### Steps to Reproduce the Issue +1. + +#### Current Behavior (Include screenshots where appropriate.) + +#### Expected Result + diff --git a/nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/feature_request.md b/nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..da2eff1 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,8 @@ +--- +name: "Feature Request" +about: "What new feature are you requesting for NERDTree?" +labels: "feature request" +--- + +#### Description + diff --git a/nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/question.md b/nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000..9144073 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,13 @@ +--- +name: "General Question" +about: "Having trouble setting up NERDTree? Need clarification on a setting? Ask your question here." +labels: "general question" +--- +Before creating an issue, take some time to search these resources. It's possible that someone else has already asked your question and gotten an answer. +- [old NERDTree issues](https://github.com/preservim/nerdtree/issues?q=is%3Aissue) +- NERDTree documentation - `:h NERDTree` +- [NERDTree Wiki](https://github.com/preservim/nerdtree/wiki) +- Other resource: , , etc. + +#### State Your Question + diff --git a/nvim/.vim/plugged/nerdtree/.github/PULL_REQUEST_TEMPLATE.md b/nvim/.vim/plugged/nerdtree/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..2ba5ffa --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ +### Description of Changes +Closes # + + +--- +### New Version Info + diff --git a/nvim/.vim/plugged/nerdtree/.github/workflows/vint.yml b/nvim/.vim/plugged/nerdtree/.github/workflows/vint.yml new file mode 100644 index 0000000..ce0f49d --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/.github/workflows/vint.yml @@ -0,0 +1,15 @@ +name: Vint +on: [push, pull_request] +jobs: + vint: + strategy: + fail-fast: false + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Run vint with reviewdog + uses: reviewdog/action-vint@v1 + with: + github_token: ${{ secrets.github_token }} + reporter: github-pr-review diff --git a/nvim/.vim/plugged/nerdtree/.gitignore b/nvim/.vim/plugged/nerdtree/.gitignore new file mode 100644 index 0000000..f77ac77 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/.gitignore @@ -0,0 +1,3 @@ +*~ +*.swp +tags diff --git a/nvim/.vim/plugged/nerdtree/.vintrc.yaml b/nvim/.vim/plugged/nerdtree/.vintrc.yaml new file mode 100644 index 0000000..1187844 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/.vintrc.yaml @@ -0,0 +1,5 @@ +cmdargs: + severity: style_problem + color: true + env: + neovim: false diff --git a/nvim/.vim/plugged/nerdtree/CHANGELOG.md b/nvim/.vim/plugged/nerdtree/CHANGELOG.md new file mode 100644 index 0000000..dac6c49 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/CHANGELOG.md @@ -0,0 +1,343 @@ +# NERDTree Change Log + +#### 7.1 +- **.2**: + - fix: GetWinNum regex pattern. (rzvxa) [#1409](https://github.com/preservim/nerdtree/pull/1409) + - fix: session restore for nerdtree buffers. (rzvxa) [#1405](https://github.com/preservim/nerdtree/pull/1405) +- **.1**: + - fix: change default binding of filelines to `FL`. (rzvxa) [#1400](https://github.com/preservim/nerdtree/pull/1400) + - fix: toggle zoom resizing. (ds2606) [#1395](https://github.com/preservim/nerdtree/pull/1395) +- **.0**: + - fix: typo in the docs. (bl4kraven) [#1390](https://github.com/preservim/nerdtree/pull/1390) + - feat: add NERDTreeExplore command. (msibal6) [#1389](https://github.com/preservim/nerdtree/pull/1389) + - fix: mapping description in NERDTree.txt. (roccomao) [#1393](https://github.com/preservim/nerdtree/pull/1393) +#### 7.0 +- **.1**: + - Fix NERDTreeFind to handle directory case sensitivity. (dangibson) [#1387](https://github.com/preservim/nerdtree/pull/1387) + - New Show file lines toggle. (hsnks100) [#1384](https://github.com/preservim/nerdtree/pull/1384) + - Add case sensitivity for refreshing nodes. (rzvxa) [#1382](https://github.com/preservim/nerdtree/pull/1382) + - Clarified the NERDTreeChangePermissions prompt. (rzvxa) [#1381](https://github.com/preservim/nerdtree/pull/1381) + - New reveal functionality for Windows. (rzvxa) [#1366](https://github.com/preservim/nerdtree/pull/1366) + - Fix bracket escaping in path names. (kai-patel) [#1359](https://github.com/preservim/nerdtree/pull/1359) + - Fix Case Sensitive Move Operation. (rzvxa) [#1375](https://github.com/preservim/nerdtree/pull/1375) + - New menu command for changing selected node permissions. (mjkloeckner) [#1348](https://github.com/preservim/nerdtree/pull/1348) + - Fix documentation errors. (BubuDavid) [#1372](https://github.com/preservim/nerdtree/pull/1372) + - Fix typo in nerdtree.vim file. (SandeshPyakurel) [#1380](https://github.com/preservim/nerdtree/pull/1380) +- **.0**: + - Now we warn about invalid files instead of ignoring them silently. (rmonico) [#1365](https://github.com/preservim/nerdtree/pull/1365) + - New g:NERDTreeWinPos options for top and bottom. (rzvxa) [#1363](https://github.com/preservim/nerdtree/pull/1363) + - Fix error in README. (nickspoons) [#1330](https://github.com/preservim/nerdtree/pull/1330) + - Fix typo in the documentation. (chapeupreto) [#1306](https://github.com/preservim/nerdtree/pull/1306) +#### 6.10 +- **.16**: Fix documentation errors. (lifecrisis) [#1269](https://github.com/preservim/nerdtree/pull/1269) +- **.15**: Ensure backward compatible testing of types. (lifecrisis) [#1266](https://github.com/preservim/nerdtree/pull/1266) +- **.14**: Replace trim() with a version-compatible alternative. (PhilRunninger) [#1265](https://github.com/preservim/nerdtree/pull/1265) +- **.13**: Change highlighting of bookmarks in the tree. (PhilRunninger) [#1261](https://github.com/preservim/nerdtree/pull/1261) +- **.12**: Answer the question about accessing files over scp or ftp. (PhilRunninger) [#1259](https://github.com/preservim/nerdtree/pull/1259) +- **.11**: Trim filenames created via the fs_menu (elanorigby) [#1243](https://github.com/preservim/nerdtree/pull/1243) +- **.10**: Improve F.A.Q. Answers and Issue Templates (PhilRunninger) [#1249](https://github.com/preservim/nerdtree/pull/1249) +- **.9**: `go` on a bookmark directory will NERDTreeFind it. (PhilRunninger) [#1236](https://github.com/preservim/nerdtree/pull/1236) +- **.8**: Put `Callback` function variables in local scope. (PhilRunninger) [#1230](https://github.com/preservim/nerdtree/pull/1230) +- **.7**: Fix mouse-clicking a file to open it. (PhilRunninger) [#1225](https://github.com/preservim/nerdtree/pull/1225) +- **.6**: Restore the default behavior of the `` key. (PhilRunninger) [#1221](https://github.com/preservim/nerdtree/pull/1221) +- **.5**: Fix `{'keepopen':0}` in NERDTreeCustomOpenArgs (PhilRunninger) [#1217](https://github.com/preservim/nerdtree/pull/1217) +- **.4**: Removed directory separator from sort key (Daniel E) [#1219](https://github.com/preservim/nerdtree/pull/1219) +- **.3**: Add new FAQ and answer: How to prevent buffers replacing NERDTree. (PhilRunninger) [#1215](https://github.com/preservim/nerdtree/pull/1215) +- **.2**: New menu command: Run a system command in this directory. (PhilRunninger) [#1214](https://github.com/preservim/nerdtree/pull/1214) +- **.1**: Escape quotation marks so they can be used in key mappings. (PhilRunninger) [#1213](https://github.com/preservim/nerdtree/pull/1213) +- **.0**: Enable full path specifications for NERDTreeIgnore (PhilRunninger) [#1207](https://github.com/preservim/nerdtree/pull/1207) +#### 6.9 +- **.12**: Respect NERDTreeCustomOpenArgs when opening bookmark (przepompownia) [#1200](https://github.com/preservim/nerdtree/pull/1200) +- **.11**: Revamp the README. (buncis, PhilRunninger) [#1192](https://github.com/preservim/nerdtree/pull/1192), [#1193](https://github.com/preservim/nerdtree/pull/1193) +- **.10**: Open a mirrored NERDTree with correct width (PhilRunninger) [#1177](https://github.com/preservim/nerdtree/pull/1177) +- **.9**: Updated Readme, removed typo (H3RSKO) [#1167](https://github.com/preservim/nerdtree/pull/1167) +- **.8**: Refactor sort comparison functions, removing redundancy (PhilRunninger) [#1166](https://github.com/preservim/nerdtree/pull/1166) +- **.7**: Fix argument of `exists()` function calls checking for autocommands. (PhilRunninger) [#1165](https://github.com/preservim/nerdtree/pull/1165) +- **.6**: Don't use silent when raising User events (PhilRunninger) [#1164](https://github.com/preservim/nerdtree/pull/1164) +- **.5**: Fix highlight for file node. (pirey) [#1157](https://github.com/preservim/nerdtree/pull/1157) +- **.4**: Make sure symbolic links' flags are highlighted correctly. (PhilRunninger) [#1156](https://github.com/preservim/nerdtree/pull/1156) +- **.3**: Fix new NERDTrees' width when previous one was in the only window. (PhilRunninger) [#1153](https://github.com/preservim/nerdtree/pull/1153) +- **.2**: Fix the scope of several key mappings (lifecrisis, PhilRunninger) [#1151](https://github.com/preservim/nerdtree/pull/1151) +- **.1**: Respect user's `&shellslash` setting in CopyNode and RemoveNode functions (PhilRunninger) [#1150](https://github.com/preservim/nerdtree/pull/1150) +- **.0**: Enable opening bookmarks in split windows. (PhilRunninger) [#1144](https://github.com/preservim/nerdtree/pull/1144) +#### 6.8 +- **.0**: Allow concealed characters to show another character. (PhilRunninger) [#1138](https://github.com/preservim/nerdtree/pull/1138) +#### 6.7 +- **.15**: Add curly braces to the list of characters to be escaped. (PhilRunninger) [#1128](https://github.com/preservim/nerdtree/pull/1128) +- **.14**: Use backward-compatible `nerdtree#and()` in one place that was missed. (PhilRunninger) [#1134](https://github.com/preservim/nerdtree/pull/1134) +- **.13**: `cmd.exe /c start "" ` for windows default viewer support. (J. Altayó) [#1130](https://github.com/preservim/nerdtree/pull/1130) +- **.12**: Fixed a bug that caused the file-tree construction to slow down significantly. (Eugenij-W) [#1126](https://github.com/preservim/nerdtree/pull/1126) +- **.11**: Fix exception in NERDTreeFind (on windows OS and If the file is located in the root directory of the disk) (Eugenij-W) [#1122](https://github.com/preservim/nerdtree/pull/1122) +- **.10**: Do not consider the tree root to be "cascadable". (lifecrisis) [#1120](https://github.com/preservim/nerdtree/pull/1120) +- **.9**: Force `:NERDTreeFocus` to allow events to be fired when switching windows. (PhilRunninger) [#1118](https://github.com/preservim/nerdtree/pull/1118) +- **.8**: Fix example code for the `NERDTreeAddKeyMap()` function. (PhilRunninger) [#1116](https://github.com/preservim/nerdtree/pull/1116) +- **.7**: Put `'%'` argument in `bufname()` for backwards compatibility. (PhilRunninger) [#1105](https://github.com/preservim/nerdtree/pull/1105) +- **.6**: If a file's already open in the window, don't edit it again. (PhilRunninger) [#1103](https://github.com/preservim/nerdtree/pull/1103) +- **.5**: Prevent unneeded tree creation in `:NERDTreeToggle[VCS] ` (PhilRunninger) [#1101](https://github.com/preservim/nerdtree/pull/1101) +- **.4**: Add missing calls to the `shellescape()` function (lifecrisis) [#1099](https://github.com/preservim/nerdtree/pull/1099) +- **.3**: Fix vsplit to not open empty buffers when opening previously closed file (AwkwardKore) [#1098](https://github.com/preservim/nerdtree/pull/1098) +- **.2**: Fix infinity loop (on winvim) in FindParentVCSRoot (Eugenij-W) [#1095](https://github.com/preservim/nerdtree/pull/1095) +- **.1**: File Move: Escape existing directory name when looking for open files. (PhilRunninger) [#1094](https://github.com/preservim/nerdtree/pull/1094) +- **.0**: Open the parent directory when revealing a non-existent file with :NERDTreeFind (bouk) [#1090](https://github.com/preservim/nerdtree/pull/1090) +#### 6.6 +- **.1**: [add] How to install using dein.vim (kazukazuinaina) [#1087](https://github.com/preservim/nerdtree/pull/1087) +- **.0**: Add the ability to turn off directory arrows (PhilRunninger) [#1085](https://github.com/preservim/nerdtree/pull/1085) +#### 6.5 +- **.0**: `NERDTreeToggle ` always sets NERDTree root. (PhilRunninger) [#1083](https://github.com/preservim/nerdtree/pull/1083) +#### 6.4 +- **.6**: NERDTreeFind shows expected message if file doesn't exist e.g. with vim-startify (andys8). [#1081](https://github.com/preservim/nerdtree/pull/1081) +- **.5**: Ensure events are (or aren't) being ignored correctly. (PhilRunninger) [#1080](https://github.com/preservim/nerdtree/pull/1080) +- **.4**: Prevent overwriting existing files/dirs on node move. (PhilRunninger) [#1079](https://github.com/preservim/nerdtree/pull/1079) +- **.3**: Fix regex that finds keyword for minimal menu. (PhilRunninger) [#1075](https://github.com/preservim/nerdtree/pull/1075) +- **.2**: Lint vimscript, fix errors and warnings, add CI job to review PRs (Caleb Maclennan) [#1071](https://github.com/preservim/nerdtree/pull/1071) +- **.1**: Ensure backward compatibility. v:t_func is not available before Vim 8.0 (Phil Runninger) +- **.0**: Allow use of function references as callbacks (HiPhish) [#1067](https://github.com/preservim/nerdtree/pull/1067) +#### 6.3 +- **.0**: Add new command that behaves like NERDTreeToggle but defaults to the root of a VCS repository. (willfindlay) [#1060](https://github.com/preservim/nerdtree/pull/1060) +#### 6.2 +- **.1**: Menu option, 'copy path to clipboard' is aware of VIM clipboard option (jhzn) [#1056](https://github.com/preservim/nerdtree/pull/1056) +- **.0**: Support tab-specific CWDs (PhilRunninger) [#1032](https://github.com/preservim/nerdtree/pull/1032) +#### 6.1 +- **.4**: Add VIM built-in package management to read me file. (pesarkhobeee) [#1049](https://github.com/preservim/nerdtree/pull/1049) +- **.3**: Save/Set screen state also on WinLeave and WinEnter. (PhilRunninger) [#1048](https://github.com/preservim/nerdtree/pull/1048) +- **.2**: Wrap saveScreenState's statements in a try-catch block. (PhilRunninger) [#1047](https://github.com/preservim/nerdtree/pull/1047) +- **.1**: Catch errors when trying to read CHANGELOG.md. (PhilRunninger) [#1045](https://github.com/preservim/nerdtree/pull/1045) +- **.0**: If file path doesn't exist, :NERDTreeFind its parent directory instead. (PhilRunninger) [#1043](https://github.com/preservim/nerdtree/pull/1043) +#### 6.0 +- **.1**: Reintroduce necessary variable mistakenly removed. (PhilRunninger) [#1040](https://github.com/preservim/nerdtree/pull/1040) +- **.0**: Make the behavior of window splits consistent (dragonxlwang, PhilRunninger) [#1035](https://github.com/preservim/nerdtree/pull/1035) +#### 5.3 +- **.3**: Fix (p)ath not displaying in the minimal menu (tuzz) [#1038](https://github.com/preservim/nerdtree/pull/1038) +- **.2**: Enable events when closing NerdTree window. (PhilRunninger) [#1037](https://github.com/preservim/nerdtree/pull/1037) +- **.1**: Fix the `e` key mapping to use netrw if desired (PhilRunninger) [#1031](https://github.com/preservim/nerdtree/pull/1031) +- **.0**: Add file extension and size to sorting capabilities (PhilRunninger) [#1029](https://github.com/preservim/nerdtree/pull/1029) +#### 5.2 +- **.9**: Suppress events for intermediate window/tab/buffer changes (PhilRunninger) [#1026](https://github.com/preservim/nerdtree/pull/1026) +- **.8**: Revert [#1019](https://github.com/preservim/nerdtree/pull/1019) to fix nvim artifacts and flickering. (PhilRunninger) [#1021](https://github.com/preservim/nerdtree/pull/1021) +- **.7**: Use :mode only in neovim. MacVim still needs to use :redraw! (PhilRunninger) [#1019](https://github.com/preservim/nerdtree/pull/1019) +- **.6**: In CHANGELOG.md and PR template, make reference to PR a true HTML link. (PhilRunninger) [#1017](https://github.com/preservim/nerdtree/pull/1017) +- **.5**: Use `:mode` instead of `:redraw!` when updating menu. (PhilRunninger) [#1016](https://github.com/preservim/nerdtree/pull/1016) +- **.4**: When searching for root line num, stop at end of file. (PhilRunninger) [#1015](https://github.com/preservim/nerdtree/pull/1015) +- **.3**: Fix `` key map on the bookmark (lkebin) [#1014](https://github.com/preservim/nerdtree/pull/1014) +- **.2**: Make Enter work on the `.. ( up a dir )` line (PhilRunninger) [#1013](https://github.com/preservim/nerdtree/pull/1013) +- **.1**: Fix nerdtree#version() on Windows. (PhilRunninger) +- **.0**: Expand functionality of `` mapping. (PhilRunninger) [#1011](https://github.com/preservim/nerdtree/pull/1011) +#### 5.1 +- **.3**: Remove @mentions from PR template and change log. They weren't working. (PhilRunninger) [#1009](https://github.com/preservim/nerdtree/pull/1009) +- **.2**: Fix NERDTree opening with the wrong size. (PhilRunninger) [#1008](https://github.com/preservim/nerdtree/pull/1008) +- **.1**: Update Changelog and create PR Template (PhilRunninger) [#1007](https://github.com/preservim/nerdtree/pull/1007) +- **.0**: Too many changes for one patch... + - Refresh a dir_node if the file wasn't found in it, and look once more. (PhilRunninger) [#1005](https://github.com/preservim/nerdtree/pull/1005) + - Add a "copy path to clipboard" menu option (PhilRunninger) [#1002](https://github.com/preservim/nerdtree/pull/1002) + - Enable root refresh on "vim ." a different way than [#999](https://github.com/preservim/nerdtree/pull/999). (PhilRunninger) [#1001](https://github.com/preservim/nerdtree/pull/1001) + - Fix refreshroot (PhilRunninger) [#999](https://github.com/preservim/nerdtree/pull/999) + - Change version check to look for 703 not 730 (vhalis) [#994](https://github.com/preservim/nerdtree/pull/994) + - Change minimum vim (PhilRunninger) [#991](https://github.com/preservim/nerdtree/pull/991) + - Allow multi-character DirArrows (PhilRunninger) [#985](https://github.com/preservim/nerdtree/pull/985) + - Remove redraw! while still clearing last message empty string. (PhilRunninger) [#979](https://github.com/preservim/nerdtree/pull/979) + - fix `_initChildren` function value set to numChildrenCached error (terryding77) [#969](https://github.com/preservim/nerdtree/pull/969) + - On Windows, do a case-insensitive comparison of paths. (PhilRunninger) [#967](https://github.com/preservim/nerdtree/pull/967) + - Remove the **Please wait... DONE** messages. (PhilRunninger) [#966](https://github.com/preservim/nerdtree/pull/966) + - Smarter delimiter default (PhilRunninger) [#963](https://github.com/preservim/nerdtree/pull/963) + - Update directory .vimdc readme example (spencerdcarlson) [#961](https://github.com/preservim/nerdtree/pull/961) + - Preview bookmarks (PhilRunninger) [#956](https://github.com/preservim/nerdtree/pull/956) + - Add new value to NERDTreeQuitOnOpen to close bookmark table (PhilRunninger) [#955](https://github.com/preservim/nerdtree/pull/955) + - Add an :EditBookmarks command to edit the bookmarks file (PhilRunninger) [#954](https://github.com/preservim/nerdtree/pull/954) + - Before copying, turn off &shellslash. Restore after copy is finished. (PhilRunninger) [#952](https://github.com/preservim/nerdtree/pull/952) + - Set a maximum window size when zooming. (PhilRunninger) [#950](https://github.com/preservim/nerdtree/pull/950) + - Confirm the wipeout of a unsaved buffer whose file has been renamed. (PhilRunninger) [#949](https://github.com/preservim/nerdtree/pull/949) + - Escape a backslash so it can be used in a key mapping. (PhilRunninger) [#948](https://github.com/preservim/nerdtree/pull/948) + - Add a NERDTreeMinimalMenu feature (tuzz) [#938](https://github.com/preservim/nerdtree/pull/938) + - fixed root path error for windows (zcodes) [#935](https://github.com/preservim/nerdtree/pull/935) + - Restore getDirChildren for use in nerdtree-project-plugin. (PhilRunninger) [#929](https://github.com/preservim/nerdtree/pull/929) + - Document NERDTreeNodeDelimiter [#912](https://github.com/preservim/nerdtree/pull/912) (PhilRunninger) [#926](https://github.com/preservim/nerdtree/pull/926) + - Allow modification of menu keybindings (Leandros) [#923](https://github.com/preservim/nerdtree/pull/923) + - Add two more disqualifications for isCascadable(). (PhilRunninger) [#914](https://github.com/preservim/nerdtree/pull/914) + - Allow highlighting more than one flag. (kristijanhusak) [#908](https://github.com/preservim/nerdtree/pull/908) + - Support sorting files and directories by modification time. (PhilRunninger) [#901](https://github.com/preservim/nerdtree/pull/901) + - Parse . and .. from path string with trailing slash. (PhilRunninger) [#899](https://github.com/preservim/nerdtree/pull/899) + - Force sort to recalculate the cached sortKey. (PhilRunninger) [#898](https://github.com/preservim/nerdtree/pull/898) + - Add NERDTreeRefreshRoot command (wgfm) [#897](https://github.com/preservim/nerdtree/pull/897) + - Call Resolve on the file's path when calling :NERDTreeFind. (PhilRunninger) [#896](https://github.com/preservim/nerdtree/pull/896) + - Catch all errors, not just NERDTree errors. (PhilRunninger) [#894](https://github.com/preservim/nerdtree/pull/894) + - Fix typo in help file (lvoisin) [#892](https://github.com/preservim/nerdtree/pull/892) + - Make NERDTreeCreator set the `'nolist'` option (lifecrisis) [#889](https://github.com/preservim/nerdtree/pull/889) + - Refresh buffers after `m`, `m` operation on a folder (PhilRunninger) [#888](https://github.com/preservim/nerdtree/pull/888) + - Use a better arg for FINDSTR when using the m,l command in Windows. (PhilRunninger) [#887](https://github.com/preservim/nerdtree/pull/887) + - Fix the / motions, which currently fail with cascades (lifecrisis) [#886](https://github.com/preservim/nerdtree/pull/886) + - Function "s:UI.getLineNum()" doesn't always work on cascades. (lifecrisis) [#882](https://github.com/preservim/nerdtree/pull/882) + - NERDTreeCWD: reset CWD if changed by NERDTreeFocus (PhilRunninger) [#878](https://github.com/preservim/nerdtree/pull/878) + - Use tabnext instead of gt to allow users to remap gt. (PhilRunninger) [#877](https://github.com/preservim/nerdtree/pull/877) + - Do a case sensitive comparison of new/existing buffers. (PhilRunninger) [#875](https://github.com/preservim/nerdtree/pull/875) + - Fix opening sub-directories that have commas in their name. (PhilRunninger) [#873](https://github.com/preservim/nerdtree/pull/873) + - Add new command to open NERDTree in the root of a VCS repository. (PhilRunninger) [#872](https://github.com/preservim/nerdtree/pull/872) + - Make sure the path to the bookmarks file exists before writing it. (PhilRunninger) [#871](https://github.com/preservim/nerdtree/pull/871) + - Unzoom NERDTree when opening a file (PhilRunninger) [#870](https://github.com/preservim/nerdtree/pull/870) + - Support unusual characters in file and directory names (PhilRunninger) [#868](https://github.com/preservim/nerdtree/pull/868) + - Reword renamed-buffer prompt to be more clear (aflock) [#867](https://github.com/preservim/nerdtree/pull/867) + - Default to placing cursor on root when closing bookmark table (lifecrisis) [#866](https://github.com/preservim/nerdtree/pull/866) + - Fix issues with sorting of nodes (PhilRunninger) [#856](https://github.com/preservim/nerdtree/pull/856) + - Better OSX detection (bubba-h57) [#853](https://github.com/preservim/nerdtree/pull/853) + - Bugfix - ensure keymaps dictionary exists before using it (mnussbaum) [#852](https://github.com/preservim/nerdtree/pull/852) + - Decrease startup-time by avoiding linear-time iteration over key mappings (mnussbaum) [#851](https://github.com/preservim/nerdtree/pull/851) + - Add code to sort mappings in quickhelp (lifecrisis) [#849](https://github.com/preservim/nerdtree/pull/849) + - Use ":clearjumps" in new NERDTree windows (lifecrisis) [#844](https://github.com/preservim/nerdtree/pull/844) + - Like m-c did before, create parent directories if needed on m-m. (PhilRunninger) [#840](https://github.com/preservim/nerdtree/pull/840) + - BUGFIX: Repair a problem with the `'u'` mapping. (lifecrisis) [#838](https://github.com/preservim/nerdtree/pull/838) + - Make the NERDTree buffer writable when rendering it. (PhilRunninger) [#837](https://github.com/preservim/nerdtree/pull/837) + - Code cleanup: Remove unsupported bookmark table mappings (lifecrisis) [#835](https://github.com/preservim/nerdtree/pull/835) + - Replace strcharpart() with substitute() for backward compatibility (bravestarr) [#834](https://github.com/preservim/nerdtree/pull/834) + - Fixed error `unknown function strcharpart` for older versions of Vim (hav4ik) [#833](https://github.com/preservim/nerdtree/pull/833) + - Clear output when NERDTree menu is aborted (lifecrisis) [#832](https://github.com/preservim/nerdtree/pull/832) + - Display a path with multi-byte characters correctly when it is truncated (bravestarr) [#830](https://github.com/preservim/nerdtree/pull/830) + - Support revealing file and executing file with xdg-open for Linux (ngnmhieu) [#824](https://github.com/preservim/nerdtree/pull/824) + - If node isn't open, count children on disk before deleting. (PhilRunninger) [#822](https://github.com/preservim/nerdtree/pull/822) + - Add new variable g:NERDTreeRemoveFileCmd (kutsan) [#816](https://github.com/preservim/nerdtree/pull/816) + - Use a better check for existence of the NERDTree buffer. (PhilRunninger) [#814](https://github.com/preservim/nerdtree/pull/814) + - Fix focussing previous buffer when closing NERDTree (mrubli) [#801](https://github.com/preservim/nerdtree/pull/801) + - Update the docs for "NERDTreeStatusline" (lifecrisis) [#796](https://github.com/preservim/nerdtree/pull/796) + - BUGFIX: Unstable behavior in the "getPath()" method (lifecrisis) [#795](https://github.com/preservim/nerdtree/pull/795) + - Revert the bugfix from pull request [#785](https://github.com/preservim/nerdtree/pull/785) (lifecrisis) [#794](https://github.com/preservim/nerdtree/pull/794) + - BUGFIX: Allow ":NERDTreeFind" to discover hidden files (lifecrisis) [#786](https://github.com/preservim/nerdtree/pull/786) + - BUGFIX: Allow ":NERDTreeFind" to reveal new files (lifecrisis) [#785](https://github.com/preservim/nerdtree/pull/785) + - Add modelines (lifecrisis) [#782](https://github.com/preservim/nerdtree/pull/782) + - Change the type of completion used by NERDTreeFind (lifecrisis) [#781](https://github.com/preservim/nerdtree/pull/781) + - change NERDTreeFind with args (zhenyangze) [#778](https://github.com/preservim/nerdtree/pull/778) + - Style Choice: Using confirm() when deleting a bookmark (lifecrisis) [#777](https://github.com/preservim/nerdtree/pull/777) + - remove useless substitute when `file =~# "/$"` (skyblueee) [#773](https://github.com/preservim/nerdtree/pull/773) + - remove useless removeLeadingSpaces in _stripMarkup (skyblueee) [#772](https://github.com/preservim/nerdtree/pull/772) + - Make the "o" mapping consistent with "x" (lifecrisis) [#769](https://github.com/preservim/nerdtree/pull/769) + - Fix a problem with the "x" handler (lifecrisis) [#768](https://github.com/preservim/nerdtree/pull/768) + - Clean up the handler for the "x" mapping (lifecrisis) [#767](https://github.com/preservim/nerdtree/pull/767) + - Revert change to tab opening method (lifecrisis) [#766](https://github.com/preservim/nerdtree/pull/766) + - BUGFIX: Add back support for "b:NERDTreeRoot" (lifecrisis) [#765](https://github.com/preservim/nerdtree/pull/765) + - Fix broken "t" and "T" mappings, tabs now open at end (lifecrisis) [#759](https://github.com/preservim/nerdtree/pull/759) + - Update doc with already existing mapping variables (asnr) [#699](https://github.com/preservim/nerdtree/pull/699) + - Fix the broken g:NERDTreeBookmarksSort setting (lifecrisis) [#696](https://github.com/preservim/nerdtree/pull/696) + - Correct NERDTreeIgnore pattern in doc (cntoplolicon) [#648](https://github.com/preservim/nerdtree/pull/648) + - Remove empty segments when splitting path (sooth-sayer) [#574](https://github.com/preservim/nerdtree/pull/574) + - Suppress autocmds less agressively (wincent) [#578](https://github.com/preservim/nerdtree/pull/578) [#691](https://github.com/preservim/nerdtree/pull/691) + - Add an Issues template to ask for more info initially. + - Fix markdown headers in readme (josephfrazier) [#676](https://github.com/preservim/nerdtree/pull/676) + - Don't touch `@o` and `@h` registers when rendering + - Fix bug with files and directories with dollar signs (alegen) [#649](https://github.com/preservim/nerdtree/pull/649) + - Reuse/reopen existing window trees where possible [#244](https://github.com/preservim/nerdtree/pull/244) + - Remove NERDTree.previousBuf() + - Change color of arrow (Leeiio) [#630](https://github.com/preservim/nerdtree/pull/630) + - Improved a tip in README.markdown (ggicci) [#628](https://github.com/preservim/nerdtree/pull/628) + - Shorten delete confimration of empty directory to `y` (mikeperri) [#530](https://github.com/preservim/nerdtree/pull/530) + - Fix API call to open directory tree in window (devm33) [#533](https://github.com/preservim/nerdtree/pull/533) + - Change default arrows on non-Windows platforms (gwilk) [#546](https://github.com/preservim/nerdtree/pull/546) + - Update to README - combine cd and git clone (zwhitchcox) [#584](https://github.com/preservim/nerdtree/pull/584) + - Update to README - Tip: start NERDTree when vim starts (therealplato) [#593](https://github.com/preservim/nerdtree/pull/593) + - Escape filename when moving an open buffer (zacharyvoase) [#595](https://github.com/preservim/nerdtree/pull/595) + - Fixed incorrect :helptags command in README (curran) [#619](https://github.com/preservim/nerdtree/pull/619) + - Fixed incomplete escaping of folder arrows (adityanatraj) [#548](https://github.com/preservim/nerdtree/pull/548) + - Added NERDTreeCascadeSingleChildDir option (juanibiapina) [#558](https://github.com/preservim/nerdtree/pull/558) + - Replace strchars() with backward compatible workaround. + - Add support for copy command in Windows (SkylerLipthay) [#231](https://github.com/preservim/nerdtree/pull/231) + - Fixed typo in README.markdown - :Helptags -> :helptags + - Rename "primary" and "secondary" trees to "tab" and "window" trees. + - Move a bunch of buffer level variables into the NERDTree and UI classes. + - Display cascading dirs on one line to save vertical/horizontal space (matt-gardner: brainstorming/testing) + - Remove the old style UI - Remove `NERDTreeDirArrows` option. + - On windows default to + and ~ for expand/collapse directory symbols. + - Lots more refactoring. Move a bunch of b: level vars into b:NERDTree and friends. + +#### 5.0.0 +- Refactor the code significantly: + * Break the classes out into their own files. + * Make the majority of the code OO - previously large parts were effectively a tangle of "global" methods. +- Add an API to assign flags to nodes. This allows VCS plugins like https://github.com/Xuyuanp/nerdtree-git-plugin to exist. Thanks to **Xuyuanp** for helping design/test/build said API. +- add `scope` argument to the key map API see :help NERDTreeAddKeyMap() +- add magic [[dir]] and [[file]] flags to NERDTreeIgnore +- add support for custom path filters. See :help NERDTreeAddPathFilter() +- add path listener API. See :help NERDTreePathListenerAPI. +- expand the fs menu functionality to list file properties (PhilRunninger, apbarrero, JESii) +- make bookmarks work with `~` home shortcuts (hiberabyss) +- show OSX specific fsmenu options in regular vim on mac (evindor) +- make dir arrow icons configurable (PickRelated) +- optimise node sorting performance when opening large dirs (vtsang) +- make the root note render prettier by truncating it at a path slash (gcmt) +- remove NERDChristmasTree option - its always christmas now +- add "cascade" open and closing for dirs containing only another single dir. See :help NERDTreeCascadeOpenSingleChildDir (pendulm) +- Many other fixes, doc updates and contributions from: **actionshrimp**, **agrussellknives**, **alvan**, **AndrewRadev**, **cperl82** (*many small fixes*), **devmanhinton**, **egalpin**, **franksort**, **gastropoda**, **handcraftedbits**, **kelaban**, **lucascaton**, **mixvin**, **pendulm**, **SchDen**, **shanesmith**, **staeff**, **stephenprater**, **toiffel**, **Twinside**, **WoLpH**, **xiaodili**, **zhangoose** + +#### 4.2.0 +- Add NERDTreeDirArrows option to make the UI use pretty arrow chars instead of the old +~| chars to define the tree structure (sickill) +- shift the syntax highlighting out into its own syntax file (gnap) +- add some mac specific options to the filesystem menu - for macvim only (andersonfreitas) +- Add NERDTreeMinimalUI option to remove some non functional parts of the nerdtree ui (camthompson) +- tweak the behaviour of :NERDTreeFind - see :help :NERDTreeFind for the new behaviour (benjamingeiger) +- if no name is given to :Bookmark, make it default to the name of the target file/dir (minyoung) +- use `file` completion when doing copying, create, and move operations (EvanDotPro) +- lots of misc bug fixes from: **AndrewRadev**, **Bogdanov**, **camthompson**, **kml**, **mathias**, **paddyoloughlin**, **scottstvnsn**, **sdewald**, **Vitaly**, **wycats**, me RAWR! + +#### 4.1.0 +- features: + - NERDTreeFind to reveal the node for the current buffer in the tree, see `|NERDTreeFind|`. This effectively merges the FindInNERDTree plugin (by **Doug McInnes**) into the script. + - make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to **Stefan Ritter** and **Rémi Prévost**. + - truncate the root node if wider than the tree window. Thanks to **Victor Gonzalez**. + +- bugfixes: + - really fix window state restoring + - fix some win32 path escaping issues. Thanks to **Stephan Baumeister**, **Ricky**, **jfilip1024**, and **Chris Chambers**. + +#### 4.0.0 +- add a new programmable menu system (see `:help NERDTreeMenu`). +- add new APIs to add menus/menu-items to the menu system as well as custom key mappings to the NERD tree buffer (see `:help NERDTreeAPI`). +- removed the old API functions +- added a mapping to maximize/restore the size of nerd tree window, thanks to Guillaume Duranceau for the patch. See :help NERDTree-A for details. +- fix a bug where secondary nerd trees (netrw hijacked trees) and NERDTreeQuitOnOpen didnt play nicely, thanks to **Curtis Harvey**. +- fix a bug where the script ignored directories whose name ended in a dot, thanks to **Aggelos Orfanakos** for the patch. +- fix a bug when using the x mapping on the tree root, thanks to **Bryan Venteicher** for the patch. +- fix a bug where the cursor position/window size of the nerd tree buffer wasnt being stored on closing the window, thanks to **Richard Hart**. +- fix a bug where NERDTreeMirror would mirror the wrong tree + +#### 3.1.1 +- fix a bug where a non-listed no-name buffer was getting created every time the tree windows was created, thanks to **Derek Wyatt** and **owen1** +- make `` behave the same as the `o` mapping +- some helptag fixes in the doc, thanks **strull**. +- fix a bug when using `:set nohidden` and opening a file where the previous buf was modified. Thanks **iElectric**. +- other minor fixes + +#### 3.1.0 +- New features: + - add mappings to open files in a vsplit, see `:help NERDTree-s` and `:help NERDTree-gs` + - make the statusline for the nerd tree window default to something hopefully more useful. See `:help 'NERDTreeStatusline'` +- Bugfixes: + - make the hijack netrw functionality work when vim is started with `vim ` (thanks to **Alf Mikula** for the patch). + - fix a bug where the CWD wasnt being changed for some operations even when NERDTreeChDirMode==2 (thanks to **Lucas S. Buchala**) + - add -bar to all the nerd tree :commands so they can chain with other :commands (thanks to **tpope**) + - fix bugs when ignorecase was set (thanks to **nach**) + - fix a bug with the relative path code (thanks to **nach**) + - fix a bug where doing a `:cd` would cause `:NERDTreeToggle` to fail (thanks **nach**) + + +#### 3.0.1 +- Bugfixes: + - fix bugs with :NERDTreeToggle and :NERDTreeMirror when `'hidden'` was not set + - fix a bug where `:NERDTree ` would fail if `` was relative and didnt start with a `./` or `../` Thanks to **James Kanze**. + - make the `q` mapping work with secondary (`:e ` style) trees, thanks to **jamessan** + - fix a bunch of small bugs with secondary trees +- More insane refactoring. + +#### 3.0.0 +- hijack netrw so that doing an `:edit ` will put a NERD tree in the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw' +- allow sharing of trees across tabs, see `:help :NERDTreeMirror` +- remove "top" and "bottom" as valid settings for NERDTreeWinPos +- change the `''` mapping to `'i'` +- change the `'H'` mapping to `'I'` +- lots of refactoring diff --git a/nvim/.vim/plugged/nerdtree/LICENCE b/nvim/.vim/plugged/nerdtree/LICENCE new file mode 100644 index 0000000..081b6cf --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/LICENCE @@ -0,0 +1,13 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + +Copyright (C) 2004 Sam Hocevar + +Everyone is permitted to copy and distribute verbatim or modified +copies of this license document, and changing it is allowed as long +as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/nvim/.vim/plugged/nerdtree/README.markdown b/nvim/.vim/plugged/nerdtree/README.markdown new file mode 100644 index 0000000..80c04ab --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/README.markdown @@ -0,0 +1,261 @@ +# The NERDTree [![Vint](https://github.com/preservim/nerdtree/workflows/Vint/badge.svg)](https://github.com/preservim/nerdtree/actions?workflow=Vint) + +## Introduction + +The NERDTree is a file system explorer for the Vim editor. Using this plugin, users can visually browse complex directory hierarchies, quickly open files for reading or editing, and perform basic file system operations. + +![NERDTree Screenshot](https://github.com/preservim/nerdtree/raw/master/screenshot.png) + +## Installation + +Use your favorite plugin manager to install this plugin. [tpope/vim-pathogen](https://github.com/tpope/vim-pathogen), [VundleVim/Vundle.vim](https://github.com/VundleVim/Vundle.vim), [junegunn/vim-plug](https://github.com/junegunn/vim-plug), and [Shougo/dein.vim](https://github.com/Shougo/dein.vim) are some of the more popular ones. A lengthy discussion of these and other managers can be found on [vi.stackexchange.com](https://vi.stackexchange.com/questions/388/what-is-the-difference-between-the-vim-plugin-managers). Basic instructions are provided below, but please **be sure to read, understand, and follow all the safety rules that come with your ~~power tools~~ plugin manager.** + +If you have no favorite, or want to manage your plugins without 3rd-party dependencies, consider using Vim 8+ packages, as described in Greg Hurrell's excellent Youtube video: [Vim screencast #75: Plugin managers](https://www.youtube.com/watch?v=X2_R3uxDN6g). + +
+Pathogen +Pathogen is more of a runtime path manager than a plugin manager. You must clone the plugins' repositories yourself to a specific location, and Pathogen makes sure they are available in Vim. + + +1. In the terminal, + ```bash + git clone https://github.com/preservim/nerdtree.git ~/.vim/bundle/nerdtree + ``` +1. In your `vimrc`, + ```vim + call pathogen#infect() + syntax on + filetype plugin indent on + ``` +1. Restart Vim, and run `:helptags ~/.vim/bundle/nerdtree/doc/` or `:Helptags`. +
+ +
+ Vundle + +1. Install Vundle, according to its instructions. +1. Add the following text to your `vimrc`. + ```vim + call vundle#begin() + Plugin 'preservim/nerdtree' + call vundle#end() + ``` +1. Restart Vim, and run the `:PluginInstall` statement to install your plugins. +
+ +
+ Vim-Plug + +1. Install Vim-Plug, according to its instructions. +1. Add the following text to your `vimrc`. +```vim +call plug#begin() + Plug 'preservim/nerdtree' +call plug#end() +``` +1. Restart Vim, and run the `:PlugInstall` statement to install your plugins. +
+ +
+ Dein + +1. Install Dein, according to its instructions. +1. Add the following text to your `vimrc`. + ```vim + call dein#begin() + call dein#add('preservim/nerdtree') + call dein#end() + ``` +1. Restart Vim, and run the `:call dein#install()` statement to install your plugins. +
+ +
+Vim 8+ packages + +If you are using Vim version 8 or higher you can use its built-in package management; see `:help packages` for more information. Just run these commands in your terminal: + +```bash +git clone https://github.com/preservim/nerdtree.git ~/.vim/pack/vendor/start/nerdtree +vim -u NONE -c "helptags ~/.vim/pack/vendor/start/nerdtree/doc" -c q +``` +
+ +## Getting Started +After installing NERDTree, the best way to learn it is to turn on the Quick Help. Open NERDTree with the `:NERDTree` command, and press `?` to turn on the Quick Help, which will show you all the mappings and commands available in the NERDTree. Of course, your most complete source of information is the documentation: `:help NERDTree`. + +## NERDTree Plugins +NERDTree can be extended with custom mappings and functions using its built-in API. The details of this API are described in the included documentation. Several plugins have been written, and are available on Github for installation like any other plugin. The plugins in this list are maintained (or not) by their respective owners, and certain combinations may be incompatible. + +* [Xuyuanp/nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin): Shows Git status flags for files and folders in NERDTree. +* [ryanoasis/vim-devicons](https://github.com/ryanoasis/vim-devicons): Adds filetype-specific icons to NERDTree files and folders, +* [tiagofumo/vim-nerdtree-syntax-highlight](https://github.com/tiagofumo/vim-nerdtree-syntax-highlight): Adds syntax highlighting to NERDTree based on filetype. +* [scrooloose/nerdtree-project-plugin](https://github.com/scrooloose/nerdtree-project-plugin): Saves and restores the state of the NERDTree between sessions. +* [PhilRunninger/nerdtree-buffer-ops](https://github.com/PhilRunninger/nerdtree-buffer-ops): 1) Highlights open files in a different color. 2) Closes a buffer directly from NERDTree. +* [PhilRunninger/nerdtree-visual-selection](https://github.com/PhilRunninger/nerdtree-visual-selection): Enables NERDTree to open, delete, move, or copy multiple Visually-selected files at once. + +If any others should be listed, mention them in an issue or pull request. + + +## Frequently Asked Questions + +In the answers to these questions, you will see code blocks that you can put in your `vimrc` file. + +### How can I map a specific key or shortcut to open NERDTree? + +NERDTree doesn't create any shortcuts outside of the NERDTree window, so as not to overwrite any of your other shortcuts. Use the `nnoremap` command in your `vimrc`. You, of course, have many keys and NERDTree commands to choose from. Here are but a few examples. +```vim +nnoremap n :NERDTreeFocus +nnoremap :NERDTree +nnoremap :NERDTreeToggle +nnoremap :NERDTreeFind +``` + +### How do I open NERDTree automatically when Vim starts? +Each code block below is slightly different, as described in the `" Comment lines`. + +```vim +" Start NERDTree and leave the cursor in it. +autocmd VimEnter * NERDTree +``` +--- +```vim +" Start NERDTree and put the cursor back in the other window. +autocmd VimEnter * NERDTree | wincmd p +``` +--- +```vim +" Start NERDTree when Vim is started without file arguments. +autocmd StdinReadPre * let s:std_in=1 +autocmd VimEnter * if argc() == 0 && !exists('s:std_in') | NERDTree | endif +``` +--- +```vim +" Start NERDTree. If a file is specified, move the cursor to its window. +autocmd StdinReadPre * let s:std_in=1 +autocmd VimEnter * NERDTree | if argc() > 0 || exists("s:std_in") | wincmd p | endif +``` +--- +```vim +" Start NERDTree, unless a file or session is specified, eg. vim -S session_file.vim. +autocmd StdinReadPre * let s:std_in=1 +autocmd VimEnter * if argc() == 0 && !exists('s:std_in') && v:this_session == '' | NERDTree | endif +``` +--- +```vim +" Start NERDTree when Vim starts with a directory argument. +autocmd StdinReadPre * let s:std_in=1 +autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists('s:std_in') | + \ execute 'NERDTree' argv()[0] | wincmd p | enew | execute 'cd '.argv()[0] | endif +``` + +### How can I close Vim or a tab automatically when NERDTree is the last window? + +Because of the changes in how Vim handles its `autocmd` and layout locking `quit` command is no longer available in Vim9 auto commands, Depending on which version you're running select one of these solutions. + +__NeoVim users should be able to choose either one of them!__ + +#### Vim9 + +```vim +" Exit Vim if NERDTree is the only window remaining in the only tab. +autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | call feedkeys(":quit\:\") | endif +``` +--- +```vim +" Close the tab if NERDTree is the only window remaining in it. +autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | call feedkeys(":quit\:\") | endif +``` + +#### Vim8 or older + +```vim +" Exit Vim if NERDTree is the only window remaining in the only tab. +autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif +``` +--- +```vim +" Close the tab if NERDTree is the only window remaining in it. +autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif +``` + +### How can I prevent other buffers replacing NERDTree in its window? + +```vim +" If another buffer tries to replace NERDTree, put it in the other window, and bring back NERDTree. +autocmd BufEnter * if winnr() == winnr('h') && bufname('#') =~ 'NERD_tree_\d\+' && bufname('%') !~ 'NERD_tree_\d\+' && winnr('$') > 1 | + \ let buf=bufnr() | buffer# | execute "normal! \w" | execute 'buffer'.buf | endif +``` + +### Can I have the same NERDTree on every tab automatically? + +```vim +" Open the existing NERDTree on each new tab. +autocmd BufWinEnter * if &buftype != 'quickfix' && getcmdwintype() == '' | silent NERDTreeMirror | endif +``` +or change your NERDTree-launching shortcut key like so: +```vim +" Mirror the NERDTree before showing it. This makes it the same on all tabs. +nnoremap :NERDTreeMirror:NERDTreeFocus +``` + +### How can I change the default arrows? + +```vim +let g:NERDTreeDirArrowExpandable = '?' +let g:NERDTreeDirArrowCollapsible = '?' +``` +The preceding values are the non-Windows default arrow symbols. Setting these variables to empty strings will remove the arrows completely and shift the entire tree two character positions to the left. See `:h NERDTreeDirArrowExpandable` for more details. + +### How can I show lines of files? + +```vim +let g:NERDTreeFileLines = 1 +``` + +Lines in the file are displayed as shown below. +``` +OpenFileOrExplorer(argv()[0]) | wincmd p | enew | wincmd p | endif | endif + +" Command to call the OpenFileOrExplorer function. +command! -n=? -complete=file -bar Edit :call OpenFileOrExplorer('') + +" Command-mode abbreviation to replace the :edit Vim command. +cnoreabbrev e Edit +``` diff --git a/nvim/.vim/plugged/nerdtree/_config.yml b/nvim/.vim/plugged/nerdtree/_config.yml new file mode 100644 index 0000000..f0e5310 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/nvim/.vim/plugged/nerdtree/autoload/nerdtree.vim b/nvim/.vim/plugged/nerdtree/autoload/nerdtree.vim new file mode 100644 index 0000000..5d950f0 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/autoload/nerdtree.vim @@ -0,0 +1,315 @@ +if exists('g:loaded_nerdtree_autoload') + finish +endif +let g:loaded_nerdtree_autoload = 1 + +let s:rootNERDTreePath = resolve(expand(':p:h:h')) + +"FUNCTION: nerdtree#version(...) {{{1 +" If any value is given as an argument, the entire line of text from the +" change log is shown for the current version; otherwise, only the version +" number is shown. +function! nerdtree#version(...) abort + let l:text = 'Unknown' + try + let l:changelog = readfile(join([s:rootNERDTreePath, 'CHANGELOG.md'], nerdtree#slash())) + let l:line = 0 + while l:line <= len(l:changelog) + if l:changelog[l:line] =~# '\d\+\.\d\+' + let l:text = substitute(l:changelog[l:line], '.*\(\d\+.\d\+\).*', '\1', '') + let l:text .= substitute(l:changelog[l:line+1], '^.\{-}\(\.\d\+\).\{-}:\(.*\)', a:0>0 ? '\1:\2' : '\1', '') + break + endif + let l:line += 1 + endwhile + catch + endtry + return l:text +endfunction + +" SECTION: General Functions {{{1 +"============================================================ + +" FUNCTION: nerdtree#closeTreeOnOpen() {{{2 +function! nerdtree#closeTreeOnOpen() abort + return g:NERDTreeQuitOnOpen == 1 || g:NERDTreeQuitOnOpen == 3 +endfunction + +" FUNCTION: nerdtree#closeBookmarksOnOpen() {{{2 +function! nerdtree#closeBookmarksOnOpen() abort + return g:NERDTreeQuitOnOpen == 2 || g:NERDTreeQuitOnOpen == 3 +endfunction + +" FUNCTION: nerdtree#slash() {{{2 +" Return the path separator used by the underlying file system. Special +" consideration is taken for the use of the 'shellslash' option on Windows +" systems. +function! nerdtree#slash() abort + if nerdtree#runningWindows() + if exists('+shellslash') && &shellslash + return '/' + endif + + return '\' + endif + + return '/' +endfunction + +"FUNCTION: nerdtree#checkForBrowse(dir) {{{2 +"inits a window tree in the current buffer if appropriate +function! nerdtree#checkForBrowse(dir) abort + if !isdirectory(a:dir) + return + endif + + if s:reuseWin(a:dir) + return + endif + + call g:NERDTreeCreator.CreateWindowTree(a:dir) +endfunction + +"FUNCTION: s:reuseWin(dir) {{{2 +"finds a NERDTree buffer with root of dir, and opens it. +function! s:reuseWin(dir) abort + let path = g:NERDTreePath.New(fnamemodify(a:dir, ':p')) + + for i in range(1, bufnr('$')) + unlet! nt + let nt = getbufvar(i, 'NERDTree') + if empty(nt) + continue + endif + + if nt.isWinTree() && nt.root.path.equals(path) + call nt.setPreviousBuf(bufnr('#')) + exec 'buffer ' . i + return 1 + endif + endfor + + return 0 +endfunction + +" FUNCTION: nerdtree#completeBookmarks(A,L,P) {{{2 +" completion function for the bookmark commands +function! nerdtree#completeBookmarks(A,L,P) abort + return filter(g:NERDTreeBookmark.BookmarkNames(), 'v:val =~# "^' . a:A . '"') +endfunction + +"FUNCTION: nerdtree#compareNodes(n1, n2) {{{2 +function! nerdtree#compareNodes(n1, n2) abort + return nerdtree#compareNodePaths(a:n1.path, a:n2.path) +endfunction + +"FUNCTION: nerdtree#compareNodePaths(p1, p2) {{{2 +function! nerdtree#compareNodePaths(p1, p2) abort + let sortKey1 = a:p1.getSortKey() + let sortKey2 = a:p2.getSortKey() + let i = 0 + while i < min([len(sortKey1), len(sortKey2)]) + " Compare chunks upto common length. + " If chunks have different type, the one which has + " integer type is the lesser. + if type(sortKey1[i]) == type(sortKey2[i]) + if sortKey1[i] <# sortKey2[i] + return - 1 + elseif sortKey1[i] ># sortKey2[i] + return 1 + endif + elseif type(sortKey1[i]) == type(0) + return -1 + elseif type(sortKey2[i]) == type(0) + return 1 + endif + let i += 1 + endwhile + + " Keys are identical upto common length. + " The key which has smaller chunks is the lesser one. + if len(sortKey1) < len(sortKey2) + return -1 + elseif len(sortKey1) > len(sortKey2) + return 1 + else + return 0 + endif +endfunction + +" FUNCTION: nerdtree#deprecated(func, [msg]) {{{2 +" Issue a deprecation warning for a:func. If a second arg is given, use this +" as the deprecation message +function! nerdtree#deprecated(func, ...) abort + let msg = a:0 ? a:func . ' ' . a:1 : a:func . ' is deprecated' + + if !exists('s:deprecationWarnings') + let s:deprecationWarnings = {} + endif + if !has_key(s:deprecationWarnings, a:func) + let s:deprecationWarnings[a:func] = 1 + echomsg msg + endif +endfunction + +" FUNCTION: nerdtree#exec(cmd, ignoreAll) {{{2 +" Same as :exec cmd but, if ignoreAll is TRUE, set eventignore=all for the duration +function! nerdtree#exec(cmd, ignoreAll) abort + let old_ei = &eventignore + if a:ignoreAll + set eventignore=all + endif + try + exec a:cmd + finally + let &eventignore = old_ei + endtry +endfunction + +" FUNCTION: nerdtree#has_opt(options, name) {{{2 +function! nerdtree#has_opt(options, name) abort + return has_key(a:options, a:name) && a:options[a:name] ==# 1 +endfunction + +" FUNCTION: nerdtree#loadClassFiles() {{{2 +function! nerdtree#loadClassFiles() abort + runtime lib/nerdtree/path.vim + runtime lib/nerdtree/menu_controller.vim + runtime lib/nerdtree/menu_item.vim + runtime lib/nerdtree/key_map.vim + runtime lib/nerdtree/bookmark.vim + runtime lib/nerdtree/tree_file_node.vim + runtime lib/nerdtree/tree_dir_node.vim + runtime lib/nerdtree/opener.vim + runtime lib/nerdtree/creator.vim + runtime lib/nerdtree/flag_set.vim + runtime lib/nerdtree/nerdtree.vim + runtime lib/nerdtree/ui.vim + runtime lib/nerdtree/event.vim + runtime lib/nerdtree/notifier.vim +endfunction + +" FUNCTION: nerdtree#postSourceActions() {{{2 +function! nerdtree#postSourceActions() abort + call g:NERDTreeBookmark.CacheBookmarks(1) + call nerdtree#ui_glue#createDefaultBindings() + + "load all nerdtree plugins + runtime! nerdtree_plugin/**/*.vim +endfunction + +"FUNCTION: nerdtree#runningWindows() {{{2 +function! nerdtree#runningWindows() abort + return has('win16') || has('win32') || has('win64') +endfunction + +"FUNCTION: nerdtree#runningCygwin() {{{2 +function! nerdtree#runningCygwin() abort + return has('win32unix') +endfunction + +"FUNCTION: nerdtree#runningMac() {{{2 +function! nerdtree#runningMac() abort + return has('gui_mac') || has('gui_macvim') || has('mac') || has('osx') +endfunction + +" FUNCTION: nerdtree#osDefaultCaseSensitiveFS() {{{2 +function! nerdtree#osDefaultCaseSensitiveFS() abort + return s:osDefaultCaseSensitiveFS +endfunction + +" FUNCTION: nerdtree#caseSensitiveFS() {{{2 +function! nerdtree#caseSensitiveFS() abort + return g:NERDTreeCaseSensitiveFS == 1 || + \((g:NERDTreeCaseSensitiveFS == 2 || g:NERDTreeCaseSensitiveFS == 3) && + \nerdtree#osDefaultCaseSensitiveFS()) +endfunction + +"FUNCTION: nerdtree#pathEquals(lhs, rhs) {{{2 +function! nerdtree#pathEquals(lhs, rhs) abort + if nerdtree#caseSensitiveFS() + return a:lhs ==# a:rhs + else + return a:lhs ==? a:rhs + endif +endfunction + +"FUNCTION: nerdtree#onBufLeave() {{{2 +" used for handling the nerdtree BufLeave/WinLeave events. +function! nerdtree#onBufLeave() abort + " detect whether we are in the middle of sourcing a session. + " if it is a buffer from the sourced session we need to restore it. + if exists('g:SessionLoad') && !exists('b:NERDTree') + let bname = bufname('%') + " is the buffer for a tab tree? + if bname =~# '^' . g:NERDTreeCreator.BufNamePrefix() . 'tab_\d\+$' + " rename loaded buffer and mark it as trash to prevent this event + " getting fired again + exec 'file TRASH_' . bname + " delete the trash buffer + exec 'bwipeout!' + " rescue the tab tree at the current working directory + call g:NERDTreeCreator.CreateTabTree(getcwd()) + " is the buffer for a window tree? + elseif bname =~# '^' . g:NERDTreeCreator.BufNamePrefix(). 'win_\d\+$' + " rescue the window tree at the current working directory + call g:NERDTreeCreator.CreateWindowTree(getcwd()) + else " unknown buffer type + " rename buffer to mark it as broken. + exec 'file BROKEN_' . bname + call nerdtree#echoError('Failed to restore "' . bname . '" from session. Is this session created with an older version of NERDTree?') + endif + else + if g:NERDTree.IsOpen() + call b:NERDTree.ui.saveScreenState() + endif + endif +endfunction + +" SECTION: View Functions {{{1 +"============================================================ + +"FUNCTION: nerdtree#echo {{{2 +"A wrapper for :echo. Appends 'NERDTree:' on the front of all messages +" +"Args: +"msg: the message to echo +function! nerdtree#echo(msg) abort + redraw + echomsg empty(a:msg) ? '' : ('NERDTree: ' . a:msg) +endfunction + +"FUNCTION: nerdtree#echoError {{{2 +"Wrapper for nerdtree#echo, sets the message type to errormsg for this message +"Args: +"msg: the message to echo +function! nerdtree#echoError(msg) abort + echohl errormsg + call nerdtree#echo(a:msg) + echohl normal +endfunction + +"FUNCTION: nerdtree#echoWarning {{{2 +"Wrapper for nerdtree#echo, sets the message type to warningmsg for this message +"Args: +"msg: the message to echo +function! nerdtree#echoWarning(msg) abort + echohl warningmsg + call nerdtree#echo(a:msg) + echohl normal +endfunction + +"FUNCTION: nerdtree#renderView {{{2 +function! nerdtree#renderView() abort + call b:NERDTree.render() +endfunction + +if nerdtree#runningWindows() + let s:osDefaultCaseSensitiveFS = 0 +elseif nerdtree#runningMac() + let s:osDefaultCaseSensitiveFS = 0 +else + let s:osDefaultCaseSensitiveFS = 1 +endif + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/autoload/nerdtree/ui_glue.vim b/nvim/.vim/plugged/nerdtree/autoload/nerdtree/ui_glue.vim new file mode 100644 index 0000000..80be00f --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/autoload/nerdtree/ui_glue.vim @@ -0,0 +1,756 @@ +if exists('g:loaded_nerdtree_ui_glue_autoload') + finish +endif +let g:loaded_nerdtree_ui_glue_autoload = 1 + +" FUNCTION: nerdtree#ui_glue#createDefaultBindings() {{{1 +function! nerdtree#ui_glue#createDefaultBindings() abort + let s = '' . s:SID() . '_' + + call NERDTreeAddKeyMap({ 'key': '', 'scope': 'all', 'callback': s . 'handleMiddleMouse' }) + call NERDTreeAddKeyMap({ 'key': '', 'scope': 'all', 'callback': s.'handleLeftClick' }) + call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'DirNode', 'callback': s.'activateDirNode' }) + call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'FileNode', 'callback': s.'activateFileNode' }) + call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'Bookmark', 'callback': s.'activateBookmark' }) + call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'all', 'callback': s.'activateAll' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'FileNode', 'callback': s.'customOpenFile'}) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'DirNode', 'callback': s.'customOpenDir'}) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'Bookmark', 'callback': s.'customOpenBookmark'}) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'all', 'callback': s.'activateAll' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'DirNode', 'callback': s.'activateDirNode' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'FileNode', 'callback': s.'activateFileNode' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'Bookmark', 'callback': s.'activateBookmark' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': 'Bookmark', 'callback': s.'previewBookmark' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'all', 'callback': s.'activateAll' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': 'FileNode', 'callback': s.'openHSplit' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': 'Bookmark', 'callback': s.'openHSplitBookmark' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': 'FileNode', 'callback': s.'openVSplit' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': 'Bookmark', 'callback': s.'openVSplitBookmark' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': 'FileNode', 'callback': s.'previewNodeCurrent' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': 'FileNode', 'callback': s.'previewNodeHSplit' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': 'Bookmark', 'callback': s.'previewNodeHSplitBookmark' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': 'FileNode', 'callback': s.'previewNodeVSplit' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': 'Bookmark', 'callback': s.'previewNodeVSplitBookmark' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenRecursively, 'scope': 'DirNode', 'callback': s.'openNodeRecursively' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdir, 'scope': 'all', 'callback': s . 'upDirCurrentRootClosed' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdirKeepOpen, 'scope': 'all', 'callback': s . 'upDirCurrentRootOpen' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChangeRoot, 'scope': 'Node', 'callback': s . 'chRoot' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChdir, 'scope': 'Node', 'callback': s.'chCwd' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapQuit, 'scope': 'all', 'callback': s.'closeTreeWindow' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCWD, 'scope': 'all', 'callback': 'nerdtree#ui_glue#chRootCwd' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefreshRoot, 'scope': 'all', 'callback': s.'refreshRoot' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefresh, 'scope': 'Node', 'callback': s.'refreshCurrent' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapHelp, 'scope': 'all', 'callback': s.'displayHelp' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleZoom, 'scope': 'all', 'callback': s.'toggleZoom' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleHidden, 'scope': 'all', 'callback': s.'toggleShowHidden' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFilters, 'scope': 'all', 'callback': s.'toggleIgnoreFilter' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFiles, 'scope': 'all', 'callback': s.'toggleShowFiles' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleBookmarks, 'scope': 'all', 'callback': s.'toggleShowBookmarks' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFileLines, 'scope': 'all', 'callback': s.'toggleShowFileLines' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseDir, 'scope': 'Node', 'callback': s.'closeCurrentDir' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseChildren, 'scope': 'DirNode', 'callback': s.'closeChildren' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapMenu, 'scope': 'Node', 'callback': s.'showMenu' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpParent, 'scope': 'Node', 'callback': s.'jumpToParent' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpFirstChild, 'scope': 'Node', 'callback': s.'jumpToFirstChild' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpLastChild, 'scope': 'Node', 'callback': s.'jumpToLastChild' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpRoot, 'scope': 'all', 'callback': s.'jumpToRoot' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpNextSibling, 'scope': 'Node', 'callback': s.'jumpToNextSibling' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpPrevSibling, 'scope': 'Node', 'callback': s.'jumpToPrevSibling' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpBookmarks, 'scope': 'all', 'callback': s.'jumpToBookmarks' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': 'Node', 'callback': s . 'openInNewTab' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': 'Node', 'callback': s . 'openInNewTabSilent' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': 'Bookmark', 'callback': s . 'openInNewTab' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': 'Bookmark', 'callback': s . 'openInNewTabSilent' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': 'DirNode', 'callback': s.'openExplorer' }) + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': 'FileNode', 'callback': s.'openExplorer' }) + + call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapDeleteBookmark, 'scope': 'Bookmark', 'callback': s.'deleteBookmark' }) +endfunction + + +"SECTION: Interface bindings {{{1 +"============================================================ + +"FUNCTION: s:customOpenFile() {{{1 +" Open file node with the 'custom' key, initially . +function! s:customOpenFile(node) abort + call a:node.activate(s:initCustomOpenArgs().file) +endfunction + +"FUNCTION: s:customOpenDir() {{{1 +" Open directory node with the 'custom' key, initially . +function! s:customOpenDir(node) abort + call s:activateDirNode(a:node, s:initCustomOpenArgs().dir) +endfunction + +"FUNCTION: s:customOpenBookmark() {{{1 +" Open bookmark node with the 'custom' key, initially . +function! s:customOpenBookmark(node) abort + if a:node.path.isDirectory + call a:node.activate(b:NERDTree, s:initCustomOpenArgs().dir) + else + call a:node.activate(b:NERDTree, s:initCustomOpenArgs().file) + endif +endfunction + +"FUNCTION: s:initCustomOpenArgs() {{{1 +function! s:initCustomOpenArgs() abort + let l:defaultOpenArgs = {'file': {'reuse': 'all', 'where': 'p', 'keepopen':!nerdtree#closeTreeOnOpen()}, 'dir': {}} + try + let g:NERDTreeCustomOpenArgs = get(g:, 'NERDTreeCustomOpenArgs', {}) + call extend(g:NERDTreeCustomOpenArgs, l:defaultOpenArgs, 'keep') + catch /^Vim(\a\+):E712:/ + call nerdtree#echoWarning('g:NERDTreeCustomOpenArgs is not set properly. Using default value.') + let g:NERDTreeCustomOpenArgs = l:defaultOpenArgs + finally + return g:NERDTreeCustomOpenArgs + endtry +endfunction + +"FUNCTION: s:activateAll() {{{1 +"handle the user activating the updir line +function! s:activateAll() abort + if getline('.') ==# g:NERDTreeUI.UpDirLine() + return nerdtree#ui_glue#upDir(0) + endif +endfunction + +" FUNCTION: s:activateDirNode(directoryNode, options) {{{1 +" Open a directory with optional options +function! s:activateDirNode(directoryNode, ...) abort + + if a:directoryNode.isRoot() && a:directoryNode.isOpen + call nerdtree#echo('cannot close tree root') + return + endif + + call a:directoryNode.activate((a:0 > 0) ? a:1 : {}) +endfunction + +"FUNCTION: s:activateFileNode() {{{1 +"handle the user activating a tree node +function! s:activateFileNode(node) abort + call a:node.activate({'reuse': 'all', 'where': 'p', 'keepopen': !nerdtree#closeTreeOnOpen()}) +endfunction + +"FUNCTION: s:activateBookmark(bookmark) {{{1 +"handle the user activating a bookmark +function! s:activateBookmark(bm) abort + call a:bm.activate(b:NERDTree, !a:bm.path.isDirectory ? {'where': 'p', 'keepopen': !nerdtree#closeTreeOnOpen()} : {}) +endfunction + +" FUNCTION: nerdtree#ui_glue#bookmarkNode(name) {{{1 +" Associate the current node with the given name +function! nerdtree#ui_glue#bookmarkNode(...) abort + let currentNode = g:NERDTreeFileNode.GetSelected() + if currentNode !=# {} + let name = a:1 + if empty(name) + let name = currentNode.path.getLastPathComponent(0) + endif + try + call currentNode.bookmark(name) + call b:NERDTree.render() + catch /^NERDTree.IllegalBookmarkNameError/ + call nerdtree#echo('bookmark names must not contain spaces') + endtry + else + call nerdtree#echo('select a node first') + endif +endfunction + +" FUNCTION: s:chCwd(node) {{{1 +function! s:chCwd(node) abort + try + call a:node.path.changeToDir() + catch /^NERDTree.PathChangeError/ + call nerdtree#echoWarning('could not change cwd') + endtry +endfunction + +" FUNCTION: s:chRoot(node) {{{1 +" changes the current root to the selected one +function! s:chRoot(node) abort + call b:NERDTree.changeRoot(a:node) +endfunction + +" FUNCTION: s:nerdtree#ui_glue#chRootCwd() {{{1 +" Change the NERDTree root to match the current working directory. +function! nerdtree#ui_glue#chRootCwd() abort + NERDTreeCWD +endfunction + +" FUNCTION: nnerdtree#ui_glue#clearBookmarks(bookmarks) {{{1 +function! nerdtree#ui_glue#clearBookmarks(bookmarks) abort + if a:bookmarks ==# '' + let currentNode = g:NERDTreeFileNode.GetSelected() + if currentNode !=# {} + call currentNode.clearBookmarks() + endif + else + for name in split(a:bookmarks, ' ') + let bookmark = g:NERDTreeBookmark.BookmarkFor(name) + call bookmark.delete() + endfor + endif + call b:NERDTree.root.refresh() + call b:NERDTree.render() +endfunction + +" FUNCTION: s:closeChildren(node) {{{1 +" closes all childnodes of the current node +function! s:closeChildren(node) abort + call a:node.closeChildren() + call b:NERDTree.render() + call a:node.putCursorHere(0, 0) +endfunction + +" FUNCTION: s:closeCurrentDir(node) {{{1 +" Close the parent directory of the current node. +function! s:closeCurrentDir(node) abort + + if a:node.isRoot() + call nerdtree#echo('cannot close parent of tree root') + return + endif + + let l:parent = a:node.parent + + while l:parent.isCascadable() + let l:parent = l:parent.parent + endwhile + + if l:parent.isRoot() + call nerdtree#echo('cannot close tree root') + return + endif + + call l:parent.close() + call b:NERDTree.render() + call l:parent.putCursorHere(0, 0) +endfunction + +" FUNCTION: s:closeTreeWindow() {{{1 +" close the tree window +function! s:closeTreeWindow() abort + if b:NERDTree.isWinTree() && b:NERDTree.previousBuf() !=# -1 + exec 'buffer ' . b:NERDTree.previousBuf() + else + if winnr('$') > 1 + call g:NERDTree.Close() + else + call nerdtree#echo('Cannot close last window') + endif + endif +endfunction + +" FUNCTION: s:deleteBookmark(bookmark) {{{1 +" Prompt the user to confirm the deletion of the selected bookmark. +function! s:deleteBookmark(bookmark) abort + let l:message = 'Delete the bookmark "' . a:bookmark.name + \ . '" from the bookmark list?' + + let l:choices = "&Yes\n&No" + + echo | redraw + let l:selection = confirm(l:message, l:choices, 1, 'Warning') + + if l:selection !=# 1 + call nerdtree#echo('bookmark not deleted') + return + endif + + try + call a:bookmark.delete() + silent call b:NERDTree.root.refresh() + call b:NERDTree.render() + echo | redraw + catch /^NERDTree/ + call nerdtree#echoWarning('could not remove bookmark') + endtry +endfunction + +" FUNCTION: s:displayHelp() {{{1 +" toggles the help display +function! s:displayHelp() abort + call b:NERDTree.ui.toggleHelp() + call b:NERDTree.render() + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:findAndRevealPath(pathStr) {{{1 +function! s:findAndRevealPath(pathStr) abort + let l:pathStr = !empty(a:pathStr) ? a:pathStr : expand('%:p') + let l:revealOpts = {} + + if empty(l:pathStr) + call nerdtree#echoWarning('no file for the current buffer') + return + endif + + if !filereadable(l:pathStr) + let l:pathStr = fnamemodify(l:pathStr, ':h') + let l:revealOpts['open'] = 1 + endif + + try + let l:pathStr = g:NERDTreePath.Resolve(l:pathStr) + let l:pathObj = g:NERDTreePath.New(l:pathStr) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echoWarning('invalid path') + return + endtry + + if !g:NERDTree.ExistsForTab() + try + let l:cwd = g:NERDTreePath.New(getcwd()) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echo('current directory does not exist.') + let l:cwd = l:pathObj.getParent() + endtry + + if l:pathObj.isUnder(l:cwd) + call g:NERDTreeCreator.CreateTabTree(l:cwd.str()) + else + call g:NERDTreeCreator.CreateTabTree(l:pathObj.getParent().str()) + endif + else + NERDTreeFocus + + if !l:pathObj.isUnder(b:NERDTree.root.path) + call s:chRoot(g:NERDTreeDirNode.New(l:pathObj.getParent(), b:NERDTree)) + endif + endif + + if l:pathObj.isHiddenUnder(b:NERDTree.root.path) + call b:NERDTree.ui.setShowHidden(1) + endif + + let l:node = b:NERDTree.root.reveal(l:pathObj, l:revealOpts) + call b:NERDTree.render() + call l:node.putCursorHere(1, 0) +endfunction + +"FUNCTION: s:handleLeftClick() {{{1 +"Checks if the click should open the current node +function! s:handleLeftClick() abort + let currentNode = g:NERDTreeFileNode.GetSelected() + if currentNode !=# {} + + "the dir arrows are multibyte chars, and vim's string functions only + "deal with single bytes - so split the line up with the hack below and + "take the line substring manually + let line = split(getline(line('.')), '\zs') + let startToCur = '' + for i in range(0,len(line)-1) + let startToCur .= line[i] + endfor + + if currentNode.path.isDirectory + if startToCur =~# g:NERDTreeUI.MarkupReg() && startToCur =~# '[+~'.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \?$' + call currentNode.activate() + return + endif + endif + + if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3 + let char = strpart(startToCur, strlen(startToCur)-1, 1) + if char !~# g:NERDTreeUI.MarkupReg() + if currentNode.path.isDirectory + call currentNode.activate() + else + call currentNode.activate({'reuse': 'all', 'where': 'p', 'keepopen':!nerdtree#closeTreeOnOpen()}) + endif + return + endif + endif + endif +endfunction + +" FUNCTION: s:handleMiddleMouse() {{{1 +function! s:handleMiddleMouse() abort + + " A middle mouse click does not automatically position the cursor as one + " would expect. Forcing the execution of a regular left mouse click here + " fixes this problem. + execute "normal! \" + + let l:currentNode = g:NERDTreeFileNode.GetSelected() + if empty(l:currentNode) + call nerdtree#echoError('use the pointer to select a node') + return + endif + + if l:currentNode.path.isDirectory + call l:currentNode.openExplorer() + else + call l:currentNode.open({'where': 'h'}) + endif +endfunction + +" FUNCTION: nerdtree#ui_glue#invokeKeyMap(key) {{{1 +"this is needed since I cant figure out how to invoke dict functions from a +"key map +function! nerdtree#ui_glue#invokeKeyMap(key) abort + call g:NERDTreeKeyMap.Invoke(a:key) +endfunction + +" FUNCTION: s:jumpToFirstChild(node) {{{1 +function! s:jumpToFirstChild(node) abort + call s:jumpToChild(a:node, 0) +endfunction + +" FUNCTION: s:jumpToLastChild(node) {{{1 +function! s:jumpToLastChild(node) abort + call s:jumpToChild(a:node, 1) +endfunction + +" FUNCTION: s:jumpToChild(node, last) {{{1 +" Jump to the first or last child node at the same file system level. +" +" Args: +" node: the node on which the cursor currently sits +" last: 1 (true) if jumping to last child, 0 (false) if jumping to first +function! s:jumpToChild(node, last) abort + let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node + + if l:node.isRoot() + return + endif + + let l:parent = l:node.parent + let l:children = l:parent.getVisibleChildren() + + let l:target = a:last ? l:children[len(l:children) - 1] : l:children[0] + + call l:target.putCursorHere(1, 0) + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:jumpToParent(node) {{{1 +" Move the cursor to the parent of the specified node. For a cascade, move to +" the parent of the cascade's first node. At the root node, do nothing. +function! s:jumpToParent(node) abort + let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node + + if l:node.isRoot() + return + endif + + if empty(l:node.parent) + call nerdtree#echo('could not jump to parent node') + return + endif + + call l:node.parent.putCursorHere(1, 0) + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:jumpToRoot() {{{1 +" moves the cursor to the root node +function! s:jumpToRoot() abort + call b:NERDTree.root.putCursorHere(1, 0) + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:jumpToNextSibling(node) {{{1 +function! s:jumpToNextSibling(node) abort + call s:jumpToSibling(a:node, 1) +endfunction + +" FUNCTION: s:jumpToPrevSibling(node) {{{1 +function! s:jumpToPrevSibling(node) abort + call s:jumpToSibling(a:node, 0) +endfunction + +" FUNCTION: s:jumpToSibling(node, forward) {{{1 +" Move the cursor to the next or previous node at the same file system level. +" +" Args: +" node: the node on which the cursor currently sits +" forward: 0 to jump to previous sibling, 1 to jump to next sibling +function! s:jumpToSibling(node, forward) abort + let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node + let l:sibling = l:node.findSibling(a:forward) + + if empty(l:sibling) + return + endif + + call l:sibling.putCursorHere(1, 0) + call b:NERDTree.ui.centerView() +endfunction + +" FUNCTION: s:jumpToBookmarks() {{{1 +" moves the cursor to the bookmark table +function! s:jumpToBookmarks() abort + try + if b:NERDTree.ui.getShowBookmarks() + call g:NERDTree.CursorToBookmarkTable() + else + call b:NERDTree.ui.setShowBookmarks(1) + endif + catch /^NERDTree/ + call nerdtree#echoError('Failed to jump to the bookmark table') + return + endtry +endfunction + +" FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1 +" Open the Bookmark that has the specified name. This function provides the +" implementation for the :OpenBookmark command. +function! nerdtree#ui_glue#openBookmark(name) abort + try + let l:bookmark = g:NERDTreeBookmark.BookmarkFor(a:name) + catch /^NERDTree.BookmarkNotFoundError/ + call nerdtree#echoError('bookmark "' . a:name . '" not found') + return + endtry + if l:bookmark.path.isDirectory + call l:bookmark.open(b:NERDTree) + return + endif + + call l:bookmark.open(b:NERDTree, s:initCustomOpenArgs().file) +endfunction + +" FUNCTION: s:openHSplit(target) {{{1 +function! s:openHSplit(target) abort + call a:target.activate({'where': 'h', 'keepopen': !nerdtree#closeTreeOnOpen()}) +endfunction + +" FUNCTION: s:openVSplit(target) {{{1 +function! s:openVSplit(target) abort + call a:target.activate({'where': 'v', 'keepopen': !nerdtree#closeTreeOnOpen()}) +endfunction + +"FUNCTION: s:openHSplitBookmark(bookmark) {{{1 +"handle the user activating a bookmark +function! s:openHSplitBookmark(bm) abort + call a:bm.activate(b:NERDTree, !a:bm.path.isDirectory ? {'where': 'h', 'keepopen': !nerdtree#closeTreeOnOpen()} : {}) +endfunction + +"FUNCTION: s:openVSplitBookmark(bookmark) {{{1 +"handle the user activating a bookmark +function! s:openVSplitBookmark(bm) abort + call a:bm.activate(b:NERDTree, !a:bm.path.isDirectory ? {'where': 'v', 'keepopen': !nerdtree#closeTreeOnOpen()} : {}) +endfunction + +" FUNCTION: s:previewHSplitBookmark(bookmark) {{{1 +function! s:previewNodeHSplitBookmark(bookmark) abort + call a:bookmark.activate(b:NERDTree, !a:bookmark.path.isDirectory ? {'stay': 1, 'where': 'h', 'keepopen': 1} : {}) +endfunction + +" FUNCTION: s:previewVSplitBookmark(bookmark) {{{1 +function! s:previewNodeVSplitBookmark(bookmark) abort + call a:bookmark.activate(b:NERDTree, !a:bookmark.path.isDirectory ? {'stay': 1, 'where': 'v', 'keepopen': 1} : {}) +endfunction + +" FUNCTION: s:openExplorer(node) {{{1 +function! s:openExplorer(node) abort + call a:node.openExplorer() +endfunction + +" FUNCTION: s:openInNewTab(target) {{{1 +function! s:openInNewTab(target) abort + let l:opener = g:NERDTreeOpener.New(a:target.path, {'where': 't', 'keepopen': !nerdtree#closeTreeOnOpen()}) + call l:opener.open(a:target) +endfunction + +" FUNCTION: s:openInNewTabSilent(target) {{{1 +function! s:openInNewTabSilent(target) abort + let l:opener = g:NERDTreeOpener.New(a:target.path, {'where': 't', 'keepopen': !nerdtree#closeTreeOnOpen(), 'stay': 1}) + call l:opener.open(a:target) +endfunction + +" FUNCTION: s:openNodeRecursively(node) {{{1 +function! s:openNodeRecursively(node) abort + call nerdtree#echo('Recursively opening node. Please wait...') + call a:node.openRecursively() + call b:NERDTree.render() + call nerdtree#echo('') +endfunction + +" FUNCTION: s:previewBookmark(bookmark) {{{1 +function! s:previewBookmark(bookmark) abort + if a:bookmark.path.isDirectory + execute 'NERDTreeFind '.a:bookmark.path.str() + else + call a:bookmark.activate(b:NERDTree, {'stay': 1, 'where': 'p', 'keepopen': 1}) + endif +endfunction + +"FUNCTION: s:previewNodeCurrent(node) {{{1 +function! s:previewNodeCurrent(node) abort + call a:node.open({'stay': 1, 'where': 'p', 'keepopen': 1}) +endfunction + +"FUNCTION: s:previewNodeHSplit(node) {{{1 +function! s:previewNodeHSplit(node) abort + call a:node.open({'stay': 1, 'where': 'h', 'keepopen': 1}) +endfunction + +"FUNCTION: s:previewNodeVSplit(node) {{{1 +function! s:previewNodeVSplit(node) abort + call a:node.open({'stay': 1, 'where': 'v', 'keepopen': 1}) +endfunction + +" FUNCTION: nerdtree#ui_glue#revealBookmark(name) {{{1 +" put the cursor on the node associate with the given name +function! nerdtree#ui_glue#revealBookmark(name) abort + try + let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0, b:NERDTree) + call targetNode.putCursorHere(0, 1) + catch /^NERDTree.BookmarkNotFoundError/ + call nerdtree#echo('Bookmark isn''t cached under the current root') + endtry +endfunction + +" FUNCTION: s:refreshRoot() {{{1 +" Reloads the current root. All nodes below this will be lost and the root dir +" will be reloaded. +function! s:refreshRoot() abort + if !g:NERDTree.IsOpen() + return + endif + call nerdtree#echo('Refreshing the root node. This could take a while...') + + let l:curWin = winnr() + call nerdtree#exec(g:NERDTree.GetWinNum() . 'wincmd w', 1) + call b:NERDTree.root.refresh() + call b:NERDTree.render() + redraw + call nerdtree#exec(l:curWin . 'wincmd w', 1) + call nerdtree#echo('') +endfunction + +" FUNCTION: s:refreshCurrent(node) {{{1 +" refreshes the root for the current node +function! s:refreshCurrent(node) abort + let node = a:node + if !node.path.isDirectory + let node = node.parent + endif + + call nerdtree#echo('Refreshing node. This could take a while...') + call node.refresh() + call b:NERDTree.render() + call nerdtree#echo('') +endfunction + +" FUNCTION: nerdtree#ui_glue#setupCommands() {{{1 +function! nerdtree#ui_glue#setupCommands() abort + command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreateTabTree('') + command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.ToggleTabTree('') + command! -n=? -complete=dir -bar NERDTreeExplore :call g:NERDTreeCreator.CreateExploreTree('') + command! -n=0 -bar NERDTreeClose :call g:NERDTree.Close() + command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreateTabTree('') + command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror() + command! -n=? -complete=file -bar NERDTreeFind call s:findAndRevealPath('') + command! -n=0 -bar NERDTreeRefreshRoot call s:refreshRoot() + command! -n=0 -bar NERDTreeFocus call NERDTreeFocus() + command! -n=0 -bar NERDTreeCWD call NERDTreeCWD() +endfunction + +" Function: s:SID() {{{1 +function! s:SID() abort + if !exists('s:sid') + let s:sid = matchstr(expand(''), '\zs\d\+\ze_SID$') + endif + return s:sid +endfun + +" FUNCTION: s:showMenu(node) {{{1 +function! s:showMenu(node) abort + let mc = g:NERDTreeMenuController.New(g:NERDTreeMenuItem.AllEnabled()) + call mc.showMenu() +endfunction + +" FUNCTION: s:toggleIgnoreFilter() {{{1 +function! s:toggleIgnoreFilter() abort + call b:NERDTree.ui.toggleIgnoreFilter() +endfunction + +" FUNCTION: s:toggleShowBookmarks() {{{1 +function! s:toggleShowBookmarks() abort + call b:NERDTree.ui.toggleShowBookmarks() +endfunction + +" FUNCTION: s:toggleShowFiles() {{{1 +function! s:toggleShowFiles() abort + call b:NERDTree.ui.toggleShowFiles() +endfunction + +" FUNCTION: s:toggleShowHidden() {{{1 +" toggles the display of hidden files +function! s:toggleShowHidden() abort + call b:NERDTree.ui.toggleShowHidden() +endfunction + +" FUNCTION: s:toggleShowFileLines() {{{1 +" toggles the display of hidden files +function! s:toggleShowFileLines() abort + call b:NERDTree.ui.toggleShowFileLines() +endfunction + +" FUNCTION: s:toggleZoom() {{{1 +function! s:toggleZoom() abort + call b:NERDTree.ui.toggleZoom() +endfunction + +" FUNCTION: nerdtree#ui_glue#upDir(preserveState) {{{1 +" Move the NERDTree up one level. +" +" Args: +" preserveState: if 1, the current root is left open when the new tree is +" rendered; if 0, the current root node is closed +function! nerdtree#ui_glue#upDir(preserveState) abort + + try + call b:NERDTree.root.cacheParent() + catch /^NERDTree.CannotCacheParentError/ + call nerdtree#echo('already at root directory') + return + endtry + + let l:oldRoot = b:NERDTree.root + let l:newRoot = b:NERDTree.root.parent + + call l:newRoot.open() + call l:newRoot.transplantChild(l:oldRoot) + + if !a:preserveState + call l:oldRoot.close() + endif + + call b:NERDTree.changeRoot(l:newRoot) + call l:oldRoot.putCursorHere(0, 0) +endfunction + +" FUNCTION: s:upDirCurrentRootOpen() {{{1 +function! s:upDirCurrentRootOpen() abort + call nerdtree#ui_glue#upDir(1) +endfunction + +" FUNCTION: s:upDirCurrentRootClosed() {{{1 +function! s:upDirCurrentRootClosed() abort + call nerdtree#ui_glue#upDir(0) +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/doc/NERDTree.txt b/nvim/.vim/plugged/nerdtree/doc/NERDTree.txt new file mode 100644 index 0000000..a0c267b --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/doc/NERDTree.txt @@ -0,0 +1,1587 @@ +*NERDTree.txt* A tree explorer plugin to rule the Vim world. Bwahahaha!! + + # #### #### ~ + ### \/#|### |/#### ~ + d8 888 ##\/#/ \||/##/_/##/_# ~ + d88 888 ee ,e e, ### \/###|/ \/ # ### ~ + d88888 888 88b d88 88b ##_\_#\_\## | #/###_/_#### ~ + 888 888 888 888 , ## #### # \ #| / #### ##/## ~ + 888 888 888 "YeeP" __#_--###`. |{,###---###-~ ~ + \ % @% ~ + Y88b Y88 888'Y88 888 88e 888 88e \%@% 88P'888'Y88 ~ + Y88b Y8 888 ,'Y 888 888D 888 888b %o% P' 888 'Y 888,8, ,e e, ,e e, ~ + b Y88b Y 888C8 888 88" 888 8888D %@% 888 888 " d88 88b d88 88b ~ + 8b Y88b 888 ",d 888 b, 888 888P %@% 888 888 888 , 888 , ~ + 88b Y88b 888,d88 888 88b, 888 88" %@% 888 888 "YeeP" "YeeP" ~ + , -=-%{@%-^- _ ~ + ejm `} Reference Manual ~ + { ~ +============================================================================== +CONTENTS *NERDTree-contents* + + 1.Intro...................................|NERDTree| + 2.Functionality provided..................|NERDTreeFunctionality| + 2.1.Global commands...................|NERDTreeGlobalCommands| + 2.2.Bookmarks.........................|NERDTreeBookmarks| + 2.2.1.The bookmark table..........|NERDTreeBookmarkTable| + 2.2.2.Bookmark commands...........|NERDTreeBookmarkCommands| + 2.2.3.Invalid bookmarks...........|NERDTreeInvalidBookmarks| + 2.3.NERDTree mappings.................|NERDTreeMappings| + 2.4.The NERDTree menu.................|NERDTreeMenu| + 3.Settings................................|NERDTreeSettings| + 3.1.Settings summary..................|NERDTreeSettingsSummary| + 3.2.Settings details..................|NERDTreeSettingsDetails| + 4.The NERDTree API........................|NERDTreeAPI| + 4.1.Key map API.......................|NERDTreeKeymapAPI| + 4.2.Menu API..........................|NERDTreeMenuAPI| + 4.3.Menu API..........................|NERDTreeAddPathFilter()| + 4.4.Path Listener API.................|NERDTreePathListenerAPI| + 5.About...................................|NERDTreeAbout| + 6.License.................................|NERDTreeLicense| + +============================================================================== +1. Intro *NERDTree* + +What is this "NERDTree"?? + +The NERDTree allows you to explore your filesystem and to open files and +directories. It presents the filesystem to you in the form of a tree which you +manipulate with the keyboard and/or mouse. It also allows you to perform +simple filesystem operations. + +The following features and functionality are provided by the NERDTree: + * Files and directories are displayed in a hierarchical tree structure + * Different highlighting is provided for the following types of nodes: + * files + * directories + * sym-links + * windows .lnk files + * read-only files + * executable files + * Many (customisable) mappings are provided to manipulate the tree: + * Mappings to open/close/explore directory nodes + * Mappings to open files in new/existing windows/tabs + * Mappings to change the current root of the tree + * Mappings to navigate around the tree + * ... + * Directories and files can be bookmarked. + * Most NERDTree navigation can also be done with the mouse + * Filtering of tree content (can be toggled at runtime) + * custom file filters to prevent e.g. vim backup files being displayed + * optional displaying of hidden files (. files) + * files can be "turned off" so that only directories are displayed + * The position and size of the NERDTree window can be customised + * The order in which the nodes in the tree are listed can be customised. + * A model of your filesystem is created/maintained as you explore it. This + has several advantages: + * All filesystem information is cached and is only re-read on demand + * If you revisit a part of the tree that you left earlier in your + session, the directory nodes will be opened/closed as you left them + * The script remembers the cursor position and window position in the NERD + tree so you can toggle it off (or just close the tree window) and then + reopen it (with NERDTreeToggle) the NERDTree window will appear exactly + as you left it + * You can have a separate NERDTree for each tab, share trees across tabs, + or a mix of both. + * By default the script overrides the default file browser (netrw), so if + you :edit a directory a (slightly modified) NERDTree will appear in the + current window + * A programmable menu system is provided (simulates right clicking on a + node) + * one default menu plugin is provided to perform basic filesystem + operations (create/delete/move/copy files/directories) + * There's an API for adding your own keymappings + + +============================================================================== +2. Functionality provided *NERDTreeFunctionality* + +------------------------------------------------------------------------------ +2.1. Global Commands *NERDTreeGlobalCommands* + +:NERDTree [ | ] *:NERDTree* + Opens a fresh NERDTree. The root of the tree depends on the argument + given. There are 3 cases: If no argument is given, the current directory + will be used. If a directory is given, that will be used. If a bookmark + name is given, the corresponding directory will be used. For example: > + :NERDTree /home/marty/vim7/src + :NERDTree foo (foo is the name of a bookmark) +< +:NERDTreeVCS [ | ] *:NERDTreeVCS* + Like |:NERDTree|, but searches up the directory tree to find the top of + the version control system repository, and roots the NERDTree there. It + works with Git, Subversion, Mercurial, Bazaar, and Darcs repositories. A + couple of examples: > + :NERDTreeVCS /home/marty/nerdtree/doc (opens /home/marty/nerdtree) + :NERDTreeVCS (opens root of repository containing CWD) +< +:NERDTreeFromBookmark *:NERDTreeFromBookmark* + Opens a fresh NERDTree with the root initialized to the directory for + . The only reason to use this command over :NERDTree is for + the completion (which is for bookmarks rather than directories). + +:NERDTreeToggle [ | ] *:NERDTreeToggle* + If a NERDTree already exists for this tab, it is reopened and rendered + again. If or is given, the root of NERDTree + is set to that path. If no NERDTree exists for this tab then this command + acts the same as the |:NERDTree| command. + +:NERDTreeToggleVCS [ | ] *:NERDTreeToggleVCS* + Like |:NERDTreeToggle|, but searches up the directory tree to find the top of + the version control system repository, and roots the NERDTree there. It + works with Git, Subversion, Mercurial, Bazaar, and Darcs repositories. A + couple of examples: > + :NERDTreeToggleVCS /home/marty/nerdtree/doc (opens /home/marty/nerdtree) + :NERDTreeToggleVCS (opens root of repository containing CWD) + +:NERDTreeFocus *:NERDTreeFocus* + Opens (or reopens) the NERDTree if it is not currently visible; + otherwise, the cursor is moved to the already-open NERDTree. + +:NERDTreeMirror *:NERDTreeMirror* + Shares an existing NERDTree, from another tab, in the current tab. + Changes made to one tree are reflected in both as they are actually the + same buffer. + + If only one other NERDTree exists, that tree is automatically mirrored. + If more than one exists, the script will ask which tree to mirror. + +:NERDTreeClose *:NERDTreeClose* + Close the NERDTree in this tab. + +:NERDTreeFind [] *:NERDTreeFind* + Without the optional argument, find and reveal the file for the active + buffer in the NERDTree window. With the argument, find and + reveal the specified path. + + Focus will be shifted to the NERDTree window, and the cursor will be + placed on the tree node for the determined path. If a NERDTree for the + current tab does not exist, a new one will be initialized. + +:NERDTreeCWD *:NERDTreeCWD* + Change the NERDTree root to the current working directory. If no + NERDTree exists for this tab, a new one is opened. + +:NERDTreeRefreshRoot *:NERDTreeRefreshRoot* + Refreshes the NERDTree root node. + +------------------------------------------------------------------------------ +2.2. Bookmarks *NERDTreeBookmarks* + +Bookmarks in the NERDTree are a way to tag files or directories of interest. +For example, you could use bookmarks to tag all of your project directories. + +------------------------------------------------------------------------------ +2.2.1. The Bookmark Table *NERDTreeBookmarkTable* + +If the bookmark table is active (see |NERDTree-B| and +|NERDTreeShowBookmarks|), it will be rendered above the tree. You can double +click bookmarks or use the |NERDTree-o| mapping to activate them. See also, +|NERDTree-t| and |NERDTree-T| + +------------------------------------------------------------------------------ +2.2.2. Bookmark commands *NERDTreeBookmarkCommands* + +Note: The following commands are only available within the NERDTree buffer. + +:Bookmark [] + Bookmark the current node as . If there is already a + bookmark, it is overwritten. must not contain spaces. + If is not provided, it defaults to the file or directory name. + For directories, a trailing slash is present. + +:BookmarkToRoot + Make the directory corresponding to the new root. If a treenode + corresponding to is already cached somewhere in the tree then + the current tree will be used, otherwise a fresh tree will be opened. + Note that if points to a file then its parent will be used + instead. + +:RevealBookmark + If the node is cached under the current root then it will be revealed + (i.e. directory nodes above it will be opened) and the cursor will be + placed on it. + +:OpenBookmark + The Bookmark named is opened as if |NERDTree-o| was applied to + its entry in the Bookmark table. If the Bookmark points to a directory, + it is made the new root of the current NERDTree. If the Bookmark points + to a file, that file is opened for editing in another window. + +:ClearBookmarks [] + Remove all the given bookmarks. If no bookmarks are given then remove all + bookmarks on the current node. + +:ClearAllBookmarks + Remove all bookmarks. + +:EditBookmarks + Opens the bookmarks file for manual editing, e.g. for removing invalid + bookmarks. + +:ReadBookmarks + Re-read the bookmarks in the |NERDTreeBookmarksFile|. + +See also |:NERDTree| and |:NERDTreeFromBookmark|. + +------------------------------------------------------------------------------ +2.2.3. Invalid Bookmarks *NERDTreeInvalidBookmarks* + +If invalid bookmarks are detected, the script will issue an error message and +the invalid bookmarks will become unavailable for use. + +These bookmarks will still be stored in the bookmarks file (see +|NERDTreeBookmarksFile|), down at the bottom. There will always be a blank line +after the valid bookmarks but before the invalid ones. + +Each line in the bookmarks file represents one bookmark. The proper format is: + + +You can use the :EditBookmarks command to open the bookmarks file for editing. +After you have corrected any invalid bookmarks, either restart vim, or run +:ReadBookmarks from the NERDTree window. + +------------------------------------------------------------------------------ +2.3. NERDTree Mappings *NERDTreeMappings* + +Default~ +Key Description help-tag~ + +o........Open files, directories and bookmarks......................|NERDTree-o| +go.......Open selected file, but leave cursor in the NERDTree......|NERDTree-go| + Find selected bookmark directory in current NERDTree +t........Open selected node/bookmark in a new tab...................|NERDTree-t| +T........Same as 't' but keep the focus on the current tab..........|NERDTree-T| +i........Open selected file in a split window.......................|NERDTree-i| +gi.......Same as i, but leave the cursor on the NERDTree...........|NERDTree-gi| +s........Open selected file in a new vsplit.........................|NERDTree-s| +gs.......Same as s, but leave the cursor on the NERDTree...........|NERDTree-gs| +.....User-definable custom open action.......................|NERDTree-| +O........Recursively open the selected directory....................|NERDTree-O| +x........Close the current nodes parent.............................|NERDTree-x| +X........Recursively close all children of the current node.........|NERDTree-X| +e........Edit the current directory.................................|NERDTree-e| + +double-click....same as |NERDTree-o|. +middle-click....same as |NERDTree-i| for files, and |NERDTree-e| for directories. + +D........Delete the current bookmark ...............................|NERDTree-D| + +P........Jump to the root node......................................|NERDTree-P| +p........Jump to current nodes parent...............................|NERDTree-p| +K........Jump up inside directories at the current tree depth.......|NERDTree-K| +J........Jump down inside directories at the current tree depth.....|NERDTree-J| +....Jump down to next sibling of the current directory.......|NERDTree-C-J| +....Jump up to previous sibling of the current directory.....|NERDTree-C-K| + +C........Change the tree root to the selected directory.............|NERDTree-C| +u........Move the tree root up one directory........................|NERDTree-u| +U........Same as 'u' except the old root node is left open..........|NERDTree-U| +r........Recursively refresh the current directory..................|NERDTree-r| +R........Recursively refresh the current root.......................|NERDTree-R| +m........Display the NERDTree menu..................................|NERDTree-m| +cd.......Change the CWD to the directory of the selected node......|NERDTree-cd| +CD.......Change tree root to the CWD...............................|NERDTree-CD| + +I........Toggle whether hidden files displayed......................|NERDTree-I| +f........Toggle whether the file filters are used...................|NERDTree-f| +F........Toggle whether files are displayed.........................|NERDTree-F| +B........Toggle whether the bookmark table is displayed.............|NERDTree-B| +L........Toggle whether the number of lines in files is displayed..|NERDTree-FL| + +q........Close the NERDTree window..................................|NERDTree-q| +A........Zoom (maximize/minimize) the NERDTree window...............|NERDTree-A| +?........Toggle the display of the quick help.......................|NERDTree-?| + +------------------------------------------------------------------------------ + *NERDTree-o* +Default key: o +Map setting: NERDTreeMapActivateNode +Applies to: files and directories. + +If a file node is selected, it is opened in the previous window. + +If a directory is selected it is opened or closed depending on its current +state. + +If a bookmark that links to a directory is selected then that directory +becomes the new root. + +If a bookmark that links to a file is selected then that file is opened in the +previous window. + +------------------------------------------------------------------------------ + *NERDTree-go* +Default key: go +Map setting: NERDTreeMapPreview +Applies to: files. + +If a file node or a bookmark that links to a file is selected, it is opened in +the previous window, but the cursor does not move. + +If a bookmark that links to a directory is selected then that directory +becomes the new root. + +The default key combo for this mapping is "g" + NERDTreeMapActivateNode (see +|NERDTree-o|). + +------------------------------------------------------------------------------ + *NERDTree-t* +Default key: t +Map setting: *NERDTreeMapOpenInTab* +Applies to: files and directories. + +Opens the selected file in a new tab. If a directory is selected, a fresh +NERDTree for that directory is opened in a new tab. + +If a bookmark which points to a directory is selected, open a NERDTree for +that directory in a new tab. If the bookmark points to a file, open that file +in a new tab. + +------------------------------------------------------------------------------ + *NERDTree-T* +Default key: T +Map setting: *NERDTreeMapOpenInTabSilent* +Applies to: files and directories. + +The same as |NERDTree-t| except that the focus is kept in the current tab. + +------------------------------------------------------------------------------ + *NERDTree-i* +Default key: i +Map setting: *NERDTreeMapOpenSplit* +Applies to: files, and bookmarks pointing to files. + +Opens the selected file in a new split window and puts the cursor in the new +window. + +------------------------------------------------------------------------------ + *NERDTree-gi* +Default key: gi +Map setting: *NERDTreeMapPreviewSplit* +Applies to: files, and bookmarks pointing to files. + +The same as |NERDTree-i| except that the cursor is not moved. + +The default key combo for this mapping is "g" + NERDTreeMapOpenSplit (see +|NERDTree-i|). + +------------------------------------------------------------------------------ + *NERDTree-s* +Default key: s +Map setting: *NERDTreeMapOpenVSplit* +Applies to: files, and bookmarks pointing to files. + +Opens the selected file in a new vertically split window and puts the cursor +in the new window. + +------------------------------------------------------------------------------ + *NERDTree-gs* +Default key: gs +Map setting: *NERDTreeMapPreviewVSplit* +Applies to: files, and bookmarks pointing to files. + +The same as |NERDTree-s| except that the cursor is not moved. + +The default key combo for this mapping is "g" + NERDTreeMapOpenVSplit (see +|NERDTree-s|). + +------------------------------------------------------------------------------ + *NERDTree-* +Default key: +Map setting: *NERDTreeMapCustomOpen* +Applies to: files, directories, and bookmarks + +Performs a customized open action on the selected node. This allows the user +to define an action that behaves differently from any of the standard +keys. See |NERDTreeCustomOpenArgs| for more details. +------------------------------------------------------------------------------ + *NERDTree-O* +Default key: O +Map setting: *NERDTreeMapOpenRecursively* +Applies to: directories. + +Recursively opens the selected directory. + +All files and directories are cached, but if a directory would not be +displayed due to file filters (see |NERDTreeIgnore| |NERDTree-f|) or the +hidden file filter (see |NERDTreeShowHidden|) then its contents are not +cached. This is handy, especially if you have .svn directories. + +------------------------------------------------------------------------------ + *NERDTree-x* +Default key: x +Map setting: *NERDTreeMapCloseDir* +Applies to: files and directories. + +Closes the parent of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-X* +Default key: X +Map setting: *NERDTreeMapCloseChildren* +Applies to: directories. + +Recursively closes all children of the selected directory. + +Tip: To quickly "reset" the tree, use |NERDTree-P| with this mapping. + +------------------------------------------------------------------------------ + *NERDTree-e* +Default key: e +Map setting: *NERDTreeMapOpenExpl* +Applies to: files and directories. + +|:edit|s the selected directory, or the selected file's directory. This could +result in a NERDTree or a netrw being opened, depending on +|NERDTreeHijackNetrw|. + +------------------------------------------------------------------------------ + *NERDTree-D* +Default key: D +Map setting: *NERDTreeMapDeleteBookmark* +Applies to: lines in the bookmarks table + +Deletes the currently selected bookmark. + +------------------------------------------------------------------------------ + *NERDTree-P* +Default key: P +Map setting: *NERDTreeMapJumpRoot* +Applies to: no restrictions. + +Jump to the tree root. + +------------------------------------------------------------------------------ + *NERDTree-p* +Default key: p +Map setting: *NERDTreeMapJumpParent* +Applies to: files and directories. + +Jump to the parent node of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-K* +Default key: K +Map setting: *NERDTreeMapJumpFirstChild* +Applies to: files and directories. + +Jump to the first child of the current nodes parent. + +If the cursor is already on the first node then do the following: + * loop back thru the siblings of the current nodes parent until we find an + open directory with children + * go to the first child of that node + +------------------------------------------------------------------------------ + *NERDTree-J* +Default key: J +Map setting: *NERDTreeMapJumpLastChild* +Applies to: files and directories. + +Jump to the last child of the current nodes parent. + +If the cursor is already on the last node then do the following: + * loop forward thru the siblings of the current nodes parent until we find + an open directory with children + * go to the last child of that node + +------------------------------------------------------------------------------ + *NERDTree-C-J* +Default key: +Map setting: *NERDTreeMapJumpNextSibling* +Applies to: files and directories. + +Jump to the next sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C-K* +Default key: +Map setting: *NERDTreeMapJumpPrevSibling* +Applies to: files and directories. + +Jump to the previous sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C* +Default key: C +Map setting: *NERDTreeMapChangeRoot* +Applies to: files and directories. + +Make the selected directory node the new tree root. If a file is selected, its +parent is used. + +------------------------------------------------------------------------------ + *NERDTree-u* +Default key: u +Map setting: *NERDTreeMapUpdir* +Applies to: no restrictions. + +Move the tree root up a directory (like doing a "cd .."). + +------------------------------------------------------------------------------ + *NERDTree-U* +Default key: U +Map setting: *NERDTreeMapUpdirKeepOpen* +Applies to: no restrictions. + +Like |NERDTree-u| except that the old tree root is kept open. + +------------------------------------------------------------------------------ + *NERDTree-r* +Default key: r +Map setting: *NERDTreeMapRefresh* +Applies to: files and directories. + +If a directory is selected, recursively refresh that directory, i.e. scan the +filesystem for changes and represent them in the tree. + +If a file node is selected then the above is done on it's parent. + +------------------------------------------------------------------------------ + *NERDTree-R* +Default key: R +Map setting: *NERDTreeMapRefreshRoot* +Applies to: no restrictions. + +Recursively refresh the tree root. + +------------------------------------------------------------------------------ + *NERDTree-m* +Default key: m +Map setting: *NERDTreeMapMenu* +Applies to: files and directories. + +Display the NERDTree menu. See |NERDTreeMenu| for details. + +------------------------------------------------------------------------------ + *NERDTree-cd* +Default key: cd +Map setting: *NERDTreeMapChdir* +Applies to: files and directories. + +Change Vim's current working directory to that of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-CD* +Default key: CD +Map setting: *NERDTreeMapCWD* +Applies to: no restrictions. + +Change the NERDTree root to Vim's current working directory. + +------------------------------------------------------------------------------ + *NERDTree-I* +Default key: I +Map setting: *NERDTreeMapToggleHidden* +Applies to: no restrictions. + +Toggles whether hidden files (i.e. "dot files") are displayed. + +------------------------------------------------------------------------------ + *NERDTree-f* +Default key: f +Map setting: *NERDTreeMapToggleFilters* +Applies to: no restrictions. + +Toggles whether file filters are used. See |NERDTreeIgnore| for details. + +------------------------------------------------------------------------------ + *NERDTree-F* +Default key: F +Map setting: *NERDTreeMapToggleFiles* +Applies to: no restrictions. + +Toggles whether file nodes are displayed. + +------------------------------------------------------------------------------ + *NERDTree-B* +Default key: B +Map setting: *NERDTreeMapToggleBookmarks* +Applies to: no restrictions. + +Toggles whether the bookmarks table is displayed. + +------------------------------------------------------------------------------ + *NERDTree-FL* +Default key: FL +Map setting: *NERDTreeMapToggleFileLines* +Applies to: no restrictions. + +Toggles whether the number of lines in files is displayed. + +------------------------------------------------------------------------------ + *NERDTree-q* +Default key: q +Map setting: *NERDTreeMapQuit* +Applies to: no restrictions. + +Closes the NERDTree window. + +------------------------------------------------------------------------------ + *NERDTree-A* +Default key: A +Map setting: *NERDTreeMapToggleZoom* +Applies to: no restrictions. + +Maximize (zoom) and minimize the NERDTree window. + +------------------------------------------------------------------------------ + *NERDTree-?* +Default key: ? +Map setting: *NERDTreeMapHelp* +Applies to: no restrictions. + +Toggles whether the quickhelp is displayed. + +------------------------------------------------------------------------------ + 2.3. The NERDTree menu *NERDTreeMenu* + +The NERDTree has a menu that can be programmed via the an API (see +|NERDTreeMenuAPI|). The idea is to simulate the "right click" menus that most +file explorers have. + +The script comes with two default menu plugins: exec_menuitem.vim and +fs_menu.vim. fs_menu.vim adds some basic filesystem operations to the menu for +creating/deleting/moving/copying files and directories. exec_menuitem.vim +provides a menu item to execute executable files. + +Related tags: |NERDTree-m| |NERDTreeApi| + +------------------------------------------------------------------------------ + *NERDTreeMenu-j* +Default key: j +Map option: *NERDTreeMenuDown* +Applies to: The NERDTree menu. + +Moves the cursor down. + +------------------------------------------------------------------------------ + *NERDTreeMenu-k* +Default key: k +Map option: *NERDTreeMenuUp* +Applies to: The NERDTree menu. + +Moves the cursor up. + +============================================================================== +3. Customisation *NERDTreeSettings* + + +------------------------------------------------------------------------------ +3.1. Customisation summary *NERDTreeSettingsSummary* + +The plugin provides the following settings that can customise the behaviour +the NERDTree. These settings should be set in your vimrc, using `:let`. + +|loaded_nerd_tree| Turns off the script. + +|NERDTreeAutoCenter| Controls whether the NERDTree window centers + when the cursor moves within a specified + distance to the top/bottom of the window. + +|NERDTreeAutoCenterThreshold| Controls the sensitivity of autocentering. + +|NERDTreeCaseSensitiveFS| Tells the NERDTree whether or not it is + running in on a case sensitive file system. + +|NERDTreeCaseSensitiveSort| Tells the NERDTree whether to be case + sensitive or not when sorting nodes. + +|NERDTreeNaturalSort| Tells the NERDTree whether to use natural sort + order or not when sorting nodes. + +|NERDTreeSortHiddenFirst| Tells the NERDTree whether to take the dot at + the beginning of the hidden file names into + account when sorting nodes. + +|NERDTreeChDirMode| Tells the NERDTree if/when it should change + vim's current working directory. + +|NERDTreeHighlightCursorline| Tell the NERDTree whether to highlight the + current cursor line. + +|NERDTreeHijackNetrw| Tell the NERDTree whether to replace the netrw + autocommands for exploring local directories. + +|NERDTreeIgnore| Tells the NERDTree which files to ignore. + +|NERDTreeRespectWildIgnore| Tells the NERDTree to respect `'wildignore'`. + +|NERDTreeBookmarksFile| Where the bookmarks are stored. + +|NERDTreeBookmarksSort| Control how the Bookmark table is sorted. + +|NERDTreeMarkBookmarks| Render bookmarked nodes with markers. + +|NERDTreeMouseMode| Manage the interpretation of mouse clicks. + +|NERDTreeQuitOnOpen| Closes the tree window or bookmark table after + opening a file. + +|NERDTreeShowBookmarks| Tells the NERDTree whether to display the + bookmarks table on startup. + +|NERDTreeShowFiles| Tells the NERDTree whether to display files in + the tree on startup. + +|NERDTreeShowHidden| Tells the NERDTree whether to display hidden + files on startup. + +|NERDTreeShowLineNumbers| Tells the NERDTree whether to display line + numbers in the tree window. + +|NERDTreeSortOrder| Tell the NERDTree how to sort the nodes in the + tree. + +|NERDTreeStatusline| Set a statusline for NERDTree windows. + +|NERDTreeWinPos| Tells the script where to put the NERDTree + window. + +|NERDTreeWinSize| Sets the window size when the NERDTree is + opened. + +|NERDTreeWinSizeMax| Sets the maximum window size when the NERDTree + is zoomed. + +|NERDTreeMinimalUI| Disables display of the 'Bookmarks' label and + 'Press ? for help' text. + +|NERDTreeMinimalMenu| Use a compact menu that fits on a single line + for adding, copying, deleting, etc + +|NERDTreeCascadeSingleChildDir| + Collapses on the same line directories that have + only one child directory. + +|NERDTreeCascadeOpenSingleChildDir| + Cascade open while selected directory has only + one child that also is a directory. + +|NERDTreeAutoDeleteBuffer| Tells the NERDTree to automatically remove a + buffer when a file is being deleted or renamed + via a context menu command. + +|NERDTreeCreatePrefix| Specify a prefix to be used when creating the + NERDTree window. + +|NERDTreeRemoveFileCmd| Specify a custom shell command to be used when + deleting files. Note that it should include one + space character at the end of the command and it + applies only to files. + +|NERDTreeRemoveDirCmd| Specify a custom shell command to be used when + deleting directories. Note that it should + include one space character at the end of the + command and it applies only to directories. + +|NERDTreeDirArrowCollapsible| These characters indicate when a directory is +|NERDTreeDirArrowExpandable| either collapsible or expandable. + +|NERDTreeNodeDelimiter| A single character that is used to separate the + file or directory name from the rest of the + characters on the line of text. + +|NERDTreeCustomOpenArgs| A dictionary with values that control how a node + is opened with the |NERDTree-| key. + +------------------------------------------------------------------------------ +3.2. Customisation details *NERDTreeSettingsDetails* + +To enable any of the below settings you should put an appropriate > + let = + + let loaded_nerd_tree=1 +< +------------------------------------------------------------------------------ + *NERDTreeAutoCenter* +Values: 0 or 1. +Default: 1 + +If set to 1, the NERDTree window will center around the cursor if it moves to +within |NERDTreeAutoCenterThreshold| lines of the top/bottom of the window. + +This is ONLY done in response to tree navigation mappings, +i.e. |NERDTree-J| |NERDTree-K| |NERDTree-C-J| |NERDTree-C-K| |NERDTree-p| +|NERDTree-P| + +The centering is done with a |zz| operation. + +------------------------------------------------------------------------------ + *NERDTreeAutoCenterThreshold* +Values: Any natural number. +Default: 3 + +This setting controls the "sensitivity" of the NERDTree auto centering. See +|NERDTreeAutoCenter| for details. + +------------------------------------------------------------------------------ + *NERDTreeCaseSensitiveFS* +Values: 0, 1, 2 or 3. +Default: 2. + +If set to 0, the NERDTree will interact with the file system without case +sensitivity. + +If set to 1, the NERDTree will interact with the file system in a case-sensitive +manner. + +If set to 2, the NERDTree assumes its case sensitivity from the OS it is +running on. It Will default to case-insensitive on Windows and macOS +machines and case-sensitive on everything else. Since it's not a foolproof +way of detection, NERDTree won't proceed with any write actions when +the destination is ambiguous. + +Setting it to 3 will perform just like 2, but without suppressing write +actions. + +------------------------------------------------------------------------------ + *NERDTreeCaseSensitiveSort* +Values: 0 or 1. +Default: 0. + +By default the NERDTree does not sort nodes case sensitively, i.e. nodes +could appear like this: > + bar.c + Baz.c + blarg.c + boner.c + Foo.c +< +But, if you set this setting to 1 then the case of the nodes will be taken +into account. The above nodes would then be sorted like this: > + Baz.c + Foo.c + bar.c + blarg.c + boner.c +< +------------------------------------------------------------------------------ + *NERDTreeNaturalSort* +Values: 0 or 1. +Default: 0. + +By default the NERDTree does not sort nodes in natural sort order, i.e. nodes +could appear like this: > + z1.txt + z10.txt + z100.txt + z11.txt + z110.txt + z2.txt + z20.txt + z3.txt +< +But if you set this setting to 1 then the natural sort order will be used. The +above nodes would then be sorted like this: > + z1.txt + z2.txt + z3.txt + z10.txt + z11.txt + z20.txt + z100.txt + z110.txt +< +------------------------------------------------------------------------------ + *NERDTreeUseTCD* +Values: 0 or 1. +Default: 0. + +By default, NERDTree will use the `:cd` command to change the current working +directory. If this setting is turned on, and the `:tcd` command is available, it +will be used instead. + +------------------------------------------------------------------------------ + *NERDTreeChDirMode* +Values: 0, 1, 2, or 3. +Default: 0. + +Use this setting to tell the script when (if at all) to change the current +working directory (CWD) for vim. + +If it is set to 0 then the CWD is never changed by the NERDTree. + +If set to 1 then the CWD is changed when the NERDTree is first loaded to the +directory it is initialized in. For example, if you start the NERDTree with > + :NERDTree /home/marty/foobar +< +then the CWD will be changed to /home/marty/foobar and will not be changed +again unless you init another NERDTree with a similar command. + +If the setting is set to 2 then it behaves the same as if set to 1 except that +the CWD is changed whenever the tree root is changed. For example, if the CWD +is /home/marty/foobar and you make the node for /home/marty/foobar/baz the new +root then the CWD will become /home/marty/foobar/baz. + +If the set to 3, then it behaves the same as if set to 2, and the CWD is +changed whenever changing tabs to whatever the tree root is on that tab. + +------------------------------------------------------------------------------ + *NERDTreeHighlightCursorline* +Values: 0 or 1. +Default: 1. + +If set to 1, the current cursor line in the NERDTree buffer will be +highlighted. This is done using the `'cursorline'` Vim option. + +------------------------------------------------------------------------------ + *NERDTreeHijackNetrw* +Values: 0 or 1. +Default: 1. + +If set to 1, doing a > + :edit +< +will open up a window level NERDTree instead of a netrw in the target window. + +Window level trees behaves slightly different from a regular trees in the +following respects: + 1. 'o' will open the selected file in the same window as the tree, + replacing it. + 2. you can have one tree per window - instead of per tab. + +------------------------------------------------------------------------------ + *NERDTreeIgnore* +Values: a list of regular expressions. +Default: ['\~$']. + +This setting is used to specify which files the NERDTree should ignore. It +must be a list of regular expressions. When the NERDTree is rendered, any +files/directories that match any of the regex's in NERDTreeIgnore won't be +displayed. + +For example if you put the following line in your vimrc: > + let NERDTreeIgnore=['\.vim$', '\~$'] +< +then all files ending in .vim or ~ will be ignored. + +There are 3 magic flags that can be appended to the end of each regular +expression to specify that the regex should match only filenames, only lowest +level directories, or a full path. These flags are "[[dir]]", "[[file]]", and +"[[path]]". Example: > + let NERDTreeIgnore=['\.d$[[dir]]', '\.o$[[file]]', 'tmp/cache$[[path]]'] +< +This will cause all directories ending in ".d" to be ignored, all files ending +in ".o" to be ignored, and the "cache" subdirectory of any "tmp" directory to +be ignored. All other "cache" directories will be displayed. + +When using the "[[path]]" tag on Windows, make sure you use escaped +backslashes for the separators in the regex, eg. 'Temp\\cache$[[path]]' + +Note: to tell the NERDTree not to ignore any files you must use the following +line: > + let NERDTreeIgnore=[] +< +The file filters can be turned on and off dynamically with the |NERDTree-f| +mapping. + +------------------------------------------------------------------------------ + *NERDTreeRespectWildIgnore* +Values: 0 or 1. +Default: 0. + +If set to 1, the `'wildignore'` setting is respected. + +------------------------------------------------------------------------------ + *NERDTreeBookmarksFile* +Values: a path +Default: $HOME/.NERDTreeBookmarks + +This is where bookmarks are saved. See |NERDTreeBookmarkCommands|. + +------------------------------------------------------------------------------ + *NERDTreeBookmarksSort* +Values: 0, 1, or 2 +Default: 1 + +This setting controls the method by which the list of user bookmarks is +sorted. When sorted, bookmarks will render in alphabetical order by name. + +If set to 0, the bookmarks list is not sorted. +If set to 1, the bookmarks list is sorted in a case-insensitive manner. +If set to 2, the bookmarks list is sorted in a case-sensitive manner. + +------------------------------------------------------------------------------ + *NERDTreeMarkBookmarks* +Values: 0 or 1 +Default: 1 + +If set to 1, Bookmarks will be specially marked whenever the NERDTree is +rendered. Users of the |NERDTreeMinimalUI| setting may prefer to disable +this setting for even less visual clutter. + +------------------------------------------------------------------------------ + *NERDTreeMouseMode* +Values: 1, 2 or 3. +Default: 1. + +If set to 1 then a double click on a node is required to open it. +If set to 2 then a single click will open directory nodes, while a double +click will still be required for file nodes. +If set to 3 then a single click will open any node. + +Note: a double click anywhere on a line that a tree node is on will +activate it, but all single-click activations must be done on name of the node +itself. For example, if you have the following node: > + | | |-application.rb +< +then (to single click activate it) you must click somewhere in +'application.rb'. + +------------------------------------------------------------------------------ + *NERDTreeQuitOnOpen* +Values: 0,1,2 or 3. +Default: 0 + +This setting governs whether the NERDTree window or the bookmarks table closes +after opening a file with the |NERDTree-o|, |NERDTree-i|, |NERDTree-t| and +|NERDTree-T| mappings. + + Value | NERDTree Window Behavior + -------+------------------------------------------------------- + 0 | No change + 1 | Closes after opening a file + 2 | Closes the bookmark table after opening a bookmark + 3(1+2) | Same as both 1 and 2 + +------------------------------------------------------------------------------ + *NERDTreeShowBookmarks* +Values: 0 or 1. +Default: 0. + +If this setting is set to 1 then the bookmarks table will be displayed. + +This setting can be toggled dynamically, per tree, with the |NERDTree-B| +mapping. + +------------------------------------------------------------------------------ + *NERDTreeShowFiles* +Values: 0 or 1. +Default: 1. + +If this setting is set to 1 then files are displayed in the NERDTree. If it +is set to 0 then only directories are displayed. + +This setting can be toggled dynamically, per tree, with the |NERDTree-F| +mapping and is useful for drastically shrinking the tree when you are +navigating to a different part of the tree. + +------------------------------------------------------------------------------ + *NERDTreeShowFilesLines* +Values: 0 or 1. +Default: 0. + +If this setting is set to 1 then the NERDTree shows number of lines for each +file. + +This setting can be toggled dynamically, per tree, with the |NERDTree-FL| +mapping. +Use one of the follow lines for this setting: > + let NERDTreeShowFilesLines=0 + let NERDTreeShowFilesLines=1 +< +------------------------------------------------------------------------------ + *NERDTreeShowHidden* +Values: 0 or 1. +Default: 0. + +This setting tells vim whether to display hidden files by default. This +setting can be dynamically toggled, per tree, with the |NERDTree-I| mapping. +Use one of the follow lines for this setting: > + let NERDTreeShowHidden=0 + let NERDTreeShowHidden=1 +< +------------------------------------------------------------------------------ + *NERDTreeShowLineNumbers* +Values: 0 or 1. +Default: 0. + +This setting tells vim whether to display line numbers for the NERDTree +window. Use one of the follow lines for this setting: > + let NERDTreeShowLineNumbers=0 + let NERDTreeShowLineNumbers=1 +< +------------------------------------------------------------------------------ + *NERDTreeSortOrder* +Values: a list of regular expressions. +Default: ['\/$', '*', '\.swp$', '\.bak$', '\~$'] + +This setting is a list of regular expressions which are used to group or sort +the nodes under their parent. + +For example, if the setting is: > + ['\.vim$', '\.c$', '\.h$', '*', 'foobar'] +< +then all .vim files will be grouped at the top, followed by all .c files then +all .h files. All files containing the string 'foobar' will be placed at the +end. The star is a special flag: it tells the script that every node that +doesn't match any of the other regexps should be placed here. + +If no star is present in NERDTreeSortOrder, then one is automatically +appended to the end of the list. + +The regex '\/$' should be used to match directory nodes. + +Files can also be sorted by 1) the modification timestamp, 2) the size, or 3) +the extension. Directories are always sorted by name. To accomplish this, the +following special flags are used: + [[timestamp]] [[-timestamp]] [[size]] [[-size]] [[extension]] +The hyphen specifies a descending sort; extensions are sorted in ascending +order only. If placed at the beginning of the list, files are sorted according +to these flags first, and then grouped by the remaining items in the list. If +the flags are in any other position of the list, this special sorting is done +secondarily. See examples 4, 5, and 6 below. + +After this sorting is done, the files in each group are sorted alphabetically. + +Examples: > + (1) ['*', '\/$'] + (2) [] + (3) ['\/$', '\.rb$', '\.php$', '*', '\.swp$', '\.bak$', '\~$'] + (4) ['[[-size]]'] + (5) ['\/$', '*', '[[timestamp]]'] + (6) ['foo','\/$','[[extension]]'] +< +1. Directories will appear last, everything else will appear above. +2. Everything will simply appear in alphabetical order. +3. Directories will appear first, then ruby and php. Swap files, bak files + and vim backup files will appear last with everything else preceding them. +4. Everything is sorted by size, largest to smallest, with directories + considered to have size 0 bytes. +5. Directories will appear first alphabetically, followed by files, sorted by + timestamp, oldest first. +6. Files and directories matching 'foo' first, followed by other directories, + then all other files. Each section of files is sorted by file extension. + +------------------------------------------------------------------------------ + *NERDTreeStatusline* +Values: Any valid `'statusline'` setting. +Default: %{exists('b:NERDTree')?b:NERDTree.root.path.str():''} + +Defines the value for the `'statusline'` setting in NERDTree windows. + +Note: The setting is actually applied using |:let-&|, not |:set|, so +escaping spaces is not necessary. + +Setting this to -1 will deactivate it so that your global `'statusline'` +setting is used. + +------------------------------------------------------------------------------ + *NERDTreeWinPos* +Values: "left", "right", "top" or "bottom" +Default: "left". + +This setting is used to determine where NERDTree window is placed on the +screen. + +This setting makes it possible to use two different explorer plugins +simultaneously. For example, you could have the taglist plugin on the left of +the window and the NERDTree on the right. + +When setting this variable to "top" or "bottom" make sure to also change the +|NERDTreeWinSize| to a more reasonable size. + +For example: +> + let g:NERDTreeWinSize = 15 +< +------------------------------------------------------------------------------ + *NERDTreeWinSize* +Values: a positive integer. +Default: 31. + +This setting is used to change the size of the NERDTree when it is loaded. + +------------------------------------------------------------------------------ + *NERDTreeMinimalUI* +Values: 0 or 1 +Default: 0 + +This setting disables the 'Bookmarks' label 'Press ? for help' text. Use one +of the following lines for this setting: > + let NERDTreeMinimalUI=0 + let NERDTreeMinimalUI=1 +< +------------------------------------------------------------------------------ + *NERDTreeMinimalMenu* +Values: 0 or 1 +Default: 0 + +This setting makes NERDTree use a smaller, more compact menu for adding, +copying, deleting nodes. This menu fits on a single line so Vim doesn't need to +scroll down to present it. This setting is recommended for users already +familiar with the menu items. It will look similar to this: + + Menu: [ (a)dd ,m,d,r,o,q,c,l] (Use j/k/enter or shortcut): + +An action can be selected with its shortcut key or with the NERDTreeMenuUp and +NERDTreeMenuDown keys, then pressing enter. + +Use one of the following lines for this setting: > + let NERDTreeMinimalMenu=0 + let NERDTreeMinimalMenu=1 +< +------------------------------------------------------------------------------ + *NERDTreeCascadeSingleChildDir* +Values: 0 or 1 +Default: 1. + +When displaying directory nodes, this setting tells NERDTree to collapse +directories that have only one child. Use one of the following lines for this +setting: > + let NERDTreeCascadeSingleChildDir=0 + let NERDTreeCascadeSingleChildDir=1 +< +------------------------------------------------------------------------------ + *NERDTreeCascadeOpenSingleChildDir* +Values: 0 or 1 +Default: 1. + +When opening directory nodes, this setting tells NERDTree to recursively open +directories that have only one child which is also a directory. NERDTree will +stop when it finds a directory that contains anything but another single +directory. This setting also causes the |NERDTree-x| mapping to close +directories in the same manner. This setting may be useful for Java projects. +Use one of the following lines for this setting: > + let NERDTreeCascadeOpenSingleChildDir=0 + let NERDTreeCascadeOpenSingleChildDir=1 +< +------------------------------------------------------------------------------ + *NERDTreeAutoDeleteBuffer* +Values: 0 or 1 +Default: 0. + +When using a context menu to delete or rename a file you may also want to +delete the buffer which is no more valid. If the setting is not set you will +see a confirmation if you really want to delete an old buffer. If you always +press 'y' then it's worth it to set this setting to 1. Use one of the +following lines for this setting: > + let NERDTreeAutoDeleteBuffer=0 + let NERDTreeAutoDeleteBuffer=1 +< +------------------------------------------------------------------------------ + *NERDTreeCreatePrefix* +Values: Any valid command prefix. +Default: "silent". + +Internally, NERDTree uses the |:edit| command to create a buffer in which to +display its tree view. You can augment this behavior by specifying a prefix +string such as "keepalt" or similar. For example, to have NERDTree create its +tree window using `silent keepalt keepjumps edit`: > + let NERDTreeCreatePrefix='silent keepalt keepjumps' +< +------------------------------------------------------------------------------ + *NERDTreeDirArrowCollapsible* *NERDTreeDirArrowExpandable* +Values: Any single character. +Defaults: Windows: ~ and + Others: ▾ and ▸ + +These characters indicate whether a directory is collapsible or expandable. +Example: > + let NERDTreeDirArrowExpandable=">" + let NERDTreeDirArrowCollapsible="v" +< +They can be set to "\u00a0" to replace the arrows with a non-breaking space. +If you do this you may need to change the node delimiter. See +|NERDTreeNodeDelimiter|. You cannot use the same character for both the arrows +and the delimiter. + +Alternatively, they can be set to '' (an empty string). This removes the +arrows and the single space that follows them, shifting the entire tree two +character positions to the left. + +------------------------------------------------------------------------------ + *NERDTreeNodeDelimiter* +Values: Any single character. +Default: varies (see below) + +This character is used to separate the file or directory name from the rest of +the characters in the line of text. It allows filenames to contain special +characters that are otherwise used in the NERDTree, such as square brackets, +braces, trailing asterisk, and leading space. For more details, see the +responsible pull request: https://github.com/preservim/nerdtree/pull/868. + +The default value of this variable depends on the features compiled into your +vim and the values of |NERDTreeDirArrowCollapsible| and +|NERDTreeDirArrowExpandable|. + * If your vim is compiled with the +conceal feature, it is the "\x07" + (BEL) character, and it is hidden by setting 'conceallevel' to 2. If you + use autocommands, make sure none of them change that setting in the + NERD_Tree_* buffers. + * If your vim does NOT have the +conceal feature and you're using "\u00a0" + (non-breaking space) to hide the directory arrows, "\u00b7" (middle dot) + is used as the default delimiter. + * If neither condition above applies, NERDTree uses "\u00a0" (non-breaking + space) as the default delimiter. + +In the 2nd and 3rd cases, NERDTree will use the Ignore highlight group to +"hide" the delimiter. It should appear as an empty space. + +Other plugins can interfere with these defaults, so if you need to change the +delimiter, be sure to choose a character that won't appear in your filenames +or any of the flags set by your installed NERDTree plugins. The suggestions +below are but a few of the many possibilities. Remember to use double quotes +when specifying by hex or Unicode. > + let NERDTreeNodeDelimiter="\x07" "bell + let NERDTreeNodeDelimiter="\u00b7" "middle dot + let NERDTreeNodeDelimiter="\u00a0" "non-breaking space + let NERDTreeNodeDelimiter="😀" "smiley face +< +------------------------------------------------------------------------------ + *NERDTreeCustomOpenArgs* +Values: A nested dictionary, as described below +Default: {'file': {'reuse': 'all', 'where': 'p'}, 'dir': {}} + +This dictionary contains two keys, 'file' and 'dir', whose values each are +another dictionary. The inner dictionary is a set of parameters used by +|NERDTree-| to open a file or directory. Setting these parameters allows you +to customize the way the node is opened. The default value matches what +|NERDTree-o| does. To change that behavior, use these keys and +values in the inner dictionaries: + +'where': specifies whether the node should be opened in a new split ("h" or + "v"), in a new tab ("t") or, in the last window ("p"). +'reuse': if file is already shown in a window, jump there; takes values + "all", "currenttab", or empty +'keepopen': boolean (0 or 1); if true, the tree window will not be closed +'stay': boolean (0 or 1); if true, remain in tree window after opening + +For example: +To open files and directories (creating a new NERDTree) in a new tab, > + {'file':{'where': 't'}, 'dir':{'where':'t'}} +< +To open a file always in the current tab, and expand directories in place, > + {'file': {'reuse':'currenttab', 'where':'p', 'keepopen':1, 'stay':1}} +< +============================================================================== +4. The NERDTree API *NERDTreeAPI* + +The NERDTree script allows you to add custom key mappings and menu items via +a set of API calls. Any scripts that use this API should be placed in +~/.vim/nerdtree_plugin/ (*nix) or ~/vimfiles/nerdtree_plugin (windows). + +The script exposes some prototype objects that can be used to manipulate the +tree and/or get information from it: > + g:NERDTreePath + g:NERDTreeDirNode + g:NERDTreeFileNode + g:NERDTreeBookmark +< +See the code/comments in NERD_tree.vim to find how to use these objects. The +following code conventions are used: + * class members start with a capital letter + * instance members start with a lower case letter + * private members start with an underscore + +See this blog post for more details: + http://got-ravings.blogspot.com/2008/09/vim-pr0n-prototype-based-objects.html + +A number of API functions take a callback argument to call. The callback can +be either a string with the name of a function to call, or a |Funcref| object +which will be called directly. + +------------------------------------------------------------------------------ +4.1. Key map API *NERDTreeKeymapAPI* + +NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()* + Adds a new keymapping for all NERDTree buffers. + {options} must be a dictionary, and must contain the following keys: + "key" - the trigger key for the new mapping + "callback" - the function the new mapping will be bound to + "quickhelpText" - the text that will appear in the quickhelp (see + |NERDTree-?|) + "override" - if 1 then this new mapping will override whatever previous + mapping was defined for the key/scope combo. Useful for overriding the + default mappings. + + Additionally, a "scope" argument may be supplied. This constrains the + mapping so that it is only activated if the cursor is on a certain object. + That object is then passed into the handling method. Possible values are: + + "FileNode" .... a file node + "DirNode" ..... a directory node + "Node" ........ a file node OR a directory node + "Bookmark" .... a bookmark + "all" ......... global scope; handler receives no arguments (default) + + Example: > + call NERDTreeAddKeyMap({ + \ 'key': 'foo', + \ 'callback': 'NERDTreeEchoPathHandler', + \ 'quickhelpText': 'echo full path of current node', + \ 'scope': 'DirNode' }) + + function! NERDTreeEchoPathHandler(dirnode) + echo a:dirnode.path.str() + endfunction +< + This code should sit in a file like ~/.vim/nerdtree_plugin/mymapping.vim. + It adds a (redundant) mapping on 'foo' which changes vim's CWD to that of + the current directory node. Note this mapping will only fire when the + cursor is on a directory node. + +------------------------------------------------------------------------------ +4.2. Menu API *NERDTreeMenuAPI* + +NERDTreeAddSubmenu({options}) *NERDTreeAddSubmenu()* + Creates and returns a new submenu. + + {options} must be a dictionary and must contain the following keys: + "text" - the text of the submenu that the user will see + "shortcut" - a shortcut key for the submenu (need not be unique) + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this submenu item will be displayed or not. The callback function must + return 0 or 1. + "parent" - the parent submenu of the new submenu (returned from a previous + invocation of NERDTreeAddSubmenu()). If this key is left out then the new + submenu will sit under the top level menu. + + See below for an example. + +NERDTreeAddMenuItem({options}) *NERDTreeAddMenuItem()* + Adds a new menu item to the NERDTree menu (see |NERDTreeMenu|). + + {options} must be a dictionary and must contain the + following keys: + "text" - the text of the menu item which the user will see + "shortcut" - a shortcut key for the menu item (need not be unique) + "callback" - the function that will be called when the user activates the + menu item. + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this menu item will be displayed or not. The callback function must return + 0 or 1. + "parent" - if the menu item belongs under a submenu then this key must be + specified. This value for this key will be the object that + was returned when the submenu was created with |NERDTreeAddSubmenu()|. + + See below for an example. + +NERDTreeAddMenuSeparator([{options}]) *NERDTreeAddMenuSeparator()* + Adds a menu separator (a row of dashes). + + {options} is an optional dictionary that may contain the following keys: + "isActiveCallback" - see description in |NERDTreeAddMenuItem()|. + +Below is an example of the menu API in action. > + call NERDTreeAddMenuSeparator() + + call NERDTreeAddMenuItem({ + \ 'text': 'a (t)op level menu item', + \ 'shortcut': 't', + \ 'callback': 'SomeFunction' }) + + let submenu = NERDTreeAddSubmenu({ + \ 'text': 'a (s)ub menu', + \ 'shortcut': 's' }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 1', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 2', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) +< +This will create the following menu: > + -------------------- + a (t)op level menu item + a (s)ub menu +< +Where selecting "a (s)ub menu" will lead to a second menu: > + (n)ested item 1 + (n)ested item 2 +< +When any of the 3 concrete menu items are selected the function "SomeFunction" +will be called. + +------------------------------------------------------------------------------ +4.3 NERDTreeAddPathFilter(callback) *NERDTreeAddPathFilter()* + +Path filters are essentially a more powerful version of |NERDTreeIgnore|. +If the simple regex matching in |NERDTreeIgnore| is not enough then use +|NERDTreeAddPathFilter()| to add a callback function that paths will be +checked against when the decision to ignore them is made. Example > + + call NERDTreeAddPathFilter('MyFilter') + + function! MyFilter(params) + "params is a dict containing keys: 'nerdtree' and 'path' which are + "g:NERDTree and g:NERDTreePath objects + + "return 1 to ignore params['path'] or 0 otherwise + endfunction +< +------------------------------------------------------------------------------ +4.4 Path Listener API *NERDTreePathListenerAPI* + +Use this API if you want to run a callback for events on Path objects. E.G > + + call g:NERDTreePathNotifier.AddListener("init", "MyListener") + + ".... + + function! MyListener(event) + "This function will be called whenever a Path object is created. + + "a:event is an object that contains a bunch of relevant info - + "including the affected path. See lib/nerdtree/event.vim for details. + endfunction +< +Current events supported: + init ~ + refresh ~ + refreshFlags ~ + +------------------------------------------------------------------------------ +NERDTreeRender() *NERDTreeRender()* + Re-renders the NERDTree buffer. Useful if you change the state of the + tree and you want to it to be reflected in the UI. + +============================================================================== +5. About *NERDTreeAbout* + +The author of the NERDTree is a terrible terrible monster called Martyzilla +who gobbles up small children with milk and sugar for breakfast. + +He can be reached at martin.grenfell at gmail dot com. He would love to hear +from you, so feel free to send him suggestions and/or comments about this +plugin. Don't be shy --- the worst he can do is slaughter you and stuff you +in the fridge for later ;) + +Martyzilla recruited two other unwitting accomplices to become his minions in +his quest to conquer the Vim plugin world. While he may still love to receive +your emails, the best way to send suggestions, bug reports, and questions is +to submit an issue at http://github.com/preservim/nerdtree/issues. + +The latest stable and development versions are on Github. + Stable: http://github.com/preservim/nerdtree (master branch) + Development: http://github.com/preservim/nerdtree/branches + +Title Credit: + * http://ascii.co.uk/art/tree + + * Patrick Gillespie's Text ASCII Art Generator + http://patorjk.com/software/taag + http://patorjk.com/software/taag/#p=display&f=Rozzo&t=the%20NERD%20Tree + +============================================================================== +6. License *NERDTreeLicense* + +The NERDTree is released under the wtfpl. +See http://sam.zoy.org/wtfpl/COPYING. + +------------------------------------------------------------------------------ + vim:tw=78:ts=8:ft=help:noet:nospell diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/bookmark.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/bookmark.vim new file mode 100644 index 0000000..8dedb5e --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/bookmark.vim @@ -0,0 +1,365 @@ +" ============================================================================ +" CLASS: Bookmark +" +" The Bookmark class serves two purposes: +" (1) It is the top-level prototype for new, concrete Bookmark objects. +" (2) It provides an interface for client code to query and manipulate the +" global list of Bookmark objects within the current Vim session. +" ============================================================================ + + +let s:Bookmark = {} +let g:NERDTreeBookmark = s:Bookmark + +" FUNCTION: Bookmark.activate(nerdtree) {{{1 +function! s:Bookmark.activate(nerdtree, ...) + call self.open(a:nerdtree, a:0 ? a:1 : {}) +endfunction + +" FUNCTION: Bookmark.AddBookmark(name, path) {{{1 +" Class method to add a new bookmark to the list, if a previous bookmark exists +" with the same name, just update the path for that bookmark +function! s:Bookmark.AddBookmark(name, path) + for i in s:Bookmark.Bookmarks() + if i.name ==# a:name + let i.path = a:path + return + endif + endfor + call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path)) +endfunction + +" FUNCTION: Bookmark.Bookmarks() {{{1 +" Class method to get all bookmarks. Lazily initializes the bookmarks global +" variable +function! s:Bookmark.Bookmarks() + if !exists('g:NERDTreeBookmarks') + let g:NERDTreeBookmarks = [] + endif + return g:NERDTreeBookmarks +endfunction + +" FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1 +" class method that returns 1 if a bookmark with the given name is found, 0 +" otherwise +function! s:Bookmark.BookmarkExistsFor(name) + try + call s:Bookmark.BookmarkFor(a:name) + return 1 + catch /^NERDTree.BookmarkNotFoundError/ + return 0 + endtry +endfunction + +" FUNCTION: Bookmark.BookmarkFor(name) {{{1 +" Class method that returns the Bookmark object having the specified name. +" Throws NERDTree.BookmarkNotFoundError if no Bookmark is found. +function! s:Bookmark.BookmarkFor(name) + let l:result = {} + for l:bookmark in s:Bookmark.Bookmarks() + if l:bookmark.name ==# a:name + let l:result = l:bookmark + break + endif + endfor + if empty(l:result) + throw 'NERDTree.BookmarkNotFoundError: "' . a:name . '" not found' + endif + return l:result +endfunction + +" FUNCTION: Bookmark.BookmarkNames() {{{1 +" Class method to return an array of all bookmark names +function! s:Bookmark.BookmarkNames() + let names = [] + for i in s:Bookmark.Bookmarks() + call add(names, i.name) + endfor + return names +endfunction + +" FUNCTION: Bookmark.CacheBookmarks(silent) {{{1 +" Class method to read all bookmarks from the bookmarks file initialize +" bookmark objects for each one. +" +" Args: +" silent - dont echo an error msg if invalid bookmarks are found +function! s:Bookmark.CacheBookmarks(silent) + if filereadable(g:NERDTreeBookmarksFile) + let g:NERDTreeBookmarks = [] + let g:NERDTreeInvalidBookmarks = [] + let bookmarkStrings = readfile(g:NERDTreeBookmarksFile) + let invalidBookmarksFound = 0 + for i in bookmarkStrings + + "ignore blank lines + if i !=# '' + + let name = substitute(i, '^\(.\{-}\) .*$', '\1', '') + let path = substitute(i, '^.\{-} \(.*\)$', '\1', '') + let path = fnamemodify(path, ':p') + + try + let bookmark = s:Bookmark.New(name, g:NERDTreePath.New(path)) + call add(g:NERDTreeBookmarks, bookmark) + catch /^NERDTree.InvalidArgumentsError/ + call add(g:NERDTreeInvalidBookmarks, i) + let invalidBookmarksFound += 1 + endtry + endif + endfor + if invalidBookmarksFound + call s:Bookmark.Write() + if !a:silent + call nerdtree#echo(invalidBookmarksFound . ' invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.') + endif + endif + endif +endfunction + +" FUNCTION: Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark) {{{1 +" Class method that indicates the relative position of two bookmarks when +" placed in alphabetical order by name. Case-sensitivity is determined by an +" option. Supports the s:Bookmark.SortBookmarksList() method. +function! s:Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark) + let l:result = 0 + if g:NERDTreeBookmarksSort ==# 1 + if a:firstBookmark.name ? a:secondBookmark.name + let l:result = 1 + endif + elseif g:NERDTreeBookmarksSort ==# 2 + if a:firstBookmark.name <# a:secondBookmark.name + let l:result = -1 + elseif a:firstBookmark.name ># a:secondBookmark.name + let l:result = 1 + endif + endif + return l:result +endfunction + +" FUNCTION: Bookmark.ClearAll() {{{1 +" Class method to delete all bookmarks. +function! s:Bookmark.ClearAll() + for i in s:Bookmark.Bookmarks() + call i.delete() + endfor + call s:Bookmark.Write() +endfunction + +" FUNCTION: Bookmark.delete() {{{1 +" Delete this bookmark. If the node for this bookmark is under the current +" root, then recache bookmarks for its Path object +function! s:Bookmark.delete() + call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self)) + call s:Bookmark.Write() +endfunction + +" FUNCTION: s:Edit() {{{1 +" opens the NERDTreeBookmarks file for manual editing +function! s:Bookmark.Edit() + call nerdtree#exec('wincmd w', 1) + call nerdtree#exec('edit '.g:NERDTreeBookmarksFile, 1) +endfunction + +" FUNCTION: Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) {{{1 +" Returns the tree node object associated with this Bookmark. +" Throws NERDTree.BookmarkedNodeNotFoundError if the node is not found. +" +" Args: +" searchFromAbsoluteRoot: boolean flag, search from the highest cached node +" if true and from the current tree root if false +function! s:Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) + if a:searchFromAbsoluteRoot + let l:searchRoot = a:nerdtree.root.AbsoluteTreeRoot() + else + let l:searchRoot = a:nerdtree.root + endif + let l:targetNode = l:searchRoot.findNode(self.path) + if empty(l:targetNode) + throw 'NERDTree.BookmarkedNodeNotFoundError: node for bookmark "' . self.name . '" not found' + endif + return l:targetNode +endfunction + +" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) {{{1 +" Class method that returns the tree node object for the Bookmark with the +" given name. Throws NERDTree.BookmarkNotFoundError if a Bookmark with the +" name does not exist. Throws NERDTree.BookmarkedNodeNotFoundError if a +" tree node for the named Bookmark could not be found. +function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) + let l:bookmark = s:Bookmark.BookmarkFor(a:name) + return l:bookmark.getNode(a:nerdtree, a:searchFromAbsoluteRoot) +endfunction + +" FUNCTION: Bookmark.GetSelected() {{{1 +" returns the Bookmark the cursor is over, or {} +function! s:Bookmark.GetSelected() + let line = getline('.') + let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '') + if name !=# line + try + return s:Bookmark.BookmarkFor(name) + catch /^NERDTree.BookmarkNotFoundError/ + return {} + endtry + endif + return {} +endfunction + +" FUNCTION: Bookmark.InvalidBookmarks() {{{1 +" Class method to get all invalid bookmark strings read from the bookmarks +" file +function! s:Bookmark.InvalidBookmarks() + if !exists('g:NERDTreeInvalidBookmarks') + let g:NERDTreeInvalidBookmarks = [] + endif + return g:NERDTreeInvalidBookmarks +endfunction + +" FUNCTION: Bookmark.mustExist() {{{1 +function! s:Bookmark.mustExist() + if !self.path.exists() + call s:Bookmark.CacheBookmarks(1) + throw 'NERDTree.BookmarkPointsToInvalidLocationError: the bookmark "'. + \ self.name .'" points to a non existing location: "'. self.path.str() + endif +endfunction + +" FUNCTION: Bookmark.New(name, path) {{{1 +" Create a new bookmark object with the given name and path object +function! s:Bookmark.New(name, path) + if a:name =~# ' ' + throw 'NERDTree.IllegalBookmarkNameError: illegal name:' . a:name + endif + + let newBookmark = copy(self) + let newBookmark.name = a:name + let newBookmark.path = a:path + return newBookmark +endfunction + +" FUNCTION: Bookmark.open(nerdtree, [options]) {{{1 +"Args: +" +"nerdtree: the tree to load open the bookmark in +" +"A dictionary containing the following keys (all optional): +" 'where': Specifies whether the node should be opened in new split/tab or in +" the previous window. Can be either 'v' (vertical split), 'h' +" (horizontal split), 't' (new tab) or 'p' (previous window). +" 'reuse': if a window is displaying the file then jump the cursor there +" 'keepopen': dont close the tree window +" 'stay': open the file, but keep the cursor in the tree win +" +function! s:Bookmark.open(nerdtree, ...) + let opts = a:0 ? a:1 : {} + + if nerdtree#closeBookmarksOnOpen() + call a:nerdtree.ui.toggleShowBookmarks() + endif + + if self.path.isDirectory && !has_key(opts, 'where') + call self.toRoot(a:nerdtree) + else + let opener = g:NERDTreeOpener.New(self.path, opts) + call opener.open(self) + endif +endfunction + +" FUNCTION: Bookmark.openInNewTab(options) {{{1 +" Create a new bookmark object with the given name and path object +function! s:Bookmark.openInNewTab(options) + call nerdtree#deprecated('Bookmark.openInNewTab', 'is deprecated, use open() instead') + call self.open(a:options) +endfunction + +" FUNCTION: Bookmark.setPath(path) {{{1 +" makes this bookmark point to the given path +function! s:Bookmark.setPath(path) + let self.path = a:path +endfunction + +" FUNCTION: Bookmark.SortBookmarksList() {{{1 +" Class method that sorts the global list of bookmarks alphabetically by name. +" Note that case-sensitivity is determined by a user option. +function! s:Bookmark.SortBookmarksList() + call sort(s:Bookmark.Bookmarks(), s:Bookmark.CompareBookmarksByName, s:Bookmark) +endfunction + +" FUNCTION: Bookmark.str() {{{1 +" Get the string that should be rendered in the view for this bookmark +function! s:Bookmark.str() + let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - strdisplaywidth(self.name) + if &number + let pathStrMaxLen = pathStrMaxLen - &numberwidth + endif + + let pathStr = self.path.str({'format': 'UI'}) + if strdisplaywidth(pathStr) > pathStrMaxLen + while strdisplaywidth(pathStr) > pathStrMaxLen && strchars(pathStr) > 0 + let pathStr = substitute(pathStr, '^.', '', '') + endwhile + let pathStr = '<' . pathStr + endif + return '>' . self.name . ' ' . pathStr +endfunction + +" FUNCTION: Bookmark.toRoot(nerdtree) {{{1 +" Set the root of the given NERDTree to the node for this Bookmark. If a node +" for this Bookmark does not exist, a new one is initialized. +function! s:Bookmark.toRoot(nerdtree) + if self.validate() + try + let l:targetNode = self.getNode(a:nerdtree, 1) + call l:targetNode.closeChildren() + catch /^NERDTree.BookmarkedNodeNotFoundError/ + let l:targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path, a:nerdtree) + endtry + call a:nerdtree.changeRoot(l:targetNode) + endif +endfunction + +" FUNCTION: Bookmark.ToRoot(name, nerdtree) {{{1 +" Class method that makes the Bookmark with the given name the root of +" specified NERDTree. +function! s:Bookmark.ToRoot(name, nerdtree) + let l:bookmark = s:Bookmark.BookmarkFor(a:name) + call l:bookmark.toRoot(a:nerdtree) +endfunction + +" FUNCTION: Bookmark.validate() {{{1 +function! s:Bookmark.validate() + if self.path.exists() + return 1 + else + call s:Bookmark.CacheBookmarks(1) + call nerdtree#echo(self.name . 'now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.') + return 0 + endif +endfunction + +" FUNCTION: Bookmark.Write() {{{1 +" Class method to write all bookmarks to the bookmarks file +function! s:Bookmark.Write() + let bookmarkStrings = [] + for i in s:Bookmark.Bookmarks() + call add(bookmarkStrings, i.name . ' ' . fnamemodify(i.path.str(), ':~')) + endfor + + "add a blank line before the invalid ones + call add(bookmarkStrings, '') + + for j in s:Bookmark.InvalidBookmarks() + call add(bookmarkStrings, j) + endfor + + try + call writefile(bookmarkStrings, g:NERDTreeBookmarksFile) + catch + call nerdtree#echoError('Failed to write bookmarks file. Make sure g:NERDTreeBookmarksFile points to a valid location.') + endtry +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/creator.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/creator.vim new file mode 100644 index 0000000..26da04c --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/creator.vim @@ -0,0 +1,438 @@ +" ============================================================================ +" CLASS: Creator +" +" This class is responsible for creating NERDTree instances. The new NERDTree +" may be a tab tree, a window tree, or a mirrored tree. In the process of +" creating a NERDTree, it sets up all of the window and buffer options and key +" mappings etc. +" ============================================================================ + + +let s:Creator = {} +let g:NERDTreeCreator = s:Creator + +" FUNCTION: s:Creator._bindMappings() {{{1 +function! s:Creator._bindMappings() + call g:NERDTreeKeyMap.BindAll() + + command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#ui_glue#revealBookmark('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark call nerdtree#ui_glue#openBookmark('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('') + command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('', b:NERDTree) + command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() call b:NERDTree.render() + command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) call b:NERDTree.render() + command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write() + command! -buffer -nargs=0 EditBookmarks call g:NERDTreeBookmark.Edit() +endfunction + +" FUNCTION: s:Creator._broadcastInitEvent() {{{1 +function! s:Creator._broadcastInitEvent() + if exists('#User#NERDTreeInit') + doautocmd User NERDTreeInit + endif +endfunction + +" FUNCTION: s:Creator.BufNamePrefix() {{{1 +function! s:Creator.BufNamePrefix() + return 'NERD_tree_' +endfunction + +" FUNCTION: s:Creator.CreateExploreTree(dir) {{{1 +function! s:Creator.CreateExploreTree(dir) + try + let path = g:NERDTreePath.New(a:dir) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echo('Invalid directory name:' . a:dir) + return + endtry + + let creator = s:Creator.New() + if getbufinfo('%')[0].changed && !&hidden && !&autowriteall + let l:splitLocation = g:NERDTreeWinPos ==# 'left' || g:NERDTreeWinPos ==# 'top' ? 'topleft ' : 'botright ' + let l:splitDirection = g:NERDTreeWinPos ==# 'left' || g:NERDTreeWinPos ==# 'right' ? 'vertical' : '' + silent! execute l:splitLocation . l:splitDirection . ' new' + else + silent! execute 'enew' + endif + + call creator.createWindowTree(a:dir) + "we want windowTree buffer to disappear after moving to any other buffer + setlocal bufhidden=wipe +endfunction + +" FUNCTION: s:Creator.CreateTabTree(a:name) {{{1 +function! s:Creator.CreateTabTree(name) + let creator = s:Creator.New() + call creator.createTabTree(a:name) +endfunction + +" FUNCTION: s:Creator.createTabTree(a:name) {{{1 +" name: the name of a bookmark or a directory +function! s:Creator.createTabTree(name) + let l:path = self._pathForString(a:name) + + " Abort if an exception was thrown (i.e., if the bookmark or directory + " does not exist). + if empty(l:path) + return + endif + + " Obey the user's preferences for changing the working directory. + if g:NERDTreeChDirMode != 0 + call l:path.changeToDir() + endif + + if g:NERDTree.ExistsForTab() + call g:NERDTree.Close() + call self._removeTreeBufForTab() + endif + + call self._createTreeWin() + call self._createNERDTree(l:path, 'tab') + call b:NERDTree.render() + call b:NERDTree.root.putCursorHere(0, 0) + + call self._broadcastInitEvent() +endfunction + +" FUNCTION: s:Creator.CreateWindowTree(dir) {{{1 +function! s:Creator.CreateWindowTree(dir) + let creator = s:Creator.New() + call creator.createWindowTree(a:dir) +endfunction + +" FUNCTION: s:Creator.createWindowTree(dir) {{{1 +function! s:Creator.createWindowTree(dir) + try + let path = g:NERDTreePath.New(a:dir) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echo('Invalid directory name:' . a:dir) + return + endtry + + "we want the directory buffer to disappear when we do the :edit below + setlocal bufhidden=wipe + + let previousBuf = expand('#') + + "we need a unique name for each window tree buffer to ensure they are + "all independent + exec g:NERDTreeCreatePrefix . ' edit ' . self._nextBufferName('win') + + call self._createNERDTree(path, 'window') + let b:NERDTree._previousBuf = bufnr(previousBuf) + call self._setCommonBufOptions() + + call b:NERDTree.render() + + call self._broadcastInitEvent() +endfunction + +" FUNCTION: s:Creator._createNERDTree(path) {{{1 +function! s:Creator._createNERDTree(path, type) + let b:NERDTree = g:NERDTree.New(a:path, a:type) + + " TODO: This assignment is kept for compatibility reasons. Many other + " plugins use b:NERDTreeRoot instead of b:NERDTree.root. Remove this + " assignment in the future. + let b:NERDTreeRoot = b:NERDTree.root + + call b:NERDTree.root.open() +endfunction + +" FUNCTION: s:Creator.CreateMirror() {{{1 +function! s:Creator.CreateMirror() + let creator = s:Creator.New() + call creator.createMirror() +endfunction + +" FUNCTION: s:Creator.createMirror() {{{1 +function! s:Creator.createMirror() + "get the names off all the nerd tree buffers + let treeBufNames = [] + for i in range(1, tabpagenr('$')) + let nextName = self._tabpagevar(i, 'NERDTreeBufName') + if nextName != -1 && (!exists('t:NERDTreeBufName') || nextName != t:NERDTreeBufName) + call add(treeBufNames, nextName) + endif + endfor + let treeBufNames = self._uniq(treeBufNames) + + "map the option names (that the user will be prompted with) to the nerd + "tree buffer names + let options = {} + let i = 0 + while i < len(treeBufNames) + let bufName = treeBufNames[i] + let treeRoot = getbufvar(bufName, 'NERDTree').root + let options[i+1 . '. ' . treeRoot.path.str() . ' (buf name: ' . bufName . ')'] = bufName + let i = i + 1 + endwhile + + "work out which tree to mirror, if there is more than 1 then ask the user + let bufferName = '' + if len(keys(options)) > 1 + let choices = ['Choose a tree to mirror'] + let choices = extend(choices, sort(keys(options))) + let choice = inputlist(choices) + if choice < 1 || choice > len(options) || choice ==# '' + return + endif + + let bufferName = options[sort(keys(options))[choice-1]] + elseif len(keys(options)) ==# 1 + let bufferName = values(options)[0] + else + call nerdtree#echo('No trees to mirror') + return + endif + + if g:NERDTree.ExistsForTab() && g:NERDTree.IsOpen() + call g:NERDTree.Close() + endif + + let t:NERDTreeBufName = bufferName + call self._createTreeWin() + exec 'buffer ' . bufferName + call b:NERDTree.ui.restoreScreenState() + if !&hidden + call b:NERDTree.render() + endif +endfunction + +" FUNCTION: s:Creator._createTreeWin() {{{1 +" Initialize the NERDTree window. Open the window, size it properly, set all +" local options, etc. +function! s:Creator._createTreeWin() + let l:splitLocation = g:NERDTreeWinPos ==# 'left' || g:NERDTreeWinPos ==# 'top' ? 'topleft ' : 'botright ' + let l:splitDirection = g:NERDTreeWinPos ==# 'left' || g:NERDTreeWinPos ==# 'right' ? 'vertical' : '' + let l:splitSize = g:NERDTreeWinSize + + if !g:NERDTree.ExistsForTab() + let t:NERDTreeBufName = self._nextBufferName('tab') + silent! execute l:splitLocation . l:splitDirection . ' ' . l:splitSize . ' new' + silent! execute 'edit ' . t:NERDTreeBufName + silent! execute l:splitDirection . ' resize '. l:splitSize + else + silent! execute l:splitLocation . l:splitDirection . ' ' . l:splitSize . ' split' + silent! execute 'buffer ' . t:NERDTreeBufName + endif + + setlocal winfixwidth + + call self._setCommonBufOptions() + + if has('patch-7.4.1925') + clearjumps + endif + +endfunction + +" FUNCTION: s:Creator._isBufHidden(nr) {{{1 +function! s:Creator._isBufHidden(nr) + redir => bufs + silent ls! + redir END + + return bufs =~ a:nr . '..h' +endfunction + +" FUNCTION: s:Creator.New() {{{1 +function! s:Creator.New() + let newCreator = copy(self) + return newCreator +endfunction + +" FUNCTION: s:Creator._nextBufferName(type='') {{{1 +" gets an optional buffer type of either 'tab' or 'win'. +" returns the buffer name for the next nerd tree of such type. +function! s:Creator._nextBufferName(...) + if a:0 > 0 + let type = a:1 + else + let type = '' + end + let name = s:Creator.BufNamePrefix() + if type ==# 'tab' + let name = name . 'tab_' + elseif type ==# 'win' + let name = name . 'win_' + endif + let name = name . self._nextBufferNumber() + return name +endfunction + +" FUNCTION: s:Creator._nextBufferNumber() {{{1 +" the number to add to the nerd tree buffer name to make the buf name unique +function! s:Creator._nextBufferNumber() + if !exists('s:Creator._NextBufNum') + let s:Creator._NextBufNum = 1 + else + let s:Creator._NextBufNum += 1 + endif + + return s:Creator._NextBufNum +endfunction + +" FUNCTION: s:Creator._pathForString(str) {{{1 +" find a bookmark or adirectory for the given string +function! s:Creator._pathForString(str) + let path = {} + if g:NERDTreeBookmark.BookmarkExistsFor(a:str) + let path = g:NERDTreeBookmark.BookmarkFor(a:str).path + else + let dir = a:str ==# '' ? getcwd() : a:str + + "hack to get an absolute path if a relative path is given + if dir =~# '^\.' + let dir = getcwd() . nerdtree#slash() . dir + endif + + "hack to prevent removing slash if dir is the root of the file system. + if dir !=# '/' + let dir = g:NERDTreePath.Resolve(dir) + endif + + try + let path = g:NERDTreePath.New(dir) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echo('No bookmark or directory found for: ' . a:str) + return {} + endtry + endif + if !path.isDirectory + let path = path.getParent() + endif + + return path +endfunction + +" Function: s:Creator._removeTreeBufForTab() {{{1 +function! s:Creator._removeTreeBufForTab() + let buf = bufnr(t:NERDTreeBufName) + + "if &hidden is not set then it will already be gone + if buf != -1 + + "nerdtree buf may be mirrored/displayed elsewhere + if self._isBufHidden(buf) + exec 'bwipeout ' . buf + endif + + endif + + unlet t:NERDTreeBufName +endfunction + +" FUNCTION: s:Creator._setCommonBufOptions() {{{1 +function! s:Creator._setCommonBufOptions() + + " Options for a non-file/control buffer. + setlocal bufhidden=hide + setlocal buftype=nofile + setlocal noswapfile + + " Options for controlling buffer/window appearance. + setlocal foldcolumn=0 + setlocal foldmethod=manual + setlocal nobuflisted + setlocal nofoldenable + setlocal nolist + setlocal nospell + setlocal nowrap + + if g:NERDTreeShowLineNumbers + setlocal number + else + setlocal nonumber + if v:version >= 703 + setlocal norelativenumber + endif + endif + + iabc + + if g:NERDTreeHighlightCursorline + setlocal cursorline + endif + + call self._setupStatusline() + call self._bindMappings() + + setlocal filetype=nerdtree +endfunction + +" FUNCTION: s:Creator._setupStatusline() {{{1 +function! s:Creator._setupStatusline() + if g:NERDTreeStatusline != -1 + let &l:statusline = g:NERDTreeStatusline + endif +endfunction + +" FUNCTION: s:Creator._tabpagevar(tabnr, var) {{{1 +function! s:Creator._tabpagevar(tabnr, var) + let currentTab = tabpagenr() + let old_ei = &eventignore + set eventignore=all + + try + exec 'tabnext ' . a:tabnr + let v = -1 + if exists('t:' . a:var) + exec 'let v = t:' . a:var + endif + exec 'tabnext ' . currentTab + + finally + let &eventignore = old_ei + endtry + + return v +endfunction + +" FUNCTION: s:Creator.ToggleTabTree(dir) {{{1 +function! s:Creator.ToggleTabTree(dir) + let creator = s:Creator.New() + call creator.toggleTabTree(a:dir) +endfunction + +" FUNCTION: s:Creator.toggleTabTree(dir) {{{1 +" Toggles the NERD tree. I.e if the NERD tree is open, it is closed. If it is +" closed, it is restored or initialized. If dir is not empty, it will be set +" as the new root. +" +" Args: +" dir: the full path for the root node (is used if the NERD tree is being +" initialized, or to change the root to a new dir.) +function! s:Creator.toggleTabTree(dir) + if g:NERDTree.ExistsForTab() + if !g:NERDTree.IsOpen() + call self._createTreeWin() + if !empty(a:dir) && a:dir !=# b:NERDTree.root.path.str() + call self.createTabTree(a:dir) + elseif !&hidden + call b:NERDTree.render() + endif + call b:NERDTree.ui.restoreScreenState() + else + call g:NERDTree.Close() + endif + else + call self.createTabTree(a:dir) + endif +endfunction + +" Function: s:Creator._uniq(list) {{{1 +" returns a:list without duplicates +function! s:Creator._uniq(list) + let uniqlist = [] + for elem in a:list + if index(uniqlist, elem) ==# -1 + let uniqlist += [elem] + endif + endfor + return uniqlist +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/event.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/event.vim new file mode 100644 index 0000000..3a89f0e --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/event.vim @@ -0,0 +1,13 @@ +"CLASS: Event +"============================================================ +let s:Event = {} +let g:NERDTreeEvent = s:Event + +function! s:Event.New(nerdtree, subject, action, params) abort + let newObj = copy(self) + let newObj.nerdtree = a:nerdtree + let newObj.subject = a:subject + let newObj.action = a:action + let newObj.params = a:params + return newObj +endfunction diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/flag_set.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/flag_set.vim new file mode 100644 index 0000000..5ae6463 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/flag_set.vim @@ -0,0 +1,58 @@ +"CLASS: FlagSet +"============================================================ +let s:FlagSet = {} +let g:NERDTreeFlagSet = s:FlagSet + +"FUNCTION: FlagSet.addFlag(scope, flag) {{{1 +function! s:FlagSet.addFlag(scope, flag) + let flags = self._flagsForScope(a:scope) + if index(flags, a:flag) == -1 + call add(flags, a:flag) + end +endfunction + +"FUNCTION: FlagSet.clearFlags(scope) {{{1 +function! s:FlagSet.clearFlags(scope) + let self._flags[a:scope] = [] +endfunction + +"FUNCTION: FlagSet._flagsForScope(scope) {{{1 +function! s:FlagSet._flagsForScope(scope) + if !has_key(self._flags, a:scope) + let self._flags[a:scope] = [] + endif + return self._flags[a:scope] +endfunction + +"FUNCTION: FlagSet.New() {{{1 +function! s:FlagSet.New() + let newObj = copy(self) + let newObj._flags = {} + return newObj +endfunction + +"FUNCTION: FlagSet.removeFlag(scope, flag) {{{1 +function! s:FlagSet.removeFlag(scope, flag) + let flags = self._flagsForScope(a:scope) + + let i = index(flags, a:flag) + if i >= 0 + call remove(flags, i) + endif +endfunction + +"FUNCTION: FlagSet.renderToString() {{{1 +function! s:FlagSet.renderToString() + let flagstring = '' + for i in values(self._flags) + let flagstring .= join(i) + endfor + + if len(flagstring) == 0 + return '' + endif + + return '[' . flagstring . ']' +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/key_map.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/key_map.vim new file mode 100644 index 0000000..e42dbde --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/key_map.vim @@ -0,0 +1,164 @@ +"CLASS: KeyMap +"============================================================ +let s:KeyMap = {} +let g:NERDTreeKeyMap = s:KeyMap +let s:keyMaps = {} + +"FUNCTION: KeyMap.All() {{{1 +function! s:KeyMap.All() + let sortedKeyMaps = values(s:keyMaps) + call sort(sortedKeyMaps, s:KeyMap.Compare, s:KeyMap) + + return sortedKeyMaps +endfunction + +"FUNCTION: KeyMap.Compare(keyMap1, keyMap2) {{{1 +function! s:KeyMap.Compare(keyMap1, keyMap2) + + if a:keyMap1.key >? a:keyMap2.key + return 1 + endif + + if a:keyMap1.key ' notation, we + " must replace each of the '<' characters with '' to ensure the string + " is not translated into its corresponding keycode during the later part + " of the map command below + " :he <> + let specialNotationRegex = '\m<\([[:alnum:]_-]\+>\)' + if self.key =~# specialNotationRegex + let keymapInvokeString = substitute(self.key, specialNotationRegex, '\1', 'g') + else + let keymapInvokeString = self.key + endif + let keymapInvokeString = escape(keymapInvokeString, '\"') + + let premap = self.key ==# '' ? ' ' : ' ' + + exec 'nnoremap '. self.key . premap . ':call nerdtree#ui_glue#invokeKeyMap("'. keymapInvokeString .'")' +endfunction + +"FUNCTION: KeyMap.Remove(key, scope) {{{1 +function! s:KeyMap.Remove(key, scope) + return remove(s:keyMaps, a:key . a:scope) +endfunction + +"FUNCTION: KeyMap.invoke() {{{1 +"Call the KeyMaps callback function +function! s:KeyMap.invoke(...) + let l:Callback = type(self.callback) ==# type(function('tr')) ? self.callback : function(self.callback) + if a:0 + call l:Callback(a:1) + else + call l:Callback() + endif +endfunction + +"FUNCTION: KeyMap.Invoke() {{{1 +"Find a keymapping for a:key and the current scope invoke it. +" +"Scope is determined as follows: +" * if the cursor is on a dir node then DirNode +" * if the cursor is on a file node then FileNode +" * if the cursor is on a bookmark then Bookmark +" +"If a keymap has the scope of 'all' then it will be called if no other keymap +"is found for a:key and the scope. +function! s:KeyMap.Invoke(key) + + "required because clicking the command window below another window still + "invokes the mapping - but changes the window cursor + "is in first + " + "TODO: remove this check when the vim bug is fixed + if !g:NERDTree.ExistsForBuf() + return {} + endif + + let node = g:NERDTreeFileNode.GetSelected() + if !empty(node) + + "try file node + if !node.path.isDirectory + let km = s:KeyMap.FindFor(a:key, 'FileNode') + if !empty(km) + return km.invoke(node) + endif + endif + + "try dir node + if node.path.isDirectory + let km = s:KeyMap.FindFor(a:key, 'DirNode') + if !empty(km) + return km.invoke(node) + endif + endif + + "try generic node + let km = s:KeyMap.FindFor(a:key, 'Node') + if !empty(km) + return km.invoke(node) + endif + + endif + + "try bookmark + let bm = g:NERDTreeBookmark.GetSelected() + if !empty(bm) + let km = s:KeyMap.FindFor(a:key, 'Bookmark') + if !empty(km) + return km.invoke(bm) + endif + endif + + "try all + let km = s:KeyMap.FindFor(a:key, 'all') + if !empty(km) + return km.invoke() + endif +endfunction + +"FUNCTION: KeyMap.Create(options) {{{1 +function! s:KeyMap.Create(options) + let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options)) + + "dont override other mappings unless the 'override' option is given + if get(opts, 'override', 0) ==# 0 && !empty(s:KeyMap.FindFor(opts['key'], opts['scope'])) + return + end + + let newKeyMap = copy(self) + let newKeyMap.key = opts['key'] + let newKeyMap.quickhelpText = opts['quickhelpText'] + let newKeyMap.callback = opts['callback'] + let newKeyMap.scope = opts['scope'] + + call s:KeyMap.Add(newKeyMap) +endfunction + +"FUNCTION: KeyMap.Add(keymap) {{{1 +function! s:KeyMap.Add(keymap) + let s:keyMaps[a:keymap.key . a:keymap.scope] = a:keymap +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/menu_controller.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/menu_controller.vim new file mode 100644 index 0000000..c648381 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/menu_controller.vim @@ -0,0 +1,211 @@ +"CLASS: MenuController +"============================================================ +let s:MenuController = {} +let g:NERDTreeMenuController = s:MenuController + +"FUNCTION: MenuController.New(menuItems) {{{1 +"create a new menu controller that operates on the given menu items +function! s:MenuController.New(menuItems) + let newMenuController = copy(self) + if a:menuItems[0].isSeparator() + let newMenuController.menuItems = a:menuItems[1:-1] + else + let newMenuController.menuItems = a:menuItems + endif + return newMenuController +endfunction + +" FUNCTION: s:MenuController.isMinimal() {{{1 +function! s:MenuController.isMinimal() + return g:NERDTreeMinimalMenu +endfunction + +" FUNCTION: MenuController.showMenu() {{{1 +" Enter the main loop of the NERDTree menu, prompting the user to select +" a menu item. +function! s:MenuController.showMenu() + call self._saveOptions() + + try + let self.selection = 0 + let l:done = 0 + + while !l:done + if has('nvim') + mode + else + redraw! + endif + call self._echoPrompt() + + let l:key = nr2char(getchar()) + let l:done = self._handleKeypress(l:key) + endwhile + finally + call self._restoreOptions() + + " Redraw when Ctrl-C or Esc is received. + if !l:done || self.selection ==# -1 + redraw! + endif + endtry + + if self.selection !=# -1 + let l:m = self._current() + call l:m.execute() + endif +endfunction + +"FUNCTION: MenuController._echoPrompt() {{{1 +function! s:MenuController._echoPrompt() + let navHelp = 'Use ' . g:NERDTreeMenuDown . '/' . g:NERDTreeMenuUp . '/enter' + + if self.isMinimal() + let selection = self.menuItems[self.selection].text + let keyword = matchstr(selection, '[^ ]*([^ ]*') + + let shortcuts = map(copy(self.menuItems), "v:val['shortcut']") + let shortcuts[self.selection] = ' ' . keyword . ' ' + + echo 'Menu: [' . join(shortcuts, ',') . '] (' . navHelp . ' or shortcut): ' + else + echo 'NERDTree Menu. ' . navHelp . ', or the shortcuts indicated' + echo '=========================================================' + + for i in range(0, len(self.menuItems)-1) + if self.selection ==# i + echo '> ' . self.menuItems[i].text + else + echo ' ' . self.menuItems[i].text + endif + endfor + endif +endfunction + +"FUNCTION: MenuController._current(key) {{{1 +"get the MenuItem that is currently selected +function! s:MenuController._current() + return self.menuItems[self.selection] +endfunction + +"FUNCTION: MenuController._handleKeypress(key) {{{1 +"change the selection (if appropriate) and return 1 if the user has made +"their choice, 0 otherwise +function! s:MenuController._handleKeypress(key) + if a:key ==# g:NERDTreeMenuDown + call self._cursorDown() + elseif a:key ==# g:NERDTreeMenuUp + call self._cursorUp() + elseif a:key ==# nr2char(27) "escape + let self.selection = -1 + return 1 + elseif a:key ==# "\r" || a:key ==# "\n" "enter and ctrl-j + return 1 + else + let index = self._nextIndexFor(a:key) + if index !=# -1 + let self.selection = index + if len(self._allIndexesFor(a:key)) ==# 1 + return 1 + endif + endif + endif + + return 0 +endfunction + +"FUNCTION: MenuController._allIndexesFor(shortcut) {{{1 +"get indexes to all menu items with the given shortcut +function! s:MenuController._allIndexesFor(shortcut) + let toReturn = [] + + for i in range(0, len(self.menuItems)-1) + if self.menuItems[i].shortcut ==# a:shortcut + call add(toReturn, i) + endif + endfor + + return toReturn +endfunction + +"FUNCTION: MenuController._nextIndexFor(shortcut) {{{1 +"get the index to the next menu item with the given shortcut, starts from the +"current cursor location and wraps around to the top again if need be +function! s:MenuController._nextIndexFor(shortcut) + for i in range(self.selection+1, len(self.menuItems)-1) + if self.menuItems[i].shortcut ==# a:shortcut + return i + endif + endfor + + for i in range(0, self.selection) + if self.menuItems[i].shortcut ==# a:shortcut + return i + endif + endfor + + return -1 +endfunction + +"FUNCTION: MenuController._setCmdheight() {{{1 +"sets &cmdheight to whatever is needed to display the menu +function! s:MenuController._setCmdheight() + if self.isMinimal() + let &cmdheight = 1 + else + let &cmdheight = len(self.menuItems) + 3 + endif +endfunction + +"FUNCTION: MenuController._saveOptions() {{{1 +"set any vim options that are required to make the menu work (saving their old +"values) +function! s:MenuController._saveOptions() + let self._oldLazyredraw = &lazyredraw + let self._oldCmdheight = &cmdheight + set nolazyredraw + call self._setCmdheight() +endfunction + +"FUNCTION: MenuController._restoreOptions() {{{1 +"restore the options we saved in _saveOptions() +function! s:MenuController._restoreOptions() + let &cmdheight = self._oldCmdheight + let &lazyredraw = self._oldLazyredraw +endfunction + +"FUNCTION: MenuController._cursorDown() {{{1 +"move the cursor to the next menu item, skipping separators +function! s:MenuController._cursorDown() + let done = 0 + while !done + if self.selection < len(self.menuItems)-1 + let self.selection += 1 + else + let self.selection = 0 + endif + + if !self._current().isSeparator() + let done = 1 + endif + endwhile +endfunction + +"FUNCTION: MenuController._cursorUp() {{{1 +"move the cursor to the previous menu item, skipping separators +function! s:MenuController._cursorUp() + let done = 0 + while !done + if self.selection > 0 + let self.selection -= 1 + else + let self.selection = len(self.menuItems)-1 + endif + + if !self._current().isSeparator() + let done = 1 + endif + endwhile +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/menu_item.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/menu_item.vim new file mode 100644 index 0000000..e0c7600 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/menu_item.vim @@ -0,0 +1,118 @@ +"CLASS: MenuItem +"============================================================ +let s:MenuItem = {} +let g:NERDTreeMenuItem = s:MenuItem + +"FUNCTION: MenuItem.All() {{{1 +"get all top level menu items +function! s:MenuItem.All() + if !exists('s:menuItems') + let s:menuItems = [] + endif + return s:menuItems +endfunction + +"FUNCTION: MenuItem.AllEnabled() {{{1 +"get all top level menu items that are currently enabled +function! s:MenuItem.AllEnabled() + let toReturn = [] + for i in s:MenuItem.All() + if i.enabled() + call add(toReturn, i) + endif + endfor + return toReturn +endfunction + +"FUNCTION: MenuItem.Create(options) {{{1 +"make a new menu item and add it to the global list +function! s:MenuItem.Create(options) + let newMenuItem = copy(self) + + let newMenuItem.text = a:options['text'] + let newMenuItem.shortcut = a:options['shortcut'] + let newMenuItem.children = [] + + let newMenuItem.isActiveCallback = -1 + if has_key(a:options, 'isActiveCallback') + let newMenuItem.isActiveCallback = a:options['isActiveCallback'] + endif + + let newMenuItem.callback = -1 + if has_key(a:options, 'callback') + let newMenuItem.callback = a:options['callback'] + endif + + if has_key(a:options, 'parent') + call add(a:options['parent'].children, newMenuItem) + else + call add(s:MenuItem.All(), newMenuItem) + endif + + return newMenuItem +endfunction + +"FUNCTION: MenuItem.CreateSeparator(options) {{{1 +"make a new separator menu item and add it to the global list +function! s:MenuItem.CreateSeparator(options) + let standard_options = { 'text': '--------------------', + \ 'shortcut': -1, + \ 'callback': -1 } + let options = extend(a:options, standard_options, 'force') + + return s:MenuItem.Create(options) +endfunction + +"FUNCTION: MenuItem.CreateSubmenu(options) {{{1 +"make a new submenu and add it to global list +function! s:MenuItem.CreateSubmenu(options) + let standard_options = { 'callback': -1 } + let options = extend(a:options, standard_options, 'force') + + return s:MenuItem.Create(options) +endfunction + +"FUNCTION: MenuItem.enabled() {{{1 +"return 1 if this menu item should be displayed +" +"delegates off to the isActiveCallback, and defaults to 1 if no callback was +"specified +function! s:MenuItem.enabled() + if self.isActiveCallback != -1 + return type(self.isActiveCallback) == type(function('tr')) ? self.isActiveCallback() : {self.isActiveCallback}() + endif + return 1 +endfunction + +"FUNCTION: MenuItem.execute() {{{1 +"perform the action behind this menu item, if this menuitem has children then +"display a new menu for them, otherwise deletegate off to the menuitem's +"callback +function! s:MenuItem.execute() + if len(self.children) + let mc = g:NERDTreeMenuController.New(self.children) + call mc.showMenu() + else + if self.callback != -1 + if type(self.callback) == type(function('tr')) + call self.callback() + else + call {self.callback}() + endif + endif + endif +endfunction + +"FUNCTION: MenuItem.isSeparator() {{{1 +"return 1 if this menuitem is a separator +function! s:MenuItem.isSeparator() + return self.callback == -1 && self.children == [] +endfunction + +"FUNCTION: MenuItem.isSubmenu() {{{1 +"return 1 if this menuitem is a submenu +function! s:MenuItem.isSubmenu() + return self.callback == -1 && !empty(self.children) +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/nerdtree.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/nerdtree.vim new file mode 100644 index 0000000..22d2dab --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/nerdtree.vim @@ -0,0 +1,209 @@ +"CLASS: NERDTree +"============================================================ +let s:NERDTree = {} +let g:NERDTree = s:NERDTree + +"FUNCTION: s:NERDTree.AddPathFilter() {{{1 +function! s:NERDTree.AddPathFilter(callback) + call add(s:NERDTree.PathFilters(), a:callback) +endfunction + +"FUNCTION: s:NERDTree.changeRoot(node) {{{1 +function! s:NERDTree.changeRoot(node) + if a:node.path.isDirectory + let self.root = a:node + else + call a:node.cacheParent() + let self.root = a:node.parent + endif + + call self.root.open() + + "change dir to the dir of the new root if instructed to + if g:NERDTreeChDirMode >= 2 + call self.root.path.changeToDir() + endif + + call self.render() + call self.root.putCursorHere(0, 0) + + if exists('#User#NERDTreeNewRoot') + doautocmd User NERDTreeNewRoot + endif +endfunction + +"FUNCTION: s:NERDTree.Close() {{{1 +"Closes the tab tree window for this tab +function! s:NERDTree.Close() + if !s:NERDTree.IsOpen() + return + endif + + if winnr('$') !=# 1 + " Use the window ID to identify the currently active window or fall + " back on the buffer ID if win_getid/win_gotoid are not available, in + " which case we'll focus an arbitrary window showing the buffer. + let l:useWinId = exists('*win_getid') && exists('*win_gotoid') + + if winnr() ==# s:NERDTree.GetWinNum() + call nerdtree#exec('wincmd p', 1) + let l:activeBufOrWin = l:useWinId ? win_getid() : bufnr('') + call nerdtree#exec('wincmd p', 1) + else + let l:activeBufOrWin = l:useWinId ? win_getid() : bufnr('') + endif + + call nerdtree#exec(s:NERDTree.GetWinNum() . ' wincmd w', 1) + call nerdtree#exec('close', 0) + if l:useWinId + call nerdtree#exec('call win_gotoid(' . l:activeBufOrWin . ')', 0) + else + call nerdtree#exec(bufwinnr(l:activeBufOrWin) . ' wincmd w', 0) + endif + else + close + endif +endfunction + +"FUNCTION: s:NERDTree.CursorToBookmarkTable(){{{1 +"Places the cursor at the top of the bookmarks table +function! s:NERDTree.CursorToBookmarkTable() + if !b:NERDTree.ui.getShowBookmarks() + throw 'NERDTree.IllegalOperationError: cant find bookmark table, bookmarks arent active' + endif + + if g:NERDTreeMinimalUI + return cursor(1, 2) + endif + + let rootNodeLine = b:NERDTree.ui.getRootLineNum() + + let line = 1 + while getline(line) !~# '^>-\+Bookmarks-\+$' + let line = line + 1 + if line >= rootNodeLine + throw 'NERDTree.BookmarkTableNotFoundError: didnt find the bookmarks table' + endif + endwhile + call cursor(line, 2) +endfunction + +"FUNCTION: s:NERDTree.CursorToTreeWin(){{{1 +"Places the cursor in the nerd tree window +function! s:NERDTree.CursorToTreeWin(...) + call g:NERDTree.MustBeOpen() + call nerdtree#exec(g:NERDTree.GetWinNum() . 'wincmd w', a:0 >0 ? a:1 : 1) +endfunction + +" Function: s:NERDTree.ExistsForBuffer() {{{1 +" Returns 1 if a nerd tree root exists in the current buffer +function! s:NERDTree.ExistsForBuf() + return exists('b:NERDTree') +endfunction + +" Function: s:NERDTree.ExistsForTab() {{{1 +" Returns 1 if a nerd tree root exists in the current tab +function! s:NERDTree.ExistsForTab() + if !exists('t:NERDTreeBufName') + return + end + + "check b:NERDTree is still there and hasn't been e.g. :bdeleted + return !empty(getbufvar(bufnr(t:NERDTreeBufName), 'NERDTree')) +endfunction + +function! s:NERDTree.ForCurrentBuf() + if s:NERDTree.ExistsForBuf() + return b:NERDTree + else + return {} + endif +endfunction + +"FUNCTION: s:NERDTree.ForCurrentTab() {{{1 +function! s:NERDTree.ForCurrentTab() + if !s:NERDTree.ExistsForTab() + return + endif + + let bufnr = bufnr(t:NERDTreeBufName) + return getbufvar(bufnr, 'NERDTree') +endfunction + +"FUNCTION: s:NERDTree.getRoot() {{{1 +function! s:NERDTree.getRoot() + return self.root +endfunction + +"FUNCTION: s:NERDTree.GetWinNum() {{{1 +"gets the nerd tree window number for this tab +function! s:NERDTree.GetWinNum() + if exists('t:NERDTreeBufName') + return bufwinnr(t:NERDTreeBufName) + endif + + " If WindowTree, there is no t:NERDTreeBufName variable. Search all windows. + for w in range(1,winnr('$')) + if bufname(winbufnr(w)) =~# '^' . g:NERDTreeCreator.BufNamePrefix() . 'win_\d\+$' + return w + endif + endfor + + return -1 +endfunction + +"FUNCTION: s:NERDTree.IsOpen() {{{1 +function! s:NERDTree.IsOpen() + return s:NERDTree.GetWinNum() !=# -1 +endfunction + +"FUNCTION: s:NERDTree.isTabTree() {{{1 +function! s:NERDTree.isTabTree() + return self._type ==# 'tab' +endfunction + +"FUNCTION: s:NERDTree.isWinTree() {{{1 +function! s:NERDTree.isWinTree() + return self._type ==# 'window' +endfunction + +"FUNCTION: s:NERDTree.MustBeOpen() {{{1 +function! s:NERDTree.MustBeOpen() + if !s:NERDTree.IsOpen() + throw 'NERDTree.TreeNotOpen' + endif +endfunction + +"FUNCTION: s:NERDTree.New() {{{1 +function! s:NERDTree.New(path, type) + let newObj = copy(self) + let newObj.ui = g:NERDTreeUI.New(newObj) + let newObj.root = g:NERDTreeDirNode.New(a:path, newObj) + let newObj._type = a:type + return newObj +endfunction + +"FUNCTION: s:NERDTree.PathFilters() {{{1 +function! s:NERDTree.PathFilters() + if !exists('s:NERDTree._PathFilters') + let s:NERDTree._PathFilters = [] + endif + return s:NERDTree._PathFilters +endfunction + +"FUNCTION: s:NERDTree.previousBuf() {{{1 +function! s:NERDTree.previousBuf() + return self._previousBuf +endfunction + +function! s:NERDTree.setPreviousBuf(bnum) + let self._previousBuf = a:bnum +endfunction + +"FUNCTION: s:NERDTree.render() {{{1 +"A convenience function - since this is called often +function! s:NERDTree.render() + call self.ui.render() +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/notifier.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/notifier.vim new file mode 100644 index 0000000..f603e77 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/notifier.vim @@ -0,0 +1,35 @@ +"CLASS: Notifier +"============================================================ +let s:Notifier = {} + +function! s:Notifier.AddListener(event, funcname) + let listeners = s:Notifier.GetListenersForEvent(a:event) + if listeners == [] + let listenersMap = s:Notifier.GetListenersMap() + let listenersMap[a:event] = listeners + endif + call add(listeners, a:funcname) +endfunction + +function! s:Notifier.NotifyListeners(event, path, nerdtree, params) + let event = g:NERDTreeEvent.New(a:nerdtree, a:path, a:event, a:params) + + for Listener in s:Notifier.GetListenersForEvent(a:event) + let l:Callback = type(Listener) == type(function('tr')) ? Listener : function(Listener) + call l:Callback(event) + endfor +endfunction + +function! s:Notifier.GetListenersMap() + if !exists('s:refreshListenersMap') + let s:refreshListenersMap = {} + endif + return s:refreshListenersMap +endfunction + +function! s:Notifier.GetListenersForEvent(name) + let listenersMap = s:Notifier.GetListenersMap() + return get(listenersMap, a:name, []) +endfunction + +let g:NERDTreePathNotifier = deepcopy(s:Notifier) diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/opener.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/opener.vim new file mode 100644 index 0000000..bc5987f --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/opener.vim @@ -0,0 +1,326 @@ +" ============================================================================ +" CLASS: Opener +" +" The Opener class defines an API for 'opening' operations. +" ============================================================================ + + +let s:Opener = {} +let g:NERDTreeOpener = s:Opener + +" FUNCTION: s:Opener._bufInWindows(bnum) {{{1 +" [[STOLEN FROM VTREEEXPLORER.VIM]] +" Determine the number of windows open to this buffer number. +" Care of Yegappan Lakshman. Thanks! +" +" Args: +" bnum: the subject buffers buffer number +function! s:Opener._bufInWindows(bnum) + let cnt = 0 + let winnum = 1 + while 1 + let bufnum = winbufnr(winnum) + if bufnum < 0 + break + endif + if bufnum ==# a:bnum + let cnt = cnt + 1 + endif + let winnum = winnum + 1 + endwhile + + return cnt +endfunction + +" FUNCTION: Opener._checkToCloseTree(newtab) {{{1 +" Check the class options to see if the tree should be closed now. +" +" Args: +" a:newtab - boolean. If set, only close the tree now if we are opening the +" target in a new tab. This is needed because we have to close tree before we +" leave the tab +function! s:Opener._checkToCloseTree(newtab) + if self._keepopen + return + endif + + if (a:newtab && self._where ==# 't') || !a:newtab + call g:NERDTree.Close() + endif +endfunction + +" FUNCTION: s:Opener._firstUsableWindow() {{{1 +" find the window number of the first normal window +function! s:Opener._firstUsableWindow() + let i = 1 + while i <= winnr('$') + let bnum = winbufnr(i) + if bnum !=# -1 && getbufvar(bnum, '&buftype') ==# '' + \ && !getwinvar(i, '&previewwindow') + \ && (!getbufvar(bnum, '&modified') || &hidden) + return i + endif + + let i += 1 + endwhile + return -1 +endfunction + +" FUNCTION: Opener._gotoTargetWin() {{{1 +function! s:Opener._gotoTargetWin() + if b:NERDTree.isWinTree() + if self._where ==# 'v' + call self._newVSplit() + elseif self._where ==# 'h' + call self._newSplit() + elseif self._where ==# 't' + tabnew + endif + else + call self._checkToCloseTree(1) + + if self._where ==# 'v' + call self._newVSplit() + elseif self._where ==# 'h' + call self._newSplit() + elseif self._where ==# 't' + tabnew + elseif self._where ==# 'p' + call self._previousWindow() + endif + + call self._checkToCloseTree(0) + endif +endfunction + +" FUNCTION: s:Opener._isWindowUsable(winnumber) {{{1 +" Returns 0 if opening a file from the tree in the given window requires it to +" be split, 1 otherwise +" +" Args: +" winnumber: the number of the window in question +function! s:Opener._isWindowUsable(winnumber) + "gotta split if theres only one window (i.e. the NERD tree) + if winnr('$') ==# 1 + return 0 + endif + + let oldwinnr = winnr() + call nerdtree#exec(a:winnumber . 'wincmd p', 1) + let specialWindow = getbufvar('%', '&buftype') !=# '' || getwinvar('%', '&previewwindow') + let modified = &modified + call nerdtree#exec(oldwinnr . 'wincmd p', 1) + + "if its a special window e.g. quickfix or another explorer plugin then we + "have to split + if specialWindow + return 0 + endif + + if &hidden + return 1 + endif + + return !modified || self._bufInWindows(winbufnr(a:winnumber)) >= 2 +endfunction + +" FUNCTION: Opener.New(path, opts) {{{1 +" Instantiate a new NERDTreeOpener object. +" Args: +" a:path: the path object that is to be opened +" a:opts: a dictionary containing the following optional keys... +" 'where': specifies whether the node should be opened in new split, in +" a new tab or, in the last window; takes values 'v', 'h', or 't' +" 'reuse': if file is already shown in a window, jump there; takes values +" 'all', 'currenttab', or empty +" 'keepopen': boolean (0 or 1); if true, the tree window will not be closed +" 'stay': boolean (0 or 1); if true, remain in tree window after opening +function! s:Opener.New(path, opts) + let l:newOpener = copy(self) + + let l:newOpener._keepopen = nerdtree#has_opt(a:opts, 'keepopen') + let l:newOpener._nerdtree = b:NERDTree + let l:newOpener._path = a:path + let l:newOpener._reuse = has_key(a:opts, 'reuse') ? a:opts['reuse'] : '' + let l:newOpener._stay = nerdtree#has_opt(a:opts, 'stay') + let l:newOpener._where = has_key(a:opts, 'where') ? a:opts['where'] : '' + + call l:newOpener._saveCursorPos() + + return l:newOpener +endfunction + +" FUNCTION: Opener._newSplit() {{{1 +function! s:Opener._newSplit() + let onlyOneWin = (winnr('$') ==# 1) + let savesplitright = &splitright + if onlyOneWin + let &splitright = (g:NERDTreeWinPos ==# 'left') + endif + " If only one window (ie. NERDTree), split vertically instead. + let splitMode = onlyOneWin ? 'vertical' : '' + + " Open the new window + try + call nerdtree#exec('wincmd p', 1) + call nerdtree#exec(splitMode . ' split',1) + catch /^Vim\%((\a\+)\)\=:E37/ + call g:NERDTree.CursorToTreeWin() + throw 'NERDTree.FileAlreadyOpenAndModifiedError: '. self._path.str() .' is already open and modified.' + catch /^Vim\%((\a\+)\)\=:/ + "do nothing + endtry + + "resize the tree window if no other window was open before + if onlyOneWin + call nerdtree#exec('wincmd p', 1) + call nerdtree#exec('silent '. splitMode .' resize '. g:NERDTreeWinSize, 1) + call nerdtree#exec('wincmd p', 0) + endif + + let &splitright=savesplitright +endfunction + +" FUNCTION: Opener._newVSplit() {{{1 +function! s:Opener._newVSplit() + let l:winwidth = winwidth('.') + + let onlyOneWin = (winnr('$') ==# 1) + let savesplitright = &splitright + if onlyOneWin + let &splitright = (g:NERDTreeWinPos ==# 'left') + let l:winwidth = g:NERDTreeWinSize + endif + + call nerdtree#exec('wincmd p', 1) + call nerdtree#exec('vsplit', 1) + + let l:currentWindowNumber = winnr() + + " Restore the NERDTree to its original width. + call g:NERDTree.CursorToTreeWin() + execute 'silent vertical resize ' . l:winwidth + + call nerdtree#exec(l:currentWindowNumber . 'wincmd w', 0) + let &splitright=savesplitright +endfunction + +" FUNCTION: Opener.open(target) {{{1 +function! s:Opener.open(target) + if self._path.isDirectory + call self._openDirectory(a:target) + return + endif + + call self._openFile() +endfunction + +" FUNCTION: Opener._openFile() {{{1 +function! s:Opener._openFile() + if !self._stay && self._keepopen && get(b:, 'NERDTreeZoomed', 0) + call b:NERDTree.ui.toggleZoom() + endif + + if self._reuseWindow() + return + endif + + call self._gotoTargetWin() + + if self._stay + silent call self._path.edit() + call self._restoreCursorPos() + return + endif + + call self._path.edit() +endfunction + +" FUNCTION: Opener._openDirectory(node) {{{1 +function! s:Opener._openDirectory(node) + call self._gotoTargetWin() + + if self._nerdtree.isWinTree() + call g:NERDTreeCreator.CreateWindowTree(a:node.path.str()) + else + if empty(self._where) + call b:NERDTree.changeRoot(a:node) + elseif self._where ==# 't' + call g:NERDTreeCreator.CreateTabTree(a:node.path.str()) + else + call g:NERDTreeCreator.CreateWindowTree(a:node.path.str()) + endif + endif + + if self._stay + call self._restoreCursorPos() + endif +endfunction + +" FUNCTION: Opener._previousWindow() {{{1 +function! s:Opener._previousWindow() + if !self._isWindowUsable(winnr('#')) && self._firstUsableWindow() ==# -1 + call self._newSplit() + else + try + if !self._isWindowUsable(winnr('#')) + call nerdtree#exec(self._firstUsableWindow() . 'wincmd w', 1) + else + call nerdtree#exec('wincmd p', 1) + endif + catch /^Vim\%((\a\+)\)\=:E37/ + call g:NERDTree.CursorToTreeWin() + throw 'NERDTree.FileAlreadyOpenAndModifiedError: '. self._path.str() .' is already open and modified.' + catch /^Vim\%((\a\+)\)\=:/ + echo v:exception + endtry + endif +endfunction + +" FUNCTION: Opener._restoreCursorPos() {{{1 +function! s:Opener._restoreCursorPos() + call nerdtree#exec(self._tabnr . 'tabnext', 1) + call nerdtree#exec(bufwinnr(self._bufnr) . 'wincmd w', 1) +endfunction + +" FUNCTION: Opener._reuseWindow() {{{1 +" put the cursor in the first window we find for this file +" +" return 1 if we were successful +function! s:Opener._reuseWindow() + if empty(self._reuse) + return 0 + endif + + "check the current tab for the window + let winnr = bufwinnr('^' . self._path.str() . '$') + if winnr !=# -1 + call nerdtree#exec(winnr . 'wincmd w', 0) + call self._checkToCloseTree(0) + return 1 + endif + + if self._reuse ==# 'currenttab' + return 0 + endif + + "check other tabs + let tabnr = self._path.tabnr() + if tabnr + call self._checkToCloseTree(1) + call nerdtree#exec(tabnr . 'tabnext', 1) + let winnr = bufwinnr('^' . self._path.str() . '$') + call nerdtree#exec(winnr . 'wincmd w', 0) + return 1 + endif + + return 0 +endfunction + +" FUNCTION: Opener._saveCursorPos() {{{1 +function! s:Opener._saveCursorPos() + let self._bufnr = bufnr('') + let self._tabnr = tabpagenr() +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/path.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/path.vim new file mode 100644 index 0000000..c99bb0b --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/path.vim @@ -0,0 +1,867 @@ +" ============================================================================ +" CLASS: Path +" +" The Path class provides an abstracted representation of a file system +" pathname. Various operations on pathnames are provided and a number of +" representations of a given path name can be accessed here. +" ============================================================================ + + +let s:Path = {} +let g:NERDTreePath = s:Path + +" FUNCTION: Path.AbsolutePathFor(pathStr) {{{1 +function! s:Path.AbsolutePathFor(pathStr) + let l:prependWorkingDir = 0 + + if nerdtree#runningWindows() + let l:prependWorkingDir = a:pathStr !~# '^.:\(\\\|\/\)\?' && a:pathStr !~# '^\(\\\\\|\/\/\)' + else + let l:prependWorkingDir = a:pathStr !~# '^/' + endif + + let l:result = a:pathStr + + if l:prependWorkingDir + let l:result = getcwd() + + if l:result[-1:] == nerdtree#slash() + let l:result = l:result . a:pathStr + else + let l:result = l:result . nerdtree#slash() . a:pathStr + endif + endif + + return l:result +endfunction + +" FUNCTION: Path.bookmarkNames() {{{1 +function! s:Path.bookmarkNames() + if !exists('self._bookmarkNames') + call self.cacheDisplayString() + endif + return self._bookmarkNames +endfunction + +" FUNCTION: Path.cacheDisplayString() {{{1 +function! s:Path.cacheDisplayString() abort + let self.cachedDisplayString = g:NERDTreeNodeDelimiter . self.getLastPathComponent(1) + + if self.isExecutable + let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . '*' + endif + + let self._bookmarkNames = [] + for i in g:NERDTreeBookmark.Bookmarks() + if i.path.equals(self) + call add(self._bookmarkNames, i.name) + endif + endfor + if !empty(self._bookmarkNames) && g:NERDTreeMarkBookmarks ==# 1 + let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' {' . join(self._bookmarkNames) . '}' + endif + + if self.isSymLink + let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' -> ' . self.symLinkDest + endif + + if !self.isDirectory && b:NERDTree.ui.getShowFileLines() != 0 + let l:bufname = self.str({'format': 'Edit'}) + let l:lines = 0 + if executable('wc') + let l:lines = split(system('wc -l "'.l:bufname.'"'))[0] + elseif nerdtree#runningWindows() + let l:lines = substitute(system('type "'.l:bufname.'" | find /c /v ""'), '\n', '', 'g') + else + let s:lines = readfile(l:bufname) + let l:lines = 0 + for s:line in s:lines + let l:lines += 1 + if l:lines >= 20000 + break + endif + endfor + endif + let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' ('.l:lines.')' + endif + if self.isReadOnly + let self.cachedDisplayString = self.addDelimiter(self.cachedDisplayString) . ' ['.g:NERDTreeGlyphReadOnly.']' + endif +endfunction + +" FUNCTION: Path.addDelimiter() {{{1 +function! s:Path.addDelimiter(line) + if a:line =~# '\(.*' . g:NERDTreeNodeDelimiter . '\)\{2}' + return a:line + else + return a:line . g:NERDTreeNodeDelimiter + endif +endfunction + +" FUNCTION: Path.changeToDir() {{{1 +function! s:Path.changeToDir() + let dir = self.str({'format': 'Cd'}) + if self.isDirectory ==# 0 + let dir = self.getParent().str({'format': 'Cd'}) + endif + + try + if g:NERDTreeUseTCD && exists(':tcd') ==# 2 + execute 'tcd ' . dir + call nerdtree#echo("Tab's CWD is now: " . getcwd()) + else + execute 'cd ' . dir + call nerdtree#echo('CWD is now: ' . getcwd()) + endif + catch + throw 'NERDTree.PathChangeError: cannot change CWD to ' . dir + endtry +endfunction + +" FUNCTION: Path.Create(fullpath) {{{1 +" +" Factory method. +" +" Creates a path object with the given path. The path is also created on the +" filesystem. If the path already exists, a NERDTree.Path.Exists exception is +" thrown. If any other errors occur, a NERDTree.Path exception is thrown. +" +" Args: +" fullpath: the full filesystem path to the file/dir to create +function! s:Path.Create(fullpath) + "bail if the a:fullpath already exists + if isdirectory(a:fullpath) || filereadable(a:fullpath) + throw "NERDTree.CreatePathError: Directory Exists: '" . a:fullpath . "'" + endif + + try + + "if it ends with a slash, assume its a dir create it + if a:fullpath =~# '\(\\\|\/\)$' + "whack the trailing slash off the end if it exists + let fullpath = substitute(a:fullpath, '\(\\\|\/\)$', '', '') + + call mkdir(fullpath, 'p') + + "assume its a file and create + else + call s:Path.createParentDirectories(a:fullpath) + call writefile([], a:fullpath) + endif + catch + throw "NERDTree.CreatePathError: Could not create path: '" . a:fullpath . "'" + endtry + + return s:Path.New(a:fullpath) +endfunction + +" FUNCTION: Path.copy(dest) {{{1 +" +" Copies the file/dir represented by this Path to the given location +" +" Args: +" dest: the location to copy this dir/file to +function! s:Path.copy(dest) + if !s:Path.CopyingSupported() + throw 'NERDTree.CopyingNotSupportedError: Copying is not supported on this OS' + endif + + call s:Path.createParentDirectories(a:dest) + + if exists('g:NERDTreeCopyCmd') + let cmd_prefix = g:NERDTreeCopyCmd + else + let cmd_prefix = (self.isDirectory ? g:NERDTreeCopyDirCmd : g:NERDTreeCopyFileCmd) + endif + + let cmd = cmd_prefix . ' ' . shellescape(self.str()) . ' ' . shellescape(a:dest) + let success = system(cmd) + if v:shell_error !=# 0 + throw "NERDTree.CopyError: Could not copy '". self.str() ."' to: '" . a:dest . "'" + endif +endfunction + +" FUNCTION: Path.CopyingSupported() {{{1 +" +" returns 1 if copying is supported for this OS +function! s:Path.CopyingSupported() + return exists('g:NERDTreeCopyCmd') || (exists('g:NERDTreeCopyDirCmd') && exists('g:NERDTreeCopyFileCmd')) +endfunction + +" FUNCTION: Path.copyingWillOverwrite(dest) {{{1 +" +" returns 1 if copy this path to the given location will cause files to +" overwritten +" +" Args: +" dest: the location this path will be copied to +function! s:Path.copyingWillOverwrite(dest) + if filereadable(a:dest) + return 1 + endif + + if isdirectory(a:dest) + let path = s:Path.JoinPathStrings(a:dest, self.getLastPathComponent(0)) + if filereadable(path) + return 1 + endif + endif +endfunction + +" FUNCTION: Path.createParentDirectories(path) {{{1 +" +" create parent directories for this path if needed +" without throwing any errors if those directories already exist +" +" Args: +" path: full path of the node whose parent directories may need to be created +function! s:Path.createParentDirectories(path) + let dir_path = fnamemodify(a:path, ':h') + if !isdirectory(dir_path) + call mkdir(dir_path, 'p') + endif +endfunction + +" FUNCTION: Path.delete() {{{1 +" +" Deletes the file or directory represented by this path. +" +" Throws NERDTree.Path.Deletion exceptions +function! s:Path.delete() + if self.isDirectory + + let cmd = g:NERDTreeRemoveDirCmd . self.str({'escape': 1}) + let success = system(cmd) + + if v:shell_error !=# 0 + throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'" + endif + else + if exists('g:NERDTreeRemoveFileCmd') + let cmd = g:NERDTreeRemoveFileCmd . self.str({'escape': 1}) + let success = system(cmd) + else + let success = delete(self.str()) + endif + + if success !=# 0 + throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'" + endif + endif + + "delete all bookmarks for this path + for i in self.bookmarkNames() + let bookmark = g:NERDTreeBookmark.BookmarkFor(i) + call bookmark.delete() + endfor +endfunction + +" FUNCTION: Path.displayString() {{{1 +" +" Returns a string that specifies how the path should be represented as a +" string +function! s:Path.displayString() + if self.cachedDisplayString ==# '' + call self.cacheDisplayString() + endif + + return self.cachedDisplayString +endfunction + +" FUNCTION: Path.edit() {{{1 +function! s:Path.edit() + let l:bufname = self.str({'format': 'Edit'}) + if bufname('%') !=# l:bufname + exec 'edit ' . l:bufname + endif +endfunction + +" FUNCTION: Path.extractDriveLetter(fullpath) {{{1 +" +" If running windows, cache the drive letter for this path +function! s:Path.extractDriveLetter(fullpath) + if nerdtree#runningWindows() + if a:fullpath =~# '^\(\\\\\|\/\/\)' + "For network shares, the 'drive' consists of the first two parts of the path, i.e. \\boxname\share + let self.drive = substitute(a:fullpath, '^\(\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\).*', '\1', '') + let self.drive = substitute(self.drive, '/', '\', 'g') + else + let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '') + endif + else + let self.drive = '' + endif + +endfunction + +" FUNCTION: Path.exists() {{{1 +" return 1 if this path points to a location that is readable or is a directory +function! s:Path.exists() + let p = self.str() + return filereadable(p) || isdirectory(p) +endfunction + +" FUNCTION: Path._escChars() {{{1 +function! s:Path._escChars() + if nerdtree#runningWindows() + return " `\|\"#%&,?()\*^<>$" + endif + + return " \\`\|\"#%&,?()\*^<>[]{}$" +endfunction + +" FUNCTION: Path.getDir() {{{1 +" +" Returns this path if it is a directory, else this paths parent. +" +" Return: +" a Path object +function! s:Path.getDir() + if self.isDirectory + return self + else + return self.getParent() + endif +endfunction + +" FUNCTION: Path.getParent() {{{1 +" +" Returns a new path object for this paths parent +" +" Return: +" a new Path object +function! s:Path.getParent() + if nerdtree#runningWindows() + let path = self.drive . '\' . join(self.pathSegments[0:-2], '\') + else + let path = '/'. join(self.pathSegments[0:-2], '/') + endif + + return s:Path.New(path) +endfunction + +" FUNCTION: Path.getLastPathComponent(dirSlash) {{{1 +" +" Gets the last part of this path. +" +" Args: +" dirSlash: if 1 then a trailing slash will be added to the returned value for +" directory nodes. +function! s:Path.getLastPathComponent(dirSlash) + if empty(self.pathSegments) + return '' + endif + let toReturn = self.pathSegments[-1] + if a:dirSlash && self.isDirectory + let toReturn = toReturn . '/' + endif + return toReturn +endfunction + +" FUNCTION: Path.getSortOrderIndex() {{{1 +" returns the index of the pattern in g:NERDTreeSortOrder that this path matches +function! s:Path.getSortOrderIndex() + let i = 0 + while i < len(g:NERDTreeSortOrder) + if g:NERDTreeSortOrder[i] !~? '\[\[-\?\(timestamp\|size\|extension\)\]\]' && + \ self.getLastPathComponent(1) =~# g:NERDTreeSortOrder[i] + return i + endif + let i = i + 1 + endwhile + + return index(g:NERDTreeSortOrder, '*') +endfunction + +" FUNCTION: Path._splitChunks(path) {{{1 +" returns a list of path chunks +function! s:Path._splitChunks(path) + let chunks = split(a:path, '\(\D\+\|\d\+\)\zs') + let i = 0 + while i < len(chunks) + "convert number literals to numbers + if match(chunks[i], '^\d\+$') ==# 0 + let chunks[i] = str2nr(chunks[i]) + endif + let i = i + 1 + endwhile + return chunks +endfunction + +" FUNCTION: Path.getSortKey() {{{1 +" returns a key used in compare function for sorting +function! s:Path.getSortKey() + if !exists('self._sortKey') || g:NERDTreeSortOrder !=# g:NERDTreeOldSortOrder + " Look for file metadata tags: [[timestamp]], [[extension]], [[size]] + let metadata = [] + for tag in g:NERDTreeSortOrder + if tag =~? '\[\[-\?timestamp\]\]' + let metadata += [self.isDirectory ? 0 : getftime(self.str()) * (tag =~# '-' ? -1 : 1)] + elseif tag =~? '\[\[-\?size\]\]' + let metadata += [self.isDirectory ? 0 : getfsize(self.str()) * (tag =~# '-' ? -1 : 1)] + elseif tag =~? '\[\[extension\]\]' + let extension = matchstr(self.getLastPathComponent(0), '[^.]\+\.\zs[^.]\+$') + let metadata += [self.isDirectory ? '' : (extension ==# '' ? nr2char(str2nr('0x10ffff',16)) : extension)] + endif + endfor + + if g:NERDTreeSortOrder[0] =~# '\[\[.*\]\]' + " Apply tags' sorting first if specified first. + let self._sortKey = metadata + [self.getSortOrderIndex()] + else + " Otherwise, do regex grouping first. + let self._sortKey = [self.getSortOrderIndex()] + metadata + endif + + let path = self.getLastPathComponent(0) + if !g:NERDTreeSortHiddenFirst + let path = substitute(path, '^[._]', '', '') + endif + if !g:NERDTreeCaseSensitiveSort + let path = tolower(path) + endif + + call extend(self._sortKey, (g:NERDTreeNaturalSort ? self._splitChunks(path) : [path])) + endif + return self._sortKey +endfunction + +" FUNCTION: Path.isHiddenUnder(path) {{{1 +function! s:Path.isHiddenUnder(path) + + if !self.isUnder(a:path) + return 0 + endif + + let l:startIndex = len(a:path.pathSegments) + let l:segments = self.pathSegments[l:startIndex : ] + + for l:segment in l:segments + + if l:segment =~# '^\.' + return 1 + endif + endfor + + return 0 +endfunction + +" FUNCTION: Path.isUnixHiddenFile() {{{1 +" check for unix hidden files +function! s:Path.isUnixHiddenFile() + return self.getLastPathComponent(0) =~# '^\.' +endfunction + +" FUNCTION: Path.isUnixHiddenPath() {{{1 +" check for unix path with hidden components +function! s:Path.isUnixHiddenPath() + if self.getLastPathComponent(0) =~# '^\.' + return 1 + else + for segment in self.pathSegments + if segment =~# '^\.' + return 1 + endif + endfor + return 0 + endif +endfunction + +" FUNCTION: Path.ignore(nerdtree) {{{1 +" returns true if this path should be ignored +function! s:Path.ignore(nerdtree) + "filter out the user specified paths to ignore + if a:nerdtree.ui.isIgnoreFilterEnabled() + for i in g:NERDTreeIgnore + if self._ignorePatternMatches(i) + return 1 + endif + endfor + + for l:Callback in g:NERDTree.PathFilters() + let l:Callback = type(l:Callback) ==# type(function('tr')) ? l:Callback : function(l:Callback) + if l:Callback({'path': self, 'nerdtree': a:nerdtree}) + return 1 + endif + endfor + endif + + "dont show hidden files unless instructed to + if !a:nerdtree.ui.getShowHidden() && self.isUnixHiddenFile() + return 1 + endif + + if a:nerdtree.ui.getShowFiles() ==# 0 && self.isDirectory ==# 0 + return 1 + endif + + return 0 +endfunction + +" FUNCTION: Path._ignorePatternMatches(pattern) {{{1 +" returns true if this path matches the given ignore pattern +function! s:Path._ignorePatternMatches(pattern) + let pat = a:pattern + if strpart(pat,len(pat)-8) ==# '[[path]]' + let pat = strpart(pat,0, len(pat)-8) + return self.str() =~# pat + elseif strpart(pat,len(pat)-7) ==# '[[dir]]' + if !self.isDirectory + return 0 + endif + let pat = strpart(pat,0, len(pat)-7) + elseif strpart(pat,len(pat)-8) ==# '[[file]]' + if self.isDirectory + return 0 + endif + let pat = strpart(pat,0, len(pat)-8) + endif + + return self.getLastPathComponent(0) =~# pat +endfunction + +" FUNCTION: Path.isAncestor(path) {{{1 +" return 1 if this path is somewhere above the given path in the filesystem. +" +" a:path should be a dir +function! s:Path.isAncestor(child) + return a:child.isUnder(self) +endfunction + +" FUNCTION: Path.isUnder(path) {{{1 +" return 1 if this path is somewhere under the given path in the filesystem. +function! s:Path.isUnder(parent) + if a:parent.isDirectory ==# 0 + return 0 + endif + if nerdtree#runningWindows() && a:parent.drive !=# self.drive + return 0 + endif + let l:this_count = len(self.pathSegments) + if l:this_count ==# 0 + return 0 + endif + let l:that_count = len(a:parent.pathSegments) + if l:that_count ==# 0 + return 1 + endif + if l:that_count >= l:this_count + return 0 + endif + for i in range(0, l:that_count-1) + if !nerdtree#pathEquals(self.pathSegments[i], a:parent.pathSegments[i]) + return 0 + endif + endfor + return 1 +endfunction + +" FUNCTION: Path.JoinPathStrings(...) {{{1 +function! s:Path.JoinPathStrings(...) + let components = [] + for i in a:000 + let components = extend(components, split(i, '/')) + endfor + return '/' . join(components, '/') +endfunction + +" FUNCTION: Path.equals() {{{1 +" +" Determines whether 2 path objects are "equal". +" They are equal if the paths they represent are the same +" +" Args: +" path: the other path obj to compare this with +function! s:Path.equals(path) + return nerdtree#pathEquals(self.str(), a:path.str()) +endfunction + +" FUNCTION: Path.New(pathStr) {{{1 +function! s:Path.New(pathStr) + let l:newPath = copy(self) + + call l:newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:pathStr)) + + let l:newPath.cachedDisplayString = '' + let l:newPath.flagSet = g:NERDTreeFlagSet.New() + + return l:newPath +endfunction + +" FUNCTION: Path.Resolve() {{{1 +" Invoke the vim resolve() function and return the result +" This is necessary because in some versions of vim resolve() removes trailing +" slashes while in other versions it doesn't. This always removes the trailing +" slash +function! s:Path.Resolve(path) + let tmp = resolve(a:path) + return tmp =~# '.\+/$' ? substitute(tmp, '/$', '', '') : tmp +endfunction + +" FUNCTION: Path.readInfoFromDisk(fullpath) {{{1 +" +" +" Throws NERDTree.Path.InvalidArguments exception. +function! s:Path.readInfoFromDisk(fullpath) + call self.extractDriveLetter(a:fullpath) + + let fullpath = s:Path.WinToUnixPath(a:fullpath) + + if getftype(fullpath) ==# 'fifo' + throw 'NERDTree.InvalidFiletypeError: Cant handle FIFO files: ' . a:fullpath + endif + + let self.pathSegments = filter(split(fullpath, '/'), '!empty(v:val)') + + let self.isReadOnly = 0 + if isdirectory(a:fullpath) + let self.isDirectory = 1 + elseif filereadable(a:fullpath) + let self.isDirectory = 0 + let self.isReadOnly = filewritable(a:fullpath) ==# 0 + else + throw 'NERDTree.InvalidArgumentsError: Invalid path = ' . a:fullpath + endif + + let self.isExecutable = 0 + if !self.isDirectory + let self.isExecutable = getfperm(a:fullpath) =~# 'x' + endif + + "grab the last part of the path (minus the trailing slash) + let lastPathComponent = self.getLastPathComponent(0) + + "get the path to the new node with the parent dir fully resolved + let hardPath = s:Path.Resolve(self.strTrunk()) . '/' . lastPathComponent + + "if the last part of the path is a symlink then flag it as such + let self.isSymLink = (s:Path.Resolve(hardPath) !=# hardPath) + if self.isSymLink + let self.symLinkDest = s:Path.Resolve(fullpath) + + "if the link is a dir then slap a / on the end of its dest + if isdirectory(self.symLinkDest) + + "we always wanna treat MS windows shortcuts as files for + "simplicity + if hardPath !~# '\.lnk$' + + let self.symLinkDest = self.symLinkDest . '/' + endif + endif + endif +endfunction + +" FUNCTION: Path.refresh(nerdtree) {{{1 +function! s:Path.refresh(nerdtree) + call self.readInfoFromDisk(self.str()) + call g:NERDTreePathNotifier.NotifyListeners('refresh', self, a:nerdtree, {}) + call self.cacheDisplayString() +endfunction + +" FUNCTION: Path.refreshFlags(nerdtree) {{{1 +function! s:Path.refreshFlags(nerdtree) + call g:NERDTreePathNotifier.NotifyListeners('refreshFlags', self, a:nerdtree, {}) + call self.cacheDisplayString() +endfunction + +" FUNCTION: Path.rename() {{{1 +" +" Renames this node on the filesystem +function! s:Path.rename(newPath) + if a:newPath ==# '' + throw 'NERDTree.InvalidArgumentsError: Invalid newPath for renaming = '. a:newPath + endif + + call s:Path.createParentDirectories(a:newPath) + + let success = rename(self.str(), a:newPath) + if success !=# 0 + throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath + endif + call self.readInfoFromDisk(a:newPath) + + for i in self.bookmarkNames() + let b = g:NERDTreeBookmark.BookmarkFor(i) + call b.setPath(copy(self)) + endfor + call g:NERDTreeBookmark.Write() +endfunction + +" FUNCTION: Path.str() {{{1 +" Return a string representation of this Path object. +" +" Args: +" This function takes a single dictionary (optional) with keys and values that +" specify how the returned pathname should be formatted. +" +" The dictionary may have the following keys: +" 'format' +" 'escape' +" 'truncateTo' +" +" The 'format' key may have a value of: +" 'Cd' - a string to be used with ":cd" and similar commands +" 'Edit' - a string to be used with ":edit" and similar commands +" 'UI' - a string to be displayed in the NERDTree user interface +" +" The 'escape' key, if specified, will cause the output to be escaped with +" Vim's internal "shellescape()" function. +" +" The 'truncateTo' key shortens the length of the path to that given by the +" value associated with 'truncateTo'. A '<' is prepended. +function! s:Path.str(...) + let options = a:0 ? a:1 : {} + let toReturn = '' + + if has_key(options, 'format') + let format = options['format'] + if has_key(self, '_strFor' . format) + exec 'let toReturn = self._strFor' . format . '()' + else + throw 'NERDTree.UnknownFormatError: unknown format "'. format .'"' + endif + else + let toReturn = self._str() + endif + + if nerdtree#has_opt(options, 'escape') + let toReturn = shellescape(toReturn) + endif + + if has_key(options, 'truncateTo') + let limit = options['truncateTo'] + if strdisplaywidth(toReturn) > limit-1 + while strdisplaywidth(toReturn) > limit-1 && strchars(toReturn) > 0 + let toReturn = substitute(toReturn, '^.', '', '') + endwhile + if len(split(toReturn, '/')) > 1 + let toReturn = ' 0) ? a:1 : {} + + call self.toggleOpen(l:options) + + " Note that we only re-render the NERDTree for this node if we did NOT + " create a new node and render it in a new window or tab. In the latter + " case, rendering the NERDTree for this node could overwrite the text of + " the new NERDTree! + if !has_key(l:options, 'where') || empty(l:options['where']) + call self.getNerdtree().render() + call self.putCursorHere(0, 0) + endif +endfunction + +" FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1 +" Adds the given treenode to the list of children for this node +" +" Args: +" -treenode: the node to add +" -inOrder: 1 if the new node should be inserted in sorted order +function! s:TreeDirNode.addChild(treenode, inOrder) + call add(self.children, a:treenode) + let a:treenode.parent = self + + if a:inOrder + call self.sortChildren() + endif +endfunction + +" FUNCTION: TreeDirNode.close() {{{1 +" Mark this TreeDirNode as closed. +function! s:TreeDirNode.close() + + " Close all directories in this directory node's cascade. This is + " necessary to ensure consistency when cascades are rendered. + for l:dirNode in self.getCascade() + let l:dirNode.isOpen = 0 + endfor +endfunction + +" FUNCTION: TreeDirNode.closeChildren() {{{1 +" Recursively close any directory nodes that are descendants of this node. +function! s:TreeDirNode.closeChildren() + for l:child in self.children + if l:child.path.isDirectory + call l:child.close() + call l:child.closeChildren() + endif + endfor +endfunction + +" FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1 +" Instantiates a new child node for this node with the given path. The new +" nodes parent is set to this node. +" +" Args: +" path: a Path object that this node will represent/contain +" inOrder: 1 if the new node should be inserted in sorted order +" +" Returns: +" the newly created node +function! s:TreeDirNode.createChild(path, inOrder) + let newTreeNode = g:NERDTreeFileNode.New(a:path, self.getNerdtree()) + call self.addChild(newTreeNode, a:inOrder) + return newTreeNode +endfunction + +" FUNCTION: TreeDirNode.displayString() {{{1 +" Assemble and return a string that can represent this TreeDirNode object in +" the NERDTree window. +function! s:TreeDirNode.displayString() + let l:result = '' + + " Build a label that identifies this TreeDirNode. + let l:label = '' + let l:cascade = self.getCascade() + for l:dirNode in l:cascade + let l:next = l:dirNode.path.displayString() + let l:label .= l:label ==# '' ? l:next : substitute(l:next,'^.','','') + endfor + + " Select the appropriate open/closed status indicator symbol. + let l:symbol = (l:cascade[-1].isOpen ? g:NERDTreeDirArrowCollapsible : g:NERDTreeDirArrowExpandable ) + let l:symbol .= (g:NERDTreeDirArrowExpandable ==# '' ? '' : ' ') + let l:flags = l:cascade[-1].path.flagSet.renderToString() + + return l:symbol . l:flags . l:label +endfunction + +" FUNCTION: TreeDirNode.findNode(path) {{{1 +" Will find one of the children (recursively) that has the given path +" +" Args: +" path: a path object +unlet s:TreeDirNode.findNode +function! s:TreeDirNode.findNode(path) + if a:path.equals(self.path) + return self + endif + if nerdtree#caseSensitiveFS() + if stridx(a:path.str(), self.path.str(), 0) ==# -1 + return {} + endif + else + if stridx(tolower(a:path.str()), tolower(self.path.str()), 0) ==# -1 + return {} + endif + endif + + if self.path.isDirectory + for i in self.children + let retVal = i.findNode(a:path) + if retVal !=# {} + return retVal + endif + endfor + endif + return {} +endfunction + +" FUNCTION: TreeDirNode.getCascade() {{{1 +" Return an array of dir nodes (starting from self) that can be cascade opened. +function! s:TreeDirNode.getCascade() + if !self.isCascadable() + return [self] + endif + + let vc = self.getVisibleChildren() + let visChild = vc[0] + + return [self] + visChild.getCascade() +endfunction + +" FUNCTION: TreeDirNode.getCascadeRoot() {{{1 +" Return the first directory node in the cascade in which this directory node +" is rendered. +function! s:TreeDirNode.getCascadeRoot() + + " Don't search above the current NERDTree root node. + if self.isRoot() + return self + endif + + let l:cascadeRoot = self + let l:parent = self.parent + + while !empty(l:parent) && !l:parent.isRoot() + + if index(l:parent.getCascade(), self) ==# -1 + break + endif + + let l:cascadeRoot = l:parent + let l:parent = l:parent.parent + endwhile + + return l:cascadeRoot +endfunction + +" FUNCTION: TreeDirNode.getChildCount() {{{1 +" Returns the number of children this node has +function! s:TreeDirNode.getChildCount() + return len(self.children) +endfunction + +" FUNCTION: TreeDirNode.getChild(path) {{{1 +" Returns child node of this node that has the given path or {} if no such node +" exists. +" +" This function doesnt not recurse into child dir nodes +" +" Args: +" path: a path object +function! s:TreeDirNode.getChild(path) + if stridx(a:path.str(), self.path.str(), 0) ==# -1 + return {} + endif + + let index = self.getChildIndex(a:path) + if index ==# -1 + return {} + else + return self.children[index] + endif + +endfunction + +" FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1 +" returns the child at the given index +" +" Args: +" indx: the index to get the child from +" visible: 1 if only the visible children array should be used, 0 if all the +" children should be searched. +function! s:TreeDirNode.getChildByIndex(indx, visible) + let array_to_search = a:visible? self.getVisibleChildren() : self.children + if a:indx > len(array_to_search) + throw 'NERDTree.InvalidArgumentsError: Index is out of bounds.' + endif + return array_to_search[a:indx] +endfunction + +" FUNCTION: TreeDirNode.getChildIndex(path) {{{1 +" Returns the index of the child node of this node that has the given path or +" -1 if no such node exists. +" +" This function doesnt not recurse into child dir nodes +" +" Args: +" path: a path object +function! s:TreeDirNode.getChildIndex(path) + if stridx(a:path.str(), self.path.str(), 0) ==# -1 + return -1 + endif + + "do a binary search for the child + let a = 0 + let z = self.getChildCount() + while a < z + let mid = (a+z)/2 + let diff = nerdtree#compareNodePaths(a:path, self.children[mid].path) + + if diff ==# -1 + let z = mid + elseif diff ==# 1 + let a = mid+1 + else + return mid + endif + endwhile + return -1 +endfunction + +" FUNCTION: TreeDirNode.getDirChildren() {{{1 +" Return a list of all child nodes from 'self.children' that are of type +" TreeDirNode. This function supports http://github.com/scrooloose/nerdtree-project-plugin.git. +function! s:TreeDirNode.getDirChildren() + return filter(copy(self.children), 'v:val.path.isDirectory ==# 1') +endfunction + +" FUNCTION: TreeDirNode._glob(pattern, all) {{{1 +" Return a list of strings naming the descendants of the directory in this +" TreeDirNode object that match the specified glob pattern. +" +" Args: +" pattern: (string) the glob pattern to apply +" all: (0 or 1) if 1, include '.' and '..' if they match 'pattern'; if 0, +" always exclude them +" +" Note: If the pathnames in the result list are below the working directory, +" they are returned as pathnames relative to that directory. This is because +" this function, internally, attempts to obey 'wildignore' rules that use +" relative paths. +function! s:TreeDirNode._glob(pattern, all) + + " Construct a path specification such that globpath() will return + " relative pathnames, if possible. + if self.path.str() ==# getcwd() + let l:pathSpec = ',' + else + let l:pathSpec = escape(fnamemodify(self.path.str({'format': 'Glob'}), ':.'), ',') + + if nerdtree#runningWindows() + let l:pathSpec = substitute(l:pathSpec, "\\[\\(.*\\]\\)", "[[]\\1", "g") + endif + + " On Windows, the drive letter may be removed by "fnamemodify()". + if nerdtree#runningWindows() && l:pathSpec[0] == nerdtree#slash() + let l:pathSpec = self.path.drive . l:pathSpec + endif + endif + + let l:globList = [] + + " See ':h version7.txt' and ':h version8.txt' for details on the + " development of the glob() and globpath() functions. + if v:version > 704 || (v:version ==# 704 && has('patch654')) + let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1, 0) + elseif v:version ==# 704 && has('patch279') + let l:globList = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore, 1) + elseif v:version > 702 || (v:version ==# 702 && has('patch051')) + let l:globString = globpath(l:pathSpec, a:pattern, !g:NERDTreeRespectWildIgnore) + let l:globList = split(l:globString, "\n") + else + let l:globString = globpath(l:pathSpec, a:pattern) + let l:globList = split(l:globString, "\n") + endif + + " If a:all is false, filter '.' and '..' from the output. + if !a:all + let l:toRemove = [] + + for l:file in l:globList + let l:tail = fnamemodify(l:file, ':t') + + " If l:file has a trailing slash, then its :tail will be ''. Use + " :h to drop the slash and the empty string after it; then use :t + " to get the directory name. + if l:tail ==# '' + let l:tail = fnamemodify(l:file, ':h:t') + endif + + if l:tail ==# '.' || l:tail ==# '..' + call add(l:toRemove, l:file) + if len(l:toRemove) ==# 2 + break + endif + endif + endfor + + for l:file in l:toRemove + call remove(l:globList, index(l:globList, l:file)) + endfor + endif + + return l:globList +endfunction + +" FUNCTION: TreeDirNode.GetSelected() {{{1 +" Returns the current node if it is a dir node, or else returns the current +" nodes parent +unlet s:TreeDirNode.GetSelected +function! s:TreeDirNode.GetSelected() + let currentDir = g:NERDTreeFileNode.GetSelected() + if currentDir !=# {} && !currentDir.isRoot() + if currentDir.path.isDirectory ==# 0 + let currentDir = currentDir.parent + endif + endif + return currentDir +endfunction + +" FUNCTION: TreeDirNode.getVisibleChildCount() {{{1 +" Returns the number of visible children this node has +function! s:TreeDirNode.getVisibleChildCount() + return len(self.getVisibleChildren()) +endfunction + +" FUNCTION: TreeDirNode.getVisibleChildren() {{{1 +" Returns a list of children to display for this node, in the correct order +" +" Return: +" an array of treenodes +function! s:TreeDirNode.getVisibleChildren() + let toReturn = [] + for i in self.children + if i.path.ignore(self.getNerdtree()) ==# 0 + call add(toReturn, i) + endif + endfor + return toReturn +endfunction + +" FUNCTION: TreeDirNode.hasVisibleChildren() {{{1 +" returns 1 if this node has any childre, 0 otherwise.. +function! s:TreeDirNode.hasVisibleChildren() + return self.getVisibleChildCount() !=# 0 +endfunction + +" FUNCTION: TreeDirNode.isCascadable() {{{1 +" true if this dir has only one visible child that is also a dir +" false if this dir is bookmarked or symlinked. Why? Two reasons: +" 1. If cascaded, we don't know which dir is bookmarked or is a symlink. +" 2. If the parent is a symlink or is bookmarked, you end up with unparsable +" text, and NERDTree cannot get the path of any child node. +" Also, return false if this directory is the tree root, which should never be +" part of a cascade. +function! s:TreeDirNode.isCascadable() + if g:NERDTreeCascadeSingleChildDir ==# 0 + return 0 + endif + + if self.isRoot() + return 0 + endif + + if self.path.isSymLink + return 0 + endif + + for i in g:NERDTreeBookmark.Bookmarks() + if i.path.equals(self.path) + return 0 + endif + endfor + + let c = self.getVisibleChildren() + return len(c) ==# 1 && c[0].path.isDirectory +endfunction + +" FUNCTION: TreeDirNode._initChildren() {{{1 +" Removes all childen from this node and re-reads them +" +" Args: +" silent: 1 if the function should not echo any 'please wait' messages for +" large directories +" +" Return: the number of child nodes read +function! s:TreeDirNode._initChildren(silent) + "remove all the current child nodes + let self.children = [] + + let files = self._glob('*', 1) + self._glob('.*', 0) + + if !a:silent && len(files) > g:NERDTreeNotificationThreshold + call nerdtree#echo('Please wait, caching a large dir ...') + endif + + let invalidFilesFound = 0 + let invalidFiles = [] + for i in files + try + let path = g:NERDTreePath.New(i) + call self.createChild(path, 0) + call g:NERDTreePathNotifier.NotifyListeners('init', path, self.getNerdtree(), {}) + catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ + let invalidFilesFound += 1 + let invalidFiles += [i] + endtry + endfor + + let g:NERDTreeOldSortOrder = g:NERDTreeSortOrder + call self.sortChildren() + + call nerdtree#echo('') + + if invalidFilesFound + call nerdtree#echoWarning(invalidFilesFound . ' Invalid file(s): ' . join(invalidFiles, ', ')) + endif + return self.getChildCount() +endfunction + +" FUNCTION: TreeDirNode.New(path, nerdtree) {{{1 +" Return a new TreeDirNode object with the given path and parent. +" +" Args: +" path: dir that the node represents +" nerdtree: the tree the node belongs to +function! s:TreeDirNode.New(path, nerdtree) + if a:path.isDirectory !=# 1 + throw 'NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object.' + endif + + let newTreeNode = copy(self) + let newTreeNode.path = a:path + + let newTreeNode.isOpen = 0 + let newTreeNode.children = [] + + let newTreeNode.parent = {} + let newTreeNode._nerdtree = a:nerdtree + + return newTreeNode +endfunction + +" FUNCTION: TreeDirNode.open([options]) {{{1 +" Open this directory node in the current tree or elsewhere if special options +" are provided. Return 0 if options were processed. Otherwise, return the +" number of new cached nodes. +function! s:TreeDirNode.open(...) + let l:options = a:0 ? a:1 : {} + + " If special options were specified, process them and return. + if has_key(l:options, 'where') && !empty(l:options['where']) + let l:opener = g:NERDTreeOpener.New(self.path, l:options) + call l:opener.open(self) + return 0 + endif + + " Open any ancestors of this node that render within the same cascade. + let l:parent = self.parent + while !empty(l:parent) && !l:parent.isRoot() + if index(l:parent.getCascade(), self) >= 0 + let l:parent.isOpen = 1 + let l:parent = l:parent.parent + else + break + endif + endwhile + + let self.isOpen = 1 + + let l:numChildrenCached = 0 + if empty(self.children) + let l:numChildrenCached = self._initChildren(0) + endif + + return l:numChildrenCached +endfunction + +" FUNCTION: TreeDirNode.openAlong([opts]) {{{1 +" recursive open the dir if it has only one directory child. +" +" return the level of opened directories. +function! s:TreeDirNode.openAlong(...) + let opts = a:0 ? a:1 : {} + let level = 0 + + let node = self + while node.path.isDirectory + call node.open(opts) + let level += 1 + if node.getVisibleChildCount() ==# 1 + let node = node.getChildByIndex(0, 1) + else + break + endif + endwhile + return level +endfunction + +" FUNCTION: TreeDirNode.openExplorer() {{{1 +" Open an explorer window for this node in the previous window. The explorer +" can be a NERDTree window or a netrw window. +function! s:TreeDirNode.openExplorer() + execute 'wincmd p' + execute 'edit '.self.path.str({'format':'Edit'}) +endfunction + +" FUNCTION: TreeDirNode.openInNewTab(options) {{{1 +unlet s:TreeDirNode.openInNewTab +function! s:TreeDirNode.openInNewTab(options) + call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead') + call self.open({'where': 't'}) +endfunction + +" FUNCTION: TreeDirNode._openInNewTab() {{{1 +function! s:TreeDirNode._openInNewTab() + tabnew + call g:NERDTreeCreator.CreateTabTree(self.path.str()) +endfunction + +" FUNCTION: TreeDirNode.openRecursively() {{{1 +" Open this directory node and any descendant directory nodes whose pathnames +" are not ignored. +function! s:TreeDirNode.openRecursively() + silent call self.open() + + for l:child in self.children + if l:child.path.isDirectory && !l:child.path.ignore(l:child.getNerdtree()) + call l:child.openRecursively() + endif + endfor +endfunction + +" FUNCTION: TreeDirNode.refresh() {{{1 +function! s:TreeDirNode.refresh() + call self.path.refresh(self.getNerdtree()) + + "if this node was ever opened, refresh its children + if self.isOpen || !empty(self.children) + let files = self._glob('*', 1) + self._glob('.*', 0) + let newChildNodes = [] + let invalidFilesFound = 0 + let invalidFiles = [] + for i in files + try + "create a new path and see if it exists in this nodes children + let path = g:NERDTreePath.New(i) + let newNode = self.getChild(path) + if newNode !=# {} && path.str() ==# newNode.path.str() + call newNode.refresh() + call add(newChildNodes, newNode) + + "the node doesnt exist so create it + else + let newNode = g:NERDTreeFileNode.New(path, self.getNerdtree()) + let newNode.parent = self + call add(newChildNodes, newNode) + endif + catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ + let invalidFilesFound += 1 + let invalidFiles += [i] + endtry + endfor + + "swap this nodes children out for the children we just read/refreshed + let self.children = newChildNodes + call self.sortChildren() + + if invalidFilesFound + call nerdtree#echoWarning(invalidFilesFound . ' Invalid file(s): ' . join(invalidFiles, ', ')) + endif + endif +endfunction + +" FUNCTION: TreeDirNode.refreshFlags() {{{1 +unlet s:TreeDirNode.refreshFlags +function! s:TreeDirNode.refreshFlags() + call self.path.refreshFlags(self.getNerdtree()) + for i in self.children + call i.refreshFlags() + endfor +endfunction + +" FUNCTION: TreeDirNode.refreshDirFlags() {{{1 +function! s:TreeDirNode.refreshDirFlags() + call self.path.refreshFlags(self.getNerdtree()) +endfunction + +" FUNCTION: TreeDirNode.reveal(path) {{{1 +" reveal the given path, i.e. cache and open all treenodes needed to display it +" in the UI +" Returns the revealed node +function! s:TreeDirNode.reveal(path, ...) + let opts = a:0 ? a:1 : {} + + if !a:path.isUnder(self.path) + throw 'NERDTree.InvalidArgumentsError: ' . a:path.str() . ' should be under ' . self.path.str() + endif + + call self.open() + + if self.path.equals(a:path.getParent()) + let n = self.findNode(a:path) + " We may be looking for a newly-saved file that isn't in the tree yet. + if n ==# {} + call self.refresh() + let n = self.findNode(a:path) + endif + if has_key(opts, 'open') + call n.open() + endif + return n + endif + + let p = a:path + while !p.getParent().equals(self.path) + let p = p.getParent() + endwhile + + let n = self.findNode(p) + return n.reveal(a:path, opts) +endfunction + +" FUNCTION: TreeDirNode.removeChild(treenode) {{{1 +" Remove the given treenode from self.children. +" Throws NERDTree.ChildNotFoundError if the node is not found. +" +" Args: +" treenode: the node object to remove +function! s:TreeDirNode.removeChild(treenode) + for i in range(0, self.getChildCount()-1) + if self.children[i].equals(a:treenode) + call remove(self.children, i) + return + endif + endfor + + throw 'NERDTree.ChildNotFoundError: child node was not found' +endfunction + +" FUNCTION: TreeDirNode.sortChildren() {{{1 +" Sort self.children by alphabetical order and directory priority. +function! s:TreeDirNode.sortChildren() + if count(g:NERDTreeSortOrder, '*') < 1 + call add(g:NERDTreeSortOrder, '*') + endif + let CompareFunc = function('nerdtree#compareNodes') + call sort(self.children, CompareFunc) + let g:NERDTreeOldSortOrder = g:NERDTreeSortOrder +endfunction + +" FUNCTION: TreeDirNode.toggleOpen([options]) {{{1 +" Opens this directory if it is closed and vice versa +function! s:TreeDirNode.toggleOpen(...) + let opts = a:0 ? a:1 : {} + if self.isOpen ==# 1 + call self.close() + else + if g:NERDTreeCascadeOpenSingleChildDir ==# 0 + call self.open(opts) + else + call self.openAlong(opts) + endif + endif +endfunction + +" FUNCTION: TreeDirNode.transplantChild(newNode) {{{1 +" Replaces the child of this with the given node (where the child node's full +" path matches a:newNode's fullpath). The search for the matching node is +" non-recursive +" +" Arg: +" newNode: the node to graft into the tree +function! s:TreeDirNode.transplantChild(newNode) + for i in range(0, self.getChildCount()-1) + if self.children[i].equals(a:newNode) + let self.children[i] = a:newNode + let a:newNode.parent = self + break + endif + endfor +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/tree_file_node.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/tree_file_node.vim new file mode 100644 index 0000000..434b3e4 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/tree_file_node.vim @@ -0,0 +1,349 @@ +" ============================================================================ +" CLASS: TreeFileNode +" +" This class is the parent of the TreeDirNode class and is the 'Component' +" part of the composite design pattern between the NERDTree node classes. +" ============================================================================ + + +let s:TreeFileNode = {} +let g:NERDTreeFileNode = s:TreeFileNode + +" FUNCTION: TreeFileNode.activate(...) {{{1 +function! s:TreeFileNode.activate(...) + call self.open(a:0 ? a:1 : {}) +endfunction + +" FUNCTION: TreeFileNode.bookmark(name) {{{1 +" bookmark this node with a:name +function! s:TreeFileNode.bookmark(name) + + " if a bookmark exists with the same name and the node is cached then save + " it so we can update its display string + let oldMarkedNode = {} + try + let oldMarkedNode = g:NERDTreeBookmark.GetNodeForName(a:name, 1, self.getNerdtree()) + catch /^NERDTree.BookmarkNotFoundError/ + catch /^NERDTree.BookmarkedNodeNotFoundError/ + endtry + + call g:NERDTreeBookmark.AddBookmark(a:name, self.path) + call self.path.cacheDisplayString() + call g:NERDTreeBookmark.Write() + + if !empty(oldMarkedNode) + call oldMarkedNode.path.cacheDisplayString() + endif +endfunction + +" FUNCTION: TreeFileNode.cacheParent() {{{1 +" initializes self.parent if it isnt already +function! s:TreeFileNode.cacheParent() + if empty(self.parent) + let parentPath = self.path.getParent() + if parentPath.equals(self.path) + throw 'NERDTree.CannotCacheParentError: already at root' + endif + let self.parent = s:TreeFileNode.New(parentPath, self.getNerdtree()) + endif +endfunction + +" FUNCTION: TreeFileNode.clearBookmarks() {{{1 +function! s:TreeFileNode.clearBookmarks() + for i in g:NERDTreeBookmark.Bookmarks() + if i.path.equals(self.path) + call i.delete() + end + endfor + call self.path.cacheDisplayString() +endfunction + +" FUNCTION: TreeFileNode.copy(dest) {{{1 +function! s:TreeFileNode.copy(dest) + call self.path.copy(a:dest) + let newPath = g:NERDTreePath.New(a:dest) + let parent = self.getNerdtree().root.findNode(newPath.getParent()) + if !empty(parent) + call parent.refresh() + return parent.findNode(newPath) + else + return {} + endif +endfunction + +" FUNCTION: TreeFileNode.delete {{{1 +" Removes this node from the tree and calls the Delete method for its path obj +function! s:TreeFileNode.delete() + call self.path.delete() + call self.parent.removeChild(self) +endfunction + +" FUNCTION: TreeFileNode.displayString() {{{1 +" +" Returns a string that specifies how the node should be represented as a +" string +" +" Return: +" a string that can be used in the view to represent this node +function! s:TreeFileNode.displayString() + return self.path.flagSet.renderToString() . self.path.displayString() +endfunction + +" FUNCTION: TreeFileNode.equals(treenode) {{{1 +" +" Compares this treenode to the input treenode and returns 1 if they are the +" same node. +" +" Use this method instead of == because sometimes when the treenodes contain +" many children, vim seg faults when doing == +" +" Args: +" treenode: the other treenode to compare to +function! s:TreeFileNode.equals(treenode) + return self.path.str() ==# a:treenode.path.str() +endfunction + +" FUNCTION: TreeFileNode.findNode(path) {{{1 +" Returns self if this node.path.Equals the given path. +" Returns {} if not equal. +" +" Args: +" path: the path object to compare against +function! s:TreeFileNode.findNode(path) + if a:path.equals(self.path) + return self + endif + return {} +endfunction + +" FUNCTION: TreeFileNode.findSibling(direction) {{{1 +" Find the next or previous sibling of this node. +" +" Args: +" direction: 0 for previous, 1 for next +" +" Return: +" The next/previous TreeFileNode object or an empty dictionary if not found. +function! s:TreeFileNode.findSibling(direction) + + " There can be no siblings if there is no parent. + if empty(self.parent) + return {} + endif + + let l:nodeIndex = self.parent.getChildIndex(self.path) + + if l:nodeIndex == -1 + return {} + endif + + " Get the next index to begin the search. + let l:nodeIndex += a:direction ? 1 : -1 + + while 0 <= l:nodeIndex && l:nodeIndex < self.parent.getChildCount() + + " Return the next node if it is not ignored. + if !self.parent.children[l:nodeIndex].path.ignore(self.getNerdtree()) + return self.parent.children[l:nodeIndex] + endif + + let l:nodeIndex += a:direction ? 1 : -1 + endwhile + + return {} +endfunction + +" FUNCTION: TreeFileNode.getNerdtree(){{{1 +function! s:TreeFileNode.getNerdtree() + return self._nerdtree +endfunction + +" FUNCTION: TreeFileNode.GetRootForTab(){{{1 +" get the root node for this tab +function! s:TreeFileNode.GetRootForTab() + if g:NERDTree.ExistsForTab() + return getbufvar(t:NERDTreeBufName, 'NERDTree').root + end + return {} +endfunction + +" FUNCTION: TreeFileNode.GetSelected() {{{1 +" If the cursor is currently positioned on a tree node, return the node. +" Otherwise, return the empty dictionary. +function! s:TreeFileNode.GetSelected() + + try + let l:path = b:NERDTree.ui.getPath(line('.')) + + if empty(l:path) + return {} + endif + + return b:NERDTree.root.findNode(l:path) + catch + return {} + endtry +endfunction + +" FUNCTION: TreeFileNode.isVisible() {{{1 +" returns 1 if this node should be visible according to the tree filters and +" hidden file filters (and their on/off status) +function! s:TreeFileNode.isVisible() + return !self.path.ignore(self.getNerdtree()) +endfunction + +" FUNCTION: TreeFileNode.isRoot() {{{1 +function! s:TreeFileNode.isRoot() + if !g:NERDTree.ExistsForBuf() + throw 'NERDTree.NoTreeError: No tree exists for the current buffer' + endif + + return self.equals(self.getNerdtree().root) +endfunction + +" FUNCTION: TreeFileNode.New(path, nerdtree) {{{1 +" Returns a new TreeNode object with the given path and parent +" +" Args: +" path: file/dir that the node represents +" nerdtree: the tree the node belongs to +function! s:TreeFileNode.New(path, nerdtree) + if a:path.isDirectory + return g:NERDTreeDirNode.New(a:path, a:nerdtree) + else + let newTreeNode = copy(self) + let newTreeNode.path = a:path + let newTreeNode.parent = {} + let newTreeNode._nerdtree = a:nerdtree + return newTreeNode + endif +endfunction + +" FUNCTION: TreeFileNode.open() {{{1 +function! s:TreeFileNode.open(...) + let opts = a:0 ? a:1 : {} + let opener = g:NERDTreeOpener.New(self.path, opts) + call opener.open(self) +endfunction + +" FUNCTION: TreeFileNode.openSplit() {{{1 +" Open this node in a new window +function! s:TreeFileNode.openSplit() + call nerdtree#deprecated('TreeFileNode.openSplit', 'is deprecated, use .open() instead.') + call self.open({'where': 'h'}) +endfunction + +" FUNCTION: TreeFileNode.openVSplit() {{{1 +" Open this node in a new vertical window +function! s:TreeFileNode.openVSplit() + call nerdtree#deprecated('TreeFileNode.openVSplit', 'is deprecated, use .open() instead.') + call self.open({'where': 'v'}) +endfunction + +" FUNCTION: TreeFileNode.openInNewTab(options) {{{1 +function! s:TreeFileNode.openInNewTab(options) + call nerdtree#deprecated('TreeFileNode.openinNewTab', 'is deprecated, use .open() instead.') + call self.open(extend({'where': 't'}, a:options)) +endfunction + +" FUNCTION: TreeFileNode.openExplorer() +function! s:TreeFileNode.openExplorer() + execute 'wincmd p' + execute 'edit '.self.path.getParent().str({'format':'Edit'}) +endfunction + +" FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{1 +" Places the cursor on the line number this node is rendered on +" +" Args: +" isJump: 1 if this cursor movement should be counted as a jump by vim +" recurseUpward: try to put the cursor on the parent if the this node isnt +" visible +function! s:TreeFileNode.putCursorHere(isJump, recurseUpward) + let ln = self.getNerdtree().ui.getLineNum(self) + if ln != -1 + if a:isJump + mark ' + endif + call cursor(ln, col('.')) + else + if a:recurseUpward + let node = self + while node != {} && self.getNerdtree().ui.getLineNum(node) ==# -1 + let node = node.parent + call node.open() + endwhile + call self._nerdtree.render() + call node.putCursorHere(a:isJump, 0) + endif + endif +endfunction + +" FUNCTION: TreeFileNode.refresh() {{{1 +function! s:TreeFileNode.refresh() + call self.path.refresh(self.getNerdtree()) +endfunction + +" FUNCTION: TreeFileNode.refreshFlags() {{{1 +function! s:TreeFileNode.refreshFlags() + call self.path.refreshFlags(self.getNerdtree()) +endfunction + +" FUNCTION: TreeFileNode.rename() {{{1 +" Calls the rename method for this nodes path obj +function! s:TreeFileNode.rename(newName) + let newName = substitute(a:newName, '\(\\\|\/\)$', '', '') + call self.path.rename(newName) + call self.parent.removeChild(self) + + let parentPath = self.path.getParent() + let newParent = self.getNerdtree().root.findNode(parentPath) + + if newParent != {} + call newParent.createChild(self.path, 1) + call newParent.refresh() + endif +endfunction + +" FUNCTION: TreeFileNode.renderToString {{{1 +" returns a string representation for this tree to be rendered in the view +function! s:TreeFileNode.renderToString() + return self._renderToString(0, 0) +endfunction + +" Args: +" depth: the current depth in the tree for this call +" drawText: 1 if we should actually draw the line for this node (if 0 then the +" child nodes are rendered only) +" for each depth in the tree +function! s:TreeFileNode._renderToString(depth, drawText) + let output = '' + if a:drawText ==# 1 + + let treeParts = repeat(' ', a:depth - 1) + let treeParts .= (self.path.isDirectory || g:NERDTreeDirArrowExpandable ==# '' ? '' : ' ') + + let line = treeParts . self.displayString() + let output = output . line . "\n" + endif + + " if the node is an open dir, draw its children + if self.path.isDirectory ==# 1 && self.isOpen ==# 1 + + let childNodesToDraw = self.getVisibleChildren() + + if self.isCascadable() && a:depth > 0 + + let output = output . childNodesToDraw[0]._renderToString(a:depth, 0) + + elseif len(childNodesToDraw) > 0 + for i in childNodesToDraw + let output = output . i._renderToString(a:depth + 1, 1) + endfor + endif + endif + + return output +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/lib/nerdtree/ui.vim b/nvim/.vim/plugged/nerdtree/lib/nerdtree/ui.vim new file mode 100644 index 0000000..3ffcaca --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/lib/nerdtree/ui.vim @@ -0,0 +1,558 @@ +" ============================================================================ +" CLASS: UI +" ============================================================================ + + +let s:UI = {} +let g:NERDTreeUI = s:UI + +" FUNCTION: s:UI.centerView() {{{1 +" centers the nerd tree window around the cursor (provided the nerd tree +" options permit) +function! s:UI.centerView() + if g:NERDTreeAutoCenter + let current_line = winline() + let lines_to_top = current_line + let lines_to_bottom = winheight(g:NERDTree.GetWinNum()) - current_line + if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold + normal! zz + endif + endif +endfunction + +" FUNCTION: s:UI._dumpHelp {{{1 +" prints out the quick help +function! s:UI._dumpHelp() + if self.getShowHelp() + let help = "\" NERDTree (" . nerdtree#version() . ") quickhelp~\n" + let help .= "\" ============================\n" + let help .= "\" File node mappings~\n" + let help .= '" '. (g:NERDTreeMouseMode ==# 3 ? 'single' : 'double') ."-click,\n" + if self.nerdtree.isTabTree() + let help .= '" '. g:NERDTreeMapActivateNode .": open in prev window\n" + else + let help .= '" '. g:NERDTreeMapActivateNode .": open in current window\n" + endif + if self.nerdtree.isTabTree() + let help .= '" '. g:NERDTreeMapPreview .": preview\n" + endif + let help .= '" '. g:NERDTreeMapOpenInTab.": open in new tab\n" + let help .= '" '. g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" + let help .= "\" middle-click,\n" + let help .= '" '. g:NERDTreeMapOpenSplit .": open split\n" + let help .= '" '. g:NERDTreeMapPreviewSplit .": preview split\n" + let help .= '" '. g:NERDTreeMapOpenVSplit .": open vsplit\n" + let help .= '" '. g:NERDTreeMapPreviewVSplit .": preview vsplit\n" + let help .= '" '. g:NERDTreeMapCustomOpen .": custom open\n" + + let help .= "\"\n\" ----------------------------\n" + let help .= "\" Directory node mappings~\n" + let help .= '" '. (g:NERDTreeMouseMode ==# 1 ? 'double' : 'single') ."-click,\n" + let help .= '" '. g:NERDTreeMapActivateNode .": open & close node\n" + let help .= '" '. g:NERDTreeMapOpenRecursively .": recursively open node\n" + let help .= '" '. g:NERDTreeMapOpenInTab.": open in new tab\n" + let help .= '" '. g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" + let help .= '" '. g:NERDTreeMapCustomOpen .": custom open\n" + let help .= '" '. g:NERDTreeMapCloseDir .": close parent of node\n" + let help .= '" '. g:NERDTreeMapCloseChildren .": close all child nodes of\n" + let help .= "\" current node recursively\n" + let help .= "\" middle-click,\n" + let help .= '" '. g:NERDTreeMapOpenExpl.": explore selected dir\n" + + let help .= "\"\n\" ----------------------------\n" + let help .= "\" Bookmark table mappings~\n" + let help .= "\" double-click,\n" + let help .= '" '. g:NERDTreeMapJumpBookmarks .": jump to bookmark table\n" + let help .= '" '. g:NERDTreeMapActivateNode .": open bookmark\n" + let help .= '" '. g:NERDTreeMapPreview .": preview file\n" + let help .= '" '. g:NERDTreeMapPreview .": find dir in tree\n" + let help .= '" '. g:NERDTreeMapOpenInTab.": open in new tab\n" + let help .= '" '. g:NERDTreeMapOpenInTabSilent .": open in new tab silently\n" + let help .= '" '. g:NERDTreeMapOpenSplit .": open split\n" + let help .= '" '. g:NERDTreeMapPreviewSplit .": preview split\n" + let help .= '" '. g:NERDTreeMapOpenVSplit .": open vsplit\n" + let help .= '" '. g:NERDTreeMapPreviewVSplit .": preview vsplit\n" + let help .= '" '. g:NERDTreeMapCustomOpen .": custom open\n" + let help .= '" '. g:NERDTreeMapDeleteBookmark .": delete bookmark\n" + + let help .= "\"\n\" ----------------------------\n" + let help .= "\" Tree navigation mappings~\n" + let help .= '" '. g:NERDTreeMapJumpRoot .": go to root\n" + let help .= '" '. g:NERDTreeMapJumpParent .": go to parent\n" + let help .= '" '. g:NERDTreeMapJumpFirstChild .": go to first child\n" + let help .= '" '. g:NERDTreeMapJumpLastChild .": go to last child\n" + let help .= '" '. g:NERDTreeMapJumpNextSibling .": go to next sibling\n" + let help .= '" '. g:NERDTreeMapJumpPrevSibling .": go to prev sibling\n" + + let help .= "\"\n\" ----------------------------\n" + let help .= "\" Filesystem mappings~\n" + let help .= '" '. g:NERDTreeMapChangeRoot .": change tree root to the\n" + let help .= "\" selected dir\n" + let help .= '" '. g:NERDTreeMapUpdir .": move tree root up a dir\n" + let help .= '" '. g:NERDTreeMapUpdirKeepOpen .": move tree root up a dir\n" + let help .= "\" but leave old root open\n" + let help .= '" '. g:NERDTreeMapRefresh .": refresh cursor dir\n" + let help .= '" '. g:NERDTreeMapRefreshRoot .": refresh current root\n" + let help .= '" '. g:NERDTreeMapMenu .": Show menu\n" + let help .= '" '. g:NERDTreeMapChdir .":change the CWD to the\n" + let help .= "\" selected dir\n" + let help .= '" '. g:NERDTreeMapCWD .":change tree root to CWD\n" + + let help .= "\"\n\" ----------------------------\n" + let help .= "\" Tree filtering mappings~\n" + let help .= '" '. g:NERDTreeMapToggleHidden .': hidden files (' . (self.getShowHidden() ? 'on' : 'off') . ")\n" + let help .= '" '. g:NERDTreeMapToggleFilters .': file filters (' . (self.isIgnoreFilterEnabled() ? 'on' : 'off') . ")\n" + let help .= '" '. g:NERDTreeMapToggleFiles .': files (' . (self.getShowFiles() ? 'on' : 'off') . ")\n" + let help .= '" '. g:NERDTreeMapToggleBookmarks .': bookmarks (' . (self.getShowBookmarks() ? 'on' : 'off') . ")\n" + let help .= '" '. g:NERDTreeMapToggleFileLines .': files lines (' . (self.getShowFileLines() ? 'on' : 'off') . ")\n" + + " add quickhelp entries for each custom key map + let help .= "\"\n\" ----------------------------\n" + let help .= "\" Custom mappings~\n" + for i in g:NERDTreeKeyMap.All() + if !empty(i.quickhelpText) + let help .= '" '. i.key .': '. i.quickhelpText ."\n" + endif + endfor + + let help .= "\"\n\" ----------------------------\n" + let help .= "\" Other mappings~\n" + let help .= '" '. g:NERDTreeMapQuit .": Close the NERDTree window\n" + let help .= '" '. g:NERDTreeMapToggleZoom .": Zoom (maximize-minimize)\n" + let help .= "\" the NERDTree window\n" + let help .= '" '. g:NERDTreeMapHelp .": toggle help\n" + let help .= "\"\n\" ----------------------------\n" + let help .= "\" Bookmark commands~\n" + let help .= "\" :Bookmark []\n" + let help .= "\" :BookmarkToRoot \n" + let help .= "\" :RevealBookmark \n" + let help .= "\" :OpenBookmark \n" + let help .= "\" :ClearBookmarks []\n" + let help .= "\" :ClearAllBookmarks\n" + let help .= "\" :ReadBookmarks\n" + let help .= "\" :WriteBookmarks\n" + let help .= "\" :EditBookmarks\n" + silent! put =help + elseif !self.isMinimal() + let help ='" Press '. g:NERDTreeMapHelp ." for help\n" + silent! put =help + endif +endfunction + + +" FUNCTION: s:UI.new(nerdtree) {{{1 +function! s:UI.New(nerdtree) + let newObj = copy(self) + let newObj.nerdtree = a:nerdtree + let newObj._showHelp = 0 + let newObj._ignoreEnabled = 1 + let newObj._showFiles = g:NERDTreeShowFiles + let newObj._showHidden = g:NERDTreeShowHidden + let newObj._showBookmarks = g:NERDTreeShowBookmarks + let newObj._showFileLines = g:NERDTreeFileLines + + return newObj +endfunction + +" FUNCTION: s:UI.getPath(ln) {{{1 +" Return the Path object for the node that is rendered on the given line +" number. If the 'up a dir' line is selected, return the Path object for +" the parent of the root. Return the empty dictionary if the given line +" does not reference a tree node. +function! s:UI.getPath(ln) + let line = getline(a:ln) + + let rootLine = self.getRootLineNum() + + if a:ln ==# rootLine + return self.nerdtree.root.path + endif + + if line ==# s:UI.UpDirLine() + return self.nerdtree.root.path.getParent() + endif + + if a:ln < rootLine + return {} + endif + + let indent = self._indentLevelFor(line) + + " remove the tree parts and the leading space + let curFile = self._stripMarkup(line) + + let dir = '' + let lnum = a:ln + while lnum > 0 + let lnum = lnum - 1 + let curLine = getline(lnum) + let curLineStripped = self._stripMarkup(curLine) + + " have we reached the top of the tree? + if lnum ==# rootLine + let dir = self.nerdtree.root.path.str({'format': 'UI'}) . dir + break + endif + if curLineStripped =~# '/$' + let lpindent = self._indentLevelFor(curLine) + if lpindent < indent + let indent = indent - 1 + + let dir = substitute (curLineStripped,'^\\', '', '') . dir + continue + endif + endif + endwhile + let curFile = self.nerdtree.root.path.drive . dir . curFile + let toReturn = g:NERDTreePath.New(curFile) + return toReturn +endfunction + +" FUNCTION: s:UI.getLineNum(node) {{{1 +" Return the line number where the given node is rendered. Return -1 if the +" given node is not visible. +function! s:UI.getLineNum(node) + + if a:node.isRoot() + return self.getRootLineNum() + endif + + let l:pathComponents = [substitute(self.nerdtree.root.path.str({'format': 'UI'}), '/\s*$', '', '')] + let l:currentPathComponent = 1 + + let l:fullPath = a:node.path.str({'format': 'UI'}) + + for l:lineNumber in range(self.getRootLineNum() + 1, line('$')) + let l:currentLine = getline(l:lineNumber) + let l:indentLevel = self._indentLevelFor(l:currentLine) + + if l:indentLevel !=# l:currentPathComponent + continue + endif + + let l:currentLine = self._stripMarkup(l:currentLine) + let l:currentPath = join(l:pathComponents, '/') . '/' . l:currentLine + + " Directories: If the current path 'starts with' the full path, then + " either the paths are equal or the line is a cascade containing the + " full path. + if l:fullPath[-1:] ==# '/' && stridx(l:currentPath, l:fullPath) ==# 0 + return l:lineNumber + endif + + " Files: The paths must exactly match. + if l:fullPath ==# l:currentPath + return l:lineNumber + endif + + " Otherwise: If the full path starts with the current path and the + " current path is a directory, we add a new path component. + if stridx(l:fullPath, l:currentPath) ==# 0 && l:currentPath[-1:] ==# '/' + let l:currentLine = substitute(l:currentLine, '/\s*$', '', '') + call add(l:pathComponents, l:currentLine) + let l:currentPathComponent += 1 + endif + endfor + + return -1 +endfunction + +" FUNCTION: s:UI.getRootLineNum(){{{1 +" gets the line number of the root node +function! s:UI.getRootLineNum() + let rootLine = 1 + while rootLine <= line('$') && getline(rootLine) !~# '^\(/\|<\)' + let rootLine = rootLine + 1 + endwhile + return rootLine +endfunction + +" FUNCTION: s:UI.getShowBookmarks() {{{1 +function! s:UI.getShowBookmarks() + return self._showBookmarks +endfunction + +" FUNCTION: s:UI.getShowFiles() {{{1 +function! s:UI.getShowFiles() + return self._showFiles +endfunction + +" FUNCTION: s:UI.getShowHelp() {{{1 +function! s:UI.getShowHelp() + return self._showHelp +endfunction + +" FUNCTION: s:UI.getShowHidden() {{{1 +function! s:UI.getShowHidden() + return self._showHidden +endfunction + +" FUNCTION: s:UI.getShowFileLines() {{{1 +function! s:UI.getShowFileLines() + return self._showFileLines +endfunction + +" FUNCTION: s:UI._indentLevelFor(line) {{{1 +function! s:UI._indentLevelFor(line) + " Replace multi-character DirArrows with a single space so the + " indentation calculation doesn't get messed up. + if g:NERDTreeDirArrowExpandable ==# '' + let l:line = ' '.a:line + else + let l:line = substitute(substitute(a:line, '\V'.g:NERDTreeDirArrowExpandable, ' ', ''), '\V'.g:NERDTreeDirArrowCollapsible, ' ', '') + endif + let leadChars = match(l:line, '\M\[^ ]') + return leadChars / s:UI.IndentWid() +endfunction + +" FUNCTION: s:UI.IndentWid() {{{1 +function! s:UI.IndentWid() + return 2 +endfunction + +" FUNCTION: s:UI.isIgnoreFilterEnabled() {{{1 +function! s:UI.isIgnoreFilterEnabled() + return self._ignoreEnabled ==# 1 +endfunction + +" FUNCTION: s:UI.isMinimal() {{{1 +function! s:UI.isMinimal() + return g:NERDTreeMinimalUI +endfunction + +" FUNCTION: s:UI.MarkupReg() {{{1 +function! s:UI.MarkupReg() + return '^ *['.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.']\? ' +endfunction + +" FUNCTION: s:UI._renderBookmarks {{{1 +function! s:UI._renderBookmarks() + + if !self.isMinimal() + call setline(line('.')+1, '>----------Bookmarks----------') + call cursor(line('.')+1, col('.')) + endif + + if g:NERDTreeBookmarksSort ==# 1 || g:NERDTreeBookmarksSort ==# 2 + call g:NERDTreeBookmark.SortBookmarksList() + endif + + for i in g:NERDTreeBookmark.Bookmarks() + call setline(line('.')+1, i.str()) + call cursor(line('.')+1, col('.')) + endfor + + call setline(line('.')+1, '') + call cursor(line('.')+1, col('.')) +endfunction + +" FUNCTION: s:UI.restoreScreenState() {{{1 +" +" Sets the screen state back to what it was when nerdtree#saveScreenState was last +" called. +" +" Assumes the cursor is in the NERDTree window +function! s:UI.restoreScreenState() + if !has_key(self, '_screenState') + return + endif + call nerdtree#exec('silent vertical resize ' . self._screenState['oldWindowSize'], 1) + + let old_scrolloff=&scrolloff + let &scrolloff=0 + call cursor(self._screenState['oldTopLine'], 0) + normal! zt + call setpos('.', self._screenState['oldPos']) + let &scrolloff=old_scrolloff +endfunction + +" FUNCTION: s:UI.saveScreenState() {{{1 +" Saves the current cursor position in the current buffer and the window +" scroll position +function! s:UI.saveScreenState() + let win = winnr() + let self._screenState = {} + try + call g:NERDTree.CursorToTreeWin() + let self._screenState['oldPos'] = getpos('.') + let self._screenState['oldTopLine'] = line('w0') + let self._screenState['oldWindowSize'] = winnr('$')==1 ? g:NERDTreeWinSize : winwidth('') + call nerdtree#exec(win . 'wincmd w', 1) + catch + endtry +endfunction + +" FUNCTION: s:UI.setShowHidden(val) {{{1 +function! s:UI.setShowHidden(val) + let self._showHidden = a:val +endfunction + +" FUNCTION: s:UI._stripMarkup(line){{{1 +" find the filename in the given line, and return it. +" +" Args: +" line: the subject line +function! s:UI._stripMarkup(line) + let l:line = substitute(a:line, '^.\{-}' . g:NERDTreeNodeDelimiter, '', '') + return substitute(l:line, g:NERDTreeNodeDelimiter.'.*$', '', '') +endfunction + +" FUNCTION: s:UI.render() {{{1 +function! s:UI.render() + setlocal noreadonly modifiable + + " remember the top line of the buffer and the current line so we can + " restore the view exactly how it was + let curLine = line('.') + let curCol = col('.') + let topLine = line('w0') + + " delete all lines in the buffer (being careful not to clobber a register) + silent 1,$delete _ + + call self._dumpHelp() + + " delete the blank line before the help and add one after it + if !self.isMinimal() + call setline(line('.')+1, '') + call cursor(line('.')+1, col('.')) + endif + + if self.getShowBookmarks() + call self._renderBookmarks() + endif + + " add the 'up a dir' line + if !self.isMinimal() + call setline(line('.')+1, s:UI.UpDirLine()) + call cursor(line('.')+1, col('.')) + endif + + " draw the header line + let header = self.nerdtree.root.path.str({'format': 'UI', 'truncateTo': winwidth(0)}) + call setline(line('.')+1, header) + call cursor(line('.')+1, col('.')) + + " draw the tree + silent put =self.nerdtree.root.renderToString() + + " delete the blank line at the top of the buffer + silent 1,1delete _ + + " restore the view + let old_scrolloff=&scrolloff + let &scrolloff=0 + call cursor(topLine, 1) + normal! zt + call cursor(curLine, curCol) + let &scrolloff = old_scrolloff + + setlocal readonly nomodifiable +endfunction + + +" FUNCTION: UI.renderViewSavingPosition {{{1 +" Renders the tree and ensures the cursor stays on the current node or the +" current nodes parent if it is no longer available upon re-rendering +function! s:UI.renderViewSavingPosition() + let currentNode = g:NERDTreeFileNode.GetSelected() + + " go up the tree till we find a node that will be visible or till we run + " out of nodes + while currentNode !=# {} && !currentNode.isVisible() && !currentNode.isRoot() + let currentNode = currentNode.parent + endwhile + + call self.render() + + if currentNode !=# {} + call currentNode.putCursorHere(0, 0) + endif +endfunction + +" FUNCTION: s:UI.toggleHelp() {{{1 +function! s:UI.toggleHelp() + let self._showHelp = !self._showHelp +endfunction + +" FUNCTION: s:UI.toggleIgnoreFilter() {{{1 +" toggles the use of the NERDTreeIgnore option +function! s:UI.toggleIgnoreFilter() + let self._ignoreEnabled = !self._ignoreEnabled + call self.renderViewSavingPosition() + call self.centerView() +endfunction + +" FUNCTION: s:UI.setShowBookmarks() {{{1 +" Sets the visibility of the Bookmark table. +function! s:UI.setShowBookmarks(value) + let self._showBookmarks = a:value + + if self.getShowBookmarks() + call self.nerdtree.render() + call g:NERDTree.CursorToBookmarkTable() + else + + if empty(g:NERDTreeFileNode.GetSelected()) + call b:NERDTree.root.putCursorHere(0, 0) + normal! 0 + endif + + call self.renderViewSavingPosition() + endif + + call self.centerView() +endfunction + +" FUNCTION: s:UI.toggleShowBookmarks() {{{1 +" Toggle the visibility of the Bookmark table. +function! s:UI.toggleShowBookmarks() + call self.setShowBookmarks(!self._showBookmarks) +endfunction + +" FUNCTION: s:UI.toggleShowFiles() {{{1 +" toggles the display of hidden files +function! s:UI.toggleShowFiles() + let self._showFiles = !self._showFiles + call self.renderViewSavingPosition() + call self.centerView() +endfunction + +" FUNCTION: s:UI.toggleShowHidden() {{{1 +" toggles the display of hidden files +function! s:UI.toggleShowHidden() + let self._showHidden = !self._showHidden + call self.renderViewSavingPosition() + call self.centerView() +endfunction + +" FUNCTION: s:UI.toggleShowFileLines() {{{1 +" toggles the display of file lines +function! s:UI.toggleShowFileLines() + let self._showFileLines = !self._showFileLines + call self.nerdtree.root.refresh() + call self.renderViewSavingPosition() + call self.centerView() +endfunction + +" FUNCTION: s:UI.toggleZoom() {{{1 +" zoom (maximize/minimize) the NERDTree window +function! s:UI.toggleZoom() + if exists('b:NERDTreeZoomed') && b:NERDTreeZoomed + setlocal nowinfixwidth + wincmd = + setlocal winfixwidth + call nerdtree#exec('silent vertical resize '. g:NERDTreeWinSize, 1) + let b:NERDTreeZoomed = 0 + else + call nerdtree#exec('vertical resize '. get(g:, 'NERDTreeWinSizeMax', ''), 1) + let b:NERDTreeZoomed = 1 + endif +endfunction + +" FUNCTION: s:UI.UpDirLine() {{{1 +function! s:UI.UpDirLine() + return '.. (up a dir)' +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/nerdtree_plugin/exec_menuitem.vim b/nvim/.vim/plugged/nerdtree/nerdtree_plugin/exec_menuitem.vim new file mode 100644 index 0000000..0188486 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/nerdtree_plugin/exec_menuitem.vim @@ -0,0 +1,40 @@ +" ============================================================================ +" File: exec_menuitem.vim +" Description: plugin for NERD Tree that provides an execute file menu item +" Maintainer: Martin Grenfell +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +if exists('g:loaded_nerdtree_exec_menuitem') + finish +endif +let g:loaded_nerdtree_exec_menuitem = 1 + +call NERDTreeAddMenuItem({ + \ 'text': '(!)Execute file', + \ 'shortcut': '!', + \ 'callback': 'NERDTreeExecFile', + \ 'isActiveCallback': 'NERDTreeExecFileActive' }) + +function! NERDTreeExecFileActive() + let node = g:NERDTreeFileNode.GetSelected() + return !node.path.isDirectory && node.path.isExecutable +endfunction + +function! NERDTreeExecFile() + let treenode = g:NERDTreeFileNode.GetSelected() + echo "==========================================================\n" + echo "Complete the command to execute (add arguments etc):\n" + let cmd = treenode.path.str({'escape': 1}) + let cmd = input(':!', cmd . ' ') + + if cmd !=# '' + exec ':!' . cmd + else + echo 'Aborted' + endif +endfunction diff --git a/nvim/.vim/plugged/nerdtree/nerdtree_plugin/fs_menu.vim b/nvim/.vim/plugged/nerdtree/nerdtree_plugin/fs_menu.vim new file mode 100644 index 0000000..c3dbc9b --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/nerdtree_plugin/fs_menu.vim @@ -0,0 +1,557 @@ +" ============================================================================ +" File: fs_menu.vim +" Description: plugin for the NERD Tree that provides a file system menu +" Maintainer: Martin Grenfell +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +if exists('g:loaded_nerdtree_fs_menu') + finish +endif +let g:loaded_nerdtree_fs_menu = 1 + +"Automatically delete the buffer after deleting or renaming a file +if !exists('g:NERDTreeAutoDeleteBuffer') + let g:NERDTreeAutoDeleteBuffer = 0 +endif + +call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'}) +call NERDTreeAddMenuItem({'text': '(m)ove the current node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'}) +call NERDTreeAddMenuItem({'text': '(d)elete the current node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'}) + +if nerdtree#runningMac() + call NERDTreeAddMenuItem({'text': '(r)eveal the current node in the Finder', 'shortcut': 'r', 'callback': 'NERDTreeRevealInFinder'}) + call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFile'}) + call NERDTreeAddMenuItem({'text': '(q)uicklook the current node', 'shortcut': 'q', 'callback': 'NERDTreeQuickLook'}) +endif + +if executable('xdg-open') + call NERDTreeAddMenuItem({'text': '(r)eveal the current node in file manager', 'shortcut': 'r', 'callback': 'NERDTreeRevealFileLinux'}) + call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFileLinux'}) +endif + +if nerdtree#runningWindows() + call NERDTreeAddMenuItem({'text': '(r)eveal the current node in the Explorer', 'shortcut': 'r', 'callback': 'NERDTreeRevealInExplorer'}) + call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFileWindows'}) +endif + +if g:NERDTreePath.CopyingSupported() + call NERDTreeAddMenuItem({'text': '(c)opy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'}) +endif +call NERDTreeAddMenuItem({'text': (has('clipboard')?'copy (p)ath to clipboard':'print (p)ath to screen'), 'shortcut': 'p', 'callback': 'NERDTreeCopyPath'}) + +if has('unix') || has('osx') + call NERDTreeAddMenuItem({'text': '(l)ist the current node', 'shortcut': 'l', 'callback': 'NERDTreeListNode'}) + call NERDTreeAddMenuItem({'text': '(C)hange node permissions', 'shortcut':'C', 'callback': 'NERDTreeChangePermissions'}) +else + call NERDTreeAddMenuItem({'text': '(l)ist the current node', 'shortcut': 'l', 'callback': 'NERDTreeListNodeWin32'}) +endif + +if exists('*system') + call NERDTreeAddMenuItem({'text': 'Run (s)ystem command in this directory', 'shortcut':'s', 'callback': 'NERDTreeSystemCommand'}) +endif + +"FUNCTION: s:inputPrompt(action){{{1 +"returns the string that should be prompted to the user for the given action +" +"Args: +"action: the action that is being performed, e.g. 'delete' +function! s:inputPrompt(action) + if a:action ==# 'add' + let title = 'Add a childnode' + let info = "Enter the dir/file name to be created. Dirs end with a '/'" + let minimal = 'Add node:' + + elseif a:action ==# 'copy' + let title = 'Copy the current node' + let info = 'Enter the new path to copy the node to:' + let minimal = 'Copy to:' + + elseif a:action ==# 'delete' + let title = 'Delete the current node' + let info = 'Are you sure you wish to delete the node:' + let minimal = 'Delete?' + + elseif a:action ==# 'deleteNonEmpty' + let title = 'Delete the current node' + let info = "STOP! Directory is not empty! To delete, type 'yes'" + let minimal = 'Delete directory?' + + elseif a:action ==# 'move' + let title = 'Rename the current node' + let info = 'Enter the new path for the node:' + let minimal = 'Move to:' + endif + + if g:NERDTreeMenuController.isMinimal() + redraw! " Clear the menu + return minimal . ' ' + else + let divider = '==========================================================' + return title . "\n" . divider . "\n" . info . "\n" + end +endfunction + +"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1 +"prints out the given msg and, if the user responds by pushing 'y' then the +"buffer with the given bufnum is deleted +" +"Args: +"bufnum: the buffer that may be deleted +"msg: a message that will be echoed to the user asking them if they wish to +" del the buffer +function! s:promptToDelBuffer(bufnum, msg) + echo a:msg + if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y' + " 1. ensure that all windows which display the just deleted filename + " now display an empty buffer (so a layout is preserved). + " Is not it better to close single tabs with this file only ? + let s:originalTabNumber = tabpagenr() + let s:originalWindowNumber = winnr() + " Go to the next buffer in buffer list if at least one extra buffer is listed + " Otherwise open a new empty buffer + if v:version >= 800 + let l:listedBufferCount = len(getbufinfo({'buflisted':1})) + elseif v:version >= 702 + let l:listedBufferCount = len(filter(range(1, bufnr('$')), 'buflisted(v:val)')) + else + " Ignore buffer count in this case to make sure we keep the old + " behavior + let l:listedBufferCount = 0 + endif + if l:listedBufferCount > 1 + call nerdtree#exec('tabdo windo if winbufnr(0) ==# ' . a:bufnum . " | exec ':bnext! ' | endif", 1) + else + call nerdtree#exec('tabdo windo if winbufnr(0) ==# ' . a:bufnum . " | exec ':enew! ' | endif", 1) + endif + call nerdtree#exec('tabnext ' . s:originalTabNumber, 1) + call nerdtree#exec(s:originalWindowNumber . 'wincmd w', 1) + " 3. We don't need a previous buffer anymore + call nerdtree#exec('bwipeout! ' . a:bufnum, 0) + endif +endfunction + +"FUNCTION: s:renameBuffer(bufNum, newNodeName, isDirectory){{{1 +"The buffer with the given bufNum is replaced with a new one +" +"Args: +"bufNum: the buffer that may be deleted +"newNodeName: the name given to the renamed node +"isDirectory: determines how to do the create the new filenames +function! s:renameBuffer(bufNum, newNodeName, isDirectory) + if a:isDirectory + let quotedFileName = fnameescape(a:newNodeName . '/' . fnamemodify(bufname(a:bufNum),':t')) + let editStr = g:NERDTreePath.New(a:newNodeName . '/' . fnamemodify(bufname(a:bufNum),':t')).str({'format': 'Edit'}) + else + let quotedFileName = fnameescape(a:newNodeName) + let editStr = g:NERDTreePath.New(a:newNodeName).str({'format': 'Edit'}) + endif + let s:originalTabNumber = tabpagenr() + let s:originalWindowNumber = winnr() + let l:tempBufferName = 'NERDTreeRenameTempBuffer' + + " 1. swap deleted file buffer with a temporary one + " this step is needed to compensate for case insensitive filesystems + + " 1.1. create an intermediate(temporary) buffer + call nerdtree#exec('badd ' . l:tempBufferName, 0) + let l:tempBufNum = bufnr(l:tempBufferName) + " 1.2. ensure that all windows which display the just deleted filename + " display the new temp buffer. + call nerdtree#exec('tabdo windo if winbufnr(0) ==# ' . a:bufNum . " | exec ':e! " . l:tempBufferName . "' | endif", 0) + " 1.3. We don't need the deleted file buffer anymore + try + call nerdtree#exec('confirm bwipeout ' . a:bufNum, 0) + catch + " This happens when answering Cancel if confirmation is needed. Do nothing. + endtry + + " 2. swap temporary buffer with the new filename buffer + " 2.1. create the actual new file buffer + call nerdtree#exec('badd ' . quotedFileName, 0) + + " 2.2. ensure that all windows which display the temporary buffer + " display a buffer for the new filename. + call nerdtree#exec('tabdo windo if winbufnr(0) ==# ' . l:tempBufNum . " | exec ':e! " . editStr . "' | endif", 0) + call nerdtree#exec('tabnext ' . s:originalTabNumber, 1) + call nerdtree#exec(s:originalWindowNumber . 'wincmd w', 1) + " 2.3. We don't need the temporary buffer anymore + try + call nerdtree#exec('confirm bwipeout ' . l:tempBufNum, 0) + catch + " This happens when answering Cancel if confirmation is needed. Do nothing. + endtry +endfunction + +"FUNCTION: NERDTreeAddNode(){{{1 +function! NERDTreeAddNode() + let curDirNode = g:NERDTreeDirNode.GetSelected() + let prompt = s:inputPrompt('add') + let newNodeName = substitute(input(prompt, curDirNode.path.str() . nerdtree#slash(), 'file'), '\(^\s*\|\s*$\)', '', 'g') + + if newNodeName ==# '' + call nerdtree#echo('Node Creation Aborted.') + return + endif + + try + let newPath = g:NERDTreePath.Create(newNodeName) + let parentNode = b:NERDTree.root.findNode(newPath.getParent()) + + let newTreeNode = g:NERDTreeFileNode.New(newPath, b:NERDTree) + " Emptying g:NERDTreeOldSortOrder forces the sort to + " recalculate the cached sortKey so nodes sort correctly. + let g:NERDTreeOldSortOrder = [] + if empty(parentNode) + call b:NERDTree.root.refresh() + call b:NERDTree.render() + elseif parentNode.isOpen || !empty(parentNode.children) + call parentNode.addChild(newTreeNode, 1) + call NERDTreeRender() + call newTreeNode.putCursorHere(1, 0) + endif + + redraw! + catch /^NERDTree/ + call nerdtree#echoWarning('Node Not Created.') + endtry +endfunction + +"FUNCTION: NERDTreeMoveNode(){{{1 +function! NERDTreeMoveNode() + let curNode = g:NERDTreeFileNode.GetSelected() + let prompt = s:inputPrompt('move') + let newNodePath = input(prompt, curNode.path.str(), 'file') + while filereadable(newNodePath) + " allow renames with different casing when g:NERDTreeCaseSensitiveFS + " is set to either 0 or 3 and the 2 paths are equal + if (g:NERDTreeCaseSensitiveFS == 0 || g:NERDTreeCaseSensitiveFS == 3) && + \nerdtree#pathEquals(curNode.path.str(), newNodePath) + break + endif + + call nerdtree#echoWarning('This destination already exists, Try again.') + + " inform the user about the flag if we think it is a false positive + " when g:NERDTreeCaseSensitiveFS is set to 2 + if g:NERDTreeCaseSensitiveFS == 2 && + \!nerdtree#osDefaultCaseSensitiveFS() && + \nerdtree#pathEquals(curNode.path.str(), newNodePath) + echon "\n(If it is a false positive please consider assigning NERDTreeCaseSensitiveFS's value)" + endif + + " prompt the user again + let newNodePath = substitute(input(prompt, curNode.path.str(), 'file'), '\(^\s*\|\s*$\)', '', 'g') + endwhile + + + if newNodePath ==# '' + call nerdtree#echo('Node Renaming Aborted.') + return + endif + + try + if curNode.path.isDirectory + let l:curPath = escape(curNode.path.str(),'\') . (nerdtree#runningWindows()?'\\':'/') . '.*' + let l:openBuffers = filter(range(1,bufnr('$')),'bufexists(v:val) && fnamemodify(bufname(v:val),":p") =~# "'.escape(l:curPath,'\').'"') + else + let l:openBuffers = filter(range(1,bufnr('$')),'bufexists(v:val) && fnamemodify(bufname(v:val),":p") ==# curNode.path.str()') + endif + + call curNode.rename(newNodePath) + " Emptying g:NERDTreeOldSortOrder forces the sort to + " recalculate the cached sortKey so nodes sort correctly. + let g:NERDTreeOldSortOrder = [] + call b:NERDTree.root.refresh() + call NERDTreeRender() + + " If the file node is open, or files under the directory node are + " open, ask the user if they want to replace the file(s) with the + " renamed files. + if !empty(l:openBuffers) + if curNode.path.isDirectory + echo "\nDirectory renamed.\n\nFiles with the old directory name are open in buffers " . join(l:openBuffers, ', ') . '. Replace these buffers with the new files? (yN)' + else + echo "\nFile renamed.\n\nThe old file is open in buffer " . l:openBuffers[0] . '. Replace this buffer with the new file? (yN)' + endif + if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y' + for bufNum in l:openBuffers + call s:renameBuffer(bufNum, newNodePath, curNode.path.isDirectory) + endfor + endif + endif + + call curNode.putCursorHere(1, 0) + + redraw! + catch /^NERDTree/ + call nerdtree#echoWarning('Node Not Renamed.') + endtry +endfunction + +" FUNCTION: NERDTreeDeleteNode() {{{1 +function! NERDTreeDeleteNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let confirmed = 0 + + if currentNode.path.isDirectory && ((currentNode.isOpen && currentNode.getChildCount() > 0) || + \ (len(currentNode._glob('*', 1)) > 0)) + let prompt = s:inputPrompt('deleteNonEmpty') . currentNode.path.str() . ': ' + let choice = input(prompt) + let confirmed = choice ==# 'yes' + else + let prompt = s:inputPrompt('delete') . currentNode.path.str() . ' (yN): ' + echo prompt + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + if confirmed + try + call currentNode.delete() + call NERDTreeRender() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + let bufnum = bufnr('^'.currentNode.path.str().'$') + if buflisted(bufnum) + let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? ' (hidden)' : '') .'. Delete this buffer? (yN)' + call s:promptToDelBuffer(bufnum, prompt) + endif + + redraw! + catch /^NERDTree/ + call nerdtree#echoWarning('Could not remove node') + endtry + else + call nerdtree#echo('delete aborted') + endif +endfunction + +" FUNCTION: NERDTreeListNode() {{{1 +function! NERDTreeListNode() + let treenode = g:NERDTreeFileNode.GetSelected() + if !empty(treenode) + let s:uname = system('uname') + let stat_cmd = 'stat -c "%s" ' + + if s:uname =~? 'Darwin' + let stat_cmd = 'stat -f "%z" ' + endif + + let cmd = 'size=$(' . stat_cmd . shellescape(treenode.path.str()) . ') && ' . + \ 'size_with_commas=$(echo $size | sed -e :a -e "s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta") && ' . + \ 'ls -ld ' . shellescape(treenode.path.str()) . ' | sed -e "s/ $size / $size_with_commas /"' + + let metadata = split(system(cmd),'\n') + call nerdtree#echo(metadata[0]) + else + call nerdtree#echo('No information available') + endif +endfunction + +" FUNCTION: NERDTreeListNodeWin32() {{{1 +function! NERDTreeListNodeWin32() + let l:node = g:NERDTreeFileNode.GetSelected() + + if !empty(l:node) + let l:path = l:node.path.str() + call nerdtree#echo(printf('%s:%s MOD:%s BYTES:%d PERMISSIONS:%s', + \ toupper(getftype(l:path)), + \ fnamemodify(l:path, ':t'), + \ strftime('%c', getftime(l:path)), + \ getfsize(l:path), + \ getfperm(l:path))) + return + endif + + call nerdtree#echo('node not recognized') +endfunction + +" FUNCTION: NERDTreeChangePermissions() {{{1 +function! NERDTreeChangePermissions() + let l:node = g:NERDTreeFileNode.GetSelected() + let l:prompt = "change node permissions (chmod args): " + let l:newNodePerm = input(l:prompt) + + if !empty(l:node) + let l:path = l:node.path.str() + let l:cmd = 'chmod ' .. newNodePerm .. ' ' .. path + let l:error = split(system(l:cmd), '\n') + + if !empty(l:error) + call nerdtree#echo(l:error[0]) + endif + + call b:NERDTree.root.refresh() + call b:NERDTree.render() + return + endif + + call nerdtree#echo('node not recognized') +endfunction + +" FUNCTION: NERDTreeCopyNode() {{{1 +function! NERDTreeCopyNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let prompt = s:inputPrompt('copy') + let newNodePath = substitute(input(prompt, currentNode.path.str(), 'file'), '\(^\s*\|\s*$\)', '', 'g') + + if newNodePath !=# '' + "strip trailing slash + let newNodePath = substitute(newNodePath, '\/$', '', '') + + let confirmed = 1 + if currentNode.path.copyingWillOverwrite(newNodePath) + call nerdtree#echo('Warning: copying may overwrite files! Continue? (yN)') + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + if confirmed + try + let newNode = currentNode.copy(newNodePath) + " Emptying g:NERDTreeOldSortOrder forces the sort to + " recalculate the cached sortKey so nodes sort correctly. + let g:NERDTreeOldSortOrder = [] + if empty(newNode) + call b:NERDTree.root.refresh() + call b:NERDTree.render() + else + call NERDTreeRender() + call newNode.putCursorHere(0, 0) + endif + catch /^NERDTree/ + call nerdtree#echoWarning('Could not copy node') + endtry + endif + else + call nerdtree#echo('Copy aborted.') + endif + redraw! +endfunction + +" FUNCTION: NERDTreeCopyPath() {{{1 +function! NERDTreeCopyPath() + let l:nodePath = g:NERDTreeFileNode.GetSelected().path.str() + if has('clipboard') + if &clipboard ==# 'unnamedplus' + let @+ = l:nodePath + else + let @* = l:nodePath + endif + call nerdtree#echo('The path [' . l:nodePath . '] was copied to your clipboard.') + else + call nerdtree#echo('The full path is: ' . l:nodePath) + endif +endfunction + +" FUNCTION: NERDTreeQuickLook() {{{1 +function! NERDTreeQuickLook() + let l:node = g:NERDTreeFileNode.GetSelected() + + if empty(l:node) + return + endif + + call system('qlmanage -p 2>/dev/null ' . shellescape(l:node.path.str())) +endfunction + +" FUNCTION: NERDTreeRevealInFinder() {{{1 +function! NERDTreeRevealInFinder() + let l:node = g:NERDTreeFileNode.GetSelected() + + if empty(l:node) + return + endif + + call system('open -R ' . shellescape(l:node.path.str())) +endfunction + +" FUNCTION: NERDTreeExecuteFile() {{{1 +function! NERDTreeExecuteFile() + let l:node = g:NERDTreeFileNode.GetSelected() + + if empty(l:node) + return + endif + + call system('open ' . shellescape(l:node.path.str())) +endfunction + +" FUNCTION: NERDTreeRevealFileLinux() {{{1 +function! NERDTreeRevealFileLinux() + let l:node = g:NERDTreeFileNode.GetSelected() + + if empty(l:node) + return + endif + + " Handle the edge case of "/", which has no parent. + if l:node.path.str() ==# '/' + call system('xdg-open /') + return + endif + + if empty(l:node.parent) + return + endif + + call system('xdg-open ' . shellescape(l:node.parent.path.str())) +endfunction + +" FUNCTION: NERDTreeExecuteFileLinux() {{{1 +function! NERDTreeExecuteFileLinux() + let l:node = g:NERDTreeFileNode.GetSelected() + + if empty(l:node) + return + endif + + call system('xdg-open ' . shellescape(l:node.path.str())) +endfunction + +" FUNCTION: NERDTreeRevealInExplorer() {{{1 +function! NERDTreeRevealInExplorer() + let l:node = g:NERDTreeFileNode.GetSelected() + + if empty(l:node) + return + endif + + call system('cmd.exe /c explorer /select, ' . shellescape(l:node.path.str())) +endfunction + +" FUNCTION: NERDTreeExecuteFileWindows() {{{1 +function! NERDTreeExecuteFileWindows() + let l:node = g:NERDTreeFileNode.GetSelected() + + if empty(l:node) + return + endif + + call system('cmd.exe /c start "" ' . shellescape(l:node.path.str())) +endfunction + +" FUNCTION: NERDTreeSystemCommand() {{{1 +function! NERDTreeSystemCommand() + let l:node = g:NERDTreeFileNode.GetSelected() + + if empty(l:node) + return + endif + + let l:cwd = getcwd() + let l:directory = l:node.path.isDirectory ? l:node.path.str() : l:node.parent.path.str() + execute 'cd '.l:directory + + let l:nl = nr2char(10) + echo l:nl . system(input(l:directory . (nerdtree#runningWindows() ? '> ' : ' $ '))) + execute 'cd '.l:cwd +endfunction + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/nerdtree_plugin/vcs.vim b/nvim/.vim/plugged/nerdtree/nerdtree_plugin/vcs.vim new file mode 100644 index 0000000..b0bae64 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/nerdtree_plugin/vcs.vim @@ -0,0 +1,47 @@ +" ============================================================================ +" File: vcs.vim +" Description: NERDTree plugin that provides a command to open on the root of +" a version control system repository. +" Maintainer: Phil Runninger +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +command! -n=? -complete=dir -bar NERDTreeVCS :call CreateTabTreeVCS('') +command! -n=? -complete=dir -bar NERDTreeToggleVCS :call ToggleTabTreeVCS('') + +" FUNCTION: s:CreateTabTreeVCS(a:name) {{{1 +function! s:CreateTabTreeVCS(name) + let l:path = g:NERDTreeCreator._pathForString(a:name) + let l:path = s:FindParentVCSRoot(l:path) + call g:NERDTreeCreator.createTabTree(empty(l:path) ? '' : l:path._str()) +endfunction + +" FUNCTION: s:ToggleTabTreeVCS(a:name) {{{1 +" Behaves the same as ToggleTabTree except roots directory at VCS root +function! s:ToggleTabTreeVCS(name) + let l:path = g:NERDTreeCreator._pathForString(a:name) + let l:path = s:FindParentVCSRoot(l:path) + call g:NERDTreeCreator.toggleTabTree(empty(l:path) ? '' : l:path._str()) +endfunction + +" FUNCTION: s:FindParentVCSRoot(a:path) {{{1 +" Finds the root version control system folder of the given path. If a:path is +" not part of a repository, return the original path. +function! s:FindParentVCSRoot(path) + let l:path = a:path + while !empty(l:path) && + \ l:path._str() !~# '^\(\a:[\\\/]\|\/\)$' && + \ !isdirectory(l:path._str() . '/.git') && + \ !isdirectory(l:path._str() . '/.svn') && + \ !isdirectory(l:path._str() . '/.hg') && + \ !isdirectory(l:path._str() . '/.bzr') && + \ !isdirectory(l:path._str() . '/_darcs') + let l:path = l:path.getParent() + endwhile + return (empty(l:path) || l:path._str() =~# '^\(\a:[\\\/]\|\/\)$') ? a:path : l:path +endfunction + diff --git a/nvim/.vim/plugged/nerdtree/plugin/NERD_tree.vim b/nvim/.vim/plugged/nerdtree/plugin/NERD_tree.vim new file mode 100644 index 0000000..0342641 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/plugin/NERD_tree.vim @@ -0,0 +1,240 @@ +" ============================================================================ +" File: NERD_tree.vim +" Maintainer: Martin Grenfell +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +" +" SECTION: Script init stuff {{{1 +"============================================================ +scriptencoding utf-8 + +if exists('loaded_nerd_tree') + finish +endif +if v:version < 703 + echoerr "NERDTree: this plugin requires vim >= 7.3. DOWNLOAD IT! You'll thank me later!" + finish +endif +let loaded_nerd_tree = 1 + +"for line continuation - i.e dont want C in &cpoptions +let s:old_cpo = &cpoptions +set cpoptions&vim + +"SECTION: Initialize variable calls and other random constants {{{2 +let g:NERDTreeAutoCenter = get(g:, 'NERDTreeAutoCenter', 1) +let g:NERDTreeAutoCenterThreshold = get(g:, 'NERDTreeAutoCenterThreshold', 3) +let g:NERDTreeCaseSensitiveFS = get(g:, 'NERDTreeCaseSensitiveFS', 2) +let g:NERDTreeCaseSensitiveSort = get(g:, 'NERDTreeCaseSensitiveSort', 0) +let g:NERDTreeNaturalSort = get(g:, 'NERDTreeNaturalSort', 0) +let g:NERDTreeSortHiddenFirst = get(g:, 'NERDTreeSortHiddenFirst', 1) +let g:NERDTreeUseTCD = get(g:, 'NERDTreeUseTCD', 0) +let g:NERDTreeChDirMode = get(g:, 'NERDTreeChDirMode', 0) +let g:NERDTreeCreatePrefix = get(g:, 'NERDTreeCreatePrefix', 'silent') +let g:NERDTreeMinimalUI = get(g:, 'NERDTreeMinimalUI', 0) +let g:NERDTreeMinimalMenu = get(g:, 'NERDTreeMinimalMenu', 0) +let g:NERDTreeIgnore = get(g:, 'NERDTreeIgnore', ['\~$']) +let g:NERDTreeBookmarksFile = get(g:, 'NERDTreeBookmarksFile', expand('$HOME') . '/.NERDTreeBookmarks') +let g:NERDTreeBookmarksSort = get(g:, 'NERDTreeBookmarksSort', 1) +let g:NERDTreeHighlightCursorline = get(g:, 'NERDTreeHighlightCursorline', 1) +let g:NERDTreeHijackNetrw = get(g:, 'NERDTreeHijackNetrw', 1) +let g:NERDTreeMarkBookmarks = get(g:, 'NERDTreeMarkBookmarks', 1) +let g:NERDTreeMouseMode = get(g:, 'NERDTreeMouseMode', 1) +let g:NERDTreeNotificationThreshold = get(g:, 'NERDTreeNotificationThreshold', 100) +let g:NERDTreeQuitOnOpen = get(g:, 'NERDTreeQuitOnOpen', 0) +let g:NERDTreeRespectWildIgnore = get(g:, 'NERDTreeRespectWildIgnore', 0) +let g:NERDTreeShowBookmarks = get(g:, 'NERDTreeShowBookmarks', 0) +let g:NERDTreeShowFiles = get(g:, 'NERDTreeShowFiles', 1) +let g:NERDTreeShowHidden = get(g:, 'NERDTreeShowHidden', 0) +let g:NERDTreeShowLineNumbers = get(g:, 'NERDTreeShowLineNumbers', 0) +let g:NERDTreeSortDirs = get(g:, 'NERDTreeSortDirs', 1) +let g:NERDTreeFileLines = get(g:, 'NERDTreeFileLines', 0) + + +if !nerdtree#runningWindows() && !nerdtree#runningCygwin() + let g:NERDTreeDirArrowExpandable = get(g:, 'NERDTreeDirArrowExpandable', '▸') + let g:NERDTreeDirArrowCollapsible = get(g:, 'NERDTreeDirArrowCollapsible', '▾') +else + let g:NERDTreeDirArrowExpandable = get(g:, 'NERDTreeDirArrowExpandable', '+') + let g:NERDTreeDirArrowCollapsible = get(g:, 'NERDTreeDirArrowCollapsible', '~') +endif + +let g:NERDTreeCascadeOpenSingleChildDir = get(g:, 'NERDTreeCascadeOpenSingleChildDir', 1) +let g:NERDTreeCascadeSingleChildDir = get(g:, 'NERDTreeCascadeSingleChildDir', 1) + +let g:NERDTreeSortOrder = get(g:, 'NERDTreeSortOrder', ['\/$', '*', '\.swp$', '\.bak$', '\~$']) +let g:NERDTreeOldSortOrder = [] + +let g:NERDTreeGlyphReadOnly = get(g:, 'NERDTreeGlyphReadOnly', 'RO') + +if has('conceal') + let g:NERDTreeNodeDelimiter = get(g:, 'NERDTreeNodeDelimiter', "\x07") +elseif (g:NERDTreeDirArrowExpandable ==# "\u00a0" || g:NERDTreeDirArrowCollapsible ==# "\u00a0") + let g:NERDTreeNodeDelimiter = get(g:, 'NERDTreeNodeDelimiter', "\u00b7") +else + let g:NERDTreeNodeDelimiter = get(g:, 'NERDTreeNodeDelimiter', "\u00a0") +endif + +"the exists() crap here is a hack to stop vim spazzing out when +"loading a session that was created with an open nerd tree. It spazzes +"because it doesnt store b:NERDTree(its a b: var, and its a hash) +let g:NERDTreeStatusline = get(g:, 'NERDTreeStatusline', "%{exists('b:NERDTree')?b:NERDTree.root.path.str():''}") + +let g:NERDTreeWinPos = get(g:, 'NERDTreeWinPos', 'left') +let g:NERDTreeWinSize = get(g:, 'NERDTreeWinSize', 31) + +"init the shell commands that will be used to copy nodes, and remove dir trees +"Note: the space after the command is important +if nerdtree#runningWindows() + let g:NERDTreeRemoveDirCmd = get(g:, 'NERDTreeRemoveDirCmd', 'rmdir /s /q ') + let g:NERDTreeCopyDirCmd = get(g:, 'NERDTreeCopyDirCmd', 'xcopy /s /e /i /y /q ') + let g:NERDTreeCopyFileCmd = get(g:, 'NERDTreeCopyFileCmd', 'copy /y ') +else + let g:NERDTreeRemoveDirCmd = get(g:, 'NERDTreeRemoveDirCmd', 'rm -rf ') + let g:NERDTreeCopyCmd = get(g:, 'NERDTreeCopyCmd', 'cp -r ') +endif + +"SECTION: Init variable calls for key mappings {{{2 +let g:NERDTreeMapCustomOpen = get(g:, 'NERDTreeMapCustomOpen', '') +let g:NERDTreeMapJumpBookmarks = get(g:, 'NERDTreeMapJumpBookmarks', 'gb') +let g:NERDTreeMapActivateNode = get(g:, 'NERDTreeMapActivateNode', 'o') +let g:NERDTreeMapChangeRoot = get(g:, 'NERDTreeMapChangeRoot', 'C') +let g:NERDTreeMapChdir = get(g:, 'NERDTreeMapChdir', 'cd') +let g:NERDTreeMapCloseChildren = get(g:, 'NERDTreeMapCloseChildren', 'X') +let g:NERDTreeMapCloseDir = get(g:, 'NERDTreeMapCloseDir', 'x') +let g:NERDTreeMapDeleteBookmark = get(g:, 'NERDTreeMapDeleteBookmark', 'D') +let g:NERDTreeMapMenu = get(g:, 'NERDTreeMapMenu', 'm') +let g:NERDTreeMapHelp = get(g:, 'NERDTreeMapHelp', '?') +let g:NERDTreeMapJumpFirstChild = get(g:, 'NERDTreeMapJumpFirstChild', 'K') +let g:NERDTreeMapJumpLastChild = get(g:, 'NERDTreeMapJumpLastChild', 'J') +let g:NERDTreeMapJumpNextSibling = get(g:, 'NERDTreeMapJumpNextSibling', '') +let g:NERDTreeMapJumpParent = get(g:, 'NERDTreeMapJumpParent', 'p') +let g:NERDTreeMapJumpPrevSibling = get(g:, 'NERDTreeMapJumpPrevSibling', '') +let g:NERDTreeMapJumpRoot = get(g:, 'NERDTreeMapJumpRoot', 'P') +let g:NERDTreeMapOpenExpl = get(g:, 'NERDTreeMapOpenExpl', 'e') +let g:NERDTreeMapOpenInTab = get(g:, 'NERDTreeMapOpenInTab', 't') +let g:NERDTreeMapOpenInTabSilent = get(g:, 'NERDTreeMapOpenInTabSilent', 'T') +let g:NERDTreeMapOpenRecursively = get(g:, 'NERDTreeMapOpenRecursively', 'O') +let g:NERDTreeMapOpenSplit = get(g:, 'NERDTreeMapOpenSplit', 'i') +let g:NERDTreeMapOpenVSplit = get(g:, 'NERDTreeMapOpenVSplit', 's') +let g:NERDTreeMapPreview = get(g:, 'NERDTreeMapPreview', 'g'.NERDTreeMapActivateNode) +let g:NERDTreeMapPreviewSplit = get(g:, 'NERDTreeMapPreviewSplit', 'g'.NERDTreeMapOpenSplit) +let g:NERDTreeMapPreviewVSplit = get(g:, 'NERDTreeMapPreviewVSplit', 'g'.NERDTreeMapOpenVSplit) +let g:NERDTreeMapQuit = get(g:, 'NERDTreeMapQuit', 'q') +let g:NERDTreeMapRefresh = get(g:, 'NERDTreeMapRefresh', 'r') +let g:NERDTreeMapRefreshRoot = get(g:, 'NERDTreeMapRefreshRoot', 'R') +let g:NERDTreeMapToggleBookmarks = get(g:, 'NERDTreeMapToggleBookmarks', 'B') +let g:NERDTreeMapToggleFiles = get(g:, 'NERDTreeMapToggleFiles', 'F') +let g:NERDTreeMapToggleFilters = get(g:, 'NERDTreeMapToggleFilters', 'f') +let g:NERDTreeMapToggleHidden = get(g:, 'NERDTreeMapToggleHidden', 'I') +let g:NERDTreeMapToggleFileLines = get(g:, 'NERDTreeMapToggleFileLines', 'FL') +let g:NERDTreeMapToggleZoom = get(g:, 'NERDTreeMapToggleZoom', 'A') +let g:NERDTreeMapUpdir = get(g:, 'NERDTreeMapUpdir', 'u') +let g:NERDTreeMapUpdirKeepOpen = get(g:, 'NERDTreeMapUpdirKeepOpen', 'U') +let g:NERDTreeMapCWD = get(g:, 'NERDTreeMapCWD', 'CD') +let g:NERDTreeMenuDown = get(g:, 'NERDTreeMenuDown', 'j') +let g:NERDTreeMenuUp = get(g:, 'NERDTreeMenuUp', 'k') + +"SECTION: Load class files{{{2 +call nerdtree#loadClassFiles() + +" SECTION: Commands {{{1 +"============================================================ +call nerdtree#ui_glue#setupCommands() + + +" SECTION: Auto commands {{{1 +"============================================================ +augroup NERDTree + "Save the cursor position whenever we close the nerd tree + exec 'autocmd BufLeave,WinLeave '. g:NERDTreeCreator.BufNamePrefix() .'* call nerdtree#onBufLeave()' + + "disallow insert mode in the NERDTree + exec 'autocmd BufEnter,WinEnter '. g:NERDTreeCreator.BufNamePrefix() .'* stopinsert' +augroup END + +if g:NERDTreeHijackNetrw + augroup NERDTreeHijackNetrw + autocmd VimEnter * silent! autocmd! FileExplorer + au BufEnter,VimEnter * call nerdtree#checkForBrowse(expand('')) + augroup END +endif + +if g:NERDTreeChDirMode ==# 3 + augroup NERDTreeChDirOnTabSwitch + autocmd TabEnter * if g:NERDTree.ExistsForTab()|call g:NERDTree.ForCurrentTab().getRoot().path.changeToDir()|endif + augroup END +endif + +" SECTION: Public API {{{1 +"============================================================ +function! NERDTreeAddMenuItem(options) + call g:NERDTreeMenuItem.Create(a:options) +endfunction + +function! NERDTreeAddMenuSeparator(...) + let opts = a:0 ? a:1 : {} + call g:NERDTreeMenuItem.CreateSeparator(opts) +endfunction + +function! NERDTreeAddSubmenu(options) + return g:NERDTreeMenuItem.Create(a:options) +endfunction + +function! NERDTreeAddKeyMap(options) + call g:NERDTreeKeyMap.Create(a:options) +endfunction + +function! NERDTreeRender() + call nerdtree#renderView() +endfunction + +function! NERDTreeFocus() + if g:NERDTree.IsOpen() + call g:NERDTree.CursorToTreeWin(0) + else + call g:NERDTreeCreator.ToggleTabTree('') + endif +endfunction + +function! NERDTreeCWD() + + if empty(getcwd()) + call nerdtree#echoWarning('current directory does not exist') + return + endif + + try + let l:cwdPath = g:NERDTreePath.New(getcwd()) + catch /^NERDTree.InvalidArgumentsError/ + call nerdtree#echoWarning('current directory does not exist') + return + endtry + + call NERDTreeFocus() + + if b:NERDTree.root.path.equals(l:cwdPath) + return + endif + + let l:newRoot = g:NERDTreeFileNode.New(l:cwdPath, b:NERDTree) + call b:NERDTree.changeRoot(l:newRoot) + normal! ^ +endfunction + +function! NERDTreeAddPathFilter(callback) + call g:NERDTree.AddPathFilter(a:callback) +endfunction + +" SECTION: Post Source Actions {{{1 +call nerdtree#postSourceActions() + +"reset &cpoptions back to users setting +let &cpoptions = s:old_cpo + +" vim: set sw=4 sts=4 et fdm=marker: diff --git a/nvim/.vim/plugged/nerdtree/screenshot.png b/nvim/.vim/plugged/nerdtree/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..0975a451e589b59b42a542a9caca4bc1f48145bf62a2782954343fe8b4cbadb4 GIT binary patch literal 87896 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�OkEM>-if5oLqld#XMc7@CEE>NzgY860qx#tdl$~ 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
  • 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 F{67l|-0c7W literal 0 HcmV?d00001 diff --git a/nvim/.vim/plugged/nerdtree/syntax/nerdtree.vim b/nvim/.vim/plugged/nerdtree/syntax/nerdtree.vim new file mode 100644 index 0000000..810a5b8 --- /dev/null +++ b/nvim/.vim/plugged/nerdtree/syntax/nerdtree.vim @@ -0,0 +1,97 @@ +let s:tree_up_dir_line = '.. (up a dir)' +syn match NERDTreeIgnore #\~# +exec 'syn match NERDTreeIgnore #\['.g:NERDTreeGlyphReadOnly.'\]#' + +"highlighting for the .. (up dir) line at the top of the tree +execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line .'#' + +"quickhelp syntax elements +syn match NERDTreeHelpKey #" \{1,2\}[^ ]*:#ms=s+2,me=e-1 +syn match NERDTreeHelpKey #" \{1,2\}[^ ]*,#ms=s+2,me=e-1 +syn match NERDTreeHelpTitle #" .*\~$#ms=s+2,me=e-1 +syn match NERDTreeToggleOn #(on)#ms=s+1,he=e-1 +syn match NERDTreeToggleOff #(off)#ms=e-3,me=e-1 +syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3 +syn match NERDTreeHelp #^".*# contains=NERDTreeHelpKey,NERDTreeHelpTitle,NERDTreeIgnore,NERDTreeToggleOff,NERDTreeToggleOn,NERDTreeHelpCommand + +"highlighting for sym links +syn match NERDTreeLinkTarget #->.*# containedin=NERDTreeDir,NERDTreeFile +syn match NERDTreeLinkFile #.* ->#me=e-3 containedin=NERDTreeFile +syn match NERDTreeLinkDir #.*/ ->#me=e-3 containedin=NERDTreeDir + +"highlighting to conceal the delimiter around the file/dir name +if has('conceal') + exec 'syn match NERDTreeNodeDelimiters #\%d' . char2nr(g:NERDTreeNodeDelimiter) . '# conceal containedin=ALL' + setlocal conceallevel=2 concealcursor=nvic +else + exec 'syn match NERDTreeNodeDelimiters #\%d' . char2nr(g:NERDTreeNodeDelimiter) . '# containedin=ALL' + hi! link NERDTreeNodeDelimiters Ignore +endif + +"highlighting for directory nodes and file nodes +syn match NERDTreeDirSlash #/# containedin=NERDTreeDir + +if g:NERDTreeDirArrowExpandable !=# '' + exec 'syn match NERDTreeClosable #' . escape(g:NERDTreeDirArrowCollapsible, '~') . '\ze .*/# containedin=NERDTreeDir,NERDTreeFile' + exec 'syn match NERDTreeOpenable #' . escape(g:NERDTreeDirArrowExpandable, '~') . '\ze .*/# containedin=NERDTreeDir,NERDTreeFile' + let s:dirArrows = escape(g:NERDTreeDirArrowCollapsible, '~]\-').escape(g:NERDTreeDirArrowExpandable, '~]\-') + exec 'syn match NERDTreeDir #[^'.s:dirArrows.' ].*/#' + exec 'syn match NERDTreeExecFile #^.*'.g:NERDTreeNodeDelimiter.'\*\($\| \)# contains=NERDTreeRO,NERDTreeBookmarkName' + exec 'syn match NERDTreeFile #^[^"\.'.s:dirArrows.'] *[^'.s:dirArrows.']*# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmarkName,NERDTreeExecFile' +else + exec 'syn match NERDTreeDir #[^'.g:NERDTreeNodeDelimiter.']\{-}/\ze\($\|'.g:NERDTreeNodeDelimiter.'\)#' + exec 'syn match NERDTreeExecFile #[^'.g:NERDTreeNodeDelimiter.']\{-}'.g:NERDTreeNodeDelimiter.'\*\($\| \)# contains=NERDTreeRO,NERDTreeBookmarkName' + exec 'syn match NERDTreeFile #^.*'.g:NERDTreeNodeDelimiter.'.*[^\/]\($\|'.g:NERDTreeNodeDelimiter.'.*\)# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmarkName,NERDTreeExecFile' +endif + +"highlighting for readonly files +exec 'syn match NERDTreeRO #.*'.g:NERDTreeNodeDelimiter.'\zs.*\ze'.g:NERDTreeNodeDelimiter.'.*\['.g:NERDTreeGlyphReadOnly.'\]# contains=NERDTreeIgnore,NERDTreeBookmarkName,NERDTreeFile' + +exec 'syn match NERDTreeFlags #\[[^\]]*\]\ze'.g:NERDTreeNodeDelimiter.'# containedin=NERDTreeFile,NERDTreeExecFile,NERDTreeLinkFile,NERDTreeRO,NERDTreeDir' + +syn match NERDTreeCWD #^[# +syn match NERDTreeBookmarksHeader #^>-\+Bookmarks-\+$# contains=NERDTreeBookmarksLeader +syn match NERDTreeBookmarkName #^>.\{-} #he=e-1 contains=NERDTreeBookmarksLeader +syn match NERDTreeBookmark #^>.*$# contains=NERDTreeBookmarksLeader,NERDTreeBookmarkName,NERDTreeBookmarksHeader + +hi def link NERDTreePart Special +hi def link NERDTreePartFile Type +hi def link NERDTreeExecFile Title +hi def link NERDTreeDirSlash Identifier + +hi def link NERDTreeBookmarksHeader statement +hi def link NERDTreeBookmarksLeader ignore +hi def link NERDTreeBookmarkName Identifier +hi def link NERDTreeBookmark normal + +hi def link NERDTreeHelp String +hi def link NERDTreeHelpKey Identifier +hi def link NERDTreeHelpCommand Identifier +hi def link NERDTreeHelpTitle Macro +hi def link NERDTreeToggleOn Question +hi def link NERDTreeToggleOff WarningMsg + +hi def link NERDTreeLinkTarget Type +hi def link NERDTreeLinkFile Macro +hi def link NERDTreeLinkDir Macro + +hi def link NERDTreeDir Directory +hi def link NERDTreeUp Directory +hi def link NERDTreeFile Normal +hi def link NERDTreeCWD Statement +hi def link NERDTreeOpenable Directory +hi def link NERDTreeClosable Directory +hi def link NERDTreeIgnore ignore +hi def link NERDTreeRO WarningMsg +hi def link NERDTreeBookmark Statement +hi def link NERDTreeFlags Number + +hi def link NERDTreeCurrentNode Search + +hi NERDTreeFile ctermbg=NONE guibg=NONE diff --git a/nvim/.vim/plugged/vim-devicons/.github/ISSUE_TEMPLATE.md b/nvim/.vim/plugged/vim-devicons/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..49b54fe --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,24 @@ +#### Requirements + + + +#### Required Info + + + +- [ ] I have searched the [issues](https://github.com/ryanoasis/vim-devicons/issues) for my issue and found nothing related and/or helpful +- [ ] I have read or at least glanced at the [FAQ](https://github.com/ryanoasis/vim-devicons/wiki/FAQ-&-Troubleshooting) +- [ ] I have read or at least glanced at the [Wiki](https://github.com/ryanoasis/vim-devicons/wiki) +- [ ] `VimDevIcons` is the last loaded vim plugin? +- [ ] What **version** of vim are you using? + - hint: `vim --version` +- [ ] What **font** are you using? +- [ ] Are you using vim from the terminal or a GUI vim? +- [ ] Are you using Mac, Linux or Windows? + +#### Optional Info + +- [ ] Provide **screenshots** where appropriate diff --git a/nvim/.vim/plugged/vim-devicons/.github/PULL_REQUEST_TEMPLATE.md b/nvim/.vim/plugged/vim-devicons/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..e9352f6 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,15 @@ +#### Requirements (please check off with 'x') + +- [ ] I have read the [Contributing Guidelines](https://github.com/ryanoasis/vim-devicons/blob/master/CONTRIBUTING.md) +- [ ] I have read or at least glanced at the [FAQ](https://github.com/ryanoasis/vim-devicons#faq--troubleshooting) +- [ ] I have read or at least glanced at the [Wiki](https://github.com/ryanoasis/vim-devicons/wiki) + +#### What does this Pull Request (PR) do? + +#### How should this be manually tested? + +#### Any background context you can provide? + +#### What are the relevant tickets (if any)? + +#### Screenshots (if appropriate or helpful) diff --git a/nvim/.vim/plugged/vim-devicons/.github/workflows/ci.yml b/nvim/.vim/plugged/vim-devicons/.github/workflows/ci.yml new file mode 100644 index 0000000..551cab3 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/.github/workflows/ci.yml @@ -0,0 +1,42 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + test: + name: Test + runs-on: ubuntu-latest + strategy: + matrix: + vim: + - v9.0.0000 + - v8.2.1000 + - v8.2.0000 + - v8.1.0000 + - v8.0.0000 + + steps: + - name: Checkout code + uses: actions/checkout@main + - name: Checkout vim-themis + uses: actions/checkout@main + with: + repository: thinca/vim-themis + path: vim-themis + + - name: Setup Vim + uses: rhysd/action-setup-vim@v1 + id: vim + with: + version: ${{ matrix.vim }} + + - name: Test + env: + THEMIS_VIM: ${{ steps.vim.outputs.executable }} + run: ./vim-themis/bin/themis --reporter spec diff --git a/nvim/.vim/plugged/vim-devicons/.github/workflows/vint.yml b/nvim/.vim/plugged/vim-devicons/.github/workflows/vint.yml new file mode 100644 index 0000000..3170aac --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/.github/workflows/vint.yml @@ -0,0 +1,32 @@ +name: vint + +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.8] + + steps: + - uses: actions/checkout@main + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@main + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + - name: Install vint + run: | + pip install vim-vint + - name: Run vint + run: | + vint --verbose --stat $(find . -type f -name '*.vim') diff --git a/nvim/.vim/plugged/vim-devicons/.gitignore b/nvim/.vim/plugged/vim-devicons/.gitignore new file mode 100644 index 0000000..0b6bf64 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/.gitignore @@ -0,0 +1,5 @@ +doc/tags +__pycache__/ +.DS_Store +.netrwhist +*.swp diff --git a/nvim/.vim/plugged/vim-devicons/CHANGELOG.md b/nvim/.vim/plugged/vim-devicons/CHANGELOG.md new file mode 100644 index 0000000..f6cd88e --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/CHANGELOG.md @@ -0,0 +1,249 @@ + +CHANGELOG +================================================================================ +This project is using [Semantic Versioning 2.0.0](http://semver.org/) + +- v0.11.0 + - Added Docker filetypes support (PR #228) (@IngoHeimbach) + - Added Swift filetypes support (PR #252) (@motform) + - Added Elixir filetypes support (PR #244) (@akoutmos) + - Added configuration for 'prePadding' (fixes #231) + - Added support for `vue` filetype extensions out-of-the-box (fixes #235) + - Added configuration for 'DevIconsArtifactFix' (#225) + - Added leftrelease override to work on single mouse click (PR #246) (@Matrix86) + - Added Travis CI with vim linting (PR #236) (@kutsan) + - Fixed Vim-Startify no longer working "out of the box" (#233) + - Fixed Denite information being discarded (fixes #216) (PR #229 @carlitux) + - Fixed inconsistent spacing between folder and file glyphs (fixes #213) + - Updated variable declarations and refactored into set function (PR #237) (@kutsan) + - Updated plugin initialization functions to autoload on demand (PR #238) (@kutsan) + - Updated documentation and refactored massively to Wiki (PR #232) (@kutsan) + - Updated `vim` glyph to better glyph (fixes #234) + - Updated Readme screenshots and badges +- v0.10.0 + - Added support for symlink directories (PR #221) (@mhartington) + - Added missing Denite config in readme (PR #217, fixes #205) (@mohamadLy) + - Fixed NERDTree folder open bug with cascade setting (fixes #194) + - Fixed potential issue with Vim-Airline (PR #219) (@chrisbra) + - Fixed readme.md (removed duplicate section) (PR #222) (@thehappydinoa) + - Updated Vim-Airline Repo link in readme (PR #220) (@chrisbra) +- v0.9.3 + - Added `tsx` filetype (PR #210) (@dustinblackman) + - Updated links of [deprecated kien/ctrlp](https://github.com/kien/ctrlp.vim) to [active ctrlp fork](https://github.com/ctrlpvim/ctrlp.vim) (PR #211) (@haxorjim) + - Updated MacOS and Windows `guifont` examples with alternate format (fixes #208) +- v0.9.2 + - Added `yaml` filetype (PR #207) (@jpoppe) + - Added mention of `vim-workspace` as an integrated plugin (PR #206) (@bagrat) + - Fixed NERDTree keymap `U` open folder icon bug (fixes #189) +- v0.9.1 + - Added `sass` filetype (PR #202) (@toastal) + - Fixed NERDTree open/close folder icon bugs (fixes #194) + - Fixed airline conflict with file enconding `skip_expected_string` feature (fixes #203) + - Fixed possible glyph artifacts on open/close folder glyphs +- v0.9.0 + - Added support for [Denite](https://github.com/Shougo/denite.nvim) (PR #191) (@0phoff) + - Added symbol for byte order marker (BOM) (utf-8) (PR #199) (@Snaptags) + - Added support for `.zshrc`, `.vimrc`, `pp` (Puppet classes extensions), and `Vagrantfile` filetypes (enhancement #200) (@kiyanwang) + - Added support for `h`, `hpp`, `hxx` (C/C++ header filetype extensions) (enhancement #190) + - Added support for `bash`, `zsh`, `ksh`, `csh`, `awk`, `ps1` (script extensions) (enhancement #196) + - Added support for `rmd` (R Markdown) (partially fixes #195) + - Fixes opened folders titles padding/spacing offset (fixes #197) +- v0.8.6 + - Added support for vimfiler explorer mode (fixes #171) + - Added `doc/tags` to `.gitignore` (PR #182) (@doronbehar) + - Added warning to readme pertaining to old versions of NERDTree and CtrlP (PR #177, fixes #174) (@Melon-Bread) + - Fixes CtrlP buffer names (PR #185) (@HerringtonDarkholme) + - Fixes character encoding issue in vim doc (PR #178) (@mhartington) + - Fixes extraneous space after glyph in airline (PR #184) (@tbodt) + - Fixes errors when NERDTree not present (PR #187) (@blueyed) + - Updated Contributor Covenant to `v1.4` + - Updated API examples +- v0.8.5 + - Fixed errors in neovim (E670) (PR #163, fixes #162) (@mhartington) + - Fixed issue of updating NERDTree window via `CursorHoldUpdate` (PR #166) (@svanharmelen) + - Fixes updating of special buffer when selected + - Fixes potential issues CtrlP opening in wrong buffer when NERDTree is opened + - Fixed issue with CtrlP `:CtrlPMRU` always defaulting to current buffer (fixes #88) + - Also adds glyphs to other CtrlP modes besides MRU as a side effect + - Fixed documentation discrepency on pluging load order (PR #169) (@F1LT3R) + - Fixed documentation related to CtrlP MRU mode (PR #170, fixes #168) (@F1LT3R) +- v0.8.4 + - Fixed always warning about deprecated CtrlP version (fixes #137) + - Fixed missing configuration info about pattern based symbols (fixes #152) + - Fixed `WebDevIconsGetFileTypeSymbol` method iterator missing `break` (PR #156) (@blueyed) + - Fixed a typo in the readme (PR #159) (@SSARCandy) + - Added reference to [tiagofumo/vim-nerdtree-syntax-highlight](https://github.com/tiagofumo/vim-nerdtree-syntax-highlight) in readme (PR #161) (@tiagofumo) + - However, the [FAQ](https://github.com/ryanoasis/vim-devicons/wiki/FAQ) has been moved to the [Wiki](https://github.com/ryanoasis/vim-devicons/wiki) in this release +- v0.8.3 + - Fixed NERDTree not displaying glyph (icon) for newly created files (fixes #153) + - Also adds info to readme about `updatetime` + - Fixed resourcing `vimrc` not maintaining current NERDTree state (fixes #154) + - Adds new public methods `webdevicons#hardRefresh()` and `webdevicons#softRefresh()` + - Makes public method `webdevicons#refresh()` do a 'soft' refresh + - Fixed various source formatting and implemented most of vim lint ([vint](https://github.com/Kuniwak/vint)) recommendations + - Added public methods available to readme +- v0.8.2 + - Updated `jsx` filetype (using React glyph) (enhancement PR #148) (@alpertuna) + - Added issue and pull request templates +- v0.8.1 + - Fixed Unite display issues (absolute paths and/or duplicate paths) (fixes #140) + - Fixed custom CtrlP open function causing 'E16' (fixes #115) + - Fixed typo in readme for setting default folder glyph (PR #143) + - Added documentation for highlighting icon/glyphs only (not just entire lines) in NERDTree (fixes #142) +- v0.8.0 + - Added support for more [unite](https://github.com/Shougo/unite.vim) actions: `file_rec/async`, `file_rec/neovim`, `file_rec/neovim2`, `file_rec/git` (enhancement PR #132, fixes #131) (@mhartington) + - Improved Darwin detection by using a lighter method/logic (#135) (@delphinus35) + - Fixes `NERDTree-C` (fix PR #139) (@endenwer) + - Fixes error using open/close symbols for folder (fixes #130) +- v0.7.1 + - Misc readme updates + - Fixed performance issues and odd graphical artifacts in v0.7.0 (fixes #127) + - Improved installation instructions and re-organized some items to [Nerd Fonts repo](https://github.com/ryanoasis/nerd-fonts) (PR #129, fixes #125, #128) (@her) +- v0.7.0 + - Deprecated support for [kien/ctrlp](https://github.com/kien/ctrlp.vim) and only support [active ctrlp fork](https://github.com/ctrlpvim/ctrlp.vim) going forward (fixes #117) + - Added information to readme about [vim-startify](https://github.com/mhinz/vim-startify) support (enhancement #94) + - Added information to readme with possible fix to 'Dots after icons' (fixes #110) (@KabbAmine) + - Added support for 'cljc' (Clojure) filetypes (fix PR #120) (@spacepluk) + - Fixed certain folders in NERDTree showing file glyphs (based on pattern matching) (fixes #112) + - Fixed OS icon being display with as Linux Tux on Mac (fixes #118,fix PR #121) (@trodrigu) + - Fixed deprecated Linux font path in readme (fix PR #123) (@jrobeson) +- v0.6.1 + - Fixed likely breaking bug: undefined variable g:DevIconsEnableFoldersOpenClose (fixes #109) + - Fixed up the changelog details +- v0.6.0 + - Added support for [Powerline](https://github.com/powerline/powerline) (enhancement PR #74) (@delphinus35) + - Added support for 'ts' (TypeScript) filetypes (enhancement #79) + - Added support for 'jl' (Julia) filetypes + - Added support for 'bat' (batch) filetypes + - Added support for 'ejs' (Embedded JavaScript Templates) filetypes (enhancement #105) (@lerrua) + - Added support for 'react.jsx' filetype + - Added support for 'procfile' filetype + - Changed default 'go' filetype glyph to a better one + - Added open & close folder glyphs (icons) (enhancement #104) + - Fixed new files not having icons until refreshing NERDTree (fixes #33) + - Solution very similar to [nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin) +- v0.5.4 + - Misc readme updates + - Add support for ocaml 'ml', 'mli' filetypes (enhancement PR #99) (@CharlieMartell) + - Add support for 'sql' and 'dump' filetypes (enhancement PR #100) (@lerrua) + - Add support for 'ico' filetypes (enhancement PR #101) (@lerrua) + - Add support for 'markdown' filetypes (enhancement PR #102) (@lerrua) + - Improved install fonts instructions on Mac (enhancement PR #103) (@lerrua) +- v0.5.3 + - Add 'slim' filetype support (same icon as 'html') (enhancement PR #98) (@lerrua) + - Add 'fish' filetype support (same icon as 'sh') (enhancement #93) (@michaelmrose) + - Updated old link references (enhancement PR #87) (@lerrua) + - Improved default Ruby icon (uses 'glyph set 2') (enhancement PR #97) (@lerrua) + - Prevent destorying user's conceal settings (Use setlocal) (enhancement PR #96) (@shawncplus) + - Fixes filenames of buffers getting lost in unite filter (fixes #86) (@ahrse) + - Various readme updates and fixes +- v0.5.2 + - Various readme updates and fixes + - Various file clean-up (.gitignore removed) + - Fixed link to install fonts (PR #83 fixes #81) (@theRemix) + - Fixed glyph used for Go (PR #82) (@hoop33) + - Added Code of Conduct +- v0.5.1 + - Fixed [CtrlP](https://github.com/ctrlpvim/ctrlp.vim) integration bugs (truncating 6 characters is unreliable) and only add glyphs for MRU File Mode (Fixes #80) + - Readme updates and improvements +- v0.5.0 + - Readme updates (removed polls sections, v0.5.0 specific changes) + - Misc code formatting fixes (tabs to spaces, modeline additions, reorganization) + - Update API: make WebDevIconsGetFileFormatSymbol return only fenc (fixes #73) + - Added Perl support (enhancement #60) + - Added support for some (mostly frontend) frameworks (enhancement #61) + - Added basic support for vim-flagship (enhancement #70) + - Added support for Unite and Vimfiler (enhancement #54) + - Added support for CtrlP (enhancement #56) + - Rebranding part 1: title and image (vim-devicons) (enhancement #76) +- v0.4.4 + - Lots of readme updates and tweaks + - Changelog semver details + - Spelling / confusing grammar corrections (PR #68) (@adelarsq) + - Fixed default folder/directory glyph (PR Fixes #72) (@cj) + - Mac OS X screenshot (Fixes #32) (@RageZBla) + - Fixed misalignment when used with [nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin) (Fixes #71) + - Fixed re-sourcing bug (Fixes #71) + - Fixed directory node user settings being overwritten (Fixes #59) + - Fixed minor screenshot issues and clean-up +- v0.4.3 + - Prevent error 'Unknown function' when opening Vim without airline plugin (Fixes #67) + - Temporary fix for gvim glyph artifact issues (particuarly NERDTree) (Fixes #58) + - Support file format symbols (glyphs) in vim-airline (Enhancement #66) + - Add vimrc setup example to readme (Documentation #65) + - Fixes Conceal highlighting issues (Fixes #53, #52) + - Make sure plugin plays nice with [nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin) (Enhancement #62) + - general readme updates and improvements + - changelog format fixes +- v0.4.2 + - Updated vim doc with latest readme updates (html2vimdoc) + - Fixes #7 update readme for font and vim setup on osx and win platforms + - Fixes #49 with a FAQ update + - Fixes #41 No such event: nerdtree syntax match (@nbicalcarata) + - Removed test files from the repo and added folders to git-ignore + - Warn about loading vim-webdevicons before nerdtree plugin + - fix lazy NERDTree (@blueyed) + - Improve conceiling with NERDTree (@blueyed) + - add instructions to readme for vim setup on os x (@alfredbez) +- v0.4.1 + - Fixes #39 - updated screenshots (particularly nerdtree) + - Fixes #37 - g:webdevicons_conceal_nerdtree_brackets applying global config + - Add instructions to readme for adding icon to lightline (@hoop33) + - Updated vim doc with latest readme updates (sync'd with html2vimdoc) + - Added TL;DR section to readme + - Add a note to readme to load NERDTree before vim-webdevicons (@hoop33) + - Fix: Automatically turning off NERDTree support (@hoop33) + - general readme updates +- v0.4.0 + - #27 Remove [ ] wrapping icons + - #26 Add detection and warning on unsupported (old) NERDTree versions + - updated readme with more links and new details on new features and conifgs + - #30 Improve vim standard plugin conventions and tips + - #30 work on sections and standard plugin conventions part 1 + - #30 clean-up of unused (for now) autoload file + - #28 setting global options broken part 1 + - #29 Add vimdoc, more updates + - autogenerating vimdoc using html2vimdoc + - readme updates +- v0.3.4 + - Adds basic support for directory/folder glyphs - fixes #22 + - optimize icon lookup - WebDevIconsGetFileTypeSymbol: use if/else (@blueyed) + - Do not clobber the default or customized airline formatter (@blueyed) + - fixed a bug related to the latest airline updates (Ali Aliev) + - various readme updates + - more sample usage images +- v0.3.3 + - Load the plugin once only (@blueyed) + - Add font installation instructions, fixes #5 (@wikimatze) + - added plugin install instructions + - slight readme re-ordering + - moved contributing section near bottom + - added additional screenshots + - added more thanks to those whose some more of the glyphs came from +- v0.3.2 + - moved screenshots into the wiki (wiki.vim-webdevicons) to reduce unnecessary project size of cloning repo +- v0.3.1 + - readme updates (with references to new font-patcher repo) + - readme updates screenshots reference wiki +- v0.3.0 + - moved font-patcher and patched fonts into a separate repo (nerd-filetype-glyphs-fonts-patcher) + - adds twigg file type support for #10 (@wikimatze) + - adds cpp file type support + - updated utf8 test file with glyphs + - readme fixes (@wikimatze, @blueyed) + - readme updates +- v0.2.1 + - readme updates +- v0.2.0 + - Script for patching any font: Initial cleaned up work for issue (feature enhancement) for #1 + - added python font patcher and readme updates +- v0.1.4 + - readme updates +- v0.1.3 + - fixes #3 make matches case insensitive (ignore case) +- v0.1.2 + - fixes lookup for exact file notes (@johngeorgewright) +- v0.1.1 + - updated readme substantially +- v0.1.0 + - release diff --git a/nvim/.vim/plugged/vim-devicons/CODE_OF_CONDUCT.md b/nvim/.vim/plugged/vim-devicons/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..c4c6c24 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team on +[VimDevIcons Gitter Chat](https://gitter.im/ryanoasis/vim-devicons) +or contacting [@ryanoasis](https://github.com/ryanoasis). All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/nvim/.vim/plugged/vim-devicons/CONTRIBUTING.md b/nvim/.vim/plugged/vim-devicons/CONTRIBUTING.md new file mode 100644 index 0000000..b884593 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/CONTRIBUTING.md @@ -0,0 +1,18 @@ +# Contributing Guide + +## How to contribute + +* Fork the project and submit a Pull Request (PR) + * Explain what the PR fixes or improves + * Screenshots for bonus points +* Use sensible commit messages + * If your PR fixes a separate issue number, include it in the commit message + +## Things to keep in mind + +* Smaller PRs are likely to be merged more quickly than bigger changes +* If it is a useful PR it **will** get merged in eventually + * [E.g. see how many have already been merged vs. still open](https://github.com/ryanoasis/vim-devicons/pulls) +* This project _was_ using [Semantic Versioning 2.0.0](http://semver.org/) but we have since mostly abandoned that +* Try to add to the unit tests where possible so we can maintain our test coverage +* Issues not filled out with the template will be closed straight away and will only be responded to once filled properly diff --git a/nvim/.vim/plugged/vim-devicons/DEVELOPER.md b/nvim/.vim/plugged/vim-devicons/DEVELOPER.md new file mode 100644 index 0000000..961c5da --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/DEVELOPER.md @@ -0,0 +1,68 @@ +### API + +```vim +" returns the font character that represents the icon +" parameters: a:1 (filename), a:2 (isDirectory) +" both parameters optional +" by default without parameters uses buffer name +WebDevIconsGetFileTypeSymbol(...) + +" returns the font character that represents +" the file format as an icon (windows, linux, mac) +WebDevIconsGetFileFormatSymbol() +``` + +#### Public Methods + +```vim +" Returns the current version of the plugin +webdevicons#version() +``` + +```vim +" Calls webdevicons#softRefresh() +" basically a backwards compatibility convenience +webdevicons#refresh() +``` + +```vim +" Does a 'hard' refresh of NERDTree +" resets vim-devicons syntax and closes and reopens NERDTree +webdevicons#hardRefresh() +``` + +```vim +" Does a 'soft' refresh of NERDTree +" resets vim-devicons syntax and toggles NERDTree to the same state +webdevicons#softRefresh() +``` + +#### API Examples + +##### Status line + +> Custom vim status line (not relying on vim-airline or lightline): + +```vim +set statusline=%f\ %{WebDevIconsGetFileTypeSymbol()}\ %h%w%m%r\ %=%(%l,%c%V\ %Y\ %=\ %P%) +``` + +##### Simple function call + +```vim +echo WebDevIconsGetFileFormatSymbol() +``` + +#### Integration with other plugins + +##### vim-startify + +```vim +let entry_format = "' ['. index .']'. repeat(' ', (3 - strlen(index)))" + +if exists('*WebDevIconsGetFileTypeSymbol') " support for vim-devicons + let entry_format .= ". WebDevIconsGetFileTypeSymbol(entry_path) .' '. entry_path" +else + let entry_format .= '. entry_path' +endif +``` diff --git a/nvim/.vim/plugged/vim-devicons/LICENSE b/nvim/.vim/plugged/vim-devicons/LICENSE new file mode 100644 index 0000000..5e32fe4 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014 Ryan L McIntyre + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/nvim/.vim/plugged/vim-devicons/README.md b/nvim/.vim/plugged/vim-devicons/README.md new file mode 100644 index 0000000..b06ec13 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/README.md @@ -0,0 +1,107 @@ +

    + VimDevIcons - Add Icons to Your Plugins +

    + +
    + +![version](https://img.shields.io/github/release/ryanoasis/vim-devicons.svg?style=for-the-badge) +![chat on gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=for-the-badge) +![code of conduct](https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=for-the-badge) +![prs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACWFBMVEXXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWkrXWko2FeWCAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAI28AACNvATX8B%2FsAAAAHdElNRQfhBQMBMCLAfV85AAAAi0lEQVQ4y2NgIBYszkPmJc5ORZE9DgEJqNxmmPS%2B43AA4h5B5TIwbD5%2BHFnoKCoXYSBMBIW7CF0eAxChoPM4ARXHB4GCZEIKKA8H%2FCoWE1LAwIBfBVp6wQA1DPhVzMJMcyggCVuqxGI%2FLhWY6Z6QPKoK7HmHkDwDwxYC8gwMdSDprXiz6PHjpQxUBgCLDfI7GXNh5gAAAABJRU5ErkJggg%3D%3D) +![CI](https://img.shields.io/github/workflow/status/ryanoasis/vim-devicons/CI?label=CI&style=for-the-badge) + +
    + +> Supports plugins such as [NERDTree](https://github.com/preservim/nerdtree), [vim-airline](https://github.com/vim-airline/vim-airline), [CtrlP](https://github.com/ctrlpvim/ctrlp.vim), [powerline](https://github.com/powerline/powerline), [denite](https://github.com/Shougo/denite.nvim), [unite](https://github.com/Shougo/unite.vim), [lightline.vim](https://github.com/itchyny/lightline.vim), [vim-startify](https://github.com/mhinz/vim-startify), [vimfiler](https://github.com/Shougo/vimfiler.vim), [vim-buffet](https://github.com/bagrat/vim-buffet) and [flagship](https://github.com/tpope/vim-flagship). + +

    + vim-devicons overall screenshot +

    + +> See [Screenshots](https://github.com/ryanoasis/vim-devicons/wiki/screenshots) for more. + +Features +-------- + +- Adds filetype glyphs (icons) to various vim plugins. +- Customizable and extendable glyphs settings. +- Supports a wide range of file type extensions. +- Supports popular full filenames, like `.gitignore`, `node_modules`, `.vimrc`, and many more. +- Supports byte order marker (BOM). +- Works with patched fonts, especially [Nerd Fonts](https://github.com/ryanoasis/nerd-fonts). + +> See [Detailed Features](https://github.com/ryanoasis/vim-devicons/wiki/Detailed-Features) for more. + +> See [Configuration](https://github.com/ryanoasis/vim-devicons/wiki/Extra-Configuration) for a list of configuration and customization options. + +Installation +------------ + +1. Install a [Nerd Font compatible font](https://github.com/ryanoasis/nerd-fonts#font-installation) or [patch your own](https://github.com/ryanoasis/nerd-fonts#font-patcher). Then set your terminal font (or `guifont` if you are using GUI version of Vim). +1. Install the Vim plugin with your favorite plugin manager, e.g. [vim-plug](https://github.com/junegunn/vim-plug): + + ```vim + Plug 'ryanoasis/vim-devicons' + ``` + + > Always load the vim-devicons as the very last one. + +1. Configure Vim + + ```vim + set encoding=UTF-8 + ``` + + > No need to set explicitly under Neovim: always uses UTF-8 as the default encoding. + + +> See [Installation](https://github.com/ryanoasis/vim-devicons/wiki/Installation) for detailed setup instructions + +Use `:help devicons` for further configuration. + +Developers +---------- + +See [DEVELOPER](DEVELOPER.md) for how to use the API. + +Troubleshooting +--------------- + +See [FAQ](https://github.com/ryanoasis/vim-devicons/wiki/FAQ-&-Troubleshooting). + +Contributing +------------ + +### [Code of Conduct](CODE_OF_CONDUCT.md) + +This project has adopted a Code of Conduct that we expect project participants to adhere to. Check out [code of conduct](CODE_OF_CONDUCT.md) for further details. + +### [Contributing Guide](CONTRIBUTING.md) + +Read our [contributing](CONTRIBUTING.md) guide to learn about how to send pull requests, creating issues properly. + +### Promotion + +You can help us by simply giving a star or voting on vim.org. It will ensure continued development going forward. + +- Star this repository [on GitHub](https://github.com/ryanoasis/vim-devicons). +- Vote for it [on vim.org](http://www.vim.org/scripts/script.php?script_id=5114). + +Acknowledgments +--------------- + +Thanks goes to these people for inspiration and helping with sending PRs. + +- [vim-airline](https://github.com/vim-airline/vim-airline) +- [nerdtree](https://github.com/preservim/nerdtree) +- [nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin) by [@Xuyuanp](https://github.com/Xuyuanp) +- [seti-ui](https://atom.io/themes/seti-ui) by [@jesseweed](https://github.com/jesseweed) +- [devicons](http://vorillaz.github.io/devicons) by [@vorillaz](https://github.com/vorillaz) +- [development.svg.icons](https://github.com/benatespina/development.svg.icons) by [@benatespina](https://github.com/benatespina) +- [Learn Vimscript the Hard Way](http://learnvimscriptthehardway.stevelosh.com/) book by [Steve Losh](http://stevelosh.com/) +- All [contributors](https://github.com/ryanoasis/vim-devicons/graphs/contributors) + +License +------- + +[MIT](LICENSE) diff --git a/nvim/.vim/plugged/vim-devicons/autoload/airline/extensions/tabline/formatters/webdevicons.vim b/nvim/.vim/plugged/vim-devicons/autoload/airline/extensions/tabline/formatters/webdevicons.vim new file mode 100644 index 0000000..b1b1a5e --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/autoload/airline/extensions/tabline/formatters/webdevicons.vim @@ -0,0 +1,14 @@ +" Version: 0.11.0 +" Webpage: https://github.com/ryanoasis/vim-devicons +" Maintainer: Ryan McIntyre +" License: see LICENSE + +function! airline#extensions#tabline#formatters#webdevicons#format(bufnr, buffers) abort + " Call original formatter. + let originalFormatter = airline#extensions#tabline#formatters#{g:_webdevicons_airline_orig_formatter}#format(a:bufnr, a:buffers) + return originalFormatter . g:WebDevIconsTabAirLineBeforeGlyphPadding . + \ WebDevIconsGetFileTypeSymbol(bufname(a:bufnr)) . g:WebDevIconsTabAirLineAfterGlyphPadding +endfunction + +" modeline syntax: +" vim: fdm=marker tabstop=2 softtabstop=2 shiftwidth=2 expandtab: diff --git a/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/ctrlp.vim b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/ctrlp.vim new file mode 100644 index 0000000..66a76c8 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/ctrlp.vim @@ -0,0 +1,30 @@ +" Initialize for up to date ctrlp fork: ctrlpvim/ctrlp.vim +" Support for kien/ctrlp.vim deprecated since v0.7.0 +" @TODO implementation for CtrlP buffer and find file mode + +function! devicons#plugins#ctrlp#init() abort + let l:ctrlp_warning_message = 'vim-devicons: https://github.com/kien/ctrlp.vim is deprecated since v0.7.0, please use https://github.com/ctrlpvim/ctrlp.vim' + let l:ctrlp_warned_file = webdevicons#pluginHome() . '/status_warned_ctrlp' + + if exists('g:loaded_ctrlp') && g:webdevicons_enable_ctrlp + let l:forkedCtrlp = exists('g:ctrlp_mruf_map_string') + + if l:forkedCtrlp + if !exists('g:ctrlp_formatline_func') + " logic for ctrlpvim/ctrlp.vim: + let g:ctrlp_formatline_func = 's:formatline(s:curtype() == "buf" ? v:val : WebDevIconsGetFileTypeSymbol(v:val) . " " . v:val) ' + endif + elseif empty(glob(l:ctrlp_warned_file)) + " logic for kien/ctrlp.vim: + echohl WarningMsg | + \ echomsg l:ctrlp_warning_message + " only warn first time, do not warn again: + try + execute writefile(['File automatically generated after warning about CtrlP once', l:ctrlp_warning_message], l:ctrlp_warned_file) + catch + endtry + endif + endif +endfunction + +" vim: tabstop=2 softtabstop=2 shiftwidth=2 expandtab: diff --git a/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/denite.vim b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/denite.vim new file mode 100644 index 0000000..c523797 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/denite.vim @@ -0,0 +1,10 @@ +function! devicons#plugins#denite#init() abort + let s:denite_ver = (exists('*denite#get_status_mode') ? 2 : 3) + if s:denite_ver == 3 + call denite#custom#source('file,file/rec,file_mru,file/old,buffer,directory/rec,directory_mru', 'converters', ['devicons_denite_converter']) + else + call denite#custom#source('file,file_rec,file_mru,file_old,buffer,directory_rec,directory_mru', 'converters', ['devicons_denite_converter']) + endif +endfunction + +" vim: tabstop=2 softtabstop=2 shiftwidth=2 expandtab: diff --git a/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/flagship.vim b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/flagship.vim new file mode 100644 index 0000000..cd3572d --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/flagship.vim @@ -0,0 +1,15 @@ +function! devicons#plugins#flagship#init() abort + if g:webdevicons_enable_flagship_statusline + augroup webdevicons_flagship_filetype + autocmd User Flags call Hoist('buffer', 'WebDevIconsGetFileTypeSymbol') + augroup END + endif + + if g:webdevicons_enable_flagship_statusline_fileformat_symbols + augroup webdevicons_flagship_filesymbol + autocmd User Flags call Hoist('buffer', 'WebDevIconsGetFileFormatSymbol') + augroup END + endif +endfunction + +" vim: tabstop=2 softtabstop=2 shiftwidth=2 expandtab: diff --git a/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/startify.vim b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/startify.vim new file mode 100644 index 0000000..6f1202a --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/startify.vim @@ -0,0 +1,6 @@ + +function! devicons#plugins#startify#init() abort + exec ":function! StartifyEntryFormat() abort \n return 'WebDevIconsGetFileTypeSymbol(absolute_path) .\" \". entry_path' \n endfunction" +endfunction + +" vim: tabstop=2 softtabstop=2 shiftwidth=2 expandtab: diff --git a/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/unite.vim b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/unite.vim new file mode 100644 index 0000000..212e1c7 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/unite.vim @@ -0,0 +1,37 @@ +function! devicons#plugins#unite#init() abort + let s:filters = { + \ 'name': 'devicons_unite_converter' + \ } + + function! s:filters.filter(candidates, context) abort + for candidate in a:candidates + + if has_key(candidate, 'action__buffer_nr') + let bufname = bufname(candidate.action__buffer_nr) + let filename = fnamemodify(bufname, ':p:t') + let path = fnamemodify(bufname, ':p:h') + elseif has_key(candidate, 'word') && has_key(candidate, 'action__path') + let path = candidate.action__path + let filename = candidate.word + endif + + let icon = WebDevIconsGetFileTypeSymbol(filename, isdirectory(filename)) + + " prevent filenames of buffers getting 'lost' + if filename != path + let path = printf('%s', filename) + endif + + " Customize output format. + let candidate.abbr = printf('%s %s', icon, path) + endfor + return a:candidates + endfunction + + call unite#define_filter(s:filters) + unlet s:filters + + call unite#custom#source('file,file_rec,buffer,file_rec/async,file_rec/neovim,file_rec/neovim2,file_rec/git', 'converters', 'devicons_unite_converter') +endfunction + +" vim: tabstop=2 softtabstop=2 shiftwidth=2 expandtab: diff --git a/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/vimfiler.vim b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/vimfiler.vim new file mode 100644 index 0000000..2bb5a6b --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/autoload/devicons/plugins/vimfiler.vim @@ -0,0 +1,8 @@ +function! devicons#plugins#vimfiler#init() abort + call vimfiler#custom#profile('default', 'context', { + \ 'columns': 'devicons:size:time', + \ 'explorer_columns': 'devicons' + \ }) +endfunction + +" vim: tabstop=2 softtabstop=2 shiftwidth=2 expandtab: diff --git a/nvim/.vim/plugged/vim-devicons/autoload/vimfiler/columns/devicons.vim b/nvim/.vim/plugged/vim-devicons/autoload/vimfiler/columns/devicons.vim new file mode 100644 index 0000000..edd69a8 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/autoload/vimfiler/columns/devicons.vim @@ -0,0 +1,80 @@ +"============================================================================= +" FILE: devicons.vim +" Version: 0.11.0 +" Webpage: https://github.com/ryanoasis/vim-devicons +" Maintainer: Ryan McIntyre +" License: 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. +" }}} +"============================================================================= + +let s:save_cpo = &cpo +set cpo&vim + +function! vimfiler#columns#devicons#define() abort + return s:column +endfunction + +let s:column = { + \ 'name' : 'devicons', + \ 'description' : 'get devicon glyph', + \ 'syntax' : 'vimfilerColumn__devicons', + \ } + +function! s:column.length(files, context) abort + return 3 +endfunction + +function! s:column.define_syntax(context) abort "{{{ + syntax match vimfilerColumn__TypeText '\[T\]' + \ contained containedin=vimfilerColumn__Type + syntax match vimfilerColumn__TypeImage '\[I\]' + \ contained containedin=vimfilerColumn__Type + syntax match vimfilerColumn__TypeArchive '\[A\]' + \ contained containedin=vimfilerColumn__Type + syntax match vimfilerColumn__TypeExecute '\[X\]' + \ contained containedin=vimfilerColumn__Type + syntax match vimfilerColumn__TypeMultimedia '\[M\]' + \ contained containedin=vimfilerColumn__Type + syntax match vimfilerColumn__TypeDirectory '\[do\]' + \ contained containedin=vimfilerColumn__Type + syntax match vimfilerColumn__TypeSystem '\[S\]' + \ contained containedin=vimfilerColumn__Type + syntax match vimfilerColumn__TypeLink '\[L\]' + \ contained containedin=vimfilerColumn__Type + + highlight def link vimfilerColumn__TypeText Constant + highlight def link vimfilerColumn__TypeImage Type + highlight def link vimfilerColumn__TypeArchive Special + highlight def link vimfilerColumn__TypeExecute Statement + highlight def link vimfilerColumn__TypeMultimedia Identifier + highlight def link vimfilerColumn__TypeDirectory Preproc + highlight def link vimfilerColumn__TypeSystem Comment + highlight def link vimfilerColumn__TypeLink Comment +endfunction"}}} + +function! s:column.get(file, context) abort + return WebDevIconsGetFileTypeSymbol(strpart(a:file.action__path, strridx(a:file.action__path, '/')), a:file.vimfiler__is_directory) +endfunction + +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: foldmethod=marker diff --git a/nvim/.vim/plugged/vim-devicons/doc/webdevicons.txt b/nvim/.vim/plugged/vim-devicons/doc/webdevicons.txt new file mode 100644 index 0000000..824e66e --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/doc/webdevicons.txt @@ -0,0 +1,1078 @@ +*devicons* + +=============================================================================== +Contents ~ + + 1. Introduction |devicons-introduction| + 2. Features |devicons-features| + 3. Installation |devicons-installation| + 4. Developers |devicons-developers| + 5. Troubleshooting |devicons-troubleshooting| + 6. Contributing |devicons-contributing| + 1. Code of Conduct [22] |devicons-code-of-conduct-22| + 2. Contributing Guide [23] |devicons-contributing-guide-23| + 3. Promotion |devicons-promotion| + 7. Acknowledgments |devicons-acknowledgments| + 8. License |devicons-license| + 9. Detailed Installation |devicons-detailed-installation| + 1. Step 1 'Nerd Font' |Nerd-Font| + 2. Step 2 'VimDevIcons Plugin' |VimDevIcons-Plugin| + 1. Pathogen [38] |devicons-pathogen-38| + 2. NeoBundle [39] |devicons-neobundle-39| + 3. Vundle [40] |devicons-vundle-40| + 4. Manual |devicons-manual| + 3. Step 3 'Configure Vim' |Configure-Vim| + 1. Set Encoding |devicons-set-encoding| + 2. Set Font |devicons-set-font| + 3. vim-airline |devicons-vim-airline| + 4. vimrc examples |devicons-vimrc-examples| + 4. That's it! You're done. |devicons-thats-it-youre-done.| + 10. Usage |devicons-usage| + 1. NERDTree |devicons-nerdtree| + 2. Unite |devicons-unite| + 3. Denite |devicons-denite| + 4. Vimfiler |devicons-vimfiler| + 5. CtrlP |devicons-ctrlp| + 6. Airline |devicons-airline| + 7. Startify |devicons-startify| + 8. Lightline Setup |devicons-lightline-setup| + 9. Powerline Setup |devicons-powerline-setup| + 10. Flagship |devicons-flagship| + 11. Detailed Features |devicons-detailed-features| + 12. Extra Configuration |devicons-extra-configuration| + 1. Character Mappings |devicons-character-mappings| + 2. API |devicons-api| + 1. Public Methods |devicons-public-methods| + 2. API Examples |devicons-api-examples| + 1. Status line |devicons-status-line| + 2. Simple function call |devicons-simple-function-call| + 3. Integration with other plugins |devicons-integration-with-other-plugins| + 1. vim-startify |devicons-vim-startify| + 13. FAQ |devicons-faq| + 1. Why isn't it working? How come I don't see any icons? |devicons-why-isnt-it-working-how-come-i-dont-see-any-icons| + 2. How did you get color matching based on file type in NERDtree? |devicons-how-did-you-get-color-matching-based-on-file-type-in-nerdtree| + 3. How did you get color matching on just the glyph/icon in NERDtree? |devicons-how-did-you-get-color-matching-on-just-glyph-icon-in-nerdtree| + 4. How do I solve issues after re-sourcing my |vimrc|? + 5. Why do I have artifacts after (or instead) of icons? |devicons-why-do-i-have-artifacts-after-of-icons| + 6. Square brackets around icons |devicons-square-brackets-around-icons| + 1. from terminal |devicons-from-terminal| + 7. Do I have to use a patched font such as Nerd Fonts? |devicons-do-i-have-to-use-patched-font-such-as-nerd-fonts| + 8. Rationale: Why does this exist? How did this start? |devicons-rationale-why-does-this-exist-how-did-this-start| + 14. References |devicons-references| + +=============================================================================== + *devicons-introduction* +Introduction ~ +> + _ ___ ____ ____ + | | / (_____ ___ / __ \___ _ __/ _/________ ____ _____ + | | / / / __ `__ \/ / / / _ | | / // // ___/ __ \/ __ \/ ___/ + | |/ / / / / / / / /_/ / __| |/ _/ // /__/ /_/ / / / (__ ) + |___/_/_/ /_/ /_/_____/\___/|___/___/\___/\____/_/ /_/____/ +< +**VimDevIcons** + +Adds Icons to Your Plugins + +Supports plugins such as NERDTree [1], vim-airline [2], CtrlP [3], powerline +[4], denite [5], unite [6], lightline.vim [7], vim-startify [8], vimfiler [9], +vim-workspace [10] and flagship [11]. + +See Screenshots [12] for more. + +=============================================================================== + *devicons-features* +Features ~ + +- Adds filetype glyphs (icons) to various vim plugins. +- Supports byte order marker (BOM). +- Customizable and extendable glyphs settings. +- Supports a wide range of file type extensions. +- Supports popular full filenames, like '.gitignore', 'node_modules', + '.vimrc'. +- Works with patched fonts, especially Nerd Fonts [13]. + +See Detailed Features [14] for more. + +See Configuration [15] for a list of configuration and customization options. + +=============================================================================== + *devicons-installation* +Installation ~ + +1. Install a Nerd Font compatible font [16] or patch your own [17]. Then set + your terminal font (or 'guifont' if you are using GUI version of Vim). + +2. Install the Vim plugin with your favorite plugin manager, e.g. vim-plug + [18]: + + "vim Plug 'ryanoasis/vim-devicons'" + + Always load the vim-devicons as the very last one. + +3. Configure Vim + + 'vim set encoding=UTF-8' + + No need to set explicitly under Neovim: always uses UTF-8 as the default + encoding. + +See Installation [19] for detailed setup instructions + +Use ':help devicons' for further configuration. + +=============================================================================== + *devicons-developers* +Developers ~ + +See DEVELOPER [20] for how to use the API. + +=============================================================================== + *devicons-troubleshooting* +Troubleshooting ~ + +See FAQ [21]. + +=============================================================================== + *devicons-contributing* +Contributing ~ + +------------------------------------------------------------------------------- + *devicons-code-of-conduct-22* +Code of Conduct [22] ~ + +This project has adopted a Code of Conduct that we expect project participants +to adhere to. Check out code of conduct [22] for further details. + +------------------------------------------------------------------------------- + *devicons-contributing-guide-23* +Contributing Guide [23] ~ + +Read our contributing [23] guide to learn about how to send pull requests, +creating issues properly. + +------------------------------------------------------------------------------- + *devicons-promotion* +Promotion ~ + +You can help us by simply giving a star or voting on vim.org. It will ensure +continued development going forward. + +- Star this repository on GitHub [24]. +- Vote for it on vim.org [25]. + +=============================================================================== + *devicons-acknowledgments* +Acknowledgments ~ + +Thanks goes to these people for inspiration and helping with sending PRs. + +- vim-airline [2] +- nerdtree [1] +- nerdtree-git-plugin [26] by @Xuyuanp [27] +- seti-ui [28] by @jesseweed [29] +- devicons [30] by @vorillaz [31] +- development.svg.icons [32] by @benatespina [33] +- Learn Vimscript the Hard Way [34] book by Steve Losh [35] +- All contributors [36] + +=============================================================================== + *devicons-license* +License ~ + +MIT [37] + +=============================================================================== + *devicons-detailed-installation* +Detailed Installation ~ + +------------------------------------------------------------------------------- + *Nerd-Font* +Step 1 'Nerd Font' ~ + +Get a **Nerd Font!** [16] or patch your own. [17] Without this, things break + +------------------------------------------------------------------------------- + *VimDevIcons-Plugin* +Step 2 'VimDevIcons Plugin' ~ + +**Set VimDevIcons to load _after_ these plugins!** + +NERDTree [1] | vim-airline [2] | CtrlP [3] | powerline [4] | Denite [5] | unite +[6] | lightline.vim [7] | vim-startify [8] | vimfiler [9] | flagship [11] + +Choose your favorite plugin manager + +------------------------------------------------------------------------------- + *devicons-pathogen-38* +Pathogen [38] ~ + +- 'git clone https://github.com/ryanoasis/vim-devicons ~/.vim/bundle/vim- + devicons' + +------------------------------------------------------------------------------- + *devicons-neobundle-39* +NeoBundle [39] ~ + +- Add to vimrc: + + "vim NeoBundle 'ryanoasis/vim-devicons'" * And install it: + + 'vim :so ~/.vimrc :NeoBundleInstall' + +------------------------------------------------------------------------------- + *devicons-vundle-40* +Vundle [40] ~ + +- Add to vimrc: + + "vim Plugin 'ryanoasis/vim-devicons'" * And install it: + + 'vim :so ~/.vimrc :PlugInstall' + +------------------------------------------------------------------------------- + *devicons-manual* +Manual ~ + +- copy all of the files into your '~/.vim' directory + +------------------------------------------------------------------------------- + *Configure-Vim* +Step 3 'Configure Vim' ~ + +Add the following in your '.vimrc' or '.gvimrc': + +------------------------------------------------------------------------------- + *devicons-set-encoding* +Set Encoding ~ + +**Set encoding to UTF-8 to show glyphs** + +'vim set encoding=utf8' + +------------------------------------------------------------------------------- + *devicons-set-font* +Set Font ~ + +**Set Vim font to a Nerd Font** + +Linux 'vim set guifont=' +> + set guifont=DroidSansMono\ Nerd\ Font\ 11 +< +macOS (OS X) and Windows +> + set guifont=:h +< + +> + set guifont=DroidSansMono\ Nerd\ Font:h11 + " or: + set guifont=DroidSansMono_Nerd_Font:h11 +< +**Note:** if you don't set 'guifont' then you'll have to set your terminal's +font, else things break! + +------------------------------------------------------------------------------- + *devicons-vim-airline* +vim-airline ~ + +**If you use vim-airline you need this:** + +'vim let g:airline_powerline_fonts = 1' + +------------------------------------------------------------------------------- + *devicons-vimrc-examples* +vimrc examples ~ + +- Sample Windows vimrc configuration 1 [41] +- Sample Linux vimrc configuration 1 [42] + +------------------------------------------------------------------------------- + *devicons-thats-it-youre-done.* +That's it! You're done. ~ + +=============================================================================== + *devicons-usage* +Usage ~ + +If you installed and setup things correctly you should now see icons in the +supported plugins! + +**Notes on include order:** _for support of these plugins: NERDTree [1], vim- +airline [2], CtrlP [3], powerline [4], Denite [5], unite [6], vimfiler [9], +flagship [11] you **must** configure vim to load those plugins__before_ vim- +devicons loads. for better nerdtree-git-plugin [26] support, you _should_ +configure vim to load nerdtree-git-plugin **_before_** VimDevIcons loads. * if +you are lazy loading Denite [5] using the Dein plugin manager, you will need to +source VimDevIcons before Denite loads. + +Lightline Setup and Powerline Setup require some extra setup as shown below: + +------------------------------------------------------------------------------- + *devicons-nerdtree* +NERDTree ~ + +Should work "out of the box", no particular configuration should be needed. +> + " Can be enabled or disabled + let g:webdevicons_enable_nerdtree = 1 +< + +> + " whether or not to show the nerdtree brackets around flags + let g:webdevicons_conceal_nerdtree_brackets = 1 +< +------------------------------------------------------------------------------- + *devicons-unite* +Unite ~ + +Should work "out of the box", no particular configuration should be needed. +> + " Can be enabled or disabled + " adding the custom source to unite + let g:webdevicons_enable_unite = 1 +< +------------------------------------------------------------------------------- + *devicons-denite* +Denite ~ + +Should work "out of the box", no particular configuration should be needed. +> + " Can be enabled or disabled + " Adding the custom source to denite + let g:webdevicons_enable_denite = 1 +< +------------------------------------------------------------------------------- + *devicons-vimfiler* +Vimfiler ~ + +Should work "out of the box", no particular configuration should be needed. +> + " Can be enabled or disabled + " adding the column to vimfiler + let g:webdevicons_enable_vimfiler = 1 +< +------------------------------------------------------------------------------- + *devicons-ctrlp* +CtrlP ~ + +Should work "out of the box", no particular configuration should be needed. +> + " Can be enabled or disabled + " add glyphs to all modes + let g:webdevicons_enable_ctrlp = 1 +< +------------------------------------------------------------------------------- + *devicons-airline* +Airline ~ + +Should work "out of the box", no particular configuration should be needed. +> + " adding to vim-airline's tabline + let g:webdevicons_enable_airline_tabline = 1 +< + +> + " adding to vim-airline's statusline + let g:webdevicons_enable_airline_statusline = 1 +< +------------------------------------------------------------------------------- + *devicons-startify* +Startify ~ + +Should work "out of the box", no particular configuration should be needed. +> + " Can be enabled or disabled + " adding to vim-startify screen + let g:webdevicons_enable_startify = 1 +< +------------------------------------------------------------------------------- + *devicons-lightline-setup* +Lightline Setup ~ + +To add the appropriate icon to lightline [7], call the function +'WebDevIconsGetFileTypeSymbol()' and/or 'WebDevIconsGetFileFormatSymbol()' in +your '.vimrc'. For example, you could set your sections to: +> + let g:lightline = { + \ 'component_function': { + \ 'filetype': 'MyFiletype', + \ 'fileformat': 'MyFileformat', + \ } + \ } + + function! MyFiletype() + return winwidth(0) > 70 ? (strlen(&filetype) ? &filetype . ' ' . WebDevIconsGetFileTypeSymbol() : 'no ft') : '' + endfunction + + function! MyFileformat() + return winwidth(0) > 70 ? (&fileformat . ' ' . WebDevIconsGetFileFormatSymbol()) : '' + endfunction +< +------------------------------------------------------------------------------- + *devicons-powerline-setup* +Powerline Setup ~ + +- _Note this is for the current Powerline [4] not the deprecated vim- + powerline [43]_ + +To enable for Powerline [4] some |vimrc| and powerline configuration changes +are needed: + +|vimrc| changes (only required if you don't already have powerline setup for +vim): +> + set rtp+=$HOME/.local/lib/python2.7/site-packages/powerline/bindings/vim/ + + " Always show statusline + set laststatus=2 + + " Use 256 colours (Use this setting only if your terminal supports 256 colours) + set t_Co=256 +< +powerline configuration changes: + +file type segment +> + { + "function": "vim_devicons.powerline.segments.webdevicons", + "priority": 10, + "draw_soft_divider": false, + "after": " " + } +< +file format segment +> + { + "function": "vim_devicons.powerline.segments.webdevicons_file_format", + "draw_soft_divider": false, + "exclude_modes": ["nc"], + "priority": 90 + } +< +for full example see sample file [44] + +------------------------------------------------------------------------------- + *devicons-flagship* +Flagship ~ + +Should work "out of the box", no particular configuration should be needed. +> + " Can be enabled or disabled + " adding to flagship's statusline + let g:webdevicons_enable_flagship_statusline = 1 +< +=============================================================================== + *devicons-detailed-features* +Detailed Features ~ + +- Adds filetype glyphs (icons) to various vim plugins, currently supports: + +- NERDTree [1] + + - Using the version hosted on vimscripts [45] in favor of GitHub will + lead to a outdated message, and icons will fail to show. + +- vim-airline [2] (statusline and tabline) + +- CtrlP [3] (All modes now supported) + + - Using the version hosted on vimscripts [46] in favor of GitHub will + lead to a outdated message, and icons will fail to show. + +- powerline [4] (statusline) + + - see: powerline setup + +- Denite [5] + + - Currently supports 'file_rec', 'file_old', 'buffer', and + 'directory_rec' + +- unite [6] + + - Currently supports 'file', 'file_rec', 'buffer', 'file_rec/async', and + 'file_rec/neovim' + +- lightline.vim [7] (statusline) + + - see: lightline setup + +- vim-startify [8] + +- vimfiler [9] + +- flagship [11] + + - Support is **experimental** because the API may be changing [47] + +- vim-workspace [10] + +- Supports byte order marker (BOM) + +- Customizable and extendable glyphs (icons) settings + +- ability to override defaults and use your own characters or glyphs + +- Supports a wide range of file type extensions by default: + +- 'styl, sass, scss, htm, html, slim, ejs, css, less, md, rmd, json, js, jsx, + rb, php, py, pyc, pyd, pyo, coffee, mustache, hbs, conf, ini, yml, yaml, + bat, jpg, jpeg, bmp, png, gif, twig, cpp, c++, cxx, cc, cp, c, h, hpp, hxx, + hs, lhs, lua, java, sh, bash, zsh, ksh, csh, awk, ps1, fish, diff, db, clj, + cljs, edn, scala, go, dart, xul, sln, suo, pl, pm, t, rss, f#, fsscript, + fsx, fs, fsi, rs, rlib, d, erl, hrl, vim, ai, psd, psb, ts, jl, pp, vue, + swift, eex, ex, exs' + +- Supports a few full filename matches, by default: + +- 'gruntfile.coffee, gruntfile.js, gruntfile.ls, gulpfile.coffee, + gulpfile.js, gulpfile.ls, dropbox, .ds_store, .gitconfig, .gitignore, + .bashrc, .zshrc, .vimrc, .bashprofile, favicon.ico, license, node_modules, + react.jsx, procfile' + +- Supports a few library pattern matches, by default: + +- 'jquery, angular, backbone, requirejs, materialize, mootools, Vagrantfile' + +- Works with patched fonts, especially Nerd Fonts [13] + +=============================================================================== + *devicons-extra-configuration* +Extra Configuration ~ + +- These options can be defined in your |vimrc| or 'gvimrc' + +- Most options are enabled **'1'** by default but can be disabled with + **'0'** + +- You _should_**not** need to configure anything, however, the following + options are provided for customizing or changing the defaults: +> + " loading the plugin + let g:webdevicons_enable = 1 +< + +> + " adding the flags to NERDTree + let g:webdevicons_enable_nerdtree = 1 +< + +> + " adding the custom source to unite + let g:webdevicons_enable_unite = 1 +< + +> + " adding the column to vimfiler + let g:webdevicons_enable_vimfiler = 1 +< + +> + " adding to vim-airline's tabline + let g:webdevicons_enable_airline_tabline = 1 +< + +> + " adding to vim-airline's statusline + let g:webdevicons_enable_airline_statusline = 1 +< + +> + " ctrlp glyphs + let g:webdevicons_enable_ctrlp = 1 +< + +> + " adding to vim-startify screen + let g:webdevicons_enable_startify = 1 +< + +> + " adding to flagship's statusline + let g:webdevicons_enable_flagship_statusline = 1 +< + +> + " turn on/off file node glyph decorations (not particularly useful) + let g:WebDevIconsUnicodeDecorateFileNodes = 1 +< + +> + " use double-width(1) or single-width(0) glyphs + " only manipulates padding, has no effect on terminal or set(guifont) font + let g:WebDevIconsUnicodeGlyphDoubleWidth = 1 +< + +> + " whether or not to show the nerdtree brackets around flags + let g:webdevicons_conceal_nerdtree_brackets = 1 +< + +> + " the amount of space to use after the glyph character (default ' ') + let g:WebDevIconsNerdTreeAfterGlyphPadding = ' ' +< + +> + " Force extra padding in NERDTree so that the filetype icons line up vertically + let g:WebDevIconsNerdTreeGitPluginForceVAlign = 1 +< + +> + " Adding the custom source to denite + let g:webdevicons_enable_denite = 1 + + + + " the amount of space to use after the glyph character in vim-airline + tabline(default '') + let g:WebDevIconsTabAirLineAfterGlyphPadding = ' ' + + + + " the amount of space to use before the glyph character in vim-airline + tabline(default ' ') + let g:WebDevIconsTabAirLineBeforeGlyphPadding = ' ' +< +------------------------------------------------------------------------------- + *devicons-character-mappings* +Character Mappings ~ + +- 'ƛ' is used as an example below, substitute for the glyph you **actually** + want to use +> + " change the default character when no match found + let g:WebDevIconsUnicodeDecorateFileNodesDefaultSymbol = 'ƛ' +< + +> + " set a byte character marker (BOM) utf-8 symbol when retrieving file encoding + " disabled by default with no value + let g:WebDevIconsUnicodeByteOrderMarkerDefaultSymbol = '' +< + +> + " enable folder/directory glyph flag (disabled by default with 0) + let g:WebDevIconsUnicodeDecorateFolderNodes = 1 +< + +> + " enable open and close folder/directory glyph flags (disabled by default with 0) + let g:DevIconsEnableFoldersOpenClose = 1 +< + +> + " enable pattern matching glyphs on folder/directory (enabled by default with 1) + let g:DevIconsEnableFolderPatternMatching = 1 +< + +> + " enable file extension pattern matching glyphs on folder/directory (disabled by default with 0) + let g:DevIconsEnableFolderExtensionPatternMatching = 0 +< + +> + " disable showing the distribution for unix file encoding (enabled by default with 1) + let g:DevIconsEnableDistro = 0 +< + +> + " enable custom folder/directory glyph exact matching + " (enabled by default when g:WebDevIconsUnicodeDecorateFolderNodes is set to 1) + let WebDevIconsUnicodeDecorateFolderNodesExactMatches = 1 +< + +> + " change the default folder/directory glyph/icon + let g:WebDevIconsUnicodeDecorateFolderNodesDefaultSymbol = 'ƛ' +< + +> + " change the default open folder/directory glyph/icon (default is '') + let g:DevIconsDefaultFolderOpenSymbol = 'ƛ' +< + +> + " change the default dictionary mappings for file extension matches + + let g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols = {} " needed + let g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols['js'] = 'ƛ' +< + +> + " change the default dictionary mappings for exact file node matches + + let g:WebDevIconsUnicodeDecorateFileNodesExactSymbols = {} " needed + let g:WebDevIconsUnicodeDecorateFileNodesExactSymbols['MyReallyCoolFile.okay'] = 'ƛ' +< + +> + " add or override individual additional filetypes + + let g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols = {} " needed + let g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols['myext'] = 'ƛ' +< + +> + " add or override pattern matches for filetypes + " these take precedence over the file extensions + + let g:WebDevIconsUnicodeDecorateFileNodesPatternSymbols = {} " needed + let g:WebDevIconsUnicodeDecorateFileNodesPatternSymbols['.*jquery.*\.js$'] = 'ƛ' +< +specify OS to decide an icon for unix fileformat (_not_ defined by default) - +this is useful for avoiding unnecessary 'system()' call. see #135 [48] for +further details. +> + let g:WebDevIconsOS = 'Darwin' +< +------------------------------------------------------------------------------- + *devicons-api* +API ~ +> + " returns the font character that represents the icon + " parameters: a:1 (filename), a:2 (isDirectory) + " both parameters optional + " by default without parameters uses buffer name + WebDevIconsGetFileTypeSymbol(...) + + " returns the font character that represents + " the file format as an icon (windows, linux, mac) + WebDevIconsGetFileFormatSymbol() +< +------------------------------------------------------------------------------- + *devicons-public-methods* +Public Methods ~ +> + " Returns the current version of the plugin + webdevicons#version() +< + +> + " Calls webdevicons#softRefresh() + " basically a backwards compatibility convenience + webdevicons#refresh() +< + +> + " Does a 'hard' refresh of NERDTree + " resets vim-devicons syntax and closes and reopens NERDTree + webdevicons#hardRefresh() +< + +> + " Does a 'soft' refresh of NERDTree + " resets vim-devicons syntax and toggles NERDTree to the same state + webdevicons#softRefresh() +< +------------------------------------------------------------------------------- + *devicons-api-examples* +API Examples ~ + +------------------------------------------------------------------------------- + *devicons-status-line* +Status line ~ + +Custom vim status line (not relying on vim-airline or lightline): +> + set statusline=%f\ %{WebDevIconsGetFileTypeSymbol()}\ %h%w%m%r\ %=%(%l,%c%V\ %Y\ %=\ %P%) +< +------------------------------------------------------------------------------- + *devicons-simple-function-call* +Simple function call ~ +> + echo WebDevIconsGetFileFormatSymbol() +< +------------------------------------------------------------------------------- + *devicons-integration-with-other-plugins* +Integration with other plugins ~ + +------------------------------------------------------------------------------- + *devicons-vim-startify* +vim-startify ~ +> + let entry_format = "' ['. index .']'. repeat(' ', (3 - strlen(index)))" + + if exists('*WebDevIconsGetFileTypeSymbol') " support for vim-devicons + let entry_format .= ". WebDevIconsGetFileTypeSymbol(entry_path) .' '. entry_path" + else + let entry_format .= '. entry_path' + endif +< +=============================================================================== + *devicons-faq* +FAQ ~ + +**Table of Contents:** + +**It's not working at all:** + +- **Why isn't it working? How come I don't see any icons?** + +**Syntax or color highlighting:** + +- **How did you get color matching based on file type in NERDtree?** +- **How did you get color matching on just the glyph/icon in NERDtree?** + +**Re-sourcing |vimrc|:** + +- **How do I solve issues after re-sourcing my |vimrc|?** + +**Weird artifacts after/on the glyphs:** + +- **Why do I have artifacts after (or instead) of icons?** +- **Square brackets around icons?** + +**Fonts:** + +- **Do I have to use a patched font such as Nerd Fonts?** + +**Why does this exist? How did this start?** + +------------------------------------------------------------------------------- + *devicons-why-isnt-it-working-how-come-i-dont-see-any-icons* +Why isn't it working? How come I don't see any icons? ~ + +- Are you using the patched font provided in the separate repo (Nerd Fonts + [13]) or are you patching your own? + +- _NOTE:_ if running vim and no font set it will default to the terminal font + that is set + +- check what the vim/gvim font is set to, from ex mode: + + 'vim :set guifont?' + +- check if the plugin is loaded (should give '1'), from ex mode: + + 'vim :echo loaded_webdevicons' + +- check if the plugin is enabled (should give '1'), from ex mode: + + 'vim :echo g:webdevicons_enable' + +- check if the plugin is enabled for NERDTree (should give '1'), from ex + mode: + + - this should _NOT_ need to be set under normal circumstances + + 'vim :echo g:webdevicons_enable_nerdtree' + +- check if you are able to see the characters, from ex mode: + + 'vim :echo g:WebDevIconsUnicodeDecorateFileNodesDefaultSymbol' + +- if all this looks correct you may try this to see if any files show flags + + - last resort, see if you can even set the default symbol and have it + display anywhere (NERDTree, vim-airline's statusline, vim-airlines's + tabline), from ex mode: + + "vim :let g:WebDevIconsUnicodeDecorateFileNodesDefaultSymbol='x'" + +------------------------------------------------------------------------------- + *devicons-how-did-you-get-color-matching-based-on-file-type-in-nerdtree* +How did you get color matching based on file type in NERDtree? ~ + +- You can either use this additional plugin: vim-nerdtree-syntax-highlight + [49] created by @tiagofumo [50] + +- Or you can use my current settings from: + https://github.com/scrooloose/nerdtree/issues/201#issuecomment-9954740 + + ```vim " NERDTress File highlighting function! + NERDTreeHighlightFile(extension, fg, bg, guifg, guibg) exec 'autocmd + FileType nerdtree highlight ' . a:extension .' ctermbg='. a:bg .' + ctermfg='. a:fg .' guibg='. a:guibg .' guifg='. a:guifg exec 'autocmd + FileType nerdtree syn match ' . a:extension .' #^\s+.*'. a:extension .'$#' + endfunction + + call NERDTreeHighlightFile('jade', 'green', 'none', 'green', '#151515') + call NERDTreeHighlightFile('ini', 'yellow', 'none', 'yellow', '#151515') + call NERDTreeHighlightFile('md', 'blue', 'none', '#3366FF', '#151515') call + NERDTreeHighlightFile('yml', 'yellow', 'none', 'yellow', '#151515') call + NERDTreeHighlightFile('config', 'yellow', 'none', 'yellow', '#151515') call + NERDTreeHighlightFile('conf', 'yellow', 'none', 'yellow', '#151515') call + NERDTreeHighlightFile('json', 'yellow', 'none', 'yellow', '#151515') call + NERDTreeHighlightFile('html', 'yellow', 'none', 'yellow', '#151515') call + NERDTreeHighlightFile('styl', 'cyan', 'none', 'cyan', '#151515') call + NERDTreeHighlightFile('css', 'cyan', 'none', 'cyan', '#151515') call + NERDTreeHighlightFile('coffee', 'Red', 'none', 'red', '#151515') call + NERDTreeHighlightFile('js', 'Red', 'none', '#ffa500', '#151515') call + NERDTreeHighlightFile('php', 'Magenta', 'none', '#ff00ff', '#151515') call + NERDTreeHighlightFile('ds_store', 'Gray', 'none', '#686868', '#151515') + call NERDTreeHighlightFile('gitconfig', 'Gray', 'none', '#686868', + '#151515') call NERDTreeHighlightFile('gitignore', 'Gray', 'none', + '#686868', '#151515') call NERDTreeHighlightFile('bashrc', 'Gray', 'none', + '#686868', '#151515') call NERDTreeHighlightFile('bashprofile', 'Gray', + 'none', '#686868', '#151515') 'Note: If the colors still are not + highlighting, try invoking such as:' autocmd VimEnter * call + NERDTreeHighlightFile('jade', 'green', 'none', 'green', '#151515') ``` per: + https://github.com/ryanoasis/vim-devicons/issues/49#issuecomment-101753558 + +------------------------------------------------------------------------------- + *devicons-how-did-you-get-color-matching-on-just-glyph-icon-in-nerdtree* +How did you get color matching on just the glyph/icon in NERDtree? ~ + +- You can add something like this to your |vimrc| + + ```vim " NERDTress File highlighting only the glyph/icon " test highlight + just the glyph (icons) in nerdtree: autocmd filetype nerdtree highlight + haskell_icon ctermbg=none ctermfg=Red guifg=#ffa500 autocmd filetype + nerdtree highlight html_icon ctermbg=none ctermfg=Red guifg=#ffa500 autocmd + filetype nerdtree highlight go_icon ctermbg=none ctermfg=Red guifg=#ffa500 + + autocmd filetype nerdtree syn match haskell_icon ## + containedin=NERDTreeFile " if you are using another syn highlight for a + given line (e.g. " NERDTreeHighlightFile) need to give that name in the + 'containedin' for this " other highlight to work with it autocmd filetype + nerdtree syn match html_icon ## containedin=NERDTreeFile,html autocmd + filetype nerdtree syn match go_icon ## containedin=NERDTreeFile ``` + +------------------------------------------------------------------------------- +How do I solve issues after re-sourcing my *vimrc*? + +- Try adding this to the bottom of your |vimrc| + + 'vim if exists("g:loaded_webdevicons") call webdevicons#refresh() endif' + +------------------------------------------------------------------------------- + *devicons-why-do-i-have-artifacts-after-of-icons* +Why do I have artifacts after (or instead) of icons? ~ + +- Dots after icons in NERDTree (on GVim), try: + +'vim autocmd FileType nerdtree setlocal nolist' + +source: Issue #110 [51] + +- Newly created files in NERDTree are slow to show the glyph (icon) +- check your current setting of ':updatetime?' +- try setting 'updatetime' in your |vimrc| to a lower value like '250', for + more info see: Issue #153 [52] + +------------------------------------------------------------------------------- + *devicons-square-brackets-around-icons* +Square brackets around icons ~ + +- By default if your Vim supports conceal you should not see these, debug + steps: + + - Check if the plugin feature is set (should be '1'): + + 'vim echo g:webdevicons_conceal_nerdtree_brackets' + + - Check that your vim was compiled with the 'conceal' feature (should be + '+conceal'): + + ```shell + +------------------------------------------------------------------------------- + *devicons-from-terminal* + from terminal ~ + + vim --version | grep conceal ``` + + - Check the 'conceallevel' (should be '3'): + + 'vim set conceallevel?' + +------------------------------------------------------------------------------- + *devicons-do-i-have-to-use-patched-font-such-as-nerd-fonts* +Do I have to use a patched font such as Nerd Fonts? ~ + +VimDevIcons was desired to work with Nerd Fonts [13], however you do _not_ have +to use a patched font or even Nerd Fonts specified glyphs. You have 2 main +options: + +fontconfig fallback + +1. Install the NERD Font symbol fonts: + +2. Symbols Nerd Font:style=1000-em [53] + +3. Symbols Nerd Font:style=2048-em [54] + +4. Install 10-nerd-font-symbols.conf [55] for Fontconfig + +5. for additional information see: Issue #124 [56] and [Nerd Fonts + 'fontconfig'] + +Use your own glyph codepoints + +- specify your own glyphs and/or use your own font (see: Character Mappings + [57]) + +------------------------------------------------------------------------------- + *devicons-rationale-why-does-this-exist-how-did-this-start* +Rationale: Why does this exist? How did this start? ~ + +After seeing the awesome theme for Atom (seti-ui) and the awesome plugins work +done for NERDTree and vim-airline and wanting something like this for Vim I +decided to create my first plugin. + +=============================================================================== + *devicons-references* +References ~ + +[1] https://github.com/scrooloose/nerdtree +[2] https://github.com/vim-airline/vim-airline +[3] https://github.com/ctrlpvim/ctrlp.vim +[4] https://github.com/powerline/powerline +[5] https://github.com/Shougo/denite.nvim +[6] https://github.com/Shougo/unite.vim +[7] https://github.com/itchyny/lightline.vim +[8] https://github.com/mhinz/vim-startify +[9] https://github.com/Shougo/vimfiler.vim +[10] https://github.com/bagrat/vim-workspace +[11] https://github.com/tpope/vim-flagship +[12] https://github.com/ryanoasis/vim-devicons/wiki/screenshots +[13] https://github.com/ryanoasis/nerd-fonts +[14] https://github.com/ryanoasis/vim-devicons/wiki/Detailed-Features +[15] https://github.com/ryanoasis/vim-devicons/wiki/Extra-Configuration +[16] https://github.com/ryanoasis/nerd-fonts#font-installation +[17] https://github.com/ryanoasis/nerd-fonts#font-patcher +[18] https://github.com/junegunn/vim-plug +[19] https://github.com/ryanoasis/vim-devicons/wiki/Installation +[20] DEVELOPER.md +[21] https://github.com/ryanoasis/vim-devicons/wiki/FAQ-&-Troubleshooting +[22] CODE_OF_CONDUCT.md +[23] CONTRIBUTING.md +[24] https://github.com/ryanoasis/vim-devicons +[25] http://www.vim.org/scripts/script.php?script_id=5114 +[26] https://github.com/Xuyuanp/nerdtree-git-plugin +[27] https://github.com/Xuyuanp +[28] https://atom.io/themes/seti-ui +[29] https://github.com/jesseweed +[30] http://vorillaz.github.io/devicons +[31] https://github.com/vorillaz +[32] https://github.com/benatespina/development.svg.icons +[33] https://github.com/benatespina +[34] http://learnvimscriptthehardway.stevelosh.com/ +[35] http://stevelosh.com/ +[36] https://github.com/ryanoasis/vim-devicons/graphs/contributors +[37] LICENSE +[38] https://github.com/tpope/vim-pathogen +[39] https://github.com/Shougo/neobundle.vim +[40] https://github.com/gmarik/vundle +[41] https://github.com/ryanoasis/vim-devicons/wiki/samples/v0.10.x/.vimrc-windows-1 +[42] https://github.com/ryanoasis/vim-devicons/wiki/samples/v0.10.x/.vimrc-linux-1 +[43] https://github.com/Lokaltog/vim-powerline +[44] https://github.com/ryanoasis/vim-devicons/wiki/samples/v0.10.x/powerline/themes/vim/default.json +[45] http://www.vim.org/scripts/script.php?script_id=1658 +[46] http://www.vim.org/scripts/script.php?script_id=3736 +[47] https://github.com/tpope/vim-flagship/issues/6#issuecomment-116121220 +[48] https://github.com/ryanoasis/vim-devicons/pull/135 +[49] https://github.com/tiagofumo/vim-nerdtree-syntax-highlight +[50] https://github.com/tiagofumo +[51] https://github.com/ryanoasis/vim-devicons/issues/110#issue-103801335 +[52] https://github.com/ryanoasis/vim-devicons/issues/153 +[53] https://github.com/ryanoasis/nerd-fonts/blob/master/src/glyphs/Symbols-1000-em%20Nerd%20Font%20Complete.ttf +[54] https://github.com/ryanoasis/nerd-fonts/blob/master/src/glyphs/Symbols-2048-em%20Nerd%20Font%20Complete.ttf +[55] https://github.com/ryanoasis/nerd-fonts/blob/master/10-nerd-font-symbols.conf +[56] https://github.com/ryanoasis/vim-devicons/issues/124 +[57] https://github.com/ryanoasis/vim-devicons#character-mappings + +vim: ft=help diff --git a/nvim/.vim/plugged/vim-devicons/nerdtree_plugin/webdevicons.vim b/nvim/.vim/plugged/vim-devicons/nerdtree_plugin/webdevicons.vim new file mode 100644 index 0000000..aafea2c --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/nerdtree_plugin/webdevicons.vim @@ -0,0 +1,389 @@ +" Version: 0.11.0 +" Webpage: https://github.com/ryanoasis/vim-devicons +" Maintainer: Ryan McIntyre +" License: see LICENSE + +" @todo fix duplicate global variable initialize here: +if !exists('g:webdevicons_enable') + let g:webdevicons_enable = 1 +endif + +if !exists('g:webdevicons_enable_nerdtree') + let g:webdevicons_enable_nerdtree = 1 +endif + +if !exists('g:DevIconsEnableFoldersOpenClose') + let g:DevIconsEnableFoldersOpenClose = 0 +endif + +if !exists('g:DevIconsEnableFolderPatternMatching') + let g:DevIconsEnableFolderPatternMatching = 1 +endif + +if !exists('g:DevIconsEnableFolderExtensionPatternMatching') + let g:DevIconsEnableFolderExtensionPatternMatching = 0 +endif + +" end @todo duplicate global variables + +" Temporary (hopefully) fix for glyph issues in gvim (proper fix is with the +" actual font patcher) +if !exists('g:webdevicons_gui_glyph_fix') + if has('gui_running') + let g:webdevicons_gui_glyph_fix = 1 + else + let g:webdevicons_gui_glyph_fix = 0 + endif +endif + +if !exists('g:DevIconsEnableNERDTreeRedraw') + if has('gui_running') + let g:DevIconsEnableNERDTreeRedraw = 1 + else + let g:DevIconsEnableNERDTreeRedraw = 0 + endif +endif + +if g:webdevicons_enable_nerdtree == 1 + if !exists('g:loaded_nerd_tree') + echohl WarningMsg | + \ echomsg 'vim-webdevicons requires NERDTree to be loaded before vim-webdevicons.' + endif + + if exists('g:loaded_nerd_tree') && g:loaded_nerd_tree == 1 && !exists('g:NERDTreePathNotifier') + let g:webdevicons_enable_nerdtree = 0 + echohl WarningMsg | + \ echomsg 'vim-webdevicons requires a newer version of NERDTree to show glyphs in NERDTree - consider updating NERDTree.' + endif + + " @todo I don't even want this to execute UNLESS the user has the + " 'nerdtree-git-plugin' INSTALLED (not LOADED) + " As it currently functions this warning will display even if the user does + " not have nerdtree-git-plugin not just if it isn't loaded yet + " (not what we want) + "if !exists('g:loaded_nerdtree_git_status') + " echohl WarningMsg | + " \ echomsg 'vim-webdevicons works better when 'nerdtree-git-plugin' is loaded before vim-webdevicons (small refresh issues otherwise).' + "endif +endif + +if !exists('g:webdevicons_enable_airline_tabline') + let g:webdevicons_enable_airline_tabline = 1 +endif + +if !exists('g:webdevicons_enable_airline_statusline') + let g:webdevicons_enable_airline_statusline = 1 +endif + +function! s:SetupListeners() + call g:NERDTreePathNotifier.AddListener('init', 'NERDTreeWebDevIconsRefreshListener') + call g:NERDTreePathNotifier.AddListener('refresh', 'NERDTreeWebDevIconsRefreshListener') + call g:NERDTreePathNotifier.AddListener('refreshFlags', 'NERDTreeWebDevIconsRefreshListener') +endfunction + +" util like helpers +" scope: local +function! s:Refresh() + call b:NERDTree.root.refreshFlags() + call NERDTreeRender() +endfunction + +" Temporary (hopefully) fix for glyph issues in gvim (proper fix is with the +" actual font patcher) + +" NERDTree-C +" scope: global +function! WebDevIconsNERDTreeChangeRootHandler(node) + call b:NERDTree.changeRoot(a:node) + call NERDTreeRender() + call a:node.putCursorHere(0, 0) + if g:DevIconsEnableNERDTreeRedraw ==# 1 + redraw! + endif +endfunction + +" NERDTree-u +" scope: global +function! WebDevIconsNERDTreeUpDirCurrentRootClosedHandler() + call nerdtree#ui_glue#upDir(0) + if g:DevIconsEnableNERDTreeRedraw ==# 1 + redraw! + endif +endfunction + +function! WebDevIconsNERDTreeDirUpdateFlags(node, glyph) + let path = a:node.path + let isOpen = a:node.isOpen + let postPadding = g:WebDevIconsNerdTreeAfterGlyphPadding + let prePadding = g:WebDevIconsNerdTreeBeforeGlyphPadding + let hasGitFlags = (len(path.flagSet._flagsForScope('git')) > 0) + let hasGitNerdTreePlugin = (exists('g:loaded_nerdtree_git_status') == 1) + let collapsesToSameLine = (exists('g:NERDTreeCascadeSingleChildDir') == 1) + let dirHasOnlyOneChildDir = 0 + + if collapsesToSameLine + " need to call to determin children: + call a:node._initChildren(1) + let dirHasOnlyOneChildDir = (a:node.getChildCount() ==# 1 && a:node.children[0].path.isDirectory) + endif + + " properly set collapsed/combined directory display to opened glyph + if collapsesToSameLine && dirHasOnlyOneChildDir + call WebDevIconsNERDTreeDirOpen(a:node.children[0]) + endif + + " align vertically at the same level: non git-flag nodes with git-flag nodes + if g:WebDevIconsNerdTreeGitPluginForceVAlign && !hasGitFlags && hasGitNerdTreePlugin + let prePadding .= ' ' + endif + + let flag = prePadding . a:glyph . postPadding + + call a:node.path.flagSet.clearFlags('webdevicons') + + if flag !=? '' + call a:node.path.flagSet.addFlag('webdevicons', flag) + "echom "added flag of " . flag + call a:node.path.refreshFlags(b:NERDTree) + "echom "flagset is now " . string(a:node.path.flagSet) + endif +endfunction + +function! WebDevIconsNERDTreeDirClose(node) + let a:node.path.isOpen = 0 + let glyph = g:WebDevIconsUnicodeDecorateFolderNodesDefaultSymbol + call WebDevIconsNERDTreeDirUpdateFlags(a:node, glyph) +endfunction + +function! WebDevIconsNERDTreeDirOpen(node) + let a:node.path.isOpen = 1 + let glyph = g:DevIconsDefaultFolderOpenSymbol + call WebDevIconsNERDTreeDirUpdateFlags(a:node, glyph) +endfunction + +function! WebDevIconsNERDTreeDirOpenRecursively(node) + call WebDevIconsNERDTreeDirOpen(a:node) + for i in a:node.children + if i.path.isDirectory ==# 1 + call WebDevIconsNERDTreeDirOpenRecursively(i) + endif + endfor +endfunction + +function! WebDevIconsNERDTreeDirCloseRecursively(node) + call WebDevIconsNERDTreeDirClose(a:node) + for i in a:node.children + if i.path.isDirectory ==# 1 + call WebDevIconsNERDTreeDirCloseRecursively(i) + endif + endfor +endfunction + +function! WebDevIconsNERDTreeDirCloseChildren(node) + for i in a:node.children + if i.path.isDirectory ==# 1 + call WebDevIconsNERDTreeDirClose(i) + endif + endfor +endfunction + +" NERDTreeMapActivateNode and <2-LeftMouse> +" handle the user activating a tree node +" scope: global +function! WebDevIconsNERDTreeMapActivateNode(node) + let isOpen = a:node.isOpen + if isOpen + let glyph = g:WebDevIconsUnicodeDecorateFolderNodesDefaultSymbol + else + let glyph = g:DevIconsDefaultFolderOpenSymbol + endif + let a:node.path.isOpen = !isOpen + call WebDevIconsNERDTreeDirUpdateFlags(a:node, glyph) + " continue with normal activate logic + call a:node.activate() + " glyph change possible artifact clean-up + if g:DevIconsEnableNERDTreeRedraw ==# 1 + redraw! + endif +endfunction + +" NERDTreeMapActivateNodeSingleMode +" handle the user activating a tree node if NERDTreeMouseMode is setted to 3 +" scope: global +function! WebDevIconsNERDTreeMapActivateNodeSingleMode(node) + if g:NERDTreeMouseMode == 3 + let isOpen = a:node.isOpen + if isOpen + let glyph = g:WebDevIconsUnicodeDecorateFolderNodesDefaultSymbol + else + let glyph = g:DevIconsDefaultFolderOpenSymbol + endif + let a:node.path.isOpen = !isOpen + call WebDevIconsNERDTreeDirUpdateFlags(a:node, glyph) + " continue with normal activate logic + call a:node.activate() + " glyph change possible artifact clean-up + if g:DevIconsEnableNERDTreeRedraw ==# 1 + redraw! + endif + endif +endfunction + +function! WebDevIconsNERDTreeMapOpenRecursively(node) + " normal original logic: + call nerdtree#echo('Recursively opening node. Please wait...') + call WebDevIconsNERDTreeDirOpenRecursively(a:node) + call a:node.openRecursively() + " continue with normal original logic: + call b:NERDTree.render() + " glyph change possible artifact clean-up + if g:DevIconsEnableNERDTreeRedraw ==# 1 + redraw! + endif + call nerdtree#echo('Recursively opening node. Please wait... DONE') +endfunction + +function! WebDevIconsNERDTreeMapCloseChildren(node) + " close children but not current node: + call WebDevIconsNERDTreeDirCloseChildren(a:node) + " continue with normal original logic: + call a:node.closeChildren() + call b:NERDTree.render() + call a:node.putCursorHere(0, 0) + " glyph change possible artifact clean-up + if g:DevIconsEnableNERDTreeRedraw ==# 1 + redraw! + endif +endfunction + +function! WebDevIconsNERDTreeMapCloseDir(node) + " continue with normal original logic: + let parent = a:node.parent + while g:NERDTreeCascadeOpenSingleChildDir && !parent.isRoot() + let childNodes = parent.getVisibleChildren() + if len(childNodes) == 1 && childNodes[0].path.isDirectory + let parent = parent.parent + else + break + endif + endwhile + if parent ==# {} || parent.isRoot() + call nerdtree#echo('cannot close tree root') + else + call parent.close() + " update the glyph + call WebDevIconsNERDTreeDirClose(parent) + call b:NERDTree.render() + call parent.putCursorHere(0, 0) + " glyph change possible artifact clean-up + if g:DevIconsEnableNERDTreeRedraw ==# 1 + redraw! + endif + endif +endfunction + +function! WebDevIconsNERDTreeMapUpdirKeepOpen() + call WebDevIconsNERDTreeDirOpen(b:NERDTree.root) + " continue with normal logic: + call nerdtree#ui_glue#upDir(1) + call s:Refresh() + " glyph change possible artifact clean-up + if g:DevIconsEnableNERDTreeRedraw ==# 1 + redraw! + endif +endfunction + +if g:webdevicons_enable == 1 && g:webdevicons_enable_nerdtree == 1 + call s:SetupListeners() + + if g:DevIconsEnableFoldersOpenClose + + " These overrides are needed because we cannot + " simply use AddListener for reliably updating + " the folder open/close glyphs because the event + " path has no access to the 'isOpen' property + " some of these are a little more brittle/fragile + " than others + " TODO FIXME better way to reliably update + " open/close glyphs in NERDTreeWebDevIconsRefreshListener + + " NERDTreeMapActivateNode + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapActivateNode, + \ 'callback': 'WebDevIconsNERDTreeMapActivateNode', + \ 'override': 1, + \ 'scope': 'DirNode' }) + + " NERDTreeMapCustomOpen + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapCustomOpen, + \ 'callback': 'WebDevIconsNERDTreeMapActivateNode', + \ 'override': 1, + \ 'scope': 'DirNode' }) + + " NERDTreeMapOpenRecursively + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapOpenRecursively, + \ 'callback': 'WebDevIconsNERDTreeMapOpenRecursively', + \ 'override': 1, + \ 'scope': 'DirNode' }) + + " NERDTreeMapCloseChildren + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapCloseChildren, + \ 'callback': 'WebDevIconsNERDTreeMapCloseChildren', + \ 'override': 1, + \ 'scope': 'DirNode' }) + + " NERDTreeMapCloseChildren + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapCloseDir, + \ 'callback': 'WebDevIconsNERDTreeMapCloseDir', + \ 'override': 1, + \ 'scope': 'Node' }) + + " <2-LeftMouse> + call NERDTreeAddKeyMap({ + \ 'key': '<2-LeftMouse>', + \ 'callback': 'WebDevIconsNERDTreeMapActivateNode', + \ 'override': 1, + \ 'scope': 'DirNode' }) + + " + call NERDTreeAddKeyMap({ + \ 'key': '', + \ 'callback': 'WebDevIconsNERDTreeMapActivateNodeSingleMode', + \ 'override': 1, + \ 'scope': 'DirNode' }) + + " NERDTreeMapUpdirKeepOpen + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapUpdirKeepOpen, + \ 'callback': 'WebDevIconsNERDTreeMapUpdirKeepOpen', + \ 'override': 1, + \ 'scope': 'all' }) + + endif + + " Temporary (hopefully) fix for glyph issues in gvim (proper fix is with the + " actual font patcher) + if g:webdevicons_gui_glyph_fix ==# 1 + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapChangeRoot, + \ 'callback': 'WebDevIconsNERDTreeChangeRootHandler', + \ 'override': 1, + \ 'quickhelpText': "change tree root to the\n\" selected dir\n\" plus devicons redraw\n\" hack fix", + \ 'scope': 'Node' }) + + call NERDTreeAddKeyMap({ + \ 'key': g:NERDTreeMapUpdir, + \ 'callback': 'WebDevIconsNERDTreeUpDirCurrentRootClosedHandler', + \ 'override': 1, + \ 'quickhelpText': "move tree root up a dir\n\" plus devicons redraw\n\" hack fix", + \ 'scope': 'all' }) + endif + +endif + +" modeline syntax: +" vim: fdm=marker tabstop=2 softtabstop=2 shiftwidth=2 expandtab: diff --git a/nvim/.vim/plugged/vim-devicons/plugin/webdevicons.vim b/nvim/.vim/plugged/vim-devicons/plugin/webdevicons.vim new file mode 100644 index 0000000..27f01ba --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/plugin/webdevicons.vim @@ -0,0 +1,703 @@ +" Version: 0.11.0 +" Webpage: https://github.com/ryanoasis/vim-devicons +" Maintainer: Ryan McIntyre +" License: see LICENSE + +let s:version = '0.11.0' +let s:plugin_home = expand(':p:h:h') + +" set scriptencoding after 'encoding' and when using multibyte chars +scriptencoding utf-8 + +" standard fix/safety: line continuation (avoiding side effects) {{{1 +"======================================================================== +let s:save_cpo = &cpo +set cpo&vim + +" standard loading / not loading {{{1 +"======================================================================== + +if exists('g:loaded_webdevicons') + finish +endif + +let g:loaded_webdevicons = 1 + +" config enable / disable settings {{{1 +"======================================================================== + +"" +" Set the variable to the default value, only if variable is not defined. +" +" @param {string} var Variable name with its scope. +" @param {*} default Default value for variable. +"" +function! s:set(var, default) abort + if !exists(a:var) + if type(a:default) + execute 'let' a:var '=' string(a:default) + else + execute 'let' a:var '=' a:default + endif + endif +endfunction + +call s:set('g:webdevicons_enable', 1) +call s:set('g:webdevicons_enable_nerdtree', 1) +call s:set('g:webdevicons_enable_unite ', 1) +call s:set('g:webdevicons_enable_denite', 1) +call s:set('g:webdevicons_enable_vimfiler', 1) +call s:set('g:webdevicons_enable_ctrlp', 1) +call s:set('g:webdevicons_enable_airline_tabline', 1) +call s:set('g:webdevicons_enable_airline_statusline', 1) +call s:set('g:webdevicons_enable_airline_statusline_fileformat_symbols', 1) +call s:set('g:webdevicons_enable_flagship_statusline', 1) +call s:set('g:webdevicons_enable_flagship_statusline_fileformat_symbols', 1) +call s:set('g:webdevicons_enable_startify', 1) +call s:set('g:webdevicons_conceal_nerdtree_brackets', 1) +call s:set('g:DevIconsAppendArtifactFix', has('gui_running') ? 1 : 0) +call s:set('g:DevIconsArtifactFixChar', ' ') + +" config options {{{1 +"======================================================================== + +call s:set('g:WebDevIconsUnicodeDecorateFileNodes', 1) +call s:set('g:WebDevIconsUnicodeDecorateFolderNodes', 1) +call s:set('g:DevIconsEnableFoldersOpenClose', 0) +call s:set('g:DevIconsEnableFolderPatternMatching', 1) +call s:set('g:DevIconsEnableFolderExtensionPatternMatching', 0) +call s:set('g:DevIconsEnableDistro', 1) +call s:set('g:WebDevIconsUnicodeDecorateFolderNodesExactMatches', 1) +call s:set('g:WebDevIconsUnicodeGlyphDoubleWidth', 1) +call s:set('g:WebDevIconsNerdTreeBeforeGlyphPadding', ' ') +call s:set('g:WebDevIconsNerdTreeAfterGlyphPadding', ' ') +call s:set('g:WebDevIconsNerdTreeGitPluginForceVAlign', 1) +call s:set('g:NERDTreeUpdateOnCursorHold', 1) " Obsolete: For backward compatibility +call s:set('g:NERDTreeGitStatusUpdateOnCursorHold', 1) +call s:set('g:WebDevIconsTabAirLineBeforeGlyphPadding', ' ') +call s:set('g:WebDevIconsTabAirLineAfterGlyphPadding', '') + +" config defaults {{{1 +"======================================================================== + +call s:set('g:WebDevIconsUnicodeDecorateFileNodesDefaultSymbol', '') +call s:set('g:WebDevIconsUnicodeByteOrderMarkerDefaultSymbol', '') +call s:set('g:WebDevIconsUnicodeDecorateFolderNodesDefaultSymbol', g:DevIconsEnableFoldersOpenClose ? '' : '') +call s:set('g:WebDevIconsUnicodeDecorateFolderNodesSymlinkSymbol', '') +call s:set('g:DevIconsDefaultFolderOpenSymbol', '') + +" functions {{{1 +"======================================================================== + +" local functions {{{2 +"======================================================================== + +" scope: local +function s:getDistro() + if exists('s:distro') + return s:distro + endif + + if has('bsd') + let s:distro = '' + return s:distro + endif + + if g:DevIconsEnableDistro && executable('lsb_release') + let s:lsb = system('lsb_release -i') + if s:lsb =~# 'Arch' + let s:distro = '' + elseif s:lsb =~# 'Gentoo' + let s:distro = '' + elseif s:lsb =~# 'Ubuntu' + let s:distro = '' + elseif s:lsb =~# 'Cent' + let s:distro = '' + elseif s:lsb =~# 'Debian' + let s:distro = '' + elseif s:lsb =~# 'Dock' + let s:distro = '' + else + let s:distro = '' + endif + return s:distro + endif + + let s:distro = '' + return s:distro +endfunction + +" scope: local +function s:isDarwin() + if exists('s:is_darwin') + return s:is_darwin + endif + + if exists('g:WebDevIconsOS') + let s:is_darwin = g:WebDevIconsOS ==? 'Darwin' + return s:is_darwin + endif + + if has('macunix') + let s:is_darwin = 1 + return s:is_darwin + endif + + if ! has('unix') + let s:is_darwin = 0 + return s:is_darwin + endif + + if system('uname -s') ==# "Darwin\n" + let s:is_darwin = 1 + else + let s:is_darwin = 0 + endif + + return s:is_darwin +endfunction + +" scope: local +function! s:strip(input) + return substitute(a:input, '^\s*\(.\{-}\)\s*$', '\1', '') +endfunction + +" scope: local +function! s:setDictionaries() + + let s:file_node_extensions = { + \ 'styl' : '', + \ 'sass' : '', + \ 'scss' : '', + \ 'htm' : '', + \ 'html' : '', + \ 'slim' : '', + \ 'haml' : '', + \ 'ejs' : '', + \ 'css' : '', + \ 'less' : '', + \ 'md' : '', + \ 'mdx' : '', + \ 'markdown' : '', + \ 'rmd' : '', + \ 'json' : '', + \ 'webmanifest' : '', + \ 'js' : '', + \ 'mjs' : '', + \ 'jsx' : '', + \ 'rb' : '', + \ 'gemspec' : '', + \ 'rake' : '', + \ 'php' : '', + \ 'py' : '', + \ 'pyc' : '', + \ 'pyo' : '', + \ 'pyd' : '', + \ 'coffee' : '', + \ 'mustache' : '', + \ 'hbs' : '', + \ 'conf' : '', + \ 'ini' : '', + \ 'yml' : '', + \ 'yaml' : '', + \ 'toml' : '', + \ 'bat' : '', + \ 'mk' : '', + \ 'jpg' : '', + \ 'jpeg' : '', + \ 'bmp' : '', + \ 'png' : '', + \ 'webp' : '', + \ 'gif' : '', + \ 'ico' : '', + \ 'twig' : '', + \ 'cpp' : '', + \ 'c++' : '', + \ 'cxx' : '', + \ 'cc' : '', + \ 'cp' : '', + \ 'c' : '', + \ 'cs' : '', + \ 'h' : '', + \ 'hh' : '', + \ 'hpp' : '', + \ 'hxx' : '', + \ 'hs' : '', + \ 'lhs' : '', + \ 'nix' : '', + \ 'lua' : '', + \ 'java' : '', + \ 'sh' : '', + \ 'fish' : '', + \ 'bash' : '', + \ 'zsh' : '', + \ 'ksh' : '', + \ 'csh' : '', + \ 'awk' : '', + \ 'ps1' : '', + \ 'ml' : 'λ', + \ 'mli' : 'λ', + \ 'diff' : '', + \ 'db' : '', + \ 'sql' : '', + \ 'dump' : '', + \ 'clj' : '', + \ 'cljc' : '', + \ 'cljs' : '', + \ 'edn' : '', + \ 'scala' : '', + \ 'go' : '', + \ 'dart' : '', + \ 'xul' : '', + \ 'sln' : '', + \ 'suo' : '', + \ 'pl' : '', + \ 'pm' : '', + \ 't' : '', + \ 'rss' : '', + \ 'f#' : '', + \ 'fsscript' : '', + \ 'fsx' : '', + \ 'fs' : '', + \ 'fsi' : '', + \ 'rs' : '', + \ 'rlib' : '', + \ 'd' : '', + \ 'erl' : '', + \ 'hrl' : '', + \ 'ex' : '', + \ 'exs' : '', + \ 'eex' : '', + \ 'leex' : '', + \ 'heex' : '', + \ 'vim' : '', + \ 'ai' : '', + \ 'psd' : '', + \ 'psb' : '', + \ 'ts' : '', + \ 'tsx' : '', + \ 'jl' : '', + \ 'pp' : '', + \ 'vue' : '﵂', + \ 'elm' : '', + \ 'swift' : '', + \ 'xcplayground' : '', + \ 'tex' : 'ﭨ', + \ 'r' : 'ﳒ', + \ 'rproj' : '鉶', + \ 'sol' : 'ﲹ', + \ 'pem' : '' + \} + + let s:file_node_exact_matches = { + \ 'exact-match-case-sensitive-1.txt' : '1', + \ 'exact-match-case-sensitive-2' : '2', + \ 'gruntfile.coffee' : '', + \ 'gruntfile.js' : '', + \ 'gruntfile.ls' : '', + \ 'gulpfile.coffee' : '', + \ 'gulpfile.js' : '', + \ 'gulpfile.ls' : '', + \ 'mix.lock' : '', + \ 'dropbox' : '', + \ '.ds_store' : '', + \ '.gitconfig' : '', + \ '.gitignore' : '', + \ '.gitattributes' : '', + \ '.gitlab-ci.yml' : '', + \ '.bashrc' : '', + \ '.zshrc' : '', + \ '.zshenv' : '', + \ '.zprofile' : '', + \ '.vimrc' : '', + \ '.gvimrc' : '', + \ '_vimrc' : '', + \ '_gvimrc' : '', + \ '.bashprofile' : '', + \ 'favicon.ico' : '', + \ 'license' : '', + \ 'node_modules' : '', + \ 'react.jsx' : '', + \ 'procfile' : '', + \ 'dockerfile' : '', + \ 'docker-compose.yml' : '', + \ 'rakefile' : '', + \ 'config.ru' : '', + \ 'gemfile' : '', + \ 'makefile' : '', + \ 'cmakelists.txt' : '', + \ 'robots.txt' : 'ﮧ' + \} + + let s:file_node_pattern_matches = { + \ '.*jquery.*\.js$' : '', + \ '.*angular.*\.js$' : '', + \ '.*backbone.*\.js$' : '', + \ '.*require.*\.js$' : '', + \ '.*materialize.*\.js$' : '', + \ '.*materialize.*\.css$' : '', + \ '.*mootools.*\.js$' : '', + \ '.*vimrc.*' : '', + \ 'Vagrantfile$' : '' + \} + + if !exists('g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols') + let g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols = {} + endif + + if !exists('g:WebDevIconsUnicodeDecorateFileNodesExactSymbols') + " do not remove: exact-match-case-sensitive-* + let g:WebDevIconsUnicodeDecorateFileNodesExactSymbols = {} + endif + + if !exists('g:WebDevIconsUnicodeDecorateFileNodesPatternSymbols') + let g:WebDevIconsUnicodeDecorateFileNodesPatternSymbols = {} + endif + + " iterate to fix allow user overriding of specific individual keys in vimrc (only gvimrc was working previously) + for [key, val] in items(s:file_node_extensions) + if !has_key(g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols, key) + let g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols[key] = val + endif + endfor + + " iterate to fix allow user overriding of specific individual keys in vimrc (only gvimrc was working previously) + for [key, val] in items(s:file_node_exact_matches) + if !has_key(g:WebDevIconsUnicodeDecorateFileNodesExactSymbols, key) + let g:WebDevIconsUnicodeDecorateFileNodesExactSymbols[key] = val + endif + endfor + + " iterate to fix allow user overriding of specific individual keys in vimrc (only gvimrc was working previously) + for [key, val] in items(s:file_node_pattern_matches) + if !has_key(g:WebDevIconsUnicodeDecorateFileNodesPatternSymbols, key) + let g:WebDevIconsUnicodeDecorateFileNodesPatternSymbols[key] = val + endif + endfor + +endfunction + +" scope: local +function! s:setSyntax() + if g:webdevicons_enable_nerdtree == 1 && g:webdevicons_conceal_nerdtree_brackets == 1 + augroup webdevicons_conceal_nerdtree_brackets + au! + autocmd FileType nerdtree syntax match hideBracketsInNerdTree "\]" contained conceal containedin=NERDTreeFlags + autocmd FileType nerdtree syntax match hideBracketsInNerdTree "\[" contained conceal containedin=NERDTreeFlags + autocmd FileType nerdtree syntax match hideBracketsInNerdTree "\]" contained conceal containedin=NERDTreeLinkFile + autocmd FileType nerdtree syntax match hideBracketsInNerdTree "\]" contained conceal containedin=NERDTreeLinkDir + autocmd FileType nerdtree syntax match hideBracketsInNerdTree "\[" contained conceal containedin=NERDTreeLinkFile + autocmd FileType nerdtree syntax match hideBracketsInNerdTree "\[" contained conceal containedin=NERDTreeLinkDir + autocmd FileType nerdtree setlocal conceallevel=3 + autocmd FileType nerdtree setlocal concealcursor=nvic + augroup END + endif +endfunction + +" scope: local +" stole solution/idea from nerdtree-git-plugin :) +function! s:setCursorHold() + if g:webdevicons_enable_nerdtree + augroup webdevicons_cursor_hold + autocmd CursorHold * silent! call s:CursorHoldUpdate() + augroup END + endif +endfunction + +" scope: local +" stole solution/idea from nerdtree-git-plugin :) +function! s:CursorHoldUpdate() + if g:NERDTreeUpdateOnCursorHold != 1 || g:NERDTreeGitStatusUpdateOnCursorHold != 1 + return + endif + + if !exists('g:NERDTree') || !g:NERDTree.IsOpen() + return + endif + + " Do not update when a special buffer is selected + if !empty(&l:buftype) + return + endif + + " winnr need to make focus go to opened file + " CursorToTreeWin needed to avoid error on opening file + let l:winnr = winnr() + let l:altwinnr = winnr('#') + + call g:NERDTree.CursorToTreeWin() + call b:NERDTree.root.refreshFlags() + call NERDTreeRender() + + exec l:altwinnr . 'wincmd w' + exec l:winnr . 'wincmd w' +endfunction + +" scope: local +function! s:hardRefreshNerdTree() + if g:webdevicons_enable_nerdtree == 1 && g:webdevicons_conceal_nerdtree_brackets == 1 && g:NERDTree.IsOpen() + NERDTreeClose + NERDTree + endif +endfunction + +" scope: local +function! s:softRefreshNerdTree() + if g:webdevicons_enable_nerdtree == 1 && exists('g:NERDTree') && g:NERDTree.IsOpen() + NERDTreeToggle + NERDTreeToggle + endif +endfunction + +" local initialization {{{2 +"======================================================================== + +" scope: local +function! s:initialize() + call s:setDictionaries() + call s:setSyntax() + call s:setCursorHold() + + if exists('g:loaded_flagship') | call devicons#plugins#flagship#init() | endif + if exists('g:loaded_unite') && g:webdevicons_enable_unite | call devicons#plugins#unite#init() | endif + if exists('g:loaded_denite') && g:webdevicons_enable_denite | call devicons#plugins#denite#init() | endif + if exists('g:loaded_vimfiler') && g:webdevicons_enable_vimfiler | call devicons#plugins#vimfiler#init() | endif + if exists('g:loaded_ctrlp') && g:webdevicons_enable_ctrlp | call devicons#plugins#ctrlp#init() | endif + if exists('g:loaded_startify') && g:webdevicons_enable_startify | call devicons#plugins#startify#init() | endif +endfunction + + +" public functions {{{2 +"======================================================================== + +" scope: public +function! webdevicons#version() + return s:version +endfunction + +" scope: public +function! webdevicons#pluginHome() + return s:plugin_home +endfunction + +" scope: public +" allow the first version of refresh to now call softRefresh +function! webdevicons#refresh() + call webdevicons#softRefresh() +endfunction + +" scope: public +function! webdevicons#hardRefresh() + call s:setSyntax() + call s:hardRefreshNerdTree() +endfunction + +" scope: public +function! webdevicons#softRefresh() + call s:setSyntax() + call s:softRefreshNerdTree() +endfunction + +" a:1 (bufferName), a:2 (isDirectory) +" scope: public +function! WebDevIconsGetFileTypeSymbol(...) abort + if a:0 == 0 + let fileNodeExtension = !empty(expand('%:e')) ? expand('%:e') : &filetype + let fileNode = expand('%:t') + let isDirectory = 0 + else + let fileNodeExtension = fnamemodify(a:1, ':e') + let fileNode = fnamemodify(a:1, ':t') + if a:0 > 1 + let isDirectory = a:2 + else + let isDirectory = 0 + endif + endif + + if isDirectory == 0 || g:DevIconsEnableFolderPatternMatching + + let symbol = g:WebDevIconsUnicodeDecorateFileNodesDefaultSymbol + let fileNodeExtension = tolower(fileNodeExtension) + let fileNode = tolower(fileNode) + + for [pattern, glyph] in items(g:WebDevIconsUnicodeDecorateFileNodesPatternSymbols) + if match(fileNode, pattern) != -1 + let symbol = glyph + break + endif + endfor + + if symbol == g:WebDevIconsUnicodeDecorateFileNodesDefaultSymbol + if has_key(g:WebDevIconsUnicodeDecorateFileNodesExactSymbols, fileNode) + let symbol = g:WebDevIconsUnicodeDecorateFileNodesExactSymbols[fileNode] + elseif ((isDirectory == 1 && g:DevIconsEnableFolderExtensionPatternMatching) || isDirectory == 0) && has_key(g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols, fileNodeExtension) + let symbol = g:WebDevIconsUnicodeDecorateFileNodesExtensionSymbols[fileNodeExtension] + elseif isDirectory == 1 + let symbol = g:WebDevIconsUnicodeDecorateFolderNodesDefaultSymbol + endif + endif + + else + let symbol = g:WebDevIconsUnicodeDecorateFolderNodesDefaultSymbol + endif + + let artifactFix = s:DevIconsGetArtifactFix() + + return symbol . artifactFix + +endfunction + +" scope: local +" Temporary (hopefully) fix for glyph issues in gvim (proper fix is with the +" actual font patcher) +function! s:DevIconsGetArtifactFix() + if g:DevIconsAppendArtifactFix == 1 + let artifactFix = g:DevIconsArtifactFixChar + else + let artifactFix = '' + endif + + return artifactFix +endfunction + +" scope: public +function! WebDevIconsGetFileFormatSymbol(...) + let fileformat = '' + let bomb = '' + + if (&bomb && g:WebDevIconsUnicodeByteOrderMarkerDefaultSymbol !=? '') + let bomb = g:WebDevIconsUnicodeByteOrderMarkerDefaultSymbol . ' ' + endif + + if &fileformat ==? 'dos' + let fileformat = '' + elseif &fileformat ==? 'unix' + let fileformat = s:isDarwin() ? '' : s:getDistro() + elseif &fileformat ==? 'mac' + let fileformat = '' + endif + + let artifactFix = s:DevIconsGetArtifactFix() + + return bomb . fileformat . artifactFix +endfunction + +" for airline plugin {{{3 +"======================================================================== + +" scope: public +function! AirlineWebDevIcons(...) + let w:airline_section_x = get(w:, 'airline_section_x', + \ get(g:, 'airline_section_x', '')) + let w:airline_section_x .= ' %{WebDevIconsGetFileTypeSymbol()} ' + let hasFileFormatEncodingPart = airline#parts#ffenc() !=? '' + if g:webdevicons_enable_airline_statusline_fileformat_symbols && hasFileFormatEncodingPart + let w:airline_section_y = ' %{&fenc . " " . WebDevIconsGetFileFormatSymbol()} ' + endif +endfunction + +if g:webdevicons_enable == 1 && exists('g:loaded_airline') && g:loaded_airline == 1 && g:webdevicons_enable_airline_statusline + call airline#add_statusline_func('AirlineWebDevIcons') +endif + +if g:webdevicons_enable == 1 && g:webdevicons_enable_airline_tabline + " Store original formatter. + let g:_webdevicons_airline_orig_formatter = get(g:, 'airline#extensions#tabline#formatter', 'default') + let g:airline#extensions#tabline#formatter = 'webdevicons' +endif + +" for nerdtree plugin {{{3 +"======================================================================== + +" scope: public +function! NERDTreeWebDevIconsRefreshListener(event) + let path = a:event.subject + let postPadding = g:WebDevIconsNerdTreeAfterGlyphPadding + let prePadding = g:WebDevIconsNerdTreeBeforeGlyphPadding + let hasGitFlags = (len(path.flagSet._flagsForScope('git')) > 0) + let hasGitNerdTreePlugin = (exists('g:loaded_nerdtree_git_status') == 1) + let artifactFix = s:DevIconsGetArtifactFix() + + " align vertically at the same level: non git-flag nodes with git-flag nodes + if g:WebDevIconsNerdTreeGitPluginForceVAlign && !hasGitFlags && hasGitNerdTreePlugin + let prePadding .= ' ' + endif + + if !path.isDirectory + " Hey we got a regular file, lets get it's proper icon + let flag = prePadding . WebDevIconsGetFileTypeSymbol(path.str()) . postPadding + + elseif path.isDirectory && g:WebDevIconsUnicodeDecorateFolderNodes == 1 + " Ok we got a directory, some more tests and checks + let directoryOpened = 0 + + if g:DevIconsEnableFoldersOpenClose && len(path.flagSet._flagsForScope('webdevicons')) > 0 + " did the user set different icons for open and close? + + " isOpen is not available on the path listener directly + " but we added one via overriding particular keymappings for NERDTree + if has_key(path, 'isOpen') && path.isOpen == 1 + let directoryOpened = 1 + endif + endif + + if g:WebDevIconsUnicodeDecorateFolderNodesExactMatches == 1 + " Did the user enable exact matching of folder type/names + " think node_modules + if g:DevIconsEnableFoldersOpenClose && directoryOpened + " the folder is open + let flag = prePadding . g:DevIconsDefaultFolderOpenSymbol . artifactFix . postPadding + else + " the folder is not open + if path.isSymLink + " We have a symlink + let flag = prePadding . g:WebDevIconsUnicodeDecorateFolderNodesSymlinkSymbol . artifactFix . postPadding + else + " We have a regular folder + let flag = prePadding . WebDevIconsGetFileTypeSymbol(path.str(), path.isDirectory) . postPadding + endif + endif + + else + " the user did not enable exact matching + if g:DevIconsEnableFoldersOpenClose && directoryOpened + " the folder is open + let flag = prePadding . g:DevIconsDefaultFolderOpenSymbol . artifactFix . postPadding + else + " the folder is not open + if path.isSymLink + " We have a symlink + let flag = prePadding . g:WebDevIconsUnicodeDecorateFolderNodesSymlinkSymbol . artifactFix . postPadding + else + " We have a regular folder + let flag = prePadding . g:WebDevIconsUnicodeDecorateFolderNodesDefaultSymbol . artifactFix . postPadding + endif + endif + + endif + + else + let flag = prePadding . ' ' . artifactFix . postPadding + endif + + call path.flagSet.clearFlags('webdevicons') + + if flag !=? '' + call path.flagSet.addFlag('webdevicons', flag) + endif + +endfunction + +" call setup after processing all the functions (to avoid errors) {{{1 +"======================================================================== +" had some issues with VimEnter, for now using: +call s:initialize() + +" standard fix/safety: line continuation (avoiding side effects) {{{1 +"======================================================================== +let &cpo = s:save_cpo +unlet s:save_cpo + +" modeline syntax: +" vim: fdm=marker tabstop=2 softtabstop=2 shiftwidth=2 expandtab: diff --git a/nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/__init__.py b/nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/__init__.py new file mode 100644 index 0000000..b4c9a26 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/__init__.py @@ -0,0 +1,2 @@ +import pkg_resources +pkg_resources.declare_namespace(__name__) diff --git a/nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/powerline/__init__.py b/nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/powerline/__init__.py new file mode 100644 index 0000000..b4c9a26 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/powerline/__init__.py @@ -0,0 +1,2 @@ +import pkg_resources +pkg_resources.declare_namespace(__name__) diff --git a/nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/powerline/segments.py b/nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/powerline/segments.py new file mode 100644 index 0000000..2bcce5a --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/pythonx/vim_devicons/powerline/segments.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# vim:se fenc=utf8 noet: +from __future__ import (unicode_literals, division, absolute_import, print_function) + +try: + import vim +except ImportError: + vim = {} + +from powerline.bindings.vim import (vim_get_func, buffer_name) +from powerline.theme import requires_segment_info + +@requires_segment_info +def webdevicons(pl, segment_info): + webdevicons = vim_get_func('WebDevIconsGetFileTypeSymbol') + name = buffer_name(segment_info) + return [] if not webdevicons else [{ + 'contents': webdevicons(name), + 'highlight_groups': ['webdevicons', 'file_name'], + }] + +@requires_segment_info +def webdevicons_file_format(pl, segment_info): + webdevicons_file_format = vim_get_func('WebDevIconsGetFileFormatSymbol') + return [] if not webdevicons_file_format else [{ + 'contents': webdevicons_file_format(), + 'highlight_groups': ['webdevicons_file_format', 'file_format'], + }] diff --git a/nvim/.vim/plugged/vim-devicons/rplugin/python3/denite/filter/devicons_denite_converter.py b/nvim/.vim/plugged/vim-devicons/rplugin/python3/denite/filter/devicons_denite_converter.py new file mode 100644 index 0000000..d0540d2 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/rplugin/python3/denite/filter/devicons_denite_converter.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# vim:se fenc=utf8 noet: +from .base import Base +from os.path import isdir + + +class Filter(Base): + + def __init__(self, vim): + super().__init__(vim) + self.name = 'devicons_denite_converter' + self.description = 'add devicons in front of candidates' + + def filter(self, context): + for candidate in context['candidates']: + + if 'bufnr' in candidate: + bufname = self.vim.funcs.bufname(candidate['bufnr']) + filename = self.vim.funcs.fnamemodify(bufname, ':p:t') + elif 'word' in candidate and 'action__path' in candidate: + filename = candidate['word'] + + icon = self.vim.funcs.WebDevIconsGetFileTypeSymbol( + filename, isdir(filename)) + + # Customize output format if not done already. + if icon not in candidate.get('abbr', '')[:10]: + candidate['abbr'] = ' {} {}'.format( + icon, candidate.get('abbr', candidate['word'])) + + return context['candidates'] diff --git a/nvim/.vim/plugged/vim-devicons/test/.themisrc b/nvim/.vim/plugged/vim-devicons/test/.themisrc new file mode 100644 index 0000000..3d7270a --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/test/.themisrc @@ -0,0 +1 @@ +filetype plugin on diff --git a/nvim/.vim/plugged/vim-devicons/test/default_setting.vim b/nvim/.vim/plugged/vim-devicons/test/default_setting.vim new file mode 100644 index 0000000..e2c23e7 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/test/default_setting.vim @@ -0,0 +1,39 @@ +scriptencoding utf-8 + +let s:suite = themis#suite('Webdevicons-default-value') +let s:assert = themis#helper('assert') + +function! s:suite.ExtensionConfig() + call s:assert.equals(g:webdevicons_enable, 1) + call s:assert.equals(g:webdevicons_enable_nerdtree, 1) + call s:assert.equals(g:webdevicons_enable_unite, 1) + call s:assert.equals(g:webdevicons_enable_denite, 1) + call s:assert.equals(g:webdevicons_enable_vimfiler, 1) + call s:assert.equals(g:webdevicons_enable_ctrlp, 1) + call s:assert.equals(g:webdevicons_enable_airline_tabline, 1) + call s:assert.equals(g:webdevicons_enable_airline_statusline, 1) + call s:assert.equals(g:webdevicons_enable_airline_statusline_fileformat_symbols, 1) + call s:assert.equals(g:webdevicons_enable_flagship_statusline, 1) + call s:assert.equals(g:webdevicons_enable_flagship_statusline_fileformat_symbols, 1) + call s:assert.equals(g:webdevicons_enable_startify, 1) + call s:assert.equals(g:webdevicons_conceal_nerdtree_brackets, 1) +endfunction + +function! s:suite.ConfigOptions() + call s:assert.equals(g:DevIconsAppendArtifactFix, 0) + call s:assert.equals(g:DevIconsArtifactFixChar, ' ') + call s:assert.equals(g:WebDevIconsUnicodeDecorateFileNodes, 1) + call s:assert.equals(g:WebDevIconsUnicodeDecorateFolderNodes, 1) + call s:assert.equals(g:DevIconsEnableFoldersOpenClose, 0) + call s:assert.equals(g:DevIconsEnableFolderPatternMatching, 1) + call s:assert.equals(g:DevIconsEnableFolderExtensionPatternMatching, 0) + call s:assert.equals(1, g:WebDevIconsUnicodeDecorateFolderNodesExactMatches, 1) + call s:assert.equals(1, g:WebDevIconsUnicodeGlyphDoubleWidth, 1) + call s:assert.equals(g:WebDevIconsNerdTreeBeforeGlyphPadding, ' ') + call s:assert.equals(g:WebDevIconsNerdTreeAfterGlyphPadding, ' ') + call s:assert.equals(g:WebDevIconsNerdTreeGitPluginForceVAlign, 1) + call s:assert.equals(g:NERDTreeUpdateOnCursorHold, 1) " Obsolete: for backward compatibility + call s:assert.equals(g:NERDTreeGitStatusUpdateOnCursorHold, 1) + call s:assert.equals(g:WebDevIconsTabAirLineBeforeGlyphPadding, ' ') + call s:assert.equals(g:WebDevIconsTabAirLineAfterGlyphPadding, '') +endfunction diff --git a/nvim/.vim/plugged/vim-devicons/test/fileformat.vim b/nvim/.vim/plugged/vim-devicons/test/fileformat.vim new file mode 100644 index 0000000..3a1b062 --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/test/fileformat.vim @@ -0,0 +1,29 @@ +scriptencoding utf-8 + +" Please use nerd-font if you watch icon-font + +let s:suite = themis#suite('WebDevIconsGetFileFormatSymbol') +let s:assert = themis#helper('assert') + +function! s:suite.UnixIcon() + set fileformat=unix + let os = system('uname -a') + if os =~# 'Darwin' + call s:assert.equals(WebDevIconsGetFileFormatSymbol(), '') + " It may return Ubuntu because github-actions's OS is Ubuntu + elseif os =~# 'Ubuntu' + call s:assert.equals(WebDevIconsGetFileFormatSymbol(), '') + else + call s:assert.skip('Skip testing except for Ubuntu and Mac.') + endif +endfunction + +function! s:suite.WindowsIcon() + set fileformat=dos + call s:assert.equals(WebDevIconsGetFileFormatSymbol(), '') +endfunction + +function! s:suite.MacIcon() + set fileformat=mac + call s:assert.equals(WebDevIconsGetFileFormatSymbol(), '') +endfunction diff --git a/nvim/.vim/plugged/vim-devicons/test/filetype.vim b/nvim/.vim/plugged/vim-devicons/test/filetype.vim new file mode 100644 index 0000000..c42fc1b --- /dev/null +++ b/nvim/.vim/plugged/vim-devicons/test/filetype.vim @@ -0,0 +1,344 @@ +scriptencoding utf-8 + +" Please use nerd-font if you watch icon-font + +let s:suite = themis#suite('WebDevIconsGetFileTypeSymbol') +let s:assert = themis#helper('assert') + +function! s:Assert(filename, icon) + call s:assert.equals(WebDevIconsGetFileTypeSymbol(a:filename), a:icon) +endfunction + +function! s:suite.NoArgument_GetDefaultIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol(), '') +endfunction + +function! s:suite.__OneArgument_VimIcon__() + let targetfilenames = ['.vimrc', 'vimrc', '.gvimrc', '_gvimrc', 'test.vim'] + let expecticon = '' + let child = themis#suite('OneArgument_VimIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_RubyIcon__() + let targetfilenames = ['test.rb', 'rakefile', 'RAKEFILE', 'Gemfile', 'config.ru'] + let expecticon = '' + let child = themis#suite('OneArgument_RubyIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_MarkDownIcon__() + let targetfilenames = ['test.md', 'test.markdown', 'test.mdx', 'test.rmd'] + let expecticon = '' + let child = themis#suite('OneArgument_MarkDownIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_PythonIcon__() + let targetfilenames = ['test.py', 'test.pyc', 'test.pyo', 'test.pyd'] + let expecticon = '' + let child = themis#suite('OneArgument_PythonIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_ShellIcon__() + let targetfilenames = ['test.sh', 'test.fish', 'test.bash', 'test.ksh', 'test.csh', 'test.awk', 'test.ps1'] + let expecticon = '' + let child = themis#suite('OneArgument_ShellIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_DBIcon__() + let targetfilenames = ['test.db', 'test.sql', 'test.dump'] + let expecticon = '' + let child = themis#suite('OneArgument_DBIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_RustIcon__() + let targetfilenames = ['test.rs', 'test.rlib'] + let expecticon = '' + let child = themis#suite('OneArgument_RustIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_DockerIcon__() + let targetfilenames = ['Dockerfile', 'docker-compose.yml'] + let expecticon = '' + let child = themis#suite('OneArgument_DockerIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_JavaScriptIcon__() + let targetfilenames = ['test.js', 'test.mjs'] + let expecticon = '' + let child = themis#suite('OneArgument_JavaScriptIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_ReactIcon__() + let targetfilenames = ['test.jsx', 'test.tsx', 'react.jsx'] + let expecticon = '' + let child = themis#suite('OneArgument_ReactIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_JsonIcon__() + let targetfilenames = ['test.json', 'test.webmanifest'] + let expecticon = '' + let child = themis#suite('OneArgument_JsonIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_GearIcon__() + let targetfilenames = ['.DS_Store', 'Makefile', 'test.mk', '.bashrc', '.zshrc', '.gitignore', '.gitattributes', 'cmakelists.txt', 'test.yaml', 'test.yml', 'test.toml', 'test.bat'] + let expecticon = '' + let child = themis#suite('OneArgument_GearIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_ErlangIcon__() + let targetfilenames = ['test.erl', 'test.hrl'] + let expecticon = '' + let child = themis#suite('OneArgument_ErlangIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_SwiftIcon__() + let targetfilenames = ['test.swift', 'test.xcplayground'] + let expecticon = '' + let child = themis#suite('OneArgument_SwiftIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_HaskellIcon__() + let targetfilenames = ['test.hs', 'test.lhs'] + let expecticon = '' + let child = themis#suite('OneArgument_HaskellIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_CppIcon__() + let targetfilenames = ['test.cpp', 'test.c++', 'test.cp', 'test.cxx', 'test.cc'] + let expecticon = '' + let child = themis#suite('OneArgument_C++Icon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_ElixirIcon__() + let targetfilenames = ['test.ex', 'test.exs', 'test.eex', 'test.leex', 'test.heex'] + let expecticon = '' + let child = themis#suite('OneArgument_ElixirIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_PerlIcon__() + let targetfilenames = ['test.pl', 'test.pm', 'test.t'] + let expecticon = '' + let child = themis#suite('OneArgument_PerlIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.__OneArgument_FSharpIcon__() + let targetfilenames = ['test.fs', 'test.fsx', 'test.fsi', 'test.fsscript'] + let expecticon = '' + let child = themis#suite('OneArgument_FSharpIcon') + + for targetfilename in targetfilenames + let child[targetfilename] = funcref('s:Assert', [targetfilename, expecticon]) + endfor +endfunction + +function! s:suite.OneArgument_GetTypeScriptIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.ts'), '') +endfunction + +function! s:suite.OneArgument_GetVueIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.vue'), '﵂') +endfunction + +function! s:suite.OneArgument_GetNodeModuleIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('node_modules'), '') +endfunction + +function! s:suite.OneArgument_GetDropboxIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('Dropbox'), '') +endfunction + +function! s:suite.OneArgument_GetRIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.r'), 'ﳒ') +endfunction + +function! s:suite.OneArgument_GetLuaIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.lua'), '') +endfunction + +function! s:suite.OneArgument_GetJavaIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.java'), '') +endfunction + +function! s:suite.OneArgument_GetCIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.c'), '') +endfunction + +function! s:suite.OneArgument_GetCSSIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.cs'), '') +endfunction + +function! s:suite.OneArgument_GetCSharpIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.cs'), '') +endfunction + +function! s:suite.OneArgument_GetElmIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.elm'), '') +endfunction + +function! s:suite.OneArgument_GetRssIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.rss'), '') +endfunction + +function! s:suite.OneArgument_GetDartIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.dart'), '') +endfunction + +function! s:suite.OneArgument_GetSolidityIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.sol'), 'ﲹ') +endfunction + +function! s:suite.OneArgument_GetGoIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.go'), '') +endfunction + +function! s:suite.OneArgument_GetPhpIcon() + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.php'),'') +endfunction + +function! s:suite.OneArgument_GetScalaIcon() + call s:assert.equals( WebDevIconsGetFileTypeSymbol('test.scala'), '') +endfunction + +function! s:suite.OneArgument_GetTexIcon() + call s:assert.equals( WebDevIconsGetFileTypeSymbol('test.tex'), 'ﭨ') +endfunction + +function! s:suite.OneArgument_GetLicenseIcon() + call s:assert.equals( WebDevIconsGetFileTypeSymbol('LICENSE'), '') +endfunction + +function! s:suite.OneArgument_GetRobotIcon() + call s:assert.equals( WebDevIconsGetFileTypeSymbol('robots.txt'), 'ﮧ') +endfunction + +function! s:suite.OneArgument_PemIcon() + call s:assert.equals( WebDevIconsGetFileTypeSymbol('test.pem'), '') +endfunction + +function! s:suite.TwoArgument_zero_GetFileIcon() + call s:assert.equals( WebDevIconsGetFileTypeSymbol('test.vim', 0), '') +endfunction + +function! s:suite.TwoArgument_one_GetFolderIcon() + call s:assert.equals( WebDevIconsGetFileTypeSymbol('test.vim', 1), '') +endfunction + +function! s:suite.TwoArgument_two_GetDefaultIcon() + call s:assert.equals( WebDevIconsGetFileTypeSymbol('test.vim', 2), '') +endfunction + +function! s:suite.TwoArgument_string_GetFileTypeIcon() + call s:assert.equals( WebDevIconsGetFileTypeSymbol('test.php', 'test.vim'), '') +endfunction + +function! s:suite.NoArgument_OverWriteFileType_GetVimIcon() + set ft=vim + call s:assert.equals(WebDevIconsGetFileTypeSymbol(), '') +endfunction + +function! s:suite.NoArgument_EditVimFile_GetVimIcon() + edit! test.vim + call s:assert.equals(WebDevIconsGetFileTypeSymbol(), '') +endfunction + +function! s:suite.NoArgument_Editvimrc_GetVimIcon() + edit! vimrc + call s:assert.equals(WebDevIconsGetFileTypeSymbol(), '') +endfunction + +function! s:suite.NoArgument_EditPythonFile_GetPythonIcon() + edit! test.py + call s:assert.equals(WebDevIconsGetFileTypeSymbol(), '') +endfunction + +function! s:suite.NoArgument_EditjavaScriptFile_GetjavaScriptIcon() + edit! test.js + call s:assert.equals(WebDevIconsGetFileTypeSymbol(), '') +endfunction + +function! s:suite.NoArgument_EditRustFile_GetRustIcon() + edit! test.rs + call s:assert.equals(WebDevIconsGetFileTypeSymbol(), '') +endfunction + +function! s:suite.NoArgument_EditMKFile_GetGearIcon() + edit! test.mk + call s:assert.equals(WebDevIconsGetFileTypeSymbol(), '') +endfunction + +function! s:suite.OneArgument_EditPythonFile_GetRubyIcon() + edit! test.py + call s:assert.equals(WebDevIconsGetFileTypeSymbol('test.rb'), '') +endfunction diff --git a/nvim/.vim/plugged/vim/.github/issue_template.md b/nvim/.vim/plugged/vim/.github/issue_template.md new file mode 100644 index 0000000..95e3310 --- /dev/null +++ b/nvim/.vim/plugged/vim/.github/issue_template.md @@ -0,0 +1,45 @@ + + +### What happened + +### What I expected to happen + +### Screenshot + +### Machine Info + +- **Vim type (`vim`/`gvim`/`neovim`)**: +- **Vim version**: +- **OS**: +- **Terminal/Terminal Emulator/VTE**: +- **`TERM` environment variable**: + +### Additional Info + + diff --git a/nvim/.vim/plugged/vim/.github/pull_request_template.md b/nvim/.vim/plugged/vim/.github/pull_request_template.md new file mode 100644 index 0000000..09571b2 --- /dev/null +++ b/nvim/.vim/plugged/vim/.github/pull_request_template.md @@ -0,0 +1,5 @@ + + diff --git a/nvim/.vim/plugged/vim/.gitignore b/nvim/.vim/plugged/vim/.gitignore new file mode 100644 index 0000000..eee0dd8 --- /dev/null +++ b/nvim/.vim/plugged/vim/.gitignore @@ -0,0 +1 @@ +doc/tags diff --git a/nvim/.vim/plugged/vim/INSTALL.md b/nvim/.vim/plugged/vim/INSTALL.md new file mode 100644 index 0000000..a803a26 --- /dev/null +++ b/nvim/.vim/plugged/vim/INSTALL.md @@ -0,0 +1,108 @@ +### [Vim](http://www.vim.org/) + +#### Install + +These are the default instructions using Vim 8's `|packages|` feature. See sections below, if you use other plugin managers. + +1. Create theme folder (in case you don't have it yet): + +- `\*nix`: + +```bash +# vim 8.2+ +mkdir -p ~/.vim/pack/themes/start +# vim 8.0 +mkdir -p ~/.vim/pack/themes/opt +``` + +- Windows: create directory `$HOME\vimfiles\pack\themes\start` or + `$HOME\vimfiles\pack\themes\opt`, according to your version. + +2. Navigate to the folder above: + +- `\*nix`: + +```bash +# vim 8.2+ +cd ~/.vim/pack/themes/start +# vim 8.0 +cd ~/.vim/pack/themes/opt +``` + +- Windows: navigate to the directory you created earlier + +3. Clone the repository using the "dracula" name: + +```bash +git clone https://github.com/dracula/vim.git dracula +``` + +(Or use your favorite GUI client, or download the ZIP) + +4. Edit your `vimrc` file with the following content: + +``` +if v:version < 802 + packadd! dracula +endif +syntax enable +colorscheme dracula +``` + +The location of the `vimrc` varies between platforms: + +- `\*nix`: `~/.vim/vimrc` or `~/.vimrc` +- Windows: `$HOME\vimfiles\vimrc` or `$HOME\_vimrc` + +#### Install using other plugin managers + +- If you [use vim + pathogen + submodules](http://vimcasts.org/episodes/synchronizing-plugins-with-git-submodules-and-pathogen/): + +Navigate to your vim directory (`\*nix`: `~/.vim`; Windows: `$HOME\vimfiles`) + +```bash +git submodule add git@github.com:dracula/vim.git bundle/dracula +``` + +Place `colorscheme dracula` after `execute pathogen#infect()`. + +- If you [use vim + vundle](https://github.com/VundleVim/Vundle): + +```vim +Plugin 'dracula/vim', { 'name': 'dracula' } +:PluginInstall +``` + +Place `colorscheme dracula` after `call vundle#end()`. + +- If you [use vim-plug](https://github.com/junegunn/vim-plug) (\`as\` will install + the plugin in a directory called 'dracula' instead of just 'vim'): + +```vim +Plug 'dracula/vim', { 'as': 'dracula' } +:PlugInstall +``` + +Place `colorscheme dracula` after `call plug#end()`. + +- If you [use spacevim](https://spacevim.org), put the + following in `~/.SpaceVim.d/init.toml`: + +```toml +[options] + colorscheme = "dracula" + colorscheme_bg = "dark" +[[custom_plugins]] + repo = "dracula/vim" + name = "dracula" + merged = false +``` + +--- + +Note that dracula must be in your `'runtimepath'` to load properly: Version 2.0 +introduced autoload functionality for part of the plugin, which doesn't work +without `'runtimepath'` properly set. Consult your plugin-managers documentation +to make sure you put dracula on the `'runtimepath'` before loading it. For +`|packages|`, versions 8.2 and later will autoload `start` packages +correctly even in your vimrc. diff --git a/nvim/.vim/plugged/vim/LICENSE b/nvim/.vim/plugged/vim/LICENSE new file mode 100644 index 0000000..e8da611 --- /dev/null +++ b/nvim/.vim/plugged/vim/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Dracula Theme + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nvim/.vim/plugged/vim/README.md b/nvim/.vim/plugged/vim/README.md new file mode 100644 index 0000000..3ab11ab --- /dev/null +++ b/nvim/.vim/plugged/vim/README.md @@ -0,0 +1,34 @@ +# Dracula for [Vim](http://www.vim.org/) + +> A dark theme for [Vim](http://www.vim.org/). + +![Screenshot](./screenshot.png) + +Screenshot taken with the [pangloss/vim-javascript](https://github.com/pangloss/vim-javascript) syntax plugin for javascript. + +## Install + +All instructions can be found at [draculatheme.com/vim](https://draculatheme.com/vim). + +## Team + +This theme is maintained by the following person(s) and a bunch of +[awesome contributors](https://github.com/dracula/vim/graphs/contributors). + +| [![Derek S.](https://avatars3.githubusercontent.com/u/5240018?v=3&s=70)](https://github.com/dsifford) | [![David Knoble](https://avatars0.githubusercontent.com/u/22802209?v=4&s=70)](https://github.com/benknoble) | +| ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| [Derek S.](https://github.com/dsifford) | [David Knoble](https://github.com/benknoble) | + +## Community + +- [Twitter](https://twitter.com/draculatheme) - Best for getting updates about themes and new stuff. +- [GitHub](https://github.com/dracula/dracula-theme/discussions) - Best for asking questions and discussing issues. +- [Discord](https://draculatheme.com/discord-invite) - Best for hanging out with the community. + +## Dracula PRO + +[![Dracula PRO](./dracula-pro.png)](https://draculatheme.com/pro) + +## License + +[MIT License](./LICENSE) diff --git a/nvim/.vim/plugged/vim/after/plugin/dracula.vim b/nvim/.vim/plugged/vim/after/plugin/dracula.vim new file mode 100644 index 0000000..b713e2d --- /dev/null +++ b/nvim/.vim/plugged/vim/after/plugin/dracula.vim @@ -0,0 +1,238 @@ +if dracula#should_abort() + finish +endif + +" Fzf: {{{ +if exists('g:loaded_fzf') && ! exists('g:fzf_colors') + let g:fzf_colors = { + \ 'fg': ['fg', 'Normal'], + \ 'bg': ['bg', 'Normal'], + \ 'hl': ['fg', 'Search'], + \ 'fg+': ['fg', 'Normal'], + \ 'bg+': ['bg', 'Normal'], + \ 'hl+': ['fg', 'DraculaOrange'], + \ 'info': ['fg', 'DraculaPurple'], + \ 'border': ['fg', 'Ignore'], + \ 'prompt': ['fg', 'DraculaGreen'], + \ 'pointer': ['fg', 'Exception'], + \ 'marker': ['fg', 'Keyword'], + \ 'spinner': ['fg', 'Label'], + \ 'header': ['fg', 'Comment'], + \} +endif +"}}} +" ALE: {{{ +if exists('g:ale_enabled') + hi! link ALEError DraculaErrorLine + hi! link ALEWarning DraculaWarnLine + hi! link ALEInfo DraculaInfoLine + + hi! link ALEErrorSign DraculaRed + hi! link ALEWarningSign DraculaOrange + hi! link ALEInfoSign DraculaCyan + + hi! link ALEVirtualTextError Comment + hi! link ALEVirtualTextWarning Comment +endif +" }}} +" CtrlP: {{{ +if exists('g:loaded_ctrlp') + hi! link CtrlPMatch IncSearch + hi! link CtrlPBufferHid Normal +endif +" }}} +" GitGutter / gitsigns: {{{ +if exists('g:loaded_gitgutter') + hi! link GitGutterAdd DiffAdd + hi! link GitGutterChange DiffChange + hi! link GitGutterDelete DiffDelete +endif +if has('nvim-0.5') && luaeval("pcall(require, 'gitsigns')") + " https://github.com/lewis6991/gitsigns.nvim requires nvim > 0.5 + " has('nvim-0.5') checks >= 0.5, so this should be future-proof. + hi! link GitSignsAdd DiffAdd + hi! link GitSignsAddLn DiffAdd + hi! link GitSignsAddNr DiffAdd + hi! link GitSignsChange DiffChange + hi! link GitSignsChangeLn DiffChange + hi! link GitSignsChangeNr DiffChange + + hi! link GitSignsDelete DraculaRed + hi! link GitSignsDeleteLn DraculaRed + hi! link GitSignsDeleteNr DraculaRed +endif +" }}} +" Tree-sitter: {{{ +" The nvim-treesitter library defines many global highlight groups that are +" linked to the regular vim syntax highlight groups. We only need to redefine +" those highlight groups when the defaults do not match the dracula +" specification. +" https://github.com/nvim-treesitter/nvim-treesitter/blob/master/plugin/nvim-treesitter.vim +if exists('g:loaded_nvim_treesitter') + " deprecated TS* highlight groups + " see https://github.com/nvim-treesitter/nvim-treesitter/pull/3656 + " # Misc + hi! link TSPunctSpecial Special + " # Constants + hi! link TSConstMacro Macro + hi! link TSStringEscape Character + hi! link TSSymbol DraculaPurple + hi! link TSAnnotation DraculaYellow + hi! link TSAttribute DraculaGreenItalic + " # Functions + hi! link TSFuncBuiltin DraculaCyan + hi! link TSFuncMacro Function + hi! link TSParameter DraculaOrangeItalic + hi! link TSParameterReference DraculaOrange + hi! link TSField DraculaOrange + hi! link TSConstructor DraculaCyan + " # Keywords + hi! link TSLabel DraculaPurpleItalic + " # Variable + hi! link TSVariableBuiltin DraculaPurpleItalic + " # Text + hi! link TSStrong DraculaFgBold + hi! link TSEmphasis DraculaFg + hi! link TSUnderline Underlined + hi! link TSTitle DraculaYellow + hi! link TSLiteral DraculaYellow + hi! link TSURI DraculaYellow + " HTML and JSX tag attributes. By default, this group is linked to TSProperty, + " which in turn links to Identifer (white). + hi! link TSTagAttribute DraculaGreenItalic + + if has('nvim-0.8.1') + " # Misc + hi! link @punctuation.delimiter Delimiter + hi! link @punctuation.bracket DraculaFg + hi! link @punctuation.special Special + hi! link @punctuation Delimiter + " # Constants + hi! link @constant Constant + hi! link @constant.builtin Constant + hi! link @constant.macro Macro + hi! link @string.regex @string.special + hi! link @string.escape @string.special + hi! link @string String + hi! link @string.regexp @string.special + hi! link @string.special SpecialChar + hi! link @string.special.symbol DraculaPurple + hi! link @string.special.url Underlined + hi! link @symbol DraculaPurple + hi! link @annotation DraculaYellow + hi! link @attribute DraculaGreenItalic + hi! link @namespace Structure + hi! link @module Structure + hi! link @module.builtin Special + " # Functions + hi! link @function.builtin DraculaCyan + hi! link @funcion.macro Function + hi! link @function Function + hi! link @parameter DraculaOrangeItalic + hi! link @parameter.reference DraculaOrange + hi! link @field DraculaOrange + hi! link @property DraculaFg + hi! link @constructor DraculaCyan + " # Keywords + hi! link @label DraculaPurpleItalic + hi! link @keyword.function DraculaPink + hi! link @keyword.operator Operator + hi! link @keyword Keyword + hi! link @exception DraculaPurple + hi! link @operator Operator + " # Types + hi! link @type Type + hi! link @type.builtin Special + hi! link @character Character + hi! link @character.special SpecialChar + hi! link @boolean Boolean + hi! link @number Number + hi! link @number.float Float + " # Variable + hi! link @variable DraculaFg + hi! link @variable.builtin DraculaPurpleItalic + hi! link @variable.parameter DraculaOrangeItalic + hi! link @variable.member DraculaOrange + " # Text + hi! link @text DraculaFg + hi! link @text.strong DraculaFgBold + hi! link @text.emphasis DraculaFg + hi! link @text.underline Underlined + hi! link @text.title DraculaYellow + hi! link @text.literal DraculaYellow + hi! link @text.uri DraculaYellow + hi! link @text.diff.add DiffAdd + hi! link @text.diff.delete DiffDelete + + hi! link @markup.strong DraculaFgBold + hi! link @markup.italic DraculaFgItalic + hi! link @markup.strikethrough DraculaFgStrikethrough + hi! link @markup.underline Underlined + + hi! link @markup Special + hi! link @markup.heading DraculaYellow + hi! link @markup.link Underlined + hi! link @markup.link.uri DraculaYellow + hi! link @markup.link.label SpecialChar + hi! link @markup.raw DraculaYellow + hi! link @markup.list Special + + hi! link @comment Comment + hi! link @comment.error DiagnosticError + hi! link @comment.warning DiagnosticWarn + hi! link @comment.note DiagnosticInfo + hi! link @comment.todo Todo + + hi! link @diff.plus Added + hi! link @diff.minus Removed + hi! link @diff.delta Changed + + " # Tags + hi! link @tag DraculaCyan + hi! link @tag.delimiter DraculaFg + " HTML and JSX tag attributes. By default, this group is linked to TSProperty, + " which in turn links to Identifer (white). + hi! link @tag.attribute DraculaGreenItalic + endif +endif +" }}} +" nvim-cmp: {{{ +" A completion engine plugin for neovim written in Lua. +" https://github.com/hrsh7th/nvim-cmp +if exists('g:loaded_cmp') + hi! link CmpItemAbbrDeprecated DraculaError + + hi! link CmpItemAbbrMatch DraculaCyan + hi! link CmpItemAbbrMatchFuzzy DraculaCyan + + hi! link CmpItemKindText DraculaFg + hi! link CmpItemKindMethod Function + hi! link CmpItemKindFunction Function + hi! link CmpItemKindConstructor DraculaCyan + hi! link CmpItemKindField DraculaOrange + hi! link CmpItemKindVariable DraculaPurpleItalic + hi! link CmpItemKindClass DraculaCyan + hi! link CmpItemKindInterface DraculaCyan + hi! link CmpItemKindModule DraculaYellow + hi! link CmpItemKindProperty DraculaPink + hi! link CmpItemKindUnit DraculaFg + hi! link CmpItemKindValue DraculaYellow + hi! link CmpItemKindEnum DraculaPink + hi! link CmpItemKindKeyword DraculaPink + hi! link CmpItemKindSnippet DraculaFg + hi! link CmpItemKindColor DraculaYellow + hi! link CmpItemKindFile DraculaYellow + hi! link CmpItemKindReference DraculaOrange + hi! link CmpItemKindFolder DraculaYellow + hi! link CmpItemKindEnumMember DraculaPurple + hi! link CmpItemKindConstant DraculaPurple + hi! link CmpItemKindStruct DraculaPink + hi! link CmpItemKindEvent DraculaFg + hi! link CmpItemKindOperator DraculaPink + hi! link CmpItemKindTypeParameter DraculaCyan + + hi! link CmpItemMenu Comment +endif +" }}} + +" vim: fdm=marker ts=2 sts=2 sw=2 fdl=0: diff --git a/nvim/.vim/plugged/vim/after/syntax/css.vim b/nvim/.vim/plugged/vim/after/syntax/css.vim new file mode 100644 index 0000000..34884ca --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/css.vim @@ -0,0 +1,15 @@ +if dracula#should_abort('css') + finish +endif + +hi! link cssAttrComma Delimiter +hi! link cssAttrRegion DraculaPink +hi! link cssAttributeSelector DraculaGreenItalic +hi! link cssBraces Delimiter +hi! link cssFunctionComma Delimiter +hi! link cssNoise DraculaPink +hi! link cssProp DraculaCyan +hi! link cssPseudoClass DraculaPink +hi! link cssPseudoClassId DraculaGreenItalic +hi! link cssUnitDecorators DraculaPink +hi! link cssVendor DraculaGreenItalic diff --git a/nvim/.vim/plugged/vim/after/syntax/gitcommit.vim b/nvim/.vim/plugged/vim/after/syntax/gitcommit.vim new file mode 100644 index 0000000..66c7961 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/gitcommit.vim @@ -0,0 +1,12 @@ +if dracula#should_abort('gitcommit') + finish +endif + +" The following two are misnomers. Colors are correct. +hi! link diffFile DraculaGreen +hi! link diffNewFile DraculaRed + +hi! link diffAdded DraculaGreen +hi! link diffLine DraculaCyanItalic +hi! link diffRemoved DraculaRed + diff --git a/nvim/.vim/plugged/vim/after/syntax/html.vim b/nvim/.vim/plugged/vim/after/syntax/html.vim new file mode 100644 index 0000000..e533b93 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/html.vim @@ -0,0 +1,9 @@ +if dracula#should_abort('html') + finish +endif + +hi! link htmlTag DraculaFg +hi! link htmlArg DraculaGreenItalic +hi! link htmlTitle DraculaFg +hi! link htmlH1 DraculaFg +hi! link htmlSpecialChar DraculaPurple diff --git a/nvim/.vim/plugged/vim/after/syntax/javascript.vim b/nvim/.vim/plugged/vim/after/syntax/javascript.vim new file mode 100644 index 0000000..f6df2d9 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/javascript.vim @@ -0,0 +1,45 @@ +if dracula#should_abort('javascript', 'javascriptreact', 'javascript.jsx') + finish +endif + +hi! link javaScriptBraces Delimiter +hi! link javaScriptNumber Constant +hi! link javaScriptNull Constant +hi! link javaScriptFunction Keyword + +" pangloss/vim-javascript {{{ + +hi! link jsArrowFunction Operator +hi! link jsBuiltins DraculaCyan +hi! link jsClassDefinition DraculaCyan +hi! link jsClassMethodType Keyword +hi! link jsDestructuringAssignment DraculaOrangeItalic +hi! link jsDocParam DraculaOrangeItalic +hi! link jsDocTags Keyword +hi! link jsDocType Type +hi! link jsDocTypeBrackets DraculaCyan +hi! link jsFuncArgOperator Operator +hi! link jsFuncArgs DraculaOrangeItalic +hi! link jsFunction Keyword +hi! link jsNull Constant +hi! link jsObjectColon DraculaPink +hi! link jsSuper DraculaPurpleItalic +hi! link jsTemplateBraces Special +hi! link jsThis DraculaPurpleItalic +hi! link jsUndefined Constant + +"}}} + +" maxmellon/vim-jsx-pretty {{{ + +hi! link jsxTag Keyword +hi! link jsxTagName Keyword +hi! link jsxComponentName Type +hi! link jsxCloseTag Type +hi! link jsxAttrib DraculaGreenItalic +hi! link jsxCloseString Identifier +hi! link jsxOpenPunct Identifier + +" }}} + +" vim: fdm=marker ts=2 sts=2 sw=2 fdl=0: diff --git a/nvim/.vim/plugged/vim/after/syntax/javascriptreact.vim b/nvim/.vim/plugged/vim/after/syntax/javascriptreact.vim new file mode 100644 index 0000000..5c948d5 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/javascriptreact.vim @@ -0,0 +1 @@ +runtime! syntax/javascript.vim diff --git a/nvim/.vim/plugged/vim/after/syntax/json.vim b/nvim/.vim/plugged/vim/after/syntax/json.vim new file mode 100644 index 0000000..9f3657b --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/json.vim @@ -0,0 +1,6 @@ +if dracula#should_abort('json') + finish +endif + +hi! link jsonKeyword DraculaCyan +hi! link jsonKeywordMatch DraculaPink diff --git a/nvim/.vim/plugged/vim/after/syntax/lua.vim b/nvim/.vim/plugged/vim/after/syntax/lua.vim new file mode 100644 index 0000000..6a14a44 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/lua.vim @@ -0,0 +1,22 @@ +if dracula#should_abort('lua') + finish +endif + +hi! link luaFunc DraculaCyan +hi! link luaTable DraculaFg + +" tbastos/vim-lua {{{ + +hi! link luaBraces DraculaFg +hi! link luaBuiltIn Constant +hi! link luaDocTag Keyword +hi! link luaErrHand DraculaCyan +hi! link luaFuncArgName DraculaOrangeItalic +hi! link luaFuncCall Function +hi! link luaLocal Keyword +hi! link luaSpecialTable Constant +hi! link luaSpecialValue DraculaCyan + +" }}} + +" vim: fdm=marker ts=2 sts=2 sw=2 fdl=0: diff --git a/nvim/.vim/plugged/vim/after/syntax/markdown.vim b/nvim/.vim/plugged/vim/after/syntax/markdown.vim new file mode 100644 index 0000000..6c87f56 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/markdown.vim @@ -0,0 +1,50 @@ +if dracula#should_abort('markdown', 'mkd') + finish +endif + +if b:current_syntax ==# 'mkd' +" plasticboy/vim-markdown {{{1 + hi! link htmlBold DraculaOrangeBold + hi! link htmlBoldItalic DraculaOrangeBoldItalic + hi! link htmlH1 DraculaPurpleBold + hi! link htmlItalic DraculaYellowItalic + hi! link mkdBlockquote DraculaYellowItalic + hi! link mkdBold DraculaOrangeBold + hi! link mkdBoldItalic DraculaOrangeBoldItalic + hi! link mkdCode DraculaGreen + hi! link mkdCodeEnd DraculaGreen + hi! link mkdCodeStart DraculaGreen + hi! link mkdHeading DraculaPurpleBold + hi! link mkdInlineUrl DraculaLink + hi! link mkdItalic DraculaYellowItalic + hi! link mkdLink DraculaPink + hi! link mkdListItem DraculaCyan + hi! link mkdRule DraculaComment + hi! link mkdUrl DraculaLink +"}}}1 +elseif b:current_syntax ==# 'markdown' +" Builtin: {{{1 + hi! link markdownBlockquote DraculaCyan + hi! link markdownBold DraculaOrangeBold + hi! link markdownBoldItalic DraculaOrangeBoldItalic + hi! link markdownCodeBlock DraculaGreen + hi! link markdownCode DraculaGreen + hi! link markdownCodeDelimiter DraculaGreen + hi! link markdownH1 DraculaPurpleBold + hi! link markdownH2 markdownH1 + hi! link markdownH3 markdownH1 + hi! link markdownH4 markdownH1 + hi! link markdownH5 markdownH1 + hi! link markdownH6 markdownH1 + hi! link markdownHeadingDelimiter markdownH1 + hi! link markdownHeadingRule markdownH1 + hi! link markdownItalic DraculaYellowItalic + hi! link markdownLinkText DraculaPink + hi! link markdownListMarker DraculaCyan + hi! link markdownOrderedListMarker DraculaCyan + hi! link markdownRule DraculaComment + hi! link markdownUrl DraculaLink +"}}} +endif + +" vim: fdm=marker ts=2 sts=2 sw=2 fdl=0: diff --git a/nvim/.vim/plugged/vim/after/syntax/ocaml.vim b/nvim/.vim/plugged/vim/after/syntax/ocaml.vim new file mode 100644 index 0000000..f6aca99 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/ocaml.vim @@ -0,0 +1,7 @@ +if dracula#should_abort('ocaml') + finish +endif + +hi! link ocamlModule Type +hi! link ocamlModPath Normal +hi! link ocamlLabel DraculaOrangeItalic diff --git a/nvim/.vim/plugged/vim/after/syntax/perl.vim b/nvim/.vim/plugged/vim/after/syntax/perl.vim new file mode 100644 index 0000000..1b3939b --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/perl.vim @@ -0,0 +1,38 @@ +if dracula#should_abort('perl') + finish +endif + +" Regex +hi! link perlMatchStartEnd DraculaRed + +" Builtin functions +hi! link perlOperator DraculaCyan +hi! link perlStatementFiledesc DraculaCyan +hi! link perlStatementFiles DraculaCyan +hi! link perlStatementFlow DraculaCyan +hi! link perlStatementHash DraculaCyan +hi! link perlStatementIOfunc DraculaCyan +hi! link perlStatementIPC DraculaCyan +hi! link perlStatementList DraculaCyan +hi! link perlStatementMisc DraculaCyan +hi! link perlStatementNetwork DraculaCyan +hi! link perlStatementNumeric DraculaCyan +hi! link perlStatementProc DraculaCyan +hi! link perlStatementPword DraculaCyan +hi! link perlStatementRegexp DraculaCyan +hi! link perlStatementScalar DraculaCyan +hi! link perlStatementSocket DraculaCyan +hi! link perlStatementTime DraculaCyan +hi! link perlStatementVector DraculaCyan + +" Highlighting for quoting constructs, tied to existing option in vim-perl +if get(g:, 'perl_string_as_statement', 0) + hi! link perlStringStartEnd DraculaRed +endif + +" Signatures +hi! link perlSignature DraculaOrangeItalic +hi! link perlSubPrototype DraculaOrangeItalic + +" Hash keys +hi! link perlVarSimpleMemberName DraculaPurple diff --git a/nvim/.vim/plugged/vim/after/syntax/php.vim b/nvim/.vim/plugged/vim/after/syntax/php.vim new file mode 100644 index 0000000..d5c0e78 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/php.vim @@ -0,0 +1,10 @@ +if dracula#should_abort('php') + finish +endif + +hi! link phpClass Type +hi! link phpClasses Type +hi! link phpDocTags DraculaCyanItalic +hi! link phpFunction Function +hi! link phpParent Normal +hi! link phpSpecialFunction DraculaCyan diff --git a/nvim/.vim/plugged/vim/after/syntax/plantuml.vim b/nvim/.vim/plugged/vim/after/syntax/plantuml.vim new file mode 100644 index 0000000..cb16c0e --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/plantuml.vim @@ -0,0 +1,13 @@ +if dracula#should_abort('plantuml') + finish +endif + +hi! link plantumlClassPrivate SpecialKey +hi! link plantumlClassProtected DraculaOrange +hi! link plantumlClassPublic Function +hi! link plantumlColonLine String +hi! link plantumlDirectedOrVerticalArrowLR Constant +hi! link plantumlDirectedOrVerticalArrowRL Constant +hi! link plantumlHorizontalArrow Constant +hi! link plantumlSkinParamKeyword DraculaCyan +hi! link plantumlTypeKeyword Keyword diff --git a/nvim/.vim/plugged/vim/after/syntax/purescript.vim b/nvim/.vim/plugged/vim/after/syntax/purescript.vim new file mode 100644 index 0000000..27b1492 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/purescript.vim @@ -0,0 +1,9 @@ +if dracula#should_abort('purescript') + finish +endif + +hi! link purescriptModule Type +hi! link purescriptImport DraculaCyan +hi! link purescriptImportAs DraculaCyan +hi! link purescriptOperator Operator +hi! link purescriptBacktick Operator diff --git a/nvim/.vim/plugged/vim/after/syntax/python.vim b/nvim/.vim/plugged/vim/after/syntax/python.vim new file mode 100644 index 0000000..7cca9c4 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/python.vim @@ -0,0 +1,11 @@ +if dracula#should_abort('python') + finish +endif + +hi! link pythonBuiltinObj Type +hi! link pythonBuiltinObject Type +hi! link pythonBuiltinType Type +hi! link pythonClassVar DraculaPurpleItalic +hi! link pythonExClass Type +hi! link pythonNone Type +hi! link pythonRun Comment diff --git a/nvim/.vim/plugged/vim/after/syntax/rst.vim b/nvim/.vim/plugged/vim/after/syntax/rst.vim new file mode 100644 index 0000000..d8d4e44 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/rst.vim @@ -0,0 +1,26 @@ +if dracula#should_abort('rst') + finish +endif + +hi! link rstComment Comment +hi! link rstTransition Comment +hi! link rstCodeBlock DraculaGreen +hi! link rstInlineLiteral DraculaGreen +hi! link rstLiteralBlock DraculaGreen +hi! link rstQuotedLiteralBlock DraculaGreen +hi! link rstStandaloneHyperlink DraculaLink +hi! link rstStrongEmphasis DraculaOrangeBold +hi! link rstSections DraculaPurpleBold +hi! link rstEmphasis DraculaYellowItalic +hi! link rstDirective Keyword +hi! link rstSubstitutionDefinition Keyword +hi! link rstCitation String +hi! link rstExDirective String +hi! link rstFootnote String +hi! link rstCitationReference Tag +hi! link rstFootnoteReference Tag +hi! link rstHyperLinkReference Tag +hi! link rstHyperlinkTarget Tag +hi! link rstInlineInternalTargets Tag +hi! link rstInterpretedTextOrHyperlinkReference Tag +hi! link rstTodo Todo diff --git a/nvim/.vim/plugged/vim/after/syntax/ruby.vim b/nvim/.vim/plugged/vim/after/syntax/ruby.vim new file mode 100644 index 0000000..adb01a6 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/ruby.vim @@ -0,0 +1,16 @@ +if dracula#should_abort('ruby') + finish +endif + +if ! exists('g:ruby_operators') + let g:ruby_operators=1 +endif + +hi! link rubyBlockArgument DraculaOrangeItalic +hi! link rubyBlockParameter DraculaOrangeItalic +hi! link rubyCurlyBlock DraculaPink +hi! link rubyGlobalVariable DraculaPurple +hi! link rubyInstanceVariable DraculaPurpleItalic +hi! link rubyInterpolationDelimiter DraculaPink +hi! link rubyRegexpDelimiter DraculaRed +hi! link rubyStringDelimiter DraculaYellow diff --git a/nvim/.vim/plugged/vim/after/syntax/rust.vim b/nvim/.vim/plugged/vim/after/syntax/rust.vim new file mode 100644 index 0000000..5c14e3e --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/rust.vim @@ -0,0 +1,5 @@ +if dracula#should_abort('rust') + finish +endif + +hi! link rustCommentLineDoc Comment diff --git a/nvim/.vim/plugged/vim/after/syntax/sass.vim b/nvim/.vim/plugged/vim/after/syntax/sass.vim new file mode 100644 index 0000000..7e0556e --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/sass.vim @@ -0,0 +1,12 @@ +if dracula#should_abort('sass') + finish +endif + +hi! link sassClass cssClassName +hi! link sassClassChar cssClassNameDot +hi! link sassId cssIdentifier +hi! link sassIdChar cssIdentifier +hi! link sassInterpolationDelimiter DraculaPink +hi! link sassMixinName Function +hi! link sassProperty cssProp +hi! link sassVariableAssignment Operator diff --git a/nvim/.vim/plugged/vim/after/syntax/sh.vim b/nvim/.vim/plugged/vim/after/syntax/sh.vim new file mode 100644 index 0000000..948e52f --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/sh.vim @@ -0,0 +1,8 @@ +if dracula#should_abort('bash', 'ksh', 'posix', 'sh') + finish +endif + +hi! link shCommandSub NONE +hi! link shEscape DraculaRed +hi! link shParen NONE +hi! link shParenError NONE diff --git a/nvim/.vim/plugged/vim/after/syntax/tex.vim b/nvim/.vim/plugged/vim/after/syntax/tex.vim new file mode 100644 index 0000000..081cef4 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/tex.vim @@ -0,0 +1,16 @@ +if dracula#should_abort('tex') + finish +endif + +hi! link texBeginEndName DraculaOrangeItalic +hi! link texBoldItalStyle DraculaOrangeBoldItalic +hi! link texBoldStyle DraculaOrangeBold +hi! link texInputFile DraculaOrangeItalic +hi! link texItalStyle DraculaYellowItalic +hi! link texLigature DraculaPurple +hi! link texMath DraculaPurple +hi! link texMathMatcher DraculaPurple +hi! link texMathSymbol DraculaPurple +hi! link texSpecialChar DraculaPurple +hi! link texSubscripts DraculaPurple +hi! link texTitle DraculaFgBold diff --git a/nvim/.vim/plugged/vim/after/syntax/typescript.vim b/nvim/.vim/plugged/vim/after/syntax/typescript.vim new file mode 100644 index 0000000..888f600 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/typescript.vim @@ -0,0 +1,57 @@ +if dracula#should_abort('typescript', 'typescriptreact', 'typescript.tsx') + finish +endif + +" HerringtonDarkholme/yats.vim {{{ + +hi! link typescriptAliasDeclaration Type +hi! link typescriptArrayMethod Function +hi! link typescriptArrowFunc Operator +hi! link typescriptArrowFuncArg DraculaOrangeItalic +hi! link typescriptAssign Operator +hi! link typescriptBOMWindowProp Constant +hi! link typescriptBinaryOp Operator +hi! link typescriptBraces Delimiter +hi! link typescriptCall typescriptArrowFuncArg +hi! link typescriptClassHeritage Type +hi! link typescriptClassName Type +hi! link typescriptDateMethod DraculaCyan +hi! link typescriptDateStaticMethod Function +hi! link typescriptDecorator DraculaGreenItalic +hi! link typescriptDefaultParam Operator +hi! link typescriptES6SetMethod DraculaCyan +hi! link typescriptEndColons Delimiter +hi! link typescriptEnum Type +hi! link typescriptEnumKeyword Keyword +hi! link typescriptFuncComma Delimiter +hi! link typescriptFuncKeyword Keyword +hi! link typescriptFuncType DraculaOrangeItalic +hi! link typescriptFuncTypeArrow Operator +hi! link typescriptGlobal Type +hi! link typescriptGlobalMethod DraculaCyan +hi! link typescriptGlobalObjects Type +hi! link typescriptIdentifier DraculaPurpleItalic +hi! link typescriptInterfaceHeritage Type +hi! link typescriptInterfaceName Type +hi! link typescriptInterpolationDelimiter Keyword +hi! link typescriptKeywordOp Keyword +hi! link typescriptLogicSymbols Operator +hi! link typescriptMember Identifier +hi! link typescriptMemberOptionality Special +hi! link typescriptObjectColon Special +hi! link typescriptObjectLabel Identifier +hi! link typescriptObjectSpread Operator +hi! link typescriptOperator Operator +hi! link typescriptParamImpl DraculaOrangeItalic +hi! link typescriptParens Delimiter +hi! link typescriptPredefinedType Type +hi! link typescriptRestOrSpread Operator +hi! link typescriptTernaryOp Operator +hi! link typescriptTypeAnnotation Special +hi! link typescriptTypeCast Operator +hi! link typescriptTypeParameter DraculaOrangeItalic +hi! link typescriptTypeReference Type +hi! link typescriptUnaryOp Operator +hi! link typescriptVariable Keyword + +" }}} diff --git a/nvim/.vim/plugged/vim/after/syntax/typescriptreact.vim b/nvim/.vim/plugged/vim/after/syntax/typescriptreact.vim new file mode 100644 index 0000000..13051f7 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/typescriptreact.vim @@ -0,0 +1,22 @@ +if dracula#should_abort('typescriptreact', 'typescript.tsx') + finish +endif + +runtime! syntax/typescript.vim + +hi! link tsxAttrib DraculaGreenItalic +hi! link tsxEqual Operator +hi! link tsxIntrinsicTagName Keyword +hi! link tsxTagName Type + +" maxmellon/vim-jsx-pretty {{{ + +hi! link jsxTag Keyword +hi! link jsxTagName Keyword +hi! link jsxComponentName Type +hi! link jsxCloseTag Type +hi! link jsxAttrib DraculaGreenItalic +hi! link jsxCloseString Identifier +hi! link jsxOpenPunct Identifier + +" }}} diff --git a/nvim/.vim/plugged/vim/after/syntax/vim.vim b/nvim/.vim/plugged/vim/after/syntax/vim.vim new file mode 100644 index 0000000..2a00301 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/vim.vim @@ -0,0 +1,14 @@ +if dracula#should_abort('vim') + finish +endif + +hi! link vimAutoCmdSfxList Type +hi! link vimAutoEventList Type +hi! link vimEnvVar Constant +hi! link vimFunction Function +hi! link vimHiBang Keyword +hi! link vimOption Type +hi! link vimSetMod Keyword +hi! link vimSetSep Delimiter +hi! link vimUserAttrbCmpltFunc Function +hi! link vimUserFunc Function diff --git a/nvim/.vim/plugged/vim/after/syntax/xml.vim b/nvim/.vim/plugged/vim/after/syntax/xml.vim new file mode 100644 index 0000000..d18fd58 --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/xml.vim @@ -0,0 +1,13 @@ +if dracula#should_abort('xml') + finish +endif + +hi! link xmlAttrib DraculaGreenItalic +hi! link xmlEqual Operator +hi! link xmlTag Delimiter +hi! link xmlTagName Statement + +" Fixes missing highlight over end tags +syn region xmlTagName + \ matchgroup=xmlTag start=+"']\@=+ + \ matchgroup=xmlTag end=+>+ diff --git a/nvim/.vim/plugged/vim/after/syntax/yaml.vim b/nvim/.vim/plugged/vim/after/syntax/yaml.vim new file mode 100644 index 0000000..2f6515e --- /dev/null +++ b/nvim/.vim/plugged/vim/after/syntax/yaml.vim @@ -0,0 +1,12 @@ +if dracula#should_abort('yaml') + finish +endif + +hi! link yamlAlias DraculaGreenItalicUnderline +hi! link yamlAnchor DraculaPinkItalic +hi! link yamlBlockMappingKey DraculaCyan +hi! link yamlFlowCollection DraculaPink +hi! link yamlFlowIndicator Delimiter +hi! link yamlNodeTag DraculaPink +hi! link yamlPlainScalar DraculaYellow + diff --git a/nvim/.vim/plugged/vim/autoload/airline/themes/dracula.vim b/nvim/.vim/plugged/vim/autoload/airline/themes/dracula.vim new file mode 100644 index 0000000..15f995a --- /dev/null +++ b/nvim/.vim/plugged/vim/autoload/airline/themes/dracula.vim @@ -0,0 +1,160 @@ +" Dracula Airline Theme: {{{ +" +" Copyright 2016, All rights reserved +" +" Code licensed under the MIT license +" http://zenorocha.mit-license.org +" +" @author Extrante +" @author Zeno Rocha +"}}} +" Helpers: {{{ + +" Takes a foreground color name, background color name, and optionally one or +" more attr-list items as input, transforms it to the format accepted by +" airline#themes#generate_color_map and returns that value +func! s:clr(fg, bg, ...) + let l:fg = g:dracula#palette[a:fg] + let l:bg = g:dracula#palette[a:bg] + return [ l:fg[0], l:bg[0], l:fg[1], l:bg[1] ] + + \ filter(copy(a:000), 'type(v:val) == 1 && len(v:val) > 0') +endfunc + +" Takes three ['fg', 'bg'] color lists and optionally a dictionary of extra +" key-value pairs and returns the value generated by +" airline#themes#generate_color_map after optionally merging the dictionary of +" extra key-value pairs. +" +" a:a -> airline_a, airline_x +" a:b -> airline_b, airline_y +" a:c -> airline_c, airline_z +func! s:color_map(a, b, c, ...) + if a:0 == 0 + return call('airline#themes#generate_color_map', [call('s:clr', a:a), call('s:clr', a:b), call('s:clr', a:c)]) + else + return call('extend', [ call('airline#themes#generate_color_map', [call('s:clr', a:a), call('s:clr', a:b), call('s:clr', a:c)]) ] + a:000) + endif +endfunc + +"}}} + +let g:airline#themes#dracula#palette = { +\ 'normal': s:color_map( +\ ['bg', 'purple'], +\ ['fg', 'comment'], +\ ['fg', 'selection'], +\ { +\ 'airline_warning': s:clr('bg', 'orange'), +\ 'airline_error': s:clr('bg', 'red'), +\ }, +\ ), +\ 'normal_modified': s:color_map( +\ ['bg', 'purple'], +\ ['fg', 'comment'], +\ ['fg', 'bgdark'], +\ { +\ 'airline_warning': s:clr('bg', 'orange'), +\ 'airline_error': s:clr('bg', 'red'), +\ }, +\ ), +\ 'insert': s:color_map( +\ ['bg', 'green'], +\ ['fg', 'comment'], +\ ['fg', 'selection'], +\ { +\ 'airline_warning': s:clr('bg', 'orange'), +\ 'airline_error': s:clr('bg', 'red'), +\ }, +\ ), +\ 'insert_modified': s:color_map( +\ ['bg', 'green'], +\ ['fg', 'comment'], +\ ['fg', 'bgdark'], +\ { +\ 'airline_warning': s:clr('bg', 'orange'), +\ 'airline_error': s:clr('bg', 'red'), +\ }, +\ ), +\ 'replace': s:color_map( +\ ['bg', 'orange'], +\ ['fg', 'comment'], +\ ['fg', 'selection'], +\ { +\ 'airline_warning': s:clr('bg', 'orange'), +\ 'airline_error': s:clr('bg', 'red'), +\ }, +\ ), +\ 'replace_modified': s:color_map( +\ ['bg', 'orange'], +\ ['fg', 'comment'], +\ ['fg', 'bgdark'], +\ { +\ 'airline_warning': s:clr('bg', 'orange'), +\ 'airline_error': s:clr('bg', 'red'), +\ }, +\ ), +\ 'visual': s:color_map( +\ ['bg', 'yellow'], +\ ['fg', 'comment'], +\ ['fg', 'selection'], +\ { +\ 'airline_warning': s:clr('bg', 'orange'), +\ 'airline_error': s:clr('bg', 'red'), +\ }, +\ ), +\ 'visual_modified': s:color_map( +\ ['bg', 'yellow'], +\ ['fg', 'comment'], +\ ['fg', 'bgdark'], +\ { +\ 'airline_warning': s:clr('bg', 'orange'), +\ 'airline_error': s:clr('bg', 'red'), +\ }, +\ ), +\ 'inactive': s:color_map( +\ ['bg', 'comment'], +\ ['fg', 'bgdark'], +\ ['fg', 'selection'], +\ { +\ 'airline_warning': s:clr('bg', 'orange'), +\ 'airline_error': s:clr('bg', 'red'), +\ }, +\ ), +\ 'terminal': s:color_map( +\ ['bg', 'green'], +\ ['fg', 'comment'], +\ ['fg', 'selection'], +\ { +\ 'airline_term': s:clr('fg', 'selection'), +\ }, +\ ), +\} + +" Extensions: {{{ +" Tabline: {{{ +if get(g:, 'airline#extensions#tabline#enabled', 0) + let g:airline#themes#dracula#palette.tabline = { + \ 'airline_tabfill': s:clr('bg', 'bglight'), + \ + \ 'airline_tab': s:clr('comment', 'bg'), + \ 'airline_tabsel': s:clr('bg', 'purple'), + \ 'airline_tabmod': s:clr('green', 'bg'), + \ + \ 'airline_tab_right': s:clr('comment', 'bg'), + \ 'airline_tabsel_right': s:clr('fg', 'bg', ), + \ 'airline_tabmod_right': s:clr('green', 'bg'), + \} +endif +"}}} +" CtrlP: {{{2 +if exists('g:loaded_ctrlp') + let g:airline#themes#dracula#palette.ctrlp = airline#extensions#ctrlp#generate_color_map( + \ s:clr('fg', 'selection'), + \ s:clr('fg', 'comment'), + \ s:clr('fg', 'purple'), + \) +endif +"}}}2 +"}}} + +" vim: fdm=marker ts=2 sts=2 sw=2 fdl=0: diff --git a/nvim/.vim/plugged/vim/autoload/dracula.vim b/nvim/.vim/plugged/vim/autoload/dracula.vim new file mode 100644 index 0000000..ff90aa0 --- /dev/null +++ b/nvim/.vim/plugged/vim/autoload/dracula.vim @@ -0,0 +1,57 @@ +" Palette: {{{ + +let g:dracula#palette = {} +let g:dracula#palette.fg = ['#F8F8F2', 253] + +let g:dracula#palette.bglighter = ['#424450', 238] +let g:dracula#palette.bglight = ['#343746', 237] +let g:dracula#palette.bg = ['#282A36', 236] +let g:dracula#palette.bgdark = ['#21222C', 235] +let g:dracula#palette.bgdarker = ['#191A21', 234] + +let g:dracula#palette.comment = ['#6272A4', 61] +let g:dracula#palette.selection = ['#44475A', 239] +let g:dracula#palette.subtle = ['#424450', 238] + +let g:dracula#palette.cyan = ['#8BE9FD', 117] +let g:dracula#palette.green = ['#50FA7B', 84] +let g:dracula#palette.orange = ['#FFB86C', 215] +let g:dracula#palette.pink = ['#FF79C6', 212] +let g:dracula#palette.purple = ['#BD93F9', 141] +let g:dracula#palette.red = ['#FF5555', 203] +let g:dracula#palette.yellow = ['#F1FA8C', 228] + +" +" ANSI +" +let g:dracula#palette.color_0 = '#21222C' +let g:dracula#palette.color_1 = '#FF5555' +let g:dracula#palette.color_2 = '#50FA7B' +let g:dracula#palette.color_3 = '#F1FA8C' +let g:dracula#palette.color_4 = '#BD93F9' +let g:dracula#palette.color_5 = '#FF79C6' +let g:dracula#palette.color_6 = '#8BE9FD' +let g:dracula#palette.color_7 = '#F8F8F2' +let g:dracula#palette.color_8 = '#6272A4' +let g:dracula#palette.color_9 = '#FF6E6E' +let g:dracula#palette.color_10 = '#69FF94' +let g:dracula#palette.color_11 = '#FFFFA5' +let g:dracula#palette.color_12 = '#D6ACFF' +let g:dracula#palette.color_13 = '#FF92DF' +let g:dracula#palette.color_14 = '#A4FFFF' +let g:dracula#palette.color_15 = '#FFFFFF' + +" }}} + +" Helper function that takes a variadic list of filetypes as args and returns +" whether or not the execution of the ftplugin should be aborted. +func! dracula#should_abort(...) + if ! exists('g:colors_name') || g:colors_name !=# 'dracula' + return 1 + elseif a:0 > 0 && (! exists('b:current_syntax') || index(a:000, b:current_syntax) == -1) + return 1 + endif + return 0 +endfunction + +" vim: fdm=marker ts=2 sts=2 sw=2 fdl=0: diff --git a/nvim/.vim/plugged/vim/autoload/lightline/colorscheme/dracula.vim b/nvim/.vim/plugged/vim/autoload/lightline/colorscheme/dracula.vim new file mode 100644 index 0000000..da21a4d --- /dev/null +++ b/nvim/.vim/plugged/vim/autoload/lightline/colorscheme/dracula.vim @@ -0,0 +1,42 @@ +" ============================================================================= +" Filename: autoload/lightline/colorscheme/dracula.vim +" Author: adamalbrecht +" License: MIT License +" Last Change: 2018/04/11 +" ============================================================================= + +let s:black = g:dracula#palette.bg +let s:gray = g:dracula#palette.selection +let s:white = g:dracula#palette.fg +let s:darkblue = g:dracula#palette.comment +let s:cyan = g:dracula#palette.cyan +let s:green = g:dracula#palette.green +let s:orange = g:dracula#palette.orange +let s:purple = g:dracula#palette.purple +let s:red = g:dracula#palette.red +let s:yellow = g:dracula#palette.yellow + +if exists('g:lightline') + + let s:p = {'normal': {}, 'inactive': {}, 'insert': {}, 'replace': {}, 'visual': {}, 'tabline': {}} + let s:p.normal.left = [ [ s:black, s:purple ], [ s:cyan, s:gray ] ] + let s:p.normal.right = [ [ s:black, s:purple ], [ s:white, s:darkblue ] ] + let s:p.inactive.right = [ [ s:black, s:darkblue ], [ s:white, s:black ] ] + let s:p.inactive.left = [ [ s:cyan, s:black ], [ s:white, s:black ] ] + let s:p.insert.left = [ [ s:black, s:green ], [ s:cyan, s:gray ] ] + let s:p.replace.left = [ [ s:black, s:red ], [ s:cyan, s:gray ] ] + let s:p.visual.left = [ [ s:black, s:orange ], [ s:cyan, s:gray ] ] + let s:p.normal.middle = [ [ s:white, s:gray ] ] + let s:p.inactive.middle = [ [ s:white, s:gray ] ] + let s:p.tabline.left = [ [ s:darkblue, s:gray ] ] + let s:p.tabline.tabsel = [ [ s:cyan, s:black ] ] + let s:p.tabline.middle = [ [ s:darkblue, s:gray ] ] + let s:p.tabline.right = copy(s:p.normal.right) + let s:p.normal.error = [ [ s:red, s:black ] ] + let s:p.normal.warning = [ [ s:yellow, s:black ] ] + + let g:lightline#colorscheme#dracula#palette = lightline#colorscheme#flatten(s:p) + +endif + +" vim: fdm=marker ts=2 sts=2 sw=2 fdl=0: diff --git a/nvim/.vim/plugged/vim/colors/dracula.vim b/nvim/.vim/plugged/vim/colors/dracula.vim new file mode 100644 index 0000000..1bc2494 --- /dev/null +++ b/nvim/.vim/plugged/vim/colors/dracula.vim @@ -0,0 +1,378 @@ +" Dracula Theme: {{{ +" +" https://github.com/zenorocha/dracula-theme +" +" Copyright 2016, All rights reserved +" +" Code licensed under the MIT license +" http://zenorocha.mit-license.org +" +" @author Trevor Heins <@heinst> +" @author Éverton Ribeiro +" @author Derek Sifford +" @author Zeno Rocha +scriptencoding utf8 +" }}} + +" Configuration: {{{ + +if v:version > 580 + highlight clear + if exists('syntax_on') + syntax reset + endif +endif + +let g:colors_name = 'dracula' + +if !(has('termguicolors') && &termguicolors) && !has('gui_running') && &t_Co != 256 + finish +endif + +" Palette: {{{2 + +let s:fg = g:dracula#palette.fg + +let s:bglighter = g:dracula#palette.bglighter +let s:bglight = g:dracula#palette.bglight +let s:bg = g:dracula#palette.bg +let s:bgdark = g:dracula#palette.bgdark +let s:bgdarker = g:dracula#palette.bgdarker + +let s:comment = g:dracula#palette.comment +let s:selection = g:dracula#palette.selection +let s:subtle = g:dracula#palette.subtle + +let s:cyan = g:dracula#palette.cyan +let s:green = g:dracula#palette.green +let s:orange = g:dracula#palette.orange +let s:pink = g:dracula#palette.pink +let s:purple = g:dracula#palette.purple +let s:red = g:dracula#palette.red +let s:yellow = g:dracula#palette.yellow + +let s:none = ['NONE', 'NONE'] + +if has('nvim') + for s:i in range(16) + let g:terminal_color_{s:i} = g:dracula#palette['color_' . s:i] + endfor +endif + +if has('terminal') + let g:terminal_ansi_colors = [] + for s:i in range(16) + call add(g:terminal_ansi_colors, g:dracula#palette['color_' . s:i]) + endfor +endif + +" }}}2 +" User Configuration: {{{2 + +if !exists('g:dracula_bold') + let g:dracula_bold = 1 +endif + +if !exists('g:dracula_italic') + let g:dracula_italic = 1 +endif + +if !exists('g:dracula_strikethrough') + let g:dracula_strikethrough = 1 +endif + +if !exists('g:dracula_underline') + let g:dracula_underline = 1 +endif + +if !exists('g:dracula_undercurl') + let g:dracula_undercurl = g:dracula_underline +endif + +if !exists('g:dracula_full_special_attrs_support') + let g:dracula_full_special_attrs_support = has('gui_running') +endif + +if !exists('g:dracula_inverse') + let g:dracula_inverse = 1 +endif + +if !exists('g:dracula_colorterm') + let g:dracula_colorterm = 1 +endif + +if !exists('g:dracula_high_contrast_diff') + let g:dracula_high_contrast_diff = 0 +endif + +"}}}2 +" Script Helpers: {{{2 + +let s:attrs = { + \ 'bold': g:dracula_bold == 1 ? 'bold' : 0, + \ 'italic': g:dracula_italic == 1 ? 'italic' : 0, + \ 'strikethrough': g:dracula_strikethrough == 1 ? 'strikethrough' : 0, + \ 'underline': g:dracula_underline == 1 ? 'underline' : 0, + \ 'undercurl': g:dracula_undercurl == 1 ? 'undercurl' : 0, + \ 'inverse': g:dracula_inverse == 1 ? 'inverse' : 0, + \} + +function! s:h(scope, fg, ...) " bg, attr_list, special + let l:fg = copy(a:fg) + let l:bg = get(a:, 1, ['NONE', 'NONE']) + + let l:attr_list = filter(get(a:, 2, ['NONE']), 'type(v:val) == 1') + let l:attrs = len(l:attr_list) > 0 ? join(l:attr_list, ',') : 'NONE' + + " If the UI does not have full support for special attributes (like underline and + " undercurl) and the highlight does not explicitly set the foreground color, + " make the foreground the same as the attribute color to ensure the user will + " get some highlight if the attribute is not supported. The default behavior + " is to assume that terminals do not have full support, but the user can set + " the global variable `g:dracula_full_special_attrs_support` explicitly if the + " default behavior is not desirable. + let l:special = get(a:, 3, ['NONE', 'NONE']) + if l:special[0] !=# 'NONE' && l:fg[0] ==# 'NONE' && !g:dracula_full_special_attrs_support + let l:fg[0] = l:special[0] + let l:fg[1] = l:special[1] + endif + + let l:hl_string = [ + \ 'highlight', a:scope, + \ 'guifg=' . l:fg[0], 'ctermfg=' . l:fg[1], + \ 'guibg=' . l:bg[0], 'ctermbg=' . l:bg[1], + \ 'gui=' . l:attrs, 'cterm=' . l:attrs, + \ 'guisp=' . l:special[0], + \] + + execute join(l:hl_string, ' ') +endfunction + +"}}}2 +" Dracula Highlight Groups: {{{2 + +call s:h('DraculaBgLight', s:none, s:bglight) +call s:h('DraculaBgLighter', s:none, s:bglighter) +call s:h('DraculaBgDark', s:none, s:bgdark) +call s:h('DraculaBgDarker', s:none, s:bgdarker) + +call s:h('DraculaFg', s:fg) +call s:h('DraculaFgUnderline', s:fg, s:none, [s:attrs.underline]) +call s:h('DraculaFgBold', s:fg, s:none, [s:attrs.bold]) +call s:h('DraculaFgStrikethrough', s:fg, s:none, [s:attrs.strikethrough]) + +call s:h('DraculaComment', s:comment) +call s:h('DraculaCommentBold', s:comment, s:none, [s:attrs.bold]) + +call s:h('DraculaSelection', s:none, s:selection) + +call s:h('DraculaSubtle', s:subtle) + +call s:h('DraculaCyan', s:cyan) +call s:h('DraculaCyanItalic', s:cyan, s:none, [s:attrs.italic]) + +call s:h('DraculaGreen', s:green) +call s:h('DraculaGreenBold', s:green, s:none, [s:attrs.bold]) +call s:h('DraculaGreenItalic', s:green, s:none, [s:attrs.italic]) +call s:h('DraculaGreenItalicUnderline', s:green, s:none, [s:attrs.italic, s:attrs.underline]) + +call s:h('DraculaOrange', s:orange) +call s:h('DraculaOrangeBold', s:orange, s:none, [s:attrs.bold]) +call s:h('DraculaOrangeItalic', s:orange, s:none, [s:attrs.italic]) +call s:h('DraculaOrangeBoldItalic', s:orange, s:none, [s:attrs.bold, s:attrs.italic]) +call s:h('DraculaOrangeInverse', s:bg, s:orange) + +call s:h('DraculaPink', s:pink) +call s:h('DraculaPinkItalic', s:pink, s:none, [s:attrs.italic]) + +call s:h('DraculaPurple', s:purple) +call s:h('DraculaPurpleBold', s:purple, s:none, [s:attrs.bold]) +call s:h('DraculaPurpleItalic', s:purple, s:none, [s:attrs.italic]) + +call s:h('DraculaRed', s:red) +call s:h('DraculaRedInverse', s:fg, s:red) + +call s:h('DraculaYellow', s:yellow) +call s:h('DraculaYellowItalic', s:yellow, s:none, [s:attrs.italic]) + +call s:h('DraculaError', s:red, s:none, [], s:red) + +call s:h('DraculaErrorLine', s:none, s:none, [s:attrs.undercurl], s:red) +call s:h('DraculaWarnLine', s:none, s:none, [s:attrs.undercurl], s:orange) +call s:h('DraculaInfoLine', s:none, s:none, [s:attrs.undercurl], s:cyan) + +call s:h('DraculaTodo', s:cyan, s:none, [s:attrs.bold, s:attrs.inverse]) +call s:h('DraculaSearch', s:green, s:none, [s:attrs.inverse]) +call s:h('DraculaBoundary', s:comment, s:bgdark) +call s:h('DraculaWinSeparator', s:comment, s:bgdark) +call s:h('DraculaLink', s:cyan, s:none, [s:attrs.underline]) + +if g:dracula_high_contrast_diff + call s:h('DraculaDiffChange', s:yellow, s:purple) + call s:h('DraculaDiffDelete', s:bgdark, s:red) +else + call s:h('DraculaDiffChange', s:orange, s:none) + call s:h('DraculaDiffDelete', s:red, s:bgdark) +endif + +call s:h('DraculaDiffText', s:bg, s:orange) +call s:h('DraculaInlayHint', s:comment, s:bgdark) + +" }}}2 + +" }}} +" User Interface: {{{ + +set background=dark + +" Required as some plugins will overwrite +call s:h('Normal', s:fg, g:dracula_colorterm || has('gui_running') ? s:bg : s:none ) +call s:h('StatusLine', s:none, s:bglighter, [s:attrs.bold]) +call s:h('StatusLineNC', s:none, s:bglight) +call s:h('StatusLineTerm', s:none, s:bglighter, [s:attrs.bold]) +call s:h('StatusLineTermNC', s:none, s:bglight) +call s:h('WildMenu', s:bg, s:purple, [s:attrs.bold]) +call s:h('CursorLine', s:none, s:subtle) + +hi! link ColorColumn DraculaBgDark +hi! link CursorColumn CursorLine +hi! link CursorLineNr DraculaYellow +hi! link DiffAdd DraculaGreen +hi! link DiffAdded DiffAdd +hi! link DiffChange DraculaDiffChange +hi! link DiffDelete DraculaDiffDelete +hi! link DiffRemoved DiffDelete +hi! link DiffText DraculaDiffText +hi! link Directory DraculaPurpleBold +hi! link ErrorMsg DraculaRedInverse +hi! link FoldColumn DraculaSubtle +hi! link Folded DraculaBoundary +hi! link IncSearch DraculaOrangeInverse +call s:h('LineNr', s:comment) +hi! link MoreMsg DraculaFgBold +hi! link NonText DraculaSubtle +hi! link Pmenu DraculaBgDark +hi! link PmenuSbar DraculaBgDark +hi! link PmenuSel DraculaSelection +hi! link PmenuThumb DraculaSelection +hi! link Question DraculaFgBold +hi! link Search DraculaSearch +call s:h('SignColumn', s:comment) +hi! link TabLine DraculaBoundary +hi! link TabLineFill DraculaBgDark +hi! link TabLineSel Normal +hi! link Title DraculaGreenBold +hi! link VertSplit DraculaWinSeparator +hi! link Visual DraculaSelection +hi! link VisualNOS Visual +hi! link WarningMsg DraculaOrangeInverse + +" }}} +" Syntax: {{{ + +" Required as some plugins will overwrite +call s:h('MatchParen', s:green, s:none, [s:attrs.underline]) +call s:h('Conceal', s:cyan, s:none) + +" Neovim uses SpecialKey for escape characters only. Vim uses it for that, plus whitespace. +if has('nvim') + hi! link SpecialKey DraculaRed + hi! link LspReferenceText DraculaSelection + hi! link LspReferenceRead DraculaSelection + hi! link LspReferenceWrite DraculaSelection + " Link old 'LspDiagnosticsDefault*' hl groups + " for backward compatibility with neovim v0.5.x + hi! link LspDiagnosticsDefaultInformation DiagnosticInfo + hi! link LspDiagnosticsDefaultHint DiagnosticHint + hi! link LspDiagnosticsDefaultError DiagnosticError + hi! link LspDiagnosticsDefaultWarning DiagnosticWarn + hi! link LspDiagnosticsUnderlineError DiagnosticUnderlineError + hi! link LspDiagnosticsUnderlineHint DiagnosticUnderlineHint + hi! link LspDiagnosticsUnderlineInformation DiagnosticUnderlineInfo + hi! link LspDiagnosticsUnderlineWarning DiagnosticUnderlineWarn + hi! link LspInlayHint DraculaInlayHint + + hi! link DiagnosticInfo DraculaCyan + hi! link DiagnosticHint DraculaCyan + hi! link DiagnosticError DraculaError + hi! link DiagnosticWarn DraculaOrange + hi! link DiagnosticUnderlineError DraculaErrorLine + hi! link DiagnosticUnderlineHint DraculaInfoLine + hi! link DiagnosticUnderlineInfo DraculaInfoLine + hi! link DiagnosticUnderlineWarn DraculaWarnLine + + hi! link WinSeparator DraculaWinSeparator + + if has('nvim-0.9') + hi! link @lsp.type.class DraculaCyan + hi! link @lsp.type.decorator DraculaGreen + hi! link @lsp.type.enum DraculaCyan + hi! link @lsp.type.enumMember DraculaPurple + hi! link @lsp.type.function DraculaGreen + hi! link @lsp.type.interface DraculaCyan + hi! link @lsp.type.macro DraculaCyan + hi! link @lsp.type.method DraculaGreen + hi! link @lsp.type.namespace DraculaCyan + hi! link @lsp.type.parameter DraculaOrangeItalic + hi! link @lsp.type.property DraculaOrange + hi! link @lsp.type.struct DraculaCyan + hi! link @lsp.type.type DraculaCyanItalic + hi! link @lsp.type.typeParameter DraculaPink + hi! link @lsp.type.variable DraculaFg + endif +else + hi! link SpecialKey DraculaPink +endif + +hi! link Comment DraculaComment +hi! link Underlined DraculaFgUnderline +hi! link Todo DraculaTodo + +hi! link Error DraculaError +hi! link SpellBad DraculaErrorLine +hi! link SpellLocal DraculaWarnLine +hi! link SpellCap DraculaInfoLine +hi! link SpellRare DraculaInfoLine + +hi! link Constant DraculaPurple +hi! link String DraculaYellow +hi! link Character DraculaPink +hi! link Number Constant +hi! link Boolean Constant +hi! link Float Constant + +hi! link Identifier DraculaFg +hi! link Function DraculaGreen + +hi! link Statement DraculaPink +hi! link Conditional DraculaPink +hi! link Repeat DraculaPink +hi! link Label DraculaPink +hi! link Operator DraculaPink +hi! link Keyword DraculaPink +hi! link Exception DraculaPink + +hi! link PreProc DraculaPink +hi! link Include DraculaPink +hi! link Define DraculaPink +hi! link Macro DraculaPink +hi! link PreCondit DraculaPink +hi! link StorageClass DraculaPink +hi! link Structure DraculaPink +hi! link Typedef DraculaPink + +hi! link Type DraculaCyanItalic + +hi! link Delimiter DraculaFg + +hi! link Special DraculaPink +hi! link SpecialComment DraculaCyanItalic +hi! link Tag DraculaCyan +hi! link helpHyperTextJump DraculaLink +hi! link helpCommand DraculaPurple +hi! link helpExample DraculaGreen +hi! link helpBacktick Special + +"}}} + +" vim: fdm=marker ts=2 sts=2 sw=2 fdl=0 et: diff --git a/nvim/.vim/plugged/vim/doc/dracula.txt b/nvim/.vim/plugged/vim/doc/dracula.txt new file mode 100644 index 0000000..5da4c8f --- /dev/null +++ b/nvim/.vim/plugged/vim/doc/dracula.txt @@ -0,0 +1,173 @@ +*dracula.txt* For Vim version 8 Last change: 2021 Oct 22 +*dracula* *vim-dracula* + + |\ ,, ~ + \\ _ || _ ~ + / \\ ,._-_ < \, _-_ \\ \\ || < \, ~ + || || || /-|| || || || || /-|| ~ + || || || (( || || || || || (( || ~ + \\/ \\, \/\\ \\,/ \\/\\ \\ \/\\ ~ + + A dark theme for vim + +============================================================================== +CONTENTS *dracula-contents* + + 1. Intro ................................................... |dracula-intro| + 2. Usage ................................................... |dracula-usage| + 3. Configuration ................................... |dracula-configuration| + 4. Personal Customization .......................... |dracula-customization| + 5. License ............................................... |dracula-license| + 6. Bugs ..................................................... |dracula-bugs| + 7. Contributing ..................................... |dracula-contributing| + 8. Credits ............................................... |dracula-credits| + +============================================================================== +INTRO *dracula-intro* + +Dracula is a vim plugin that contains + + - a dark colorscheme for vim + - a similarly-themed colorscheme for the vim plugin airline + (https://github.com/vim-airline/vim-airline) + +============================================================================== +USAGE *dracula-usage* + +Install it with your favorite plugin manager, and then > + colorscheme dracula +in your vimrc! See also |dracula_runtimepath|. + +If you are an airline user, you can also do > + let g:airline_theme='dracula' +to have airline use Dracula. + + *dracula_runtimepath* + +Note that dracula must be in your 'runtimepath' for this command to work +properly: Version 2.0 introduced autoload functionality for part of the +plugin, which doesn't work without 'runtimepath' properly set. + +For users of Vim 8's |packages| feature, it suffices to put > + packadd! dracula + colorscheme dracula +in your vimrc. {name} Should be replaced by the directory you put the code in. +For example, if you use ~/.vim/pack/themes/start/my-dracula-theme, you would +do > + packadd! my-dracula-theme + +For users of other plugin managers, consult your documentation +to make sure you put dracula on the 'runtimepath' before loading it. + +============================================================================== +CONFIGURATION *dracula-configuration* + +There are a couple of variables used by Dracula that you might want to adjust +depending on your terminal's capabilities. + +Default values are shown. + +------------------------------------------------------------------------------ +In the following section, `1` signifies `on` and `0` signifies `off`. + +* *g:dracula_bold* +Include bold attributes in highlighting > + let g:dracula_bold = 1 + +* *g:dracula_italic* +Include italic attributes in highlighting > + let g:dracula_italic = 1 + +* *g:dracula_strikethrough* +Include strikethrough attributes in highlighting > + let g:dracula_strikethrough = 1 + +* *g:dracula_underline* +Include underline attributes in highlighting > + let g:dracula_underline = 1 + +* *g:dracula_undercurl* +Include undercurl attributes in highlighting (only if underline enabled) > + let g:dracula_undercurl = 1 + +* *g:dracula_full_special_attrs_support* +Explicitly declare full support for special attributes. By default it is 1 +for graphical applications and 0 for terminals and terminal emulators. On +terminal emulators, set to 1 to allow underline/undercurl highlights without +changing the foreground color. > + let g:dracula_full_special_attrs_support = 1 + +* *g:dracula_high_contrast_diff* +Use high-contrast color when in diff mode. By default it is disabled, set to +1 to enable it. + let g:dracula_high_contrast_diff = 1 + +* *g:dracula_inverse* +Include inverse attributes in highlighting > + let g:dracula_inverse = 1 + +* *g:dracula_colorterm* +Include background fill colors > + let g:dracula_colorterm = 1 + +============================================================================== +CUSTOMIZATION *dracula-customization* + +Like all colorschemes, Dracula is easy to customize with |autocmd|. Make use +of the |ColorScheme| event as in the following examples. + +It would be a good idea to put all of your personal changes in an |augroup|, +which you can do with the following code: > + augroup dracula_customization + au! + " autocmds... + augroup END +> + +- To add underline styling to |hl-CursorLine|, you can use the following: > + autocmd ColorScheme dracula hi CursorLine cterm=underline term=underline +< +============================================================================== +LICENSE *dracula-license* + +MIT License. Copyright © 2016 Dracula Theme. +Full text available at +https://github.com/dracula/vim/blob/master/LICENSE + +============================================================================== +BUGS *dracula-bugs* + +At the time of this writing, no major bugs have been found. + +If you find one and wish to report it, you can do so at +https://github.com/dracula/vim/issues + +============================================================================== +CONTRIBUTING *dracula-contributing* + +Want to submit a new feature, bugfix, or hack on Dracula? +Submit pull requests to +https://github.com/dracula/vim/pulls + +Existing code determines style guidelines. + +============================================================================== +CREDITS *dracula-credits* + +Proudly built by the Dracula Theme organization +https://github.com/dracula + +Dracula for other applications available at +https://draculatheme.com + +Further information available at +https://draculatheme.com/vim + +Maintained by: +- Derek S. (https://github.com/dsifford) +- D. Ben Knoble (https://github.com/benknoble) + +Git repository: +https://github.com/dracula/vim + + vim:tw=78:ts=8:ft=help:norl: diff --git a/nvim/.vim/plugged/vim/dracula-pro.png b/nvim/.vim/plugged/vim/dracula-pro.png new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..c3a89142667efb8cae5d42b8bfa4adcdefa8452ec91768299f877879ea79e19b GIT binary patch literal 339197 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%0D|6Zq16NaUo2IeigM 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
    s~XLj*T2h4*r~cI{zEY@hOd+% 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

    Aqgd8aEQ>_}T);8w>lWz)0EBFV)| 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

    Oh My Zsh

    + +Oh My Zsh is an open source, community-driven framework for managing your [zsh](https://www.zsh.org/) configuration. + +Sounds boring. Let's try again. + +**Oh My Zsh will not make you a 10x developer...but you may feel like one.** + +Once installed, your terminal shell will become the talk of the town _or your money back!_ With each keystroke in your command prompt, you'll take advantage of the hundreds of powerful plugins and beautiful themes. Strangers will come up to you in cafés and ask you, _"that is amazing! are you some sort of genius?"_ + +Finally, you'll begin to get the sort of attention that you have always felt you deserved. ...or maybe you'll use the time that you're saving to start flossing more often. 😬 + +To learn more, visit [ohmyz.sh](https://ohmyz.sh), follow [@ohmyzsh](https://twitter.com/ohmyzsh) on Twitter, and join us on [Discord](https://discord.gg/ohmyzsh). + +[![CI](https://github.com/ohmyzsh/ohmyzsh/workflows/CI/badge.svg)](https://github.com/ohmyzsh/ohmyzsh/actions?query=workflow%3ACI) +[![X (formerly Twitter) Follow](https://img.shields.io/twitter/follow/ohmyzsh?label=%40ohmyzsh&logo=x&style=flat)](https://twitter.com/intent/follow?screen_name=ohmyzsh) +[![Mastodon Follow](https://img.shields.io/mastodon/follow/111169632522566717?label=%40ohmyzsh&domain=https%3A%2F%2Fmstdn.social&logo=mastodon&style=flat)](https://mstdn.social/@ohmyzsh) +[![Discord server](https://img.shields.io/discord/642496866407284746)](https://discord.gg/ohmyzsh) +[![Gitpod ready](https://img.shields.io/badge/Gitpod-ready-blue?logo=gitpod)](https://gitpod.io/#https://github.com/ohmyzsh/ohmyzsh) + +
    +Table of Contents + +- [Getting Started](#getting-started) + - [Operating System Compatibility](#operating-system-compatibility) + - [Prerequisites](#prerequisites) + - [Basic Installation](#basic-installation) + - [Manual Inspection](#manual-inspection) +- [Using Oh My Zsh](#using-oh-my-zsh) + - [Plugins](#plugins) + - [Enabling Plugins](#enabling-plugins) + - [Using Plugins](#using-plugins) + - [Themes](#themes) + - [Selecting A Theme](#selecting-a-theme) + - [FAQ](#faq) +- [Advanced Topics](#advanced-topics) + - [Advanced Installation](#advanced-installation) + - [Custom Directory](#custom-directory) + - [Unattended Install](#unattended-install) + - [Installing From A Forked Repository](#installing-from-a-forked-repository) + - [Manual Installation](#manual-installation) + - [Installation Problems](#installation-problems) + - [Custom Plugins And Themes](#custom-plugins-and-themes) + - [Enable GNU ls In macOS And freeBSD Systems](#enable-gnu-ls-in-macos-and-freebsd-systems) + - [Skip Aliases](#skip-aliases) + - [Disable async git prompt](#disable-async-git-prompt) +- [Getting Updates](#getting-updates) + - [Updates Verbosity](#updates-verbosity) + - [Manual Updates](#manual-updates) +- [Uninstalling Oh My Zsh](#uninstalling-oh-my-zsh) +- [How Do I Contribute To Oh My Zsh?](#how-do-i-contribute-to-oh-my-zsh) + - [Do Not Send Us Themes](#do-not-send-us-themes) +- [Contributors](#contributors) +- [Follow Us](#follow-us) +- [Merchandise](#merchandise) +- [License](#license) +- [About Planet Argon](#about-planet-argon) + +
    + +## Getting Started + +### Operating System Compatibility + +| O/S | Status | +| :------------- | :-----: | +| Android | ✅ | +| freeBSD | ✅ | +| LCARS | 🛸 | +| Linux | ✅ | +| macOS | ✅ | +| OS/2 Warp | ❌ | +| Windows (WSL2) | ✅ | + + +### Prerequisites + +- [Zsh](https://www.zsh.org) should be installed (v4.3.9 or more recent is fine but we prefer 5.0.8 and newer). If not pre-installed (run `zsh --version` to confirm), check the following wiki instructions here: [Installing ZSH](https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH) +- `curl` or `wget` should be installed +- `git` should be installed (recommended v2.4.11 or higher) + +### Basic Installation + +Oh My Zsh is installed by running one of the following commands in your terminal. You can install this via the command-line with either `curl`, `wget` or another similar tool. + +| Method | Command | +| :-------- | :------------------------------------------------------------------------------------------------ | +| **curl** | `sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"` | +| **wget** | `sh -c "$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"` | +| **fetch** | `sh -c "$(fetch -o - https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"` | + +Alternatively, the installer is also mirrored outside GitHub. Using this URL instead may be required if you're in a country like China or India (for certain ISPs), that blocks `raw.githubusercontent.com`: + +| Method | Command | +| :-------- | :------------------------------------------------------------------------------------------------ | +| **curl** | `sh -c "$(curl -fsSL https://install.ohmyz.sh/)"` | +| **wget** | `sh -c "$(wget -O- https://install.ohmyz.sh/)"` | +| **fetch** | `sh -c "$(fetch -o - https://install.ohmyz.sh/)"` | + +_Note that any previous `.zshrc` will be renamed to `.zshrc.pre-oh-my-zsh`. After installation, you can move the configuration you want to preserve into the new `.zshrc`._ + +#### Manual Inspection + +It's a good idea to inspect the install script from projects you don't yet know. You can do +that by downloading the install script first, looking through it so everything looks normal, +then running it: + +```sh +wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh +sh install.sh +``` + +If the above URL times out or otherwise fails, you may have to substitute the URL for `https://install.ohmyz.sh` to be able to get the script. + +## Using Oh My Zsh + +### Plugins + +Oh My Zsh comes with a shitload of plugins for you to take advantage of. You can take a look in the [plugins](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins) directory and/or the [wiki](https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins) to see what's currently available. + +#### Enabling Plugins + +Once you spot a plugin (or several) that you'd like to use with Oh My Zsh, you'll need to enable them in the `.zshrc` file. You'll find the zshrc file in your `$HOME` directory. Open it with your favorite text editor and you'll see a spot to list all the plugins you want to load. + +```sh +vi ~/.zshrc +``` + +For example, this might begin to look like this: + +```sh +plugins=( + git + bundler + dotenv + macos + rake + rbenv + ruby +) +``` + +_Note that the plugins are separated by whitespace (spaces, tabs, new lines...). **Do not** use commas between them or it will break._ + +#### Using Plugins + +Each built-in plugin includes a **README**, documenting it. This README should show the aliases (if the plugin adds any) and extra goodies that are included in that particular plugin. + +### Themes + +We'll admit it. Early in the Oh My Zsh world, we may have gotten a bit too theme happy. We have over one hundred and fifty themes now bundled. Most of them have [screenshots](https://github.com/ohmyzsh/ohmyzsh/wiki/Themes) on the wiki (We are working on updating this!). Check them out! + +#### Selecting A Theme + +_Robby's theme is the default one. It's not the fanciest one. It's not the simplest one. It's just the right one (for him)._ + +Once you find a theme that you'd like to use, you will need to edit the `~/.zshrc` file. You'll see an environment variable (all caps) in there that looks like: + +```sh +ZSH_THEME="robbyrussell" +``` + +To use a different theme, simply change the value to match the name of your desired theme. For example: + +```sh +ZSH_THEME="agnoster" # (this is one of the fancy ones) +# see https://github.com/ohmyzsh/ohmyzsh/wiki/Themes#agnoster +``` + +_Note: many themes require installing a [Powerline Font](https://github.com/powerline/fonts) or a [Nerd Font](https://github.com/ryanoasis/nerd-fonts) in order to render properly. Without them, these themes will render [weird prompt symbols](https://github.com/ohmyzsh/ohmyzsh/wiki/FAQ#i-have-a-weird-character-in-my-prompt)_ + +Open up a new terminal window and your prompt should look something like this: + +![Agnoster theme](https://cloud.githubusercontent.com/assets/2618447/6316862/70f58fb6-ba03-11e4-82c9-c083bf9a6574.png) + +In case you did not find a suitable theme for your needs, please have a look at the wiki for [more of them](https://github.com/ohmyzsh/ohmyzsh/wiki/External-themes). + +If you're feeling feisty, you can let the computer select one randomly for you each time you open a new terminal window. + +```sh +ZSH_THEME="random" # (...please let it be pie... please be some pie..) +``` + +And if you want to pick random theme from a list of your favorite themes: + +```sh +ZSH_THEME_RANDOM_CANDIDATES=( + "robbyrussell" + "agnoster" +) +``` + +If you only know which themes you don't like, you can add them similarly to an ignored list: + +```sh +ZSH_THEME_RANDOM_IGNORED=(pygmalion tjkirch_mod) +``` + +### FAQ + +If you have some more questions or issues, you might find a solution in our [FAQ](https://github.com/ohmyzsh/ohmyzsh/wiki/FAQ). + +## Advanced Topics + +If you're the type that likes to get their hands dirty, these sections might resonate. + +### Advanced Installation + +Some users may want to manually install Oh My Zsh, or change the default path or other settings that +the installer accepts (these settings are also documented at the top of the install script). + +#### Custom Directory + +The default location is `~/.oh-my-zsh` (hidden in your home directory, you can access it with `cd ~/.oh-my-zsh`) + +If you'd like to change the install directory with the `ZSH` environment variable, either by running +`export ZSH=/your/path` before installing, or by setting it before the end of the install pipeline +like this: + +```sh +ZSH="$HOME/.dotfiles/oh-my-zsh" sh install.sh +``` + +#### Unattended Install + +If you're running the Oh My Zsh install script as part of an automated install, you can pass the `--unattended` +flag to the `install.sh` script. This will have the effect of not trying to change +the default shell, and it also won't run `zsh` when the installation has finished. + +```sh +sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended +``` + +If you're in China, India, or another country that blocks `raw.githubusercontent.com`, you may have to substitute the URL for `https://install.ohmyz.sh` for it to install. + +#### Installing From A Forked Repository + +The install script also accepts these variables to allow the installation of a different repository: + +- `REPO` (default: `ohmyzsh/ohmyzsh`): this takes the form of `owner/repository`. If you set + this variable, the installer will look for a repository at `https://github.com/{owner}/{repository}`. + +- `REMOTE` (default: `https://github.com/${REPO}.git`): this is the full URL of the git repository + clone. You can use this setting if you want to install from a fork that is not on GitHub (GitLab, + Bitbucket...) or if you want to clone with SSH instead of HTTPS (`git@github.com:user/project.git`). + + _NOTE: it's incompatible with setting the `REPO` variable. This setting will take precedence._ + +- `BRANCH` (default: `master`): you can use this setting if you want to change the default branch to be + checked out when cloning the repository. This might be useful for testing a Pull Request, or if you + want to use a branch other than `master`. + +For example: + +```sh +REPO=apjanke/oh-my-zsh BRANCH=edge sh install.sh +``` + +#### Manual Installation + +##### 1. Clone The Repository + +```sh +git clone https://github.com/ohmyzsh/ohmyzsh.git ~/.oh-my-zsh +``` + +##### 2. _Optionally_, Backup Your Existing `~/.zshrc` File + +```sh +cp ~/.zshrc ~/.zshrc.orig +``` + +##### 3. Create A New Zsh Configuration File + +You can create a new zsh config file by copying the template that we have included for you. + +```sh +cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc +``` + +##### 4. Change Your Default Shell + +```sh +chsh -s $(which zsh) +``` + +You must log out from your user session and log back in to see this change. + +##### 5. Initialize Your New Zsh Configuration + +Once you open up a new terminal window, it should load zsh with Oh My Zsh's configuration. + +### Installation Problems + +If you have any hiccups installing, here are a few common fixes. + +- You _might_ need to modify your `PATH` in `~/.zshrc` if you're not able to find some commands after switching to `oh-my-zsh`. +- If you installed manually or changed the install location, check the `ZSH` environment variable in `~/.zshrc`. + +### Custom Plugins And Themes + +If you want to override any of the default behaviors, just add a new file (ending in `.zsh`) in the `custom/` directory. + +If you have many functions that go well together, you can put them as a `XYZ.plugin.zsh` file in the `custom/plugins/` directory and then enable this plugin. + +If you would like to override the functionality of a plugin distributed with Oh My Zsh, create a plugin of the same name in the `custom/plugins/` directory and it will be loaded instead of the one in `plugins/`. + +### Enable GNU ls In macOS And freeBSD Systems + +
    + +The default behaviour in Oh My Zsh is to use BSD `ls` in macOS and FreeBSD systems. If GNU `ls` is installed +(as `gls` command), you can choose to use it instead. To do it, you can use zstyle-based config before +sourcing `oh-my-zsh.sh`: + +```zsh +zstyle ':omz:lib:theme-and-appearance' gnu-ls yes +``` + +_Note: this is not compatible with `DISABLE_LS_COLORS=true`_ + +### Skip Aliases + + + +If you want to skip default Oh My Zsh aliases (those defined in `lib/*` files) or plugin aliases, +you can use the settings below in your `~/.zshrc` file, **before Oh My Zsh is loaded**. Note that +there are many different ways to skip aliases, depending on your needs. + +```sh +# Skip all aliases, in lib files and enabled plugins +zstyle ':omz:*' aliases no + +# Skip all aliases in lib files +zstyle ':omz:lib:*' aliases no +# Skip only aliases defined in the directories.zsh lib file +zstyle ':omz:lib:directories' aliases no + +# Skip all plugin aliases +zstyle ':omz:plugins:*' aliases no +# Skip only the aliases from the git plugin +zstyle ':omz:plugins:git' aliases no +``` + +You can combine these in other ways taking into account that more specific scopes take precedence: + +```sh +# Skip all plugin aliases, except for the git plugin +zstyle ':omz:plugins:*' aliases no +zstyle ':omz:plugins:git' aliases yes +``` + +A previous version of this feature was using the setting below, which has been removed: + +```sh +zstyle ':omz:directories' aliases no +``` + +Instead, you can now use the following: + +```sh +zstyle ':omz:lib:directories' aliases no +``` + +### Disable async git prompt + +Async prompt functions are an experimental feature (included on April 3, 2024) that allows Oh My Zsh to render prompt information +asynchronously. This can improve prompt rendering performance, but it might not work well with some setups. We hope that's not an +issue, but if you're seeing problems with this new feature, you can turn it off by setting the following in your .zshrc file, +before Oh My Zsh is sourced: + +```sh +zstyle ':omz:alpha:lib:git' async-prompt no +``` + +#### Notice + +> This feature is currently in a testing phase and it may be subject to change in the future. +> It is also not currently compatible with plugin managers such as zpm or zinit, which don't +> source the init script (`oh-my-zsh.sh`) where this feature is implemented in. + +> It is also not currently aware of "aliases" that are defined as functions. Example of such +> are `gccd`, `ggf`, or `ggl` functions from the git plugin. + +## Getting Updates + +By default, you will be prompted to check for updates every 2 weeks. You can choose other update modes by adding a line to your `~/.zshrc` file, **before Oh My Zsh is loaded**: + +1. Automatic update without confirmation prompt: + + ```sh + zstyle ':omz:update' mode auto + ``` + +2. Just offer a reminder every few days, if there are updates available: + + ```sh + zstyle ':omz:update' mode reminder + ``` + +3. To disable automatic updates entirely: + + ```sh + zstyle ':omz:update' mode disabled + ``` + +NOTE: you can control how often Oh My Zsh checks for updates with the following setting: + +```sh +# This will check for updates every 7 days +zstyle ':omz:update' frequency 7 +# This will check for updates every time you open the terminal (not recommended) +zstyle ':omz:update' frequency 0 +``` + +### Updates Verbosity + +You can also limit the update verbosity with the following settings: + +```sh +zstyle ':omz:update' verbose default # default update prompt + +zstyle ':omz:update' verbose minimal # only few lines + +zstyle ':omz:update' verbose silent # only errors +``` + +### Manual Updates + +If you'd like to update at any point in time (maybe someone just released a new plugin and you don't want to wait a week?) you just need to run: + +```sh +omz update +``` + +Magic! 🎉 + +## Uninstalling Oh My Zsh + +Oh My Zsh isn't for everyone. We'll miss you, but we want to make this an easy breakup. + +If you want to uninstall `oh-my-zsh`, just run `uninstall_oh_my_zsh` from the command-line. It will remove itself and revert your previous `bash` or `zsh` configuration. + +## How Do I Contribute To Oh My Zsh? + +Before you participate in our delightful community, please read the [code of conduct](CODE_OF_CONDUCT.md). + +I'm far from being a [Zsh](https://www.zsh.org/) expert and suspect there are many ways to improve – if you have ideas on how to make the configuration easier to maintain (and faster), don't hesitate to fork and send pull requests! + +We also need people to test out pull requests. So take a look through [the open issues](https://github.com/ohmyzsh/ohmyzsh/issues) and help where you can. + +See [Contributing](CONTRIBUTING.md) for more details. + +### Do Not Send Us Themes + +We have (more than) enough themes for the time being. Please add your theme to the [external themes](https://github.com/ohmyzsh/ohmyzsh/wiki/External-themes) wiki page. + +## Contributors + +Oh My Zsh has a vibrant community of happy users and delightful contributors. Without all the time and help from our contributors, it wouldn't be so awesome. + +Thank you so much! + + + + + +## Follow Us + +We're on social media: + +- [@ohmyzsh](https://twitter.com/ohmyzsh) on Twitter. You should follow it. +- [Facebook](https://www.facebook.com/Oh-My-Zsh-296616263819290/) poke us. +- [Instagram](https://www.instagram.com/_ohmyzsh/) tag us in your post showing Oh My Zsh! +- [Discord](https://discord.gg/ohmyzsh) to chat with us! + +## Merchandise + +We have [stickers, shirts, and coffee mugs available](https://shop.planetargon.com/collections/oh-my-zsh?utm_source=github) for you to show off your love of Oh My Zsh. Again, you will become the talk of the town! + +## License + +Oh My Zsh is released under the [MIT license](LICENSE.txt). + +## About Planet Argon + +![Planet Argon](https://pa-github-assets.s3.amazonaws.com/PARGON_logo_digital_COL-small.jpg) + +Oh My Zsh was started by the team at [Planet Argon](https://www.planetargon.com/?utm_source=github), a [Ruby on Rails development agency](http://www.planetargon.com/services/ruby-on-rails-development?utm_source=github). Check out our [other open source projects](https://www.planetargon.com/open-source?utm_source=github). diff --git a/zsh/.oh-my-zsh/SECURITY.md b/zsh/.oh-my-zsh/SECURITY.md new file mode 100644 index 0000000..d924ffd --- /dev/null +++ b/zsh/.oh-my-zsh/SECURITY.md @@ -0,0 +1,23 @@ +# Security Policy + +## Supported Versions + +At the moment Oh My Zsh only considers the very latest commit to be supported. +We combine that with our fast response to incidents and the automated updates +to minimize the time between vulnerability publication and patch release. + +| Version | Supported | +|:-------------- |:------------------ | +| master | :white_check_mark: | +| other commits | :x: | + +In the near future we will introduce versioning, so expect this section to change. + +## Reporting a Vulnerability + +**Do not submit an issue or pull request**: this might reveal the vulnerability. + +Instead, you should email the maintainers directly at: [**security@ohmyz.sh**](mailto:security@ohmyz.sh), +or using the link to [privately report a vulnerability with GitHub](https://github.com/ohmyzsh/ohmyzsh/security/advisories/new). + +We will deal with the vulnerability privately and submit a patch as soon as possible. diff --git a/zsh/.oh-my-zsh/lib/async_prompt.zsh b/zsh/.oh-my-zsh/lib/async_prompt.zsh new file mode 100644 index 0000000..f2da123 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/async_prompt.zsh @@ -0,0 +1,144 @@ +# The async code is taken from +# https://github.com/zsh-users/zsh-autosuggestions/blob/master/src/async.zsh +# https://github.com/woefe/git-prompt.zsh/blob/master/git-prompt.zsh + +zmodload zsh/system +autoload -Uz is-at-least + +# For now, async prompt function handlers are set up like so: +# First, define the async function handler and register the handler +# with _omz_register_handler: +# +# function _git_prompt_status_async { +# # Do some expensive operation that outputs to stdout +# } +# _omz_register_handler _git_prompt_status_async +# +# Then add a stub prompt function in `$PROMPT` or similar prompt variables, +# which will show the output of "$_OMZ_ASYNC_OUTPUT[handler_name]": +# +# function git_prompt_status { +# echo -n $_OMZ_ASYNC_OUTPUT[_git_prompt_status_async] +# } +# +# RPROMPT='$(git_prompt_status)' +# +# This API is subject to change and optimization. Rely on it at your own risk. + +function _omz_register_handler { + setopt localoptions noksharrays + typeset -ga _omz_async_functions + # we want to do nothing if there's no $1 function or we already set it up + if [[ -z "$1" ]] || (( ! ${+functions[$1]} )) \ + || (( ${_omz_async_functions[(Ie)$1]} )); then + return + fi + _omz_async_functions+=("$1") + # let's add the hook to async_request if it's not there yet + if (( ! ${precmd_functions[(Ie)_omz_async_request]} )) \ + && (( ${+functions[_omz_async_request]})); then + autoload -Uz add-zsh-hook + add-zsh-hook precmd _omz_async_request + fi +} + +# Set up async handlers and callbacks +function _omz_async_request { + local -i ret=$? + typeset -gA _OMZ_ASYNC_FDS _OMZ_ASYNC_PIDS _OMZ_ASYNC_OUTPUT + + # executor runs a subshell for all async requests based on key + local handler + for handler in ${_omz_async_functions}; do + (( ${+functions[$handler]} )) || continue + + local fd=${_OMZ_ASYNC_FDS[$handler]:--1} + local pid=${_OMZ_ASYNC_PIDS[$handler]:--1} + + # If we've got a pending request, cancel it + if (( fd != -1 && pid != -1 )) && { true <&$fd } 2>/dev/null; then + # Close the file descriptor and remove the handler + exec {fd}<&- + zle -F $fd + + # Zsh will make a new process group for the child process only if job + # control is enabled (MONITOR option) + if [[ -o MONITOR ]]; then + # Send the signal to the process group to kill any processes that may + # have been forked by the async function handler + kill -TERM -$pid 2>/dev/null + else + # Kill just the child process since it wasn't placed in a new process + # group. If the async function handler forked any child processes they may + # be orphaned and left behind. + kill -TERM $pid 2>/dev/null + fi + fi + + # Define global variables to store the file descriptor, PID and output + _OMZ_ASYNC_FDS[$handler]=-1 + _OMZ_ASYNC_PIDS[$handler]=-1 + + # Fork a process to fetch the git status and open a pipe to read from it + exec {fd}< <( + # Tell parent process our PID + builtin echo ${sysparams[pid]} + # Set exit code for the handler if used + () { return $ret } + # Run the async function handler + $handler + ) + + # Save FD for handler + _OMZ_ASYNC_FDS[$handler]=$fd + + # There's a weird bug here where ^C stops working unless we force a fork + # See https://github.com/zsh-users/zsh-autosuggestions/issues/364 + # and https://github.com/zsh-users/zsh-autosuggestions/pull/612 + is-at-least 5.8 || command true + + # Save the PID from the handler child process + read -u $fd "_OMZ_ASYNC_PIDS[$handler]" + + # When the fd is readable, call the response handler + zle -F "$fd" _omz_async_callback + done +} + +# Called when new data is ready to be read from the pipe +function _omz_async_callback() { + emulate -L zsh + + local fd=$1 # First arg will be fd ready for reading + local err=$2 # Second arg will be passed in case of error + + if [[ -z "$err" || "$err" == "hup" ]]; then + # Get handler name from fd + local handler="${(k)_OMZ_ASYNC_FDS[(r)$fd]}" + + # Store old output which is supposed to be already printed + local old_output="${_OMZ_ASYNC_OUTPUT[$handler]}" + + # Read output from fd + IFS= read -r -u $fd -d '' "_OMZ_ASYNC_OUTPUT[$handler]" + + # Repaint prompt if output has changed + if [[ "$old_output" != "${_OMZ_ASYNC_OUTPUT[$handler]}" ]]; then + zle .reset-prompt + zle -R + fi + + # Close the fd + exec {fd}<&- + fi + + # Always remove the handler + zle -F "$fd" + + # Unset global FD variable to prevent closing user created FDs in the precmd hook + _OMZ_ASYNC_FDS[$handler]=-1 + _OMZ_ASYNC_PIDS[$handler]=-1 +} + +autoload -Uz add-zsh-hook +add-zsh-hook precmd _omz_async_request diff --git a/zsh/.oh-my-zsh/lib/bzr.zsh b/zsh/.oh-my-zsh/lib/bzr.zsh new file mode 100644 index 0000000..2bad0b3 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/bzr.zsh @@ -0,0 +1,10 @@ +## Bazaar integration +## Just works with the GIT integration just add $(bzr_prompt_info) to the PROMPT +function bzr_prompt_info() { + BZR_CB=`bzr nick 2> /dev/null | grep -v "ERROR" | cut -d ":" -f2 | awk -F / '{print "bzr::"$1}'` + if [ -n "$BZR_CB" ]; then + BZR_DIRTY="" + [[ -n `bzr status` ]] && BZR_DIRTY=" %{$fg[red]%} * %{$fg[green]%}" + echo "$ZSH_THEME_SCM_PROMPT_PREFIX$BZR_CB$BZR_DIRTY$ZSH_THEME_GIT_PROMPT_SUFFIX" + fi +} \ No newline at end of file diff --git a/zsh/.oh-my-zsh/lib/cli.zsh b/zsh/.oh-my-zsh/lib/cli.zsh new file mode 100644 index 0000000..16b260b --- /dev/null +++ b/zsh/.oh-my-zsh/lib/cli.zsh @@ -0,0 +1,839 @@ +#!/usr/bin/env zsh + +function omz { + [[ $# -gt 0 ]] || { + _omz::help + return 1 + } + + local command="$1" + shift + + # Subcommand functions start with _ so that they don't + # appear as completion entries when looking for `omz` + (( ${+functions[_omz::$command]} )) || { + _omz::help + return 1 + } + + _omz::$command "$@" +} + +function _omz { + local -a cmds subcmds + cmds=( + 'changelog:Print the changelog' + 'help:Usage information' + 'plugin:Manage plugins' + 'pr:Manage Oh My Zsh Pull Requests' + 'reload:Reload the current zsh session' + 'theme:Manage themes' + 'update:Update Oh My Zsh' + 'version:Show the version' + ) + + if (( CURRENT == 2 )); then + _describe 'command' cmds + elif (( CURRENT == 3 )); then + case "$words[2]" in + changelog) local -a refs + refs=("${(@f)$(builtin cd -q "$ZSH"; command git for-each-ref --format="%(refname:short):%(subject)" refs/heads refs/tags)}") + _describe 'command' refs ;; + plugin) subcmds=( + 'disable:Disable plugin(s)' + 'enable:Enable plugin(s)' + 'info:Get plugin information' + 'list:List plugins' + 'load:Load plugin(s)' + ) + _describe 'command' subcmds ;; + pr) subcmds=('clean:Delete all Pull Request branches' 'test:Test a Pull Request') + _describe 'command' subcmds ;; + theme) subcmds=('list:List themes' 'set:Set a theme in your .zshrc file' 'use:Load a theme') + _describe 'command' subcmds ;; + esac + elif (( CURRENT == 4 )); then + case "${words[2]}::${words[3]}" in + plugin::(disable|enable|load)) + local -aU valid_plugins + + if [[ "${words[3]}" = disable ]]; then + # if command is "disable", only offer already enabled plugins + valid_plugins=($plugins) + else + valid_plugins=("$ZSH"/plugins/*/{_*,*.plugin.zsh}(-.N:h:t) "$ZSH_CUSTOM"/plugins/*/{_*,*.plugin.zsh}(-.N:h:t)) + # if command is "enable", remove already enabled plugins + [[ "${words[3]}" = enable ]] && valid_plugins=(${valid_plugins:|plugins}) + fi + + _describe 'plugin' valid_plugins ;; + plugin::info) + local -aU plugins + plugins=("$ZSH"/plugins/*/{_*,*.plugin.zsh}(-.N:h:t) "$ZSH_CUSTOM"/plugins/*/{_*,*.plugin.zsh}(-.N:h:t)) + _describe 'plugin' plugins ;; + theme::(set|use)) + local -aU themes + themes=("$ZSH"/themes/*.zsh-theme(-.N:t:r) "$ZSH_CUSTOM"/**/*.zsh-theme(-.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::)) + _describe 'theme' themes ;; + esac + elif (( CURRENT > 4 )); then + case "${words[2]}::${words[3]}" in + plugin::(enable|disable|load)) + local -aU valid_plugins + + if [[ "${words[3]}" = disable ]]; then + # if command is "disable", only offer already enabled plugins + valid_plugins=($plugins) + else + valid_plugins=("$ZSH"/plugins/*/{_*,*.plugin.zsh}(-.N:h:t) "$ZSH_CUSTOM"/plugins/*/{_*,*.plugin.zsh}(-.N:h:t)) + # if command is "enable", remove already enabled plugins + [[ "${words[3]}" = enable ]] && valid_plugins=(${valid_plugins:|plugins}) + fi + + # Remove plugins already passed as arguments + # NOTE: $(( CURRENT - 1 )) is the last plugin argument completely passed, i.e. that which + # has a space after them. This is to avoid removing plugins partially passed, which makes + # the completion not add a space after the completed plugin. + local -a args + args=(${words[4,$(( CURRENT - 1))]}) + valid_plugins=(${valid_plugins:|args}) + + _describe 'plugin' valid_plugins ;; + esac + fi + + return 0 +} + +# If run from a script, do not set the completion function +if (( ${+functions[compdef]} )); then + compdef _omz omz +fi + +## Utility functions + +function _omz::confirm { + # If question supplied, ask it before reading the answer + # NOTE: uses the logname of the caller function + if [[ -n "$1" ]]; then + _omz::log prompt "$1" "${${functrace[1]#_}%:*}" + fi + + # Read one character + read -r -k 1 + + # If no newline entered, add a newline + if [[ "$REPLY" != $'\n' ]]; then + echo + fi +} + +function _omz::log { + # if promptsubst is set, a message with `` or $() + # will be run even if quoted due to `print -P` + setopt localoptions nopromptsubst + + # $1 = info|warn|error|debug + # $2 = text + # $3 = (optional) name of the logger + + local logtype=$1 + local logname=${3:-${${functrace[1]#_}%:*}} + + # Don't print anything if debug is not active + if [[ $logtype = debug && -z $_OMZ_DEBUG ]]; then + return + fi + + # Choose coloring based on log type + case "$logtype" in + prompt) print -Pn "%S%F{blue}$logname%f%s: $2" ;; + debug) print -P "%F{white}$logname%f: $2" ;; + info) print -P "%F{green}$logname%f: $2" ;; + warn) print -P "%S%F{yellow}$logname%f%s: $2" ;; + error) print -P "%S%F{red}$logname%f%s: $2" ;; + esac >&2 +} + +## User-facing commands + +function _omz::help { + cat >&2 < [options] + +Available commands: + + help Print this help message + changelog Print the changelog + plugin Manage plugins + pr Manage Oh My Zsh Pull Requests + reload Reload the current zsh session + theme Manage themes + update Update Oh My Zsh + version Show the version + +EOF +} + +function _omz::changelog { + local version=${1:-HEAD} format=${3:-"--text"} + + if ( + builtin cd -q "$ZSH" + ! command git show-ref --verify refs/heads/$version && \ + ! command git show-ref --verify refs/tags/$version && \ + ! command git rev-parse --verify "${version}^{commit}" + ) &>/dev/null; then + cat >&2 < must be a valid branch, tag or commit. +EOF + return 1 + fi + + "$ZSH/tools/changelog.sh" "$version" "${2:-}" "$format" +} + +function _omz::plugin { + (( $# > 0 && $+functions[$0::$1] )) || { + cat >&2 < [options] + +Available commands: + + disable Disable plugin(s) + enable Enable plugin(s) + info Get information of a plugin + list List all available Oh My Zsh plugins + load Load plugin(s) + +EOF + return 1 + } + + local command="$1" + shift + + $0::$command "$@" +} + +function _omz::plugin::disable { + if [[ -z "$1" ]]; then + echo >&2 "Usage: ${(j: :)${(s.::.)0#_}} [...]" + return 1 + fi + + # Check that plugin is in $plugins + local -a dis_plugins + for plugin in "$@"; do + if [[ ${plugins[(Ie)$plugin]} -eq 0 ]]; then + _omz::log warn "plugin '$plugin' is not enabled." + continue + fi + dis_plugins+=("$plugin") + done + + # Exit if there are no enabled plugins to disable + if [[ ${#dis_plugins} -eq 0 ]]; then + return 1 + fi + + # Remove plugins substitution awk script + local awk_subst_plugins="\ + gsub(/[ \t]+(${(j:|:)dis_plugins})[ \t]+/, \" \") # with spaces before or after + gsub(/[ \t]+(${(j:|:)dis_plugins})$/, \"\") # with spaces before and EOL + gsub(/^(${(j:|:)dis_plugins})[ \t]+/, \"\") # with BOL and spaces after + + gsub(/\((${(j:|:)dis_plugins})[ \t]+/, \"(\") # with parenthesis before and spaces after + gsub(/[ \t]+(${(j:|:)dis_plugins})\)/, \")\") # with spaces before or parenthesis after + gsub(/\((${(j:|:)dis_plugins})\)/, \"()\") # with only parentheses + + gsub(/^(${(j:|:)dis_plugins})\)/, \")\") # with BOL and closing parenthesis + gsub(/\((${(j:|:)dis_plugins})$/, \"(\") # with opening parenthesis and EOL +" + + # Disable plugins awk script + local awk_script=" +# if plugins=() is in oneline form, substitute disabled plugins and go to next line +/^[ \t]*plugins=\([^#]+\).*\$/ { + $awk_subst_plugins + print \$0 + next +} + +# if plugins=() is in multiline form, enable multi flag and disable plugins if they're there +/^[ \t]*plugins=\(/ { + multi=1 + $awk_subst_plugins + print \$0 + next +} + +# if multi flag is enabled and we find a valid closing parenthesis, remove plugins and disable multi flag +multi == 1 && /^[^#]*\)/ { + multi=0 + $awk_subst_plugins + print \$0 + next +} + +multi == 1 && length(\$0) > 0 { + $awk_subst_plugins + if (length(\$0) > 0) print \$0 + next +} + +{ print \$0 } +" + + local zdot="${ZDOTDIR:-$HOME}" + local zshrc="${${:-"${zdot}/.zshrc"}:A}" + awk "$awk_script" "$zshrc" > "$zdot/.zshrc.new" \ + && command cp -f "$zshrc" "$zdot/.zshrc.bck" \ + && command mv -f "$zdot/.zshrc.new" "$zshrc" + + # Exit if the new .zshrc file wasn't created correctly + [[ $? -eq 0 ]] || { + local ret=$? + _omz::log error "error disabling plugins." + return $ret + } + + # Exit if the new .zshrc file has syntax errors + if ! command zsh -n "$zdot/.zshrc"; then + _omz::log error "broken syntax in '"${zdot/#$HOME/\~}/.zshrc"'. Rolling back changes..." + command mv -f "$zdot/.zshrc.bck" "$zshrc" + return 1 + fi + + # Restart the zsh session if there were no errors + _omz::log info "plugins disabled: ${(j:, :)dis_plugins}." + + # Only reload zsh if run in an interactive session + [[ ! -o interactive ]] || _omz::reload +} + +function _omz::plugin::enable { + if [[ -z "$1" ]]; then + echo >&2 "Usage: ${(j: :)${(s.::.)0#_}} [...]" + return 1 + fi + + # Check that plugin is not in $plugins + local -a add_plugins + for plugin in "$@"; do + if [[ ${plugins[(Ie)$plugin]} -ne 0 ]]; then + _omz::log warn "plugin '$plugin' is already enabled." + continue + fi + add_plugins+=("$plugin") + done + + # Exit if there are no plugins to enable + if [[ ${#add_plugins} -eq 0 ]]; then + return 1 + fi + + # Enable plugins awk script + local awk_script=" +# if plugins=() is in oneline form, substitute ) with new plugins and go to the next line +/^[ \t]*plugins=\([^#]+\).*\$/ { + sub(/\)/, \" $add_plugins&\") + print \$0 + next +} + +# if plugins=() is in multiline form, enable multi flag +/^[ \t]*plugins=\(/ { + multi=1 +} + +# if multi flag is enabled and we find a valid closing parenthesis, +# add new plugins and disable multi flag +multi == 1 && /^[^#]*\)/ { + multi=0 + sub(/\)/, \" $add_plugins&\") + print \$0 + next +} + +{ print \$0 } +" + + local zdot="${ZDOTDIR:-$HOME}" + local zshrc="${${:-"${zdot}/.zshrc"}:A}" + awk "$awk_script" "$zshrc" > "$zdot/.zshrc.new" \ + && command cp -f "$zshrc" "$zdot/.zshrc.bck" \ + && command mv -f "$zdot/.zshrc.new" "$zshrc" + + # Exit if the new .zshrc file wasn't created correctly + [[ $? -eq 0 ]] || { + local ret=$? + _omz::log error "error enabling plugins." + return $ret + } + + # Exit if the new .zshrc file has syntax errors + if ! command zsh -n "$zdot/.zshrc"; then + _omz::log error "broken syntax in '"${zdot/#$HOME/\~}/.zshrc"'. Rolling back changes..." + command mv -f "$zdot/.zshrc.bck" "$zshrc" + return 1 + fi + + # Restart the zsh session if there were no errors + _omz::log info "plugins enabled: ${(j:, :)add_plugins}." + + # Only reload zsh if run in an interactive session + [[ ! -o interactive ]] || _omz::reload +} + +function _omz::plugin::info { + if [[ -z "$1" ]]; then + echo >&2 "Usage: ${(j: :)${(s.::.)0#_}} " + return 1 + fi + + local readme + for readme in "$ZSH_CUSTOM/plugins/$1/README.md" "$ZSH/plugins/$1/README.md"; do + if [[ -f "$readme" ]]; then + (( ${+commands[less]} )) && less "$readme" || cat "$readme" + return 0 + fi + done + + if [[ -d "$ZSH_CUSTOM/plugins/$1" || -d "$ZSH/plugins/$1" ]]; then + _omz::log error "the '$1' plugin doesn't have a README file" + else + _omz::log error "'$1' plugin not found" + fi + + return 1 +} + +function _omz::plugin::list { + local -a custom_plugins builtin_plugins + custom_plugins=("$ZSH_CUSTOM"/plugins/*(-/N:t)) + builtin_plugins=("$ZSH"/plugins/*(-/N:t)) + + # If the command is being piped, print all found line by line + if [[ ! -t 1 ]]; then + print -l ${(q-)custom_plugins} ${(q-)builtin_plugins} + return + fi + + if (( ${#custom_plugins} )); then + print -P "%U%BCustom plugins%b%u:" + print -lac ${(q-)custom_plugins} + fi + + if (( ${#builtin_plugins} )); then + (( ${#custom_plugins} )) && echo # add a line of separation + + print -P "%U%BBuilt-in plugins%b%u:" + print -lac ${(q-)builtin_plugins} + fi +} + +function _omz::plugin::load { + if [[ -z "$1" ]]; then + echo >&2 "Usage: ${(j: :)${(s.::.)0#_}} [...]" + return 1 + fi + + local plugin base has_completion=0 + for plugin in "$@"; do + if [[ -d "$ZSH_CUSTOM/plugins/$plugin" ]]; then + base="$ZSH_CUSTOM/plugins/$plugin" + elif [[ -d "$ZSH/plugins/$plugin" ]]; then + base="$ZSH/plugins/$plugin" + else + _omz::log warn "plugin '$plugin' not found" + continue + fi + + # Check if its a valid plugin + if [[ ! -f "$base/_$plugin" && ! -f "$base/$plugin.plugin.zsh" ]]; then + _omz::log warn "'$plugin' is not a valid plugin" + continue + # It is a valid plugin, add its directory to $fpath unless it is already there + elif (( ! ${fpath[(Ie)$base]} )); then + fpath=("$base" $fpath) + fi + + # Check if it has completion to reload compinit + local -a comp_files + comp_files=($base/_*(N)) + has_completion=$(( $#comp_files > 0 )) + + # Load the plugin + if [[ -f "$base/$plugin.plugin.zsh" ]]; then + source "$base/$plugin.plugin.zsh" + fi + done + + # If we have completion, we need to reload the completion + # We pass -D to avoid generating a new dump file, which would overwrite our + # current one for the next session (and we don't want that because we're not + # actually enabling the plugins for the next session). + # Note that we still have to pass -d "$_comp_dumpfile", so that compinit + # doesn't use the default zcompdump location (${ZDOTDIR:-$HOME}/.zcompdump). + if (( has_completion )); then + compinit -D -d "$_comp_dumpfile" + fi +} + +function _omz::pr { + (( $# > 0 && $+functions[$0::$1] )) || { + cat >&2 < [options] + +Available commands: + + clean Delete all PR branches (ohmyzsh/pull-*) + test Fetch PR #NUMBER and rebase against master + +EOF + return 1 + } + + local command="$1" + shift + + $0::$command "$@" +} + +function _omz::pr::clean { + ( + set -e + builtin cd -q "$ZSH" + + # Check if there are PR branches + local fmt branches + fmt="%(color:bold blue)%(align:18,right)%(refname:short)%(end)%(color:reset) %(color:dim bold red)%(objectname:short)%(color:reset) %(color:yellow)%(contents:subject)" + branches="$(command git for-each-ref --sort=-committerdate --color --format="$fmt" "refs/heads/ohmyzsh/pull-*")" + + # Exit if there are no PR branches + if [[ -z "$branches" ]]; then + _omz::log info "there are no Pull Request branches to remove." + return + fi + + # Print found PR branches + echo "$branches\n" + # Confirm before removing the branches + _omz::confirm "do you want remove these Pull Request branches? [Y/n] " + # Only proceed if the answer is a valid yes option + [[ "$REPLY" != [yY$'\n'] ]] && return + + _omz::log info "removing all Oh My Zsh Pull Request branches..." + command git branch --list 'ohmyzsh/pull-*' | while read branch; do + command git branch -D "$branch" + done + ) +} + +function _omz::pr::test { + # Allow $1 to be a URL to the pull request + if [[ "$1" = https://* ]]; then + 1="${1:t}" + fi + + # Check the input + if ! [[ -n "$1" && "$1" =~ ^[[:digit:]]+$ ]]; then + echo >&2 "Usage: ${(j: :)${(s.::.)0#_}} " + return 1 + fi + + # Save current git HEAD + local branch + branch=$(builtin cd -q "$ZSH"; git symbolic-ref --short HEAD) || { + _omz::log error "error when getting the current git branch. Aborting..." + return 1 + } + + + # Fetch PR onto ohmyzsh/pull- branch and rebase against master + # If any of these operations fail, undo the changes made + ( + set -e + builtin cd -q "$ZSH" + + # Get the ohmyzsh git remote + command git remote -v | while read remote url _; do + case "$url" in + https://github.com/ohmyzsh/ohmyzsh(|.git)) found=1; break ;; + git@github.com:ohmyzsh/ohmyzsh(|.git)) found=1; break ;; + esac + done + + (( $found )) || { + _omz::log error "could not found the ohmyzsh git remote. Aborting..." + return 1 + } + + # Fetch pull request head + _omz::log info "fetching PR #$1 to ohmyzsh/pull-$1..." + command git fetch -f "$remote" refs/pull/$1/head:ohmyzsh/pull-$1 || { + _omz::log error "error when trying to fetch PR #$1." + return 1 + } + + # Rebase pull request branch against the current master + _omz::log info "rebasing PR #$1..." + local ret gpgsign + { + # Back up commit.gpgsign setting: use --local to get the current repository + # setting, not the global one. If --local is not a known option, it will + # exit with a 129 status code. + gpgsign=$(command git config --local commit.gpgsign 2>/dev/null) || ret=$? + [[ $ret -ne 129 ]] || gpgsign=$(command git config commit.gpgsign 2>/dev/null) + command git config commit.gpgsign false + + command git rebase master ohmyzsh/pull-$1 || { + command git rebase --abort &>/dev/null + _omz::log warn "could not rebase PR #$1 on top of master." + _omz::log warn "you might not see the latest stable changes." + _omz::log info "run \`zsh\` to test the changes." + return 1 + } + } always { + case "$gpgsign" in + "") command git config --unset commit.gpgsign ;; + *) command git config commit.gpgsign "$gpgsign" ;; + esac + } + + _omz::log info "fetch of PR #${1} successful." + ) + + # If there was an error, abort running zsh to test the PR + [[ $? -eq 0 ]] || return 1 + + # Run zsh to test the changes + _omz::log info "running \`zsh\` to test the changes. Run \`exit\` to go back." + command zsh -l + + # After testing, go back to the previous HEAD if the user wants + _omz::confirm "do you want to go back to the previous branch? [Y/n] " + # Only proceed if the answer is a valid yes option + [[ "$REPLY" != [yY$'\n'] ]] && return + + ( + set -e + builtin cd -q "$ZSH" + + command git checkout "$branch" -- || { + _omz::log error "could not go back to the previous branch ('$branch')." + return 1 + } + ) +} + +function _omz::reload { + # Delete current completion cache + command rm -f $_comp_dumpfile $ZSH_COMPDUMP + + # Old zsh versions don't have ZSH_ARGZERO + local zsh="${ZSH_ARGZERO:-${functrace[-1]%:*}}" + # Check whether to run a login shell + [[ "$zsh" = -* || -o login ]] && exec -l "${zsh#-}" || exec "$zsh" +} + +function _omz::theme { + (( $# > 0 && $+functions[$0::$1] )) || { + cat >&2 < [options] + +Available commands: + + list List all available Oh My Zsh themes + set Set a theme in your .zshrc file + use Load a theme + +EOF + return 1 + } + + local command="$1" + shift + + $0::$command "$@" +} + +function _omz::theme::list { + local -a custom_themes builtin_themes + custom_themes=("$ZSH_CUSTOM"/**/*.zsh-theme(-.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::)) + builtin_themes=("$ZSH"/themes/*.zsh-theme(-.N:t:r)) + + # If the command is being piped, print all found line by line + if [[ ! -t 1 ]]; then + print -l ${(q-)custom_themes} ${(q-)builtin_themes} + return + fi + + # Print theme in use + if [[ -n "$ZSH_THEME" ]]; then + print -Pn "%U%BCurrent theme%b%u: " + [[ $ZSH_THEME = random ]] && echo "$RANDOM_THEME (via random)" || echo "$ZSH_THEME" + echo + fi + + # Print custom themes if there are any + if (( ${#custom_themes} )); then + print -P "%U%BCustom themes%b%u:" + print -lac ${(q-)custom_themes} + echo + fi + + # Print built-in themes + print -P "%U%BBuilt-in themes%b%u:" + print -lac ${(q-)builtin_themes} +} + +function _omz::theme::set { + if [[ -z "$1" ]]; then + echo >&2 "Usage: ${(j: :)${(s.::.)0#_}} " + return 1 + fi + + # Check that theme exists + if [[ ! -f "$ZSH_CUSTOM/$1.zsh-theme" ]] \ + && [[ ! -f "$ZSH_CUSTOM/themes/$1.zsh-theme" ]] \ + && [[ ! -f "$ZSH/themes/$1.zsh-theme" ]]; then + _omz::log error "%B$1%b theme not found" + return 1 + fi + + # Enable theme in .zshrc + local awk_script=' +!set && /^[ \t]*ZSH_THEME=[^#]+.*$/ { + set=1 + sub(/^[ \t]*ZSH_THEME=[^#]+.*$/, "ZSH_THEME=\"'$1'\" # set by `omz`") + print $0 + next +} + +{ print $0 } + +END { + # If no ZSH_THEME= line was found, return an error + if (!set) exit 1 +} +' + + local zdot="${ZDOTDIR:-$HOME}" + local zshrc="${${:-"${zdot}/.zshrc"}:A}" + awk "$awk_script" "$zshrc" > "$zdot/.zshrc.new" \ + || { + # Prepend ZSH_THEME= line to .zshrc if it doesn't exist + cat < "$zdot/.zshrc.new" \ + && command cp -f "$zshrc" "$zdot/.zshrc.bck" \ + && command mv -f "$zdot/.zshrc.new" "$zshrc" + + # Exit if the new .zshrc file wasn't created correctly + [[ $? -eq 0 ]] || { + local ret=$? + _omz::log error "error setting theme." + return $ret + } + + # Exit if the new .zshrc file has syntax errors + if ! command zsh -n "$zdot/.zshrc"; then + _omz::log error "broken syntax in '"${zdot/#$HOME/\~}/.zshrc"'. Rolling back changes..." + command mv -f "$zdot/.zshrc.bck" "$zshrc" + return 1 + fi + + # Restart the zsh session if there were no errors + _omz::log info "'$1' theme set correctly." + + # Only reload zsh if run in an interactive session + [[ ! -o interactive ]] || _omz::reload +} + +function _omz::theme::use { + if [[ -z "$1" ]]; then + echo >&2 "Usage: ${(j: :)${(s.::.)0#_}} " + return 1 + fi + + # Respect compatibility with old lookup order + if [[ -f "$ZSH_CUSTOM/$1.zsh-theme" ]]; then + source "$ZSH_CUSTOM/$1.zsh-theme" + elif [[ -f "$ZSH_CUSTOM/themes/$1.zsh-theme" ]]; then + source "$ZSH_CUSTOM/themes/$1.zsh-theme" + elif [[ -f "$ZSH/themes/$1.zsh-theme" ]]; then + source "$ZSH/themes/$1.zsh-theme" + else + _omz::log error "%B$1%b theme not found" + return 1 + fi + + # Update theme settings + ZSH_THEME="$1" + [[ $1 = random ]] || unset RANDOM_THEME +} + +function _omz::update { + # Check if git command is available + (( $+commands[git] )) || { + _omz::log error "git is not installed. Aborting..." + return 1 + } + + local last_commit=$(builtin cd -q "$ZSH"; git rev-parse HEAD 2>/dev/null) + [[ $? -eq 0 ]] || { + _omz::log error "\`$ZSH\` is not a git directory. Aborting..." + return 1 + } + + # Run update script + zstyle -s ':omz:update' verbose verbose_mode || verbose_mode=default + if [[ "$1" != --unattended ]]; then + ZSH="$ZSH" command zsh -f "$ZSH/tools/upgrade.sh" -i -v $verbose_mode || return $? + else + ZSH="$ZSH" command zsh -f "$ZSH/tools/upgrade.sh" -v $verbose_mode || return $? + fi + + # Update last updated file + zmodload zsh/datetime + echo "LAST_EPOCH=$(( EPOCHSECONDS / 60 / 60 / 24 ))" >! "${ZSH_CACHE_DIR}/.zsh-update" + # Remove update lock if it exists + command rm -rf "$ZSH/log/update.lock" + + # Restart the zsh session if there were changes + if [[ "$1" != --unattended && "$(builtin cd -q "$ZSH"; git rev-parse HEAD)" != "$last_commit" ]]; then + # Old zsh versions don't have ZSH_ARGZERO + local zsh="${ZSH_ARGZERO:-${functrace[-1]%:*}}" + # Check whether to run a login shell + [[ "$zsh" = -* || -o login ]] && exec -l "${zsh#-}" || exec "$zsh" + fi +} + +function _omz::version { + ( + builtin cd -q "$ZSH" + + # Get the version name: + # 1) try tag-like version + # 2) try branch name + # 3) try name-rev (tag~ or branch~) + local version + version=$(command git describe --tags HEAD 2>/dev/null) \ + || version=$(command git symbolic-ref --quiet --short HEAD 2>/dev/null) \ + || version=$(command git name-rev --no-undefined --name-only --exclude="remotes/*" HEAD 2>/dev/null) \ + || version="" + + # Get short hash for the current HEAD + local commit=$(command git rev-parse --short HEAD 2>/dev/null) + + # Show version and commit hash + printf "%s (%s)\n" "$version" "$commit" + ) +} diff --git a/zsh/.oh-my-zsh/lib/clipboard.zsh b/zsh/.oh-my-zsh/lib/clipboard.zsh new file mode 100644 index 0000000..65b05f6 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/clipboard.zsh @@ -0,0 +1,107 @@ +# System clipboard integration +# +# This file has support for doing system clipboard copy and paste operations +# from the command line in a generic cross-platform fashion. +# +# This is uses essentially the same heuristic as neovim, with the additional +# special support for Cygwin. +# See: https://github.com/neovim/neovim/blob/e682d799fa3cf2e80a02d00c6ea874599d58f0e7/runtime/autoload/provider/clipboard.vim#L55-L121 +# +# - pbcopy, pbpaste (macOS) +# - cygwin (Windows running Cygwin) +# - wl-copy, wl-paste (if $WAYLAND_DISPLAY is set) +# - xsel (if $DISPLAY is set) +# - xclip (if $DISPLAY is set) +# - lemonade (for SSH) https://github.com/pocke/lemonade +# - doitclient (for SSH) http://www.chiark.greenend.org.uk/~sgtatham/doit/ +# - win32yank (Windows) +# - tmux (if $TMUX is set) +# +# Defines two functions, clipcopy and clippaste, based on the detected platform. +## +# +# clipcopy - Copy data to clipboard +# +# Usage: +# +# | clipcopy - copies stdin to clipboard +# +# clipcopy - copies a file's contents to clipboard +# +## +# +# clippaste - "Paste" data from clipboard to stdout +# +# Usage: +# +# clippaste - writes clipboard's contents to stdout +# +# clippaste | - pastes contents and pipes it to another process +# +# clippaste > - paste contents to a file +# +# Examples: +# +# # Pipe to another process +# clippaste | grep foo +# +# # Paste to a file +# clippaste > file.txt +# +function detect-clipboard() { + emulate -L zsh + + if [[ "${OSTYPE}" == darwin* ]] && (( ${+commands[pbcopy]} )) && (( ${+commands[pbpaste]} )); then + function clipcopy() { cat "${1:-/dev/stdin}" | pbcopy; } + function clippaste() { pbpaste; } + elif [[ "${OSTYPE}" == (cygwin|msys)* ]]; then + function clipcopy() { cat "${1:-/dev/stdin}" > /dev/clipboard; } + function clippaste() { cat /dev/clipboard; } + elif (( $+commands[clip.exe] )) && (( $+commands[powershell.exe] )); then + function clipcopy() { cat "${1:-/dev/stdin}" | clip.exe; } + function clippaste() { powershell.exe -noprofile -command Get-Clipboard; } + elif [ -n "${WAYLAND_DISPLAY:-}" ] && (( ${+commands[wl-copy]} )) && (( ${+commands[wl-paste]} )); then + function clipcopy() { cat "${1:-/dev/stdin}" | wl-copy &>/dev/null &|; } + function clippaste() { wl-paste --no-newline; } + elif [ -n "${DISPLAY:-}" ] && (( ${+commands[xsel]} )); then + function clipcopy() { cat "${1:-/dev/stdin}" | xsel --clipboard --input; } + function clippaste() { xsel --clipboard --output; } + elif [ -n "${DISPLAY:-}" ] && (( ${+commands[xclip]} )); then + function clipcopy() { cat "${1:-/dev/stdin}" | xclip -selection clipboard -in &>/dev/null &|; } + function clippaste() { xclip -out -selection clipboard; } + elif (( ${+commands[lemonade]} )); then + function clipcopy() { cat "${1:-/dev/stdin}" | lemonade copy; } + function clippaste() { lemonade paste; } + elif (( ${+commands[doitclient]} )); then + function clipcopy() { cat "${1:-/dev/stdin}" | doitclient wclip; } + function clippaste() { doitclient wclip -r; } + elif (( ${+commands[win32yank]} )); then + function clipcopy() { cat "${1:-/dev/stdin}" | win32yank -i; } + function clippaste() { win32yank -o; } + elif [[ $OSTYPE == linux-android* ]] && (( $+commands[termux-clipboard-set] )); then + function clipcopy() { cat "${1:-/dev/stdin}" | termux-clipboard-set; } + function clippaste() { termux-clipboard-get; } + elif [ -n "${TMUX:-}" ] && (( ${+commands[tmux]} )); then + function clipcopy() { tmux load-buffer "${1:--}"; } + function clippaste() { tmux save-buffer -; } + else + function _retry_clipboard_detection_or_fail() { + local clipcmd="${1}"; shift + if detect-clipboard; then + "${clipcmd}" "$@" + else + print "${clipcmd}: Platform $OSTYPE not supported or xclip/xsel not installed" >&2 + return 1 + fi + } + function clipcopy() { _retry_clipboard_detection_or_fail clipcopy "$@"; } + function clippaste() { _retry_clipboard_detection_or_fail clippaste "$@"; } + return 1 + fi +} + +function clipcopy clippaste { + unfunction clipcopy clippaste + detect-clipboard || true # let one retry + "$0" "$@" +} diff --git a/zsh/.oh-my-zsh/lib/compfix.zsh b/zsh/.oh-my-zsh/lib/compfix.zsh new file mode 100644 index 0000000..e1ea518 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/compfix.zsh @@ -0,0 +1,44 @@ +# Handle completions insecurities (i.e., completion-dependent directories with +# insecure ownership or permissions) by: +# +# * Human-readably notifying the user of these insecurities. +function handle_completion_insecurities() { + # List of the absolute paths of all unique insecure directories, split on + # newline from compaudit()'s output resembling: + # + # There are insecure directories: + # /usr/share/zsh/site-functions + # /usr/share/zsh/5.0.6/functions + # /usr/share/zsh + # /usr/share/zsh/5.0.6 + # + # Since the ignorable first line is printed to stderr and thus not captured, + # stderr is squelched to prevent this output from leaking to the user. + local -aU insecure_dirs + insecure_dirs=( ${(f@):-"$(compaudit 2>/dev/null)"} ) + + # If no such directories exist, get us out of here. + [[ -z "${insecure_dirs}" ]] && return + + # List ownership and permissions of all insecure directories. + print "[oh-my-zsh] Insecure completion-dependent directories detected:" + ls -ld "${(@)insecure_dirs}" + + cat < +# +# Usage: +# +# omz_diagnostic_dump [-v] [-V] [file] +# +# NOTE: This is a work in progress. Its interface and behavior are going to change, +# and probably in non-back-compatible ways. +# +# Outputs a bunch of information about the state and configuration of +# oh-my-zsh, zsh, and the user's system. This is intended to provide a +# bunch of context for diagnosing your own or a third party's problems, and to +# be suitable for posting to public bug reports. +# +# The output is human-readable and its format may change over time. It is not +# suitable for parsing. All the output is in one single file so it can be posted +# as a gist or bug comment on GitHub. GitHub doesn't support attaching tarballs +# or other files to bugs; otherwise, this would probably have an option to produce +# tarballs that contain copies of the config and customization files instead of +# catting them all in to one file. +# +# This is intended to be widely portable, and run anywhere that oh-my-zsh does. +# Feel free to report any portability issues as bugs. +# +# This is written in a defensive style so it still works (and can detect) cases when +# basic functionality like echo and which have been redefined. In particular, almost +# everything is invoked with "builtin" or "command", to work in the face of user +# redefinitions. +# +# OPTIONS +# +# [file] Specifies the output file. If not given, a file in the current directory +# is selected automatically. +# +# -v Increase the verbosity of the dump output. May be specified multiple times. +# Verbosity levels: +# 0 - Basic info, shell state, omz configuration, git state +# 1 - (default) Adds key binding info and configuration file contents +# 2 - Adds zcompdump file contents +# +# -V Reduce the verbosity of the dump output. May be specified multiple times. +# +# TODO: +# * Multi-file capture +# * Add automatic gist uploading +# * Consider whether to move default output file location to TMPDIR. More robust +# but less user friendly. +# + +autoload -Uz is-at-least + +function omz_diagnostic_dump() { + emulate -L zsh + + builtin echo "Generating diagnostic dump; please be patient..." + + local thisfcn=omz_diagnostic_dump + local -A opts + local opt_verbose opt_noverbose opt_outfile + local timestamp=$(date +%Y%m%d-%H%M%S) + local outfile=omz_diagdump_$timestamp.txt + builtin zparseopts -A opts -D -- "v+=opt_verbose" "V+=opt_noverbose" + local verbose n_verbose=${#opt_verbose} n_noverbose=${#opt_noverbose} + (( verbose = 1 + n_verbose - n_noverbose )) + + if [[ ${#*} > 0 ]]; then + opt_outfile=$1 + fi + if [[ ${#*} > 1 ]]; then + builtin echo "$thisfcn: error: too many arguments" >&2 + return 1 + fi + if [[ -n "$opt_outfile" ]]; then + outfile="$opt_outfile" + fi + + # Always write directly to a file so terminal escape sequences are + # captured cleanly + _omz_diag_dump_one_big_text &> "$outfile" + if [[ $? != 0 ]]; then + builtin echo "$thisfcn: error while creating diagnostic dump; see $outfile for details" + fi + + builtin echo + builtin echo Diagnostic dump file created at: "$outfile" + builtin echo + builtin echo To share this with OMZ developers, post it as a gist on GitHub + builtin echo at "https://gist.github.com" and share the link to the gist. + builtin echo + builtin echo "WARNING: This dump file contains all your zsh and omz configuration files," + builtin echo "so don't share it publicly if there's sensitive information in them." + builtin echo + +} + +function _omz_diag_dump_one_big_text() { + local program programs progfile md5 + + builtin echo oh-my-zsh diagnostic dump + builtin echo + builtin echo $outfile + builtin echo + + # Basic system and zsh information + command date + command uname -a + builtin echo OSTYPE=$OSTYPE + builtin echo ZSH_VERSION=$ZSH_VERSION + builtin echo User: $USERNAME + builtin echo umask: $(umask) + builtin echo + _omz_diag_dump_os_specific_version + builtin echo + + # Installed programs + programs=(sh zsh ksh bash sed cat grep ls find git posh) + local progfile="" extra_str="" sha_str="" + for program in $programs; do + extra_str="" sha_str="" + progfile=$(builtin which $program) + if [[ $? == 0 ]]; then + if [[ -e $progfile ]]; then + if builtin whence shasum &>/dev/null; then + sha_str=($(command shasum $progfile)) + sha_str=$sha_str[1] + extra_str+=" SHA $sha_str" + fi + if [[ -h "$progfile" ]]; then + extra_str+=" ( -> ${progfile:A} )" + fi + fi + builtin printf '%-9s %-20s %s\n' "$program is" "$progfile" "$extra_str" + else + builtin echo "$program: not found" + fi + done + builtin echo + builtin echo Command Versions: + builtin echo "zsh: $(zsh --version)" + builtin echo "this zsh session: $ZSH_VERSION" + builtin echo "bash: $(bash --version | command grep bash)" + builtin echo "git: $(git --version)" + builtin echo "grep: $(grep --version)" + builtin echo + + # Core command definitions + _omz_diag_dump_check_core_commands || return 1 + builtin echo + + # ZSH Process state + builtin echo Process state: + builtin echo pwd: $PWD + if builtin whence pstree &>/dev/null; then + builtin echo Process tree for this shell: + pstree -p $$ + else + ps -fT + fi + builtin set | command grep -a '^\(ZSH\|plugins\|TERM\|LC_\|LANG\|precmd\|chpwd\|preexec\|FPATH\|TTY\|DISPLAY\|PATH\)\|OMZ' + builtin echo + #TODO: Should this include `env` instead of or in addition to `export`? + builtin echo Exported: + builtin echo $(builtin export | command sed 's/=.*//') + builtin echo + builtin echo Locale: + command locale + builtin echo + + # Zsh installation and configuration + builtin echo Zsh configuration: + builtin echo setopt: $(builtin setopt) + builtin echo + builtin echo zstyle: + builtin zstyle + builtin echo + builtin echo 'compaudit output:' + compaudit + builtin echo + builtin echo '$fpath directories:' + command ls -lad $fpath + builtin echo + + # Oh-my-zsh installation + builtin echo oh-my-zsh installation: + command ls -ld ~/.z* + command ls -ld ~/.oh* + builtin echo + builtin echo oh-my-zsh git state: + (builtin cd $ZSH && builtin echo "HEAD: $(git rev-parse HEAD)" && git remote -v && git status | command grep "[^[:space:]]") + if [[ $verbose -ge 1 ]]; then + (builtin cd $ZSH && git reflog --date=default | command grep pull) + fi + builtin echo + if [[ -e $ZSH_CUSTOM ]]; then + local custom_dir=$ZSH_CUSTOM + if [[ -h $custom_dir ]]; then + custom_dir=$(builtin cd $custom_dir && pwd -P) + fi + builtin echo "oh-my-zsh custom dir:" + builtin echo " $ZSH_CUSTOM ($custom_dir)" + (builtin cd ${custom_dir:h} && command find ${custom_dir:t} -name .git -prune -o -print) + builtin echo + fi + + # Key binding and terminal info + if [[ $verbose -ge 1 ]]; then + builtin echo "bindkey:" + builtin bindkey + builtin echo + builtin echo "infocmp:" + command infocmp -L + builtin echo + fi + + # Configuration file info + local zdotdir=${ZDOTDIR:-$HOME} + builtin echo "Zsh configuration files:" + local cfgfile cfgfiles + # Some files for bash that zsh does not use are intentionally included + # to help with diagnosing behavior differences between bash and zsh + cfgfiles=( /etc/zshenv /etc/zprofile /etc/zshrc /etc/zlogin /etc/zlogout + $zdotdir/.zshenv $zdotdir/.zprofile $zdotdir/.zshrc $zdotdir/.zlogin $zdotdir/.zlogout + ~/.zsh.pre-oh-my-zsh + /etc/bashrc /etc/profile ~/.bashrc ~/.profile ~/.bash_profile ~/.bash_logout ) + command ls -lad $cfgfiles 2>&1 + builtin echo + if [[ $verbose -ge 1 ]]; then + for cfgfile in $cfgfiles; do + _omz_diag_dump_echo_file_w_header $cfgfile + done + fi + builtin echo + builtin echo "Zsh compdump files:" + local dumpfile dumpfiles + command ls -lad $zdotdir/.zcompdump* + dumpfiles=( $zdotdir/.zcompdump*(N) ) + if [[ $verbose -ge 2 ]]; then + for dumpfile in $dumpfiles; do + _omz_diag_dump_echo_file_w_header $dumpfile + done + fi + +} + +function _omz_diag_dump_check_core_commands() { + builtin echo "Core command check:" + local redefined name builtins externals reserved_words + redefined=() + # All the zsh non-module builtin commands + # These are taken from the zsh reference manual for 5.0.2 + # Commands from modules should not be included. + # (For back-compatibility, if any of these are newish, they should be removed, + # or at least made conditional on the version of the current running zsh.) + # "history" is also excluded because OMZ is known to redefine that + reserved_words=( do done esac then elif else fi for case if while function + repeat time until select coproc nocorrect foreach end '!' '[[' '{' '}' + ) + builtins=( alias autoload bg bindkey break builtin bye cd chdir command + comparguments compcall compctl compdescribe compfiles compgroups compquote comptags + comptry compvalues continue dirs disable disown echo echotc echoti emulate + enable eval exec exit false fc fg functions getln getopts hash + jobs kill let limit log logout noglob popd print printf + pushd pushln pwd r read rehash return sched set setopt shift + source suspend test times trap true ttyctl type ulimit umask unalias + unfunction unhash unlimit unset unsetopt vared wait whence where which zcompile + zle zmodload zparseopts zregexparse zstyle ) + if is-at-least 5.1; then + reserved_word+=( declare export integer float local readonly typeset ) + else + builtins+=( declare export integer float local readonly typeset ) + fi + builtins_fatal=( builtin command local ) + externals=( zsh ) + for name in $reserved_words; do + if [[ $(builtin whence -w $name) != "$name: reserved" ]]; then + builtin echo "reserved word '$name' has been redefined" + builtin which $name + redefined+=$name + fi + done + for name in $builtins; do + if [[ $(builtin whence -w $name) != "$name: builtin" ]]; then + builtin echo "builtin '$name' has been redefined" + builtin which $name + redefined+=$name + fi + done + for name in $externals; do + if [[ $(builtin whence -w $name) != "$name: command" ]]; then + builtin echo "command '$name' has been redefined" + builtin which $name + redefined+=$name + fi + done + + if [[ -n "$redefined" ]]; then + builtin echo "SOME CORE COMMANDS HAVE BEEN REDEFINED: $redefined" + else + builtin echo "All core commands are defined normally" + fi + +} + +function _omz_diag_dump_echo_file_w_header() { + local file=$1 + if [[ ( -f $file || -h $file ) ]]; then + builtin echo "========== $file ==========" + if [[ -h $file ]]; then + builtin echo "========== ( => ${file:A} ) ==========" + fi + command cat $file + builtin echo "========== end $file ==========" + builtin echo + elif [[ -d $file ]]; then + builtin echo "File '$file' is a directory" + elif [[ ! -e $file ]]; then + builtin echo "File '$file' does not exist" + else + command ls -lad "$file" + fi +} + +function _omz_diag_dump_os_specific_version() { + local osname osver version_file version_files + case "$OSTYPE" in + darwin*) + osname=$(command sw_vers -productName) + osver=$(command sw_vers -productVersion) + builtin echo "OS Version: $osname $osver build $(sw_vers -buildVersion)" + ;; + cygwin) + command systeminfo | command head -n 4 | command tail -n 2 + ;; + esac + + if builtin which lsb_release >/dev/null; then + builtin echo "OS Release: $(command lsb_release -s -d)" + fi + + version_files=( /etc/*-release(N) /etc/*-version(N) /etc/*_version(N) ) + for version_file in $version_files; do + builtin echo "$version_file:" + command cat "$version_file" + builtin echo + done +} + diff --git a/zsh/.oh-my-zsh/lib/directories.zsh b/zsh/.oh-my-zsh/lib/directories.zsh new file mode 100644 index 0000000..bd01529 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/directories.zsh @@ -0,0 +1,40 @@ +# Changing/making/removing directory +setopt auto_cd +setopt auto_pushd +setopt pushd_ignore_dups +setopt pushdminus + + +alias -g ...='../..' +alias -g ....='../../..' +alias -g .....='../../../..' +alias -g ......='../../../../..' + +alias -- -='cd -' +alias 1='cd -1' +alias 2='cd -2' +alias 3='cd -3' +alias 4='cd -4' +alias 5='cd -5' +alias 6='cd -6' +alias 7='cd -7' +alias 8='cd -8' +alias 9='cd -9' + +alias md='mkdir -p' +alias rd=rmdir + +function d () { + if [[ -n $1 ]]; then + dirs "$@" + else + dirs -v | head -n 10 + fi +} +compdef _dirs d + +# List directory contents +alias lsa='ls -lah' +alias l='ls -lah' +alias ll='ls -lh' +alias la='ls -lAh' diff --git a/zsh/.oh-my-zsh/lib/functions.zsh b/zsh/.oh-my-zsh/lib/functions.zsh new file mode 100644 index 0000000..4cee90f --- /dev/null +++ b/zsh/.oh-my-zsh/lib/functions.zsh @@ -0,0 +1,267 @@ +function zsh_stats() { + fc -l 1 \ + | awk '{ CMD[$2]++; count++; } END { for (a in CMD) print CMD[a] " " CMD[a]*100/count "% " a }' \ + | grep -v "./" | sort -nr | head -n 20 | column -c3 -s " " -t | nl +} + +function uninstall_oh_my_zsh() { + command env ZSH="$ZSH" sh "$ZSH/tools/uninstall.sh" +} + +function upgrade_oh_my_zsh() { + echo >&2 "${fg[yellow]}Note: \`$0\` is deprecated. Use \`omz update\` instead.$reset_color" + omz update +} + +function open_command() { + local open_cmd + + # define the open command + case "$OSTYPE" in + darwin*) open_cmd='open' ;; + cygwin*) open_cmd='cygstart' ;; + linux*) [[ "$(uname -r)" != *icrosoft* ]] && open_cmd='nohup xdg-open' || { + open_cmd='cmd.exe /c start ""' + [[ -e "$1" ]] && { 1="$(wslpath -w "${1:a}")" || return 1 } + } ;; + msys*) open_cmd='start ""' ;; + *) echo "Platform $OSTYPE not supported" + return 1 + ;; + esac + + # If a URL is passed, $BROWSER might be set to a local browser within SSH. + # See https://github.com/ohmyzsh/ohmyzsh/issues/11098 + if [[ -n "$BROWSER" && "$1" = (http|https)://* ]]; then + "$BROWSER" "$@" + return + fi + + ${=open_cmd} "$@" &>/dev/null +} + +# take functions + +# mkcd is equivalent to takedir +function mkcd takedir() { + mkdir -p $@ && cd ${@:$#} +} + +function takeurl() { + local data thedir + data="$(mktemp)" + curl -L "$1" > "$data" + tar xf "$data" + thedir="$(tar tf "$data" | head -n 1)" + rm "$data" + cd "$thedir" +} + +function takegit() { + git clone "$1" + cd "$(basename ${1%%.git})" +} + +function take() { + if [[ $1 =~ ^(https?|ftp).*\.(tar\.(gz|bz2|xz)|tgz)$ ]]; then + takeurl "$1" + elif [[ $1 =~ ^([A-Za-z0-9]\+@|https?|git|ssh|ftps?|rsync).*\.git/?$ ]]; then + takegit "$1" + else + takedir "$@" + fi +} + +# +# Get the value of an alias. +# +# Arguments: +# 1. alias - The alias to get its value from +# STDOUT: +# The value of alias $1 (if it has one). +# Return value: +# 0 if the alias was found, +# 1 if it does not exist +# +function alias_value() { + (( $+aliases[$1] )) && echo $aliases[$1] +} + +# +# Try to get the value of an alias, +# otherwise return the input. +# +# Arguments: +# 1. alias - The alias to get its value from +# STDOUT: +# The value of alias $1, or $1 if there is no alias $1. +# Return value: +# Always 0 +# +function try_alias_value() { + alias_value "$1" || echo "$1" +} + +# +# Set variable "$1" to default value "$2" if "$1" is not yet defined. +# +# Arguments: +# 1. name - The variable to set +# 2. val - The default value +# Return value: +# 0 if the variable exists, 3 if it was set +# +function default() { + (( $+parameters[$1] )) && return 0 + typeset -g "$1"="$2" && return 3 +} + +# +# Set environment variable "$1" to default value "$2" if "$1" is not yet defined. +# +# Arguments: +# 1. name - The env variable to set +# 2. val - The default value +# Return value: +# 0 if the env variable exists, 3 if it was set +# +function env_default() { + [[ ${parameters[$1]} = *-export* ]] && return 0 + export "$1=$2" && return 3 +} + + +# Required for $langinfo +zmodload zsh/langinfo + +# URL-encode a string +# +# Encodes a string using RFC 2396 URL-encoding (%-escaped). +# See: https://www.ietf.org/rfc/rfc2396.txt +# +# By default, reserved characters and unreserved "mark" characters are +# not escaped by this function. This allows the common usage of passing +# an entire URL in, and encoding just special characters in it, with +# the expectation that reserved and mark characters are used appropriately. +# The -r and -m options turn on escaping of the reserved and mark characters, +# respectively, which allows arbitrary strings to be fully escaped for +# embedding inside URLs, where reserved characters might be misinterpreted. +# +# Prints the encoded string on stdout. +# Returns nonzero if encoding failed. +# +# Usage: +# omz_urlencode [-r] [-m] [-P] [ ...] +# +# -r causes reserved characters (;/?:@&=+$,) to be escaped +# +# -m causes "mark" characters (_.!~*''()-) to be escaped +# +# -P causes spaces to be encoded as '%20' instead of '+' +function omz_urlencode() { + emulate -L zsh + local -a opts + zparseopts -D -E -a opts r m P + + local in_str="$@" + local url_str="" + local spaces_as_plus + if [[ -z $opts[(r)-P] ]]; then spaces_as_plus=1; fi + local str="$in_str" + + # URLs must use UTF-8 encoding; convert str to UTF-8 if required + local encoding=$langinfo[CODESET] + local safe_encodings + safe_encodings=(UTF-8 utf8 US-ASCII) + if [[ -z ${safe_encodings[(r)$encoding]} ]]; then + str=$(echo -E "$str" | iconv -f $encoding -t UTF-8) + if [[ $? != 0 ]]; then + echo "Error converting string from $encoding to UTF-8" >&2 + return 1 + fi + fi + + # Use LC_CTYPE=C to process text byte-by-byte + # Note that this doesn't work in Termux, as it only has UTF-8 locale. + # Characters will be processed as UTF-8, which is fine for URLs. + local i byte ord LC_ALL=C + export LC_ALL + local reserved=';/?:@&=+$,' + local mark='_.!~*''()-' + local dont_escape="[A-Za-z0-9" + if [[ -z $opts[(r)-r] ]]; then + dont_escape+=$reserved + fi + # $mark must be last because of the "-" + if [[ -z $opts[(r)-m] ]]; then + dont_escape+=$mark + fi + dont_escape+="]" + + # Implemented to use a single printf call and avoid subshells in the loop, + # for performance (primarily on Windows). + local url_str="" + for (( i = 1; i <= ${#str}; ++i )); do + byte="$str[i]" + if [[ "$byte" =~ "$dont_escape" ]]; then + url_str+="$byte" + else + if [[ "$byte" == " " && -n $spaces_as_plus ]]; then + url_str+="+" + elif [[ "$PREFIX" = *com.termux* ]]; then + # Termux does not have non-UTF8 locales, so just send the UTF-8 character directly + url_str+="$byte" + else + ord=$(( [##16] #byte )) + url_str+="%$ord" + fi + fi + done + echo -E "$url_str" +} + +# URL-decode a string +# +# Decodes a RFC 2396 URL-encoded (%-escaped) string. +# This decodes the '+' and '%' escapes in the input string, and leaves +# other characters unchanged. Does not enforce that the input is a +# valid URL-encoded string. This is a convenience to allow callers to +# pass in a full URL or similar strings and decode them for human +# presentation. +# +# Outputs the encoded string on stdout. +# Returns nonzero if encoding failed. +# +# Usage: +# omz_urldecode - prints decoded string followed by a newline +function omz_urldecode { + emulate -L zsh + local encoded_url=$1 + + # Work bytewise, since URLs escape UTF-8 octets + local caller_encoding=$langinfo[CODESET] + local LC_ALL=C + export LC_ALL + + # Change + back to ' ' + local tmp=${encoded_url:gs/+/ /} + # Protect other escapes to pass through the printf unchanged + tmp=${tmp:gs/\\/\\\\/} + # Handle %-escapes by turning them into `\xXX` printf escapes + tmp=${tmp:gs/%/\\x/} + local decoded="$(printf -- "$tmp")" + + # Now we have a UTF-8 encoded string in the variable. We need to re-encode + # it if caller is in a non-UTF-8 locale. + local -a safe_encodings + safe_encodings=(UTF-8 utf8 US-ASCII) + if [[ -z ${safe_encodings[(r)$caller_encoding]} ]]; then + decoded=$(echo -E "$decoded" | iconv -f UTF-8 -t $caller_encoding) + if [[ $? != 0 ]]; then + echo "Error converting string from UTF-8 to $caller_encoding" >&2 + return 1 + fi + fi + + echo -E "$decoded" +} diff --git a/zsh/.oh-my-zsh/lib/git.zsh b/zsh/.oh-my-zsh/lib/git.zsh new file mode 100644 index 0000000..d802924 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/git.zsh @@ -0,0 +1,334 @@ +autoload -Uz is-at-least + +# The git prompt's git commands are read-only and should not interfere with +# other processes. This environment variable is equivalent to running with `git +# --no-optional-locks`, but falls back gracefully for older versions of git. +# See git(1) for and git-status(1) for a description of that flag. +# +# We wrap in a local function instead of exporting the variable directly in +# order to avoid interfering with manually-run git commands by the user. +function __git_prompt_git() { + GIT_OPTIONAL_LOCKS=0 command git "$@" +} + +function _omz_git_prompt_info() { + # If we are on a folder not tracked by git, get out. + # Otherwise, check for hide-info at global and local repository level + if ! __git_prompt_git rev-parse --git-dir &> /dev/null \ + || [[ "$(__git_prompt_git config --get oh-my-zsh.hide-info 2>/dev/null)" == 1 ]]; then + return 0 + fi + + # Get either: + # - the current branch name + # - the tag name if we are on a tag + # - the short SHA of the current commit + local ref + ref=$(__git_prompt_git symbolic-ref --short HEAD 2> /dev/null) \ + || ref=$(__git_prompt_git describe --tags --exact-match HEAD 2> /dev/null) \ + || ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) \ + || return 0 + + # Use global ZSH_THEME_GIT_SHOW_UPSTREAM=1 for including upstream remote info + local upstream + if (( ${+ZSH_THEME_GIT_SHOW_UPSTREAM} )); then + upstream=$(__git_prompt_git rev-parse --abbrev-ref --symbolic-full-name "@{upstream}" 2>/dev/null) \ + && upstream=" -> ${upstream}" + fi + + echo "${ZSH_THEME_GIT_PROMPT_PREFIX}${ref:gs/%/%%}${upstream:gs/%/%%}$(parse_git_dirty)${ZSH_THEME_GIT_PROMPT_SUFFIX}" +} + +# Use async version if setting is enabled or undefined +if zstyle -T ':omz:alpha:lib:git' async-prompt; then + function git_prompt_info() { + if [[ -n "${_OMZ_ASYNC_OUTPUT[_omz_git_prompt_info]}" ]]; then + echo -n "${_OMZ_ASYNC_OUTPUT[_omz_git_prompt_info]}" + fi + } + + function git_prompt_status() { + if [[ -n "${_OMZ_ASYNC_OUTPUT[_omz_git_prompt_status]}" ]]; then + echo -n "${_OMZ_ASYNC_OUTPUT[_omz_git_prompt_status]}" + fi + } + + # Conditionally register the async handler, only if it's needed in $PROMPT + # or any of the other prompt variables + function _defer_async_git_register() { + # Check if git_prompt_info is used in a prompt variable + case "${PS1}:${PS2}:${PS3}:${PS4}:${RPROMPT}:${RPS1}:${RPS2}:${RPS3}:${RPS4}" in + *(\$\(git_prompt_info\)|\`git_prompt_info\`)*) + _omz_register_handler _omz_git_prompt_info + ;; + esac + + case "${PS1}:${PS2}:${PS3}:${PS4}:${RPROMPT}:${RPS1}:${RPS2}:${RPS3}:${RPS4}" in + *(\$\(git_prompt_status\)|\`git_prompt_status\`)*) + _omz_register_handler _omz_git_prompt_status + ;; + esac + + add-zsh-hook -d precmd _defer_async_git_register + unset -f _defer_async_git_register + } + + # Register the async handler first. This needs to be done before + # the async request prompt is run + precmd_functions=(_defer_async_git_register $precmd_functions) +else + function git_prompt_info() { + _omz_git_prompt_info + } + function git_prompt_status() { + _omz_git_prompt_status + } +fi + +# Checks if working tree is dirty +function parse_git_dirty() { + local STATUS + local -a FLAGS + FLAGS=('--porcelain') + if [[ "$(__git_prompt_git config --get oh-my-zsh.hide-dirty)" != "1" ]]; then + if [[ "${DISABLE_UNTRACKED_FILES_DIRTY:-}" == "true" ]]; then + FLAGS+='--untracked-files=no' + fi + case "${GIT_STATUS_IGNORE_SUBMODULES:-}" in + git) + # let git decide (this respects per-repo config in .gitmodules) + ;; + *) + # if unset: ignore dirty submodules + # other values are passed to --ignore-submodules + FLAGS+="--ignore-submodules=${GIT_STATUS_IGNORE_SUBMODULES:-dirty}" + ;; + esac + STATUS=$(__git_prompt_git status ${FLAGS} 2> /dev/null | tail -n 1) + fi + if [[ -n $STATUS ]]; then + echo "$ZSH_THEME_GIT_PROMPT_DIRTY" + else + echo "$ZSH_THEME_GIT_PROMPT_CLEAN" + fi +} + +# Gets the difference between the local and remote branches +function git_remote_status() { + local remote ahead behind git_remote_status git_remote_status_detailed + remote=${$(__git_prompt_git rev-parse --verify ${hook_com[branch]}@{upstream} --symbolic-full-name 2>/dev/null)/refs\/remotes\/} + if [[ -n ${remote} ]]; then + ahead=$(__git_prompt_git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l) + behind=$(__git_prompt_git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l) + + if [[ $ahead -eq 0 ]] && [[ $behind -eq 0 ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_EQUAL_REMOTE" + elif [[ $ahead -gt 0 ]] && [[ $behind -eq 0 ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE" + git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}" + elif [[ $behind -gt 0 ]] && [[ $ahead -eq 0 ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE" + git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}" + elif [[ $ahead -gt 0 ]] && [[ $behind -gt 0 ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE" + git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}" + fi + + if [[ -n $ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_DETAILED ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_PREFIX${remote:gs/%/%%}$git_remote_status_detailed$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_SUFFIX" + fi + + echo $git_remote_status + fi +} + +# Outputs the name of the current branch +# Usage example: git pull origin $(git_current_branch) +# Using '--quiet' with 'symbolic-ref' will not cause a fatal error (128) if +# it's not a symbolic ref, but in a Git repo. +function git_current_branch() { + local ref + ref=$(__git_prompt_git symbolic-ref --quiet HEAD 2> /dev/null) + local ret=$? + if [[ $ret != 0 ]]; then + [[ $ret == 128 ]] && return # no git repo. + ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) || return + fi + echo ${ref#refs/heads/} +} + + +# Gets the number of commits ahead from remote +function git_commits_ahead() { + if __git_prompt_git rev-parse --git-dir &>/dev/null; then + local commits="$(__git_prompt_git rev-list --count @{upstream}..HEAD 2>/dev/null)" + if [[ -n "$commits" && "$commits" != 0 ]]; then + echo "$ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX$commits$ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX" + fi + fi +} + +# Gets the number of commits behind remote +function git_commits_behind() { + if __git_prompt_git rev-parse --git-dir &>/dev/null; then + local commits="$(__git_prompt_git rev-list --count HEAD..@{upstream} 2>/dev/null)" + if [[ -n "$commits" && "$commits" != 0 ]]; then + echo "$ZSH_THEME_GIT_COMMITS_BEHIND_PREFIX$commits$ZSH_THEME_GIT_COMMITS_BEHIND_SUFFIX" + fi + fi +} + +# Outputs if current branch is ahead of remote +function git_prompt_ahead() { + if [[ -n "$(__git_prompt_git rev-list origin/$(git_current_branch)..HEAD 2> /dev/null)" ]]; then + echo "$ZSH_THEME_GIT_PROMPT_AHEAD" + fi +} + +# Outputs if current branch is behind remote +function git_prompt_behind() { + if [[ -n "$(__git_prompt_git rev-list HEAD..origin/$(git_current_branch) 2> /dev/null)" ]]; then + echo "$ZSH_THEME_GIT_PROMPT_BEHIND" + fi +} + +# Outputs if current branch exists on remote or not +function git_prompt_remote() { + if [[ -n "$(__git_prompt_git show-ref origin/$(git_current_branch) 2> /dev/null)" ]]; then + echo "$ZSH_THEME_GIT_PROMPT_REMOTE_EXISTS" + else + echo "$ZSH_THEME_GIT_PROMPT_REMOTE_MISSING" + fi +} + +# Formats prompt string for current git commit short SHA +function git_prompt_short_sha() { + local SHA + SHA=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" +} + +# Formats prompt string for current git commit long SHA +function git_prompt_long_sha() { + local SHA + SHA=$(__git_prompt_git rev-parse HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" +} + +function _omz_git_prompt_status() { + [[ "$(__git_prompt_git config --get oh-my-zsh.hide-status 2>/dev/null)" = 1 ]] && return + + # Maps a git status prefix to an internal constant + # This cannot use the prompt constants, as they may be empty + local -A prefix_constant_map + prefix_constant_map=( + '\?\? ' 'UNTRACKED' + 'A ' 'ADDED' + 'M ' 'ADDED' + 'MM ' 'MODIFIED' + ' M ' 'MODIFIED' + 'AM ' 'MODIFIED' + ' T ' 'MODIFIED' + 'R ' 'RENAMED' + ' D ' 'DELETED' + 'D ' 'DELETED' + 'UU ' 'UNMERGED' + 'ahead' 'AHEAD' + 'behind' 'BEHIND' + 'diverged' 'DIVERGED' + 'stashed' 'STASHED' + ) + + # Maps the internal constant to the prompt theme + local -A constant_prompt_map + constant_prompt_map=( + 'UNTRACKED' "$ZSH_THEME_GIT_PROMPT_UNTRACKED" + 'ADDED' "$ZSH_THEME_GIT_PROMPT_ADDED" + 'MODIFIED' "$ZSH_THEME_GIT_PROMPT_MODIFIED" + 'RENAMED' "$ZSH_THEME_GIT_PROMPT_RENAMED" + 'DELETED' "$ZSH_THEME_GIT_PROMPT_DELETED" + 'UNMERGED' "$ZSH_THEME_GIT_PROMPT_UNMERGED" + 'AHEAD' "$ZSH_THEME_GIT_PROMPT_AHEAD" + 'BEHIND' "$ZSH_THEME_GIT_PROMPT_BEHIND" + 'DIVERGED' "$ZSH_THEME_GIT_PROMPT_DIVERGED" + 'STASHED' "$ZSH_THEME_GIT_PROMPT_STASHED" + ) + + # The order that the prompt displays should be added to the prompt + local status_constants + status_constants=( + UNTRACKED ADDED MODIFIED RENAMED DELETED + STASHED UNMERGED AHEAD BEHIND DIVERGED + ) + + local status_text + status_text="$(__git_prompt_git status --porcelain -b 2> /dev/null)" + + # Don't continue on a catastrophic failure + if [[ $? -eq 128 ]]; then + return 1 + fi + + # A lookup table of each git status encountered + local -A statuses_seen + + if __git_prompt_git rev-parse --verify refs/stash &>/dev/null; then + statuses_seen[STASHED]=1 + fi + + local status_lines + status_lines=("${(@f)${status_text}}") + + # If the tracking line exists, get and parse it + if [[ "$status_lines[1]" =~ "^## [^ ]+ \[(.*)\]" ]]; then + local branch_statuses + branch_statuses=("${(@s/,/)match}") + for branch_status in $branch_statuses; do + if [[ ! $branch_status =~ "(behind|diverged|ahead) ([0-9]+)?" ]]; then + continue + fi + local last_parsed_status=$prefix_constant_map[$match[1]] + statuses_seen[$last_parsed_status]=$match[2] + done + fi + + # For each status prefix, do a regex comparison + for status_prefix in ${(k)prefix_constant_map}; do + local status_constant="${prefix_constant_map[$status_prefix]}" + local status_regex=$'(^|\n)'"$status_prefix" + + if [[ "$status_text" =~ $status_regex ]]; then + statuses_seen[$status_constant]=1 + fi + done + + # Display the seen statuses in the order specified + local status_prompt + for status_constant in $status_constants; do + if (( ${+statuses_seen[$status_constant]} )); then + local next_display=$constant_prompt_map[$status_constant] + status_prompt="$next_display$status_prompt" + fi + done + + echo $status_prompt +} + +# Outputs the name of the current user +# Usage example: $(git_current_user_name) +function git_current_user_name() { + __git_prompt_git config user.name 2>/dev/null +} + +# Outputs the email of the current user +# Usage example: $(git_current_user_email) +function git_current_user_email() { + __git_prompt_git config user.email 2>/dev/null +} + +# Output the name of the root directory of the git repository +# Usage example: $(git_repo_name) +function git_repo_name() { + local repo_path + if repo_path="$(__git_prompt_git rev-parse --show-toplevel 2>/dev/null)" && [[ -n "$repo_path" ]]; then + echo ${repo_path:t} + fi +} diff --git a/zsh/.oh-my-zsh/lib/grep.zsh b/zsh/.oh-my-zsh/lib/grep.zsh new file mode 100644 index 0000000..17794a9 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/grep.zsh @@ -0,0 +1,41 @@ +__GREP_CACHE_FILE="$ZSH_CACHE_DIR"/grep-alias + +# See if there's a cache file modified in the last day +__GREP_ALIAS_CACHES=("$__GREP_CACHE_FILE"(Nm-1)) +if [[ -n "$__GREP_ALIAS_CACHES" ]]; then + source "$__GREP_CACHE_FILE" +else + grep-flags-available() { + command grep "$@" "" &>/dev/null <<< "" + } + + # Ignore these folders (if the necessary grep flags are available) + EXC_FOLDERS="{.bzr,CVS,.git,.hg,.svn,.idea,.tox}" + + # Check for --exclude-dir, otherwise check for --exclude. If --exclude + # isn't available, --color won't be either (they were released at the same + # time (v2.5): https://git.savannah.gnu.org/cgit/grep.git/tree/NEWS?id=1236f007 + if grep-flags-available --color=auto --exclude-dir=.cvs; then + GREP_OPTIONS="--color=auto --exclude-dir=$EXC_FOLDERS" + elif grep-flags-available --color=auto --exclude=.cvs; then + GREP_OPTIONS="--color=auto --exclude=$EXC_FOLDERS" + fi + + if [[ -n "$GREP_OPTIONS" ]]; then + # export grep, egrep and fgrep settings + alias grep="grep $GREP_OPTIONS" + alias egrep="grep -E $GREP_OPTIONS" + alias fgrep="grep -F $GREP_OPTIONS" + + # write to cache file if cache directory is writable + if [[ -w "$ZSH_CACHE_DIR" ]]; then + alias -L grep egrep fgrep >| "$__GREP_CACHE_FILE" + fi + fi + + # Clean up + unset GREP_OPTIONS EXC_FOLDERS + unfunction grep-flags-available +fi + +unset __GREP_CACHE_FILE __GREP_ALIAS_CACHES diff --git a/zsh/.oh-my-zsh/lib/history.zsh b/zsh/.oh-my-zsh/lib/history.zsh new file mode 100644 index 0000000..7863102 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/history.zsh @@ -0,0 +1,41 @@ +## History wrapper +function omz_history { + # parse arguments and remove from $@ + local clear list stamp + zparseopts -E -D c=clear l=list f=stamp E=stamp i=stamp t:=stamp + + if [[ -n "$clear" ]]; then + # if -c provided, clobber the history file + echo -n >| "$HISTFILE" + fc -p "$HISTFILE" + echo >&2 History file deleted. + elif [[ $# -eq 0 ]]; then + # if no arguments provided, show full history starting from 1 + builtin fc $stamp -l 1 + else + # otherwise, run `fc -l` with a custom format + builtin fc $stamp -l "$@" + fi +} + +# Timestamp format +case ${HIST_STAMPS-} in + "mm/dd/yyyy") alias history='omz_history -f' ;; + "dd.mm.yyyy") alias history='omz_history -E' ;; + "yyyy-mm-dd") alias history='omz_history -i' ;; + "") alias history='omz_history' ;; + *) alias history="omz_history -t '$HIST_STAMPS'" ;; +esac + +## History file configuration +[ -z "$HISTFILE" ] && HISTFILE="$HOME/.zsh_history" +[ "$HISTSIZE" -lt 50000 ] && HISTSIZE=50000 +[ "$SAVEHIST" -lt 10000 ] && SAVEHIST=10000 + +## History command configuration +setopt extended_history # record timestamp of command in HISTFILE +setopt hist_expire_dups_first # delete duplicates first when HISTFILE size exceeds HISTSIZE +setopt hist_ignore_dups # ignore duplicated commands history list +setopt hist_ignore_space # ignore commands that start with space +setopt hist_verify # show command with history expansion to user before running it +setopt share_history # share command history data diff --git a/zsh/.oh-my-zsh/lib/key-bindings.zsh b/zsh/.oh-my-zsh/lib/key-bindings.zsh new file mode 100644 index 0000000..3c59377 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/key-bindings.zsh @@ -0,0 +1,145 @@ +# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html +# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Builtins +# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Standard-Widgets + +# Make sure that the terminal is in application mode when zle is active, since +# only then values from $terminfo are valid +if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then + function zle-line-init() { + echoti smkx + } + function zle-line-finish() { + echoti rmkx + } + zle -N zle-line-init + zle -N zle-line-finish +fi + +# Use emacs key bindings +bindkey -e + +# [PageUp] - Up a line of history +if [[ -n "${terminfo[kpp]}" ]]; then + bindkey -M emacs "${terminfo[kpp]}" up-line-or-history + bindkey -M viins "${terminfo[kpp]}" up-line-or-history + bindkey -M vicmd "${terminfo[kpp]}" up-line-or-history +fi +# [PageDown] - Down a line of history +if [[ -n "${terminfo[knp]}" ]]; then + bindkey -M emacs "${terminfo[knp]}" down-line-or-history + bindkey -M viins "${terminfo[knp]}" down-line-or-history + bindkey -M vicmd "${terminfo[knp]}" down-line-or-history +fi + +# Start typing + [Up-Arrow] - fuzzy find history forward +autoload -U up-line-or-beginning-search +zle -N up-line-or-beginning-search + +bindkey -M emacs "^[[A" up-line-or-beginning-search +bindkey -M viins "^[[A" up-line-or-beginning-search +bindkey -M vicmd "^[[A" up-line-or-beginning-search +if [[ -n "${terminfo[kcuu1]}" ]]; then + bindkey -M emacs "${terminfo[kcuu1]}" up-line-or-beginning-search + bindkey -M viins "${terminfo[kcuu1]}" up-line-or-beginning-search + bindkey -M vicmd "${terminfo[kcuu1]}" up-line-or-beginning-search +fi + +# Start typing + [Down-Arrow] - fuzzy find history backward +autoload -U down-line-or-beginning-search +zle -N down-line-or-beginning-search + +bindkey -M emacs "^[[B" down-line-or-beginning-search +bindkey -M viins "^[[B" down-line-or-beginning-search +bindkey -M vicmd "^[[B" down-line-or-beginning-search +if [[ -n "${terminfo[kcud1]}" ]]; then + bindkey -M emacs "${terminfo[kcud1]}" down-line-or-beginning-search + bindkey -M viins "${terminfo[kcud1]}" down-line-or-beginning-search + bindkey -M vicmd "${terminfo[kcud1]}" down-line-or-beginning-search +fi + +# [Home] - Go to beginning of line +if [[ -n "${terminfo[khome]}" ]]; then + bindkey -M emacs "${terminfo[khome]}" beginning-of-line + bindkey -M viins "${terminfo[khome]}" beginning-of-line + bindkey -M vicmd "${terminfo[khome]}" beginning-of-line +fi +# [End] - Go to end of line +if [[ -n "${terminfo[kend]}" ]]; then + bindkey -M emacs "${terminfo[kend]}" end-of-line + bindkey -M viins "${terminfo[kend]}" end-of-line + bindkey -M vicmd "${terminfo[kend]}" end-of-line +fi + +# [Shift-Tab] - move through the completion menu backwards +if [[ -n "${terminfo[kcbt]}" ]]; then + bindkey -M emacs "${terminfo[kcbt]}" reverse-menu-complete + bindkey -M viins "${terminfo[kcbt]}" reverse-menu-complete + bindkey -M vicmd "${terminfo[kcbt]}" reverse-menu-complete +fi + +# [Backspace] - delete backward +bindkey -M emacs '^?' backward-delete-char +bindkey -M viins '^?' backward-delete-char +bindkey -M vicmd '^?' backward-delete-char +# [Delete] - delete forward +if [[ -n "${terminfo[kdch1]}" ]]; then + bindkey -M emacs "${terminfo[kdch1]}" delete-char + bindkey -M viins "${terminfo[kdch1]}" delete-char + bindkey -M vicmd "${terminfo[kdch1]}" delete-char +else + bindkey -M emacs "^[[3~" delete-char + bindkey -M viins "^[[3~" delete-char + bindkey -M vicmd "^[[3~" delete-char + + bindkey -M emacs "^[3;5~" delete-char + bindkey -M viins "^[3;5~" delete-char + bindkey -M vicmd "^[3;5~" delete-char +fi + +# [Ctrl-Delete] - delete whole forward-word +bindkey -M emacs '^[[3;5~' kill-word +bindkey -M viins '^[[3;5~' kill-word +bindkey -M vicmd '^[[3;5~' kill-word + +# [Ctrl-RightArrow] - move forward one word +bindkey -M emacs '^[[1;5C' forward-word +bindkey -M viins '^[[1;5C' forward-word +bindkey -M vicmd '^[[1;5C' forward-word +# [Ctrl-LeftArrow] - move backward one word +bindkey -M emacs '^[[1;5D' backward-word +bindkey -M viins '^[[1;5D' backward-word +bindkey -M vicmd '^[[1;5D' backward-word + + +bindkey '\ew' kill-region # [Esc-w] - Kill from the cursor to the mark +bindkey -s '\el' 'ls\n' # [Esc-l] - run command: ls +bindkey '^r' history-incremental-search-backward # [Ctrl-r] - Search backward incrementally for a specified string. The string may begin with ^ to anchor the search to the beginning of the line. +bindkey ' ' magic-space # [Space] - don't do history expansion + + +# Edit the current command line in $EDITOR +autoload -U edit-command-line +zle -N edit-command-line +bindkey '\C-x\C-e' edit-command-line + +# file rename magick +bindkey "^[m" copy-prev-shell-word + +# consider emacs keybindings: + +#bindkey -e ## emacs key bindings +# +#bindkey '^[[A' up-line-or-search +#bindkey '^[[B' down-line-or-search +#bindkey '^[^[[C' emacs-forward-word +#bindkey '^[^[[D' emacs-backward-word +# +#bindkey -s '^X^Z' '%-^M' +#bindkey '^[e' expand-cmd-path +#bindkey '^[^I' reverse-menu-complete +#bindkey '^X^N' accept-and-infer-next-history +#bindkey '^W' kill-region +#bindkey '^I' complete-word +## Fix weird sequence that rxvt produces +#bindkey -s '^[[Z' '\t' +# diff --git a/zsh/.oh-my-zsh/lib/misc.zsh b/zsh/.oh-my-zsh/lib/misc.zsh new file mode 100644 index 0000000..a223863 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/misc.zsh @@ -0,0 +1,38 @@ +autoload -Uz is-at-least + +# *-magic is known buggy in some versions; disable if so +if [[ $DISABLE_MAGIC_FUNCTIONS != true ]]; then + for d in $fpath; do + if [[ -e "$d/url-quote-magic" ]]; then + if is-at-least 5.1; then + autoload -Uz bracketed-paste-magic + zle -N bracketed-paste bracketed-paste-magic + fi + autoload -Uz url-quote-magic + zle -N self-insert url-quote-magic + break + fi + done +fi + +setopt multios # enable redirect to multiple streams: echo >file1 >file2 +setopt long_list_jobs # show long list format job notifications +setopt interactivecomments # recognize comments + +# define pager dependant on what is available (less or more) +if (( ${+commands[less]} )); then + env_default 'PAGER' 'less' + env_default 'LESS' '-R' +elif (( ${+commands[more]} )); then + env_default 'PAGER' 'more' +fi + +## super user alias +alias _='sudo ' + +## more intelligent acking for ubuntu users and no alias for users without ack +if (( $+commands[ack-grep] )); then + alias afind='ack-grep -il' +elif (( $+commands[ack] )); then + alias afind='ack -il' +fi diff --git a/zsh/.oh-my-zsh/lib/nvm.zsh b/zsh/.oh-my-zsh/lib/nvm.zsh new file mode 100644 index 0000000..d73c938 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/nvm.zsh @@ -0,0 +1,6 @@ +# get the nvm-controlled node.js version +function nvm_prompt_info() { + which nvm &>/dev/null || return + local nvm_prompt=${$(nvm current)#v} + echo "${ZSH_THEME_NVM_PROMPT_PREFIX}${nvm_prompt:gs/%/%%}${ZSH_THEME_NVM_PROMPT_SUFFIX}" +} diff --git a/zsh/.oh-my-zsh/lib/prompt_info_functions.zsh b/zsh/.oh-my-zsh/lib/prompt_info_functions.zsh new file mode 100644 index 0000000..90a0ee8 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/prompt_info_functions.zsh @@ -0,0 +1,44 @@ +# *_prompt_info functions for usage in your prompt +# +# Plugin creators, please add your *_prompt_info function to the list +# of dummy implementations to help theme creators not receiving errors +# without the need of implementing conditional clauses. +# +# See also lib/bzr.zsh, lib/git.zsh and lib/nvm.zsh for +# git_prompt_info, bzr_prompt_info and nvm_prompt_info + +# Dummy implementations that return false to prevent command_not_found +# errors with themes, that implement these functions +# Real implementations will be used when the respective plugins are loaded +function chruby_prompt_info \ + rbenv_prompt_info \ + hg_prompt_info \ + pyenv_prompt_info \ + svn_prompt_info \ + vi_mode_prompt_info \ + virtualenv_prompt_info \ + jenv_prompt_info \ + azure_prompt_info \ + tf_prompt_info \ +{ + return 1 +} + +# oh-my-zsh supports an rvm prompt by default +# get the name of the rvm ruby version +function rvm_prompt_info() { + [ -f $HOME/.rvm/bin/rvm-prompt ] || return 1 + local rvm_prompt + rvm_prompt=$($HOME/.rvm/bin/rvm-prompt ${=ZSH_THEME_RVM_PROMPT_OPTIONS} 2>/dev/null) + [[ -z "${rvm_prompt}" ]] && return 1 + echo "${ZSH_THEME_RUBY_PROMPT_PREFIX}${rvm_prompt:gs/%/%%}${ZSH_THEME_RUBY_PROMPT_SUFFIX}" +} + +ZSH_THEME_RVM_PROMPT_OPTIONS="i v g" + + +# use this to enable users to see their ruby version, no matter which +# version management system they use +function ruby_prompt_info() { + echo "$(rvm_prompt_info || rbenv_prompt_info || chruby_prompt_info)" +} diff --git a/zsh/.oh-my-zsh/lib/spectrum.zsh b/zsh/.oh-my-zsh/lib/spectrum.zsh new file mode 100644 index 0000000..791c303 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/spectrum.zsh @@ -0,0 +1,38 @@ +# A script to make using 256 colors in zsh less painful. +# P.C. Shyamshankar +# Copied from https://github.com/sykora/etc/blob/master/zsh/functions/spectrum/ + +typeset -AHg FX FG BG + +FX=( + reset "%{%}" + bold "%{%}" no-bold "%{%}" + dim "%{%}" no-dim "%{%}" + italic "%{%}" no-italic "%{%}" + underline "%{%}" no-underline "%{%}" + blink "%{%}" no-blink "%{%}" + reverse "%{%}" no-reverse "%{%}" +) + +for color in {000..255}; do + FG[$color]="%{[38;5;${color}m%}" + BG[$color]="%{[48;5;${color}m%}" +done + +# Show all 256 colors with color number +function spectrum_ls() { + setopt localoptions nopromptsubst + local ZSH_SPECTRUM_TEXT=${ZSH_SPECTRUM_TEXT:-Arma virumque cano Troiae qui primus ab oris} + for code in {000..255}; do + print -P -- "$code: ${FG[$code]}${ZSH_SPECTRUM_TEXT}%{$reset_color%}" + done +} + +# Show all 256 colors where the background is set to specific color +function spectrum_bls() { + setopt localoptions nopromptsubst + local ZSH_SPECTRUM_TEXT=${ZSH_SPECTRUM_TEXT:-Arma virumque cano Troiae qui primus ab oris} + for code in {000..255}; do + print -P -- "$code: ${BG[$code]}${ZSH_SPECTRUM_TEXT}%{$reset_color%}" + done +} diff --git a/zsh/.oh-my-zsh/lib/termsupport.zsh b/zsh/.oh-my-zsh/lib/termsupport.zsh new file mode 100644 index 0000000..3d1f127 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/termsupport.zsh @@ -0,0 +1,163 @@ +# Set terminal window and tab/icon title +# +# usage: title short_tab_title [long_window_title] +# +# See: http://www.faqs.org/docs/Linux-mini/Xterm-Title.html#ss3.1 +# Fully supports screen, iterm, and probably most modern xterm and rxvt +# (In screen, only short_tab_title is used) +# Limited support for Apple Terminal (Terminal can't set window and tab separately) +function title { + setopt localoptions nopromptsubst + + # Don't set the title if inside emacs, unless using vterm + [[ -n "${INSIDE_EMACS:-}" && "$INSIDE_EMACS" != vterm ]] && return + + # if $2 is unset use $1 as default + # if it is set and empty, leave it as is + : ${2=$1} + + case "$TERM" in + cygwin|xterm*|putty*|rxvt*|konsole*|ansi|mlterm*|alacritty*|st*|foot*|contour*) + print -Pn "\e]2;${2:q}\a" # set window name + print -Pn "\e]1;${1:q}\a" # set tab name + ;; + screen*|tmux*) + print -Pn "\ek${1:q}\e\\" # set screen hardstatus + ;; + *) + if [[ "$TERM_PROGRAM" == "iTerm.app" ]]; then + print -Pn "\e]2;${2:q}\a" # set window name + print -Pn "\e]1;${1:q}\a" # set tab name + else + # Try to use terminfo to set the title if the feature is available + if (( ${+terminfo[fsl]} && ${+terminfo[tsl]} )); then + print -Pn "${terminfo[tsl]}$1${terminfo[fsl]}" + fi + fi + ;; + esac +} + +ZSH_THEME_TERM_TAB_TITLE_IDLE="%15<..<%~%<<" #15 char left truncated PWD +ZSH_THEME_TERM_TITLE_IDLE="%n@%m:%~" +# Avoid duplication of directory in terminals with independent dir display +if [[ "$TERM_PROGRAM" == Apple_Terminal ]]; then + ZSH_THEME_TERM_TITLE_IDLE="%n@%m" +fi + +# Runs before showing the prompt +function omz_termsupport_precmd { + [[ "${DISABLE_AUTO_TITLE:-}" != true ]] || return + title "$ZSH_THEME_TERM_TAB_TITLE_IDLE" "$ZSH_THEME_TERM_TITLE_IDLE" +} + +# Runs before executing the command +function omz_termsupport_preexec { + [[ "${DISABLE_AUTO_TITLE:-}" != true ]] || return + + emulate -L zsh + setopt extended_glob + + # split command into array of arguments + local -a cmdargs + cmdargs=("${(z)2}") + # if running fg, extract the command from the job description + if [[ "${cmdargs[1]}" = fg ]]; then + # get the job id from the first argument passed to the fg command + local job_id jobspec="${cmdargs[2]#%}" + # logic based on jobs arguments: + # http://zsh.sourceforge.net/Doc/Release/Jobs-_0026-Signals.html#Jobs + # https://www.zsh.org/mla/users/2007/msg00704.html + case "$jobspec" in + <->) # %number argument: + # use the same passed as an argument + job_id=${jobspec} ;; + ""|%|+) # empty, %% or %+ argument: + # use the current job, which appears with a + in $jobstates: + # suspended:+:5071=suspended (tty output) + job_id=${(k)jobstates[(r)*:+:*]} ;; + -) # %- argument: + # use the previous job, which appears with a - in $jobstates: + # suspended:-:6493=suspended (signal) + job_id=${(k)jobstates[(r)*:-:*]} ;; + [?]*) # %?string argument: + # use $jobtexts to match for a job whose command *contains* + job_id=${(k)jobtexts[(r)*${(Q)jobspec}*]} ;; + *) # %string argument: + # use $jobtexts to match for a job whose command *starts with* + job_id=${(k)jobtexts[(r)${(Q)jobspec}*]} ;; + esac + + # override preexec function arguments with job command + if [[ -n "${jobtexts[$job_id]}" ]]; then + 1="${jobtexts[$job_id]}" + 2="${jobtexts[$job_id]}" + fi + fi + + # cmd name only, or if this is sudo or ssh, the next cmd + local CMD="${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%}" + local LINE="${2:gs/%/%%}" + + title "$CMD" "%100>...>${LINE}%<<" +} + +autoload -Uz add-zsh-hook + +if [[ -z "$INSIDE_EMACS" || "$INSIDE_EMACS" = vterm ]]; then + add-zsh-hook precmd omz_termsupport_precmd + add-zsh-hook preexec omz_termsupport_preexec +fi + +# Keep terminal emulator's current working directory correct, +# even if the current working directory path contains symbolic links +# +# References: +# - Apple's Terminal.app: https://superuser.com/a/315029 +# - iTerm2: https://iterm2.com/documentation-escape-codes.html (iTerm2 Extension / CurrentDir+RemoteHost) +# - Konsole: https://bugs.kde.org/show_bug.cgi?id=327720#c1 +# - libvte (gnome-terminal, mate-terminal, …): https://bugzilla.gnome.org/show_bug.cgi?id=675987#c14 +# Apparently it had a bug before ~2012 were it would display the unknown OSC 7 code +# +# As of May 2021 mlterm, PuTTY, rxvt, screen, termux & xterm simply ignore the unknown OSC. + +# Don't define the function if we're inside Emacs or in an SSH session (#11696) +if [[ -n "$INSIDE_EMACS" || -n "$SSH_CLIENT" || -n "$SSH_TTY" ]]; then + return +fi + +# Don't define the function if we're in an unsupported terminal +case "$TERM" in + # all of these either process OSC 7 correctly or ignore entirely + xterm*|putty*|rxvt*|konsole*|mlterm*|alacritty*|screen*|tmux*) ;; + contour*|foot*) ;; + *) + # Terminal.app and iTerm2 process OSC 7 correctly + case "$TERM_PROGRAM" in + Apple_Terminal|iTerm.app) ;; + *) return ;; + esac ;; +esac + +# Emits the control sequence to notify many terminal emulators +# of the cwd +# +# Identifies the directory using a file: URI scheme, including +# the host name to disambiguate local vs. remote paths. +function omz_termsupport_cwd { + # Percent-encode the host and path names. + local URL_HOST URL_PATH + URL_HOST="$(omz_urlencode -P $HOST)" || return 1 + URL_PATH="$(omz_urlencode -P $PWD)" || return 1 + + # Konsole errors if the HOST is provided + [[ -z "$KONSOLE_PROFILE_NAME" && -z "$KONSOLE_DBUS_SESSION" ]] || URL_HOST="" + + # common control sequence (OSC 7) to set current host and path + printf "\e]7;file://%s%s\e\\" "${URL_HOST}" "${URL_PATH}" +} + +# Use a precmd hook instead of a chpwd hook to avoid contaminating output +# i.e. when a script or function changes directory without `cd -q`, chpwd +# will be called the output may be swallowed by the script or function. +add-zsh-hook precmd omz_termsupport_cwd diff --git a/zsh/.oh-my-zsh/lib/tests/cli.test.zsh b/zsh/.oh-my-zsh/lib/tests/cli.test.zsh new file mode 100644 index 0000000..fd1095a --- /dev/null +++ b/zsh/.oh-my-zsh/lib/tests/cli.test.zsh @@ -0,0 +1,169 @@ +#!/usr/bin/zsh -df + +run_awk() { + local -a dis_plugins=(${=1}) + local input_text="$2" + + (( ! DEBUG )) || set -xv + + local awk_subst_plugins="\ + gsub(/[ \t]+(${(j:|:)dis_plugins})[ \t]+/, \" \") # with spaces before or after + gsub(/[ \t]+(${(j:|:)dis_plugins})$/, \"\") # with spaces before and EOL + gsub(/^(${(j:|:)dis_plugins})[ \t]+/, \"\") # with BOL and spaces after + + gsub(/\((${(j:|:)dis_plugins})[ \t]+/, \"(\") # with parenthesis before and spaces after + gsub(/[ \t]+(${(j:|:)dis_plugins})\)/, \")\") # with spaces before or parenthesis after + gsub(/\((${(j:|:)dis_plugins})\)/, \"()\") # with only parentheses + + gsub(/^(${(j:|:)dis_plugins})\)/, \")\") # with BOL and closing parenthesis + gsub(/\((${(j:|:)dis_plugins})$/, \"(\") # with opening parenthesis and EOL + " + # Disable plugins awk script + local awk_script=" + # if plugins=() is in oneline form, substitute disabled plugins and go to next line + /^[ \t]*plugins=\([^#]+\).*\$/ { + $awk_subst_plugins + print \$0 + next + } + + # if plugins=() is in multiline form, enable multi flag and disable plugins if they're there + /^[ \t]*plugins=\(/ { + multi=1 + $awk_subst_plugins + print \$0 + next + } + + # if multi flag is enabled and we find a valid closing parenthesis, remove plugins and disable multi flag + multi == 1 && /^[^#]*\)/ { + multi=0 + $awk_subst_plugins + print \$0 + next + } + + multi == 1 && length(\$0) > 0 { + $awk_subst_plugins + if (length(\$0) > 0) print \$0 + next + } + + { print \$0 } + " + + command awk "$awk_script" <<< "$input_text" + + (( ! DEBUG )) || set +xv +} + +# runs awk against stdin, checks if the resulting file is not empty and then checks if the file has valid zsh syntax +run_awk_and_test() { + local description="$1" + local plugins_to_disable="$2" + local input_text="$3" + local expected_output="$4" + + local tmpfile==(:) + + { + print -u2 "Test: $description" + DEBUG=0 run_awk "$plugins_to_disable" "$input_text" >| $tmpfile + + if [[ ! -s "$tmpfile" ]]; then + print -u2 "\e[31mError\e[0m: output file empty" + return 1 + fi + + if ! zsh -n $tmpfile; then + print -u2 "\e[31mError\e[0m: zsh syntax error" + diff -u $tmpfile <(echo "$expected_output") + return 1 + fi + + if ! diff -u --color=always $tmpfile <(echo "$expected_output"); then + if (( DEBUG )); then + print -u2 "" + DEBUG=1 run_awk "$plugins_to_disable" "$input_text" + print -u2 "" + fi + print -u2 "\e[31mError\e[0m: output file does not match expected output" + return 1 + fi + + print -u2 "\e[32mSuccess\e[0m" + } always { + print -u2 "" + command rm -f "$tmpfile" + } +} + +# These tests are for the `omz plugin disable` command +run_awk_and_test \ + "it should delete a single plugin in oneline format" \ + "git" \ + "plugins=(git)" \ + "plugins=()" + +run_awk_and_test \ + "it should delete a single plugin in multiline format" \ + "github" \ +"plugins=( + github +)" \ +"plugins=( +)" + +run_awk_and_test \ + "it should delete multiple plugins in oneline format" \ + "github git z" \ + "plugins=(github git z)" \ + "plugins=()" + +run_awk_and_test \ + "it should delete multiple plugins in multiline format" \ + "github git z" \ +"plugins=( + github + git + z +)" \ +"plugins=( +)" + +run_awk_and_test \ + "it should delete a single plugin among multiple in oneline format" \ + "git" \ + "plugins=(github git z)" \ + "plugins=(github z)" + +run_awk_and_test \ + "it should delete a single plugin among multiple in multiline format" \ + "git" \ +"plugins=( + github + git + z +)" \ +"plugins=( + github + z +)" + +run_awk_and_test \ + "it should delete multiple plugins in mixed format" \ + "git z" \ +"plugins=(github +git z)" \ +"plugins=(github +)" + +run_awk_and_test \ + "it should delete multiple plugins in mixed format 2" \ + "github z" \ +"plugins=(github + git +z)" \ +"plugins=( + git +)" diff --git a/zsh/.oh-my-zsh/lib/theme-and-appearance.zsh b/zsh/.oh-my-zsh/lib/theme-and-appearance.zsh new file mode 100644 index 0000000..a5b93e5 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/theme-and-appearance.zsh @@ -0,0 +1,81 @@ +# Sets color variable such as $fg, $bg, $color and $reset_color +autoload -U colors && colors + +# Expand variables and commands in PROMPT variables +setopt prompt_subst + +# Prompt function theming defaults +ZSH_THEME_GIT_PROMPT_PREFIX="git:(" # Beginning of the git prompt, before the branch name +ZSH_THEME_GIT_PROMPT_SUFFIX=")" # End of the git prompt +ZSH_THEME_GIT_PROMPT_DIRTY="*" # Text to display if the branch is dirty +ZSH_THEME_GIT_PROMPT_CLEAN="" # Text to display if the branch is clean +ZSH_THEME_RUBY_PROMPT_PREFIX="(" +ZSH_THEME_RUBY_PROMPT_SUFFIX=")" + + +# Use diff --color if available +if command diff --color /dev/null{,} &>/dev/null; then + function diff { + command diff --color "$@" + } +fi + +# Don't set ls coloring if disabled +[[ "$DISABLE_LS_COLORS" != true ]] || return 0 + +# Default coloring for BSD-based ls +export LSCOLORS="Gxfxcxdxbxegedabagacad" + +# Default coloring for GNU-based ls +if [[ -z "$LS_COLORS" ]]; then + # Define LS_COLORS via dircolors if available. Otherwise, set a default + # equivalent to LSCOLORS (generated via https://geoff.greer.fm/lscolors) + if (( $+commands[dircolors] )); then + [[ -f "$HOME/.dircolors" ]] \ + && source <(dircolors -b "$HOME/.dircolors") \ + || source <(dircolors -b) + else + export LS_COLORS="di=1;36:ln=35:so=32:pi=33:ex=31:bd=34;46:cd=34;43:su=30;41:sg=30;46:tw=30;42:ow=30;43" + fi +fi + +function test-ls-args { + local cmd="$1" # ls, gls, colorls, ... + local args="${@[2,-1]}" # arguments except the first one + command "$cmd" "$args" /dev/null &>/dev/null +} + +# Find the option for using colors in ls, depending on the version +case "$OSTYPE" in + netbsd*) + # On NetBSD, test if `gls` (GNU ls) is installed (this one supports colors); + # otherwise, leave ls as is, because NetBSD's ls doesn't support -G + test-ls-args gls --color && alias ls='gls --color=tty' + ;; + openbsd*) + # On OpenBSD, `gls` (ls from GNU coreutils) and `colorls` (ls from base, + # with color and multibyte support) are available from ports. + # `colorls` will be installed on purpose and can't be pulled in by installing + # coreutils (which might be installed for ), so prefer it to `gls`. + test-ls-args gls --color && alias ls='gls --color=tty' + test-ls-args colorls -G && alias ls='colorls -G' + ;; + (darwin|freebsd)*) + # This alias works by default just using $LSCOLORS + test-ls-args ls -G && alias ls='ls -G' + # Only use GNU ls if installed and there are user defaults for $LS_COLORS, + # as the default coloring scheme is not very pretty + zstyle -t ':omz:lib:theme-and-appearance' gnu-ls \ + && test-ls-args gls --color \ + && alias ls='gls --color=tty' + ;; + *) + if test-ls-args ls --color; then + alias ls='ls --color=tty' + elif test-ls-args ls -G; then + alias ls='ls -G' + fi + ;; +esac + +unfunction test-ls-args diff --git a/zsh/.oh-my-zsh/lib/vcs_info.zsh b/zsh/.oh-my-zsh/lib/vcs_info.zsh new file mode 100644 index 0000000..9a2de01 --- /dev/null +++ b/zsh/.oh-my-zsh/lib/vcs_info.zsh @@ -0,0 +1,53 @@ +# Don't skip this file until a Zsh release does the necessary quoting. +# This is because even though 5.8.1 undid recursive prompt_subst inside +# prompt sequences, % characters in relevant fields will still be rendered +# incorrectly in vcs_info, on all Zsh releases up to writing this. +# +# There is no release yet that does this right, since it requires changing +# how what vcs_info hooks expect to receive. Even so, I'd rather be correct +# and break custom vcs_info hooks than have a broken prompt. + +# Quote necessary $hook_com[] items just before they are used +# in the line "VCS_INFO_hook 'post-backend'" of the VCS_INFO_formats +# function, where is: +# +# base: the full path of the repository's root directory. +# base-name: the name of the repository's root directory. +# branch: the name of the currently checked out branch. +# misc: a string that may contain anything the vcs_info backend wants. +# revision: an identifier of the currently checked out revision. +# subdir: the path of the current directory relative to the +# repository's root directory. +# +# This patch %-quotes these fields previous to their use in vcs_info hooks and +# the zformat call and, eventually, when they get expanded in the prompt. +# It's important to quote these here, and not later after hooks have modified the +# fields, because then we could be quoting % characters from valid prompt sequences, +# like %F{color}, %B, etc. +# +# 32 │ hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})" +# 33 │ hook_com[subdir_orig]="${hook_com[subdir]}" +# 34 │ +# 35 + │ for tmp in base base-name branch misc revision subdir; do +# 36 + │ hook_com[$tmp]="${hook_com[$tmp]//\%/%%}" +# 37 + │ done +# 38 + │ +# 39 │ VCS_INFO_hook 'post-backend' +# +# This is especially important so that no command substitution is performed +# due to malicious input as a consequence of CVE-2021-45444, which affects +# zsh versions from 5.0.3 to 5.8. +# +autoload -Uz +X regexp-replace VCS_INFO_formats 2>/dev/null || return 0 + +# We use $tmp here because it's already a local variable in VCS_INFO_formats +typeset PATCH='for tmp (base base-name branch misc revision subdir) hook_com[$tmp]="${hook_com[$tmp]//\%/%%}"' +# Unique string to avoid reapplying the patch if this code gets called twice +typeset PATCH_ID=vcs_info-patch-9b9840f2-91e5-4471-af84-9e9a0dc68c1b +# Only patch the VCS_INFO_formats function if not already patched +if [[ "$functions[VCS_INFO_formats]" != *$PATCH_ID* ]]; then + regexp-replace 'functions[VCS_INFO_formats]' \ + "VCS_INFO_hook 'post-backend'" \ + ': ${PATCH_ID}; ${PATCH}; ${MATCH}' +fi +unset PATCH PATCH_ID diff --git a/zsh/.oh-my-zsh/oh-my-zsh.sh b/zsh/.oh-my-zsh/oh-my-zsh.sh new file mode 100644 index 0000000..7881dce --- /dev/null +++ b/zsh/.oh-my-zsh/oh-my-zsh.sh @@ -0,0 +1,238 @@ +# ANSI formatting function (\033[m) +# 0: reset, 1: bold, 4: underline, 22: no bold, 24: no underline, 31: red, 33: yellow +omz_f() { + [ $# -gt 0 ] || return + IFS=";" printf "\033[%sm" $* +} +# If stdout is not a terminal ignore all formatting +[ -t 1 ] || omz_f() { :; } + +# Protect against non-zsh execution of Oh My Zsh (use POSIX syntax here) +[ -n "$ZSH_VERSION" ] || { + omz_ptree() { + # Get process tree of the current process + pid=$$; pids="$pid" + while [ ${pid-0} -ne 1 ] && ppid=$(ps -e -o pid,ppid | awk "\$1 == $pid { print \$2 }"); do + pids="$pids $pid"; pid=$ppid + done + + # Show process tree + case "$(uname)" in + Linux) ps -o ppid,pid,command -f -p $pids 2>/dev/null ;; + Darwin|*) ps -o ppid,pid,command -p $pids 2>/dev/null ;; + esac + + # If ps command failed, try Busybox ps + [ $? -eq 0 ] || ps -o ppid,pid,comm | awk "NR == 1 || index(\"$pids\", \$2) != 0" + } + + { + shell=$(ps -o pid,comm | awk "\$1 == $$ { print \$2 }") + printf "$(omz_f 1 31)Error:$(omz_f 22) Oh My Zsh can't be loaded from: $(omz_f 1)${shell}$(omz_f 22). " + printf "You need to run $(omz_f 1)zsh$(omz_f 22) instead.$(omz_f 0)\n" + printf "$(omz_f 33)Here's the process tree:$(omz_f 22)\n\n" + omz_ptree + printf "$(omz_f 0)\n" + } >&2 + + return 1 +} + +# Check if in emulation mode, if so early return +# https://github.com/ohmyzsh/ohmyzsh/issues/11686 +[[ "$(emulate)" = zsh ]] || { + printf "$(omz_f 1 31)Error:$(omz_f 22) Oh My Zsh can't be loaded in \`$(emulate)\` emulation mode.$(omz_f 0)\n" >&2 + return 1 +} + +unset -f omz_f + +# If ZSH is not defined, use the current script's directory. +[[ -z "$ZSH" ]] && export ZSH="${${(%):-%x}:a:h}" + +# Set ZSH_CACHE_DIR to the path where cache files should be created +# or else we will use the default cache/ +if [[ -z "$ZSH_CACHE_DIR" ]]; then + ZSH_CACHE_DIR="$ZSH/cache" +fi + +# Make sure $ZSH_CACHE_DIR is writable, otherwise use a directory in $HOME +if [[ ! -w "$ZSH_CACHE_DIR" ]]; then + ZSH_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/oh-my-zsh" +fi + +# Create cache and completions dir and add to $fpath +mkdir -p "$ZSH_CACHE_DIR/completions" +(( ${fpath[(Ie)"$ZSH_CACHE_DIR/completions"]} )) || fpath=("$ZSH_CACHE_DIR/completions" $fpath) + +# Check for updates on initial load... +source "$ZSH/tools/check_for_upgrade.sh" + +# Initializes Oh My Zsh + +# add a function path +fpath=("$ZSH/functions" "$ZSH/completions" $fpath) + +# Load all stock functions (from $fpath files) called below. +autoload -U compaudit compinit zrecompile + +# Set ZSH_CUSTOM to the path where your custom config files +# and plugins exists, or else we will use the default custom/ +if [[ -z "$ZSH_CUSTOM" ]]; then + ZSH_CUSTOM="$ZSH/custom" +fi + +is_plugin() { + local base_dir=$1 + local name=$2 + builtin test -f $base_dir/plugins/$name/$name.plugin.zsh \ + || builtin test -f $base_dir/plugins/$name/_$name +} + +# Add all defined plugins to fpath. This must be done +# before running compinit. +for plugin ($plugins); do + if is_plugin "$ZSH_CUSTOM" "$plugin"; then + fpath=("$ZSH_CUSTOM/plugins/$plugin" $fpath) + elif is_plugin "$ZSH" "$plugin"; then + fpath=("$ZSH/plugins/$plugin" $fpath) + else + echo "[oh-my-zsh] plugin '$plugin' not found" + fi +done + +# Figure out the SHORT hostname +if [[ "$OSTYPE" = darwin* ]]; then + # macOS's $HOST changes with dhcp, etc. Use ComputerName if possible. + SHORT_HOST=$(scutil --get ComputerName 2>/dev/null) || SHORT_HOST="${HOST/.*/}" +else + SHORT_HOST="${HOST/.*/}" +fi + +# Save the location of the current completion dump file. +if [[ -z "$ZSH_COMPDUMP" ]]; then + ZSH_COMPDUMP="${ZDOTDIR:-$HOME}/.zcompdump-${SHORT_HOST}-${ZSH_VERSION}" +fi + +# Construct zcompdump OMZ metadata +zcompdump_revision="#omz revision: $(builtin cd -q "$ZSH"; git rev-parse HEAD 2>/dev/null)" +zcompdump_fpath="#omz fpath: $fpath" + +# Delete the zcompdump file if OMZ zcompdump metadata changed +if ! command grep -q -Fx "$zcompdump_revision" "$ZSH_COMPDUMP" 2>/dev/null \ + || ! command grep -q -Fx "$zcompdump_fpath" "$ZSH_COMPDUMP" 2>/dev/null; then + command rm -f "$ZSH_COMPDUMP" + zcompdump_refresh=1 +fi + +if [[ "$ZSH_DISABLE_COMPFIX" != true ]]; then + source "$ZSH/lib/compfix.zsh" + # Load only from secure directories + compinit -i -d "$ZSH_COMPDUMP" + # If completion insecurities exist, warn the user + handle_completion_insecurities &| +else + # If the user wants it, load from all found directories + compinit -u -d "$ZSH_COMPDUMP" +fi + +# Append zcompdump metadata if missing +if (( $zcompdump_refresh )) \ + || ! command grep -q -Fx "$zcompdump_revision" "$ZSH_COMPDUMP" 2>/dev/null; then + # Use `tee` in case the $ZSH_COMPDUMP filename is invalid, to silence the error + # See https://github.com/ohmyzsh/ohmyzsh/commit/dd1a7269#commitcomment-39003489 + tee -a "$ZSH_COMPDUMP" &>/dev/null </dev/null; then + zrecompile -q -p "$ZSH_COMPDUMP" + command rm -rf "$ZSH_COMPDUMP.zwc.old" "${ZSH_COMPDUMP}.lock" +fi + +_omz_source() { + local context filepath="$1" + + # Construct zstyle context based on path + case "$filepath" in + lib/*) context="lib:${filepath:t:r}" ;; # :t = lib_name.zsh, :r = lib_name + plugins/*) context="plugins:${filepath:h:t}" ;; # :h = plugins/plugin_name, :t = plugin_name + esac + + local disable_aliases=0 + zstyle -T ":omz:${context}" aliases || disable_aliases=1 + + # Back up alias names prior to sourcing + local -A aliases_pre galiases_pre + if (( disable_aliases )); then + aliases_pre=("${(@kv)aliases}") + galiases_pre=("${(@kv)galiases}") + fi + + # Source file from $ZSH_CUSTOM if it exists, otherwise from $ZSH + if [[ -f "$ZSH_CUSTOM/$filepath" ]]; then + source "$ZSH_CUSTOM/$filepath" + elif [[ -f "$ZSH/$filepath" ]]; then + source "$ZSH/$filepath" + fi + + # Unset all aliases that don't appear in the backed up list of aliases + if (( disable_aliases )); then + if (( #aliases_pre )); then + aliases=("${(@kv)aliases_pre}") + else + (( #aliases )) && unalias "${(@k)aliases}" + fi + if (( #galiases_pre )); then + galiases=("${(@kv)galiases_pre}") + else + (( #galiases )) && unalias "${(@k)galiases}" + fi + fi +} + +# Load all of the lib files in ~/oh-my-zsh/lib that end in .zsh +# TIP: Add files you don't want in git to .gitignore +for lib_file ("$ZSH"/lib/*.zsh); do + _omz_source "lib/${lib_file:t}" +done +unset lib_file + +# Load all of the plugins that were defined in ~/.zshrc +for plugin ($plugins); do + _omz_source "plugins/$plugin/$plugin.plugin.zsh" +done +unset plugin + +# Load all of your custom configurations from custom/ +for config_file ("$ZSH_CUSTOM"/*.zsh(N)); do + source "$config_file" +done +unset config_file + +# Load the theme +is_theme() { + local base_dir=$1 + local name=$2 + builtin test -f $base_dir/$name.zsh-theme +} + +if [[ -n "$ZSH_THEME" ]]; then + if is_theme "$ZSH_CUSTOM" "$ZSH_THEME"; then + source "$ZSH_CUSTOM/$ZSH_THEME.zsh-theme" + elif is_theme "$ZSH_CUSTOM/themes" "$ZSH_THEME"; then + source "$ZSH_CUSTOM/themes/$ZSH_THEME.zsh-theme" + elif is_theme "$ZSH/themes" "$ZSH_THEME"; then + source "$ZSH/themes/$ZSH_THEME.zsh-theme" + else + echo "[oh-my-zsh] theme '$ZSH_THEME' not found" + fi +fi + +# set completion colors to be the same as `ls`, after theme has been loaded +[[ -z "$LS_COLORS" ]] || zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" diff --git a/zsh/.oh-my-zsh/plugins/1password/1password.plugin.zsh b/zsh/.oh-my-zsh/plugins/1password/1password.plugin.zsh new file mode 100644 index 0000000..f49ee26 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/1password/1password.plugin.zsh @@ -0,0 +1,9 @@ +# Do nothing if op is not installed +(( ${+commands[op]} )) || return + +# Load op completion +eval "$(op completion zsh)" +compdef _op op + +# Load opswd function +autoload -Uz opswd diff --git a/zsh/.oh-my-zsh/plugins/1password/README.md b/zsh/.oh-my-zsh/plugins/1password/README.md new file mode 100644 index 0000000..2670d9d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/1password/README.md @@ -0,0 +1,40 @@ +# 1Password + +This plugin adds 1Password functionality to oh-my-zsh. + +To use, add `1password` to the list of plugins in your `.zshrc` file: + +```zsh +plugins=(... 1password) +``` + +Then, you can use the command `opswd` to copy passwords for services into your +clipboard. + +## `opswd` + +The `opswd` command is a wrapper around the `op` command. It takes a service +name as an argument and copies the username, then the password for that service +to the clipboard, after confirmation on the user part. + +If the service also contains a TOTP, it is copied to the clipboard after confirmation +on the user part. Finally, after 20 seconds, the clipboard is cleared. + +For example, `opswd github.com` will put your GitHub username into your clipboard. Then, +it will ask for confirmation to continue, and copy the password to your clipboard. Finally, +if a TOTP is available, it will be copied to the clipboard after your confirmation. + +This function has completion support, so you can use tab completion to select which +service you want to get. + +> NOTE: you need to be signed in for `opswd` to work. If you are using biometric unlock, +> 1Password CLI will automatically prompt you to sign in. See: +> +> - [Get started with 1Password CLI 2: Sign in](https://developer.1password.com/docs/cli/get-started#sign-in) +> - [Sign in to your 1Password account manually](https://developer.1password.com/docs/cli/sign-in-manually) + +## Requirements + +- [1Password CLI 2](https://developer.1password.com/docs/cli/get-started#install) + + > NOTE: if you're using 1Password CLI 1, [see how to upgrade to CLI 2](https://developer.1password.com/docs/cli/upgrade). diff --git a/zsh/.oh-my-zsh/plugins/1password/_opswd b/zsh/.oh-my-zsh/plugins/1password/_opswd new file mode 100644 index 0000000..64046b8 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/1password/_opswd @@ -0,0 +1,19 @@ +#compdef opswd + +function _opswd() { + local -a services + services=("${(@f)$(op item list --categories Login --cache 2>/dev/null | awk 'NR != 1 { print $2 }')}") + [[ -z "$services" ]] || compadd -a -- services +} + +# TODO: 2022-03-26: Remove support for op CLI 1 +autoload -Uz is-at-least +is-at-least 2.0.0 $(op --version) || { + function _opswd() { + local -a services + services=("${(@f)$(op list items --categories Login 2>/dev/null | op get item - --fields title 2>/dev/null)}") + [[ -z "$services" ]] || compadd -a -- services + } +} + +_opswd "$@" diff --git a/zsh/.oh-my-zsh/plugins/1password/opswd b/zsh/.oh-my-zsh/plugins/1password/opswd new file mode 100644 index 0000000..0f7f885 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/1password/opswd @@ -0,0 +1,90 @@ +#autoload + +# opswd puts the password of the named service into the clipboard. If there's a +# one time password, it will be copied into the clipboard after 10 seconds. The +# clipboard is cleared after another 20 seconds. +function opswd() { + if [[ $# -lt 1 ]]; then + echo "Usage: opswd " + return 1 + fi + + local service=$1 + + # If not logged in, print error and return + op user list > /dev/null || return + + local username + # Copy the username to the clipboard + if ! username=$(op item get "$service" --fields username 2>/dev/null); then + echo "error: could not obtain username for $service" + return 1 + fi + + echo -n "$username" | clipcopy + echo "✔ username for service $service copied to the clipboard. Press Enter to continue" + read + + local password + # Copy the password to the clipboard + if ! password=$(op item get "$service" --fields password 2>/dev/null); then + echo "error: could not obtain password for $service" + return 1 + fi + + echo -n "$password" | clipcopy + echo "✔ password for $service copied to clipboard. Press Enter to continue" + read + + # If there's a one time password, copy it to the clipboard + local totp + if totp=$(op item get --otp "$service" 2>/dev/null) && [[ -n "$totp" ]]; then + echo -n "$totp" | clipcopy + echo "✔ TOTP for $service copied to clipboard" + fi + + (sleep 20 && clipcopy /dev/null) &! +} + +# TODO: 2022-03-26: Remove support for op CLI 1 +autoload -Uz is-at-least +is-at-least 2.0.0 $(op --version) || { + print -ru2 ${(%):-"%F{yellow}opswd: usage with op version $(op --version) is deprecated. Upgrade to CLI 2 and reload zsh. +For instructions, see https://developer.1password.com/docs/cli/upgrade.%f"} + + # opswd puts the password of the named service into the clipboard. If there's a + # one time password, it will be copied into the clipboard after 10 seconds. The + # clipboard is cleared after another 20 seconds. + function opswd() { + if [[ $# -lt 1 ]]; then + echo "Usage: opswd " + return 1 + fi + + local service=$1 + + # If not logged in, print error and return + op list users > /dev/null || return + + local password + # Copy the password to the clipboard + if ! password=$(op get item "$service" --fields password 2>/dev/null); then + echo "error: could not obtain password for $service" + return 1 + fi + + echo -n "$password" | clipcopy + echo "✔ password for $service copied to clipboard" + + # If there's a one time password, copy it to the clipboard after 5 seconds + local totp + if totp=$(op get totp "$service" 2>/dev/null) && [[ -n "$totp" ]]; then + sleep 10 && echo -n "$totp" | clipcopy + echo "✔ TOTP for $service copied to clipboard" + fi + + (sleep 20 && clipcopy /dev/null) &! + } +} + +opswd "$@" diff --git a/zsh/.oh-my-zsh/plugins/adb/README.md b/zsh/.oh-my-zsh/plugins/adb/README.md new file mode 100644 index 0000000..6dd73b5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/adb/README.md @@ -0,0 +1,8 @@ +# adb autocomplete plugin + +* Adds autocomplete options for all adb commands. +* Add autocomplete for `adb -s` + +## Requirements + +In order to make this work, you will need to have the Android adb tools set up in your path. diff --git a/zsh/.oh-my-zsh/plugins/adb/_adb b/zsh/.oh-my-zsh/plugins/adb/_adb new file mode 100644 index 0000000..6ca04d1 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/adb/_adb @@ -0,0 +1,67 @@ +#compdef adb +#autoload + +# in order to make this work, you will need to have the android adb tools + +# adb zsh completion, based on homebrew completion + +local -a _1st_arguments +_1st_arguments=( +'bugreport:return all information from the device that should be included in a bug report.' +'connect:connect to a device via TCP/IP Port 5555 is default.' +'devices:list all connected devices' +'disconnect:disconnect from a TCP/IP device. Port 5555 is default.' +'emu:run emulator console command' +'forward:forward socket connections' +'get-devpath:print the device path' +'get-serialno:print the serial number of the device' +'get-state:print the current state of the device: offline | bootloader | device' +'help:show the help message' +'install:push this package file to the device and install it' +'jdwp:list PIDs of processes hosting a JDWP transport' +'keygen:generate adb public/private key' +'kill-server:kill the server if it is running' +'logcat:view device log' +'pull:copy file/dir from device' +'push:copy file/dir to device' +'reboot:reboots the device, optionally into the bootloader or recovery program' +'reboot-bootloader:reboots the device into the bootloader' +'remount:remounts the partitions on the device read-write' +'root:restarts the adbd daemon with root permissions' +'sideload:push a ZIP to device and install it' +'shell:run remote shell interactively' +'sync:copy host->device only if changed (-l means list but dont copy)' +'start-server:ensure that there is a server running' +'tcpip:restart host adb in tcpip mode' +'uninstall:remove this app package from the device' +'usb:restart the adbd daemon listing on USB' +'version:show version num' +'wait-for-device:block until device is online' +) + +local expl +local -a pkgs installed_pkgs + +_arguments \ + '-s[devices]:specify device:->specify_device' \ + '*:: :->subcmds' && return 0 + +case "$state" in + specify_device) + _values -C 'devices' ${$(adb devices -l|awk 'NR>1&& $1 \ + {sub(/ +/," ",$0); \ + gsub(":","\\:",$1); \ + for(i=1;i<=NF;i++) { + if($i ~ /model:/) { split($i,m,":") } \ + else if($i ~ /product:/) { split($i,p,":") } } \ + printf "%s[%s(%s)] ",$1, p[2], m[2]}'):-""} + return + ;; +esac + +if (( CURRENT == 1 )); then + _describe -t commands "adb subcommand" _1st_arguments + return +fi + +_files diff --git a/zsh/.oh-my-zsh/plugins/ag/README.md b/zsh/.oh-my-zsh/plugins/ag/README.md new file mode 100644 index 0000000..2ef34e4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ag/README.md @@ -0,0 +1,13 @@ +# The Silver Searcher + +This plugin provides completion support for [`ag`](https://github.com/ggreer/the_silver_searcher). + +To use it, add ag to the plugins array in your zshrc file. + +```zsh +plugins=(... ag) +``` + +## INSTALLATION NOTES + +Besides oh-my-zsh, `ag` needs to be installed by following these steps: https://github.com/ggreer/the_silver_searcher#installing. diff --git a/zsh/.oh-my-zsh/plugins/ag/_ag b/zsh/.oh-my-zsh/plugins/ag/_ag new file mode 100644 index 0000000..e63c3a2 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ag/_ag @@ -0,0 +1,66 @@ +#compdef ag +#autoload + +typeset -A opt_args + +# Took the liberty of not listing every option… specially aliases and -D +_ag () { + local -a _1st_arguments + _1st_arguments=( + '--ackmate:Print results in AckMate-parseable format' + {'-A','--after'}':[LINES] Print lines after match (Default: 2)' + {'-B','--before'}':[LINES] Print lines before match (Default: 2)' + '--break:Print newlines between matches in different files' + '--nobreak:Do not print newlines between matches in different files' + {'-c','--count'}':Only print the number of matches in each file' + '--color:Print color codes in results (Default: On)' + '--nocolor:Do not print color codes in results' + '--color-line-number:Color codes for line numbers (Default: 1;33)' + '--color-match:Color codes for result match numbers (Default: 30;43)' + '--color-path:Color codes for path names (Default: 1;32)' + '--column:Print column numbers in results' + {'-H','--heading'}':Print file names (On unless searching a single file)' + '--noheading:Do not print file names (On unless searching a single file)' + '--line-numbers:Print line numbers even for streams' + {'-C','--context'}':[LINES] Print lines before and after matches (Default: 2)' + '-g:[PATTERN] Print filenames matching PATTERN' + {'-l','--files-with-matches'}':Only print filenames that contain matches' + {'-L','--files-without-matches'}':Only print filenames that do not contain matches' + '--no-numbers:Do not print line numbers' + {'-o','--only-matching'}':Prints only the matching part of the lines' + '--print-long-lines:Print matches on very long lines (Default: 2k characters)' + '--passthrough:When searching a stream, print all lines even if they do not match' + '--silent:Suppress all log messages, including errors' + '--stats:Print stats (files scanned, time taken, etc.)' + '--vimgrep:Print results like vim :vimgrep /pattern/g would' + {'-0','--null'}':Separate filenames with null (for "xargs -0")' + + {'-a','--all-types'}':Search all files (does not include hidden files / .gitignore)' + '--depth:[NUM] Search up to NUM directories deep (Default: 25)' + {'-f','--follow'}':Follow symlinks' + {'-G','--file-search-regex'}':[PATTERN] Limit search to filenames matching PATTERN' + '--hidden:Search hidden files (obeys .*ignore files)' + {'-i','--ignore-case'}':Match case insensitively' + '--ignore:[PATTERN] Ignore files/directories matching PATTERN' + {'-m','--max-count'}':[NUM] Skip the rest of a file after NUM matches (Default: 10k)' + {'-p','--path-to-agignore'}':[PATH] Use .agignore file at PATH' + {'-Q','--literal'}':Do not parse PATTERN as a regular expression' + {'-s','--case-sensitive'}':Match case' + {'-S','--smart-case'}':Insensitive match unless PATTERN has uppercase (Default: On)' + '--search-binary:Search binary files for matches' + {'-t','--all-text'}':Search all text files (Hidden files not included)' + {'-u','--unrestricted'}':Search all files (ignore .agignore and _all_)' + {'-U','--skip-vcs-ignores'}':Ignore VCS files (stil obey .agignore)' + {'-v','--invert-match'}':Invert match' + {'-w','--word-regexp'}':Only match whole words' + {'-z','--search-zip'}':Search contents of compressed (e.g., gzip) files' + + '--list-file-types:list of supported file types' + ) + + if [[ $words[-1] =~ "^-" ]]; then + _describe -t commands "ag options" _1st_arguments && ret=0 + else + _files && ret=0 + fi +} diff --git a/zsh/.oh-my-zsh/plugins/alias-finder/.zunit.yml b/zsh/.oh-my-zsh/plugins/alias-finder/.zunit.yml new file mode 100644 index 0000000..d634b20 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/alias-finder/.zunit.yml @@ -0,0 +1,9 @@ +tap: false +directories: + tests: tests + output: tests/_output + support: tests/_support +time_limit: 0 +fail_fast: false +allow_risky: false +verbose: true diff --git a/zsh/.oh-my-zsh/plugins/alias-finder/README.md b/zsh/.oh-my-zsh/plugins/alias-finder/README.md new file mode 100644 index 0000000..108c1fe --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/alias-finder/README.md @@ -0,0 +1,33 @@ +# alias-finder plugin + +This plugin searches the defined aliases and outputs any that match the command inputted. This makes learning new aliases easier. + +## Usage + +To use it, add `alias-finder` to the `plugins` array of your zshrc file: +``` +plugins=(... alias-finder) +``` + +To enable it for every single command, set zstyle in your `~/.zshrc`. + +```zsh +# ~/.zshrc + +zstyle ':omz:plugins:alias-finder' autoload yes # disabled by default +zstyle ':omz:plugins:alias-finder' longer yes # disabled by default +zstyle ':omz:plugins:alias-finder' exact yes # disabled by default +zstyle ':omz:plugins:alias-finder' cheaper yes # disabled by default +``` + +As you can see, options are also available with zstyle. + +### Options + +> In order to clarify, let's say `alias a=abc` has source 'abc' and destination 'a'. + +- Use `--longer` or `-l` to include aliases where the source is longer than the input (in other words, the source could contain the whole input). +- Use `--exact` or `-e` to avoid aliases where the source is shorter than the input (in other words, the source must be the same with the input). +- Use `--cheaper` or `-c` to avoid aliases where the destination is longer than the input (in other words, the destination must be the shorter than the input). + + diff --git a/zsh/.oh-my-zsh/plugins/alias-finder/alias-finder.plugin.zsh b/zsh/.oh-my-zsh/plugins/alias-finder/alias-finder.plugin.zsh new file mode 100644 index 0000000..c04056c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/alias-finder/alias-finder.plugin.zsh @@ -0,0 +1,62 @@ +alias-finder() { + local cmd=" " exact="" longer="" cheaper="" wordEnd="'{0,1}$" finder="" filter="" + + # build command and options + for c in "$@"; do + case $c in + # TODO: Remove backward compatibility (other than zstyle form) + # set options if exist + -e|--exact) exact=true;; + -l|--longer) longer=true;; + -c|--cheaper) cheaper=true;; + # concatenate cmd + *) cmd="$cmd$c " ;; + esac + done + + zstyle -t ':omz:plugins:alias-finder' longer && longer=true + zstyle -t ':omz:plugins:alias-finder' exact && exact=true + zstyle -t ':omz:plugins:alias-finder' cheaper && cheaper=true + + # format cmd for grep + ## - replace newlines with spaces + ## - trim both ends + ## - replace multiple spaces with one space + ## - add escaping character to special characters + cmd=$(echo -n "$cmd" | tr '\n' ' ' | xargs | tr -s '[:space:]' | sed 's/[].\|$(){}?+*^[]/\\&/g') + + if [[ $longer == true ]]; then + wordEnd="" # remove wordEnd to find longer aliases + fi + + # find with alias and grep, removing last word each time until no more words + while [[ $cmd != "" ]]; do + finder="'{0,1}$cmd$wordEnd" + + # make filter to find only shorter results than current cmd + if [[ $cheaper == true ]]; then + cmdLen=$(echo -n "$cmd" | wc -c) + filter="^'{0,1}.{0,$((cmdLen - 1))}=" + fi + + alias | grep -E "$filter" | grep -E "=$finder" + + if [[ $exact == true ]]; then + break # because exact case is only one + elif [[ $longer = true ]]; then + break # because above grep command already found every longer aliases during first cycle + fi + + cmd=$(sed -E 's/ {0,}[^ ]*$//' <<< "$cmd") # remove last word + done +} + +preexec_alias-finder() { + # TODO: Remove backward compatibility (other than zstyle form) + zstyle -t ':omz:plugins:alias-finder' autoload && alias-finder $1 || if [[ $ZSH_ALIAS_FINDER_AUTOMATIC = true ]]; then + alias-finder $1 + fi +} + +autoload -U add-zsh-hook +add-zsh-hook preexec preexec_alias-finder diff --git a/zsh/.oh-my-zsh/plugins/alias-finder/tests/_output/.gitkeep b/zsh/.oh-my-zsh/plugins/alias-finder/tests/_output/.gitkeep new file mode 100644 index 0000000..473a0f4 diff --git a/zsh/.oh-my-zsh/plugins/alias-finder/tests/_support/.gitkeep b/zsh/.oh-my-zsh/plugins/alias-finder/tests/_support/.gitkeep new file mode 100644 index 0000000..473a0f4 diff --git a/zsh/.oh-my-zsh/plugins/alias-finder/tests/_support/bootstrap b/zsh/.oh-my-zsh/plugins/alias-finder/tests/_support/bootstrap new file mode 100644 index 0000000..772344f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/alias-finder/tests/_support/bootstrap @@ -0,0 +1,2 @@ +#!/usr/bin/env zsh +# Write your bootstrap code here diff --git a/zsh/.oh-my-zsh/plugins/alias-finder/tests/test_run.sh b/zsh/.oh-my-zsh/plugins/alias-finder/tests/test_run.sh new file mode 100644 index 0000000..a98ef3b --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/alias-finder/tests/test_run.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env zunit + +@setup { + load ../alias-finder.plugin.zsh + + set_git_aliases() { + unalias -a # all + alias g="git" + alias gc="git commit" + alias gcv="git commit -v" + alias gcvs="git commit -v -S" + } +} + +@test 'find aliases that contain input' { + set_git_aliases + + run alias-finder "git" + + assert "${#lines[@]}" equals 1 + assert "${lines[1]}" same_as "g=git" +} + +@test 'find aliases that contain input with whitespaces at ends' { + set_git_aliases + + run alias-finder " git " + + assert "${#lines[@]}" equals 1 + assert "${lines[1]}" same_as "g=git" +} + +@test 'find aliases that contain multiple words' { + set_git_aliases + + run alias-finder "git commit -v" + + assert "${#lines[@]}" equals 3 + assert "${lines[1]}" same_as "gcv='git commit -v'" + assert "${lines[2]}" same_as "gc='git commit'" + assert "${lines[3]}" same_as "g=git" +} + +@test 'find alias that is the same with input when --exact option is set' { + set_git_aliases + + run alias-finder -e "git" + + assert "${#lines[@]}" equals 1 + assert "${lines[1]}" same_as "g=git" +} + +@test 'find alias that is the same with multiple words input when --exact option is set' { + set_git_aliases + + run alias-finder -e "git commit -v" + + assert "${#lines[@]}" equals 1 + assert "${lines[1]}" same_as "gcv='git commit -v'" +} + +@test 'find alias that is the same with or longer than input when --longer option is set' { + set_git_aliases + + run alias-finder -l "git" + + assert "${#lines[@]}" equals 4 + assert "${lines[1]}" same_as "g=git" + assert "${lines[2]}" same_as "gc='git commit'" + assert "${lines[3]}" same_as "gcv='git commit -v'" + assert "${lines[4]}" same_as "gcvs='git commit -v -S'" +} + +@test 'find alias that is the same with or longer than multiple words input when --longer option is set' { + set_git_aliases + + run alias-finder -l "git commit -v" + + assert "${#lines[@]}" equals 2 + assert "${lines[1]}" same_as "gcv='git commit -v'" + assert "${lines[2]}" same_as "gcvs='git commit -v -S'" +} + +@test 'find aliases including expensive (longer) than input' { + set_git_aliases + alias expensiveCommands="git commit" + + run alias-finder "git commit -v" + + assert "${#lines[@]}" equals 4 + assert "${lines[1]}" same_as "gcv='git commit -v'" + assert "${lines[2]}" same_as "expensiveCommands='git commit'" + assert "${lines[3]}" same_as "gc='git commit'" + assert "${lines[4]}" same_as "g=git" +} + +@test 'find aliases excluding expensive (longer) than input when --cheap option is set' { + set_git_aliases + alias expensiveCommands="git commit" + + run alias-finder -c "git commit -v" + + assert "${#lines[@]}" equals 3 + assert "${lines[1]}" same_as "gcv='git commit -v'" + assert "${lines[2]}" same_as "gc='git commit'" + assert "${lines[3]}" same_as "g=git" +} diff --git a/zsh/.oh-my-zsh/plugins/aliases/.gitignore b/zsh/.oh-my-zsh/plugins/aliases/.gitignore new file mode 100644 index 0000000..da551aa --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/aliases/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/zsh/.oh-my-zsh/plugins/aliases/README.md b/zsh/.oh-my-zsh/plugins/aliases/README.md new file mode 100644 index 0000000..1b01c02 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/aliases/README.md @@ -0,0 +1,28 @@ +# Aliases cheatsheet + +**Maintainer:** [@hqingyi](https://github.com/hqingyi) + +With lots of 3rd-party amazing aliases installed, this plugin helps list the shortcuts +that are currently available based on the plugins you have enabled. + +To use it, add `aliases` to the plugins array in your zshrc file: + +```zsh +plugins=(aliases) +``` + +Requirements: Python needs to be installed. + +## Usage + +- `als`: show all aliases by group + +- `als -h/--help`: print help message + +- `als `: filter and highlight aliases by `` + +- `als -g /--group `: show only aliases for group ``. Multiple uses of the flag show all groups + +- `als --groups`: show only group names + + ![screenshot](https://github.com/ohmyzsh/ohmyzsh/assets/66907184/5bfa00ea-5fc3-4e97-8b22-2f74f6b948c7) diff --git a/zsh/.oh-my-zsh/plugins/aliases/aliases.plugin.zsh b/zsh/.oh-my-zsh/plugins/aliases/aliases.plugin.zsh new file mode 100644 index 0000000..e635041 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/aliases/aliases.plugin.zsh @@ -0,0 +1,14 @@ +# Handle $0 according to the standard: +# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" + +eval ' + function als(){ + (( $+commands[python3] )) || { + echo "[error] No python executable detected" + return + } + alias | python3 "'"${0:h}"'/cheatsheet.py" "$@" + } +' diff --git a/zsh/.oh-my-zsh/plugins/aliases/cheatsheet.py b/zsh/.oh-my-zsh/plugins/aliases/cheatsheet.py new file mode 100644 index 0000000..843b027 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/aliases/cheatsheet.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +import sys +import itertools +import termcolor +import argparse + +def parse(line): + left = line[0:line.find('=')].strip() + right = line[line.find('=')+1:].strip('\'"\n ') + try: + cmd = next(part for part in right.split() if len([char for char in '=<>' if char in part])==0) + except StopIteration: + cmd = right + return (left, right, cmd) + +def cheatsheet(lines): + exps = [ parse(line) for line in lines ] + exps.sort(key=lambda exp:exp[2]) + cheatsheet = {'_default': []} + for key, group in itertools.groupby(exps, lambda exp:exp[2]): + group_list = [ item for item in group ] + if len(group_list)==1: + target_aliases = cheatsheet['_default'] + else: + if key not in cheatsheet: + cheatsheet[key] = [] + target_aliases = cheatsheet[key] + target_aliases.extend(group_list) + return cheatsheet + +def pretty_print_group(key, aliases, highlight=None, only_groupname=False): + if len(aliases) == 0: + return + group_hl_formatter = lambda g, hl: termcolor.colored(hl, 'yellow').join([termcolor.colored(part, 'red') for part in ('[%s]' % g).split(hl)]) + alias_hl_formatter = lambda alias, hl: termcolor.colored(hl, 'yellow').join([termcolor.colored(part, 'green') for part in ('\t%s = %s' % alias[0:2]).split(hl)]) + group_formatter = lambda g: termcolor.colored('[%s]' % g, 'red') + alias_formatter = lambda alias: termcolor.colored('\t%s = %s' % alias[0:2], 'green') + if highlight and len(highlight)>0: + print (group_hl_formatter(key, highlight)) + if not only_groupname: + print ('\n'.join([alias_hl_formatter(alias, highlight) for alias in aliases])) + else: + print (group_formatter(key)) + if not only_groupname: + print ('\n'.join([alias_formatter(alias) for alias in aliases])) + print ('') + +def pretty_print(cheatsheet, wfilter, group_list=None, groups_only=False): + sorted_key = sorted(cheatsheet.keys()) + for key in sorted_key: + if group_list and key not in group_list: + continue + aliases = cheatsheet.get(key) + if not wfilter: + pretty_print_group(key, aliases, wfilter, groups_only) + else: + pretty_print_group(key, [ alias for alias in aliases if alias[0].find(wfilter)>-1 or alias[1].find(wfilter)>-1], wfilter) + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="Pretty print aliases.", prog="als") + parser.add_argument('filter', nargs="*", metavar="", help="search aliases matching keywords") + parser.add_argument('-g', '--group', dest="group_list", action='append', help="only print aliases in given groups") + parser.add_argument('--groups', dest='groups_only', action='store_true', help="only print alias groups") + args = parser.parse_args() + + lines = sys.stdin.readlines() + group_list = args.group_list or None + wfilter = " ".join(args.filter) or None + pretty_print(cheatsheet(lines), wfilter, group_list, args.groups_only) diff --git a/zsh/.oh-my-zsh/plugins/aliases/termcolor.py b/zsh/.oh-my-zsh/plugins/aliases/termcolor.py new file mode 100644 index 0000000..cf64d4f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/aliases/termcolor.py @@ -0,0 +1,168 @@ +# coding: utf-8 +# Copyright (c) 2008-2011 Volvox Development Team +# +# 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. +# +# Author: Konstantin Lepa + +"""ANSI Color formatting for output in terminal.""" + +from __future__ import print_function +import os + + +__ALL__ = [ 'colored', 'cprint' ] + +VERSION = (1, 1, 0) + +ATTRIBUTES = dict( + list(zip([ + 'bold', + 'dark', + '', + 'underline', + 'blink', + '', + 'reverse', + 'concealed' + ], + list(range(1, 9)) + )) + ) +del ATTRIBUTES[''] + + +HIGHLIGHTS = dict( + list(zip([ + 'on_grey', + 'on_red', + 'on_green', + 'on_yellow', + 'on_blue', + 'on_magenta', + 'on_cyan', + 'on_white' + ], + list(range(40, 48)) + )) + ) + + +COLORS = dict( + list(zip([ + 'grey', + 'red', + 'green', + 'yellow', + 'blue', + 'magenta', + 'cyan', + 'white', + ], + list(range(30, 38)) + )) + ) + + +RESET = '\033[0m' + + +def colored(text, color=None, on_color=None, attrs=None): + """Colorize text. + + Available text colors: + red, green, yellow, blue, magenta, cyan, white. + + Available text highlights: + on_red, on_green, on_yellow, on_blue, on_magenta, on_cyan, on_white. + + Available attributes: + bold, dark, underline, blink, reverse, concealed. + + Example: + colored('Hello, World!', 'red', 'on_grey', ['blue', 'blink']) + colored('Hello, World!', 'green') + """ + if os.getenv('ANSI_COLORS_DISABLED') is None: + fmt_str = '\033[%dm%s' + if color is not None: + text = fmt_str % (COLORS[color], text) + + if on_color is not None: + text = fmt_str % (HIGHLIGHTS[on_color], text) + + if attrs is not None: + for attr in attrs: + text = fmt_str % (ATTRIBUTES[attr], text) + + text += RESET + return text + + +def cprint(text, color=None, on_color=None, attrs=None, **kwargs): + """Print colorize text. + + It accepts arguments of print function. + """ + + print((colored(text, color, on_color, attrs)), **kwargs) + + +if __name__ == '__main__': + print('Current terminal type: %s' % os.getenv('TERM')) + print('Test basic colors:') + cprint('Grey color', 'grey') + cprint('Red color', 'red') + cprint('Green color', 'green') + cprint('Yellow color', 'yellow') + cprint('Blue color', 'blue') + cprint('Magenta color', 'magenta') + cprint('Cyan color', 'cyan') + cprint('White color', 'white') + print(('-' * 78)) + + print('Test highlights:') + cprint('On grey color', on_color='on_grey') + cprint('On red color', on_color='on_red') + cprint('On green color', on_color='on_green') + cprint('On yellow color', on_color='on_yellow') + cprint('On blue color', on_color='on_blue') + cprint('On magenta color', on_color='on_magenta') + cprint('On cyan color', on_color='on_cyan') + cprint('On white color', color='grey', on_color='on_white') + print('-' * 78) + + print('Test attributes:') + cprint('Bold grey color', 'grey', attrs=['bold']) + cprint('Dark red color', 'red', attrs=['dark']) + cprint('Underline green color', 'green', attrs=['underline']) + cprint('Blink yellow color', 'yellow', attrs=['blink']) + cprint('Reversed blue color', 'blue', attrs=['reverse']) + cprint('Concealed Magenta color', 'magenta', attrs=['concealed']) + cprint('Bold underline reverse cyan color', 'cyan', + attrs=['bold', 'underline', 'reverse']) + cprint('Dark blink concealed white color', 'white', + attrs=['dark', 'blink', 'concealed']) + print(('-' * 78)) + + print('Test mixing:') + cprint('Underline red on grey color', 'red', 'on_grey', + ['underline']) + cprint('Reversed green on red color', 'green', 'on_red', ['reverse']) + diff --git a/zsh/.oh-my-zsh/plugins/ansible/README.md b/zsh/.oh-my-zsh/plugins/ansible/README.md new file mode 100644 index 0000000..ee5de3c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ansible/README.md @@ -0,0 +1,33 @@ +# ansible plugin + +## Introduction + +The `ansible plugin` adds several aliases for useful [ansible](https://docs.ansible.com/ansible/latest/index.html) commands and [aliases](#aliases). + +To use it, add `ansible` to the plugins array of your zshrc file: + +``` +plugins=(... ansible) +``` + +## Aliases + +| Command | Description | +|:-------------------------------------------|:--------------------------------------------------------------------| +| `ansible-version` / `aver` | Show the version on ansible installed in this host | +| `ansible-role-init ` / `arinit` | Creates the Ansible Role as per Ansible Galaxy standard | +| `a` | command `ansible` | +| `aconf` | command `ansible-config` | +| `acon` | command `ansible-console` | +| `ainv` | command `ansible-inventory` | +| `aplaybook` | command `ansible-playbook` | +| `adoc` | command `ansible-doc` | +| `agal` | command `ansible-galaxy` | +| `apull` | command `ansible-pull` | +| `aval` | command `ansible-vault` | + +## Maintainer + +### [Deepankumar](https://github.com/deepan10) + +[https://github.com/deepan10/oh-my-zsh/tree/features/ansible-plugin](https://github.com/deepan10/oh-my-zsh/tree/features/ansible-plugin) diff --git a/zsh/.oh-my-zsh/plugins/ansible/ansible.plugin.zsh b/zsh/.oh-my-zsh/plugins/ansible/ansible.plugin.zsh new file mode 100644 index 0000000..073cfef --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ansible/ansible.plugin.zsh @@ -0,0 +1,28 @@ +# Functions +function ansible-version(){ + ansible --version +} + +function ansible-role-init(){ + if ! [ -z $1 ] ; then + echo "Ansible Role : $1 Creating...." + ansible-galaxy init $1 + tree $1 + else + echo "Usage : ansible-role-init " + echo "Example : ansible-role-init role1" + fi +} + +# Alias +alias a='ansible ' +alias aconf='ansible-config ' +alias acon='ansible-console ' +alias aver='ansible-version' +alias arinit='ansible-role-init' +alias aplaybook='ansible-playbook ' +alias ainv='ansible-inventory ' +alias adoc='ansible-doc ' +alias agal='ansible-galaxy ' +alias apull='ansible-pull ' +alias aval='ansible-vault' diff --git a/zsh/.oh-my-zsh/plugins/ant/README.md b/zsh/.oh-my-zsh/plugins/ant/README.md new file mode 100644 index 0000000..ec3fae0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ant/README.md @@ -0,0 +1,12 @@ +# Ant + +This plugin provides completion for [Ant](https://ant.apache.org/). + +To use it, add `ant` to the plugins array in your zshrc file: + +```zsh +plugins=(... ant) +``` + +It caches ant targets in a file named `.ant_targets`, you might want to add that to +your `.gitignore` file. diff --git a/zsh/.oh-my-zsh/plugins/ant/_ant b/zsh/.oh-my-zsh/plugins/ant/_ant new file mode 100644 index 0000000..9885c36 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ant/_ant @@ -0,0 +1,22 @@ +#compdef ant + +_ant_does_target_list_need_generating () { + [[ ! -f .ant_targets ]] && return 0 + [[ build.xml -nt .ant_targets ]] && return 0 + return 1 +} + +_ant () { + if [[ ! -f build.xml ]]; then + return + fi + + if ! _ant_does_target_list_need_generating; then + return + fi + + ant -p | awk -F " " 'NR > 5 { print lastTarget } { lastTarget = $1 }' >| .ant_targets + compadd -- "$(cat .ant_targets)" +} + +_ant "$@" diff --git a/zsh/.oh-my-zsh/plugins/ant/ant.plugin.zsh b/zsh/.oh-my-zsh/plugins/ant/ant.plugin.zsh new file mode 100644 index 0000000..f2323f8 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ant/ant.plugin.zsh @@ -0,0 +1,2 @@ +# Default to colored output +export ANT_ARGS='-logger org.apache.tools.ant.listener.AnsiColorLogger' diff --git a/zsh/.oh-my-zsh/plugins/apache2-macports/README.md b/zsh/.oh-my-zsh/plugins/apache2-macports/README.md new file mode 100644 index 0000000..7819edc --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/apache2-macports/README.md @@ -0,0 +1,21 @@ +# apache2-macports plugin + +Enables aliases to control a local Apache2 installed via [MacPorts](https://www.macports.org/). + +To use it, add `apache2-macports` to the plugins array in your zshrc file: + +```zsh +plugins=(... apache2-macports) +``` + +## Aliases + +| Alias | Function | Description | +|----------------|-----------------------------------------|-----------------------| +| apache2restart | `sudo /path/to/apache2.wrapper restart` | Restart apache daemon | +| apache2start | `sudo /path/to/apache2.wrapper start` | Start apache daemon | +| apache2stop | `sudo /path/to/apache2.wrapper stop` | Stop apache daemon | + +## Contributors + +- Alexander Rinass (alex@rinass.net) diff --git a/zsh/.oh-my-zsh/plugins/apache2-macports/apache2-macports.plugin.zsh b/zsh/.oh-my-zsh/plugins/apache2-macports/apache2-macports.plugin.zsh new file mode 100644 index 0000000..6a85672 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/apache2-macports/apache2-macports.plugin.zsh @@ -0,0 +1,6 @@ +# commands to control local apache2 server installation +# paths are for osx installation via macports + +alias apache2start='sudo /opt/local/etc/LaunchDaemons/org.macports.apache2/apache2.wrapper start' +alias apache2stop='sudo /opt/local/etc/LaunchDaemons/org.macports.apache2/apache2.wrapper stop' +alias apache2restart='sudo /opt/local/etc/LaunchDaemons/org.macports.apache2/apache2.wrapper restart' diff --git a/zsh/.oh-my-zsh/plugins/arcanist/README.md b/zsh/.oh-my-zsh/plugins/arcanist/README.md new file mode 100644 index 0000000..a900aa7 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/arcanist/README.md @@ -0,0 +1,43 @@ +## arcanist + +This plugin adds many useful aliases for [arcanist](https://github.com/phacility/arcanist). + +To use it, add `arcanist` to the plugins array of your zshrc file: + +```zsh +plugins=(... arcanist) +``` + +## Aliases + +| Alias | Command | +| ------- | ---------------------------------- | +| ara | `arc amend` | +| arb | `arc branch` | +| arbl | `arc bland` | +| arco | `arc cover` | +| arci | `arc commit` | +| ard | `arc diff` | +| ardc | `arc diff --create` | +| ardp | `arc diff --preview` | +| ardnu | `arc diff --nounit` | +| ardnupc | `arc diff --nounit --plan-changes` | +| ardpc | `arc diff --plan-changes` | +| are | `arc export` | +| arh | `arc help` | +| arho | `arc hotfix` | +| arl | `arc land` | +| arli | `arc lint` | +| arls | `arc list` | +| arpa | `arc patch` | + +## Functions + +The following functions make copy pasting revision ids from the URL bar of your browser +easier, as they allow for copy pasting the whole URL. For example: `ardu` accepts +both `https://arcanist-url.com/` as well as ``. + +| Function | Command | +| ------------------------- | --------------------------------- | +| ardu [URL or revision_id] | `arc diff --update` [revision_id] | +| arpa [URL or revision_id] | `arc patch` [revision_id] | diff --git a/zsh/.oh-my-zsh/plugins/arcanist/arcanist.plugin.zsh b/zsh/.oh-my-zsh/plugins/arcanist/arcanist.plugin.zsh new file mode 100644 index 0000000..895173f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/arcanist/arcanist.plugin.zsh @@ -0,0 +1,39 @@ +# +# Aliases +# (sorted alphabetically) +# + +alias ara='arc amend' +alias arb='arc branch' +alias arbl='arc bland' +alias arco='arc cover' +alias arci='arc commit' + +alias ard='arc diff' +alias ardc='arc diff --create' +alias ardnu='arc diff --nounit' +alias ardnupc='arc diff --nounit --plan-changes' +alias ardpc='arc diff --plan-changes' +alias ardp='arc diff --preview' # creates a new diff in the phab interface + +alias are='arc export' +alias arh='arc help' +alias arho='arc hotfix' +alias arl='arc land' +alias arli='arc lint' +alias arls='arc list' + +# +# Functions +# (sorted alphabetically) +# + +ardu() { + # Both `ardu https://arcanist-url.com/`, and `ardu ` work. + arc diff --update "${1:t}" +} + +arpa() { + # Both `arpa https://arcanist-url.com/`, and `arpa ` work. + arc patch "${1:t}" +} diff --git a/zsh/.oh-my-zsh/plugins/archlinux/README.md b/zsh/.oh-my-zsh/plugins/archlinux/README.md new file mode 100644 index 0000000..b23500a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/archlinux/README.md @@ -0,0 +1,184 @@ +# Arch Linux plugin + +This plugin adds some aliases and functions to work with Arch Linux. + +To use it, add `archlinux` to the plugins array in your zshrc file: + +```zsh +plugins=(... archlinux) +``` + +## Features + +### Pacman + +| Alias | Command | Description | +|--------------|----------------------------------------|------------------------------------------------------------------| +| pacin | `sudo pacman -S` | Install packages from the repositories | +| pacins | `sudo pacman -U` | Install a package from a local file | +| pacinsd | `sudo pacman -S --asdeps` | Install packages as dependencies of another package | +| paclean | `sudo pacman -Sc` | Clean out old and unused caches and packages | +| pacloc | `pacman -Qi` | Display information about a package in the local database | +| paclocs | `pacman -Qs` | Search for packages in the local database | +| paclr | `sudo pacman -Scc` | Remove all files from the cache | +| paclsorphans | `sudo pacman -Qdt` | List all orphaned packages | +| pacmir | `sudo pacman -Syy` | Force refresh of all package lists after updating mirrorlist | +| pacre | `sudo pacman -R` | Remove packages, keeping its settings and dependencies | +| pacrem | `sudo pacman -Rns` | Remove packages, including its settings and dependencies | +| pacrep | `pacman -Si` | Display information about a package in the repositories | +| pacreps | `pacman -Ss` | Search for packages in the repositories | +| pacrmorphans | `sudo pacman -Rs $(pacman -Qtdq)` | Delete all orphaned packages | +| pacupd | `sudo pacman -Sy` | Update and refresh local package, ABS and AUR databases | +| pacupg | `sudo pacman -Syu` | Sync with repositories before upgrading packages | +| pacfileupg | `sudo pacman -Fy` | Download fresh package databases from the server | +| pacfiles | `pacman -F` | Search package file names for matching strings | +| pacls | `pacman -Ql` | List files in a package | +| pacown | `pacman -Qo` | Show which package owns a file | +| upgrade[¹](#f1) | `sudo pacman -Syu` | Sync with repositories before upgrading packages | + +| Function | Description | +|----------------|-----------------------------------------------------------| +| pacdisowned | List all disowned files in your system | +| paclist | List all explicitly installed packages with a description | +| pacmanallkeys | Get all keys for developers and trusted users | +| pacmansignkeys | Locally trust all keys passed as parameters | +| pacweb | Open the website of an ArchLinux package | + +Note: paclist used to print packages with a description which are (1) explicitly installed +and (2) available for upgrade. Due to flawed scripting, it also printed all packages if no +upgrades were available. Use `pacman -Que` instead. + +### AUR helpers + +#### Aura + +| Alias | Command | Description | +|---------|-------------------------------------------------|-------------------------------------------------------------------------| +| auclean | `sudo aura -Sc` | Clean out old and unused caches and packages | +| auclr | `sudo aura -Scc` | Remove all files from the cache | +| auin | `sudo aura -S` | Install packages from the repositories | +| aurin | `sudo aura -A` | Install packages from the repositories | +| auins | `sudo aura -U` | Install a package from a local file | +| auinsd | `sudo aura -S --asdeps` | Install packages as dependencies of another package (repositories only) | +| aurinsd | `sudo aura -A --asdeps` | Install packages as dependencies of another package (AUR only) | +| auloc | `aura -Qi` | Display information about a package in the local database | +| aulocs | `aura -Qs` | Search for packages in the local database | +| auls | `aura -Qql` | List all files owned by a given package | +| aulst | `aura -Qe` | List installed packages including from AUR (tagged as "local") | +| aumir | `sudo aura -Syy` | Force refresh of all package lists after updating mirrorlist | +| aurph | `sudo aura -Oj` | Remove orphans using aura | +| auown | `aura -Qqo` | Search for packages that own the specified file(s) | +| aure | `sudo aura -R` | Remove packages, keeping its settings and dependencies | +| aurem | `sudo aura -Rns` | Remove packages, including its settings and unneeded dependencies | +| aurep | `aura -Si` | Display information about a package in the repositories | +| aurrep | `aura -Ai` | Display information about a package from AUR | +| aureps | `aura -As --both` | Search for packages in the repositories and AUR | +| auras | `aura -As --both` | Same as above | +| auupd | `sudo aura -Sy` | Update and refresh local package, ABS and AUR databases | +| auupg | `sudo sh -c "aura -Syu && aura -Au"` | Sync with repositories before upgrading all packages (from AUR too) | +| ausu | `sudo sh -c "aura -Syu --no-confirm && aura -Au --no-confirm"` | Same as `auupg`, but without confirmation | +| upgrade[¹](#f1) | `sudo aura -Syu` | Sync with repositories before upgrading packages | + +| Function | Description | +|-----------------|---------------------------------------------------------------------| +| auownloc _file_ | Display information about a package that owns the specified file(s) | +| auownls _file_ | List all files owned by a package that owns the specified file(s) | + +#### Pacaur + +| Alias | Command | Description | +|---------|-----------------------------------|---------------------------------------------------------------------| +| pacclean| `pacaur -Sc` | Clean out old and unused caches and packages | +| pacclr | `pacaur -Scc` | Remove all files from the cache | +| pain | `pacaur -S` | Install packages from the repositories | +| pains | `pacaur -U` | Install a package from a local file | +| painsd | `pacaur -S --asdeps` | Install packages as dependencies of another package | +| paloc | `pacaur -Qi` | Display information about a package in the local database | +| palocs | `pacaur -Qs` | Search for packages in the local database | +| palst | `pacaur -Qe` | List installed packages including from AUR (tagged as "local") | +| pamir | `pacaur -Syy` | Force refresh of all package lists after updating mirrorlist | +| paorph | `pacaur -Qtd` | Remove orphans using pacaur | +| pare | `pacaur -R` | Remove packages, keeping its settings and dependencies | +| parem | `pacaur -Rns` | Remove packages, including its settings and unneeded dependencies | +| parep | `pacaur -Si` | Display information about a package in the repositories | +| pareps | `pacaur -Ss` | Search for packages in the repositories | +| paupd | `pacaur -Sy` | Update and refresh local package, ABS and AUR databases | +| paupg | `pacaur -Syua` | Sync with repositories before upgrading all packages (from AUR too) | +| pasu | `pacaur -Syua --no-confirm` | Same as `paupg`, but without confirmation | +| upgrade[¹](#f1) | `pacaur -Syu` | Sync with repositories before upgrading packages | + +#### Trizen + +| Alias | Command | Description | +|---------|-----------------------------------|---------------------------------------------------------------------| +| trconf | `trizen -C` | Fix all configuration files with vimdiff | +| trclean | `trizen -Sc` | Clean out old and unused caches and packages | +| trclr | `trizen -Scc` | Remove all files from the cache | +| trin | `trizen -S` | Install packages from the repositories | +| trins | `trizen -U` | Install a package from a local file | +| trinsd | `trizen -S --asdeps` | Install packages as dependencies of another package | +| trloc | `trizen -Qi` | Display information about a package in the local database | +| trlocs | `trizen -Qs` | Search for packages in the local database | +| trlst | `trizen -Qe` | List installed packages including from AUR (tagged as "local") | +| trmir | `trizen -Syy` | Force refresh of all package lists after updating mirrorlist | +| trorph | `trizen -Qtd` | Remove orphans using yaourt | +| trre | `trizen -R` | Remove packages, keeping its settings and dependencies | +| trrem | `trizen -Rns` | Remove packages, including its settings and unneeded dependencies | +| trrep | `trizen -Si` | Display information about a package in the repositories | +| trreps | `trizen -Ss` | Search for packages in the repositories | +| trupd | `trizen -Sy` | Update and refresh local package, ABS and AUR databases | +| trupg | `trizen -Syua` | Sync with repositories before upgrading all packages (from AUR too) | +| trsu | `trizen -Syua --no-confirm` | Same as `trupg`, but without confirmation | +| upgrade[¹](#f1) | `trizen -Syu` | Sync with repositories before upgrading packages | + +#### Yay + +| Alias | Command | Description | +|---------|--------------------------------|-------------------------------------------------------------------| +| yaconf | `yay -Pg` | Print current configuration | +| yaclean | `yay -Sc` | Clean out old and unused caches and packages | +| yaclr | `yay -Scc` | Remove all files from the cache | +| yain | `yay -S` | Install packages from the repositories | +| yains | `yay -U` | Install a package from a local file | +| yainsd | `yay -S --asdeps` | Install packages as dependencies of another package | +| yaloc | `yay -Qi` | Display information about a package in the local database | +| yalocs | `yay -Qs` | Search for packages in the local database | +| yalst | `yay -Qe` | List installed packages including from AUR (tagged as "local") | +| yamir | `yay -Syy` | Force refresh of all package lists after updating mirrorlist | +| yaorph | `yay -Qtd` | Remove orphans using yay | +| yare | `yay -R` | Remove packages, keeping its settings and dependencies | +| yarem | `yay -Rns` | Remove packages, including its settings and unneeded dependencies | +| yarep | `yay -Si` | Display information about a package in the repositories | +| yareps | `yay -Ss` | Search for packages in the repositories | +| yaupd | `yay -Sy` | Update and refresh local package, ABS and AUR databases | +| yaupg | `yay -Syu` | Sync with repositories before upgrading packages | +| yasu | `yay -Syu --no-confirm` | Same as `yaupg`, but without confirmation | +| upgrade[¹](#f1) | `yay -Syu` | Sync with repositories before upgrading packages | + +--- + +¹ +The `upgrade` alias is set for all package managers. Its value will depend on +whether the package manager is installed, checked in the following order: + +1. `yay` +2. `trizen` +3. `pacaur` +4. `aura` +5. `pacman` + +## Contributors + +- Benjamin Boudreau - dreurmail@gmail.com +- Celso Miranda - contacto@celsomiranda.net +- ratijas (ivan tkachenko) - me@ratijas.tk +- Juraj Fiala - doctorjellyface@riseup.net +- KhasMek - Boushh@gmail.com +- Majora320 (Moses Miller) - Majora320@gmail.com +- Martin Putniorz - mputniorz@gmail.com +- MatthR3D - matthr3d@gmail.com +- ornicar - thibault.duplessis@gmail.com +- Ybalrid (Arthur Brainville) - ybalrid@ybalrid.info +- Jeff M. Hubbard - jeffmhubbard@gmail.com +- K. Harishankar(harishnkr) - hari2menon1234@gmail.com +- WH-2099 - wh2099@outlook.com \ No newline at end of file diff --git a/zsh/.oh-my-zsh/plugins/archlinux/archlinux.plugin.zsh b/zsh/.oh-my-zsh/plugins/archlinux/archlinux.plugin.zsh new file mode 100644 index 0000000..5394f99 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/archlinux/archlinux.plugin.zsh @@ -0,0 +1,203 @@ +####################################### +# Pacman # +####################################### + +# Pacman - https://wiki.archlinux.org/index.php/Pacman_Tips +alias pacupg='sudo pacman -Syu' +alias pacin='sudo pacman -S' +alias paclean='sudo pacman -Sc' +alias pacins='sudo pacman -U' +alias paclr='sudo pacman -Scc' +alias pacre='sudo pacman -R' +alias pacrem='sudo pacman -Rns' +alias pacrep='pacman -Si' +alias pacreps='pacman -Ss' +alias pacloc='pacman -Qi' +alias paclocs='pacman -Qs' +alias pacinsd='sudo pacman -S --asdeps' +alias pacmir='sudo pacman -Syy' +alias paclsorphans='sudo pacman -Qdt' +alias pacrmorphans='sudo pacman -Rs $(pacman -Qtdq)' +alias pacfileupg='sudo pacman -Fy' +alias pacfiles='pacman -F' +alias pacls='pacman -Ql' +alias pacown='pacman -Qo' +alias pacupd="sudo pacman -Sy" + +function paclist() { + pacman -Qqe | xargs -I{} -P0 --no-run-if-empty pacman -Qs --color=auto "^{}\$" +} + +function pacdisowned() { + local tmp_dir db fs + tmp_dir=$(mktemp --directory) + db=$tmp_dir/db + fs=$tmp_dir/fs + + trap "rm -rf $tmp_dir" EXIT + + pacman -Qlq | sort -u > "$db" + + find /etc /usr ! -name lost+found \ + \( -type d -printf '%p/\n' -o -print \) | sort > "$fs" + + comm -23 "$fs" "$db" + + rm -rf $tmp_dir +} + +alias pacmanallkeys='sudo pacman-key --refresh-keys' + +function pacmansignkeys() { + local key + for key in $@; do + sudo pacman-key --recv-keys $key + sudo pacman-key --lsign-key $key + printf 'trust\n3\n' | sudo gpg --homedir /etc/pacman.d/gnupg \ + --no-permission-warning --command-fd 0 --edit-key $key + done +} + +if (( $+commands[xdg-open] )); then + function pacweb() { + if [[ $# = 0 || "$1" =~ '--help|-h' ]]; then + local underline_color="\e[${color[underline]}m" + echo "$0 - open the website of an ArchLinux package" + echo + echo "Usage:" + echo " $bold_color$0$reset_color ${underline_color}target${reset_color}" + return 1 + fi + + local pkg="$1" + local infos="$(LANG=C pacman -Si "$pkg")" + if [[ -z "$infos" ]]; then + return + fi + local repo="$(grep -m 1 '^Repo' <<< "$infos" | grep -oP '[^ ]+$')" + local arch="$(grep -m 1 '^Arch' <<< "$infos" | grep -oP '[^ ]+$')" + xdg-open "https://www.archlinux.org/packages/$repo/$arch/$pkg/" &>/dev/null + } +fi + +####################################### +# AUR helpers # +####################################### + +if (( $+commands[aura] )); then + alias auin='sudo aura -S' + alias aurin='sudo aura -A' + alias auclean='sudo aura -Sc' + alias auclr='sudo aura -Scc' + alias auins='sudo aura -U' + alias auinsd='sudo aura -S --asdeps' + alias aurinsd='sudo aura -A --asdeps' + alias auloc='aura -Qi' + alias aulocs='aura -Qs' + alias aulst='aura -Qe' + alias aumir='sudo aura -Syy' + alias aurph='sudo aura -Oj' + alias aure='sudo aura -R' + alias aurem='sudo aura -Rns' + alias aurep='aura -Si' + alias aurrep='aura -Ai' + alias aureps='aura -As --both' + alias auras='aura -As --both' + alias auupd="sudo aura -Sy" + alias auupg='sudo sh -c "aura -Syu && aura -Au"' + alias ausu='sudo sh -c "aura -Syu --no-confirm && aura -Au --no-confirm"' + + # extra bonus specially for aura + alias auown="aura -Qqo" + alias auls="aura -Qql" + function auownloc() { aura -Qi $(aura -Qqo $@); } + function auownls () { aura -Qql $(aura -Qqo $@); } +fi + +if (( $+commands[pacaur] )); then + alias pacclean='pacaur -Sc' + alias pacclr='pacaur -Scc' + alias paupg='pacaur -Syu' + alias pasu='pacaur -Syu --noconfirm' + alias pain='pacaur -S' + alias pains='pacaur -U' + alias pare='pacaur -R' + alias parem='pacaur -Rns' + alias parep='pacaur -Si' + alias pareps='pacaur -Ss' + alias paloc='pacaur -Qi' + alias palocs='pacaur -Qs' + alias palst='pacaur -Qe' + alias paorph='pacaur -Qtd' + alias painsd='pacaur -S --asdeps' + alias pamir='pacaur -Syy' + alias paupd="pacaur -Sy" +fi + +if (( $+commands[trizen] )); then + alias trconf='trizen -C' + alias trupg='trizen -Syua' + alias trsu='trizen -Syua --noconfirm' + alias trin='trizen -S' + alias trclean='trizen -Sc' + alias trclr='trizen -Scc' + alias trins='trizen -U' + alias trre='trizen -R' + alias trrem='trizen -Rns' + alias trrep='trizen -Si' + alias trreps='trizen -Ss' + alias trloc='trizen -Qi' + alias trlocs='trizen -Qs' + alias trlst='trizen -Qe' + alias trorph='trizen -Qtd' + alias trinsd='trizen -S --asdeps' + alias trmir='trizen -Syy' + alias trupd="trizen -Sy" +fi + +if (( $+commands[yay] )); then + alias yaconf='yay -Pg' + alias yaclean='yay -Sc' + alias yaclr='yay -Scc' + alias yaupg='yay -Syu' + alias yasu='yay -Syu --noconfirm' + alias yain='yay -S' + alias yains='yay -U' + alias yare='yay -R' + alias yarem='yay -Rns' + alias yarep='yay -Si' + alias yareps='yay -Ss' + alias yaloc='yay -Qi' + alias yalocs='yay -Qs' + alias yalst='yay -Qe' + alias yaorph='yay -Qtd' + alias yainsd='yay -S --asdeps' + alias yamir='yay -Syy' + alias yaupd="yay -Sy" +fi + +# Check Arch Linux PGP Keyring before System Upgrade to prevent failure. +function upgrade() { + echo ":: Checking Arch Linux PGP Keyring..." + local installedver="$(LANG= sudo pacman -Qi archlinux-keyring | grep -Po '(?<=Version : ).*')" + local currentver="$(LANG= sudo pacman -Si archlinux-keyring | grep -Po '(?<=Version : ).*')" + if [ $installedver != $currentver ]; then + echo " Arch Linux PGP Keyring is out of date." + echo " Updating before full system upgrade." + sudo pacman -Sy --needed --noconfirm archlinux-keyring + else + echo " Arch Linux PGP Keyring is up to date." + echo " Proceeding with full system upgrade." + fi + if (( $+commands[yay] )); then + yay -Syu + elif (( $+commands[trizen] )); then + trizen -Syu + elif (( $+commands[pacaur] )); then + pacaur -Syu + elif (( $+commands[aura] )); then + sudo aura -Syu + else + sudo pacman -Syu + fi +} diff --git a/zsh/.oh-my-zsh/plugins/argocd/README.md b/zsh/.oh-my-zsh/plugins/argocd/README.md new file mode 100644 index 0000000..3c483fd --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/argocd/README.md @@ -0,0 +1,20 @@ +# Argo CD plugin + +This plugin adds completion for the [Argo CD](https://argoproj.github.io/cd/) CLI. + +To use it, add `argocd` to the plugins array in your zshrc file: + +```zsh +plugins=(... argocd) +``` + +This plugin does not add any aliases. + +## Cache + +This plugin caches the completion script and is automatically updated asynchronously when the plugin is +loaded, which is usually when you start up a new terminal emulator. + +The cache is stored at: + +- `$ZSH_CACHE/completions/_argocd` completions script diff --git a/zsh/.oh-my-zsh/plugins/argocd/argocd.plugin.zsh b/zsh/.oh-my-zsh/plugins/argocd/argocd.plugin.zsh new file mode 100644 index 0000000..32ad205 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/argocd/argocd.plugin.zsh @@ -0,0 +1,14 @@ +# Autocompletion for argocd. +if (( ! $+commands[argocd] )); then + return +fi + +# If the completion file doesn't exist yet, we need to autoload it and +# bind it to `argocd`. Otherwise, compinit will have already done that. +if [[ ! -f "$ZSH_CACHE_DIR/completions/_argocd" ]]; then + typeset -g -A _comps + autoload -Uz _argocd + _comps[argocd]=_argocd +fi + +argocd completion zsh >| "$ZSH_CACHE_DIR/completions/_argocd" &| diff --git a/zsh/.oh-my-zsh/plugins/asdf/README.md b/zsh/.oh-my-zsh/plugins/asdf/README.md new file mode 100644 index 0000000..f3f8f24 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/asdf/README.md @@ -0,0 +1,30 @@ +## asdf + +**Maintainer:** [@RobLoach](https://github.com/RobLoach) + +Adds integration with [asdf](https://github.com/asdf-vm/asdf), the extendable version manager, with support for Ruby, Node.js, Elixir, Erlang and more. + +### Installation + +1. [Download asdf](https://asdf-vm.com/guide/getting-started.html#_2-download-asdf) by running the following: + + ``` + git clone https://github.com/asdf-vm/asdf.git ~/.asdf + ``` + +2. [Enable asdf](https://asdf-vm.com/guide/getting-started.html#_3-install-asdf) by adding it to your `plugins` definition in `~/.zshrc`. + + ``` + plugins=(asdf) + ``` + +### Usage + +See the [asdf documentation](https://asdf-vm.com/guide/getting-started.html#_4-install-a-plugin) for information on how to use asdf: + +``` +asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git +asdf install nodejs latest +asdf global nodejs latest +asdf local nodejs latest +``` diff --git a/zsh/.oh-my-zsh/plugins/asdf/asdf.plugin.zsh b/zsh/.oh-my-zsh/plugins/asdf/asdf.plugin.zsh new file mode 100644 index 0000000..09cc24a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/asdf/asdf.plugin.zsh @@ -0,0 +1,30 @@ +# Find where asdf should be installed +ASDF_DIR="${ASDF_DIR:-$HOME/.asdf}" +ASDF_COMPLETIONS="$ASDF_DIR/completions" + +if [[ ! -f "$ASDF_DIR/asdf.sh" || ! -f "$ASDF_COMPLETIONS/_asdf" ]]; then + # If not found, check for archlinux/AUR package (/opt/asdf-vm/) + if [[ -f "/opt/asdf-vm/asdf.sh" ]]; then + ASDF_DIR="/opt/asdf-vm" + ASDF_COMPLETIONS="$ASDF_DIR" + # If not found, check for Homebrew package + elif (( $+commands[brew] )); then + _ASDF_PREFIX="$(brew --prefix asdf)" + ASDF_DIR="${_ASDF_PREFIX}/libexec" + ASDF_COMPLETIONS="${_ASDF_PREFIX}/share/zsh/site-functions" + unset _ASDF_PREFIX + else + return + fi +fi + +# Load command +if [[ -f "$ASDF_DIR/asdf.sh" ]]; then + source "$ASDF_DIR/asdf.sh" + # Load completions + if [[ -f "$ASDF_COMPLETIONS/_asdf" ]]; then + fpath+=("$ASDF_COMPLETIONS") + autoload -Uz _asdf + compdef _asdf asdf # compdef is already loaded before loading plugins + fi +fi diff --git a/zsh/.oh-my-zsh/plugins/autoenv/README.md b/zsh/.oh-my-zsh/plugins/autoenv/README.md new file mode 100644 index 0000000..ae29ed5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/autoenv/README.md @@ -0,0 +1,20 @@ +# Autoenv plugin + +This plugin loads the [Autoenv](https://github.com/inishchith/autoenv). + +To use it, add `autoenv` to the plugins array in your zshrc file: + +```zsh +plugins=(... autoenv) +``` + +## Functions + +* `use_env()`: creates and/or activates a virtualenv. For use in `.env` files. + See the source code for details. + +## Requirements + +In order to make this work, you will need to have the autoenv installed. + +More info on the usage and install at [the project's homepage](https://github.com/inishchith/autoenv). diff --git a/zsh/.oh-my-zsh/plugins/autoenv/autoenv.plugin.zsh b/zsh/.oh-my-zsh/plugins/autoenv/autoenv.plugin.zsh new file mode 100644 index 0000000..e44e6ea --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/autoenv/autoenv.plugin.zsh @@ -0,0 +1,80 @@ +# Initialization: activate autoenv or report its absence +() { +local d autoenv_dir install_locations +if ! type autoenv_init >/dev/null; then + # Check if activate.sh is in $PATH + if (( $+commands[activate.sh] )); then + autoenv_dir="${commands[activate.sh]:h}" + fi + + # Locate autoenv installation + if [[ -z $autoenv_dir ]]; then + install_locations=( + ~/.autoenv + ~/.local/bin + /usr/local/opt/autoenv + /opt/homebrew/opt/autoenv + /usr/local/bin + /usr/share/autoenv-git + ~/Library/Python/bin + .venv/bin + venv/bin + env/bin + .env/bin + ) + for d ( $install_locations ); do + if [[ -e $d/activate || -e $d/activate.sh ]]; then + autoenv_dir=$d + break + fi + done + fi + + # Look for Homebrew path as a last resort + if [[ -z "$autoenv_dir" ]] && (( $+commands[brew] )); then + d=$(brew --prefix)/opt/autoenv + if [[ -e $d/activate || -e $d/activate.sh ]]; then + autoenv_dir=$d + fi + fi + + # Complain if autoenv is not installed + if [[ -z $autoenv_dir ]]; then + cat <&2 +-------- AUTOENV --------- +Could not locate autoenv installation. +Please check if autoenv is correctly installed. +In the meantime the autoenv plugin is DISABLED. +-------------------------- +END + return 1 + fi + # Load autoenv + if [[ -e $autoenv_dir/activate ]]; then + source $autoenv_dir/activate + else + source $autoenv_dir/activate.sh + fi +fi +} +[[ $? != 0 ]] && return $? + +# The use_env call below is a reusable command to activate/create a new Python +# virtualenv, requiring only a single declarative line of code in your .env files. +# It only performs an action if the requested virtualenv is not the current one. + +use_env() { + local venv + venv="$1" + if [[ "${VIRTUAL_ENV:t}" != "$venv" ]]; then + if workon | grep -q "$venv"; then + workon "$venv" + else + echo -n "Create virtualenv $venv now? (Yn) " + read answer + if [[ "$answer" == "Y" ]]; then + mkvirtualenv "$venv" + fi + fi + fi +} diff --git a/zsh/.oh-my-zsh/plugins/autojump/README.md b/zsh/.oh-my-zsh/plugins/autojump/README.md new file mode 100644 index 0000000..41bbfc5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/autojump/README.md @@ -0,0 +1,11 @@ +# Autojump plugin + +This plugin loads the [autojump navigation tool](https://github.com/wting/autojump). + +To use it, add `autojump` to the plugins array in your zshrc file: + +```zsh +plugins=(... autojump) +``` + +**Note:** you have to [install autojump](https://github.com/wting/autojump#installation) first. diff --git a/zsh/.oh-my-zsh/plugins/autojump/autojump.plugin.zsh b/zsh/.oh-my-zsh/plugins/autojump/autojump.plugin.zsh new file mode 100644 index 0000000..cadf73a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/autojump/autojump.plugin.zsh @@ -0,0 +1,40 @@ +declare -a autojump_paths +autojump_paths=( + $HOME/.autojump/etc/profile.d/autojump.zsh # manual installation + $HOME/.autojump/share/autojump/autojump.zsh # manual installation + $HOME/.nix-profile/etc/profile.d/autojump.sh # NixOS installation + /run/current-system/sw/share/autojump/autojump.zsh # NixOS installation + /etc/profiles/per-user/$USER/share/autojump/autojump.zsh # Home Manager, NixOS with user-scoped packages + /usr/share/autojump/autojump.zsh # Debian and Ubuntu package + /etc/profile.d/autojump.zsh # manual installation + /etc/profile.d/autojump.sh # Gentoo installation + /usr/local/share/autojump/autojump.zsh # FreeBSD installation + /usr/pkg/share/autojump/autojump.zsh # NetBSD installation + /opt/local/etc/profile.d/autojump.sh # macOS with MacPorts + /usr/local/etc/profile.d/autojump.sh # macOS with Homebrew (default) + /opt/homebrew/etc/profile.d/autojump.sh # macOS with Homebrew (default on M1 macs) + /opt/pkg/share/autojump/autojump.zsh # macOS with pkgsrc + /etc/profiles/per-user/$USER/etc/profile.d/autojump.sh # macOS Nix, Home Manager and flakes + /nix/var/nix/gcroots/current-system/sw/share/zsh/site-functions/autojump.zsh # macOS Nix, nix-darwin +) + +for file in $autojump_paths; do + if [[ -f "$file" ]]; then + source "$file" + found=1 + break + fi +done + +# if no path found, try Homebrew +if (( ! found && $+commands[brew] )); then + file=$(brew --prefix)/etc/profile.d/autojump.sh + if [[ -f "$file" ]]; then + source "$file" + found=1 + fi +fi + +(( ! found )) && echo '[oh-my-zsh] autojump not found. Please install it first.' + +unset autojump_paths file found diff --git a/zsh/.oh-my-zsh/plugins/autopep8/README.md b/zsh/.oh-my-zsh/plugins/autopep8/README.md new file mode 100644 index 0000000..fa22225 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/autopep8/README.md @@ -0,0 +1,8 @@ +# autopep8 plugin + +This plugin adds completion for [autopep8](https://pypi.org/project/autopep8/), a tool that automatically formats Python code to conform to the [PEP 8](http://www.python.org/dev/peps/pep-0008/) style guide. + +To use it, add autopep8 to the plugins array of your zshrc file: +``` +plugins=(... autopep8) +``` diff --git a/zsh/.oh-my-zsh/plugins/autopep8/_autopep8 b/zsh/.oh-my-zsh/plugins/autopep8/_autopep8 new file mode 100644 index 0000000..455c182 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/autopep8/_autopep8 @@ -0,0 +1,32 @@ +#compdef autopep8 +# +# this is zsh completion function file. +# generated by genzshcomp(ver: 0.5.1) +# + +typeset -A opt_args +local context state line + +_arguments -s -S \ + "--help[show this help message and exit]:" \ + "-h[show this help message and exit]:" \ + "--version[show program's version number and exit]:" \ + "--verbose[print verbose messages; multiple -v result in more verbose messages]" \ + "-v[print verbose messages; multiple -v result in more verbose messages]" \ + "--diff[print the diff for the fixed source]" \ + "-d[print the diff for the fixed source]" \ + "--in-place[make changes to files in place]" \ + "-i[make changes to files in place]" \ + "--recursive[run recursively; must be used with --in-place or --diff]" \ + "-r[run recursively; must be used with --in-place or --diff]" \ + "--jobs[number of parallel jobs; match CPU count if value is less than 1]::n number of parallel jobs; match CPU count if value is:_files" \ + "-j[number of parallel jobs; match CPU count if value is less than 1]::n number of parallel jobs; match CPU count if value is:_files" \ + "--pep8-passes[maximum number of additional pep8 passes (default: 100)]::n:_files" \ + "-p[maximum number of additional pep8 passes (default: 100)]::n:_files" \ + "-a[-a result in more aggressive changes]::result:_files" \ + "--exclude[exclude files/directories that match these comma- separated globs]::globs:_files" \ + "--list-fixes[list codes for fixes; used by --ignore and --select]" \ + "--ignore[do not fix these errors/warnings (default E226,E24)]::errors:_files" \ + "--select[fix only these errors/warnings (e.g. E4,W)]::errors:_files" \ + "--max-line-length[set maximum allowed line length (default: 79)]::n:_files" \ + "*::args:_files" diff --git a/zsh/.oh-my-zsh/plugins/aws/README.md b/zsh/.oh-my-zsh/plugins/aws/README.md new file mode 100644 index 0000000..cf5217d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/aws/README.md @@ -0,0 +1,98 @@ +# aws + +This plugin provides completion support for [awscli v2](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/index.html) +and a few utilities to manage AWS profiles/regions and display them in the prompt. +[awscli v1](https://docs.aws.amazon.com/cli/latest/userguide/cliv2-migration.html) is no longer supported. + +To use it, add `aws` to the plugins array in your zshrc file. + +```zsh +plugins=(... aws) +``` + +## Plugin commands + +* `asp []`: sets `$AWS_PROFILE` and `$AWS_DEFAULT_PROFILE` (legacy) to ``. + It also sets `$AWS_EB_PROFILE` to `` for the Elastic Beanstalk CLI. It sets `$AWS_PROFILE_REGION` for display in `aws_prompt_info`. + Run `asp` without arguments to clear the profile. +* `asp [] login`: If AWS SSO has been configured in your aws profile, it will run the `aws sso login` command following profile selection. +* `asp [] login []`: In addition to `asp [] login`, if SSO session has been configured in your aws profile, it will run the `aws sso login --sso-session ` command following profile selection. +* `asp [] logout`: If AWS SSO has been configured in your aws profile, it will run the `aws sso logout` command following profile selection. + +* `asr []`: sets `$AWS_REGION` and `$AWS_DEFAULT_REGION` (legacy) to ``. + Run `asr` without arguments to clear the profile. + +* `acp [] []`: in addition to `asp` functionality, it actually changes + the profile by assuming the role specified in the `` configuration. It supports + MFA and sets `$AWS_ACCESS_KEY_ID`, `$AWS_SECRET_ACCESS_KEY` and `$AWS_SESSION_TOKEN`, if + obtained. It requires the roles to be configured as per the + [official guide](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html). + Run `acp` without arguments to clear the profile. + +* `agp`: gets the current value of `$AWS_PROFILE`. + +* `agr`: gets the current value of `$AWS_REGION`. + +* `aws_change_access_key`: changes the AWS access key of a profile. + +* `aws_profiles`: lists the available profiles in the `$AWS_CONFIG_FILE` (default: `~/.aws/config`). + Used to provide completion for the `asp` function. + +* `aws_regions`: lists the available regions. + Used to provide completion for the `asr` function. + +## Plugin options + +* Set `SHOW_AWS_PROMPT=false` in your zshrc file if you want to prevent the plugin from modifying your RPROMPT. + Some themes might overwrite the value of RPROMPT instead of appending to it, so they'll need to be fixed to + see the AWS profile/region prompt. + +* Set `AWS_PROFILE_STATE_ENABLED=true` in your zshrc file if you want the aws profile to persist between shell sessions. + This option might slow down your shell startup time. + By default the state file path is `/tmp/.aws_current_profile`. This means that the state won't survive a reboot or otherwise GC. + You can control the state file path using the `AWS_STATE_FILE` environment variable. + +## Theme + +The plugin creates an `aws_prompt_info` function that you can use in your theme, which displays +the current `$AWS_PROFILE` and `$AWS_REGION`. It uses four variables to control how that is shown: + +* ZSH_THEME_AWS_PROFILE_PREFIX: sets the prefix of the AWS_PROFILE. Defaults to ``. + +* ZSH_THEME_AWS_REGION_PREFIX: sets the prefix of the AWS_REGION. Defaults to ``. + +* ZSH_THEME_AWS_DIVIDER: sets the divider between ZSH_THEME_AWS_PROFILE_SUFFIX and ZSH_THEME_AWS_REGION_PREFIX. Defaults to ` ` (single space). + +## Configuration + +[Configuration and credential file settings](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html) by AWS + +### Scenario: IAM roles with a source profile and MFA authentication + +Source profile credentials in `~/.aws/credentials`: + +```ini +[source-profile-name] +aws_access_key_id = ... +aws_secret_access_key = ... +``` + +Role configuration in `~/.aws/config`: + +```ini +[profile source-profile-name] +mfa_serial = arn:aws:iam::111111111111:mfa/myuser +region = us-east-1 +output = json + +[profile profile-with-role] +role_arn = arn:aws:iam::9999999999999:role/myrole +mfa_serial = arn:aws:iam::111111111111:mfa/myuser +source_profile = source-profile-name +region = us-east-1 +output = json +``` diff --git a/zsh/.oh-my-zsh/plugins/aws/aws.plugin.zsh b/zsh/.oh-my-zsh/plugins/aws/aws.plugin.zsh new file mode 100644 index 0000000..3f1249a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/aws/aws.plugin.zsh @@ -0,0 +1,338 @@ +function agp() { + echo $AWS_PROFILE +} + +function agr() { + echo $AWS_REGION +} + +# Update state file if enabled +function _aws_update_state() { + if [[ "$AWS_PROFILE_STATE_ENABLED" == true ]]; then + test -d $(dirname ${AWS_STATE_FILE}) || exit 1 + echo "${AWS_PROFILE} ${AWS_REGION}" > "${AWS_STATE_FILE}" + fi +} + +function _aws_clear_state() { + if [[ "$AWS_PROFILE_STATE_ENABLED" == true ]]; then + test -d $(dirname ${AWS_STATE_FILE}) || exit 1 + echo -n > "${AWS_STATE_FILE}" + fi +} + +# AWS profile selection +function asp() { + if [[ -z "$1" ]]; then + unset AWS_DEFAULT_PROFILE AWS_PROFILE AWS_EB_PROFILE AWS_PROFILE_REGION + _aws_clear_state + echo AWS profile cleared. + return + fi + + local -a available_profiles + available_profiles=($(aws_profiles)) + if [[ -z "${available_profiles[(r)$1]}" ]]; then + echo "${fg[red]}Profile '$1' not found in '${AWS_CONFIG_FILE:-$HOME/.aws/config}'" >&2 + echo "Available profiles: ${(j:, :)available_profiles:-no profiles found}${reset_color}" >&2 + return 1 + fi + + export AWS_DEFAULT_PROFILE=$1 + export AWS_PROFILE=$1 + export AWS_EB_PROFILE=$1 + + export AWS_PROFILE_REGION=$(aws configure get region) + + _aws_update_state + + if [[ "$2" == "login" ]]; then + if [[ -n "$3" ]]; then + aws sso login --sso-session $3 + else + aws sso login + fi + elif [[ "$2" == "logout" ]]; then + aws sso logout + fi +} + +# AWS region selection +function asr() { + if [[ -z "$1" ]]; then + unset AWS_DEFAULT_REGION AWS_REGION + _aws_update_state + echo AWS region cleared. + return + fi + + local -a available_regions + available_regions=($(aws_regions)) + if [[ -z "${available_regions[(r)$1]}" ]]; then + echo "${fg[red]}Available regions: \n$(aws_regions)" + return 1 + fi + + export AWS_REGION=$1 + export AWS_DEFAULT_REGION=$1 + _aws_update_state +} + +# AWS profile switch +function acp() { + if [[ -z "$1" ]]; then + unset AWS_DEFAULT_PROFILE AWS_PROFILE AWS_EB_PROFILE + unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN + echo AWS profile cleared. + return + fi + + local -a available_profiles + available_profiles=($(aws_profiles)) + if [[ -z "${available_profiles[(r)$1]}" ]]; then + echo "${fg[red]}Profile '$1' not found in '${AWS_CONFIG_FILE:-$HOME/.aws/config}'" >&2 + echo "Available profiles: ${(j:, :)available_profiles:-no profiles found}${reset_color}" >&2 + return 1 + fi + + local profile="$1" + local mfa_token="$2" + + # Get fallback credentials for if the aws command fails or no command is run + local aws_access_key_id="$(aws configure get aws_access_key_id --profile $profile)" + local aws_secret_access_key="$(aws configure get aws_secret_access_key --profile $profile)" + local aws_session_token="$(aws configure get aws_session_token --profile $profile)" + + + # First, if the profile has MFA configured, lets get the token and session duration + local mfa_serial="$(aws configure get mfa_serial --profile $profile)" + local sess_duration="$(aws configure get duration_seconds --profile $profile)" + + if [[ -n "$mfa_serial" ]]; then + local -a mfa_opt + if [[ -z "$mfa_token" ]]; then + echo -n "Please enter your MFA token for $mfa_serial: " + read -r mfa_token + fi + if [[ -z "$sess_duration" ]]; then + echo -n "Please enter the session duration in seconds (900-43200; default: 3600, which is the default maximum for a role): " + read -r sess_duration + fi + mfa_opt=(--serial-number "$mfa_serial" --token-code "$mfa_token" --duration-seconds "${sess_duration:-3600}") + fi + + # Now see whether we need to just MFA for the current role, or assume a different one + local role_arn="$(aws configure get role_arn --profile $profile)" + local sess_name="$(aws configure get role_session_name --profile $profile)" + + if [[ -n "$role_arn" ]]; then + # Means we need to assume a specified role + aws_command=(aws sts assume-role --role-arn "$role_arn" "${mfa_opt[@]}") + + # Check whether external_id is configured to use while assuming the role + local external_id="$(aws configure get external_id --profile $profile)" + if [[ -n "$external_id" ]]; then + aws_command+=(--external-id "$external_id") + fi + + # Get source profile to use to assume role + local source_profile="$(aws configure get source_profile --profile $profile)" + if [[ -z "$sess_name" ]]; then + sess_name="${source_profile:-profile}" + fi + aws_command+=(--profile="${source_profile:-profile}" --role-session-name "${sess_name}") + + echo "Assuming role $role_arn using profile ${source_profile:-profile}" + else + # Means we only need to do MFA + aws_command=(aws sts get-session-token --profile="$profile" "${mfa_opt[@]}") + echo "Obtaining session token for profile $profile" + fi + + # Format output of aws command for easier processing + aws_command+=(--query '[Credentials.AccessKeyId,Credentials.SecretAccessKey,Credentials.SessionToken]' --output text) + + # Run the aws command to obtain credentials + local -a credentials + credentials=(${(ps:\t:)"$(${aws_command[@]})"}) + + if [[ -n "$credentials" ]]; then + aws_access_key_id="${credentials[1]}" + aws_secret_access_key="${credentials[2]}" + aws_session_token="${credentials[3]}" + fi + + # Switch to AWS profile + if [[ -n "${aws_access_key_id}" && -n "$aws_secret_access_key" ]]; then + export AWS_DEFAULT_PROFILE="$profile" + export AWS_PROFILE="$profile" + export AWS_EB_PROFILE="$profile" + export AWS_ACCESS_KEY_ID="$aws_access_key_id" + export AWS_SECRET_ACCESS_KEY="$aws_secret_access_key" + + if [[ -n "$aws_session_token" ]]; then + export AWS_SESSION_TOKEN="$aws_session_token" + else + unset AWS_SESSION_TOKEN + fi + + echo "Switched to AWS Profile: $profile" + fi +} + +function aws_change_access_key() { + if [[ -z "$1" ]]; then + echo "usage: $0 " + return 1 + fi + + local profile="$1" + # Get current access key + local original_aws_access_key_id="$(aws configure get aws_access_key_id --profile $profile)" + + asp "$profile" || return 1 + echo "Generating a new access key pair for you now." + if aws --no-cli-pager iam create-access-key; then + echo "Insert the newly generated credentials when asked." + aws --no-cli-pager configure --profile $profile + else + echo "Current access keys:" + aws --no-cli-pager iam list-access-keys + echo "Profile \"${profile}\" is currently using the $original_aws_access_key_id key. You can delete an old access key by running \`aws --profile $profile iam delete-access-key --access-key-id AccessKeyId\`" + return 1 + fi + + read -q "yn?Would you like to disable your previous access key (${original_aws_access_key_id}) now? " + case $yn in + [Yy]*) + echo -n "\nDisabling access key ${original_aws_access_key_id}..." + if aws --no-cli-pager iam update-access-key --access-key-id ${original_aws_access_key_id} --status Inactive; then + echo "done." + else + echo "\nFailed to disable ${original_aws_access_key_id} key." + fi + ;; + *) + echo "" + ;; + esac + echo "You can now safely delete the old access key by running \`aws --profile $profile iam delete-access-key --access-key-id ${original_aws_access_key_id}\`" + echo "Your current keys are:" + aws --no-cli-pager iam list-access-keys +} + +function aws_regions() { + local region + if [[ $AWS_DEFAULT_REGION ]];then + region="$AWS_DEFAULT_REGION" + elif [[ $AWS_REGION ]];then + region="$AWS_REGION" + else + region="us-west-1" + fi + + if [[ $AWS_DEFAULT_PROFILE || $AWS_PROFILE ]];then + aws ec2 describe-regions --region $region |grep RegionName | awk -F ':' '{gsub(/"/, "", $2);gsub(/,/, "", $2);gsub(/ /, "", $2); print $2}' + else + echo "You must specify a AWS profile." + fi +} + +function aws_profiles() { + aws --no-cli-pager configure list-profiles 2> /dev/null && return + [[ -r "${AWS_CONFIG_FILE:-$HOME/.aws/config}" ]] || return 1 + grep --color=never -Eo '\[.*\]' "${AWS_CONFIG_FILE:-$HOME/.aws/config}" | sed -E 's/^[[:space:]]*\[(profile)?[[:space:]]*([^[:space:]]+)\][[:space:]]*$/\2/g' +} + +function _aws_regions() { + reply=($(aws_regions)) +} +compctl -K _aws_regions asr + +function _aws_profiles() { + reply=($(aws_profiles)) +} +compctl -K _aws_profiles asp acp aws_change_access_key + +# AWS prompt +function aws_prompt_info() { + local _aws_to_show + local region="${AWS_REGION:-${AWS_DEFAULT_REGION:-$AWS_PROFILE_REGION}}" + + if [[ -n "$AWS_PROFILE" ]];then + _aws_to_show+="${ZSH_THEME_AWS_PROFILE_PREFIX=""}" + fi + + if [[ -n "$region" ]]; then + [[ -n "$_aws_to_show" ]] && _aws_to_show+="${ZSH_THEME_AWS_DIVIDER=" "}" + _aws_to_show+="${ZSH_THEME_AWS_REGION_PREFIX=""}" + fi + + echo "$_aws_to_show" +} + +if [[ "$SHOW_AWS_PROMPT" != false && "$RPROMPT" != *'$(aws_prompt_info)'* ]]; then + RPROMPT='$(aws_prompt_info)'"$RPROMPT" +fi + +if [[ "$AWS_PROFILE_STATE_ENABLED" == true ]]; then + AWS_STATE_FILE="${AWS_STATE_FILE:-/tmp/.aws_current_profile}" + test -s "${AWS_STATE_FILE}" || return + + aws_state=($(cat $AWS_STATE_FILE)) + + export AWS_DEFAULT_PROFILE="${aws_state[1]}" + export AWS_PROFILE="$AWS_DEFAULT_PROFILE" + export AWS_EB_PROFILE="$AWS_DEFAULT_PROFILE" + + test -z "${aws_state[2]}" && AWS_REGION=$(aws configure get region) + + export AWS_REGION=${AWS_REGION:-$aws_state[2]} + export AWS_DEFAULT_REGION="$AWS_REGION" +fi + +# Load awscli completions + +# AWS CLI v2 comes with its own autocompletion. Check if that is there, otherwise fall back +if command -v aws_completer &> /dev/null; then + autoload -Uz bashcompinit && bashcompinit + complete -C aws_completer aws +else + function _awscli-homebrew-installed() { + # check if Homebrew is installed + (( $+commands[brew] )) || return 1 + + # speculatively check default brew prefix + if [ -h /usr/local/opt/awscli ]; then + _brew_prefix=/usr/local/opt/awscli + else + # ok, it is not in the default prefix + # this call to brew is expensive (about 400 ms), so at least let's make it only once + _brew_prefix=$(brew --prefix awscli) + fi + } + + # get aws_zsh_completer.sh location from $PATH + _aws_zsh_completer_path="$commands[aws_zsh_completer.sh]" + + # otherwise check common locations + if [[ -z $_aws_zsh_completer_path ]]; then + # Homebrew + if _awscli-homebrew-installed; then + _aws_zsh_completer_path=$_brew_prefix/libexec/bin/aws_zsh_completer.sh + # Ubuntu + elif [[ -e /usr/share/zsh/vendor-completions/_awscli ]]; then + _aws_zsh_completer_path=/usr/share/zsh/vendor-completions/_awscli + # NixOS + elif [[ -e "${commands[aws]:P:h:h}/share/zsh/site-functions/aws_zsh_completer.sh" ]]; then + _aws_zsh_completer_path="${commands[aws]:P:h:h}/share/zsh/site-functions/aws_zsh_completer.sh" + # RPM + else + _aws_zsh_completer_path=/usr/share/zsh/site-functions/aws_zsh_completer.sh + fi + fi + + [[ -r $_aws_zsh_completer_path ]] && source $_aws_zsh_completer_path + unset _aws_zsh_completer_path _brew_prefix +fi + diff --git a/zsh/.oh-my-zsh/plugins/azure/README.md b/zsh/.oh-my-zsh/plugins/azure/README.md new file mode 100644 index 0000000..4f453e1 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/azure/README.md @@ -0,0 +1,49 @@ +# azure + +This plugin provides completion support for [azure cli](https://docs.microsoft.com/en-us/cli/azure/) +and a few utilities to manage azure subscriptions and display them in the prompt. + +To use it, add `azure` to the plugins array in your zshrc file. + +```zsh +plugins=(... azure) +``` + +## Plugin commands + + +* `az_subscriptions`: lists the available subscriptions in the `AZURE_CONFIG_DIR` (default: `~/.azure/`). + Used to provide completion for the `azss` function. + +* `azgs`: gets the current value of `$azure_subscription`. + +* `azss []`: sets the `$azure_subscription`. + + +NOTE : because azure keeps the state of active subscription in ${AZURE_CONFIG_DIR:-$HOME/.azure/azureProfile.json}, the prompt command requires `jq` to be enabled to parse the file. If jq is not in the path the prompt will show nothing + +## Theme + +The plugin creates an `azure_prompt_info` function that you can use in your theme, which displays +the current `$azure_subscription`. It uses two variables to control how that is shown: + +- ZSH_THEME_AZURE_PREFIX: sets the prefix of the azure_subscription. Defaults to ``. + + +``` +RPROMPT='$(azure_prompt_info)' +``` + +## Develop + +On ubuntu get a working environment with : + +` docker run -it -v $(pwd):/mnt -w /mnt ubuntu bash` + +``` +apt install -y curl jq zsh git vim +sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" +curl -sL https://aka.ms/InstallAzureCLIDeb | bash +``` \ No newline at end of file diff --git a/zsh/.oh-my-zsh/plugins/azure/azure.plugin.zsh b/zsh/.oh-my-zsh/plugins/azure/azure.plugin.zsh new file mode 100644 index 0000000..9dd8a3c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/azure/azure.plugin.zsh @@ -0,0 +1,60 @@ +# AZ Get Subscriptions +function azgs() { + az account show --output tsv --query 'name' 2>/dev/null +} + +# AZ Subscription Selection +alias azss="az account set --subscription" + + +function az_subscriptions() { + az account list --all --output tsv --query '[*].name' 2> /dev/null +} + +function _az_subscriptions() { + reply=($(az_subscriptions)) +} +compctl -K _az_subscriptions azss + +# Azure prompt +function azure_prompt_info() { + [[ ! -f "${AZURE_CONFIG_DIR:-$HOME/.azure}/azureProfile.json" ]] && return + # azgs is too expensive, if we have jq, we enable the prompt + (( $+commands[jq] )) || return 1 + azgs=$(jq -r '.subscriptions[] | select(.isDefault==true) .name' "${AZURE_CONFIG_DIR:-$HOME/.azure}/azureProfile.json") + echo "${ZSH_THEME_AZURE_PREFIX:=}" +} + + +# Load az completions +function _az-homebrew-installed() { + # check if Homebrew is installed + (( $+commands[brew] )) || return 1 + + # if so, we assume it's default way to install brew + if [[ ${commands[brew]:t2} == bin/brew ]]; then + _brew_prefix="${commands[brew]:h:h}" # remove trailing /bin/brew + else + # ok, it is not in the default prefix + # this call to brew is expensive (about 400 ms), so at least let's make it only once + _brew_prefix=$(brew --prefix) + fi +} + + +# get az.completion.sh location from $PATH +_az_zsh_completer_path="$commands[az_zsh_completer.sh]" + +# otherwise check common locations +if [[ -z $_az_zsh_completer_path ]]; then + # Homebrew + if _az-homebrew-installed; then + _az_zsh_completer_path=$_brew_prefix/etc/bash_completion.d/az + # Linux + else + _az_zsh_completer_path=/etc/bash_completion.d/azure-cli + fi +fi + +[[ -r $_az_zsh_completer_path ]] && autoload -U +X bashcompinit && bashcompinit && source $_az_zsh_completer_path +unset _az_zsh_completer_path _brew_prefix diff --git a/zsh/.oh-my-zsh/plugins/battery/README.md b/zsh/.oh-my-zsh/plugins/battery/README.md new file mode 100644 index 0000000..2e21d19 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/battery/README.md @@ -0,0 +1,29 @@ +# Battery Plugin + +This plugin adds some functions you can use to display battery information in your custom theme. + +To use, add `battery` to the list of plugins in your `.zshrc` file: + +`plugins=(... battery)` + +Then, add the `battery_pct_prompt` function to your custom theme. For example: + +```zsh +RPROMPT='$(battery_pct_prompt) ...' +``` + +## Requirements + +- On Linux, you must have the `acpi` or `acpitool` commands installed on your operating system. + On Debian/Ubuntu, you can do that with `sudo apt install acpi` or `sudo apt install acpitool`. + +- On Android (via [Termux](https://play.google.com/store/apps/details?id=com.termux)), you must have: + + 1. The `Termux:API` addon app installed: + [Google Play](https://play.google.com/store/apps/details?id=com.termux.api) | [F-Droid](https://f-droid.org/packages/com.termux.api/) + + 2. The `termux-api` package installed within termux: + + ```sh + pkg install termux-api + ``` diff --git a/zsh/.oh-my-zsh/plugins/battery/battery.plugin.zsh b/zsh/.oh-my-zsh/plugins/battery/battery.plugin.zsh new file mode 100644 index 0000000..9d4f0fa --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/battery/battery.plugin.zsh @@ -0,0 +1,306 @@ +########################################### +# Battery plugin for oh-my-zsh # +# Original Author: Peter hoeg (peterhoeg) # +# Email: peter@speartail.com # +########################################### +# Author: Sean Jones (neuralsandwich) # +# Email: neuralsandwich@gmail.com # +# Modified to add support for Apple Mac # +########################################### +# Author: J (927589452) # +# Modified to add support for FreeBSD # +########################################### +# Author: Avneet Singh (kalsi-avneet) # +# Modified to add support for Android # +########################################### +# Author: Not Pua (im-notpua) # +# Modified to add support for OpenBSD # +########################################### + + +if [[ "$OSTYPE" = darwin* ]]; then + function battery_is_charging() { + ioreg -rc AppleSmartBattery | command grep -q '^.*"ExternalConnected"\ =\ Yes' + } + function battery_pct() { + pmset -g batt | grep -Eo "\d+%" | cut -d% -f1 + } + function battery_pct_remaining() { + if battery_is_charging; then + echo "External Power" + else + battery_pct + fi + } + function battery_time_remaining() { + local smart_battery_status="$(ioreg -rc "AppleSmartBattery")" + if [[ $(echo $smart_battery_status | command grep -c '^.*"ExternalConnected"\ =\ No') -eq 1 ]]; then + timeremaining=$(echo $smart_battery_status | command grep '^.*"AvgTimeToEmpty"\ =\ ' | sed -e 's/^.*"AvgTimeToEmpty"\ =\ //') + if [ $timeremaining -gt 720 ]; then + echo "::" + else + echo "~$((timeremaining / 60)):$((timeremaining % 60))" + fi + else + echo "∞" + fi + } + function battery_pct_prompt () { + local battery_pct color + if ioreg -rc AppleSmartBattery | command grep -q '^.*"ExternalConnected"\ =\ No'; then + battery_pct=$(battery_pct_remaining) + if [[ $battery_pct -gt 50 ]]; then + color='green' + elif [[ $battery_pct -gt 20 ]]; then + color='yellow' + else + color='red' + fi + echo "%{$fg[$color]%}[${battery_pct}%%]%{$reset_color%}" + else + echo "∞" + fi + } + +elif [[ "$OSTYPE" = freebsd* ]]; then + function battery_is_charging() { + [[ $(sysctl -n hw.acpi.battery.state) -eq 2 ]] + } + function battery_pct() { + if (( $+commands[sysctl] )); then + sysctl -n hw.acpi.battery.life + fi + } + function battery_pct_remaining() { + if ! battery_is_charging; then + battery_pct + else + echo "External Power" + fi + } + function battery_time_remaining() { + local remaining_time + remaining_time=$(sysctl -n hw.acpi.battery.time) + if [[ $remaining_time -ge 0 ]]; then + ((hour = $remaining_time / 60 )) + ((minute = $remaining_time % 60 )) + printf %02d:%02d $hour $minute + fi + } + function battery_pct_prompt() { + local battery_pct color + battery_pct=$(battery_pct_remaining) + if battery_is_charging; then + echo "∞" + else + if [[ $battery_pct -gt 50 ]]; then + color='green' + elif [[ $battery_pct -gt 20 ]]; then + color='yellow' + else + color='red' + fi + echo "%{$fg[$color]%}${battery_pct}%%%{$reset_color%}" + fi + } +elif [[ "$OSTYPE" = linux-android ]] && (( ${+commands[termux-battery-status]} )); then + function battery_is_charging() { + termux-battery-status 2>/dev/null | command awk '/status/ { exit ($0 ~ /DISCHARGING/) }' + } + function battery_pct() { + # Sample output: + # { + # "health": "GOOD", + # "percentage": 93, + # "plugged": "UNPLUGGED", + # "status": "DISCHARGING", + # "temperature": 29.0, + # "current": 361816 + # } + termux-battery-status 2>/dev/null | command awk '/percentage/ { gsub(/[,]/,""); print $2}' + } + function battery_pct_remaining() { + if ! battery_is_charging; then + battery_pct + else + echo "External Power" + fi + } + function battery_time_remaining() { } # Not available on android + function battery_pct_prompt() { + local battery_pct color + battery_pct=$(battery_pct_remaining) + if battery_is_charging; then + echo "∞" + else + if [[ $battery_pct -gt 50 ]]; then + color='green' + elif [[ $battery_pct -gt 20 ]]; then + color='yellow' + else + color='red' + fi + echo "%{$fg[$color]%}${battery_pct}%%%{$reset_color%}" + fi + } +elif [[ "$OSTYPE" = openbsd* ]]; then + function battery_is_charging() { + [[ $(apm -b) -eq 3 ]] + } + function battery_pct() { + apm -l + } + function battery_pct_remaining() { + if ! battery_is_charging; then + battery_pct + else + echo "External Power" + fi + } + function battery_time_remaining() { + local remaining_time + remaining_time=$(apm -m) + if [[ $remaining_time -ge 0 ]]; then + ((hour = $remaining_time / 60 )) + ((minute = $remaining_time % 60 )) + printf %02d:%02d $hour $minute + fi + } + function battery_pct_prompt() { + local battery_pct color + battery_pct=$(battery_pct_remaining) + if battery_is_charging; then + echo "∞" + else + if [[ $battery_pct -gt 50 ]]; then + color='green' + elif [[ $battery_pct -gt 20 ]]; then + color='yellow' + else + color='red' + fi + echo "%{$fg[$color]%}${battery_pct}%%%{$reset_color%}" + fi + } + +elif [[ "$OSTYPE" = linux* ]]; then + function battery_is_charging() { + if (( $+commands[acpitool] )); then + ! acpitool 2>/dev/null | command grep -qE '^\s+Battery.*Discharging' + elif (( $+commands[acpi] )); then + ! acpi 2>/dev/null | command grep -v "rate information unavailable" | command grep -q '^Battery.*Discharging' + fi + } + function battery_pct() { + if (( $+commands[acpitool] )); then + # Sample output: + # Battery #1 : Unknown, 99.55% + # Battery #2 : Discharging, 49.58%, 01:12:05 + # All batteries : 62.60%, 02:03:03 + local -i pct=$(acpitool 2>/dev/null | command awk -F, ' + /^\s+All batteries/ { + gsub(/[^0-9.]/, "", $1) + pct=$1 + exit + } + !pct && /^\s+Battery/ { + gsub(/[^0-9.]/, "", $2) + pct=$2 + } + END { print pct } + ') + echo $pct + elif (( $+commands[acpi] )); then + # Sample output: + # Battery 0: Discharging, 0%, rate information unavailable + # Battery 1: Full, 100% + acpi 2>/dev/null | command awk -F, ' + /rate information unavailable/ { next } + /^Battery.*: /{ gsub(/[^0-9]/, "", $2); print $2; exit } + ' + fi + } + function battery_pct_remaining() { + if ! battery_is_charging; then + battery_pct + else + echo "External Power" + fi + } + function battery_time_remaining() { + if ! battery_is_charging; then + acpi 2>/dev/null | command grep -v "rate information unavailable" | cut -f3 -d ',' + fi + } + function battery_pct_prompt() { + local battery_pct color + battery_pct=$(battery_pct_remaining) + if battery_is_charging; then + echo "∞" + else + if [[ $battery_pct -gt 50 ]]; then + color='green' + elif [[ $battery_pct -gt 20 ]]; then + color='yellow' + else + color='red' + fi + echo "%{$fg[$color]%}${battery_pct}%%%{$reset_color%}" + fi + } +else + # Empty functions so we don't cause errors in prompts + function battery_is_charging { false } + function battery_pct \ + battery_pct_remaining \ + battery_time_remaining \ + battery_pct_prompt { } +fi + +function battery_level_gauge() { + local gauge_slots=${BATTERY_GAUGE_SLOTS:-10} + local green_threshold=${BATTERY_GREEN_THRESHOLD:-$(( gauge_slots * 0.6 ))} + local yellow_threshold=${BATTERY_YELLOW_THRESHOLD:-$(( gauge_slots * 0.4 ))} + local color_green=${BATTERY_COLOR_GREEN:-%F{green}} + local color_yellow=${BATTERY_COLOR_YELLOW:-%F{yellow}} + local color_red=${BATTERY_COLOR_RED:-%F{red}} + local color_reset=${BATTERY_COLOR_RESET:-%{%f%k%b%}} + local battery_prefix=${BATTERY_GAUGE_PREFIX:-'['} + local battery_suffix=${BATTERY_GAUGE_SUFFIX:-']'} + local filled_symbol=${BATTERY_GAUGE_FILLED_SYMBOL:-'▶'} + local empty_symbol=${BATTERY_GAUGE_EMPTY_SYMBOL:-'▷'} + local charging_color=${BATTERY_CHARGING_COLOR:-$color_yellow} + local charging_symbol=${BATTERY_CHARGING_SYMBOL:-'⚡'} + + local -i battery_remaining_percentage=$(battery_pct) + local filled empty gauge_color + + if [[ $battery_remaining_percentage =~ [0-9]+ ]]; then + filled=$(( ($battery_remaining_percentage * $gauge_slots) / 100 )) + empty=$(( $gauge_slots - $filled )) + + if [[ $filled -gt $green_threshold ]]; then + gauge_color=$color_green + elif [[ $filled -gt $yellow_threshold ]]; then + gauge_color=$color_yellow + else + gauge_color=$color_red + fi + else + filled=$gauge_slots + empty=0 + filled_symbol=${BATTERY_UNKNOWN_SYMBOL:-'.'} + fi + + local charging=' ' + battery_is_charging && charging=$charging_symbol + + # Charging status and prefix + print -n ${charging_color}${charging}${color_reset}${battery_prefix}${gauge_color} + # Filled slots + [[ $filled -gt 0 ]] && printf ${filled_symbol//\%/\%\%}'%.0s' {1..$filled} + # Empty slots + [[ $filled -lt $gauge_slots ]] && printf ${empty_symbol//\%/\%\%}'%.0s' {1..$empty} + # Suffix + print -n ${color_reset}${battery_suffix}${color_reset} +} diff --git a/zsh/.oh-my-zsh/plugins/bazel/README.md b/zsh/.oh-my-zsh/plugins/bazel/README.md new file mode 100644 index 0000000..70445db --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bazel/README.md @@ -0,0 +1,22 @@ +# Bazel plugin + +This plugin adds completion and aliases for [bazel](https://bazel.build), an open-source build and test tool that scalably supports multi-language and multi-platform projects. + +To use it, add `bazel` to the plugins array in your zshrc file: + +```zsh +plugins=(... bazel) +``` + +The plugin has a copy of [the completion script from the git repository][1]. + +[1]: https://github.com/bazelbuild/bazel/blob/master/scripts/zsh_completion/_bazel + +## Aliases + +| Alias | Command | Description | +| ------- | -------------------------------------- | ------------------------------------------------------ | +| bzb | `bazel build` | The `bazel build` command | +| bzt | `bazel test` | The `bazel test` command | +| bzr | `bazel run` | The `bazel run` command | +| bzq | `bazel query` | The `bazel query` command | diff --git a/zsh/.oh-my-zsh/plugins/bazel/_bazel b/zsh/.oh-my-zsh/plugins/bazel/_bazel new file mode 100644 index 0000000..5a5313b --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bazel/_bazel @@ -0,0 +1,341 @@ +#compdef bazel bazelisk + +# Copyright 2015 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Installation +# ------------ +# +# 1. Add this script to a directory on your $fpath: +# fpath[1,0]=~/.zsh/completion/ +# mkdir -p ~/.zsh/completion/ +# cp scripts/zsh_completion/_bazel ~/.zsh/completion +# +# 2. Optionally, add the following to your .zshrc. +# zstyle ':completion:*' use-cache on +# zstyle ':completion:*' cache-path ~/.zsh/cache +# +# This way, the completion script does not have to parse Bazel's options +# repeatedly. The directory in cache-path must be created manually. +# +# 3. Restart the shell +# +# Options +# ------- +# completion:init:bazel:* cache-lifetime +# Lifetime for the completion cache (if turned on, default: 1 week) + +local curcontext="$curcontext" state line + +: ${BAZEL_COMPLETION_PACKAGE_PATH:=%workspace%} +: ${BAZEL:=bazel} +_bazel_b() { ${BAZEL} --noblock_for_lock "$@" 2>/dev/null; } + +# Default cache lifetime is 1 week +zstyle -s ":completion:${curcontext}:" cache-lifetime lifetime +if [[ -z "${lifetime}" ]]; then + lifetime=$((60*60*24*7)) +fi + +_bazel_cache_policy() { + local -a oldp + oldp=( "$1"(Nms+${lifetime}) ) + (( $#oldp )) +} + +_set_cache_policy() { + zstyle -s ":completion:*:$curcontext*" cache-policy update_policy + + if [[ -z "$update_policy" ]]; then + zstyle ":completion:$curcontext*" cache-policy _bazel_cache_policy + fi +} + +# Skips over all global arguments. After invocation, OFFSET contains the +# position of the bazel command in $words. +_adapt_subcommand_offset() { + OFFSET=2 + for w in ${words[2,-1]}; do + if [[ $w == (#b)-* ]]; then + (( OFFSET++ )) + else + return + fi + done +} + +# Retrieve the cache but also check that the value is not empty. +_bazel_safe_retrieve_cache() { + _retrieve_cache $1 && [[ ${(P)#2} -gt 0 ]] +} + +# Puts the name of the variable that contains the options for the bazel +# subcommand handed in as the first argument into the global variable +# _bazel_cmd_options. +_bazel_get_options() { + local lcmd=$1 + _bazel_cmd_options=_bazel_${lcmd}_options + _bazel_cmd_args=_bazel_${lcmd}_args + if [[ ${(P)#_bazel_cmd_options} != 0 ]]; then + return + fi + if _cache_invalid BAZEL_${lcmd}_options || _cache_invalid BAZEL_${lcmd}_args \ + || ! _bazel_safe_retrieve_cache BAZEL_${lcmd}_options ${_bazel_cmd_options} \ + || ! _retrieve_cache BAZEL_${lcmd}_args ${_bazel_cmd_args}; then + if ! eval "$(_bazel_b help completion)"; then + return + fi + local opts_var + if [[ $lcmd == "startup_options" ]]; then + opts_var="BAZEL_STARTUP_OPTIONS" + else + opts_var="BAZEL_COMMAND_${lcmd:u}_FLAGS" + fi + local -a raw_options + if ! eval "raw_options=(\${(@f)$opts_var})"; then + return + fi + + local -a option_list + for opt in $raw_options; do + case $opt in + --*"={"*) + local lst="${${opt##*"={"}%"}"}" + local opt="${opt%%=*}=" + option_list+=("${opt}:string:_values '' ${lst//,/ }") ;; + --*=path) + option_list+=("${opt%path}:path:_files") ;; + --*=label) + option_list+=("${opt%label}:target:_bazel_complete_target") ;; + --*=*) + option_list+=("${opt}:string:") ;; + *) + option_list+=("$opt") ;; + esac + done + + local -a cmd_args + local cmd_type + if eval "cmd_type=\${BAZEL_COMMAND_${lcmd:u}_ARGUMENT}" && [[ -n $cmd_type ]]; then + case $cmd_type in + label|label-*) + cmd_args+=("*::${cmd_type}:_bazel_complete_target_${cmd_type//-/_}") ;; + info-key) + cmd_args+=('1::key:_bazel_info_key') ;; + path) + cmd_args+=('1::profile:_path_files') ;; + "command|{"*"}") + local lst=${${cmd_type#"command|{"}%"}"} + cmd_args+=("1::topic:_bazel_help_topic -- ${lst//,/ }") ;; + esac + fi + + typeset -g "${_bazel_cmd_options}"="${(pj:|:)option_list[*]}" + _store_cache BAZEL_${lcmd}_options ${_bazel_cmd_options} + typeset -g "${_bazel_cmd_args}"="${(pj:|:)cmd_args[*]}" + _store_cache BAZEL_${lcmd}_args ${_bazel_cmd_args} + fi +} + +_get_build_targets() { + local pkg=$1 + local rule_re + typeset -a completions + case $target_type in + test) + rule_re=".*_test" + ;; + build) + rule_re=".*" + ;; + bin) + rule_re=".*_test|.*_binary" + ;; + esac + completions=(${$(_bazel_b query "kind(\"${rule_re}\", ${pkg}:all)" 2>/dev/null)##*:}) + if ( (( ${#completions} > 0 )) && [[ $target_type != bin ]] ); then + completions+=(all) + fi + echo ${completions[*]} +} + +# Returns all packages that match $PREFIX. PREFIX may start with //, in which +# case the workspace roots are searched. Otherwise, they are completed based on +# PWD. +_get_build_packages() { + local workspace pfx + typeset -a package_roots paths final_paths + workspace=$PWD + package_roots=(${(ps.:.)BAZEL_COMPLETION_PACKAGE_PATH}) + package_roots=(${^package_roots//\%workspace\%/$workspace}) + if [[ "${(e)PREFIX}" == //* ]]; then + pfx=${(e)PREFIX[2,-1]} + else + pfx=${(e)PREFIX} + fi + paths=(${^package_roots}/${pfx}*(/)) + for p in ${paths[*]}; do + if [[ -f ${p}/BUILD || -f ${p}/BUILD.bazel ]]; then + final_paths+=(${p##*/}:) + fi + final_paths+=(${p##*/}/) + done + echo ${final_paths[*]} +} + +_package_remove_slash() { + if [[ $KEYS == ':' && $LBUFFER == */ ]]; then + LBUFFER=${LBUFFER[1,-2]} + fi +} + +# Completion function for BUILD targets, called by the completion system. +_bazel_complete_target() { + local expl + typeset -a packages targets + if [[ "${(e)PREFIX}" != *:* ]]; then + # There is no : in the prefix, completion can be either + # a package or a target, if the cwd is a package itself. + if [[ -f $PWD/BUILD || -f $PWD/BUILD.bazel ]]; then + targets=($(_get_build_targets "")) + _description build_target expl "BUILD target" + compadd "${expl[@]}" -a targets + fi + packages=($(_get_build_packages)) + _description build_package expl "BUILD package" + # Chop of the leading path segments from the prefix for display. + compset -P '*/' + compadd -R _package_remove_slash -S '' "${expl[@]}" -a packages + else + targets=($(_get_build_targets "${${(e)PREFIX}%:*}")) + _description build_target expl "BUILD target" + # Ignore the current prefix for the upcoming completion, since we only list + # the names of the targets, not the full path. + compset -P '*:' + compadd "${expl[@]}" -a targets + fi +} + +_bazel_complete_target_label() { + typeset -g target_type=build + _bazel_complete_target +} + +_bazel_complete_target_label_test() { + typeset -g target_type=test + _bazel_complete_target +} + +_bazel_complete_target_label_bin() { + typeset -g target_type=bin + _bazel_complete_target +} + +### Actual completion commands + +_bazel() { + _adapt_subcommand_offset + if (( CURRENT - OFFSET > 0 )); then + # Remember the subcommand name, stored globally so we can access it + # from any subsequent function + cmd=${words[OFFSET]//-/_} + + # Set the context for the subcommand. + curcontext="${curcontext%:*:*}:bazel-$cmd:" + _set_cache_policy + + # Narrow the range of words we are looking at to exclude cmd + # name and any leading options + (( CURRENT = CURRENT - OFFSET + 1 )) + shift $((OFFSET - 1)) words + # Run the completion for the subcommand + _bazel_get_options $cmd + _arguments : \ + ${(Pps:|:)_bazel_cmd_options} \ + ${(Pps:|:)_bazel_cmd_args} + else + _set_cache_policy + # Start special handling for global options, + # which can be retrieved by calling + # $ bazel help startup_options + _bazel_get_options startup_options + _arguments : \ + ${(Pps:|:)_bazel_cmd_options} \ + "*:commands:_bazel_commands" + fi + return +} + +_get_commands() { + # bazel_cmd_list is a global (g) array (a) + typeset -ga _bazel_cmd_list + # Use `bazel help` instead of `bazel help completion` to get command + # descriptions. + if _bazel_cmd_list=("${(@f)$(_bazel_b help | awk ' +/Available commands/ { command=1; } +/ [-a-z]+[ \t]+.+/ { if (command) { printf "%s:", $1; for (i=2; i<=NF; i++) printf "%s ", $i; print "" } } +/^$/ { command=0; }')}"); then + _store_cache BAZEL_commands _bazel_cmd_list + fi +} + +# Completion function for bazel subcommands, called by the completion system. +_bazel_commands() { + if [[ ${#_bazel_cmd_list} == 0 ]]; then + if _cache_invalid BAZEL_commands \ + || ! _bazel_safe_retrieve_cache BAZEL_commands _bazel_cmd_list; then + _get_commands + fi + fi + + _describe -t bazel-commands 'Bazel command' _bazel_cmd_list +} + +# Completion function for bazel help options, called by the completion system. +_bazel_help_topic() { + if [[ ${#_bazel_cmd_list} == 0 ]]; then + if _cache_invalid BAZEL_commands \ + || ! _bazel_safe_retrieve_cache BAZEL_commands _bazel_cmd_list; then + _get_commands + fi + fi + + while [[ $# -gt 0 ]]; do + if [[ $1 == -- ]]; then + shift + break + fi + shift + done + _bazel_help_list=($@) + _bazel_help_list+=($_bazel_cmd_list) + _describe -t bazel-help 'Help topic' _bazel_help_list +} + +# Completion function for bazel info keys, called by the completion system. +_bazel_info_key() { + if [[ ${#_bazel_info_keys_list} == 0 ]]; then + if _cache_invalid BAZEL_info_keys \ + || ! _bazel_safe_retrieve_cache BAZEL_info_keys _bazel_info_keys_list; then + typeset -ga _bazel_info_keys_list + # Use `bazel help` instead of `bazel help completion` to get info-key + # descriptions. + if _bazel_info_keys_list=("${(@f)$(_bazel_b help info-keys | awk ' + { printf "%s:", $1; for (i=2; i<=NF; i++) printf "%s ", $i; print "" }')}"); then + _store_cache BAZEL_info_keys _bazel_info_keys_list + fi + fi + fi + _describe -t bazel-info 'Key' _bazel_info_keys_list +} diff --git a/zsh/.oh-my-zsh/plugins/bazel/bazel.plugin.zsh b/zsh/.oh-my-zsh/plugins/bazel/bazel.plugin.zsh new file mode 100644 index 0000000..7fa489f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bazel/bazel.plugin.zsh @@ -0,0 +1,5 @@ +# Aliases for bazel +alias bzb='bazel build' +alias bzt='bazel test' +alias bzr='bazel run' +alias bzq='bazel query' diff --git a/zsh/.oh-my-zsh/plugins/bbedit/README.md b/zsh/.oh-my-zsh/plugins/bbedit/README.md new file mode 100644 index 0000000..a5c006d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bbedit/README.md @@ -0,0 +1,20 @@ +## bbedit + +Plugin for BBEdit, an HTML and text editor for Mac OS X + +### Requirements + + * [BBEdit](https://www.barebones.com/products/bbedit/) + * [BBEdit Command-Line Tools](https://www.barebones.com/support/bbedit/cmd-line-tools.html) + +### Usage + + * If the `bb` command is called without an argument, launch BBEdit + + * If `bb` is passed a directory, cd to it and open it in BBEdit + + * If `bb` is passed a file, open it in BBEdit + + * If `bbpb` create a new BBEdit document with the contents of the clipboard + + * If `bbd` alias for BBEdit diff tool diff --git a/zsh/.oh-my-zsh/plugins/bbedit/bbedit.plugin.zsh b/zsh/.oh-my-zsh/plugins/bbedit/bbedit.plugin.zsh new file mode 100644 index 0000000..935c9c1 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bbedit/bbedit.plugin.zsh @@ -0,0 +1,21 @@ +alias bbpb='pbpaste | bbedit --clean --view-top' + +alias bbd=bbdiff + +# +# If the bb command is called without an argument, launch BBEdit +# If bb is passed a directory, cd to it and open it in BBEdit +# If bb is passed a file, open it in BBEdit +# +function bb() { + if [[ -z "$1" ]] + then + bbedit --launch + else + bbedit "$1" + if [[ -d "$1" ]] + then + cd "$1" + fi + fi +} diff --git a/zsh/.oh-my-zsh/plugins/bedtools/README.md b/zsh/.oh-my-zsh/plugins/bedtools/README.md new file mode 100644 index 0000000..179f2a6 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bedtools/README.md @@ -0,0 +1,5 @@ +# Bedtools plugin + +This plugin adds support for the [bedtools suite](http://bedtools.readthedocs.org/en/latest/): + +* Adds autocomplete options for all bedtools sub commands. diff --git a/zsh/.oh-my-zsh/plugins/bedtools/_bedtools b/zsh/.oh-my-zsh/plugins/bedtools/_bedtools new file mode 100644 index 0000000..b172134 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bedtools/_bedtools @@ -0,0 +1,64 @@ +#compdef bedtools +#autoload + +local curcontext="$curcontext" state line ret=1 +local -a _files + +_arguments -C \ + '1: :->cmds' \ + '2:: :->args' && ret=0 + +case $state in + cmds) + _values "bedtools command" \ + "--contact[Feature requests, bugs, mailing lists, etc.]" \ + "--help[Print this help menu.]" \ + "--version[What version of bedtools are you using?.]" \ + "annotate[Annotate coverage of features from multiple files.]" \ + "bamtobed[Convert BAM alignments to BED (& other) formats.]" \ + "bamtofastq[Convert BAM records to FASTQ records.]" \ + "bed12tobed6[Breaks BED12 intervals into discrete BED6 intervals.]" \ + "bedpetobam[Convert BEDPE intervals to BAM records.]" \ + "bedtobam[Convert intervals to BAM records.]" \ + "closest[Find the closest, potentially non-overlapping interval.]" \ + "cluster[Cluster (but don't merge) overlapping/nearby intervals.]" \ + "complement[Extract intervals _not_ represented by an interval file.]" \ + "coverage[Compute the coverage over defined intervals.]" \ + "expand[Replicate lines based on lists of values in columns.]" \ + "fisher[Calculate Fisher statistic b/w two feature files.]" \ + "flank[Create new intervals from the flanks of existing intervals.]" \ + "genomecov[Compute the coverage over an entire genome.]" \ + "getfasta[Use intervals to extract sequences from a FASTA file.]" \ + "groupby[Group by common cols. & summarize oth. cols. (~ SQL "groupBy")]" \ + "igv[Create an IGV snapshot batch script.]" \ + "intersect[Find overlapping intervals in various ways.]" \ + "jaccard[Calculate the Jaccard statistic b/w two sets of intervals.]" \ + "links[Create a HTML page of links to UCSC locations.]" \ + "makewindows[Make interval "windows" across a genome.]" \ + "map[Apply a function to a column for each overlapping interval.]" \ + "maskfasta[Use intervals to mask sequences from a FASTA file.]" \ + "merge[Combine overlapping/nearby intervals into a single interval.]" \ + "multicov[Counts coverage from multiple BAMs at specific intervals.]" \ + "multiinter[Identifies common intervals among multiple interval files.]" \ + "nuc[Profile the nucleotide content of intervals in a FASTA file.]" \ + "overlap[Computes the amount of overlap from two intervals.]" \ + "pairtobed[Find pairs that overlap intervals in various ways.]" \ + "pairtopair[Find pairs that overlap other pairs in various ways.]" \ + "random[Generate random intervals in a genome.]" \ + "reldist[Calculate the distribution of relative distances b/w two files.]" \ + "sample[Sample random records from file using reservoir sampling.]" \ + "shuffle[Randomly redistrubute intervals in a genome.]" \ + "slop[Adjust the size of intervals.]" \ + "sort[Order the intervals in a file.]" \ + "subtract[Remove intervals based on overlaps b/w two files.]" \ + "tag[Tag BAM alignments based on overlaps with interval files.]" \ + "unionbedg[Combines coverage intervals from multiple BEDGRAPH files.]" \ + "window[Find overlapping intervals within a window around an interval.]" \ + ret=0 + ;; + *) + _files + ;; +esac + +return ret diff --git a/zsh/.oh-my-zsh/plugins/bgnotify/README.md b/zsh/.oh-my-zsh/plugins/bgnotify/README.md new file mode 100644 index 0000000..8b33c51 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bgnotify/README.md @@ -0,0 +1,63 @@ +# bgnotify zsh plugin + +cross-platform background notifications for long running commands! Supports OSX and Linux. + +Standalone homepage: [t413/zsh-background-notify](https://github.com/t413/zsh-background-notify) + +--- + +## How to use + +Just add bgnotify to your plugins list in your `.zshrc` + +- On OS X you'll need [terminal-notifier](https://github.com/alloy/terminal-notifier) + * `brew install terminal-notifier` (or `gem install terminal-notifier`) +- On Linux, make sure you have `notify-send` or `kdialog` installed. If you're using Ubuntu you should already be all set! +- On Windows you can use [notifu](https://www.paralint.com/projects/notifu/) or the Cygwin Ports libnotify package + + +## Screenshots + +**Linux** + +![screenshot from 2014-11-07 15 58 36](https://cloud.githubusercontent.com/assets/326829/4962187/256b465c-66da-11e4-927d-cc2fc105e31f.png) + +**OS X** + +![screenshot 2014-11-08 14 15 12](https://cloud.githubusercontent.com/assets/326829/4965780/19fa3eac-6795-11e4-8ed6-0355711123a9.png) + +**Windows** + +![screenshot from 2014-11-07 15 55 00](https://cloud.githubusercontent.com/assets/326829/4962159/a2625ca0-66d9-11e4-9e91-c5834913190e.png) + + +## Configuration + +One can configure a few things: + +- `bgnotify_bell` enabled or disables the terminal bell (default true) +- `bgnotify_threshold` sets the notification threshold time (default 6 seconds) +- `function bgnotify_formatted` lets you change the notification. You can for instance customize the message and pass in an icon. + +Use these by adding a function definition before the your call to source. Example: + +```sh +bgnotify_bell=false ## disable terminal bell +bgnotify_threshold=4 ## set your own notification threshold + +function bgnotify_formatted { + ## $1=exit_status, $2=command, $3=elapsed_time + + # Humanly readable elapsed time + local elapsed="$(( $3 % 60 ))s" + (( $3 < 60 )) || elapsed="$((( $3 % 3600) / 60 ))m $elapsed" + (( $3 < 3600 )) || elapsed="$(( $3 / 3600 ))h $elapsed" + + [ $1 -eq 0 ] && title="Holy Smokes Batman" || title="Holy Graf Zeppelin" + [ $1 -eq 0 ] && icon="$HOME/icons/success.png" || icon="$HOME/icons/fail.png" + bgnotify "$title - took ${elapsed}" "$2" "$icon" +} + +plugins=(git bgnotify) ## add to plugins list +source $ZSH/oh-my-zsh.sh ## existing source call +``` diff --git a/zsh/.oh-my-zsh/plugins/bgnotify/bgnotify.plugin.zsh b/zsh/.oh-my-zsh/plugins/bgnotify/bgnotify.plugin.zsh new file mode 100644 index 0000000..1b8893d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bgnotify/bgnotify.plugin.zsh @@ -0,0 +1,141 @@ +#!/usr/bin/env zsh + +## Setup + +[[ -o interactive ]] || return # don't load on non-interactive shells +[[ -z "$SSH_CLIENT" && -z "$SSH_TTY" ]] || return # don't load on a SSH connection + +zmodload zsh/datetime # faster than `date` + + +## Zsh Hooks + +function bgnotify_begin { + bgnotify_timestamp=$EPOCHSECONDS + bgnotify_lastcmd="${1:-$2}" +} + +function bgnotify_end { + { + local exit_status=$? + local elapsed=$(( EPOCHSECONDS - bgnotify_timestamp )) + + # check time elapsed + [[ $bgnotify_timestamp -gt 0 ]] || return 0 + [[ $elapsed -ge $bgnotify_threshold ]] || return 0 + + # check if Terminal app is not active + [[ $(bgnotify_appid) != "$bgnotify_termid" ]] || return 0 + + bgnotify_formatted "$exit_status" "$bgnotify_lastcmd" "$elapsed" + } always { + bgnotify_timestamp=0 + } +} + +autoload -Uz add-zsh-hook +add-zsh-hook preexec bgnotify_begin +add-zsh-hook precmd bgnotify_end + + +## Functions + +# allow custom function override +(( ${+functions[bgnotify_formatted]} )) || \ +function bgnotify_formatted { + local exit_status=$1 + local cmd="$2" + + # humanly readable elapsed time + local elapsed="$(( $3 % 60 ))s" + (( $3 < 60 )) || elapsed="$((( $3 % 3600) / 60 ))m $elapsed" + (( $3 < 3600 )) || elapsed="$(( $3 / 3600 ))h $elapsed" + + [[ $bgnotify_bell = true ]] && printf '\a' # beep sound + if [[ $exit_status -eq 0 ]]; then + bgnotify "#win (took $elapsed)" "$cmd" + else + bgnotify "#fail (took $elapsed)" "$cmd" + fi +} + +function bgnotify_appid { + if (( ${+commands[osascript]} )); then + osascript -e "tell application id \"$(bgnotify_programid)\" to get the {id, frontmost, id of front window, visible of front window}" 2>/dev/null + elif [[ -n $WAYLAND_DISPLAY ]] && (( ${+commands[swaymsg]} )); then # wayland+sway + local app_id=$(bgnotify_find_sway_appid) + [[ -n "$app_id" ]] && echo "$app_id" || echo $EPOCHSECONDS + elif [[ -z $WAYLAND_DISPLAY ]] && [[ -n $DISPLAY ]] && (( ${+commands[xprop]} )); then + xprop -root _NET_ACTIVE_WINDOW 2>/dev/null | cut -d' ' -f5 + else + echo $EPOCHSECONDS + fi +} + + +function bgnotify_find_sway_appid { + # output is "app_id,container_id", for example "Alacritty,1694" + # see example swaymsg output: https://github.com/ohmyzsh/ohmyzsh/files/13463939/output.json + if (( ${+commands[jq]} )); then + swaymsg -t get_tree | jq '.. | select(.type?) | select(.focused==true) | {app_id, id} | join(",")' + else + swaymsg -t get_tree | awk ' + BEGIN { Id = ""; Appid = ""; FocusNesting = -1; Nesting = 0 } + { + # Enter a block + if ($0 ~ /.*{$/) Nesting++ + + # Exit a block. If Nesting is now less than FocusNesting, we have the data we are looking for + if ($0 ~ /^[[:blank:]]*}.*/) { Nesting--; if (FocusNesting > 0 && Nesting < FocusNesting) exit 0 } + + # Save the Id, it is potentially what we are looking for + if ($0 ~ /^[[:blank:]]*"id": [0-9]*,?$/) { sub(/^[[:blank:]]*"id": /, ""); sub(/,$/, ""); Id = $0 } + + # Save the Appid, it is potentially what we are looking for + if ($0 ~ /^[[:blank:]]*"app_id": ".*",?$/) { sub(/^[[:blank:]]*"app_id": "/, ""); sub(/",$/, ""); Appid = $0 } + + # Window is focused, this nesting block contains the Id and Appid we want! + if ($0 ~ /^[[:blank:]]*"focused": true,?$/) { FocusNesting = Nesting } + } + END { + if (Appid != "" && Id != "" && FocusNesting != -1) print Appid "," Id + else print "" + }' + fi +} + +function bgnotify_programid { + case "$TERM_PROGRAM" in + iTerm.app) echo 'com.googlecode.iterm2' ;; + Apple_Terminal) echo 'com.apple.terminal' ;; + esac +} + +function bgnotify { + local title="$1" + local message="$2" + local icon="$3" + if (( ${+commands[terminal-notifier]} )); then # macOS + local term_id=$(bgnotify_programid) + terminal-notifier -message "$message" -title "$title" ${=icon:+-appIcon "$icon"} ${=term_id:+-activate "$term_id"} &>/dev/null + elif (( ${+commands[growlnotify]} )); then # macOS growl + growlnotify -m "$title" "$message" + elif (( ${+commands[notify-send]} )); then + notify-send "$title" "$message" ${=icon:+--icon "$icon"} + elif (( ${+commands[kdialog]} )); then # KDE + kdialog --title "$title" --passivepopup "$message" 5 + elif (( ${+commands[notifu]} )); then # cygwin + notifu /m "$message" /p "$title" ${=icon:+/i "$icon"} + fi +} + +## Defaults + +# enable terminal bell on notify by default +bgnotify_bell=${bgnotify_bell:-true} + +# notify if command took longer than 5s by default +bgnotify_threshold=${bgnotify_threshold:-5} + +# bgnotify_appid is slow in macOS and the terminal ID won't change, so cache it at startup +bgnotify_termid="$(bgnotify_appid)" diff --git a/zsh/.oh-my-zsh/plugins/bower/README.md b/zsh/.oh-my-zsh/plugins/bower/README.md new file mode 100644 index 0000000..4c86216 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bower/README.md @@ -0,0 +1,17 @@ +# Bower plugin + +This plugin adds completion for [Bower](https://bower.io/) and a few useful aliases for common Bower commands. + +To use it, add `bower` to the plugins array in your zshrc file: + +```zsh +plugins=(... bower) +``` + +## Aliases + +| Alias | Command | Description | +|-------|-----------------|--------------------------------------------------------| +| bi | `bower install` | Installs the project dependencies listed in bower.json | +| bl | `bower list` | List local packages and possible updates | +| bs | `bower search` | Finds all packages or a specific package. | diff --git a/zsh/.oh-my-zsh/plugins/bower/_bower b/zsh/.oh-my-zsh/plugins/bower/_bower new file mode 100644 index 0000000..a7eeee4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bower/_bower @@ -0,0 +1,58 @@ + + +# Credits to npm's awesome completion utility. +# +# Bower completion script, based on npm completion script. + +###-begin-bower-completion-### +# +# Installation: bower completion >> ~/.bashrc (or ~/.zshrc) +# Or, maybe: bower completion > /usr/local/etc/bash_completion.d/bower +# + +COMP_WORDBREAKS=${COMP_WORDBREAKS/=/} +COMP_WORDBREAKS=${COMP_WORDBREAKS/@/} +export COMP_WORDBREAKS + +if type complete &>/dev/null; then + _bower_completion () { + local si="$IFS" + IFS=$'\n' COMPREPLY=($(COMP_CWORD="$COMP_CWORD" \ + COMP_LINE="$COMP_LINE" \ + COMP_POINT="$COMP_POINT" \ + bower completion -- "${COMP_WORDS[@]}" \ + 2>/dev/null)) || return $? + IFS="$si" + } + complete -F _bower_completion bower +elif type compdef &>/dev/null; then + _bower_completion() { + si=$IFS + compadd -- $(COMP_CWORD=$((CURRENT-1)) \ + COMP_LINE=$BUFFER \ + COMP_POINT=0 \ + bower completion -- "${words[@]}" \ + 2>/dev/null) + IFS=$si + } + compdef _bower_completion bower +elif type compctl &>/dev/null; then + _bower_completion () { + local cword line point words si + read -Ac words + read -cn cword + let cword-=1 + read -l line + read -ln point + si="$IFS" + IFS=$'\n' reply=($(COMP_CWORD="$cword" \ + COMP_LINE="$line" \ + COMP_POINT="$point" \ + bower completion -- "${words[@]}" \ + 2>/dev/null)) || return $? + IFS="$si" + } + compctl -K _bower_completion bower +fi +###-end-bower-completion-### + diff --git a/zsh/.oh-my-zsh/plugins/bower/bower.plugin.zsh b/zsh/.oh-my-zsh/plugins/bower/bower.plugin.zsh new file mode 100644 index 0000000..a6efafc --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bower/bower.plugin.zsh @@ -0,0 +1,84 @@ +alias bi="bower install" +alias bisd="bower install --save-dev" +alias bis="bower install --save" +alias bl="bower list" +alias bs="bower search" + +_bower_installed_packages () { + bower_package_list=$(bower ls --no-color 2>/dev/null| awk 'NR>3{print p}{p=$0}'| cut -d ' ' -f 2|sed 's/#.*//') +} +_bower () +{ + local -a _1st_arguments _no_color _dopts _save_dev _force_latest _production + local expl + typeset -A opt_args + + _no_color=('--no-color[Do not print colors (available in all commands)]') + + _dopts=( + '(--save)--save[Save installed packages into the project"s bower.json dependencies]' + '(--force)--force[Force fetching remote resources even if a local copy exists on disk]' + ) + + _save_dev=('(--save-dev)--save-dev[Save installed packages into the project"s bower.json devDependencies]') + + _force_latest=('(--force-latest)--force-latest[Force latest version on conflict]') + + _production=('(--production)--production[Do not install project devDependencies]') + + _1st_arguments=( + 'cache-clean:Clean the Bower cache, or the specified package caches' \ + 'help:Display help information about Bower' \ + 'info:Version info and description of a particular package' \ + 'init:Interactively create a bower.json file' \ + 'install:Install a package locally' \ + 'link:Symlink a package folder' \ + 'lookup:Look up a package URL by name' \ + 'register:Register a package' \ + 'search:Search for a package by name' \ + 'uninstall:Remove a package' \ + 'update:Update a package' \ + {ls,list}:'[List all installed packages]' + ) + _arguments \ + $_no_color \ + '*:: :->subcmds' && return 0 + + if (( CURRENT == 1 )); then + _describe -t commands "bower subcommand" _1st_arguments + return + fi + + case "$words[1]" in + install) + _arguments \ + $_dopts \ + $_save_dev \ + $_force_latest \ + $_no_color \ + $_production + ;; + update) + _arguments \ + $_dopts \ + $_no_color \ + $_force_latest + _bower_installed_packages + compadd "$@" $(echo $bower_package_list) + ;; + uninstall) + _arguments \ + $_no_color \ + $_dopts + _bower_installed_packages + compadd "$@" $(echo $bower_package_list) + ;; + *) + _arguments \ + $_no_color \ + ;; + esac + +} + +compdef _bower bower diff --git a/zsh/.oh-my-zsh/plugins/branch/README.md b/zsh/.oh-my-zsh/plugins/branch/README.md new file mode 100644 index 0000000..94dd458 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/branch/README.md @@ -0,0 +1,49 @@ +# Branch plugin + +This plugin displays the current Git or Mercurial branch, fast. If in a Mercurial repository, +also display the current bookmark, if present. + +To use it, add `branch` to the plugins array in your zshrc file: + +```zsh +plugins=(... branch) +``` + +## Speed test + +- `hg branch`: + + ```console + $ time hg branch + 0.11s user 0.14s system 70% cpu 0.355 total + ``` + +- branch plugin: + + ```console + $ time zsh /tmp/branch_prompt_info_test.zsh + 0.00s user 0.01s system 78% cpu 0.014 total + ``` + +## Usage + +Copy your theme to `$ZSH_CUSTOM/themes/` and modify it to add `$(branch_prompt_info)` in your prompt. +This example is for the `robbyrussell` theme: + +```diff +diff --git a/themes/robbyrussell.zsh-theme b/themes/robbyrussell.zsh-theme +index 2fd5f2cd..9d89a464 100644 +--- a/themes/robbyrussell.zsh-theme ++++ b/themes/robbyrussell.zsh-theme +@@ -1,5 +1,5 @@ + PROMPT="%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ )" +-PROMPT+=' %{$fg[cyan]%}%c%{$reset_color%} $(git_prompt_info)' ++PROMPT+=' %{$fg[cyan]%}%c%{$reset_color%} $(branch_prompt_info)' + + ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[blue]%}git:(%{$fg[red]%}" + ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} " +``` + +## Maintainer + +Victor Torres () diff --git a/zsh/.oh-my-zsh/plugins/branch/branch.plugin.zsh b/zsh/.oh-my-zsh/plugins/branch/branch.plugin.zsh new file mode 100644 index 0000000..e1c51f9 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/branch/branch.plugin.zsh @@ -0,0 +1,35 @@ +# Branch: displays the current Git or Mercurial branch fast. +# Victor Torres +# Oct 2, 2015 + +function branch_prompt_info() { + # Start checking in current working directory + local branch="" dir="$PWD" + while [[ "$dir" != '/' ]]; do + # Found .git directory + if [[ -d "${dir}/.git" ]]; then + branch="${"$(<"${dir}/.git/HEAD")"##*/}" + echo '±' "${branch:gs/%/%%}" + return + fi + + # Found .hg directory + if [[ -d "${dir}/.hg" ]]; then + if [[ -f "${dir}/.hg/branch" ]]; then + branch="$(<"${dir}/.hg/branch")" + else + branch="default" + fi + + if [[ -f "${dir}/.hg/bookmarks.current" ]]; then + branch="${branch}/$(<"${dir}/.hg/bookmarks.current")" + fi + + echo '☿' "${branch:gs/%/%%}" + return + fi + + # Check parent directory + dir="${dir:h}" + done +} diff --git a/zsh/.oh-my-zsh/plugins/brew/README.md b/zsh/.oh-my-zsh/plugins/brew/README.md new file mode 100644 index 0000000..a5da99d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/brew/README.md @@ -0,0 +1,43 @@ +# brew plugin + +The plugin adds several aliases for common [brew](https://brew.sh) commands. + +To use it, add `brew` to the plugins array of your zshrc file: + +```zsh +plugins=(... brew) +``` + +## Shellenv + +If `brew` is not found in the PATH, this plugin will attempt to find it in common locations, and execute +`brew shellenv` to set the environment appropriately. This plugin will also export +`HOMEBREW_PREFIX="$(brew --prefix)"` if not previously defined for convenience. + +In case you installed `brew` in a non-common location, you can still set `BREW_LOCATION` variable pointing to +the `brew` binary before sourcing `oh-my-zsh.sh` and it'll set up the environment. + +## Aliases + +| Alias | Command | Description | +| -------- | --------------------------------------- | ------------------------------------------------------------------- | +| `bcubc` | `brew upgrade --cask && brew cleanup` | Update outdated casks, then run cleanup. | +| `bcubo` | `brew update && brew outdated --cask` | Update Homebrew data, then list outdated casks. | +| `brewp` | `brew pin` | Pin a specified formula so that it's not upgraded. | +| `brews` | `brew list -1` | List installed formulae or the installed files for a given formula. | +| `brewsp` | `brew list --pinned` | List pinned formulae, or show the version of a given formula. | +| `bubc` | `brew upgrade && brew cleanup` | Upgrade outdated formulae and casks, then run cleanup. | +| `bugbc` | `brew upgrade --greedy && brew cleanup` | Upgrade outdated formulae and casks (greedy), then run cleanup. | +| `bubo` | `brew update && brew outdated` | Update Homebrew data, then list outdated formulae and casks. | +| `bubu` | `bubo && bubc` | Do the last two operations above. | +| `bfu` | `brew upgrade --formula` | Upgrade only formulas (not casks). | +| `buz` | `brew uninstall --zap` | Remove all files associated with a cask. | + +## Completion + +This plugin configures paths with Homebrew's completion functions automatically, so you don't need to do it +manually. See: https://docs.brew.sh/Shell-Completion#configuring-completions-in-zsh. + +With the release of Homebrew 1.0, they decided to bundle the zsh completion as part of the brew installation, +so we no longer ship it with the brew plugin; now it only has brew aliases. If you find that brew completion +no longer works, make sure you have your Homebrew installation fully up to date. diff --git a/zsh/.oh-my-zsh/plugins/brew/brew.plugin.zsh b/zsh/.oh-my-zsh/plugins/brew/brew.plugin.zsh new file mode 100644 index 0000000..e7f3572 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/brew/brew.plugin.zsh @@ -0,0 +1,60 @@ +if (( ! $+commands[brew] )); then + if [[ -n "$BREW_LOCATION" ]]; then + if [[ ! -x "$BREW_LOCATION" ]]; then + echo "[oh-my-zsh] $BREW_LOCATION is not executable" + return + fi + elif [[ -x /opt/homebrew/bin/brew ]]; then + BREW_LOCATION="/opt/homebrew/bin/brew" + elif [[ -x /usr/local/bin/brew ]]; then + BREW_LOCATION="/usr/local/bin/brew" + elif [[ -x /home/linuxbrew/.linuxbrew/bin/brew ]]; then + BREW_LOCATION="/home/linuxbrew/.linuxbrew/bin/brew" + elif [[ -x "$HOME/.linuxbrew/bin/brew" ]]; then + BREW_LOCATION="$HOME/.linuxbrew/bin/brew" + else + return + fi + + # Only add Homebrew installation to PATH, MANPATH, and INFOPATH if brew is + # not already on the path, to prevent duplicate entries. This aligns with + # the behavior of the brew installer.sh post-install steps. + eval "$("$BREW_LOCATION" shellenv)" + unset BREW_LOCATION +fi + +if [[ -z "$HOMEBREW_PREFIX" ]]; then + # Maintain compatability with potential custom user profiles, where we had + # previously relied on always sourcing shellenv. OMZ plugins should not rely + # on this to be defined due to out of order processing. + export HOMEBREW_PREFIX="$(brew --prefix)" +fi + +if [[ -d "$HOMEBREW_PREFIX/share/zsh/site-functions" ]]; then + fpath+=("$HOMEBREW_PREFIX/share/zsh/site-functions") +fi + +alias bcubc='brew upgrade --cask && brew cleanup' +alias bcubo='brew update && brew outdated --cask' +alias brewp='brew pin' +alias brewsp='brew list --pinned' +alias bubc='brew upgrade && brew cleanup' +alias bugbc='brew upgrade --greedy && brew cleanup' +alias bubo='brew update && brew outdated' +alias bubu='bubo && bubc' +alias bubug='bubo && bugbc' +alias bfu='brew upgrade --formula' +alias buz='brew uninstall --zap' + +function brews() { + local formulae="$(brew leaves | xargs brew deps --installed --for-each)" + local casks="$(brew list --cask 2>/dev/null)" + + local blue="$(tput setaf 4)" + local bold="$(tput bold)" + local off="$(tput sgr0)" + + echo "${blue}==>${off} ${bold}Formulae${off}" + echo "${formulae}" | sed "s/^\(.*\):\(.*\)$/\1${blue}\2${off}/" + echo "\n${blue}==>${off} ${bold}Casks${off}\n${casks}" +} diff --git a/zsh/.oh-my-zsh/plugins/bridgetown/README.md b/zsh/.oh-my-zsh/plugins/bridgetown/README.md new file mode 100644 index 0000000..2fdbd53 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bridgetown/README.md @@ -0,0 +1,26 @@ +# Bridgetown plugin + +This plugin adds some aliases and autocompletion for common [Bridgetown](https://bridgetownrb.com/) commands. + +To use it, add `bridgetown` to the plugins array in your zshrc file: + +```zsh +plugins=(... bridgetown) +``` + +## Aliases + +| Alias | Command | +|-------|----------------------------| +| br | `bridgetown` | +| bra | `bin/bridgetown apply` | +| brb | `bin/bridgetown build` | +| brc | `bin/bridgetown console` | +| brclean | `bin/bridgetown clean` | +| brd | `bin/bridgetown deploy` | +| brdoc | `bin/bridgetown doctor` | +| brh | `bin/bridgetown help` | +| brn | `bridgetown new` | +| brp | `bridgetown plugins` | +| brpl | `bridgetown plugins list` | +| brs | `bin/bridgetown start` | diff --git a/zsh/.oh-my-zsh/plugins/bridgetown/bridgetown.plugin.zsh b/zsh/.oh-my-zsh/plugins/bridgetown/bridgetown.plugin.zsh new file mode 100644 index 0000000..ae309d0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bridgetown/bridgetown.plugin.zsh @@ -0,0 +1,12 @@ +alias br='bridgetown' +alias bra='bin/bridgetown apply' +alias brb='bin/bridgetown build' +alias brc='bin/bridgetown console' +alias brclean='bin/bridgetown clean' +alias brd='bin/bridgetown deploy' +alias brdoc='bin/bridgetown doctor' +alias brh='bin/bridgetown help' +alias brn='bridgetown new' +alias brp='bridgetown plugins' +alias brpl='bridgetown plugins list' +alias brs='bin/bridgetown start' diff --git a/zsh/.oh-my-zsh/plugins/bun/README.md b/zsh/.oh-my-zsh/plugins/bun/README.md new file mode 100644 index 0000000..92f7330 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bun/README.md @@ -0,0 +1,20 @@ +# Bun Plugin + +This plugin sets up completion for [Bun](https://bun.sh). + +To use it, add `bun` to the plugins array in your zshrc file: + +```zsh +plugins=(... bun) +``` + +This plugin does not add any aliases. + +## Cache + +This plugin caches the completion script and is automatically updated when the +plugin is loaded, which is usually when you start up a new terminal emulator. + +The cache is stored at: + +- `$ZSH_CACHE_DIR/completions/_bun_` completions script diff --git a/zsh/.oh-my-zsh/plugins/bun/bun.plugin.zsh b/zsh/.oh-my-zsh/plugins/bun/bun.plugin.zsh new file mode 100644 index 0000000..5bcde15 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bun/bun.plugin.zsh @@ -0,0 +1,14 @@ +# If Bun is not found, don't do the rest of the script +if (( ! $+commands[bun] )); then + return +fi + +# If the completion file doesn't exist yet, we need to autoload it and +# bind it to `bun`. Otherwise, compinit will have already done that. +if [[ ! -f "$ZSH_CACHE_DIR/completions/_bun" ]]; then + typeset -g -A _comps + autoload -Uz _bun + _comps[bun]=_bun +fi + +bun completions >| "$ZSH_CACHE_DIR/completions/_bun" &| diff --git a/zsh/.oh-my-zsh/plugins/bundler/README.md b/zsh/.oh-my-zsh/plugins/bundler/README.md new file mode 100644 index 0000000..0b74e70 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bundler/README.md @@ -0,0 +1,74 @@ +# Bundler + +This plugin adds completion for basic bundler commands, as well as aliases and helper functions for +an easier experience with bundler. + +To use it, add `bundler` to the plugins array in your zshrc file: + +```zsh +plugins=(... bundler) +``` + +## Aliases + +| Alias | Command | Description | +|--------|--------------------------------------|------------------------------------------------------------------------------------------| +| `ba` | `bundle add` | Add gem to the Gemfile and run bundle install | +| `bck` | `bundle check` | Verifies if dependencies are satisfied by installed gems | +| `bcn` | `bundle clean` | Cleans up unused gems in your bundler directory | +| `be` | `bundle exec` | Execute a command in the context of the bundle | +| `bi` | `bundle install --jobs=` | Install the dependencies specified in your Gemfile (using all cores in bundler >= 1.4.0) | +| `bl` | `bundle list` | List all the gems in the bundle | +| `bo` | `bundle open` | Opens the source directory for a gem in your bundle | +| `bout` | `bundle outdated` | List installed gems with newer versions available | +| `bp` | `bundle package` | Package your needed .gem files into your application | +| `bu` | `bundle update` | Update your gems to the latest available versions | + +## Gem wrapper + +The plugin adds a wrapper for common gems, which: + +- Looks for a binstub under `./bin/` and executes it if present. +- Calls `bundle exec ` otherwise. + +Common gems wrapped by default (by name of the executable): + +`annotate`, `cap`, `capify`, `cucumber`, `foodcritic`, `guard`, `hanami`, `irb`, `jekyll`, `kitchen`, `knife`, `middleman`, `nanoc`, `pry`, `puma`, `rackup`, `rainbows`, `rake`, `rspec`, `rubocop`, `shotgun`, `sidekiq`, `spec`, `spork`, `spring`, `strainer`, `tailor`, `taps`, `thin`, `thor`, `unicorn` and `unicorn_rails`. + +### Settings + +You can add or remove gems from the list of wrapped commands. +Please **use the exact name of the executable** and not the gem name. + +#### Include gems to be wrapped (`BUNDLED_COMMANDS`) + +Add this before the plugin list in your `.zshrc`: + +```sh +BUNDLED_COMMANDS=(rubocop) +plugins=(... bundler ...) +``` + +This will add the wrapper for the `rubocop` gem (i.e. the executable). + +#### Exclude gems from being wrapped (`UNBUNDLED_COMMANDS`) + +Add this before the plugin list in your `.zshrc`: + +```sh +UNBUNDLED_COMMANDS=(foreman spin) +plugins=(... bundler ...) +``` + +This will exclude the `foreman` and `spin` gems (i.e. their executable) from being wrapped. + +### Excluded gems + +These gems should not be called with `bundle exec`. Please see [issue #2923](https://github.com/ohmyzsh/ohmyzsh/pull/2923) on GitHub for clarification: + +- `berks` +- `foreman` +- `mailcatcher` +- `rails` +- `ruby` +- `spin` diff --git a/zsh/.oh-my-zsh/plugins/bundler/_bundler b/zsh/.oh-my-zsh/plugins/bundler/_bundler new file mode 100644 index 0000000..3d6637c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bundler/_bundler @@ -0,0 +1,105 @@ +#compdef bundle bundler + +local curcontext="$curcontext" state line _gems _opts ret=1 + +_arguments -C -A "-v" -A "--version" \ + '(- 1 *)'{-v,--version}'[display version information]' \ + '1: :->cmds' \ + '*:: :->args' && ret=0 + +case $state in + cmds) + _values "bundle command" \ + "install[Install the gems specified by the Gemfile or Gemfile.lock]" \ + "update[Update dependencies to their latest versions]" \ + "package[Package the .gem files required by your application]" \ + "exec[Execute a script in the context of the current bundle]" \ + "config[Specify and read configuration options for bundler]" \ + "check[Determine whether the requirements for your application are installed]" \ + "list[Show all of the gems in the current bundle]" \ + "show[Show the source location of a particular gem in the bundle]" \ + "info[Show details of a particular gem in the bundle]" \ + "outdated[Show all of the outdated gems in the current bundle]" \ + "console[Start an IRB session in the context of the current bundle]" \ + "open[Open an installed gem in the editor]" \ + "viz[Generate a visual representation of your dependencies]" \ + "init[Generate a simple Gemfile, placed in the current directory]" \ + "gem[Create a simple gem, suitable for development with bundler]" \ + "platform[Displays platform compatibility information]" \ + "clean[Cleans up unused gems in your bundler directory]" \ + "help[Describe available tasks or one specific task]" + ret=0 + ;; + args) + case $line[1] in + help) + _values 'commands' \ + 'install' \ + 'update' \ + 'package' \ + 'exec' \ + 'config' \ + 'check' \ + 'list' \ + 'show' \ + 'outdated' \ + 'console' \ + 'open' \ + 'viz' \ + 'init' \ + 'gem' \ + 'platform' \ + 'help' && ret=0 + ;; + install) + _arguments \ + '(--no-color)--no-color[disable colorization in output]' \ + '(--local)--local[do not attempt to connect to rubygems.org]' \ + '(--quiet)--quiet[only output warnings and errors]' \ + '(--gemfile)--gemfile=-[use the specified gemfile instead of Gemfile]:gemfile' \ + '(--system)--system[install to the system location]' \ + '(--deployment)--deployment[install using defaults tuned for deployment environments]' \ + '(--frozen)--frozen[do not allow the Gemfile.lock to be updated after this install]' \ + '(--path)--path=-[specify a different path than the system default]:path:_files' \ + '(--binstubs)--binstubs=-[generate bin stubs for bundled gems to ./bin]:directory:_files' \ + '(--without)--without=-[exclude gems that are part of the specified named group]:groups' + ret=0 + ;; + exec) + _normal && ret=0 + ;; + clean) + _arguments \ + '(--force)--force[forces clean even if --path is not set]' \ + '(--dry-run)--dry-run[only print out changes, do not actually clean gems]' \ + '(--no-color)--no-color[Disable colorization in output]' \ + '(--verbose)--verbose[Enable verbose output mode]' + ret=0 + ;; + outdated) + _arguments \ + '(--pre)--pre[Check for newer pre-release gems]' \ + '(--source)--source[Check against a specific source]' \ + '(--local)--local[Do not attempt to fetch gems remotely and use the gem cache instead]' \ + '(--no-color)--no-color[Disable colorization in output]' \ + '(--verbose)--verbose[Enable verbose output mode]' + ret=0 + ;; + (open|show|info) + _gems=( $(bundle show 2> /dev/null | sed -e '/^ \*/!d; s/^ \* \([^ ]*\) .*/\1/') ) + if [[ $_gems != "" ]]; then + _values 'gems' $_gems && ret=0 + fi + ;; + *) + _opts=( $(bundle help $line[1] | sed -e '/^ \[-/!d; s/^ \[\(-[^=]*\)=.*/\1/') ) + _opts+=( $(bundle help $line[1] | sed -e '/^ -/!d; s/^ \(-.\), \[\(-[^=]*\)=.*/\1 \2/') ) + if [[ $_opts != "" ]]; then + _values 'options' $_opts && ret=0 + fi + ;; + esac + ;; +esac + +return ret diff --git a/zsh/.oh-my-zsh/plugins/bundler/bundler.plugin.zsh b/zsh/.oh-my-zsh/plugins/bundler/bundler.plugin.zsh new file mode 100644 index 0000000..3198f6e --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/bundler/bundler.plugin.zsh @@ -0,0 +1,127 @@ +## Aliases + +alias ba="bundle add" +alias bck="bundle check" +alias bcn="bundle clean" +alias be="bundle exec" +alias bi="bundle_install" +alias bl="bundle list" +alias bo="bundle open" +alias bout="bundle outdated" +alias bp="bundle package" +alias bu="bundle update" + +## Functions + +bundle_install() { + # Bail out if bundler is not installed + if (( ! $+commands[bundle] )); then + echo "Bundler is not installed" + return 1 + fi + + # Bail out if not in a bundled project + if ! _within-bundled-project; then + echo "Can't 'bundle install' outside a bundled project" + return 1 + fi + + # Check the bundler version is at least 1.4.0 + autoload -Uz is-at-least + local bundler_version=$(bundle version | cut -d' ' -f3) + if ! is-at-least 1.4.0 "$bundler_version"; then + bundle install "$@" + return $? + fi + + # If bundler is at least 1.4.0, use all the CPU cores to bundle install + if [[ "$OSTYPE" = (darwin|freebsd)* ]]; then + local cores_num="$(sysctl -n hw.ncpu)" + else + local cores_num="$(nproc)" + fi + BUNDLE_JOBS="$cores_num" bundle install "$@" +} + +## Gem wrapper + +bundled_commands=( + annotate + cap + capify + cucumber + foodcritic + guard + hanami + irb + jekyll + kitchen + knife + middleman + nanoc + pry + puma + rackup + rainbows + rake + rspec + rubocop + shotgun + sidekiq + spec + spork + spring + strainer + tailor + taps + thin + thor + unicorn + unicorn_rails +) + +# Remove $UNBUNDLED_COMMANDS from the bundled_commands list +bundled_commands=(${bundled_commands:|UNBUNDLED_COMMANDS}) +unset UNBUNDLED_COMMANDS + +# Add $BUNDLED_COMMANDS to the bundled_commands list +bundled_commands+=($BUNDLED_COMMANDS) +unset BUNDLED_COMMANDS + +# Check if in the root or a subdirectory of a bundled project +_within-bundled-project() { + local check_dir="$PWD" + while [[ "$check_dir" != "/" ]]; do + if [[ -f "$check_dir/Gemfile" || -f "$check_dir/gems.rb" ]]; then + return 0 + fi + check_dir="${check_dir:h}" + done + return 1 +} + +_run-with-bundler() { + if (( ! $+commands[bundle] )) || ! _within-bundled-project; then + "$@" + return $? + fi + + if [[ -f "./bin/${1}" ]]; then + ./bin/${^^@} + else + bundle exec "$@" + fi +} + +for cmd in $bundled_commands; do + # Create wrappers for bundled and unbundled execution + eval "function unbundled_$cmd () { \"$cmd\" \"\$@\"; }" + eval "function bundled_$cmd () { _run-with-bundler \"$cmd\" \"\$@\"; }" + alias "$cmd"="bundled_$cmd" + + # Bind completion function to wrapped gem if available + if (( $+functions[_$cmd] )); then + compdef "_$cmd" "bundled_$cmd"="$cmd" + fi +done +unset cmd bundled_commands diff --git a/zsh/.oh-my-zsh/plugins/cabal/README.md b/zsh/.oh-my-zsh/plugins/cabal/README.md new file mode 100644 index 0000000..ec492b4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cabal/README.md @@ -0,0 +1,9 @@ +# Cabal + +This plugin provides completion for [Cabal](https://www.haskell.org/cabal/), a build tool for Haskell. It +also provides a function `cabal_sandbox_info` that prints whether the current working directory is in a sandbox. + +To use it, add cabal to the plugins array of your zshrc file: +``` +plugins=(... cabal) +``` diff --git a/zsh/.oh-my-zsh/plugins/cabal/cabal.plugin.zsh b/zsh/.oh-my-zsh/plugins/cabal/cabal.plugin.zsh new file mode 100644 index 0000000..0a99027 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cabal/cabal.plugin.zsh @@ -0,0 +1,93 @@ +function cabal_sandbox_info() { + cabal_files=(*.cabal(N)) + if [ $#cabal_files -gt 0 ]; then + if [ -f cabal.sandbox.config ]; then + echo "%{$fg[green]%}sandboxed%{$reset_color%}" + else + echo "%{$fg[red]%}not sandboxed%{$reset_color%}" + fi + fi +} + +function _cabal_commands() { + local ret=1 state + _arguments ':subcommand:->subcommand' && ret=0 + + case $state in + subcommand) + subcommands=( + "bench:Run the benchmark, if any (configure with UserHooks)" + "build:Compile all targets or specific target." + "check:Check the package for common mistakes" + "clean:Clean up after a build" + "copy:Copy the files into the install locations" + "configure:Prepare to build the package" + "exec:Run a command with the cabal environment" + "fetch:Downloads packages for later installation" + "freeze:Freeze dependencies." + "get:Gets a package's source code" + "haddock:Generate Haddock HTML documentation" + "help:Help about commands" + "hscolour:Generate HsColour colourised code, in HTML format" + "info:Display detailed information about a particular package" + "init:Interactively create a .cabal file" + "install:Installs a list of packages" + "list:List packages matching a search string" + "register:Register this package with the compiler" + "repl:Open an interpreter session for the given target" + "report:Upload build reports to a remote server" + "run:Runs the compiled executable" + "sandbox:Create/modify/delete a sandbox" + "sdist:Generate a source distribution file (.tar.gz)" + "test:Run the test suite, if any (configure with UserHooks)" + "unpack:Unpacks packages for user inspection" + "update:Updates list of known packages" + "upload:Uploads source packages to Hackage" + ) + _describe -t subcommands 'cabal subcommands' subcommands && ret=0 + esac + + return ret +} + +compdef _cabal_commands cabal + +function _cab_commands() { + local ret=1 state + _arguments ':subcommand:->subcommand' && ret=0 + + case $state in + subcommand) + subcommands=( + "sync:Fetch the latest package index" + "install:Install packages" + "uninstall:Uninstall packages" + "installed:List installed packages" + "configure:Configure a cabal package" + "build:Build a cabal package" + "clean:Clean up a build directory" + "outdated:Display outdated packages" + "info:Display information of a package" + "sdist:Make tar.gz for source distribution" + "upload:Uploading tar.gz to HackageDB" + "get:Untar a package in the current directory" + "deps:Show dependencies of this package" + "revdeps:Show reverse dependencies of this package" + "check:Check consistency of packages" + "genpaths:Generate Paths_.hs" + "search:Search available packages by package name" + "add:Add a source directory" + "test:Run tests" + "bench:Run benchmarks" + "doc:Generate manuals" + "ghci:Run GHCi (with a sandbox)" + "init:Initialize a sandbox" + "help:Display the help message of the command" + ) + _describe -t subcommands 'cab subcommands' subcommands && ret=0 + esac + + return ret +} + +command -v cab >/dev/null 2>&1 && { compdef _cab_commands cab } diff --git a/zsh/.oh-my-zsh/plugins/cake/README.md b/zsh/.oh-my-zsh/plugins/cake/README.md new file mode 100644 index 0000000..6d0b2d2 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cake/README.md @@ -0,0 +1,15 @@ +# Cake + +This plugin provides completion for [CakePHP](https://cakephp.org/). + +To use it add cake to the plugins array in your zshrc file. + +```bash +plugins=(... cake) +``` + +## Note + +This plugin generates a cache file of the cake tasks found, named `.cake_task_cache`, in the current working directory. +It is regenerated when the Cakefile is newer than the cache file. It is advised that you add the cake file to your +`.gitignore` files. diff --git a/zsh/.oh-my-zsh/plugins/cake/cake.plugin.zsh b/zsh/.oh-my-zsh/plugins/cake/cake.plugin.zsh new file mode 100644 index 0000000..82d854e --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cake/cake.plugin.zsh @@ -0,0 +1,33 @@ +# Set this to 1 if you want to cache the tasks +_cake_cache_task_list=1 + +# Cache filename +_cake_task_cache_file='.cake_task_cache' + +_cake_get_target_list () { + cake | grep '^cake ' | sed -e "s/cake \([^ ]*\) .*/\1/" | grep -v '^$' +} + +_cake_does_target_list_need_generating () { + + if [ ${_cake_cache_task_list} -eq 0 ]; then + return 1; + fi + + [ ! -f ${_cake_task_cache_file} ] && return 0; + [ Cakefile -nt ${_cake_task_cache_file} ] && return 0; + return 1; +} + +_cake () { + if [ -f Cakefile ]; then + if _cake_does_target_list_need_generating; then + _cake_get_target_list > ${_cake_task_cache_file} + compadd `cat ${_cake_task_cache_file}` + else + compadd `_cake_get_target_list` + fi + fi +} + +compdef _cake cake diff --git a/zsh/.oh-my-zsh/plugins/cakephp3/README.md b/zsh/.oh-my-zsh/plugins/cakephp3/README.md new file mode 100644 index 0000000..dd5697a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cakephp3/README.md @@ -0,0 +1,16 @@ +# cakephp3 plugin + +The plugin adds aliases and autocompletion for [cakephp3](https://book.cakephp.org/3.0/en/index.html). + +To use it, add `cakephp3` to the plugins array of your zshrc file: +``` +plugins=(... cakephp3) +``` + +## Aliases + +| Alias | Command | +|-----------|-------------------------------| +| c3 | `bin/cake` | +| c3cache | `bin/cake orm_cache clear` | +| c3migrate | `bin/cake migrations migrate` | diff --git a/zsh/.oh-my-zsh/plugins/cakephp3/cakephp3.plugin.zsh b/zsh/.oh-my-zsh/plugins/cakephp3/cakephp3.plugin.zsh new file mode 100644 index 0000000..1b2c210 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cakephp3/cakephp3.plugin.zsh @@ -0,0 +1,38 @@ +# CakePHP 3 basic command completion +_cakephp3_get_command_list () { + bin/cake completion commands +} + +_cakephp3_get_sub_command_list () { + bin/cake completion subcommands ${words[2]} +} + +_cakephp3_get_3rd_argument () { + bin/cake ${words[2]} ${words[3]} | \grep '\-\ '| \awk '{print $2}' +} + +_cakephp3 () { + local -a has3rdargument + has3rdargument=("all" "controller" "fixture" "model" "template") + if [ -f bin/cake ]; then + if (( CURRENT == 2 )); then + compadd $(_cakephp3_get_command_list) + fi + if (( CURRENT == 3 )); then + compadd $(_cakephp3_get_sub_command_list) + fi + if (( CURRENT == 4 )); then + if [[ ${has3rdargument[(i)${words[3]}]} -le ${#has3rdargument} ]]; then + compadd $(_cakephp3_get_3rd_argument) + fi + fi + fi +} + +compdef _cakephp3 bin/cake +compdef _cakephp3 cake + +#Alias +alias c3='bin/cake' +alias c3cache='bin/cake schema_cache clear' +alias c3migrate='bin/cake migrations migrate' diff --git a/zsh/.oh-my-zsh/plugins/capistrano/README.md b/zsh/.oh-my-zsh/plugins/capistrano/README.md new file mode 100644 index 0000000..9ec3cdf --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/capistrano/README.md @@ -0,0 +1,14 @@ +# Capistrano + +This plugin provides completion for [Capistrano](https://capistranorb.com/). + +To use it add capistrano to the plugins array in your zshrc file. + +```bash +plugins=(... capistrano) +``` + +For a working completion use the `capit` command instead of `cap`, because cap is a +[reserved word in zsh](http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fcap-Module). + +`capit` automatically runs cap with bundler if a Gemfile is found. diff --git a/zsh/.oh-my-zsh/plugins/capistrano/_capistrano b/zsh/.oh-my-zsh/plugins/capistrano/_capistrano new file mode 100644 index 0000000..b9e9bcc --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/capistrano/_capistrano @@ -0,0 +1,49 @@ +#compdef capit +#autoload + +# Added `capit` because `cap` is a reserved word. `cap` completion doesn't work. +# http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fcap-Module + +local curcontext="$curcontext" state line ret=1 +local -a _configs + +_arguments -C \ + '1: :->cmds' \ + '2:: :->args' && ret=0 + +_cap_tasks() { + if [[ -f config/deploy.rb || -f Capfile ]]; then + if [[ ! -f .cap_tasks~ ]]; then + capit --tasks | sed 's/\(\[\)\(.*\)\(\]\)/\2:/' | awk '{command=$2; $1=$2=$3=""; gsub(/^[ \t\r\n]+/, "", $0); gsub(":", "\\:", command); print command"["$0"]"}' > .cap_tasks~ + fi + + OLD_IFS=$IFS + IFS=$'\n' + _values 'cap commands' $(< .cap_tasks~) + IFS=$OLD_IFS + # zmodload zsh/mapfile + # _values ${(f)mapfile[.cap_tasks~]} + fi +} + +_cap_stages() { + compadd $(find config/deploy -name \*.rb | cut -d/ -f3 | sed s:.rb::g) +} + +case $state in + cmds) + # check if it uses multistage + if [[ -d config/deploy ]]; then + _cap_stages + else + _cap_tasks + fi + ret=0 + ;; + args) + _cap_tasks + ret=0 + ;; +esac + +return ret diff --git a/zsh/.oh-my-zsh/plugins/capistrano/capistrano.plugin.zsh b/zsh/.oh-my-zsh/plugins/capistrano/capistrano.plugin.zsh new file mode 100644 index 0000000..afc4684 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/capistrano/capistrano.plugin.zsh @@ -0,0 +1,11 @@ +# Added `capit` because `cap` is a reserved word. `cap` completion doesn't work. +# http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fcap-Module + +function capit() { + if [ -f Gemfile ] + then + bundle exec cap $* + else + cap $* + fi +} diff --git a/zsh/.oh-my-zsh/plugins/cask/README.md b/zsh/.oh-my-zsh/plugins/cask/README.md new file mode 100644 index 0000000..45b19ca --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cask/README.md @@ -0,0 +1,15 @@ +# Cask plugin + +[Cask](https://github.com/cask/cask) is a project management tool for Emacs that helps +automate the package development cycle; development, dependencies, testing, building, +packaging and more. + +This plugin loads `cask` completion from non-standard locations, such as if installed +via Homebrew or others. To enable it, add `cask` to your plugins array: + +```zsh +plugins=(... cask) +``` + +Make sure you have the `cask` directory in your `$PATH` before loading Oh My Zsh, +otherwise you'll get a "command not found" error. diff --git a/zsh/.oh-my-zsh/plugins/cask/cask.plugin.zsh b/zsh/.oh-my-zsh/plugins/cask/cask.plugin.zsh new file mode 100644 index 0000000..20c9801 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cask/cask.plugin.zsh @@ -0,0 +1,26 @@ +() { + emulate -L zsh + + if ! (( $+commands[cask] )); then + print "zsh cask plugin: cask command not found" >&2 + return + fi + + cask_base=${commands[cask]:h:h} + + # Plain cask installation location (for Cask 0.7.2 and earlier) + comp_files=($cask_base/etc/cask_completion.zsh) + + # Mac Homebrew installs the completion in a different location + if (( $+commands[brew] )); then + comp_files+=($(brew --prefix)/share/zsh/site-functions/cask_completion.zsh) + fi + + # Load first found file + for f in $comp_files; do + if [[ -f "$f" ]]; then + source "$f" + break + fi + done +} diff --git a/zsh/.oh-my-zsh/plugins/catimg/README.md b/zsh/.oh-my-zsh/plugins/catimg/README.md new file mode 100644 index 0000000..4c4c137 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/catimg/README.md @@ -0,0 +1,23 @@ +# catimg + +Plugin for displaying images on the terminal using the `catimg.sh` script provided by [posva](https://github.com/posva/catimg) + +To use it, add `catimg` to the plugins array in your zshrc file: + +```zsh +plugins=(... catimg) +``` + +## Requirements + +- `convert` (ImageMagick) + +## Functions + +| Function | Description | +| -------- | ---------------------------------------- | +| `catimg` | Displays the given image on the terminal | + +## Usage examples + +[![asciicast](https://asciinema.org/a/204702.png)](https://asciinema.org/a/204702) diff --git a/zsh/.oh-my-zsh/plugins/catimg/catimg.plugin.zsh b/zsh/.oh-my-zsh/plugins/catimg/catimg.plugin.zsh new file mode 100644 index 0000000..00f306c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/catimg/catimg.plugin.zsh @@ -0,0 +1,17 @@ +################################################################################ +# catimg script by Eduardo San Martin Morote aka Posva # +# https://posva.net # +# # +# Output the content of an image to the stdout using the 256 colors of the # +# terminal. # +# GitHub: https://github.com/posva/catimg # +################################################################################ + + +function catimg() { + if [[ -x `which convert` ]]; then + zsh $ZSH/plugins/catimg/catimg.sh $@ + else + echo "catimg need convert (ImageMagick) to work)" + fi +} diff --git a/zsh/.oh-my-zsh/plugins/catimg/catimg.sh b/zsh/.oh-my-zsh/plugins/catimg/catimg.sh new file mode 100644 index 0000000..0efec2e --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/catimg/catimg.sh @@ -0,0 +1,88 @@ +################################################################################ +# catimg script by Eduardo San Martin Morote aka Posva # +# https://posva.net # +# # +# Output the content of an image to the stdout using the 256 colors of the # +# terminal. # +# GitHub: https://github.com/posva/catimg # +################################################################################ + +function help() { + echo "Usage catimg [-h] [-w width] [-c char] img" + echo "By default char is \" \" and w is the terminal width" +} + +# VARIABLES +COLOR_FILE=$(dirname $0)/colors.png +CHAR=" " + +WIDTH="" +IMG="" + +while getopts qw:c:h opt; do + case "$opt" in + w) WIDTH="$OPTARG" ;; + c) CHAR="$OPTARG" ;; + h) help; exit ;; + *) help ; exit 1;; + esac + done + +while [ "$1" ]; do + IMG="$1" + shift +done + +if [ "$IMG" = "" -o ! -f "$IMG" ]; then + help + exit 1 +fi + +if [ ! "$WIDTH" ]; then + COLS=$(expr $(tput cols) "/" $(echo -n "$CHAR" | wc -c)) +else + COLS=$(expr $WIDTH "/" $(echo -n "$CHAR" | wc -c)) +fi +WIDTH=$(convert "$IMG" -print "%w\n" /dev/null) +if [ "$WIDTH" -gt "$COLS" ]; then + WIDTH=$COLS +fi + +REMAP="" +if convert "$IMG" -resize $COLS\> +dither -remap $COLOR_FILE /dev/null ; then + REMAP="-remap $COLOR_FILE" +else + echo "The version of convert is too old, don't expect good results :(" >&2 + #convert "$IMG" -colors 256 PNG8:tmp.png + #IMG="tmp.png" +fi + +# Display the image +I=0 +convert "$IMG" -resize $COLS\> +dither `echo $REMAP` txt:- 2>/dev/null | +sed -e 's/.*none.*/NO NO NO/g' -e '1d;s/^.*(\(.*\)[,)].*$/\1/g;y/,/ /' | +while read R G B f; do + if [ ! "$R" = "NO" ]; then + if [ "$R" -eq "$G" -a "$G" -eq "$B" ]; then + (( + I++, + IDX = 232 + R * 23 / 255 + )) + else + (( + I++, + IDX = 16 + + R * 5 / 255 * 36 + + G * 5 / 255 * 6 + + B * 5 / 255 + )) + fi + #echo "$R,$G,$B: $IDX" + echo -ne "\e[48;5;${IDX}m${CHAR}" + else + (( I++ )) + echo -ne "\e[0m${CHAR}" + fi + # New lines + (( $I % $WIDTH )) || echo -e "\e[0m" +done diff --git a/zsh/.oh-my-zsh/plugins/catimg/colors.png b/zsh/.oh-my-zsh/plugins/catimg/colors.png new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..74d0074160d237f7d506d977ab1f7f609ee210b03cde5b95c5f3d375cce35b5a GIT binary patch literal 353 zcmV-n0iOPeP) zV|@Gn{~G8ykjRV#PQCxH|Hm1Kz--RQKmY&$#Kd628_Utk00000NkvXXu0mjflf#Hs literal 0 HcmV?d00001 diff --git a/zsh/.oh-my-zsh/plugins/celery/README.md b/zsh/.oh-my-zsh/plugins/celery/README.md new file mode 100644 index 0000000..8dac54f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/celery/README.md @@ -0,0 +1,9 @@ +# Celery + +This plugin provides completion for [Celery](http://www.celeryproject.org/). + +To use it add celery to the plugins array in your zshrc file. + +```bash +plugins=(... celery) +``` diff --git a/zsh/.oh-my-zsh/plugins/celery/_celery b/zsh/.oh-my-zsh/plugins/celery/_celery new file mode 100644 index 0000000..cafbd7d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/celery/_celery @@ -0,0 +1,129 @@ +#compdef celery +#autoload + +#celery zsh completion + +_celery () { +local -a _1st_arguments ifargs dopts controlargs + +typeset -A opt_args + +_1st_arguments=('worker' 'events' 'beat' 'shell' 'multi' 'amqp' 'status' 'inspect' \ + 'control' 'purge' 'list' 'migrate' 'call' 'result' 'report') +ifargs=('--app=' '--broker=' '--loader=' '--config=' '--version') +dopts=('--detach' '--umask=' '--gid=' '--uid=' '--pidfile=' '--logfile=' '--loglevel=') +controlargs=('--timeout' '--destination') +_arguments \ + '(-A --app=)'{-A,--app}'[app instance to use (e.g. module.attr_name):APP]' \ + '(-b --broker=)'{-b,--broker}'[url to broker. default is "amqp://guest@localhost//":BROKER]' \ + '(--loader)--loader[name of custom loader class to use.:LOADER]' \ + '(--config)--config[Name of the configuration module:CONFIG]' \ + '(--workdir)--workdir[Optional directory to change to after detaching.:WORKING_DIRECTORY]' \ + '(-q --quiet)'{-q,--quiet}'[Don"t show as much output.]' \ + '(-C --no-color)'{-C,--no-color}'[Don"t display colors.]' \ + '(--version)--version[show program"s version number and exit]' \ + '(- : *)'{-h,--help}'[show this help message and exit]' \ + '*:: :->subcmds' && return 0 + +if (( CURRENT == 1 )); then + _describe -t commands "celery subcommand" _1st_arguments + return +fi + +case "$words[1]" in + worker) + _arguments \ + '(-C --concurrency=)'{-C,--concurrency=}'[Number of child processes processing the queue. The default is the number of CPUs.]' \ + '(--pool)--pool=:::(processes eventlet gevent threads solo)' \ + '(--purge --discard)'{--discard,--purge}'[Purges all waiting tasks before the daemon is started.]' \ + '(-f --logfile=)'{-f,--logfile=}'[Path to log file. If no logfile is specified, stderr is used.]' \ + '(--loglevel=)--loglevel=:::(critical error warning info debug)' \ + '(-N --hostname=)'{-N,--hostname=}'[Set custom hostname, e.g. "foo.example.com".]' \ + '(-B --beat)'{-B,--beat}'[Also run the celerybeat periodic task scheduler.]' \ + '(-s --schedule=)'{-s,--schedule=}'[Path to the schedule database if running with the -B option. Defaults to celerybeat-schedule.]' \ + '(-S --statedb=)'{-S,--statedb=}'[Path to the state database.Default: None]' \ + '(-E --events)'{-E,--events}'[Send events that can be captured by monitors like celeryev, celerymon, and others.]' \ + '(--time-limit=)--time-limit=[nables a hard time limit (in seconds int/float) for tasks]' \ + '(--soft-time-limit=)--soft-time-limit=[Enables a soft time limit (in seconds int/float) for tasks]' \ + '(--maxtasksperchild=)--maxtasksperchild=[Maximum number of tasks a pool worker can execute before it"s terminated and replaced by a new worker.]' \ + '(-Q --queues=)'{-Q,--queues=}'[List of queues to enable for this worker, separated by comma. By default all configured queues are enabled.]' \ + '(-I --include=)'{-I,--include=}'[Comma separated list of additional modules to import.]' \ + '(--pidfile=)--pidfile=[Optional file used to store the process pid.]' \ + '(--autoscale=)--autoscale=[Enable autoscaling by providing max_concurrency, min_concurrency.]' \ + '(--autoreload)--autoreload[Enable autoreloading.]' \ + '(--no-execv)--no-execv[Don"t do execv after multiprocessing child fork.]' + compadd -a ifargs + ;; + inspect) + _values -s \ + 'active[dump active tasks (being processed)]' \ + 'active_queues[dump queues being consumed from]' \ + 'ping[ping worker(s)]' \ + 'registered[dump of registered tasks]' \ + 'report[get bugreport info]' \ + 'reserved[dump reserved tasks (waiting to be processed)]' \ + 'revoked[dump of revoked task ids]' \ + 'scheduled[dump scheduled tasks (eta/countdown/retry)]' \ + 'stats[dump worker statistics]' + compadd -a controlargs ifargs + ;; + control) + _values -s \ + 'add_consumer[tell worker(s) to start consuming a queue]' \ + 'autoscale[change autoscale settings]' \ + 'cancel_consumer[tell worker(s) to stop consuming a queue]' \ + 'disable_events[tell worker(s) to disable events]' \ + 'enable_events[tell worker(s) to enable events]' \ + 'pool_grow[start more pool processes]' \ + 'pool_shrink[use less pool processes]' \ + 'rate_limit[tell worker(s) to modify the rate limit for a task type]' \ + 'time_limit[tell worker(s) to modify the time limit for a task type.]' + compadd -a controlargs ifargs + ;; + multi) + _values -s \ + '--nosplash[Don"t display program info.]' \ + '--verbose[Show more output.]' \ + '--no-color[Don"t display colors.]' \ + '--quiet[Don"t show as much output.]' \ + 'start' 'restart' 'stopwait' 'stop' 'show' \ + 'names' 'expand' 'get' 'kill' + compadd -a ifargs + ;; + amqp) + _values -s \ + 'queue.declare' 'queue.purge' 'exchange.delete' 'basic.publish' \ + 'exchange.declare' 'queue.delete' 'queue.bind' 'basic.get' + ;; + list) + _values -s, 'bindings' + ;; + shell) + _values -s \ + '--ipython[force iPython.]' \ + '--bpython[force bpython.]' \ + '--python[force default Python shell.]' \ + '--without-tasks[don"t add tasks to locals.]' \ + '--eventlet[use eventlet.]' \ + '--gevent[use gevent.]' + compadd -a ifargs + ;; + beat) + _arguments \ + '(-s --schedule=)'{-s,--schedule=}'[Path to the schedule database. Defaults to celerybeat-schedule.]' \ + '(-S --scheduler=)'{-S,--scheduler=}'[Scheduler class to use. Default is celery.beat.PersistentScheduler.]' \ + '(--max-interval)--max-interval[]' + compadd -a dopts fargs + ;; + events) + _arguments \ + '(-d --dump)'{-d,--dump}'[Dump events to stdout.]' \ + '(-c --camera=)'{-c,--camera=}'[Take snapshots of events using this camera.]' \ + '(-F --frequency=)'{-F,--frequency=}'[Camera: Shutter frequency. Default is every 1.0 seconds.]' \ + '(-r --maxrate=)'{-r,--maxrate=}'[Camera: Optional shutter rate limit (e.g. 10/m).]' + compadd -a dopts fargs + ;; + *) + ;; + esac +} diff --git a/zsh/.oh-my-zsh/plugins/charm/README.md b/zsh/.oh-my-zsh/plugins/charm/README.md new file mode 100644 index 0000000..ed67bf8 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/charm/README.md @@ -0,0 +1,9 @@ +# Charm plugin + +This plugin adds completion for the [charm](https://github.com/charmbracelet/charm) CLI. + +To use it, add `charm` to the plugins array in your zshrc file: + +```zsh +plugins=(... charm) +``` diff --git a/zsh/.oh-my-zsh/plugins/charm/charm.plugin.zsh b/zsh/.oh-my-zsh/plugins/charm/charm.plugin.zsh new file mode 100644 index 0000000..f87ea9c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/charm/charm.plugin.zsh @@ -0,0 +1,14 @@ +# Autocompletion for the Charm CLI (charm). +if (( ! $+commands[charm] )); then + return +fi + +# If the completion file doesn't exist yet, we need to autoload it and +# bind it to `charm`. Otherwise, compinit will have already done that. +if [[ ! -f "$ZSH_CACHE_DIR/completions/_charm" ]]; then + typeset -g -A _comps + autoload -Uz _charm + _comps[charm]=_charm +fi + +charm completion zsh >| "$ZSH_CACHE_DIR/completions/_charm" &| diff --git a/zsh/.oh-my-zsh/plugins/chruby/README.md b/zsh/.oh-my-zsh/plugins/chruby/README.md new file mode 100644 index 0000000..5e00af4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/chruby/README.md @@ -0,0 +1,21 @@ +# chruby plugin + +This plugin loads [chruby](https://github.com/postmodern/chruby), a tool that changes the +current Ruby version, and completion and a prompt function to display the Ruby version. +Supports brew and manual installation of chruby. + +To use it, add `chruby` to the plugins array in your zshrc file: + +```zsh +plugins=(... chruby) +``` + +## Usage + +If you'd prefer to specify an explicit path to load chruby from +you can set variables like so: + +```zsh +zstyle :omz:plugins:chruby path /local/path/to/chruby.sh +zstyle :omz:plugins:chruby auto /local/path/to/auto.sh +``` diff --git a/zsh/.oh-my-zsh/plugins/chruby/chruby.plugin.zsh b/zsh/.oh-my-zsh/plugins/chruby/chruby.plugin.zsh new file mode 100644 index 0000000..2f67f91 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/chruby/chruby.plugin.zsh @@ -0,0 +1,94 @@ +## load chruby from different locations + +_source-from-omz-settings() { + local _chruby_path _chruby_auto + + zstyle -s :omz:plugins:chruby path _chruby_path || return 1 + zstyle -s :omz:plugins:chruby auto _chruby_auto || return 1 + + if [[ -r ${_chruby_path} ]]; then + source ${_chruby_path} + fi + + if [[ -r ${_chruby_auto} ]]; then + source ${_chruby_auto} + fi +} + +_source-from-homebrew() { + (( $+commands[brew] )) || return 1 + + local _brew_prefix + # check default brew prefix + if [[ -h /usr/local/opt/chruby ]];then + _brew_prefix="/usr/local/opt/chruby" + else + # ok , it is not default prefix + # this call to brew is expensive ( about 400 ms ), so at least let's make it only once + _brew_prefix=$(brew --prefix chruby) + fi + + [[ -r "$_brew_prefix" ]] || return 1 + + source $_brew_prefix/share/chruby/chruby.sh + source $_brew_prefix/share/chruby/auto.sh +} + +_load-chruby-dirs() { + local dir + for dir in "$HOME/.rubies" "$PREFIX/opt/rubies"; do + if [[ -d "$dir" ]]; then + RUBIES+=("$dir") + fi + done +} + +# Load chruby +if _source-from-omz-settings; then + _load-chruby-dirs +elif [[ -r "/usr/local/share/chruby/chruby.sh" ]] ; then + source /usr/local/share/chruby/chruby.sh + source /usr/local/share/chruby/auto.sh + _load-chruby-dirs +elif _source-from-homebrew; then + _load-chruby-dirs +fi + +unfunction _source-from-homebrew _source-from-omz-settings _load-chruby-dirs + + +## chruby utility functions and aliases + +# rvm and rbenv plugins also provide this alias +alias rubies='chruby' + +function current_ruby() { + local ruby + ruby="$(chruby | grep \* | tr -d '* ')" + if [[ $(chruby | grep -c \*) -eq 1 ]]; then + echo ${ruby} + else + echo "system" + fi +} + +function chruby_prompt_info() { + echo "${$(current_ruby):gs/%/%%}" +} + +# Complete chruby command with installed rubies +_chruby() { + compadd $(chruby | tr -d '* ') + if PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" command ruby &>/dev/null; then + compadd system + fi +} + +compdef _chruby chruby + + +# Simple definition completer for ruby-build +if command ruby-build &> /dev/null; then + _ruby-build() { compadd $(ruby-build --definitions) } + compdef _ruby-build ruby-build +fi diff --git a/zsh/.oh-my-zsh/plugins/chucknorris/.gitignore b/zsh/.oh-my-zsh/plugins/chucknorris/.gitignore new file mode 100644 index 0000000..b1ca281 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/chucknorris/.gitignore @@ -0,0 +1 @@ +fortunes/chucknorris.dat diff --git a/zsh/.oh-my-zsh/plugins/chucknorris/README.md b/zsh/.oh-my-zsh/plugins/chucknorris/README.md new file mode 100644 index 0000000..b871f4d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/chucknorris/README.md @@ -0,0 +1,38 @@ +# chucknorris + +Chuck Norris fortunes plugin for Oh My Zsh. Perfectly suitable as MOTD. + +To use it add `chucknorris` to the plugins array in you zshrc file. + +```zsh +plugins=(... chucknorris) +``` + +## Usage + +| Command | Description | +| ----------- | ------------------------------- | +| `chuck` | Print random Chuck Norris quote | +| `chuck_cow` | Print quote in cowthink | + +Example: output of `chuck_cow`: + +``` +Last login: Fri Jan 30 23:12:26 on ttys001 + ______________________________________ +( When Chuck Norris plays Monopoly, it ) +( affects the actual world economy. ) + -------------------------------------- + o ^__^ + o (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` + +## Requirements + +- `fortune` +- `cowsay` if using `chuck_cow` + +Available via homebrew, apt, ... diff --git a/zsh/.oh-my-zsh/plugins/chucknorris/chucknorris.plugin.zsh b/zsh/.oh-my-zsh/plugins/chucknorris/chucknorris.plugin.zsh new file mode 100644 index 0000000..92a6fd4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/chucknorris/chucknorris.plugin.zsh @@ -0,0 +1,24 @@ +() { + # %x: name of file containing code being executed + local fortunes_dir="${${(%):-%x}:h}/fortunes" + + # Aliases + alias chuck="fortune -a $fortunes_dir" + alias chuck_cow="chuck | cowthink" + + # Automatically generate or update Chuck's compiled fortune data file + if [[ "$fortunes_dir/chucknorris" -ot "$fortunes_dir/chucknorris.dat" ]]; then + return + fi + + # For some reason, Cygwin puts strfile in /usr/sbin, which is not on the path by default + local strfile="${commands[strfile]:-/usr/sbin/strfile}" + if [[ ! -x "$strfile" ]]; then + echo "[oh-my-zsh] chucknorris depends on strfile, which is not installed" >&2 + echo "[oh-my-zsh] strfile is often provided as part of the 'fortune' package" >&2 + return + fi + + # Generate the compiled fortune data file + $strfile "$fortunes_dir/chucknorris" "$fortunes_dir/chucknorris.dat" >/dev/null +} diff --git a/zsh/.oh-my-zsh/plugins/chucknorris/fortunes/chucknorris b/zsh/.oh-my-zsh/plugins/chucknorris/fortunes/chucknorris new file mode 100644 index 0000000..10603c4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/chucknorris/fortunes/chucknorris @@ -0,0 +1,568 @@ +King Kong climbed the Empire State building in fear of Chuck Norris who was downstairs at the time. +% +"2012" is code for, Chuck Norris when he is pissed. +% +"The Big Chuck Norris Roundhouse-Kick Theory" +% +"The wind cries Chuck Norris" +% +"Walker Texas Ranger: The Movie 3-D" was considered by Warner Brothers; however the technology to create the visual effects will never be possible. +% +A Handicapped parking sign does not signify that this spot is for handicapped people. It is actually in fact a warning, that the spot belongs to Chuck Norris and that you will be handicapped if you park there. +% +Abraham Lincoln didn't die because he was shot, Chuck Norris roundhouse-kicked so fast his foot went back in time and killed Abraham Lincoln. +% +Achievement Unlocked: Chuck Norris of Death +% +After Chuck counted to infinity the first time, he vowed to count to infinity a second time....by counting the bodies of those previously roundhoused. +% +Aliens fear that Chuck Norris might abduct them. +% +An angry glare from Chuck Norris is known to kill on the spot. +% +Behind every successful man is Chuck Norris. +% +Beware of dogs... Dogs, beware of Chuck Norris. +% +Bruce Lee didn't defeat Chuck Norris. Chuck hit Bruce with a Delayed roundhouse kick that was so fast that Lee only felt the impact a year later! +% +CNN was originally created as the "Chuck Norris Network" to update Americans with on-the-spot ass kicking in real-time. +% +Casinos pay Chuck Norris not to play at anything or wish anyone good luck. +% +Chuck Norris - the new standard. +% +Chuck Norris CAN balance the light-switch between ON and OFF. +% +Chuck Norris CAN believe it's not butter. +% +Chuck Norris CAN spell with an I before E even after C. +% +Chuck Norris can play the theme from the Twilight Zone with his beard. +% +Chuck Norris can power solar panels. At night. +% +Chuck Norris watches "the Nat.Geo. Specials" on Discovery Channel. +% +Chuck Norris bowled a 301 after constructing another pin out of his beard hair. +% +Chuck Norris burnt a fire proof vest, UNDERWATER! +% +Chuck Norris can French kiss his elbow. +% +Chuck Norris can bake in a freezer. +% +Chuck Norris can defuse a bomb by cutting the wrong wire. +% +Chuck Norris can dig a hole in air. +% +Chuck Norris can divide by zero. +% +Chuck Norris can do a regime change with a roundhouse kick. +% +Chuck Norris can fit 10 gallons of water in a 5 gallon bucket. +% +Chuck Norris can grill a popsicle. +% +Chuck Norris can lead a horse to water AND make it drink. +% +Chuck Norris can make his own megazord "The Chuck Norris Roundhouse Kickers Ultimate Super Awesome Megazord". +% +Chuck Norris can milk an alligator. +% +Chuck Norris can play the death waltz with his chin. +% +Chuck Norris can roundhouse kick someone through a window without breaking the glass. +% +Chuck Norris can roundhouse-kick round houses into squares. +% +Chuck Norris can rub two fires together and make a stick! +% +Chuck Norris can see in 3D with just one eye. +% +Chuck Norris can slam a revolving door. +% +Chuck Norris can terminate a repeating decimal. +% +Chuck Norris can turn toast back into bread. +% +Chuck Norris can win a game of Connect Four in only three moves. +% +Chuck Norris can win in a top spinning tournament with a cube. +% +Chuck Norris can't perform Hadoukens, he IS a Hadouken. +% +Chuck Norris checks under his bed for Fedor Emelianenko because he takes Fedor to the vet regularly. +% +Chuck Norris counted to infinity - twice. +% +Chuck Norris created Heavy Metal when he was upset. +% +Chuck Norris does not get frostbite. Chuck Norris bites frost. +% +Chuck Norris does not have a cell phone because he hears everything. +% +Chuck Norris does not sleep. He waits. +% +Chuck Norris doesn't bowl strikes, he just knocks down one pin and the other nine faint. +% +Chuck Norris doesn't call the wrong number, you just answer the wrong phone. +% +Chuck Norris doesn't cheat death, he beats it fair and square. +% +Chuck Norris doesn't churn butter. He roundhouse kicks the cows and the butter comes straight out. +% +Chuck Norris doesn't eat, he just sucks the energy out of food by staring at it. +% +Chuck Norris doesn't exhale. The air runs desperately scared out of his lungs. +% +Chuck Norris doesn't go hunting.... CHUCK NORRIS GOES KILLING. +% +Chuck Norris doesn't let it go. +% +Chuck Norris doesn't like Mudkipz. +% +Chuck Norris doesn't look for fun. The fun looks for Chuck Norris. +% +Chuck Norris doesn't need a bulletproof vest. He catches them with his bare hands. +% +Chuck Norris doesn't need air, he is air. +% +Chuck Norris doesn't need sunglasses, the sun needs Chuck Norris glasses. +% +Chuck Norris doesn't need to brush his teeth, his spit acts as a bleach. +% +Chuck Norris doesn't read books. He stares them down until he gets the information he wants. +% +Chuck Norris doesn't throw up if he drinks too much. Chuck Norris throws down! +% +Chuck Norris doesn't eat salad, he eats vegetarians. +% +Chuck Norris doesn't wash his clothes, he disembowels them. +% +Chuck Norris doesn't wear a watch. HE decides what time it is. +% +Chuck Norris doesn't carry a list. He always knows what to do. +% +Chuck Norris drives an ice cream truck covered in human skulls. +% +Chuck Norris drowned a man ON LAND. +% +Chuck Norris fed the Hunger Games. +% +Chuck Norris found the hay in the needle stack. +% +Chuck Norris found the last digit of pi. +% +Chuck Norris had a knife thrown at him. The knife didn't impale him; he impaled the knife. +% +Chuck Norris has a battle cruiser AND a car. +% +Chuck Norris has killed the Dead Sea. +% +Chuck Norris has made a 148 break at snooker. +% +Chuck Norris invented Kentucky Fried Chicken's famous secret recipe, with eleven herbs and spices. But nobody ever mentions the twelfth ingredient: Fear. +% +Chuck Norris is allowed two carry-ons. +% +Chuck Norris is currently suing NBC, claiming Law and Order are trademarked names for his left and right legs. +% +Chuck Norris is currently suing any broadway theater that plays "The Nutcracker". He claims its an infringement on his "other" roundhouse kick. +% +Chuck Norris is entitled to his own facts. +% +Chuck Norris is my Homeboy. +% +Chuck Norris is so fast, he can run around the world and punch himself in the back of the head. +% +Chuck Norris is so hard, he uses diamonds as stress balls. +% +Chuck Norris is so scary, he makes sharks swim backwards away from him. +% +Chuck Norris is ten feet tall, weighs two-tons, breathes fire, and could eat a hammer and take a shotgun blast standing. +% +Chuck Norris is the ghost in paranormal activity. +% +Chuck Norris is the life of parties he doesn't attend. +% +Chuck Norris is the meaning of life. Too bad he's also the meaning of death. +% +Chuck Norris is the only man to ever defeat a brick wall in a game of tennis. +% +Chuck Norris is the only one who can tear a facebook page! +% +Chuck Norris is the reason that the world will end in 2012. He was getting bored with the Earth. +% +Chuck Norris is the reason tumbleweeds tumble. +% +Chuck Norris is the reason why Waldo is hiding. +% +Chuck Norris is waiting for Mt. St. Helens to erupt again. He's hoping the lava is hot enough to soften his beard so he can shave for the first time. +% +Chuck Norris isn't allowed at the zoo, because when he's there the animals are too terrified to come out of their cages. +% +Chuck Norris made a statue bleed. +% +Chuck Norris made the big bang just by clicking his fingers. +% +Chuck Norris never trains, because he's Chuck Norris. +% +Chuck Norris once cried just to see what it was like. The end result was the creation of life. +% +Chuck Norris once cut a knife with a stick of butter. +% +Chuck Norris once got a 200 yard punt return. +% +Chuck Norris once had a pet monkey named KING KONG. +% +Chuck Norris once had a street named after him. The name removed at once, because nobody crosses Chuck Norris, and lives. +% +Chuck Norris once had a weak moment, just to know what it felt like. +% +Chuck Norris once played Duck Duck Goose with a group of Kindergarteners. Only one kid made it to first grade. +% +Chuck Norris once proved p^~p by induction on his beard hairs. +% +Chuck Norris once punched the ground to stop an earthquake. The resulting aftershock caused the BP oil spill. +% +Chuck Norris once round-house kicked a salesman. Over the phone. +% +Chuck Norris once roundhouse kicked a football. The astronomical society now considers it a planet. +% +Chuck Norris once thought he was wrong. He was, however, mistaken. +% +Chuck Norris once walked down a street with his fists in his pockets. He was then arrested for concealing two deadly weapons. +% +Chuck Norris once won the Tour de France riding a "big wheel". +% +Chuck Norris originally appeared in the "Street Fighter II" video game, but was removed by Beta Testers because every button caused him to do a roundhouse kick. When asked bout this "glitch," Norris replied, "That's no glitch." +% +Chuck Norris owns all number 1 pencils. +% +Chuck Norris pees Adamantium. +% +Chuck Norris plays Texas Hold'Em with Zeus, every second Wednesday of the month. +% +Chuck Norris played "Got your Nose" with Voldemort and won. +% +Chuck Norris played the game of thrones and won. +% +Chuck Norris protects his bodyguards. +% +Chuck Norris rolled a 20 on a 6 sided die. +% +Chuck Norris roundhouse kicks people in the face first and asks questions later. +% +Chuck Norris sent a BBM to an iPhone. +% +Chuck Norris shops at Sam's Club, but leaves without having his receipt checked. +% +Chuck Norris splattered tiger blood and Adonis' DNA on Charlie Sheen with 1 roundhouse kick! +% +Chuck Norris started Chuck Norris. +% +Chuck Norris starts his day with 6 live chickens, two cows, three pigs, and a boiling hot cup of pure fury. +% +Chuck Norris told me to put this here. +% +Chuck Norris uses a real mouse to move the cursor, type on the keyboard, write e-mails, code entire websites, and make coffee. +% +Chuck Norris uses pepper spray to spice up his steaks. +% +Chuck Norris was heard in a soundproof room! +% +Chuck Norris was once turned down for American Idol. When Simon was questioned about it, he replied "I'm retiring after this season". I wonder why? +% +Chuck Norris was originally in Mortal Kombat, but that version was deleted because no one can beat Chuck Norris in a fight. +% +Chuck Norris was the image used for Papa Smurf. +% +Chuck Norris was the reason why the Great Wall of China was constructed. It failed miserably. +% +Chuck Norris was what Willis was talking about. +% +Chuck Norris wasn't born on his birthday. +% +Chuck Norris watched the first steps on the moon... from his summer home on Mars. +% +Chuck Norris went up the creek without a paddle... or a canoe. +% +Chuck Norris will attain statehood in 2009. His state flower will be the Magnolia. +% +Chuck Norris wins NASCAR races with all right turns. +% +Chuck Norris won a stepdance contest by standing on his hands. +% +Chuck Norris yells at drill Sergeants. +% +Chuck Norris' dog picks up after him. +% +Chuck Norris' films are factual documentaries. +% +Chuck Norris' first job was as a paperboy. There were no survivors. +% +Chuck Norris' glass is never half full or half empty. It stays full even after he takes a drink. +% +Chuck Norris' hand is the only hand that can beat a Royal Flush. +% +Chuck Norris' personal airplane is called Air Force Chuck. +% +Chuck Norris. Enough said. +% +Chuck Norris: even Naruto can't believe it. +% +Chuck Norris can make sour milk turn fresh. +% +Contrary to popular belief, Rome WAS built in a day, by Chuck Norris. +% +Contrary to popular belief, America is not a democracy, it is a Chucktatorship. +% +Contrary to popular belief, Chuck Norris, not the box jellyfish of northern Australia, is the most venomous creature on Earth. +% +Cops don't need badges in their wallets, but only a picture of Chuck Norris. +% +Crop circles are Chuck Norris' way of telling the world that sometimes corn needs to lie down. +% +Did you hear about the boy who cried Chuck Norris? +% +Dog the Bounty Hunter can't track Chuck Norris down. +% +Don't get Chuck Norris angry. Last time somebody did that, Chuck Norris made the Grand Canyon. +% +Earth's rotation is purely governed by the direction that Chuck Norris is walking. +% +Ever wonder what really happened to the dinosaurs? They all dug their own graves when they heard Chuck Norris was coming. +% +Every line in a Chuck Norris haiku is "A roundhouse kick to the face." And they all have the correct number of syllables. +% +Every phobia known to man has a phobia of Chuck Norris. +% +Every time there's an earthquake, you know Chuck Norris is hungry. The earthquake is caused by his stomach growling. +% +Evolution's driving mechanism is nature's desperate attempt to escape Chuck Norris. +% +Fear of spiders is arachnophobia. Fear of tight spaces is claustrophobia. Fear of Chuck Norris is called Logic. +% +Fool me once, shame on you. Fool Chuck Norris once and he will roundhouse you in the face. +% +Ghosts can see Chuck Norris. +% +Guns don't kill people. Chuck Norris kills people. +% +How much wood could a woodchuck chuck if a woodchuck could chuck wood? No woodchuck could chuck Chuck's wood! +% +If Chuck Norris were a calendar, every month would be named Chucktober, and every day he'd kick your ass. +% +If Chuck Norris were to get into a fight with another Chuck Norris, Chuck Norris would win. +% +If God doesn't know, Chuck does. +% +If Goliath listened to Chuck Norris, he would have won. +% +If at first you don't succeed, you're not Chuck Norris. +% +If you ask Chuck Norris what time it is, he always says, "Two seconds 'til." After you ask, "Two seconds 'til what?" he roundhouse kicks you in the face. +% +If you put in the correct cheat code in Halo 2, you can have Master Chief play without his helmet, revealing himself to be Chuck Norris. +% +If you see a man in the street who looks like Chuck Norris, but isn't, run: you don't want to be caught in the resulting roundhouse kick to his face. +% +If you spell Chuck Norris in Scrabble, you win. Forever. +% +In 1945 The US army asked if they could clone Chuck Norris. Instead he said he could sort out the Japanese. +% +In Texas, there are five sizes for fountain drinks: small, medium, large, Texas sized, and Chuck Norris sized. It is a cup made of a human skull. +% +In a rain storm Chuck Norris stays dry. Rain drops are scared to hit him. +% +In the back of the book of world records, it says "All records are held by Chuck Norris. The ones listed are in second place." +% +James Bond has a license to kill. He got it from Chuck Norris. +% +Jedis are now taught to use the "Chuck". +% +MacGyver immediately tried to make a bomb out of some Q-Tips and Gatorade, but Chuck Norris roundhouse-kicked him in the solar plexus. MacGyver promptly threw up his own heart. +% +Machiavelli said it is better to be feared than loved because he was inspired by Chuck Norris. +% +May the Force be with Chuck Norris... for its own good. +% +Merlin was Chuck Norris' assistant. +% +Most people have 23 pairs of chromosomes. Chuck Norris has 72... and they're all poisonous. +% +Note to self: Don't be the cashier to tell Chuck Norris his coupons have expired. +% +Chuck Norris' keyboard has no control key. Chuck Norris is always in control. +% +Once upon a time, Chuck Norris found himself in a town called Shit Creek. He opened a Paddle Store. +% +One glance from Chuck Norris and snow turns itself yellow. +% +One time a test cheated on Chuck Norris. +% +Only Chuck Norris can win the mind game, 'cause he never minds. +% +Only Chuck Norris is stronger than an Altoid. +% +Outer space exists because it's afraid to be on the same planet with Chuck Norris. +% +Ozzy Osbourne once accidentally bit the head off a live bat - Chuck Norris once deliberately bit the head off a live pterodactyl. +% +Pluto is actually an orbiting group of British soldiers from the American Revolution who entered space after the Chuck gave them a roundhouse kick to the face. +% +Police label anyone attacking Chuck Norris as a Code 45-11.... a suicide. +% +Remember the Soviet Union? They decided to quit after watching a DeltaForce marathon on Satellite TV. +% +Simon doesn't say... Chuck Norris says. +% +Some boots were made for walking. Some boots may walk all over you, but Chuck Norris' boots walk THROUGH you. +% +Some kids pee their name in snow. Chuck Norris pees his name in concrete. +% +Some people ask for a Kleenex when they sneeze, Chuck Norris asks for a body bag. +% +Someone once videotaped Chuck Norris getting pissed off. It was called Walker: Texas Chain Saw Massacre. +% +Staring at Chuck Norris for extended periods of time without proper eye protection will cause blindness, and possibly foot sized bruises on the face. +% +Taking Karate Lessons = $100, Buying MMA DVD's = $150, Subscribing to a UFC event = $50, Getting a Roundhouse Kick from Chuck Norris = PRICELESS. +% +That's not an eclipse. That's the sun hiding from Chuck Norris. +% +The Beatles are on iTunes because Chuck Norris bought a Mac. +% +The Earth is made up of two-thirds water and one-third Chuck Norris. +% +The Earth was almost destroyed by a 50 km wide asteroid in 1984, but Chuck Norris roundhouse kicked it into the Sun. +% +The Great Wall of China was originally created to keep Chuck Norris out. It failed miserably. +% +The Joneses are trying to keep up with Chuck Norris. +% +The Matrix Trilogy would have ended on the first movie had Keanu Reeves said, “I know Chuck Norris.” +% +The answer to life, the universe and everything isn't 42. It's Chuck Norris. +% +The apple falls far from the tree, when Chuck's roundhouse kick is taken to the trunk. +% +The best part of waking up is not Folgers in your cup. it's knowing that Chuck Norris let you live. +% +The chief export of Chuck Norris is pain. +% +The dictionary references Chuck Norris several times, he is mentioned under Fear, Law, Order and Chucktatorship. +% +The leading causes of death in the United States are: 1. Heart Disease 2. Chuck Norris 3. Cancer. +% +The letters in Chuck Norris cannot be unscrambled. +% +The only place where the Starship Enterprise refuses to boldly go is Chuck Norris' planet... which is all of them. +% +The only reason that USA lost the 2011 world cup to Japan is because Chuck Norris wasn't there. +% +The only sure things are Death and Taxes, and when Chuck Norris goes to work for the IRS, they'll be the same thing. +% +The only way sharks will come near CN underwater is when CN is inside of a cage. +% +The only word that rhymes with orange is Chuck Norris. +% +The producers of the movie "The Last Airbender" are now in talks with Chuck Norris in Order to star him in their next sequel "The Last Skull Bender". +% +The quickest way to a man's heart is with Chuck Norris' fist. +% +The reason why Batman only comes out at night is because he's afraid he might encounter Chuck Norris in the morning and afternoon. +% +The red phone in the oval office rings directly to Chuck Norris' cell phone. +% +The show Survivor had the original premise of putting people on an island with Chuck Norris. There were no survivors, and nobody is brave enough to go to the island to retrieve the footage. +% +The square root of Chuck Norris is pain. Do not try to square Chuck Norris. The result is death. +% +The sun only rises every morning because Chuck Norris allows it to. +% +The truth hurts, doesn't it? Chuck Norris' truth kills. +% +There is no chin behind Chuck Norris' beard. There is only another fist. +% +There is no limbo, only a world that doesn't know of Chuck Norris. +% +There is no such thing as global warming. Chuck Norris was cold, so he turned the sun up. +% +There is no theory of evolution, just a list of creatures Chuck Norris has allowed to live. +% +This one time at band camp... BAM! Chuck Norris. +% +Those who ignore history, are doomed by Chuck Norris. +% +Trick me once, shame on you, trick Chuck Norris.. rest in peace. +% +Unlike Jack Bauer, Chuck Norris doesn't need bullets. A quick roundhouse to the face kills twice as fast. +% +Walker: Texas Ranger went into syndication before the first episode was shot. +% +What was going through the minds of all of Chuck Norris' victims before they died? His shoe. +% +Whatever Chuck Norris wants, it will instantly appear. +% +When Betty White gets angry, she turns into the Hulk. When Valerie Bertinelli gets mad, she turns into Chuck Norris. +% +When Chuck Norris creates a login, it tells him "password not strong enough." He types in his name and it tells him "password too strong." +% +When Chuck Norris does a pushup, he isn't lifting himself up, he's pushing the Earth down. +% +When Chuck Norris drinks water, the water automatically pasteurized. +% +When Chuck Norris goes to Vegas, he doesn't have to gamble. The casinos just give him stacks of money. +% +When Chuck Norris goes to rodeos, bulls ride him. +% +When Chuck Norris goes to the library, he looks for the Guinness book of records in the comedy section. +% +When Chuck Norris inhales helium, his voice doesn't change. +% +When Chuck Norris performs a roundhouse kick, he's actually measuring the circumference of the universe. +% +When Chuck Norris played the card game War with a friend, France surrendered. +% +When Chuck Norris pokes the Pillsbury Doughboy, it's not a laughing matter. +% +When Chuck Norris roundhouse-kicks you, he decides when you will feel the impact. +% +When Chuck Norris sends in his taxes, he sends blank forms and includes only a picture of himself, crouched and ready to attack. Chuck Norris has not had to pay taxes, ever. +% +When Chuck Norris tosses a coin, it lands on both heads and tails. +% +When God said "Let there be light!", Chuck Norris said "Only for half the day." +% +When Presidents speak, their nation listens. When Chuck Norris blinks, the whole world listens. +% +When Steven Seagal kills a ninja, he only takes its hide. When Chuck Norris kills a ninja, he uses every part. +% +When chuck Norris was in school, he made his PE teacher run laps. +% +When does Chuck Norris run out of shotgun bullets? whenever he wants to. +% +When taking the SAT, write "Chuck Norris" for every answer. You will score over 8000. +% +When the Boogeyman goes to sleep every night, he checks his closet for Chuck Norris. +% +When things go bump in the night, it's Chuck Norris +% +While visiting the Hexagon, Chuck Norris was asked to demonstrate his famous roundhouse kick. Henceforth, it has been known as the Pentagon. +% +Why didn't the chicken cross the road? Because Chuck Norris got to it first. +% +You know Chuck Norris' pet lizard, right? Last I heard, he was in the movie "Godzilla". Oh, and his pet turtle starred in "Gamera" as well. +% +http://chucknorrisfacts.com/ is built in Drupal because Chuck Norris knows a good CMS when he sees one. +% +Chuck Norris made the first Giraffe by uppercutting a horse. +% +Chuck Norris can hear sign language. +% +Chuck Norris make onions cry. +% +Chuck Norris doesn't shake hands, he makes them tremble. +% diff --git a/zsh/.oh-my-zsh/plugins/cloudfoundry/README.md b/zsh/.oh-my-zsh/plugins/cloudfoundry/README.md new file mode 100644 index 0000000..dd2b6d4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cloudfoundry/README.md @@ -0,0 +1,58 @@ +# Cloudfoundry Plugin + +This plugin is intended to offer a few simple aliases for regular users of the [Cloud Foundry Cli][1]. Most are just simple aliases that will save a bit of typing. Others include mini functions and or accept parameters. Take a look at the table below for details. + +| Alias | Command | Description | +|----------|-----------------------------|--------------------------------------------------------------------------| +| cfl | `cf login` | Login to Cloud Foundry | +| cft | `cf target` | Target the cli at a specific Org/Space in Cloud Foundry | +| cfa | `cf apps` | List all applications in the current Org/Space | +| cfs | `cf services` | List all services in the current Org/Space | +| cfm | `cf marketplace` | List the services available in the Marketplace | +| cfp | `cf push` | Push your application code to Cloud Foundry | +| cfcs | `cf create-service` | Create a service based on a Marketplace offering | +| cfbs | `cf bind-service` | Bind an application to a service you created | +| cfus | `cf unbind-service` | Unbind a service from an application | +| cfds | `cf delete-service` | Delete a service you no longer have bound | +| cfup | `cf cups` | Create a "user-provided-service" | +| cflg | `cf logs` | Tail the logs of an application (requires ) | +| cfr | `cf routes` | List all the routes in the current Space | +| cfe | `cf env` | Show the environment variables for an application (requires ) | +| cfsh | `cf ssh` | Attach to a running container (requires an etc.) | +| cfsc | `cf scale` | Scale an application (requires an etc.) | +| cfev | `cf events` | Show the application events (requires ) | +| cfdor | `cf delete-orphaned-routes` | Delete routes that are no longer bound to applications | +| cfbpk | `cf buildpacks` | List the available buildpacks | +| cfdm | `cf domains` | List the domains associates with this Cloud Foundry foundation | +| cfsp | `cf spaces` | List all the Spaces in the current Org | +| cfap | `cf app` | Show the details of a deployed application (requires ) | +| cfh. | `export CF_HOME=$PWD/.cf` | Set the current directory as CF_HOME | +| cfh~ | `export CF_HOME=~/.cf` | Set the user's root directory as CF_HOME | +| cfhu | `unset CF_HOME` | Unsets CF_HOME | +| cfpm | `cf push -f` | Push an application using a manifest (requires location) | +| cflr | `cf logs --recent` | Show the recent logs (requires ) | +| cfsrt | `cf start` | Start an application (requires ) | +| cfstp | `cf stop` | Stop an application (requires ) | +| cfstg | `cf restage` | Restage an application (requires ) | +| cfdel | `cf delete` | Delete an application (requires ) | +| cfsrtall | - | Start all apps that are currently in the "Stopped" state | +| cfstpall | - | Stop all apps that are currently in the "Started" state | + +For help and advice on what any of the commands does, consult the built in `cf` help functions as follows:- + +```bash +cf help # List the most popular and commonly used commands +cf help -a # Complete list of all possible commands +cf --help # Help on a specific command including arguments and examples +``` + +Alternatively, seek out the [online documentation][3]. And don't forget, there are loads of great [community plugins for the cf-cli][4] command line tool that can greatly extend its power and usefulness. + +## Contributors + +Contributed to `oh_my_zsh` by [benwilcock][2]. + +[1]: https://docs.cloudfoundry.org/cf-cli/install-go-cli.html +[2]: https://github.com/benwilcock +[3]: https://docs.cloudfoundry.org/cf-cli/getting-started.html +[4]: https://plugins.cloudfoundry.org/ diff --git a/zsh/.oh-my-zsh/plugins/cloudfoundry/cloudfoundry.plugin.zsh b/zsh/.oh-my-zsh/plugins/cloudfoundry/cloudfoundry.plugin.zsh new file mode 100644 index 0000000..b29cce2 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cloudfoundry/cloudfoundry.plugin.zsh @@ -0,0 +1,34 @@ +# Some Useful CloudFoundry Aliases & Functions +alias cfl="cf login" +alias cft="cf target" +alias cfa="cf apps" +alias cfs="cf services" +alias cfm="cf marketplace" +alias cfp="cf push" +alias cfcs="cf create-service" +alias cfbs="cf bind-service" +alias cfus="cf unbind-service" +alias cfds="cf delete-service" +alias cfup="cf cups" +alias cflg="cf logs" +alias cfr="cf routes" +alias cfe="cf env" +alias cfsh="cf ssh" +alias cfsc="cf scale" +alias cfev="cf events" +alias cfdor="cf delete-orphaned-routes" +alias cfbpk="cf buildpacks" +alias cfdm="cf domains" +alias cfsp="cf spaces" +function cfap() { cf app $1 } +function cfh.() { export CF_HOME=$PWD/.cf } +function cfh~() { export CF_HOME=~/.cf } +function cfhu() { unset CF_HOME } +function cfpm() { cf push -f $1 } +function cflr() { cf logs $1 --recent } +function cfsrt() { cf start $1 } +function cfstp() { cf stop $1 } +function cfstg() { cf restage $1 } +function cfdel() { cf delete $1 } +function cfsrtall() {cf apps | awk '/stopped/ { system("cf start " $1)}'} +function cfstpall() {cf apps | awk '/started/ { system("cf stop " $1)}'} diff --git a/zsh/.oh-my-zsh/plugins/codeclimate/README.md b/zsh/.oh-my-zsh/plugins/codeclimate/README.md new file mode 100644 index 0000000..05fe5c0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/codeclimate/README.md @@ -0,0 +1,8 @@ +# codeclimate plugin + +This plugin adds autocompletion for the [`codeclimate` CLI](https://github.com/codeclimate/codeclimate). + +To use it, add `codeclimate` to the plugins array in your zshrc file: +```zsh +plugins=(... codeclimate) +``` diff --git a/zsh/.oh-my-zsh/plugins/codeclimate/_codeclimate b/zsh/.oh-my-zsh/plugins/codeclimate/_codeclimate new file mode 100644 index 0000000..afb157f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/codeclimate/_codeclimate @@ -0,0 +1,82 @@ +#compdef codeclimate + +_codeclimate_all_engines() { + engines_all=(`codeclimate engines:list | tail -n +2 | gawk '{ print $2 }' | gawk -F: '{ print $1 }'`) +} + +_codeclimate_installed_engines() { + _codeclimate_all_engines + + engines_installed=() + + if [ -e .codeclimate.yml ] + then + for engine in $engines_all + do + if grep -q $engine ".codeclimate.yml" + then + engines_installed+=$engine + fi + done + fi +} + +_codeclimate_not_installed_engines() { + _codeclimate_all_engines + + engines_not_installed=() + + if [ -e .codeclimate.yml ] + then + for engine in $engines_all + do + if ! grep -q $engine ".codeclimate.yml" + then + engines_not_installed+=$engine + fi + done + fi +} + +local curcontext="$curcontext" state line ret=1 +local expl +local -a engines_all engines_installed engines_not_installed + +_arguments \ + '1: :->cmds' \ + '*:: :->args' && ret=0 + +case $state in + cmds) + _values "bundle command" \ + "analyze[Analyze all relevant files in the current working directory]" \ + "console[Start an interactive session providing access to the classes within the CLI]" \ + "engines\:disable[Prevents the engine from being used in this project]" \ + "engines\:enable[This engine will be run the next time your project is analyzed]" \ + "engines\:install[Compares the list of engines in your .codeclimate.yml file to those that are currently installed, then installs any missing engines]" \ + "engines\:list[Lists all available engines in the Code Climate Docker Hub]" \ + "engines\:remove[Removes an engine from your .codeclimate.yml file]" \ + "help[Displays a list of commands that can be passed to the Code Climate CLI]" \ + "init[Generates a new .codeclimate.yml file in the current working directory]" \ + "validate-config[Validates the .codeclimate.yml file in the current working directory]" \ + "version[Displays the current version of the Code Climate CLI]" + ret=0 + ;; + args) + case $line[1] in + engines:enable) + _codeclimate_not_installed_engines + _wanted engines_not_installed expl 'not installed engines' compadd -a engines_not_installed ;; + engines:disable|engines:remove) + _codeclimate_installed_engines + _wanted engines_installed expl 'installed engines' compadd -a engines_installed ;; + analyze) + _arguments \ + '-f:Output Format:(text json)' + ret=0 + ;; + esac + ;; +esac + +return ret diff --git a/zsh/.oh-my-zsh/plugins/coffee/README.md b/zsh/.oh-my-zsh/plugins/coffee/README.md new file mode 100644 index 0000000..3625871 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/coffee/README.md @@ -0,0 +1,31 @@ +# Coffeescript Plugin + +This plugin provides aliases for quickly compiling and previewing your +coffeescript code. + +When writing Coffeescript it's very common to want to preview the output of a +certain snippet of code, either because you want to test the output or because +you'd like to execute it in a browser console which doesn't accept Coffeescript. + +Preview the compiled result of your coffeescript with `cf "code"` as per the +following: + +```zsh +$ cf 'if a then b else c' +if (a) { + b; +} else { + c; +} +``` + +Also provides the following aliases: + +* **cfc:** Copies the compiled JS to your clipboard. Very useful when you want + to run the code in a JS console. + +* **cfp:** Compiles from your currently copied clipboard. Useful when you want + to compile large/multi-line snippets + +* **cfpc:** Paste coffeescript from clipboard, compile to JS, then copy the + the result back to clipboard. diff --git a/zsh/.oh-my-zsh/plugins/coffee/_coffee b/zsh/.oh-my-zsh/plugins/coffee/_coffee new file mode 100644 index 0000000..c4e25e6 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/coffee/_coffee @@ -0,0 +1,81 @@ +#compdef coffee +# ------------------------------------------------------------------------------ +# Copyright (c) 2011 GitHub zsh-users - https://github.com/zsh-users +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the zsh-users nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL ZSH-USERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ------------------------------------------------------------------------------ +# Description +# ----------- +# +# Completion script for Coffee.js v0.6.11 (https://coffeescript.org) +# +# ------------------------------------------------------------------------------ +# Authors +# ------- +# +# * Mario Fernandez (https://github.com/sirech) +# * Dong Weiming (https://github.com/dongweiming) +# +# ------------------------------------------------------------------------------ + +local curcontext="$curcontext" state line ret=1 version +local -a opts +typeset -A opt_args +version=(${(f)"$(_call_program version $words[1] --version)"}) || return ret +version=${${(z)${version[1]}}[3]} + +autoload -Uz is-at-least +if ! is-at-least 1.6.3 "$version"; then + opts+=('(-l --lint)'{-l,--lint}'[pipe the compiled JavaScript through JavaScript Lint]' + '(-r --require)'{-r,--require}'[require a library before executing your script]:library') +fi + + +_arguments -C \ + '(- *)'{-h,--help}'[display this help message]' \ + '(- *)'{-v,--version}'[display the version number]' \ + $opts \ + '(-b --bare)'{-b,--bare}'[compile without a top-level function wrapper]' \ + '(-e --eval)'{-e,--eval}'[pass a string from the command line as input]:Inline Script' \ + '(-i --interactive)'{-i,--interactive}'[run an interactive CoffeeScript REPL]' \ + '(-j --join)'{-j,--join}'[concatenate the source CoffeeScript before compiling]:Destination JS file:_files -g "*.js"' \ + '(--nodejs)--nodejs[pass options directly to the "node" binary]' \ + '(-c --compile)'{-c,--compile}'[compile to JavaScript and save as .js files]' \ + '(-o --output)'{-o,--output}'[set the output directory for compiled JavaScript]:Output Directory:_files -/' \ + '(-n -t -p)'{-n,--nodes}'[print out the parse tree that the parser produces]' \ + '(-n -t -p)'{-p,--print}'[print out the compiled JavaScript]' \ + '(-n -t -p)'{-t,--tokens}'[print out the tokens that the lexer/rewriter produce]' \ + '(-s --stdio)'{-s,--stdio}'[listen for and compile scripts over stdio]' \ + '(-w --watch)'{-w,--watch}'[watch scripts for changes and rerun commands]' \ + '*:script or directory:_files' && ret=0 + +return ret + +# Local Variables: +# mode: Shell-Script +# sh-indentation: 2 +# indent-tabs-mode: nil +# sh-basic-offset: 2 +# End: +# vim: ft=zsh sw=2 ts=2 et diff --git a/zsh/.oh-my-zsh/plugins/coffee/coffee.plugin.zsh b/zsh/.oh-my-zsh/plugins/coffee/coffee.plugin.zsh new file mode 100644 index 0000000..9c6ccf0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/coffee/coffee.plugin.zsh @@ -0,0 +1,16 @@ +#!/bin/zsh + +# compile a string of coffeescript and print to output +cf () { + coffee -peb "$1" +} +# compile & copy to clipboard +cfc () { + cf "$1" | clipcopy +} + +# compile from clipboard & print +alias cfp='cf "$(clippaste)"' + +# compile from clipboard and copy to clipboard +alias cfpc='cfp | clipcopy' diff --git a/zsh/.oh-my-zsh/plugins/colemak/.gitignore b/zsh/.oh-my-zsh/plugins/colemak/.gitignore new file mode 100644 index 0000000..e9d1b4c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/colemak/.gitignore @@ -0,0 +1 @@ +.less diff --git a/zsh/.oh-my-zsh/plugins/colemak/README.md b/zsh/.oh-my-zsh/plugins/colemak/README.md new file mode 100644 index 0000000..ee42387 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/colemak/README.md @@ -0,0 +1,48 @@ +# Colemak plugin + +This plugin remaps keys in `zsh`'s [`vi`-style navigation mode](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Keymaps) +for a [Colemak](https://colemak.com/) keyboard layout, to match the QWERTY position: + +![Colemak layout on a US keyboard](https://colemak.com/wiki/images/6/6c/Colemak2.png) + +To use it, add it to the plugins array in your `~/.zshrc` file: + +``` +plugins=(... colemak) +``` + +You will also need to enable `vi` mode, so add another line to `~/.zshrc`: +``` +bindkey -v +``` + +Restart your shell and hit the `` key to activate `vicmd` (navigation) mode, +and start navigating `zsh` with your new keybindings! + +## Key bindings for vicmd + +| Old | New | Binding | Description | +|------------|------------|---------------------------|----------------------------------------------------| +| `CTRL`+`j` | `CTRL`+`n` | accept-line | Insert new line | +| `j` | `n` | down-line-or-history | Move one line down or command history forwards | +| `k` | `e` | up-line-or-history | Move one line up or command history backwards | +| `l` | `i` | vi-forward-char | Move one character to the right | +| `n` | `k` | vi-repeat-search | Repeat command search forwards | +| `N` | `K` | vi-rev-repeat-search | Repeat command search backwards | +| `i` | `u` | vi-insert | Enter insert mode | +| `I` | `U` | vi-insert-bol | Move to first non-blank char and enter insert mode | +| `` | `l` | vi-undo-change | Undo change | +| `J` | `N` | vi-join | Join the current line with the next one | +| `e` | `j` | vi-forward-word-end | Move to the end of the next word | +| `E` | `J` | vi-forward-blank-word-end | Move to end of the current or next word | + +## Key bindings for less + +| Keyboard shortcut | `less` key binding | +|-------------------|--------------------| +| `n` | forw-line | +| `e` | back-line | +| `k` | repeat-search | +| `ESC`+`k` | repeat-search-all | +| `K` | reverse-search | +| `ESC`+`K` | reverse-search-all | diff --git a/zsh/.oh-my-zsh/plugins/colemak/colemak-less b/zsh/.oh-my-zsh/plugins/colemak/colemak-less new file mode 100644 index 0000000..2276b20 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/colemak/colemak-less @@ -0,0 +1,6 @@ +n forw-line +e back-line +k repeat-search +\ek repeat-search-all +K reverse-search +\eK reverse-search-all diff --git a/zsh/.oh-my-zsh/plugins/colemak/colemak.plugin.zsh b/zsh/.oh-my-zsh/plugins/colemak/colemak.plugin.zsh new file mode 100644 index 0000000..299985e --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/colemak/colemak.plugin.zsh @@ -0,0 +1,38 @@ +# ctrl-j newline +bindkey '^n' accept-line +bindkey -a '^n' accept-line + +# another rotation to match qwerty +bindkey -a 'n' down-line-or-history +bindkey -a 'e' up-line-or-history +bindkey -a 'i' vi-forward-char + +# make qwerty +bindkey -a 'k' vi-repeat-search +bindkey -a 'K' vi-rev-repeat-search +bindkey -a 'u' vi-insert +bindkey -a 'U' vi-insert-bol +bindkey -a 'l' vi-undo-change +bindkey -a 'N' vi-join + +# spare +bindkey -a 'j' vi-forward-word-end +bindkey -a 'J' vi-forward-blank-word-end + +# Handle $0 according to the standard: +# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" + +# New less versions will read this file directly +export LESSKEYIN="${0:h:A}/colemak-less" + +# Only run lesskey if less version is older than v582 +less_ver=$(less --version | awk '{print $2;exit}') +autoload -Uz is-at-least +if ! is-at-least 582 $less_ver; then + # Old less versions will read this transformed file + export LESSKEY="${0:h:A}/.less" + lesskey -o "$LESSKEY" "$LESSKEYIN" 2>/dev/null +fi +unset less_ver diff --git a/zsh/.oh-my-zsh/plugins/colored-man-pages/README.md b/zsh/.oh-my-zsh/plugins/colored-man-pages/README.md new file mode 100644 index 0000000..dfcd8e0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/colored-man-pages/README.md @@ -0,0 +1,32 @@ +# Colored man pages plugin + +This plugin adds colors to man pages. + +To use it, add `colored-man-pages` to the plugins array in your zshrc file: + +```zsh +plugins=(... colored-man-pages) +``` + +It will also automatically colorize man pages displayed by `dman` or `debman`, +from [`debian-goodies`](https://packages.debian.org/stable/debian-goodies). + +You can also try to color other pages by prefixing the respective command with `colored`: + +```zsh +colored git help clone +``` + +## Customization + +The plugin declares global associative array `less_termcap`, which maps termcap capabilities to escape +sequences for the `less` pager. This mapping can be further customized by the user after the plugin is +loaded. Check out sources for more. + +For example: `less_termcap[md]` maps to `LESS_TERMCAP_md` which is the escape sequence that tells `less` +how to print something in bold. It's currently shown in bold red, but if you want to change it, you +can redefine `less_termcap[md]` in your zshrc file, after OMZ is sourced: + +```zsh +less_termcap[md]="${fg_bold[blue]}" # this tells less to print bold text in bold blue +``` diff --git a/zsh/.oh-my-zsh/plugins/colored-man-pages/colored-man-pages.plugin.zsh b/zsh/.oh-my-zsh/plugins/colored-man-pages/colored-man-pages.plugin.zsh new file mode 100644 index 0000000..1045c7d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/colored-man-pages/colored-man-pages.plugin.zsh @@ -0,0 +1,54 @@ +# Requires colors autoload. +# See termcap(5). + +# Set up once, and then reuse. This way it supports user overrides after the +# plugin is loaded. +typeset -AHg less_termcap + +# bold & blinking mode +less_termcap[mb]="${fg_bold[red]}" +less_termcap[md]="${fg_bold[red]}" +less_termcap[me]="${reset_color}" +# standout mode +less_termcap[so]="${fg_bold[yellow]}${bg[blue]}" +less_termcap[se]="${reset_color}" +# underlining +less_termcap[us]="${fg_bold[green]}" +less_termcap[ue]="${reset_color}" + +# Handle $0 according to the standard: +# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" + +# Absolute path to this file's directory. +typeset -g __colored_man_pages_dir="${0:A:h}" + +function colored() { + local -a environment + + # Convert associative array to plain array of NAME=VALUE items. + local k v + for k v in "${(@kv)less_termcap}"; do + environment+=( "LESS_TERMCAP_${k}=${v}" ) + done + + # Prefer `less` whenever available, since we specifically configured + # environment for it. + environment+=( PAGER="${commands[less]:-$PAGER}" ) + environment+=( GROFF_NO_SGR=1 ) + + # See ./nroff script. + if [[ "$OSTYPE" = solaris* ]]; then + environment+=( PATH="${__colored_man_pages_dir}:$PATH" ) + fi + + command env $environment "$@" +} + +# Colorize man and dman/debman (from debian-goodies) +function man \ + dman \ + debman { + colored $0 "$@" +} diff --git a/zsh/.oh-my-zsh/plugins/colored-man-pages/nroff b/zsh/.oh-my-zsh/plugins/colored-man-pages/nroff new file mode 100755 index 0000000..1dd8c0d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/colored-man-pages/nroff @@ -0,0 +1,12 @@ +#!/bin/sh + +# The whole point of this wrapper is to replace emboldening factor -u0 with +# -u1 under certain circumstances on Solaris. + +if [ "$1,$2,$3" = "-u0,-Tlp,-man" ]; then + shift + exec /usr/bin/nroff -u1 "$@" +else + # Some other invocation of nroff + exec /usr/bin/nroff "$@" +fi diff --git a/zsh/.oh-my-zsh/plugins/colorize/README.md b/zsh/.oh-my-zsh/plugins/colorize/README.md new file mode 100644 index 0000000..ece86f2 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/colorize/README.md @@ -0,0 +1,56 @@ +# colorize + +With this plugin you can syntax-highlight file contents of over 300 supported languages and other text formats. + +Colorize will highlight the content based on the filename extension. If it can't find a syntax-highlighting +method for a given extension, it will try to find one by looking at the file contents. If no highlight method +is found it will just cat the file normally, without syntax highlighting. + +## Setup + +To use it, add colorize to the plugins array of your `~/.zshrc` file: +``` +plugins=(... colorize) +``` + +## Configuration + +### Requirements + +This plugin requires that at least one of the following tools is installed: + +* [Chroma](https://github.com/alecthomas/chroma) +* [Pygments](https://pygments.org/download/) + +### Colorize tool + +Colorize supports `pygmentize` and `chroma` as syntax highlighter. By default colorize uses `pygmentize` unless it's not installed and `chroma` is. This can be overridden by the `ZSH_COLORIZE_TOOL` environment variable: + +``` +ZSH_COLORIZE_TOOL=chroma +``` + +### Styles + +Pygments offers multiple styles. By default, the `default` style is used, but you can choose another theme by setting the `ZSH_COLORIZE_STYLE` environment variable: + +``` +ZSH_COLORIZE_STYLE="colorful" +``` + +### Chroma Formatter Settings + +Chroma supports terminal output in 8 color, 256 color, and true-color. If you need to change the default terminal output style from the standard 8 color output, set the `ZSH_COLORIZE_CHROMA_FORMATTER` environment variable: + +``` +ZSH_COLORIZE_CHROMA_FORMATTER=terminal256 +``` + +## Usage + +* `ccat [files]`: colorize the contents of the file (or files, if more than one are provided). + If no files are passed it will colorize the standard input. + +* `cless [less-options] [files]`: colorize the contents of the file (or files, if more than one are provided) and open less. + If no files are passed it will colorize the standard input. + The LESSOPEN and LESSCLOSE will be overwritten for this to work, but only in a local scope. diff --git a/zsh/.oh-my-zsh/plugins/colorize/colorize.plugin.zsh b/zsh/.oh-my-zsh/plugins/colorize/colorize.plugin.zsh new file mode 100644 index 0000000..4f0e6f9 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/colorize/colorize.plugin.zsh @@ -0,0 +1,114 @@ +# Easier alias to use the plugin +alias ccat="colorize_cat" +alias cless="colorize_less" + +# '$0:A' gets the absolute path of this file +ZSH_COLORIZE_PLUGIN_PATH=$0:A + +colorize_check_requirements() { + local -a available_tools + available_tools=("chroma" "pygmentize") + + if [ -z "$ZSH_COLORIZE_TOOL" ]; then + if (( $+commands[pygmentize] )); then + ZSH_COLORIZE_TOOL="pygmentize" + elif (( $+commands[chroma] )); then + ZSH_COLORIZE_TOOL="chroma" + else + echo "Neither 'pygments' nor 'chroma' is installed!" >&2 + return 1 + fi + fi + + if [[ ${available_tools[(Ie)$ZSH_COLORIZE_TOOL]} -eq 0 ]]; then + echo "ZSH_COLORIZE_TOOL '$ZSH_COLORIZE_TOOL' not recognized. Available options are 'pygmentize' and 'chroma'." >&2 + return 1 + elif ! (( $+commands[$ZSH_COLORIZE_TOOL] )); then + echo "Package '$ZSH_COLORIZE_TOOL' is not installed!" >&2 + return 1 + fi +} + +colorize_cat() { + if ! colorize_check_requirements; then + return 1 + fi + + # If the environment variable ZSH_COLORIZE_STYLE + # is set, use that theme instead. Otherwise, + # use the default. + if [ -z "$ZSH_COLORIZE_STYLE" ]; then + # Both pygmentize & chroma support 'emacs' + ZSH_COLORIZE_STYLE="emacs" + fi + + # Use stdin if no arguments have been passed. + if [ $# -eq 0 ]; then + if [[ "$ZSH_COLORIZE_TOOL" == "pygmentize" ]]; then + pygmentize -O style="$ZSH_COLORIZE_STYLE" -g + else + chroma --style="$ZSH_COLORIZE_STYLE" --formatter="${ZSH_COLORIZE_CHROMA_FORMATTER:-terminal}" + fi + return $? + fi + + # Guess lexer from file extension, or guess it from file contents if unsuccessful. + local FNAME lexer + for FNAME in "$@"; do + if [[ "$ZSH_COLORIZE_TOOL" == "pygmentize" ]]; then + lexer=$(pygmentize -N "$FNAME") + if [[ $lexer != text ]]; then + pygmentize -O style="$ZSH_COLORIZE_STYLE" -l "$lexer" "$FNAME" + else + pygmentize -O style="$ZSH_COLORIZE_STYLE" -g "$FNAME" + fi + else + chroma --style="$ZSH_COLORIZE_STYLE" --formatter="${ZSH_COLORIZE_CHROMA_FORMATTER:-terminal}" "$FNAME" + fi + done +} + +# The less option 'F - Forward forever; like "tail -f".' will not work in this implementation +# caused by the lack of the ability to follow the file within pygmentize. +colorize_less() { + if ! colorize_check_requirements; then + return 1 + fi + + _cless() { + # LESS="-R $LESS" enables raw ANSI colors, while maintain already set options. + local LESS="-R $LESS" + + # This variable tells less to pipe every file through the specified command + # (see the man page of less INPUT PREPROCESSOR). + # 'zsh -ic "colorize_cat %s 2> /dev/null"' would not work for huge files like + # the ~/.zsh_history. For such files the tty of the preprocessor will be suspended. + # Therefore we must source this file to make colorize_cat available in the + # preprocessor without the interactive mode. + # `2>/dev/null` will suppress the error for large files 'broken pipe' of the python + # script pygmentize, which will show up if less has not fully "loaded the file" + # (e.g. when not scrolled to the bottom) while already the next file will be displayed. + local LESSOPEN="| zsh -c 'source \"$ZSH_COLORIZE_PLUGIN_PATH\"; \ + ZSH_COLORIZE_TOOL=$ZSH_COLORIZE_TOOL ZSH_COLORIZE_STYLE=$ZSH_COLORIZE_STYLE \ + colorize_cat %s 2> /dev/null'" + + # LESSCLOSE will be set to prevent any errors by executing a user script + # which assumes that his LESSOPEN has been executed. + local LESSCLOSE="" + + LESS="$LESS" LESSOPEN="$LESSOPEN" LESSCLOSE="$LESSCLOSE" command less "$@" + } + + if [ -t 0 ]; then + _cless "$@" + else + # The input is not associated with a terminal, therefore colorize_cat will + # colorize this input and pass it to less. + # Less has now to decide what to use. If any files have been provided, less + # will ignore the input by default, otherwise the colorized input will be used. + # If files have been supplied and the input has been redirected, this will + # lead to unnecessary overhead, but retains the ability to use the less options + # without checking for them inside this script. + colorize_cat | _cless "$@" + fi +} diff --git a/zsh/.oh-my-zsh/plugins/command-not-found/README.md b/zsh/.oh-my-zsh/plugins/command-not-found/README.md new file mode 100644 index 0000000..0a11892 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/command-not-found/README.md @@ -0,0 +1,34 @@ +# command-not-found plugin + +This plugin uses the command-not-found package for zsh to provide suggested packages to be installed if a command cannot be found. + +To use it, add `command-not-found` to the plugins array of your zshrc file: + +```zsh +plugins=(... command-not-found) +``` + +An example of how this plugin works in Ubuntu: +``` +$ mutt +The program 'mutt' can be found in the following packages: + * mutt + * mutt-kz + * mutt-patched +Try: sudo apt install +``` + +### Supported platforms + +It works out of the box with the command-not-found packages for: + +- [Ubuntu](https://www.porcheron.info/command-not-found-for-zsh/) +- [Debian](https://packages.debian.org/search?keywords=command-not-found) +- [Arch Linux](https://wiki.archlinux.org/index.php/Pkgfile#Command_not_found) +- [macOS (Homebrew)](https://github.com/Homebrew/homebrew-command-not-found) +- [Fedora](https://fedoraproject.org/wiki/Features/PackageKitCommandNotFound) +- [NixOS](https://github.com/NixOS/nixpkgs/tree/master/nixos/modules/programs/command-not-found) +- [Termux](https://github.com/termux/command-not-found) +- [SUSE](https://www.unix.com/man-page/suse/1/command-not-found/) + +You can add support for other platforms by submitting a Pull Request. diff --git a/zsh/.oh-my-zsh/plugins/command-not-found/command-not-found.plugin.zsh b/zsh/.oh-my-zsh/plugins/command-not-found/command-not-found.plugin.zsh new file mode 100644 index 0000000..23bc4f9 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/command-not-found/command-not-found.plugin.zsh @@ -0,0 +1,70 @@ +## Platforms with a built-in command-not-found handler init file + +for file ( + # Arch Linux. Must have pkgfile installed: https://wiki.archlinux.org/index.php/Pkgfile#Command_not_found + /usr/share/doc/pkgfile/command-not-found.zsh + # Homebrew: https://github.com/Homebrew/homebrew-command-not-found + /opt/homebrew/Library/Taps/homebrew/homebrew-command-not-found/handler.sh + /usr/local/Homebrew/Library/Taps/homebrew/homebrew-command-not-found/handler.sh + /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-command-not-found/handler.sh +); do + if [[ -r "$file" ]]; then + source "$file" + unset file + return 0 + fi +done +unset file + + +## Platforms with manual command_not_found_handler() setup + +# Debian and derivatives: https://launchpad.net/ubuntu/+source/command-not-found +if [[ -x /usr/lib/command-not-found || -x /usr/share/command-not-found/command-not-found ]]; then + command_not_found_handler() { + if [[ -x /usr/lib/command-not-found ]]; then + /usr/lib/command-not-found -- "$1" + return $? + elif [[ -x /usr/share/command-not-found/command-not-found ]]; then + /usr/share/command-not-found/command-not-found -- "$1" + return $? + else + printf "zsh: command not found: %s\n" "$1" >&2 + return 127 + fi + } +fi + +# Fedora: https://fedoraproject.org/wiki/Features/PackageKitCommandNotFound +if [[ -x /usr/libexec/pk-command-not-found ]]; then + command_not_found_handler() { + if [[ -S /var/run/dbus/system_bus_socket && -x /usr/libexec/packagekitd ]]; then + /usr/libexec/pk-command-not-found "$@" + return $? + fi + + printf "zsh: command not found: %s\n" "$1" >&2 + return 127 + } +fi + +# NixOS: https://github.com/NixOS/nixpkgs/tree/master/nixos/modules/programs/command-not-found +if [[ -x /run/current-system/sw/bin/command-not-found ]]; then + command_not_found_handler() { + /run/current-system/sw/bin/command-not-found "$@" + } +fi + +# Termux: https://github.com/termux/command-not-found +if [[ -x /data/data/com.termux/files/usr/libexec/termux/command-not-found ]]; then + command_not_found_handler() { + /data/data/com.termux/files/usr/libexec/termux/command-not-found "$1" + } +fi + +# SUSE and derivates: https://www.unix.com/man-page/suse/1/command-not-found/ +if [[ -x /usr/bin/command-not-found ]]; then + command_not_found_handler() { + /usr/bin/command-not-found "$1" + } +fi diff --git a/zsh/.oh-my-zsh/plugins/common-aliases/README.md b/zsh/.oh-my-zsh/plugins/common-aliases/README.md new file mode 100644 index 0000000..f279c69 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/common-aliases/README.md @@ -0,0 +1,130 @@ +# Common Aliases Plugin + +This plugin creates helpful shortcut aliases for many commonly used commands. + +To use it add `common-aliases` to the plugins array in your zshrc file: + +```zsh +plugins=(... common-aliases) +``` + +## Aliases + +### ls command + +| Alias | Command | Description | +| ----- | ------------ | --------------------------------------------------------------------------- | +| l | `ls -lFh` | List files as a long list, show size, type, human-readable | +| la | `ls -lAFh` | List almost all files as a long list show size, type, human-readable | +| lr | `ls -tRFh` | List files recursively sorted by date, show type, human-readable | +| lt | `ls -ltFh` | List files as a long list sorted by date, show type, human-readable | +| ll | `ls -l` | List files as a long list | +| ldot | `ls -ld .*` | List dot files as a long list | +| lS | `ls -1FSsh` | List files showing only size and name sorted by size | +| lart | `ls -1Fcart` | List all files sorted in reverse of create/modification time (oldest first) | +| lrt | `ls -1Fcrt` | List files sorted in reverse of create/modification time(oldest first) | +| lsr | `ls -lARFh` | List all files and directories recursively | +| lsn | `ls -1` | List files and directories in a single column | + +### File handling + +| Alias | Command | Description | +| ----- | --------------------- | ------------------------------------------------------------------------------- | +| rm | `rm -i` | Remove a file | +| cp | `cp -i` | Copy a file | +| mv | `mv -i` | Move a file | +| zshrc | `${=EDITOR} ~/.zshrc` | Quickly access the ~/.zshrc file | +| dud | `du -d 1 -h` | Display the size of files at depth 1 in current location in human-readable form | +| duf\* | `du -sh` | Display the size of files in current location in human-readable form | +| t | `tail -f` | Shorthand for tail which outputs the last part of a file | + +\* Only if the [`duf`](https://github.com/muesli/duf) command isn't installed. + +### find and grep + +| Alias | Command | Description | +| ----- | -------------------------------------------------- | ------------------------------------ | +| fd\* | `find . -type d -name` | Find a directory with the given name | +| ff | `find . -type f -name` | Find a file with the given name | +| grep | `grep --color` | Searches for a query string | +| sgrep | `grep -R -n -H -C 5 --exclude-dir={.git,.svn,CVS}` | Useful for searching within files | + +\* Only if the [`fd`](https://github.com/sharkdp/fd) command isn't installed. + +### Other Aliases + +| Alias | Command | Description | +| -------- | ------------------ | ----------------------------------------------------------- | +| h | `history` | Lists all recently used commands | +| hgrep | `fc -El 0 \| grep` | Searches for a word in the list of previously used commands | +| help | `man` | Opens up the man page for a command | +| p | `ps -f` | Displays currently executing processes | +| sortnr | `sort -n -r` | Used to sort the lines of a text file | +| unexport | `unset` | Used to unset an environment variable | + +## Global aliases + +These aliases are expanded in any position in the command line, meaning you can use them even at the +end of the command you've typed. Examples: + +Quickly pipe to less: + +```zsh +$ ls -l /var/log L +# will run +$ ls -l /var/log | less +``` + +Silences stderr output: + +```zsh +$ find . -type f NE +# will run +$ find . -type f 2>/dev/null +``` + +| Alias | Command | Description | +| ----- | --------------------------- | ----------------------------------------------------------- | +| H | `\| head` | Pipes output to head which outputs the first part of a file | +| T | `\| tail` | Pipes output to tail which outputs the last part of a file | +| G | `\| grep` | Pipes output to grep to search for some word | +| L | `\| less` | Pipes output to less, useful for paging | +| M | `\| most` | Pipes output to more, useful for paging | +| LL | `2>&1 \| less` | Writes stderr to stdout and passes it to less | +| CA | `2>&1 \| cat -A` | Writes stderr to stdout and passes it to cat | +| NE | `2 > /dev/null` | Silences stderr | +| NUL | `> /dev/null 2>&1` | Silences both stdout and stderr | +| P | `2>&1\| pygmentize -l pytb` | Writes stderr to stdout and passes it to pygmentize | + +## File extension aliases + +These are special aliases that are triggered when a file name is passed as the command. For example, +if the pdf file extension is aliased to `acroread` (a popular Linux pdf reader), when running `file.pdf` +that file will be open with `acroread`. + +### Reading Docs + +| Alias | Command | Description | +| ----- | ---------- | ---------------------------------- | +| pdf | `acroread` | Opens up a document using acroread | +| ps | `gv` | Opens up a .ps file using gv | +| dvi | `xdvi` | Opens up a .dvi file using xdvi | +| chm | `xchm` | Opens up a .chm file using xchm | +| djvu | `djview` | Opens up a .djvu file using djview | + +### Listing files inside a packed file + +| Alias | Command | Description | +| ------ | ---------- | --------------------------------- | +| zip | `unzip -l` | Lists files inside a .zip file | +| rar | `unrar l` | Lists files inside a .rar file | +| tar | `tar tf` | Lists files inside a .tar file | +| tar.gz | `echo` | Lists files inside a .tar.gz file | +| ace | `unace l` | Lists files inside a .ace file | + +### Some other features + +- Opens urls in terminal using browser specified by the variable `$BROWSER` +- Opens C, C++, Tex and text files using editor specified by the variable `$EDITOR` +- Opens images using image viewer specified by the variable `$XIVIEWER` +- Opens videos and other media using mplayer diff --git a/zsh/.oh-my-zsh/plugins/common-aliases/common-aliases.plugin.zsh b/zsh/.oh-my-zsh/plugins/common-aliases/common-aliases.plugin.zsh new file mode 100644 index 0000000..3a2ee7a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/common-aliases/common-aliases.plugin.zsh @@ -0,0 +1,90 @@ +# Advanced Aliases. +# Use with caution +# + +# ls, the common ones I use a lot shortened for rapid fire usage +alias l='ls -lFh' #size,show type,human readable +alias la='ls -lAFh' #long list,show almost all,show type,human readable +alias lr='ls -tRFh' #sorted by date,recursive,show type,human readable +alias lt='ls -ltFh' #long list,sorted by date,show type,human readable +alias ll='ls -l' #long list +alias ldot='ls -ld .*' +alias lS='ls -1FSsh' +alias lart='ls -1Fcart' +alias lrt='ls -1Fcrt' +alias lsr='ls -lARFh' #Recursive list of files and directories +alias lsn='ls -1' #A column contains name of files and directories + +alias zshrc='${=EDITOR} ${ZDOTDIR:-$HOME}/.zshrc' # Quick access to the .zshrc file + +alias grep='grep --color' +alias sgrep='grep -R -n -H -C 5 --exclude-dir={.git,.svn,CVS} ' + +alias t='tail -f' + +# Command line head / tail shortcuts +alias -g H='| head' +alias -g T='| tail' +alias -g G='| grep' +alias -g L="| less" +alias -g M="| most" +alias -g LL="2>&1 | less" +alias -g CA="2>&1 | cat -A" +alias -g NE="2> /dev/null" +alias -g NUL="> /dev/null 2>&1" +alias -g P="2>&1| pygmentize -l pytb" + +alias dud='du -d 1 -h' +(( $+commands[duf] )) || alias duf='du -sh *' +(( $+commands[fd] )) || alias fd='find . -type d -name' +alias ff='find . -type f -name' + +alias h='history' +alias hgrep="fc -El 0 | grep" +alias help='man' +alias p='ps -f' +alias sortnr='sort -n -r' +alias unexport='unset' + +alias rm='rm -i' +alias cp='cp -i' +alias mv='mv -i' + +# zsh is able to auto-do some kungfoo +# depends on the SUFFIX :) +autoload -Uz is-at-least +if is-at-least 4.2.0; then + # open browser on urls + if [[ -n "$BROWSER" ]]; then + _browser_fts=(htm html de org net com at cx nl se dk) + for ft in $_browser_fts; do alias -s $ft='$BROWSER'; done + fi + + _editor_fts=(cpp cxx cc c hh h inl asc txt TXT tex) + for ft in $_editor_fts; do alias -s $ft='$EDITOR'; done + + if [[ -n "$XIVIEWER" ]]; then + _image_fts=(jpg jpeg png gif mng tiff tif xpm) + for ft in $_image_fts; do alias -s $ft='$XIVIEWER'; done + fi + + _media_fts=(ape avi flv m4a mkv mov mp3 mpeg mpg ogg ogm rm wav webm) + for ft in $_media_fts; do alias -s $ft=mplayer; done + + #read documents + alias -s pdf=acroread + alias -s ps=gv + alias -s dvi=xdvi + alias -s chm=xchm + alias -s djvu=djview + + #list whats inside packed file + alias -s zip="unzip -l" + alias -s rar="unrar l" + alias -s tar="tar tf" + alias -s tar.gz="echo " + alias -s ace="unace l" +fi + +# Make zsh know about hosts already accessed by SSH +zstyle -e ':completion:*:(ssh|scp|sftp|rsh|rsync):hosts' hosts 'reply=(${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) /dev/null)"}%%[# ]*}//,/ })' diff --git a/zsh/.oh-my-zsh/plugins/compleat/README.md b/zsh/.oh-my-zsh/plugins/compleat/README.md new file mode 100644 index 0000000..acc1e7d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/compleat/README.md @@ -0,0 +1,9 @@ +# compleat plugin + +This plugin looks for [compleat](https://github.com/mbrubeck/compleat) and loads its completion. + +To use it, add compleat to the plugins array in your zshrc file: + +```zsh +plugins=(... compleat) +``` diff --git a/zsh/.oh-my-zsh/plugins/compleat/compleat.plugin.zsh b/zsh/.oh-my-zsh/plugins/compleat/compleat.plugin.zsh new file mode 100644 index 0000000..0854fd0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/compleat/compleat.plugin.zsh @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------------------ +# FILE: compleat.plugin.zsh +# DESCRIPTION: oh-my-zsh plugin file. +# AUTHOR: Sorin Ionescu (sorin.ionescu@gmail.com) +# VERSION: 1.0.0 +# ------------------------------------------------------------------------------ + +if (( ${+commands[compleat]} )); then + local prefix="${commands[compleat]:h:h}" + local setup="${prefix}/share/compleat-1.0/compleat_setup" + + if [[ -f "$setup" ]]; then + if ! bashcompinit >/dev/null 2>&1; then + autoload -U bashcompinit + bashcompinit -i + fi + + source "$setup" + fi +fi diff --git a/zsh/.oh-my-zsh/plugins/composer/README.md b/zsh/.oh-my-zsh/plugins/composer/README.md new file mode 100644 index 0000000..26f7b36 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/composer/README.md @@ -0,0 +1,35 @@ +# composer + +This plugin provides completion for [composer](https://getcomposer.org/), as well as aliases +for frequent composer commands. It also adds Composer's global binaries to the PATH, using +Composer if available. + +To use it add `composer` to the plugins array in your zshrc file. + +```zsh +plugins=(... composer) +``` + +Original author: Daniel Gomes + +## Aliases + +| Alias | Command | Description | +| ------ | ---------------------------------- | --------------------------------------------------------------------------------------- | +| `c` | `composer` | Starts composer | +| `ccp` | `composer create-project` | Create new project from an existing package | +| `cdo` | `composer dump-autoload -o` | Converts PSR-0/4 autoloading to classmap for a faster autoloader (good for production) | +| `cdu` | `composer dump-autoload` | Updates the autoloader | +| `cget` | `curl -s \| php` | Installs composer in the current directory | +| `cgr` | `composer global require` | Allows require command to run on COMPOSER_HOME directory | +| `cgrm` | `composer global remove` | Allows remove command to run on COMPOSER_HOME directory | +| `cgu` | `composer global update` | Allows update command to run on COMPOSER_HOME directory | +| `ci` | `composer install` | Resolves and installs dependencies from `composer.json` | +| `co` | `composer outdated` | Shows a list of installed packages with available updates | +| `cod` | `composer outdated --direct` | Shows a list of installed packages with available updates which are direct dependencies | +| `cr` | `composer require` | Adds new packages to `composer.json` | +| `crm` | `composer remove` | Removes packages from `composer.json` | +| `cs` | `composer show` | Lists available packages, with optional filtering | +| `csu` | `composer self-update` | Updates composer to the latest version | +| `cu` | `composer update` | Updates composer dependencies and `composer.lock` file | +| `cuh` | `composer update -d ` | Updates globally installed packages | diff --git a/zsh/.oh-my-zsh/plugins/composer/composer.plugin.zsh b/zsh/.oh-my-zsh/plugins/composer/composer.plugin.zsh new file mode 100644 index 0000000..8060da4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/composer/composer.plugin.zsh @@ -0,0 +1,76 @@ +## Basic Composer command completion +# Since Zsh 5.7, an improved composer command completion is provided +if ! is-at-least 5.7; then + _composer () { + local curcontext="$curcontext" state line + typeset -A opt_args + _arguments '*:: :->subcmds' + + if (( CURRENT == 1 )) || ( (( CURRENT == 2 )) && [[ "$words[1]" = "global" ]] ); then + # Command list + local -a subcmds + subcmds=("${(@f)"$($_comp_command1 --no-ansi 2>/dev/null | awk ' + /Available commands/{ r=1 } + r == 1 && /^[ \t]*[a-z]+/{ + gsub(/^[ \t]+/, "") + gsub(/ +/, ":") + print $0 + } + ')"}") + _describe -t commands 'composer command' subcmds + else + # Required list + compadd $($_comp_command1 show -s --no-ansi 2>/dev/null \ + | sed '1,/requires/d' \ + | awk 'NF > 0 && !/^requires \(dev\)/{ print $1 }') + fi + } + + compdef _composer composer + compdef _composer composer.phar +fi + + +## Aliases +alias c='composer' +alias ccp='composer create-project' +alias cdo='composer dump-autoload -o' +alias cdu='composer dump-autoload' +alias cget='curl -s https://getcomposer.org/installer | php' +alias cgr='composer global require' +alias cgrm='composer global remove' +alias cgu='composer global update' +alias ci='composer install' +alias co='composer outdated' +alias cod='composer outdated --direct' +alias cr='composer require' +alias crm='composer remove' +alias cs='composer show' +alias csu='composer self-update' +alias cu='composer update' +alias cuh='composer update --working-dir=$(composer config -g home)' + + +## If Composer not found, try to add known directories to $PATH +if (( ! $+commands[composer] )); then + [[ -d "$HOME/.composer/vendor/bin" ]] && export PATH="$PATH:$HOME/.composer/vendor/bin" + [[ -d "$HOME/.config/composer/vendor/bin" ]] && export PATH="$PATH:$HOME/.config/composer/vendor/bin" + + # If still not found, don't do the rest of the script + (( $+commands[composer] )) || return 0 +fi + + +## Add Composer's global binaries to PATH +autoload -Uz _store_cache _retrieve_cache _cache_invalid +_retrieve_cache composer + +if [[ -z $__composer_bin_dir ]]; then + __composer_bin_dir=$(composer global config bin-dir --absolute 2>/dev/null) + _store_cache composer __composer_bin_dir +fi + +# Add Composer's global binaries to PATH +export PATH="$PATH:$__composer_bin_dir" + +unset __composer_bin_dir diff --git a/zsh/.oh-my-zsh/plugins/copybuffer/README.md b/zsh/.oh-my-zsh/plugins/copybuffer/README.md new file mode 100644 index 0000000..97fd124 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/copybuffer/README.md @@ -0,0 +1,11 @@ +# `copybuffer` plugin + +This plugin adds the ctrl-o keyboard shortcut to copy the current text +in the command line to the system clipboard. + +This is useful if you type a command - and before you hit enter to execute it - want +to copy it maybe so you can paste it into a script, gist or whatnot. + +```zsh +plugins=(... copybuffer) +``` diff --git a/zsh/.oh-my-zsh/plugins/copybuffer/copybuffer.plugin.zsh b/zsh/.oh-my-zsh/plugins/copybuffer/copybuffer.plugin.zsh new file mode 100644 index 0000000..6ffb283 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/copybuffer/copybuffer.plugin.zsh @@ -0,0 +1,16 @@ +# copy the active line from the command line buffer +# onto the system clipboard + +copybuffer () { + if builtin which clipcopy &>/dev/null; then + printf "%s" "$BUFFER" | clipcopy + else + zle -M "clipcopy not found. Please make sure you have Oh My Zsh installed correctly." + fi +} + +zle -N copybuffer + +bindkey -M emacs "^O" copybuffer +bindkey -M viins "^O" copybuffer +bindkey -M vicmd "^O" copybuffer diff --git a/zsh/.oh-my-zsh/plugins/copyfile/README.md b/zsh/.oh-my-zsh/plugins/copyfile/README.md new file mode 100644 index 0000000..f96e55c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/copyfile/README.md @@ -0,0 +1,11 @@ +# copyfile plugin + +Puts the contents of a file in your system clipboard so you can paste it anywhere. + +To use, add `copyfile` to your plugins array: + +```zsh +plugins=(... copyfile) +``` + +Then you can run the command `copyfile ` to copy the file named `filename`. diff --git a/zsh/.oh-my-zsh/plugins/copyfile/copyfile.plugin.zsh b/zsh/.oh-my-zsh/plugins/copyfile/copyfile.plugin.zsh new file mode 100644 index 0000000..1c3f53d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/copyfile/copyfile.plugin.zsh @@ -0,0 +1,7 @@ +# Copies the contents of a given file to the system or X Windows clipboard +# +# copyfile +function copyfile { + emulate -L zsh + clipcopy $1 +} diff --git a/zsh/.oh-my-zsh/plugins/copypath/README.md b/zsh/.oh-my-zsh/plugins/copypath/README.md new file mode 100644 index 0000000..330bf75 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/copypath/README.md @@ -0,0 +1,15 @@ +# copypath plugin + +Copies the path of given directory or file to the system clipboard. + +To use it, add `copypath` to the plugins array in your zshrc file: + +```zsh +plugins=(... copypath) +``` + +## Usage + +- `copypath`: copies the absolute path of the current directory. + +- `copypath `: copies the absolute path of the given file. diff --git a/zsh/.oh-my-zsh/plugins/copypath/copypath.plugin.zsh b/zsh/.oh-my-zsh/plugins/copypath/copypath.plugin.zsh new file mode 100644 index 0000000..d721e21 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/copypath/copypath.plugin.zsh @@ -0,0 +1,15 @@ +# Copies the path of given directory or file to the system or X Windows clipboard. +# Copy current directory if no parameter. +function copypath { + # If no argument passed, use current directory + local file="${1:-.}" + + # If argument is not an absolute path, prepend $PWD + [[ $file = /* ]] || file="$PWD/$file" + + # Copy the absolute path without resolving symlinks + # If clipcopy fails, exit the function with an error + print -n "${file:a}" | clipcopy || return 1 + + echo ${(%):-"%B${file:a}%b copied to clipboard."} +} diff --git a/zsh/.oh-my-zsh/plugins/cp/README.md b/zsh/.oh-my-zsh/plugins/cp/README.md new file mode 100644 index 0000000..86caad0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cp/README.md @@ -0,0 +1,32 @@ +# cp plugin + +This plugin defines a `cpv` function that uses `rsync` so that you +get the features and security of this command. + +To enable, add `cp` to your `plugins` array in your zshrc file: + +```zsh +plugins=(... cp) +``` + +## Description + +The enabled options for rsync are: + +- `-p`: preserves permissions. + +- `-o`: preserves owner. + +* `-g`: preserves group. + +* `-b`: make a backup of the original file instead of overwriting it, if it exists. + +* `-r`: recurse directories. + +* `-hhh`: outputs numbers in human-readable format, in units of 1024 (K, M, G, T). + +* `--backup-dir="/tmp/rsync-$USERNAME"`: move backup copies to "/tmp/rsync-$USERNAME". + +* `-e /dev/null`: only work on local files (disable remote shells). + +* `--progress`: display progress. diff --git a/zsh/.oh-my-zsh/plugins/cp/cp.plugin.zsh b/zsh/.oh-my-zsh/plugins/cp/cp.plugin.zsh new file mode 100644 index 0000000..5c77f80 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cp/cp.plugin.zsh @@ -0,0 +1,4 @@ +cpv() { + rsync -pogbr -hhh --backup-dir="/tmp/rsync-${USERNAME}" -e /dev/null --progress "$@" +} +compdef _files cpv diff --git a/zsh/.oh-my-zsh/plugins/cpanm/README.md b/zsh/.oh-my-zsh/plugins/cpanm/README.md new file mode 100644 index 0000000..374cdf5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cpanm/README.md @@ -0,0 +1,9 @@ +# Cpanm + +This plugin provides completion for [Cpanm](https://github.com/miyagawa/cpanminus) ([docs](https://metacpan.org/pod/App::cpanminus)). + +To use it add cpanm to the plugins array in your zshrc file. + +```zsh +plugins=(... cpanm) +``` diff --git a/zsh/.oh-my-zsh/plugins/cpanm/_cpanm b/zsh/.oh-my-zsh/plugins/cpanm/_cpanm new file mode 100644 index 0000000..b23857f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/cpanm/_cpanm @@ -0,0 +1,64 @@ +#compdef cpanm + +## +# cpanminus Z Shell completion script +## +# +# Current supported cpanm version: 1.4000 (Tue Mar 8 01:00:49 PST 2011) +# + +local arguments curcontext="$curcontext" +typeset -A opt_args + + +arguments=( + +# Commands +# '(--install -i)'{--install,-i}'[Installs the modules]' + '(- :)--self-upgrade[Upgrades itself]' + '(- :)--info[Displays distribution info on CPAN]' + '(--installdeps)--installdeps[Only install dependencies]' + '(--look)--look[Download/unpack the distribution and then open the directory with your shell]' + '(- :)'{--help,-h}'[Displays help information]' + '(- :)'{--version,-V}'[Displays software version]' + +# Options + {--force,-f}'[Force install]' + {--notest,-n}'[Do not run unit tests]' + {--sudo,-S}'[sudo to run install commands]' + '(-v --verbose --quiet -q)'{--verbose,-v}'[Turns on chatty output]' + '(-q --quiet --verbose -v)'{--quiet,-q}'[Turns off all output]' + {--local-lib,-l}'[Specify the install base to install modules]' + {--local-lib-contained,-L}'[Specify the install base to install all non-core modules]' + '--mirror[Specify the base URL for the mirror (e.g. http://cpan.cpantesters.org/)]:URLs:_urls' + '--mirror-only[Use the mirror\''s index file instead of the CPAN Meta DB]' + '--prompt[Prompt when configure/build/test fails]' + '--reinstall[Reinstall the distribution even if you already have the latest version installed]' + '--interactive[Turn on interactive configure]' + + '--scandeps[Scan the dependencies of given modules and output the tree in a text format]' + '--format[Specify what format to display the scanned dependency tree]:scandeps format:(tree json yaml dists)' + + '--save-dists[Specify the optional directory path to copy downloaded tarballs]' +# '--uninst-shadows[Uninstalls the shadow files of the distribution that you\''re installing]' + + '--auto-cleanup[Number of days that cpanm\''s work directories expire in. Defaults to 7]' + '(--no-man-pages)--man-pages[Generates man pages for executables (man1) and libraries (man3)]' + '(--man-pages)--no-man-pages[Do not generate man pages]' + + + # Note: Normally with "--lwp", "--wget" and "--curl" options set to true (which is the default) cpanm tries LWP, + # Wget, cURL and HTTP::Tiny (in that order) and uses the first one available. + # (So that the exclusions are not enabled here for the completion) + '(--lwp)--lwp[Use LWP module to download stuff]' + '(--wget)--wget[Use GNU Wget (if available) to download stuff]' + '(--curl)--curl[Use cURL (if available) to download stuff]' + +# Other completions + '*:Local directory or archive:_files -/ -g "*.(tar.gz|tgz|tar.bz2|zip)(-.)"' + # '*::args: _normal' # this looks for default files (any files) +) +_arguments -s $arguments \ + && return 0 + +return 1 diff --git a/zsh/.oh-my-zsh/plugins/dash/README.md b/zsh/.oh-my-zsh/plugins/dash/README.md new file mode 100644 index 0000000..3b5efca --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dash/README.md @@ -0,0 +1,28 @@ +# Dash plugin + +This plugin adds command line functionality for [Dash](https://kapeli.com/dash), +an API Documentation Browser for macOS. This plugin requires Dash to be installed +to work. + +To use it, add `dash` to the plugins array in your zshrc file: + +```zsh +plugins=(... dash) +``` + +## Usage + +- Open and switch to the dash application. +``` +dash +``` + +- Query for something in dash app: `dash query` +``` +dash golang +``` + +- You can optionally provide a keyword: `dash [keyword:]query` +``` +dash python:tuple +``` diff --git a/zsh/.oh-my-zsh/plugins/dash/dash.plugin.zsh b/zsh/.oh-my-zsh/plugins/dash/dash.plugin.zsh new file mode 100644 index 0000000..909c526 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dash/dash.plugin.zsh @@ -0,0 +1,84 @@ +# Usage: dash [keyword:]query +dash() { open -a Dash.app dash://"$*" } +compdef _dash dash + +_dash() { + # No sense doing this for anything except the 2nd position and if we haven't + # specified which docset to query against + if [[ $CURRENT -ne 2 || "$words[2]" =~ ":" ]]; then + return + fi + + local -aU docsets + docsets=() + + # Use defaults to get the array of docsets from preferences + # Have to smash it into one big line so that each docset is an element of our docsets array + # Only output docsets that are actually enabled + local -a enabled_docsets + enabled_docsets=("${(@f)$(defaults read com.kapeli.dashdoc docsets \ + | tr -d '\n' | grep -oE '\{.*?\}' | grep -E 'isEnabled = 1;')}") + + local docset name keyword + # Now get each docset and output each on their own line + for docset in "$enabled_docsets[@]"; do + keyword='' + # Order of preference as explained to me by @kapeli via email + for locator in keyword suggestedKeyword platform; do + # Echo the docset, try to find the appropriate keyword + # Strip doublequotes and colon from any keyword so that everything has the + # same format when output (we'll add the colon in the completion) + if [[ "$docset" =~ "$locator = ([^;]*);" ]]; then + keyword="${match[1]//[\":]}" + fi + + if [[ -z "$keyword" ]]; then + continue + fi + + # if we fall back to platform, we should do some checking per @kapeli + if [[ "$locator" == "platform" ]]; then + # Since these are the only special cases right now, let's not do the + # expensive processing unless we have to + if [[ "$keyword" = (python|java|qt|cocos2d) ]]; then + if [[ "$docset" =~ "docsetName = ([^;]*);" ]]; then + name="${match[1]//[\":]}" + case "$keyword" in + python) + case "$name" in + "Python 2") keyword="python2" ;; + "Python 3") keyword="python3" ;; + esac ;; + java) + case "$name" in + "Java SE7") keyword="java7" ;; + "Java SE6") keyword="java6" ;; + "Java SE8") keyword="java8" ;; + esac ;; + qt) + case "$name" in + "Qt 5") keyword="qt5" ;; + "Qt 4"|Qt) keyword="qt4" ;; + esac ;; + cocos2d) + case "$name" in + Cocos3D) keyword="cocos3d" ;; + esac ;; + esac + fi + fi + fi + + # Bail once we have a match + break + done + + # If we have a keyword, add it to the list! + if [[ -n "$keyword" ]]; then + docsets+=($keyword) + fi + done + + # special thanks to [arx] on #zsh for getting me sorted on this piece + compadd -qS: -- "$docsets[@]" +} diff --git a/zsh/.oh-my-zsh/plugins/dbt/README.md b/zsh/.oh-my-zsh/plugins/dbt/README.md new file mode 100644 index 0000000..2ca5bb0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dbt/README.md @@ -0,0 +1,29 @@ +# dbt plugin + +## Introduction + +The `dbt plugin` adds several aliases for useful [dbt](https://docs.getdbt.com/) commands and +[aliases](#aliases). + +To use it, add `dbt` to the plugins array of your zshrc file: + +``` +plugins=(... dbt) +``` + +## Aliases + +| Alias | Command | Description | +| ------ | ------------------------------------------------ | ---------------------------------------------------- | +| dbtlm | `dbt ls -s state:modified` | List modified models only | +| dbtrm | `dbt run -s state:modified` | Run modified models only | +| dbttm | `dbt test -m state:modified` | Test modified models only | +| dbtrtm | `dbtrm && dbttm` | Run and test modified models only | +| dbtrs | `dbt clean; dbt deps; dbt seed` | Re-seed data | +| dbtfrt | `dbtrs; dbt run --full-refresh; dbt test` | Perform a full fresh run with tests | +| dbtcds | `dbt docs generate; dbt docs serve` | Generate docs without compiling | +| dbtds | `dbt docs generate --no-compile; dbt docs serve` | Generate and serve docs skipping doc. re-compilation | + +## Maintainer + +### [msempere](https://github.com/msempere) diff --git a/zsh/.oh-my-zsh/plugins/dbt/dbt.plugin.zsh b/zsh/.oh-my-zsh/plugins/dbt/dbt.plugin.zsh new file mode 100644 index 0000000..b95d9b5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dbt/dbt.plugin.zsh @@ -0,0 +1,23 @@ +# list modified models only +alias dbtlm="dbt ls -s state:modified" + +# run modified models only +alias dbtrm="dbt run -s state:modified" + +# test modified models only +alias dbttm="dbt test -m state:modified" + +# run and test modified models only +alias dbtrtm="dbtrm && dbttm" + +# re-seed data +alias dbtrs="dbt clean; dbt deps; dbt seed" + +# perform a full fresh run with tests +alias dbtfrt="dbtrs; dbt run --full-refresh; dbt test" + +# generate and serve docs +alias dbtcds="dbt docs generate; dbt docs serve" + +# generate and serve docs skipping doc. re-compilation +alias dbtds="dbt docs generate --no-compile; dbt docs serve" diff --git a/zsh/.oh-my-zsh/plugins/debian/README.md b/zsh/.oh-my-zsh/plugins/debian/README.md new file mode 100644 index 0000000..99c4cb9 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/debian/README.md @@ -0,0 +1,92 @@ +# debian + +This plugin provides Debian-related aliases and functions for zsh. + +To use it add `debian` to the plugins array in your zshrc file. + +```zsh +plugins=(... debian) +``` + +## Settings + +- `$apt_pref`: use aptitude or apt if installed, fallback is apt-get. +- `$apt_upgr`: use upgrade or safe-upgrade (for aptitude). + +Set **both** `$apt_pref` and `$apt_upgr` to whatever command you want (before sourcing Oh My Zsh) to override this behavior, e.g.: + +```sh +apt_pref='apt' +apt_upgr='full-upgrade' +``` + +## Common Aliases + +| Alias | Command | Description | +| ------ | ---------------------------------------------------------------------- | ---------------------------------------------------------- | +| `age` | `apt-get` | Command line tool for handling packages | +| `api` | `aptitude` | Same functionality as `apt-get`, provides extra options | +| `acs` | `apt-cache search` | Command line tool for searching apt software package cache | +| `aps` | `aptitude search` | Searches installed packages using aptitude | +| `as` | `aptitude -F '* %p -> %d \n(%v/%V)' --no-gui --disable-columns search` | Print searched packages using a custom format | +| `afs` | `apt-file search --regexp` | Search file in packages | +| `asrc` | `apt-get source` | Fetch source packages through `apt-get` | +| `app` | `apt-cache policy` | Displays priority of package sources | + +## Superuser Operations Aliases + +| Alias | Command | Description | +| -------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| `aac` | `sudo $apt_pref autoclean` | Clears out the local repository of retrieved package files | +| `aar` | `sudo $apt_pref autoremove` | Removes packages installed automatically that are no longer needed | +| `abd` | `sudo $apt_pref build-dep` | Installs all dependencies for building packages | +| `ac` | `sudo $apt_pref clean` | Clears out the local repository of retrieved package files except lock files | +| `ad` | `sudo $apt_pref update` | Updates the package lists for upgrades for packages | +| `adg` | `sudo $apt_pref update && sudo $apt_pref $apt_upgr` | Update and upgrade packages | +| `ads` | `sudo apt-get dselect-upgrade` | Installs packages from list and removes all not in the list | +| `adu` | `sudo $apt_pref update && sudo $apt_pref dist-upgrade` | Smart upgrade that handles dependencies | +| `afu` | `sudo apt-file update` | Update the files in packages | +| `ai` | `sudo $apt_pref install` | Command-line tool to install package | +| `ail` | `sed -e 's/ */ /g' -e 's/ *//' \| cut -s -d ' ' -f 1 \| xargs sudo $apt_pref install` | Install all packages given on the command line while using only the first word of each line | +| `alu` | `sudo apt update && apt list -u && sudo apt upgrade` | Update, list and upgrade packages | +| `ap` | `sudo $apt_pref purge` | Removes packages along with configuration files | +| `au` | `sudo $apt_pref $apt_upgr` | Install package upgrades | +| `di` | `sudo dpkg -i` | Install all .deb files in the current directory | +| `dia` | `sudo dpkg -i ./*.deb` | Install all .deb files in the current directory | +| `kclean` | `sudo aptitude remove -P ?and(~i~nlinux-(ima\|hea) ?not(~n$(uname -r)))` | Remove ALL kernel images and headers EXCEPT the one in use | + +## Aliases - Commands using `su` + +| Alias | Command | +| ----- | --------------------------------------------------------- | +| `aac` | `su -ls "$apt_pref autoclean" root` | +| `aar` | `su -ls "$apt_pref autoremove" root` | +| `ac` | `su -ls "$apt_pref clean" root` | +| `ad` | `su -lc "$apt_pref update" root` | +| `adg` | `su -lc "$apt_pref update && aptitude $apt_upgr" root` | +| `adu` | `su -lc "$apt_pref update && aptitude dist-upgrade" root` | +| `afu` | `su -lc "apt-file update"` | +| `au` | `su -lc "$apt_pref $apt_upgr" root` | +| `dia` | `su -lc "dpkg -i ./*.deb" root` | + +## Miscellaneous Aliases + +| Alias | Command | Description | +| --------- | ---------------------------------------------- | ------------------------------ | +| `allpkgs` | `aptitude search -F "%p" --disable-columns ~i` | Display all installed packages | +| `mydeb` | `time dpkg-buildpackage -rfakeroot -us -uc` | Create a basic .deb package | + +## Functions + +| Function | Description | +| ------------------- | --------------------------------------------------------------- | +| `apt-copy` | Create a simple script that can be used to 'duplicate' a system | +| `apt-history` | Displays apt history for a command | +| `apt-list-packages` | List packages by size | +| `kerndeb` | Builds kernel packages | + +## Authors + +- [@AlexBio](https://github.com/AlexBio) +- [@dbb](https://github.com/dbb) +- [@Mappleconfusers](https://github.com/Mappleconfusers) diff --git a/zsh/.oh-my-zsh/plugins/debian/debian.plugin.zsh b/zsh/.oh-my-zsh/plugins/debian/debian.plugin.zsh new file mode 100644 index 0000000..670cbff --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/debian/debian.plugin.zsh @@ -0,0 +1,227 @@ +# Use aptitude or apt if installed, fallback is apt-get +# You can just set apt_pref='apt-get' to override it. + +if [[ -z $apt_pref || -z $apt_upgr ]]; then + if [[ -e $commands[aptitude] ]]; then + apt_pref='aptitude' + apt_upgr='safe-upgrade' + elif [[ -e $commands[apt] ]]; then + apt_pref='apt' + apt_upgr='upgrade' + else + apt_pref='apt-get' + apt_upgr='upgrade' + fi +fi + +# Use sudo by default if it's installed +if [[ -e $commands[sudo] ]]; then + use_sudo=1 +fi + +# Aliases ################################################################### +# These are for more obscure uses of apt-get and aptitude that aren't covered +# below. +alias age='apt-get' +alias api='aptitude' + +# Some self-explanatory aliases +alias acs="apt-cache search" +alias aps='aptitude search' +alias as="aptitude -F '* %p -> %d \n(%v/%V)' --no-gui --disable-columns search" + +# apt-file +alias afs='apt-file search --regexp' + + +# These are apt-get only +alias asrc='apt-get source' +alias app='apt-cache policy' + +# superuser operations ###################################################### +if [[ $use_sudo -eq 1 ]]; then +# commands using sudo ####### + alias aac="sudo $apt_pref autoclean" + alias abd="sudo $apt_pref build-dep" + alias ac="sudo $apt_pref clean" + alias ad="sudo $apt_pref update" + alias adg="sudo $apt_pref update && sudo $apt_pref $apt_upgr" + alias adu="sudo $apt_pref update && sudo $apt_pref dist-upgrade" + alias afu="sudo apt-file update" + alias au="sudo $apt_pref $apt_upgr" + alias ai="sudo $apt_pref install" + # Install all packages given on the command line while using only the first word of each line: + # acse ... | ail + + alias ail="sed -e 's/ */ /g' -e 's/ *//' | cut -s -d ' ' -f 1 | xargs sudo $apt_pref install" + alias ap="sudo $apt_pref purge" + alias aar="sudo $apt_pref autoremove" + + # apt-get only + alias ads="sudo apt-get dselect-upgrade" + + # apt only + alias alu="sudo apt update && apt list -u && sudo apt upgrade" + + # Install all .deb files in the current directory. + # Warning: you will need to put the glob in single quotes if you use: + # glob_subst + alias dia="sudo dpkg -i ./*.deb" + alias di="sudo dpkg -i" + + # Remove ALL kernel images and headers EXCEPT the one in use + alias kclean='sudo aptitude remove -P "?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))"' + + +# commands using su ######### +else + alias aac="su -ls '$apt_pref autoclean' root" + function abd() { + cmd="su -lc '$apt_pref build-dep $@' root" + print "$cmd" + eval "$cmd" + } + alias ac="su -ls '$apt_pref clean' root" + alias ad="su -lc '$apt_pref update' root" + alias adg="su -lc '$apt_pref update && aptitude $apt_upgr' root" + alias adu="su -lc '$apt_pref update && aptitude dist-upgrade' root" + alias afu="su -lc '$apt-file update'" + alias au="su -lc '$apt_pref $apt_upgr' root" + function ai() { + cmd="su -lc '$apt_pref install $@' root" + print "$cmd" + eval "$cmd" + } + function ap() { + cmd="su -lc '$apt_pref purge $@' root" + print "$cmd" + eval "$cmd" + } + function aar() { + cmd="su -lc '$apt_pref autoremove $@' root" + print "$cmd" + eval "$cmd" + } + # Install all .deb files in the current directory + # Assumes glob_subst is off + alias dia='su -lc "dpkg -i ./*.deb" root' + alias di='su -lc "dpkg -i" root' + + # Remove ALL kernel images and headers EXCEPT the one in use + alias kclean='su -lc "aptitude remove -P \"?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))\"" root' +fi + +# Completion ################################################################ + +# +# Registers a compdef for $1 that calls $apt_pref with the commands $2 +# To do that it creates a new completion function called _apt_pref_$2 +# +function apt_pref_compdef() { + local f fb + f="_apt_pref_${2}" + + eval "function ${f}() { + shift words; + service=\"\$apt_pref\"; + words=(\"\$apt_pref\" '$2' \$words); + ((CURRENT++)) + test \"\${apt_pref}\" = 'aptitude' && _aptitude || _apt + }" + + compdef "$f" "$1" +} + +apt_pref_compdef aac "autoclean" +apt_pref_compdef abd "build-dep" +apt_pref_compdef ac "clean" +apt_pref_compdef ad "update" +apt_pref_compdef afu "update" +apt_pref_compdef au "$apt_upgr" +apt_pref_compdef ai "install" +apt_pref_compdef ail "install" +apt_pref_compdef ap "purge" +apt_pref_compdef aar "autoremove" +apt_pref_compdef ads "dselect-upgrade" + +# Misc. ##################################################################### +# print all installed packages +alias allpkgs='aptitude search -F "%p" --disable-columns ~i' + +# Create a basic .deb package +alias mydeb='time dpkg-buildpackage -rfakeroot -us -uc' + + +# Functions ################################################################# +# create a simple script that can be used to 'duplicate' a system +function apt-copy() { + print '#!/bin/sh'"\n" > apt-copy.sh + + cmd='$apt_pref install' + + for p in ${(f)"$(aptitude search -F "%p" --disable-columns \~i)"}; { + cmd="${cmd} ${p}" + } + + print $cmd "\n" >> apt-copy.sh + + chmod +x apt-copy.sh +} + +# Prints apt history +# Usage: +# apt-history install +# apt-history upgrade +# apt-history remove +# apt-history rollback +# apt-history list +# Based On: https://linuxcommando.blogspot.com/2008/08/how-to-show-apt-log-history.html +function apt-history() { + case "$1" in + install) + zgrep --no-filename 'install ' $(ls -rt /var/log/dpkg*) + ;; + upgrade|remove) + zgrep --no-filename $1 $(ls -rt /var/log/dpkg*) + ;; + rollback) + zgrep --no-filename upgrade $(ls -rt /var/log/dpkg*) | \ + grep "$2" -A10000000 | \ + grep "$3" -B10000000 | \ + awk '{print $4"="$5}' + ;; + list) + zgrep --no-filename '' $(ls -rt /var/log/dpkg*) + ;; + *) + echo "Parameters:" + echo " install - Lists all packages that have been installed." + echo " upgrade - Lists all packages that have been upgraded." + echo " remove - Lists all packages that have been removed." + echo " rollback - Lists rollback information." + echo " list - Lists all contains of dpkg logs." + ;; + esac +} + +# Kernel-package building shortcut +function kerndeb() { + # temporarily unset MAKEFLAGS ( '-j3' will fail ) + MAKEFLAGS=$( print - $MAKEFLAGS | perl -pe 's/-j\s*[\d]+//g' ) + print '$MAKEFLAGS set to '"'$MAKEFLAGS'" + appendage='-custom' # this shows up in $(uname -r ) + revision=$(date +"%Y%m%d") # this shows up in the .deb file name + + make-kpkg clean + + time fakeroot make-kpkg --append-to-version "$appendage" --revision \ + "$revision" kernel_image kernel_headers +} + +# List packages by size +function apt-list-packages() { + dpkg-query -W --showformat='${Installed-Size} ${Package} ${Status}\n' | \ + grep -v deinstall | \ + sort -n | \ + awk '{print $1" "$2}' +} diff --git a/zsh/.oh-my-zsh/plugins/deno/README.md b/zsh/.oh-my-zsh/plugins/deno/README.md new file mode 100644 index 0000000..aa84fd8 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/deno/README.md @@ -0,0 +1,20 @@ +# Deno Plugin + +This plugin sets up completion and aliases for [Deno](https://deno.land). + +## Aliases + +| Alias | Full command | +| ----- | ------------------- | +| db | deno bundle | +| dc | deno compile | +| dca | deno cache | +| dfmt | deno fmt | +| dh | deno help | +| dli | deno lint | +| drn | deno run | +| drA | deno run -A | +| drw | deno run --watch | +| dru | deno run --unstable | +| dts | deno test | +| dup | deno upgrade | diff --git a/zsh/.oh-my-zsh/plugins/deno/deno.plugin.zsh b/zsh/.oh-my-zsh/plugins/deno/deno.plugin.zsh new file mode 100644 index 0000000..eb4c6e5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/deno/deno.plugin.zsh @@ -0,0 +1,28 @@ +# ALIASES +alias db='deno bundle' +alias dc='deno compile' +alias dca='deno cache' +alias dfmt='deno fmt' +alias dh='deno help' +alias dli='deno lint' +alias drn='deno run' +alias drA='deno run -A' +alias drw='deno run --watch' +alias dru='deno run --unstable' +alias dts='deno test' +alias dup='deno upgrade' + +# COMPLETION FUNCTION +if (( ! $+commands[deno] )); then + return +fi + +# If the completion file doesn't exist yet, we need to autoload it and +# bind it to `deno`. Otherwise, compinit will have already done that. +if [[ ! -f "$ZSH_CACHE_DIR/completions/_deno" ]]; then + typeset -g -A _comps + autoload -Uz _deno + _comps[deno]=_deno +fi + +deno completions zsh >| "$ZSH_CACHE_DIR/completions/_deno" &| diff --git a/zsh/.oh-my-zsh/plugins/dircycle/README.md b/zsh/.oh-my-zsh/plugins/dircycle/README.md new file mode 100644 index 0000000..987f331 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dircycle/README.md @@ -0,0 +1,78 @@ +# dircycle + +Plugin for cycling through the directory stack + +This plugin enables directory navigation similar to using back and forward on browsers or common file explorers like Finder or Nautilus. It uses a small zle trick that lets you cycle through your directory stack left or right using Ctrl + Shift + Left / Right . This is useful when moving back and forth between directories in development environments, and can be thought of as kind of a nondestructive pushd/popd. + +## Enabling the plugin + +1. Open your `.zshrc` file and add `dircycle` in the plugins section: + + ```zsh + plugins=( + # all your enabled plugins + dircycle + ) + ``` + +2. Restart the shell or restart your Terminal session: + + ```console + $ exec zsh + $ + ``` + +## Usage Examples + +Say you opened these directories on the terminal: + +```console +~$ cd Projects +~/Projects$ cd Hacktoberfest +~/Projects/Hacktoberfest$ cd oh-my-zsh +~/Projects/Hacktoberfest/oh-my-zsh$ dirs -v +0 ~/Projects/Hacktoberfest/oh-my-zsh +1 ~/Projects/Hacktoberfest +2 ~/Projects +3 ~ +``` + +By pressing Ctrl + Shift + Left, the current working directory or `$CWD` will be from `oh-my-zsh` to `Hacktoberfest`. Press it again and it will be at `Projects`. + +And by pressing Ctrl + Shift + Right, the `$CWD` will be from `Projects` to `Hacktoberfest`. Press it again and it will be at `oh-my-zsh`. + +Here's a example history table with the same accessed directories like above: + +| Current `$CWD` | Key press | New `$CWD` | +| --------------- | ----------------------------------------------------- | --------------- | +| `oh-my-zsh` | Ctrl + Shift + Left | `Hacktoberfest` | +| `Hacktoberfest` | Ctrl + Shift + Left | `Projects` | +| `Projects` | Ctrl + Shift + Left | `~` | +| `~` | Ctrl + Shift + Right | `Projects` | +| `Projects` | Ctrl + Shift + Right | `Hacktoberfest` | +| `Hacktoberfest` | Ctrl + Shift + Right | `oh-my-zsh` | +| `oh-my-zsh` | Ctrl + Shift + Right | `~` | + +Note the last traversal, when pressing Ctrl + Shift + Right on a last known `$CWD`, it will change back to the first known `$CWD`, which in the example is `~`. + +Here's an asciinema cast demonstrating the example above: + +[![asciicast](https://asciinema.org/a/204406.png)](https://asciinema.org/a/204406) + +## Functions + +| Function | Description | +| -------------------- | --------------------------------------------------------------------------------------------------------- | +| `insert-cycledleft` | Change `$CWD` to the previous known stack, binded on Ctrl + Shift + Left | +| `insert-cycledright` | Change `$CWD` to the next known stack, binded on Ctrl + Shift + Right | + +## Rebinding keys + +You can bind these functions to other key sequences, as long as you know the bindkey sequence. For example, these commands bind to Alt + Shift + Left / Right in `xterm-256color`: + +```zsh +bindkey '^[[1;4D' insert-cycledleft +bindkey '^[[1;4C' insert-cycledright +``` + +You can get the bindkey sequence by pressing Ctrl + V, then pressing the keyboard shortcut you want to use. diff --git a/zsh/.oh-my-zsh/plugins/dircycle/dircycle.plugin.zsh b/zsh/.oh-my-zsh/plugins/dircycle/dircycle.plugin.zsh new file mode 100644 index 0000000..4caa141 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dircycle/dircycle.plugin.zsh @@ -0,0 +1,54 @@ +# enables cycling through the directory stack using +# Ctrl+Shift+Left/Right +# +# left/right direction follows the order in which directories +# were visited, like left/right arrows do in a browser + +# NO_PUSHD_MINUS syntax: +# pushd +N: start counting from left of `dirs' output +# pushd -N: start counting from right of `dirs' output + +switch-to-dir () { + setopt localoptions nopushdminus + [[ ${#dirstack} -eq 0 ]] && return 1 + + while ! builtin pushd -q $1 &>/dev/null; do + # We found a missing directory: pop it out of the dir stack + builtin popd -q $1 + + # Stop trying if there are no more directories in the dir stack + [[ ${#dirstack} -eq 0 ]] && return 1 + done +} + +insert-cycledleft () { + switch-to-dir +1 || return + + local fn + for fn (chpwd $chpwd_functions precmd $precmd_functions); do + (( $+functions[$fn] )) && $fn + done + zle reset-prompt +} +zle -N insert-cycledleft + +insert-cycledright () { + switch-to-dir -0 || return + + local fn + for fn (chpwd $chpwd_functions precmd $precmd_functions); do + (( $+functions[$fn] )) && $fn + done + zle reset-prompt +} +zle -N insert-cycledright + + +# These sequences work for xterm, Apple Terminal.app, and probably others. +# Not for rxvt-unicode, but it doesn't seem differentiate Ctrl-Shift-Arrow +# from plain Shift-Arrow, at least by default. +# iTerm2 does not have these key combinations defined by default; you will need +# to add them under "Keys" in your profile if you want to use this. You can do +# this conveniently by loading the "xterm with Numeric Keypad" preset. +bindkey "\e[1;6D" insert-cycledleft +bindkey "\e[1;6C" insert-cycledright diff --git a/zsh/.oh-my-zsh/plugins/direnv/README.md b/zsh/.oh-my-zsh/plugins/direnv/README.md new file mode 100644 index 0000000..b460661 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/direnv/README.md @@ -0,0 +1,15 @@ +# direnv plugin + +This plugin creates the [Direnv](https://direnv.net/) hook. + +To use it, add `direnv` to the plugins array in your zshrc file: + +```zsh +plugins=(... direnv) +``` + +## Requirements + +In order to make this work, you will need to have the direnv installed. + +More info on the usage and install: https://github.com/direnv/direnv diff --git a/zsh/.oh-my-zsh/plugins/direnv/direnv.plugin.zsh b/zsh/.oh-my-zsh/plugins/direnv/direnv.plugin.zsh new file mode 100644 index 0000000..acecd44 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/direnv/direnv.plugin.zsh @@ -0,0 +1,16 @@ +# Don't continue if direnv is not found +command -v direnv &>/dev/null || return + +_direnv_hook() { + trap -- '' SIGINT; + eval "$(direnv export zsh)"; + trap - SIGINT; +} +typeset -ag precmd_functions; +if [[ -z "${precmd_functions[(r)_direnv_hook]+1}" ]]; then + precmd_functions=( _direnv_hook ${precmd_functions[@]} ) +fi +typeset -ag chpwd_functions; +if [[ -z "${chpwd_functions[(r)_direnv_hook]+1}" ]]; then + chpwd_functions=( _direnv_hook ${chpwd_functions[@]} ) +fi diff --git a/zsh/.oh-my-zsh/plugins/dirhistory/README.md b/zsh/.oh-my-zsh/plugins/dirhistory/README.md new file mode 100644 index 0000000..2e02c92 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dirhistory/README.md @@ -0,0 +1,62 @@ +# Dirhistory plugin + +This plugin adds keyboard shortcuts for navigating directory history and hierarchy. + +To use it, add `dirhistory` to the plugins array in your zshrc file: + +```zsh +plugins=(... dirhistory) +``` + +## Keyboard Shortcuts + +| Shortcut | Description | +|-----------------------------------|-----------------------------------------------------------| +| Alt + Left | Go to previous directory | +| Alt + Right | Go to next directory | +| Alt + Up | Move into the parent directory | +| Alt + Down | Move into the first child directory by alphabetical order | + +**For macOS: use the Option key () instead of Alt**. + +> NOTE: some terminals might override the Alt + Arrows key bindings (e.g. Windows Terminal). +> If these don't work check your terminal settings and change them to a different keyboard shortcut. + +## Usage + +This plugin allows you to navigate the history of previous working directories using Alt + Left +and Alt + Right. Alt + Left moves to past directories, and +Alt + Right goes back to recent directories. + +**NOTE: the maximum directory history size is 30.** + +You can also navigate **directory hierarchies** using Alt + Up and Alt + Down. +Alt + Up moves to the parent directory, while Alt + Down moves into the first +child directory found in alphabetical order (useful to navigate long empty directories, e.g. Java packages). + +For example, if the shell was started, and the following commands were entered: + +```shell +cd ~ +cd /usr +cd share +cd doc +``` + +the directory stack (`dirs -v`) would look like this: + +```console +$ dirs -v +0 /usr/share/doc +1 /usr/share +2 /usr +3 ~ +``` + +then entering Alt + Left at the prompt would change directory from `/usr/share/doc` to `/usr/share`, +then if pressed again to `/usr`, then `~`. If Alt + Right were pressed the directory would be changed +to `/usr` again. + +After that, Alt + Down will probably go to `/usr/bin` if `bin` is the first directory in alphabetical +order (depends on your `/usr` folder structure). Alt + Up will return to `/usr`, and once more will get +you to the root folder (`/`). diff --git a/zsh/.oh-my-zsh/plugins/dirhistory/dirhistory.plugin.zsh b/zsh/.oh-my-zsh/plugins/dirhistory/dirhistory.plugin.zsh new file mode 100644 index 0000000..3645d68 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dirhistory/dirhistory.plugin.zsh @@ -0,0 +1,225 @@ +## +# Navigate directory history using ALT-LEFT and ALT-RIGHT. ALT-LEFT moves back to directories +# that the user has changed to in the past, and ALT-RIGHT undoes ALT-LEFT. +# +# Navigate directory hierarchy using ALT-UP and ALT-DOWN. +# ALT-UP moves to higher hierarchy (cd ..) +# ALT-DOWN moves into the first directory found in alphabetical order +# + +dirhistory_past=($PWD) +dirhistory_future=() +export dirhistory_past +export dirhistory_future + +export DIRHISTORY_SIZE=30 + +# Pop the last element of dirhistory_past. +# Pass the name of the variable to return the result in. +# Returns the element if the array was not empty, +# otherwise returns empty string. +function pop_past() { + setopt localoptions no_ksh_arrays + if [[ $#dirhistory_past -gt 0 ]]; then + typeset -g $1="${dirhistory_past[$#dirhistory_past]}" + dirhistory_past[$#dirhistory_past]=() + fi +} + +function pop_future() { + setopt localoptions no_ksh_arrays + if [[ $#dirhistory_future -gt 0 ]]; then + typeset -g $1="${dirhistory_future[$#dirhistory_future]}" + dirhistory_future[$#dirhistory_future]=() + fi +} + +# Push a new element onto the end of dirhistory_past. If the size of the array +# is >= DIRHISTORY_SIZE, the array is shifted +function push_past() { + setopt localoptions no_ksh_arrays + if [[ $#dirhistory_past -ge $DIRHISTORY_SIZE ]]; then + shift dirhistory_past + fi + if [[ $#dirhistory_past -eq 0 || $dirhistory_past[$#dirhistory_past] != "$1" ]]; then + dirhistory_past+=($1) + fi +} + +function push_future() { + setopt localoptions no_ksh_arrays + if [[ $#dirhistory_future -ge $DIRHISTORY_SIZE ]]; then + shift dirhistory_future + fi + if [[ $#dirhistory_future -eq 0 || $dirhistory_futuret[$#dirhistory_future] != "$1" ]]; then + dirhistory_future+=($1) + fi +} + +# Called by zsh when directory changes +autoload -U add-zsh-hook +add-zsh-hook chpwd chpwd_dirhistory +function chpwd_dirhistory() { + push_past $PWD + # If DIRHISTORY_CD is not set... + if [[ -z "${DIRHISTORY_CD+x}" ]]; then + # ... clear future. + dirhistory_future=() + fi +} + +function dirhistory_cd(){ + DIRHISTORY_CD="1" + cd $1 + unset DIRHISTORY_CD +} + +# Move backward in directory history +function dirhistory_back() { + local cw="" + local d="" + # Last element in dirhistory_past is the cwd. + + pop_past cw + if [[ "" == "$cw" ]]; then + # Someone overwrote our variable. Recover it. + dirhistory_past=($PWD) + return + fi + + pop_past d + if [[ "" != "$d" ]]; then + dirhistory_cd $d + push_future $cw + else + push_past $cw + fi +} + + +# Move forward in directory history +function dirhistory_forward() { + local d="" + + pop_future d + if [[ "" != "$d" ]]; then + dirhistory_cd $d + push_past $d + fi +} + + +# Bind keys to history navigation +function dirhistory_zle_dirhistory_back() { + # Erase current line in buffer + zle .kill-buffer + dirhistory_back + zle .accept-line +} + +function dirhistory_zle_dirhistory_future() { + # Erase current line in buffer + zle .kill-buffer + dirhistory_forward + zle .accept-line +} + +zle -N dirhistory_zle_dirhistory_back +zle -N dirhistory_zle_dirhistory_future + +for keymap in emacs vicmd viins; do + # dirhistory_back + bindkey -M $keymap "\e[3D" dirhistory_zle_dirhistory_back # xterm in normal mode + bindkey -M $keymap "\e[1;3D" dirhistory_zle_dirhistory_back # xterm in normal mode + bindkey -M $keymap "\e\e[D" dirhistory_zle_dirhistory_back # Putty + bindkey -M $keymap "\eO3D" dirhistory_zle_dirhistory_back # GNU screen + + case "$TERM_PROGRAM" in + Apple_Terminal) bindkey -M $keymap "^[b" dirhistory_zle_dirhistory_back ;; # Terminal.app + iTerm.app) bindkey -M $keymap "^[^[[D" dirhistory_zle_dirhistory_back ;; # iTerm2 + esac + + if (( ${+terminfo[kcub1]} )); then + bindkey -M $keymap "^[${terminfo[kcub1]}" dirhistory_zle_dirhistory_back # urxvt + fi + + # dirhistory_future + bindkey -M $keymap "\e[3C" dirhistory_zle_dirhistory_future # xterm in normal mode + bindkey -M $keymap "\e[1;3C" dirhistory_zle_dirhistory_future # xterm in normal mode + bindkey -M $keymap "\e\e[C" dirhistory_zle_dirhistory_future # Putty + bindkey -M $keymap "\eO3C" dirhistory_zle_dirhistory_future # GNU screen + + case "$TERM_PROGRAM" in + Apple_Terminal) bindkey -M $keymap "^[f" dirhistory_zle_dirhistory_future ;; # Terminal.app + iTerm.app) bindkey -M $keymap "^[^[[C" dirhistory_zle_dirhistory_future ;; # iTerm2 + esac + + if (( ${+terminfo[kcuf1]} )); then + bindkey -M $keymap "^[${terminfo[kcuf1]}" dirhistory_zle_dirhistory_future # urxvt + fi +done + +# +# HIERARCHY Implemented in this section, in case someone wants to split it to another plugin if it clashes bindings +# + +# Move up in hierarchy +function dirhistory_up() { + cd .. || return 1 +} + +# Move down in hierarchy +function dirhistory_down() { + cd "$(find . -mindepth 1 -maxdepth 1 -type d | sort -n | head -n 1)" || return 1 +} + + +# Bind keys to hierarchy navigation +function dirhistory_zle_dirhistory_up() { + zle .kill-buffer # Erase current line in buffer + dirhistory_up + zle .accept-line +} + +function dirhistory_zle_dirhistory_down() { + zle .kill-buffer # Erase current line in buffer + dirhistory_down + zle .accept-line +} + +zle -N dirhistory_zle_dirhistory_up +zle -N dirhistory_zle_dirhistory_down + +for keymap in emacs vicmd viins; do + # dirhistory_up + bindkey -M $keymap "\e[3A" dirhistory_zle_dirhistory_up # xterm in normal mode + bindkey -M $keymap "\e[1;3A" dirhistory_zle_dirhistory_up # xterm in normal mode + bindkey -M $keymap "\e\e[A" dirhistory_zle_dirhistory_up # Putty + bindkey -M $keymap "\eO3A" dirhistory_zle_dirhistory_up # GNU screen + + case "$TERM_PROGRAM" in + Apple_Terminal) bindkey -M $keymap "^[[A" dirhistory_zle_dirhistory_up ;; # Terminal.app + iTerm.app) bindkey -M $keymap "^[^[[A" dirhistory_zle_dirhistory_up ;; # iTerm2 + esac + + if (( ${+terminfo[kcuu1]} )); then + bindkey -M $keymap "^[${terminfo[kcuu1]}" dirhistory_zle_dirhistory_up # urxvt + fi + + # dirhistory_down + bindkey -M $keymap "\e[3B" dirhistory_zle_dirhistory_down # xterm in normal mode + bindkey -M $keymap "\e[1;3B" dirhistory_zle_dirhistory_down # xterm in normal mode + bindkey -M $keymap "\e\e[B" dirhistory_zle_dirhistory_down # Putty + bindkey -M $keymap "\eO3B" dirhistory_zle_dirhistory_down # GNU screen + + case "$TERM_PROGRAM" in + Apple_Terminal) bindkey -M $keymap "^[[B" dirhistory_zle_dirhistory_down ;; # Terminal.app + iTerm.app) bindkey -M $keymap "^[^[[B" dirhistory_zle_dirhistory_down ;; # iTerm2 + esac + + if (( ${+terminfo[kcud1]} )); then + bindkey -M $keymap "^[${terminfo[kcud1]}" dirhistory_zle_dirhistory_down # urxvt + fi +done + +unset keymap diff --git a/zsh/.oh-my-zsh/plugins/dirpersist/README.md b/zsh/.oh-my-zsh/plugins/dirpersist/README.md new file mode 100644 index 0000000..4eb2957 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dirpersist/README.md @@ -0,0 +1,10 @@ +# Dirpersist plugin + +This plugin keeps a running tally of the previous 20 unique directories in the `$HOME/.zdirs` file. +When you cd to a new directory, it is prepended to the beginning of the file. + +To use it, add `dirpersist` to the plugins array in your zshrc file: + +```zsh +plugins=(... dirpersist) +``` diff --git a/zsh/.oh-my-zsh/plugins/dirpersist/dirpersist.plugin.zsh b/zsh/.oh-my-zsh/plugins/dirpersist/dirpersist.plugin.zsh new file mode 100644 index 0000000..699be7f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dirpersist/dirpersist.plugin.zsh @@ -0,0 +1,21 @@ +# Save dirstack history to .zdirs +# adapted from: +# github.com/grml/grml-etc-core/blob/master/etc/zsh/zshrc#L1547 + +DIRSTACKSIZE=${DIRSTACKSIZE:-20} +dirstack_file=${dirstack_file:-${HOME}/.zdirs} + +if [[ -f ${dirstack_file} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then + dirstack=( ${(f)"$(< $dirstack_file)"} ) + # "cd -" won't work after login by just setting $OLDPWD, so + [[ -d $dirstack[1] ]] && cd $dirstack[1] && cd $OLDPWD +fi + +autoload -U add-zsh-hook +add-zsh-hook chpwd chpwd_dirpersist +chpwd_dirpersist() { + if (( $DIRSTACKSIZE <= 0 )) || [[ -z $dirstack_file ]]; then return; fi + local -ax my_stack + my_stack=( ${PWD} ${dirstack} ) + builtin print -l ${(u)my_stack} >! ${dirstack_file} +} diff --git a/zsh/.oh-my-zsh/plugins/dnf/README.md b/zsh/.oh-my-zsh/plugins/dnf/README.md new file mode 100644 index 0000000..e492519 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dnf/README.md @@ -0,0 +1,32 @@ +# dnf plugin + +This plugin makes `dnf` usage easier by adding aliases for the most common commands. + +`dnf` is the new package manager for RPM-based distributions, which replaces `yum`. + +To use it, add `dnf` to the plugins array in your zshrc file: + +```zsh +plugins=(... dnf) +``` + +Classic `dnf` is getting superseded by `dnf5`; this plugin detects the presence +of `dnf5` and uses it as drop-in alternative to the slower `dnf`. + +## Aliases + +| Alias | Command | Description | +|-------|-------------------------|--------------------------| +| dnfl | `dnf list` | List packages | +| dnfli | `dnf list installed` | List installed packages | +| dnfgl | `dnf grouplist` | List package groups | +| dnfmc | `dnf makecache` | Generate metadata cache | +| dnfp | `dnf info` | Show package information | +| dnfs | `dnf search` | Search package | +| **Use `sudo`** | +| dnfu | `sudo dnf upgrade` | Upgrade package | +| dnfi | `sudo dnf install` | Install package | +| dnfgi | `sudo dnf groupinstall` | Install package group | +| dnfr | `sudo dnf remove` | Remove package | +| dnfgr | `sudo dnf groupremove` | Remove package group | +| dnfc | `sudo dnf clean all` | Clean cache | diff --git a/zsh/.oh-my-zsh/plugins/dnf/dnf.plugin.zsh b/zsh/.oh-my-zsh/plugins/dnf/dnf.plugin.zsh new file mode 100644 index 0000000..d2c36d5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dnf/dnf.plugin.zsh @@ -0,0 +1,19 @@ +## Aliases +local dnfprog="dnf" + +# Prefer dnf5 if installed +command -v dnf5 > /dev/null && dnfprog=dnf5 + +alias dnfl="${dnfprog} list" # List packages +alias dnfli="${dnfprog} list installed" # List installed packages +alias dnfgl="${dnfprog} grouplist" # List package groups +alias dnfmc="${dnfprog} makecache" # Generate metadata cache +alias dnfp="${dnfprog} info" # Show package information +alias dnfs="${dnfprog} search" # Search package + +alias dnfu="sudo ${dnfprog} upgrade" # Upgrade package +alias dnfi="sudo ${dnfprog} install" # Install package +alias dnfgi="sudo ${dnfprog} groupinstall" # Install package group +alias dnfr="sudo ${dnfprog} remove" # Remove package +alias dnfgr="sudo ${dnfprog} groupremove" # Remove package group +alias dnfc="sudo ${dnfprog} clean all" # Clean cache diff --git a/zsh/.oh-my-zsh/plugins/dnote/README.md b/zsh/.oh-my-zsh/plugins/dnote/README.md new file mode 100644 index 0000000..e5190c1 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dnote/README.md @@ -0,0 +1,51 @@ +# Dnote Plugin + +This plugin adds auto-completion for [Dnote](https://www.getdnote.com/), a simple command line notebook. + +To use it, add `dnote` to the plugins array in your zshrc file: + +```zsh +plugins=(dnote) +``` + +## Usage + +At the basic level, this plugin completes all Dnote commands. + +```zsh +$ dnote a(press here) +``` + +would result in: + +```zsh +$ dnote add +``` + +For some commands, this plugin dynamically suggests matching book names. + +For instance, if you have three books that begin with 'j': 'javascript', 'job', 'js', + +```zsh +$ dnote view j(press here) +``` + +would result in: + +```zsh +$ dnote v j +javascript job js +``` + +As another example, + +```zsh +$ dnote edit ja(press here) +``` + +would result in: + + +```zsh +$ dnote v javascript +`````` diff --git a/zsh/.oh-my-zsh/plugins/dnote/_dnote b/zsh/.oh-my-zsh/plugins/dnote/_dnote new file mode 100644 index 0000000..9bebd4c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dnote/_dnote @@ -0,0 +1,39 @@ +#compdef dnote + +local -a _1st_arguments + +_1st_arguments=( + 'add:add a new note' + 'view:list books, notes, or view a content' + 'edit:edit a note or a book' + 'remove:remove a note or a book' + 'find:find notes by keywords' + 'sync:sync data with the server' + 'login:login to the dnote server' + 'logout:logout from the dnote server' + 'version:print the current version' + 'help:get help about any command' +) + +get_booknames() { + local names=$(dnote view --name-only) + local -a ret + + while read -r line; do + ret+=("${line}") + done <<< "$names" + + echo "$ret" +} + +if (( CURRENT == 2 )); then + _describe -t commands "dnote subcommand" _1st_arguments + return +elif (( CURRENT == 3 )); then + case "$words[2]" in + v|view|a|add) + _alternative \ + "names:book names:($(get_booknames))" + esac +fi + diff --git a/zsh/.oh-my-zsh/plugins/docker-compose/README.md b/zsh/.oh-my-zsh/plugins/docker-compose/README.md new file mode 100644 index 0000000..3c40738 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/docker-compose/README.md @@ -0,0 +1,34 @@ +# Docker-compose + +This plugin provides completion for [docker-compose](https://docs.docker.com/compose/) as well as some +aliases for frequent docker-compose commands. + +To use it, add docker-compose to the plugins array of your zshrc file: + +```zsh +plugins=(... docker-compose) +``` + +## Aliases + +| Alias | Command | Description | +|-----------|----------------------------------|----------------------------------------------------------------------------------| +| dco | `docker-compose` | Docker-compose main command | +| dcb | `docker-compose build` | Build containers | +| dce | `docker-compose exec` | Execute command inside a container | +| dcps | `docker-compose ps` | List containers | +| dcrestart | `docker-compose restart` | Restart container | +| dcrm | `docker-compose rm` | Remove container | +| dcr | `docker-compose run` | Run a command in container | +| dcstop | `docker-compose stop` | Stop a container | +| dcup | `docker-compose up` | Build, (re)create, start, and attach to containers for a service | +| dcupb | `docker-compose up --build` | Same as `dcup`, but build images before starting containers | +| dcupd | `docker-compose up -d` | Same as `dcup`, but starts as daemon | +| dcupdb | `docker-compose up -d --build` | Same as `dcup`, but build images before starting containers and starts as daemon | +| dcdn | `docker-compose down` | Stop and remove containers | +| dcl | `docker-compose logs` | Show logs of container | +| dclf | `docker-compose logs -f` | Show logs and follow output | +| dclF | `docker-compose logs -f --tail0` | Just follow recent logs | +| dcpull | `docker-compose pull` | Pull image of a service | +| dcstart | `docker-compose start` | Start a container | +| dck | `docker-compose kill` | Kills containers | diff --git a/zsh/.oh-my-zsh/plugins/docker-compose/_docker-compose b/zsh/.oh-my-zsh/plugins/docker-compose/_docker-compose new file mode 100644 index 0000000..f4be93f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/docker-compose/_docker-compose @@ -0,0 +1,421 @@ +#compdef docker-compose + +# Description +# ----------- +# zsh completion for docker-compose +# ------------------------------------------------------------------------- +# Authors +# ------- +# * Steve Durrheimer +# ------------------------------------------------------------------------- +# Inspiration +# ----------- +# * @albers docker-compose bash completion script +# * @felixr docker zsh completion script : https://github.com/felixr/docker-zsh-completion +# ------------------------------------------------------------------------- + +__docker-compose_q() { + docker-compose 2>/dev/null $compose_options "$@" +} + +# All services defined in docker-compose.yml +__docker-compose_all_services_in_compose_file() { + local already_selected + local -a services + already_selected=$(echo $words | tr " " "|") + __docker-compose_q ps --services "$@" \ + | grep -Ev "^(${already_selected})$" +} + +# All services, even those without an existing container +__docker-compose_services_all() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + services=$(__docker-compose_all_services_in_compose_file "$@") + _alternative "args:services:($services)" && ret=0 + + return ret +} + +# All services that are defined by a Dockerfile reference +__docker-compose_services_from_build() { + [[ $PREFIX = -* ]] && return 1 + __docker-compose_services_all --filter source=build +} + +# All services that are defined by an image +__docker-compose_services_from_image() { + [[ $PREFIX = -* ]] && return 1 + __docker-compose_services_all --filter source=image +} + +__docker-compose_pausedservices() { + [[ $PREFIX = -* ]] && return 1 + __docker-compose_services_all --filter status=paused +} + +__docker-compose_stoppedservices() { + [[ $PREFIX = -* ]] && return 1 + __docker-compose_services_all --filter status=stopped +} + +__docker-compose_runningservices() { + [[ $PREFIX = -* ]] && return 1 + __docker-compose_services_all --filter status=running +} + +__docker-compose_services() { + [[ $PREFIX = -* ]] && return 1 + __docker-compose_services_all +} + +__docker-compose_caching_policy() { + oldp=( "$1"(Nmh+1) ) # 1 hour + (( $#oldp )) +} + +__docker-compose_commands() { + local cache_policy + + zstyle -s ":completion:${curcontext}:" cache-policy cache_policy + if [[ -z "$cache_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy __docker-compose_caching_policy + fi + + if ( [[ ${+_docker_compose_subcommands} -eq 0 ]] || _cache_invalid docker_compose_subcommands) \ + && ! _retrieve_cache docker_compose_subcommands; + then + local -a lines + lines=(${(f)"$(_call_program commands docker-compose 2>&1)"}) + _docker_compose_subcommands=(${${${lines[$((${lines[(i)Commands:]} + 1)),${lines[(I) *]}]}## #}/ ##/:}) + (( $#_docker_compose_subcommands > 0 )) && _store_cache docker_compose_subcommands _docker_compose_subcommands + fi + _describe -t docker-compose-commands "docker-compose command" _docker_compose_subcommands +} + +__docker-compose_subcommand() { + local opts_help opts_force_recreate opts_no_recreate opts_no_build opts_remove_orphans opts_timeout opts_no_color opts_no_deps + + opts_help='(: -)--help[Print usage]' + opts_force_recreate="(--no-recreate)--force-recreate[Recreate containers even if their configuration and image haven't changed. Incompatible with --no-recreate.]" + opts_no_recreate="(--force-recreate)--no-recreate[If containers already exist, don't recreate them. Incompatible with --force-recreate.]" + opts_no_build="(--build)--no-build[Don't build an image, even if it's missing.]" + opts_remove_orphans="--remove-orphans[Remove containers for services not defined in the Compose file]" + opts_timeout=('(-t --timeout)'{-t,--timeout}"[Specify a shutdown timeout in seconds. (default: 10)]:seconds: ") + opts_no_color='--no-color[Produce monochrome output.]' + opts_no_deps="--no-deps[Don't start linked services.]" + + integer ret=1 + + case "$words[1]" in + (build) + _arguments \ + $opts_help \ + "*--build-arg=[Set build-time variables for one service.]:=: " \ + '--force-rm[Always remove intermediate containers.]' \ + '(--quiet -q)'{--quiet,-q}'[Curb build output]' \ + '(--memory -m)'{--memory,-m}'[Memory limit for the build container.]' \ + '--no-cache[Do not use cache when building the image.]' \ + '--pull[Always attempt to pull a newer version of the image.]' \ + '--compress[Compress the build context using gzip.]' \ + '--parallel[Build images in parallel.]' \ + '*:services:__docker-compose_services_from_build' && ret=0 + ;; + (config) + _arguments \ + $opts_help \ + '(--quiet -q)'{--quiet,-q}"[Only validate the configuration, don't print anything.]" \ + '--resolve-image-digests[Pin image tags to digests.]' \ + '--services[Print the service names, one per line.]' \ + '--volumes[Print the volume names, one per line.]' \ + '--hash[Print the service config hash, one per line. Set "service1,service2" for a list of specified services.]' && ret=0 + ;; + (create) + _arguments \ + $opts_help \ + $opts_force_recreate \ + $opts_no_recreate \ + $opts_no_build \ + "(--no-build)--build[Build images before creating containers.]" \ + '*:services:__docker-compose_services' && ret=0 + ;; + (down) + _arguments \ + $opts_help \ + $opts_timeout \ + "--rmi[Remove images. Type must be one of: 'all': Remove all images used by any service. 'local': Remove only images that don't have a custom tag set by the \`image\` field.]:type:(all local)" \ + '(-v --volumes)'{-v,--volumes}"[Remove named volumes declared in the \`volumes\` section of the Compose file and anonymous volumes attached to containers.]" \ + $opts_remove_orphans && ret=0 + ;; + (events) + _arguments \ + $opts_help \ + '--json[Output events as a stream of json objects]' \ + '*:services:__docker-compose_services' && ret=0 + ;; + (exec) + _arguments \ + $opts_help \ + '-d[Detached mode: Run command in the background.]' \ + '--privileged[Give extended privileges to the process.]' \ + '(-u --user)'{-u,--user=}'[Run the command as this user.]:username:_users' \ + '-T[Disable pseudo-tty allocation. By default `docker-compose exec` allocates a TTY.]' \ + '--index=[Index of the container if there are multiple instances of a service \[default: 1\]]:index: ' \ + '*'{-e,--env}'[KEY=VAL Set an environment variable (can be used multiple times)]:environment variable KEY=VAL: ' \ + '(-w --workdir)'{-w,--workdir=}'[Working directory inside the container]:workdir: ' \ + '(-):running services:__docker-compose_runningservices' \ + '(-):command: _command_names -e' \ + '*::arguments: _normal' && ret=0 + ;; + (help) + _arguments ':subcommand:__docker-compose_commands' && ret=0 + ;; + (images) + _arguments \ + $opts_help \ + '-q[Only display IDs]' \ + '*:services:__docker-compose_services' && ret=0 + ;; + (kill) + _arguments \ + $opts_help \ + '-s[SIGNAL to send to the container. Default signal is SIGKILL.]:signal:_signals' \ + '*:running services:__docker-compose_runningservices' && ret=0 + ;; + (logs) + _arguments \ + $opts_help \ + '(-f --follow)'{-f,--follow}'[Follow log output]' \ + $opts_no_color \ + '--tail=[Number of lines to show from the end of the logs for each container.]:number of lines: ' \ + '(-t --timestamps)'{-t,--timestamps}'[Show timestamps]' \ + '*:services:__docker-compose_services' && ret=0 + ;; + (pause) + _arguments \ + $opts_help \ + '*:running services:__docker-compose_runningservices' && ret=0 + ;; + (port) + _arguments \ + $opts_help \ + '--protocol=[tcp or udp \[default: tcp\]]:protocol:(tcp udp)' \ + '--index=[index of the container if there are multiple instances of a service \[default: 1\]]:index: ' \ + '1:running services:__docker-compose_runningservices' \ + '2:port:_ports' && ret=0 + ;; + (ps) + _arguments \ + $opts_help \ + '-q[Only display IDs]' \ + '--filter KEY=VAL[Filter services by a property]:=:' \ + '*:services:__docker-compose_services' && ret=0 + ;; + (pull) + _arguments \ + $opts_help \ + '--ignore-pull-failures[Pull what it can and ignores images with pull failures.]' \ + '--no-parallel[Disable parallel pulling]' \ + '(-q --quiet)'{-q,--quiet}'[Pull without printing progress information]' \ + '--include-deps[Also pull services declared as dependencies]' \ + '*:services:__docker-compose_services_from_image' && ret=0 + ;; + (push) + _arguments \ + $opts_help \ + '--ignore-push-failures[Push what it can and ignores images with push failures.]' \ + '*:services:__docker-compose_services' && ret=0 + ;; + (rm) + _arguments \ + $opts_help \ + '(-f --force)'{-f,--force}"[Don't ask to confirm removal]" \ + '-v[Remove any anonymous volumes attached to containers]' \ + '*:stopped services:__docker-compose_stoppedservices' && ret=0 + ;; + (run) + _arguments \ + $opts_help \ + $opts_no_deps \ + '-d[Detached mode: Run container in the background, print new container name.]' \ + '*-e[KEY=VAL Set an environment variable (can be used multiple times)]:environment variable KEY=VAL: ' \ + '*'{-l,--label}'[KEY=VAL Add or override a label (can be used multiple times)]:label KEY=VAL: ' \ + '--entrypoint[Overwrite the entrypoint of the image.]:entry point: ' \ + '--name=[Assign a name to the container]:name: ' \ + '(-p --publish)'{-p,--publish=}"[Publish a container's port(s) to the host]" \ + '--rm[Remove container after run. Ignored in detached mode.]' \ + "--service-ports[Run command with the service's ports enabled and mapped to the host.]" \ + '-T[Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY.]' \ + '(-u --user)'{-u,--user=}'[Run as specified username or uid]:username or uid:_users' \ + '(-v --volume)*'{-v,--volume=}'[Bind mount a volume]:volume: ' \ + '(-w --workdir)'{-w,--workdir=}'[Working directory inside the container]:workdir: ' \ + "--use-aliases[Use the services network aliases in the network(s) the container connects to]" \ + '(-):services:__docker-compose_services' \ + '(-):command: _command_names -e' \ + '*::arguments: _normal' && ret=0 + ;; + (scale) + _arguments \ + $opts_help \ + $opts_timeout \ + '*:running services:__docker-compose_runningservices' && ret=0 + ;; + (start) + _arguments \ + $opts_help \ + '*:stopped services:__docker-compose_stoppedservices' && ret=0 + ;; + (stop|restart) + _arguments \ + $opts_help \ + $opts_timeout \ + '*:running services:__docker-compose_runningservices' && ret=0 + ;; + (top) + _arguments \ + $opts_help \ + '*:running services:__docker-compose_runningservices' && ret=0 + ;; + (unpause) + _arguments \ + $opts_help \ + '*:paused services:__docker-compose_pausedservices' && ret=0 + ;; + (up) + _arguments \ + $opts_help \ + '(--abort-on-container-exit)-d[Detached mode: Run containers in the background, print new container names. Incompatible with --abort-on-container-exit and --attach-dependencies.]' \ + $opts_no_color \ + $opts_no_deps \ + $opts_force_recreate \ + $opts_no_recreate \ + $opts_no_build \ + "(--no-build)--build[Build images before starting containers.]" \ + "(-d)--abort-on-container-exit[Stops all containers if any container was stopped. Incompatible with -d.]" \ + "(-d)--attach-dependencies[Attach to dependent containers. Incompatible with -d.]" \ + '(-t --timeout)'{-t,--timeout}"[Use this timeout in seconds for container shutdown when attached or when containers are already running. (default: 10)]:seconds: " \ + '--scale[SERVICE=NUM Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.]:service scale SERVICE=NUM: ' \ + '--exit-code-from=[Return the exit code of the selected service container. Implies --abort-on-container-exit]:service:__docker-compose_services' \ + $opts_remove_orphans \ + '*:services:__docker-compose_services' && ret=0 + ;; + (version) + _arguments \ + $opts_help \ + "--short[Shows only Compose's version number.]" && ret=0 + ;; + (*) + _message 'Unknown sub command' && ret=1 + ;; + esac + + return ret +} + +_docker-compose() { + # Support for subservices, which allows for `compdef _docker docker-shell=_docker_containers`. + # Based on /usr/share/zsh/functions/Completion/Unix/_git without support for `ret`. + if [[ $service != docker-compose ]]; then + _call_function - _$service + return + fi + + local curcontext="$curcontext" state line + integer ret=1 + typeset -A opt_args + + local file_description + + if [[ -n ${words[(r)-f]} || -n ${words[(r)--file]} ]] ; then + file_description="Specify an override docker-compose file (default: docker-compose.override.yml)" + else + file_description="Specify an alternate docker-compose file (default: docker-compose.yml)" + fi + + _arguments -C \ + '(- :)'{-h,--help}'[Get help]' \ + '*'{-f,--file}"[${file_description}]:file:_files -g '*.yml'" \ + '(-p --project-name)'{-p,--project-name}'[Specify an alternate project name (default: directory name)]:project name:' \ + '--env-file[Specify an alternate environment file (default: .env)]:env-file:_files' \ + "--compatibility[If set, Compose will attempt to convert keys in v3 files to their non-Swarm equivalent]" \ + '(- :)'{-v,--version}'[Print version and exit]' \ + '--verbose[Show more output]' \ + '--log-level=[Set log level]:level:(DEBUG INFO WARNING ERROR CRITICAL)' \ + '--no-ansi[Do not print ANSI control characters]' \ + '--ansi=[Control when to print ANSI control characters]:when:(never always auto)' \ + '(-H --host)'{-H,--host}'[Daemon socket to connect to]:host:' \ + '--tls[Use TLS; implied by --tlsverify]' \ + '--tlscacert=[Trust certs signed only by this CA]:ca path:' \ + '--tlscert=[Path to TLS certificate file]:client cert path:' \ + '--tlskey=[Path to TLS key file]:tls key path:' \ + '--tlsverify[Use TLS and verify the remote]' \ + "--skip-hostname-check[Don't check the daemon's hostname against the name specified in the client certificate (for example if your docker host is an IP address)]" \ + '(-): :->command' \ + '(-)*:: :->option-or-argument' && ret=0 + + local -a relevant_compose_flags relevant_compose_repeatable_flags relevant_docker_flags compose_options docker_options + + relevant_compose_flags=( + "--env-file" + "--file" "-f" + "--host" "-H" + "--project-name" "-p" + "--tls" + "--tlscacert" + "--tlscert" + "--tlskey" + "--tlsverify" + "--skip-hostname-check" + ) + + relevant_compose_repeatable_flags=( + "--file" "-f" + ) + + relevant_docker_flags=( + "--host" "-H" + "--tls" + "--tlscacert" + "--tlscert" + "--tlskey" + "--tlsverify" + ) + + for k in "${(@k)opt_args}"; do + if [[ -n "${relevant_docker_flags[(r)$k]}" ]]; then + docker_options+=$k + if [[ -n "$opt_args[$k]" ]]; then + docker_options+=$opt_args[$k] + fi + fi + if [[ -n "${relevant_compose_flags[(r)$k]}" ]]; then + if [[ -n "${relevant_compose_repeatable_flags[(r)$k]}" ]]; then + values=("${(@s/:/)opt_args[$k]}") + for value in $values + do + compose_options+=$k + compose_options+=$value + done + else + compose_options+=$k + if [[ -n "$opt_args[$k]" ]]; then + compose_options+=$opt_args[$k] + fi + fi + fi + done + + case $state in + (command) + __docker-compose_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-compose-$words[1]: + __docker-compose_subcommand && ret=0 + ;; + esac + + return ret +} + +_docker-compose "$@" diff --git a/zsh/.oh-my-zsh/plugins/docker-compose/docker-compose.plugin.zsh b/zsh/.oh-my-zsh/plugins/docker-compose/docker-compose.plugin.zsh new file mode 100644 index 0000000..b4f0f8f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/docker-compose/docker-compose.plugin.zsh @@ -0,0 +1,24 @@ +# support Compose v2 as docker CLI plugin +(( ${+commands[docker-compose]} )) && dccmd='docker-compose' || dccmd='docker compose' + +alias dco="$dccmd" +alias dcb="$dccmd build" +alias dce="$dccmd exec" +alias dcps="$dccmd ps" +alias dcrestart="$dccmd restart" +alias dcrm="$dccmd rm" +alias dcr="$dccmd run" +alias dcstop="$dccmd stop" +alias dcup="$dccmd up" +alias dcupb="$dccmd up --build" +alias dcupd="$dccmd up -d" +alias dcupdb="$dccmd up -d --build" +alias dcdn="$dccmd down" +alias dcl="$dccmd logs" +alias dclf="$dccmd logs -f" +alias dclF="$dccmd logs -f --tail 0" +alias dcpull="$dccmd pull" +alias dcstart="$dccmd start" +alias dck="$dccmd kill" + +unset dccmd diff --git a/zsh/.oh-my-zsh/plugins/docker-machine/README.md b/zsh/.oh-my-zsh/plugins/docker-machine/README.md new file mode 100644 index 0000000..9c3c533 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/docker-machine/README.md @@ -0,0 +1,19 @@ +# docker-machine plugin for oh my zsh + +### Usage + +#### docker-vm +Will create a docker-machine with the name "dev" (required only once) +To create a second machine call "docker-vm foobar" or pass any other name + +#### docker-up +This will start your "dev" docker-machine (if necessary) and set it as the active one +To start a named machine use "docker-up foobar" + +#### docker-switch dev +Use this to activate a running docker-machine (or to switch between multiple machines) +You need to call either this or docker-up when opening a new terminal + +#### docker-stop +This will stop your "dev" docker-machine +To stop a named machine use "docker-stop foobar" \ No newline at end of file diff --git a/zsh/.oh-my-zsh/plugins/docker-machine/_docker-machine b/zsh/.oh-my-zsh/plugins/docker-machine/_docker-machine new file mode 100644 index 0000000..7f10520 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/docker-machine/_docker-machine @@ -0,0 +1,359 @@ +#compdef docker-machine +# Description +# ----------- +# zsh completion for docker-machine +# https://github.com/leonhartX/docker-machine-zsh-completion +# ------------------------------------------------------------------------- +# Version +# ------- +# 0.1.1 +# ------------------------------------------------------------------------- +# Authors +# ------- +# * Ke Xu +# ------------------------------------------------------------------------- +# Inspiration +# ----------- +# * @sdurrheimer docker-compose-zsh-completion https://github.com/sdurrheimer/docker-compose-zsh-completion +# * @ilkka _docker-machine + + +__docker-machine_get_hosts() { + [[ $PREFIX = -* ]] && return 1 + local state + declare -a hosts + state=$1; shift + if [[ $state != all ]]; then + hosts=(${(f)"$(_call_program commands docker-machine ls -q --filter state=$state)"}) + else + hosts=(${(f)"$(_call_program commands docker-machine ls -q)"}) + fi + _describe 'host' hosts "$@" && ret=0 + return ret +} + +__docker-machine_hosts_with_state() { + declare -a hosts + hosts=(${(f)"$(_call_program commands docker-machine ls -f '{{.Name}}\:{{.DriverName}}\({{.State}}\)\ {{.URL}}')"}) + _describe 'host' hosts +} + +__docker-machine_hosts_all() { + __docker-machine_get_hosts all "$@" +} + +__docker-machine_hosts_running() { + __docker-machine_get_hosts Running "$@" +} + +__docker-machine_get_swarm() { + declare -a swarms + swarms=(${(f)"$(_call_program commands docker-machine ls -f {{.Swarm}} | awk '{print $1}')"}) + _describe 'swarm' swarms +} + +__docker-machine_hosts_and_files() { + _alternative "hosts:host:__docker-machine_hosts_all -qS ':'" 'files:files:_path_files' +} + +__docker-machine_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (driver) + _describe -t driver-filter-opts "driver filter" opts_driver && ret=0 + ;; + (swarm) + __docker-machine_get_swarm && ret=0 + ;; + (state) + opts_state=('Running' 'Paused' 'Saved' 'Stopped' 'Stopping' 'Starting' 'Error') + _describe -t state-filter-opts "state filter" opts_state && ret=0 + ;; + (name) + __docker-machine_hosts_all && ret=0 + ;; + (label) + _message 'label' && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('driver' 'swarm' 'state' 'name' 'label') + _describe -t filter-opts "filter" opts -qS "=" && ret=0 + fi + return ret +} + +__get_swarm_discovery() { + declare -a masters services + local service + services=() + masters=($(docker-machine ls -f {{.Swarm}} |grep '(master)' |awk '{print $1}')) + for master in $masters; do + service=${${${(f)"$(_call_program commands docker-machine inspect -f '{{.HostOptions.SwarmOptions.Discovery}}:{{.Name}}' $master)"}/:/\\:}} + services=($services $service) + done + _describe -t services "swarm service" services && ret=0 + return ret +} + +__get_create_argument() { + typeset -g docker_machine_driver + if [[ CURRENT -le 2 ]]; then + docker_machine_driver="none" + elif [[ CURRENT > 2 && $words[CURRENT-2] = '-d' || $words[CURRENT-2] = '--driver' ]]; then + docker_machine_driver=$words[CURRENT-1] + elif [[ $words[CURRENT-1] =~ '^(-d|--driver)=' ]]; then + docker_machine_driver=${${words[CURRENT-1]}/*=/} + fi + local driver_opt_cmd + local -a opts_provider opts_common opts_read_argument + opts_read_argument=( + ": :->argument" + ) + opts_common=( + $opts_help \ + '(--driver -d)'{--driver=,-d=}'[Driver to create machine with]:dirver:->driver-option' \ + '--engine-install-url=[Custom URL to use for engine installation]:url' \ + '*--engine-opt=[Specify arbitrary flags to include with the created engine in the form flag=value]:flag' \ + '*--engine-insecure-registry=[Specify insecure registries to allow with the created engine]:registry' \ + '*--engine-registry-mirror=[Specify registry mirrors to use]:mirror' \ + '*--engine-label=[Specify labels for the created engine]:label' \ + '--engine-storage-driver=[Specify a storage driver to use with the engine]:storage-driver:->storage-driver-option' \ + '*--engine-env=[Specify environment variables to set in the engine]:environment' \ + '--swarm[Configure Machine with Swarm]' \ + '--swarm-image=[Specify Docker image to use for Swarm]:image' \ + '--swarm-master[Configure Machine to be a Swarm master]' \ + '--swarm-discovery=[Discovery service to use with Swarm]:service:->swarm-service' \ + '--swarm-strategy=[Define a default scheduling strategy for Swarm]:strategy:(spread binpack random)' \ + '*--swarm-opt=[Define arbitrary flags for swarm]:flag' \ + '*--swarm-join-opt=[Define arbitrary flags for Swarm join]:flag' \ + '--swarm-host=[ip/socket to listen on for Swarm master]:host' \ + '--swarm-addr=[addr to advertise for Swarm (default: detect and use the machine IP)]:address' \ + '--swarm-experimental[Enable Swarm experimental features]' \ + '*--tls-san=[Support extra SANs for TLS certs]:option' + ) + driver_opt_cmd="docker-machine create -d $docker_machine_driver | grep $docker_machine_driver | sed -e 's/\(--.*\)\ *\[\1[^]]*\]/*\1/g' -e 's/\(\[[^]]*\)/\\\\\\1\\\\/g' -e 's/\".*\"\(.*\)/\1/g' | awk '{printf \"%s[\", \$1; for(i=2;i<=NF;i++) {printf \"%s \", \$i}; print \"]\"}'" + if [[ $docker_machine_driver != "none" ]]; then + opts_provider=(${(f)"$(_call_program commands $driver_opt_cmd)"}) + _arguments \ + $opts_provider \ + $opts_read_argument \ + $opts_common && ret=0 + else + _arguments $opts_common && ret=0 + fi + case $state in + (driver-option) + _describe -t driver-option "driver" opts_driver && ret=0 + ;; + (storage-driver-option) + _describe -t storage-driver-option "storage driver" opts_storage_driver && ret=0 + ;; + (swarm-service) + __get_swarm_discovery && ret=0 + ;; + (argument) + ret=0 + ;; + esac + return ret +} + + +__docker-machine_subcommand() { + local -a opts_help + opts_help=("(- :)--help[Print usage]") + local -a opts_only_host opts_driver opts_storage_driver opts_state + opts_only_host=( + "$opts_help" + "*:host:__docker-machine_hosts_all" + ) + opts_driver=('amazonec2' 'azure' 'digitalocean' 'exoscale' 'generic' 'google' 'hyperv' 'none' 'openstack' 'rackspace' 'softlayer' 'virtualbox' 'vmwarefusion' 'vmwarevcloudair' 'vmwarevsphere') + opts_storage_driver=('overlay' 'aufs' 'btrfs' 'devicemapper' 'vfs' 'zfs') + integer ret=1 + + case "$words[1]" in + (active) + _arguments \ + $opts_help \ + '(--timeout -t)'{--timeout=,-t=}'[Timeout in seconds, default to 10s]:seconds' && ret=0 + ;; + (config) + _arguments \ + $opts_help \ + '--swarm[Display the Swarm config instead of the Docker daemon]' \ + "*:host:__docker-machine_hosts_all" && ret=0 + ;; + (create) + __get_create_argument + ;; + (env) + _arguments \ + $opts_help \ + '--swarm[Display the Swarm config instead of the Docker daemon]' \ + '--shell=[Force environment to be configured for a specified shell: \[fish, cmd, powershell\], default is auto-detect]:shell' \ + '(--unset -u)'{--unset,-u}'[Unset variables instead of setting them]' \ + '--no-proxy[Add machine IP to NO_PROXY environment variable]' \ + '*:host:__docker-machine_hosts_running' && ret=0 + ;; + (help) + _arguments ':subcommand:__docker-machine_commands' && ret=0 + ;; + (inspect) + _arguments \ + $opts_help \ + '(--format -f)'{--format=,-f=}'[Format the output using the given go template]:template' \ + '*:host:__docker-machine_hosts_all' && ret=0 + ;; + (ip) + _arguments \ + $opts_help \ + '*:host:__docker-machine_hosts_running' && ret=0 + ;; + (kill) + _arguments \ + $opts_help \ + '*:host:__docker-machine_hosts_with_state' && ret=0 + ;; + (ls) + _arguments \ + $opts_help \ + '(--quiet -q)'{--quiet,-q}'[Enable quiet mode]' \ + '*--filter=[Filter output based on conditions provided]:filter:->filter-options' \ + '(--timeout -t)'{--timeout=,-t=}'[Timeout in seconds, default to 10s]:seconds' \ + '(--format -f)'{--format=,-f=}'[Pretty-print machines using a Go template]:template' && ret=0 + case $state in + (filter-options) + __docker-machine_filters && ret=0 + ;; + esac + ;; + (provision) + _arguments $opts_only_host && ret=0 + ;; + (regenerate-certs) + _arguments \ + $opts_help \ + '(--force -f)'{--force,-f}'[Force rebuild and do not prompt]' \ + '*:host:__docker-machine_hosts_all' && ret=0 + ;; + (restart) + _arguments \ + $opts_help \ + '*:host:__docker-machine_hosts_with_state' && ret=0 + ;; + (rm) + _arguments \ + $opts_help \ + '(--force -f)'{--force,-f}'[Remove local configuration even if machine cannot be removed, also implies an automatic yes (`-y`)]' \ + '-y[Assumes automatic yes to proceed with remove, without prompting further user confirmation]' \ + '*:host:__docker-machine_hosts_with_state' && ret=0 + ;; + (scp) + _arguments \ + $opts_help \ + '(--recursive -r)'{--recursive,-r}'[Copy files recursively (required to copy directories))]' \ + '*:files:__docker-machine_hosts_and_files' && ret=0 + ;; + (ssh) + _arguments \ + $opts_help \ + '*:host:__docker-machine_hosts_running' && ret=0 + ;; + (start) + _arguments \ + $opts_help \ + '*:host:__docker-machine_hosts_with_state' && ret=0 + ;; + (status) + _arguments $opts_only_host && ret=0 + ;; + (stop) + _arguments \ + $opts_help \ + '*:host:__docker-machine_hosts_with_state' && ret=0 + ;; + (upgrade) + _arguments $opts_only_host && ret=0 + ;; + (url) + _arguments \ + $opts_help \ + '*:host:__docker-machine_hosts_running' && ret=0 + ;; + esac + + return ret +} + + +__docker-machine_commands() { + local cache_policy + + zstyle -s ":completion:${curcontext}:" cache-policy cache_policy + if [[ -z "$cache_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy __docker-machine_caching_policy + fi + + if ( [[ ${+_docker_machine_subcommands} -eq 0 ]] || _cache_invalid docker_machine_subcommands) \ + && ! _retrieve_cache docker_machine_subcommands; + then + local -a lines + lines=(${(f)"$(_call_program commands docker-machine 2>&1)"}) + _docker_machine_subcommands=(${${${lines[$((${lines[(i)Commands:]} + 1)),${lines[(I) *]}]}## #}/$'\t'##/:}) + (( $#_docker_machine_subcommands > 0 )) && _store_cache docker_machine_subcommands _docker_machine_subcommands + fi + _describe -t docker-machine-commands "docker-machine command" _docker_machine_subcommands +} + +__docker-machine_caching_policy() { + oldp=( "$1"(Nmh+1) ) + (( $#oldp )) +} + +_docker-machine() { + if [[ $service != docker-machine ]]; then + _call_function - _$service + return + fi + + local curcontext="$curcontext" state line + integer ret=1 + typeset -A opt_args + + _arguments -C \ + "(- :)"{-h,--help}"[Show help]" \ + "(-D --debug)"{-D,--debug}"[Enable debug mode]" \ + '(-s --storage-path)'{-s,--storage-path}'[Configures storage path]:file:_files' \ + '--tls-ca-cert[CA to verify remotes against]:file:_files' \ + '--tls-ca-key[Private key to generate certificates]:file:_files' \ + '--tls-client-cert[Client cert to use for TLS]:file:_files' \ + '--tls-client-key[Private key used in client TLS auth]:file:_files' \ + '--github-api-token[Token to use for requests to the GitHub API]' \ + '--native-ssh[Use the native (Go-based) SSH implementation.]' \ + '--bugsnag-api-token[Bugsnag API token for crash reporting]' \ + '(- :)'{-v,--version}'[Print the version]' \ + "(-): :->command" \ + "(-)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker-machine_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-machine-$words[1]: + __docker-machine_subcommand && ret=0 + ret=0 + ;; + esac + + return ret +} + +_docker-machine "$@" diff --git a/zsh/.oh-my-zsh/plugins/docker-machine/docker-machine.plugin.zsh b/zsh/.oh-my-zsh/plugins/docker-machine/docker-machine.plugin.zsh new file mode 100644 index 0000000..5257737 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/docker-machine/docker-machine.plugin.zsh @@ -0,0 +1,33 @@ +DEFAULT_MACHINE="default" + +docker-up() { + if [ -z "$1" ] + then + docker-machine start "${DEFAULT_MACHINE}" + eval $(docker-machine env "${DEFAULT_MACHINE}") + else + docker-machine start $1 + eval $(docker-machine env $1) + fi + echo $DOCKER_HOST +} +docker-stop() { + if [ -z "$1" ] + then + docker-machine stop "${DEFAULT_MACHINE}" + else + docker-machine stop $1 + fi +} +docker-switch() { + eval $(docker-machine env $1) + echo $DOCKER_HOST +} +docker-vm() { + if [ -z "$1" ] + then + docker-machine create -d virtualbox --virtualbox-disk-size 20000 --virtualbox-memory 4096 --virtualbox-cpu-count 2 "${DEFAULT_MACHINE}" + else + docker-machine create -d virtualbox --virtualbox-disk-size 20000 --virtualbox-memory 4096 --virtualbox-cpu-count 2 $1 + fi +} \ No newline at end of file diff --git a/zsh/.oh-my-zsh/plugins/docker/README.md b/zsh/.oh-my-zsh/plugins/docker/README.md new file mode 100644 index 0000000..1ae07eb --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/docker/README.md @@ -0,0 +1,80 @@ +# Docker plugin + +This plugin adds auto-completion and aliases for [docker](https://www.docker.com/). + +To use it add `docker` to the plugins array in your zshrc file. + +```zsh +plugins=(... docker) +``` + +A copy of the completion script from the docker/cli git repo: +https://github.com/docker/cli/blob/master/contrib/completion/zsh/_docker + +## Settings + +By default, the completion doesn't allow option-stacking, meaning if you try to complete +`docker run -it ` it won't work, because you're _stacking_ the `-i` and `-t` options. + +[You can enable it](https://github.com/docker/cli/commit/b10fb43048) by **adding the lines below to your zshrc +file**, but be aware of the side effects: + +> This enables Zsh to understand commands like `docker run -it ubuntu`. However, by enabling this, this also +> makes Zsh complete `docker run -u` with `docker run -uapprox` which is not valid. The users have to put +> the space or the equal sign themselves before trying to complete. +> +> Therefore, this behavior is disabled by default. To enable it: +> +> ```sh +> zstyle ':completion:*:*:docker:*' option-stacking yes +> zstyle ':completion:*:*:docker-*:*' option-stacking yes +> ``` + +### Use old-style completion + +If the current completion does not work well for you, you can enable legacy completion instead with the +following setting. See https://github.com/ohmyzsh/ohmyzsh/issues/11789 for more information. + +```zsh +zstyle ':omz:plugins:docker' legacy-completion yes +``` + +## Aliases + +| Alias | Command | Description | +| :------ | :---------------------------- | :--------------------------------------------------------------------------------------- | +| dbl | `docker build` | Build an image from a Dockerfile | +| dcin | `docker container inspect` | Display detailed information on one or more containers | +| dcls | `docker container ls` | List all the running docker containers | +| dclsa | `docker container ls -a` | List all running and stopped containers | +| dib | `docker image build` | Build an image from a Dockerfile (same as docker build) | +| dii | `docker image inspect` | Display detailed information on one or more images | +| dils | `docker image ls` | List docker images | +| dipu | `docker image push` | Push an image or repository to a remote registry | +| dirm | `docker image rm` | Remove one or more images | +| dit | `docker image tag` | Add a name and tag to a particular image | +| dlo | `docker container logs` | Fetch the logs of a docker container | +| dnc | `docker network create` | Create a new network | +| dncn | `docker network connect` | Connect a container to a network | +| dndcn | `docker network disconnect` | Disconnect a container from a network | +| dni | `docker network inspect` | Return information about one or more networks | +| dnls | `docker network ls` | List all networks the engine daemon knows about, including those spanning multiple hosts | +| dnrm | `docker network rm` | Remove one or more networks | +| dpo | `docker container port` | List port mappings or a specific mapping for the container | +| dps | `docker ps` | List all the running docker containers | +| dpsa | `docker ps -a` | List all running and stopped containers | +| dpu | `docker pull` | Pull an image or a repository from a registry | +| dr | `docker container run` | Create a new container and start it using the specified command | +| drit | `docker container run -it` | Create a new container and start it in an interactive shell | +| drm | `docker container rm` | Remove the specified container(s) | +| drm! | `docker container rm -f` | Force the removal of a running container (uses SIGKILL) | +| dst | `docker container start` | Start one or more stopped containers | +| drs | `docker container restart` | Restart one or more containers | +| dsta | `docker stop $(docker ps -q)` | Stop all running containers | +| dstp | `docker container stop` | Stop one or more running containers | +| dtop | `docker top` | Display the running processes of a container | +| dvi | `docker volume inspect` | Display detailed information about one or more volumes | +| dvls | `docker volume ls` | List all the volumes known to docker | +| dvprune | `docker volume prune` | Cleanup dangling volumes | +| dxc | `docker container exec` | Run a new command in a running container | +| dxcit | `docker container exec -it` | Run a new command in a running container in an interactive shell | diff --git a/zsh/.oh-my-zsh/plugins/docker/completions/_docker b/zsh/.oh-my-zsh/plugins/docker/completions/_docker new file mode 100644 index 0000000..c41bc2e --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/docker/completions/_docker @@ -0,0 +1,3126 @@ +#compdef docker dockerd +# +# zsh completion for docker (http://docker.com) +# +# version: 0.3.0 +# github: https://github.com/felixr/docker-zsh-completion +# +# contributors: +# - Felix Riedel +# - Steve Durrheimer +# - Vincent Bernat +# - Rohan Verma +# +# license: +# +# Copyright (c) 2013, Felix Riedel +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# Short-option stacking can be enabled with: +# zstyle ':completion:*:*:docker:*' option-stacking yes +# zstyle ':completion:*:*:docker-*:*' option-stacking yes +__docker_arguments() { + if zstyle -t ":completion:${curcontext}:" option-stacking; then + print -- -s + fi +} + +__docker_get_containers() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local kind type line s + declare -a running stopped lines args names + + kind=$1; shift + type=$1; shift + [[ $kind = (stopped|all) ]] && args=($args -a) + + lines=(${(f)${:-"$(_call_program commands docker $docker_options ps --format 'table' --no-trunc $args)"$'\n'}}) + + # Parse header line to find columns + local i=1 j=1 k header=${lines[1]} + declare -A begin end + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done + end[${header[$i,$((j-1))]}]=-1 # Last column, should go to the end of the line + lines=(${lines[2,-1]}) + + # Container ID + if [[ $type = (ids|all) ]]; then + for line in $lines; do + s="${${line[${begin[CONTAINER ID]},${end[CONTAINER ID]}]%% ##}[0,12]}" + s="$s:${(l:15:: :::)${${line[${begin[CREATED]},${end[CREATED]}]/ ago/}%% ##}}" + s="$s, ${${${line[${begin[IMAGE]},${end[IMAGE]}]}/:/\\:}%% ##}" + if [[ ${line[${begin[STATUS]},${end[STATUS]}]} = (Exit*|Created*) ]]; then + stopped=($stopped $s) + else + running=($running $s) + fi + done + fi + + # Names: we only display the one without slash. All other names + # are generated and may clutter the completion. However, with + # Swarm, all names may be prefixed by the swarm node name. + if [[ $type = (names|all) ]]; then + for line in $lines; do + names=(${(ps:,:)${${line[${begin[NAMES]},${end[NAMES]}]}%% *}}) + # First step: find a common prefix and strip it (swarm node case) + (( ${#${(u)names%%/*}} == 1 )) && names=${names#${names[1]%%/*}/} + # Second step: only keep the first name without a / + s=${${names:#*/*}[1]} + # If no name, well give up. + (( $#s != 0 )) || continue + s="$s:${(l:15:: :::)${${line[${begin[CREATED]},${end[CREATED]}]/ ago/}%% ##}}" + s="$s, ${${${line[${begin[IMAGE]},${end[IMAGE]}]}/:/\\:}%% ##}" + if [[ ${line[${begin[STATUS]},${end[STATUS]}]} = (Exit*|Created*) ]]; then + stopped=($stopped $s) + else + running=($running $s) + fi + done + fi + + [[ $kind = (running|all) ]] && _describe -t containers-running "running containers" running "$@" && ret=0 + [[ $kind = (stopped|all) ]] && _describe -t containers-stopped "stopped containers" stopped "$@" && ret=0 + return ret +} + +__docker_complete_stopped_containers() { + [[ $PREFIX = -* ]] && return 1 + __docker_get_containers stopped all "$@" +} + +__docker_complete_running_containers() { + [[ $PREFIX = -* ]] && return 1 + __docker_get_containers running all "$@" +} + +__docker_complete_containers() { + [[ $PREFIX = -* ]] && return 1 + __docker_get_containers all all "$@" +} + +__docker_complete_containers_ids() { + [[ $PREFIX = -* ]] && return 1 + __docker_get_containers all ids "$@" +} + +__docker_complete_containers_names() { + [[ $PREFIX = -* ]] && return 1 + __docker_get_containers all names "$@" +} + +__docker_complete_info_plugins() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + emulate -L zsh + setopt extendedglob + local -a plugins + plugins=(${(ps: :)${(M)${(f)${${"$(_call_program commands docker $docker_options info)"##*$'\n'Plugins:}%%$'\n'^ *}}:# $1: *}## $1: }) + _describe -t plugins "$1 plugins" plugins && ret=0 + return ret +} + +__docker_complete_images() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + declare -a images + images=(${${${(f)${:-"$(_call_program commands docker $docker_options images)"$'\n'}}[2,-1]}/(#b)([^ ]##) ##([^ ]##) ##([^ ]##)*/${match[3]}:${(r:15:: :::)match[2]} in ${match[1]}}) + _describe -t docker-images "images" images && ret=0 + __docker_complete_repositories_with_tags && ret=0 + return ret +} + +__docker_complete_repositories() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + declare -a repos + repos=(${${${(f)${:-"$(_call_program commands docker $docker_options images)"$'\n'}}%% *}[2,-1]}) + repos=(${repos#}) + _describe -t docker-repos "repositories" repos && ret=0 + return ret +} + +__docker_complete_repositories_with_tags() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + declare -a repos onlyrepos matched + declare m + repos=(${${${${(f)${:-"$(_call_program commands docker $docker_options images)"$'\n'}}[2,-1]}/ ##/:::}%% *}) + repos=(${${repos%:::}#}) + # Check if we have a prefix-match for the current prefix. + onlyrepos=(${repos%::*}) + for m in $onlyrepos; do + [[ ${PREFIX##${~~m}} != ${PREFIX} ]] && { + # Yes, complete with tags + repos=(${${repos/:::/:}/:/\\:}) + _describe -t docker-repos-with-tags "repositories with tags" repos && ret=0 + return ret + } + done + # No, only complete repositories + onlyrepos=(${${repos%:::*}/:/\\:}) + _describe -t docker-repos "repositories" onlyrepos -qS : && ret=0 + + return ret +} + +__docker_search() { + [[ $PREFIX = -* ]] && return 1 + local cache_policy + zstyle -s ":completion:${curcontext}:" cache-policy cache_policy + if [[ -z "$cache_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy __docker_caching_policy + fi + + local searchterm cachename + searchterm="${words[$CURRENT]%/}" + cachename=_docker-search-$searchterm + + local expl + local -a result + if ( [[ ${(P)+cachename} -eq 0 ]] || _cache_invalid ${cachename#_} ) \ + && ! _retrieve_cache ${cachename#_}; then + _message "Searching for ${searchterm}..." + result=(${${${(f)${:-"$(_call_program commands docker $docker_options search $searchterm)"$'\n'}}%% *}[2,-1]}) + _store_cache ${cachename#_} result + fi + _wanted dockersearch expl 'available images' compadd -a result +} + +__docker_get_log_options() { + [[ $PREFIX = -* ]] && return 1 + + integer ret=1 + local log_driver=${opt_args[--log-driver]:-"all"} + local -a common_options common_options2 awslogs_options fluentd_options gelf_options journald_options json_file_options logentries_options syslog_options splunk_options + + common_options=("max-buffer-size" "mode") + common_options2=("env" "env-regex" "labels") + awslogs_options=($common_options "awslogs-create-group" "awslogs-datetime-format" "awslogs-group" "awslogs-multiline-pattern" "awslogs-region" "awslogs-stream" "tag") + fluentd_options=($common_options $common_options2 "fluentd-address" "fluentd-async-connect" "fluentd-buffer-limit" "fluentd-retry-wait" "fluentd-max-retries" "fluentd-sub-second-precision" "tag") + gcplogs_options=($common_options $common_options2 "gcp-log-cmd" "gcp-meta-id" "gcp-meta-name" "gcp-meta-zone" "gcp-project") + gelf_options=($common_options $common_options2 "gelf-address" "gelf-compression-level" "gelf-compression-type" "tag") + journald_options=($common_options $common_options2 "tag") + json_file_options=($common_options $common_options2 "max-file" "max-size") + logentries_options=($common_options $common_options2 "logentries-token" "tag") + syslog_options=($common_options $common_options2 "syslog-address" "syslog-facility" "syslog-format" "syslog-tls-ca-cert" "syslog-tls-cert" "syslog-tls-key" "syslog-tls-skip-verify" "tag") + splunk_options=($common_options $common_options2 "splunk-caname" "splunk-capath" "splunk-format" "splunk-gzip" "splunk-gzip-level" "splunk-index" "splunk-insecureskipverify" "splunk-source" "splunk-sourcetype" "splunk-token" "splunk-url" "splunk-verify-connection" "tag") + + [[ $log_driver = (awslogs|all) ]] && _describe -t awslogs-options "awslogs options" awslogs_options "$@" && ret=0 + [[ $log_driver = (fluentd|all) ]] && _describe -t fluentd-options "fluentd options" fluentd_options "$@" && ret=0 + [[ $log_driver = (gcplogs|all) ]] && _describe -t gcplogs-options "gcplogs options" gcplogs_options "$@" && ret=0 + [[ $log_driver = (gelf|all) ]] && _describe -t gelf-options "gelf options" gelf_options "$@" && ret=0 + [[ $log_driver = (journald|all) ]] && _describe -t journald-options "journald options" journald_options "$@" && ret=0 + [[ $log_driver = (json-file|all) ]] && _describe -t json-file-options "json-file options" json_file_options "$@" && ret=0 + [[ $log_driver = (logentries|all) ]] && _describe -t logentries-options "logentries options" logentries_options "$@" && ret=0 + [[ $log_driver = (syslog|all) ]] && _describe -t syslog-options "syslog options" syslog_options "$@" && ret=0 + [[ $log_driver = (splunk|all) ]] && _describe -t splunk-options "splunk options" splunk_options "$@" && ret=0 + + return ret +} + +__docker_complete_log_drivers() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + drivers=(awslogs etwlogs fluentd gcplogs gelf journald json-file none splunk syslog) + _describe -t log-drivers "log drivers" drivers && ret=0 + return ret +} + +__docker_complete_log_options() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (syslog-format) + local opts=('rfc3164' 'rfc5424' 'rfc5424micro') + _describe -t syslog-format-opts "syslog format options" opts && ret=0 + ;; + (mode) + local opts=('blocking' 'non-blocking') + _describe -t mode-opts "mode options" opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + __docker_get_log_options -qS "=" && ret=0 + fi + + return ret +} + +__docker_complete_detach_keys() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + compset -P "*," + keys=(${:-{a-z}}) + ctrl_keys=(${:-ctrl-{{a-z},{@,'[','\\','^',']',_}}}) + _describe -t detach_keys "[a-z]" keys -qS "," && ret=0 + _describe -t detach_keys-ctrl "'ctrl-' + 'a-z @ [ \\\\ ] ^ _'" ctrl_keys -qS "," && ret=0 +} + +__docker_complete_pid() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local -a opts vopts + + opts=('host') + vopts=('container') + + if compset -P '*:'; then + case "${${words[-1]%:*}#*=}" in + (container) + __docker_complete_running_containers && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + _describe -t pid-value-opts "PID Options with value" vopts -qS ":" && ret=0 + _describe -t pid-opts "PID Options" opts && ret=0 + fi + + return ret +} + +__docker_complete_runtimes() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + emulate -L zsh + setopt extendedglob + local -a runtimes_opts + runtimes_opts=(${(ps: :)${(f)${${"$(_call_program commands docker $docker_options info)"##*$'\n'Runtimes: }%%$'\n'^ *}}}) + _describe -t runtimes-opts "runtimes options" runtimes_opts && ret=0 +} + +__docker_complete_ps_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (ancestor) + __docker_complete_images && ret=0 + ;; + (before|since) + __docker_complete_containers && ret=0 + ;; + (health) + health_opts=('healthy' 'none' 'starting' 'unhealthy') + _describe -t health-filter-opts "health filter options" health_opts && ret=0 + ;; + (id) + __docker_complete_containers_ids && ret=0 + ;; + (is-task) + _describe -t boolean-filter-opts "filter options" boolean_opts && ret=0 + ;; + (name) + __docker_complete_containers_names && ret=0 + ;; + (network) + __docker_complete_networks && ret=0 + ;; + (status) + status_opts=('created' 'dead' 'exited' 'paused' 'restarting' 'running' 'removing') + _describe -t status-filter-opts "status filter options" status_opts && ret=0 + ;; + (volume) + __docker_complete_volumes && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('ancestor' 'before' 'exited' 'expose' 'health' 'id' 'label' 'name' 'network' 'publish' 'since' 'status' 'volume') + _describe -t filter-opts "Filter Options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_complete_search_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + declare -a boolean_opts opts + + boolean_opts=('true' 'false') + opts=('is-automated' 'is-official' 'stars') + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (is-automated|is-official) + _describe -t boolean-filter-opts "filter options" boolean_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_complete_images_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + declare -a boolean_opts opts + + boolean_opts=('true' 'false') + opts=('before' 'dangling' 'label' 'reference' 'since') + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (before|reference|since) + __docker_complete_images && ret=0 + ;; + (dangling) + _describe -t boolean-filter-opts "filter options" boolean_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + _describe -t filter-opts "Filter Options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_complete_events_filter() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + declare -a opts + + opts=('container' 'daemon' 'event' 'image' 'label' 'network' 'scope' 'type' 'volume') + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (container) + __docker_complete_containers && ret=0 + ;; + (daemon) + emulate -L zsh + setopt extendedglob + local -a daemon_opts + daemon_opts=( + ${(f)${${"$(_call_program commands docker $docker_options info)"##*$'\n'Name: }%%$'\n'^ *}} + ${${(f)${${"$(_call_program commands docker $docker_options info)"##*$'\n'ID: }%%$'\n'^ *}}//:/\\:} + ) + _describe -t daemon-filter-opts "daemon filter options" daemon_opts && ret=0 + ;; + (event) + local -a event_opts + event_opts=('attach' 'commit' 'connect' 'copy' 'create' 'delete' 'destroy' 'detach' 'die' 'disable' 'disconnect' 'enable' 'exec_create' 'exec_detach' + 'exec_start' 'export' 'health_status' 'import' 'install' 'kill' 'load' 'mount' 'oom' 'pause' 'pull' 'push' 'reload' 'remove' 'rename' 'resize' + 'restart' 'save' 'start' 'stop' 'tag' 'top' 'unmount' 'unpause' 'untag' 'update') + _describe -t event-filter-opts "event filter options" event_opts && ret=0 + ;; + (image) + __docker_complete_images && ret=0 + ;; + (network) + __docker_complete_networks && ret=0 + ;; + (scope) + local -a scope_opts + scope_opts=('local' 'swarm') + _describe -t scope-filter-opts "scope filter options" scope_opts && ret=0 + ;; + (type) + local -a type_opts + type_opts=('container' 'daemon' 'image' 'network' 'volume') + _describe -t type-filter-opts "type filter options" type_opts && ret=0 + ;; + (volume) + __docker_complete_volumes && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_complete_prune_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + declare -a opts + + opts=('until') + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + *) + _message 'value' && ret=0 + ;; + esac + else + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +# BO checkpoint + +__docker_checkpoint_commands() { + local -a _docker_checkpoint_subcommands + _docker_checkpoint_subcommands=( + "create:Create a checkpoint from a running container" + "ls:List checkpoints for a container" + "rm:Remove a checkpoint" + ) + _describe -t docker-checkpoint-commands "docker checkpoint command" _docker_checkpoint_subcommands +} + +__docker_checkpoint_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (create) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--checkpoint-dir=[Use a custom checkpoint storage directory]:dir:_directories" \ + "($help)--leave-running[Leave the container running after checkpoint]" \ + "($help -)1:container:__docker_complete_running_containers" \ + "($help -)2:checkpoint: " && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--checkpoint-dir=[Use a custom checkpoint storage directory]:dir:_directories" \ + "($help -)1:container:__docker_complete_containers" && ret=0 + ;; + (rm|remove) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--checkpoint-dir=[Use a custom checkpoint storage directory]:dir:_directories" \ + "($help -)1:container:__docker_complete_containers" \ + "($help -)2:checkpoint: " && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_checkpoint_commands" && ret=0 + ;; + esac + + return ret +} + +# EO checkpoint + +# BO container + +__docker_container_commands() { + local -a _docker_container_subcommands + _docker_container_subcommands=( + "attach:Attach to a running container" + "commit:Create a new image from a container's changes" + "cp:Copy files/folders between a container and the local filesystem" + "create:Create a new container" + "diff:Inspect changes on a container's filesystem" + "exec:Execute a command in a running container" + "export:Export a container's filesystem as a tar archive" + "inspect:Display detailed information on one or more containers" + "kill:Kill one or more running containers" + "logs:Fetch the logs of a container" + "ls:List containers" + "pause:Pause all processes within one or more containers" + "port:List port mappings or a specific mapping for the container" + "prune:Remove all stopped containers" + "rename:Rename a container" + "restart:Restart one or more containers" + "rm:Remove one or more containers" + "run:Create and run a new container from an image" + "start:Start one or more stopped containers" + "stats:Display a live stream of container(s) resource usage statistics" + "stop:Stop one or more running containers" + "top:Display the running processes of a container" + "unpause:Unpause all processes within one or more containers" + "update:Update configuration of one or more containers" + "wait:Block until one or more containers stop, then print their exit codes" + ) + _describe -t docker-container-commands "docker container command" _docker_container_subcommands +} + +__docker_container_subcommand() { + local -a _command_args opts_help opts_attach_exec_run_start opts_create_run opts_create_run_update + local expl help="--help" + integer ret=1 + + opts_attach_exec_run_start=( + "($help)--detach-keys=[Escape key sequence used to detach a container]:sequence:__docker_complete_detach_keys" + ) + opts_create_run=( + "($help -a --attach)"{-a=,--attach=}"[Attach to stdin, stdout or stderr]:device:(STDIN STDOUT STDERR)" + "($help)*--add-host=[Add a custom host-to-IP mapping]:host\:ip mapping: " + "($help)*--annotation=[Add an annotation to the container (passed through to the OCI runtime)]:annotations: " + "($help)*--blkio-weight-device=[Block IO (relative device weight)]:device:Block IO weight: " + "($help)*--cap-add=[Add Linux capabilities]:capability: " + "($help)*--cap-drop=[Drop Linux capabilities]:capability: " + "($help)--cgroupns=[Cgroup namespace mode to use]:cgroup namespace mode: " + "($help)--cgroup-parent=[Parent cgroup for the container]:cgroup: " + "($help)--cidfile=[Write the container ID to the file]:CID file:_files" + "($help)--cpus=[Number of CPUs (default 0.000)]:cpus: " + "($help)*--device=[Add a host device to the container]:device:_files" + "($help)*--device-cgroup-rule=[Add a rule to the cgroup allowed devices list]:device:cgroup: " + "($help)*--device-read-bps=[Limit the read rate (bytes per second) from a device]:device:IO rate: " + "($help)*--device-read-iops=[Limit the read rate (IO per second) from a device]:device:IO rate: " + "($help)*--device-write-bps=[Limit the write rate (bytes per second) to a device]:device:IO rate: " + "($help)*--device-write-iops=[Limit the write rate (IO per second) to a device]:device:IO rate: " + "($help)--disable-content-trust[Skip image verification]" + "($help)*--dns=[Custom DNS servers]:DNS server: " + "($help)*--dns-option=[Custom DNS options]:DNS option: " + "($help)*--dns-search=[Custom DNS search domains]:DNS domains: " + "($help)*--domainname=[Container NIS domain name]:domainname:_hosts" + "($help)*"{-e=,--env=}"[Environment variables]:environment variable: " + "($help)--entrypoint=[Overwrite the default entrypoint of the image]:entry point: " + "($help)*--env-file=[Read environment variables from a file]:environment file:_files" + "($help)*--expose=[Expose a port from the container without publishing it]: " + "($help)*--gpus=[GPU devices to add to the container ('all' to pass all GPUs)]:device: " + "($help)*--group-add=[Set one or more supplementary user groups for the container]:group:_groups" + "($help -h --hostname)"{-h=,--hostname=}"[Container host name]:hostname:_hosts" + "($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]" + "($help)--init[Run an init inside the container that forwards signals and reaps processes]" + "($help)--ip=[IPv4 address]:IPv4: " + "($help)--ip6=[IPv6 address]:IPv6: " + "($help)--ipc=[IPC namespace to use]:IPC namespace: " + "($help)--isolation=[Container isolation technology]:isolation:(default hyperv process)" + "($help)*--link=[Add link to another container]:link:->link" + "($help)*--link-local-ip=[Container IPv4/IPv6 link-local addresses]:IPv4/IPv6: " + "($help)*"{-l=,--label=}"[Container metadata]:label: " + "($help)--log-driver=[Default driver for container logs]:logging driver:__docker_complete_log_drivers" + "($help)*--log-opt=[Log driver specific options]:log driver options:__docker_complete_log_options" + "($help)--mac-address=[Container MAC address]:MAC address: " + "($help)*--mount=[Attach a filesystem mount to the container]:mount: " + "($help)--name=[Container name]:name: " + "($help)--network=[Connect a container to a network]:network mode:(bridge none container host)" + "($help)*--network-alias=[Add network-scoped alias for the container]:alias: " + "($help)--oom-kill-disable[Disable OOM Killer]" + "($help)--oom-score-adj[Tune the host's OOM preferences for containers (accepts -1000 to 1000)]" + "($help)--pids-limit[Tune container pids limit (set -1 for unlimited)]" + "($help -P --publish-all)"{-P,--publish-all}"[Publish all exposed ports]" + "($help)*"{-p=,--publish=}"[Expose a container's port to the host]:port:_ports" + "($help)--pid=[PID namespace to use]:PID namespace:__docker_complete_pid" + "($help)--privileged[Give extended privileges to this container]" + "($help -q --quiet)"{-q,--quiet}"[Suppress the pull output]" + "($help)--read-only[Mount the container's root filesystem as read only]" + "($help)*--security-opt=[Security options]:security option: " + "($help)*--shm-size=[Size of '/dev/shm' (format is '')]:shm size: " + "($help)--stop-signal=[Signal to kill a container]:signal:_signals" + "($help)--stop-timeout=[Timeout (in seconds) to stop a container]:time: " + "($help)*--sysctl=-[sysctl options]:sysctl: " + "($help -t --tty)"{-t,--tty}"[Allocate a pseudo-tty]" + "($help -u --user)"{-u=,--user=}"[Username or UID]:user:_users" + "($help)*--ulimit=[ulimit options]:ulimit: " + "($help)--userns=[Container user namespace]:user namespace:(host)" + "($help)--tmpfs[mount tmpfs]" + "($help)*-v[Bind mount a volume]:volume:_directories -W / -P '/' -S '\:' -r '/ '" + "($help)--volume-driver=[Optional volume driver for the container]:volume driver:(local)" + "($help)*--volumes-from=[Mount volumes from the specified container]:volume: " + "($help -w --workdir)"{-w=,--workdir=}"[Working directory inside the container]:directory:_directories" + ) + opts_create_run_update=( + "($help)--blkio-weight=[Block IO (relative weight), between 10 and 1000]:Block IO weight:(10 100 500 1000)" + "($help -c --cpu-shares)"{-c=,--cpu-shares=}"[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)" + "($help)--cpu-period=[Limit the CPU CFS (Completely Fair Scheduler) period]:CPU period: " + "($help)--cpu-quota=[Limit the CPU CFS (Completely Fair Scheduler) quota]:CPU quota: " + "($help)--cpu-rt-period=[Limit the CPU real-time period]:CPU real-time period in microseconds: " + "($help)--cpu-rt-runtime=[Limit the CPU real-time runtime]:CPU real-time runtime in microseconds: " + "($help)--cpuset-cpus=[CPUs in which to allow execution]:CPUs: " + "($help)--cpuset-mems=[MEMs in which to allow execution]:MEMs: " + "($help)--kernel-memory=[Kernel memory limit in bytes]:Memory limit: " + "($help -m --memory)"{-m=,--memory=}"[Memory limit]:Memory limit: " + "($help)--memory-reservation=[Memory soft limit]:Memory limit: " + "($help)--memory-swap=[Total memory limit with swap]:Memory limit: " + "($help)--pids-limit[Tune container pids limit (set -1 for unlimited)]" + "($help)--restart=[Restart policy]:restart policy:(no on-failure always unless-stopped)" + ) + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (attach) + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_attach_exec_run_start \ + "($help)--no-stdin[Do not attach stdin]" \ + "($help)--sig-proxy[Proxy all received signals to the process (non-TTY mode only)]" \ + "($help -):containers:__docker_complete_running_containers" && ret=0 + ;; + (commit) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --author)"{-a=,--author=}"[Author]:author: " \ + "($help)*"{-c=,--change=}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \ + "($help -m --message)"{-m=,--message=}"[Commit message]:message: " \ + "($help -p --pause)"{-p,--pause}"[Pause container during commit]" \ + "($help -):container:__docker_complete_containers" \ + "($help -): :__docker_complete_repositories_with_tags" && ret=0 + ;; + (cp) + local state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -L --follow-link)"{-L,--follow-link}"[Always follow symbol link]" \ + "($help -)1:container:->container" \ + "($help -)2:hostpath:_files" && ret=0 + case $state in + (container) + if compset -P "*:"; then + _files && ret=0 + else + __docker_complete_containers -qS ":" && ret=0 + fi + ;; + esac + ;; + (create) + local state + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_create_run \ + $opts_create_run_update \ + "($help -): :__docker_complete_images" \ + "($help -):command: _command_names -e" \ + "($help -)*::arguments: _normal" && ret=0 + case $state in + (link) + if compset -P "*:"; then + _wanted alias expl "Alias" compadd -E "" && ret=0 + else + __docker_complete_running_containers -qS ":" && ret=0 + fi + ;; + esac + ;; + (diff) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:containers:__docker_complete_containers" && ret=0 + ;; + (exec) + local state + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_attach_exec_run_start \ + "($help -d --detach)"{-d,--detach}"[Detached mode: leave the container running in the background]" \ + "($help)*"{-e=,--env=}"[Set environment variables]:environment variable: " \ + "($help)*--env-file=[Read environment variables from a file]:environment file:_files" \ + "($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]" \ + "($help)--privileged[Give extended Linux capabilities to the command]" \ + "($help -t --tty)"{-t,--tty}"[Allocate a pseudo-tty]" \ + "($help -u --user)"{-u=,--user=}"[Username or UID]:user:_users" \ + "($help -w --workdir)"{-w=,--workdir=}"[Working directory inside the container]:directory:_directories" \ + "($help -):containers:__docker_complete_running_containers" \ + "($help -)*::command:->anycommand" && ret=0 + case $state in + (anycommand) + shift 1 words + (( CURRENT-- )) + _normal && ret=0 + ;; + esac + ;; + (export) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -o --output)"{-o=,--output=}"[Write to a file, instead of stdout]:output file:_files" \ + "($help -)*:containers:__docker_complete_containers" && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " \ + "($help -s --size)"{-s,--size}"[Display total file sizes]" \ + "($help -)*:containers:__docker_complete_containers" && ret=0 + ;; + (kill) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -s --signal)"{-s=,--signal=}"[Signal to send]:signal:_signals" \ + "($help -)*:containers:__docker_complete_running_containers" && ret=0 + ;; + (logs) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--details[Show extra details provided to logs]" \ + "($help -f --follow)"{-f,--follow}"[Follow log output]" \ + "($help -s --since)"{-s=,--since=}"[Show logs since this timestamp]:timestamp: " \ + "($help -t --timestamps)"{-t,--timestamps}"[Show timestamps]" \ + "($help -n --tail)"{-n=,--tail=}"[Number of lines to show from the end of the logs]:lines:(1 10 20 50 all)" \ + "($help -)*:containers:__docker_complete_containers" && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Show all containers]" \ + "($help)--before=[Show only container created before...]:containers:__docker_complete_containers" \ + "($help)*"{-f=,--filter=}"[Filter values]:filter:__docker_complete_ps_filters" \ + "($help)--format=[Format the output using the given Go template]:template: " \ + "($help -l --latest)"{-l,--latest}"[Show only the latest created container]" \ + "($help -n --last)"{-n=,--last=}"[Show n last created containers (includes all states)]:n:(1 5 10 25 50)" \ + "($help)--no-trunc[Do not truncate output]" \ + "($help -q --quiet)"{-q,--quiet}"[Only show container IDs]" \ + "($help -s --size)"{-s,--size}"[Display total file sizes]" \ + "($help)--since=[Show only containers created since...]:containers:__docker_complete_containers" && ret=0 + ;; + (pause|unpause) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:containers:__docker_complete_running_containers" && ret=0 + ;; + (port) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)1:containers:__docker_complete_running_containers" \ + "($help -)2:port:_ports" && ret=0 + ;; + (prune) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*--filter=[Filter values]:filter:__docker_complete_prune_filters" \ + "($help -f --force)"{-f,--force}"[Do not prompt for confirmation]" && ret=0 + ;; + (rename) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -):old name:__docker_complete_containers" \ + "($help -):new name: " && ret=0 + ;; + (restart) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -t --time)"{-t=,--time=}"[Number of seconds to try to stop for before killing the container]:seconds to before killing:(1 5 10 30 60)" \ + "($help -)*:containers:__docker_complete_containers" && ret=0 + ;; + (rm) + local state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --force)"{-f,--force}"[Force removal]" \ + "($help -l --link)"{-l,--link}"[Remove the specified link and not the underlying container]" \ + "($help -v --volumes)"{-v,--volumes}"[Remove the volumes associated to the container]" \ + "($help -)*:containers:->values" && ret=0 + case $state in + (values) + if [[ ${words[(r)-f]} == -f || ${words[(r)--force]} == --force ]]; then + __docker_complete_containers && ret=0 + else + __docker_complete_stopped_containers && ret=0 + fi + ;; + esac + ;; + (run) + local state + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_create_run \ + $opts_create_run_update \ + $opts_attach_exec_run_start \ + "($help -d --detach)"{-d,--detach}"[Detached mode: leave the container running in the background]" \ + "($help)--health-cmd=[Command to run to check health]:command: " \ + "($help)--health-interval=[Time between running the check]:time: " \ + "($help)--health-retries=[Consecutive failures needed to report unhealthy]:retries:(1 2 3 4 5)" \ + "($help)--health-timeout=[Maximum time to allow one check to run]:time: " \ + "($help)--no-healthcheck[Disable any container-specified HEALTHCHECK]" \ + "($help)--rm[Remove intermediate containers when it exits]" \ + "($help)--runtime=[Name of the runtime to be used for that container]:runtime:__docker_complete_runtimes" \ + "($help)--sig-proxy[Proxy all received signals to the process (non-TTY mode only)]" \ + "($help)--storage-opt=[Storage driver options for the container]:storage options:->storage-opt" \ + "($help -): :__docker_complete_images" \ + "($help -):command: _command_names -e" \ + "($help -)*::arguments: _normal" && ret=0 + case $state in + (link) + if compset -P "*:"; then + _wanted alias expl "Alias" compadd -E "" && ret=0 + else + __docker_complete_running_containers -qS ":" && ret=0 + fi + ;; + (storage-opt) + if compset -P "*="; then + _message "value" && ret=0 + else + opts=('size') + _describe -t filter-opts "storage options" opts -qS "=" && ret=0 + fi + ;; + esac + ;; + (start) + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_attach_exec_run_start \ + "($help -a --attach)"{-a,--attach}"[Attach container's stdout/stderr and forward all signals]" \ + "($help -i --interactive)"{-i,--interactive}"[Attach container's stdin]" \ + "($help -)*:containers:__docker_complete_stopped_containers" && ret=0 + ;; + (stats) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Show all containers (default shows just running)]" \ + "($help)--format=[Format the output using the given Go template]:template: " \ + "($help)--no-stream[Disable streaming stats and only pull the first result]" \ + "($help)--no-trunc[Do not truncate output]" \ + "($help -)*:containers:__docker_complete_running_containers" && ret=0 + ;; + (stop) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -t --time)"{-t=,--time=}"[Number of seconds to try to stop for before killing the container]:seconds to before killing:(1 5 10 30 60)" \ + "($help -)*:containers:__docker_complete_running_containers" && ret=0 + ;; + (top) + local state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)1:containers:__docker_complete_running_containers" \ + "($help -)*:: :->ps-arguments" && ret=0 + case $state in + (ps-arguments) + _ps && ret=0 + ;; + esac + ;; + (update) + local state + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_create_run_update \ + "($help -)*: :->values" && ret=0 + case $state in + (values) + if [[ ${words[(r)--kernel-memory*]} = (--kernel-memory*) ]]; then + __docker_complete_stopped_containers && ret=0 + else + __docker_complete_containers && ret=0 + fi + ;; + esac + ;; + (wait) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:containers:__docker_complete_running_containers" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_container_commands" && ret=0 + ;; + esac + + return ret +} + +# EO container + +# BO image + +__docker_image_commands() { + local -a _docker_image_subcommands + _docker_image_subcommands=( + "build:Build an image from a Dockerfile" + "history:Show the history of an image" + "import:Import the contents from a tarball to create a filesystem image" + "inspect:Display detailed information on one or more images" + "load:Load an image from a tar archive or STDIN" + "ls:List images" + "prune:Remove unused images" + "pull:Download an image from a registry" + "push:Upload an image to a registry" + "rm:Remove one or more images" + "save:Save one or more images to a tar archive (streamed to STDOUT by default)" + "tag:Tag an image into a repository" + ) + _describe -t docker-image-commands "docker image command" _docker_image_subcommands +} + +__docker_image_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (build) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*--add-host=[Add a custom host-to-IP mapping]:host\:ip mapping: " \ + "($help)*--build-arg=[Build-time variables]:=: " \ + "($help)*--cache-from=[Images to consider as cache sources]: :__docker_complete_repositories_with_tags" \ + "($help -c --cpu-shares)"{-c=,--cpu-shares=}"[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)" \ + "($help)--cgroup-parent=[Parent cgroup for the container]:cgroup: " \ + "($help)--compress[Compress the build context using gzip]" \ + "($help)--cpu-period=[Limit the CPU CFS (Completely Fair Scheduler) period]:CPU period: " \ + "($help)--cpu-quota=[Limit the CPU CFS (Completely Fair Scheduler) quota]:CPU quota: " \ + "($help)--cpu-rt-period=[Limit the CPU real-time period]:CPU real-time period in microseconds: " \ + "($help)--cpu-rt-runtime=[Limit the CPU real-time runtime]:CPU real-time runtime in microseconds: " \ + "($help)--cpuset-cpus=[CPUs in which to allow execution]:CPUs: " \ + "($help)--cpuset-mems=[MEMs in which to allow execution]:MEMs: " \ + "($help)--disable-content-trust[Skip image verification]" \ + "($help -f --file)"{-f=,--file=}"[Name of the Dockerfile]:Dockerfile:_files" \ + "($help)--force-rm[Always remove intermediate containers]" \ + "($help)--isolation=[Container isolation technology]:isolation:(default hyperv process)" \ + "($help)*--label=[Set metadata for an image]:label=value: " \ + "($help -m --memory)"{-m=,--memory=}"[Memory limit]:Memory limit: " \ + "($help)--memory-swap=[Total memory limit with swap]:Memory limit: " \ + "($help)--network=[Connect a container to a network]:network mode:(bridge none container host)" \ + "($help)--no-cache[Do not use cache when building the image]" \ + "($help)--pull[Attempt to pull a newer version of the image]" \ + "($help -q --quiet)"{-q,--quiet}"[Suppress verbose build output]" \ + "($help)--rm[Remove intermediate containers after a successful build]" \ + "($help)*--shm-size=[Size of '/dev/shm' (format is '')]:shm size: " \ + "($help)--squash[Squash newly built layers into a single new layer]" \ + "($help -t --tag)*"{-t=,--tag=}"[Repository, name and tag for the image]: :__docker_complete_repositories_with_tags" \ + "($help)--target=[Set the target build stage to build.]" \ + "($help)*--ulimit=[ulimit options]:ulimit: " \ + "($help)--userns=[Container user namespace]:user namespace:(host)" \ + "($help -):path or URL:_directories" && ret=0 + ;; + (history) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -H --human)"{-H,--human}"[Print sizes and dates in human readable format]" \ + "($help)--no-trunc[Do not truncate output]" \ + "($help -q --quiet)"{-q,--quiet}"[Only show image IDs]" \ + "($help -)*: :__docker_complete_images" && ret=0 + ;; + (import) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-c=,--change=}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \ + "($help -m --message)"{-m=,--message=}"[Commit message for imported image]:message: " \ + "($help -):URL:(- http:// file://)" \ + "($help -): :__docker_complete_repositories_with_tags" && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " \ + "($help -)*:images:__docker_complete_images" && ret=0 + ;; + (load) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -i --input)"{-i=,--input=}"[Read from tar archive file]:archive file:_files -g \"*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|)|(tbz|tgz|txz))(-.)\"" \ + "($help -q --quiet)"{-q,--quiet}"[Suppress the load output]" && ret=0 + ;; + (ls|list) + local state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Show all images]" \ + "($help)--digests[Show digests]" \ + "($help)*"{-f=,--filter=}"[Filter values]:filter:__docker_complete_images_filters" \ + "($help)--format=[Format the output using the given Go template]:template: " \ + "($help)--no-trunc[Do not truncate output]" \ + "($help -q --quiet)"{-q,--quiet}"[Only show image IDs]" \ + "($help -): :__docker_complete_repositories" && ret=0 + ;; + (prune) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Remove all unused images, not just dangling ones]" \ + "($help)*--filter=[Filter values]:filter:__docker_complete_prune_filters" \ + "($help -f --force)"{-f,--force}"[Do not prompt for confirmation]" && ret=0 + ;; + (pull) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all-tags)"{-a,--all-tags}"[Download all tagged images]" \ + "($help)--disable-content-trust[Skip image verification]" \ + "($help -):name:__docker_search" && ret=0 + ;; + (push) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all-tags)"{-a,--all-tags}"[Push all tags of an image to the repository]" \ + "($help)--disable-content-trust[Skip image signing]" \ + "($help -): :__docker_complete_images" && ret=0 + ;; + (rm) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --force)"{-f,--force}"[Force removal]" \ + "($help)--no-prune[Do not delete untagged parents]" \ + "($help -)*: :__docker_complete_images" && ret=0 + ;; + (save) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -o --output)"{-o=,--output=}"[Write to file]:file:_files" \ + "($help -)*: :__docker_complete_images" && ret=0 + ;; + (tag) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -):source:__docker_complete_images"\ + "($help -):destination:__docker_complete_repositories_with_tags" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_container_commands" && ret=0 + ;; + esac + + return ret +} + +# EO image + +# BO network + +__docker_network_complete_ls_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (driver) + __docker_complete_info_plugins Network && ret=0 + ;; + (id) + __docker_complete_networks_ids && ret=0 + ;; + (name) + __docker_complete_networks_names && ret=0 + ;; + (scope) + opts=('global' 'local' 'swarm') + _describe -t scope-filter-opts "Scope filter options" opts && ret=0 + ;; + (type) + opts=('builtin' 'custom') + _describe -t type-filter-opts "Type filter options" opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('driver' 'id' 'label' 'name' 'scope' 'type') + _describe -t filter-opts "Filter Options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_get_networks() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines networks + + type=$1; shift + + lines=(${(f)${:-"$(_call_program commands docker $docker_options network ls)"$'\n'}}) + + # Parse header line to find columns + local i=1 j=1 k header=${lines[1]} + declare -A begin end + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done + end[${header[$i,$((j-1))]}]=-1 + lines=(${lines[2,-1]}) + + # Network ID + if [[ $type = (ids|all) ]]; then + for line in $lines; do + s="${line[${begin[NETWORK ID]},${end[NETWORK ID]}]%% ##}" + s="$s:${(l:7:: :::)${${line[${begin[DRIVER]},${end[DRIVER]}]}%% ##}}" + s="$s, ${${line[${begin[SCOPE]},${end[SCOPE]}]}%% ##}" + networks=($networks $s) + done + fi + + # Names + if [[ $type = (names|all) ]]; then + for line in $lines; do + s="${line[${begin[NAME]},${end[NAME]}]%% ##}" + s="$s:${(l:7:: :::)${${line[${begin[DRIVER]},${end[DRIVER]}]}%% ##}}" + s="$s, ${${line[${begin[SCOPE]},${end[SCOPE]}]}%% ##}" + networks=($networks $s) + done + fi + + _describe -t networks-list "networks" networks "$@" && ret=0 + return ret +} + +__docker_complete_networks() { + [[ $PREFIX = -* ]] && return 1 + __docker_get_networks all "$@" +} + +__docker_complete_networks_ids() { + [[ $PREFIX = -* ]] && return 1 + __docker_get_networks ids "$@" +} + +__docker_complete_networks_names() { + [[ $PREFIX = -* ]] && return 1 + __docker_get_networks names "$@" +} + +__docker_network_commands() { + local -a _docker_network_subcommands + _docker_network_subcommands=( + "connect:Connect a container to a network" + "create:Creates a new network with a name specified by the user" + "disconnect:Disconnects a container from a network" + "inspect:Displays detailed information on a network" + "ls:Lists all the networks created by the user" + "prune:Remove all unused networks" + "rm:Deletes one or more networks" + ) + _describe -t docker-network-commands "docker network command" _docker_network_subcommands +} + +__docker_network_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (connect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*--alias=[Add network-scoped alias for the container]:alias: " \ + "($help)--ip=[IPv4 address]:IPv4: " \ + "($help)--ip6=[IPv6 address]:IPv6: " \ + "($help)*--link=[Add a link to another container]:link:->link" \ + "($help)*--link-local-ip=[Add a link-local address for the container]:IPv4/IPv6: " \ + "($help -)1:network:__docker_complete_networks" \ + "($help -)2:containers:__docker_complete_containers" && ret=0 + + case $state in + (link) + if compset -P "*:"; then + _wanted alias expl "Alias" compadd -E "" && ret=0 + else + __docker_complete_running_containers -qS ":" && ret=0 + fi + ;; + esac + ;; + (create) + _arguments $(__docker_arguments) -A '-*' \ + $opts_help \ + "($help)--attachable[Enable manual container attachment]" \ + "($help)*--aux-address[Auxiliary IPv4 or IPv6 addresses used by network driver]:key=IP: " \ + "($help -d --driver)"{-d=,--driver=}"[Driver to manage the Network]:driver:(null host bridge overlay)" \ + "($help)*--gateway=[IPv4 or IPv6 Gateway for the master subnet]:IP: " \ + "($help)--internal[Restricts external access to the network]" \ + "($help)*--ip-range=[Allocate container ip from a sub-range]:IP/mask: " \ + "($help)--ipam-driver=[IP Address Management Driver]:driver:(default)" \ + "($help)*--ipam-opt=[Custom IPAM plugin options]:opt=value: " \ + "($help)--ipv6[Enable IPv6 networking]" \ + "($help)*--label=[Set metadata on a network]:label=value: " \ + "($help)*"{-o=,--opt=}"[Driver specific options]:opt=value: " \ + "($help)*--subnet=[Subnet in CIDR format that represents a network segment]:IP/mask: " \ + "($help -)1:Network Name: " && ret=0 + ;; + (disconnect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)1:network:__docker_complete_networks" \ + "($help -)2:containers:__docker_complete_containers" && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " \ + "($help)--verbose[Show detailed information]" \ + "($help -)*:network:__docker_complete_networks" && ret=0 + ;; + (ls) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--no-trunc[Do not truncate the output]" \ + "($help)*"{-f=,--filter=}"[Provide filter values]:filter:__docker_network_complete_ls_filters" \ + "($help)--format=[Format the output using the given Go template]:template: " \ + "($help -q --quiet)"{-q,--quiet}"[Only display network IDs]" && ret=0 + ;; + (prune) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*--filter=[Filter values]:filter:__docker_complete_prune_filters" \ + "($help -f --force)"{-f,--force}"[Do not prompt for confirmation]" && ret=0 + ;; + (rm) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:network:__docker_complete_networks" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_network_commands" && ret=0 + ;; + esac + + return ret +} + +# EO network + +# BO node + +__docker_node_complete_ls_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (id) + __docker_complete_nodes_ids && ret=0 + ;; + (membership) + membership_opts=('accepted' 'pending' 'rejected') + _describe -t membership-opts "membership options" membership_opts && ret=0 + ;; + (name) + __docker_complete_nodes_names && ret=0 + ;; + (role) + role_opts=('manager' 'worker') + _describe -t role-opts "role options" role_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('id' 'label' 'membership' 'name' 'node.label' 'role') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_node_complete_ps_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (desired-state) + state_opts=('accepted' 'running' 'shutdown') + _describe -t state-opts "desired state options" state_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('desired-state' 'id' 'label' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_nodes() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines nodes args + + type=$1; shift + filter=$1; shift + [[ $filter != "none" ]] && args=("-f $filter") + + lines=(${(f)${:-"$(_call_program commands docker $docker_options node ls $args)"$'\n'}}) + # Parse header line to find columns + local i=1 j=1 k header=${lines[1]} + declare -A begin end + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done + end[${header[$i,$((j-1))]}]=-1 + lines=(${lines[2,-1]}) + + # Node ID + if [[ $type = (ids|all) ]]; then + for line in $lines; do + s="${line[${begin[ID]},${end[ID]}]%% ##}" + nodes=($nodes $s) + done + fi + + # Names + if [[ $type = (names|all) ]]; then + for line in $lines; do + s="${line[${begin[HOSTNAME]},${end[HOSTNAME]}]%% ##}" + nodes=($nodes $s) + done + fi + + _describe -t nodes-list "nodes" nodes "$@" && ret=0 + return ret +} + +__docker_complete_nodes() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes all none "$@" +} + +__docker_complete_nodes_ids() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes ids none "$@" +} + +__docker_complete_nodes_names() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes names none "$@" +} + +__docker_complete_pending_nodes() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes all "membership=pending" "$@" +} + +__docker_complete_manager_nodes() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes all "role=manager" "$@" +} + +__docker_complete_worker_nodes() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes all "role=worker" "$@" +} + +__docker_node_commands() { + local -a _docker_node_subcommands + _docker_node_subcommands=( + "demote:Demote a node as manager in the swarm" + "inspect:Display detailed information on one or more nodes" + "ls:List nodes in the swarm" + "promote:Promote a node as manager in the swarm" + "rm:Remove one or more nodes from the swarm" + "ps:List tasks running on one or more nodes, defaults to current node" + "update:Update a node" + ) + _describe -t docker-node-commands "docker node command" _docker_node_subcommands +} + +__docker_node_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (rm|remove) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --force)"{-f,--force}"[Force remove a node from the swarm]" \ + "($help -)*:node:__docker_complete_pending_nodes" && ret=0 + ;; + (demote) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:node:__docker_complete_manager_nodes" && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " \ + "($help)--pretty[Print the information in a human friendly format]" \ + "($help -)*:node:__docker_complete_nodes" && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Provide filter values]:filter:__docker_node_complete_ls_filters" \ + "($help -q --quiet)"{-q,--quiet}"[Only display IDs]" && ret=0 + ;; + (promote) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:node:__docker_complete_worker_nodes" && ret=0 + ;; + (ps) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Display all instances]" \ + "($help)*"{-f=,--filter=}"[Provide filter values]:filter:__docker_node_complete_ps_filters" \ + "($help)--format=[Format the output using the given go template]:template: " \ + "($help)--no-resolve[Do not map IDs to Names]" \ + "($help)--no-trunc[Do not truncate output]" \ + "($help -q --quiet)"{-q,--quiet}"[Only display IDs]" \ + "($help -)*:node:__docker_complete_nodes" && ret=0 + ;; + (update) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--availability=[Availability of the node]:availability:(active pause drain)" \ + "($help)*--label-add=[Add or update a node label]:key=value: " \ + "($help)*--label-rm=[Remove a node label if exists]:label: " \ + "($help)--role=[Role of the node]:role:(manager worker)" \ + "($help -)1:node:__docker_complete_nodes" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_node_commands" && ret=0 + ;; + esac + + return ret +} + +# EO node + +# BO plugin + +__docker_plugin_complete_ls_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (capability) + opts=('authz' 'ipamdriver' 'logdriver' 'metricscollector' 'networkdriver' 'volumedriver') + _describe -t capability-opts "capability options" opts && ret=0 + ;; + (enabled) + opts=('false' 'true') + _describe -t enabled-opts "enabled options" opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('capability' 'enabled') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_plugins() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines plugins args + + filter=$1; shift + [[ $filter != "none" ]] && args=("-f $filter") + + lines=(${(f)${:-"$(_call_program commands docker $docker_options plugin ls $args)"$'\n'}}) + + # Parse header line to find columns + local i=1 j=1 k header=${lines[1]} + declare -A begin end + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done + end[${header[$i,$((j-1))]}]=-1 + lines=(${lines[2,-1]}) + + # Name + for line in $lines; do + s="${line[${begin[NAME]},${end[NAME]}]%% ##}" + s="$s:${(l:7:: :::)${${line[${begin[TAG]},${end[TAG]}]}%% ##}}" + plugins=($plugins $s) + done + + _describe -t plugins-list "plugins" plugins "$@" && ret=0 + return ret +} + +__docker_complete_plugins() { + [[ $PREFIX = -* ]] && return 1 + __docker_plugins none "$@" +} + +__docker_complete_enabled_plugins() { + [[ $PREFIX = -* ]] && return 1 + __docker_plugins enabled=true "$@" +} + +__docker_complete_disabled_plugins() { + [[ $PREFIX = -* ]] && return 1 + __docker_plugins enabled=false "$@" +} + +__docker_plugin_commands() { + local -a _docker_plugin_subcommands + _docker_plugin_subcommands=( + "disable:Disable a plugin" + "enable:Enable a plugin" + "inspect:Return low-level information about a plugin" + "install:Install a plugin" + "ls:List plugins" + "push:Push a plugin" + "rm:Remove a plugin" + "set:Change settings for a plugin" + "upgrade:Upgrade an existing plugin" + ) + _describe -t docker-plugin-commands "docker plugin command" _docker_plugin_subcommands +} + +__docker_plugin_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (disable) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --force)"{-f,--force}"[Force the disable of an active plugin]" \ + "($help -)1:plugin:__docker_complete_enabled_plugins" && ret=0 + ;; + (enable) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--timeout=[HTTP client timeout (in seconds)]:timeout: " \ + "($help -)1:plugin:__docker_complete_disabled_plugins" && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given Go template]:template: " \ + "($help -)*:plugin:__docker_complete_plugins" && ret=0 + ;; + (install) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--alias=[Local name for plugin]:alias: " \ + "($help)--disable[Do not enable the plugin on install]" \ + "($help)--disable-content-trust[Skip image verification (default true)]" \ + "($help)--grant-all-permissions[Grant all permissions necessary to run the plugin]" \ + "($help -)1:plugin:__docker_complete_plugins" \ + "($help -)*:key=value: " && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Filter output based on conditions provided]:filter:__docker_plugin_complete_ls_filters" \ + "($help --format)--format=[Format the output using the given Go template]:template: " \ + "($help)--no-trunc[Don't truncate output]" \ + "($help -q --quiet)"{-q,--quiet}"[Only display IDs]" && ret=0 + ;; + (push) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--disable-content-trust[Skip image verification (default true)]" \ + "($help -)1:plugin:__docker_complete_plugins" && ret=0 + ;; + (rm|remove) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --force)"{-f,--force}"[Force the removal of an active plugin]" \ + "($help -)*:plugin:__docker_complete_plugins" && ret=0 + ;; + (set) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)1:plugin:__docker_complete_plugins" \ + "($help -)*:key=value: " && ret=0 + ;; + (upgrade) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--disable-content-trust[Skip image verification (default true)]" \ + "($help)--grant-all-permissions[Grant all permissions necessary to run the plugin]" \ + "($help)--skip-remote-check[Do not check if specified remote plugin matches existing plugin image]" \ + "($help -)1:plugin:__docker_complete_plugins" \ + "($help -):remote: " && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_plugin_commands" && ret=0 + ;; + esac + + return ret +} + +# EO plugin + +# BO secret + +__docker_secrets() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines secrets + + type=$1; shift + + lines=(${(f)${:-"$(_call_program commands docker $docker_options secret ls)"$'\n'}}) + + # Parse header line to find columns + local i=1 j=1 k header=${lines[1]} + declare -A begin end + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done + end[${header[$i,$((j-1))]}]=-1 + lines=(${lines[2,-1]}) + + # ID + if [[ $type = (ids|all) ]]; then + for line in $lines; do + s="${line[${begin[ID]},${end[ID]}]%% ##}" + secrets=($secrets $s) + done + fi + + # Names + if [[ $type = (names|all) ]]; then + for line in $lines; do + s="${line[${begin[NAME]},${end[NAME]}]%% ##}" + secrets=($secrets $s) + done + fi + + _describe -t secrets-list "secrets" secrets "$@" && ret=0 + return ret +} + +__docker_complete_secrets() { + [[ $PREFIX = -* ]] && return 1 + __docker_secrets all "$@" +} + +__docker_secret_commands() { + local -a _docker_secret_subcommands + _docker_secret_subcommands=( + "create:Create a secret using stdin as content" + "inspect:Display detailed information on one or more secrets" + "ls:List secrets" + "rm:Remove one or more secrets" + ) + _describe -t docker-secret-commands "docker secret command" _docker_secret_subcommands +} + +__docker_secret_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (create) + _arguments $(__docker_arguments) -A '-*' \ + $opts_help \ + "($help)*"{-l=,--label=}"[Secret labels]:label: " \ + "($help -):secret: " && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given Go template]:template: " \ + "($help -)*:secret:__docker_complete_secrets" && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--format=[Format the output using the given go template]:template: " \ + "($help -q --quiet)"{-q,--quiet}"[Only display IDs]" && ret=0 + ;; + (rm|remove) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:secret:__docker_complete_secrets" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_secret_commands" && ret=0 + ;; + esac + + return ret +} + +# EO secret + +# BO service + +__docker_service_complete_ls_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (id) + __docker_complete_services_ids && ret=0 + ;; + (mode) + opts=('global' 'replicated') + _describe -t mode-opts "mode options" opts && ret=0 + ;; + (name) + __docker_complete_services_names && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('id' 'label' 'mode' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_service_complete_ps_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (desired-state) + state_opts=('accepted' 'running' 'shutdown') + _describe -t state-opts "desired state options" state_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('desired-state' 'id' 'label' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_service_complete_placement_pref() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (spread) + opts=('engine.labels' 'node.labels') + _describe -t spread-opts "spread options" opts -qS "." && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('spread') + _describe -t pref-opts "placement pref options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_services() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines services + + type=$1; shift + + lines=(${(f)${:-"$(_call_program commands docker $docker_options service ls)"$'\n'}}) + + # Parse header line to find columns + local i=1 j=1 k header=${lines[1]} + declare -A begin end + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done + end[${header[$i,$((j-1))]}]=-1 + lines=(${lines[2,-1]}) + + # Service ID + if [[ $type = (ids|all) ]]; then + for line in $lines; do + s="${line[${begin[ID]},${end[ID]}]%% ##}" + s="$s:${(l:7:: :::)${${line[${begin[IMAGE]},${end[IMAGE]}]}%% ##}}" + services=($services $s) + done + fi + + # Names + if [[ $type = (names|all) ]]; then + for line in $lines; do + s="${line[${begin[NAME]},${end[NAME]}]%% ##}" + s="$s:${(l:7:: :::)${${line[${begin[IMAGE]},${end[IMAGE]}]}%% ##}}" + services=($services $s) + done + fi + + _describe -t services-list "services" services "$@" && ret=0 + return ret +} + +__docker_complete_services() { + [[ $PREFIX = -* ]] && return 1 + __docker_services all "$@" +} + +__docker_complete_services_ids() { + [[ $PREFIX = -* ]] && return 1 + __docker_services ids "$@" +} + +__docker_complete_services_names() { + [[ $PREFIX = -* ]] && return 1 + __docker_services names "$@" +} + +__docker_service_commands() { + local -a _docker_service_subcommands + _docker_service_subcommands=( + "create:Create a new service" + "inspect:Display detailed information on one or more services" + "logs:Fetch the logs of a service or task" + "ls:List services" + "rm:Remove one or more services" + "rollback:Revert changes to a service's configuration" + "scale:Scale one or multiple replicated services" + "ps:List the tasks of a service" + "update:Update a service" + ) + _describe -t docker-service-commands "docker service command" _docker_service_subcommands +} + +__docker_service_subcommand() { + local -a _command_args opts_help opts_create_update + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + opts_create_update=( + "($help)*--cap-add=[Add Linux capabilities]:capability: " + "($help)*--cap-drop=[Drop Linux capabilities]:capability: " + "($help)*--constraint=[Placement constraints]:constraint: " + "($help)--endpoint-mode=[Placement constraints]:mode:(dnsrr vip)" + "($help)*"{-e=,--env=}"[Set environment variables]:env: " + "($help)--health-cmd=[Command to run to check health]:command: " + "($help)--health-interval=[Time between running the check]:time: " + "($help)--health-retries=[Consecutive failures needed to report unhealthy]:retries:(1 2 3 4 5)" + "($help)--health-timeout=[Maximum time to allow one check to run]:time: " + "($help)--hostname=[Service container hostname]:hostname: " \ + "($help)--isolation=[Service container isolation mode]:isolation:(default process hyperv)" \ + "($help)*--label=[Service labels]:label: " + "($help)--limit-cpu=[Limit CPUs]:value: " + "($help)--limit-memory=[Limit Memory]:value: " + "($help)--limit-pids[Limit maximum number of processes (default 0 = unlimited)]" + "($help)--log-driver=[Logging driver for service]:logging driver:__docker_complete_log_drivers" + "($help)*--log-opt=[Logging driver options]:log driver options:__docker_complete_log_options" + "($help)*--mount=[Attach a filesystem mount to the service]:mount: " + "($help)*--network=[Network attachments]:network: " + "($help)--no-healthcheck[Disable any container-specified HEALTHCHECK]" + "($help)--read-only[Mount the container's root filesystem as read only]" + "($help)--replicas=[Number of tasks]:replicas: " + "($help)--reserve-cpu=[Reserve CPUs]:value: " + "($help)--reserve-memory=[Reserve Memory]:value: " + "($help)--restart-condition=[Restart when condition is met]:mode:(any none on-failure)" + "($help)--restart-delay=[Delay between restart attempts]:delay: " + "($help)--restart-max-attempts=[Maximum number of restarts before giving up]:max-attempts: " + "($help)--restart-window=[Window used to evaluate the restart policy]:duration: " + "($help)--rollback-delay=[Delay between task rollbacks]:duration: " + "($help)--rollback-failure-action=[Action on rollback failure]:action:(continue pause)" + "($help)--rollback-max-failure-ratio=[Failure rate to tolerate during a rollback]:failure rate: " + "($help)--rollback-monitor=[Duration after each task rollback to monitor for failure]:duration: " + "($help)--rollback-parallelism=[Maximum number of tasks rolled back simultaneously]:number: " + "($help)*--secret=[Specify secrets to expose to the service]:secret:__docker_complete_secrets" + "($help)--stop-grace-period=[Time to wait before force killing a container]:grace period: " + "($help)--stop-signal=[Signal to stop the container]:signal:_signals" + "($help -t --tty)"{-t,--tty}"[Allocate a pseudo-TTY]" + "($help)--update-delay=[Delay between updates]:delay: " + "($help)--update-failure-action=[Action on update failure]:mode:(continue pause rollback)" + "($help)--update-max-failure-ratio=[Failure rate to tolerate during an update]:fraction: " + "($help)--update-monitor=[Duration after each task update to monitor for failure]:window: " + "($help)--update-parallelism=[Maximum number of tasks updated simultaneously]:number: " + "($help -u --user)"{-u=,--user=}"[Username or UID]:user:_users" + "($help)--with-registry-auth[Send registry authentication details to swarm agents]" + "($help -w --workdir)"{-w=,--workdir=}"[Working directory inside the container]:directory:_directories" + ) + + case "$words[1]" in + (create) + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_create_update \ + "($help)*--container-label=[Container labels]:label: " \ + "($help)*--dns=[Set custom DNS servers]:DNS: " \ + "($help)*--dns-option=[Set DNS options]:DNS option: " \ + "($help)*--dns-search=[Set custom DNS search domains]:DNS search: " \ + "($help)*--env-file=[Read environment variables from a file]:environment file:_files" \ + "($help)*--group=[Set one or more supplementary user groups for the container]:group: _groups " \ + "($help)--mode=[Service Mode]:mode:(global replicated)" \ + "($help)--name=[Service name]:name: " \ + "($help)*--placement-pref=[Add a placement preference]:pref:__docker_service_complete_placement_pref" \ + "($help)*"{-p=,--publish=}"[Publish a port as a node port]:port: " \ + "($help -): :__docker_complete_images" \ + "($help -):command: _command_names -e" \ + "($help -)*::arguments: _normal" && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " \ + "($help)--pretty[Print the information in a human friendly format]" \ + "($help -)*:service:__docker_complete_services" && ret=0 + ;; + (logs) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --follow)"{-f,--follow}"[Follow log output]" \ + "($help)--no-resolve[Do not map IDs to Names]" \ + "($help)--no-task-ids[Do not include task IDs]" \ + "($help)--no-trunc[Do not truncate output]" \ + "($help)--since=[Show logs since timestamp]:timestamp: " \ + "($help -n --tail)"{-n=,--tail=}"[Number of lines to show from the end of the logs]:lines:(1 10 20 50 all)" \ + "($help -t --timestamps)"{-t,--timestamps}"[Show timestamps]" \ + "($help -)1:service:__docker_complete_services" && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Filter output based on conditions provided]:filter:__docker_service_complete_ls_filters" \ + "($help)--format=[Format the output using the given Go template]:template: " \ + "($help -q --quiet)"{-q,--quiet}"[Only display IDs]" && ret=0 + ;; + (rm|remove) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:service:__docker_complete_services" && ret=0 + ;; + (rollback) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -d --detach)"{-d=false,--detach=false}"[Disable detached mode]" \ + "($help -q --quiet)"{-q,--quiet}"[Suppress progress output]" \ + "($help -)*:service:__docker_complete_services" && ret=0 + ;; + (scale) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -d --detach)"{-d=false,--detach=false}"[Disable detached mode]" \ + "($help -)*:service:->values" && ret=0 + case $state in + (values) + if compset -P '*='; then + _message 'replicas' && ret=0 + else + __docker_complete_services -qS "=" + fi + ;; + esac + ;; + (ps) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Provide filter values]:filter:__docker_service_complete_ps_filters" \ + "($help)--format=[Format the output using the given go template]:template: " \ + "($help)--no-resolve[Do not map IDs to Names]" \ + "($help)--no-trunc[Do not truncate output]" \ + "($help -q --quiet)"{-q,--quiet}"[Only display task IDs]" \ + "($help -)*:service:__docker_complete_services" && ret=0 + ;; + (update) + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_create_update \ + "($help)--arg=[Service command args]:arguments: _normal" \ + "($help)*--container-label-add=[Add or update container labels]:label: " \ + "($help)*--container-label-rm=[Remove a container label by its key]:label: " \ + "($help)*--dns-add=[Add or update custom DNS servers]:DNS: " \ + "($help)*--dns-rm=[Remove custom DNS servers]:DNS: " \ + "($help)*--dns-option-add=[Add or update DNS options]:DNS option: " \ + "($help)*--dns-option-rm=[Remove DNS options]:DNS option: " \ + "($help)*--dns-search-add=[Add or update custom DNS search domains]:DNS search: " \ + "($help)*--dns-search-rm=[Remove DNS search domains]:DNS search: " \ + "($help)--force[Force update]" \ + "($help)*--group-add=[Add additional supplementary user groups to the container]:group:_groups" \ + "($help)*--group-rm=[Remove previously added supplementary user groups from the container]:group:_groups" \ + "($help)--image=[Service image tag]:image:__docker_complete_repositories" \ + "($help)*--placement-pref-add=[Add a placement preference]:pref:__docker_service_complete_placement_pref" \ + "($help)*--placement-pref-rm=[Remove a placement preference]:pref:__docker_service_complete_placement_pref" \ + "($help)*--publish-add=[Add or update a port]:port: " \ + "($help)*--publish-rm=[Remove a port(target-port mandatory)]:port: " \ + "($help)--rollback[Rollback to previous specification]" \ + "($help -)1:service:__docker_complete_services" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_service_commands" && ret=0 + ;; + esac + + return ret +} + +# EO service + +# BO stack + +__docker_stack_complete_ps_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (desired-state) + state_opts=('accepted' 'running' 'shutdown') + _describe -t state-opts "desired state options" state_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('desired-state' 'id' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_stack_complete_services_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('id' 'label' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_stacks() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines stacks + + lines=(${(f)${:-"$(_call_program commands docker $docker_options stack ls)"$'\n'}}) + + # Parse header line to find columns + local i=1 j=1 k header=${lines[1]} + declare -A begin end + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done + end[${header[$i,$((j-1))]}]=-1 + lines=(${lines[2,-1]}) + + # Service NAME + for line in $lines; do + s="${line[${begin[NAME]},${end[NAME]}]%% ##}" + stacks=($stacks $s) + done + + _describe -t stacks-list "stacks" stacks "$@" && ret=0 + return ret +} + +__docker_complete_stacks() { + [[ $PREFIX = -* ]] && return 1 + __docker_stacks "$@" +} + +__docker_stack_commands() { + local -a _docker_stack_subcommands + _docker_stack_subcommands=( + "deploy:Deploy a new stack or update an existing stack" + "ls:List stacks" + "ps:List the tasks in the stack" + "rm:Remove the stack" + "services:List the services in the stack" + ) + _describe -t docker-stack-commands "docker stack command" _docker_stack_subcommands +} + +__docker_stack_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (deploy|up) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -c --compose-file)"{-c=,--compose-file=}"[Path to a Compose file, or '-' to read from stdin]:compose file:_files -g \"*.(yml|yaml)\"" \ + "($help)--with-registry-auth[Send registry authentication details to Swarm agents]" \ + "($help -):stack:__docker_complete_stacks" && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help && ret=0 + ;; + (ps) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Display all tasks]" \ + "($help)*"{-f=,--filter=}"[Filter output based on conditions provided]:filter:__docker_stack_complete_ps_filters" \ + "($help)--format=[Format the output using the given go template]:template: " \ + "($help)--no-resolve[Do not map IDs to Names]" \ + "($help)--no-trunc[Do not truncate output]" \ + "($help -q --quiet)"{-q,--quiet}"[Only display task IDs]" \ + "($help -):stack:__docker_complete_stacks" && ret=0 + ;; + (rm|remove|down) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -):stack:__docker_complete_stacks" && ret=0 + ;; + (services) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Filter output based on conditions provided]:filter:__docker_stack_complete_services_filters" \ + "($help)--format=[Format the output using the given Go template]:template: " \ + "($help -q --quiet)"{-q,--quiet}"[Only display IDs]" \ + "($help -):stack:__docker_complete_stacks" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_stack_commands" && ret=0 + ;; + esac + + return ret +} + +# EO stack + +# BO swarm + +__docker_swarm_commands() { + local -a _docker_swarm_subcommands + _docker_swarm_subcommands=( + "init:Initialize a swarm" + "join:Join a swarm as a node and/or manager" + "join-token:Manage join tokens" + "leave:Leave a swarm" + "unlock:Unlock swarm" + "unlock-key:Manage the unlock key" + "update:Update the swarm" + ) + _describe -t docker-swarm-commands "docker swarm command" _docker_swarm_subcommands +} + +__docker_swarm_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (init) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--advertise-addr=[Advertised address]:ip\:port: " \ + "($help)--data-path-addr=[Data path IP or interface]:ip " \ + "($help)--data-path-port=[Data Path Port]:port " \ + "($help)--default-addr-pool=[Default address pool]" \ + "($help)--default-addr-pool-mask-length=[Default address pool subnet mask length]" \ + "($help)--autolock[Enable manager autolocking]" \ + "($help)--availability=[Availability of the node]:availability:(active drain pause)" \ + "($help)--cert-expiry=[Validity period for node certificates]:duration: " \ + "($help)--dispatcher-heartbeat=[Dispatcher heartbeat period]:duration: " \ + "($help)*--external-ca=[Specifications of one or more certificate signing endpoints]:endpoint: " \ + "($help)--force-new-cluster[Force create a new cluster from current state]" \ + "($help)--listen-addr=[Listen address]:ip\:port: " \ + "($help)--max-snapshots[Number of additional Raft snapshots to retain]" \ + "($help)--snapshot-interval[Number of log entries between Raft snapshots]" \ + "($help)--task-history-limit=[Task history retention limit]:limit: " && ret=0 + ;; + (join) + _arguments $(__docker_arguments) -A '-*' \ + $opts_help \ + "($help)--advertise-addr=[Advertised address]:ip\:port: " \ + "($help)--data-path-addr=[Data path IP or interface]:ip " \ + "($help)--availability=[Availability of the node]:availability:(active drain pause)" \ + "($help)--listen-addr=[Listen address]:ip\:port: " \ + "($help)--token=[Token for entry into the swarm]:secret: " \ + "($help -):host\:port: " && ret=0 + ;; + (join-token) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -q --quiet)"{-q,--quiet}"[Only display token]" \ + "($help)--rotate[Rotate join token]" \ + "($help -):role:(manager worker)" && ret=0 + ;; + (leave) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --force)"{-f,--force}"[Force this node to leave the swarm, ignoring warnings]" && ret=0 + ;; + (unlock) + _arguments $(__docker_arguments) \ + $opts_help && ret=0 + ;; + (unlock-key) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -q --quiet)"{-q,--quiet}"[Only display token]" \ + "($help)--rotate[Rotate unlock token]" && ret=0 + ;; + (update) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--autolock[Enable manager autolocking]" \ + "($help)--cert-expiry=[Validity period for node certificates]:duration: " \ + "($help)--dispatcher-heartbeat=[Dispatcher heartbeat period]:duration: " \ + "($help)*--external-ca=[Specifications of one or more certificate signing endpoints]:endpoint: " \ + "($help)--max-snapshots[Number of additional Raft snapshots to retain]" \ + "($help)--snapshot-interval[Number of log entries between Raft snapshots]" \ + "($help)--task-history-limit=[Task history retention limit]:limit: " && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_network_commands" && ret=0 + ;; + esac + + return ret +} + +# EO swarm + +# BO system + +__docker_system_commands() { + local -a _docker_system_subcommands + _docker_system_subcommands=( + "df:Show docker filesystem usage" + "events:Get real time events from the server" + "info:Display system-wide information" + "prune:Remove unused data" + ) + _describe -t docker-system-commands "docker system command" _docker_system_subcommands +} + +__docker_system_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (df) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -v --verbose)"{-v,--verbose}"[Show detailed information on space usage]" && ret=0 + ;; + (events) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Filter values]:filter:__docker_complete_events_filter" \ + "($help)--since=[Events created since this timestamp]:timestamp: " \ + "($help)--until=[Events created until this timestamp]:timestamp: " \ + "($help)--format=[Format the output using the given go template]:template: " && ret=0 + ;; + (info) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " && ret=0 + ;; + (prune) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Remove all unused data, not just dangling ones]" \ + "($help)*--filter=[Filter values]:filter:__docker_complete_prune_filters" \ + "($help -f --force)"{-f,--force}"[Do not prompt for confirmation]" \ + "($help)--volumes=[Remove all unused volumes]" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_volume_commands" && ret=0 + ;; + esac + + return ret +} + +# EO system + +# BO volume + +__docker_volume_complete_ls_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (dangling) + dangling_opts=('true' 'false') + _describe -t dangling-filter-opts "Dangling Filter Options" dangling_opts && ret=0 + ;; + (driver) + __docker_complete_info_plugins Volume && ret=0 + ;; + (name) + __docker_complete_volumes && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('dangling' 'driver' 'label' 'name') + _describe -t filter-opts "Filter Options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_complete_volumes() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + declare -a lines volumes + + lines=(${(f)${:-"$(_call_program commands docker $docker_options volume ls)"$'\n'}}) + + # Parse header line to find columns + local i=1 j=1 k header=${lines[1]} + declare -A begin end + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done + end[${header[$i,$((j-1))]}]=-1 + lines=(${lines[2,-1]}) + + # Names + local line s + for line in $lines; do + s="${line[${begin[VOLUME NAME]},${end[VOLUME NAME]}]%% ##}" + s="$s:${(l:7:: :::)${${line[${begin[DRIVER]},${end[DRIVER]}]}%% ##}}" + volumes=($volumes $s) + done + + _describe -t volumes-list "volumes" volumes && ret=0 + return ret +} + +__docker_volume_commands() { + local -a _docker_volume_subcommands + _docker_volume_subcommands=( + "create:Create a volume" + "inspect:Display detailed information on one or more volumes" + "ls:List volumes" + "prune:Remove all unused volumes" + "rm:Remove one or more volumes" + ) + _describe -t docker-volume-commands "docker volume command" _docker_volume_subcommands +} + +__docker_volume_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (create) + _arguments $(__docker_arguments) -A '-*' \ + $opts_help \ + "($help -d --driver)"{-d=,--driver=}"[Volume driver name]:Driver name:(local)" \ + "($help)*--label=[Set metadata for a volume]:label=value: " \ + "($help)*"{-o=,--opt=}"[Driver specific options]:Driver option: " \ + "($help -)1:Volume name: " && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " \ + "($help -)1:volume:__docker_complete_volumes" && ret=0 + ;; + (ls) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Provide filter values]:filter:__docker_volume_complete_ls_filters" \ + "($help)--format=[Format the output using the given Go template]:template: " \ + "($help -q --quiet)"{-q,--quiet}"[Only display volume names]" && ret=0 + ;; + (prune) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Remove all unused local volumes, not just anonymous ones]" \ + "($help)*--filter=[Filter values]:filter:__docker_complete_prune_filters" \ + "($help -f --force)"{-f,--force}"[Do not prompt for confirmation]" && ret=0 + ;; + (rm) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --force)"{-f,--force}"[Force the removal of one or more volumes]" \ + "($help -):volume:__docker_complete_volumes" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_volume_commands" && ret=0 + ;; + esac + + return ret +} + +# EO volume + +# BO context + +__docker_complete_contexts() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + declare -a contexts + + contexts=(${(f)${:-"$(_call_program commands docker $docker_options context ls -q)"$'\n'}}) + + _describe -t context-list "context" contexts && ret=0 + return ret +} + +__docker_context_commands() { + local -a _docker_context_subcommands + _docker_context_subcommands=( + "create:Create new context" + "inspect:Display detailed information on one or more contexts" + "list:List available contexts" + "rm:Remove one or more contexts" + "show:Print the current context" + "update:Update a context" + "use:Set the default context" + ) + _describe -t docker-context-commands "docker context command" _docker_context_subcommands +} + +__docker_context_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (create) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--description=[Description of the context]:description:" \ + "($help)--docker=[Set the docker endpoint]:docker:" \ + "($help)--from=[Create context from a named context]:from:__docker_complete_contexts" \ + "($help -):name: " && ret=0 + ;; + (use) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)1:context:__docker_complete_contexts" && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)1:context:__docker_complete_contexts" && ret=0 + ;; + (rm) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)1:context:__docker_complete_contexts" && ret=0 + ;; + (update) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--description=[Description of the context]:description:" \ + "($help)--docker=[Set the docker endpoint]:docker:" \ + "($help -):name:" && ret=0 + ;; + esac + + return ret +} + +# EO context + +__docker_caching_policy() { + oldp=( "$1"(Nmh+1) ) # 1 hour + (( $#oldp )) +} + +__docker_commands() { + local cache_policy + integer force_invalidation=0 + + zstyle -s ":completion:${curcontext}:" cache-policy cache_policy + if [[ -z "$cache_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy __docker_caching_policy + fi + + if ( (( ! ${+_docker_hide_legacy_commands} )) || _cache_invalid docker_hide_legacy_commands ) \ + && ! _retrieve_cache docker_hide_legacy_commands; + then + _docker_hide_legacy_commands="${DOCKER_HIDE_LEGACY_COMMANDS}" + _store_cache docker_hide_legacy_commands _docker_hide_legacy_commands + fi + + if [[ "${_docker_hide_legacy_commands}" != "${DOCKER_HIDE_LEGACY_COMMANDS}" ]]; then + force_invalidation=1 + _docker_hide_legacy_commands="${DOCKER_HIDE_LEGACY_COMMANDS}" + _store_cache docker_hide_legacy_commands _docker_hide_legacy_commands + fi + + if ( [[ ${+_docker_subcommands} -eq 0 ]] || _cache_invalid docker_subcommands ) \ + && ! _retrieve_cache docker_subcommands || [[ ${force_invalidation} -eq 1 ]]; + then + local -a lines + lines=(${(f)"$(_call_program commands docker 2>&1)"}) + _docker_subcommands=(${${${(M)${lines[$((${lines[(i)*Commands:]} + 1)),-1]}:# *}## #}/\*# ##/:}) + _docker_subcommands=($_docker_subcommands 'daemon:Enable daemon mode' 'help:Show help for a command') + (( $#_docker_subcommands > 2 )) && _store_cache docker_subcommands _docker_subcommands + fi + _describe -t docker-commands "docker command" _docker_subcommands +} + +__docker_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (attach|commit|cp|create|diff|exec|export|kill|logs|pause|unpause|port|rename|restart|rm|run|start|stats|stop|top|update|wait) + __docker_container_subcommand && ret=0 + ;; + (build|history|import|load|pull|push|save|tag) + __docker_image_subcommand && ret=0 + ;; + (checkpoint) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_checkpoint_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_checkpoint_subcommand && ret=0 + ;; + esac + ;; + (container) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_container_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_container_subcommand && ret=0 + ;; + esac + ;; + (context) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_context_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_context_subcommand && ret=0 + ;; + esac + ;; + (daemon) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*--add-runtime=[Register an additional OCI compatible runtime]:runtime:__docker_complete_runtimes" \ + "($help)*--allow-nondistributable-artifacts=[Push nondistributable artifacts to specified registries]:registry: " \ + "($help)--api-cors-header=[CORS headers in the Engine API]:CORS headers: " \ + "($help)*--authorization-plugin=[Authorization plugins to load]" \ + "($help -b --bridge)"{-b=,--bridge=}"[Attach containers to a network bridge]:bridge:_net_interfaces" \ + "($help)--bip=[Network bridge IP]:IP address: " \ + "($help)--cgroup-parent=[Parent cgroup for all containers]:cgroup: " \ + "($help)--config-file=[Path to daemon configuration file]:Config File:_files" \ + "($help)--containerd=[Path to containerd socket]:socket:_files -g \"*.sock\"" \ + "($help)--containerd-namespace=[Containerd namespace to use]:containerd namespace:" \ + "($help)--containerd-plugins-namespace=[Containerd namespace to use for plugins]:containerd namespace:" \ + "($help)--data-root=[Root directory of persisted Docker data]:path:_directories" \ + "($help -D --debug)"{-D,--debug}"[Enable debug mode]" \ + "($help)--default-gateway[Container default gateway IPv4 address]:IPv4 address: " \ + "($help)--default-gateway-v6[Container default gateway IPv6 address]:IPv6 address: " \ + "($help)--default-shm-size=[Default shm size for containers]:size:" \ + "($help)*--default-ulimit=[Default ulimits for containers]:ulimit: " \ + "($help)*--dns=[DNS server to use]:DNS: " \ + "($help)*--dns-opt=[DNS options to use]:DNS option: " \ + "($help)*--dns-search=[DNS search domains to use]:DNS search: " \ + "($help)*--exec-opt=[Runtime execution options]:runtime execution options: " \ + "($help)--exec-root=[Root directory for execution state files]:path:_directories" \ + "($help)--experimental[Enable experimental features]" \ + "($help)--fixed-cidr=[IPv4 subnet for fixed IPs]:IPv4 subnet: " \ + "($help)--fixed-cidr-v6=[IPv6 subnet for fixed IPs]:IPv6 subnet: " \ + "($help -G --group)"{-G=,--group=}"[Group for the unix socket]:group:_groups" \ + "($help -H --host)"{-H=,--host=}"[tcp://host:port to bind/connect to]:host: " \ + "($help)--icc[Enable inter-container communication]" \ + "($help)--init[Run an init inside containers to forward signals and reap processes]" \ + "($help)--init-path=[Path to the docker-init binary]:docker-init binary:_files" \ + "($help)*--insecure-registry=[Enable insecure registry communication]:registry: " \ + "($help)--ip=[Default IP when binding container ports]" \ + "($help)--ip-forward[Enable net.ipv4.ip_forward]" \ + "($help)--ip-masq[Enable IP masquerading]" \ + "($help)--iptables[Enable addition of iptables rules]" \ + "($help)--ipv6[Enable IPv6 networking]" \ + "($help -l --log-level)"{-l=,--log-level=}"[Logging level]:level:(debug info warn error fatal)" \ + "($help)*--label=[Key=value labels]:label: " \ + "($help)--live-restore[Enable live restore of docker when containers are still running]" \ + "($help)--log-driver=[Default driver for container logs]:logging driver:__docker_complete_log_drivers" \ + "($help)*--log-opt=[Default log driver options for containers]:log driver options:__docker_complete_log_options" \ + "($help)--max-concurrent-downloads[Set the max concurrent downloads]" \ + "($help)--max-concurrent-uploads[Set the max concurrent uploads]" \ + "($help)--max-download-attempts[Set the max download attempts for each pull]" \ + "($help)--mtu=[Network MTU]:mtu:(0 576 1420 1500 9000)" \ + "($help)--oom-score-adjust=[Set the oom_score_adj for the daemon]:oom-score:(-500)" \ + "($help -p --pidfile)"{-p=,--pidfile=}"[Path to use for daemon PID file]:PID file:_files" \ + "($help)--raw-logs[Full timestamps without ANSI coloring]" \ + "($help)*--registry-mirror=[Preferred registry mirror]:registry mirror: " \ + "($help)--seccomp-profile=[Path to seccomp profile]:path:_files -g \"*.json\"" \ + "($help -s --storage-driver)"{-s=,--storage-driver=}"[Storage driver to use]:driver:(btrfs devicemapper overlay2 vfs zfs)" \ + "($help)--selinux-enabled[Enable selinux support]" \ + "($help)--shutdown-timeout=[Set the shutdown timeout value in seconds]:time: " \ + "($help)*--storage-opt=[Storage driver options]:storage driver options: " \ + "($help)--tls[Use TLS]" \ + "($help)--tlscacert=[Trust certs signed only by this CA]:PEM file:_files -g \"*.(pem|crt)\"" \ + "($help)--tlscert=[Path to TLS certificate file]:PEM file:_files -g \"*.(pem|crt)\"" \ + "($help)--tlskey=[Path to TLS key file]:Key file:_files -g \"*.(pem|key)\"" \ + "($help)--tlsverify[Use TLS and verify the remote]" \ + "($help)--userns-remap=[User/Group setting for user namespaces]:user\:group:->users-groups" \ + "($help)--userland-proxy[Use userland proxy for loopback traffic]" \ + "($help)--userland-proxy-path=[Path to the userland proxy binary]:binary:_files" \ + "($help)--validate[Validate daemon configuration and exit]" && ret=0 + + case $state in + (users-groups) + if compset -P '*:'; then + _groups && ret=0 + else + _describe -t userns-default "default Docker user management" '(default)' && ret=0 + _users && ret=0 + fi + ;; + esac + ;; + (events|info) + __docker_system_subcommand && ret=0 + ;; + (image) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_image_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_image_subcommand && ret=0 + ;; + esac + ;; + (images) + words[1]='ls' + __docker_image_subcommand && ret=0 + ;; + (inspect) + local state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " \ + "($help -s --size)"{-s,--size}"[Display total file sizes if the type is container]" \ + "($help)--type=[Return JSON for specified type]:type:(container image network node plugin service volume)" \ + "($help -)*: :->values" && ret=0 + + case $state in + (values) + if [[ ${words[(r)--type=container]} == --type=container ]]; then + __docker_complete_containers && ret=0 + elif [[ ${words[(r)--type=image]} == --type=image ]]; then + __docker_complete_images && ret=0 + elif [[ ${words[(r)--type=network]} == --type=network ]]; then + __docker_complete_networks && ret=0 + elif [[ ${words[(r)--type=node]} == --type=node ]]; then + __docker_complete_nodes && ret=0 + elif [[ ${words[(r)--type=plugin]} == --type=plugin ]]; then + __docker_complete_plugins && ret=0 + elif [[ ${words[(r)--type=service]} == --type=secrets ]]; then + __docker_complete_secrets && ret=0 + elif [[ ${words[(r)--type=service]} == --type=service ]]; then + __docker_complete_services && ret=0 + elif [[ ${words[(r)--type=volume]} == --type=volume ]]; then + __docker_complete_volumes && ret=0 + else + __docker_complete_containers + __docker_complete_images + __docker_complete_networks + __docker_complete_nodes + __docker_complete_plugins + __docker_complete_secrets + __docker_complete_services + __docker_complete_volumes && ret=0 + fi + ;; + esac + ;; + (login) + _arguments $(__docker_arguments) -A '-*' \ + $opts_help \ + "($help -p --password)"{-p=,--password=}"[Password]:password: " \ + "($help)--password-stdin[Read password from stdin]" \ + "($help -u --username)"{-u=,--username=}"[Username]:username: " \ + "($help -)1:server: " && ret=0 + ;; + (logout) + _arguments $(__docker_arguments) -A '-*' \ + $opts_help \ + "($help -)1:server: " && ret=0 + ;; + (network) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_network_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_network_subcommand && ret=0 + ;; + esac + ;; + (node) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_node_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_node_subcommand && ret=0 + ;; + esac + ;; + (plugin) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_plugin_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_plugin_subcommand && ret=0 + ;; + esac + ;; + (ps) + words[1]='ls' + __docker_container_subcommand && ret=0 + ;; + (rmi) + words[1]='rm' + __docker_image_subcommand && ret=0 + ;; + (search) + _arguments $(__docker_arguments) -A '-*' \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Filter values]:filter:__docker_complete_search_filters" \ + "($help)--limit=[Maximum returned search results]:limit:(1 5 10 25 50)" \ + "($help)--no-trunc[Do not truncate output]" \ + "($help -):term: " && ret=0 + ;; + (secret) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_secret_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_secret_subcommand && ret=0 + ;; + esac + ;; + (service) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_service_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_service_subcommand && ret=0 + ;; + esac + ;; + (stack) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_stack_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_stack_subcommand && ret=0 + ;; + esac + ;; + (swarm) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_swarm_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_swarm_subcommand && ret=0 + ;; + esac + ;; + (system) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_system_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_system_subcommand && ret=0 + ;; + esac + ;; + (version) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " && ret=0 + ;; + (volume) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_volume_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_volume_subcommand && ret=0 + ;; + esac + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_commands" && ret=0 + ;; + esac + + return ret +} + +_docker() { + # Support for subservices, which allows for `compdef _docker docker-shell=_docker_containers`. + # Based on /usr/share/zsh/functions/Completion/Unix/_git without support for `ret`. + if [[ $service != docker ]]; then + _call_function - _$service + return + fi + + local curcontext="$curcontext" state line help="-h --help" + integer ret=1 + typeset -A opt_args + + _arguments $(__docker_arguments) -C \ + "(: -)"{-h,--help}"[Print usage]" \ + "($help)--config[Location of client config files]:path:_directories" \ + "($help -c --context)"{-c=,--context=}"[Execute the command in a docker context]:context:__docker_complete_contexts" \ + "($help -D --debug)"{-D,--debug}"[Enable debug mode]" \ + "($help -H --host)"{-H=,--host=}"[tcp://host:port to bind/connect to]:host: " \ + "($help -l --log-level)"{-l=,--log-level=}"[Logging level]:level:(debug info warn error fatal)" \ + "($help)--tls[Use TLS]" \ + "($help)--tlscacert=[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \ + "($help)--tlscert=[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \ + "($help)--tlskey=[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \ + "($help)--tlsverify[Use TLS and verify the remote]" \ + "($help)--userland-proxy[Use userland proxy for loopback traffic]" \ + "($help -v --version)"{-v,--version}"[Print version information and quit]" \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + local host=${opt_args[-H]}${opt_args[--host]} + local config=${opt_args[--config]} + local context=${opt_args[-c]}${opt_args[--context]} + local docker_options="${host:+--host $host} ${config:+--config $config} ${context:+--context $context} " + + case $state in + (command) + __docker_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-$words[1]: + __docker_subcommand && ret=0 + ;; + esac + + return ret +} + +_dockerd() { + integer ret=1 + words[1]='daemon' + __docker_subcommand && ret=0 + return ret +} + +_docker "$@" + +# Local Variables: +# mode: Shell-Script +# sh-indentation: 4 +# indent-tabs-mode: nil +# sh-basic-offset: 4 +# End: +# vim: ft=zsh sw=4 ts=4 et diff --git a/zsh/.oh-my-zsh/plugins/docker/docker.plugin.zsh b/zsh/.oh-my-zsh/plugins/docker/docker.plugin.zsh new file mode 100644 index 0000000..dbabf3a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/docker/docker.plugin.zsh @@ -0,0 +1,64 @@ +alias dbl='docker build' +alias dcin='docker container inspect' +alias dcls='docker container ls' +alias dclsa='docker container ls -a' +alias dib='docker image build' +alias dii='docker image inspect' +alias dils='docker image ls' +alias dipu='docker image push' +alias dirm='docker image rm' +alias dit='docker image tag' +alias dlo='docker container logs' +alias dnc='docker network create' +alias dncn='docker network connect' +alias dndcn='docker network disconnect' +alias dni='docker network inspect' +alias dnls='docker network ls' +alias dnrm='docker network rm' +alias dpo='docker container port' +alias dps='docker ps' +alias dpsa='docker ps -a' +alias dpu='docker pull' +alias dr='docker container run' +alias drit='docker container run -it' +alias drm='docker container rm' +alias 'drm!'='docker container rm -f' +alias dst='docker container start' +alias drs='docker container restart' +alias dsta='docker stop $(docker ps -q)' +alias dstp='docker container stop' +alias dtop='docker top' +alias dvi='docker volume inspect' +alias dvls='docker volume ls' +alias dvprune='docker volume prune' +alias dxc='docker container exec' +alias dxcit='docker container exec -it' + +if (( ! $+commands[docker] )); then + return +fi + +# Standarized $0 handling +# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" + +# If the completion file doesn't exist yet, we need to autoload it and +# bind it to `docker`. Otherwise, compinit will have already done that. +if [[ ! -f "$ZSH_CACHE_DIR/completions/_docker" ]]; then + typeset -g -A _comps + autoload -Uz _docker + _comps[docker]=_docker +fi + +{ + # `docker completion` is only available from 23.0.0 on + # docker version returns `Docker version 24.0.2, build cb74dfcd85` + # with `s:,:` remove the comma after the version, and select third word of it + if zstyle -t ':omz:plugins:docker' legacy-completion || \ + ! is-at-least 23.0.0 ${${(s:,:z)"$(command docker --version)"}[3]}; then + command cp "${0:h}/completions/_docker" "$ZSH_CACHE_DIR/completions/_docker" + else + command docker completion zsh | tee "$ZSH_CACHE_DIR/completions/_docker" > /dev/null + fi +} &| diff --git a/zsh/.oh-my-zsh/plugins/doctl/README.md b/zsh/.oh-my-zsh/plugins/doctl/README.md new file mode 100644 index 0000000..507bd93 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/doctl/README.md @@ -0,0 +1,9 @@ +# Doctl + +This plugin provides completion for [Doctl](https://github.com/digitalocean/doctl). + +To use it add doctl to the plugins array in your zshrc file. + +```bash +plugins=(... doctl) +``` diff --git a/zsh/.oh-my-zsh/plugins/doctl/doctl.plugin.zsh b/zsh/.oh-my-zsh/plugins/doctl/doctl.plugin.zsh new file mode 100644 index 0000000..88cd069 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/doctl/doctl.plugin.zsh @@ -0,0 +1,17 @@ +# Autocompletion for doctl, the command line tool for DigitalOcean service +# +# doctl project: https://github.com/digitalocean/doctl +# +# Author: https://github.com/HalisCz + +if (( ! $+commands[doctl] )); then + return +fi + +if [[ ! -f "$ZSH_CACHE_DIR/completions/_doctl" ]]; then + typeset -g -A _comps + autoload -Uz _doctl + _comps[doctl]=_doctl +fi + +doctl completion zsh >| "$ZSH_CACHE_DIR/completions/_doctl" &| diff --git a/zsh/.oh-my-zsh/plugins/dotenv/README.md b/zsh/.oh-my-zsh/plugins/dotenv/README.md new file mode 100644 index 0000000..0f362c6 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dotenv/README.md @@ -0,0 +1,92 @@ +# dotenv + +Automatically load your project ENV variables from `.env` file when you `cd` into project root directory. + +Storing configuration in the environment is one of the tenets of a [twelve-factor app](https://www.12factor.net). Anything that is likely to change between deployment environments, such as resource handles for databases or credentials for external services, should be extracted from the code into environment variables. + +To use it, add `dotenv` to the plugins array in your zshrc file: + +```sh +plugins=(... dotenv) +``` + +## Usage + +Create `.env` file inside your project root directory and put your ENV variables there. + +For example: + +```sh +export AWS_S3_TOKEN=d84a83539134f28f412c652b09f9f98eff96c9a +export SECRET_KEY=7c6c72d959416d5aa368a409362ec6e2ac90d7f +export MONGO_URI=mongodb://127.0.0.1:27017 +export PORT=3001 +``` + +`export` is optional. This format works as well: + +```sh +AWS_S3_TOKEN=d84a83539134f28f412c652b09f9f98eff96c9a +SECRET_KEY=7c6c72d959416d5aa368a409362ec6e2ac90d7f +MONGO_URI=mongodb://127.0.0.1:27017 +PORT=3001 +``` + +You can even mix both formats, although it's probably a bad idea. + +## Settings + +### ZSH_DOTENV_FILE + +You can also modify the name of the file to be loaded with the variable `ZSH_DOTENV_FILE`. +If the variable isn't set, the plugin will default to use `.env`. +For example, this will make the plugin look for files named `.dotenv` and load them: + +```zsh +# in ~/.zshrc, before Oh My Zsh is sourced: +ZSH_DOTENV_FILE=.dotenv +``` + +### ZSH_DOTENV_PROMPT + +Set `ZSH_DOTENV_PROMPT=false` in your zshrc file if you don't want the confirmation message. +You can also choose the `Always` option when prompted to always allow sourcing the .env file +in that directory. See the next section for more details. + +### ZSH_DOTENV_ALLOWED_LIST, ZSH_DOTENV_DISALLOWED_LIST + +The default behavior of the plugin is to always ask whether to source a dotenv file. There's +a **Y**es, **N**o, **A**lways and N**e**ver option. If you choose Always, the directory of the .env file +will be added to an allowed list; if you choose Never, it will be added to a disallowed list. +If a directory is found in either of those lists, the plugin won't ask for confirmation and will +instead either source the .env file or proceed without action respectively. + +The allowed and disallowed lists are saved by default in `$ZSH_CACHE_DIR/dotenv-allowed.list` and +`$ZSH_CACHE_DIR/dotenv-disallowed.list` respectively. If you want to change that location, +change the `$ZSH_DOTENV_ALLOWED_LIST` and `$ZSH_DOTENV_DISALLOWED_LIST` variables, like so: + +```zsh +# in ~/.zshrc, before Oh My Zsh is sourced: +ZSH_DOTENV_ALLOWED_LIST=/path/to/dotenv/allowed/list +ZSH_DOTENV_DISALLOWED_LIST=/path/to/dotenv/disallowed/list +``` + +The file is just a list of directories, separated by a newline character. If you want +to change your decision, just edit the file and remove the line for the directory you want to +change. + +NOTE: if a directory is found in both the allowed and disallowed lists, the disallowed list +takes preference, _i.e._ the .env file will never be sourced. + +## Version Control + +**It's strongly recommended to add `.env` file to `.gitignore`**, because usually it contains sensitive information such as your credentials, secret keys, passwords etc. You don't want to commit this file, it's supposed to be local only. + +## Disclaimer + +This plugin only sources the `.env` file. Nothing less, nothing more. It doesn't do any checks. It's designed to be the fastest and simplest option. You're responsible for the `.env` file content. You can put some code (or weird symbols) there, but do it on your own risk. `dotenv` is the basic tool, yet it does the job. + +If you need more advanced and feature-rich ENV management, check out these awesome projects: + +* [direnv](https://github.com/direnv/direnv) +* [zsh-autoenv](https://github.com/Tarrasch/zsh-autoenv) diff --git a/zsh/.oh-my-zsh/plugins/dotenv/dotenv.plugin.zsh b/zsh/.oh-my-zsh/plugins/dotenv/dotenv.plugin.zsh new file mode 100644 index 0000000..2e19ef4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dotenv/dotenv.plugin.zsh @@ -0,0 +1,67 @@ +## Settings + +# Filename of the dotenv file to look for +: ${ZSH_DOTENV_FILE:=.env} + +# Path to the file containing allowed paths +: ${ZSH_DOTENV_ALLOWED_LIST:="${ZSH_CACHE_DIR:-$ZSH/cache}/dotenv-allowed.list"} +: ${ZSH_DOTENV_DISALLOWED_LIST:="${ZSH_CACHE_DIR:-$ZSH/cache}/dotenv-disallowed.list"} + + +## Functions + +source_env() { + if [[ ! -f "$ZSH_DOTENV_FILE" ]]; then + return + fi + + if [[ "$ZSH_DOTENV_PROMPT" != false ]]; then + local confirmation dirpath="${PWD:A}" + + # make sure there is an (dis-)allowed file + touch "$ZSH_DOTENV_ALLOWED_LIST" + touch "$ZSH_DOTENV_DISALLOWED_LIST" + + # early return if disallowed + if command grep -Fx -q "$dirpath" "$ZSH_DOTENV_DISALLOWED_LIST" &>/dev/null; then + return + fi + + # check if current directory's .env file is allowed or ask for confirmation + if ! command grep -Fx -q "$dirpath" "$ZSH_DOTENV_ALLOWED_LIST" &>/dev/null; then + # get cursor column and print new line before prompt if not at line beginning + local column + echo -ne "\e[6n" > /dev/tty + read -t 1 -s -d R column < /dev/tty + column="${column##*\[*;}" + [[ $column -eq 1 ]] || echo + + # print same-line prompt and output newline character if necessary + echo -n "dotenv: found '$ZSH_DOTENV_FILE' file. Source it? ([Y]es/[n]o/[a]lways/n[e]ver) " + read -k 1 confirmation + [[ "$confirmation" = $'\n' ]] || echo + + # check input + case "$confirmation" in + [nN]) return ;; + [aA]) echo "$dirpath" >> "$ZSH_DOTENV_ALLOWED_LIST" ;; + [eE]) echo "$dirpath" >> "$ZSH_DOTENV_DISALLOWED_LIST"; return ;; + *) ;; # interpret anything else as a yes + esac + fi + fi + + # test .env syntax + zsh -fn $ZSH_DOTENV_FILE || { + echo "dotenv: error when sourcing '$ZSH_DOTENV_FILE' file" >&2 + return 1 + } + + setopt localoptions allexport + source $ZSH_DOTENV_FILE +} + +autoload -U add-zsh-hook +add-zsh-hook chpwd source_env + +source_env diff --git a/zsh/.oh-my-zsh/plugins/dotnet/README.md b/zsh/.oh-my-zsh/plugins/dotnet/README.md new file mode 100644 index 0000000..3df326a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dotnet/README.md @@ -0,0 +1,25 @@ +# .NET Core CLI plugin + +This plugin provides completion and useful aliases for [.NET Core CLI](https://dotnet.microsoft.com/). + +To use it, add `dotnet` to the plugins array in your zshrc file. + +``` +plugins=(... dotnet) +``` + +## Aliases + +| Alias | Command | Description | +|-------|------------------|-------------------------------------------------------------------| +| dn | dotnet new | Create a new .NET project or file. | +| dr | dotnet run | Build and run a .NET project output. | +| dt | dotnet test | Run unit tests using the test runner specified in a .NET project. | +| dw | dotnet watch | Watch for source file changes and restart the dotnet command. | +| dwr | dotnet watch run | Watch for source file changes and restart the `run` command. | +| dwt | dotnet watch test| Watch for source file changes and restart the `test` command. | +| ds | dotnet sln | Modify Visual Studio solution files. | +| da | dotnet add | Add a package or reference to a .NET project. | +| dp | dotnet pack | Create a NuGet package. | +| dng | dotnet nuget | Provides additional NuGet commands. | +| db | dotnet build | Build a .NET project | diff --git a/zsh/.oh-my-zsh/plugins/dotnet/dotnet.plugin.zsh b/zsh/.oh-my-zsh/plugins/dotnet/dotnet.plugin.zsh new file mode 100644 index 0000000..f87ffac --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/dotnet/dotnet.plugin.zsh @@ -0,0 +1,26 @@ +# This scripts is copied from (MIT License): +# https://raw.githubusercontent.com/dotnet/sdk/main/scripts/register-completions.zsh + +#compdef dotnet +_dotnet_completion() { + local -a completions=("${(@f)$(dotnet complete "${words}")}") + compadd -a completions + _files +} + +compdef _dotnet_completion dotnet + +# Aliases bellow are here for backwards compatibility +# added by Shaun Tabone (https://github.com/xontab) + +alias dn='dotnet new' +alias dr='dotnet run' +alias dt='dotnet test' +alias dw='dotnet watch' +alias dwr='dotnet watch run' +alias dwt='dotnet watch test' +alias ds='dotnet sln' +alias da='dotnet add' +alias dp='dotnet pack' +alias dng='dotnet nuget' +alias db='dotnet build' diff --git a/zsh/.oh-my-zsh/plugins/droplr/README.md b/zsh/.oh-my-zsh/plugins/droplr/README.md new file mode 100644 index 0000000..02eae59 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/droplr/README.md @@ -0,0 +1,19 @@ +# droplr + +Use [Droplr](https://droplr.com/) from the command line to upload files and shorten +links. It needs to have [Droplr.app](https://droplr.com/apps) installed and logged +in. MacOS only. + +To use it, add `droplr` to the `$plugins` variable in your zshrc file: + +```zsh +plugins=(... droplr) +``` + +Author: [Fabio Fernandes](https://github.com/fabiofl) + +## Examples + +- Upload a file: `droplr ./path/to/file/` + +- Shorten a link: `droplr https://example.com` diff --git a/zsh/.oh-my-zsh/plugins/droplr/droplr.plugin.zsh b/zsh/.oh-my-zsh/plugins/droplr/droplr.plugin.zsh new file mode 100644 index 0000000..e690089 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/droplr/droplr.plugin.zsh @@ -0,0 +1,15 @@ +# Only compatible with MacOS +[[ "$OSTYPE" == darwin* ]] || return + +droplr() { + if [[ $# -eq 0 ]]; then + echo You need to specify a parameter. >&2 + return 1 + fi + + if [[ "$1" =~ ^https?:// ]]; then + osascript -e 'tell app "Droplr" to shorten "'"$1"'"' + else + open -ga /Applications/Droplr.app "$1" + fi +} diff --git a/zsh/.oh-my-zsh/plugins/drush/README.md b/zsh/.oh-my-zsh/plugins/drush/README.md new file mode 100644 index 0000000..73a8b23 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/drush/README.md @@ -0,0 +1,66 @@ +# Drush + +This plugin adds aliases and functions for [Drush](https://www.drush.org), a command-line shell +and Unix scripting interface for Drupal. It also adds completion for the `drush` command. + +To enable it, add `drush` to the plugins array in zshrc file: + +```zsh +plugins=(... drush) +``` + +## Aliases + +| Alias | Command | Description | +| ------- | ----------------------------------------------------------- | -------------------------------------------------------------------- | +| `dr` | `drush` | Display drush help | +| `drca` | `drush cc all` | _(Deprecated in Drush 8)_ Clear all drupal caches | +| `drcb` | `drush cc block` | _(Deprecated in Drush 8)_ Clear block cache | +| `drcex` | `drush config:export -y` | Export Drupal configuration to a directory | +| `drcg` | `drush cc registry` | _(Deprecated in Drush 8)_ Clear registry cache | +| `drcim` | `drush config:import -y` | Import config from a config directory | +| `drcj` | `drush cc css-js` | Clear css-js cache | +| `drcm` | `drush cc menu` | Clear menu cache | +| `drcml` | `drush cc module-list` | Clear module-list cache | +| `drcr` | `drush core-cron` | Run all cron hooks in all active modules for specified site | +| `drct` | `drush cc theme-registry` | Clear theme-registry cache | +| `drcv` | `drush cc views` | Clear views cache _(make sure that the views module is enabled)_ | +| `drdmp` | `drush drush sql-dump --ordered-dump --result-file=dumpsql` | Backup database in a new dump.sql file | +| `drf` | `drush features` | Display features status | +| `drfr` | `drush features-revert -y` | Revert a feature module on your site | +| `drfra` | `drush features-revert-all` | Revert all enabled feature module on your site | +| `drfu` | `drush features-update -y` | Update a feature module on your site | +| `drif` | `drush image-flush --all` | Flush all derived images | +| `drpm` | `drush pm-list --type=module` | Show a list of available modules | +| `drst` | `drush core-status` | Provides a birds-eye view of the current Drupal installation, if any | +| `druli` | `drush user:login` | Display a one time login link for user ID 1, or another user | +| `drup` | `drush updatedb` | Apply any database updates required (as with running update.php) | +| `drups` | `drush updatedb-status` | List any pending database updates | +| `drv` | `drush version` | Show drush version | +| `drvd` | `drush variable-del` | Delete a variable | +| `drvg` | `drush variable-get` | Get a list of some or all site variables and values | +| `drvs` | `drush variable-set` | Set a variable | +| `drws` | `drush watchdog:show` | Show watchdog messages | +| `drwse` | `drush watchdog:show --extended` | Show watchdog messages with extended information | +| `drwst` | `drush watchdog:tail` | Tail watchdog messages | + +## Functions + +- `dren`: download and enable one or more extensions (modules or themes). Must be + invoked with one or more parameters, e.g.: `dren devel` or `dren devel module_filter views`. + +- `drf`: edit drushrc, site alias, and Drupal settings.php files. + Can be invoked with one or without parameters, e.g.: `drf 1`. + +- `dris`: disable one or more extensions (modules or themes). Must be invoked with + one or more parameters, e.g.: `dris devel` or `dris devel module_filter views`. + +- `drpu`: uninstall one or more modules. Must be invoked with one or more + parameters, e.g.: `drpu devel` or `drpu devel module_filter views`. + +- `drnew`: creates a brand new drupal website. Note: as soon as the installation + is complete, `drush` will print a username and a random password into the terminal: + + ```text + Installation complete. User name: admin User password: cf7t8yqNEm + ``` diff --git a/zsh/.oh-my-zsh/plugins/drush/drush.complete.sh b/zsh/.oh-my-zsh/plugins/drush/drush.complete.sh new file mode 100644 index 0000000..63fcd66 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/drush/drush.complete.sh @@ -0,0 +1,50 @@ +# BASH completion script for Drush. +# +# Place this in your /etc/bash_completion.d/ directory or source it from your +# ~/.bash_completion or ~/.bash_profile files. Alternatively, source +# examples/example.bashrc instead, as it will automatically find and source +# this file. +# +# If you're using ZSH instead of BASH, add the following to your ~/.zshrc file +# and source it. +# +# autoload bashcompinit +# bashcompinit +# source /path/to/your/drush.complete.sh + +# Ensure drush is available. +which drush > /dev/null || alias drush &> /dev/null || return + +__drush_ps1() { + f="${TMPDIR:-/tmp/}/drush-env-${USER}/drush-drupal-site-$$" + if [ -f $f ] + then + __DRUPAL_SITE=$(cat "$f") + else + __DRUPAL_SITE="$DRUPAL_SITE" + fi + + # Set DRUSH_PS1_SHOWCOLORHINTS to a non-empty value and define a + # __drush_ps1_colorize_alias() function for color hints in your Drush PS1 + # prompt. See example.prompt.sh for an example implementation. + if [ -n "${__DRUPAL_SITE-}" ] && [ -n "${DRUSH_PS1_SHOWCOLORHINTS-}" ]; then + __drush_ps1_colorize_alias + fi + + [[ -n "$__DRUPAL_SITE" ]] && printf "${1:- (%s)}" "$__DRUPAL_SITE" +} + +# Completion function, uses the "drush complete" command to retrieve +# completions for a specific command line COMP_WORDS. +_drush_completion() { + # Set IFS to newline (locally), since we only use newline separators, and + # need to retain spaces (or not) after completions. + local IFS=$'\n' + # The '< /dev/null' is a work around for a bug in php libedit stdin handling. + # Note that libedit in place of libreadline in some distributions. See: + # https://bugs.launchpad.net/ubuntu/+source/php5/+bug/322214 + COMPREPLY=( $(drush --early=includes/complete.inc "${COMP_WORDS[@]}" < /dev/null 2> /dev/null) ) +} + +# Register our completion function. We include common short aliases for Drush. +complete -o bashdefault -o default -o nospace -F _drush_completion d dr drush drush5 drush6 drush7 drush8 drush.php diff --git a/zsh/.oh-my-zsh/plugins/drush/drush.plugin.zsh b/zsh/.oh-my-zsh/plugins/drush/drush.plugin.zsh new file mode 100644 index 0000000..b44f055 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/drush/drush.plugin.zsh @@ -0,0 +1,107 @@ +# Functions +function dren() { + drush en "$@" -y +} + +function dris() { + drush pm-disable "$@" -y +} + +function drpu() { + drush pm-uninstall "$@" -y +} + +function drf() { + if [[ -z "$1" ]] then + drush core-config + else + drush core-config --choice=$1 + fi +} + +function drfi() { + case "$1" in + fields) drush field-info fields ;; + types) drush field-info types ;; + *) drush field-info ;; + esac +} + +function drnew() { + ( + cd + echo "Website's name: " + read WEBSITE_NAME + + HOST=http://$(hostname -i)/ + + if [[ $WEBSITE_NAME == "" ]] then + MINUTES=$(date +%M:%S) + WEBSITE_NAME="Drupal-$MINUTES" + echo "Your website will be named: $WEBSITE_NAME" + fi + + drush dl drupal --drupal-project-rename=$WEBSITE_NAME + + echo "Type your localhost directory: (Leave empty for /var/www/html/)" + read DIRECTORY + + if [[ $DIRECTORY == "" ]] then + DIRECTORY="/var/www/html/" + fi + + echo "Moving to $DIRECTORY$WEBSITE_NAME" + sudo mv $WEBSITE_NAME $DIRECTORY + cd $DIRECTORY$WEBSITE_NAME + + echo "Database's user: " + read DATABASE_USR + echo "Database's password: " + read -s DATABASE_PWD + echo "Database's name for your project: " + read DATABASE + + DB_URL="mysql://$DATABASE_USR:$DATABASE_PWD@localhost/$DATABASE" + drush site-install standard --db-url=$DB_URL --site-name=$WEBSITE_NAME + + open_command $HOST$WEBSITE_NAME + echo "Done" + ) +} + +# Aliases +alias dr="drush" +alias drca="drush cc all" # Deprecated for Drush 8 +alias drcb="drush cc block" # Deprecated for Drush 8 +alias drcex="drush config:export -y" +alias drcg="drush cc registry" # Deprecated for Drush 8 +alias drcim="drush config:import -y" +alias drcj="drush cc css-js" +alias drcm="drush cc menu" +alias drcml="drush cc module-list" +alias drcr="drush core-cron" +alias drct="drush cc theme-registry" +alias drcv="drush cc views" +alias drdmp="drush sql-dump --ordered-dump --result-file=dump.sql" +alias drf="drush features" +alias drfr="drush features-revert -y" +alias drfra="drush features-revert-all" +alias drfu="drush features-update -y" +alias drif="drush image-flush --all" +alias drpm="drush pm-list --type=module" +alias drst="drush core-status" +alias druli="drush user:login" +alias drup="drush updatedb" +alias drups="drush updatedb-status" +alias drv="drush version" +alias drvd="drush variable-del" +alias drvg="drush variable-get" +alias drvs="drush variable-set" +alias drws="drush watchdog:show" +alias drwse="drush watchdog:show --extended" +alias drwst="drush watchdog:tail" + +# Enable drush autocomplete support +autoload bashcompinit +bashcompinit +source $(dirname $0)/drush.complete.sh diff --git a/zsh/.oh-my-zsh/plugins/eecms/README.md b/zsh/.oh-my-zsh/plugins/eecms/README.md new file mode 100644 index 0000000..5f565f7 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/eecms/README.md @@ -0,0 +1,11 @@ +# eecms plugin + +This plugin adds auto-completion of console commands for [`eecms`](https://github.com/ExpressionEngine/ExpressionEngine). + +To use it, add `eecms` to the plugins array of your `.zshrc` file: +``` +plugins=(... eecms) +``` + +It also adds the alias `eecms` which finds the eecms file in the current project +and runs it with php. diff --git a/zsh/.oh-my-zsh/plugins/eecms/eecms.plugin.zsh b/zsh/.oh-my-zsh/plugins/eecms/eecms.plugin.zsh new file mode 100644 index 0000000..16e5f33 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/eecms/eecms.plugin.zsh @@ -0,0 +1,20 @@ +# ExpressionEngine CMS basic command completion + +_eecms_console () { + echo "php $(find . -maxdepth 3 -mindepth 1 -name 'eecms' -type f | head -n 1)" +} + +_eecms_get_command_list () { + `_eecms_console` | sed "/Available commands/,/^/d" | sed "s/[[:space:]].*//g" +} + +_eecms () { + compadd `_eecms_get_command_list` +} + +compdef _eecms '`_eecms_console`' +compdef _eecms 'system/ee/eecms' +compdef _eecms eecms + +#Alias +alias eecms='`_eecms_console`' diff --git a/zsh/.oh-my-zsh/plugins/emacs/README.md b/zsh/.oh-my-zsh/plugins/emacs/README.md new file mode 100644 index 0000000..789dad2 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emacs/README.md @@ -0,0 +1,30 @@ +# Emacs plugin + +This plugin utilizes the Emacs daemon capability, allowing the user to quickly open frames, whether they are opened in a terminal via a ssh connection, or X frames opened on the same host. The plugin also provides some aliases for such operations. + +- You don't have the cost of starting Emacs all the time anymore +- Opening a file is as fast as Emacs does not have anything else to do. +- You can share opened buffered across opened frames. +- Configuration changes made at runtime are applied to all frames. + +**NOTE:** requires Emacs 24 and newer. + +To use it, add emacs to the plugins array in your zshrc file: + +```zsh +plugins=(... emacs) +``` + +## Aliases + +The plugin uses a custom launcher (which we'll call here `$EMACS_LAUNCHER`) that is just a wrapper around [`emacsclient`](https://www.emacswiki.org/emacs/EmacsClient). + +| Alias | Command | Description | +|--------|----------------------------------------------------|----------------------------------------------------------------| +| emacs | `$EMACS_LAUNCHER --no-wait` | Opens a temporary emacsclient frame | +| e | `emacs` | Same as emacs alias | +| te | `$EMACS_LAUNCHER -nw` | Open terminal emacsclient | +| eeval | `$EMACS_LAUNCHER --eval` | Same as `M-x eval` but from outside Emacs | +| eframe | `emacsclient --alternate-editor="" --create-frame` | Create new X frame | +| efile | - | Print the path to the file open in the current buffer | +| ecd | - | Print the directory of the file open in the current buffer | diff --git a/zsh/.oh-my-zsh/plugins/emacs/emacs.plugin.zsh b/zsh/.oh-my-zsh/plugins/emacs/emacs.plugin.zsh new file mode 100644 index 0000000..0456808 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emacs/emacs.plugin.zsh @@ -0,0 +1,68 @@ +# Emacs 23 daemon capability is a killing feature. +# One emacs process handles all your frames whether +# you use a frame opened in a terminal via a ssh connection or X frames +# opened on the same host. + +# Benefits are multiple +# - You don't have the cost of starting Emacs all the time anymore +# - Opening a file is as fast as Emacs does not have anything else to do. +# - You can share opened buffered across opened frames. +# - Configuration changes made at runtime are applied to all frames. + +# Require emacs version to be minimum 24 +autoload -Uz is-at-least +is-at-least 24 "${${(Az)"$(emacsclient --version 2>/dev/null)"}[2]}" || return 0 + +# Handle $0 according to the standard: +# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" + +# Path to custom emacsclient launcher +export EMACS_PLUGIN_LAUNCHER="${0:A:h}/emacsclient.sh" + +# set EDITOR if not already defined. +export EDITOR="${EDITOR:-${EMACS_PLUGIN_LAUNCHER}}" + +alias emacs="$EMACS_PLUGIN_LAUNCHER --no-wait" +alias e=emacs +# open terminal emacsclient +alias te="$EMACS_PLUGIN_LAUNCHER -nw" + +# same than M-x eval but from outside Emacs. +alias eeval="$EMACS_PLUGIN_LAUNCHER --eval" +# create a new X frame +alias eframe='emacsclient --alternate-editor="" --create-frame' + +# Emacs ANSI Term tracking +if [[ -n "$INSIDE_EMACS" ]]; then + chpwd_emacs() { print -P "\033AnSiTc %d"; } + print -P "\033AnSiTc %d" # Track current working directory + print -P "\033AnSiTu %n" # Track username + + # add chpwd hook + autoload -Uz add-zsh-hook + add-zsh-hook chpwd chpwd_emacs +fi + +# Write to standard output the path to the file +# opened in the current buffer. +function efile { + local cmd="(buffer-file-name (window-buffer))" + local file="$("$EMACS_PLUGIN_LAUNCHER" --eval "$cmd" | tr -d \")" + + if [[ -z "$file" ]]; then + echo "Can't deduce current buffer filename." >&2 + return 1 + fi + + echo "$file" +} + +# Write to standard output the directory of the file +# opened in the current buffer +function ecd { + local file + file="$(efile)" || return $? + echo "${file:h}" +} diff --git a/zsh/.oh-my-zsh/plugins/emacs/emacsclient.sh b/zsh/.oh-my-zsh/plugins/emacs/emacsclient.sh new file mode 100755 index 0000000..b06f658 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emacs/emacsclient.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +emacsfun() { + local cmd frames + + # Build the Emacs Lisp command to check for suitable frames + # See https://www.gnu.org/software/emacs/manual/html_node/elisp/Frames.html#index-framep + case "$*" in + *-t*|*--tty*|*-nw*) cmd="(memq 't (mapcar 'framep (frame-list)))" ;; # if != nil, there are tty frames + *) cmd="(delete 't (mapcar 'framep (frame-list)))" ;; # if != nil, there are graphical terminals (x, w32, ns) + esac + + # Check if there are suitable frames + frames="$(emacsclient -a '' -n -e "$cmd" 2>/dev/null |sed 's/.*\x07//g' )" + + # Only create another X frame if there isn't one present + if [ -z "$frames" -o "$frames" = nil ]; then + emacsclient --alternate-editor="" --create-frame "$@" + return $? + fi + + emacsclient --alternate-editor="" "$@" +} + +# Adapted from https://github.com/davidshepherd7/emacs-read-stdin/blob/master/emacs-read-stdin.sh +# If the second argument is - then write stdin to a tempfile and open the +# tempfile. (first argument will be `--no-wait` passed in by the plugin.zsh) +if [ $# -ge 2 -a "$2" = "-" ]; then + # Create a tempfile to hold stdin + tempfile="$(mktemp --tmpdir emacs-stdin-$USERNAME.XXXXXXX 2>/dev/null \ + || mktemp -t emacs-stdin-$USERNAME)" # support BSD mktemp + # Redirect stdin to the tempfile + cat - > "$tempfile" + # Reset $2 to the tempfile so that "$@" works as expected + set -- "$1" "$tempfile" "${@:3}" +fi + +emacsfun "$@" diff --git a/zsh/.oh-my-zsh/plugins/ember-cli/README.md b/zsh/.oh-my-zsh/plugins/ember-cli/README.md new file mode 100644 index 0000000..95e0ef9 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ember-cli/README.md @@ -0,0 +1,33 @@ +# Ember CLI + +This plugin adds completion and aliases for using [`ember-cli`](https://cli.emberjs.com/). + +To use it, add `ember-cli` to the plugins array in your zshrc file: + +```zsh +plugins=(... ember-cli) +``` + +## Aliases + +| Alias | Command | +| ----- | -------------------- | +| `ea` | `ember addon` | +| `eb` | `ember build` | +| `ed` | `ember destroy` | +| `eg` | `ember generate` | +| `eh` | `ember help` | +| `ei` | `ember install` | +| `ein` | `ember init` | +| `es` | `ember serve` | +| `et` | `ember test` | +| `ets` | `ember test --serve` | +| `eu` | `ember update` | +| `ev` | `ember version` | + +## Maintainers + +- [BilalBudhani](https://github.com/BilalBudhani) +- [eubenesa](https://github.com/eubenesa) +- [scottkidder](https://github.com/scottkidder] +- [t-sauer](https://www.github.com/t-sauer) diff --git a/zsh/.oh-my-zsh/plugins/ember-cli/_ember-cli b/zsh/.oh-my-zsh/plugins/ember-cli/_ember-cli new file mode 100644 index 0000000..460fa02 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ember-cli/_ember-cli @@ -0,0 +1,189 @@ +#compdef ember + +local curcontext="$curcontext" state line ret=1 + +_arguments -C -A "--version" -A "--help" \ + '(- 1 *)--help' \ + '(- 1 *)--version' \ + '1: :->cmds' \ + '*:: :->args' && ret=0 + +case $state in + cmds) + _values "ember command" \ + "addon[Generates a new folder structure for building an addon, complete with test harness]" \ + "asset-sizes[Shows the sizes of your asset files]" \ + "build[Builds your app and places it into the output path (dist/ by default)]" \ + "destroy[Destroys code generated by generate command]" \ + "generate[Generates new code from blueprints]" \ + "help[Outputs the usage instructions for all commands or the provided command]" \ + "init[Creates a new ember-cli project in the current folder]" \ + "install[Installs an ember-cli addon from npm]" \ + "new[Creates a new directory and runs ember init in it]" \ + "serve[Builds and serves your app, rebuilding on file changes]" \ + "test[Runs your app's test suite]" \ + "version[outputs ember-cli version]" + ret=0 + ;; + args) + case $line[1] in + help) + _values 'commands' \ + 'addon' \ + 'asset-sizes' \ + 'build' \ + 'destroy' \ + 'generate' \ + 'help' \ + 'init' \ + 'install' \ + 'new' \ + 'serve' \ + 'test' \ + 'vesion' && ret=0 + ;; + addon) + _arguments \ + '(--blueprint)--blueprint=-' \ + '(--directory)--directory=-' \ + '(--dry-run)--dry-run' \ + '(--skip-bower)--skip-bower' \ + '(--skip-git)--skip-git' \ + '(--skip-npm)--skip-npm' \ + '(--verbose)--verbose' + ;; + asset-sizes) + _arguments \ + '(--output-path)--output-path=-' + ;; + build) + _arguments \ + '(--environment)--environment=-' \ + '(--output-path)--output-path=-' \ + '(--output-path)--suppress-sizes' \ + '(--watch)--watch' \ + '(--watcher)--watcher=-' \ + '(-dev)-dev' \ + '(-prod)-prod' + ;; + destroy|generate) + _values 'arguments' \ + '(--classic)--classic' \ + '(--dry-run)--dry-run' \ + '(--dummy)--dummy' \ + '(--in-repo-addon)--in-repo-addon-=' \ + '(--pod)--pod' \ + '(--verbose)--verbose' && ret=0 + _values 'blueprints' \ + 'acceptance-test' \ + 'adapter' \ + 'adapter-test' \ + 'component' \ + 'component-addon' \ + 'component-test' \ + 'controller' \ + 'controller-test' \ + 'helper' \ + 'helper-addon' \ + 'helper-test' \ + 'initializer' \ + 'initializer-addon' \ + 'initializer-test' \ + 'instance-initializer' \ + 'instance-initializer-addon' \ + 'instance-initializer-test' \ + 'mixin' \ + 'mixin-test' \ + 'model' \ + 'model-test' \ + 'resource' \ + 'route' \ + 'route-addon' \ + 'route-test' \ + 'serializer' \ + 'serializer-test' \ + 'service' \ + 'service-test' \ + 'template' \ + 'test-helper' \ + 'transform' \ + 'transform-test' \ + 'util' \ + 'util-test' \ + 'view' \ + 'view-test' \ + 'addon' \ + 'addon-import' \ + 'app' \ + 'blueprint' \ + 'http-mock' \ + 'http-proxy' \ + 'in-repo-addon' \ + 'lib' \ + 'server' \ + 'vendor-shim' && ret=0 + ;; + init) + _arguments \ + '(--blueprint)--blueprint=-' \ + '(--name)--name=-' \ + '(--dry-run)--dry-run' \ + '(--skip-bower)--skip-bower' \ + '(--skip-npm)--skip-npm' \ + '(--verbose)--verbose' + ;; + install) + _arguments \ + '(--save-dev)--save-dev' \ + '(--save)--save' + ;; + new) + _arguments \ + '(--blueprint)--blueprint=-' \ + '(--directory)--directory=-' \ + '(--dry-run)--dry-run' \ + '(--skip-bower)--skip-bower' \ + '(--skip-git)--skip-git' \ + '(--skip-npm)--skip-npm' \ + '(--verbose)--verbose' + ;; + serve) + _arguments \ + '(--port)--port=-[To use a port different than 4200. Pass 0 to automatically pick an available port.]' \ + '(--host)--host=-[Listens on all interfaces by default]' \ + '(--proxy)--proxy=-' \ + '(--secure-proxy)--secure-proxy[Set to false to proxy self-signed SSL certificates]' \ + '(--transparent-proxy)--transparent-proxy[Set to false to omit x-forwarded-* headers when proxying]' \ + '(--watcher)--watcher=-' \ + '(--live-reload)--live-reload' \ + '(--live-reload-host)--live-reload-host=-[Defaults to host]' \ + '(--live-reload-base-url)--live-reload-base-url=-[Defaults to baseURL]' \ + '(--live-reload-port)--live-reload-port=-[Defaults to port number within \[49152...65535\]]' \ + '(--environment)--environment=-' \ + '(--output-path)--output-path=-' \ + '(--ssl)--ssl' \ + '(--ssl-key)--ssl-key=-' \ + '(--ssl-cert)--ssl-cert=-' + ;; + test) + _arguments \ + '(--environment)--environment=-' \ + '(--config-file)--config-file=-' \ + '(--server)--server' \ + '(--host)--host=-' \ + '(--test-port)--test-port=-[The test port to use when running with --server.]' \ + '(--filter)--filter=-[A string to filter tests to run]' \ + '(--module)--module=-[The name of a test module to run]' \ + '(--watcher)--watcher=-' \ + '(--launch)--launch=-[A comma separated list of browsers to launch for tests.]' \ + '(--reporter)--reporter=-[Test reporter to use \[tap|dot|xunit\] (default: tap)]' \ + '(--silent)--silent[Suppress any output except for the test report]' \ + '(--test-page)--test-page=-[Test page to invoke]' \ + '(--path)--path=-[Reuse an existing build at given path.]' \ + '(--query)--query=-[A query string to append to the test page URL.]' + ;; + esac + ;; +esac + +return ret diff --git a/zsh/.oh-my-zsh/plugins/ember-cli/ember-cli.plugin.zsh b/zsh/.oh-my-zsh/plugins/ember-cli/ember-cli.plugin.zsh new file mode 100644 index 0000000..0a2c09b --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/ember-cli/ember-cli.plugin.zsh @@ -0,0 +1,12 @@ +alias ea='ember addon' +alias eb='ember build' +alias ed='ember destroy' +alias eg='ember generate' +alias eh='ember help' +alias ei='ember install' +alias ein='ember init' +alias es='ember serve' +alias et='ember test' +alias ets='ember test --serve' +alias eu='ember update' +alias ev='ember version' diff --git a/zsh/.oh-my-zsh/plugins/emoji-clock/README.md b/zsh/.oh-my-zsh/plugins/emoji-clock/README.md new file mode 100644 index 0000000..4736798 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emoji-clock/README.md @@ -0,0 +1,14 @@ +# emoji-clock + +The plugin displays current time as an emoji symbol with half hour accuracy. + +To use it, add `emoji-clock` to the plugins array of your zshrc file: +``` +plugins=(... emoji-clock) +``` + +## Features + +| Function | Description | +|-------------------|----------------------------------------------------------------------| +| `emoji-clock` | Displays current time in clock emoji symbol with half hour accuracy | diff --git a/zsh/.oh-my-zsh/plugins/emoji-clock/emoji-clock.plugin.zsh b/zsh/.oh-my-zsh/plugins/emoji-clock/emoji-clock.plugin.zsh new file mode 100644 index 0000000..eab00ae --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emoji-clock/emoji-clock.plugin.zsh @@ -0,0 +1,33 @@ +# ------------------------------------------------------------------------------ +# FILE: emoji-clock.plugin.zsh +# DESCRIPTION: The current time with half hour accuracy as an emoji symbol. +# Inspired by Andre Torrez' "Put A Burger In Your Shell" +# https://notes.torrez.org/2013/04/put-a-burger-in-your-shell.html +# AUTHOR: Alexis Hildebrandt (afh[at]surryhill.net) +# VERSION: 1.0.0 +# ----------------------------------------------------------------------------- + +function emoji-clock() { + # Add 15 minutes to the current time and save the value as $minutes. + (( minutes = $(date '+%M') + 15 )) + (( hour = $(date '+%I') + minutes / 60 )) + # make sure minutes and hours don't exceed 60 nor 12 respectively + (( minutes %= 60 )); (( hour %= 12 )) + + case $hour in + 0) clock="🕛"; [ $minutes -ge 30 ] && clock="🕧";; + 1) clock="🕐"; [ $minutes -ge 30 ] && clock="🕜";; + 2) clock="🕑"; [ $minutes -ge 30 ] && clock="🕝";; + 3) clock="🕒"; [ $minutes -ge 30 ] && clock="🕞";; + 4) clock="🕓"; [ $minutes -ge 30 ] && clock="🕟";; + 5) clock="🕔"; [ $minutes -ge 30 ] && clock="🕠";; + 6) clock="🕕"; [ $minutes -ge 30 ] && clock="🕡";; + 7) clock="🕖"; [ $minutes -ge 30 ] && clock="🕢";; + 8) clock="🕗"; [ $minutes -ge 30 ] && clock="🕣";; + 9) clock="🕘"; [ $minutes -ge 30 ] && clock="🕤";; + 10) clock="🕙"; [ $minutes -ge 30 ] && clock="🕥";; + 11) clock="🕚"; [ $minutes -ge 30 ] && clock="🕦";; + *) clock="⌛";; + esac + echo $clock +} diff --git a/zsh/.oh-my-zsh/plugins/emoji/README.md b/zsh/.oh-my-zsh/plugins/emoji/README.md new file mode 100644 index 0000000..64e357b --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emoji/README.md @@ -0,0 +1,127 @@ +# emoji plugin + +Support for conveniently working with Unicode emoji in Zsh. + +## Features + +This plugin provides support for working with Unicode emoji characters in `zsh` using human-readable identifiers. It provides global variables which map emoji names to the actual characters, country names to their flags, and some named groupings of emoji. It also provides associated functions for displaying them. + +#### Variables + +Variable | Description +----------------- | -------------------------------- + $emoji | Maps emoji names to characters (except flags) + $emoji_flags | Maps country names to flag characters (using region indicators) + $emoji_groups | Named groups of emoji. Keys are group names; values are whitespace-separated lists of character names + +You may define new emoji groups at run time by modifying `$emoji_groups`. The special group name `all` is reserved for use by the plugin. You should not modify `$emoji` or `$emoji_flags`. + +#### Functions + +Function | Description +---------------- | ------------------------------- + random_emoji | Prints a random emoji character + display_emoji | Displays emoji, along with their names + +## Usage and Examples + +To output a specific emoji, use: +``` +$> echo $emoji[] +``` +E.g.: +``` +$> echo $emoji[mouse_face] +``` + +To output a random emoji, use: +``` +$> random_emoji +``` +To output a random emoji from a particular group, use: +``` +$> random_emoji +``` +E.g.: +``` +$> random_emoji fruits +$> random_emoji animals +$> random_emoji vehicles +$> random_emoji faces +``` + +The defined group names can be found with `echo ${(k)emoji_groups}`. + +To list all available emoji with their names, use: +``` +$> display_emoji +$> display_emoji faces +$> display_emoji people +``` + +To use emoji in a prompt: +``` +PROMPT="$emoji[penguin] > "" +PROMPT='$(random_emoji fruits) > ' +surfer=$emoji[surfer] +PROMPT="$surfer > " +``` + +## Technical Details + +The emoji names and codes are sourced from Unicode Technical Report \#51, which provides information on emoji support in Unicode. It can be found at https://www.unicode.org/reports/tr51/index.html. + +The group definitions are added by this OMZ plugin. They are not based on external definitions. + +The values in the `$emoji*` maps are the emoji characters themselves, not escape sequences or other forms that require interpretation. They can be used in any context and do not require escape sequence support from commands like `echo` or `print`. + +The emoji in the main `$emoji` map are standalone character sequences which can all be output on their own, without worrying about combining characters. The values may actually be multi-code-point sequences, instead of a single code point, and may include combining characters in those sequences. But they're arranged so their effects do not extend beyond that sequence. + +The exception to this is the skin tone / hair style variation selectors. These are included in the main `$emoji` map because they can be displayed on their own, as well as used as combining characters. (If they follow a character that is not one of the emoji characters they combine with, they are displayed as color swatches.) + + +## Experimental Features + +This defines some additional variables and functions, but these are experimental and subject to change at any time. You shouldn't rely on them being available. They're mostly for the use of emoji plugin developers to help decide what to include in future revisions. + +Variables: + +Variable | Description +----------------- | -------------------------------- + $emoji_skintone | Skin tone modifiers (from Unicode 8.0) + + +#### Skin Tone Variation Selection + +This includes experimental support for the skin tone Variation Selectors introduced with Unicode 8.0, which let you select different skin tones for emoji involving humans. + +NOTE: This really is experimental. The skin tone selectors are a relatively new feature and may not be supported by all systems. And the support in this plugin is a work in progress. It may not work in all places. In fact, I haven't gotten it to work anywhere yet. -apjanke + +The "variation selectors" are combining characters which change the appearance of the preceding character. A variation selector character can be output immediately following a human emoji to change its skin tone color. You can also output a variation selector on its own to display a color swatch of that skin tone. + +The `$emoji_skintone` associative array maps skin tone IDs to the variation selector characters. To use one, output it immediately following a smiley or other human emoji. + +``` +echo $emoji[waving_hand]$emoji_skintone[5] +``` + +Note that `$emoji_skintone` is an associative array, and its keys are the *names* of "Fitzpatrick Skin Type" groups, not linear indexes into a normal array. The names are `1_2`, `3`, `4`, `5`, and `6`. (Types 1 and 2 are combined into a single color.) See the [Diversity section in Unicode TR 51](https://www.unicode.org/reports/tr51/index.html#Diversity) for details. + +#### Gemoji support + +The [gemoji project](https://github.com/github/gemoji) seems to be the de facto main source for short names and other emoji-related metadata that isn't included in the official Unicode reports. So, our list of emojis incorporates some of their aliases to make your life more convenient: + +``` +echo $emoji[grinning_face_with_smiling_eyes] +echo $emoji[smile] +``` + +These two commands yield the same emoji (😄). The first name is the official one, in the Unicode reference, and the second one is the alias that was in Gemoji's database. + +## TODO + +These are things that could be enhanced in future revisions of the plugin. + +* Incorporate CLDR data for ordering and groupings +* Short :bracket: style names (from gemoji) +* ZWJ combining function? \ No newline at end of file diff --git a/zsh/.oh-my-zsh/plugins/emoji/emoji-char-definitions.zsh b/zsh/.oh-my-zsh/plugins/emoji/emoji-char-definitions.zsh new file mode 100644 index 0000000..47937c7 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emoji/emoji-char-definitions.zsh @@ -0,0 +1,7274 @@ + +# emoji-char-definitions.zsh - Emoji definitions for oh-my-zsh emoji plugin +# +# This file is auto-generated by update_emoji.py. Do not edit it manually. +# +# This contains the definition for: +# $emoji - which maps character names to Unicode characters +# $emoji_flags - maps country names to Unicode flag characters using region +# indicators +# $emoji_mod - maps modifier components to Unicode characters +# $emoji_groups - a single associative array to avoid cluttering up the +# global namespace, and to allow adding additional group +# definitions at run time. The keys are the group names, and +# the values are whitespace-separated lists of emoji +# character names. + +# Main emoji +typeset -gAH emoji +# National flags +typeset -gAH emoji_flags +# Combining modifiers +typeset -gAH emoji_mod +# Emoji groups +typeset -gAH emoji_groups +emoji[grinning_face]=$'\U1F600' +emoji[grinning]=$'\U1F600' +emoji[grinning_face_with_big_eyes]=$'\U1F603' +emoji[smiley]=$'\U1F603' +emoji[grinning_face_with_smiling_eyes]=$'\U1F604' +emoji[smile]=$'\U1F604' +emoji[beaming_face_with_smiling_eyes]=$'\U1F601' +emoji[grin]=$'\U1F601' +emoji[grinning_squinting_face]=$'\U1F606' +emoji[laughing]=$'\U1F606' +emoji[satisfied]=$'\U1F606' +emoji[grinning_face_with_sweat]=$'\U1F605' +emoji[sweat_smile]=$'\U1F605' +emoji[rolling_on_the_floor_laughing]=$'\U1F923' +emoji[rofl]=$'\U1F923' +emoji[face_with_tears_of_joy]=$'\U1F602' +emoji[joy]=$'\U1F602' +emoji[slightly_smiling_face]=$'\U1F642' +emoji[upside_down_face]=$'\U1F643' +emoji[winking_face]=$'\U1F609' +emoji[wink]=$'\U1F609' +emoji[smiling_face_with_smiling_eyes]=$'\U1F60A' +emoji[blush]=$'\U1F60A' +emoji[smiling_face_with_halo]=$'\U1F607' +emoji[innocent]=$'\U1F607' +emoji[smiling_face_with_hearts]=$'\U1F970' +emoji[smiling_face_with_three_hearts]=$'\U1F970' +emoji[smiling_face_with_heart_eyes]=$'\U1F60D' +emoji[heart_eyes]=$'\U1F60D' +emoji[star_struck]=$'\U1F929' +emoji[face_blowing_a_kiss]=$'\U1F618' +emoji[kissing_heart]=$'\U1F618' +emoji[kissing_face]=$'\U1F617' +emoji[kissing]=$'\U1F617' +emoji[smiling_face]=$'\U263A\UFE0F' +emoji[relaxed]=$'\U263A\UFE0F' +emoji[smiling_face_unqualified]=$'\U263A' +emoji[kissing_face_with_closed_eyes]=$'\U1F61A' +emoji[kissing_closed_eyes]=$'\U1F61A' +emoji[kissing_face_with_smiling_eyes]=$'\U1F619' +emoji[kissing_smiling_eyes]=$'\U1F619' +emoji[face_savoring_food]=$'\U1F60B' +emoji[yum]=$'\U1F60B' +emoji[face_with_tongue]=$'\U1F61B' +emoji[stuck_out_tongue]=$'\U1F61B' +emoji[winking_face_with_tongue]=$'\U1F61C' +emoji[stuck_out_tongue_winking_eye]=$'\U1F61C' +emoji[zany_face]=$'\U1F92A' +emoji[squinting_face_with_tongue]=$'\U1F61D' +emoji[stuck_out_tongue_closed_eyes]=$'\U1F61D' +emoji[money_mouth_face]=$'\U1F911' +emoji[hugging_face]=$'\U1F917' +emoji[hugs]=$'\U1F917' +emoji[face_with_hand_over_mouth]=$'\U1F92D' +emoji[hand_over_mouth]=$'\U1F92D' +emoji[shushing_face]=$'\U1F92B' +emoji[thinking_face]=$'\U1F914' +emoji[thinking]=$'\U1F914' +emoji[zipper_mouth_face]=$'\U1F910' +emoji[face_with_raised_eyebrow]=$'\U1F928' +emoji[raised_eyebrow]=$'\U1F928' +emoji[neutral_face]=$'\U1F610' +emoji[expressionless_face]=$'\U1F611' +emoji[expressionless]=$'\U1F611' +emoji[face_without_mouth]=$'\U1F636' +emoji[no_mouth]=$'\U1F636' +emoji[smirking_face]=$'\U1F60F' +emoji[smirk]=$'\U1F60F' +emoji[unamused_face]=$'\U1F612' +emoji[unamused]=$'\U1F612' +emoji[face_with_rolling_eyes]=$'\U1F644' +emoji[roll_eyes]=$'\U1F644' +emoji[grimacing_face]=$'\U1F62C' +emoji[grimacing]=$'\U1F62C' +emoji[lying_face]=$'\U1F925' +emoji[relieved_face]=$'\U1F60C' +emoji[relieved]=$'\U1F60C' +emoji[pensive_face]=$'\U1F614' +emoji[pensive]=$'\U1F614' +emoji[sleepy_face]=$'\U1F62A' +emoji[sleepy]=$'\U1F62A' +emoji[drooling_face]=$'\U1F924' +emoji[sleeping_face]=$'\U1F634' +emoji[sleeping]=$'\U1F634' +emoji[face_with_medical_mask]=$'\U1F637' +emoji[mask]=$'\U1F637' +emoji[face_with_thermometer]=$'\U1F912' +emoji[face_with_head_bandage]=$'\U1F915' +emoji[nauseated_face]=$'\U1F922' +emoji[face_vomiting]=$'\U1F92E' +emoji[vomiting_face]=$'\U1F92E' +emoji[sneezing_face]=$'\U1F927' +emoji[hot_face]=$'\U1F975' +emoji[cold_face]=$'\U1F976' +emoji[woozy_face]=$'\U1F974' +emoji[dizzy_face]=$'\U1F635' +emoji[exploding_head]=$'\U1F92F' +emoji[cowboy_hat_face]=$'\U1F920' +emoji[partying_face]=$'\U1F973' +emoji[smiling_face_with_sunglasses]=$'\U1F60E' +emoji[nerd_face]=$'\U1F913' +emoji[face_with_monocle]=$'\U1F9D0' +emoji[monocle_face]=$'\U1F9D0' +emoji[confused_face]=$'\U1F615' +emoji[confused]=$'\U1F615' +emoji[worried_face]=$'\U1F61F' +emoji[worried]=$'\U1F61F' +emoji[slightly_frowning_face]=$'\U1F641' +emoji[slightly_frowning_face_1]=$'\U2639\UFE0F' +emoji[frowning_face_unqualified]=$'\U2639' +emoji[frowning_face]=$'\U2639' +emoji[face_with_open_mouth]=$'\U1F62E' +emoji[open_mouth]=$'\U1F62E' +emoji[hushed_face]=$'\U1F62F' +emoji[hushed]=$'\U1F62F' +emoji[astonished_face]=$'\U1F632' +emoji[astonished]=$'\U1F632' +emoji[flushed_face]=$'\U1F633' +emoji[flushed]=$'\U1F633' +emoji[pleading_face]=$'\U1F97A' +emoji[frowning_face_with_open_mouth]=$'\U1F626' +emoji[frowning]=$'\U1F626' +emoji[anguished_face]=$'\U1F627' +emoji[anguished]=$'\U1F627' +emoji[fearful_face]=$'\U1F628' +emoji[fearful]=$'\U1F628' +emoji[anxious_face_with_sweat]=$'\U1F630' +emoji[cold_sweat]=$'\U1F630' +emoji[sad_but_relieved_face]=$'\U1F625' +emoji[disappointed_relieved]=$'\U1F625' +emoji[crying_face]=$'\U1F622' +emoji[cry]=$'\U1F622' +emoji[loudly_crying_face]=$'\U1F62D' +emoji[sob]=$'\U1F62D' +emoji[face_screaming_in_fear]=$'\U1F631' +emoji[scream]=$'\U1F631' +emoji[confounded_face]=$'\U1F616' +emoji[confounded]=$'\U1F616' +emoji[persevering_face]=$'\U1F623' +emoji[persevere]=$'\U1F623' +emoji[disappointed_face]=$'\U1F61E' +emoji[disappointed]=$'\U1F61E' +emoji[downcast_face_with_sweat]=$'\U1F613' +emoji[sweat]=$'\U1F613' +emoji[weary_face]=$'\U1F629' +emoji[weary]=$'\U1F629' +emoji[tired_face]=$'\U1F62B' +emoji[yawning_face]=$'\U1F971' +emoji[face_with_steam_from_nose]=$'\U1F624' +emoji[triumph]=$'\U1F624' +emoji[pouting_face]=$'\U1F621' +emoji[rage]=$'\U1F621' +emoji[pout]=$'\U1F621' +emoji[angry_face]=$'\U1F620' +emoji[angry]=$'\U1F620' +emoji[face_with_symbols_on_mouth]=$'\U1F92C' +emoji[cursing_face]=$'\U1F92C' +emoji[smiling_face_with_horns]=$'\U1F608' +emoji[smiling_imp]=$'\U1F608' +emoji[angry_face_with_horns]=$'\U1F47F' +emoji[imp]=$'\U1F47F' +emoji[skull]=$'\U1F480' +emoji[skull_and_crossbones]=$'\U2620\UFE0F' +emoji[skull_and_crossbones_unqualified]=$'\U2620' +emoji[pile_of_poo]=$'\U1F4A9' +emoji[hankey]=$'\U1F4A9' +emoji[poop]=$'\U1F4A9' +emoji[shit]=$'\U1F4A9' +emoji[clown_face]=$'\U1F921' +emoji[ogre]=$'\U1F479' +emoji[japanese_ogre]=$'\U1F479' +emoji[goblin]=$'\U1F47A' +emoji[japanese_goblin]=$'\U1F47A' +emoji[ghost]=$'\U1F47B' +emoji[alien]=$'\U1F47D' +emoji[alien_monster]=$'\U1F47E' +emoji[space_invader]=$'\U1F47E' +emoji[robot]=$'\U1F916' +emoji[grinning_cat]=$'\U1F63A' +emoji[smiley_cat]=$'\U1F63A' +emoji[grinning_cat_with_smiling_eyes]=$'\U1F638' +emoji[smile_cat]=$'\U1F638' +emoji[cat_with_tears_of_joy]=$'\U1F639' +emoji[joy_cat]=$'\U1F639' +emoji[smiling_cat_with_heart_eyes]=$'\U1F63B' +emoji[heart_eyes_cat]=$'\U1F63B' +emoji[cat_with_wry_smile]=$'\U1F63C' +emoji[smirk_cat]=$'\U1F63C' +emoji[kissing_cat]=$'\U1F63D' +emoji[weary_cat]=$'\U1F640' +emoji[scream_cat]=$'\U1F640' +emoji[crying_cat]=$'\U1F63F' +emoji[crying_cat_face]=$'\U1F63F' +emoji[pouting_cat]=$'\U1F63E' +emoji[see_no_evil_monkey]=$'\U1F648' +emoji[see_no_evil]=$'\U1F648' +emoji[hear_no_evil_monkey]=$'\U1F649' +emoji[hear_no_evil]=$'\U1F649' +emoji[speak_no_evil_monkey]=$'\U1F64A' +emoji[speak_no_evil]=$'\U1F64A' +emoji[kiss_mark]=$'\U1F48B' +emoji[love_letter]=$'\U1F48C' +emoji[heart_with_arrow]=$'\U1F498' +emoji[cupid]=$'\U1F498' +emoji[heart_with_ribbon]=$'\U1F49D' +emoji[gift_heart]=$'\U1F49D' +emoji[sparkling_heart]=$'\U1F496' +emoji[growing_heart]=$'\U1F497' +emoji[heartpulse]=$'\U1F497' +emoji[beating_heart]=$'\U1F493' +emoji[heartbeat]=$'\U1F493' +emoji[revolving_hearts]=$'\U1F49E' +emoji[two_hearts]=$'\U1F495' +emoji[heart_decoration]=$'\U1F49F' +emoji[heart_exclamation]=$'\U2763\UFE0F' +emoji[heavy_heart_exclamation]=$'\U2763\UFE0F' +emoji[heart_exclamation_unqualified]=$'\U2763' +emoji[broken_heart]=$'\U1F494' +emoji[red_heart]=$'\U2764\UFE0F' +emoji[heart]=$'\U2764\UFE0F' +emoji[red_heart_unqualified]=$'\U2764' +emoji[orange_heart]=$'\U1F9E1' +emoji[yellow_heart]=$'\U1F49B' +emoji[green_heart]=$'\U1F49A' +emoji[blue_heart]=$'\U1F499' +emoji[purple_heart]=$'\U1F49C' +emoji[brown_heart]=$'\U1F90E' +emoji[black_heart]=$'\U1F5A4' +emoji[white_heart]=$'\U1F90D' +emoji[hundred_points]=$'\U1F4AF' +emoji[100]=$'\U1F4AF' +emoji[anger_symbol]=$'\U1F4A2' +emoji[anger]=$'\U1F4A2' +emoji[collision]=$'\U1F4A5' +emoji[boom]=$'\U1F4A5' +emoji[dizzy]=$'\U1F4AB' +emoji[sweat_droplets]=$'\U1F4A6' +emoji[sweat_drops]=$'\U1F4A6' +emoji[dashing_away]=$'\U1F4A8' +emoji[dash]=$'\U1F4A8' +emoji[hole]=$'\U1F573\UFE0F' +emoji[hole_unqualified]=$'\U1F573' +emoji[bomb]=$'\U1F4A3' +emoji[speech_balloon]=$'\U1F4AC' +emoji[eye_in_speech_bubble]=$'\U1F441\UFE0F\U200D\U1F5E8\UFE0F' +emoji[eye_speech_bubble]=$'\U1F441\UFE0F\U200D\U1F5E8\UFE0F' +emoji[eye_in_speech_bubble_unqualified]=$'\U1F441\U200D\U1F5E8\UFE0F' +emoji[eye_in_speech_bubble_unqualified_1]=$'\U1F441\UFE0F\U200D\U1F5E8' +emoji[eye_in_speech_bubble_unqualified_2]=$'\U1F441\U200D\U1F5E8' +emoji[left_speech_bubble]=$'\U1F5E8\UFE0F' +emoji[left_speech_bubble_unqualified]=$'\U1F5E8' +emoji[right_anger_bubble]=$'\U1F5EF\UFE0F' +emoji[right_anger_bubble_unqualified]=$'\U1F5EF' +emoji[thought_balloon]=$'\U1F4AD' +emoji[zzz]=$'\U1F4A4' +emoji[waving_hand]=$'\U1F44B' +emoji[wave]=$'\U1F44B' +emoji[waving_hand_light_skin_tone]=$'\U1F44B\U1F3FB' +emoji[waving_hand_medium_light_skin_tone]=$'\U1F44B\U1F3FC' +emoji[waving_hand_medium_skin_tone]=$'\U1F44B\U1F3FD' +emoji[waving_hand_medium_dark_skin_tone]=$'\U1F44B\U1F3FE' +emoji[waving_hand_dark_skin_tone]=$'\U1F44B\U1F3FF' +emoji[raised_back_of_hand]=$'\U1F91A' +emoji[raised_back_of_hand_light_skin_tone]=$'\U1F91A\U1F3FB' +emoji[raised_back_of_hand_medium_light_skin_tone]=$'\U1F91A\U1F3FC' +emoji[raised_back_of_hand_medium_skin_tone]=$'\U1F91A\U1F3FD' +emoji[raised_back_of_hand_medium_dark_skin_tone]=$'\U1F91A\U1F3FE' +emoji[raised_back_of_hand_dark_skin_tone]=$'\U1F91A\U1F3FF' +emoji[hand_with_fingers_splayed]=$'\U1F590\UFE0F' +emoji[hand_with_fingers_splayed_unqualified]=$'\U1F590' +emoji[raised_hand_with_fingers_splayed]=$'\U1F590' +emoji[hand_with_fingers_splayed_light_skin_tone]=$'\U1F590\U1F3FB' +emoji[hand_with_fingers_splayed_medium_light_skin_tone]=$'\U1F590\U1F3FC' +emoji[hand_with_fingers_splayed_medium_skin_tone]=$'\U1F590\U1F3FD' +emoji[hand_with_fingers_splayed_medium_dark_skin_tone]=$'\U1F590\U1F3FE' +emoji[hand_with_fingers_splayed_dark_skin_tone]=$'\U1F590\U1F3FF' +emoji[raised_hand]=$'\U270B' +emoji[hand]=$'\U270B' +emoji[raised_hand_light_skin_tone]=$'\U270B\U1F3FB' +emoji[raised_hand_medium_light_skin_tone]=$'\U270B\U1F3FC' +emoji[raised_hand_medium_skin_tone]=$'\U270B\U1F3FD' +emoji[raised_hand_medium_dark_skin_tone]=$'\U270B\U1F3FE' +emoji[raised_hand_dark_skin_tone]=$'\U270B\U1F3FF' +emoji[vulcan_salute]=$'\U1F596' +emoji[vulcan_salute_light_skin_tone]=$'\U1F596\U1F3FB' +emoji[vulcan_salute_medium_light_skin_tone]=$'\U1F596\U1F3FC' +emoji[vulcan_salute_medium_skin_tone]=$'\U1F596\U1F3FD' +emoji[vulcan_salute_medium_dark_skin_tone]=$'\U1F596\U1F3FE' +emoji[vulcan_salute_dark_skin_tone]=$'\U1F596\U1F3FF' +emoji[OK_hand]=$'\U1F44C' +emoji[ok_hand]=$'\U1F44C' +emoji[OK_hand_light_skin_tone]=$'\U1F44C\U1F3FB' +emoji[OK_hand_medium_light_skin_tone]=$'\U1F44C\U1F3FC' +emoji[OK_hand_medium_skin_tone]=$'\U1F44C\U1F3FD' +emoji[OK_hand_medium_dark_skin_tone]=$'\U1F44C\U1F3FE' +emoji[OK_hand_dark_skin_tone]=$'\U1F44C\U1F3FF' +emoji[pinching_hand]=$'\U1F90F' +emoji[pinching_hand_light_skin_tone]=$'\U1F90F\U1F3FB' +emoji[pinching_hand_medium_light_skin_tone]=$'\U1F90F\U1F3FC' +emoji[pinching_hand_medium_skin_tone]=$'\U1F90F\U1F3FD' +emoji[pinching_hand_medium_dark_skin_tone]=$'\U1F90F\U1F3FE' +emoji[pinching_hand_dark_skin_tone]=$'\U1F90F\U1F3FF' +emoji[victory_hand]=$'\U270C\UFE0F' +emoji[v]=$'\U270C\UFE0F' +emoji[victory_hand_unqualified]=$'\U270C' +emoji[victory_hand_light_skin_tone]=$'\U270C\U1F3FB' +emoji[victory_hand_medium_light_skin_tone]=$'\U270C\U1F3FC' +emoji[victory_hand_medium_skin_tone]=$'\U270C\U1F3FD' +emoji[victory_hand_medium_dark_skin_tone]=$'\U270C\U1F3FE' +emoji[victory_hand_dark_skin_tone]=$'\U270C\U1F3FF' +emoji[crossed_fingers]=$'\U1F91E' +emoji[crossed_fingers_light_skin_tone]=$'\U1F91E\U1F3FB' +emoji[crossed_fingers_medium_light_skin_tone]=$'\U1F91E\U1F3FC' +emoji[crossed_fingers_medium_skin_tone]=$'\U1F91E\U1F3FD' +emoji[crossed_fingers_medium_dark_skin_tone]=$'\U1F91E\U1F3FE' +emoji[crossed_fingers_dark_skin_tone]=$'\U1F91E\U1F3FF' +emoji[love_you_gesture]=$'\U1F91F' +emoji[love_you_gesture_light_skin_tone]=$'\U1F91F\U1F3FB' +emoji[love_you_gesture_medium_light_skin_tone]=$'\U1F91F\U1F3FC' +emoji[love_you_gesture_medium_skin_tone]=$'\U1F91F\U1F3FD' +emoji[love_you_gesture_medium_dark_skin_tone]=$'\U1F91F\U1F3FE' +emoji[love_you_gesture_dark_skin_tone]=$'\U1F91F\U1F3FF' +emoji[sign_of_the_horns]=$'\U1F918' +emoji[metal]=$'\U1F918' +emoji[sign_of_the_horns_light_skin_tone]=$'\U1F918\U1F3FB' +emoji[sign_of_the_horns_medium_light_skin_tone]=$'\U1F918\U1F3FC' +emoji[sign_of_the_horns_medium_skin_tone]=$'\U1F918\U1F3FD' +emoji[sign_of_the_horns_medium_dark_skin_tone]=$'\U1F918\U1F3FE' +emoji[sign_of_the_horns_dark_skin_tone]=$'\U1F918\U1F3FF' +emoji[call_me_hand]=$'\U1F919' +emoji[call_me_hand_light_skin_tone]=$'\U1F919\U1F3FB' +emoji[call_me_hand_medium_light_skin_tone]=$'\U1F919\U1F3FC' +emoji[call_me_hand_medium_skin_tone]=$'\U1F919\U1F3FD' +emoji[call_me_hand_medium_dark_skin_tone]=$'\U1F919\U1F3FE' +emoji[call_me_hand_dark_skin_tone]=$'\U1F919\U1F3FF' +emoji[backhand_index_pointing_left]=$'\U1F448' +emoji[point_left]=$'\U1F448' +emoji[backhand_index_pointing_left_light_skin_tone]=$'\U1F448\U1F3FB' +emoji[backhand_index_pointing_left_medium_light_skin_tone]=$'\U1F448\U1F3FC' +emoji[backhand_index_pointing_left_medium_skin_tone]=$'\U1F448\U1F3FD' +emoji[backhand_index_pointing_left_medium_dark_skin_tone]=$'\U1F448\U1F3FE' +emoji[backhand_index_pointing_left_dark_skin_tone]=$'\U1F448\U1F3FF' +emoji[backhand_index_pointing_right]=$'\U1F449' +emoji[point_right]=$'\U1F449' +emoji[backhand_index_pointing_right_light_skin_tone]=$'\U1F449\U1F3FB' +emoji[backhand_index_pointing_right_medium_light_skin_tone]=$'\U1F449\U1F3FC' +emoji[backhand_index_pointing_right_medium_skin_tone]=$'\U1F449\U1F3FD' +emoji[backhand_index_pointing_right_medium_dark_skin_tone]=$'\U1F449\U1F3FE' +emoji[backhand_index_pointing_right_dark_skin_tone]=$'\U1F449\U1F3FF' +emoji[backhand_index_pointing_up]=$'\U1F446' +emoji[point_up_2]=$'\U1F446' +emoji[backhand_index_pointing_up_light_skin_tone]=$'\U1F446\U1F3FB' +emoji[backhand_index_pointing_up_medium_light_skin_tone]=$'\U1F446\U1F3FC' +emoji[backhand_index_pointing_up_medium_skin_tone]=$'\U1F446\U1F3FD' +emoji[backhand_index_pointing_up_medium_dark_skin_tone]=$'\U1F446\U1F3FE' +emoji[backhand_index_pointing_up_dark_skin_tone]=$'\U1F446\U1F3FF' +emoji[middle_finger]=$'\U1F595' +emoji[fu]=$'\U1F595' +emoji[middle_finger_light_skin_tone]=$'\U1F595\U1F3FB' +emoji[middle_finger_medium_light_skin_tone]=$'\U1F595\U1F3FC' +emoji[middle_finger_medium_skin_tone]=$'\U1F595\U1F3FD' +emoji[middle_finger_medium_dark_skin_tone]=$'\U1F595\U1F3FE' +emoji[middle_finger_dark_skin_tone]=$'\U1F595\U1F3FF' +emoji[backhand_index_pointing_down]=$'\U1F447' +emoji[point_down]=$'\U1F447' +emoji[backhand_index_pointing_down_light_skin_tone]=$'\U1F447\U1F3FB' +emoji[backhand_index_pointing_down_medium_light_skin_tone]=$'\U1F447\U1F3FC' +emoji[backhand_index_pointing_down_medium_skin_tone]=$'\U1F447\U1F3FD' +emoji[backhand_index_pointing_down_medium_dark_skin_tone]=$'\U1F447\U1F3FE' +emoji[backhand_index_pointing_down_dark_skin_tone]=$'\U1F447\U1F3FF' +emoji[index_pointing_up]=$'\U261D\UFE0F' +emoji[point_up]=$'\U261D\UFE0F' +emoji[index_pointing_up_unqualified]=$'\U261D' +emoji[index_pointing_up_light_skin_tone]=$'\U261D\U1F3FB' +emoji[index_pointing_up_medium_light_skin_tone]=$'\U261D\U1F3FC' +emoji[index_pointing_up_medium_skin_tone]=$'\U261D\U1F3FD' +emoji[index_pointing_up_medium_dark_skin_tone]=$'\U261D\U1F3FE' +emoji[index_pointing_up_dark_skin_tone]=$'\U261D\U1F3FF' +emoji[thumbs_up]=$'\U1F44D' +emoji[+1]=$'\U1F44D' +emoji[thumbsup]=$'\U1F44D' +emoji[thumbs_up_light_skin_tone]=$'\U1F44D\U1F3FB' +emoji[thumbs_up_medium_light_skin_tone]=$'\U1F44D\U1F3FC' +emoji[thumbs_up_medium_skin_tone]=$'\U1F44D\U1F3FD' +emoji[thumbs_up_medium_dark_skin_tone]=$'\U1F44D\U1F3FE' +emoji[thumbs_up_dark_skin_tone]=$'\U1F44D\U1F3FF' +emoji[thumbs_down]=$'\U1F44E' +emoji[-1]=$'\U1F44E' +emoji[thumbsdown]=$'\U1F44E' +emoji[thumbs_down_light_skin_tone]=$'\U1F44E\U1F3FB' +emoji[thumbs_down_medium_light_skin_tone]=$'\U1F44E\U1F3FC' +emoji[thumbs_down_medium_skin_tone]=$'\U1F44E\U1F3FD' +emoji[thumbs_down_medium_dark_skin_tone]=$'\U1F44E\U1F3FE' +emoji[thumbs_down_dark_skin_tone]=$'\U1F44E\U1F3FF' +emoji[raised_fist]=$'\U270A' +emoji[fist_raised]=$'\U270A' +emoji[fist]=$'\U270A' +emoji[raised_fist_light_skin_tone]=$'\U270A\U1F3FB' +emoji[raised_fist_medium_light_skin_tone]=$'\U270A\U1F3FC' +emoji[raised_fist_medium_skin_tone]=$'\U270A\U1F3FD' +emoji[raised_fist_medium_dark_skin_tone]=$'\U270A\U1F3FE' +emoji[raised_fist_dark_skin_tone]=$'\U270A\U1F3FF' +emoji[oncoming_fist]=$'\U1F44A' +emoji[fist_oncoming]=$'\U1F44A' +emoji[facepunch]=$'\U1F44A' +emoji[punch]=$'\U1F44A' +emoji[oncoming_fist_light_skin_tone]=$'\U1F44A\U1F3FB' +emoji[oncoming_fist_medium_light_skin_tone]=$'\U1F44A\U1F3FC' +emoji[oncoming_fist_medium_skin_tone]=$'\U1F44A\U1F3FD' +emoji[oncoming_fist_medium_dark_skin_tone]=$'\U1F44A\U1F3FE' +emoji[oncoming_fist_dark_skin_tone]=$'\U1F44A\U1F3FF' +emoji[left_facing_fist]=$'\U1F91B' +emoji[fist_left]=$'\U1F91B' +emoji[left_facing_fist_light_skin_tone]=$'\U1F91B\U1F3FB' +emoji[left_facing_fist_medium_light_skin_tone]=$'\U1F91B\U1F3FC' +emoji[left_facing_fist_medium_skin_tone]=$'\U1F91B\U1F3FD' +emoji[left_facing_fist_medium_dark_skin_tone]=$'\U1F91B\U1F3FE' +emoji[left_facing_fist_dark_skin_tone]=$'\U1F91B\U1F3FF' +emoji[right_facing_fist]=$'\U1F91C' +emoji[fist_right]=$'\U1F91C' +emoji[right_facing_fist_light_skin_tone]=$'\U1F91C\U1F3FB' +emoji[right_facing_fist_medium_light_skin_tone]=$'\U1F91C\U1F3FC' +emoji[right_facing_fist_medium_skin_tone]=$'\U1F91C\U1F3FD' +emoji[right_facing_fist_medium_dark_skin_tone]=$'\U1F91C\U1F3FE' +emoji[right_facing_fist_dark_skin_tone]=$'\U1F91C\U1F3FF' +emoji[clapping_hands]=$'\U1F44F' +emoji[clap]=$'\U1F44F' +emoji[clapping_hands_light_skin_tone]=$'\U1F44F\U1F3FB' +emoji[clapping_hands_medium_light_skin_tone]=$'\U1F44F\U1F3FC' +emoji[clapping_hands_medium_skin_tone]=$'\U1F44F\U1F3FD' +emoji[clapping_hands_medium_dark_skin_tone]=$'\U1F44F\U1F3FE' +emoji[clapping_hands_dark_skin_tone]=$'\U1F44F\U1F3FF' +emoji[raising_hands]=$'\U1F64C' +emoji[raised_hands]=$'\U1F64C' +emoji[raising_hands_light_skin_tone]=$'\U1F64C\U1F3FB' +emoji[raising_hands_medium_light_skin_tone]=$'\U1F64C\U1F3FC' +emoji[raising_hands_medium_skin_tone]=$'\U1F64C\U1F3FD' +emoji[raising_hands_medium_dark_skin_tone]=$'\U1F64C\U1F3FE' +emoji[raising_hands_dark_skin_tone]=$'\U1F64C\U1F3FF' +emoji[open_hands]=$'\U1F450' +emoji[open_hands_light_skin_tone]=$'\U1F450\U1F3FB' +emoji[open_hands_medium_light_skin_tone]=$'\U1F450\U1F3FC' +emoji[open_hands_medium_skin_tone]=$'\U1F450\U1F3FD' +emoji[open_hands_medium_dark_skin_tone]=$'\U1F450\U1F3FE' +emoji[open_hands_dark_skin_tone]=$'\U1F450\U1F3FF' +emoji[palms_up_together]=$'\U1F932' +emoji[palms_up_together_light_skin_tone]=$'\U1F932\U1F3FB' +emoji[palms_up_together_medium_light_skin_tone]=$'\U1F932\U1F3FC' +emoji[palms_up_together_medium_skin_tone]=$'\U1F932\U1F3FD' +emoji[palms_up_together_medium_dark_skin_tone]=$'\U1F932\U1F3FE' +emoji[palms_up_together_dark_skin_tone]=$'\U1F932\U1F3FF' +emoji[handshake]=$'\U1F91D' +emoji[folded_hands]=$'\U1F64F' +emoji[pray]=$'\U1F64F' +emoji[folded_hands_light_skin_tone]=$'\U1F64F\U1F3FB' +emoji[folded_hands_medium_light_skin_tone]=$'\U1F64F\U1F3FC' +emoji[folded_hands_medium_skin_tone]=$'\U1F64F\U1F3FD' +emoji[folded_hands_medium_dark_skin_tone]=$'\U1F64F\U1F3FE' +emoji[folded_hands_dark_skin_tone]=$'\U1F64F\U1F3FF' +emoji[writing_hand]=$'\U270D\UFE0F' +emoji[writing_hand_unqualified]=$'\U270D' +emoji[writing_hand_light_skin_tone]=$'\U270D\U1F3FB' +emoji[writing_hand_medium_light_skin_tone]=$'\U270D\U1F3FC' +emoji[writing_hand_medium_skin_tone]=$'\U270D\U1F3FD' +emoji[writing_hand_medium_dark_skin_tone]=$'\U270D\U1F3FE' +emoji[writing_hand_dark_skin_tone]=$'\U270D\U1F3FF' +emoji[nail_polish]=$'\U1F485' +emoji[nail_care]=$'\U1F485' +emoji[nail_polish_light_skin_tone]=$'\U1F485\U1F3FB' +emoji[nail_polish_medium_light_skin_tone]=$'\U1F485\U1F3FC' +emoji[nail_polish_medium_skin_tone]=$'\U1F485\U1F3FD' +emoji[nail_polish_medium_dark_skin_tone]=$'\U1F485\U1F3FE' +emoji[nail_polish_dark_skin_tone]=$'\U1F485\U1F3FF' +emoji[selfie]=$'\U1F933' +emoji[selfie_light_skin_tone]=$'\U1F933\U1F3FB' +emoji[selfie_medium_light_skin_tone]=$'\U1F933\U1F3FC' +emoji[selfie_medium_skin_tone]=$'\U1F933\U1F3FD' +emoji[selfie_medium_dark_skin_tone]=$'\U1F933\U1F3FE' +emoji[selfie_dark_skin_tone]=$'\U1F933\U1F3FF' +emoji[flexed_biceps]=$'\U1F4AA' +emoji[muscle]=$'\U1F4AA' +emoji[flexed_biceps_light_skin_tone]=$'\U1F4AA\U1F3FB' +emoji[flexed_biceps_medium_light_skin_tone]=$'\U1F4AA\U1F3FC' +emoji[flexed_biceps_medium_skin_tone]=$'\U1F4AA\U1F3FD' +emoji[flexed_biceps_medium_dark_skin_tone]=$'\U1F4AA\U1F3FE' +emoji[flexed_biceps_dark_skin_tone]=$'\U1F4AA\U1F3FF' +emoji[mechanical_arm]=$'\U1F9BE' +emoji[mechanical_leg]=$'\U1F9BF' +emoji[mechanical_leg_1]=$'\U1F9B5' +emoji[leg]=$'\U1F9B5' +emoji[leg_light_skin_tone]=$'\U1F9B5\U1F3FB' +emoji[leg_medium_light_skin_tone]=$'\U1F9B5\U1F3FC' +emoji[leg_medium_skin_tone]=$'\U1F9B5\U1F3FD' +emoji[leg_medium_dark_skin_tone]=$'\U1F9B5\U1F3FE' +emoji[leg_dark_skin_tone]=$'\U1F9B5\U1F3FF' +emoji[foot]=$'\U1F9B6' +emoji[foot_light_skin_tone]=$'\U1F9B6\U1F3FB' +emoji[foot_medium_light_skin_tone]=$'\U1F9B6\U1F3FC' +emoji[foot_medium_skin_tone]=$'\U1F9B6\U1F3FD' +emoji[foot_medium_dark_skin_tone]=$'\U1F9B6\U1F3FE' +emoji[foot_dark_skin_tone]=$'\U1F9B6\U1F3FF' +emoji[ear]=$'\U1F442' +emoji[ear_light_skin_tone]=$'\U1F442\U1F3FB' +emoji[ear_medium_light_skin_tone]=$'\U1F442\U1F3FC' +emoji[ear_medium_skin_tone]=$'\U1F442\U1F3FD' +emoji[ear_medium_dark_skin_tone]=$'\U1F442\U1F3FE' +emoji[ear_dark_skin_tone]=$'\U1F442\U1F3FF' +emoji[ear_with_hearing_aid]=$'\U1F9BB' +emoji[ear_with_hearing_aid_light_skin_tone]=$'\U1F9BB\U1F3FB' +emoji[ear_with_hearing_aid_medium_light_skin_tone]=$'\U1F9BB\U1F3FC' +emoji[ear_with_hearing_aid_medium_skin_tone]=$'\U1F9BB\U1F3FD' +emoji[ear_with_hearing_aid_medium_dark_skin_tone]=$'\U1F9BB\U1F3FE' +emoji[ear_with_hearing_aid_dark_skin_tone]=$'\U1F9BB\U1F3FF' +emoji[nose]=$'\U1F443' +emoji[nose_light_skin_tone]=$'\U1F443\U1F3FB' +emoji[nose_medium_light_skin_tone]=$'\U1F443\U1F3FC' +emoji[nose_medium_skin_tone]=$'\U1F443\U1F3FD' +emoji[nose_medium_dark_skin_tone]=$'\U1F443\U1F3FE' +emoji[nose_dark_skin_tone]=$'\U1F443\U1F3FF' +emoji[brain]=$'\U1F9E0' +emoji[tooth]=$'\U1F9B7' +emoji[bone]=$'\U1F9B4' +emoji[eyes]=$'\U1F440' +emoji[eyes_1]=$'\U1F441\UFE0F' +emoji[eye_unqualified]=$'\U1F441' +emoji[eye]=$'\U1F441' +emoji[tongue]=$'\U1F445' +emoji[mouth]=$'\U1F444' +emoji[lips]=$'\U1F444' +emoji[baby]=$'\U1F476' +emoji[baby_light_skin_tone]=$'\U1F476\U1F3FB' +emoji[baby_medium_light_skin_tone]=$'\U1F476\U1F3FC' +emoji[baby_medium_skin_tone]=$'\U1F476\U1F3FD' +emoji[baby_medium_dark_skin_tone]=$'\U1F476\U1F3FE' +emoji[baby_dark_skin_tone]=$'\U1F476\U1F3FF' +emoji[child]=$'\U1F9D2' +emoji[child_light_skin_tone]=$'\U1F9D2\U1F3FB' +emoji[child_medium_light_skin_tone]=$'\U1F9D2\U1F3FC' +emoji[child_medium_skin_tone]=$'\U1F9D2\U1F3FD' +emoji[child_medium_dark_skin_tone]=$'\U1F9D2\U1F3FE' +emoji[child_dark_skin_tone]=$'\U1F9D2\U1F3FF' +emoji[boy]=$'\U1F466' +emoji[boy_light_skin_tone]=$'\U1F466\U1F3FB' +emoji[boy_medium_light_skin_tone]=$'\U1F466\U1F3FC' +emoji[boy_medium_skin_tone]=$'\U1F466\U1F3FD' +emoji[boy_medium_dark_skin_tone]=$'\U1F466\U1F3FE' +emoji[boy_dark_skin_tone]=$'\U1F466\U1F3FF' +emoji[girl]=$'\U1F467' +emoji[girl_light_skin_tone]=$'\U1F467\U1F3FB' +emoji[girl_medium_light_skin_tone]=$'\U1F467\U1F3FC' +emoji[girl_medium_skin_tone]=$'\U1F467\U1F3FD' +emoji[girl_medium_dark_skin_tone]=$'\U1F467\U1F3FE' +emoji[girl_dark_skin_tone]=$'\U1F467\U1F3FF' +emoji[person]=$'\U1F9D1' +emoji[adult]=$'\U1F9D1' +emoji[person_light_skin_tone]=$'\U1F9D1\U1F3FB' +emoji[person_medium_light_skin_tone]=$'\U1F9D1\U1F3FC' +emoji[person_medium_skin_tone]=$'\U1F9D1\U1F3FD' +emoji[person_medium_dark_skin_tone]=$'\U1F9D1\U1F3FE' +emoji[person_dark_skin_tone]=$'\U1F9D1\U1F3FF' +emoji[person_blond_hair]=$'\U1F471' +emoji[blond_haired_person]=$'\U1F471' +emoji[person_light_skin_tone_blond_hair]=$'\U1F471\U1F3FB' +emoji[person_medium_light_skin_tone_blond_hair]=$'\U1F471\U1F3FC' +emoji[person_medium_skin_tone_blond_hair]=$'\U1F471\U1F3FD' +emoji[person_medium_dark_skin_tone_blond_hair]=$'\U1F471\U1F3FE' +emoji[person_dark_skin_tone_blond_hair]=$'\U1F471\U1F3FF' +emoji[man]=$'\U1F468' +emoji[man_light_skin_tone]=$'\U1F468\U1F3FB' +emoji[man_medium_light_skin_tone]=$'\U1F468\U1F3FC' +emoji[man_medium_skin_tone]=$'\U1F468\U1F3FD' +emoji[man_medium_dark_skin_tone]=$'\U1F468\U1F3FE' +emoji[man_dark_skin_tone]=$'\U1F468\U1F3FF' +emoji[man_beard]=$'\U1F9D4' +emoji[bearded_person]=$'\U1F9D4' +emoji[man_light_skin_tone_beard]=$'\U1F9D4\U1F3FB' +emoji[man_medium_light_skin_tone_beard]=$'\U1F9D4\U1F3FC' +emoji[man_medium_skin_tone_beard]=$'\U1F9D4\U1F3FD' +emoji[man_medium_dark_skin_tone_beard]=$'\U1F9D4\U1F3FE' +emoji[man_dark_skin_tone_beard]=$'\U1F9D4\U1F3FF' +emoji[man_blond_hair]=$'\U1F471\U200D\U2642\UFE0F' +emoji[man_blond_hair_minimally]=$'\U1F471\U200D\U2642' +emoji[blond_haired_man]=$'\U1F471\U200D\U2642' +emoji[man_light_skin_tone_blond_hair]=$'\U1F471\U1F3FB\U200D\U2642\UFE0F' +emoji[man_light_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FB\U200D\U2642' +emoji[man_medium_light_skin_tone_blond_hair]=$'\U1F471\U1F3FC\U200D\U2642\UFE0F' +emoji[man_medium_light_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FC\U200D\U2642' +emoji[man_medium_skin_tone_blond_hair]=$'\U1F471\U1F3FD\U200D\U2642\UFE0F' +emoji[man_medium_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FD\U200D\U2642' +emoji[man_medium_dark_skin_tone_blond_hair]=$'\U1F471\U1F3FE\U200D\U2642\UFE0F' +emoji[man_medium_dark_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FE\U200D\U2642' +emoji[man_dark_skin_tone_blond_hair]=$'\U1F471\U1F3FF\U200D\U2642\UFE0F' +emoji[man_dark_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FF\U200D\U2642' +emoji[man_red_hair]=$'\U1F468\U200D\U1F9B0' +emoji[red_haired_man]=$'\U1F468\U200D\U1F9B0' +emoji[man_light_skin_tone_red_hair]=$'\U1F468\U1F3FB\U200D\U1F9B0' +emoji[man_medium_light_skin_tone_red_hair]=$'\U1F468\U1F3FC\U200D\U1F9B0' +emoji[man_medium_skin_tone_red_hair]=$'\U1F468\U1F3FD\U200D\U1F9B0' +emoji[man_medium_dark_skin_tone_red_hair]=$'\U1F468\U1F3FE\U200D\U1F9B0' +emoji[man_dark_skin_tone_red_hair]=$'\U1F468\U1F3FF\U200D\U1F9B0' +emoji[man_curly_hair]=$'\U1F468\U200D\U1F9B1' +emoji[curly_haired_man]=$'\U1F468\U200D\U1F9B1' +emoji[man_light_skin_tone_curly_hair]=$'\U1F468\U1F3FB\U200D\U1F9B1' +emoji[man_medium_light_skin_tone_curly_hair]=$'\U1F468\U1F3FC\U200D\U1F9B1' +emoji[man_medium_skin_tone_curly_hair]=$'\U1F468\U1F3FD\U200D\U1F9B1' +emoji[man_medium_dark_skin_tone_curly_hair]=$'\U1F468\U1F3FE\U200D\U1F9B1' +emoji[man_dark_skin_tone_curly_hair]=$'\U1F468\U1F3FF\U200D\U1F9B1' +emoji[man_white_hair]=$'\U1F468\U200D\U1F9B3' +emoji[white_haired_man]=$'\U1F468\U200D\U1F9B3' +emoji[man_light_skin_tone_white_hair]=$'\U1F468\U1F3FB\U200D\U1F9B3' +emoji[man_medium_light_skin_tone_white_hair]=$'\U1F468\U1F3FC\U200D\U1F9B3' +emoji[man_medium_skin_tone_white_hair]=$'\U1F468\U1F3FD\U200D\U1F9B3' +emoji[man_medium_dark_skin_tone_white_hair]=$'\U1F468\U1F3FE\U200D\U1F9B3' +emoji[man_dark_skin_tone_white_hair]=$'\U1F468\U1F3FF\U200D\U1F9B3' +emoji[man_bald]=$'\U1F468\U200D\U1F9B2' +emoji[bald_man]=$'\U1F468\U200D\U1F9B2' +emoji[man_light_skin_tone_bald]=$'\U1F468\U1F3FB\U200D\U1F9B2' +emoji[man_medium_light_skin_tone_bald]=$'\U1F468\U1F3FC\U200D\U1F9B2' +emoji[man_medium_skin_tone_bald]=$'\U1F468\U1F3FD\U200D\U1F9B2' +emoji[man_medium_dark_skin_tone_bald]=$'\U1F468\U1F3FE\U200D\U1F9B2' +emoji[man_dark_skin_tone_bald]=$'\U1F468\U1F3FF\U200D\U1F9B2' +emoji[woman]=$'\U1F469' +emoji[woman_light_skin_tone]=$'\U1F469\U1F3FB' +emoji[woman_medium_light_skin_tone]=$'\U1F469\U1F3FC' +emoji[woman_medium_skin_tone]=$'\U1F469\U1F3FD' +emoji[woman_medium_dark_skin_tone]=$'\U1F469\U1F3FE' +emoji[woman_dark_skin_tone]=$'\U1F469\U1F3FF' +emoji[woman_blond_hair]=$'\U1F471\U200D\U2640\UFE0F' +emoji[woman_blond_hair_minimally]=$'\U1F471\U200D\U2640' +emoji[blond_haired_woman]=$'\U1F471\U200D\U2640' +emoji[blonde_woman]=$'\U1F471\U200D\U2640' +emoji[woman_light_skin_tone_blond_hair]=$'\U1F471\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_light_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FB\U200D\U2640' +emoji[woman_medium_light_skin_tone_blond_hair]=$'\U1F471\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_medium_light_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FC\U200D\U2640' +emoji[woman_medium_skin_tone_blond_hair]=$'\U1F471\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_medium_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FD\U200D\U2640' +emoji[woman_medium_dark_skin_tone_blond_hair]=$'\U1F471\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_medium_dark_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FE\U200D\U2640' +emoji[woman_dark_skin_tone_blond_hair]=$'\U1F471\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_dark_skin_tone_blond_hair_minimally]=$'\U1F471\U1F3FF\U200D\U2640' +emoji[woman_red_hair]=$'\U1F469\U200D\U1F9B0' +emoji[red_haired_woman]=$'\U1F469\U200D\U1F9B0' +emoji[woman_light_skin_tone_red_hair]=$'\U1F469\U1F3FB\U200D\U1F9B0' +emoji[woman_medium_light_skin_tone_red_hair]=$'\U1F469\U1F3FC\U200D\U1F9B0' +emoji[woman_medium_skin_tone_red_hair]=$'\U1F469\U1F3FD\U200D\U1F9B0' +emoji[woman_medium_dark_skin_tone_red_hair]=$'\U1F469\U1F3FE\U200D\U1F9B0' +emoji[woman_dark_skin_tone_red_hair]=$'\U1F469\U1F3FF\U200D\U1F9B0' +emoji[woman_curly_hair]=$'\U1F469\U200D\U1F9B1' +emoji[curly_haired_woman]=$'\U1F469\U200D\U1F9B1' +emoji[woman_light_skin_tone_curly_hair]=$'\U1F469\U1F3FB\U200D\U1F9B1' +emoji[woman_medium_light_skin_tone_curly_hair]=$'\U1F469\U1F3FC\U200D\U1F9B1' +emoji[woman_medium_skin_tone_curly_hair]=$'\U1F469\U1F3FD\U200D\U1F9B1' +emoji[woman_medium_dark_skin_tone_curly_hair]=$'\U1F469\U1F3FE\U200D\U1F9B1' +emoji[woman_dark_skin_tone_curly_hair]=$'\U1F469\U1F3FF\U200D\U1F9B1' +emoji[woman_white_hair]=$'\U1F469\U200D\U1F9B3' +emoji[white_haired_woman]=$'\U1F469\U200D\U1F9B3' +emoji[woman_light_skin_tone_white_hair]=$'\U1F469\U1F3FB\U200D\U1F9B3' +emoji[woman_medium_light_skin_tone_white_hair]=$'\U1F469\U1F3FC\U200D\U1F9B3' +emoji[woman_medium_skin_tone_white_hair]=$'\U1F469\U1F3FD\U200D\U1F9B3' +emoji[woman_medium_dark_skin_tone_white_hair]=$'\U1F469\U1F3FE\U200D\U1F9B3' +emoji[woman_dark_skin_tone_white_hair]=$'\U1F469\U1F3FF\U200D\U1F9B3' +emoji[woman_bald]=$'\U1F469\U200D\U1F9B2' +emoji[bald_woman]=$'\U1F469\U200D\U1F9B2' +emoji[woman_light_skin_tone_bald]=$'\U1F469\U1F3FB\U200D\U1F9B2' +emoji[woman_medium_light_skin_tone_bald]=$'\U1F469\U1F3FC\U200D\U1F9B2' +emoji[woman_medium_skin_tone_bald]=$'\U1F469\U1F3FD\U200D\U1F9B2' +emoji[woman_medium_dark_skin_tone_bald]=$'\U1F469\U1F3FE\U200D\U1F9B2' +emoji[woman_dark_skin_tone_bald]=$'\U1F469\U1F3FF\U200D\U1F9B2' +emoji[older_person]=$'\U1F9D3' +emoji[older_adult]=$'\U1F9D3' +emoji[older_person_light_skin_tone]=$'\U1F9D3\U1F3FB' +emoji[older_person_medium_light_skin_tone]=$'\U1F9D3\U1F3FC' +emoji[older_person_medium_skin_tone]=$'\U1F9D3\U1F3FD' +emoji[older_person_medium_dark_skin_tone]=$'\U1F9D3\U1F3FE' +emoji[older_person_dark_skin_tone]=$'\U1F9D3\U1F3FF' +emoji[old_man]=$'\U1F474' +emoji[older_man]=$'\U1F474' +emoji[old_man_light_skin_tone]=$'\U1F474\U1F3FB' +emoji[old_man_medium_light_skin_tone]=$'\U1F474\U1F3FC' +emoji[old_man_medium_skin_tone]=$'\U1F474\U1F3FD' +emoji[old_man_medium_dark_skin_tone]=$'\U1F474\U1F3FE' +emoji[old_man_dark_skin_tone]=$'\U1F474\U1F3FF' +emoji[old_woman]=$'\U1F475' +emoji[older_woman]=$'\U1F475' +emoji[old_woman_light_skin_tone]=$'\U1F475\U1F3FB' +emoji[old_woman_medium_light_skin_tone]=$'\U1F475\U1F3FC' +emoji[old_woman_medium_skin_tone]=$'\U1F475\U1F3FD' +emoji[old_woman_medium_dark_skin_tone]=$'\U1F475\U1F3FE' +emoji[old_woman_dark_skin_tone]=$'\U1F475\U1F3FF' +emoji[person_frowning]=$'\U1F64D' +emoji[frowning_person]=$'\U1F64D' +emoji[person_frowning_light_skin_tone]=$'\U1F64D\U1F3FB' +emoji[person_frowning_medium_light_skin_tone]=$'\U1F64D\U1F3FC' +emoji[person_frowning_medium_skin_tone]=$'\U1F64D\U1F3FD' +emoji[person_frowning_medium_dark_skin_tone]=$'\U1F64D\U1F3FE' +emoji[person_frowning_dark_skin_tone]=$'\U1F64D\U1F3FF' +emoji[man_frowning]=$'\U1F64D\U200D\U2642\UFE0F' +emoji[man_frowning_minimally]=$'\U1F64D\U200D\U2642' +emoji[frowning_man]=$'\U1F64D\U200D\U2642' +emoji[man_frowning_light_skin_tone]=$'\U1F64D\U1F3FB\U200D\U2642\UFE0F' +emoji[man_frowning_light_skin_tone_minimally]=$'\U1F64D\U1F3FB\U200D\U2642' +emoji[man_frowning_medium_light_skin_tone]=$'\U1F64D\U1F3FC\U200D\U2642\UFE0F' +emoji[man_frowning_medium_light_skin_tone_minimally]=$'\U1F64D\U1F3FC\U200D\U2642' +emoji[man_frowning_medium_skin_tone]=$'\U1F64D\U1F3FD\U200D\U2642\UFE0F' +emoji[man_frowning_medium_skin_tone_minimally]=$'\U1F64D\U1F3FD\U200D\U2642' +emoji[man_frowning_medium_dark_skin_tone]=$'\U1F64D\U1F3FE\U200D\U2642\UFE0F' +emoji[man_frowning_medium_dark_skin_tone_minimally]=$'\U1F64D\U1F3FE\U200D\U2642' +emoji[man_frowning_dark_skin_tone]=$'\U1F64D\U1F3FF\U200D\U2642\UFE0F' +emoji[man_frowning_dark_skin_tone_minimally]=$'\U1F64D\U1F3FF\U200D\U2642' +emoji[woman_frowning]=$'\U1F64D\U200D\U2640\UFE0F' +emoji[woman_frowning_minimally]=$'\U1F64D\U200D\U2640' +emoji[frowning_woman]=$'\U1F64D\U200D\U2640' +emoji[woman_frowning_light_skin_tone]=$'\U1F64D\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_frowning_light_skin_tone_minimally]=$'\U1F64D\U1F3FB\U200D\U2640' +emoji[woman_frowning_medium_light_skin_tone]=$'\U1F64D\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_frowning_medium_light_skin_tone_minimally]=$'\U1F64D\U1F3FC\U200D\U2640' +emoji[woman_frowning_medium_skin_tone]=$'\U1F64D\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_frowning_medium_skin_tone_minimally]=$'\U1F64D\U1F3FD\U200D\U2640' +emoji[woman_frowning_medium_dark_skin_tone]=$'\U1F64D\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_frowning_medium_dark_skin_tone_minimally]=$'\U1F64D\U1F3FE\U200D\U2640' +emoji[woman_frowning_dark_skin_tone]=$'\U1F64D\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_frowning_dark_skin_tone_minimally]=$'\U1F64D\U1F3FF\U200D\U2640' +emoji[person_pouting]=$'\U1F64E' +emoji[person_pouting_light_skin_tone]=$'\U1F64E\U1F3FB' +emoji[person_pouting_medium_light_skin_tone]=$'\U1F64E\U1F3FC' +emoji[person_pouting_medium_skin_tone]=$'\U1F64E\U1F3FD' +emoji[person_pouting_medium_dark_skin_tone]=$'\U1F64E\U1F3FE' +emoji[person_pouting_dark_skin_tone]=$'\U1F64E\U1F3FF' +emoji[man_pouting]=$'\U1F64E\U200D\U2642\UFE0F' +emoji[man_pouting_minimally]=$'\U1F64E\U200D\U2642' +emoji[pouting_man]=$'\U1F64E\U200D\U2642' +emoji[man_pouting_light_skin_tone]=$'\U1F64E\U1F3FB\U200D\U2642\UFE0F' +emoji[man_pouting_light_skin_tone_minimally]=$'\U1F64E\U1F3FB\U200D\U2642' +emoji[man_pouting_medium_light_skin_tone]=$'\U1F64E\U1F3FC\U200D\U2642\UFE0F' +emoji[man_pouting_medium_light_skin_tone_minimally]=$'\U1F64E\U1F3FC\U200D\U2642' +emoji[man_pouting_medium_skin_tone]=$'\U1F64E\U1F3FD\U200D\U2642\UFE0F' +emoji[man_pouting_medium_skin_tone_minimally]=$'\U1F64E\U1F3FD\U200D\U2642' +emoji[man_pouting_medium_dark_skin_tone]=$'\U1F64E\U1F3FE\U200D\U2642\UFE0F' +emoji[man_pouting_medium_dark_skin_tone_minimally]=$'\U1F64E\U1F3FE\U200D\U2642' +emoji[man_pouting_dark_skin_tone]=$'\U1F64E\U1F3FF\U200D\U2642\UFE0F' +emoji[man_pouting_dark_skin_tone_minimally]=$'\U1F64E\U1F3FF\U200D\U2642' +emoji[woman_pouting]=$'\U1F64E\U200D\U2640\UFE0F' +emoji[woman_pouting_minimally]=$'\U1F64E\U200D\U2640' +emoji[pouting_woman]=$'\U1F64E\U200D\U2640' +emoji[woman_pouting_light_skin_tone]=$'\U1F64E\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_pouting_light_skin_tone_minimally]=$'\U1F64E\U1F3FB\U200D\U2640' +emoji[woman_pouting_medium_light_skin_tone]=$'\U1F64E\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_pouting_medium_light_skin_tone_minimally]=$'\U1F64E\U1F3FC\U200D\U2640' +emoji[woman_pouting_medium_skin_tone]=$'\U1F64E\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_pouting_medium_skin_tone_minimally]=$'\U1F64E\U1F3FD\U200D\U2640' +emoji[woman_pouting_medium_dark_skin_tone]=$'\U1F64E\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_pouting_medium_dark_skin_tone_minimally]=$'\U1F64E\U1F3FE\U200D\U2640' +emoji[woman_pouting_dark_skin_tone]=$'\U1F64E\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_pouting_dark_skin_tone_minimally]=$'\U1F64E\U1F3FF\U200D\U2640' +emoji[person_gesturing_NO]=$'\U1F645' +emoji[no_good]=$'\U1F645' +emoji[person_gesturing_NO_light_skin_tone]=$'\U1F645\U1F3FB' +emoji[person_gesturing_NO_medium_light_skin_tone]=$'\U1F645\U1F3FC' +emoji[person_gesturing_NO_medium_skin_tone]=$'\U1F645\U1F3FD' +emoji[person_gesturing_NO_medium_dark_skin_tone]=$'\U1F645\U1F3FE' +emoji[person_gesturing_NO_dark_skin_tone]=$'\U1F645\U1F3FF' +emoji[man_gesturing_NO]=$'\U1F645\U200D\U2642\UFE0F' +emoji[man_gesturing_NO_minimally]=$'\U1F645\U200D\U2642' +emoji[no_good_man]=$'\U1F645\U200D\U2642' +emoji[ng_man]=$'\U1F645\U200D\U2642' +emoji[man_gesturing_NO_light_skin_tone]=$'\U1F645\U1F3FB\U200D\U2642\UFE0F' +emoji[man_gesturing_NO_light_skin_tone_minimally]=$'\U1F645\U1F3FB\U200D\U2642' +emoji[man_gesturing_NO_medium_light_skin_tone]=$'\U1F645\U1F3FC\U200D\U2642\UFE0F' +emoji[man_gesturing_NO_medium_light_skin_tone_minimally]=$'\U1F645\U1F3FC\U200D\U2642' +emoji[man_gesturing_NO_medium_skin_tone]=$'\U1F645\U1F3FD\U200D\U2642\UFE0F' +emoji[man_gesturing_NO_medium_skin_tone_minimally]=$'\U1F645\U1F3FD\U200D\U2642' +emoji[man_gesturing_NO_medium_dark_skin_tone]=$'\U1F645\U1F3FE\U200D\U2642\UFE0F' +emoji[man_gesturing_NO_medium_dark_skin_tone_minimally]=$'\U1F645\U1F3FE\U200D\U2642' +emoji[man_gesturing_NO_dark_skin_tone]=$'\U1F645\U1F3FF\U200D\U2642\UFE0F' +emoji[man_gesturing_NO_dark_skin_tone_minimally]=$'\U1F645\U1F3FF\U200D\U2642' +emoji[woman_gesturing_NO]=$'\U1F645\U200D\U2640\UFE0F' +emoji[woman_gesturing_NO_minimally]=$'\U1F645\U200D\U2640' +emoji[no_good_woman]=$'\U1F645\U200D\U2640' +emoji[ng_woman]=$'\U1F645\U200D\U2640' +emoji[woman_gesturing_NO_light_skin_tone]=$'\U1F645\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_gesturing_NO_light_skin_tone_minimally]=$'\U1F645\U1F3FB\U200D\U2640' +emoji[woman_gesturing_NO_medium_light_skin_tone]=$'\U1F645\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_gesturing_NO_medium_light_skin_tone_minimally]=$'\U1F645\U1F3FC\U200D\U2640' +emoji[woman_gesturing_NO_medium_skin_tone]=$'\U1F645\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_gesturing_NO_medium_skin_tone_minimally]=$'\U1F645\U1F3FD\U200D\U2640' +emoji[woman_gesturing_NO_medium_dark_skin_tone]=$'\U1F645\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_gesturing_NO_medium_dark_skin_tone_minimally]=$'\U1F645\U1F3FE\U200D\U2640' +emoji[woman_gesturing_NO_dark_skin_tone]=$'\U1F645\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_gesturing_NO_dark_skin_tone_minimally]=$'\U1F645\U1F3FF\U200D\U2640' +emoji[person_gesturing_OK]=$'\U1F646' +emoji[ok_person]=$'\U1F646' +emoji[person_gesturing_OK_light_skin_tone]=$'\U1F646\U1F3FB' +emoji[person_gesturing_OK_medium_light_skin_tone]=$'\U1F646\U1F3FC' +emoji[person_gesturing_OK_medium_skin_tone]=$'\U1F646\U1F3FD' +emoji[person_gesturing_OK_medium_dark_skin_tone]=$'\U1F646\U1F3FE' +emoji[person_gesturing_OK_dark_skin_tone]=$'\U1F646\U1F3FF' +emoji[man_gesturing_OK]=$'\U1F646\U200D\U2642\UFE0F' +emoji[man_gesturing_OK_minimally]=$'\U1F646\U200D\U2642' +emoji[ok_man]=$'\U1F646\U200D\U2642' +emoji[man_gesturing_OK_light_skin_tone]=$'\U1F646\U1F3FB\U200D\U2642\UFE0F' +emoji[man_gesturing_OK_light_skin_tone_minimally]=$'\U1F646\U1F3FB\U200D\U2642' +emoji[man_gesturing_OK_medium_light_skin_tone]=$'\U1F646\U1F3FC\U200D\U2642\UFE0F' +emoji[man_gesturing_OK_medium_light_skin_tone_minimally]=$'\U1F646\U1F3FC\U200D\U2642' +emoji[man_gesturing_OK_medium_skin_tone]=$'\U1F646\U1F3FD\U200D\U2642\UFE0F' +emoji[man_gesturing_OK_medium_skin_tone_minimally]=$'\U1F646\U1F3FD\U200D\U2642' +emoji[man_gesturing_OK_medium_dark_skin_tone]=$'\U1F646\U1F3FE\U200D\U2642\UFE0F' +emoji[man_gesturing_OK_medium_dark_skin_tone_minimally]=$'\U1F646\U1F3FE\U200D\U2642' +emoji[man_gesturing_OK_dark_skin_tone]=$'\U1F646\U1F3FF\U200D\U2642\UFE0F' +emoji[man_gesturing_OK_dark_skin_tone_minimally]=$'\U1F646\U1F3FF\U200D\U2642' +emoji[woman_gesturing_OK]=$'\U1F646\U200D\U2640\UFE0F' +emoji[woman_gesturing_OK_minimally]=$'\U1F646\U200D\U2640' +emoji[ok_woman]=$'\U1F646\U200D\U2640' +emoji[woman_gesturing_OK_light_skin_tone]=$'\U1F646\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_gesturing_OK_light_skin_tone_minimally]=$'\U1F646\U1F3FB\U200D\U2640' +emoji[woman_gesturing_OK_medium_light_skin_tone]=$'\U1F646\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_gesturing_OK_medium_light_skin_tone_minimally]=$'\U1F646\U1F3FC\U200D\U2640' +emoji[woman_gesturing_OK_medium_skin_tone]=$'\U1F646\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_gesturing_OK_medium_skin_tone_minimally]=$'\U1F646\U1F3FD\U200D\U2640' +emoji[woman_gesturing_OK_medium_dark_skin_tone]=$'\U1F646\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_gesturing_OK_medium_dark_skin_tone_minimally]=$'\U1F646\U1F3FE\U200D\U2640' +emoji[woman_gesturing_OK_dark_skin_tone]=$'\U1F646\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_gesturing_OK_dark_skin_tone_minimally]=$'\U1F646\U1F3FF\U200D\U2640' +emoji[person_tipping_hand]=$'\U1F481' +emoji[tipping_hand_person]=$'\U1F481' +emoji[information_desk_person]=$'\U1F481' +emoji[person_tipping_hand_light_skin_tone]=$'\U1F481\U1F3FB' +emoji[person_tipping_hand_medium_light_skin_tone]=$'\U1F481\U1F3FC' +emoji[person_tipping_hand_medium_skin_tone]=$'\U1F481\U1F3FD' +emoji[person_tipping_hand_medium_dark_skin_tone]=$'\U1F481\U1F3FE' +emoji[person_tipping_hand_dark_skin_tone]=$'\U1F481\U1F3FF' +emoji[man_tipping_hand]=$'\U1F481\U200D\U2642\UFE0F' +emoji[man_tipping_hand_minimally]=$'\U1F481\U200D\U2642' +emoji[tipping_hand_man]=$'\U1F481\U200D\U2642' +emoji[sassy_man]=$'\U1F481\U200D\U2642' +emoji[man_tipping_hand_light_skin_tone]=$'\U1F481\U1F3FB\U200D\U2642\UFE0F' +emoji[man_tipping_hand_light_skin_tone_minimally]=$'\U1F481\U1F3FB\U200D\U2642' +emoji[man_tipping_hand_medium_light_skin_tone]=$'\U1F481\U1F3FC\U200D\U2642\UFE0F' +emoji[man_tipping_hand_medium_light_skin_tone_minimally]=$'\U1F481\U1F3FC\U200D\U2642' +emoji[man_tipping_hand_medium_skin_tone]=$'\U1F481\U1F3FD\U200D\U2642\UFE0F' +emoji[man_tipping_hand_medium_skin_tone_minimally]=$'\U1F481\U1F3FD\U200D\U2642' +emoji[man_tipping_hand_medium_dark_skin_tone]=$'\U1F481\U1F3FE\U200D\U2642\UFE0F' +emoji[man_tipping_hand_medium_dark_skin_tone_minimally]=$'\U1F481\U1F3FE\U200D\U2642' +emoji[man_tipping_hand_dark_skin_tone]=$'\U1F481\U1F3FF\U200D\U2642\UFE0F' +emoji[man_tipping_hand_dark_skin_tone_minimally]=$'\U1F481\U1F3FF\U200D\U2642' +emoji[woman_tipping_hand]=$'\U1F481\U200D\U2640\UFE0F' +emoji[woman_tipping_hand_minimally]=$'\U1F481\U200D\U2640' +emoji[tipping_hand_woman]=$'\U1F481\U200D\U2640' +emoji[sassy_woman]=$'\U1F481\U200D\U2640' +emoji[woman_tipping_hand_light_skin_tone]=$'\U1F481\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_tipping_hand_light_skin_tone_minimally]=$'\U1F481\U1F3FB\U200D\U2640' +emoji[woman_tipping_hand_medium_light_skin_tone]=$'\U1F481\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_tipping_hand_medium_light_skin_tone_minimally]=$'\U1F481\U1F3FC\U200D\U2640' +emoji[woman_tipping_hand_medium_skin_tone]=$'\U1F481\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_tipping_hand_medium_skin_tone_minimally]=$'\U1F481\U1F3FD\U200D\U2640' +emoji[woman_tipping_hand_medium_dark_skin_tone]=$'\U1F481\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_tipping_hand_medium_dark_skin_tone_minimally]=$'\U1F481\U1F3FE\U200D\U2640' +emoji[woman_tipping_hand_dark_skin_tone]=$'\U1F481\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_tipping_hand_dark_skin_tone_minimally]=$'\U1F481\U1F3FF\U200D\U2640' +emoji[person_raising_hand]=$'\U1F64B' +emoji[raising_hand]=$'\U1F64B' +emoji[person_raising_hand_light_skin_tone]=$'\U1F64B\U1F3FB' +emoji[person_raising_hand_medium_light_skin_tone]=$'\U1F64B\U1F3FC' +emoji[person_raising_hand_medium_skin_tone]=$'\U1F64B\U1F3FD' +emoji[person_raising_hand_medium_dark_skin_tone]=$'\U1F64B\U1F3FE' +emoji[person_raising_hand_dark_skin_tone]=$'\U1F64B\U1F3FF' +emoji[man_raising_hand]=$'\U1F64B\U200D\U2642\UFE0F' +emoji[man_raising_hand_minimally]=$'\U1F64B\U200D\U2642' +emoji[raising_hand_man]=$'\U1F64B\U200D\U2642' +emoji[man_raising_hand_light_skin_tone]=$'\U1F64B\U1F3FB\U200D\U2642\UFE0F' +emoji[man_raising_hand_light_skin_tone_minimally]=$'\U1F64B\U1F3FB\U200D\U2642' +emoji[man_raising_hand_medium_light_skin_tone]=$'\U1F64B\U1F3FC\U200D\U2642\UFE0F' +emoji[man_raising_hand_medium_light_skin_tone_minimally]=$'\U1F64B\U1F3FC\U200D\U2642' +emoji[man_raising_hand_medium_skin_tone]=$'\U1F64B\U1F3FD\U200D\U2642\UFE0F' +emoji[man_raising_hand_medium_skin_tone_minimally]=$'\U1F64B\U1F3FD\U200D\U2642' +emoji[man_raising_hand_medium_dark_skin_tone]=$'\U1F64B\U1F3FE\U200D\U2642\UFE0F' +emoji[man_raising_hand_medium_dark_skin_tone_minimally]=$'\U1F64B\U1F3FE\U200D\U2642' +emoji[man_raising_hand_dark_skin_tone]=$'\U1F64B\U1F3FF\U200D\U2642\UFE0F' +emoji[man_raising_hand_dark_skin_tone_minimally]=$'\U1F64B\U1F3FF\U200D\U2642' +emoji[woman_raising_hand]=$'\U1F64B\U200D\U2640\UFE0F' +emoji[woman_raising_hand_minimally]=$'\U1F64B\U200D\U2640' +emoji[raising_hand_woman]=$'\U1F64B\U200D\U2640' +emoji[woman_raising_hand_light_skin_tone]=$'\U1F64B\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_raising_hand_light_skin_tone_minimally]=$'\U1F64B\U1F3FB\U200D\U2640' +emoji[woman_raising_hand_medium_light_skin_tone]=$'\U1F64B\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_raising_hand_medium_light_skin_tone_minimally]=$'\U1F64B\U1F3FC\U200D\U2640' +emoji[woman_raising_hand_medium_skin_tone]=$'\U1F64B\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_raising_hand_medium_skin_tone_minimally]=$'\U1F64B\U1F3FD\U200D\U2640' +emoji[woman_raising_hand_medium_dark_skin_tone]=$'\U1F64B\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_raising_hand_medium_dark_skin_tone_minimally]=$'\U1F64B\U1F3FE\U200D\U2640' +emoji[woman_raising_hand_dark_skin_tone]=$'\U1F64B\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_raising_hand_dark_skin_tone_minimally]=$'\U1F64B\U1F3FF\U200D\U2640' +emoji[deaf_person]=$'\U1F9CF' +emoji[deaf_person_light_skin_tone]=$'\U1F9CF\U1F3FB' +emoji[deaf_person_medium_light_skin_tone]=$'\U1F9CF\U1F3FC' +emoji[deaf_person_medium_skin_tone]=$'\U1F9CF\U1F3FD' +emoji[deaf_person_medium_dark_skin_tone]=$'\U1F9CF\U1F3FE' +emoji[deaf_person_dark_skin_tone]=$'\U1F9CF\U1F3FF' +emoji[deaf_man]=$'\U1F9CF\U200D\U2642\UFE0F' +emoji[deaf_man_minimally]=$'\U1F9CF\U200D\U2642' +emoji[deaf_man_light_skin_tone]=$'\U1F9CF\U1F3FB\U200D\U2642\UFE0F' +emoji[deaf_man_light_skin_tone_minimally]=$'\U1F9CF\U1F3FB\U200D\U2642' +emoji[deaf_man_medium_light_skin_tone]=$'\U1F9CF\U1F3FC\U200D\U2642\UFE0F' +emoji[deaf_man_medium_light_skin_tone_minimally]=$'\U1F9CF\U1F3FC\U200D\U2642' +emoji[deaf_man_medium_skin_tone]=$'\U1F9CF\U1F3FD\U200D\U2642\UFE0F' +emoji[deaf_man_medium_skin_tone_minimally]=$'\U1F9CF\U1F3FD\U200D\U2642' +emoji[deaf_man_medium_dark_skin_tone]=$'\U1F9CF\U1F3FE\U200D\U2642\UFE0F' +emoji[deaf_man_medium_dark_skin_tone_minimally]=$'\U1F9CF\U1F3FE\U200D\U2642' +emoji[deaf_man_dark_skin_tone]=$'\U1F9CF\U1F3FF\U200D\U2642\UFE0F' +emoji[deaf_man_dark_skin_tone_minimally]=$'\U1F9CF\U1F3FF\U200D\U2642' +emoji[deaf_woman]=$'\U1F9CF\U200D\U2640\UFE0F' +emoji[deaf_woman_minimally]=$'\U1F9CF\U200D\U2640' +emoji[deaf_woman_light_skin_tone]=$'\U1F9CF\U1F3FB\U200D\U2640\UFE0F' +emoji[deaf_woman_light_skin_tone_minimally]=$'\U1F9CF\U1F3FB\U200D\U2640' +emoji[deaf_woman_medium_light_skin_tone]=$'\U1F9CF\U1F3FC\U200D\U2640\UFE0F' +emoji[deaf_woman_medium_light_skin_tone_minimally]=$'\U1F9CF\U1F3FC\U200D\U2640' +emoji[deaf_woman_medium_skin_tone]=$'\U1F9CF\U1F3FD\U200D\U2640\UFE0F' +emoji[deaf_woman_medium_skin_tone_minimally]=$'\U1F9CF\U1F3FD\U200D\U2640' +emoji[deaf_woman_medium_dark_skin_tone]=$'\U1F9CF\U1F3FE\U200D\U2640\UFE0F' +emoji[deaf_woman_medium_dark_skin_tone_minimally]=$'\U1F9CF\U1F3FE\U200D\U2640' +emoji[deaf_woman_dark_skin_tone]=$'\U1F9CF\U1F3FF\U200D\U2640\UFE0F' +emoji[deaf_woman_dark_skin_tone_minimally]=$'\U1F9CF\U1F3FF\U200D\U2640' +emoji[person_bowing]=$'\U1F647' +emoji[bow]=$'\U1F647' +emoji[person_bowing_light_skin_tone]=$'\U1F647\U1F3FB' +emoji[person_bowing_medium_light_skin_tone]=$'\U1F647\U1F3FC' +emoji[person_bowing_medium_skin_tone]=$'\U1F647\U1F3FD' +emoji[person_bowing_medium_dark_skin_tone]=$'\U1F647\U1F3FE' +emoji[person_bowing_dark_skin_tone]=$'\U1F647\U1F3FF' +emoji[man_bowing]=$'\U1F647\U200D\U2642\UFE0F' +emoji[man_bowing_minimally]=$'\U1F647\U200D\U2642' +emoji[bowing_man]=$'\U1F647\U200D\U2642' +emoji[man_bowing_light_skin_tone]=$'\U1F647\U1F3FB\U200D\U2642\UFE0F' +emoji[man_bowing_light_skin_tone_minimally]=$'\U1F647\U1F3FB\U200D\U2642' +emoji[man_bowing_medium_light_skin_tone]=$'\U1F647\U1F3FC\U200D\U2642\UFE0F' +emoji[man_bowing_medium_light_skin_tone_minimally]=$'\U1F647\U1F3FC\U200D\U2642' +emoji[man_bowing_medium_skin_tone]=$'\U1F647\U1F3FD\U200D\U2642\UFE0F' +emoji[man_bowing_medium_skin_tone_minimally]=$'\U1F647\U1F3FD\U200D\U2642' +emoji[man_bowing_medium_dark_skin_tone]=$'\U1F647\U1F3FE\U200D\U2642\UFE0F' +emoji[man_bowing_medium_dark_skin_tone_minimally]=$'\U1F647\U1F3FE\U200D\U2642' +emoji[man_bowing_dark_skin_tone]=$'\U1F647\U1F3FF\U200D\U2642\UFE0F' +emoji[man_bowing_dark_skin_tone_minimally]=$'\U1F647\U1F3FF\U200D\U2642' +emoji[woman_bowing]=$'\U1F647\U200D\U2640\UFE0F' +emoji[woman_bowing_minimally]=$'\U1F647\U200D\U2640' +emoji[bowing_woman]=$'\U1F647\U200D\U2640' +emoji[woman_bowing_light_skin_tone]=$'\U1F647\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_bowing_light_skin_tone_minimally]=$'\U1F647\U1F3FB\U200D\U2640' +emoji[woman_bowing_medium_light_skin_tone]=$'\U1F647\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_bowing_medium_light_skin_tone_minimally]=$'\U1F647\U1F3FC\U200D\U2640' +emoji[woman_bowing_medium_skin_tone]=$'\U1F647\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_bowing_medium_skin_tone_minimally]=$'\U1F647\U1F3FD\U200D\U2640' +emoji[woman_bowing_medium_dark_skin_tone]=$'\U1F647\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_bowing_medium_dark_skin_tone_minimally]=$'\U1F647\U1F3FE\U200D\U2640' +emoji[woman_bowing_dark_skin_tone]=$'\U1F647\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_bowing_dark_skin_tone_minimally]=$'\U1F647\U1F3FF\U200D\U2640' +emoji[person_facepalming]=$'\U1F926' +emoji[facepalm]=$'\U1F926' +emoji[person_facepalming_light_skin_tone]=$'\U1F926\U1F3FB' +emoji[person_facepalming_medium_light_skin_tone]=$'\U1F926\U1F3FC' +emoji[person_facepalming_medium_skin_tone]=$'\U1F926\U1F3FD' +emoji[person_facepalming_medium_dark_skin_tone]=$'\U1F926\U1F3FE' +emoji[person_facepalming_dark_skin_tone]=$'\U1F926\U1F3FF' +emoji[man_facepalming]=$'\U1F926\U200D\U2642\UFE0F' +emoji[man_facepalming_minimally]=$'\U1F926\U200D\U2642' +emoji[man_facepalming_light_skin_tone]=$'\U1F926\U1F3FB\U200D\U2642\UFE0F' +emoji[man_facepalming_light_skin_tone_minimally]=$'\U1F926\U1F3FB\U200D\U2642' +emoji[man_facepalming_medium_light_skin_tone]=$'\U1F926\U1F3FC\U200D\U2642\UFE0F' +emoji[man_facepalming_medium_light_skin_tone_minimally]=$'\U1F926\U1F3FC\U200D\U2642' +emoji[man_facepalming_medium_skin_tone]=$'\U1F926\U1F3FD\U200D\U2642\UFE0F' +emoji[man_facepalming_medium_skin_tone_minimally]=$'\U1F926\U1F3FD\U200D\U2642' +emoji[man_facepalming_medium_dark_skin_tone]=$'\U1F926\U1F3FE\U200D\U2642\UFE0F' +emoji[man_facepalming_medium_dark_skin_tone_minimally]=$'\U1F926\U1F3FE\U200D\U2642' +emoji[man_facepalming_dark_skin_tone]=$'\U1F926\U1F3FF\U200D\U2642\UFE0F' +emoji[man_facepalming_dark_skin_tone_minimally]=$'\U1F926\U1F3FF\U200D\U2642' +emoji[woman_facepalming]=$'\U1F926\U200D\U2640\UFE0F' +emoji[woman_facepalming_minimally]=$'\U1F926\U200D\U2640' +emoji[woman_facepalming_light_skin_tone]=$'\U1F926\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_facepalming_light_skin_tone_minimally]=$'\U1F926\U1F3FB\U200D\U2640' +emoji[woman_facepalming_medium_light_skin_tone]=$'\U1F926\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_facepalming_medium_light_skin_tone_minimally]=$'\U1F926\U1F3FC\U200D\U2640' +emoji[woman_facepalming_medium_skin_tone]=$'\U1F926\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_facepalming_medium_skin_tone_minimally]=$'\U1F926\U1F3FD\U200D\U2640' +emoji[woman_facepalming_medium_dark_skin_tone]=$'\U1F926\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_facepalming_medium_dark_skin_tone_minimally]=$'\U1F926\U1F3FE\U200D\U2640' +emoji[woman_facepalming_dark_skin_tone]=$'\U1F926\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_facepalming_dark_skin_tone_minimally]=$'\U1F926\U1F3FF\U200D\U2640' +emoji[person_shrugging]=$'\U1F937' +emoji[shrug]=$'\U1F937' +emoji[person_shrugging_light_skin_tone]=$'\U1F937\U1F3FB' +emoji[person_shrugging_medium_light_skin_tone]=$'\U1F937\U1F3FC' +emoji[person_shrugging_medium_skin_tone]=$'\U1F937\U1F3FD' +emoji[person_shrugging_medium_dark_skin_tone]=$'\U1F937\U1F3FE' +emoji[person_shrugging_dark_skin_tone]=$'\U1F937\U1F3FF' +emoji[man_shrugging]=$'\U1F937\U200D\U2642\UFE0F' +emoji[man_shrugging_minimally]=$'\U1F937\U200D\U2642' +emoji[man_shrugging_light_skin_tone]=$'\U1F937\U1F3FB\U200D\U2642\UFE0F' +emoji[man_shrugging_light_skin_tone_minimally]=$'\U1F937\U1F3FB\U200D\U2642' +emoji[man_shrugging_medium_light_skin_tone]=$'\U1F937\U1F3FC\U200D\U2642\UFE0F' +emoji[man_shrugging_medium_light_skin_tone_minimally]=$'\U1F937\U1F3FC\U200D\U2642' +emoji[man_shrugging_medium_skin_tone]=$'\U1F937\U1F3FD\U200D\U2642\UFE0F' +emoji[man_shrugging_medium_skin_tone_minimally]=$'\U1F937\U1F3FD\U200D\U2642' +emoji[man_shrugging_medium_dark_skin_tone]=$'\U1F937\U1F3FE\U200D\U2642\UFE0F' +emoji[man_shrugging_medium_dark_skin_tone_minimally]=$'\U1F937\U1F3FE\U200D\U2642' +emoji[man_shrugging_dark_skin_tone]=$'\U1F937\U1F3FF\U200D\U2642\UFE0F' +emoji[man_shrugging_dark_skin_tone_minimally]=$'\U1F937\U1F3FF\U200D\U2642' +emoji[woman_shrugging]=$'\U1F937\U200D\U2640\UFE0F' +emoji[woman_shrugging_minimally]=$'\U1F937\U200D\U2640' +emoji[woman_shrugging_light_skin_tone]=$'\U1F937\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_shrugging_light_skin_tone_minimally]=$'\U1F937\U1F3FB\U200D\U2640' +emoji[woman_shrugging_medium_light_skin_tone]=$'\U1F937\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_shrugging_medium_light_skin_tone_minimally]=$'\U1F937\U1F3FC\U200D\U2640' +emoji[woman_shrugging_medium_skin_tone]=$'\U1F937\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_shrugging_medium_skin_tone_minimally]=$'\U1F937\U1F3FD\U200D\U2640' +emoji[woman_shrugging_medium_dark_skin_tone]=$'\U1F937\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_shrugging_medium_dark_skin_tone_minimally]=$'\U1F937\U1F3FE\U200D\U2640' +emoji[woman_shrugging_dark_skin_tone]=$'\U1F937\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_shrugging_dark_skin_tone_minimally]=$'\U1F937\U1F3FF\U200D\U2640' +emoji[man_health_worker]=$'\U1F468\U200D\U2695\UFE0F' +emoji[man_health_worker_minimally]=$'\U1F468\U200D\U2695' +emoji[man_health_worker_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U2695\UFE0F' +emoji[man_health_worker_light_skin_tone_minimally]=$'\U1F468\U1F3FB\U200D\U2695' +emoji[man_health_worker_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U2695\UFE0F' +emoji[man_health_worker_medium_light_skin_tone_minimally]=$'\U1F468\U1F3FC\U200D\U2695' +emoji[man_health_worker_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U2695\UFE0F' +emoji[man_health_worker_medium_skin_tone_minimally]=$'\U1F468\U1F3FD\U200D\U2695' +emoji[man_health_worker_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U2695\UFE0F' +emoji[man_health_worker_medium_dark_skin_tone_minimally]=$'\U1F468\U1F3FE\U200D\U2695' +emoji[man_health_worker_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U2695\UFE0F' +emoji[man_health_worker_dark_skin_tone_minimally]=$'\U1F468\U1F3FF\U200D\U2695' +emoji[woman_health_worker]=$'\U1F469\U200D\U2695\UFE0F' +emoji[woman_health_worker_minimally]=$'\U1F469\U200D\U2695' +emoji[woman_health_worker_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U2695\UFE0F' +emoji[woman_health_worker_light_skin_tone_minimally]=$'\U1F469\U1F3FB\U200D\U2695' +emoji[woman_health_worker_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U2695\UFE0F' +emoji[woman_health_worker_medium_light_skin_tone_minimally]=$'\U1F469\U1F3FC\U200D\U2695' +emoji[woman_health_worker_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U2695\UFE0F' +emoji[woman_health_worker_medium_skin_tone_minimally]=$'\U1F469\U1F3FD\U200D\U2695' +emoji[woman_health_worker_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U2695\UFE0F' +emoji[woman_health_worker_medium_dark_skin_tone_minimally]=$'\U1F469\U1F3FE\U200D\U2695' +emoji[woman_health_worker_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U2695\UFE0F' +emoji[woman_health_worker_dark_skin_tone_minimally]=$'\U1F469\U1F3FF\U200D\U2695' +emoji[man_student]=$'\U1F468\U200D\U1F393' +emoji[man_student_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F393' +emoji[man_student_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F393' +emoji[man_student_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F393' +emoji[man_student_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F393' +emoji[man_student_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F393' +emoji[woman_student]=$'\U1F469\U200D\U1F393' +emoji[woman_student_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F393' +emoji[woman_student_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F393' +emoji[woman_student_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F393' +emoji[woman_student_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F393' +emoji[woman_student_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F393' +emoji[man_teacher]=$'\U1F468\U200D\U1F3EB' +emoji[man_teacher_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F3EB' +emoji[man_teacher_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F3EB' +emoji[man_teacher_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F3EB' +emoji[man_teacher_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F3EB' +emoji[man_teacher_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F3EB' +emoji[woman_teacher]=$'\U1F469\U200D\U1F3EB' +emoji[woman_teacher_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F3EB' +emoji[woman_teacher_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F3EB' +emoji[woman_teacher_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F3EB' +emoji[woman_teacher_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F3EB' +emoji[woman_teacher_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F3EB' +emoji[man_judge]=$'\U1F468\U200D\U2696\UFE0F' +emoji[man_judge_minimally]=$'\U1F468\U200D\U2696' +emoji[man_judge_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U2696\UFE0F' +emoji[man_judge_light_skin_tone_minimally]=$'\U1F468\U1F3FB\U200D\U2696' +emoji[man_judge_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U2696\UFE0F' +emoji[man_judge_medium_light_skin_tone_minimally]=$'\U1F468\U1F3FC\U200D\U2696' +emoji[man_judge_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U2696\UFE0F' +emoji[man_judge_medium_skin_tone_minimally]=$'\U1F468\U1F3FD\U200D\U2696' +emoji[man_judge_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U2696\UFE0F' +emoji[man_judge_medium_dark_skin_tone_minimally]=$'\U1F468\U1F3FE\U200D\U2696' +emoji[man_judge_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U2696\UFE0F' +emoji[man_judge_dark_skin_tone_minimally]=$'\U1F468\U1F3FF\U200D\U2696' +emoji[woman_judge]=$'\U1F469\U200D\U2696\UFE0F' +emoji[woman_judge_minimally]=$'\U1F469\U200D\U2696' +emoji[woman_judge_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U2696\UFE0F' +emoji[woman_judge_light_skin_tone_minimally]=$'\U1F469\U1F3FB\U200D\U2696' +emoji[woman_judge_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U2696\UFE0F' +emoji[woman_judge_medium_light_skin_tone_minimally]=$'\U1F469\U1F3FC\U200D\U2696' +emoji[woman_judge_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U2696\UFE0F' +emoji[woman_judge_medium_skin_tone_minimally]=$'\U1F469\U1F3FD\U200D\U2696' +emoji[woman_judge_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U2696\UFE0F' +emoji[woman_judge_medium_dark_skin_tone_minimally]=$'\U1F469\U1F3FE\U200D\U2696' +emoji[woman_judge_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U2696\UFE0F' +emoji[woman_judge_dark_skin_tone_minimally]=$'\U1F469\U1F3FF\U200D\U2696' +emoji[man_farmer]=$'\U1F468\U200D\U1F33E' +emoji[man_farmer_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F33E' +emoji[man_farmer_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F33E' +emoji[man_farmer_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F33E' +emoji[man_farmer_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F33E' +emoji[man_farmer_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F33E' +emoji[woman_farmer]=$'\U1F469\U200D\U1F33E' +emoji[woman_farmer_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F33E' +emoji[woman_farmer_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F33E' +emoji[woman_farmer_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F33E' +emoji[woman_farmer_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F33E' +emoji[woman_farmer_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F33E' +emoji[man_cook]=$'\U1F468\U200D\U1F373' +emoji[man_cook_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F373' +emoji[man_cook_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F373' +emoji[man_cook_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F373' +emoji[man_cook_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F373' +emoji[man_cook_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F373' +emoji[woman_cook]=$'\U1F469\U200D\U1F373' +emoji[woman_cook_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F373' +emoji[woman_cook_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F373' +emoji[woman_cook_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F373' +emoji[woman_cook_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F373' +emoji[woman_cook_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F373' +emoji[man_mechanic]=$'\U1F468\U200D\U1F527' +emoji[man_mechanic_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F527' +emoji[man_mechanic_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F527' +emoji[man_mechanic_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F527' +emoji[man_mechanic_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F527' +emoji[man_mechanic_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F527' +emoji[woman_mechanic]=$'\U1F469\U200D\U1F527' +emoji[woman_mechanic_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F527' +emoji[woman_mechanic_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F527' +emoji[woman_mechanic_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F527' +emoji[woman_mechanic_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F527' +emoji[woman_mechanic_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F527' +emoji[man_factory_worker]=$'\U1F468\U200D\U1F3ED' +emoji[man_factory_worker_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F3ED' +emoji[man_factory_worker_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F3ED' +emoji[man_factory_worker_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F3ED' +emoji[man_factory_worker_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F3ED' +emoji[man_factory_worker_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F3ED' +emoji[woman_factory_worker]=$'\U1F469\U200D\U1F3ED' +emoji[woman_factory_worker_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F3ED' +emoji[woman_factory_worker_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F3ED' +emoji[woman_factory_worker_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F3ED' +emoji[woman_factory_worker_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F3ED' +emoji[woman_factory_worker_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F3ED' +emoji[man_office_worker]=$'\U1F468\U200D\U1F4BC' +emoji[man_office_worker_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F4BC' +emoji[man_office_worker_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F4BC' +emoji[man_office_worker_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F4BC' +emoji[man_office_worker_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F4BC' +emoji[man_office_worker_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F4BC' +emoji[woman_office_worker]=$'\U1F469\U200D\U1F4BC' +emoji[woman_office_worker_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F4BC' +emoji[woman_office_worker_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F4BC' +emoji[woman_office_worker_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F4BC' +emoji[woman_office_worker_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F4BC' +emoji[woman_office_worker_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F4BC' +emoji[man_scientist]=$'\U1F468\U200D\U1F52C' +emoji[man_scientist_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F52C' +emoji[man_scientist_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F52C' +emoji[man_scientist_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F52C' +emoji[man_scientist_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F52C' +emoji[man_scientist_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F52C' +emoji[woman_scientist]=$'\U1F469\U200D\U1F52C' +emoji[woman_scientist_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F52C' +emoji[woman_scientist_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F52C' +emoji[woman_scientist_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F52C' +emoji[woman_scientist_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F52C' +emoji[woman_scientist_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F52C' +emoji[man_technologist]=$'\U1F468\U200D\U1F4BB' +emoji[man_technologist_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F4BB' +emoji[man_technologist_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F4BB' +emoji[man_technologist_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F4BB' +emoji[man_technologist_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F4BB' +emoji[man_technologist_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F4BB' +emoji[woman_technologist]=$'\U1F469\U200D\U1F4BB' +emoji[woman_technologist_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F4BB' +emoji[woman_technologist_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F4BB' +emoji[woman_technologist_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F4BB' +emoji[woman_technologist_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F4BB' +emoji[woman_technologist_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F4BB' +emoji[man_singer]=$'\U1F468\U200D\U1F3A4' +emoji[man_singer_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F3A4' +emoji[man_singer_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F3A4' +emoji[man_singer_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F3A4' +emoji[man_singer_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F3A4' +emoji[man_singer_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F3A4' +emoji[woman_singer]=$'\U1F469\U200D\U1F3A4' +emoji[woman_singer_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F3A4' +emoji[woman_singer_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F3A4' +emoji[woman_singer_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F3A4' +emoji[woman_singer_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F3A4' +emoji[woman_singer_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F3A4' +emoji[man_artist]=$'\U1F468\U200D\U1F3A8' +emoji[man_artist_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F3A8' +emoji[man_artist_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F3A8' +emoji[man_artist_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F3A8' +emoji[man_artist_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F3A8' +emoji[man_artist_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F3A8' +emoji[woman_artist]=$'\U1F469\U200D\U1F3A8' +emoji[woman_artist_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F3A8' +emoji[woman_artist_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F3A8' +emoji[woman_artist_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F3A8' +emoji[woman_artist_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F3A8' +emoji[woman_artist_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F3A8' +emoji[man_pilot]=$'\U1F468\U200D\U2708\UFE0F' +emoji[man_pilot_minimally]=$'\U1F468\U200D\U2708' +emoji[man_pilot_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U2708\UFE0F' +emoji[man_pilot_light_skin_tone_minimally]=$'\U1F468\U1F3FB\U200D\U2708' +emoji[man_pilot_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U2708\UFE0F' +emoji[man_pilot_medium_light_skin_tone_minimally]=$'\U1F468\U1F3FC\U200D\U2708' +emoji[man_pilot_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U2708\UFE0F' +emoji[man_pilot_medium_skin_tone_minimally]=$'\U1F468\U1F3FD\U200D\U2708' +emoji[man_pilot_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U2708\UFE0F' +emoji[man_pilot_medium_dark_skin_tone_minimally]=$'\U1F468\U1F3FE\U200D\U2708' +emoji[man_pilot_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U2708\UFE0F' +emoji[man_pilot_dark_skin_tone_minimally]=$'\U1F468\U1F3FF\U200D\U2708' +emoji[woman_pilot]=$'\U1F469\U200D\U2708\UFE0F' +emoji[woman_pilot_minimally]=$'\U1F469\U200D\U2708' +emoji[woman_pilot_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U2708\UFE0F' +emoji[woman_pilot_light_skin_tone_minimally]=$'\U1F469\U1F3FB\U200D\U2708' +emoji[woman_pilot_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U2708\UFE0F' +emoji[woman_pilot_medium_light_skin_tone_minimally]=$'\U1F469\U1F3FC\U200D\U2708' +emoji[woman_pilot_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U2708\UFE0F' +emoji[woman_pilot_medium_skin_tone_minimally]=$'\U1F469\U1F3FD\U200D\U2708' +emoji[woman_pilot_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U2708\UFE0F' +emoji[woman_pilot_medium_dark_skin_tone_minimally]=$'\U1F469\U1F3FE\U200D\U2708' +emoji[woman_pilot_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U2708\UFE0F' +emoji[woman_pilot_dark_skin_tone_minimally]=$'\U1F469\U1F3FF\U200D\U2708' +emoji[man_astronaut]=$'\U1F468\U200D\U1F680' +emoji[man_astronaut_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F680' +emoji[man_astronaut_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F680' +emoji[man_astronaut_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F680' +emoji[man_astronaut_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F680' +emoji[man_astronaut_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F680' +emoji[woman_astronaut]=$'\U1F469\U200D\U1F680' +emoji[woman_astronaut_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F680' +emoji[woman_astronaut_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F680' +emoji[woman_astronaut_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F680' +emoji[woman_astronaut_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F680' +emoji[woman_astronaut_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F680' +emoji[man_firefighter]=$'\U1F468\U200D\U1F692' +emoji[man_firefighter_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F692' +emoji[man_firefighter_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F692' +emoji[man_firefighter_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F692' +emoji[man_firefighter_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F692' +emoji[man_firefighter_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F692' +emoji[woman_firefighter]=$'\U1F469\U200D\U1F692' +emoji[woman_firefighter_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F692' +emoji[woman_firefighter_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F692' +emoji[woman_firefighter_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F692' +emoji[woman_firefighter_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F692' +emoji[woman_firefighter_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F692' +emoji[police_officer]=$'\U1F46E' +emoji[cop]=$'\U1F46E' +emoji[police_officer_light_skin_tone]=$'\U1F46E\U1F3FB' +emoji[police_officer_medium_light_skin_tone]=$'\U1F46E\U1F3FC' +emoji[police_officer_medium_skin_tone]=$'\U1F46E\U1F3FD' +emoji[police_officer_medium_dark_skin_tone]=$'\U1F46E\U1F3FE' +emoji[police_officer_dark_skin_tone]=$'\U1F46E\U1F3FF' +emoji[man_police_officer]=$'\U1F46E\U200D\U2642\UFE0F' +emoji[man_police_officer_minimally]=$'\U1F46E\U200D\U2642' +emoji[policeman]=$'\U1F46E\U200D\U2642' +emoji[man_police_officer_light_skin_tone]=$'\U1F46E\U1F3FB\U200D\U2642\UFE0F' +emoji[man_police_officer_light_skin_tone_minimally]=$'\U1F46E\U1F3FB\U200D\U2642' +emoji[man_police_officer_medium_light_skin_tone]=$'\U1F46E\U1F3FC\U200D\U2642\UFE0F' +emoji[man_police_officer_medium_light_skin_tone_minimally]=$'\U1F46E\U1F3FC\U200D\U2642' +emoji[man_police_officer_medium_skin_tone]=$'\U1F46E\U1F3FD\U200D\U2642\UFE0F' +emoji[man_police_officer_medium_skin_tone_minimally]=$'\U1F46E\U1F3FD\U200D\U2642' +emoji[man_police_officer_medium_dark_skin_tone]=$'\U1F46E\U1F3FE\U200D\U2642\UFE0F' +emoji[man_police_officer_medium_dark_skin_tone_minimally]=$'\U1F46E\U1F3FE\U200D\U2642' +emoji[man_police_officer_dark_skin_tone]=$'\U1F46E\U1F3FF\U200D\U2642\UFE0F' +emoji[man_police_officer_dark_skin_tone_minimally]=$'\U1F46E\U1F3FF\U200D\U2642' +emoji[woman_police_officer]=$'\U1F46E\U200D\U2640\UFE0F' +emoji[woman_police_officer_minimally]=$'\U1F46E\U200D\U2640' +emoji[policewoman]=$'\U1F46E\U200D\U2640' +emoji[woman_police_officer_light_skin_tone]=$'\U1F46E\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_police_officer_light_skin_tone_minimally]=$'\U1F46E\U1F3FB\U200D\U2640' +emoji[woman_police_officer_medium_light_skin_tone]=$'\U1F46E\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_police_officer_medium_light_skin_tone_minimally]=$'\U1F46E\U1F3FC\U200D\U2640' +emoji[woman_police_officer_medium_skin_tone]=$'\U1F46E\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_police_officer_medium_skin_tone_minimally]=$'\U1F46E\U1F3FD\U200D\U2640' +emoji[woman_police_officer_medium_dark_skin_tone]=$'\U1F46E\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_police_officer_medium_dark_skin_tone_minimally]=$'\U1F46E\U1F3FE\U200D\U2640' +emoji[woman_police_officer_dark_skin_tone]=$'\U1F46E\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_police_officer_dark_skin_tone_minimally]=$'\U1F46E\U1F3FF\U200D\U2640' +emoji[detective]=$'\U1F575\UFE0F' +emoji[detective_unqualified]=$'\U1F575' +emoji[detective_light_skin_tone]=$'\U1F575\U1F3FB' +emoji[detective_medium_light_skin_tone]=$'\U1F575\U1F3FC' +emoji[detective_medium_skin_tone]=$'\U1F575\U1F3FD' +emoji[detective_medium_dark_skin_tone]=$'\U1F575\U1F3FE' +emoji[detective_dark_skin_tone]=$'\U1F575\U1F3FF' +emoji[man_detective]=$'\U1F575\UFE0F\U200D\U2642\UFE0F' +emoji[male_detective]=$'\U1F575\UFE0F\U200D\U2642\UFE0F' +emoji[man_detective_unqualified]=$'\U1F575\U200D\U2642\UFE0F' +emoji[man_detective_unqualified_1]=$'\U1F575\UFE0F\U200D\U2642' +emoji[man_detective_unqualified_2]=$'\U1F575\U200D\U2642' +emoji[man_detective_light_skin_tone]=$'\U1F575\U1F3FB\U200D\U2642\UFE0F' +emoji[man_detective_light_skin_tone_minimally]=$'\U1F575\U1F3FB\U200D\U2642' +emoji[man_detective_medium_light_skin_tone]=$'\U1F575\U1F3FC\U200D\U2642\UFE0F' +emoji[man_detective_medium_light_skin_tone_minimally]=$'\U1F575\U1F3FC\U200D\U2642' +emoji[man_detective_medium_skin_tone]=$'\U1F575\U1F3FD\U200D\U2642\UFE0F' +emoji[man_detective_medium_skin_tone_minimally]=$'\U1F575\U1F3FD\U200D\U2642' +emoji[man_detective_medium_dark_skin_tone]=$'\U1F575\U1F3FE\U200D\U2642\UFE0F' +emoji[man_detective_medium_dark_skin_tone_minimally]=$'\U1F575\U1F3FE\U200D\U2642' +emoji[man_detective_dark_skin_tone]=$'\U1F575\U1F3FF\U200D\U2642\UFE0F' +emoji[man_detective_dark_skin_tone_minimally]=$'\U1F575\U1F3FF\U200D\U2642' +emoji[woman_detective]=$'\U1F575\UFE0F\U200D\U2640\UFE0F' +emoji[female_detective]=$'\U1F575\UFE0F\U200D\U2640\UFE0F' +emoji[woman_detective_unqualified]=$'\U1F575\U200D\U2640\UFE0F' +emoji[woman_detective_unqualified_1]=$'\U1F575\UFE0F\U200D\U2640' +emoji[woman_detective_unqualified_2]=$'\U1F575\U200D\U2640' +emoji[woman_detective_light_skin_tone]=$'\U1F575\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_detective_light_skin_tone_minimally]=$'\U1F575\U1F3FB\U200D\U2640' +emoji[woman_detective_medium_light_skin_tone]=$'\U1F575\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_detective_medium_light_skin_tone_minimally]=$'\U1F575\U1F3FC\U200D\U2640' +emoji[woman_detective_medium_skin_tone]=$'\U1F575\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_detective_medium_skin_tone_minimally]=$'\U1F575\U1F3FD\U200D\U2640' +emoji[woman_detective_medium_dark_skin_tone]=$'\U1F575\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_detective_medium_dark_skin_tone_minimally]=$'\U1F575\U1F3FE\U200D\U2640' +emoji[woman_detective_dark_skin_tone]=$'\U1F575\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_detective_dark_skin_tone_minimally]=$'\U1F575\U1F3FF\U200D\U2640' +emoji[guard]=$'\U1F482' +emoji[guard_light_skin_tone]=$'\U1F482\U1F3FB' +emoji[guard_medium_light_skin_tone]=$'\U1F482\U1F3FC' +emoji[guard_medium_skin_tone]=$'\U1F482\U1F3FD' +emoji[guard_medium_dark_skin_tone]=$'\U1F482\U1F3FE' +emoji[guard_dark_skin_tone]=$'\U1F482\U1F3FF' +emoji[man_guard]=$'\U1F482\U200D\U2642\UFE0F' +emoji[man_guard_minimally]=$'\U1F482\U200D\U2642' +emoji[guardsman]=$'\U1F482\U200D\U2642' +emoji[man_guard_light_skin_tone]=$'\U1F482\U1F3FB\U200D\U2642\UFE0F' +emoji[man_guard_light_skin_tone_minimally]=$'\U1F482\U1F3FB\U200D\U2642' +emoji[man_guard_medium_light_skin_tone]=$'\U1F482\U1F3FC\U200D\U2642\UFE0F' +emoji[man_guard_medium_light_skin_tone_minimally]=$'\U1F482\U1F3FC\U200D\U2642' +emoji[man_guard_medium_skin_tone]=$'\U1F482\U1F3FD\U200D\U2642\UFE0F' +emoji[man_guard_medium_skin_tone_minimally]=$'\U1F482\U1F3FD\U200D\U2642' +emoji[man_guard_medium_dark_skin_tone]=$'\U1F482\U1F3FE\U200D\U2642\UFE0F' +emoji[man_guard_medium_dark_skin_tone_minimally]=$'\U1F482\U1F3FE\U200D\U2642' +emoji[man_guard_dark_skin_tone]=$'\U1F482\U1F3FF\U200D\U2642\UFE0F' +emoji[man_guard_dark_skin_tone_minimally]=$'\U1F482\U1F3FF\U200D\U2642' +emoji[woman_guard]=$'\U1F482\U200D\U2640\UFE0F' +emoji[woman_guard_minimally]=$'\U1F482\U200D\U2640' +emoji[guardswoman]=$'\U1F482\U200D\U2640' +emoji[woman_guard_light_skin_tone]=$'\U1F482\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_guard_light_skin_tone_minimally]=$'\U1F482\U1F3FB\U200D\U2640' +emoji[woman_guard_medium_light_skin_tone]=$'\U1F482\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_guard_medium_light_skin_tone_minimally]=$'\U1F482\U1F3FC\U200D\U2640' +emoji[woman_guard_medium_skin_tone]=$'\U1F482\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_guard_medium_skin_tone_minimally]=$'\U1F482\U1F3FD\U200D\U2640' +emoji[woman_guard_medium_dark_skin_tone]=$'\U1F482\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_guard_medium_dark_skin_tone_minimally]=$'\U1F482\U1F3FE\U200D\U2640' +emoji[woman_guard_dark_skin_tone]=$'\U1F482\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_guard_dark_skin_tone_minimally]=$'\U1F482\U1F3FF\U200D\U2640' +emoji[construction_worker]=$'\U1F477' +emoji[construction_worker_light_skin_tone]=$'\U1F477\U1F3FB' +emoji[construction_worker_medium_light_skin_tone]=$'\U1F477\U1F3FC' +emoji[construction_worker_medium_skin_tone]=$'\U1F477\U1F3FD' +emoji[construction_worker_medium_dark_skin_tone]=$'\U1F477\U1F3FE' +emoji[construction_worker_dark_skin_tone]=$'\U1F477\U1F3FF' +emoji[man_construction_worker]=$'\U1F477\U200D\U2642\UFE0F' +emoji[man_construction_worker_minimally]=$'\U1F477\U200D\U2642' +emoji[construction_worker_man]=$'\U1F477\U200D\U2642' +emoji[man_construction_worker_light_skin_tone]=$'\U1F477\U1F3FB\U200D\U2642\UFE0F' +emoji[man_construction_worker_light_skin_tone_minimally]=$'\U1F477\U1F3FB\U200D\U2642' +emoji[man_construction_worker_medium_light_skin_tone]=$'\U1F477\U1F3FC\U200D\U2642\UFE0F' +emoji[man_construction_worker_medium_light_skin_tone_minimally]=$'\U1F477\U1F3FC\U200D\U2642' +emoji[man_construction_worker_medium_skin_tone]=$'\U1F477\U1F3FD\U200D\U2642\UFE0F' +emoji[man_construction_worker_medium_skin_tone_minimally]=$'\U1F477\U1F3FD\U200D\U2642' +emoji[man_construction_worker_medium_dark_skin_tone]=$'\U1F477\U1F3FE\U200D\U2642\UFE0F' +emoji[man_construction_worker_medium_dark_skin_tone_minimally]=$'\U1F477\U1F3FE\U200D\U2642' +emoji[man_construction_worker_dark_skin_tone]=$'\U1F477\U1F3FF\U200D\U2642\UFE0F' +emoji[man_construction_worker_dark_skin_tone_minimally]=$'\U1F477\U1F3FF\U200D\U2642' +emoji[woman_construction_worker]=$'\U1F477\U200D\U2640\UFE0F' +emoji[woman_construction_worker_minimally]=$'\U1F477\U200D\U2640' +emoji[construction_worker_woman]=$'\U1F477\U200D\U2640' +emoji[woman_construction_worker_light_skin_tone]=$'\U1F477\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_construction_worker_light_skin_tone_minimally]=$'\U1F477\U1F3FB\U200D\U2640' +emoji[woman_construction_worker_medium_light_skin_tone]=$'\U1F477\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_construction_worker_medium_light_skin_tone_minimally]=$'\U1F477\U1F3FC\U200D\U2640' +emoji[woman_construction_worker_medium_skin_tone]=$'\U1F477\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_construction_worker_medium_skin_tone_minimally]=$'\U1F477\U1F3FD\U200D\U2640' +emoji[woman_construction_worker_medium_dark_skin_tone]=$'\U1F477\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_construction_worker_medium_dark_skin_tone_minimally]=$'\U1F477\U1F3FE\U200D\U2640' +emoji[woman_construction_worker_dark_skin_tone]=$'\U1F477\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_construction_worker_dark_skin_tone_minimally]=$'\U1F477\U1F3FF\U200D\U2640' +emoji[prince]=$'\U1F934' +emoji[prince_light_skin_tone]=$'\U1F934\U1F3FB' +emoji[prince_medium_light_skin_tone]=$'\U1F934\U1F3FC' +emoji[prince_medium_skin_tone]=$'\U1F934\U1F3FD' +emoji[prince_medium_dark_skin_tone]=$'\U1F934\U1F3FE' +emoji[prince_dark_skin_tone]=$'\U1F934\U1F3FF' +emoji[princess]=$'\U1F478' +emoji[princess_light_skin_tone]=$'\U1F478\U1F3FB' +emoji[princess_medium_light_skin_tone]=$'\U1F478\U1F3FC' +emoji[princess_medium_skin_tone]=$'\U1F478\U1F3FD' +emoji[princess_medium_dark_skin_tone]=$'\U1F478\U1F3FE' +emoji[princess_dark_skin_tone]=$'\U1F478\U1F3FF' +emoji[person_wearing_turban]=$'\U1F473' +emoji[person_with_turban]=$'\U1F473' +emoji[person_wearing_turban_light_skin_tone]=$'\U1F473\U1F3FB' +emoji[person_wearing_turban_medium_light_skin_tone]=$'\U1F473\U1F3FC' +emoji[person_wearing_turban_medium_skin_tone]=$'\U1F473\U1F3FD' +emoji[person_wearing_turban_medium_dark_skin_tone]=$'\U1F473\U1F3FE' +emoji[person_wearing_turban_dark_skin_tone]=$'\U1F473\U1F3FF' +emoji[man_wearing_turban]=$'\U1F473\U200D\U2642\UFE0F' +emoji[man_wearing_turban_minimally]=$'\U1F473\U200D\U2642' +emoji[man_with_turban]=$'\U1F473\U200D\U2642' +emoji[man_wearing_turban_light_skin_tone]=$'\U1F473\U1F3FB\U200D\U2642\UFE0F' +emoji[man_wearing_turban_light_skin_tone_minimally]=$'\U1F473\U1F3FB\U200D\U2642' +emoji[man_wearing_turban_medium_light_skin_tone]=$'\U1F473\U1F3FC\U200D\U2642\UFE0F' +emoji[man_wearing_turban_medium_light_skin_tone_minimally]=$'\U1F473\U1F3FC\U200D\U2642' +emoji[man_wearing_turban_medium_skin_tone]=$'\U1F473\U1F3FD\U200D\U2642\UFE0F' +emoji[man_wearing_turban_medium_skin_tone_minimally]=$'\U1F473\U1F3FD\U200D\U2642' +emoji[man_wearing_turban_medium_dark_skin_tone]=$'\U1F473\U1F3FE\U200D\U2642\UFE0F' +emoji[man_wearing_turban_medium_dark_skin_tone_minimally]=$'\U1F473\U1F3FE\U200D\U2642' +emoji[man_wearing_turban_dark_skin_tone]=$'\U1F473\U1F3FF\U200D\U2642\UFE0F' +emoji[man_wearing_turban_dark_skin_tone_minimally]=$'\U1F473\U1F3FF\U200D\U2642' +emoji[woman_wearing_turban]=$'\U1F473\U200D\U2640\UFE0F' +emoji[woman_wearing_turban_minimally]=$'\U1F473\U200D\U2640' +emoji[woman_with_turban]=$'\U1F473\U200D\U2640' +emoji[woman_wearing_turban_light_skin_tone]=$'\U1F473\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_wearing_turban_light_skin_tone_minimally]=$'\U1F473\U1F3FB\U200D\U2640' +emoji[woman_wearing_turban_medium_light_skin_tone]=$'\U1F473\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_wearing_turban_medium_light_skin_tone_minimally]=$'\U1F473\U1F3FC\U200D\U2640' +emoji[woman_wearing_turban_medium_skin_tone]=$'\U1F473\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_wearing_turban_medium_skin_tone_minimally]=$'\U1F473\U1F3FD\U200D\U2640' +emoji[woman_wearing_turban_medium_dark_skin_tone]=$'\U1F473\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_wearing_turban_medium_dark_skin_tone_minimally]=$'\U1F473\U1F3FE\U200D\U2640' +emoji[woman_wearing_turban_dark_skin_tone]=$'\U1F473\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_wearing_turban_dark_skin_tone_minimally]=$'\U1F473\U1F3FF\U200D\U2640' +emoji[man_with_Chinese_cap]=$'\U1F472' +emoji[man_with_gua_pi_mao]=$'\U1F472' +emoji[man_with_Chinese_cap_light_skin_tone]=$'\U1F472\U1F3FB' +emoji[man_with_Chinese_cap_medium_light_skin_tone]=$'\U1F472\U1F3FC' +emoji[man_with_Chinese_cap_medium_skin_tone]=$'\U1F472\U1F3FD' +emoji[man_with_Chinese_cap_medium_dark_skin_tone]=$'\U1F472\U1F3FE' +emoji[man_with_Chinese_cap_dark_skin_tone]=$'\U1F472\U1F3FF' +emoji[woman_with_headscarf]=$'\U1F9D5' +emoji[woman_with_headscarf_light_skin_tone]=$'\U1F9D5\U1F3FB' +emoji[woman_with_headscarf_medium_light_skin_tone]=$'\U1F9D5\U1F3FC' +emoji[woman_with_headscarf_medium_skin_tone]=$'\U1F9D5\U1F3FD' +emoji[woman_with_headscarf_medium_dark_skin_tone]=$'\U1F9D5\U1F3FE' +emoji[woman_with_headscarf_dark_skin_tone]=$'\U1F9D5\U1F3FF' +emoji[man_in_tuxedo]=$'\U1F935' +emoji[man_in_tuxedo_light_skin_tone]=$'\U1F935\U1F3FB' +emoji[man_in_tuxedo_medium_light_skin_tone]=$'\U1F935\U1F3FC' +emoji[man_in_tuxedo_medium_skin_tone]=$'\U1F935\U1F3FD' +emoji[man_in_tuxedo_medium_dark_skin_tone]=$'\U1F935\U1F3FE' +emoji[man_in_tuxedo_dark_skin_tone]=$'\U1F935\U1F3FF' +emoji[bride_with_veil]=$'\U1F470' +emoji[bride_with_veil_light_skin_tone]=$'\U1F470\U1F3FB' +emoji[bride_with_veil_medium_light_skin_tone]=$'\U1F470\U1F3FC' +emoji[bride_with_veil_medium_skin_tone]=$'\U1F470\U1F3FD' +emoji[bride_with_veil_medium_dark_skin_tone]=$'\U1F470\U1F3FE' +emoji[bride_with_veil_dark_skin_tone]=$'\U1F470\U1F3FF' +emoji[pregnant_woman]=$'\U1F930' +emoji[pregnant_woman_light_skin_tone]=$'\U1F930\U1F3FB' +emoji[pregnant_woman_medium_light_skin_tone]=$'\U1F930\U1F3FC' +emoji[pregnant_woman_medium_skin_tone]=$'\U1F930\U1F3FD' +emoji[pregnant_woman_medium_dark_skin_tone]=$'\U1F930\U1F3FE' +emoji[pregnant_woman_dark_skin_tone]=$'\U1F930\U1F3FF' +emoji[breast_feeding]=$'\U1F931' +emoji[breast_feeding_light_skin_tone]=$'\U1F931\U1F3FB' +emoji[breast_feeding_medium_light_skin_tone]=$'\U1F931\U1F3FC' +emoji[breast_feeding_medium_skin_tone]=$'\U1F931\U1F3FD' +emoji[breast_feeding_medium_dark_skin_tone]=$'\U1F931\U1F3FE' +emoji[breast_feeding_dark_skin_tone]=$'\U1F931\U1F3FF' +emoji[baby_angel]=$'\U1F47C' +emoji[angel]=$'\U1F47C' +emoji[baby_angel_light_skin_tone]=$'\U1F47C\U1F3FB' +emoji[baby_angel_medium_light_skin_tone]=$'\U1F47C\U1F3FC' +emoji[baby_angel_medium_skin_tone]=$'\U1F47C\U1F3FD' +emoji[baby_angel_medium_dark_skin_tone]=$'\U1F47C\U1F3FE' +emoji[baby_angel_dark_skin_tone]=$'\U1F47C\U1F3FF' +emoji[Santa_Claus]=$'\U1F385' +emoji[santa]=$'\U1F385' +emoji[Santa_Claus_light_skin_tone]=$'\U1F385\U1F3FB' +emoji[Santa_Claus_medium_light_skin_tone]=$'\U1F385\U1F3FC' +emoji[Santa_Claus_medium_skin_tone]=$'\U1F385\U1F3FD' +emoji[Santa_Claus_medium_dark_skin_tone]=$'\U1F385\U1F3FE' +emoji[Santa_Claus_dark_skin_tone]=$'\U1F385\U1F3FF' +emoji[Mrs_Claus]=$'\U1F936' +emoji[mrs_claus]=$'\U1F936' +emoji[Mrs_Claus_light_skin_tone]=$'\U1F936\U1F3FB' +emoji[Mrs_Claus_medium_light_skin_tone]=$'\U1F936\U1F3FC' +emoji[Mrs_Claus_medium_skin_tone]=$'\U1F936\U1F3FD' +emoji[Mrs_Claus_medium_dark_skin_tone]=$'\U1F936\U1F3FE' +emoji[Mrs_Claus_dark_skin_tone]=$'\U1F936\U1F3FF' +emoji[superhero]=$'\U1F9B8' +emoji[superhero_light_skin_tone]=$'\U1F9B8\U1F3FB' +emoji[superhero_medium_light_skin_tone]=$'\U1F9B8\U1F3FC' +emoji[superhero_medium_skin_tone]=$'\U1F9B8\U1F3FD' +emoji[superhero_medium_dark_skin_tone]=$'\U1F9B8\U1F3FE' +emoji[superhero_dark_skin_tone]=$'\U1F9B8\U1F3FF' +emoji[man_superhero]=$'\U1F9B8\U200D\U2642\UFE0F' +emoji[man_superhero_minimally]=$'\U1F9B8\U200D\U2642' +emoji[superhero_man]=$'\U1F9B8\U200D\U2642' +emoji[man_superhero_light_skin_tone]=$'\U1F9B8\U1F3FB\U200D\U2642\UFE0F' +emoji[man_superhero_light_skin_tone_minimally]=$'\U1F9B8\U1F3FB\U200D\U2642' +emoji[man_superhero_medium_light_skin_tone]=$'\U1F9B8\U1F3FC\U200D\U2642\UFE0F' +emoji[man_superhero_medium_light_skin_tone_minimally]=$'\U1F9B8\U1F3FC\U200D\U2642' +emoji[man_superhero_medium_skin_tone]=$'\U1F9B8\U1F3FD\U200D\U2642\UFE0F' +emoji[man_superhero_medium_skin_tone_minimally]=$'\U1F9B8\U1F3FD\U200D\U2642' +emoji[man_superhero_medium_dark_skin_tone]=$'\U1F9B8\U1F3FE\U200D\U2642\UFE0F' +emoji[man_superhero_medium_dark_skin_tone_minimally]=$'\U1F9B8\U1F3FE\U200D\U2642' +emoji[man_superhero_dark_skin_tone]=$'\U1F9B8\U1F3FF\U200D\U2642\UFE0F' +emoji[man_superhero_dark_skin_tone_minimally]=$'\U1F9B8\U1F3FF\U200D\U2642' +emoji[woman_superhero]=$'\U1F9B8\U200D\U2640\UFE0F' +emoji[woman_superhero_minimally]=$'\U1F9B8\U200D\U2640' +emoji[superhero_woman]=$'\U1F9B8\U200D\U2640' +emoji[woman_superhero_light_skin_tone]=$'\U1F9B8\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_superhero_light_skin_tone_minimally]=$'\U1F9B8\U1F3FB\U200D\U2640' +emoji[woman_superhero_medium_light_skin_tone]=$'\U1F9B8\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_superhero_medium_light_skin_tone_minimally]=$'\U1F9B8\U1F3FC\U200D\U2640' +emoji[woman_superhero_medium_skin_tone]=$'\U1F9B8\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_superhero_medium_skin_tone_minimally]=$'\U1F9B8\U1F3FD\U200D\U2640' +emoji[woman_superhero_medium_dark_skin_tone]=$'\U1F9B8\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_superhero_medium_dark_skin_tone_minimally]=$'\U1F9B8\U1F3FE\U200D\U2640' +emoji[woman_superhero_dark_skin_tone]=$'\U1F9B8\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_superhero_dark_skin_tone_minimally]=$'\U1F9B8\U1F3FF\U200D\U2640' +emoji[supervillain]=$'\U1F9B9' +emoji[supervillain_light_skin_tone]=$'\U1F9B9\U1F3FB' +emoji[supervillain_medium_light_skin_tone]=$'\U1F9B9\U1F3FC' +emoji[supervillain_medium_skin_tone]=$'\U1F9B9\U1F3FD' +emoji[supervillain_medium_dark_skin_tone]=$'\U1F9B9\U1F3FE' +emoji[supervillain_dark_skin_tone]=$'\U1F9B9\U1F3FF' +emoji[man_supervillain]=$'\U1F9B9\U200D\U2642\UFE0F' +emoji[man_supervillain_minimally]=$'\U1F9B9\U200D\U2642' +emoji[supervillain_man]=$'\U1F9B9\U200D\U2642' +emoji[man_supervillain_light_skin_tone]=$'\U1F9B9\U1F3FB\U200D\U2642\UFE0F' +emoji[man_supervillain_light_skin_tone_minimally]=$'\U1F9B9\U1F3FB\U200D\U2642' +emoji[man_supervillain_medium_light_skin_tone]=$'\U1F9B9\U1F3FC\U200D\U2642\UFE0F' +emoji[man_supervillain_medium_light_skin_tone_minimally]=$'\U1F9B9\U1F3FC\U200D\U2642' +emoji[man_supervillain_medium_skin_tone]=$'\U1F9B9\U1F3FD\U200D\U2642\UFE0F' +emoji[man_supervillain_medium_skin_tone_minimally]=$'\U1F9B9\U1F3FD\U200D\U2642' +emoji[man_supervillain_medium_dark_skin_tone]=$'\U1F9B9\U1F3FE\U200D\U2642\UFE0F' +emoji[man_supervillain_medium_dark_skin_tone_minimally]=$'\U1F9B9\U1F3FE\U200D\U2642' +emoji[man_supervillain_dark_skin_tone]=$'\U1F9B9\U1F3FF\U200D\U2642\UFE0F' +emoji[man_supervillain_dark_skin_tone_minimally]=$'\U1F9B9\U1F3FF\U200D\U2642' +emoji[woman_supervillain]=$'\U1F9B9\U200D\U2640\UFE0F' +emoji[woman_supervillain_minimally]=$'\U1F9B9\U200D\U2640' +emoji[supervillain_woman]=$'\U1F9B9\U200D\U2640' +emoji[woman_supervillain_light_skin_tone]=$'\U1F9B9\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_supervillain_light_skin_tone_minimally]=$'\U1F9B9\U1F3FB\U200D\U2640' +emoji[woman_supervillain_medium_light_skin_tone]=$'\U1F9B9\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_supervillain_medium_light_skin_tone_minimally]=$'\U1F9B9\U1F3FC\U200D\U2640' +emoji[woman_supervillain_medium_skin_tone]=$'\U1F9B9\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_supervillain_medium_skin_tone_minimally]=$'\U1F9B9\U1F3FD\U200D\U2640' +emoji[woman_supervillain_medium_dark_skin_tone]=$'\U1F9B9\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_supervillain_medium_dark_skin_tone_minimally]=$'\U1F9B9\U1F3FE\U200D\U2640' +emoji[woman_supervillain_dark_skin_tone]=$'\U1F9B9\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_supervillain_dark_skin_tone_minimally]=$'\U1F9B9\U1F3FF\U200D\U2640' +emoji[mage]=$'\U1F9D9' +emoji[mage_light_skin_tone]=$'\U1F9D9\U1F3FB' +emoji[mage_medium_light_skin_tone]=$'\U1F9D9\U1F3FC' +emoji[mage_medium_skin_tone]=$'\U1F9D9\U1F3FD' +emoji[mage_medium_dark_skin_tone]=$'\U1F9D9\U1F3FE' +emoji[mage_dark_skin_tone]=$'\U1F9D9\U1F3FF' +emoji[man_mage]=$'\U1F9D9\U200D\U2642\UFE0F' +emoji[man_mage_minimally]=$'\U1F9D9\U200D\U2642' +emoji[mage_man]=$'\U1F9D9\U200D\U2642' +emoji[man_mage_light_skin_tone]=$'\U1F9D9\U1F3FB\U200D\U2642\UFE0F' +emoji[man_mage_light_skin_tone_minimally]=$'\U1F9D9\U1F3FB\U200D\U2642' +emoji[man_mage_medium_light_skin_tone]=$'\U1F9D9\U1F3FC\U200D\U2642\UFE0F' +emoji[man_mage_medium_light_skin_tone_minimally]=$'\U1F9D9\U1F3FC\U200D\U2642' +emoji[man_mage_medium_skin_tone]=$'\U1F9D9\U1F3FD\U200D\U2642\UFE0F' +emoji[man_mage_medium_skin_tone_minimally]=$'\U1F9D9\U1F3FD\U200D\U2642' +emoji[man_mage_medium_dark_skin_tone]=$'\U1F9D9\U1F3FE\U200D\U2642\UFE0F' +emoji[man_mage_medium_dark_skin_tone_minimally]=$'\U1F9D9\U1F3FE\U200D\U2642' +emoji[man_mage_dark_skin_tone]=$'\U1F9D9\U1F3FF\U200D\U2642\UFE0F' +emoji[man_mage_dark_skin_tone_minimally]=$'\U1F9D9\U1F3FF\U200D\U2642' +emoji[woman_mage]=$'\U1F9D9\U200D\U2640\UFE0F' +emoji[woman_mage_minimally]=$'\U1F9D9\U200D\U2640' +emoji[mage_woman]=$'\U1F9D9\U200D\U2640' +emoji[woman_mage_light_skin_tone]=$'\U1F9D9\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_mage_light_skin_tone_minimally]=$'\U1F9D9\U1F3FB\U200D\U2640' +emoji[woman_mage_medium_light_skin_tone]=$'\U1F9D9\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_mage_medium_light_skin_tone_minimally]=$'\U1F9D9\U1F3FC\U200D\U2640' +emoji[woman_mage_medium_skin_tone]=$'\U1F9D9\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_mage_medium_skin_tone_minimally]=$'\U1F9D9\U1F3FD\U200D\U2640' +emoji[woman_mage_medium_dark_skin_tone]=$'\U1F9D9\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_mage_medium_dark_skin_tone_minimally]=$'\U1F9D9\U1F3FE\U200D\U2640' +emoji[woman_mage_dark_skin_tone]=$'\U1F9D9\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_mage_dark_skin_tone_minimally]=$'\U1F9D9\U1F3FF\U200D\U2640' +emoji[fairy]=$'\U1F9DA' +emoji[fairy_light_skin_tone]=$'\U1F9DA\U1F3FB' +emoji[fairy_medium_light_skin_tone]=$'\U1F9DA\U1F3FC' +emoji[fairy_medium_skin_tone]=$'\U1F9DA\U1F3FD' +emoji[fairy_medium_dark_skin_tone]=$'\U1F9DA\U1F3FE' +emoji[fairy_dark_skin_tone]=$'\U1F9DA\U1F3FF' +emoji[man_fairy]=$'\U1F9DA\U200D\U2642\UFE0F' +emoji[man_fairy_minimally]=$'\U1F9DA\U200D\U2642' +emoji[fairy_man]=$'\U1F9DA\U200D\U2642' +emoji[man_fairy_light_skin_tone]=$'\U1F9DA\U1F3FB\U200D\U2642\UFE0F' +emoji[man_fairy_light_skin_tone_minimally]=$'\U1F9DA\U1F3FB\U200D\U2642' +emoji[man_fairy_medium_light_skin_tone]=$'\U1F9DA\U1F3FC\U200D\U2642\UFE0F' +emoji[man_fairy_medium_light_skin_tone_minimally]=$'\U1F9DA\U1F3FC\U200D\U2642' +emoji[man_fairy_medium_skin_tone]=$'\U1F9DA\U1F3FD\U200D\U2642\UFE0F' +emoji[man_fairy_medium_skin_tone_minimally]=$'\U1F9DA\U1F3FD\U200D\U2642' +emoji[man_fairy_medium_dark_skin_tone]=$'\U1F9DA\U1F3FE\U200D\U2642\UFE0F' +emoji[man_fairy_medium_dark_skin_tone_minimally]=$'\U1F9DA\U1F3FE\U200D\U2642' +emoji[man_fairy_dark_skin_tone]=$'\U1F9DA\U1F3FF\U200D\U2642\UFE0F' +emoji[man_fairy_dark_skin_tone_minimally]=$'\U1F9DA\U1F3FF\U200D\U2642' +emoji[woman_fairy]=$'\U1F9DA\U200D\U2640\UFE0F' +emoji[woman_fairy_minimally]=$'\U1F9DA\U200D\U2640' +emoji[fairy_woman]=$'\U1F9DA\U200D\U2640' +emoji[woman_fairy_light_skin_tone]=$'\U1F9DA\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_fairy_light_skin_tone_minimally]=$'\U1F9DA\U1F3FB\U200D\U2640' +emoji[woman_fairy_medium_light_skin_tone]=$'\U1F9DA\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_fairy_medium_light_skin_tone_minimally]=$'\U1F9DA\U1F3FC\U200D\U2640' +emoji[woman_fairy_medium_skin_tone]=$'\U1F9DA\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_fairy_medium_skin_tone_minimally]=$'\U1F9DA\U1F3FD\U200D\U2640' +emoji[woman_fairy_medium_dark_skin_tone]=$'\U1F9DA\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_fairy_medium_dark_skin_tone_minimally]=$'\U1F9DA\U1F3FE\U200D\U2640' +emoji[woman_fairy_dark_skin_tone]=$'\U1F9DA\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_fairy_dark_skin_tone_minimally]=$'\U1F9DA\U1F3FF\U200D\U2640' +emoji[vampire]=$'\U1F9DB' +emoji[vampire_light_skin_tone]=$'\U1F9DB\U1F3FB' +emoji[vampire_medium_light_skin_tone]=$'\U1F9DB\U1F3FC' +emoji[vampire_medium_skin_tone]=$'\U1F9DB\U1F3FD' +emoji[vampire_medium_dark_skin_tone]=$'\U1F9DB\U1F3FE' +emoji[vampire_dark_skin_tone]=$'\U1F9DB\U1F3FF' +emoji[man_vampire]=$'\U1F9DB\U200D\U2642\UFE0F' +emoji[man_vampire_minimally]=$'\U1F9DB\U200D\U2642' +emoji[vampire_man]=$'\U1F9DB\U200D\U2642' +emoji[man_vampire_light_skin_tone]=$'\U1F9DB\U1F3FB\U200D\U2642\UFE0F' +emoji[man_vampire_light_skin_tone_minimally]=$'\U1F9DB\U1F3FB\U200D\U2642' +emoji[man_vampire_medium_light_skin_tone]=$'\U1F9DB\U1F3FC\U200D\U2642\UFE0F' +emoji[man_vampire_medium_light_skin_tone_minimally]=$'\U1F9DB\U1F3FC\U200D\U2642' +emoji[man_vampire_medium_skin_tone]=$'\U1F9DB\U1F3FD\U200D\U2642\UFE0F' +emoji[man_vampire_medium_skin_tone_minimally]=$'\U1F9DB\U1F3FD\U200D\U2642' +emoji[man_vampire_medium_dark_skin_tone]=$'\U1F9DB\U1F3FE\U200D\U2642\UFE0F' +emoji[man_vampire_medium_dark_skin_tone_minimally]=$'\U1F9DB\U1F3FE\U200D\U2642' +emoji[man_vampire_dark_skin_tone]=$'\U1F9DB\U1F3FF\U200D\U2642\UFE0F' +emoji[man_vampire_dark_skin_tone_minimally]=$'\U1F9DB\U1F3FF\U200D\U2642' +emoji[woman_vampire]=$'\U1F9DB\U200D\U2640\UFE0F' +emoji[woman_vampire_minimally]=$'\U1F9DB\U200D\U2640' +emoji[vampire_woman]=$'\U1F9DB\U200D\U2640' +emoji[woman_vampire_light_skin_tone]=$'\U1F9DB\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_vampire_light_skin_tone_minimally]=$'\U1F9DB\U1F3FB\U200D\U2640' +emoji[woman_vampire_medium_light_skin_tone]=$'\U1F9DB\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_vampire_medium_light_skin_tone_minimally]=$'\U1F9DB\U1F3FC\U200D\U2640' +emoji[woman_vampire_medium_skin_tone]=$'\U1F9DB\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_vampire_medium_skin_tone_minimally]=$'\U1F9DB\U1F3FD\U200D\U2640' +emoji[woman_vampire_medium_dark_skin_tone]=$'\U1F9DB\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_vampire_medium_dark_skin_tone_minimally]=$'\U1F9DB\U1F3FE\U200D\U2640' +emoji[woman_vampire_dark_skin_tone]=$'\U1F9DB\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_vampire_dark_skin_tone_minimally]=$'\U1F9DB\U1F3FF\U200D\U2640' +emoji[merperson]=$'\U1F9DC' +emoji[merperson_light_skin_tone]=$'\U1F9DC\U1F3FB' +emoji[merperson_medium_light_skin_tone]=$'\U1F9DC\U1F3FC' +emoji[merperson_medium_skin_tone]=$'\U1F9DC\U1F3FD' +emoji[merperson_medium_dark_skin_tone]=$'\U1F9DC\U1F3FE' +emoji[merperson_dark_skin_tone]=$'\U1F9DC\U1F3FF' +emoji[merman]=$'\U1F9DC\U200D\U2642\UFE0F' +emoji[merman_minimally]=$'\U1F9DC\U200D\U2642' +emoji[merman_light_skin_tone]=$'\U1F9DC\U1F3FB\U200D\U2642\UFE0F' +emoji[merman_light_skin_tone_minimally]=$'\U1F9DC\U1F3FB\U200D\U2642' +emoji[merman_medium_light_skin_tone]=$'\U1F9DC\U1F3FC\U200D\U2642\UFE0F' +emoji[merman_medium_light_skin_tone_minimally]=$'\U1F9DC\U1F3FC\U200D\U2642' +emoji[merman_medium_skin_tone]=$'\U1F9DC\U1F3FD\U200D\U2642\UFE0F' +emoji[merman_medium_skin_tone_minimally]=$'\U1F9DC\U1F3FD\U200D\U2642' +emoji[merman_medium_dark_skin_tone]=$'\U1F9DC\U1F3FE\U200D\U2642\UFE0F' +emoji[merman_medium_dark_skin_tone_minimally]=$'\U1F9DC\U1F3FE\U200D\U2642' +emoji[merman_dark_skin_tone]=$'\U1F9DC\U1F3FF\U200D\U2642\UFE0F' +emoji[merman_dark_skin_tone_minimally]=$'\U1F9DC\U1F3FF\U200D\U2642' +emoji[mermaid]=$'\U1F9DC\U200D\U2640\UFE0F' +emoji[mermaid_minimally]=$'\U1F9DC\U200D\U2640' +emoji[mermaid_light_skin_tone]=$'\U1F9DC\U1F3FB\U200D\U2640\UFE0F' +emoji[mermaid_light_skin_tone_minimally]=$'\U1F9DC\U1F3FB\U200D\U2640' +emoji[mermaid_medium_light_skin_tone]=$'\U1F9DC\U1F3FC\U200D\U2640\UFE0F' +emoji[mermaid_medium_light_skin_tone_minimally]=$'\U1F9DC\U1F3FC\U200D\U2640' +emoji[mermaid_medium_skin_tone]=$'\U1F9DC\U1F3FD\U200D\U2640\UFE0F' +emoji[mermaid_medium_skin_tone_minimally]=$'\U1F9DC\U1F3FD\U200D\U2640' +emoji[mermaid_medium_dark_skin_tone]=$'\U1F9DC\U1F3FE\U200D\U2640\UFE0F' +emoji[mermaid_medium_dark_skin_tone_minimally]=$'\U1F9DC\U1F3FE\U200D\U2640' +emoji[mermaid_dark_skin_tone]=$'\U1F9DC\U1F3FF\U200D\U2640\UFE0F' +emoji[mermaid_dark_skin_tone_minimally]=$'\U1F9DC\U1F3FF\U200D\U2640' +emoji[elf]=$'\U1F9DD' +emoji[elf_light_skin_tone]=$'\U1F9DD\U1F3FB' +emoji[elf_medium_light_skin_tone]=$'\U1F9DD\U1F3FC' +emoji[elf_medium_skin_tone]=$'\U1F9DD\U1F3FD' +emoji[elf_medium_dark_skin_tone]=$'\U1F9DD\U1F3FE' +emoji[elf_dark_skin_tone]=$'\U1F9DD\U1F3FF' +emoji[man_elf]=$'\U1F9DD\U200D\U2642\UFE0F' +emoji[man_elf_minimally]=$'\U1F9DD\U200D\U2642' +emoji[elf_man]=$'\U1F9DD\U200D\U2642' +emoji[man_elf_light_skin_tone]=$'\U1F9DD\U1F3FB\U200D\U2642\UFE0F' +emoji[man_elf_light_skin_tone_minimally]=$'\U1F9DD\U1F3FB\U200D\U2642' +emoji[man_elf_medium_light_skin_tone]=$'\U1F9DD\U1F3FC\U200D\U2642\UFE0F' +emoji[man_elf_medium_light_skin_tone_minimally]=$'\U1F9DD\U1F3FC\U200D\U2642' +emoji[man_elf_medium_skin_tone]=$'\U1F9DD\U1F3FD\U200D\U2642\UFE0F' +emoji[man_elf_medium_skin_tone_minimally]=$'\U1F9DD\U1F3FD\U200D\U2642' +emoji[man_elf_medium_dark_skin_tone]=$'\U1F9DD\U1F3FE\U200D\U2642\UFE0F' +emoji[man_elf_medium_dark_skin_tone_minimally]=$'\U1F9DD\U1F3FE\U200D\U2642' +emoji[man_elf_dark_skin_tone]=$'\U1F9DD\U1F3FF\U200D\U2642\UFE0F' +emoji[man_elf_dark_skin_tone_minimally]=$'\U1F9DD\U1F3FF\U200D\U2642' +emoji[woman_elf]=$'\U1F9DD\U200D\U2640\UFE0F' +emoji[woman_elf_minimally]=$'\U1F9DD\U200D\U2640' +emoji[elf_woman]=$'\U1F9DD\U200D\U2640' +emoji[woman_elf_light_skin_tone]=$'\U1F9DD\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_elf_light_skin_tone_minimally]=$'\U1F9DD\U1F3FB\U200D\U2640' +emoji[woman_elf_medium_light_skin_tone]=$'\U1F9DD\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_elf_medium_light_skin_tone_minimally]=$'\U1F9DD\U1F3FC\U200D\U2640' +emoji[woman_elf_medium_skin_tone]=$'\U1F9DD\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_elf_medium_skin_tone_minimally]=$'\U1F9DD\U1F3FD\U200D\U2640' +emoji[woman_elf_medium_dark_skin_tone]=$'\U1F9DD\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_elf_medium_dark_skin_tone_minimally]=$'\U1F9DD\U1F3FE\U200D\U2640' +emoji[woman_elf_dark_skin_tone]=$'\U1F9DD\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_elf_dark_skin_tone_minimally]=$'\U1F9DD\U1F3FF\U200D\U2640' +emoji[genie]=$'\U1F9DE' +emoji[man_genie]=$'\U1F9DE\U200D\U2642\UFE0F' +emoji[man_genie_minimally]=$'\U1F9DE\U200D\U2642' +emoji[genie_man]=$'\U1F9DE\U200D\U2642' +emoji[woman_genie]=$'\U1F9DE\U200D\U2640\UFE0F' +emoji[woman_genie_minimally]=$'\U1F9DE\U200D\U2640' +emoji[genie_woman]=$'\U1F9DE\U200D\U2640' +emoji[zombie]=$'\U1F9DF' +emoji[man_zombie]=$'\U1F9DF\U200D\U2642\UFE0F' +emoji[man_zombie_minimally]=$'\U1F9DF\U200D\U2642' +emoji[zombie_man]=$'\U1F9DF\U200D\U2642' +emoji[woman_zombie]=$'\U1F9DF\U200D\U2640\UFE0F' +emoji[woman_zombie_minimally]=$'\U1F9DF\U200D\U2640' +emoji[zombie_woman]=$'\U1F9DF\U200D\U2640' +emoji[person_getting_massage]=$'\U1F486' +emoji[massage]=$'\U1F486' +emoji[person_getting_massage_light_skin_tone]=$'\U1F486\U1F3FB' +emoji[person_getting_massage_medium_light_skin_tone]=$'\U1F486\U1F3FC' +emoji[person_getting_massage_medium_skin_tone]=$'\U1F486\U1F3FD' +emoji[person_getting_massage_medium_dark_skin_tone]=$'\U1F486\U1F3FE' +emoji[person_getting_massage_dark_skin_tone]=$'\U1F486\U1F3FF' +emoji[man_getting_massage]=$'\U1F486\U200D\U2642\UFE0F' +emoji[man_getting_massage_minimally]=$'\U1F486\U200D\U2642' +emoji[massage_man]=$'\U1F486\U200D\U2642' +emoji[man_getting_massage_light_skin_tone]=$'\U1F486\U1F3FB\U200D\U2642\UFE0F' +emoji[man_getting_massage_light_skin_tone_minimally]=$'\U1F486\U1F3FB\U200D\U2642' +emoji[man_getting_massage_medium_light_skin_tone]=$'\U1F486\U1F3FC\U200D\U2642\UFE0F' +emoji[man_getting_massage_medium_light_skin_tone_minimally]=$'\U1F486\U1F3FC\U200D\U2642' +emoji[man_getting_massage_medium_skin_tone]=$'\U1F486\U1F3FD\U200D\U2642\UFE0F' +emoji[man_getting_massage_medium_skin_tone_minimally]=$'\U1F486\U1F3FD\U200D\U2642' +emoji[man_getting_massage_medium_dark_skin_tone]=$'\U1F486\U1F3FE\U200D\U2642\UFE0F' +emoji[man_getting_massage_medium_dark_skin_tone_minimally]=$'\U1F486\U1F3FE\U200D\U2642' +emoji[man_getting_massage_dark_skin_tone]=$'\U1F486\U1F3FF\U200D\U2642\UFE0F' +emoji[man_getting_massage_dark_skin_tone_minimally]=$'\U1F486\U1F3FF\U200D\U2642' +emoji[woman_getting_massage]=$'\U1F486\U200D\U2640\UFE0F' +emoji[woman_getting_massage_minimally]=$'\U1F486\U200D\U2640' +emoji[massage_woman]=$'\U1F486\U200D\U2640' +emoji[woman_getting_massage_light_skin_tone]=$'\U1F486\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_getting_massage_light_skin_tone_minimally]=$'\U1F486\U1F3FB\U200D\U2640' +emoji[woman_getting_massage_medium_light_skin_tone]=$'\U1F486\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_getting_massage_medium_light_skin_tone_minimally]=$'\U1F486\U1F3FC\U200D\U2640' +emoji[woman_getting_massage_medium_skin_tone]=$'\U1F486\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_getting_massage_medium_skin_tone_minimally]=$'\U1F486\U1F3FD\U200D\U2640' +emoji[woman_getting_massage_medium_dark_skin_tone]=$'\U1F486\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_getting_massage_medium_dark_skin_tone_minimally]=$'\U1F486\U1F3FE\U200D\U2640' +emoji[woman_getting_massage_dark_skin_tone]=$'\U1F486\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_getting_massage_dark_skin_tone_minimally]=$'\U1F486\U1F3FF\U200D\U2640' +emoji[person_getting_haircut]=$'\U1F487' +emoji[haircut]=$'\U1F487' +emoji[person_getting_haircut_light_skin_tone]=$'\U1F487\U1F3FB' +emoji[person_getting_haircut_medium_light_skin_tone]=$'\U1F487\U1F3FC' +emoji[person_getting_haircut_medium_skin_tone]=$'\U1F487\U1F3FD' +emoji[person_getting_haircut_medium_dark_skin_tone]=$'\U1F487\U1F3FE' +emoji[person_getting_haircut_dark_skin_tone]=$'\U1F487\U1F3FF' +emoji[man_getting_haircut]=$'\U1F487\U200D\U2642\UFE0F' +emoji[man_getting_haircut_minimally]=$'\U1F487\U200D\U2642' +emoji[haircut_man]=$'\U1F487\U200D\U2642' +emoji[man_getting_haircut_light_skin_tone]=$'\U1F487\U1F3FB\U200D\U2642\UFE0F' +emoji[man_getting_haircut_light_skin_tone_minimally]=$'\U1F487\U1F3FB\U200D\U2642' +emoji[man_getting_haircut_medium_light_skin_tone]=$'\U1F487\U1F3FC\U200D\U2642\UFE0F' +emoji[man_getting_haircut_medium_light_skin_tone_minimally]=$'\U1F487\U1F3FC\U200D\U2642' +emoji[man_getting_haircut_medium_skin_tone]=$'\U1F487\U1F3FD\U200D\U2642\UFE0F' +emoji[man_getting_haircut_medium_skin_tone_minimally]=$'\U1F487\U1F3FD\U200D\U2642' +emoji[man_getting_haircut_medium_dark_skin_tone]=$'\U1F487\U1F3FE\U200D\U2642\UFE0F' +emoji[man_getting_haircut_medium_dark_skin_tone_minimally]=$'\U1F487\U1F3FE\U200D\U2642' +emoji[man_getting_haircut_dark_skin_tone]=$'\U1F487\U1F3FF\U200D\U2642\UFE0F' +emoji[man_getting_haircut_dark_skin_tone_minimally]=$'\U1F487\U1F3FF\U200D\U2642' +emoji[woman_getting_haircut]=$'\U1F487\U200D\U2640\UFE0F' +emoji[woman_getting_haircut_minimally]=$'\U1F487\U200D\U2640' +emoji[haircut_woman]=$'\U1F487\U200D\U2640' +emoji[woman_getting_haircut_light_skin_tone]=$'\U1F487\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_getting_haircut_light_skin_tone_minimally]=$'\U1F487\U1F3FB\U200D\U2640' +emoji[woman_getting_haircut_medium_light_skin_tone]=$'\U1F487\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_getting_haircut_medium_light_skin_tone_minimally]=$'\U1F487\U1F3FC\U200D\U2640' +emoji[woman_getting_haircut_medium_skin_tone]=$'\U1F487\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_getting_haircut_medium_skin_tone_minimally]=$'\U1F487\U1F3FD\U200D\U2640' +emoji[woman_getting_haircut_medium_dark_skin_tone]=$'\U1F487\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_getting_haircut_medium_dark_skin_tone_minimally]=$'\U1F487\U1F3FE\U200D\U2640' +emoji[woman_getting_haircut_dark_skin_tone]=$'\U1F487\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_getting_haircut_dark_skin_tone_minimally]=$'\U1F487\U1F3FF\U200D\U2640' +emoji[person_walking]=$'\U1F6B6' +emoji[walking]=$'\U1F6B6' +emoji[person_walking_light_skin_tone]=$'\U1F6B6\U1F3FB' +emoji[person_walking_medium_light_skin_tone]=$'\U1F6B6\U1F3FC' +emoji[person_walking_medium_skin_tone]=$'\U1F6B6\U1F3FD' +emoji[person_walking_medium_dark_skin_tone]=$'\U1F6B6\U1F3FE' +emoji[person_walking_dark_skin_tone]=$'\U1F6B6\U1F3FF' +emoji[man_walking]=$'\U1F6B6\U200D\U2642\UFE0F' +emoji[man_walking_minimally]=$'\U1F6B6\U200D\U2642' +emoji[walking_man]=$'\U1F6B6\U200D\U2642' +emoji[man_walking_light_skin_tone]=$'\U1F6B6\U1F3FB\U200D\U2642\UFE0F' +emoji[man_walking_light_skin_tone_minimally]=$'\U1F6B6\U1F3FB\U200D\U2642' +emoji[man_walking_medium_light_skin_tone]=$'\U1F6B6\U1F3FC\U200D\U2642\UFE0F' +emoji[man_walking_medium_light_skin_tone_minimally]=$'\U1F6B6\U1F3FC\U200D\U2642' +emoji[man_walking_medium_skin_tone]=$'\U1F6B6\U1F3FD\U200D\U2642\UFE0F' +emoji[man_walking_medium_skin_tone_minimally]=$'\U1F6B6\U1F3FD\U200D\U2642' +emoji[man_walking_medium_dark_skin_tone]=$'\U1F6B6\U1F3FE\U200D\U2642\UFE0F' +emoji[man_walking_medium_dark_skin_tone_minimally]=$'\U1F6B6\U1F3FE\U200D\U2642' +emoji[man_walking_dark_skin_tone]=$'\U1F6B6\U1F3FF\U200D\U2642\UFE0F' +emoji[man_walking_dark_skin_tone_minimally]=$'\U1F6B6\U1F3FF\U200D\U2642' +emoji[woman_walking]=$'\U1F6B6\U200D\U2640\UFE0F' +emoji[woman_walking_minimally]=$'\U1F6B6\U200D\U2640' +emoji[walking_woman]=$'\U1F6B6\U200D\U2640' +emoji[woman_walking_light_skin_tone]=$'\U1F6B6\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_walking_light_skin_tone_minimally]=$'\U1F6B6\U1F3FB\U200D\U2640' +emoji[woman_walking_medium_light_skin_tone]=$'\U1F6B6\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_walking_medium_light_skin_tone_minimally]=$'\U1F6B6\U1F3FC\U200D\U2640' +emoji[woman_walking_medium_skin_tone]=$'\U1F6B6\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_walking_medium_skin_tone_minimally]=$'\U1F6B6\U1F3FD\U200D\U2640' +emoji[woman_walking_medium_dark_skin_tone]=$'\U1F6B6\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_walking_medium_dark_skin_tone_minimally]=$'\U1F6B6\U1F3FE\U200D\U2640' +emoji[woman_walking_dark_skin_tone]=$'\U1F6B6\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_walking_dark_skin_tone_minimally]=$'\U1F6B6\U1F3FF\U200D\U2640' +emoji[person_standing]=$'\U1F9CD' +emoji[standing_person]=$'\U1F9CD' +emoji[person_standing_light_skin_tone]=$'\U1F9CD\U1F3FB' +emoji[person_standing_medium_light_skin_tone]=$'\U1F9CD\U1F3FC' +emoji[person_standing_medium_skin_tone]=$'\U1F9CD\U1F3FD' +emoji[person_standing_medium_dark_skin_tone]=$'\U1F9CD\U1F3FE' +emoji[person_standing_dark_skin_tone]=$'\U1F9CD\U1F3FF' +emoji[man_standing]=$'\U1F9CD\U200D\U2642\UFE0F' +emoji[man_standing_minimally]=$'\U1F9CD\U200D\U2642' +emoji[standing_man]=$'\U1F9CD\U200D\U2642' +emoji[man_standing_light_skin_tone]=$'\U1F9CD\U1F3FB\U200D\U2642\UFE0F' +emoji[man_standing_light_skin_tone_minimally]=$'\U1F9CD\U1F3FB\U200D\U2642' +emoji[man_standing_medium_light_skin_tone]=$'\U1F9CD\U1F3FC\U200D\U2642\UFE0F' +emoji[man_standing_medium_light_skin_tone_minimally]=$'\U1F9CD\U1F3FC\U200D\U2642' +emoji[man_standing_medium_skin_tone]=$'\U1F9CD\U1F3FD\U200D\U2642\UFE0F' +emoji[man_standing_medium_skin_tone_minimally]=$'\U1F9CD\U1F3FD\U200D\U2642' +emoji[man_standing_medium_dark_skin_tone]=$'\U1F9CD\U1F3FE\U200D\U2642\UFE0F' +emoji[man_standing_medium_dark_skin_tone_minimally]=$'\U1F9CD\U1F3FE\U200D\U2642' +emoji[man_standing_dark_skin_tone]=$'\U1F9CD\U1F3FF\U200D\U2642\UFE0F' +emoji[man_standing_dark_skin_tone_minimally]=$'\U1F9CD\U1F3FF\U200D\U2642' +emoji[woman_standing]=$'\U1F9CD\U200D\U2640\UFE0F' +emoji[woman_standing_minimally]=$'\U1F9CD\U200D\U2640' +emoji[standing_woman]=$'\U1F9CD\U200D\U2640' +emoji[woman_standing_light_skin_tone]=$'\U1F9CD\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_standing_light_skin_tone_minimally]=$'\U1F9CD\U1F3FB\U200D\U2640' +emoji[woman_standing_medium_light_skin_tone]=$'\U1F9CD\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_standing_medium_light_skin_tone_minimally]=$'\U1F9CD\U1F3FC\U200D\U2640' +emoji[woman_standing_medium_skin_tone]=$'\U1F9CD\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_standing_medium_skin_tone_minimally]=$'\U1F9CD\U1F3FD\U200D\U2640' +emoji[woman_standing_medium_dark_skin_tone]=$'\U1F9CD\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_standing_medium_dark_skin_tone_minimally]=$'\U1F9CD\U1F3FE\U200D\U2640' +emoji[woman_standing_dark_skin_tone]=$'\U1F9CD\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_standing_dark_skin_tone_minimally]=$'\U1F9CD\U1F3FF\U200D\U2640' +emoji[person_kneeling]=$'\U1F9CE' +emoji[kneeling_person]=$'\U1F9CE' +emoji[person_kneeling_light_skin_tone]=$'\U1F9CE\U1F3FB' +emoji[person_kneeling_medium_light_skin_tone]=$'\U1F9CE\U1F3FC' +emoji[person_kneeling_medium_skin_tone]=$'\U1F9CE\U1F3FD' +emoji[person_kneeling_medium_dark_skin_tone]=$'\U1F9CE\U1F3FE' +emoji[person_kneeling_dark_skin_tone]=$'\U1F9CE\U1F3FF' +emoji[man_kneeling]=$'\U1F9CE\U200D\U2642\UFE0F' +emoji[man_kneeling_minimally]=$'\U1F9CE\U200D\U2642' +emoji[kneeling_man]=$'\U1F9CE\U200D\U2642' +emoji[man_kneeling_light_skin_tone]=$'\U1F9CE\U1F3FB\U200D\U2642\UFE0F' +emoji[man_kneeling_light_skin_tone_minimally]=$'\U1F9CE\U1F3FB\U200D\U2642' +emoji[man_kneeling_medium_light_skin_tone]=$'\U1F9CE\U1F3FC\U200D\U2642\UFE0F' +emoji[man_kneeling_medium_light_skin_tone_minimally]=$'\U1F9CE\U1F3FC\U200D\U2642' +emoji[man_kneeling_medium_skin_tone]=$'\U1F9CE\U1F3FD\U200D\U2642\UFE0F' +emoji[man_kneeling_medium_skin_tone_minimally]=$'\U1F9CE\U1F3FD\U200D\U2642' +emoji[man_kneeling_medium_dark_skin_tone]=$'\U1F9CE\U1F3FE\U200D\U2642\UFE0F' +emoji[man_kneeling_medium_dark_skin_tone_minimally]=$'\U1F9CE\U1F3FE\U200D\U2642' +emoji[man_kneeling_dark_skin_tone]=$'\U1F9CE\U1F3FF\U200D\U2642\UFE0F' +emoji[man_kneeling_dark_skin_tone_minimally]=$'\U1F9CE\U1F3FF\U200D\U2642' +emoji[woman_kneeling]=$'\U1F9CE\U200D\U2640\UFE0F' +emoji[woman_kneeling_minimally]=$'\U1F9CE\U200D\U2640' +emoji[kneeling_woman]=$'\U1F9CE\U200D\U2640' +emoji[woman_kneeling_light_skin_tone]=$'\U1F9CE\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_kneeling_light_skin_tone_minimally]=$'\U1F9CE\U1F3FB\U200D\U2640' +emoji[woman_kneeling_medium_light_skin_tone]=$'\U1F9CE\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_kneeling_medium_light_skin_tone_minimally]=$'\U1F9CE\U1F3FC\U200D\U2640' +emoji[woman_kneeling_medium_skin_tone]=$'\U1F9CE\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_kneeling_medium_skin_tone_minimally]=$'\U1F9CE\U1F3FD\U200D\U2640' +emoji[woman_kneeling_medium_dark_skin_tone]=$'\U1F9CE\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_kneeling_medium_dark_skin_tone_minimally]=$'\U1F9CE\U1F3FE\U200D\U2640' +emoji[woman_kneeling_dark_skin_tone]=$'\U1F9CE\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_kneeling_dark_skin_tone_minimally]=$'\U1F9CE\U1F3FF\U200D\U2640' +emoji[man_with_probing_cane]=$'\U1F468\U200D\U1F9AF' +emoji[man_with_probing_cane_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F9AF' +emoji[man_with_probing_cane_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F9AF' +emoji[man_with_probing_cane_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F9AF' +emoji[man_with_probing_cane_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F9AF' +emoji[man_with_probing_cane_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F9AF' +emoji[woman_with_probing_cane]=$'\U1F469\U200D\U1F9AF' +emoji[woman_with_probing_cane_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F9AF' +emoji[woman_with_probing_cane_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F9AF' +emoji[woman_with_probing_cane_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F9AF' +emoji[woman_with_probing_cane_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F9AF' +emoji[woman_with_probing_cane_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F9AF' +emoji[man_in_motorized_wheelchair]=$'\U1F468\U200D\U1F9BC' +emoji[man_in_motorized_wheelchair_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F9BC' +emoji[man_in_motorized_wheelchair_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F9BC' +emoji[man_in_motorized_wheelchair_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F9BC' +emoji[man_in_motorized_wheelchair_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F9BC' +emoji[man_in_motorized_wheelchair_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F9BC' +emoji[woman_in_motorized_wheelchair]=$'\U1F469\U200D\U1F9BC' +emoji[woman_in_motorized_wheelchair_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F9BC' +emoji[woman_in_motorized_wheelchair_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F9BC' +emoji[woman_in_motorized_wheelchair_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F9BC' +emoji[woman_in_motorized_wheelchair_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F9BC' +emoji[woman_in_motorized_wheelchair_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F9BC' +emoji[man_in_manual_wheelchair]=$'\U1F468\U200D\U1F9BD' +emoji[man_in_manual_wheelchair_light_skin_tone]=$'\U1F468\U1F3FB\U200D\U1F9BD' +emoji[man_in_manual_wheelchair_medium_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F9BD' +emoji[man_in_manual_wheelchair_medium_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F9BD' +emoji[man_in_manual_wheelchair_medium_dark_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F9BD' +emoji[man_in_manual_wheelchair_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F9BD' +emoji[woman_in_manual_wheelchair]=$'\U1F469\U200D\U1F9BD' +emoji[woman_in_manual_wheelchair_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F9BD' +emoji[woman_in_manual_wheelchair_medium_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F9BD' +emoji[woman_in_manual_wheelchair_medium_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F9BD' +emoji[woman_in_manual_wheelchair_medium_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F9BD' +emoji[woman_in_manual_wheelchair_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F9BD' +emoji[person_running]=$'\U1F3C3' +emoji[runner]=$'\U1F3C3' +emoji[running]=$'\U1F3C3' +emoji[person_running_light_skin_tone]=$'\U1F3C3\U1F3FB' +emoji[person_running_medium_light_skin_tone]=$'\U1F3C3\U1F3FC' +emoji[person_running_medium_skin_tone]=$'\U1F3C3\U1F3FD' +emoji[person_running_medium_dark_skin_tone]=$'\U1F3C3\U1F3FE' +emoji[person_running_dark_skin_tone]=$'\U1F3C3\U1F3FF' +emoji[man_running]=$'\U1F3C3\U200D\U2642\UFE0F' +emoji[man_running_minimally]=$'\U1F3C3\U200D\U2642' +emoji[running_man]=$'\U1F3C3\U200D\U2642' +emoji[man_running_light_skin_tone]=$'\U1F3C3\U1F3FB\U200D\U2642\UFE0F' +emoji[man_running_light_skin_tone_minimally]=$'\U1F3C3\U1F3FB\U200D\U2642' +emoji[man_running_medium_light_skin_tone]=$'\U1F3C3\U1F3FC\U200D\U2642\UFE0F' +emoji[man_running_medium_light_skin_tone_minimally]=$'\U1F3C3\U1F3FC\U200D\U2642' +emoji[man_running_medium_skin_tone]=$'\U1F3C3\U1F3FD\U200D\U2642\UFE0F' +emoji[man_running_medium_skin_tone_minimally]=$'\U1F3C3\U1F3FD\U200D\U2642' +emoji[man_running_medium_dark_skin_tone]=$'\U1F3C3\U1F3FE\U200D\U2642\UFE0F' +emoji[man_running_medium_dark_skin_tone_minimally]=$'\U1F3C3\U1F3FE\U200D\U2642' +emoji[man_running_dark_skin_tone]=$'\U1F3C3\U1F3FF\U200D\U2642\UFE0F' +emoji[man_running_dark_skin_tone_minimally]=$'\U1F3C3\U1F3FF\U200D\U2642' +emoji[woman_running]=$'\U1F3C3\U200D\U2640\UFE0F' +emoji[woman_running_minimally]=$'\U1F3C3\U200D\U2640' +emoji[running_woman]=$'\U1F3C3\U200D\U2640' +emoji[woman_running_light_skin_tone]=$'\U1F3C3\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_running_light_skin_tone_minimally]=$'\U1F3C3\U1F3FB\U200D\U2640' +emoji[woman_running_medium_light_skin_tone]=$'\U1F3C3\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_running_medium_light_skin_tone_minimally]=$'\U1F3C3\U1F3FC\U200D\U2640' +emoji[woman_running_medium_skin_tone]=$'\U1F3C3\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_running_medium_skin_tone_minimally]=$'\U1F3C3\U1F3FD\U200D\U2640' +emoji[woman_running_medium_dark_skin_tone]=$'\U1F3C3\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_running_medium_dark_skin_tone_minimally]=$'\U1F3C3\U1F3FE\U200D\U2640' +emoji[woman_running_dark_skin_tone]=$'\U1F3C3\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_running_dark_skin_tone_minimally]=$'\U1F3C3\U1F3FF\U200D\U2640' +emoji[woman_dancing]=$'\U1F483' +emoji[dancer]=$'\U1F483' +emoji[woman_dancing_light_skin_tone]=$'\U1F483\U1F3FB' +emoji[woman_dancing_medium_light_skin_tone]=$'\U1F483\U1F3FC' +emoji[woman_dancing_medium_skin_tone]=$'\U1F483\U1F3FD' +emoji[woman_dancing_medium_dark_skin_tone]=$'\U1F483\U1F3FE' +emoji[woman_dancing_dark_skin_tone]=$'\U1F483\U1F3FF' +emoji[woman_dancing_dark_skin_tone_1]=$'\U1F57A' +emoji[man_dancing]=$'\U1F57A' +emoji[man_dancing_light_skin_tone]=$'\U1F57A\U1F3FB' +emoji[man_dancing_medium_light_skin_tone]=$'\U1F57A\U1F3FC' +emoji[man_dancing_medium_skin_tone]=$'\U1F57A\U1F3FD' +emoji[man_dancing_medium_dark_skin_tone]=$'\U1F57A\U1F3FE' +emoji[man_dancing_dark_skin_tone]=$'\U1F57A\U1F3FF' +emoji[man_in_suit_levitating]=$'\U1F574\UFE0F' +emoji[man_in_suit_levitating_unqualified]=$'\U1F574' +emoji[business_suit_levitating]=$'\U1F574' +emoji[man_in_suit_levitating_light_skin_tone]=$'\U1F574\U1F3FB' +emoji[man_in_suit_levitating_medium_light_skin_tone]=$'\U1F574\U1F3FC' +emoji[man_in_suit_levitating_medium_skin_tone]=$'\U1F574\U1F3FD' +emoji[man_in_suit_levitating_medium_dark_skin_tone]=$'\U1F574\U1F3FE' +emoji[man_in_suit_levitating_dark_skin_tone]=$'\U1F574\U1F3FF' +emoji[people_with_bunny_ears]=$'\U1F46F' +emoji[dancers]=$'\U1F46F' +emoji[men_with_bunny_ears]=$'\U1F46F\U200D\U2642\UFE0F' +emoji[men_with_bunny_ears_minimally]=$'\U1F46F\U200D\U2642' +emoji[dancing_men]=$'\U1F46F\U200D\U2642' +emoji[women_with_bunny_ears]=$'\U1F46F\U200D\U2640\UFE0F' +emoji[women_with_bunny_ears_minimally]=$'\U1F46F\U200D\U2640' +emoji[dancing_women]=$'\U1F46F\U200D\U2640' +emoji[person_in_steamy_room]=$'\U1F9D6' +emoji[sauna_person]=$'\U1F9D6' +emoji[person_in_steamy_room_light_skin_tone]=$'\U1F9D6\U1F3FB' +emoji[person_in_steamy_room_medium_light_skin_tone]=$'\U1F9D6\U1F3FC' +emoji[person_in_steamy_room_medium_skin_tone]=$'\U1F9D6\U1F3FD' +emoji[person_in_steamy_room_medium_dark_skin_tone]=$'\U1F9D6\U1F3FE' +emoji[person_in_steamy_room_dark_skin_tone]=$'\U1F9D6\U1F3FF' +emoji[man_in_steamy_room]=$'\U1F9D6\U200D\U2642\UFE0F' +emoji[man_in_steamy_room_minimally]=$'\U1F9D6\U200D\U2642' +emoji[sauna_man]=$'\U1F9D6\U200D\U2642' +emoji[man_in_steamy_room_light_skin_tone]=$'\U1F9D6\U1F3FB\U200D\U2642\UFE0F' +emoji[man_in_steamy_room_light_skin_tone_minimally]=$'\U1F9D6\U1F3FB\U200D\U2642' +emoji[man_in_steamy_room_medium_light_skin_tone]=$'\U1F9D6\U1F3FC\U200D\U2642\UFE0F' +emoji[man_in_steamy_room_medium_light_skin_tone_minimally]=$'\U1F9D6\U1F3FC\U200D\U2642' +emoji[man_in_steamy_room_medium_skin_tone]=$'\U1F9D6\U1F3FD\U200D\U2642\UFE0F' +emoji[man_in_steamy_room_medium_skin_tone_minimally]=$'\U1F9D6\U1F3FD\U200D\U2642' +emoji[man_in_steamy_room_medium_dark_skin_tone]=$'\U1F9D6\U1F3FE\U200D\U2642\UFE0F' +emoji[man_in_steamy_room_medium_dark_skin_tone_minimally]=$'\U1F9D6\U1F3FE\U200D\U2642' +emoji[man_in_steamy_room_dark_skin_tone]=$'\U1F9D6\U1F3FF\U200D\U2642\UFE0F' +emoji[man_in_steamy_room_dark_skin_tone_minimally]=$'\U1F9D6\U1F3FF\U200D\U2642' +emoji[woman_in_steamy_room]=$'\U1F9D6\U200D\U2640\UFE0F' +emoji[woman_in_steamy_room_minimally]=$'\U1F9D6\U200D\U2640' +emoji[sauna_woman]=$'\U1F9D6\U200D\U2640' +emoji[woman_in_steamy_room_light_skin_tone]=$'\U1F9D6\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_in_steamy_room_light_skin_tone_minimally]=$'\U1F9D6\U1F3FB\U200D\U2640' +emoji[woman_in_steamy_room_medium_light_skin_tone]=$'\U1F9D6\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_in_steamy_room_medium_light_skin_tone_minimally]=$'\U1F9D6\U1F3FC\U200D\U2640' +emoji[woman_in_steamy_room_medium_skin_tone]=$'\U1F9D6\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_in_steamy_room_medium_skin_tone_minimally]=$'\U1F9D6\U1F3FD\U200D\U2640' +emoji[woman_in_steamy_room_medium_dark_skin_tone]=$'\U1F9D6\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_in_steamy_room_medium_dark_skin_tone_minimally]=$'\U1F9D6\U1F3FE\U200D\U2640' +emoji[woman_in_steamy_room_dark_skin_tone]=$'\U1F9D6\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_in_steamy_room_dark_skin_tone_minimally]=$'\U1F9D6\U1F3FF\U200D\U2640' +emoji[person_climbing]=$'\U1F9D7' +emoji[climbing]=$'\U1F9D7' +emoji[person_climbing_light_skin_tone]=$'\U1F9D7\U1F3FB' +emoji[person_climbing_medium_light_skin_tone]=$'\U1F9D7\U1F3FC' +emoji[person_climbing_medium_skin_tone]=$'\U1F9D7\U1F3FD' +emoji[person_climbing_medium_dark_skin_tone]=$'\U1F9D7\U1F3FE' +emoji[person_climbing_dark_skin_tone]=$'\U1F9D7\U1F3FF' +emoji[man_climbing]=$'\U1F9D7\U200D\U2642\UFE0F' +emoji[man_climbing_minimally]=$'\U1F9D7\U200D\U2642' +emoji[climbing_man]=$'\U1F9D7\U200D\U2642' +emoji[man_climbing_light_skin_tone]=$'\U1F9D7\U1F3FB\U200D\U2642\UFE0F' +emoji[man_climbing_light_skin_tone_minimally]=$'\U1F9D7\U1F3FB\U200D\U2642' +emoji[man_climbing_medium_light_skin_tone]=$'\U1F9D7\U1F3FC\U200D\U2642\UFE0F' +emoji[man_climbing_medium_light_skin_tone_minimally]=$'\U1F9D7\U1F3FC\U200D\U2642' +emoji[man_climbing_medium_skin_tone]=$'\U1F9D7\U1F3FD\U200D\U2642\UFE0F' +emoji[man_climbing_medium_skin_tone_minimally]=$'\U1F9D7\U1F3FD\U200D\U2642' +emoji[man_climbing_medium_dark_skin_tone]=$'\U1F9D7\U1F3FE\U200D\U2642\UFE0F' +emoji[man_climbing_medium_dark_skin_tone_minimally]=$'\U1F9D7\U1F3FE\U200D\U2642' +emoji[man_climbing_dark_skin_tone]=$'\U1F9D7\U1F3FF\U200D\U2642\UFE0F' +emoji[man_climbing_dark_skin_tone_minimally]=$'\U1F9D7\U1F3FF\U200D\U2642' +emoji[woman_climbing]=$'\U1F9D7\U200D\U2640\UFE0F' +emoji[woman_climbing_minimally]=$'\U1F9D7\U200D\U2640' +emoji[climbing_woman]=$'\U1F9D7\U200D\U2640' +emoji[woman_climbing_light_skin_tone]=$'\U1F9D7\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_climbing_light_skin_tone_minimally]=$'\U1F9D7\U1F3FB\U200D\U2640' +emoji[woman_climbing_medium_light_skin_tone]=$'\U1F9D7\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_climbing_medium_light_skin_tone_minimally]=$'\U1F9D7\U1F3FC\U200D\U2640' +emoji[woman_climbing_medium_skin_tone]=$'\U1F9D7\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_climbing_medium_skin_tone_minimally]=$'\U1F9D7\U1F3FD\U200D\U2640' +emoji[woman_climbing_medium_dark_skin_tone]=$'\U1F9D7\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_climbing_medium_dark_skin_tone_minimally]=$'\U1F9D7\U1F3FE\U200D\U2640' +emoji[woman_climbing_dark_skin_tone]=$'\U1F9D7\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_climbing_dark_skin_tone_minimally]=$'\U1F9D7\U1F3FF\U200D\U2640' +emoji[person_fencing]=$'\U1F93A' +emoji[horse_racing]=$'\U1F3C7' +emoji[horse_racing_light_skin_tone]=$'\U1F3C7\U1F3FB' +emoji[horse_racing_medium_light_skin_tone]=$'\U1F3C7\U1F3FC' +emoji[horse_racing_medium_skin_tone]=$'\U1F3C7\U1F3FD' +emoji[horse_racing_medium_dark_skin_tone]=$'\U1F3C7\U1F3FE' +emoji[horse_racing_dark_skin_tone]=$'\U1F3C7\U1F3FF' +emoji[skier]=$'\U26F7\UFE0F' +emoji[skier_unqualified]=$'\U26F7' +emoji[snowboarder]=$'\U1F3C2' +emoji[snowboarder_light_skin_tone]=$'\U1F3C2\U1F3FB' +emoji[snowboarder_medium_light_skin_tone]=$'\U1F3C2\U1F3FC' +emoji[snowboarder_medium_skin_tone]=$'\U1F3C2\U1F3FD' +emoji[snowboarder_medium_dark_skin_tone]=$'\U1F3C2\U1F3FE' +emoji[snowboarder_dark_skin_tone]=$'\U1F3C2\U1F3FF' +emoji[person_golfing]=$'\U1F3CC\UFE0F' +emoji[person_golfing_unqualified]=$'\U1F3CC' +emoji[golfing]=$'\U1F3CC' +emoji[person_golfing_light_skin_tone]=$'\U1F3CC\U1F3FB' +emoji[person_golfing_medium_light_skin_tone]=$'\U1F3CC\U1F3FC' +emoji[person_golfing_medium_skin_tone]=$'\U1F3CC\U1F3FD' +emoji[person_golfing_medium_dark_skin_tone]=$'\U1F3CC\U1F3FE' +emoji[person_golfing_dark_skin_tone]=$'\U1F3CC\U1F3FF' +emoji[man_golfing]=$'\U1F3CC\UFE0F\U200D\U2642\UFE0F' +emoji[golfing_man]=$'\U1F3CC\UFE0F\U200D\U2642\UFE0F' +emoji[man_golfing_unqualified]=$'\U1F3CC\U200D\U2642\UFE0F' +emoji[man_golfing_unqualified_1]=$'\U1F3CC\UFE0F\U200D\U2642' +emoji[man_golfing_unqualified_2]=$'\U1F3CC\U200D\U2642' +emoji[man_golfing_light_skin_tone]=$'\U1F3CC\U1F3FB\U200D\U2642\UFE0F' +emoji[man_golfing_light_skin_tone_minimally]=$'\U1F3CC\U1F3FB\U200D\U2642' +emoji[man_golfing_medium_light_skin_tone]=$'\U1F3CC\U1F3FC\U200D\U2642\UFE0F' +emoji[man_golfing_medium_light_skin_tone_minimally]=$'\U1F3CC\U1F3FC\U200D\U2642' +emoji[man_golfing_medium_skin_tone]=$'\U1F3CC\U1F3FD\U200D\U2642\UFE0F' +emoji[man_golfing_medium_skin_tone_minimally]=$'\U1F3CC\U1F3FD\U200D\U2642' +emoji[man_golfing_medium_dark_skin_tone]=$'\U1F3CC\U1F3FE\U200D\U2642\UFE0F' +emoji[man_golfing_medium_dark_skin_tone_minimally]=$'\U1F3CC\U1F3FE\U200D\U2642' +emoji[man_golfing_dark_skin_tone]=$'\U1F3CC\U1F3FF\U200D\U2642\UFE0F' +emoji[man_golfing_dark_skin_tone_minimally]=$'\U1F3CC\U1F3FF\U200D\U2642' +emoji[woman_golfing]=$'\U1F3CC\UFE0F\U200D\U2640\UFE0F' +emoji[golfing_woman]=$'\U1F3CC\UFE0F\U200D\U2640\UFE0F' +emoji[woman_golfing_unqualified]=$'\U1F3CC\U200D\U2640\UFE0F' +emoji[woman_golfing_unqualified_1]=$'\U1F3CC\UFE0F\U200D\U2640' +emoji[woman_golfing_unqualified_2]=$'\U1F3CC\U200D\U2640' +emoji[woman_golfing_light_skin_tone]=$'\U1F3CC\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_golfing_light_skin_tone_minimally]=$'\U1F3CC\U1F3FB\U200D\U2640' +emoji[woman_golfing_medium_light_skin_tone]=$'\U1F3CC\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_golfing_medium_light_skin_tone_minimally]=$'\U1F3CC\U1F3FC\U200D\U2640' +emoji[woman_golfing_medium_skin_tone]=$'\U1F3CC\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_golfing_medium_skin_tone_minimally]=$'\U1F3CC\U1F3FD\U200D\U2640' +emoji[woman_golfing_medium_dark_skin_tone]=$'\U1F3CC\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_golfing_medium_dark_skin_tone_minimally]=$'\U1F3CC\U1F3FE\U200D\U2640' +emoji[woman_golfing_dark_skin_tone]=$'\U1F3CC\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_golfing_dark_skin_tone_minimally]=$'\U1F3CC\U1F3FF\U200D\U2640' +emoji[person_surfing]=$'\U1F3C4' +emoji[surfer]=$'\U1F3C4' +emoji[person_surfing_light_skin_tone]=$'\U1F3C4\U1F3FB' +emoji[person_surfing_medium_light_skin_tone]=$'\U1F3C4\U1F3FC' +emoji[person_surfing_medium_skin_tone]=$'\U1F3C4\U1F3FD' +emoji[person_surfing_medium_dark_skin_tone]=$'\U1F3C4\U1F3FE' +emoji[person_surfing_dark_skin_tone]=$'\U1F3C4\U1F3FF' +emoji[man_surfing]=$'\U1F3C4\U200D\U2642\UFE0F' +emoji[man_surfing_minimally]=$'\U1F3C4\U200D\U2642' +emoji[surfing_man]=$'\U1F3C4\U200D\U2642' +emoji[man_surfing_light_skin_tone]=$'\U1F3C4\U1F3FB\U200D\U2642\UFE0F' +emoji[man_surfing_light_skin_tone_minimally]=$'\U1F3C4\U1F3FB\U200D\U2642' +emoji[man_surfing_medium_light_skin_tone]=$'\U1F3C4\U1F3FC\U200D\U2642\UFE0F' +emoji[man_surfing_medium_light_skin_tone_minimally]=$'\U1F3C4\U1F3FC\U200D\U2642' +emoji[man_surfing_medium_skin_tone]=$'\U1F3C4\U1F3FD\U200D\U2642\UFE0F' +emoji[man_surfing_medium_skin_tone_minimally]=$'\U1F3C4\U1F3FD\U200D\U2642' +emoji[man_surfing_medium_dark_skin_tone]=$'\U1F3C4\U1F3FE\U200D\U2642\UFE0F' +emoji[man_surfing_medium_dark_skin_tone_minimally]=$'\U1F3C4\U1F3FE\U200D\U2642' +emoji[man_surfing_dark_skin_tone]=$'\U1F3C4\U1F3FF\U200D\U2642\UFE0F' +emoji[man_surfing_dark_skin_tone_minimally]=$'\U1F3C4\U1F3FF\U200D\U2642' +emoji[woman_surfing]=$'\U1F3C4\U200D\U2640\UFE0F' +emoji[woman_surfing_minimally]=$'\U1F3C4\U200D\U2640' +emoji[surfing_woman]=$'\U1F3C4\U200D\U2640' +emoji[woman_surfing_light_skin_tone]=$'\U1F3C4\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_surfing_light_skin_tone_minimally]=$'\U1F3C4\U1F3FB\U200D\U2640' +emoji[woman_surfing_medium_light_skin_tone]=$'\U1F3C4\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_surfing_medium_light_skin_tone_minimally]=$'\U1F3C4\U1F3FC\U200D\U2640' +emoji[woman_surfing_medium_skin_tone]=$'\U1F3C4\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_surfing_medium_skin_tone_minimally]=$'\U1F3C4\U1F3FD\U200D\U2640' +emoji[woman_surfing_medium_dark_skin_tone]=$'\U1F3C4\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_surfing_medium_dark_skin_tone_minimally]=$'\U1F3C4\U1F3FE\U200D\U2640' +emoji[woman_surfing_dark_skin_tone]=$'\U1F3C4\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_surfing_dark_skin_tone_minimally]=$'\U1F3C4\U1F3FF\U200D\U2640' +emoji[person_rowing_boat]=$'\U1F6A3' +emoji[rowboat]=$'\U1F6A3' +emoji[person_rowing_boat_light_skin_tone]=$'\U1F6A3\U1F3FB' +emoji[person_rowing_boat_medium_light_skin_tone]=$'\U1F6A3\U1F3FC' +emoji[person_rowing_boat_medium_skin_tone]=$'\U1F6A3\U1F3FD' +emoji[person_rowing_boat_medium_dark_skin_tone]=$'\U1F6A3\U1F3FE' +emoji[person_rowing_boat_dark_skin_tone]=$'\U1F6A3\U1F3FF' +emoji[man_rowing_boat]=$'\U1F6A3\U200D\U2642\UFE0F' +emoji[man_rowing_boat_minimally]=$'\U1F6A3\U200D\U2642' +emoji[rowing_man]=$'\U1F6A3\U200D\U2642' +emoji[man_rowing_boat_light_skin_tone]=$'\U1F6A3\U1F3FB\U200D\U2642\UFE0F' +emoji[man_rowing_boat_light_skin_tone_minimally]=$'\U1F6A3\U1F3FB\U200D\U2642' +emoji[man_rowing_boat_medium_light_skin_tone]=$'\U1F6A3\U1F3FC\U200D\U2642\UFE0F' +emoji[man_rowing_boat_medium_light_skin_tone_minimally]=$'\U1F6A3\U1F3FC\U200D\U2642' +emoji[man_rowing_boat_medium_skin_tone]=$'\U1F6A3\U1F3FD\U200D\U2642\UFE0F' +emoji[man_rowing_boat_medium_skin_tone_minimally]=$'\U1F6A3\U1F3FD\U200D\U2642' +emoji[man_rowing_boat_medium_dark_skin_tone]=$'\U1F6A3\U1F3FE\U200D\U2642\UFE0F' +emoji[man_rowing_boat_medium_dark_skin_tone_minimally]=$'\U1F6A3\U1F3FE\U200D\U2642' +emoji[man_rowing_boat_dark_skin_tone]=$'\U1F6A3\U1F3FF\U200D\U2642\UFE0F' +emoji[man_rowing_boat_dark_skin_tone_minimally]=$'\U1F6A3\U1F3FF\U200D\U2642' +emoji[woman_rowing_boat]=$'\U1F6A3\U200D\U2640\UFE0F' +emoji[woman_rowing_boat_minimally]=$'\U1F6A3\U200D\U2640' +emoji[rowing_woman]=$'\U1F6A3\U200D\U2640' +emoji[woman_rowing_boat_light_skin_tone]=$'\U1F6A3\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_rowing_boat_light_skin_tone_minimally]=$'\U1F6A3\U1F3FB\U200D\U2640' +emoji[woman_rowing_boat_medium_light_skin_tone]=$'\U1F6A3\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_rowing_boat_medium_light_skin_tone_minimally]=$'\U1F6A3\U1F3FC\U200D\U2640' +emoji[woman_rowing_boat_medium_skin_tone]=$'\U1F6A3\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_rowing_boat_medium_skin_tone_minimally]=$'\U1F6A3\U1F3FD\U200D\U2640' +emoji[woman_rowing_boat_medium_dark_skin_tone]=$'\U1F6A3\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_rowing_boat_medium_dark_skin_tone_minimally]=$'\U1F6A3\U1F3FE\U200D\U2640' +emoji[woman_rowing_boat_dark_skin_tone]=$'\U1F6A3\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_rowing_boat_dark_skin_tone_minimally]=$'\U1F6A3\U1F3FF\U200D\U2640' +emoji[person_swimming]=$'\U1F3CA' +emoji[swimmer]=$'\U1F3CA' +emoji[person_swimming_light_skin_tone]=$'\U1F3CA\U1F3FB' +emoji[person_swimming_medium_light_skin_tone]=$'\U1F3CA\U1F3FC' +emoji[person_swimming_medium_skin_tone]=$'\U1F3CA\U1F3FD' +emoji[person_swimming_medium_dark_skin_tone]=$'\U1F3CA\U1F3FE' +emoji[person_swimming_dark_skin_tone]=$'\U1F3CA\U1F3FF' +emoji[man_swimming]=$'\U1F3CA\U200D\U2642\UFE0F' +emoji[man_swimming_minimally]=$'\U1F3CA\U200D\U2642' +emoji[swimming_man]=$'\U1F3CA\U200D\U2642' +emoji[man_swimming_light_skin_tone]=$'\U1F3CA\U1F3FB\U200D\U2642\UFE0F' +emoji[man_swimming_light_skin_tone_minimally]=$'\U1F3CA\U1F3FB\U200D\U2642' +emoji[man_swimming_medium_light_skin_tone]=$'\U1F3CA\U1F3FC\U200D\U2642\UFE0F' +emoji[man_swimming_medium_light_skin_tone_minimally]=$'\U1F3CA\U1F3FC\U200D\U2642' +emoji[man_swimming_medium_skin_tone]=$'\U1F3CA\U1F3FD\U200D\U2642\UFE0F' +emoji[man_swimming_medium_skin_tone_minimally]=$'\U1F3CA\U1F3FD\U200D\U2642' +emoji[man_swimming_medium_dark_skin_tone]=$'\U1F3CA\U1F3FE\U200D\U2642\UFE0F' +emoji[man_swimming_medium_dark_skin_tone_minimally]=$'\U1F3CA\U1F3FE\U200D\U2642' +emoji[man_swimming_dark_skin_tone]=$'\U1F3CA\U1F3FF\U200D\U2642\UFE0F' +emoji[man_swimming_dark_skin_tone_minimally]=$'\U1F3CA\U1F3FF\U200D\U2642' +emoji[woman_swimming]=$'\U1F3CA\U200D\U2640\UFE0F' +emoji[woman_swimming_minimally]=$'\U1F3CA\U200D\U2640' +emoji[swimming_woman]=$'\U1F3CA\U200D\U2640' +emoji[woman_swimming_light_skin_tone]=$'\U1F3CA\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_swimming_light_skin_tone_minimally]=$'\U1F3CA\U1F3FB\U200D\U2640' +emoji[woman_swimming_medium_light_skin_tone]=$'\U1F3CA\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_swimming_medium_light_skin_tone_minimally]=$'\U1F3CA\U1F3FC\U200D\U2640' +emoji[woman_swimming_medium_skin_tone]=$'\U1F3CA\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_swimming_medium_skin_tone_minimally]=$'\U1F3CA\U1F3FD\U200D\U2640' +emoji[woman_swimming_medium_dark_skin_tone]=$'\U1F3CA\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_swimming_medium_dark_skin_tone_minimally]=$'\U1F3CA\U1F3FE\U200D\U2640' +emoji[woman_swimming_dark_skin_tone]=$'\U1F3CA\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_swimming_dark_skin_tone_minimally]=$'\U1F3CA\U1F3FF\U200D\U2640' +emoji[person_bouncing_ball]=$'\U26F9\UFE0F' +emoji[person_bouncing_ball_unqualified]=$'\U26F9' +emoji[bouncing_ball_person]=$'\U26F9' +emoji[person_bouncing_ball_light_skin_tone]=$'\U26F9\U1F3FB' +emoji[person_bouncing_ball_medium_light_skin_tone]=$'\U26F9\U1F3FC' +emoji[person_bouncing_ball_medium_skin_tone]=$'\U26F9\U1F3FD' +emoji[person_bouncing_ball_medium_dark_skin_tone]=$'\U26F9\U1F3FE' +emoji[person_bouncing_ball_dark_skin_tone]=$'\U26F9\U1F3FF' +emoji[man_bouncing_ball]=$'\U26F9\UFE0F\U200D\U2642\UFE0F' +emoji[bouncing_ball_man]=$'\U26F9\UFE0F\U200D\U2642\UFE0F' +emoji[basketball_man]=$'\U26F9\UFE0F\U200D\U2642\UFE0F' +emoji[man_bouncing_ball_unqualified]=$'\U26F9\U200D\U2642\UFE0F' +emoji[man_bouncing_ball_unqualified_1]=$'\U26F9\UFE0F\U200D\U2642' +emoji[man_bouncing_ball_unqualified_2]=$'\U26F9\U200D\U2642' +emoji[man_bouncing_ball_light_skin_tone]=$'\U26F9\U1F3FB\U200D\U2642\UFE0F' +emoji[man_bouncing_ball_light_skin_tone_minimally]=$'\U26F9\U1F3FB\U200D\U2642' +emoji[man_bouncing_ball_medium_light_skin_tone]=$'\U26F9\U1F3FC\U200D\U2642\UFE0F' +emoji[man_bouncing_ball_medium_light_skin_tone_minimally]=$'\U26F9\U1F3FC\U200D\U2642' +emoji[man_bouncing_ball_medium_skin_tone]=$'\U26F9\U1F3FD\U200D\U2642\UFE0F' +emoji[man_bouncing_ball_medium_skin_tone_minimally]=$'\U26F9\U1F3FD\U200D\U2642' +emoji[man_bouncing_ball_medium_dark_skin_tone]=$'\U26F9\U1F3FE\U200D\U2642\UFE0F' +emoji[man_bouncing_ball_medium_dark_skin_tone_minimally]=$'\U26F9\U1F3FE\U200D\U2642' +emoji[man_bouncing_ball_dark_skin_tone]=$'\U26F9\U1F3FF\U200D\U2642\UFE0F' +emoji[man_bouncing_ball_dark_skin_tone_minimally]=$'\U26F9\U1F3FF\U200D\U2642' +emoji[woman_bouncing_ball]=$'\U26F9\UFE0F\U200D\U2640\UFE0F' +emoji[bouncing_ball_woman]=$'\U26F9\UFE0F\U200D\U2640\UFE0F' +emoji[basketball_woman]=$'\U26F9\UFE0F\U200D\U2640\UFE0F' +emoji[woman_bouncing_ball_unqualified]=$'\U26F9\U200D\U2640\UFE0F' +emoji[woman_bouncing_ball_unqualified_1]=$'\U26F9\UFE0F\U200D\U2640' +emoji[woman_bouncing_ball_unqualified_2]=$'\U26F9\U200D\U2640' +emoji[woman_bouncing_ball_light_skin_tone]=$'\U26F9\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_bouncing_ball_light_skin_tone_minimally]=$'\U26F9\U1F3FB\U200D\U2640' +emoji[woman_bouncing_ball_medium_light_skin_tone]=$'\U26F9\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_bouncing_ball_medium_light_skin_tone_minimally]=$'\U26F9\U1F3FC\U200D\U2640' +emoji[woman_bouncing_ball_medium_skin_tone]=$'\U26F9\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_bouncing_ball_medium_skin_tone_minimally]=$'\U26F9\U1F3FD\U200D\U2640' +emoji[woman_bouncing_ball_medium_dark_skin_tone]=$'\U26F9\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_bouncing_ball_medium_dark_skin_tone_minimally]=$'\U26F9\U1F3FE\U200D\U2640' +emoji[woman_bouncing_ball_dark_skin_tone]=$'\U26F9\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_bouncing_ball_dark_skin_tone_minimally]=$'\U26F9\U1F3FF\U200D\U2640' +emoji[person_lifting_weights]=$'\U1F3CB\UFE0F' +emoji[person_lifting_weights_unqualified]=$'\U1F3CB' +emoji[weight_lifting]=$'\U1F3CB' +emoji[person_lifting_weights_light_skin_tone]=$'\U1F3CB\U1F3FB' +emoji[person_lifting_weights_medium_light_skin_tone]=$'\U1F3CB\U1F3FC' +emoji[person_lifting_weights_medium_skin_tone]=$'\U1F3CB\U1F3FD' +emoji[person_lifting_weights_medium_dark_skin_tone]=$'\U1F3CB\U1F3FE' +emoji[person_lifting_weights_dark_skin_tone]=$'\U1F3CB\U1F3FF' +emoji[man_lifting_weights]=$'\U1F3CB\UFE0F\U200D\U2642\UFE0F' +emoji[weight_lifting_man]=$'\U1F3CB\UFE0F\U200D\U2642\UFE0F' +emoji[man_lifting_weights_unqualified]=$'\U1F3CB\U200D\U2642\UFE0F' +emoji[man_lifting_weights_unqualified_1]=$'\U1F3CB\UFE0F\U200D\U2642' +emoji[man_lifting_weights_unqualified_2]=$'\U1F3CB\U200D\U2642' +emoji[man_lifting_weights_light_skin_tone]=$'\U1F3CB\U1F3FB\U200D\U2642\UFE0F' +emoji[man_lifting_weights_light_skin_tone_minimally]=$'\U1F3CB\U1F3FB\U200D\U2642' +emoji[man_lifting_weights_medium_light_skin_tone]=$'\U1F3CB\U1F3FC\U200D\U2642\UFE0F' +emoji[man_lifting_weights_medium_light_skin_tone_minimally]=$'\U1F3CB\U1F3FC\U200D\U2642' +emoji[man_lifting_weights_medium_skin_tone]=$'\U1F3CB\U1F3FD\U200D\U2642\UFE0F' +emoji[man_lifting_weights_medium_skin_tone_minimally]=$'\U1F3CB\U1F3FD\U200D\U2642' +emoji[man_lifting_weights_medium_dark_skin_tone]=$'\U1F3CB\U1F3FE\U200D\U2642\UFE0F' +emoji[man_lifting_weights_medium_dark_skin_tone_minimally]=$'\U1F3CB\U1F3FE\U200D\U2642' +emoji[man_lifting_weights_dark_skin_tone]=$'\U1F3CB\U1F3FF\U200D\U2642\UFE0F' +emoji[man_lifting_weights_dark_skin_tone_minimally]=$'\U1F3CB\U1F3FF\U200D\U2642' +emoji[woman_lifting_weights]=$'\U1F3CB\UFE0F\U200D\U2640\UFE0F' +emoji[weight_lifting_woman]=$'\U1F3CB\UFE0F\U200D\U2640\UFE0F' +emoji[woman_lifting_weights_unqualified]=$'\U1F3CB\U200D\U2640\UFE0F' +emoji[woman_lifting_weights_unqualified_1]=$'\U1F3CB\UFE0F\U200D\U2640' +emoji[woman_lifting_weights_unqualified_2]=$'\U1F3CB\U200D\U2640' +emoji[woman_lifting_weights_light_skin_tone]=$'\U1F3CB\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_lifting_weights_light_skin_tone_minimally]=$'\U1F3CB\U1F3FB\U200D\U2640' +emoji[woman_lifting_weights_medium_light_skin_tone]=$'\U1F3CB\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_lifting_weights_medium_light_skin_tone_minimally]=$'\U1F3CB\U1F3FC\U200D\U2640' +emoji[woman_lifting_weights_medium_skin_tone]=$'\U1F3CB\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_lifting_weights_medium_skin_tone_minimally]=$'\U1F3CB\U1F3FD\U200D\U2640' +emoji[woman_lifting_weights_medium_dark_skin_tone]=$'\U1F3CB\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_lifting_weights_medium_dark_skin_tone_minimally]=$'\U1F3CB\U1F3FE\U200D\U2640' +emoji[woman_lifting_weights_dark_skin_tone]=$'\U1F3CB\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_lifting_weights_dark_skin_tone_minimally]=$'\U1F3CB\U1F3FF\U200D\U2640' +emoji[person_biking]=$'\U1F6B4' +emoji[bicyclist]=$'\U1F6B4' +emoji[person_biking_light_skin_tone]=$'\U1F6B4\U1F3FB' +emoji[person_biking_medium_light_skin_tone]=$'\U1F6B4\U1F3FC' +emoji[person_biking_medium_skin_tone]=$'\U1F6B4\U1F3FD' +emoji[person_biking_medium_dark_skin_tone]=$'\U1F6B4\U1F3FE' +emoji[person_biking_dark_skin_tone]=$'\U1F6B4\U1F3FF' +emoji[man_biking]=$'\U1F6B4\U200D\U2642\UFE0F' +emoji[man_biking_minimally]=$'\U1F6B4\U200D\U2642' +emoji[biking_man]=$'\U1F6B4\U200D\U2642' +emoji[man_biking_light_skin_tone]=$'\U1F6B4\U1F3FB\U200D\U2642\UFE0F' +emoji[man_biking_light_skin_tone_minimally]=$'\U1F6B4\U1F3FB\U200D\U2642' +emoji[man_biking_medium_light_skin_tone]=$'\U1F6B4\U1F3FC\U200D\U2642\UFE0F' +emoji[man_biking_medium_light_skin_tone_minimally]=$'\U1F6B4\U1F3FC\U200D\U2642' +emoji[man_biking_medium_skin_tone]=$'\U1F6B4\U1F3FD\U200D\U2642\UFE0F' +emoji[man_biking_medium_skin_tone_minimally]=$'\U1F6B4\U1F3FD\U200D\U2642' +emoji[man_biking_medium_dark_skin_tone]=$'\U1F6B4\U1F3FE\U200D\U2642\UFE0F' +emoji[man_biking_medium_dark_skin_tone_minimally]=$'\U1F6B4\U1F3FE\U200D\U2642' +emoji[man_biking_dark_skin_tone]=$'\U1F6B4\U1F3FF\U200D\U2642\UFE0F' +emoji[man_biking_dark_skin_tone_minimally]=$'\U1F6B4\U1F3FF\U200D\U2642' +emoji[woman_biking]=$'\U1F6B4\U200D\U2640\UFE0F' +emoji[woman_biking_minimally]=$'\U1F6B4\U200D\U2640' +emoji[biking_woman]=$'\U1F6B4\U200D\U2640' +emoji[woman_biking_light_skin_tone]=$'\U1F6B4\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_biking_light_skin_tone_minimally]=$'\U1F6B4\U1F3FB\U200D\U2640' +emoji[woman_biking_medium_light_skin_tone]=$'\U1F6B4\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_biking_medium_light_skin_tone_minimally]=$'\U1F6B4\U1F3FC\U200D\U2640' +emoji[woman_biking_medium_skin_tone]=$'\U1F6B4\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_biking_medium_skin_tone_minimally]=$'\U1F6B4\U1F3FD\U200D\U2640' +emoji[woman_biking_medium_dark_skin_tone]=$'\U1F6B4\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_biking_medium_dark_skin_tone_minimally]=$'\U1F6B4\U1F3FE\U200D\U2640' +emoji[woman_biking_dark_skin_tone]=$'\U1F6B4\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_biking_dark_skin_tone_minimally]=$'\U1F6B4\U1F3FF\U200D\U2640' +emoji[person_mountain_biking]=$'\U1F6B5' +emoji[mountain_bicyclist]=$'\U1F6B5' +emoji[person_mountain_biking_light_skin_tone]=$'\U1F6B5\U1F3FB' +emoji[person_mountain_biking_medium_light_skin_tone]=$'\U1F6B5\U1F3FC' +emoji[person_mountain_biking_medium_skin_tone]=$'\U1F6B5\U1F3FD' +emoji[person_mountain_biking_medium_dark_skin_tone]=$'\U1F6B5\U1F3FE' +emoji[person_mountain_biking_dark_skin_tone]=$'\U1F6B5\U1F3FF' +emoji[man_mountain_biking]=$'\U1F6B5\U200D\U2642\UFE0F' +emoji[man_mountain_biking_minimally]=$'\U1F6B5\U200D\U2642' +emoji[mountain_biking_man]=$'\U1F6B5\U200D\U2642' +emoji[man_mountain_biking_light_skin_tone]=$'\U1F6B5\U1F3FB\U200D\U2642\UFE0F' +emoji[man_mountain_biking_light_skin_tone_minimally]=$'\U1F6B5\U1F3FB\U200D\U2642' +emoji[man_mountain_biking_medium_light_skin_tone]=$'\U1F6B5\U1F3FC\U200D\U2642\UFE0F' +emoji[man_mountain_biking_medium_light_skin_tone_minimally]=$'\U1F6B5\U1F3FC\U200D\U2642' +emoji[man_mountain_biking_medium_skin_tone]=$'\U1F6B5\U1F3FD\U200D\U2642\UFE0F' +emoji[man_mountain_biking_medium_skin_tone_minimally]=$'\U1F6B5\U1F3FD\U200D\U2642' +emoji[man_mountain_biking_medium_dark_skin_tone]=$'\U1F6B5\U1F3FE\U200D\U2642\UFE0F' +emoji[man_mountain_biking_medium_dark_skin_tone_minimally]=$'\U1F6B5\U1F3FE\U200D\U2642' +emoji[man_mountain_biking_dark_skin_tone]=$'\U1F6B5\U1F3FF\U200D\U2642\UFE0F' +emoji[man_mountain_biking_dark_skin_tone_minimally]=$'\U1F6B5\U1F3FF\U200D\U2642' +emoji[woman_mountain_biking]=$'\U1F6B5\U200D\U2640\UFE0F' +emoji[woman_mountain_biking_minimally]=$'\U1F6B5\U200D\U2640' +emoji[mountain_biking_woman]=$'\U1F6B5\U200D\U2640' +emoji[woman_mountain_biking_light_skin_tone]=$'\U1F6B5\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_mountain_biking_light_skin_tone_minimally]=$'\U1F6B5\U1F3FB\U200D\U2640' +emoji[woman_mountain_biking_medium_light_skin_tone]=$'\U1F6B5\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_mountain_biking_medium_light_skin_tone_minimally]=$'\U1F6B5\U1F3FC\U200D\U2640' +emoji[woman_mountain_biking_medium_skin_tone]=$'\U1F6B5\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_mountain_biking_medium_skin_tone_minimally]=$'\U1F6B5\U1F3FD\U200D\U2640' +emoji[woman_mountain_biking_medium_dark_skin_tone]=$'\U1F6B5\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_mountain_biking_medium_dark_skin_tone_minimally]=$'\U1F6B5\U1F3FE\U200D\U2640' +emoji[woman_mountain_biking_dark_skin_tone]=$'\U1F6B5\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_mountain_biking_dark_skin_tone_minimally]=$'\U1F6B5\U1F3FF\U200D\U2640' +emoji[person_cartwheeling]=$'\U1F938' +emoji[cartwheeling]=$'\U1F938' +emoji[person_cartwheeling_light_skin_tone]=$'\U1F938\U1F3FB' +emoji[person_cartwheeling_medium_light_skin_tone]=$'\U1F938\U1F3FC' +emoji[person_cartwheeling_medium_skin_tone]=$'\U1F938\U1F3FD' +emoji[person_cartwheeling_medium_dark_skin_tone]=$'\U1F938\U1F3FE' +emoji[person_cartwheeling_dark_skin_tone]=$'\U1F938\U1F3FF' +emoji[man_cartwheeling]=$'\U1F938\U200D\U2642\UFE0F' +emoji[man_cartwheeling_minimally]=$'\U1F938\U200D\U2642' +emoji[man_cartwheeling_light_skin_tone]=$'\U1F938\U1F3FB\U200D\U2642\UFE0F' +emoji[man_cartwheeling_light_skin_tone_minimally]=$'\U1F938\U1F3FB\U200D\U2642' +emoji[man_cartwheeling_medium_light_skin_tone]=$'\U1F938\U1F3FC\U200D\U2642\UFE0F' +emoji[man_cartwheeling_medium_light_skin_tone_minimally]=$'\U1F938\U1F3FC\U200D\U2642' +emoji[man_cartwheeling_medium_skin_tone]=$'\U1F938\U1F3FD\U200D\U2642\UFE0F' +emoji[man_cartwheeling_medium_skin_tone_minimally]=$'\U1F938\U1F3FD\U200D\U2642' +emoji[man_cartwheeling_medium_dark_skin_tone]=$'\U1F938\U1F3FE\U200D\U2642\UFE0F' +emoji[man_cartwheeling_medium_dark_skin_tone_minimally]=$'\U1F938\U1F3FE\U200D\U2642' +emoji[man_cartwheeling_dark_skin_tone]=$'\U1F938\U1F3FF\U200D\U2642\UFE0F' +emoji[man_cartwheeling_dark_skin_tone_minimally]=$'\U1F938\U1F3FF\U200D\U2642' +emoji[woman_cartwheeling]=$'\U1F938\U200D\U2640\UFE0F' +emoji[woman_cartwheeling_minimally]=$'\U1F938\U200D\U2640' +emoji[woman_cartwheeling_light_skin_tone]=$'\U1F938\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_cartwheeling_light_skin_tone_minimally]=$'\U1F938\U1F3FB\U200D\U2640' +emoji[woman_cartwheeling_medium_light_skin_tone]=$'\U1F938\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_cartwheeling_medium_light_skin_tone_minimally]=$'\U1F938\U1F3FC\U200D\U2640' +emoji[woman_cartwheeling_medium_skin_tone]=$'\U1F938\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_cartwheeling_medium_skin_tone_minimally]=$'\U1F938\U1F3FD\U200D\U2640' +emoji[woman_cartwheeling_medium_dark_skin_tone]=$'\U1F938\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_cartwheeling_medium_dark_skin_tone_minimally]=$'\U1F938\U1F3FE\U200D\U2640' +emoji[woman_cartwheeling_dark_skin_tone]=$'\U1F938\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_cartwheeling_dark_skin_tone_minimally]=$'\U1F938\U1F3FF\U200D\U2640' +emoji[people_wrestling]=$'\U1F93C' +emoji[wrestling]=$'\U1F93C' +emoji[men_wrestling]=$'\U1F93C\U200D\U2642\UFE0F' +emoji[men_wrestling_minimally]=$'\U1F93C\U200D\U2642' +emoji[women_wrestling]=$'\U1F93C\U200D\U2640\UFE0F' +emoji[women_wrestling_minimally]=$'\U1F93C\U200D\U2640' +emoji[person_playing_water_polo]=$'\U1F93D' +emoji[water_polo]=$'\U1F93D' +emoji[person_playing_water_polo_light_skin_tone]=$'\U1F93D\U1F3FB' +emoji[person_playing_water_polo_medium_light_skin_tone]=$'\U1F93D\U1F3FC' +emoji[person_playing_water_polo_medium_skin_tone]=$'\U1F93D\U1F3FD' +emoji[person_playing_water_polo_medium_dark_skin_tone]=$'\U1F93D\U1F3FE' +emoji[person_playing_water_polo_dark_skin_tone]=$'\U1F93D\U1F3FF' +emoji[man_playing_water_polo]=$'\U1F93D\U200D\U2642\UFE0F' +emoji[man_playing_water_polo_minimally]=$'\U1F93D\U200D\U2642' +emoji[man_playing_water_polo_light_skin_tone]=$'\U1F93D\U1F3FB\U200D\U2642\UFE0F' +emoji[man_playing_water_polo_light_skin_tone_minimally]=$'\U1F93D\U1F3FB\U200D\U2642' +emoji[man_playing_water_polo_medium_light_skin_tone]=$'\U1F93D\U1F3FC\U200D\U2642\UFE0F' +emoji[man_playing_water_polo_medium_light_skin_tone_minimally]=$'\U1F93D\U1F3FC\U200D\U2642' +emoji[man_playing_water_polo_medium_skin_tone]=$'\U1F93D\U1F3FD\U200D\U2642\UFE0F' +emoji[man_playing_water_polo_medium_skin_tone_minimally]=$'\U1F93D\U1F3FD\U200D\U2642' +emoji[man_playing_water_polo_medium_dark_skin_tone]=$'\U1F93D\U1F3FE\U200D\U2642\UFE0F' +emoji[man_playing_water_polo_medium_dark_skin_tone_minimally]=$'\U1F93D\U1F3FE\U200D\U2642' +emoji[man_playing_water_polo_dark_skin_tone]=$'\U1F93D\U1F3FF\U200D\U2642\UFE0F' +emoji[man_playing_water_polo_dark_skin_tone_minimally]=$'\U1F93D\U1F3FF\U200D\U2642' +emoji[woman_playing_water_polo]=$'\U1F93D\U200D\U2640\UFE0F' +emoji[woman_playing_water_polo_minimally]=$'\U1F93D\U200D\U2640' +emoji[woman_playing_water_polo_light_skin_tone]=$'\U1F93D\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_playing_water_polo_light_skin_tone_minimally]=$'\U1F93D\U1F3FB\U200D\U2640' +emoji[woman_playing_water_polo_medium_light_skin_tone]=$'\U1F93D\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_playing_water_polo_medium_light_skin_tone_minimally]=$'\U1F93D\U1F3FC\U200D\U2640' +emoji[woman_playing_water_polo_medium_skin_tone]=$'\U1F93D\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_playing_water_polo_medium_skin_tone_minimally]=$'\U1F93D\U1F3FD\U200D\U2640' +emoji[woman_playing_water_polo_medium_dark_skin_tone]=$'\U1F93D\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_playing_water_polo_medium_dark_skin_tone_minimally]=$'\U1F93D\U1F3FE\U200D\U2640' +emoji[woman_playing_water_polo_dark_skin_tone]=$'\U1F93D\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_playing_water_polo_dark_skin_tone_minimally]=$'\U1F93D\U1F3FF\U200D\U2640' +emoji[person_playing_handball]=$'\U1F93E' +emoji[handball_person]=$'\U1F93E' +emoji[person_playing_handball_light_skin_tone]=$'\U1F93E\U1F3FB' +emoji[person_playing_handball_medium_light_skin_tone]=$'\U1F93E\U1F3FC' +emoji[person_playing_handball_medium_skin_tone]=$'\U1F93E\U1F3FD' +emoji[person_playing_handball_medium_dark_skin_tone]=$'\U1F93E\U1F3FE' +emoji[person_playing_handball_dark_skin_tone]=$'\U1F93E\U1F3FF' +emoji[man_playing_handball]=$'\U1F93E\U200D\U2642\UFE0F' +emoji[man_playing_handball_minimally]=$'\U1F93E\U200D\U2642' +emoji[man_playing_handball_light_skin_tone]=$'\U1F93E\U1F3FB\U200D\U2642\UFE0F' +emoji[man_playing_handball_light_skin_tone_minimally]=$'\U1F93E\U1F3FB\U200D\U2642' +emoji[man_playing_handball_medium_light_skin_tone]=$'\U1F93E\U1F3FC\U200D\U2642\UFE0F' +emoji[man_playing_handball_medium_light_skin_tone_minimally]=$'\U1F93E\U1F3FC\U200D\U2642' +emoji[man_playing_handball_medium_skin_tone]=$'\U1F93E\U1F3FD\U200D\U2642\UFE0F' +emoji[man_playing_handball_medium_skin_tone_minimally]=$'\U1F93E\U1F3FD\U200D\U2642' +emoji[man_playing_handball_medium_dark_skin_tone]=$'\U1F93E\U1F3FE\U200D\U2642\UFE0F' +emoji[man_playing_handball_medium_dark_skin_tone_minimally]=$'\U1F93E\U1F3FE\U200D\U2642' +emoji[man_playing_handball_dark_skin_tone]=$'\U1F93E\U1F3FF\U200D\U2642\UFE0F' +emoji[man_playing_handball_dark_skin_tone_minimally]=$'\U1F93E\U1F3FF\U200D\U2642' +emoji[woman_playing_handball]=$'\U1F93E\U200D\U2640\UFE0F' +emoji[woman_playing_handball_minimally]=$'\U1F93E\U200D\U2640' +emoji[woman_playing_handball_light_skin_tone]=$'\U1F93E\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_playing_handball_light_skin_tone_minimally]=$'\U1F93E\U1F3FB\U200D\U2640' +emoji[woman_playing_handball_medium_light_skin_tone]=$'\U1F93E\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_playing_handball_medium_light_skin_tone_minimally]=$'\U1F93E\U1F3FC\U200D\U2640' +emoji[woman_playing_handball_medium_skin_tone]=$'\U1F93E\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_playing_handball_medium_skin_tone_minimally]=$'\U1F93E\U1F3FD\U200D\U2640' +emoji[woman_playing_handball_medium_dark_skin_tone]=$'\U1F93E\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_playing_handball_medium_dark_skin_tone_minimally]=$'\U1F93E\U1F3FE\U200D\U2640' +emoji[woman_playing_handball_dark_skin_tone]=$'\U1F93E\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_playing_handball_dark_skin_tone_minimally]=$'\U1F93E\U1F3FF\U200D\U2640' +emoji[person_juggling]=$'\U1F939' +emoji[juggling_person]=$'\U1F939' +emoji[person_juggling_light_skin_tone]=$'\U1F939\U1F3FB' +emoji[person_juggling_medium_light_skin_tone]=$'\U1F939\U1F3FC' +emoji[person_juggling_medium_skin_tone]=$'\U1F939\U1F3FD' +emoji[person_juggling_medium_dark_skin_tone]=$'\U1F939\U1F3FE' +emoji[person_juggling_dark_skin_tone]=$'\U1F939\U1F3FF' +emoji[man_juggling]=$'\U1F939\U200D\U2642\UFE0F' +emoji[man_juggling_minimally]=$'\U1F939\U200D\U2642' +emoji[man_juggling_light_skin_tone]=$'\U1F939\U1F3FB\U200D\U2642\UFE0F' +emoji[man_juggling_light_skin_tone_minimally]=$'\U1F939\U1F3FB\U200D\U2642' +emoji[man_juggling_medium_light_skin_tone]=$'\U1F939\U1F3FC\U200D\U2642\UFE0F' +emoji[man_juggling_medium_light_skin_tone_minimally]=$'\U1F939\U1F3FC\U200D\U2642' +emoji[man_juggling_medium_skin_tone]=$'\U1F939\U1F3FD\U200D\U2642\UFE0F' +emoji[man_juggling_medium_skin_tone_minimally]=$'\U1F939\U1F3FD\U200D\U2642' +emoji[man_juggling_medium_dark_skin_tone]=$'\U1F939\U1F3FE\U200D\U2642\UFE0F' +emoji[man_juggling_medium_dark_skin_tone_minimally]=$'\U1F939\U1F3FE\U200D\U2642' +emoji[man_juggling_dark_skin_tone]=$'\U1F939\U1F3FF\U200D\U2642\UFE0F' +emoji[man_juggling_dark_skin_tone_minimally]=$'\U1F939\U1F3FF\U200D\U2642' +emoji[woman_juggling]=$'\U1F939\U200D\U2640\UFE0F' +emoji[woman_juggling_minimally]=$'\U1F939\U200D\U2640' +emoji[woman_juggling_light_skin_tone]=$'\U1F939\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_juggling_light_skin_tone_minimally]=$'\U1F939\U1F3FB\U200D\U2640' +emoji[woman_juggling_medium_light_skin_tone]=$'\U1F939\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_juggling_medium_light_skin_tone_minimally]=$'\U1F939\U1F3FC\U200D\U2640' +emoji[woman_juggling_medium_skin_tone]=$'\U1F939\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_juggling_medium_skin_tone_minimally]=$'\U1F939\U1F3FD\U200D\U2640' +emoji[woman_juggling_medium_dark_skin_tone]=$'\U1F939\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_juggling_medium_dark_skin_tone_minimally]=$'\U1F939\U1F3FE\U200D\U2640' +emoji[woman_juggling_dark_skin_tone]=$'\U1F939\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_juggling_dark_skin_tone_minimally]=$'\U1F939\U1F3FF\U200D\U2640' +emoji[person_in_lotus_position]=$'\U1F9D8' +emoji[lotus_position]=$'\U1F9D8' +emoji[person_in_lotus_position_light_skin_tone]=$'\U1F9D8\U1F3FB' +emoji[person_in_lotus_position_medium_light_skin_tone]=$'\U1F9D8\U1F3FC' +emoji[person_in_lotus_position_medium_skin_tone]=$'\U1F9D8\U1F3FD' +emoji[person_in_lotus_position_medium_dark_skin_tone]=$'\U1F9D8\U1F3FE' +emoji[person_in_lotus_position_dark_skin_tone]=$'\U1F9D8\U1F3FF' +emoji[man_in_lotus_position]=$'\U1F9D8\U200D\U2642\UFE0F' +emoji[man_in_lotus_position_minimally]=$'\U1F9D8\U200D\U2642' +emoji[lotus_position_man]=$'\U1F9D8\U200D\U2642' +emoji[man_in_lotus_position_light_skin_tone]=$'\U1F9D8\U1F3FB\U200D\U2642\UFE0F' +emoji[man_in_lotus_position_light_skin_tone_minimally]=$'\U1F9D8\U1F3FB\U200D\U2642' +emoji[man_in_lotus_position_medium_light_skin_tone]=$'\U1F9D8\U1F3FC\U200D\U2642\UFE0F' +emoji[man_in_lotus_position_medium_light_skin_tone_minimally]=$'\U1F9D8\U1F3FC\U200D\U2642' +emoji[man_in_lotus_position_medium_skin_tone]=$'\U1F9D8\U1F3FD\U200D\U2642\UFE0F' +emoji[man_in_lotus_position_medium_skin_tone_minimally]=$'\U1F9D8\U1F3FD\U200D\U2642' +emoji[man_in_lotus_position_medium_dark_skin_tone]=$'\U1F9D8\U1F3FE\U200D\U2642\UFE0F' +emoji[man_in_lotus_position_medium_dark_skin_tone_minimally]=$'\U1F9D8\U1F3FE\U200D\U2642' +emoji[man_in_lotus_position_dark_skin_tone]=$'\U1F9D8\U1F3FF\U200D\U2642\UFE0F' +emoji[man_in_lotus_position_dark_skin_tone_minimally]=$'\U1F9D8\U1F3FF\U200D\U2642' +emoji[woman_in_lotus_position]=$'\U1F9D8\U200D\U2640\UFE0F' +emoji[woman_in_lotus_position_minimally]=$'\U1F9D8\U200D\U2640' +emoji[lotus_position_woman]=$'\U1F9D8\U200D\U2640' +emoji[woman_in_lotus_position_light_skin_tone]=$'\U1F9D8\U1F3FB\U200D\U2640\UFE0F' +emoji[woman_in_lotus_position_light_skin_tone_minimally]=$'\U1F9D8\U1F3FB\U200D\U2640' +emoji[woman_in_lotus_position_medium_light_skin_tone]=$'\U1F9D8\U1F3FC\U200D\U2640\UFE0F' +emoji[woman_in_lotus_position_medium_light_skin_tone_minimally]=$'\U1F9D8\U1F3FC\U200D\U2640' +emoji[woman_in_lotus_position_medium_skin_tone]=$'\U1F9D8\U1F3FD\U200D\U2640\UFE0F' +emoji[woman_in_lotus_position_medium_skin_tone_minimally]=$'\U1F9D8\U1F3FD\U200D\U2640' +emoji[woman_in_lotus_position_medium_dark_skin_tone]=$'\U1F9D8\U1F3FE\U200D\U2640\UFE0F' +emoji[woman_in_lotus_position_medium_dark_skin_tone_minimally]=$'\U1F9D8\U1F3FE\U200D\U2640' +emoji[woman_in_lotus_position_dark_skin_tone]=$'\U1F9D8\U1F3FF\U200D\U2640\UFE0F' +emoji[woman_in_lotus_position_dark_skin_tone_minimally]=$'\U1F9D8\U1F3FF\U200D\U2640' +emoji[person_taking_bath]=$'\U1F6C0' +emoji[bath]=$'\U1F6C0' +emoji[person_taking_bath_light_skin_tone]=$'\U1F6C0\U1F3FB' +emoji[person_taking_bath_medium_light_skin_tone]=$'\U1F6C0\U1F3FC' +emoji[person_taking_bath_medium_skin_tone]=$'\U1F6C0\U1F3FD' +emoji[person_taking_bath_medium_dark_skin_tone]=$'\U1F6C0\U1F3FE' +emoji[person_taking_bath_dark_skin_tone]=$'\U1F6C0\U1F3FF' +emoji[person_in_bed]=$'\U1F6CC' +emoji[sleeping_bed]=$'\U1F6CC' +emoji[person_in_bed_light_skin_tone]=$'\U1F6CC\U1F3FB' +emoji[person_in_bed_medium_light_skin_tone]=$'\U1F6CC\U1F3FC' +emoji[person_in_bed_medium_skin_tone]=$'\U1F6CC\U1F3FD' +emoji[person_in_bed_medium_dark_skin_tone]=$'\U1F6CC\U1F3FE' +emoji[person_in_bed_dark_skin_tone]=$'\U1F6CC\U1F3FF' +emoji[people_holding_hands]=$'\U1F9D1\U200D\U1F91D\U200D\U1F9D1' +emoji[people_holding_hands_light_skin_tone]=$'\U1F9D1\U1F3FB\U200D\U1F91D\U200D\U1F9D1\U1F3FB' +emoji[people_holding_hands_medium_light_skin_tone_light_skin_tone]=$'\U1F9D1\U1F3FC\U200D\U1F91D\U200D\U1F9D1\U1F3FB' +emoji[people_holding_hands_medium_light_skin_tone_light_skin_tone_1]=$'\U1F9D1\U1F3FC\U200D\U1F91D\U200D\U1F9D1\U1F3FC' +emoji[people_holding_hands_medium_skin_tone_light_skin_tone]=$'\U1F9D1\U1F3FD\U200D\U1F91D\U200D\U1F9D1\U1F3FB' +emoji[people_holding_hands_medium_skin_tone_medium_light_skin_tone]=$'\U1F9D1\U1F3FD\U200D\U1F91D\U200D\U1F9D1\U1F3FC' +emoji[people_holding_hands_medium_skin_tone_medium_light_skin_tone_1]=$'\U1F9D1\U1F3FD\U200D\U1F91D\U200D\U1F9D1\U1F3FD' +emoji[people_holding_hands_medium_dark_skin_tone_light_skin_tone]=$'\U1F9D1\U1F3FE\U200D\U1F91D\U200D\U1F9D1\U1F3FB' +emoji[people_holding_hands_medium_dark_skin_tone_medium_light_skin_tone]=$'\U1F9D1\U1F3FE\U200D\U1F91D\U200D\U1F9D1\U1F3FC' +emoji[people_holding_hands_medium_dark_skin_tone_medium_skin_tone]=$'\U1F9D1\U1F3FE\U200D\U1F91D\U200D\U1F9D1\U1F3FD' +emoji[people_holding_hands_medium_dark_skin_tone_medium_skin_tone_1]=$'\U1F9D1\U1F3FE\U200D\U1F91D\U200D\U1F9D1\U1F3FE' +emoji[people_holding_hands_dark_skin_tone_light_skin_tone]=$'\U1F9D1\U1F3FF\U200D\U1F91D\U200D\U1F9D1\U1F3FB' +emoji[people_holding_hands_dark_skin_tone_medium_light_skin_tone]=$'\U1F9D1\U1F3FF\U200D\U1F91D\U200D\U1F9D1\U1F3FC' +emoji[people_holding_hands_dark_skin_tone_medium_skin_tone]=$'\U1F9D1\U1F3FF\U200D\U1F91D\U200D\U1F9D1\U1F3FD' +emoji[people_holding_hands_dark_skin_tone_medium_dark_skin_tone]=$'\U1F9D1\U1F3FF\U200D\U1F91D\U200D\U1F9D1\U1F3FE' +emoji[people_holding_hands_dark_skin_tone_medium_dark_skin_tone_1]=$'\U1F9D1\U1F3FF\U200D\U1F91D\U200D\U1F9D1\U1F3FF' +emoji[women_holding_hands]=$'\U1F46D' +emoji[two_women_holding_hands]=$'\U1F46D' +emoji[women_holding_hands_light_skin_tone]=$'\U1F46D\U1F3FB' +emoji[women_holding_hands_medium_light_skin_tone_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F91D\U200D\U1F469\U1F3FB' +emoji[women_holding_hands_medium_light_skin_tone_light_skin_tone_1]=$'\U1F46D\U1F3FC' +emoji[women_holding_hands_medium_skin_tone_light_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F91D\U200D\U1F469\U1F3FB' +emoji[women_holding_hands_medium_skin_tone_medium_light_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F91D\U200D\U1F469\U1F3FC' +emoji[women_holding_hands_medium_skin_tone_medium_light_skin_tone_1]=$'\U1F46D\U1F3FD' +emoji[women_holding_hands_medium_dark_skin_tone_light_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F91D\U200D\U1F469\U1F3FB' +emoji[women_holding_hands_medium_dark_skin_tone_medium_light_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F91D\U200D\U1F469\U1F3FC' +emoji[women_holding_hands_medium_dark_skin_tone_medium_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F91D\U200D\U1F469\U1F3FD' +emoji[women_holding_hands_medium_dark_skin_tone_medium_skin_tone_1]=$'\U1F46D\U1F3FE' +emoji[women_holding_hands_dark_skin_tone_light_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F91D\U200D\U1F469\U1F3FB' +emoji[women_holding_hands_dark_skin_tone_medium_light_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F91D\U200D\U1F469\U1F3FC' +emoji[women_holding_hands_dark_skin_tone_medium_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F91D\U200D\U1F469\U1F3FD' +emoji[women_holding_hands_dark_skin_tone_medium_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F91D\U200D\U1F469\U1F3FE' +emoji[women_holding_hands_dark_skin_tone_medium_dark_skin_tone_1]=$'\U1F46D\U1F3FF' +emoji[woman_and_man_holding_hands]=$'\U1F46B' +emoji[couple]=$'\U1F46B' +emoji[woman_and_man_holding_hands_light_skin_tone]=$'\U1F46B\U1F3FB' +emoji[woman_and_man_holding_hands_light_skin_tone_medium_light_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F91D\U200D\U1F468\U1F3FC' +emoji[woman_and_man_holding_hands_light_skin_tone_medium_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F91D\U200D\U1F468\U1F3FD' +emoji[woman_and_man_holding_hands_light_skin_tone_medium_dark_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F91D\U200D\U1F468\U1F3FE' +emoji[woman_and_man_holding_hands_light_skin_tone_dark_skin_tone]=$'\U1F469\U1F3FB\U200D\U1F91D\U200D\U1F468\U1F3FF' +emoji[woman_and_man_holding_hands_medium_light_skin_tone_light_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F91D\U200D\U1F468\U1F3FB' +emoji[woman_and_man_holding_hands_medium_light_skin_tone_light_skin_tone_1]=$'\U1F46B\U1F3FC' +emoji[woman_and_man_holding_hands_medium_light_skin_tone_medium_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F91D\U200D\U1F468\U1F3FD' +emoji[woman_and_man_holding_hands_medium_light_skin_tone_medium_dark_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F91D\U200D\U1F468\U1F3FE' +emoji[woman_and_man_holding_hands_medium_light_skin_tone_dark_skin_tone]=$'\U1F469\U1F3FC\U200D\U1F91D\U200D\U1F468\U1F3FF' +emoji[woman_and_man_holding_hands_medium_skin_tone_light_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F91D\U200D\U1F468\U1F3FB' +emoji[woman_and_man_holding_hands_medium_skin_tone_medium_light_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F91D\U200D\U1F468\U1F3FC' +emoji[woman_and_man_holding_hands_medium_skin_tone_medium_light_skin_tone_1]=$'\U1F46B\U1F3FD' +emoji[woman_and_man_holding_hands_medium_skin_tone_medium_dark_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F91D\U200D\U1F468\U1F3FE' +emoji[woman_and_man_holding_hands_medium_skin_tone_dark_skin_tone]=$'\U1F469\U1F3FD\U200D\U1F91D\U200D\U1F468\U1F3FF' +emoji[woman_and_man_holding_hands_medium_dark_skin_tone_light_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F91D\U200D\U1F468\U1F3FB' +emoji[woman_and_man_holding_hands_medium_dark_skin_tone_medium_light_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F91D\U200D\U1F468\U1F3FC' +emoji[woman_and_man_holding_hands_medium_dark_skin_tone_medium_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F91D\U200D\U1F468\U1F3FD' +emoji[woman_and_man_holding_hands_medium_dark_skin_tone_medium_skin_tone_1]=$'\U1F46B\U1F3FE' +emoji[woman_and_man_holding_hands_medium_dark_skin_tone_dark_skin_tone]=$'\U1F469\U1F3FE\U200D\U1F91D\U200D\U1F468\U1F3FF' +emoji[woman_and_man_holding_hands_dark_skin_tone_light_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F91D\U200D\U1F468\U1F3FB' +emoji[woman_and_man_holding_hands_dark_skin_tone_medium_light_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F91D\U200D\U1F468\U1F3FC' +emoji[woman_and_man_holding_hands_dark_skin_tone_medium_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F91D\U200D\U1F468\U1F3FD' +emoji[woman_and_man_holding_hands_dark_skin_tone_medium_dark_skin_tone]=$'\U1F469\U1F3FF\U200D\U1F91D\U200D\U1F468\U1F3FE' +emoji[woman_and_man_holding_hands_dark_skin_tone_medium_dark_skin_tone_1]=$'\U1F46B\U1F3FF' +emoji[men_holding_hands]=$'\U1F46C' +emoji[two_men_holding_hands]=$'\U1F46C' +emoji[men_holding_hands_light_skin_tone]=$'\U1F46C\U1F3FB' +emoji[men_holding_hands_medium_light_skin_tone_light_skin_tone]=$'\U1F468\U1F3FC\U200D\U1F91D\U200D\U1F468\U1F3FB' +emoji[men_holding_hands_medium_light_skin_tone_light_skin_tone_1]=$'\U1F46C\U1F3FC' +emoji[men_holding_hands_medium_skin_tone_light_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F91D\U200D\U1F468\U1F3FB' +emoji[men_holding_hands_medium_skin_tone_medium_light_skin_tone]=$'\U1F468\U1F3FD\U200D\U1F91D\U200D\U1F468\U1F3FC' +emoji[men_holding_hands_medium_skin_tone_medium_light_skin_tone_1]=$'\U1F46C\U1F3FD' +emoji[men_holding_hands_medium_dark_skin_tone_light_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F91D\U200D\U1F468\U1F3FB' +emoji[men_holding_hands_medium_dark_skin_tone_medium_light_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F91D\U200D\U1F468\U1F3FC' +emoji[men_holding_hands_medium_dark_skin_tone_medium_skin_tone]=$'\U1F468\U1F3FE\U200D\U1F91D\U200D\U1F468\U1F3FD' +emoji[men_holding_hands_medium_dark_skin_tone_medium_skin_tone_1]=$'\U1F46C\U1F3FE' +emoji[men_holding_hands_dark_skin_tone_light_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F91D\U200D\U1F468\U1F3FB' +emoji[men_holding_hands_dark_skin_tone_medium_light_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F91D\U200D\U1F468\U1F3FC' +emoji[men_holding_hands_dark_skin_tone_medium_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F91D\U200D\U1F468\U1F3FD' +emoji[men_holding_hands_dark_skin_tone_medium_dark_skin_tone]=$'\U1F468\U1F3FF\U200D\U1F91D\U200D\U1F468\U1F3FE' +emoji[men_holding_hands_dark_skin_tone_medium_dark_skin_tone_1]=$'\U1F46C\U1F3FF' +emoji[kiss]=$'\U1F48F' +emoji[couplekiss]=$'\U1F48F' +emoji[kiss_woman_man]=$'\U1F469\U200D\U2764\UFE0F\U200D\U1F48B\U200D\U1F468' +emoji[couplekiss_man_woman]=$'\U1F469\U200D\U2764\UFE0F\U200D\U1F48B\U200D\U1F468' +emoji[kiss_woman_man_minimally]=$'\U1F469\U200D\U2764\U200D\U1F48B\U200D\U1F468' +emoji[kiss_man_man]=$'\U1F468\U200D\U2764\UFE0F\U200D\U1F48B\U200D\U1F468' +emoji[couplekiss_man_man]=$'\U1F468\U200D\U2764\UFE0F\U200D\U1F48B\U200D\U1F468' +emoji[kiss_man_man_minimally]=$'\U1F468\U200D\U2764\U200D\U1F48B\U200D\U1F468' +emoji[kiss_woman_woman]=$'\U1F469\U200D\U2764\UFE0F\U200D\U1F48B\U200D\U1F469' +emoji[couplekiss_woman_woman]=$'\U1F469\U200D\U2764\UFE0F\U200D\U1F48B\U200D\U1F469' +emoji[kiss_woman_woman_minimally]=$'\U1F469\U200D\U2764\U200D\U1F48B\U200D\U1F469' +emoji[couple_with_heart]=$'\U1F491' +emoji[couple_with_heart_woman_man]=$'\U1F469\U200D\U2764\UFE0F\U200D\U1F468' +emoji[couple_with_heart_woman_man_minimally]=$'\U1F469\U200D\U2764\U200D\U1F468' +emoji[couple_with_heart_man_man]=$'\U1F468\U200D\U2764\UFE0F\U200D\U1F468' +emoji[couple_with_heart_man_man_minimally]=$'\U1F468\U200D\U2764\U200D\U1F468' +emoji[couple_with_heart_woman_woman]=$'\U1F469\U200D\U2764\UFE0F\U200D\U1F469' +emoji[couple_with_heart_woman_woman_minimally]=$'\U1F469\U200D\U2764\U200D\U1F469' +emoji[family]=$'\U1F46A' +emoji[family_man_woman_boy]=$'\U1F468\U200D\U1F469\U200D\U1F466' +emoji[family_man_woman_girl]=$'\U1F468\U200D\U1F469\U200D\U1F467' +emoji[family_man_woman_girl_boy]=$'\U1F468\U200D\U1F469\U200D\U1F467\U200D\U1F466' +emoji[family_man_woman_boy_boy]=$'\U1F468\U200D\U1F469\U200D\U1F466\U200D\U1F466' +emoji[family_man_woman_girl_girl]=$'\U1F468\U200D\U1F469\U200D\U1F467\U200D\U1F467' +emoji[family_man_man_boy]=$'\U1F468\U200D\U1F468\U200D\U1F466' +emoji[family_man_man_girl]=$'\U1F468\U200D\U1F468\U200D\U1F467' +emoji[family_man_man_girl_boy]=$'\U1F468\U200D\U1F468\U200D\U1F467\U200D\U1F466' +emoji[family_man_man_boy_boy]=$'\U1F468\U200D\U1F468\U200D\U1F466\U200D\U1F466' +emoji[family_man_man_girl_girl]=$'\U1F468\U200D\U1F468\U200D\U1F467\U200D\U1F467' +emoji[family_woman_woman_boy]=$'\U1F469\U200D\U1F469\U200D\U1F466' +emoji[family_woman_woman_girl]=$'\U1F469\U200D\U1F469\U200D\U1F467' +emoji[family_woman_woman_girl_boy]=$'\U1F469\U200D\U1F469\U200D\U1F467\U200D\U1F466' +emoji[family_woman_woman_boy_boy]=$'\U1F469\U200D\U1F469\U200D\U1F466\U200D\U1F466' +emoji[family_woman_woman_girl_girl]=$'\U1F469\U200D\U1F469\U200D\U1F467\U200D\U1F467' +emoji[family_man_boy]=$'\U1F468\U200D\U1F466' +emoji[family_man_boy_boy]=$'\U1F468\U200D\U1F466\U200D\U1F466' +emoji[family_man_girl]=$'\U1F468\U200D\U1F467' +emoji[family_man_girl_boy]=$'\U1F468\U200D\U1F467\U200D\U1F466' +emoji[family_man_girl_girl]=$'\U1F468\U200D\U1F467\U200D\U1F467' +emoji[family_woman_boy]=$'\U1F469\U200D\U1F466' +emoji[family_woman_boy_boy]=$'\U1F469\U200D\U1F466\U200D\U1F466' +emoji[family_woman_girl]=$'\U1F469\U200D\U1F467' +emoji[family_woman_girl_boy]=$'\U1F469\U200D\U1F467\U200D\U1F466' +emoji[family_woman_girl_girl]=$'\U1F469\U200D\U1F467\U200D\U1F467' +emoji[speaking_head]=$'\U1F5E3\UFE0F' +emoji[speaking_head_unqualified]=$'\U1F5E3' +emoji[bust_in_silhouette]=$'\U1F464' +emoji[busts_in_silhouette]=$'\U1F465' +emoji[footprints]=$'\U1F463' +emoji_mod[light_skin_tone]=$'\U1F3FB' +emoji_mod[medium_light_skin_tone]=$'\U1F3FC' +emoji_mod[medium_skin_tone]=$'\U1F3FD' +emoji_mod[medium_dark_skin_tone]=$'\U1F3FE' +emoji_mod[medium_dark_skin_tone_1]=$'\U1F3FF' +emoji_mod[red_hair]=$'\U1F9B0' +emoji_mod[curly_hair]=$'\U1F9B1' +emoji_mod[white_hair]=$'\U1F9B3' +emoji_mod[bald]=$'\U1F9B2' +emoji[monkey_face]=$'\U1F435' +emoji[monkey_face_1]=$'\U1F412' +emoji[monkey]=$'\U1F412' +emoji[gorilla]=$'\U1F98D' +emoji[orangutan]=$'\U1F9A7' +emoji[dog_face]=$'\U1F436' +emoji[dog]=$'\U1F436' +emoji[dog_face_1]=$'\U1F415' +emoji[dog2]=$'\U1F415' +emoji[guide_dog]=$'\U1F9AE' +emoji[service_dog]=$'\U1F415\U200D\U1F9BA' +emoji[poodle]=$'\U1F429' +emoji[wolf]=$'\U1F43A' +emoji[fox]=$'\U1F98A' +emoji[fox_face]=$'\U1F98A' +emoji[raccoon]=$'\U1F99D' +emoji[cat_face]=$'\U1F431' +emoji[cat]=$'\U1F431' +emoji[cat_face_1]=$'\U1F408' +emoji[cat2]=$'\U1F408' +emoji[lion]=$'\U1F981' +emoji[tiger_face]=$'\U1F42F' +emoji[tiger]=$'\U1F42F' +emoji[tiger_face_1]=$'\U1F405' +emoji[tiger2]=$'\U1F405' +emoji[leopard]=$'\U1F406' +emoji[horse_face]=$'\U1F434' +emoji[horse]=$'\U1F434' +emoji[horse_face_1]=$'\U1F40E' +emoji[racehorse]=$'\U1F40E' +emoji[unicorn]=$'\U1F984' +emoji[zebra]=$'\U1F993' +emoji[deer]=$'\U1F98C' +emoji[cow_face]=$'\U1F42E' +emoji[ox]=$'\U1F402' +emoji[water_buffalo]=$'\U1F403' +emoji[cow]=$'\U1F404' +emoji[cow2]=$'\U1F404' +emoji[pig_face]=$'\U1F437' +emoji[pig]=$'\U1F437' +emoji[pig_face_1]=$'\U1F416' +emoji[pig2]=$'\U1F416' +emoji[boar]=$'\U1F417' +emoji[pig_nose]=$'\U1F43D' +emoji[ram]=$'\U1F40F' +emoji[ewe]=$'\U1F411' +emoji[sheep]=$'\U1F411' +emoji[goat]=$'\U1F410' +emoji[camel]=$'\U1F42A' +emoji[dromedary_camel]=$'\U1F42A' +emoji[two_hump_camel]=$'\U1F42B' +emoji[llama]=$'\U1F999' +emoji[giraffe]=$'\U1F992' +emoji[elephant]=$'\U1F418' +emoji[rhinoceros]=$'\U1F98F' +emoji[hippopotamus]=$'\U1F99B' +emoji[mouse_face]=$'\U1F42D' +emoji[mouse]=$'\U1F42D' +emoji[mouse_face_1]=$'\U1F401' +emoji[mouse2]=$'\U1F401' +emoji[rat]=$'\U1F400' +emoji[hamster]=$'\U1F439' +emoji[rabbit_face]=$'\U1F430' +emoji[rabbit]=$'\U1F430' +emoji[rabbit_face_1]=$'\U1F407' +emoji[rabbit2]=$'\U1F407' +emoji[chipmunk]=$'\U1F43F\UFE0F' +emoji[chipmunk_unqualified]=$'\U1F43F' +emoji[hedgehog]=$'\U1F994' +emoji[bat]=$'\U1F987' +emoji[bear]=$'\U1F43B' +emoji[koala]=$'\U1F428' +emoji[panda]=$'\U1F43C' +emoji[panda_face]=$'\U1F43C' +emoji[sloth]=$'\U1F9A5' +emoji[otter]=$'\U1F9A6' +emoji[skunk]=$'\U1F9A8' +emoji[kangaroo]=$'\U1F998' +emoji[badger]=$'\U1F9A1' +emoji[paw_prints]=$'\U1F43E' +emoji[feet]=$'\U1F43E' +emoji[turkey]=$'\U1F983' +emoji[chicken]=$'\U1F414' +emoji[rooster]=$'\U1F413' +emoji[hatching_chick]=$'\U1F423' +emoji[baby_chick]=$'\U1F424' +emoji[front_facing_baby_chick]=$'\U1F425' +emoji[hatched_chick]=$'\U1F425' +emoji[bird]=$'\U1F426' +emoji[penguin]=$'\U1F427' +emoji[dove]=$'\U1F54A\UFE0F' +emoji[dove_unqualified]=$'\U1F54A' +emoji[eagle]=$'\U1F985' +emoji[duck]=$'\U1F986' +emoji[swan]=$'\U1F9A2' +emoji[owl]=$'\U1F989' +emoji[flamingo]=$'\U1F9A9' +emoji[peacock]=$'\U1F99A' +emoji[parrot]=$'\U1F99C' +emoji[frog]=$'\U1F438' +emoji[crocodile]=$'\U1F40A' +emoji[turtle]=$'\U1F422' +emoji[lizard]=$'\U1F98E' +emoji[snake]=$'\U1F40D' +emoji[dragon_face]=$'\U1F432' +emoji[dragon_face_1]=$'\U1F409' +emoji[dragon]=$'\U1F409' +emoji[sauropod]=$'\U1F995' +emoji[T_Rex]=$'\U1F996' +emoji[t-rex]=$'\U1F996' +emoji[spouting_whale]=$'\U1F433' +emoji[whale]=$'\U1F433' +emoji[spouting_whale_1]=$'\U1F40B' +emoji[whale2]=$'\U1F40B' +emoji[dolphin]=$'\U1F42C' +emoji[flipper]=$'\U1F42C' +emoji[fish]=$'\U1F41F' +emoji[tropical_fish]=$'\U1F420' +emoji[blowfish]=$'\U1F421' +emoji[shark]=$'\U1F988' +emoji[octopus]=$'\U1F419' +emoji[spiral_shell]=$'\U1F41A' +emoji[shell]=$'\U1F41A' +emoji[snail]=$'\U1F40C' +emoji[butterfly]=$'\U1F98B' +emoji[bug]=$'\U1F41B' +emoji[ant]=$'\U1F41C' +emoji[honeybee]=$'\U1F41D' +emoji[bee]=$'\U1F41D' +emoji[lady_beetle]=$'\U1F41E' +emoji[beetle]=$'\U1F41E' +emoji[cricket]=$'\U1F997' +emoji[spider]=$'\U1F577\UFE0F' +emoji[spider_unqualified]=$'\U1F577' +emoji[spider_web]=$'\U1F578\UFE0F' +emoji[spider_web_unqualified]=$'\U1F578' +emoji[scorpion]=$'\U1F982' +emoji[mosquito]=$'\U1F99F' +emoji[microbe]=$'\U1F9A0' +emoji[bouquet]=$'\U1F490' +emoji[cherry_blossom]=$'\U1F338' +emoji[white_flower]=$'\U1F4AE' +emoji[rosette]=$'\U1F3F5\UFE0F' +emoji[rosette_unqualified]=$'\U1F3F5' +emoji[rosette_unqualified_1]=$'\U1F339' +emoji[rose]=$'\U1F339' +emoji[wilted_flower]=$'\U1F940' +emoji[hibiscus]=$'\U1F33A' +emoji[sunflower]=$'\U1F33B' +emoji[blossom]=$'\U1F33C' +emoji[tulip]=$'\U1F337' +emoji[seedling]=$'\U1F331' +emoji[evergreen_tree]=$'\U1F332' +emoji[deciduous_tree]=$'\U1F333' +emoji[palm_tree]=$'\U1F334' +emoji[cactus]=$'\U1F335' +emoji[sheaf_of_rice]=$'\U1F33E' +emoji[ear_of_rice]=$'\U1F33E' +emoji[herb]=$'\U1F33F' +emoji[shamrock]=$'\U2618\UFE0F' +emoji[shamrock_unqualified]=$'\U2618' +emoji[four_leaf_clover]=$'\U1F340' +emoji[maple_leaf]=$'\U1F341' +emoji[fallen_leaf]=$'\U1F342' +emoji[leaf_fluttering_in_wind]=$'\U1F343' +emoji[leaves]=$'\U1F343' +emoji[grapes]=$'\U1F347' +emoji[melon]=$'\U1F348' +emoji[watermelon]=$'\U1F349' +emoji[tangerine]=$'\U1F34A' +emoji[orange]=$'\U1F34A' +emoji[mandarin]=$'\U1F34A' +emoji[lemon]=$'\U1F34B' +emoji[banana]=$'\U1F34C' +emoji[pineapple]=$'\U1F34D' +emoji[mango]=$'\U1F96D' +emoji[red_apple]=$'\U1F34E' +emoji[apple]=$'\U1F34E' +emoji[green_apple]=$'\U1F34F' +emoji[pear]=$'\U1F350' +emoji[peach]=$'\U1F351' +emoji[cherries]=$'\U1F352' +emoji[strawberry]=$'\U1F353' +emoji[kiwi_fruit]=$'\U1F95D' +emoji[tomato]=$'\U1F345' +emoji[coconut]=$'\U1F965' +emoji[avocado]=$'\U1F951' +emoji[eggplant]=$'\U1F346' +emoji[potato]=$'\U1F954' +emoji[carrot]=$'\U1F955' +emoji[ear_of_corn]=$'\U1F33D' +emoji[corn]=$'\U1F33D' +emoji[hot_pepper]=$'\U1F336\UFE0F' +emoji[hot_pepper_unqualified]=$'\U1F336' +emoji[cucumber]=$'\U1F952' +emoji[leafy_green]=$'\U1F96C' +emoji[broccoli]=$'\U1F966' +emoji[garlic]=$'\U1F9C4' +emoji[onion]=$'\U1F9C5' +emoji[mushroom]=$'\U1F344' +emoji[peanuts]=$'\U1F95C' +emoji[chestnut]=$'\U1F330' +emoji[bread]=$'\U1F35E' +emoji[croissant]=$'\U1F950' +emoji[baguette_bread]=$'\U1F956' +emoji[pretzel]=$'\U1F968' +emoji[bagel]=$'\U1F96F' +emoji[pancakes]=$'\U1F95E' +emoji[waffle]=$'\U1F9C7' +emoji[cheese_wedge]=$'\U1F9C0' +emoji[cheese]=$'\U1F9C0' +emoji[meat_on_bone]=$'\U1F356' +emoji[poultry_leg]=$'\U1F357' +emoji[cut_of_meat]=$'\U1F969' +emoji[bacon]=$'\U1F953' +emoji[hamburger]=$'\U1F354' +emoji[french_fries]=$'\U1F35F' +emoji[fries]=$'\U1F35F' +emoji[pizza]=$'\U1F355' +emoji[hot_dog]=$'\U1F32D' +emoji[hotdog]=$'\U1F32D' +emoji[sandwich]=$'\U1F96A' +emoji[taco]=$'\U1F32E' +emoji[burrito]=$'\U1F32F' +emoji[stuffed_flatbread]=$'\U1F959' +emoji[falafel]=$'\U1F9C6' +emoji[egg]=$'\U1F95A' +emoji[cooking]=$'\U1F373' +emoji[fried_egg]=$'\U1F373' +emoji[shallow_pan_of_food]=$'\U1F958' +emoji[pot_of_food]=$'\U1F372' +emoji[stew]=$'\U1F372' +emoji[bowl_with_spoon]=$'\U1F963' +emoji[green_salad]=$'\U1F957' +emoji[popcorn]=$'\U1F37F' +emoji[butter]=$'\U1F9C8' +emoji[salt]=$'\U1F9C2' +emoji[canned_food]=$'\U1F96B' +emoji[bento_box]=$'\U1F371' +emoji[bento]=$'\U1F371' +emoji[rice_cracker]=$'\U1F358' +emoji[rice_ball]=$'\U1F359' +emoji[cooked_rice]=$'\U1F35A' +emoji[rice]=$'\U1F35A' +emoji[curry_rice]=$'\U1F35B' +emoji[curry]=$'\U1F35B' +emoji[steaming_bowl]=$'\U1F35C' +emoji[ramen]=$'\U1F35C' +emoji[spaghetti]=$'\U1F35D' +emoji[roasted_sweet_potato]=$'\U1F360' +emoji[sweet_potato]=$'\U1F360' +emoji[oden]=$'\U1F362' +emoji[sushi]=$'\U1F363' +emoji[fried_shrimp]=$'\U1F364' +emoji[fish_cake_with_swirl]=$'\U1F365' +emoji[fish_cake]=$'\U1F365' +emoji[moon_cake]=$'\U1F96E' +emoji[dango]=$'\U1F361' +emoji[dumpling]=$'\U1F95F' +emoji[fortune_cookie]=$'\U1F960' +emoji[takeout_box]=$'\U1F961' +emoji[crab]=$'\U1F980' +emoji[lobster]=$'\U1F99E' +emoji[shrimp]=$'\U1F990' +emoji[squid]=$'\U1F991' +emoji[oyster]=$'\U1F9AA' +emoji[soft_ice_cream]=$'\U1F366' +emoji[icecream]=$'\U1F366' +emoji[shaved_ice]=$'\U1F367' +emoji[ice_cream]=$'\U1F368' +emoji[doughnut]=$'\U1F369' +emoji[cookie]=$'\U1F36A' +emoji[birthday_cake]=$'\U1F382' +emoji[birthday]=$'\U1F382' +emoji[shortcake]=$'\U1F370' +emoji[cake]=$'\U1F370' +emoji[cupcake]=$'\U1F9C1' +emoji[pie]=$'\U1F967' +emoji[chocolate_bar]=$'\U1F36B' +emoji[candy]=$'\U1F36C' +emoji[lollipop]=$'\U1F36D' +emoji[custard]=$'\U1F36E' +emoji[honey_pot]=$'\U1F36F' +emoji[baby_bottle]=$'\U1F37C' +emoji[glass_of_milk]=$'\U1F95B' +emoji[milk_glass]=$'\U1F95B' +emoji[hot_beverage]=$'\U2615' +emoji[coffee]=$'\U2615' +emoji[teacup_without_handle]=$'\U1F375' +emoji[tea]=$'\U1F375' +emoji[sake]=$'\U1F376' +emoji[bottle_with_popping_cork]=$'\U1F37E' +emoji[champagne]=$'\U1F37E' +emoji[wine_glass]=$'\U1F377' +emoji[cocktail_glass]=$'\U1F378' +emoji[cocktail]=$'\U1F378' +emoji[tropical_drink]=$'\U1F379' +emoji[beer_mug]=$'\U1F37A' +emoji[beer]=$'\U1F37A' +emoji[clinking_beer_mugs]=$'\U1F37B' +emoji[beers]=$'\U1F37B' +emoji[clinking_glasses]=$'\U1F942' +emoji[tumbler_glass]=$'\U1F943' +emoji[cup_with_straw]=$'\U1F964' +emoji[beverage_box]=$'\U1F9C3' +emoji[mate]=$'\U1F9C9' +emoji[ice_cube]=$'\U1F9CA' +emoji[chopsticks]=$'\U1F962' +emoji[fork_and_knife_with_plate]=$'\U1F37D\UFE0F' +emoji[fork_and_knife_with_plate_unqualified]=$'\U1F37D' +emoji[plate_with_cutlery]=$'\U1F37D' +emoji[fork_and_knife_with_plate_unqualified_1]=$'\U1F374' +emoji[fork_and_knife]=$'\U1F374' +emoji[spoon]=$'\U1F944' +emoji[kitchen_knife]=$'\U1F52A' +emoji[hocho]=$'\U1F52A' +emoji[knife]=$'\U1F52A' +emoji[amphora]=$'\U1F3FA' +emoji[globe_showing_Europe_Africa]=$'\U1F30D' +emoji[earth_africa]=$'\U1F30D' +emoji[globe_showing_Americas]=$'\U1F30E' +emoji[earth_americas]=$'\U1F30E' +emoji[globe_showing_Asia_Australia]=$'\U1F30F' +emoji[earth_asia]=$'\U1F30F' +emoji[globe_with_meridians]=$'\U1F310' +emoji[world_map]=$'\U1F5FA\UFE0F' +emoji[world_map_unqualified]=$'\U1F5FA' +emoji[map_of_Japan]=$'\U1F5FE' +emoji[japan]=$'\U1F5FE' +emoji[compass]=$'\U1F9ED' +emoji[snow_capped_mountain]=$'\U1F3D4\UFE0F' +emoji[snow_capped_mountain_unqualified]=$'\U1F3D4' +emoji[mountain_snow]=$'\U1F3D4' +emoji[snow_capped_mountain_unqualified_1]=$'\U26F0\UFE0F' +emoji[snow_capped_mountain_unqualified_2]=$'\U26F0' +emoji[mountain]=$'\U26F0' +emoji[volcano]=$'\U1F30B' +emoji[mount_fuji]=$'\U1F5FB' +emoji[camping]=$'\U1F3D5\UFE0F' +emoji[camping_unqualified]=$'\U1F3D5' +emoji[beach_with_umbrella]=$'\U1F3D6\UFE0F' +emoji[beach_with_umbrella_unqualified]=$'\U1F3D6' +emoji[beach_umbrella]=$'\U1F3D6' +emoji[desert]=$'\U1F3DC\UFE0F' +emoji[desert_unqualified]=$'\U1F3DC' +emoji[desert_island]=$'\U1F3DD\UFE0F' +emoji[desert_island_unqualified]=$'\U1F3DD' +emoji[national_park]=$'\U1F3DE\UFE0F' +emoji[national_park_unqualified]=$'\U1F3DE' +emoji[stadium]=$'\U1F3DF\UFE0F' +emoji[stadium_unqualified]=$'\U1F3DF' +emoji[classical_building]=$'\U1F3DB\UFE0F' +emoji[classical_building_unqualified]=$'\U1F3DB' +emoji[building_construction]=$'\U1F3D7\UFE0F' +emoji[building_construction_unqualified]=$'\U1F3D7' +emoji[brick]=$'\U1F9F1' +emoji[bricks]=$'\U1F9F1' +emoji[houses]=$'\U1F3D8\UFE0F' +emoji[houses_unqualified]=$'\U1F3D8' +emoji[derelict_house]=$'\U1F3DA\UFE0F' +emoji[derelict_house_unqualified]=$'\U1F3DA' +emoji[derelict_house_unqualified_1]=$'\U1F3E0' +emoji[house]=$'\U1F3E0' +emoji[house_with_garden]=$'\U1F3E1' +emoji[office_building]=$'\U1F3E2' +emoji[office]=$'\U1F3E2' +emoji[Japanese_post_office]=$'\U1F3E3' +emoji[post_office]=$'\U1F3E3' +emoji[Japanese_post_office_1]=$'\U1F3E4' +emoji[european_post_office]=$'\U1F3E4' +emoji[hospital]=$'\U1F3E5' +emoji[bank]=$'\U1F3E6' +emoji[hotel]=$'\U1F3E8' +emoji[love_hotel]=$'\U1F3E9' +emoji[convenience_store]=$'\U1F3EA' +emoji[school]=$'\U1F3EB' +emoji[department_store]=$'\U1F3EC' +emoji[factory]=$'\U1F3ED' +emoji[Japanese_castle]=$'\U1F3EF' +emoji[japanese_castle]=$'\U1F3EF' +emoji[Japanese_castle_1]=$'\U1F3F0' +emoji[european_castle]=$'\U1F3F0' +emoji[wedding]=$'\U1F492' +emoji[Tokyo_tower]=$'\U1F5FC' +emoji[tokyo_tower]=$'\U1F5FC' +emoji[Statue_of_Liberty]=$'\U1F5FD' +emoji[statue_of_liberty]=$'\U1F5FD' +emoji[church]=$'\U26EA' +emoji[mosque]=$'\U1F54C' +emoji[hindu_temple]=$'\U1F6D5' +emoji[synagogue]=$'\U1F54D' +emoji[shinto_shrine]=$'\U26E9\UFE0F' +emoji[shinto_shrine_unqualified]=$'\U26E9' +emoji[kaaba]=$'\U1F54B' +emoji[fountain]=$'\U26F2' +emoji[tent]=$'\U26FA' +emoji[foggy]=$'\U1F301' +emoji[night_with_stars]=$'\U1F303' +emoji[cityscape]=$'\U1F3D9\UFE0F' +emoji[cityscape_unqualified]=$'\U1F3D9' +emoji[sunrise_over_mountains]=$'\U1F304' +emoji[sunrise_over_mountains_1]=$'\U1F305' +emoji[sunrise]=$'\U1F305' +emoji[cityscape_at_dusk]=$'\U1F306' +emoji[city_sunset]=$'\U1F306' +emoji[sunset]=$'\U1F307' +emoji[city_sunrise]=$'\U1F307' +emoji[bridge_at_night]=$'\U1F309' +emoji[hot_springs]=$'\U2668\UFE0F' +emoji[hotsprings]=$'\U2668\UFE0F' +emoji[hot_springs_unqualified]=$'\U2668' +emoji[carousel_horse]=$'\U1F3A0' +emoji[ferris_wheel]=$'\U1F3A1' +emoji[roller_coaster]=$'\U1F3A2' +emoji[barber_pole]=$'\U1F488' +emoji[barber]=$'\U1F488' +emoji[circus_tent]=$'\U1F3AA' +emoji[locomotive]=$'\U1F682' +emoji[steam_locomotive]=$'\U1F682' +emoji[railway_car]=$'\U1F683' +emoji[high_speed_train]=$'\U1F684' +emoji[bullettrain_side]=$'\U1F684' +emoji[bullet_train]=$'\U1F685' +emoji[bullettrain_front]=$'\U1F685' +emoji[bullet_train_1]=$'\U1F686' +emoji[train2]=$'\U1F686' +emoji[metro]=$'\U1F687' +emoji[light_rail]=$'\U1F688' +emoji[station]=$'\U1F689' +emoji[tram]=$'\U1F68A' +emoji[monorail]=$'\U1F69D' +emoji[mountain_railway]=$'\U1F69E' +emoji[tram_car]=$'\U1F68B' +emoji[train]=$'\U1F68B' +emoji[bus]=$'\U1F68C' +emoji[oncoming_bus]=$'\U1F68D' +emoji[trolleybus]=$'\U1F68E' +emoji[minibus]=$'\U1F690' +emoji[ambulance]=$'\U1F691' +emoji[fire_engine]=$'\U1F692' +emoji[police_car]=$'\U1F693' +emoji[oncoming_police_car]=$'\U1F694' +emoji[taxi]=$'\U1F695' +emoji[oncoming_taxi]=$'\U1F696' +emoji[automobile]=$'\U1F697' +emoji[car]=$'\U1F697' +emoji[red_car]=$'\U1F697' +emoji[oncoming_automobile]=$'\U1F698' +emoji[sport_utility_vehicle]=$'\U1F699' +emoji[blue_car]=$'\U1F699' +emoji[delivery_truck]=$'\U1F69A' +emoji[truck]=$'\U1F69A' +emoji[articulated_lorry]=$'\U1F69B' +emoji[tractor]=$'\U1F69C' +emoji[racing_car]=$'\U1F3CE\UFE0F' +emoji[racing_car_unqualified]=$'\U1F3CE' +emoji[motorcycle]=$'\U1F3CD\UFE0F' +emoji[motorcycle_unqualified]=$'\U1F3CD' +emoji[motor_scooter]=$'\U1F6F5' +emoji[manual_wheelchair]=$'\U1F9BD' +emoji[motorized_wheelchair]=$'\U1F9BC' +emoji[auto_rickshaw]=$'\U1F6FA' +emoji[bicycle]=$'\U1F6B2' +emoji[bike]=$'\U1F6B2' +emoji[kick_scooter]=$'\U1F6F4' +emoji[skateboard]=$'\U1F6F9' +emoji[bus_stop]=$'\U1F68F' +emoji[busstop]=$'\U1F68F' +emoji[motorway]=$'\U1F6E3\UFE0F' +emoji[motorway_unqualified]=$'\U1F6E3' +emoji[railway_track]=$'\U1F6E4\UFE0F' +emoji[railway_track_unqualified]=$'\U1F6E4' +emoji[oil_drum]=$'\U1F6E2\UFE0F' +emoji[oil_drum_unqualified]=$'\U1F6E2' +emoji[fuel_pump]=$'\U26FD' +emoji[fuelpump]=$'\U26FD' +emoji[police_car_light]=$'\U1F6A8' +emoji[rotating_light]=$'\U1F6A8' +emoji[horizontal_traffic_light]=$'\U1F6A5' +emoji[traffic_light]=$'\U1F6A5' +emoji[vertical_traffic_light]=$'\U1F6A6' +emoji[stop_sign]=$'\U1F6D1' +emoji[construction]=$'\U1F6A7' +emoji[anchor]=$'\U2693' +emoji[sailboat]=$'\U26F5' +emoji[boat]=$'\U26F5' +emoji[canoe]=$'\U1F6F6' +emoji[speedboat]=$'\U1F6A4' +emoji[passenger_ship]=$'\U1F6F3\UFE0F' +emoji[passenger_ship_unqualified]=$'\U1F6F3' +emoji[ferry]=$'\U26F4\UFE0F' +emoji[ferry_unqualified]=$'\U26F4' +emoji[motor_boat]=$'\U1F6E5\UFE0F' +emoji[motor_boat_unqualified]=$'\U1F6E5' +emoji[ship]=$'\U1F6A2' +emoji[airplane]=$'\U2708\UFE0F' +emoji[airplane_unqualified]=$'\U2708' +emoji[small_airplane]=$'\U1F6E9\UFE0F' +emoji[small_airplane_unqualified]=$'\U1F6E9' +emoji[airplane_departure]=$'\U1F6EB' +emoji[flight_departure]=$'\U1F6EB' +emoji[airplane_arrival]=$'\U1F6EC' +emoji[flight_arrival]=$'\U1F6EC' +emoji[parachute]=$'\U1FA82' +emoji[seat]=$'\U1F4BA' +emoji[helicopter]=$'\U1F681' +emoji[suspension_railway]=$'\U1F69F' +emoji[mountain_cableway]=$'\U1F6A0' +emoji[aerial_tramway]=$'\U1F6A1' +emoji[satellite]=$'\U1F6F0\UFE0F' +emoji[satellite_unqualified]=$'\U1F6F0' +emoji[artificial_satellite]=$'\U1F6F0' +emoji[rocket]=$'\U1F680' +emoji[flying_saucer]=$'\U1F6F8' +emoji[bellhop_bell]=$'\U1F6CE\UFE0F' +emoji[bellhop_bell_unqualified]=$'\U1F6CE' +emoji[luggage]=$'\U1F9F3' +emoji[hourglass_done]=$'\U231B' +emoji[hourglass]=$'\U231B' +emoji[hourglass_not_done]=$'\U23F3' +emoji[hourglass_flowing_sand]=$'\U23F3' +emoji[watch]=$'\U231A' +emoji[alarm_clock]=$'\U23F0' +emoji[stopwatch]=$'\U23F1\UFE0F' +emoji[stopwatch_unqualified]=$'\U23F1' +emoji[timer_clock]=$'\U23F2\UFE0F' +emoji[timer_clock_unqualified]=$'\U23F2' +emoji[mantelpiece_clock]=$'\U1F570\UFE0F' +emoji[mantelpiece_clock_unqualified]=$'\U1F570' +emoji[twelve_o_clock]=$'\U1F55B' +emoji[clock12]=$'\U1F55B' +emoji[twelve_thirty]=$'\U1F567' +emoji[clock1230]=$'\U1F567' +emoji[one_o_clock]=$'\U1F550' +emoji[clock1]=$'\U1F550' +emoji[one_thirty]=$'\U1F55C' +emoji[clock130]=$'\U1F55C' +emoji[two_o_clock]=$'\U1F551' +emoji[clock2]=$'\U1F551' +emoji[two_thirty]=$'\U1F55D' +emoji[clock230]=$'\U1F55D' +emoji[three_o_clock]=$'\U1F552' +emoji[clock3]=$'\U1F552' +emoji[three_thirty]=$'\U1F55E' +emoji[clock330]=$'\U1F55E' +emoji[four_o_clock]=$'\U1F553' +emoji[clock4]=$'\U1F553' +emoji[four_thirty]=$'\U1F55F' +emoji[clock430]=$'\U1F55F' +emoji[five_o_clock]=$'\U1F554' +emoji[clock5]=$'\U1F554' +emoji[five_thirty]=$'\U1F560' +emoji[clock530]=$'\U1F560' +emoji[six_o_clock]=$'\U1F555' +emoji[clock6]=$'\U1F555' +emoji[six_thirty]=$'\U1F561' +emoji[clock630]=$'\U1F561' +emoji[seven_o_clock]=$'\U1F556' +emoji[clock7]=$'\U1F556' +emoji[seven_thirty]=$'\U1F562' +emoji[clock730]=$'\U1F562' +emoji[eight_o_clock]=$'\U1F557' +emoji[clock8]=$'\U1F557' +emoji[eight_thirty]=$'\U1F563' +emoji[clock830]=$'\U1F563' +emoji[nine_o_clock]=$'\U1F558' +emoji[clock9]=$'\U1F558' +emoji[nine_thirty]=$'\U1F564' +emoji[clock930]=$'\U1F564' +emoji[ten_o_clock]=$'\U1F559' +emoji[clock10]=$'\U1F559' +emoji[ten_thirty]=$'\U1F565' +emoji[clock1030]=$'\U1F565' +emoji[eleven_o_clock]=$'\U1F55A' +emoji[clock11]=$'\U1F55A' +emoji[eleven_thirty]=$'\U1F566' +emoji[clock1130]=$'\U1F566' +emoji[new_moon]=$'\U1F311' +emoji[waxing_crescent_moon]=$'\U1F312' +emoji[first_quarter_moon]=$'\U1F313' +emoji[waxing_gibbous_moon]=$'\U1F314' +emoji[moon]=$'\U1F314' +emoji[full_moon]=$'\U1F315' +emoji[waning_gibbous_moon]=$'\U1F316' +emoji[last_quarter_moon]=$'\U1F317' +emoji[waning_crescent_moon]=$'\U1F318' +emoji[waning_crescent_moon_1]=$'\U1F319' +emoji[crescent_moon]=$'\U1F319' +emoji[new_moon_face]=$'\U1F31A' +emoji[new_moon_with_face]=$'\U1F31A' +emoji[first_quarter_moon_face]=$'\U1F31B' +emoji[first_quarter_moon_with_face]=$'\U1F31B' +emoji[last_quarter_moon_face]=$'\U1F31C' +emoji[last_quarter_moon_with_face]=$'\U1F31C' +emoji[thermometer]=$'\U1F321\UFE0F' +emoji[thermometer_unqualified]=$'\U1F321' +emoji[sun]=$'\U2600\UFE0F' +emoji[sunny]=$'\U2600\UFE0F' +emoji[sun_unqualified]=$'\U2600' +emoji[full_moon_face]=$'\U1F31D' +emoji[full_moon_with_face]=$'\U1F31D' +emoji[sun_with_face]=$'\U1F31E' +emoji[ringed_planet]=$'\U1FA90' +emoji[star]=$'\U2B50' +emoji[glowing_star]=$'\U1F31F' +emoji[star2]=$'\U1F31F' +emoji[shooting_star]=$'\U1F320' +emoji[stars]=$'\U1F320' +emoji[milky_way]=$'\U1F30C' +emoji[cloud]=$'\U2601\UFE0F' +emoji[cloud_unqualified]=$'\U2601' +emoji[sun_behind_cloud]=$'\U26C5' +emoji[partly_sunny]=$'\U26C5' +emoji[cloud_with_lightning_and_rain]=$'\U26C8\UFE0F' +emoji[cloud_with_lightning_and_rain_unqualified]=$'\U26C8' +emoji[sun_behind_small_cloud]=$'\U1F324\UFE0F' +emoji[sun_behind_small_cloud_unqualified]=$'\U1F324' +emoji[sun_behind_large_cloud]=$'\U1F325\UFE0F' +emoji[sun_behind_large_cloud_unqualified]=$'\U1F325' +emoji[sun_behind_rain_cloud]=$'\U1F326\UFE0F' +emoji[sun_behind_rain_cloud_unqualified]=$'\U1F326' +emoji[cloud_with_rain]=$'\U1F327\UFE0F' +emoji[cloud_with_rain_unqualified]=$'\U1F327' +emoji[cloud_with_snow]=$'\U1F328\UFE0F' +emoji[cloud_with_snow_unqualified]=$'\U1F328' +emoji[cloud_with_lightning]=$'\U1F329\UFE0F' +emoji[cloud_with_lightning_unqualified]=$'\U1F329' +emoji[tornado]=$'\U1F32A\UFE0F' +emoji[tornado_unqualified]=$'\U1F32A' +emoji[fog]=$'\U1F32B\UFE0F' +emoji[fog_unqualified]=$'\U1F32B' +emoji[wind_face]=$'\U1F32C\UFE0F' +emoji[wind_face_unqualified]=$'\U1F32C' +emoji[cyclone]=$'\U1F300' +emoji[rainbow]=$'\U1F308' +emoji[closed_umbrella]=$'\U1F302' +emoji[closed_umbrella_1]=$'\U2602\UFE0F' +emoji[open_umbrella]=$'\U2602\UFE0F' +emoji[umbrella_unqualified]=$'\U2602' +emoji[umbrella_with_rain_drops]=$'\U2614' +emoji[umbrella]=$'\U2614' +emoji[umbrella_on_ground]=$'\U26F1\UFE0F' +emoji[umbrella_on_ground_unqualified]=$'\U26F1' +emoji[parasol_on_ground]=$'\U26F1' +emoji[high_voltage]=$'\U26A1' +emoji[zap]=$'\U26A1' +emoji[snowflake]=$'\U2744\UFE0F' +emoji[snowflake_unqualified]=$'\U2744' +emoji[snowman]=$'\U2603\UFE0F' +emoji[snowman_with_snow]=$'\U2603\UFE0F' +emoji[snowman_unqualified]=$'\U2603' +emoji[snowman_without_snow]=$'\U26C4' +emoji[comet]=$'\U2604\UFE0F' +emoji[comet_unqualified]=$'\U2604' +emoji[fire]=$'\U1F525' +emoji[droplet]=$'\U1F4A7' +emoji[water_wave]=$'\U1F30A' +emoji[ocean]=$'\U1F30A' +emoji[jack_o_lantern]=$'\U1F383' +emoji[Christmas_tree]=$'\U1F384' +emoji[christmas_tree]=$'\U1F384' +emoji[fireworks]=$'\U1F386' +emoji[sparkler]=$'\U1F387' +emoji[firecracker]=$'\U1F9E8' +emoji[sparkles]=$'\U2728' +emoji[balloon]=$'\U1F388' +emoji[party_popper]=$'\U1F389' +emoji[tada]=$'\U1F389' +emoji[confetti_ball]=$'\U1F38A' +emoji[tanabata_tree]=$'\U1F38B' +emoji[pine_decoration]=$'\U1F38D' +emoji[bamboo]=$'\U1F38D' +emoji[Japanese_dolls]=$'\U1F38E' +emoji[dolls]=$'\U1F38E' +emoji[carp_streamer]=$'\U1F38F' +emoji[flags]=$'\U1F38F' +emoji[wind_chime]=$'\U1F390' +emoji[moon_viewing_ceremony]=$'\U1F391' +emoji[rice_scene]=$'\U1F391' +emoji[red_envelope]=$'\U1F9E7' +emoji[ribbon]=$'\U1F380' +emoji[wrapped_gift]=$'\U1F381' +emoji[gift]=$'\U1F381' +emoji[reminder_ribbon]=$'\U1F397\UFE0F' +emoji[reminder_ribbon_unqualified]=$'\U1F397' +emoji[admission_tickets]=$'\U1F39F\UFE0F' +emoji[admission_tickets_unqualified]=$'\U1F39F' +emoji[tickets]=$'\U1F39F' +emoji[admission_tickets_unqualified_1]=$'\U1F3AB' +emoji[ticket]=$'\U1F3AB' +emoji[military_medal]=$'\U1F396\UFE0F' +emoji[military_medal_unqualified]=$'\U1F396' +emoji[medal_military]=$'\U1F396' +emoji[trophy]=$'\U1F3C6' +emoji[sports_medal]=$'\U1F3C5' +emoji[medal_sports]=$'\U1F3C5' +emoji[1st_place_medal]=$'\U1F947' +emoji[2nd_place_medal]=$'\U1F948' +emoji[3rd_place_medal]=$'\U1F949' +emoji[soccer_ball]=$'\U26BD' +emoji[soccer]=$'\U26BD' +emoji[baseball]=$'\U26BE' +emoji[softball]=$'\U1F94E' +emoji[basketball]=$'\U1F3C0' +emoji[volleyball]=$'\U1F3D0' +emoji[american_football]=$'\U1F3C8' +emoji[football]=$'\U1F3C8' +emoji[rugby_football]=$'\U1F3C9' +emoji[tennis]=$'\U1F3BE' +emoji[flying_disc]=$'\U1F94F' +emoji[bowling]=$'\U1F3B3' +emoji[cricket_game]=$'\U1F3CF' +emoji[field_hockey]=$'\U1F3D1' +emoji[ice_hockey]=$'\U1F3D2' +emoji[lacrosse]=$'\U1F94D' +emoji[ping_pong]=$'\U1F3D3' +emoji[badminton]=$'\U1F3F8' +emoji[boxing_glove]=$'\U1F94A' +emoji[martial_arts_uniform]=$'\U1F94B' +emoji[goal_net]=$'\U1F945' +emoji[flag_in_hole]=$'\U26F3' +emoji[golf]=$'\U26F3' +emoji[ice_skate]=$'\U26F8\UFE0F' +emoji[ice_skate_unqualified]=$'\U26F8' +emoji[fishing_pole]=$'\U1F3A3' +emoji[fishing_pole_and_fish]=$'\U1F3A3' +emoji[diving_mask]=$'\U1F93F' +emoji[running_shirt]=$'\U1F3BD' +emoji[running_shirt_with_sash]=$'\U1F3BD' +emoji[skis]=$'\U1F3BF' +emoji[ski]=$'\U1F3BF' +emoji[sled]=$'\U1F6F7' +emoji[curling_stone]=$'\U1F94C' +emoji[direct_hit]=$'\U1F3AF' +emoji[dart]=$'\U1F3AF' +emoji[yo_yo]=$'\U1FA80' +emoji[kite]=$'\U1FA81' +emoji[pool_8_ball]=$'\U1F3B1' +emoji[8ball]=$'\U1F3B1' +emoji[crystal_ball]=$'\U1F52E' +emoji[nazar_amulet]=$'\U1F9FF' +emoji[video_game]=$'\U1F3AE' +emoji[joystick]=$'\U1F579\UFE0F' +emoji[joystick_unqualified]=$'\U1F579' +emoji[slot_machine]=$'\U1F3B0' +emoji[game_die]=$'\U1F3B2' +emoji[puzzle_piece]=$'\U1F9E9' +emoji[jigsaw]=$'\U1F9E9' +emoji[teddy_bear]=$'\U1F9F8' +emoji[spade_suit]=$'\U2660\UFE0F' +emoji[spades]=$'\U2660\UFE0F' +emoji[spade_suit_unqualified]=$'\U2660' +emoji[heart_suit]=$'\U2665\UFE0F' +emoji[hearts]=$'\U2665\UFE0F' +emoji[heart_suit_unqualified]=$'\U2665' +emoji[diamond_suit]=$'\U2666\UFE0F' +emoji[diamonds]=$'\U2666\UFE0F' +emoji[diamond_suit_unqualified]=$'\U2666' +emoji[club_suit]=$'\U2663\UFE0F' +emoji[clubs]=$'\U2663\UFE0F' +emoji[club_suit_unqualified]=$'\U2663' +emoji[chess_pawn]=$'\U265F\UFE0F' +emoji[chess_pawn_unqualified]=$'\U265F' +emoji[joker]=$'\U1F0CF' +emoji[black_joker]=$'\U1F0CF' +emoji[mahjong_red_dragon]=$'\U1F004' +emoji[mahjong]=$'\U1F004' +emoji[flower_playing_cards]=$'\U1F3B4' +emoji[performing_arts]=$'\U1F3AD' +emoji[framed_picture]=$'\U1F5BC\UFE0F' +emoji[framed_picture_unqualified]=$'\U1F5BC' +emoji[artist_palette]=$'\U1F3A8' +emoji[art]=$'\U1F3A8' +emoji[thread]=$'\U1F9F5' +emoji[yarn]=$'\U1F9F6' +emoji[glasses]=$'\U1F453' +emoji[eyeglasses]=$'\U1F453' +emoji[sunglasses]=$'\U1F576\UFE0F' +emoji[sunglasses_unqualified]=$'\U1F576' +emoji[dark_sunglasses]=$'\U1F576' +emoji[goggles]=$'\U1F97D' +emoji[lab_coat]=$'\U1F97C' +emoji[safety_vest]=$'\U1F9BA' +emoji[necktie]=$'\U1F454' +emoji[t_shirt]=$'\U1F455' +emoji[shirt]=$'\U1F455' +emoji[tshirt]=$'\U1F455' +emoji[jeans]=$'\U1F456' +emoji[scarf]=$'\U1F9E3' +emoji[gloves]=$'\U1F9E4' +emoji[coat]=$'\U1F9E5' +emoji[socks]=$'\U1F9E6' +emoji[dress]=$'\U1F457' +emoji[kimono]=$'\U1F458' +emoji[sari]=$'\U1F97B' +emoji[one_piece_swimsuit]=$'\U1FA71' +emoji[swim_brief]=$'\U1FA72' +emoji[shorts]=$'\U1FA73' +emoji[bikini]=$'\U1F459' +emoji[woman_s_clothes]=$'\U1F45A' +emoji[womans_clothes]=$'\U1F45A' +emoji[purse]=$'\U1F45B' +emoji[handbag]=$'\U1F45C' +emoji[clutch_bag]=$'\U1F45D' +emoji[pouch]=$'\U1F45D' +emoji[shopping_bags]=$'\U1F6CD\UFE0F' +emoji[shopping_bags_unqualified]=$'\U1F6CD' +emoji[shopping]=$'\U1F6CD' +emoji[backpack]=$'\U1F392' +emoji[school_satchel]=$'\U1F392' +emoji[man_s_shoe]=$'\U1F45E' +emoji[mans_shoe]=$'\U1F45E' +emoji[shoe]=$'\U1F45E' +emoji[running_shoe]=$'\U1F45F' +emoji[athletic_shoe]=$'\U1F45F' +emoji[hiking_boot]=$'\U1F97E' +emoji[flat_shoe]=$'\U1F97F' +emoji[high_heeled_shoe]=$'\U1F460' +emoji[high_heel]=$'\U1F460' +emoji[woman_s_sandal]=$'\U1F461' +emoji[sandal]=$'\U1F461' +emoji[ballet_shoes]=$'\U1FA70' +emoji[woman_s_boot]=$'\U1F462' +emoji[boot]=$'\U1F462' +emoji[crown]=$'\U1F451' +emoji[woman_s_hat]=$'\U1F452' +emoji[womans_hat]=$'\U1F452' +emoji[top_hat]=$'\U1F3A9' +emoji[tophat]=$'\U1F3A9' +emoji[graduation_cap]=$'\U1F393' +emoji[mortar_board]=$'\U1F393' +emoji[billed_cap]=$'\U1F9E2' +emoji[rescue_worker_s_helmet]=$'\U26D1\UFE0F' +emoji[rescue_worker_s_helmet_unqualified]=$'\U26D1' +emoji[rescue_worker_helmet]=$'\U26D1' +emoji[prayer_beads]=$'\U1F4FF' +emoji[lipstick]=$'\U1F484' +emoji[ring]=$'\U1F48D' +emoji[gem_stone]=$'\U1F48E' +emoji[gem]=$'\U1F48E' +emoji[muted_speaker]=$'\U1F507' +emoji[mute]=$'\U1F507' +emoji[speaker_low_volume]=$'\U1F508' +emoji[speaker]=$'\U1F508' +emoji[speaker_medium_volume]=$'\U1F509' +emoji[sound]=$'\U1F509' +emoji[speaker_high_volume]=$'\U1F50A' +emoji[loud_sound]=$'\U1F50A' +emoji[loudspeaker]=$'\U1F4E2' +emoji[megaphone]=$'\U1F4E3' +emoji[mega]=$'\U1F4E3' +emoji[postal_horn]=$'\U1F4EF' +emoji[bell]=$'\U1F514' +emoji[bell_with_slash]=$'\U1F515' +emoji[no_bell]=$'\U1F515' +emoji[musical_score]=$'\U1F3BC' +emoji[musical_note]=$'\U1F3B5' +emoji[musical_notes]=$'\U1F3B6' +emoji[notes]=$'\U1F3B6' +emoji[studio_microphone]=$'\U1F399\UFE0F' +emoji[studio_microphone_unqualified]=$'\U1F399' +emoji[level_slider]=$'\U1F39A\UFE0F' +emoji[level_slider_unqualified]=$'\U1F39A' +emoji[control_knobs]=$'\U1F39B\UFE0F' +emoji[control_knobs_unqualified]=$'\U1F39B' +emoji[microphone]=$'\U1F3A4' +emoji[headphone]=$'\U1F3A7' +emoji[headphones]=$'\U1F3A7' +emoji[radio]=$'\U1F4FB' +emoji[saxophone]=$'\U1F3B7' +emoji[guitar]=$'\U1F3B8' +emoji[musical_keyboard]=$'\U1F3B9' +emoji[trumpet]=$'\U1F3BA' +emoji[violin]=$'\U1F3BB' +emoji[banjo]=$'\U1FA95' +emoji[drum]=$'\U1F941' +emoji[mobile_phone]=$'\U1F4F1' +emoji[iphone]=$'\U1F4F1' +emoji[mobile_phone_with_arrow]=$'\U1F4F2' +emoji[calling]=$'\U1F4F2' +emoji[telephone]=$'\U260E\UFE0F' +emoji[phone]=$'\U260E\UFE0F' +emoji[telephone_unqualified]=$'\U260E' +emoji[telephone_receiver]=$'\U1F4DE' +emoji[pager]=$'\U1F4DF' +emoji[fax_machine]=$'\U1F4E0' +emoji[fax]=$'\U1F4E0' +emoji[battery]=$'\U1F50B' +emoji[electric_plug]=$'\U1F50C' +emoji[laptop_computer]=$'\U1F4BB' +emoji[computer]=$'\U1F4BB' +emoji[desktop_computer]=$'\U1F5A5\UFE0F' +emoji[desktop_computer_unqualified]=$'\U1F5A5' +emoji[printer]=$'\U1F5A8\UFE0F' +emoji[printer_unqualified]=$'\U1F5A8' +emoji[keyboard]=$'\U2328\UFE0F' +emoji[keyboard_unqualified]=$'\U2328' +emoji[computer_mouse]=$'\U1F5B1\UFE0F' +emoji[computer_mouse_unqualified]=$'\U1F5B1' +emoji[trackball]=$'\U1F5B2\UFE0F' +emoji[trackball_unqualified]=$'\U1F5B2' +emoji[computer_disk]=$'\U1F4BD' +emoji[minidisc]=$'\U1F4BD' +emoji[floppy_disk]=$'\U1F4BE' +emoji[optical_disk]=$'\U1F4BF' +emoji[cd]=$'\U1F4BF' +emoji[dvd]=$'\U1F4C0' +emoji[abacus]=$'\U1F9EE' +emoji[movie_camera]=$'\U1F3A5' +emoji[film_frames]=$'\U1F39E\UFE0F' +emoji[film_frames_unqualified]=$'\U1F39E' +emoji[film_strip]=$'\U1F39E' +emoji[film_projector]=$'\U1F4FD\UFE0F' +emoji[film_projector_unqualified]=$'\U1F4FD' +emoji[clapper_board]=$'\U1F3AC' +emoji[clapper]=$'\U1F3AC' +emoji[television]=$'\U1F4FA' +emoji[tv]=$'\U1F4FA' +emoji[camera]=$'\U1F4F7' +emoji[camera_with_flash]=$'\U1F4F8' +emoji[camera_flash]=$'\U1F4F8' +emoji[video_camera]=$'\U1F4F9' +emoji[videocassette]=$'\U1F4FC' +emoji[vhs]=$'\U1F4FC' +emoji[magnifying_glass_tilted_left]=$'\U1F50D' +emoji[mag]=$'\U1F50D' +emoji[magnifying_glass_tilted_right]=$'\U1F50E' +emoji[mag_right]=$'\U1F50E' +emoji[candle]=$'\U1F56F\UFE0F' +emoji[candle_unqualified]=$'\U1F56F' +emoji[light_bulb]=$'\U1F4A1' +emoji[bulb]=$'\U1F4A1' +emoji[flashlight]=$'\U1F526' +emoji[red_paper_lantern]=$'\U1F3EE' +emoji[izakaya_lantern]=$'\U1F3EE' +emoji[lantern]=$'\U1F3EE' +emoji[diya_lamp]=$'\U1FA94' +emoji[notebook_with_decorative_cover]=$'\U1F4D4' +emoji[closed_book]=$'\U1F4D5' +emoji[open_book]=$'\U1F4D6' +emoji[book]=$'\U1F4D6' +emoji[green_book]=$'\U1F4D7' +emoji[blue_book]=$'\U1F4D8' +emoji[orange_book]=$'\U1F4D9' +emoji[books]=$'\U1F4DA' +emoji[notebook]=$'\U1F4D3' +emoji[ledger]=$'\U1F4D2' +emoji[page_with_curl]=$'\U1F4C3' +emoji[scroll]=$'\U1F4DC' +emoji[page_facing_up]=$'\U1F4C4' +emoji[newspaper]=$'\U1F4F0' +emoji[rolled_up_newspaper]=$'\U1F5DE\UFE0F' +emoji[rolled_up_newspaper_unqualified]=$'\U1F5DE' +emoji[newspaper_roll]=$'\U1F5DE' +emoji[bookmark_tabs]=$'\U1F4D1' +emoji[bookmark_tabs_1]=$'\U1F516' +emoji[bookmark]=$'\U1F516' +emoji[label]=$'\U1F3F7\UFE0F' +emoji[label_unqualified]=$'\U1F3F7' +emoji[money_bag]=$'\U1F4B0' +emoji[moneybag]=$'\U1F4B0' +emoji[yen_banknote]=$'\U1F4B4' +emoji[yen]=$'\U1F4B4' +emoji[dollar_banknote]=$'\U1F4B5' +emoji[dollar]=$'\U1F4B5' +emoji[euro_banknote]=$'\U1F4B6' +emoji[euro]=$'\U1F4B6' +emoji[pound_banknote]=$'\U1F4B7' +emoji[pound]=$'\U1F4B7' +emoji[money_with_wings]=$'\U1F4B8' +emoji[credit_card]=$'\U1F4B3' +emoji[receipt]=$'\U1F9FE' +emoji[chart_increasing_with_yen]=$'\U1F4B9' +emoji[chart]=$'\U1F4B9' +emoji[currency_exchange]=$'\U1F4B1' +emoji[heavy_dollar_sign]=$'\U1F4B2' +emoji[envelope]=$'\U2709\UFE0F' +emoji[email]=$'\U2709\UFE0F' +emoji[envelope_unqualified]=$'\U2709' +emoji[e_mail]=$'\U1F4E7' +emoji[e-mail]=$'\U1F4E7' +emoji[incoming_envelope]=$'\U1F4E8' +emoji[envelope_with_arrow]=$'\U1F4E9' +emoji[outbox_tray]=$'\U1F4E4' +emoji[inbox_tray]=$'\U1F4E5' +emoji[package]=$'\U1F4E6' +emoji[closed_mailbox_with_raised_flag]=$'\U1F4EB' +emoji[mailbox]=$'\U1F4EB' +emoji[closed_mailbox_with_lowered_flag]=$'\U1F4EA' +emoji[mailbox_closed]=$'\U1F4EA' +emoji[open_mailbox_with_raised_flag]=$'\U1F4EC' +emoji[mailbox_with_mail]=$'\U1F4EC' +emoji[open_mailbox_with_lowered_flag]=$'\U1F4ED' +emoji[mailbox_with_no_mail]=$'\U1F4ED' +emoji[postbox]=$'\U1F4EE' +emoji[ballot_box_with_ballot]=$'\U1F5F3\UFE0F' +emoji[ballot_box_with_ballot_unqualified]=$'\U1F5F3' +emoji[ballot_box]=$'\U1F5F3' +emoji[pencil]=$'\U270F\UFE0F' +emoji[pencil2]=$'\U270F\UFE0F' +emoji[pencil_unqualified]=$'\U270F' +emoji[black_nib]=$'\U2712\UFE0F' +emoji[black_nib_unqualified]=$'\U2712' +emoji[fountain_pen]=$'\U1F58B\UFE0F' +emoji[fountain_pen_unqualified]=$'\U1F58B' +emoji[fountain_pen_unqualified_1]=$'\U1F58A\UFE0F' +emoji[fountain_pen_unqualified_2]=$'\U1F58A' +emoji[pen]=$'\U1F58A' +emoji[paintbrush]=$'\U1F58C\UFE0F' +emoji[paintbrush_unqualified]=$'\U1F58C' +emoji[crayon]=$'\U1F58D\UFE0F' +emoji[crayon_unqualified]=$'\U1F58D' +emoji[memo]=$'\U1F4DD' +emoji[briefcase]=$'\U1F4BC' +emoji[file_folder]=$'\U1F4C1' +emoji[open_file_folder]=$'\U1F4C2' +emoji[card_index_dividers]=$'\U1F5C2\UFE0F' +emoji[card_index_dividers_unqualified]=$'\U1F5C2' +emoji[calendar]=$'\U1F4C5' +emoji[date]=$'\U1F4C5' +emoji[tear_off_calendar]=$'\U1F4C6' +emoji[spiral_notepad]=$'\U1F5D2\UFE0F' +emoji[spiral_notepad_unqualified]=$'\U1F5D2' +emoji[spiral_calendar]=$'\U1F5D3\UFE0F' +emoji[spiral_calendar_unqualified]=$'\U1F5D3' +emoji[card_index]=$'\U1F4C7' +emoji[chart_increasing]=$'\U1F4C8' +emoji[chart_with_upwards_trend]=$'\U1F4C8' +emoji[chart_decreasing]=$'\U1F4C9' +emoji[chart_with_downwards_trend]=$'\U1F4C9' +emoji[bar_chart]=$'\U1F4CA' +emoji[clipboard]=$'\U1F4CB' +emoji[pushpin]=$'\U1F4CC' +emoji[round_pushpin]=$'\U1F4CD' +emoji[paperclip]=$'\U1F4CE' +emoji[linked_paperclips]=$'\U1F587\UFE0F' +emoji[linked_paperclips_unqualified]=$'\U1F587' +emoji[paperclips]=$'\U1F587' +emoji[straight_ruler]=$'\U1F4CF' +emoji[triangular_ruler]=$'\U1F4D0' +emoji[scissors]=$'\U2702\UFE0F' +emoji[scissors_unqualified]=$'\U2702' +emoji[card_file_box]=$'\U1F5C3\UFE0F' +emoji[card_file_box_unqualified]=$'\U1F5C3' +emoji[file_cabinet]=$'\U1F5C4\UFE0F' +emoji[file_cabinet_unqualified]=$'\U1F5C4' +emoji[wastebasket]=$'\U1F5D1\UFE0F' +emoji[wastebasket_unqualified]=$'\U1F5D1' +emoji[locked]=$'\U1F512' +emoji[lock]=$'\U1F512' +emoji[unlocked]=$'\U1F513' +emoji[unlock]=$'\U1F513' +emoji[locked_with_pen]=$'\U1F50F' +emoji[lock_with_ink_pen]=$'\U1F50F' +emoji[locked_with_key]=$'\U1F510' +emoji[closed_lock_with_key]=$'\U1F510' +emoji[locked_with_key_1]=$'\U1F511' +emoji[key]=$'\U1F511' +emoji[old_key]=$'\U1F5DD\UFE0F' +emoji[old_key_unqualified]=$'\U1F5DD' +emoji[hammer]=$'\U1F528' +emoji[axe]=$'\U1FA93' +emoji[pick]=$'\U26CF\UFE0F' +emoji[pick_unqualified]=$'\U26CF' +emoji[hammer_and_pick]=$'\U2692\UFE0F' +emoji[hammer_and_pick_unqualified]=$'\U2692' +emoji[hammer_and_wrench]=$'\U1F6E0\UFE0F' +emoji[hammer_and_wrench_unqualified]=$'\U1F6E0' +emoji[dagger]=$'\U1F5E1\UFE0F' +emoji[dagger_unqualified]=$'\U1F5E1' +emoji[crossed_swords]=$'\U2694\UFE0F' +emoji[crossed_swords_unqualified]=$'\U2694' +emoji[pistol]=$'\U1F52B' +emoji[gun]=$'\U1F52B' +emoji[bow_and_arrow]=$'\U1F3F9' +emoji[shield]=$'\U1F6E1\UFE0F' +emoji[shield_unqualified]=$'\U1F6E1' +emoji[wrench]=$'\U1F527' +emoji[nut_and_bolt]=$'\U1F529' +emoji[gear]=$'\U2699\UFE0F' +emoji[gear_unqualified]=$'\U2699' +emoji[clamp]=$'\U1F5DC\UFE0F' +emoji[clamp_unqualified]=$'\U1F5DC' +emoji[balance_scale]=$'\U2696\UFE0F' +emoji[balance_scale_unqualified]=$'\U2696' +emoji[probing_cane]=$'\U1F9AF' +emoji[link]=$'\U1F517' +emoji[chains]=$'\U26D3\UFE0F' +emoji[chains_unqualified]=$'\U26D3' +emoji[toolbox]=$'\U1F9F0' +emoji[magnet]=$'\U1F9F2' +emoji[alembic]=$'\U2697\UFE0F' +emoji[alembic_unqualified]=$'\U2697' +emoji[test_tube]=$'\U1F9EA' +emoji[petri_dish]=$'\U1F9EB' +emoji[dna]=$'\U1F9EC' +emoji[microscope]=$'\U1F52C' +emoji[telescope]=$'\U1F52D' +emoji[satellite_antenna]=$'\U1F4E1' +emoji[syringe]=$'\U1F489' +emoji[drop_of_blood]=$'\U1FA78' +emoji[pill]=$'\U1F48A' +emoji[adhesive_bandage]=$'\U1FA79' +emoji[stethoscope]=$'\U1FA7A' +emoji[door]=$'\U1F6AA' +emoji[bed]=$'\U1F6CF\UFE0F' +emoji[bed_unqualified]=$'\U1F6CF' +emoji[couch_and_lamp]=$'\U1F6CB\UFE0F' +emoji[couch_and_lamp_unqualified]=$'\U1F6CB' +emoji[chair]=$'\U1FA91' +emoji[toilet]=$'\U1F6BD' +emoji[shower]=$'\U1F6BF' +emoji[bathtub]=$'\U1F6C1' +emoji[razor]=$'\U1FA92' +emoji[lotion_bottle]=$'\U1F9F4' +emoji[safety_pin]=$'\U1F9F7' +emoji[broom]=$'\U1F9F9' +emoji[basket]=$'\U1F9FA' +emoji[roll_of_paper]=$'\U1F9FB' +emoji[soap]=$'\U1F9FC' +emoji[sponge]=$'\U1F9FD' +emoji[fire_extinguisher]=$'\U1F9EF' +emoji[shopping_cart]=$'\U1F6D2' +emoji[cigarette]=$'\U1F6AC' +emoji[smoking]=$'\U1F6AC' +emoji[coffin]=$'\U26B0\UFE0F' +emoji[coffin_unqualified]=$'\U26B0' +emoji[funeral_urn]=$'\U26B1\UFE0F' +emoji[funeral_urn_unqualified]=$'\U26B1' +emoji[moai]=$'\U1F5FF' +emoji[moyai]=$'\U1F5FF' +emoji[ATM_sign]=$'\U1F3E7' +emoji[atm]=$'\U1F3E7' +emoji[litter_in_bin_sign]=$'\U1F6AE' +emoji[put_litter_in_its_place]=$'\U1F6AE' +emoji[potable_water]=$'\U1F6B0' +emoji[wheelchair_symbol]=$'\U267F' +emoji[wheelchair]=$'\U267F' +emoji[men_s_room]=$'\U1F6B9' +emoji[mens]=$'\U1F6B9' +emoji[women_s_room]=$'\U1F6BA' +emoji[womens]=$'\U1F6BA' +emoji[restroom]=$'\U1F6BB' +emoji[baby_symbol]=$'\U1F6BC' +emoji[water_closet]=$'\U1F6BE' +emoji[wc]=$'\U1F6BE' +emoji[passport_control]=$'\U1F6C2' +emoji[customs]=$'\U1F6C3' +emoji[baggage_claim]=$'\U1F6C4' +emoji[left_luggage]=$'\U1F6C5' +emoji[warning]=$'\U26A0\UFE0F' +emoji[warning_unqualified]=$'\U26A0' +emoji[children_crossing]=$'\U1F6B8' +emoji[no_entry]=$'\U26D4' +emoji[prohibited]=$'\U1F6AB' +emoji[no_entry_sign]=$'\U1F6AB' +emoji[no_bicycles]=$'\U1F6B3' +emoji[no_smoking]=$'\U1F6AD' +emoji[no_littering]=$'\U1F6AF' +emoji[do_not_litter]=$'\U1F6AF' +emoji[non_potable_water]=$'\U1F6B1' +emoji[non-potable_water]=$'\U1F6B1' +emoji[no_pedestrians]=$'\U1F6B7' +emoji[no_mobile_phones]=$'\U1F4F5' +emoji[no_one_under_eighteen]=$'\U1F51E' +emoji[underage]=$'\U1F51E' +emoji[radioactive]=$'\U2622\UFE0F' +emoji[radioactive_unqualified]=$'\U2622' +emoji[biohazard]=$'\U2623\UFE0F' +emoji[biohazard_unqualified]=$'\U2623' +emoji[up_arrow]=$'\U2B06\UFE0F' +emoji[arrow_up]=$'\U2B06\UFE0F' +emoji[up_arrow_unqualified]=$'\U2B06' +emoji[up_right_arrow]=$'\U2197\UFE0F' +emoji[arrow_upper_right]=$'\U2197\UFE0F' +emoji[up_right_arrow_unqualified]=$'\U2197' +emoji[up_right_arrow_unqualified_1]=$'\U27A1\UFE0F' +emoji[arrow_right]=$'\U27A1\UFE0F' +emoji[up_right_arrow_unqualified_2]=$'\U27A1' +emoji[down_right_arrow]=$'\U2198\UFE0F' +emoji[arrow_lower_right]=$'\U2198\UFE0F' +emoji[down_right_arrow_unqualified]=$'\U2198' +emoji[down_arrow]=$'\U2B07\UFE0F' +emoji[arrow_down]=$'\U2B07\UFE0F' +emoji[down_arrow_unqualified]=$'\U2B07' +emoji[down_left_arrow]=$'\U2199\UFE0F' +emoji[arrow_lower_left]=$'\U2199\UFE0F' +emoji[down_left_arrow_unqualified]=$'\U2199' +emoji[down_left_arrow_unqualified_1]=$'\U2B05\UFE0F' +emoji[arrow_left]=$'\U2B05\UFE0F' +emoji[down_left_arrow_unqualified_2]=$'\U2B05' +emoji[up_left_arrow]=$'\U2196\UFE0F' +emoji[arrow_upper_left]=$'\U2196\UFE0F' +emoji[up_left_arrow_unqualified]=$'\U2196' +emoji[up_down_arrow]=$'\U2195\UFE0F' +emoji[arrow_up_down]=$'\U2195\UFE0F' +emoji[up_down_arrow_unqualified]=$'\U2195' +emoji[left_right_arrow]=$'\U2194\UFE0F' +emoji[left_right_arrow_unqualified]=$'\U2194' +emoji[right_arrow_curving_left]=$'\U21A9\UFE0F' +emoji[leftwards_arrow_with_hook]=$'\U21A9\UFE0F' +emoji[right_arrow_curving_left_unqualified]=$'\U21A9' +emoji[left_arrow_curving_right]=$'\U21AA\UFE0F' +emoji[arrow_right_hook]=$'\U21AA\UFE0F' +emoji[left_arrow_curving_right_unqualified]=$'\U21AA' +emoji[right_arrow_curving_up]=$'\U2934\UFE0F' +emoji[arrow_heading_up]=$'\U2934\UFE0F' +emoji[right_arrow_curving_up_unqualified]=$'\U2934' +emoji[right_arrow_curving_down]=$'\U2935\UFE0F' +emoji[arrow_heading_down]=$'\U2935\UFE0F' +emoji[right_arrow_curving_down_unqualified]=$'\U2935' +emoji[clockwise_vertical_arrows]=$'\U1F503' +emoji[arrows_clockwise]=$'\U1F503' +emoji[counterclockwise_arrows_button]=$'\U1F504' +emoji[arrows_counterclockwise]=$'\U1F504' +emoji[BACK_arrow]=$'\U1F519' +emoji[back]=$'\U1F519' +emoji[END_arrow]=$'\U1F51A' +emoji[end]=$'\U1F51A' +emoji[ON_arrow]=$'\U1F51B' +emoji[on]=$'\U1F51B' +emoji[SOON_arrow]=$'\U1F51C' +emoji[soon]=$'\U1F51C' +emoji[TOP_arrow]=$'\U1F51D' +emoji[top]=$'\U1F51D' +emoji[place_of_worship]=$'\U1F6D0' +emoji[atom_symbol]=$'\U269B\UFE0F' +emoji[atom_symbol_unqualified]=$'\U269B' +emoji[atom_symbol_unqualified_1]=$'\U1F549\UFE0F' +emoji[om_unqualified]=$'\U1F549' +emoji[om]=$'\U1F549' +emoji[star_of_David]=$'\U2721\UFE0F' +emoji[star_of_david]=$'\U2721\UFE0F' +emoji[star_of_David_unqualified]=$'\U2721' +emoji[wheel_of_dharma]=$'\U2638\UFE0F' +emoji[wheel_of_dharma_unqualified]=$'\U2638' +emoji[yin_yang]=$'\U262F\UFE0F' +emoji[yin_yang_unqualified]=$'\U262F' +emoji[latin_cross]=$'\U271D\UFE0F' +emoji[latin_cross_unqualified]=$'\U271D' +emoji[orthodox_cross]=$'\U2626\UFE0F' +emoji[orthodox_cross_unqualified]=$'\U2626' +emoji[star_and_crescent]=$'\U262A\UFE0F' +emoji[star_and_crescent_unqualified]=$'\U262A' +emoji[peace_symbol]=$'\U262E\UFE0F' +emoji[peace_symbol_unqualified]=$'\U262E' +emoji[menorah]=$'\U1F54E' +emoji[dotted_six_pointed_star]=$'\U1F52F' +emoji[six_pointed_star]=$'\U1F52F' +emoji[Aries]=$'\U2648' +emoji[aries]=$'\U2648' +emoji[Taurus]=$'\U2649' +emoji[taurus]=$'\U2649' +emoji[Gemini]=$'\U264A' +emoji[gemini]=$'\U264A' +emoji[Cancer]=$'\U264B' +emoji[cancer]=$'\U264B' +emoji[Leo]=$'\U264C' +emoji[leo]=$'\U264C' +emoji[Virgo]=$'\U264D' +emoji[virgo]=$'\U264D' +emoji[Libra]=$'\U264E' +emoji[libra]=$'\U264E' +emoji[Scorpio]=$'\U264F' +emoji[scorpius]=$'\U264F' +emoji[Sagittarius]=$'\U2650' +emoji[sagittarius]=$'\U2650' +emoji[Capricorn]=$'\U2651' +emoji[capricorn]=$'\U2651' +emoji[Aquarius]=$'\U2652' +emoji[aquarius]=$'\U2652' +emoji[Pisces]=$'\U2653' +emoji[pisces]=$'\U2653' +emoji[Ophiuchus]=$'\U26CE' +emoji[ophiuchus]=$'\U26CE' +emoji[shuffle_tracks_button]=$'\U1F500' +emoji[twisted_rightwards_arrows]=$'\U1F500' +emoji[repeat_button]=$'\U1F501' +emoji[repeat]=$'\U1F501' +emoji[repeat_single_button]=$'\U1F502' +emoji[repeat_one]=$'\U1F502' +emoji[play_button]=$'\U25B6\UFE0F' +emoji[arrow_forward]=$'\U25B6\UFE0F' +emoji[play_button_unqualified]=$'\U25B6' +emoji[fast_forward_button]=$'\U23E9' +emoji[fast_forward]=$'\U23E9' +emoji[next_track_button]=$'\U23ED\UFE0F' +emoji[next_track_button_unqualified]=$'\U23ED' +emoji[play_or_pause_button]=$'\U23EF\UFE0F' +emoji[play_or_pause_button_unqualified]=$'\U23EF' +emoji[reverse_button]=$'\U25C0\UFE0F' +emoji[arrow_backward]=$'\U25C0\UFE0F' +emoji[reverse_button_unqualified]=$'\U25C0' +emoji[fast_reverse_button]=$'\U23EA' +emoji[rewind]=$'\U23EA' +emoji[last_track_button]=$'\U23EE\UFE0F' +emoji[last_track_button_unqualified]=$'\U23EE' +emoji[previous_track_button]=$'\U23EE' +emoji[upwards_button]=$'\U1F53C' +emoji[arrow_up_small]=$'\U1F53C' +emoji[fast_up_button]=$'\U23EB' +emoji[arrow_double_up]=$'\U23EB' +emoji[downwards_button]=$'\U1F53D' +emoji[arrow_down_small]=$'\U1F53D' +emoji[fast_down_button]=$'\U23EC' +emoji[arrow_double_down]=$'\U23EC' +emoji[pause_button]=$'\U23F8\UFE0F' +emoji[pause_button_unqualified]=$'\U23F8' +emoji[stop_button]=$'\U23F9\UFE0F' +emoji[stop_button_unqualified]=$'\U23F9' +emoji[record_button]=$'\U23FA\UFE0F' +emoji[record_button_unqualified]=$'\U23FA' +emoji[eject_button]=$'\U23CF\UFE0F' +emoji[eject_button_unqualified]=$'\U23CF' +emoji[cinema]=$'\U1F3A6' +emoji[dim_button]=$'\U1F505' +emoji[low_brightness]=$'\U1F505' +emoji[bright_button]=$'\U1F506' +emoji[high_brightness]=$'\U1F506' +emoji[antenna_bars]=$'\U1F4F6' +emoji[signal_strength]=$'\U1F4F6' +emoji[vibration_mode]=$'\U1F4F3' +emoji[mobile_phone_off]=$'\U1F4F4' +emoji[female_sign]=$'\U2640\UFE0F' +emoji[female_sign_unqualified]=$'\U2640' +emoji[female_sign_unqualified_1]=$'\U2642\UFE0F' +emoji[male_sign]=$'\U2642\UFE0F' +emoji[female_sign_unqualified_2]=$'\U2642' +emoji[medical_symbol]=$'\U2695\UFE0F' +emoji[medical_symbol_unqualified]=$'\U2695' +emoji[infinity]=$'\U267E\UFE0F' +emoji[infinity_unqualified]=$'\U267E' +emoji[recycling_symbol]=$'\U267B\UFE0F' +emoji[recycle]=$'\U267B\UFE0F' +emoji[recycling_symbol_unqualified]=$'\U267B' +emoji[fleur_de_lis]=$'\U269C\UFE0F' +emoji[fleur_de_lis_unqualified]=$'\U269C' +emoji[trident_emblem]=$'\U1F531' +emoji[trident]=$'\U1F531' +emoji[name_badge]=$'\U1F4DB' +emoji[Japanese_symbol_for_beginner]=$'\U1F530' +emoji[beginner]=$'\U1F530' +emoji[hollow_red_circle]=$'\U2B55' +emoji[o]=$'\U2B55' +emoji[check_mark_button]=$'\U2705' +emoji[white_check_mark]=$'\U2705' +emoji[check_box_with_check]=$'\U2611\UFE0F' +emoji[ballot_box_with_check]=$'\U2611\UFE0F' +emoji[check_box_with_check_unqualified]=$'\U2611' +emoji[check_mark]=$'\U2714\UFE0F' +emoji[heavy_check_mark]=$'\U2714\UFE0F' +emoji[check_mark_unqualified]=$'\U2714' +emoji[multiplication_sign]=$'\U2716\UFE0F' +emoji[heavy_multiplication_x]=$'\U2716\UFE0F' +emoji[multiplication_sign_unqualified]=$'\U2716' +emoji[cross_mark]=$'\U274C' +emoji[x]=$'\U274C' +emoji[cross_mark_button]=$'\U274E' +emoji[negative_squared_cross_mark]=$'\U274E' +emoji[plus_sign]=$'\U2795' +emoji[heavy_plus_sign]=$'\U2795' +emoji[minus_sign]=$'\U2796' +emoji[heavy_minus_sign]=$'\U2796' +emoji[division_sign]=$'\U2797' +emoji[heavy_division_sign]=$'\U2797' +emoji[curly_loop]=$'\U27B0' +emoji[double_curly_loop]=$'\U27BF' +emoji[loop]=$'\U27BF' +emoji[part_alternation_mark]=$'\U303D\UFE0F' +emoji[part_alternation_mark_unqualified]=$'\U303D' +emoji[eight_spoked_asterisk]=$'\U2733\UFE0F' +emoji[eight_spoked_asterisk_unqualified]=$'\U2733' +emoji[eight_pointed_star]=$'\U2734\UFE0F' +emoji[eight_pointed_black_star]=$'\U2734\UFE0F' +emoji[eight_pointed_star_unqualified]=$'\U2734' +emoji[sparkle]=$'\U2747\UFE0F' +emoji[sparkle_unqualified]=$'\U2747' +emoji[double_exclamation_mark]=$'\U203C\UFE0F' +emoji[bangbang]=$'\U203C\UFE0F' +emoji[double_exclamation_mark_unqualified]=$'\U203C' +emoji[exclamation_question_mark]=$'\U2049\UFE0F' +emoji[interrobang]=$'\U2049\UFE0F' +emoji[exclamation_question_mark_unqualified]=$'\U2049' +emoji[exclamation_question_mark_unqualified_1]=$'\U2753' +emoji[question]=$'\U2753' +emoji[white_question_mark]=$'\U2754' +emoji[grey_question]=$'\U2754' +emoji[white_exclamation_mark]=$'\U2755' +emoji[grey_exclamation]=$'\U2755' +emoji[white_exclamation_mark_1]=$'\U2757' +emoji[exclamation]=$'\U2757' +emoji[heavy_exclamation_mark]=$'\U2757' +emoji[wavy_dash]=$'\U3030\UFE0F' +emoji[wavy_dash_unqualified]=$'\U3030' +emoji[copyright]=$'\U00A9\UFE0F' +emoji[copyright_unqualified]=$'\U00A9' +emoji[registered]=$'\U00AE\UFE0F' +emoji[registered_unqualified]=$'\U00AE' +emoji[trade_mark]=$'\U2122\UFE0F' +emoji[tm]=$'\U2122\UFE0F' +emoji[trade_mark_unqualified]=$'\U2122' +emoji[keycap_#]=$'\U0023\UFE0F\U20E3' +emoji[hash]=$'\U0023\UFE0F\U20E3' +emoji[keycap_#_unqualified]=$'\U0023\U20E3' +emoji[keycap_*]=$'\U002A\UFE0F\U20E3' +emoji[asterisk]=$'\U002A\UFE0F\U20E3' +emoji[keycap_*_unqualified]=$'\U002A\U20E3' +emoji[keycap_0]=$'\U0030\UFE0F\U20E3' +emoji[zero]=$'\U0030\UFE0F\U20E3' +emoji[keycap_0_unqualified]=$'\U0030\U20E3' +emoji[keycap_1]=$'\U0031\UFE0F\U20E3' +emoji[one]=$'\U0031\UFE0F\U20E3' +emoji[keycap_1_unqualified]=$'\U0031\U20E3' +emoji[keycap_2]=$'\U0032\UFE0F\U20E3' +emoji[two]=$'\U0032\UFE0F\U20E3' +emoji[keycap_2_unqualified]=$'\U0032\U20E3' +emoji[keycap_3]=$'\U0033\UFE0F\U20E3' +emoji[three]=$'\U0033\UFE0F\U20E3' +emoji[keycap_3_unqualified]=$'\U0033\U20E3' +emoji[keycap_4]=$'\U0034\UFE0F\U20E3' +emoji[four]=$'\U0034\UFE0F\U20E3' +emoji[keycap_4_unqualified]=$'\U0034\U20E3' +emoji[keycap_5]=$'\U0035\UFE0F\U20E3' +emoji[five]=$'\U0035\UFE0F\U20E3' +emoji[keycap_5_unqualified]=$'\U0035\U20E3' +emoji[keycap_6]=$'\U0036\UFE0F\U20E3' +emoji[six]=$'\U0036\UFE0F\U20E3' +emoji[keycap_6_unqualified]=$'\U0036\U20E3' +emoji[keycap_7]=$'\U0037\UFE0F\U20E3' +emoji[seven]=$'\U0037\UFE0F\U20E3' +emoji[keycap_7_unqualified]=$'\U0037\U20E3' +emoji[keycap_8]=$'\U0038\UFE0F\U20E3' +emoji[eight]=$'\U0038\UFE0F\U20E3' +emoji[keycap_8_unqualified]=$'\U0038\U20E3' +emoji[keycap_9]=$'\U0039\UFE0F\U20E3' +emoji[nine]=$'\U0039\UFE0F\U20E3' +emoji[keycap_9_unqualified]=$'\U0039\U20E3' +emoji[keycap_10]=$'\U1F51F' +emoji[keycap_ten]=$'\U1F51F' +emoji[input_latin_uppercase]=$'\U1F520' +emoji[capital_abcd]=$'\U1F520' +emoji[input_latin_lowercase]=$'\U1F521' +emoji[abcd]=$'\U1F521' +emoji[input_numbers]=$'\U1F522' +emoji[1234]=$'\U1F522' +emoji[input_symbols]=$'\U1F523' +emoji[symbols]=$'\U1F523' +emoji[input_latin_letters]=$'\U1F524' +emoji[abc]=$'\U1F524' +emoji[A_button_blood_type_]=$'\U1F170\UFE0F' +emoji[a]=$'\U1F170\UFE0F' +emoji[A_button_blood_type__unqualified]=$'\U1F170' +emoji[AB_button_blood_type_]=$'\U1F18E' +emoji[ab]=$'\U1F18E' +emoji[AB_button_blood_type__1]=$'\U1F171\UFE0F' +emoji[b]=$'\U1F171\UFE0F' +emoji[B_button_blood_type__unqualified]=$'\U1F171' +emoji[CL_button]=$'\U1F191' +emoji[cl]=$'\U1F191' +emoji[COOL_button]=$'\U1F192' +emoji[cool]=$'\U1F192' +emoji[FREE_button]=$'\U1F193' +emoji[free]=$'\U1F193' +emoji[information]=$'\U2139\UFE0F' +emoji[information_source]=$'\U2139\UFE0F' +emoji[information_unqualified]=$'\U2139' +emoji[ID_button]=$'\U1F194' +emoji[id]=$'\U1F194' +emoji[circled_M]=$'\U24C2\UFE0F' +emoji[m]=$'\U24C2\UFE0F' +emoji[circled_M_unqualified]=$'\U24C2' +emoji[NEW_button]=$'\U1F195' +emoji[new]=$'\U1F195' +emoji[NG_button]=$'\U1F196' +emoji[ng]=$'\U1F196' +emoji[O_button_blood_type_]=$'\U1F17E\UFE0F' +emoji[o2]=$'\U1F17E\UFE0F' +emoji[O_button_blood_type__unqualified]=$'\U1F17E' +emoji[OK_button]=$'\U1F197' +emoji[ok]=$'\U1F197' +emoji[P_button]=$'\U1F17F\UFE0F' +emoji[parking]=$'\U1F17F\UFE0F' +emoji[P_button_unqualified]=$'\U1F17F' +emoji[SOS_button]=$'\U1F198' +emoji[sos]=$'\U1F198' +emoji[UP_button]=$'\U1F199' +emoji[up]=$'\U1F199' +emoji[VS_button]=$'\U1F19A' +emoji[vs]=$'\U1F19A' +emoji[Japanese_here_button]=$'\U1F201' +emoji[koko]=$'\U1F201' +emoji[Japanese_service_charge_button]=$'\U1F202\UFE0F' +emoji[sa]=$'\U1F202\UFE0F' +emoji[Japanese_service_charge_button_unqualified]=$'\U1F202' +emoji[Japanese_monthly_amount_button]=$'\U1F237\UFE0F' +emoji[u6708]=$'\U1F237\UFE0F' +emoji[Japanese_monthly_amount_button_unqualified]=$'\U1F237' +emoji[Japanese_not_free_of_charge_button]=$'\U1F236' +emoji[u6709]=$'\U1F236' +emoji[Japanese_reserved_button]=$'\U1F22F' +emoji[u6307]=$'\U1F22F' +emoji[Japanese_bargain_button]=$'\U1F250' +emoji[ideograph_advantage]=$'\U1F250' +emoji[Japanese_discount_button]=$'\U1F239' +emoji[u5272]=$'\U1F239' +emoji[Japanese_free_of_charge_button]=$'\U1F21A' +emoji[u7121]=$'\U1F21A' +emoji[Japanese_prohibited_button]=$'\U1F232' +emoji[u7981]=$'\U1F232' +emoji[Japanese_acceptable_button]=$'\U1F251' +emoji[accept]=$'\U1F251' +emoji[Japanese_application_button]=$'\U1F238' +emoji[u7533]=$'\U1F238' +emoji[Japanese_passing_grade_button]=$'\U1F234' +emoji[u5408]=$'\U1F234' +emoji[Japanese_vacancy_button]=$'\U1F233' +emoji[u7a7a]=$'\U1F233' +emoji[Japanese_congratulations_button]=$'\U3297\UFE0F' +emoji[congratulations]=$'\U3297\UFE0F' +emoji[Japanese_congratulations_button_unqualified]=$'\U3297' +emoji[Japanese_secret_button]=$'\U3299\UFE0F' +emoji[secret]=$'\U3299\UFE0F' +emoji[Japanese_secret_button_unqualified]=$'\U3299' +emoji[Japanese_open_for_business_button]=$'\U1F23A' +emoji[u55b6]=$'\U1F23A' +emoji[Japanese_no_vacancy_button]=$'\U1F235' +emoji[u6e80]=$'\U1F235' +emoji[red_circle]=$'\U1F534' +emoji[orange_circle]=$'\U1F7E0' +emoji[yellow_circle]=$'\U1F7E1' +emoji[green_circle]=$'\U1F7E2' +emoji[blue_circle]=$'\U1F535' +emoji[large_blue_circle]=$'\U1F535' +emoji[purple_circle]=$'\U1F7E3' +emoji[brown_circle]=$'\U1F7E4' +emoji[black_circle]=$'\U26AB' +emoji[white_circle]=$'\U26AA' +emoji[red_square]=$'\U1F7E5' +emoji[orange_square]=$'\U1F7E7' +emoji[yellow_square]=$'\U1F7E8' +emoji[green_square]=$'\U1F7E9' +emoji[blue_square]=$'\U1F7E6' +emoji[purple_square]=$'\U1F7EA' +emoji[brown_square]=$'\U1F7EB' +emoji[black_large_square]=$'\U2B1B' +emoji[white_large_square]=$'\U2B1C' +emoji[black_medium_square]=$'\U25FC\UFE0F' +emoji[black_medium_square_unqualified]=$'\U25FC' +emoji[white_medium_square]=$'\U25FB\UFE0F' +emoji[white_medium_square_unqualified]=$'\U25FB' +emoji[black_medium_small_square]=$'\U25FE' +emoji[white_medium_small_square]=$'\U25FD' +emoji[black_small_square]=$'\U25AA\UFE0F' +emoji[black_small_square_unqualified]=$'\U25AA' +emoji[white_small_square]=$'\U25AB\UFE0F' +emoji[white_small_square_unqualified]=$'\U25AB' +emoji[large_orange_diamond]=$'\U1F536' +emoji[large_blue_diamond]=$'\U1F537' +emoji[small_orange_diamond]=$'\U1F538' +emoji[small_blue_diamond]=$'\U1F539' +emoji[red_triangle_pointed_up]=$'\U1F53A' +emoji[small_red_triangle]=$'\U1F53A' +emoji[red_triangle_pointed_down]=$'\U1F53B' +emoji[small_red_triangle_down]=$'\U1F53B' +emoji[diamond_with_a_dot]=$'\U1F4A0' +emoji[diamond_shape_with_a_dot_inside]=$'\U1F4A0' +emoji[radio_button]=$'\U1F518' +emoji[white_square_button]=$'\U1F533' +emoji[black_square_button]=$'\U1F532' +emoji_flags[chequered_flag]=$'\U1F3C1' +emoji_flags[checkered_flag]=$'\U1F3C1' +emoji_flags[triangular_flag]=$'\U1F6A9' +emoji_flags[triangular_flag_on_post]=$'\U1F6A9' +emoji_flags[crossed_flags]=$'\U1F38C' +emoji_flags[black_flag]=$'\U1F3F4' +emoji_flags[white_flag]=$'\U1F3F3\UFE0F' +emoji_flags[white_flag_unqualified]=$'\U1F3F3' +emoji_flags[rainbow_flag]=$'\U1F3F3\UFE0F\U200D\U1F308' +emoji_flags[rainbow_flag_unqualified]=$'\U1F3F3\U200D\U1F308' +emoji_flags[pirate_flag]=$'\U1F3F4\U200D\U2620\UFE0F' +emoji_flags[pirate_flag_minimally]=$'\U1F3F4\U200D\U2620' +emoji_flags[Ascension_Island]=$'\U1F1E6\U1F1E8' +emoji_flags[ascension_island]=$'\U1F1E6\U1F1E8' +emoji_flags[Andorra]=$'\U1F1E6\U1F1E9' +emoji_flags[AD]=$'\U1F1E6\U1F1E9' +emoji_flags[AND]=$'\U1F1E6\U1F1E9' +emoji_flags[andorra]=$'\U1F1E6\U1F1E9' +emoji_flags[United_Arab_Emirates]=$'\U1F1E6\U1F1EA' +emoji_flags[AE]=$'\U1F1E6\U1F1EA' +emoji_flags[ARE]=$'\U1F1E6\U1F1EA' +emoji_flags[united_arab_emirates]=$'\U1F1E6\U1F1EA' +emoji_flags[Afghanistan]=$'\U1F1E6\U1F1EB' +emoji_flags[AF]=$'\U1F1E6\U1F1EB' +emoji_flags[AFG]=$'\U1F1E6\U1F1EB' +emoji_flags[afghanistan]=$'\U1F1E6\U1F1EB' +emoji_flags[Antigua_and_Barbuda]=$'\U1F1E6\U1F1EC' +emoji_flags[AG]=$'\U1F1E6\U1F1EC' +emoji_flags[ATG]=$'\U1F1E6\U1F1EC' +emoji_flags[antigua_barbuda]=$'\U1F1E6\U1F1EC' +emoji_flags[Anguilla]=$'\U1F1E6\U1F1EE' +emoji_flags[AI]=$'\U1F1E6\U1F1EE' +emoji_flags[AIA]=$'\U1F1E6\U1F1EE' +emoji_flags[anguilla]=$'\U1F1E6\U1F1EE' +emoji_flags[Albania]=$'\U1F1E6\U1F1F1' +emoji_flags[AL]=$'\U1F1E6\U1F1F1' +emoji_flags[ALB]=$'\U1F1E6\U1F1F1' +emoji_flags[albania]=$'\U1F1E6\U1F1F1' +emoji_flags[Armenia]=$'\U1F1E6\U1F1F2' +emoji_flags[AM]=$'\U1F1E6\U1F1F2' +emoji_flags[ARM]=$'\U1F1E6\U1F1F2' +emoji_flags[armenia]=$'\U1F1E6\U1F1F2' +emoji_flags[Angola]=$'\U1F1E6\U1F1F4' +emoji_flags[AO]=$'\U1F1E6\U1F1F4' +emoji_flags[AGO]=$'\U1F1E6\U1F1F4' +emoji_flags[angola]=$'\U1F1E6\U1F1F4' +emoji_flags[Antarctica]=$'\U1F1E6\U1F1F6' +emoji_flags[AQ]=$'\U1F1E6\U1F1F6' +emoji_flags[ATA]=$'\U1F1E6\U1F1F6' +emoji_flags[antarctica]=$'\U1F1E6\U1F1F6' +emoji_flags[Argentina]=$'\U1F1E6\U1F1F7' +emoji_flags[AR]=$'\U1F1E6\U1F1F7' +emoji_flags[ARG]=$'\U1F1E6\U1F1F7' +emoji_flags[argentina]=$'\U1F1E6\U1F1F7' +emoji_flags[American_Samoa]=$'\U1F1E6\U1F1F8' +emoji_flags[AS]=$'\U1F1E6\U1F1F8' +emoji_flags[ASM]=$'\U1F1E6\U1F1F8' +emoji_flags[american_samoa]=$'\U1F1E6\U1F1F8' +emoji_flags[Austria]=$'\U1F1E6\U1F1F9' +emoji_flags[AT]=$'\U1F1E6\U1F1F9' +emoji_flags[AUT]=$'\U1F1E6\U1F1F9' +emoji_flags[austria]=$'\U1F1E6\U1F1F9' +emoji_flags[Australia]=$'\U1F1E6\U1F1FA' +emoji_flags[AU]=$'\U1F1E6\U1F1FA' +emoji_flags[AUS]=$'\U1F1E6\U1F1FA' +emoji_flags[australia]=$'\U1F1E6\U1F1FA' +emoji_flags[Aruba]=$'\U1F1E6\U1F1FC' +emoji_flags[AW]=$'\U1F1E6\U1F1FC' +emoji_flags[ABW]=$'\U1F1E6\U1F1FC' +emoji_flags[aruba]=$'\U1F1E6\U1F1FC' +emoji_flags[Åland_Islands]=$'\U1F1E6\U1F1FD' +emoji_flags[AX]=$'\U1F1E6\U1F1FD' +emoji_flags[ALA]=$'\U1F1E6\U1F1FD' +emoji_flags[aland_islands]=$'\U1F1E6\U1F1FD' +emoji_flags[Azerbaijan]=$'\U1F1E6\U1F1FF' +emoji_flags[AZ]=$'\U1F1E6\U1F1FF' +emoji_flags[AZE]=$'\U1F1E6\U1F1FF' +emoji_flags[azerbaijan]=$'\U1F1E6\U1F1FF' +emoji_flags[Bosnia_and_Herzegovina]=$'\U1F1E7\U1F1E6' +emoji_flags[BA]=$'\U1F1E7\U1F1E6' +emoji_flags[BIH]=$'\U1F1E7\U1F1E6' +emoji_flags[bosnia_herzegovina]=$'\U1F1E7\U1F1E6' +emoji_flags[Barbados]=$'\U1F1E7\U1F1E7' +emoji_flags[BB]=$'\U1F1E7\U1F1E7' +emoji_flags[BRB]=$'\U1F1E7\U1F1E7' +emoji_flags[barbados]=$'\U1F1E7\U1F1E7' +emoji_flags[Bangladesh]=$'\U1F1E7\U1F1E9' +emoji_flags[BD]=$'\U1F1E7\U1F1E9' +emoji_flags[BGD]=$'\U1F1E7\U1F1E9' +emoji_flags[bangladesh]=$'\U1F1E7\U1F1E9' +emoji_flags[Belgium]=$'\U1F1E7\U1F1EA' +emoji_flags[BE]=$'\U1F1E7\U1F1EA' +emoji_flags[BEL]=$'\U1F1E7\U1F1EA' +emoji_flags[belgium]=$'\U1F1E7\U1F1EA' +emoji_flags[Burkina_Faso]=$'\U1F1E7\U1F1EB' +emoji_flags[BF]=$'\U1F1E7\U1F1EB' +emoji_flags[BFA]=$'\U1F1E7\U1F1EB' +emoji_flags[burkina_faso]=$'\U1F1E7\U1F1EB' +emoji_flags[Bulgaria]=$'\U1F1E7\U1F1EC' +emoji_flags[BG]=$'\U1F1E7\U1F1EC' +emoji_flags[BGR]=$'\U1F1E7\U1F1EC' +emoji_flags[bulgaria]=$'\U1F1E7\U1F1EC' +emoji_flags[Bahrain]=$'\U1F1E7\U1F1ED' +emoji_flags[BH]=$'\U1F1E7\U1F1ED' +emoji_flags[BHR]=$'\U1F1E7\U1F1ED' +emoji_flags[bahrain]=$'\U1F1E7\U1F1ED' +emoji_flags[Burundi]=$'\U1F1E7\U1F1EE' +emoji_flags[BI]=$'\U1F1E7\U1F1EE' +emoji_flags[BDI]=$'\U1F1E7\U1F1EE' +emoji_flags[burundi]=$'\U1F1E7\U1F1EE' +emoji_flags[Benin]=$'\U1F1E7\U1F1EF' +emoji_flags[BJ]=$'\U1F1E7\U1F1EF' +emoji_flags[BEN]=$'\U1F1E7\U1F1EF' +emoji_flags[benin]=$'\U1F1E7\U1F1EF' +emoji_flags[St_Barthélemy]=$'\U1F1E7\U1F1F1' +emoji_flags[BL]=$'\U1F1E7\U1F1F1' +emoji_flags[BLM]=$'\U1F1E7\U1F1F1' +emoji_flags[st_barthelemy]=$'\U1F1E7\U1F1F1' +emoji_flags[Bermuda]=$'\U1F1E7\U1F1F2' +emoji_flags[BM]=$'\U1F1E7\U1F1F2' +emoji_flags[BMU]=$'\U1F1E7\U1F1F2' +emoji_flags[bermuda]=$'\U1F1E7\U1F1F2' +emoji_flags[Brunei]=$'\U1F1E7\U1F1F3' +emoji_flags[BN]=$'\U1F1E7\U1F1F3' +emoji_flags[BRN]=$'\U1F1E7\U1F1F3' +emoji_flags[brunei]=$'\U1F1E7\U1F1F3' +emoji_flags[Bolivia]=$'\U1F1E7\U1F1F4' +emoji_flags[BO]=$'\U1F1E7\U1F1F4' +emoji_flags[BOL]=$'\U1F1E7\U1F1F4' +emoji_flags[bolivia]=$'\U1F1E7\U1F1F4' +emoji_flags[Caribbean_Netherlands]=$'\U1F1E7\U1F1F6' +emoji_flags[BQ]=$'\U1F1E7\U1F1F6' +emoji_flags[BES]=$'\U1F1E7\U1F1F6' +emoji_flags[caribbean_netherlands]=$'\U1F1E7\U1F1F6' +emoji_flags[Brazil]=$'\U1F1E7\U1F1F7' +emoji_flags[BR]=$'\U1F1E7\U1F1F7' +emoji_flags[BRA]=$'\U1F1E7\U1F1F7' +emoji_flags[brazil]=$'\U1F1E7\U1F1F7' +emoji_flags[Bahamas]=$'\U1F1E7\U1F1F8' +emoji_flags[BS]=$'\U1F1E7\U1F1F8' +emoji_flags[BHS]=$'\U1F1E7\U1F1F8' +emoji_flags[bahamas]=$'\U1F1E7\U1F1F8' +emoji_flags[Bhutan]=$'\U1F1E7\U1F1F9' +emoji_flags[BT]=$'\U1F1E7\U1F1F9' +emoji_flags[BTN]=$'\U1F1E7\U1F1F9' +emoji_flags[bhutan]=$'\U1F1E7\U1F1F9' +emoji_flags[Bouvet_Island]=$'\U1F1E7\U1F1FB' +emoji_flags[BV]=$'\U1F1E7\U1F1FB' +emoji_flags[BVT]=$'\U1F1E7\U1F1FB' +emoji_flags[bouvet_island]=$'\U1F1E7\U1F1FB' +emoji_flags[Botswana]=$'\U1F1E7\U1F1FC' +emoji_flags[BW]=$'\U1F1E7\U1F1FC' +emoji_flags[BWA]=$'\U1F1E7\U1F1FC' +emoji_flags[botswana]=$'\U1F1E7\U1F1FC' +emoji_flags[Belarus]=$'\U1F1E7\U1F1FE' +emoji_flags[BY]=$'\U1F1E7\U1F1FE' +emoji_flags[BLR]=$'\U1F1E7\U1F1FE' +emoji_flags[belarus]=$'\U1F1E7\U1F1FE' +emoji_flags[Belize]=$'\U1F1E7\U1F1FF' +emoji_flags[BZ]=$'\U1F1E7\U1F1FF' +emoji_flags[BLZ]=$'\U1F1E7\U1F1FF' +emoji_flags[belize]=$'\U1F1E7\U1F1FF' +emoji_flags[Canada]=$'\U1F1E8\U1F1E6' +emoji_flags[CA]=$'\U1F1E8\U1F1E6' +emoji_flags[CAN]=$'\U1F1E8\U1F1E6' +emoji_flags[canada]=$'\U1F1E8\U1F1E6' +emoji_flags[Cocos_Keeling_Islands]=$'\U1F1E8\U1F1E8' +emoji_flags[CC]=$'\U1F1E8\U1F1E8' +emoji_flags[CCK]=$'\U1F1E8\U1F1E8' +emoji_flags[cocos_islands]=$'\U1F1E8\U1F1E8' +emoji_flags[Congo__Kinshasa]=$'\U1F1E8\U1F1E9' +emoji_flags[CD]=$'\U1F1E8\U1F1E9' +emoji_flags[COD]=$'\U1F1E8\U1F1E9' +emoji_flags[congo_kinshasa]=$'\U1F1E8\U1F1E9' +emoji_flags[Central_African_Republic]=$'\U1F1E8\U1F1EB' +emoji_flags[CF]=$'\U1F1E8\U1F1EB' +emoji_flags[CAF]=$'\U1F1E8\U1F1EB' +emoji_flags[central_african_republic]=$'\U1F1E8\U1F1EB' +emoji_flags[Congo__Brazzaville]=$'\U1F1E8\U1F1EC' +emoji_flags[CG]=$'\U1F1E8\U1F1EC' +emoji_flags[COG]=$'\U1F1E8\U1F1EC' +emoji_flags[congo_brazzaville]=$'\U1F1E8\U1F1EC' +emoji_flags[Switzerland]=$'\U1F1E8\U1F1ED' +emoji_flags[CH]=$'\U1F1E8\U1F1ED' +emoji_flags[CHE]=$'\U1F1E8\U1F1ED' +emoji_flags[switzerland]=$'\U1F1E8\U1F1ED' +emoji_flags[Côte_d_Ivoire]=$'\U1F1E8\U1F1EE' +emoji_flags[CI]=$'\U1F1E8\U1F1EE' +emoji_flags[CIV]=$'\U1F1E8\U1F1EE' +emoji_flags[cote_divoire]=$'\U1F1E8\U1F1EE' +emoji_flags[Cook_Islands]=$'\U1F1E8\U1F1F0' +emoji_flags[CK]=$'\U1F1E8\U1F1F0' +emoji_flags[COK]=$'\U1F1E8\U1F1F0' +emoji_flags[cook_islands]=$'\U1F1E8\U1F1F0' +emoji_flags[Chile]=$'\U1F1E8\U1F1F1' +emoji_flags[CL]=$'\U1F1E8\U1F1F1' +emoji_flags[CHL]=$'\U1F1E8\U1F1F1' +emoji_flags[chile]=$'\U1F1E8\U1F1F1' +emoji_flags[Cameroon]=$'\U1F1E8\U1F1F2' +emoji_flags[CM]=$'\U1F1E8\U1F1F2' +emoji_flags[CMR]=$'\U1F1E8\U1F1F2' +emoji_flags[cameroon]=$'\U1F1E8\U1F1F2' +emoji_flags[China]=$'\U1F1E8\U1F1F3' +emoji_flags[CN]=$'\U1F1E8\U1F1F3' +emoji_flags[CHN]=$'\U1F1E8\U1F1F3' +emoji_flags[cn]=$'\U1F1E8\U1F1F3' +emoji_flags[Colombia]=$'\U1F1E8\U1F1F4' +emoji_flags[CO]=$'\U1F1E8\U1F1F4' +emoji_flags[COL]=$'\U1F1E8\U1F1F4' +emoji_flags[colombia]=$'\U1F1E8\U1F1F4' +emoji_flags[Clipperton_Island]=$'\U1F1E8\U1F1F5' +emoji_flags[clipperton_island]=$'\U1F1E8\U1F1F5' +emoji_flags[Costa_Rica]=$'\U1F1E8\U1F1F7' +emoji_flags[CR]=$'\U1F1E8\U1F1F7' +emoji_flags[CRI]=$'\U1F1E8\U1F1F7' +emoji_flags[costa_rica]=$'\U1F1E8\U1F1F7' +emoji_flags[Cuba]=$'\U1F1E8\U1F1FA' +emoji_flags[CU]=$'\U1F1E8\U1F1FA' +emoji_flags[CUB]=$'\U1F1E8\U1F1FA' +emoji_flags[cuba]=$'\U1F1E8\U1F1FA' +emoji_flags[Cape_Verde]=$'\U1F1E8\U1F1FB' +emoji_flags[CV]=$'\U1F1E8\U1F1FB' +emoji_flags[CPV]=$'\U1F1E8\U1F1FB' +emoji_flags[cape_verde]=$'\U1F1E8\U1F1FB' +emoji_flags[Curaçao]=$'\U1F1E8\U1F1FC' +emoji_flags[CW]=$'\U1F1E8\U1F1FC' +emoji_flags[CUW]=$'\U1F1E8\U1F1FC' +emoji_flags[curacao]=$'\U1F1E8\U1F1FC' +emoji_flags[Christmas_Island]=$'\U1F1E8\U1F1FD' +emoji_flags[CX]=$'\U1F1E8\U1F1FD' +emoji_flags[CXR]=$'\U1F1E8\U1F1FD' +emoji_flags[christmas_island]=$'\U1F1E8\U1F1FD' +emoji_flags[Cyprus]=$'\U1F1E8\U1F1FE' +emoji_flags[CY]=$'\U1F1E8\U1F1FE' +emoji_flags[CYP]=$'\U1F1E8\U1F1FE' +emoji_flags[cyprus]=$'\U1F1E8\U1F1FE' +emoji_flags[Czechia]=$'\U1F1E8\U1F1FF' +emoji_flags[CZ]=$'\U1F1E8\U1F1FF' +emoji_flags[CZE]=$'\U1F1E8\U1F1FF' +emoji_flags[czech_republic]=$'\U1F1E8\U1F1FF' +emoji_flags[Germany]=$'\U1F1E9\U1F1EA' +emoji_flags[DE]=$'\U1F1E9\U1F1EA' +emoji_flags[DEU]=$'\U1F1E9\U1F1EA' +emoji_flags[de]=$'\U1F1E9\U1F1EA' +emoji_flags[Diego_Garcia]=$'\U1F1E9\U1F1EC' +emoji_flags[diego_garcia]=$'\U1F1E9\U1F1EC' +emoji_flags[Djibouti]=$'\U1F1E9\U1F1EF' +emoji_flags[DJ]=$'\U1F1E9\U1F1EF' +emoji_flags[DJI]=$'\U1F1E9\U1F1EF' +emoji_flags[djibouti]=$'\U1F1E9\U1F1EF' +emoji_flags[Denmark]=$'\U1F1E9\U1F1F0' +emoji_flags[DK]=$'\U1F1E9\U1F1F0' +emoji_flags[DNK]=$'\U1F1E9\U1F1F0' +emoji_flags[denmark]=$'\U1F1E9\U1F1F0' +emoji_flags[Dominica]=$'\U1F1E9\U1F1F2' +emoji_flags[DM]=$'\U1F1E9\U1F1F2' +emoji_flags[DMA]=$'\U1F1E9\U1F1F2' +emoji_flags[dominica]=$'\U1F1E9\U1F1F2' +emoji_flags[Dominican_Republic]=$'\U1F1E9\U1F1F4' +emoji_flags[DO]=$'\U1F1E9\U1F1F4' +emoji_flags[DOM]=$'\U1F1E9\U1F1F4' +emoji_flags[dominican_republic]=$'\U1F1E9\U1F1F4' +emoji_flags[Algeria]=$'\U1F1E9\U1F1FF' +emoji_flags[DZ]=$'\U1F1E9\U1F1FF' +emoji_flags[DZA]=$'\U1F1E9\U1F1FF' +emoji_flags[algeria]=$'\U1F1E9\U1F1FF' +emoji_flags[Ceuta_and_Melilla]=$'\U1F1EA\U1F1E6' +emoji_flags[ceuta_melilla]=$'\U1F1EA\U1F1E6' +emoji_flags[Ecuador]=$'\U1F1EA\U1F1E8' +emoji_flags[EC]=$'\U1F1EA\U1F1E8' +emoji_flags[ECU]=$'\U1F1EA\U1F1E8' +emoji_flags[ecuador]=$'\U1F1EA\U1F1E8' +emoji_flags[Estonia]=$'\U1F1EA\U1F1EA' +emoji_flags[EE]=$'\U1F1EA\U1F1EA' +emoji_flags[EST]=$'\U1F1EA\U1F1EA' +emoji_flags[estonia]=$'\U1F1EA\U1F1EA' +emoji_flags[Egypt]=$'\U1F1EA\U1F1EC' +emoji_flags[EG]=$'\U1F1EA\U1F1EC' +emoji_flags[EGY]=$'\U1F1EA\U1F1EC' +emoji_flags[egypt]=$'\U1F1EA\U1F1EC' +emoji_flags[Western_Sahara]=$'\U1F1EA\U1F1ED' +emoji_flags[EH]=$'\U1F1EA\U1F1ED' +emoji_flags[ESH]=$'\U1F1EA\U1F1ED' +emoji_flags[western_sahara]=$'\U1F1EA\U1F1ED' +emoji_flags[Eritrea]=$'\U1F1EA\U1F1F7' +emoji_flags[ER]=$'\U1F1EA\U1F1F7' +emoji_flags[ERI]=$'\U1F1EA\U1F1F7' +emoji_flags[eritrea]=$'\U1F1EA\U1F1F7' +emoji_flags[Spain]=$'\U1F1EA\U1F1F8' +emoji_flags[ES]=$'\U1F1EA\U1F1F8' +emoji_flags[ESP]=$'\U1F1EA\U1F1F8' +emoji_flags[es]=$'\U1F1EA\U1F1F8' +emoji_flags[Ethiopia]=$'\U1F1EA\U1F1F9' +emoji_flags[ET]=$'\U1F1EA\U1F1F9' +emoji_flags[ETH]=$'\U1F1EA\U1F1F9' +emoji_flags[ethiopia]=$'\U1F1EA\U1F1F9' +emoji_flags[European_Union]=$'\U1F1EA\U1F1FA' +emoji_flags[eu]=$'\U1F1EA\U1F1FA' +emoji_flags[european_union]=$'\U1F1EA\U1F1FA' +emoji_flags[Finland]=$'\U1F1EB\U1F1EE' +emoji_flags[FI]=$'\U1F1EB\U1F1EE' +emoji_flags[FIN]=$'\U1F1EB\U1F1EE' +emoji_flags[finland]=$'\U1F1EB\U1F1EE' +emoji_flags[Fiji]=$'\U1F1EB\U1F1EF' +emoji_flags[FJ]=$'\U1F1EB\U1F1EF' +emoji_flags[FJI]=$'\U1F1EB\U1F1EF' +emoji_flags[fiji]=$'\U1F1EB\U1F1EF' +emoji_flags[Falkland_Islands]=$'\U1F1EB\U1F1F0' +emoji_flags[FK]=$'\U1F1EB\U1F1F0' +emoji_flags[FLK]=$'\U1F1EB\U1F1F0' +emoji_flags[falkland_islands]=$'\U1F1EB\U1F1F0' +emoji_flags[Micronesia]=$'\U1F1EB\U1F1F2' +emoji_flags[FM]=$'\U1F1EB\U1F1F2' +emoji_flags[FSM]=$'\U1F1EB\U1F1F2' +emoji_flags[micronesia]=$'\U1F1EB\U1F1F2' +emoji_flags[Faroe_Islands]=$'\U1F1EB\U1F1F4' +emoji_flags[FO]=$'\U1F1EB\U1F1F4' +emoji_flags[FRO]=$'\U1F1EB\U1F1F4' +emoji_flags[faroe_islands]=$'\U1F1EB\U1F1F4' +emoji_flags[France]=$'\U1F1EB\U1F1F7' +emoji_flags[FR]=$'\U1F1EB\U1F1F7' +emoji_flags[FRA]=$'\U1F1EB\U1F1F7' +emoji_flags[fr]=$'\U1F1EB\U1F1F7' +emoji_flags[Gabon]=$'\U1F1EC\U1F1E6' +emoji_flags[GA]=$'\U1F1EC\U1F1E6' +emoji_flags[GAB]=$'\U1F1EC\U1F1E6' +emoji_flags[gabon]=$'\U1F1EC\U1F1E6' +emoji_flags[United_Kingdom]=$'\U1F1EC\U1F1E7' +emoji_flags[GB]=$'\U1F1EC\U1F1E7' +emoji_flags[GBR]=$'\U1F1EC\U1F1E7' +emoji_flags[gb]=$'\U1F1EC\U1F1E7' +emoji_flags[uk]=$'\U1F1EC\U1F1E7' +emoji_flags[Grenada]=$'\U1F1EC\U1F1E9' +emoji_flags[GD]=$'\U1F1EC\U1F1E9' +emoji_flags[GRD]=$'\U1F1EC\U1F1E9' +emoji_flags[grenada]=$'\U1F1EC\U1F1E9' +emoji_flags[Georgia]=$'\U1F1EC\U1F1EA' +emoji_flags[GE]=$'\U1F1EC\U1F1EA' +emoji_flags[GEO]=$'\U1F1EC\U1F1EA' +emoji_flags[georgia]=$'\U1F1EC\U1F1EA' +emoji_flags[French_Guiana]=$'\U1F1EC\U1F1EB' +emoji_flags[GF]=$'\U1F1EC\U1F1EB' +emoji_flags[GUF]=$'\U1F1EC\U1F1EB' +emoji_flags[french_guiana]=$'\U1F1EC\U1F1EB' +emoji_flags[Guernsey]=$'\U1F1EC\U1F1EC' +emoji_flags[GG]=$'\U1F1EC\U1F1EC' +emoji_flags[GGY]=$'\U1F1EC\U1F1EC' +emoji_flags[guernsey]=$'\U1F1EC\U1F1EC' +emoji_flags[Ghana]=$'\U1F1EC\U1F1ED' +emoji_flags[GH]=$'\U1F1EC\U1F1ED' +emoji_flags[GHA]=$'\U1F1EC\U1F1ED' +emoji_flags[ghana]=$'\U1F1EC\U1F1ED' +emoji_flags[Gibraltar]=$'\U1F1EC\U1F1EE' +emoji_flags[GI]=$'\U1F1EC\U1F1EE' +emoji_flags[GIB]=$'\U1F1EC\U1F1EE' +emoji_flags[gibraltar]=$'\U1F1EC\U1F1EE' +emoji_flags[Greenland]=$'\U1F1EC\U1F1F1' +emoji_flags[GL]=$'\U1F1EC\U1F1F1' +emoji_flags[GRL]=$'\U1F1EC\U1F1F1' +emoji_flags[greenland]=$'\U1F1EC\U1F1F1' +emoji_flags[Gambia]=$'\U1F1EC\U1F1F2' +emoji_flags[GM]=$'\U1F1EC\U1F1F2' +emoji_flags[GMB]=$'\U1F1EC\U1F1F2' +emoji_flags[gambia]=$'\U1F1EC\U1F1F2' +emoji_flags[Guinea]=$'\U1F1EC\U1F1F3' +emoji_flags[GN]=$'\U1F1EC\U1F1F3' +emoji_flags[GIN]=$'\U1F1EC\U1F1F3' +emoji_flags[guinea]=$'\U1F1EC\U1F1F3' +emoji_flags[Guadeloupe]=$'\U1F1EC\U1F1F5' +emoji_flags[GP]=$'\U1F1EC\U1F1F5' +emoji_flags[GLP]=$'\U1F1EC\U1F1F5' +emoji_flags[guadeloupe]=$'\U1F1EC\U1F1F5' +emoji_flags[Equatorial_Guinea]=$'\U1F1EC\U1F1F6' +emoji_flags[GQ]=$'\U1F1EC\U1F1F6' +emoji_flags[GNQ]=$'\U1F1EC\U1F1F6' +emoji_flags[equatorial_guinea]=$'\U1F1EC\U1F1F6' +emoji_flags[Greece]=$'\U1F1EC\U1F1F7' +emoji_flags[GR]=$'\U1F1EC\U1F1F7' +emoji_flags[GRC]=$'\U1F1EC\U1F1F7' +emoji_flags[greece]=$'\U1F1EC\U1F1F7' +emoji_flags[South_Georgia_and_South_Sandwich_Islands]=$'\U1F1EC\U1F1F8' +emoji_flags[GS]=$'\U1F1EC\U1F1F8' +emoji_flags[SGS]=$'\U1F1EC\U1F1F8' +emoji_flags[south_georgia_south_sandwich_islands]=$'\U1F1EC\U1F1F8' +emoji_flags[Guatemala]=$'\U1F1EC\U1F1F9' +emoji_flags[GT]=$'\U1F1EC\U1F1F9' +emoji_flags[GTM]=$'\U1F1EC\U1F1F9' +emoji_flags[guatemala]=$'\U1F1EC\U1F1F9' +emoji_flags[Guam]=$'\U1F1EC\U1F1FA' +emoji_flags[GU]=$'\U1F1EC\U1F1FA' +emoji_flags[GUM]=$'\U1F1EC\U1F1FA' +emoji_flags[guam]=$'\U1F1EC\U1F1FA' +emoji_flags[Guinea_Bissau]=$'\U1F1EC\U1F1FC' +emoji_flags[GW]=$'\U1F1EC\U1F1FC' +emoji_flags[GNB]=$'\U1F1EC\U1F1FC' +emoji_flags[guinea_bissau]=$'\U1F1EC\U1F1FC' +emoji_flags[Guyana]=$'\U1F1EC\U1F1FE' +emoji_flags[GY]=$'\U1F1EC\U1F1FE' +emoji_flags[GUY]=$'\U1F1EC\U1F1FE' +emoji_flags[guyana]=$'\U1F1EC\U1F1FE' +emoji_flags[Hong_Kong_SAR_China]=$'\U1F1ED\U1F1F0' +emoji_flags[HK]=$'\U1F1ED\U1F1F0' +emoji_flags[HKG]=$'\U1F1ED\U1F1F0' +emoji_flags[hong_kong]=$'\U1F1ED\U1F1F0' +emoji_flags[Heard_and_McDonald_Islands]=$'\U1F1ED\U1F1F2' +emoji_flags[HM]=$'\U1F1ED\U1F1F2' +emoji_flags[HMD]=$'\U1F1ED\U1F1F2' +emoji_flags[heard_mcdonald_islands]=$'\U1F1ED\U1F1F2' +emoji_flags[Honduras]=$'\U1F1ED\U1F1F3' +emoji_flags[HN]=$'\U1F1ED\U1F1F3' +emoji_flags[HND]=$'\U1F1ED\U1F1F3' +emoji_flags[honduras]=$'\U1F1ED\U1F1F3' +emoji_flags[Croatia]=$'\U1F1ED\U1F1F7' +emoji_flags[HR]=$'\U1F1ED\U1F1F7' +emoji_flags[HRV]=$'\U1F1ED\U1F1F7' +emoji_flags[croatia]=$'\U1F1ED\U1F1F7' +emoji_flags[Haiti]=$'\U1F1ED\U1F1F9' +emoji_flags[HT]=$'\U1F1ED\U1F1F9' +emoji_flags[HTI]=$'\U1F1ED\U1F1F9' +emoji_flags[haiti]=$'\U1F1ED\U1F1F9' +emoji_flags[Hungary]=$'\U1F1ED\U1F1FA' +emoji_flags[HU]=$'\U1F1ED\U1F1FA' +emoji_flags[HUN]=$'\U1F1ED\U1F1FA' +emoji_flags[hungary]=$'\U1F1ED\U1F1FA' +emoji_flags[Canary_Islands]=$'\U1F1EE\U1F1E8' +emoji_flags[canary_islands]=$'\U1F1EE\U1F1E8' +emoji_flags[Indonesia]=$'\U1F1EE\U1F1E9' +emoji_flags[ID]=$'\U1F1EE\U1F1E9' +emoji_flags[IDN]=$'\U1F1EE\U1F1E9' +emoji_flags[indonesia]=$'\U1F1EE\U1F1E9' +emoji_flags[Ireland]=$'\U1F1EE\U1F1EA' +emoji_flags[IE]=$'\U1F1EE\U1F1EA' +emoji_flags[IRL]=$'\U1F1EE\U1F1EA' +emoji_flags[ireland]=$'\U1F1EE\U1F1EA' +emoji_flags[Israel]=$'\U1F1EE\U1F1F1' +emoji_flags[IL]=$'\U1F1EE\U1F1F1' +emoji_flags[ISR]=$'\U1F1EE\U1F1F1' +emoji_flags[israel]=$'\U1F1EE\U1F1F1' +emoji_flags[Isle_of_Man]=$'\U1F1EE\U1F1F2' +emoji_flags[IM]=$'\U1F1EE\U1F1F2' +emoji_flags[IMN]=$'\U1F1EE\U1F1F2' +emoji_flags[isle_of_man]=$'\U1F1EE\U1F1F2' +emoji_flags[India]=$'\U1F1EE\U1F1F3' +emoji_flags[IN]=$'\U1F1EE\U1F1F3' +emoji_flags[IND]=$'\U1F1EE\U1F1F3' +emoji_flags[india]=$'\U1F1EE\U1F1F3' +emoji_flags[British_Indian_Ocean_Territory]=$'\U1F1EE\U1F1F4' +emoji_flags[IO]=$'\U1F1EE\U1F1F4' +emoji_flags[IOT]=$'\U1F1EE\U1F1F4' +emoji_flags[british_indian_ocean_territory]=$'\U1F1EE\U1F1F4' +emoji_flags[Iraq]=$'\U1F1EE\U1F1F6' +emoji_flags[IQ]=$'\U1F1EE\U1F1F6' +emoji_flags[IRQ]=$'\U1F1EE\U1F1F6' +emoji_flags[iraq]=$'\U1F1EE\U1F1F6' +emoji_flags[Iran]=$'\U1F1EE\U1F1F7' +emoji_flags[IR]=$'\U1F1EE\U1F1F7' +emoji_flags[IRN]=$'\U1F1EE\U1F1F7' +emoji_flags[iran]=$'\U1F1EE\U1F1F7' +emoji_flags[Iceland]=$'\U1F1EE\U1F1F8' +emoji_flags[IS]=$'\U1F1EE\U1F1F8' +emoji_flags[ISL]=$'\U1F1EE\U1F1F8' +emoji_flags[iceland]=$'\U1F1EE\U1F1F8' +emoji_flags[Italy]=$'\U1F1EE\U1F1F9' +emoji_flags[IT]=$'\U1F1EE\U1F1F9' +emoji_flags[ITA]=$'\U1F1EE\U1F1F9' +emoji_flags[it]=$'\U1F1EE\U1F1F9' +emoji_flags[Jersey]=$'\U1F1EF\U1F1EA' +emoji_flags[JE]=$'\U1F1EF\U1F1EA' +emoji_flags[JEY]=$'\U1F1EF\U1F1EA' +emoji_flags[jersey]=$'\U1F1EF\U1F1EA' +emoji_flags[Jamaica]=$'\U1F1EF\U1F1F2' +emoji_flags[JM]=$'\U1F1EF\U1F1F2' +emoji_flags[JAM]=$'\U1F1EF\U1F1F2' +emoji_flags[jamaica]=$'\U1F1EF\U1F1F2' +emoji_flags[Jordan]=$'\U1F1EF\U1F1F4' +emoji_flags[JO]=$'\U1F1EF\U1F1F4' +emoji_flags[JOR]=$'\U1F1EF\U1F1F4' +emoji_flags[jordan]=$'\U1F1EF\U1F1F4' +emoji_flags[Japan]=$'\U1F1EF\U1F1F5' +emoji_flags[JP]=$'\U1F1EF\U1F1F5' +emoji_flags[JPN]=$'\U1F1EF\U1F1F5' +emoji_flags[jp]=$'\U1F1EF\U1F1F5' +emoji_flags[Kenya]=$'\U1F1F0\U1F1EA' +emoji_flags[KE]=$'\U1F1F0\U1F1EA' +emoji_flags[KEN]=$'\U1F1F0\U1F1EA' +emoji_flags[kenya]=$'\U1F1F0\U1F1EA' +emoji_flags[Kyrgyzstan]=$'\U1F1F0\U1F1EC' +emoji_flags[KG]=$'\U1F1F0\U1F1EC' +emoji_flags[KGZ]=$'\U1F1F0\U1F1EC' +emoji_flags[kyrgyzstan]=$'\U1F1F0\U1F1EC' +emoji_flags[Cambodia]=$'\U1F1F0\U1F1ED' +emoji_flags[KH]=$'\U1F1F0\U1F1ED' +emoji_flags[KHM]=$'\U1F1F0\U1F1ED' +emoji_flags[cambodia]=$'\U1F1F0\U1F1ED' +emoji_flags[Kiribati]=$'\U1F1F0\U1F1EE' +emoji_flags[KI]=$'\U1F1F0\U1F1EE' +emoji_flags[KIR]=$'\U1F1F0\U1F1EE' +emoji_flags[kiribati]=$'\U1F1F0\U1F1EE' +emoji_flags[Comoros]=$'\U1F1F0\U1F1F2' +emoji_flags[KM]=$'\U1F1F0\U1F1F2' +emoji_flags[COM]=$'\U1F1F0\U1F1F2' +emoji_flags[comoros]=$'\U1F1F0\U1F1F2' +emoji_flags[St_Kitts_and_Nevis]=$'\U1F1F0\U1F1F3' +emoji_flags[KN]=$'\U1F1F0\U1F1F3' +emoji_flags[KNA]=$'\U1F1F0\U1F1F3' +emoji_flags[st_kitts_nevis]=$'\U1F1F0\U1F1F3' +emoji_flags[North_Korea]=$'\U1F1F0\U1F1F5' +emoji_flags[KP]=$'\U1F1F0\U1F1F5' +emoji_flags[PRK]=$'\U1F1F0\U1F1F5' +emoji_flags[north_korea]=$'\U1F1F0\U1F1F5' +emoji_flags[South_Korea]=$'\U1F1F0\U1F1F7' +emoji_flags[KR]=$'\U1F1F0\U1F1F7' +emoji_flags[KOR]=$'\U1F1F0\U1F1F7' +emoji_flags[kr]=$'\U1F1F0\U1F1F7' +emoji_flags[Kuwait]=$'\U1F1F0\U1F1FC' +emoji_flags[KW]=$'\U1F1F0\U1F1FC' +emoji_flags[KWT]=$'\U1F1F0\U1F1FC' +emoji_flags[kuwait]=$'\U1F1F0\U1F1FC' +emoji_flags[Cayman_Islands]=$'\U1F1F0\U1F1FE' +emoji_flags[KY]=$'\U1F1F0\U1F1FE' +emoji_flags[CYM]=$'\U1F1F0\U1F1FE' +emoji_flags[cayman_islands]=$'\U1F1F0\U1F1FE' +emoji_flags[Kazakhstan]=$'\U1F1F0\U1F1FF' +emoji_flags[KZ]=$'\U1F1F0\U1F1FF' +emoji_flags[KAZ]=$'\U1F1F0\U1F1FF' +emoji_flags[kazakhstan]=$'\U1F1F0\U1F1FF' +emoji_flags[Laos]=$'\U1F1F1\U1F1E6' +emoji_flags[LA]=$'\U1F1F1\U1F1E6' +emoji_flags[LAO]=$'\U1F1F1\U1F1E6' +emoji_flags[laos]=$'\U1F1F1\U1F1E6' +emoji_flags[Lebanon]=$'\U1F1F1\U1F1E7' +emoji_flags[LB]=$'\U1F1F1\U1F1E7' +emoji_flags[LBN]=$'\U1F1F1\U1F1E7' +emoji_flags[lebanon]=$'\U1F1F1\U1F1E7' +emoji_flags[St_Lucia]=$'\U1F1F1\U1F1E8' +emoji_flags[LC]=$'\U1F1F1\U1F1E8' +emoji_flags[LCA]=$'\U1F1F1\U1F1E8' +emoji_flags[st_lucia]=$'\U1F1F1\U1F1E8' +emoji_flags[Liechtenstein]=$'\U1F1F1\U1F1EE' +emoji_flags[LI]=$'\U1F1F1\U1F1EE' +emoji_flags[LIE]=$'\U1F1F1\U1F1EE' +emoji_flags[liechtenstein]=$'\U1F1F1\U1F1EE' +emoji_flags[Sri_Lanka]=$'\U1F1F1\U1F1F0' +emoji_flags[LK]=$'\U1F1F1\U1F1F0' +emoji_flags[LKA]=$'\U1F1F1\U1F1F0' +emoji_flags[sri_lanka]=$'\U1F1F1\U1F1F0' +emoji_flags[Liberia]=$'\U1F1F1\U1F1F7' +emoji_flags[LR]=$'\U1F1F1\U1F1F7' +emoji_flags[LBR]=$'\U1F1F1\U1F1F7' +emoji_flags[liberia]=$'\U1F1F1\U1F1F7' +emoji_flags[Lesotho]=$'\U1F1F1\U1F1F8' +emoji_flags[LS]=$'\U1F1F1\U1F1F8' +emoji_flags[LSO]=$'\U1F1F1\U1F1F8' +emoji_flags[lesotho]=$'\U1F1F1\U1F1F8' +emoji_flags[Lithuania]=$'\U1F1F1\U1F1F9' +emoji_flags[LT]=$'\U1F1F1\U1F1F9' +emoji_flags[LTU]=$'\U1F1F1\U1F1F9' +emoji_flags[lithuania]=$'\U1F1F1\U1F1F9' +emoji_flags[Luxembourg]=$'\U1F1F1\U1F1FA' +emoji_flags[LU]=$'\U1F1F1\U1F1FA' +emoji_flags[LUX]=$'\U1F1F1\U1F1FA' +emoji_flags[luxembourg]=$'\U1F1F1\U1F1FA' +emoji_flags[Latvia]=$'\U1F1F1\U1F1FB' +emoji_flags[LV]=$'\U1F1F1\U1F1FB' +emoji_flags[LVA]=$'\U1F1F1\U1F1FB' +emoji_flags[latvia]=$'\U1F1F1\U1F1FB' +emoji_flags[Libya]=$'\U1F1F1\U1F1FE' +emoji_flags[LY]=$'\U1F1F1\U1F1FE' +emoji_flags[LBY]=$'\U1F1F1\U1F1FE' +emoji_flags[libya]=$'\U1F1F1\U1F1FE' +emoji_flags[Morocco]=$'\U1F1F2\U1F1E6' +emoji_flags[MA]=$'\U1F1F2\U1F1E6' +emoji_flags[MAR]=$'\U1F1F2\U1F1E6' +emoji_flags[morocco]=$'\U1F1F2\U1F1E6' +emoji_flags[Monaco]=$'\U1F1F2\U1F1E8' +emoji_flags[MC]=$'\U1F1F2\U1F1E8' +emoji_flags[MCO]=$'\U1F1F2\U1F1E8' +emoji_flags[monaco]=$'\U1F1F2\U1F1E8' +emoji_flags[Moldova]=$'\U1F1F2\U1F1E9' +emoji_flags[MD]=$'\U1F1F2\U1F1E9' +emoji_flags[MDA]=$'\U1F1F2\U1F1E9' +emoji_flags[moldova]=$'\U1F1F2\U1F1E9' +emoji_flags[Montenegro]=$'\U1F1F2\U1F1EA' +emoji_flags[ME]=$'\U1F1F2\U1F1EA' +emoji_flags[MNE]=$'\U1F1F2\U1F1EA' +emoji_flags[montenegro]=$'\U1F1F2\U1F1EA' +emoji_flags[St_Martin]=$'\U1F1F2\U1F1EB' +emoji_flags[MF]=$'\U1F1F2\U1F1EB' +emoji_flags[MAF]=$'\U1F1F2\U1F1EB' +emoji_flags[st_martin]=$'\U1F1F2\U1F1EB' +emoji_flags[Madagascar]=$'\U1F1F2\U1F1EC' +emoji_flags[MG]=$'\U1F1F2\U1F1EC' +emoji_flags[MDG]=$'\U1F1F2\U1F1EC' +emoji_flags[madagascar]=$'\U1F1F2\U1F1EC' +emoji_flags[Marshall_Islands]=$'\U1F1F2\U1F1ED' +emoji_flags[MH]=$'\U1F1F2\U1F1ED' +emoji_flags[MHL]=$'\U1F1F2\U1F1ED' +emoji_flags[marshall_islands]=$'\U1F1F2\U1F1ED' +emoji_flags[Macedonia]=$'\U1F1F2\U1F1F0' +emoji_flags[MK]=$'\U1F1F2\U1F1F0' +emoji_flags[MKD]=$'\U1F1F2\U1F1F0' +emoji_flags[macedonia]=$'\U1F1F2\U1F1F0' +emoji_flags[Mali]=$'\U1F1F2\U1F1F1' +emoji_flags[ML]=$'\U1F1F2\U1F1F1' +emoji_flags[MLI]=$'\U1F1F2\U1F1F1' +emoji_flags[mali]=$'\U1F1F2\U1F1F1' +emoji_flags[Myanmar_Burma_]=$'\U1F1F2\U1F1F2' +emoji_flags[MM]=$'\U1F1F2\U1F1F2' +emoji_flags[MMR]=$'\U1F1F2\U1F1F2' +emoji_flags[myanmar]=$'\U1F1F2\U1F1F2' +emoji_flags[Mongolia]=$'\U1F1F2\U1F1F3' +emoji_flags[MN]=$'\U1F1F2\U1F1F3' +emoji_flags[MNG]=$'\U1F1F2\U1F1F3' +emoji_flags[mongolia]=$'\U1F1F2\U1F1F3' +emoji_flags[Macao_SAR_China]=$'\U1F1F2\U1F1F4' +emoji_flags[MO]=$'\U1F1F2\U1F1F4' +emoji_flags[MAC]=$'\U1F1F2\U1F1F4' +emoji_flags[macau]=$'\U1F1F2\U1F1F4' +emoji_flags[Northern_Mariana_Islands]=$'\U1F1F2\U1F1F5' +emoji_flags[MP]=$'\U1F1F2\U1F1F5' +emoji_flags[MNP]=$'\U1F1F2\U1F1F5' +emoji_flags[northern_mariana_islands]=$'\U1F1F2\U1F1F5' +emoji_flags[Martinique]=$'\U1F1F2\U1F1F6' +emoji_flags[MQ]=$'\U1F1F2\U1F1F6' +emoji_flags[MTQ]=$'\U1F1F2\U1F1F6' +emoji_flags[martinique]=$'\U1F1F2\U1F1F6' +emoji_flags[Mauritania]=$'\U1F1F2\U1F1F7' +emoji_flags[MR]=$'\U1F1F2\U1F1F7' +emoji_flags[MRT]=$'\U1F1F2\U1F1F7' +emoji_flags[mauritania]=$'\U1F1F2\U1F1F7' +emoji_flags[Montserrat]=$'\U1F1F2\U1F1F8' +emoji_flags[MS]=$'\U1F1F2\U1F1F8' +emoji_flags[MSR]=$'\U1F1F2\U1F1F8' +emoji_flags[montserrat]=$'\U1F1F2\U1F1F8' +emoji_flags[Malta]=$'\U1F1F2\U1F1F9' +emoji_flags[MT]=$'\U1F1F2\U1F1F9' +emoji_flags[MLT]=$'\U1F1F2\U1F1F9' +emoji_flags[malta]=$'\U1F1F2\U1F1F9' +emoji_flags[Mauritius]=$'\U1F1F2\U1F1FA' +emoji_flags[MU]=$'\U1F1F2\U1F1FA' +emoji_flags[MUS]=$'\U1F1F2\U1F1FA' +emoji_flags[mauritius]=$'\U1F1F2\U1F1FA' +emoji_flags[Maldives]=$'\U1F1F2\U1F1FB' +emoji_flags[MV]=$'\U1F1F2\U1F1FB' +emoji_flags[MDV]=$'\U1F1F2\U1F1FB' +emoji_flags[maldives]=$'\U1F1F2\U1F1FB' +emoji_flags[Malawi]=$'\U1F1F2\U1F1FC' +emoji_flags[MW]=$'\U1F1F2\U1F1FC' +emoji_flags[MWI]=$'\U1F1F2\U1F1FC' +emoji_flags[malawi]=$'\U1F1F2\U1F1FC' +emoji_flags[Mexico]=$'\U1F1F2\U1F1FD' +emoji_flags[MX]=$'\U1F1F2\U1F1FD' +emoji_flags[MEX]=$'\U1F1F2\U1F1FD' +emoji_flags[mexico]=$'\U1F1F2\U1F1FD' +emoji_flags[Malaysia]=$'\U1F1F2\U1F1FE' +emoji_flags[MY]=$'\U1F1F2\U1F1FE' +emoji_flags[MYS]=$'\U1F1F2\U1F1FE' +emoji_flags[malaysia]=$'\U1F1F2\U1F1FE' +emoji_flags[Mozambique]=$'\U1F1F2\U1F1FF' +emoji_flags[MZ]=$'\U1F1F2\U1F1FF' +emoji_flags[MOZ]=$'\U1F1F2\U1F1FF' +emoji_flags[mozambique]=$'\U1F1F2\U1F1FF' +emoji_flags[Namibia]=$'\U1F1F3\U1F1E6' +emoji_flags[NA]=$'\U1F1F3\U1F1E6' +emoji_flags[NAM]=$'\U1F1F3\U1F1E6' +emoji_flags[namibia]=$'\U1F1F3\U1F1E6' +emoji_flags[New_Caledonia]=$'\U1F1F3\U1F1E8' +emoji_flags[NC]=$'\U1F1F3\U1F1E8' +emoji_flags[NCL]=$'\U1F1F3\U1F1E8' +emoji_flags[new_caledonia]=$'\U1F1F3\U1F1E8' +emoji_flags[Niger]=$'\U1F1F3\U1F1EA' +emoji_flags[NE]=$'\U1F1F3\U1F1EA' +emoji_flags[NER]=$'\U1F1F3\U1F1EA' +emoji_flags[niger]=$'\U1F1F3\U1F1EA' +emoji_flags[Norfolk_Island]=$'\U1F1F3\U1F1EB' +emoji_flags[NF]=$'\U1F1F3\U1F1EB' +emoji_flags[NFK]=$'\U1F1F3\U1F1EB' +emoji_flags[norfolk_island]=$'\U1F1F3\U1F1EB' +emoji_flags[Nigeria]=$'\U1F1F3\U1F1EC' +emoji_flags[NG]=$'\U1F1F3\U1F1EC' +emoji_flags[NGA]=$'\U1F1F3\U1F1EC' +emoji_flags[nigeria]=$'\U1F1F3\U1F1EC' +emoji_flags[Nicaragua]=$'\U1F1F3\U1F1EE' +emoji_flags[NI]=$'\U1F1F3\U1F1EE' +emoji_flags[NIC]=$'\U1F1F3\U1F1EE' +emoji_flags[nicaragua]=$'\U1F1F3\U1F1EE' +emoji_flags[Netherlands]=$'\U1F1F3\U1F1F1' +emoji_flags[NL]=$'\U1F1F3\U1F1F1' +emoji_flags[NLD]=$'\U1F1F3\U1F1F1' +emoji_flags[netherlands]=$'\U1F1F3\U1F1F1' +emoji_flags[Norway]=$'\U1F1F3\U1F1F4' +emoji_flags[NO]=$'\U1F1F3\U1F1F4' +emoji_flags[NOR]=$'\U1F1F3\U1F1F4' +emoji_flags[norway]=$'\U1F1F3\U1F1F4' +emoji_flags[Nepal]=$'\U1F1F3\U1F1F5' +emoji_flags[NP]=$'\U1F1F3\U1F1F5' +emoji_flags[NPL]=$'\U1F1F3\U1F1F5' +emoji_flags[nepal]=$'\U1F1F3\U1F1F5' +emoji_flags[Nauru]=$'\U1F1F3\U1F1F7' +emoji_flags[NR]=$'\U1F1F3\U1F1F7' +emoji_flags[NRU]=$'\U1F1F3\U1F1F7' +emoji_flags[nauru]=$'\U1F1F3\U1F1F7' +emoji_flags[Niue]=$'\U1F1F3\U1F1FA' +emoji_flags[NU]=$'\U1F1F3\U1F1FA' +emoji_flags[NIU]=$'\U1F1F3\U1F1FA' +emoji_flags[niue]=$'\U1F1F3\U1F1FA' +emoji_flags[New_Zealand]=$'\U1F1F3\U1F1FF' +emoji_flags[NZ]=$'\U1F1F3\U1F1FF' +emoji_flags[NZL]=$'\U1F1F3\U1F1FF' +emoji_flags[new_zealand]=$'\U1F1F3\U1F1FF' +emoji_flags[Oman]=$'\U1F1F4\U1F1F2' +emoji_flags[OM]=$'\U1F1F4\U1F1F2' +emoji_flags[OMN]=$'\U1F1F4\U1F1F2' +emoji_flags[oman]=$'\U1F1F4\U1F1F2' +emoji_flags[Panama]=$'\U1F1F5\U1F1E6' +emoji_flags[PA]=$'\U1F1F5\U1F1E6' +emoji_flags[PAN]=$'\U1F1F5\U1F1E6' +emoji_flags[panama]=$'\U1F1F5\U1F1E6' +emoji_flags[Peru]=$'\U1F1F5\U1F1EA' +emoji_flags[PE]=$'\U1F1F5\U1F1EA' +emoji_flags[PER]=$'\U1F1F5\U1F1EA' +emoji_flags[peru]=$'\U1F1F5\U1F1EA' +emoji_flags[French_Polynesia]=$'\U1F1F5\U1F1EB' +emoji_flags[PF]=$'\U1F1F5\U1F1EB' +emoji_flags[PYF]=$'\U1F1F5\U1F1EB' +emoji_flags[french_polynesia]=$'\U1F1F5\U1F1EB' +emoji_flags[Papua_New_Guinea]=$'\U1F1F5\U1F1EC' +emoji_flags[PG]=$'\U1F1F5\U1F1EC' +emoji_flags[PNG]=$'\U1F1F5\U1F1EC' +emoji_flags[papua_new_guinea]=$'\U1F1F5\U1F1EC' +emoji_flags[Philippines]=$'\U1F1F5\U1F1ED' +emoji_flags[PH]=$'\U1F1F5\U1F1ED' +emoji_flags[PHL]=$'\U1F1F5\U1F1ED' +emoji_flags[philippines]=$'\U1F1F5\U1F1ED' +emoji_flags[Pakistan]=$'\U1F1F5\U1F1F0' +emoji_flags[PK]=$'\U1F1F5\U1F1F0' +emoji_flags[PAK]=$'\U1F1F5\U1F1F0' +emoji_flags[pakistan]=$'\U1F1F5\U1F1F0' +emoji_flags[Poland]=$'\U1F1F5\U1F1F1' +emoji_flags[PL]=$'\U1F1F5\U1F1F1' +emoji_flags[POL]=$'\U1F1F5\U1F1F1' +emoji_flags[poland]=$'\U1F1F5\U1F1F1' +emoji_flags[St_Pierre_and_Miquelon]=$'\U1F1F5\U1F1F2' +emoji_flags[PM]=$'\U1F1F5\U1F1F2' +emoji_flags[SPM]=$'\U1F1F5\U1F1F2' +emoji_flags[st_pierre_miquelon]=$'\U1F1F5\U1F1F2' +emoji_flags[Pitcairn_Islands]=$'\U1F1F5\U1F1F3' +emoji_flags[PN]=$'\U1F1F5\U1F1F3' +emoji_flags[PCN]=$'\U1F1F5\U1F1F3' +emoji_flags[pitcairn_islands]=$'\U1F1F5\U1F1F3' +emoji_flags[Puerto_Rico]=$'\U1F1F5\U1F1F7' +emoji_flags[PR]=$'\U1F1F5\U1F1F7' +emoji_flags[PRI]=$'\U1F1F5\U1F1F7' +emoji_flags[puerto_rico]=$'\U1F1F5\U1F1F7' +emoji_flags[Palestinian_Territories]=$'\U1F1F5\U1F1F8' +emoji_flags[PS]=$'\U1F1F5\U1F1F8' +emoji_flags[PSE]=$'\U1F1F5\U1F1F8' +emoji_flags[palestinian_territories]=$'\U1F1F5\U1F1F8' +emoji_flags[Portugal]=$'\U1F1F5\U1F1F9' +emoji_flags[PT]=$'\U1F1F5\U1F1F9' +emoji_flags[PRT]=$'\U1F1F5\U1F1F9' +emoji_flags[portugal]=$'\U1F1F5\U1F1F9' +emoji_flags[Palau]=$'\U1F1F5\U1F1FC' +emoji_flags[PW]=$'\U1F1F5\U1F1FC' +emoji_flags[PLW]=$'\U1F1F5\U1F1FC' +emoji_flags[palau]=$'\U1F1F5\U1F1FC' +emoji_flags[Paraguay]=$'\U1F1F5\U1F1FE' +emoji_flags[PY]=$'\U1F1F5\U1F1FE' +emoji_flags[PRY]=$'\U1F1F5\U1F1FE' +emoji_flags[paraguay]=$'\U1F1F5\U1F1FE' +emoji_flags[Qatar]=$'\U1F1F6\U1F1E6' +emoji_flags[QA]=$'\U1F1F6\U1F1E6' +emoji_flags[QAT]=$'\U1F1F6\U1F1E6' +emoji_flags[qatar]=$'\U1F1F6\U1F1E6' +emoji_flags[Réunion]=$'\U1F1F7\U1F1EA' +emoji_flags[RE]=$'\U1F1F7\U1F1EA' +emoji_flags[REU]=$'\U1F1F7\U1F1EA' +emoji_flags[reunion]=$'\U1F1F7\U1F1EA' +emoji_flags[Romania]=$'\U1F1F7\U1F1F4' +emoji_flags[RO]=$'\U1F1F7\U1F1F4' +emoji_flags[ROU]=$'\U1F1F7\U1F1F4' +emoji_flags[romania]=$'\U1F1F7\U1F1F4' +emoji_flags[Serbia]=$'\U1F1F7\U1F1F8' +emoji_flags[RS]=$'\U1F1F7\U1F1F8' +emoji_flags[SRB]=$'\U1F1F7\U1F1F8' +emoji_flags[serbia]=$'\U1F1F7\U1F1F8' +emoji_flags[Russia]=$'\U1F1F7\U1F1FA' +emoji_flags[RU]=$'\U1F1F7\U1F1FA' +emoji_flags[RUS]=$'\U1F1F7\U1F1FA' +emoji_flags[ru]=$'\U1F1F7\U1F1FA' +emoji_flags[Rwanda]=$'\U1F1F7\U1F1FC' +emoji_flags[RW]=$'\U1F1F7\U1F1FC' +emoji_flags[RWA]=$'\U1F1F7\U1F1FC' +emoji_flags[rwanda]=$'\U1F1F7\U1F1FC' +emoji_flags[Saudi_Arabia]=$'\U1F1F8\U1F1E6' +emoji_flags[SA]=$'\U1F1F8\U1F1E6' +emoji_flags[SAU]=$'\U1F1F8\U1F1E6' +emoji_flags[saudi_arabia]=$'\U1F1F8\U1F1E6' +emoji_flags[Solomon_Islands]=$'\U1F1F8\U1F1E7' +emoji_flags[SB]=$'\U1F1F8\U1F1E7' +emoji_flags[SLB]=$'\U1F1F8\U1F1E7' +emoji_flags[solomon_islands]=$'\U1F1F8\U1F1E7' +emoji_flags[Seychelles]=$'\U1F1F8\U1F1E8' +emoji_flags[SC]=$'\U1F1F8\U1F1E8' +emoji_flags[SYC]=$'\U1F1F8\U1F1E8' +emoji_flags[seychelles]=$'\U1F1F8\U1F1E8' +emoji_flags[Sudan]=$'\U1F1F8\U1F1E9' +emoji_flags[SD]=$'\U1F1F8\U1F1E9' +emoji_flags[SDN]=$'\U1F1F8\U1F1E9' +emoji_flags[sudan]=$'\U1F1F8\U1F1E9' +emoji_flags[Sweden]=$'\U1F1F8\U1F1EA' +emoji_flags[SE]=$'\U1F1F8\U1F1EA' +emoji_flags[SWE]=$'\U1F1F8\U1F1EA' +emoji_flags[sweden]=$'\U1F1F8\U1F1EA' +emoji_flags[Singapore]=$'\U1F1F8\U1F1EC' +emoji_flags[SG]=$'\U1F1F8\U1F1EC' +emoji_flags[SGP]=$'\U1F1F8\U1F1EC' +emoji_flags[singapore]=$'\U1F1F8\U1F1EC' +emoji_flags[St_Helena]=$'\U1F1F8\U1F1ED' +emoji_flags[SH]=$'\U1F1F8\U1F1ED' +emoji_flags[SHN]=$'\U1F1F8\U1F1ED' +emoji_flags[st_helena]=$'\U1F1F8\U1F1ED' +emoji_flags[Slovenia]=$'\U1F1F8\U1F1EE' +emoji_flags[SI]=$'\U1F1F8\U1F1EE' +emoji_flags[SVN]=$'\U1F1F8\U1F1EE' +emoji_flags[slovenia]=$'\U1F1F8\U1F1EE' +emoji_flags[Svalbard_and_Jan_Mayen]=$'\U1F1F8\U1F1EF' +emoji_flags[SJ]=$'\U1F1F8\U1F1EF' +emoji_flags[SJM]=$'\U1F1F8\U1F1EF' +emoji_flags[svalbard_jan_mayen]=$'\U1F1F8\U1F1EF' +emoji_flags[Slovakia]=$'\U1F1F8\U1F1F0' +emoji_flags[SK]=$'\U1F1F8\U1F1F0' +emoji_flags[SVK]=$'\U1F1F8\U1F1F0' +emoji_flags[slovakia]=$'\U1F1F8\U1F1F0' +emoji_flags[Sierra_Leone]=$'\U1F1F8\U1F1F1' +emoji_flags[SL]=$'\U1F1F8\U1F1F1' +emoji_flags[SLE]=$'\U1F1F8\U1F1F1' +emoji_flags[sierra_leone]=$'\U1F1F8\U1F1F1' +emoji_flags[San_Marino]=$'\U1F1F8\U1F1F2' +emoji_flags[SM]=$'\U1F1F8\U1F1F2' +emoji_flags[SMR]=$'\U1F1F8\U1F1F2' +emoji_flags[san_marino]=$'\U1F1F8\U1F1F2' +emoji_flags[Senegal]=$'\U1F1F8\U1F1F3' +emoji_flags[SN]=$'\U1F1F8\U1F1F3' +emoji_flags[SEN]=$'\U1F1F8\U1F1F3' +emoji_flags[senegal]=$'\U1F1F8\U1F1F3' +emoji_flags[Somalia]=$'\U1F1F8\U1F1F4' +emoji_flags[SO]=$'\U1F1F8\U1F1F4' +emoji_flags[SOM]=$'\U1F1F8\U1F1F4' +emoji_flags[somalia]=$'\U1F1F8\U1F1F4' +emoji_flags[Suriname]=$'\U1F1F8\U1F1F7' +emoji_flags[SR]=$'\U1F1F8\U1F1F7' +emoji_flags[SUR]=$'\U1F1F8\U1F1F7' +emoji_flags[suriname]=$'\U1F1F8\U1F1F7' +emoji_flags[South_Sudan]=$'\U1F1F8\U1F1F8' +emoji_flags[SS]=$'\U1F1F8\U1F1F8' +emoji_flags[SSD]=$'\U1F1F8\U1F1F8' +emoji_flags[south_sudan]=$'\U1F1F8\U1F1F8' +emoji_flags[São_Tomé_and_Príncipe]=$'\U1F1F8\U1F1F9' +emoji_flags[sao_tome_principe]=$'\U1F1F8\U1F1F9' +emoji_flags[El_Salvador]=$'\U1F1F8\U1F1FB' +emoji_flags[SV]=$'\U1F1F8\U1F1FB' +emoji_flags[SLV]=$'\U1F1F8\U1F1FB' +emoji_flags[el_salvador]=$'\U1F1F8\U1F1FB' +emoji_flags[Sint_Maarten]=$'\U1F1F8\U1F1FD' +emoji_flags[SX]=$'\U1F1F8\U1F1FD' +emoji_flags[SXM]=$'\U1F1F8\U1F1FD' +emoji_flags[sint_maarten]=$'\U1F1F8\U1F1FD' +emoji_flags[Syria]=$'\U1F1F8\U1F1FE' +emoji_flags[SY]=$'\U1F1F8\U1F1FE' +emoji_flags[SYR]=$'\U1F1F8\U1F1FE' +emoji_flags[syria]=$'\U1F1F8\U1F1FE' +emoji_flags[Eswatini]=$'\U1F1F8\U1F1FF' +emoji_flags[SZ]=$'\U1F1F8\U1F1FF' +emoji_flags[SWZ]=$'\U1F1F8\U1F1FF' +emoji_flags[swaziland]=$'\U1F1F8\U1F1FF' +emoji_flags[Tristan_da_Cunha]=$'\U1F1F9\U1F1E6' +emoji_flags[tristan_da_cunha]=$'\U1F1F9\U1F1E6' +emoji_flags[Turks_and_Caicos_Islands]=$'\U1F1F9\U1F1E8' +emoji_flags[TC]=$'\U1F1F9\U1F1E8' +emoji_flags[TCA]=$'\U1F1F9\U1F1E8' +emoji_flags[turks_caicos_islands]=$'\U1F1F9\U1F1E8' +emoji_flags[Chad]=$'\U1F1F9\U1F1E9' +emoji_flags[TD]=$'\U1F1F9\U1F1E9' +emoji_flags[TCD]=$'\U1F1F9\U1F1E9' +emoji_flags[chad]=$'\U1F1F9\U1F1E9' +emoji_flags[French_Southern_Territories]=$'\U1F1F9\U1F1EB' +emoji_flags[TF]=$'\U1F1F9\U1F1EB' +emoji_flags[ATF]=$'\U1F1F9\U1F1EB' +emoji_flags[french_southern_territories]=$'\U1F1F9\U1F1EB' +emoji_flags[Togo]=$'\U1F1F9\U1F1EC' +emoji_flags[TG]=$'\U1F1F9\U1F1EC' +emoji_flags[TGO]=$'\U1F1F9\U1F1EC' +emoji_flags[togo]=$'\U1F1F9\U1F1EC' +emoji_flags[Thailand]=$'\U1F1F9\U1F1ED' +emoji_flags[TH]=$'\U1F1F9\U1F1ED' +emoji_flags[THA]=$'\U1F1F9\U1F1ED' +emoji_flags[thailand]=$'\U1F1F9\U1F1ED' +emoji_flags[Tajikistan]=$'\U1F1F9\U1F1EF' +emoji_flags[TJ]=$'\U1F1F9\U1F1EF' +emoji_flags[TJK]=$'\U1F1F9\U1F1EF' +emoji_flags[tajikistan]=$'\U1F1F9\U1F1EF' +emoji_flags[Tokelau]=$'\U1F1F9\U1F1F0' +emoji_flags[TK]=$'\U1F1F9\U1F1F0' +emoji_flags[TKL]=$'\U1F1F9\U1F1F0' +emoji_flags[tokelau]=$'\U1F1F9\U1F1F0' +emoji_flags[Timor_Leste]=$'\U1F1F9\U1F1F1' +emoji_flags[TL]=$'\U1F1F9\U1F1F1' +emoji_flags[TLS]=$'\U1F1F9\U1F1F1' +emoji_flags[timor_leste]=$'\U1F1F9\U1F1F1' +emoji_flags[Turkmenistan]=$'\U1F1F9\U1F1F2' +emoji_flags[TM]=$'\U1F1F9\U1F1F2' +emoji_flags[TKM]=$'\U1F1F9\U1F1F2' +emoji_flags[turkmenistan]=$'\U1F1F9\U1F1F2' +emoji_flags[Tunisia]=$'\U1F1F9\U1F1F3' +emoji_flags[TN]=$'\U1F1F9\U1F1F3' +emoji_flags[TUN]=$'\U1F1F9\U1F1F3' +emoji_flags[tunisia]=$'\U1F1F9\U1F1F3' +emoji_flags[Tonga]=$'\U1F1F9\U1F1F4' +emoji_flags[TO]=$'\U1F1F9\U1F1F4' +emoji_flags[TON]=$'\U1F1F9\U1F1F4' +emoji_flags[tonga]=$'\U1F1F9\U1F1F4' +emoji_flags[Turkey]=$'\U1F1F9\U1F1F7' +emoji_flags[TR]=$'\U1F1F9\U1F1F7' +emoji_flags[TUR]=$'\U1F1F9\U1F1F7' +emoji_flags[tr]=$'\U1F1F9\U1F1F7' +emoji_flags[Trinidad_and_Tobago]=$'\U1F1F9\U1F1F9' +emoji_flags[TT]=$'\U1F1F9\U1F1F9' +emoji_flags[TTO]=$'\U1F1F9\U1F1F9' +emoji_flags[trinidad_tobago]=$'\U1F1F9\U1F1F9' +emoji_flags[Tuvalu]=$'\U1F1F9\U1F1FB' +emoji_flags[TV]=$'\U1F1F9\U1F1FB' +emoji_flags[TUV]=$'\U1F1F9\U1F1FB' +emoji_flags[tuvalu]=$'\U1F1F9\U1F1FB' +emoji_flags[Taiwan]=$'\U1F1F9\U1F1FC' +emoji_flags[TW]=$'\U1F1F9\U1F1FC' +emoji_flags[TWN]=$'\U1F1F9\U1F1FC' +emoji_flags[taiwan]=$'\U1F1F9\U1F1FC' +emoji_flags[Tanzania]=$'\U1F1F9\U1F1FF' +emoji_flags[TZ]=$'\U1F1F9\U1F1FF' +emoji_flags[TZA]=$'\U1F1F9\U1F1FF' +emoji_flags[tanzania]=$'\U1F1F9\U1F1FF' +emoji_flags[Ukraine]=$'\U1F1FA\U1F1E6' +emoji_flags[UA]=$'\U1F1FA\U1F1E6' +emoji_flags[UKR]=$'\U1F1FA\U1F1E6' +emoji_flags[ukraine]=$'\U1F1FA\U1F1E6' +emoji_flags[Uganda]=$'\U1F1FA\U1F1EC' +emoji_flags[UG]=$'\U1F1FA\U1F1EC' +emoji_flags[UGA]=$'\U1F1FA\U1F1EC' +emoji_flags[uganda]=$'\U1F1FA\U1F1EC' +emoji_flags[U_S_Outlying_Islands]=$'\U1F1FA\U1F1F2' +emoji_flags[us_outlying_islands]=$'\U1F1FA\U1F1F2' +emoji_flags[United_Nations]=$'\U1F1FA\U1F1F3' +emoji_flags[united_nations]=$'\U1F1FA\U1F1F3' +emoji_flags[United_States]=$'\U1F1FA\U1F1F8' +emoji_flags[US]=$'\U1F1FA\U1F1F8' +emoji_flags[USA]=$'\U1F1FA\U1F1F8' +emoji_flags[us]=$'\U1F1FA\U1F1F8' +emoji_flags[Uruguay]=$'\U1F1FA\U1F1FE' +emoji_flags[UY]=$'\U1F1FA\U1F1FE' +emoji_flags[URY]=$'\U1F1FA\U1F1FE' +emoji_flags[uruguay]=$'\U1F1FA\U1F1FE' +emoji_flags[Uzbekistan]=$'\U1F1FA\U1F1FF' +emoji_flags[UZ]=$'\U1F1FA\U1F1FF' +emoji_flags[UZB]=$'\U1F1FA\U1F1FF' +emoji_flags[uzbekistan]=$'\U1F1FA\U1F1FF' +emoji_flags[Vatican_City]=$'\U1F1FB\U1F1E6' +emoji_flags[VA]=$'\U1F1FB\U1F1E6' +emoji_flags[VAT]=$'\U1F1FB\U1F1E6' +emoji_flags[vatican_city]=$'\U1F1FB\U1F1E6' +emoji_flags[St_Vincent_and_Grenadines]=$'\U1F1FB\U1F1E8' +emoji_flags[VC]=$'\U1F1FB\U1F1E8' +emoji_flags[VCT]=$'\U1F1FB\U1F1E8' +emoji_flags[st_vincent_grenadines]=$'\U1F1FB\U1F1E8' +emoji_flags[Venezuela]=$'\U1F1FB\U1F1EA' +emoji_flags[VE]=$'\U1F1FB\U1F1EA' +emoji_flags[VEN]=$'\U1F1FB\U1F1EA' +emoji_flags[venezuela]=$'\U1F1FB\U1F1EA' +emoji_flags[British_Virgin_Islands]=$'\U1F1FB\U1F1EC' +emoji_flags[VG]=$'\U1F1FB\U1F1EC' +emoji_flags[VGB]=$'\U1F1FB\U1F1EC' +emoji_flags[british_virgin_islands]=$'\U1F1FB\U1F1EC' +emoji_flags[U_S_Virgin_Islands]=$'\U1F1FB\U1F1EE' +emoji_flags[VI]=$'\U1F1FB\U1F1EE' +emoji_flags[VIR]=$'\U1F1FB\U1F1EE' +emoji_flags[us_virgin_islands]=$'\U1F1FB\U1F1EE' +emoji_flags[Vietnam]=$'\U1F1FB\U1F1F3' +emoji_flags[VN]=$'\U1F1FB\U1F1F3' +emoji_flags[VNM]=$'\U1F1FB\U1F1F3' +emoji_flags[vietnam]=$'\U1F1FB\U1F1F3' +emoji_flags[Vanuatu]=$'\U1F1FB\U1F1FA' +emoji_flags[VU]=$'\U1F1FB\U1F1FA' +emoji_flags[VUT]=$'\U1F1FB\U1F1FA' +emoji_flags[vanuatu]=$'\U1F1FB\U1F1FA' +emoji_flags[Wallis_and_Futuna]=$'\U1F1FC\U1F1EB' +emoji_flags[WF]=$'\U1F1FC\U1F1EB' +emoji_flags[WLF]=$'\U1F1FC\U1F1EB' +emoji_flags[wallis_futuna]=$'\U1F1FC\U1F1EB' +emoji_flags[Samoa]=$'\U1F1FC\U1F1F8' +emoji_flags[WS]=$'\U1F1FC\U1F1F8' +emoji_flags[WSM]=$'\U1F1FC\U1F1F8' +emoji_flags[samoa]=$'\U1F1FC\U1F1F8' +emoji_flags[Kosovo]=$'\U1F1FD\U1F1F0' +emoji_flags[XK]=$'\U1F1FD\U1F1F0' +emoji_flags[XKX]=$'\U1F1FD\U1F1F0' +emoji_flags[kosovo]=$'\U1F1FD\U1F1F0' +emoji_flags[Yemen]=$'\U1F1FE\U1F1EA' +emoji_flags[YE]=$'\U1F1FE\U1F1EA' +emoji_flags[YEM]=$'\U1F1FE\U1F1EA' +emoji_flags[yemen]=$'\U1F1FE\U1F1EA' +emoji_flags[Mayotte]=$'\U1F1FE\U1F1F9' +emoji_flags[YT]=$'\U1F1FE\U1F1F9' +emoji_flags[MYT]=$'\U1F1FE\U1F1F9' +emoji_flags[mayotte]=$'\U1F1FE\U1F1F9' +emoji_flags[South_Africa]=$'\U1F1FF\U1F1E6' +emoji_flags[ZA]=$'\U1F1FF\U1F1E6' +emoji_flags[ZAF]=$'\U1F1FF\U1F1E6' +emoji_flags[south_africa]=$'\U1F1FF\U1F1E6' +emoji_flags[Zambia]=$'\U1F1FF\U1F1F2' +emoji_flags[ZM]=$'\U1F1FF\U1F1F2' +emoji_flags[ZMB]=$'\U1F1FF\U1F1F2' +emoji_flags[zambia]=$'\U1F1FF\U1F1F2' +emoji_flags[Zimbabwe]=$'\U1F1FF\U1F1FC' +emoji_flags[ZW]=$'\U1F1FF\U1F1FC' +emoji_flags[ZWE]=$'\U1F1FF\U1F1FC' +emoji_flags[zimbabwe]=$'\U1F1FF\U1F1FC' +emoji_flags[England]=$'\U1F3F4\UE0067\UE0062\UE0065\UE006E\UE0067\UE007F' +emoji_flags[england]=$'\U1F3F4\UE0067\UE0062\UE0065\UE006E\UE0067\UE007F' +emoji_flags[Scotland]=$'\U1F3F4\UE0067\UE0062\UE0073\UE0063\UE0074\UE007F' +emoji_flags[scotland]=$'\U1F3F4\UE0067\UE0062\UE0073\UE0063\UE0074\UE007F' +emoji_flags[Wales]=$'\U1F3F4\UE0067\UE0062\UE0077\UE006C\UE0073\UE007F' +emoji_flags[wales]=$'\U1F3F4\UE0067\UE0062\UE0077\UE006C\UE0073\UE007F' + +emoji_groups[fruits]=" + grapes + melon + watermelon + tangerine + lemon + banana + pineapple + mango + red_apple + green_apple + pear + peach + cherries + strawberry + kiwi_fruit + tomato + coconut +" + +emoji_groups[vehicles]=" + locomotive + railway_car + high_speed_train + bullet_train + bullet_train_1 + metro + light_rail + station + tram + monorail + mountain_railway + tram_car + bus + oncoming_bus + trolleybus + minibus + ambulance + fire_engine + police_car + oncoming_police_car + taxi + oncoming_taxi + automobile + oncoming_automobile + sport_utility_vehicle + delivery_truck + articulated_lorry + tractor + racing_car + motorcycle + motor_scooter + manual_wheelchair + motorized_wheelchair + auto_rickshaw + bicycle + kick_scooter + skateboard + bus_stop + motorway + railway_track + oil_drum + fuel_pump + police_car_light + horizontal_traffic_light + vertical_traffic_light + stop_sign + construction + anchor + sailboat + canoe + speedboat + passenger_ship + ferry + motor_boat + ship + airplane + small_airplane + airplane_departure + airplane_arrival + parachute + seat + helicopter + suspension_railway + mountain_cableway + aerial_tramway + satellite + rocket + flying_saucer + ATM_sign + litter_in_bin_sign + potable_water + wheelchair_symbol + men_s_room + women_s_room + restroom + baby_symbol + water_closet + passport_control + customs + baggage_claim + left_luggage +" + +emoji_groups[hands]=" + waving_hand + waving_hand_light_skin_tone + waving_hand_medium_light_skin_tone + waving_hand_medium_skin_tone + waving_hand_medium_dark_skin_tone + waving_hand_dark_skin_tone + raised_back_of_hand + raised_back_of_hand_light_skin_tone + raised_back_of_hand_medium_light_skin_tone + raised_back_of_hand_medium_skin_tone + raised_back_of_hand_medium_dark_skin_tone + raised_back_of_hand_dark_skin_tone + hand_with_fingers_splayed + hand_with_fingers_splayed_light_skin_tone + hand_with_fingers_splayed_medium_light_skin_tone + hand_with_fingers_splayed_medium_skin_tone + hand_with_fingers_splayed_medium_dark_skin_tone + hand_with_fingers_splayed_dark_skin_tone + raised_hand + raised_hand_light_skin_tone + raised_hand_medium_light_skin_tone + raised_hand_medium_skin_tone + raised_hand_medium_dark_skin_tone + raised_hand_dark_skin_tone + vulcan_salute + vulcan_salute_light_skin_tone + vulcan_salute_medium_light_skin_tone + vulcan_salute_medium_skin_tone + vulcan_salute_medium_dark_skin_tone + vulcan_salute_dark_skin_tone + OK_hand + OK_hand_light_skin_tone + OK_hand_medium_light_skin_tone + OK_hand_medium_skin_tone + OK_hand_medium_dark_skin_tone + OK_hand_dark_skin_tone + pinching_hand + pinching_hand_light_skin_tone + pinching_hand_medium_light_skin_tone + pinching_hand_medium_skin_tone + pinching_hand_medium_dark_skin_tone + pinching_hand_dark_skin_tone + victory_hand + victory_hand_light_skin_tone + victory_hand_medium_light_skin_tone + victory_hand_medium_skin_tone + victory_hand_medium_dark_skin_tone + victory_hand_dark_skin_tone + crossed_fingers + crossed_fingers_light_skin_tone + crossed_fingers_medium_light_skin_tone + crossed_fingers_medium_skin_tone + crossed_fingers_medium_dark_skin_tone + crossed_fingers_dark_skin_tone + love_you_gesture + love_you_gesture_light_skin_tone + love_you_gesture_medium_light_skin_tone + love_you_gesture_medium_skin_tone + love_you_gesture_medium_dark_skin_tone + love_you_gesture_dark_skin_tone + sign_of_the_horns + sign_of_the_horns_light_skin_tone + sign_of_the_horns_medium_light_skin_tone + sign_of_the_horns_medium_skin_tone + sign_of_the_horns_medium_dark_skin_tone + sign_of_the_horns_dark_skin_tone + call_me_hand + call_me_hand_light_skin_tone + call_me_hand_medium_light_skin_tone + call_me_hand_medium_skin_tone + call_me_hand_medium_dark_skin_tone + call_me_hand_dark_skin_tone + backhand_index_pointing_left + backhand_index_pointing_left_light_skin_tone + backhand_index_pointing_left_medium_light_skin_tone + backhand_index_pointing_left_medium_skin_tone + backhand_index_pointing_left_medium_dark_skin_tone + backhand_index_pointing_left_dark_skin_tone + backhand_index_pointing_right + backhand_index_pointing_right_light_skin_tone + backhand_index_pointing_right_medium_light_skin_tone + backhand_index_pointing_right_medium_skin_tone + backhand_index_pointing_right_medium_dark_skin_tone + backhand_index_pointing_right_dark_skin_tone + backhand_index_pointing_up + backhand_index_pointing_up_light_skin_tone + backhand_index_pointing_up_medium_light_skin_tone + backhand_index_pointing_up_medium_skin_tone + backhand_index_pointing_up_medium_dark_skin_tone + backhand_index_pointing_up_dark_skin_tone + middle_finger + middle_finger_light_skin_tone + middle_finger_medium_light_skin_tone + middle_finger_medium_skin_tone + middle_finger_medium_dark_skin_tone + middle_finger_dark_skin_tone + backhand_index_pointing_down + backhand_index_pointing_down_light_skin_tone + backhand_index_pointing_down_medium_light_skin_tone + backhand_index_pointing_down_medium_skin_tone + backhand_index_pointing_down_medium_dark_skin_tone + backhand_index_pointing_down_dark_skin_tone + index_pointing_up + index_pointing_up_light_skin_tone + index_pointing_up_medium_light_skin_tone + index_pointing_up_medium_skin_tone + index_pointing_up_medium_dark_skin_tone + index_pointing_up_dark_skin_tone + thumbs_up + thumbs_up_light_skin_tone + thumbs_up_medium_light_skin_tone + thumbs_up_medium_skin_tone + thumbs_up_medium_dark_skin_tone + thumbs_up_dark_skin_tone + thumbs_down + thumbs_down_light_skin_tone + thumbs_down_medium_light_skin_tone + thumbs_down_medium_skin_tone + thumbs_down_medium_dark_skin_tone + thumbs_down_dark_skin_tone + raised_fist + raised_fist_light_skin_tone + raised_fist_medium_light_skin_tone + raised_fist_medium_skin_tone + raised_fist_medium_dark_skin_tone + raised_fist_dark_skin_tone + oncoming_fist + oncoming_fist_light_skin_tone + oncoming_fist_medium_light_skin_tone + oncoming_fist_medium_skin_tone + oncoming_fist_medium_dark_skin_tone + oncoming_fist_dark_skin_tone + left_facing_fist + left_facing_fist_light_skin_tone + left_facing_fist_medium_light_skin_tone + left_facing_fist_medium_skin_tone + left_facing_fist_medium_dark_skin_tone + left_facing_fist_dark_skin_tone + right_facing_fist + right_facing_fist_light_skin_tone + right_facing_fist_medium_light_skin_tone + right_facing_fist_medium_skin_tone + right_facing_fist_medium_dark_skin_tone + right_facing_fist_dark_skin_tone + writing_hand + writing_hand_light_skin_tone + writing_hand_medium_light_skin_tone + writing_hand_medium_skin_tone + writing_hand_medium_dark_skin_tone + writing_hand_dark_skin_tone + nail_polish + nail_polish_light_skin_tone + nail_polish_medium_light_skin_tone + nail_polish_medium_skin_tone + nail_polish_medium_dark_skin_tone + nail_polish_dark_skin_tone + selfie + selfie_light_skin_tone + selfie_medium_light_skin_tone + selfie_medium_skin_tone + selfie_medium_dark_skin_tone + selfie_dark_skin_tone +" + +emoji_groups[people]=" + person_frowning + person_frowning_light_skin_tone + person_frowning_medium_light_skin_tone + person_frowning_medium_skin_tone + person_frowning_medium_dark_skin_tone + person_frowning_dark_skin_tone + man_frowning + man_frowning_light_skin_tone + man_frowning_medium_light_skin_tone + man_frowning_medium_skin_tone + man_frowning_medium_dark_skin_tone + man_frowning_dark_skin_tone + woman_frowning + woman_frowning_light_skin_tone + woman_frowning_medium_light_skin_tone + woman_frowning_medium_skin_tone + woman_frowning_medium_dark_skin_tone + woman_frowning_dark_skin_tone + person_pouting + person_pouting_light_skin_tone + person_pouting_medium_light_skin_tone + person_pouting_medium_skin_tone + person_pouting_medium_dark_skin_tone + person_pouting_dark_skin_tone + man_pouting + man_pouting_light_skin_tone + man_pouting_medium_light_skin_tone + man_pouting_medium_skin_tone + man_pouting_medium_dark_skin_tone + man_pouting_dark_skin_tone + woman_pouting + woman_pouting_light_skin_tone + woman_pouting_medium_light_skin_tone + woman_pouting_medium_skin_tone + woman_pouting_medium_dark_skin_tone + woman_pouting_dark_skin_tone + person_gesturing_NO + person_gesturing_NO_light_skin_tone + person_gesturing_NO_medium_light_skin_tone + person_gesturing_NO_medium_skin_tone + person_gesturing_NO_medium_dark_skin_tone + person_gesturing_NO_dark_skin_tone + man_gesturing_NO + man_gesturing_NO_light_skin_tone + man_gesturing_NO_medium_light_skin_tone + man_gesturing_NO_medium_skin_tone + man_gesturing_NO_medium_dark_skin_tone + man_gesturing_NO_dark_skin_tone + woman_gesturing_NO + woman_gesturing_NO_light_skin_tone + woman_gesturing_NO_medium_light_skin_tone + woman_gesturing_NO_medium_skin_tone + woman_gesturing_NO_medium_dark_skin_tone + woman_gesturing_NO_dark_skin_tone + person_gesturing_OK + person_gesturing_OK_light_skin_tone + person_gesturing_OK_medium_light_skin_tone + person_gesturing_OK_medium_skin_tone + person_gesturing_OK_medium_dark_skin_tone + person_gesturing_OK_dark_skin_tone + man_gesturing_OK + man_gesturing_OK_light_skin_tone + man_gesturing_OK_medium_light_skin_tone + man_gesturing_OK_medium_skin_tone + man_gesturing_OK_medium_dark_skin_tone + man_gesturing_OK_dark_skin_tone + woman_gesturing_OK + woman_gesturing_OK_light_skin_tone + woman_gesturing_OK_medium_light_skin_tone + woman_gesturing_OK_medium_skin_tone + woman_gesturing_OK_medium_dark_skin_tone + woman_gesturing_OK_dark_skin_tone + person_tipping_hand + person_tipping_hand_light_skin_tone + person_tipping_hand_medium_light_skin_tone + person_tipping_hand_medium_skin_tone + person_tipping_hand_medium_dark_skin_tone + person_tipping_hand_dark_skin_tone + man_tipping_hand + man_tipping_hand_light_skin_tone + man_tipping_hand_medium_light_skin_tone + man_tipping_hand_medium_skin_tone + man_tipping_hand_medium_dark_skin_tone + man_tipping_hand_dark_skin_tone + woman_tipping_hand + woman_tipping_hand_light_skin_tone + woman_tipping_hand_medium_light_skin_tone + woman_tipping_hand_medium_skin_tone + woman_tipping_hand_medium_dark_skin_tone + woman_tipping_hand_dark_skin_tone + person_raising_hand + person_raising_hand_light_skin_tone + person_raising_hand_medium_light_skin_tone + person_raising_hand_medium_skin_tone + person_raising_hand_medium_dark_skin_tone + person_raising_hand_dark_skin_tone + man_raising_hand + man_raising_hand_light_skin_tone + man_raising_hand_medium_light_skin_tone + man_raising_hand_medium_skin_tone + man_raising_hand_medium_dark_skin_tone + man_raising_hand_dark_skin_tone + woman_raising_hand + woman_raising_hand_light_skin_tone + woman_raising_hand_medium_light_skin_tone + woman_raising_hand_medium_skin_tone + woman_raising_hand_medium_dark_skin_tone + woman_raising_hand_dark_skin_tone + deaf_person + deaf_person_light_skin_tone + deaf_person_medium_light_skin_tone + deaf_person_medium_skin_tone + deaf_person_medium_dark_skin_tone + deaf_person_dark_skin_tone + deaf_man + deaf_man_light_skin_tone + deaf_man_medium_light_skin_tone + deaf_man_medium_skin_tone + deaf_man_medium_dark_skin_tone + deaf_man_dark_skin_tone + deaf_woman + deaf_woman_light_skin_tone + deaf_woman_medium_light_skin_tone + deaf_woman_medium_skin_tone + deaf_woman_medium_dark_skin_tone + deaf_woman_dark_skin_tone + person_bowing + person_bowing_light_skin_tone + person_bowing_medium_light_skin_tone + person_bowing_medium_skin_tone + person_bowing_medium_dark_skin_tone + person_bowing_dark_skin_tone + man_bowing + man_bowing_light_skin_tone + man_bowing_medium_light_skin_tone + man_bowing_medium_skin_tone + man_bowing_medium_dark_skin_tone + man_bowing_dark_skin_tone + woman_bowing + woman_bowing_light_skin_tone + woman_bowing_medium_light_skin_tone + woman_bowing_medium_skin_tone + woman_bowing_medium_dark_skin_tone + woman_bowing_dark_skin_tone + person_facepalming + person_facepalming_light_skin_tone + person_facepalming_medium_light_skin_tone + person_facepalming_medium_skin_tone + person_facepalming_medium_dark_skin_tone + person_facepalming_dark_skin_tone + man_facepalming + man_facepalming_light_skin_tone + man_facepalming_medium_light_skin_tone + man_facepalming_medium_skin_tone + man_facepalming_medium_dark_skin_tone + man_facepalming_dark_skin_tone + woman_facepalming + woman_facepalming_light_skin_tone + woman_facepalming_medium_light_skin_tone + woman_facepalming_medium_skin_tone + woman_facepalming_medium_dark_skin_tone + woman_facepalming_dark_skin_tone + person_shrugging + person_shrugging_light_skin_tone + person_shrugging_medium_light_skin_tone + person_shrugging_medium_skin_tone + person_shrugging_medium_dark_skin_tone + person_shrugging_dark_skin_tone + man_shrugging + man_shrugging_light_skin_tone + man_shrugging_medium_light_skin_tone + man_shrugging_medium_skin_tone + man_shrugging_medium_dark_skin_tone + man_shrugging_dark_skin_tone + woman_shrugging + woman_shrugging_light_skin_tone + woman_shrugging_medium_light_skin_tone + woman_shrugging_medium_skin_tone + woman_shrugging_medium_dark_skin_tone + woman_shrugging_dark_skin_tone + man_health_worker + man_health_worker_light_skin_tone + man_health_worker_medium_light_skin_tone + man_health_worker_medium_skin_tone + man_health_worker_medium_dark_skin_tone + man_health_worker_dark_skin_tone + woman_health_worker + woman_health_worker_light_skin_tone + woman_health_worker_medium_light_skin_tone + woman_health_worker_medium_skin_tone + woman_health_worker_medium_dark_skin_tone + woman_health_worker_dark_skin_tone + man_student + man_student_light_skin_tone + man_student_medium_light_skin_tone + man_student_medium_skin_tone + man_student_medium_dark_skin_tone + man_student_dark_skin_tone + woman_student + woman_student_light_skin_tone + woman_student_medium_light_skin_tone + woman_student_medium_skin_tone + woman_student_medium_dark_skin_tone + woman_student_dark_skin_tone + man_teacher + man_teacher_light_skin_tone + man_teacher_medium_light_skin_tone + man_teacher_medium_skin_tone + man_teacher_medium_dark_skin_tone + man_teacher_dark_skin_tone + woman_teacher + woman_teacher_light_skin_tone + woman_teacher_medium_light_skin_tone + woman_teacher_medium_skin_tone + woman_teacher_medium_dark_skin_tone + woman_teacher_dark_skin_tone + man_judge + man_judge_light_skin_tone + man_judge_medium_light_skin_tone + man_judge_medium_skin_tone + man_judge_medium_dark_skin_tone + man_judge_dark_skin_tone + woman_judge + woman_judge_light_skin_tone + woman_judge_medium_light_skin_tone + woman_judge_medium_skin_tone + woman_judge_medium_dark_skin_tone + woman_judge_dark_skin_tone + man_farmer + man_farmer_light_skin_tone + man_farmer_medium_light_skin_tone + man_farmer_medium_skin_tone + man_farmer_medium_dark_skin_tone + man_farmer_dark_skin_tone + woman_farmer + woman_farmer_light_skin_tone + woman_farmer_medium_light_skin_tone + woman_farmer_medium_skin_tone + woman_farmer_medium_dark_skin_tone + woman_farmer_dark_skin_tone + man_cook + man_cook_light_skin_tone + man_cook_medium_light_skin_tone + man_cook_medium_skin_tone + man_cook_medium_dark_skin_tone + man_cook_dark_skin_tone + woman_cook + woman_cook_light_skin_tone + woman_cook_medium_light_skin_tone + woman_cook_medium_skin_tone + woman_cook_medium_dark_skin_tone + woman_cook_dark_skin_tone + man_mechanic + man_mechanic_light_skin_tone + man_mechanic_medium_light_skin_tone + man_mechanic_medium_skin_tone + man_mechanic_medium_dark_skin_tone + man_mechanic_dark_skin_tone + woman_mechanic + woman_mechanic_light_skin_tone + woman_mechanic_medium_light_skin_tone + woman_mechanic_medium_skin_tone + woman_mechanic_medium_dark_skin_tone + woman_mechanic_dark_skin_tone + man_factory_worker + man_factory_worker_light_skin_tone + man_factory_worker_medium_light_skin_tone + man_factory_worker_medium_skin_tone + man_factory_worker_medium_dark_skin_tone + man_factory_worker_dark_skin_tone + woman_factory_worker + woman_factory_worker_light_skin_tone + woman_factory_worker_medium_light_skin_tone + woman_factory_worker_medium_skin_tone + woman_factory_worker_medium_dark_skin_tone + woman_factory_worker_dark_skin_tone + man_office_worker + man_office_worker_light_skin_tone + man_office_worker_medium_light_skin_tone + man_office_worker_medium_skin_tone + man_office_worker_medium_dark_skin_tone + man_office_worker_dark_skin_tone + woman_office_worker + woman_office_worker_light_skin_tone + woman_office_worker_medium_light_skin_tone + woman_office_worker_medium_skin_tone + woman_office_worker_medium_dark_skin_tone + woman_office_worker_dark_skin_tone + man_scientist + man_scientist_light_skin_tone + man_scientist_medium_light_skin_tone + man_scientist_medium_skin_tone + man_scientist_medium_dark_skin_tone + man_scientist_dark_skin_tone + woman_scientist + woman_scientist_light_skin_tone + woman_scientist_medium_light_skin_tone + woman_scientist_medium_skin_tone + woman_scientist_medium_dark_skin_tone + woman_scientist_dark_skin_tone + man_technologist + man_technologist_light_skin_tone + man_technologist_medium_light_skin_tone + man_technologist_medium_skin_tone + man_technologist_medium_dark_skin_tone + man_technologist_dark_skin_tone + woman_technologist + woman_technologist_light_skin_tone + woman_technologist_medium_light_skin_tone + woman_technologist_medium_skin_tone + woman_technologist_medium_dark_skin_tone + woman_technologist_dark_skin_tone + man_singer + man_singer_light_skin_tone + man_singer_medium_light_skin_tone + man_singer_medium_skin_tone + man_singer_medium_dark_skin_tone + man_singer_dark_skin_tone + woman_singer + woman_singer_light_skin_tone + woman_singer_medium_light_skin_tone + woman_singer_medium_skin_tone + woman_singer_medium_dark_skin_tone + woman_singer_dark_skin_tone + man_artist + man_artist_light_skin_tone + man_artist_medium_light_skin_tone + man_artist_medium_skin_tone + man_artist_medium_dark_skin_tone + man_artist_dark_skin_tone + woman_artist + woman_artist_light_skin_tone + woman_artist_medium_light_skin_tone + woman_artist_medium_skin_tone + woman_artist_medium_dark_skin_tone + woman_artist_dark_skin_tone + man_pilot + man_pilot_light_skin_tone + man_pilot_medium_light_skin_tone + man_pilot_medium_skin_tone + man_pilot_medium_dark_skin_tone + man_pilot_dark_skin_tone + woman_pilot + woman_pilot_light_skin_tone + woman_pilot_medium_light_skin_tone + woman_pilot_medium_skin_tone + woman_pilot_medium_dark_skin_tone + woman_pilot_dark_skin_tone + man_astronaut + man_astronaut_light_skin_tone + man_astronaut_medium_light_skin_tone + man_astronaut_medium_skin_tone + man_astronaut_medium_dark_skin_tone + man_astronaut_dark_skin_tone + woman_astronaut + woman_astronaut_light_skin_tone + woman_astronaut_medium_light_skin_tone + woman_astronaut_medium_skin_tone + woman_astronaut_medium_dark_skin_tone + woman_astronaut_dark_skin_tone + man_firefighter + man_firefighter_light_skin_tone + man_firefighter_medium_light_skin_tone + man_firefighter_medium_skin_tone + man_firefighter_medium_dark_skin_tone + man_firefighter_dark_skin_tone + woman_firefighter + woman_firefighter_light_skin_tone + woman_firefighter_medium_light_skin_tone + woman_firefighter_medium_skin_tone + woman_firefighter_medium_dark_skin_tone + woman_firefighter_dark_skin_tone + police_officer + police_officer_light_skin_tone + police_officer_medium_light_skin_tone + police_officer_medium_skin_tone + police_officer_medium_dark_skin_tone + police_officer_dark_skin_tone + man_police_officer + man_police_officer_light_skin_tone + man_police_officer_medium_light_skin_tone + man_police_officer_medium_skin_tone + man_police_officer_medium_dark_skin_tone + man_police_officer_dark_skin_tone + woman_police_officer + woman_police_officer_light_skin_tone + woman_police_officer_medium_light_skin_tone + woman_police_officer_medium_skin_tone + woman_police_officer_medium_dark_skin_tone + woman_police_officer_dark_skin_tone + detective + detective_light_skin_tone + detective_medium_light_skin_tone + detective_medium_skin_tone + detective_medium_dark_skin_tone + detective_dark_skin_tone + man_detective + man_detective_light_skin_tone + man_detective_medium_light_skin_tone + man_detective_medium_skin_tone + man_detective_medium_dark_skin_tone + man_detective_dark_skin_tone + woman_detective + woman_detective_light_skin_tone + woman_detective_medium_light_skin_tone + woman_detective_medium_skin_tone + woman_detective_medium_dark_skin_tone + woman_detective_dark_skin_tone + guard + guard_light_skin_tone + guard_medium_light_skin_tone + guard_medium_skin_tone + guard_medium_dark_skin_tone + guard_dark_skin_tone + man_guard + man_guard_light_skin_tone + man_guard_medium_light_skin_tone + man_guard_medium_skin_tone + man_guard_medium_dark_skin_tone + man_guard_dark_skin_tone + woman_guard + woman_guard_light_skin_tone + woman_guard_medium_light_skin_tone + woman_guard_medium_skin_tone + woman_guard_medium_dark_skin_tone + woman_guard_dark_skin_tone + construction_worker + construction_worker_light_skin_tone + construction_worker_medium_light_skin_tone + construction_worker_medium_skin_tone + construction_worker_medium_dark_skin_tone + construction_worker_dark_skin_tone + man_construction_worker + man_construction_worker_light_skin_tone + man_construction_worker_medium_light_skin_tone + man_construction_worker_medium_skin_tone + man_construction_worker_medium_dark_skin_tone + man_construction_worker_dark_skin_tone + woman_construction_worker + woman_construction_worker_light_skin_tone + woman_construction_worker_medium_light_skin_tone + woman_construction_worker_medium_skin_tone + woman_construction_worker_medium_dark_skin_tone + woman_construction_worker_dark_skin_tone + prince + prince_light_skin_tone + prince_medium_light_skin_tone + prince_medium_skin_tone + prince_medium_dark_skin_tone + prince_dark_skin_tone + princess + princess_light_skin_tone + princess_medium_light_skin_tone + princess_medium_skin_tone + princess_medium_dark_skin_tone + princess_dark_skin_tone + person_wearing_turban + person_wearing_turban_light_skin_tone + person_wearing_turban_medium_light_skin_tone + person_wearing_turban_medium_skin_tone + person_wearing_turban_medium_dark_skin_tone + person_wearing_turban_dark_skin_tone + man_wearing_turban + man_wearing_turban_light_skin_tone + man_wearing_turban_medium_light_skin_tone + man_wearing_turban_medium_skin_tone + man_wearing_turban_medium_dark_skin_tone + man_wearing_turban_dark_skin_tone + woman_wearing_turban + woman_wearing_turban_light_skin_tone + woman_wearing_turban_medium_light_skin_tone + woman_wearing_turban_medium_skin_tone + woman_wearing_turban_medium_dark_skin_tone + woman_wearing_turban_dark_skin_tone + man_with_Chinese_cap + man_with_Chinese_cap_light_skin_tone + man_with_Chinese_cap_medium_light_skin_tone + man_with_Chinese_cap_medium_skin_tone + man_with_Chinese_cap_medium_dark_skin_tone + man_with_Chinese_cap_dark_skin_tone + woman_with_headscarf + woman_with_headscarf_light_skin_tone + woman_with_headscarf_medium_light_skin_tone + woman_with_headscarf_medium_skin_tone + woman_with_headscarf_medium_dark_skin_tone + woman_with_headscarf_dark_skin_tone + man_in_tuxedo + man_in_tuxedo_light_skin_tone + man_in_tuxedo_medium_light_skin_tone + man_in_tuxedo_medium_skin_tone + man_in_tuxedo_medium_dark_skin_tone + man_in_tuxedo_dark_skin_tone + bride_with_veil + bride_with_veil_light_skin_tone + bride_with_veil_medium_light_skin_tone + bride_with_veil_medium_skin_tone + bride_with_veil_medium_dark_skin_tone + bride_with_veil_dark_skin_tone + pregnant_woman + pregnant_woman_light_skin_tone + pregnant_woman_medium_light_skin_tone + pregnant_woman_medium_skin_tone + pregnant_woman_medium_dark_skin_tone + pregnant_woman_dark_skin_tone + breast_feeding + breast_feeding_light_skin_tone + breast_feeding_medium_light_skin_tone + breast_feeding_medium_skin_tone + breast_feeding_medium_dark_skin_tone + breast_feeding_dark_skin_tone + baby_angel + baby_angel_light_skin_tone + baby_angel_medium_light_skin_tone + baby_angel_medium_skin_tone + baby_angel_medium_dark_skin_tone + baby_angel_dark_skin_tone + Santa_Claus + Santa_Claus_light_skin_tone + Santa_Claus_medium_light_skin_tone + Santa_Claus_medium_skin_tone + Santa_Claus_medium_dark_skin_tone + Santa_Claus_dark_skin_tone + Mrs_Claus + Mrs_Claus_light_skin_tone + Mrs_Claus_medium_light_skin_tone + Mrs_Claus_medium_skin_tone + Mrs_Claus_medium_dark_skin_tone + Mrs_Claus_dark_skin_tone + superhero + superhero_light_skin_tone + superhero_medium_light_skin_tone + superhero_medium_skin_tone + superhero_medium_dark_skin_tone + superhero_dark_skin_tone + man_superhero + man_superhero_light_skin_tone + man_superhero_medium_light_skin_tone + man_superhero_medium_skin_tone + man_superhero_medium_dark_skin_tone + man_superhero_dark_skin_tone + woman_superhero + woman_superhero_light_skin_tone + woman_superhero_medium_light_skin_tone + woman_superhero_medium_skin_tone + woman_superhero_medium_dark_skin_tone + woman_superhero_dark_skin_tone + supervillain + supervillain_light_skin_tone + supervillain_medium_light_skin_tone + supervillain_medium_skin_tone + supervillain_medium_dark_skin_tone + supervillain_dark_skin_tone + man_supervillain + man_supervillain_light_skin_tone + man_supervillain_medium_light_skin_tone + man_supervillain_medium_skin_tone + man_supervillain_medium_dark_skin_tone + man_supervillain_dark_skin_tone + woman_supervillain + woman_supervillain_light_skin_tone + woman_supervillain_medium_light_skin_tone + woman_supervillain_medium_skin_tone + woman_supervillain_medium_dark_skin_tone + woman_supervillain_dark_skin_tone + mage + mage_light_skin_tone + mage_medium_light_skin_tone + mage_medium_skin_tone + mage_medium_dark_skin_tone + mage_dark_skin_tone + man_mage + man_mage_light_skin_tone + man_mage_medium_light_skin_tone + man_mage_medium_skin_tone + man_mage_medium_dark_skin_tone + man_mage_dark_skin_tone + woman_mage + woman_mage_light_skin_tone + woman_mage_medium_light_skin_tone + woman_mage_medium_skin_tone + woman_mage_medium_dark_skin_tone + woman_mage_dark_skin_tone + fairy + fairy_light_skin_tone + fairy_medium_light_skin_tone + fairy_medium_skin_tone + fairy_medium_dark_skin_tone + fairy_dark_skin_tone + man_fairy + man_fairy_light_skin_tone + man_fairy_medium_light_skin_tone + man_fairy_medium_skin_tone + man_fairy_medium_dark_skin_tone + man_fairy_dark_skin_tone + woman_fairy + woman_fairy_light_skin_tone + woman_fairy_medium_light_skin_tone + woman_fairy_medium_skin_tone + woman_fairy_medium_dark_skin_tone + woman_fairy_dark_skin_tone + vampire + vampire_light_skin_tone + vampire_medium_light_skin_tone + vampire_medium_skin_tone + vampire_medium_dark_skin_tone + vampire_dark_skin_tone + man_vampire + man_vampire_light_skin_tone + man_vampire_medium_light_skin_tone + man_vampire_medium_skin_tone + man_vampire_medium_dark_skin_tone + man_vampire_dark_skin_tone + woman_vampire + woman_vampire_light_skin_tone + woman_vampire_medium_light_skin_tone + woman_vampire_medium_skin_tone + woman_vampire_medium_dark_skin_tone + woman_vampire_dark_skin_tone + merperson + merperson_light_skin_tone + merperson_medium_light_skin_tone + merperson_medium_skin_tone + merperson_medium_dark_skin_tone + merperson_dark_skin_tone + merman + merman_light_skin_tone + merman_medium_light_skin_tone + merman_medium_skin_tone + merman_medium_dark_skin_tone + merman_dark_skin_tone + mermaid + mermaid_light_skin_tone + mermaid_medium_light_skin_tone + mermaid_medium_skin_tone + mermaid_medium_dark_skin_tone + mermaid_dark_skin_tone + elf + elf_light_skin_tone + elf_medium_light_skin_tone + elf_medium_skin_tone + elf_medium_dark_skin_tone + elf_dark_skin_tone + man_elf + man_elf_light_skin_tone + man_elf_medium_light_skin_tone + man_elf_medium_skin_tone + man_elf_medium_dark_skin_tone + man_elf_dark_skin_tone + woman_elf + woman_elf_light_skin_tone + woman_elf_medium_light_skin_tone + woman_elf_medium_skin_tone + woman_elf_medium_dark_skin_tone + woman_elf_dark_skin_tone + genie + man_genie + woman_genie + zombie + man_zombie + woman_zombie + person_getting_massage + person_getting_massage_light_skin_tone + person_getting_massage_medium_light_skin_tone + person_getting_massage_medium_skin_tone + person_getting_massage_medium_dark_skin_tone + person_getting_massage_dark_skin_tone + man_getting_massage + man_getting_massage_light_skin_tone + man_getting_massage_medium_light_skin_tone + man_getting_massage_medium_skin_tone + man_getting_massage_medium_dark_skin_tone + man_getting_massage_dark_skin_tone + woman_getting_massage + woman_getting_massage_light_skin_tone + woman_getting_massage_medium_light_skin_tone + woman_getting_massage_medium_skin_tone + woman_getting_massage_medium_dark_skin_tone + woman_getting_massage_dark_skin_tone + person_getting_haircut + person_getting_haircut_light_skin_tone + person_getting_haircut_medium_light_skin_tone + person_getting_haircut_medium_skin_tone + person_getting_haircut_medium_dark_skin_tone + person_getting_haircut_dark_skin_tone + man_getting_haircut + man_getting_haircut_light_skin_tone + man_getting_haircut_medium_light_skin_tone + man_getting_haircut_medium_skin_tone + man_getting_haircut_medium_dark_skin_tone + man_getting_haircut_dark_skin_tone + woman_getting_haircut + woman_getting_haircut_light_skin_tone + woman_getting_haircut_medium_light_skin_tone + woman_getting_haircut_medium_skin_tone + woman_getting_haircut_medium_dark_skin_tone + woman_getting_haircut_dark_skin_tone + person_walking + person_walking_light_skin_tone + person_walking_medium_light_skin_tone + person_walking_medium_skin_tone + person_walking_medium_dark_skin_tone + person_walking_dark_skin_tone + man_walking + man_walking_light_skin_tone + man_walking_medium_light_skin_tone + man_walking_medium_skin_tone + man_walking_medium_dark_skin_tone + man_walking_dark_skin_tone + woman_walking + woman_walking_light_skin_tone + woman_walking_medium_light_skin_tone + woman_walking_medium_skin_tone + woman_walking_medium_dark_skin_tone + woman_walking_dark_skin_tone + person_standing + person_standing_light_skin_tone + person_standing_medium_light_skin_tone + person_standing_medium_skin_tone + person_standing_medium_dark_skin_tone + person_standing_dark_skin_tone + man_standing + man_standing_light_skin_tone + man_standing_medium_light_skin_tone + man_standing_medium_skin_tone + man_standing_medium_dark_skin_tone + man_standing_dark_skin_tone + woman_standing + woman_standing_light_skin_tone + woman_standing_medium_light_skin_tone + woman_standing_medium_skin_tone + woman_standing_medium_dark_skin_tone + woman_standing_dark_skin_tone + person_kneeling + person_kneeling_light_skin_tone + person_kneeling_medium_light_skin_tone + person_kneeling_medium_skin_tone + person_kneeling_medium_dark_skin_tone + person_kneeling_dark_skin_tone + man_kneeling + man_kneeling_light_skin_tone + man_kneeling_medium_light_skin_tone + man_kneeling_medium_skin_tone + man_kneeling_medium_dark_skin_tone + man_kneeling_dark_skin_tone + woman_kneeling + woman_kneeling_light_skin_tone + woman_kneeling_medium_light_skin_tone + woman_kneeling_medium_skin_tone + woman_kneeling_medium_dark_skin_tone + woman_kneeling_dark_skin_tone + man_with_probing_cane + man_with_probing_cane_light_skin_tone + man_with_probing_cane_medium_light_skin_tone + man_with_probing_cane_medium_skin_tone + man_with_probing_cane_medium_dark_skin_tone + man_with_probing_cane_dark_skin_tone + woman_with_probing_cane + woman_with_probing_cane_light_skin_tone + woman_with_probing_cane_medium_light_skin_tone + woman_with_probing_cane_medium_skin_tone + woman_with_probing_cane_medium_dark_skin_tone + woman_with_probing_cane_dark_skin_tone + man_in_motorized_wheelchair + man_in_motorized_wheelchair_light_skin_tone + man_in_motorized_wheelchair_medium_light_skin_tone + man_in_motorized_wheelchair_medium_skin_tone + man_in_motorized_wheelchair_medium_dark_skin_tone + man_in_motorized_wheelchair_dark_skin_tone + woman_in_motorized_wheelchair + woman_in_motorized_wheelchair_light_skin_tone + woman_in_motorized_wheelchair_medium_light_skin_tone + woman_in_motorized_wheelchair_medium_skin_tone + woman_in_motorized_wheelchair_medium_dark_skin_tone + woman_in_motorized_wheelchair_dark_skin_tone + man_in_manual_wheelchair + man_in_manual_wheelchair_light_skin_tone + man_in_manual_wheelchair_medium_light_skin_tone + man_in_manual_wheelchair_medium_skin_tone + man_in_manual_wheelchair_medium_dark_skin_tone + man_in_manual_wheelchair_dark_skin_tone + woman_in_manual_wheelchair + woman_in_manual_wheelchair_light_skin_tone + woman_in_manual_wheelchair_medium_light_skin_tone + woman_in_manual_wheelchair_medium_skin_tone + woman_in_manual_wheelchair_medium_dark_skin_tone + woman_in_manual_wheelchair_dark_skin_tone + person_running + person_running_light_skin_tone + person_running_medium_light_skin_tone + person_running_medium_skin_tone + person_running_medium_dark_skin_tone + person_running_dark_skin_tone + man_running + man_running_light_skin_tone + man_running_medium_light_skin_tone + man_running_medium_skin_tone + man_running_medium_dark_skin_tone + man_running_dark_skin_tone + woman_running + woman_running_light_skin_tone + woman_running_medium_light_skin_tone + woman_running_medium_skin_tone + woman_running_medium_dark_skin_tone + woman_running_dark_skin_tone + woman_dancing + woman_dancing_light_skin_tone + woman_dancing_medium_light_skin_tone + woman_dancing_medium_skin_tone + woman_dancing_medium_dark_skin_tone + woman_dancing_dark_skin_tone + woman_dancing_dark_skin_tone_1 + man_dancing_light_skin_tone + man_dancing_medium_light_skin_tone + man_dancing_medium_skin_tone + man_dancing_medium_dark_skin_tone + man_dancing_dark_skin_tone + man_in_suit_levitating + man_in_suit_levitating_light_skin_tone + man_in_suit_levitating_medium_light_skin_tone + man_in_suit_levitating_medium_skin_tone + man_in_suit_levitating_medium_dark_skin_tone + man_in_suit_levitating_dark_skin_tone + people_with_bunny_ears + men_with_bunny_ears + women_with_bunny_ears + person_in_steamy_room + person_in_steamy_room_light_skin_tone + person_in_steamy_room_medium_light_skin_tone + person_in_steamy_room_medium_skin_tone + person_in_steamy_room_medium_dark_skin_tone + person_in_steamy_room_dark_skin_tone + man_in_steamy_room + man_in_steamy_room_light_skin_tone + man_in_steamy_room_medium_light_skin_tone + man_in_steamy_room_medium_skin_tone + man_in_steamy_room_medium_dark_skin_tone + man_in_steamy_room_dark_skin_tone + woman_in_steamy_room + woman_in_steamy_room_light_skin_tone + woman_in_steamy_room_medium_light_skin_tone + woman_in_steamy_room_medium_skin_tone + woman_in_steamy_room_medium_dark_skin_tone + woman_in_steamy_room_dark_skin_tone + person_climbing + person_climbing_light_skin_tone + person_climbing_medium_light_skin_tone + person_climbing_medium_skin_tone + person_climbing_medium_dark_skin_tone + person_climbing_dark_skin_tone + man_climbing + man_climbing_light_skin_tone + man_climbing_medium_light_skin_tone + man_climbing_medium_skin_tone + man_climbing_medium_dark_skin_tone + man_climbing_dark_skin_tone + woman_climbing + woman_climbing_light_skin_tone + woman_climbing_medium_light_skin_tone + woman_climbing_medium_skin_tone + woman_climbing_medium_dark_skin_tone + woman_climbing_dark_skin_tone + person_fencing + horse_racing + horse_racing_light_skin_tone + horse_racing_medium_light_skin_tone + horse_racing_medium_skin_tone + horse_racing_medium_dark_skin_tone + horse_racing_dark_skin_tone + skier + snowboarder + snowboarder_light_skin_tone + snowboarder_medium_light_skin_tone + snowboarder_medium_skin_tone + snowboarder_medium_dark_skin_tone + snowboarder_dark_skin_tone + person_golfing + person_golfing_light_skin_tone + person_golfing_medium_light_skin_tone + person_golfing_medium_skin_tone + person_golfing_medium_dark_skin_tone + person_golfing_dark_skin_tone + man_golfing + man_golfing_light_skin_tone + man_golfing_medium_light_skin_tone + man_golfing_medium_skin_tone + man_golfing_medium_dark_skin_tone + man_golfing_dark_skin_tone + woman_golfing + woman_golfing_light_skin_tone + woman_golfing_medium_light_skin_tone + woman_golfing_medium_skin_tone + woman_golfing_medium_dark_skin_tone + woman_golfing_dark_skin_tone + person_surfing + person_surfing_light_skin_tone + person_surfing_medium_light_skin_tone + person_surfing_medium_skin_tone + person_surfing_medium_dark_skin_tone + person_surfing_dark_skin_tone + man_surfing + man_surfing_light_skin_tone + man_surfing_medium_light_skin_tone + man_surfing_medium_skin_tone + man_surfing_medium_dark_skin_tone + man_surfing_dark_skin_tone + woman_surfing + woman_surfing_light_skin_tone + woman_surfing_medium_light_skin_tone + woman_surfing_medium_skin_tone + woman_surfing_medium_dark_skin_tone + woman_surfing_dark_skin_tone + person_rowing_boat + person_rowing_boat_light_skin_tone + person_rowing_boat_medium_light_skin_tone + person_rowing_boat_medium_skin_tone + person_rowing_boat_medium_dark_skin_tone + person_rowing_boat_dark_skin_tone + man_rowing_boat + man_rowing_boat_light_skin_tone + man_rowing_boat_medium_light_skin_tone + man_rowing_boat_medium_skin_tone + man_rowing_boat_medium_dark_skin_tone + man_rowing_boat_dark_skin_tone + woman_rowing_boat + woman_rowing_boat_light_skin_tone + woman_rowing_boat_medium_light_skin_tone + woman_rowing_boat_medium_skin_tone + woman_rowing_boat_medium_dark_skin_tone + woman_rowing_boat_dark_skin_tone + person_swimming + person_swimming_light_skin_tone + person_swimming_medium_light_skin_tone + person_swimming_medium_skin_tone + person_swimming_medium_dark_skin_tone + person_swimming_dark_skin_tone + man_swimming + man_swimming_light_skin_tone + man_swimming_medium_light_skin_tone + man_swimming_medium_skin_tone + man_swimming_medium_dark_skin_tone + man_swimming_dark_skin_tone + woman_swimming + woman_swimming_light_skin_tone + woman_swimming_medium_light_skin_tone + woman_swimming_medium_skin_tone + woman_swimming_medium_dark_skin_tone + woman_swimming_dark_skin_tone + person_bouncing_ball + person_bouncing_ball_light_skin_tone + person_bouncing_ball_medium_light_skin_tone + person_bouncing_ball_medium_skin_tone + person_bouncing_ball_medium_dark_skin_tone + person_bouncing_ball_dark_skin_tone + man_bouncing_ball + man_bouncing_ball_light_skin_tone + man_bouncing_ball_medium_light_skin_tone + man_bouncing_ball_medium_skin_tone + man_bouncing_ball_medium_dark_skin_tone + man_bouncing_ball_dark_skin_tone + woman_bouncing_ball + woman_bouncing_ball_light_skin_tone + woman_bouncing_ball_medium_light_skin_tone + woman_bouncing_ball_medium_skin_tone + woman_bouncing_ball_medium_dark_skin_tone + woman_bouncing_ball_dark_skin_tone + person_lifting_weights + person_lifting_weights_light_skin_tone + person_lifting_weights_medium_light_skin_tone + person_lifting_weights_medium_skin_tone + person_lifting_weights_medium_dark_skin_tone + person_lifting_weights_dark_skin_tone + man_lifting_weights + man_lifting_weights_light_skin_tone + man_lifting_weights_medium_light_skin_tone + man_lifting_weights_medium_skin_tone + man_lifting_weights_medium_dark_skin_tone + man_lifting_weights_dark_skin_tone + woman_lifting_weights + woman_lifting_weights_light_skin_tone + woman_lifting_weights_medium_light_skin_tone + woman_lifting_weights_medium_skin_tone + woman_lifting_weights_medium_dark_skin_tone + woman_lifting_weights_dark_skin_tone + person_biking + person_biking_light_skin_tone + person_biking_medium_light_skin_tone + person_biking_medium_skin_tone + person_biking_medium_dark_skin_tone + person_biking_dark_skin_tone + man_biking + man_biking_light_skin_tone + man_biking_medium_light_skin_tone + man_biking_medium_skin_tone + man_biking_medium_dark_skin_tone + man_biking_dark_skin_tone + woman_biking + woman_biking_light_skin_tone + woman_biking_medium_light_skin_tone + woman_biking_medium_skin_tone + woman_biking_medium_dark_skin_tone + woman_biking_dark_skin_tone + person_mountain_biking + person_mountain_biking_light_skin_tone + person_mountain_biking_medium_light_skin_tone + person_mountain_biking_medium_skin_tone + person_mountain_biking_medium_dark_skin_tone + person_mountain_biking_dark_skin_tone + man_mountain_biking + man_mountain_biking_light_skin_tone + man_mountain_biking_medium_light_skin_tone + man_mountain_biking_medium_skin_tone + man_mountain_biking_medium_dark_skin_tone + man_mountain_biking_dark_skin_tone + woman_mountain_biking + woman_mountain_biking_light_skin_tone + woman_mountain_biking_medium_light_skin_tone + woman_mountain_biking_medium_skin_tone + woman_mountain_biking_medium_dark_skin_tone + woman_mountain_biking_dark_skin_tone + person_cartwheeling + person_cartwheeling_light_skin_tone + person_cartwheeling_medium_light_skin_tone + person_cartwheeling_medium_skin_tone + person_cartwheeling_medium_dark_skin_tone + person_cartwheeling_dark_skin_tone + man_cartwheeling + man_cartwheeling_light_skin_tone + man_cartwheeling_medium_light_skin_tone + man_cartwheeling_medium_skin_tone + man_cartwheeling_medium_dark_skin_tone + man_cartwheeling_dark_skin_tone + woman_cartwheeling + woman_cartwheeling_light_skin_tone + woman_cartwheeling_medium_light_skin_tone + woman_cartwheeling_medium_skin_tone + woman_cartwheeling_medium_dark_skin_tone + woman_cartwheeling_dark_skin_tone + people_wrestling + men_wrestling + women_wrestling + person_playing_water_polo + person_playing_water_polo_light_skin_tone + person_playing_water_polo_medium_light_skin_tone + person_playing_water_polo_medium_skin_tone + person_playing_water_polo_medium_dark_skin_tone + person_playing_water_polo_dark_skin_tone + man_playing_water_polo + man_playing_water_polo_light_skin_tone + man_playing_water_polo_medium_light_skin_tone + man_playing_water_polo_medium_skin_tone + man_playing_water_polo_medium_dark_skin_tone + man_playing_water_polo_dark_skin_tone + woman_playing_water_polo + woman_playing_water_polo_light_skin_tone + woman_playing_water_polo_medium_light_skin_tone + woman_playing_water_polo_medium_skin_tone + woman_playing_water_polo_medium_dark_skin_tone + woman_playing_water_polo_dark_skin_tone + person_playing_handball + person_playing_handball_light_skin_tone + person_playing_handball_medium_light_skin_tone + person_playing_handball_medium_skin_tone + person_playing_handball_medium_dark_skin_tone + person_playing_handball_dark_skin_tone + man_playing_handball + man_playing_handball_light_skin_tone + man_playing_handball_medium_light_skin_tone + man_playing_handball_medium_skin_tone + man_playing_handball_medium_dark_skin_tone + man_playing_handball_dark_skin_tone + woman_playing_handball + woman_playing_handball_light_skin_tone + woman_playing_handball_medium_light_skin_tone + woman_playing_handball_medium_skin_tone + woman_playing_handball_medium_dark_skin_tone + woman_playing_handball_dark_skin_tone + person_juggling + person_juggling_light_skin_tone + person_juggling_medium_light_skin_tone + person_juggling_medium_skin_tone + person_juggling_medium_dark_skin_tone + person_juggling_dark_skin_tone + man_juggling + man_juggling_light_skin_tone + man_juggling_medium_light_skin_tone + man_juggling_medium_skin_tone + man_juggling_medium_dark_skin_tone + man_juggling_dark_skin_tone + woman_juggling + woman_juggling_light_skin_tone + woman_juggling_medium_light_skin_tone + woman_juggling_medium_skin_tone + woman_juggling_medium_dark_skin_tone + woman_juggling_dark_skin_tone + person_in_lotus_position + person_in_lotus_position_light_skin_tone + person_in_lotus_position_medium_light_skin_tone + person_in_lotus_position_medium_skin_tone + person_in_lotus_position_medium_dark_skin_tone + person_in_lotus_position_dark_skin_tone + man_in_lotus_position + man_in_lotus_position_light_skin_tone + man_in_lotus_position_medium_light_skin_tone + man_in_lotus_position_medium_skin_tone + man_in_lotus_position_medium_dark_skin_tone + man_in_lotus_position_dark_skin_tone + woman_in_lotus_position + woman_in_lotus_position_light_skin_tone + woman_in_lotus_position_medium_light_skin_tone + woman_in_lotus_position_medium_skin_tone + woman_in_lotus_position_medium_dark_skin_tone + woman_in_lotus_position_dark_skin_tone + person_taking_bath + person_taking_bath_light_skin_tone + person_taking_bath_medium_light_skin_tone + person_taking_bath_medium_skin_tone + person_taking_bath_medium_dark_skin_tone + person_taking_bath_dark_skin_tone + person_in_bed + person_in_bed_light_skin_tone + person_in_bed_medium_light_skin_tone + person_in_bed_medium_skin_tone + person_in_bed_medium_dark_skin_tone + person_in_bed_dark_skin_tone + people_holding_hands + people_holding_hands_light_skin_tone + people_holding_hands_medium_light_skin_tone_light_skin_tone + people_holding_hands_medium_light_skin_tone_light_skin_tone_1 + people_holding_hands_medium_skin_tone_light_skin_tone + people_holding_hands_medium_skin_tone_medium_light_skin_tone + people_holding_hands_medium_skin_tone_medium_light_skin_tone_1 + people_holding_hands_medium_dark_skin_tone_light_skin_tone + people_holding_hands_medium_dark_skin_tone_medium_light_skin_tone + people_holding_hands_medium_dark_skin_tone_medium_skin_tone + people_holding_hands_medium_dark_skin_tone_medium_skin_tone_1 + people_holding_hands_dark_skin_tone_light_skin_tone + people_holding_hands_dark_skin_tone_medium_light_skin_tone + people_holding_hands_dark_skin_tone_medium_skin_tone + people_holding_hands_dark_skin_tone_medium_dark_skin_tone + people_holding_hands_dark_skin_tone_medium_dark_skin_tone_1 + women_holding_hands + women_holding_hands_light_skin_tone + women_holding_hands_medium_light_skin_tone_light_skin_tone + women_holding_hands_medium_light_skin_tone_light_skin_tone_1 + women_holding_hands_medium_skin_tone_light_skin_tone + women_holding_hands_medium_skin_tone_medium_light_skin_tone + women_holding_hands_medium_skin_tone_medium_light_skin_tone_1 + women_holding_hands_medium_dark_skin_tone_light_skin_tone + women_holding_hands_medium_dark_skin_tone_medium_light_skin_tone + women_holding_hands_medium_dark_skin_tone_medium_skin_tone + women_holding_hands_medium_dark_skin_tone_medium_skin_tone_1 + women_holding_hands_dark_skin_tone_light_skin_tone + women_holding_hands_dark_skin_tone_medium_light_skin_tone + women_holding_hands_dark_skin_tone_medium_skin_tone + women_holding_hands_dark_skin_tone_medium_dark_skin_tone + women_holding_hands_dark_skin_tone_medium_dark_skin_tone_1 + woman_and_man_holding_hands + woman_and_man_holding_hands_light_skin_tone + woman_and_man_holding_hands_light_skin_tone_medium_light_skin_tone + woman_and_man_holding_hands_light_skin_tone_medium_skin_tone + woman_and_man_holding_hands_light_skin_tone_medium_dark_skin_tone + woman_and_man_holding_hands_light_skin_tone_dark_skin_tone + woman_and_man_holding_hands_medium_light_skin_tone_light_skin_tone + woman_and_man_holding_hands_medium_light_skin_tone_light_skin_tone_1 + woman_and_man_holding_hands_medium_light_skin_tone_medium_skin_tone + woman_and_man_holding_hands_medium_light_skin_tone_medium_dark_skin_tone + woman_and_man_holding_hands_medium_light_skin_tone_dark_skin_tone + woman_and_man_holding_hands_medium_skin_tone_light_skin_tone + woman_and_man_holding_hands_medium_skin_tone_medium_light_skin_tone + woman_and_man_holding_hands_medium_skin_tone_medium_light_skin_tone_1 + woman_and_man_holding_hands_medium_skin_tone_medium_dark_skin_tone + woman_and_man_holding_hands_medium_skin_tone_dark_skin_tone + woman_and_man_holding_hands_medium_dark_skin_tone_light_skin_tone + woman_and_man_holding_hands_medium_dark_skin_tone_medium_light_skin_tone + woman_and_man_holding_hands_medium_dark_skin_tone_medium_skin_tone + woman_and_man_holding_hands_medium_dark_skin_tone_medium_skin_tone_1 + woman_and_man_holding_hands_medium_dark_skin_tone_dark_skin_tone + woman_and_man_holding_hands_dark_skin_tone_light_skin_tone + woman_and_man_holding_hands_dark_skin_tone_medium_light_skin_tone + woman_and_man_holding_hands_dark_skin_tone_medium_skin_tone + woman_and_man_holding_hands_dark_skin_tone_medium_dark_skin_tone + woman_and_man_holding_hands_dark_skin_tone_medium_dark_skin_tone_1 + men_holding_hands + men_holding_hands_light_skin_tone + men_holding_hands_medium_light_skin_tone_light_skin_tone + men_holding_hands_medium_light_skin_tone_light_skin_tone_1 + men_holding_hands_medium_skin_tone_light_skin_tone + men_holding_hands_medium_skin_tone_medium_light_skin_tone + men_holding_hands_medium_skin_tone_medium_light_skin_tone_1 + men_holding_hands_medium_dark_skin_tone_light_skin_tone + men_holding_hands_medium_dark_skin_tone_medium_light_skin_tone + men_holding_hands_medium_dark_skin_tone_medium_skin_tone + men_holding_hands_medium_dark_skin_tone_medium_skin_tone_1 + men_holding_hands_dark_skin_tone_light_skin_tone + men_holding_hands_dark_skin_tone_medium_light_skin_tone + men_holding_hands_dark_skin_tone_medium_skin_tone + men_holding_hands_dark_skin_tone_medium_dark_skin_tone + men_holding_hands_dark_skin_tone_medium_dark_skin_tone_1 + kiss + kiss_woman_man + kiss_man_man + kiss_woman_woman + couple_with_heart + couple_with_heart_woman_man + couple_with_heart_man_man + couple_with_heart_woman_woman + family + family_man_woman_boy + family_man_woman_girl + family_man_woman_girl_boy + family_man_woman_boy_boy + family_man_woman_girl_girl + family_man_man_boy + family_man_man_girl + family_man_man_girl_boy + family_man_man_boy_boy + family_man_man_girl_girl + family_woman_woman_boy + family_woman_woman_girl + family_woman_woman_girl_boy + family_woman_woman_boy_boy + family_woman_woman_girl_girl + family_man_boy + family_man_boy_boy + family_man_girl + family_man_girl_boy + family_man_girl_girl + family_woman_boy + family_woman_boy_boy + family_woman_girl + family_woman_girl_boy + family_woman_girl_girl + speaking_head + bust_in_silhouette + busts_in_silhouette + footprints +" + +emoji_groups[animals]=" + monkey_face + monkey_face_1 + gorilla + orangutan + dog_face + dog_face_1 + guide_dog + service_dog + poodle + wolf + fox + raccoon + cat_face + cat_face_1 + lion + tiger_face + tiger_face_1 + leopard + horse_face + horse_face_1 + unicorn + zebra + deer + cow_face + ox + water_buffalo + cow + pig_face + pig_face_1 + boar + pig_nose + ram + ewe + goat + camel + two_hump_camel + llama + giraffe + elephant + rhinoceros + hippopotamus + mouse_face + mouse_face_1 + rat + hamster + rabbit_face + rabbit_face_1 + chipmunk + hedgehog + bat + bear + koala + panda + sloth + otter + skunk + kangaroo + badger + paw_prints + turkey + chicken + rooster + hatching_chick + baby_chick + front_facing_baby_chick + bird + penguin + dove + eagle + duck + swan + owl + flamingo + peacock + parrot + frog + crocodile + turtle + lizard + snake + dragon_face + dragon_face_1 + sauropod + T_Rex + spouting_whale + spouting_whale_1 + dolphin + fish + tropical_fish + blowfish + shark + octopus + spiral_shell + snail + butterfly + bug + ant + honeybee + lady_beetle + cricket + spider + spider_web + scorpion + mosquito + microbe +" + +emoji_groups[faces]=" + grinning_face + grinning_face_with_big_eyes + grinning_face_with_smiling_eyes + beaming_face_with_smiling_eyes + grinning_squinting_face + grinning_face_with_sweat + rolling_on_the_floor_laughing + face_with_tears_of_joy + slightly_smiling_face + upside_down_face + winking_face + smiling_face_with_smiling_eyes + smiling_face_with_halo + smiling_face_with_hearts + smiling_face_with_heart_eyes + star_struck + face_blowing_a_kiss + kissing_face + smiling_face + kissing_face_with_closed_eyes + kissing_face_with_smiling_eyes + face_savoring_food + face_with_tongue + winking_face_with_tongue + zany_face + squinting_face_with_tongue + money_mouth_face + hugging_face + face_with_hand_over_mouth + shushing_face + thinking_face + zipper_mouth_face + face_with_raised_eyebrow + neutral_face + expressionless_face + face_without_mouth + smirking_face + unamused_face + face_with_rolling_eyes + grimacing_face + lying_face + relieved_face + pensive_face + sleepy_face + drooling_face + sleeping_face + face_with_medical_mask + face_with_thermometer + face_with_head_bandage + nauseated_face + face_vomiting + sneezing_face + hot_face + cold_face + woozy_face + dizzy_face + exploding_head + cowboy_hat_face + partying_face + smiling_face_with_sunglasses + nerd_face + face_with_monocle + confused_face + worried_face + slightly_frowning_face + slightly_frowning_face_1 + face_with_open_mouth + hushed_face + astonished_face + flushed_face + pleading_face + frowning_face_with_open_mouth + anguished_face + fearful_face + anxious_face_with_sweat + sad_but_relieved_face + crying_face + loudly_crying_face + face_screaming_in_fear + confounded_face + persevering_face + disappointed_face + downcast_face_with_sweat + weary_face + tired_face + yawning_face + face_with_steam_from_nose + pouting_face + angry_face + face_with_symbols_on_mouth + smiling_face_with_horns + angry_face_with_horns + skull + skull_and_crossbones + pile_of_poo + clown_face + ogre + goblin + ghost + alien + alien_monster + robot +" + +emoji_groups[flags]=" + chequered_flag + triangular_flag + crossed_flags + black_flag + white_flag + rainbow_flag + pirate_flag + Ascension_Island + Andorra + United_Arab_Emirates + Afghanistan + Antigua_and_Barbuda + Anguilla + Albania + Armenia + Angola + Antarctica + Argentina + American_Samoa + Austria + Australia + Aruba + Åland_Islands + Azerbaijan + Bosnia_and_Herzegovina + Barbados + Bangladesh + Belgium + Burkina_Faso + Bulgaria + Bahrain + Burundi + Benin + St_Barthélemy + Bermuda + Brunei + Bolivia + Caribbean_Netherlands + Brazil + Bahamas + Bhutan + Bouvet_Island + Botswana + Belarus + Belize + Canada + Cocos_Keeling_Islands + Congo__Kinshasa + Central_African_Republic + Congo__Brazzaville + Switzerland + Côte_d_Ivoire + Cook_Islands + Chile + Cameroon + China + Colombia + Clipperton_Island + Costa_Rica + Cuba + Cape_Verde + Curaçao + Christmas_Island + Cyprus + Czechia + Germany + Diego_Garcia + Djibouti + Denmark + Dominica + Dominican_Republic + Algeria + Ceuta_and_Melilla + Ecuador + Estonia + Egypt + Western_Sahara + Eritrea + Spain + Ethiopia + European_Union + Finland + Fiji + Falkland_Islands + Micronesia + Faroe_Islands + France + Gabon + United_Kingdom + Grenada + Georgia + French_Guiana + Guernsey + Ghana + Gibraltar + Greenland + Gambia + Guinea + Guadeloupe + Equatorial_Guinea + Greece + South_Georgia_and_South_Sandwich_Islands + Guatemala + Guam + Guinea_Bissau + Guyana + Hong_Kong_SAR_China + Heard_and_McDonald_Islands + Honduras + Croatia + Haiti + Hungary + Canary_Islands + Indonesia + Ireland + Israel + Isle_of_Man + India + British_Indian_Ocean_Territory + Iraq + Iran + Iceland + Italy + Jersey + Jamaica + Jordan + Japan + Kenya + Kyrgyzstan + Cambodia + Kiribati + Comoros + St_Kitts_and_Nevis + North_Korea + South_Korea + Kuwait + Cayman_Islands + Kazakhstan + Laos + Lebanon + St_Lucia + Liechtenstein + Sri_Lanka + Liberia + Lesotho + Lithuania + Luxembourg + Latvia + Libya + Morocco + Monaco + Moldova + Montenegro + St_Martin + Madagascar + Marshall_Islands + Macedonia + Mali + Myanmar_Burma_ + Mongolia + Macao_SAR_China + Northern_Mariana_Islands + Martinique + Mauritania + Montserrat + Malta + Mauritius + Maldives + Malawi + Mexico + Malaysia + Mozambique + Namibia + New_Caledonia + Niger + Norfolk_Island + Nigeria + Nicaragua + Netherlands + Norway + Nepal + Nauru + Niue + New_Zealand + Oman + Panama + Peru + French_Polynesia + Papua_New_Guinea + Philippines + Pakistan + Poland + St_Pierre_and_Miquelon + Pitcairn_Islands + Puerto_Rico + Palestinian_Territories + Portugal + Palau + Paraguay + Qatar + Réunion + Romania + Serbia + Russia + Rwanda + Saudi_Arabia + Solomon_Islands + Seychelles + Sudan + Sweden + Singapore + St_Helena + Slovenia + Svalbard_and_Jan_Mayen + Slovakia + Sierra_Leone + San_Marino + Senegal + Somalia + Suriname + South_Sudan + São_Tomé_and_Príncipe + El_Salvador + Sint_Maarten + Syria + Eswatini + Tristan_da_Cunha + Turks_and_Caicos_Islands + Chad + French_Southern_Territories + Togo + Thailand + Tajikistan + Tokelau + Timor_Leste + Turkmenistan + Tunisia + Tonga + Turkey + Trinidad_and_Tobago + Tuvalu + Taiwan + Tanzania + Ukraine + Uganda + U_S_Outlying_Islands + United_Nations + United_States + Uruguay + Uzbekistan + Vatican_City + St_Vincent_and_Grenadines + Venezuela + British_Virgin_Islands + U_S_Virgin_Islands + Vietnam + Vanuatu + Wallis_and_Futuna + Samoa + Kosovo + Yemen + Mayotte + South_Africa + Zambia + Zimbabwe + England + Scotland + Wales +" diff --git a/zsh/.oh-my-zsh/plugins/emoji/emoji-data.txt b/zsh/.oh-my-zsh/plugins/emoji/emoji-data.txt new file mode 100644 index 0000000..8b4994c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emoji/emoji-data.txt @@ -0,0 +1,4122 @@ +# emoji-data.txt +# (Originally emoji-test.txt) +# (Retrieved from https://unicode.org/Public/emoji/12.0/emoji-test.txt) + +# Date: 2019-01-27, 15:43:01 GMT +# © 2019 Unicode®, Inc. +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. +# For terms of use, see http://www.unicode.org/terms_of_use.html +# +# Emoji Keyboard/Display Test Data for UTS #51 +# Version: 12.0 +# +# For documentation and usage, see http://www.unicode.org/reports/tr51 +# +# This file provides data for testing which emoji forms should be in keyboards and which should also be displayed/processed. +# Format: code points; status # emoji name +# Code points — list of one or more hex code points, separated by spaces +# Status +# component — an Emoji_Component, +# excluding Regional_Indicators, ASCII, and non-Emoji. +# fully-qualified — a fully-qualified emoji (see ED-18 in UTS #51), +# excluding Emoji_Component +# minimally-qualified — a minimally-qualified emoji (see ED-18a in UTS #51) +# unqualified — a unqualified emoji (See ED-19 in UTS #51) +# Notes: +# • This includes the emoji components that need emoji presentation (skin tone and hair) +# when isolated, but omits the components that need not have an emoji +# presentation when isolated. +# • The RGI set is covered by the listed fully-qualified emoji. +# • The listed minimally-qualified and unqualified cover all cases where an +# element of the RGI set is missing one or more emoji presentation selectors. +# • The file is in CLDR order, not codepoint order. This is recommended (but not required!) for keyboard palettes. +# • The groups and subgroups are illustrative. See the Emoji Order chart for more information. + + +# group: Smileys & Emotion + +# subgroup: face-smiling +1F600 ; fully-qualified # 😀 grinning face +1F603 ; fully-qualified # 😃 grinning face with big eyes +1F604 ; fully-qualified # 😄 grinning face with smiling eyes +1F601 ; fully-qualified # 😁 beaming face with smiling eyes +1F606 ; fully-qualified # 😆 grinning squinting face +1F605 ; fully-qualified # 😅 grinning face with sweat +1F923 ; fully-qualified # 🤣 rolling on the floor laughing +1F602 ; fully-qualified # 😂 face with tears of joy +1F642 ; fully-qualified # 🙂 slightly smiling face +1F643 ; fully-qualified # 🙃 upside-down face +1F609 ; fully-qualified # 😉 winking face +1F60A ; fully-qualified # 😊 smiling face with smiling eyes +1F607 ; fully-qualified # 😇 smiling face with halo + +# subgroup: face-affection +1F970 ; fully-qualified # 🥰 smiling face with hearts +1F60D ; fully-qualified # 😍 smiling face with heart-eyes +1F929 ; fully-qualified # 🤩 star-struck +1F618 ; fully-qualified # 😘 face blowing a kiss +1F617 ; fully-qualified # 😗 kissing face +263A FE0F ; fully-qualified # ☺️ smiling face +263A ; unqualified # ☺ smiling face +1F61A ; fully-qualified # 😚 kissing face with closed eyes +1F619 ; fully-qualified # 😙 kissing face with smiling eyes + +# subgroup: face-tongue +1F60B ; fully-qualified # 😋 face savoring food +1F61B ; fully-qualified # 😛 face with tongue +1F61C ; fully-qualified # 😜 winking face with tongue +1F92A ; fully-qualified # 🤪 zany face +1F61D ; fully-qualified # 😝 squinting face with tongue +1F911 ; fully-qualified # 🤑 money-mouth face + +# subgroup: face-hand +1F917 ; fully-qualified # 🤗 hugging face +1F92D ; fully-qualified # 🤭 face with hand over mouth +1F92B ; fully-qualified # 🤫 shushing face +1F914 ; fully-qualified # 🤔 thinking face + +# subgroup: face-neutral-skeptical +1F910 ; fully-qualified # 🤐 zipper-mouth face +1F928 ; fully-qualified # 🤨 face with raised eyebrow +1F610 ; fully-qualified # 😐 neutral face +1F611 ; fully-qualified # 😑 expressionless face +1F636 ; fully-qualified # 😶 face without mouth +1F60F ; fully-qualified # 😏 smirking face +1F612 ; fully-qualified # 😒 unamused face +1F644 ; fully-qualified # 🙄 face with rolling eyes +1F62C ; fully-qualified # 😬 grimacing face +1F925 ; fully-qualified # 🤥 lying face + +# subgroup: face-sleepy +1F60C ; fully-qualified # 😌 relieved face +1F614 ; fully-qualified # 😔 pensive face +1F62A ; fully-qualified # 😪 sleepy face +1F924 ; fully-qualified # 🤤 drooling face +1F634 ; fully-qualified # 😴 sleeping face + +# subgroup: face-unwell +1F637 ; fully-qualified # 😷 face with medical mask +1F912 ; fully-qualified # 🤒 face with thermometer +1F915 ; fully-qualified # 🤕 face with head-bandage +1F922 ; fully-qualified # 🤢 nauseated face +1F92E ; fully-qualified # 🤮 face vomiting +1F927 ; fully-qualified # 🤧 sneezing face +1F975 ; fully-qualified # 🥵 hot face +1F976 ; fully-qualified # 🥶 cold face +1F974 ; fully-qualified # 🥴 woozy face +1F635 ; fully-qualified # 😵 dizzy face +1F92F ; fully-qualified # 🤯 exploding head + +# subgroup: face-hat +1F920 ; fully-qualified # 🤠 cowboy hat face +1F973 ; fully-qualified # 🥳 partying face + +# subgroup: face-glasses +1F60E ; fully-qualified # 😎 smiling face with sunglasses +1F913 ; fully-qualified # 🤓 nerd face +1F9D0 ; fully-qualified # 🧐 face with monocle + +# subgroup: face-concerned +1F615 ; fully-qualified # 😕 confused face +1F61F ; fully-qualified # 😟 worried face +1F641 ; fully-qualified # 🙁 slightly frowning face +2639 FE0F ; fully-qualified # ☹️ frowning face +2639 ; unqualified # ☹ frowning face +1F62E ; fully-qualified # 😮 face with open mouth +1F62F ; fully-qualified # 😯 hushed face +1F632 ; fully-qualified # 😲 astonished face +1F633 ; fully-qualified # 😳 flushed face +1F97A ; fully-qualified # 🥺 pleading face +1F626 ; fully-qualified # 😦 frowning face with open mouth +1F627 ; fully-qualified # 😧 anguished face +1F628 ; fully-qualified # 😨 fearful face +1F630 ; fully-qualified # 😰 anxious face with sweat +1F625 ; fully-qualified # 😥 sad but relieved face +1F622 ; fully-qualified # 😢 crying face +1F62D ; fully-qualified # 😭 loudly crying face +1F631 ; fully-qualified # 😱 face screaming in fear +1F616 ; fully-qualified # 😖 confounded face +1F623 ; fully-qualified # 😣 persevering face +1F61E ; fully-qualified # 😞 disappointed face +1F613 ; fully-qualified # 😓 downcast face with sweat +1F629 ; fully-qualified # 😩 weary face +1F62B ; fully-qualified # 😫 tired face +1F971 ; fully-qualified # 🥱 yawning face + +# subgroup: face-negative +1F624 ; fully-qualified # 😤 face with steam from nose +1F621 ; fully-qualified # 😡 pouting face +1F620 ; fully-qualified # 😠 angry face +1F92C ; fully-qualified # 🤬 face with symbols on mouth +1F608 ; fully-qualified # 😈 smiling face with horns +1F47F ; fully-qualified # 👿 angry face with horns +1F480 ; fully-qualified # 💀 skull +2620 FE0F ; fully-qualified # ☠️ skull and crossbones +2620 ; unqualified # ☠ skull and crossbones + +# subgroup: face-costume +1F4A9 ; fully-qualified # 💩 pile of poo +1F921 ; fully-qualified # 🤡 clown face +1F479 ; fully-qualified # 👹 ogre +1F47A ; fully-qualified # 👺 goblin +1F47B ; fully-qualified # 👻 ghost +1F47D ; fully-qualified # 👽 alien +1F47E ; fully-qualified # 👾 alien monster +1F916 ; fully-qualified # 🤖 robot + +# subgroup: cat-face +1F63A ; fully-qualified # 😺 grinning cat +1F638 ; fully-qualified # 😸 grinning cat with smiling eyes +1F639 ; fully-qualified # 😹 cat with tears of joy +1F63B ; fully-qualified # 😻 smiling cat with heart-eyes +1F63C ; fully-qualified # 😼 cat with wry smile +1F63D ; fully-qualified # 😽 kissing cat +1F640 ; fully-qualified # 🙀 weary cat +1F63F ; fully-qualified # 😿 crying cat +1F63E ; fully-qualified # 😾 pouting cat + +# subgroup: monkey-face +1F648 ; fully-qualified # 🙈 see-no-evil monkey +1F649 ; fully-qualified # 🙉 hear-no-evil monkey +1F64A ; fully-qualified # 🙊 speak-no-evil monkey + +# subgroup: emotion +1F48B ; fully-qualified # 💋 kiss mark +1F48C ; fully-qualified # 💌 love letter +1F498 ; fully-qualified # 💘 heart with arrow +1F49D ; fully-qualified # 💝 heart with ribbon +1F496 ; fully-qualified # 💖 sparkling heart +1F497 ; fully-qualified # 💗 growing heart +1F493 ; fully-qualified # 💓 beating heart +1F49E ; fully-qualified # 💞 revolving hearts +1F495 ; fully-qualified # 💕 two hearts +1F49F ; fully-qualified # 💟 heart decoration +2763 FE0F ; fully-qualified # ❣️ heart exclamation +2763 ; unqualified # ❣ heart exclamation +1F494 ; fully-qualified # 💔 broken heart +2764 FE0F ; fully-qualified # ❤️ red heart +2764 ; unqualified # ❤ red heart +1F9E1 ; fully-qualified # 🧡 orange heart +1F49B ; fully-qualified # 💛 yellow heart +1F49A ; fully-qualified # 💚 green heart +1F499 ; fully-qualified # 💙 blue heart +1F49C ; fully-qualified # 💜 purple heart +1F90E ; fully-qualified # 🤎 brown heart +1F5A4 ; fully-qualified # 🖤 black heart +1F90D ; fully-qualified # 🤍 white heart +1F4AF ; fully-qualified # 💯 hundred points +1F4A2 ; fully-qualified # 💢 anger symbol +1F4A5 ; fully-qualified # 💥 collision +1F4AB ; fully-qualified # 💫 dizzy +1F4A6 ; fully-qualified # 💦 sweat droplets +1F4A8 ; fully-qualified # 💨 dashing away +1F573 FE0F ; fully-qualified # 🕳️ hole +1F573 ; unqualified # 🕳 hole +1F4A3 ; fully-qualified # 💣 bomb +1F4AC ; fully-qualified # 💬 speech balloon +1F441 FE0F 200D 1F5E8 FE0F ; fully-qualified # 👁️‍🗨️ eye in speech bubble +1F441 200D 1F5E8 FE0F ; unqualified # 👁‍🗨️ eye in speech bubble +1F441 FE0F 200D 1F5E8 ; unqualified # 👁️‍🗨 eye in speech bubble +1F441 200D 1F5E8 ; unqualified # 👁‍🗨 eye in speech bubble +1F5E8 FE0F ; fully-qualified # 🗨️ left speech bubble +1F5E8 ; unqualified # 🗨 left speech bubble +1F5EF FE0F ; fully-qualified # 🗯️ right anger bubble +1F5EF ; unqualified # 🗯 right anger bubble +1F4AD ; fully-qualified # 💭 thought balloon +1F4A4 ; fully-qualified # 💤 zzz + +# Smileys & Emotion subtotal: 160 +# Smileys & Emotion subtotal: 160 w/o modifiers + +# group: People & Body + +# subgroup: hand-fingers-open +1F44B ; fully-qualified # 👋 waving hand +1F44B 1F3FB ; fully-qualified # 👋🏻 waving hand: light skin tone +1F44B 1F3FC ; fully-qualified # 👋🏼 waving hand: medium-light skin tone +1F44B 1F3FD ; fully-qualified # 👋🏽 waving hand: medium skin tone +1F44B 1F3FE ; fully-qualified # 👋🏾 waving hand: medium-dark skin tone +1F44B 1F3FF ; fully-qualified # 👋🏿 waving hand: dark skin tone +1F91A ; fully-qualified # 🤚 raised back of hand +1F91A 1F3FB ; fully-qualified # 🤚🏻 raised back of hand: light skin tone +1F91A 1F3FC ; fully-qualified # 🤚🏼 raised back of hand: medium-light skin tone +1F91A 1F3FD ; fully-qualified # 🤚🏽 raised back of hand: medium skin tone +1F91A 1F3FE ; fully-qualified # 🤚🏾 raised back of hand: medium-dark skin tone +1F91A 1F3FF ; fully-qualified # 🤚🏿 raised back of hand: dark skin tone +1F590 FE0F ; fully-qualified # 🖐️ hand with fingers splayed +1F590 ; unqualified # 🖐 hand with fingers splayed +1F590 1F3FB ; fully-qualified # 🖐🏻 hand with fingers splayed: light skin tone +1F590 1F3FC ; fully-qualified # 🖐🏼 hand with fingers splayed: medium-light skin tone +1F590 1F3FD ; fully-qualified # 🖐🏽 hand with fingers splayed: medium skin tone +1F590 1F3FE ; fully-qualified # 🖐🏾 hand with fingers splayed: medium-dark skin tone +1F590 1F3FF ; fully-qualified # 🖐🏿 hand with fingers splayed: dark skin tone +270B ; fully-qualified # ✋ raised hand +270B 1F3FB ; fully-qualified # ✋🏻 raised hand: light skin tone +270B 1F3FC ; fully-qualified # ✋🏼 raised hand: medium-light skin tone +270B 1F3FD ; fully-qualified # ✋🏽 raised hand: medium skin tone +270B 1F3FE ; fully-qualified # ✋🏾 raised hand: medium-dark skin tone +270B 1F3FF ; fully-qualified # ✋🏿 raised hand: dark skin tone +1F596 ; fully-qualified # 🖖 vulcan salute +1F596 1F3FB ; fully-qualified # 🖖🏻 vulcan salute: light skin tone +1F596 1F3FC ; fully-qualified # 🖖🏼 vulcan salute: medium-light skin tone +1F596 1F3FD ; fully-qualified # 🖖🏽 vulcan salute: medium skin tone +1F596 1F3FE ; fully-qualified # 🖖🏾 vulcan salute: medium-dark skin tone +1F596 1F3FF ; fully-qualified # 🖖🏿 vulcan salute: dark skin tone + +# subgroup: hand-fingers-partial +1F44C ; fully-qualified # 👌 OK hand +1F44C 1F3FB ; fully-qualified # 👌🏻 OK hand: light skin tone +1F44C 1F3FC ; fully-qualified # 👌🏼 OK hand: medium-light skin tone +1F44C 1F3FD ; fully-qualified # 👌🏽 OK hand: medium skin tone +1F44C 1F3FE ; fully-qualified # 👌🏾 OK hand: medium-dark skin tone +1F44C 1F3FF ; fully-qualified # 👌🏿 OK hand: dark skin tone +1F90F ; fully-qualified # 🤏 pinching hand +1F90F 1F3FB ; fully-qualified # 🤏🏻 pinching hand: light skin tone +1F90F 1F3FC ; fully-qualified # 🤏🏼 pinching hand: medium-light skin tone +1F90F 1F3FD ; fully-qualified # 🤏🏽 pinching hand: medium skin tone +1F90F 1F3FE ; fully-qualified # 🤏🏾 pinching hand: medium-dark skin tone +1F90F 1F3FF ; fully-qualified # 🤏🏿 pinching hand: dark skin tone +270C FE0F ; fully-qualified # ✌️ victory hand +270C ; unqualified # ✌ victory hand +270C 1F3FB ; fully-qualified # ✌🏻 victory hand: light skin tone +270C 1F3FC ; fully-qualified # ✌🏼 victory hand: medium-light skin tone +270C 1F3FD ; fully-qualified # ✌🏽 victory hand: medium skin tone +270C 1F3FE ; fully-qualified # ✌🏾 victory hand: medium-dark skin tone +270C 1F3FF ; fully-qualified # ✌🏿 victory hand: dark skin tone +1F91E ; fully-qualified # 🤞 crossed fingers +1F91E 1F3FB ; fully-qualified # 🤞🏻 crossed fingers: light skin tone +1F91E 1F3FC ; fully-qualified # 🤞🏼 crossed fingers: medium-light skin tone +1F91E 1F3FD ; fully-qualified # 🤞🏽 crossed fingers: medium skin tone +1F91E 1F3FE ; fully-qualified # 🤞🏾 crossed fingers: medium-dark skin tone +1F91E 1F3FF ; fully-qualified # 🤞🏿 crossed fingers: dark skin tone +1F91F ; fully-qualified # 🤟 love-you gesture +1F91F 1F3FB ; fully-qualified # 🤟🏻 love-you gesture: light skin tone +1F91F 1F3FC ; fully-qualified # 🤟🏼 love-you gesture: medium-light skin tone +1F91F 1F3FD ; fully-qualified # 🤟🏽 love-you gesture: medium skin tone +1F91F 1F3FE ; fully-qualified # 🤟🏾 love-you gesture: medium-dark skin tone +1F91F 1F3FF ; fully-qualified # 🤟🏿 love-you gesture: dark skin tone +1F918 ; fully-qualified # 🤘 sign of the horns +1F918 1F3FB ; fully-qualified # 🤘🏻 sign of the horns: light skin tone +1F918 1F3FC ; fully-qualified # 🤘🏼 sign of the horns: medium-light skin tone +1F918 1F3FD ; fully-qualified # 🤘🏽 sign of the horns: medium skin tone +1F918 1F3FE ; fully-qualified # 🤘🏾 sign of the horns: medium-dark skin tone +1F918 1F3FF ; fully-qualified # 🤘🏿 sign of the horns: dark skin tone +1F919 ; fully-qualified # 🤙 call me hand +1F919 1F3FB ; fully-qualified # 🤙🏻 call me hand: light skin tone +1F919 1F3FC ; fully-qualified # 🤙🏼 call me hand: medium-light skin tone +1F919 1F3FD ; fully-qualified # 🤙🏽 call me hand: medium skin tone +1F919 1F3FE ; fully-qualified # 🤙🏾 call me hand: medium-dark skin tone +1F919 1F3FF ; fully-qualified # 🤙🏿 call me hand: dark skin tone + +# subgroup: hand-single-finger +1F448 ; fully-qualified # 👈 backhand index pointing left +1F448 1F3FB ; fully-qualified # 👈🏻 backhand index pointing left: light skin tone +1F448 1F3FC ; fully-qualified # 👈🏼 backhand index pointing left: medium-light skin tone +1F448 1F3FD ; fully-qualified # 👈🏽 backhand index pointing left: medium skin tone +1F448 1F3FE ; fully-qualified # 👈🏾 backhand index pointing left: medium-dark skin tone +1F448 1F3FF ; fully-qualified # 👈🏿 backhand index pointing left: dark skin tone +1F449 ; fully-qualified # 👉 backhand index pointing right +1F449 1F3FB ; fully-qualified # 👉🏻 backhand index pointing right: light skin tone +1F449 1F3FC ; fully-qualified # 👉🏼 backhand index pointing right: medium-light skin tone +1F449 1F3FD ; fully-qualified # 👉🏽 backhand index pointing right: medium skin tone +1F449 1F3FE ; fully-qualified # 👉🏾 backhand index pointing right: medium-dark skin tone +1F449 1F3FF ; fully-qualified # 👉🏿 backhand index pointing right: dark skin tone +1F446 ; fully-qualified # 👆 backhand index pointing up +1F446 1F3FB ; fully-qualified # 👆🏻 backhand index pointing up: light skin tone +1F446 1F3FC ; fully-qualified # 👆🏼 backhand index pointing up: medium-light skin tone +1F446 1F3FD ; fully-qualified # 👆🏽 backhand index pointing up: medium skin tone +1F446 1F3FE ; fully-qualified # 👆🏾 backhand index pointing up: medium-dark skin tone +1F446 1F3FF ; fully-qualified # 👆🏿 backhand index pointing up: dark skin tone +1F595 ; fully-qualified # 🖕 middle finger +1F595 1F3FB ; fully-qualified # 🖕🏻 middle finger: light skin tone +1F595 1F3FC ; fully-qualified # 🖕🏼 middle finger: medium-light skin tone +1F595 1F3FD ; fully-qualified # 🖕🏽 middle finger: medium skin tone +1F595 1F3FE ; fully-qualified # 🖕🏾 middle finger: medium-dark skin tone +1F595 1F3FF ; fully-qualified # 🖕🏿 middle finger: dark skin tone +1F447 ; fully-qualified # 👇 backhand index pointing down +1F447 1F3FB ; fully-qualified # 👇🏻 backhand index pointing down: light skin tone +1F447 1F3FC ; fully-qualified # 👇🏼 backhand index pointing down: medium-light skin tone +1F447 1F3FD ; fully-qualified # 👇🏽 backhand index pointing down: medium skin tone +1F447 1F3FE ; fully-qualified # 👇🏾 backhand index pointing down: medium-dark skin tone +1F447 1F3FF ; fully-qualified # 👇🏿 backhand index pointing down: dark skin tone +261D FE0F ; fully-qualified # ☝️ index pointing up +261D ; unqualified # ☝ index pointing up +261D 1F3FB ; fully-qualified # ☝🏻 index pointing up: light skin tone +261D 1F3FC ; fully-qualified # ☝🏼 index pointing up: medium-light skin tone +261D 1F3FD ; fully-qualified # ☝🏽 index pointing up: medium skin tone +261D 1F3FE ; fully-qualified # ☝🏾 index pointing up: medium-dark skin tone +261D 1F3FF ; fully-qualified # ☝🏿 index pointing up: dark skin tone + +# subgroup: hand-fingers-closed +1F44D ; fully-qualified # 👍 thumbs up +1F44D 1F3FB ; fully-qualified # 👍🏻 thumbs up: light skin tone +1F44D 1F3FC ; fully-qualified # 👍🏼 thumbs up: medium-light skin tone +1F44D 1F3FD ; fully-qualified # 👍🏽 thumbs up: medium skin tone +1F44D 1F3FE ; fully-qualified # 👍🏾 thumbs up: medium-dark skin tone +1F44D 1F3FF ; fully-qualified # 👍🏿 thumbs up: dark skin tone +1F44E ; fully-qualified # 👎 thumbs down +1F44E 1F3FB ; fully-qualified # 👎🏻 thumbs down: light skin tone +1F44E 1F3FC ; fully-qualified # 👎🏼 thumbs down: medium-light skin tone +1F44E 1F3FD ; fully-qualified # 👎🏽 thumbs down: medium skin tone +1F44E 1F3FE ; fully-qualified # 👎🏾 thumbs down: medium-dark skin tone +1F44E 1F3FF ; fully-qualified # 👎🏿 thumbs down: dark skin tone +270A ; fully-qualified # ✊ raised fist +270A 1F3FB ; fully-qualified # ✊🏻 raised fist: light skin tone +270A 1F3FC ; fully-qualified # ✊🏼 raised fist: medium-light skin tone +270A 1F3FD ; fully-qualified # ✊🏽 raised fist: medium skin tone +270A 1F3FE ; fully-qualified # ✊🏾 raised fist: medium-dark skin tone +270A 1F3FF ; fully-qualified # ✊🏿 raised fist: dark skin tone +1F44A ; fully-qualified # 👊 oncoming fist +1F44A 1F3FB ; fully-qualified # 👊🏻 oncoming fist: light skin tone +1F44A 1F3FC ; fully-qualified # 👊🏼 oncoming fist: medium-light skin tone +1F44A 1F3FD ; fully-qualified # 👊🏽 oncoming fist: medium skin tone +1F44A 1F3FE ; fully-qualified # 👊🏾 oncoming fist: medium-dark skin tone +1F44A 1F3FF ; fully-qualified # 👊🏿 oncoming fist: dark skin tone +1F91B ; fully-qualified # 🤛 left-facing fist +1F91B 1F3FB ; fully-qualified # 🤛🏻 left-facing fist: light skin tone +1F91B 1F3FC ; fully-qualified # 🤛🏼 left-facing fist: medium-light skin tone +1F91B 1F3FD ; fully-qualified # 🤛🏽 left-facing fist: medium skin tone +1F91B 1F3FE ; fully-qualified # 🤛🏾 left-facing fist: medium-dark skin tone +1F91B 1F3FF ; fully-qualified # 🤛🏿 left-facing fist: dark skin tone +1F91C ; fully-qualified # 🤜 right-facing fist +1F91C 1F3FB ; fully-qualified # 🤜🏻 right-facing fist: light skin tone +1F91C 1F3FC ; fully-qualified # 🤜🏼 right-facing fist: medium-light skin tone +1F91C 1F3FD ; fully-qualified # 🤜🏽 right-facing fist: medium skin tone +1F91C 1F3FE ; fully-qualified # 🤜🏾 right-facing fist: medium-dark skin tone +1F91C 1F3FF ; fully-qualified # 🤜🏿 right-facing fist: dark skin tone + +# subgroup: hands +1F44F ; fully-qualified # 👏 clapping hands +1F44F 1F3FB ; fully-qualified # 👏🏻 clapping hands: light skin tone +1F44F 1F3FC ; fully-qualified # 👏🏼 clapping hands: medium-light skin tone +1F44F 1F3FD ; fully-qualified # 👏🏽 clapping hands: medium skin tone +1F44F 1F3FE ; fully-qualified # 👏🏾 clapping hands: medium-dark skin tone +1F44F 1F3FF ; fully-qualified # 👏🏿 clapping hands: dark skin tone +1F64C ; fully-qualified # 🙌 raising hands +1F64C 1F3FB ; fully-qualified # 🙌🏻 raising hands: light skin tone +1F64C 1F3FC ; fully-qualified # 🙌🏼 raising hands: medium-light skin tone +1F64C 1F3FD ; fully-qualified # 🙌🏽 raising hands: medium skin tone +1F64C 1F3FE ; fully-qualified # 🙌🏾 raising hands: medium-dark skin tone +1F64C 1F3FF ; fully-qualified # 🙌🏿 raising hands: dark skin tone +1F450 ; fully-qualified # 👐 open hands +1F450 1F3FB ; fully-qualified # 👐🏻 open hands: light skin tone +1F450 1F3FC ; fully-qualified # 👐🏼 open hands: medium-light skin tone +1F450 1F3FD ; fully-qualified # 👐🏽 open hands: medium skin tone +1F450 1F3FE ; fully-qualified # 👐🏾 open hands: medium-dark skin tone +1F450 1F3FF ; fully-qualified # 👐🏿 open hands: dark skin tone +1F932 ; fully-qualified # 🤲 palms up together +1F932 1F3FB ; fully-qualified # 🤲🏻 palms up together: light skin tone +1F932 1F3FC ; fully-qualified # 🤲🏼 palms up together: medium-light skin tone +1F932 1F3FD ; fully-qualified # 🤲🏽 palms up together: medium skin tone +1F932 1F3FE ; fully-qualified # 🤲🏾 palms up together: medium-dark skin tone +1F932 1F3FF ; fully-qualified # 🤲🏿 palms up together: dark skin tone +1F91D ; fully-qualified # 🤝 handshake +1F64F ; fully-qualified # 🙏 folded hands +1F64F 1F3FB ; fully-qualified # 🙏🏻 folded hands: light skin tone +1F64F 1F3FC ; fully-qualified # 🙏🏼 folded hands: medium-light skin tone +1F64F 1F3FD ; fully-qualified # 🙏🏽 folded hands: medium skin tone +1F64F 1F3FE ; fully-qualified # 🙏🏾 folded hands: medium-dark skin tone +1F64F 1F3FF ; fully-qualified # 🙏🏿 folded hands: dark skin tone + +# subgroup: hand-prop +270D FE0F ; fully-qualified # ✍️ writing hand +270D ; unqualified # ✍ writing hand +270D 1F3FB ; fully-qualified # ✍🏻 writing hand: light skin tone +270D 1F3FC ; fully-qualified # ✍🏼 writing hand: medium-light skin tone +270D 1F3FD ; fully-qualified # ✍🏽 writing hand: medium skin tone +270D 1F3FE ; fully-qualified # ✍🏾 writing hand: medium-dark skin tone +270D 1F3FF ; fully-qualified # ✍🏿 writing hand: dark skin tone +1F485 ; fully-qualified # 💅 nail polish +1F485 1F3FB ; fully-qualified # 💅🏻 nail polish: light skin tone +1F485 1F3FC ; fully-qualified # 💅🏼 nail polish: medium-light skin tone +1F485 1F3FD ; fully-qualified # 💅🏽 nail polish: medium skin tone +1F485 1F3FE ; fully-qualified # 💅🏾 nail polish: medium-dark skin tone +1F485 1F3FF ; fully-qualified # 💅🏿 nail polish: dark skin tone +1F933 ; fully-qualified # 🤳 selfie +1F933 1F3FB ; fully-qualified # 🤳🏻 selfie: light skin tone +1F933 1F3FC ; fully-qualified # 🤳🏼 selfie: medium-light skin tone +1F933 1F3FD ; fully-qualified # 🤳🏽 selfie: medium skin tone +1F933 1F3FE ; fully-qualified # 🤳🏾 selfie: medium-dark skin tone +1F933 1F3FF ; fully-qualified # 🤳🏿 selfie: dark skin tone + +# subgroup: body-parts +1F4AA ; fully-qualified # 💪 flexed biceps +1F4AA 1F3FB ; fully-qualified # 💪🏻 flexed biceps: light skin tone +1F4AA 1F3FC ; fully-qualified # 💪🏼 flexed biceps: medium-light skin tone +1F4AA 1F3FD ; fully-qualified # 💪🏽 flexed biceps: medium skin tone +1F4AA 1F3FE ; fully-qualified # 💪🏾 flexed biceps: medium-dark skin tone +1F4AA 1F3FF ; fully-qualified # 💪🏿 flexed biceps: dark skin tone +1F9BE ; fully-qualified # 🦾 mechanical arm +1F9BF ; fully-qualified # 🦿 mechanical leg +1F9B5 ; fully-qualified # 🦵 leg +1F9B5 1F3FB ; fully-qualified # 🦵🏻 leg: light skin tone +1F9B5 1F3FC ; fully-qualified # 🦵🏼 leg: medium-light skin tone +1F9B5 1F3FD ; fully-qualified # 🦵🏽 leg: medium skin tone +1F9B5 1F3FE ; fully-qualified # 🦵🏾 leg: medium-dark skin tone +1F9B5 1F3FF ; fully-qualified # 🦵🏿 leg: dark skin tone +1F9B6 ; fully-qualified # 🦶 foot +1F9B6 1F3FB ; fully-qualified # 🦶🏻 foot: light skin tone +1F9B6 1F3FC ; fully-qualified # 🦶🏼 foot: medium-light skin tone +1F9B6 1F3FD ; fully-qualified # 🦶🏽 foot: medium skin tone +1F9B6 1F3FE ; fully-qualified # 🦶🏾 foot: medium-dark skin tone +1F9B6 1F3FF ; fully-qualified # 🦶🏿 foot: dark skin tone +1F442 ; fully-qualified # 👂 ear +1F442 1F3FB ; fully-qualified # 👂🏻 ear: light skin tone +1F442 1F3FC ; fully-qualified # 👂🏼 ear: medium-light skin tone +1F442 1F3FD ; fully-qualified # 👂🏽 ear: medium skin tone +1F442 1F3FE ; fully-qualified # 👂🏾 ear: medium-dark skin tone +1F442 1F3FF ; fully-qualified # 👂🏿 ear: dark skin tone +1F9BB ; fully-qualified # 🦻 ear with hearing aid +1F9BB 1F3FB ; fully-qualified # 🦻🏻 ear with hearing aid: light skin tone +1F9BB 1F3FC ; fully-qualified # 🦻🏼 ear with hearing aid: medium-light skin tone +1F9BB 1F3FD ; fully-qualified # 🦻🏽 ear with hearing aid: medium skin tone +1F9BB 1F3FE ; fully-qualified # 🦻🏾 ear with hearing aid: medium-dark skin tone +1F9BB 1F3FF ; fully-qualified # 🦻🏿 ear with hearing aid: dark skin tone +1F443 ; fully-qualified # 👃 nose +1F443 1F3FB ; fully-qualified # 👃🏻 nose: light skin tone +1F443 1F3FC ; fully-qualified # 👃🏼 nose: medium-light skin tone +1F443 1F3FD ; fully-qualified # 👃🏽 nose: medium skin tone +1F443 1F3FE ; fully-qualified # 👃🏾 nose: medium-dark skin tone +1F443 1F3FF ; fully-qualified # 👃🏿 nose: dark skin tone +1F9E0 ; fully-qualified # 🧠 brain +1F9B7 ; fully-qualified # 🦷 tooth +1F9B4 ; fully-qualified # 🦴 bone +1F440 ; fully-qualified # 👀 eyes +1F441 FE0F ; fully-qualified # 👁️ eye +1F441 ; unqualified # 👁 eye +1F445 ; fully-qualified # 👅 tongue +1F444 ; fully-qualified # 👄 mouth + +# subgroup: person +1F476 ; fully-qualified # 👶 baby +1F476 1F3FB ; fully-qualified # 👶🏻 baby: light skin tone +1F476 1F3FC ; fully-qualified # 👶🏼 baby: medium-light skin tone +1F476 1F3FD ; fully-qualified # 👶🏽 baby: medium skin tone +1F476 1F3FE ; fully-qualified # 👶🏾 baby: medium-dark skin tone +1F476 1F3FF ; fully-qualified # 👶🏿 baby: dark skin tone +1F9D2 ; fully-qualified # 🧒 child +1F9D2 1F3FB ; fully-qualified # 🧒🏻 child: light skin tone +1F9D2 1F3FC ; fully-qualified # 🧒🏼 child: medium-light skin tone +1F9D2 1F3FD ; fully-qualified # 🧒🏽 child: medium skin tone +1F9D2 1F3FE ; fully-qualified # 🧒🏾 child: medium-dark skin tone +1F9D2 1F3FF ; fully-qualified # 🧒🏿 child: dark skin tone +1F466 ; fully-qualified # 👦 boy +1F466 1F3FB ; fully-qualified # 👦🏻 boy: light skin tone +1F466 1F3FC ; fully-qualified # 👦🏼 boy: medium-light skin tone +1F466 1F3FD ; fully-qualified # 👦🏽 boy: medium skin tone +1F466 1F3FE ; fully-qualified # 👦🏾 boy: medium-dark skin tone +1F466 1F3FF ; fully-qualified # 👦🏿 boy: dark skin tone +1F467 ; fully-qualified # 👧 girl +1F467 1F3FB ; fully-qualified # 👧🏻 girl: light skin tone +1F467 1F3FC ; fully-qualified # 👧🏼 girl: medium-light skin tone +1F467 1F3FD ; fully-qualified # 👧🏽 girl: medium skin tone +1F467 1F3FE ; fully-qualified # 👧🏾 girl: medium-dark skin tone +1F467 1F3FF ; fully-qualified # 👧🏿 girl: dark skin tone +1F9D1 ; fully-qualified # 🧑 person +1F9D1 1F3FB ; fully-qualified # 🧑🏻 person: light skin tone +1F9D1 1F3FC ; fully-qualified # 🧑🏼 person: medium-light skin tone +1F9D1 1F3FD ; fully-qualified # 🧑🏽 person: medium skin tone +1F9D1 1F3FE ; fully-qualified # 🧑🏾 person: medium-dark skin tone +1F9D1 1F3FF ; fully-qualified # 🧑🏿 person: dark skin tone +1F471 ; fully-qualified # 👱 person: blond hair +1F471 1F3FB ; fully-qualified # 👱🏻 person: light skin tone, blond hair +1F471 1F3FC ; fully-qualified # 👱🏼 person: medium-light skin tone, blond hair +1F471 1F3FD ; fully-qualified # 👱🏽 person: medium skin tone, blond hair +1F471 1F3FE ; fully-qualified # 👱🏾 person: medium-dark skin tone, blond hair +1F471 1F3FF ; fully-qualified # 👱🏿 person: dark skin tone, blond hair +1F468 ; fully-qualified # 👨 man +1F468 1F3FB ; fully-qualified # 👨🏻 man: light skin tone +1F468 1F3FC ; fully-qualified # 👨🏼 man: medium-light skin tone +1F468 1F3FD ; fully-qualified # 👨🏽 man: medium skin tone +1F468 1F3FE ; fully-qualified # 👨🏾 man: medium-dark skin tone +1F468 1F3FF ; fully-qualified # 👨🏿 man: dark skin tone +1F9D4 ; fully-qualified # 🧔 man: beard +1F9D4 1F3FB ; fully-qualified # 🧔🏻 man: light skin tone, beard +1F9D4 1F3FC ; fully-qualified # 🧔🏼 man: medium-light skin tone, beard +1F9D4 1F3FD ; fully-qualified # 🧔🏽 man: medium skin tone, beard +1F9D4 1F3FE ; fully-qualified # 🧔🏾 man: medium-dark skin tone, beard +1F9D4 1F3FF ; fully-qualified # 🧔🏿 man: dark skin tone, beard +1F471 200D 2642 FE0F ; fully-qualified # 👱‍♂️ man: blond hair +1F471 200D 2642 ; minimally-qualified # 👱‍♂ man: blond hair +1F471 1F3FB 200D 2642 FE0F ; fully-qualified # 👱🏻‍♂️ man: light skin tone, blond hair +1F471 1F3FB 200D 2642 ; minimally-qualified # 👱🏻‍♂ man: light skin tone, blond hair +1F471 1F3FC 200D 2642 FE0F ; fully-qualified # 👱🏼‍♂️ man: medium-light skin tone, blond hair +1F471 1F3FC 200D 2642 ; minimally-qualified # 👱🏼‍♂ man: medium-light skin tone, blond hair +1F471 1F3FD 200D 2642 FE0F ; fully-qualified # 👱🏽‍♂️ man: medium skin tone, blond hair +1F471 1F3FD 200D 2642 ; minimally-qualified # 👱🏽‍♂ man: medium skin tone, blond hair +1F471 1F3FE 200D 2642 FE0F ; fully-qualified # 👱🏾‍♂️ man: medium-dark skin tone, blond hair +1F471 1F3FE 200D 2642 ; minimally-qualified # 👱🏾‍♂ man: medium-dark skin tone, blond hair +1F471 1F3FF 200D 2642 FE0F ; fully-qualified # 👱🏿‍♂️ man: dark skin tone, blond hair +1F471 1F3FF 200D 2642 ; minimally-qualified # 👱🏿‍♂ man: dark skin tone, blond hair +1F468 200D 1F9B0 ; fully-qualified # 👨‍🦰 man: red hair +1F468 1F3FB 200D 1F9B0 ; fully-qualified # 👨🏻‍🦰 man: light skin tone, red hair +1F468 1F3FC 200D 1F9B0 ; fully-qualified # 👨🏼‍🦰 man: medium-light skin tone, red hair +1F468 1F3FD 200D 1F9B0 ; fully-qualified # 👨🏽‍🦰 man: medium skin tone, red hair +1F468 1F3FE 200D 1F9B0 ; fully-qualified # 👨🏾‍🦰 man: medium-dark skin tone, red hair +1F468 1F3FF 200D 1F9B0 ; fully-qualified # 👨🏿‍🦰 man: dark skin tone, red hair +1F468 200D 1F9B1 ; fully-qualified # 👨‍🦱 man: curly hair +1F468 1F3FB 200D 1F9B1 ; fully-qualified # 👨🏻‍🦱 man: light skin tone, curly hair +1F468 1F3FC 200D 1F9B1 ; fully-qualified # 👨🏼‍🦱 man: medium-light skin tone, curly hair +1F468 1F3FD 200D 1F9B1 ; fully-qualified # 👨🏽‍🦱 man: medium skin tone, curly hair +1F468 1F3FE 200D 1F9B1 ; fully-qualified # 👨🏾‍🦱 man: medium-dark skin tone, curly hair +1F468 1F3FF 200D 1F9B1 ; fully-qualified # 👨🏿‍🦱 man: dark skin tone, curly hair +1F468 200D 1F9B3 ; fully-qualified # 👨‍🦳 man: white hair +1F468 1F3FB 200D 1F9B3 ; fully-qualified # 👨🏻‍🦳 man: light skin tone, white hair +1F468 1F3FC 200D 1F9B3 ; fully-qualified # 👨🏼‍🦳 man: medium-light skin tone, white hair +1F468 1F3FD 200D 1F9B3 ; fully-qualified # 👨🏽‍🦳 man: medium skin tone, white hair +1F468 1F3FE 200D 1F9B3 ; fully-qualified # 👨🏾‍🦳 man: medium-dark skin tone, white hair +1F468 1F3FF 200D 1F9B3 ; fully-qualified # 👨🏿‍🦳 man: dark skin tone, white hair +1F468 200D 1F9B2 ; fully-qualified # 👨‍🦲 man: bald +1F468 1F3FB 200D 1F9B2 ; fully-qualified # 👨🏻‍🦲 man: light skin tone, bald +1F468 1F3FC 200D 1F9B2 ; fully-qualified # 👨🏼‍🦲 man: medium-light skin tone, bald +1F468 1F3FD 200D 1F9B2 ; fully-qualified # 👨🏽‍🦲 man: medium skin tone, bald +1F468 1F3FE 200D 1F9B2 ; fully-qualified # 👨🏾‍🦲 man: medium-dark skin tone, bald +1F468 1F3FF 200D 1F9B2 ; fully-qualified # 👨🏿‍🦲 man: dark skin tone, bald +1F469 ; fully-qualified # 👩 woman +1F469 1F3FB ; fully-qualified # 👩🏻 woman: light skin tone +1F469 1F3FC ; fully-qualified # 👩🏼 woman: medium-light skin tone +1F469 1F3FD ; fully-qualified # 👩🏽 woman: medium skin tone +1F469 1F3FE ; fully-qualified # 👩🏾 woman: medium-dark skin tone +1F469 1F3FF ; fully-qualified # 👩🏿 woman: dark skin tone +1F471 200D 2640 FE0F ; fully-qualified # 👱‍♀️ woman: blond hair +1F471 200D 2640 ; minimally-qualified # 👱‍♀ woman: blond hair +1F471 1F3FB 200D 2640 FE0F ; fully-qualified # 👱🏻‍♀️ woman: light skin tone, blond hair +1F471 1F3FB 200D 2640 ; minimally-qualified # 👱🏻‍♀ woman: light skin tone, blond hair +1F471 1F3FC 200D 2640 FE0F ; fully-qualified # 👱🏼‍♀️ woman: medium-light skin tone, blond hair +1F471 1F3FC 200D 2640 ; minimally-qualified # 👱🏼‍♀ woman: medium-light skin tone, blond hair +1F471 1F3FD 200D 2640 FE0F ; fully-qualified # 👱🏽‍♀️ woman: medium skin tone, blond hair +1F471 1F3FD 200D 2640 ; minimally-qualified # 👱🏽‍♀ woman: medium skin tone, blond hair +1F471 1F3FE 200D 2640 FE0F ; fully-qualified # 👱🏾‍♀️ woman: medium-dark skin tone, blond hair +1F471 1F3FE 200D 2640 ; minimally-qualified # 👱🏾‍♀ woman: medium-dark skin tone, blond hair +1F471 1F3FF 200D 2640 FE0F ; fully-qualified # 👱🏿‍♀️ woman: dark skin tone, blond hair +1F471 1F3FF 200D 2640 ; minimally-qualified # 👱🏿‍♀ woman: dark skin tone, blond hair +1F469 200D 1F9B0 ; fully-qualified # 👩‍🦰 woman: red hair +1F469 1F3FB 200D 1F9B0 ; fully-qualified # 👩🏻‍🦰 woman: light skin tone, red hair +1F469 1F3FC 200D 1F9B0 ; fully-qualified # 👩🏼‍🦰 woman: medium-light skin tone, red hair +1F469 1F3FD 200D 1F9B0 ; fully-qualified # 👩🏽‍🦰 woman: medium skin tone, red hair +1F469 1F3FE 200D 1F9B0 ; fully-qualified # 👩🏾‍🦰 woman: medium-dark skin tone, red hair +1F469 1F3FF 200D 1F9B0 ; fully-qualified # 👩🏿‍🦰 woman: dark skin tone, red hair +1F469 200D 1F9B1 ; fully-qualified # 👩‍🦱 woman: curly hair +1F469 1F3FB 200D 1F9B1 ; fully-qualified # 👩🏻‍🦱 woman: light skin tone, curly hair +1F469 1F3FC 200D 1F9B1 ; fully-qualified # 👩🏼‍🦱 woman: medium-light skin tone, curly hair +1F469 1F3FD 200D 1F9B1 ; fully-qualified # 👩🏽‍🦱 woman: medium skin tone, curly hair +1F469 1F3FE 200D 1F9B1 ; fully-qualified # 👩🏾‍🦱 woman: medium-dark skin tone, curly hair +1F469 1F3FF 200D 1F9B1 ; fully-qualified # 👩🏿‍🦱 woman: dark skin tone, curly hair +1F469 200D 1F9B3 ; fully-qualified # 👩‍🦳 woman: white hair +1F469 1F3FB 200D 1F9B3 ; fully-qualified # 👩🏻‍🦳 woman: light skin tone, white hair +1F469 1F3FC 200D 1F9B3 ; fully-qualified # 👩🏼‍🦳 woman: medium-light skin tone, white hair +1F469 1F3FD 200D 1F9B3 ; fully-qualified # 👩🏽‍🦳 woman: medium skin tone, white hair +1F469 1F3FE 200D 1F9B3 ; fully-qualified # 👩🏾‍🦳 woman: medium-dark skin tone, white hair +1F469 1F3FF 200D 1F9B3 ; fully-qualified # 👩🏿‍🦳 woman: dark skin tone, white hair +1F469 200D 1F9B2 ; fully-qualified # 👩‍🦲 woman: bald +1F469 1F3FB 200D 1F9B2 ; fully-qualified # 👩🏻‍🦲 woman: light skin tone, bald +1F469 1F3FC 200D 1F9B2 ; fully-qualified # 👩🏼‍🦲 woman: medium-light skin tone, bald +1F469 1F3FD 200D 1F9B2 ; fully-qualified # 👩🏽‍🦲 woman: medium skin tone, bald +1F469 1F3FE 200D 1F9B2 ; fully-qualified # 👩🏾‍🦲 woman: medium-dark skin tone, bald +1F469 1F3FF 200D 1F9B2 ; fully-qualified # 👩🏿‍🦲 woman: dark skin tone, bald +1F9D3 ; fully-qualified # 🧓 older person +1F9D3 1F3FB ; fully-qualified # 🧓🏻 older person: light skin tone +1F9D3 1F3FC ; fully-qualified # 🧓🏼 older person: medium-light skin tone +1F9D3 1F3FD ; fully-qualified # 🧓🏽 older person: medium skin tone +1F9D3 1F3FE ; fully-qualified # 🧓🏾 older person: medium-dark skin tone +1F9D3 1F3FF ; fully-qualified # 🧓🏿 older person: dark skin tone +1F474 ; fully-qualified # 👴 old man +1F474 1F3FB ; fully-qualified # 👴🏻 old man: light skin tone +1F474 1F3FC ; fully-qualified # 👴🏼 old man: medium-light skin tone +1F474 1F3FD ; fully-qualified # 👴🏽 old man: medium skin tone +1F474 1F3FE ; fully-qualified # 👴🏾 old man: medium-dark skin tone +1F474 1F3FF ; fully-qualified # 👴🏿 old man: dark skin tone +1F475 ; fully-qualified # 👵 old woman +1F475 1F3FB ; fully-qualified # 👵🏻 old woman: light skin tone +1F475 1F3FC ; fully-qualified # 👵🏼 old woman: medium-light skin tone +1F475 1F3FD ; fully-qualified # 👵🏽 old woman: medium skin tone +1F475 1F3FE ; fully-qualified # 👵🏾 old woman: medium-dark skin tone +1F475 1F3FF ; fully-qualified # 👵🏿 old woman: dark skin tone + +# subgroup: person-gesture +1F64D ; fully-qualified # 🙍 person frowning +1F64D 1F3FB ; fully-qualified # 🙍🏻 person frowning: light skin tone +1F64D 1F3FC ; fully-qualified # 🙍🏼 person frowning: medium-light skin tone +1F64D 1F3FD ; fully-qualified # 🙍🏽 person frowning: medium skin tone +1F64D 1F3FE ; fully-qualified # 🙍🏾 person frowning: medium-dark skin tone +1F64D 1F3FF ; fully-qualified # 🙍🏿 person frowning: dark skin tone +1F64D 200D 2642 FE0F ; fully-qualified # 🙍‍♂️ man frowning +1F64D 200D 2642 ; minimally-qualified # 🙍‍♂ man frowning +1F64D 1F3FB 200D 2642 FE0F ; fully-qualified # 🙍🏻‍♂️ man frowning: light skin tone +1F64D 1F3FB 200D 2642 ; minimally-qualified # 🙍🏻‍♂ man frowning: light skin tone +1F64D 1F3FC 200D 2642 FE0F ; fully-qualified # 🙍🏼‍♂️ man frowning: medium-light skin tone +1F64D 1F3FC 200D 2642 ; minimally-qualified # 🙍🏼‍♂ man frowning: medium-light skin tone +1F64D 1F3FD 200D 2642 FE0F ; fully-qualified # 🙍🏽‍♂️ man frowning: medium skin tone +1F64D 1F3FD 200D 2642 ; minimally-qualified # 🙍🏽‍♂ man frowning: medium skin tone +1F64D 1F3FE 200D 2642 FE0F ; fully-qualified # 🙍🏾‍♂️ man frowning: medium-dark skin tone +1F64D 1F3FE 200D 2642 ; minimally-qualified # 🙍🏾‍♂ man frowning: medium-dark skin tone +1F64D 1F3FF 200D 2642 FE0F ; fully-qualified # 🙍🏿‍♂️ man frowning: dark skin tone +1F64D 1F3FF 200D 2642 ; minimally-qualified # 🙍🏿‍♂ man frowning: dark skin tone +1F64D 200D 2640 FE0F ; fully-qualified # 🙍‍♀️ woman frowning +1F64D 200D 2640 ; minimally-qualified # 🙍‍♀ woman frowning +1F64D 1F3FB 200D 2640 FE0F ; fully-qualified # 🙍🏻‍♀️ woman frowning: light skin tone +1F64D 1F3FB 200D 2640 ; minimally-qualified # 🙍🏻‍♀ woman frowning: light skin tone +1F64D 1F3FC 200D 2640 FE0F ; fully-qualified # 🙍🏼‍♀️ woman frowning: medium-light skin tone +1F64D 1F3FC 200D 2640 ; minimally-qualified # 🙍🏼‍♀ woman frowning: medium-light skin tone +1F64D 1F3FD 200D 2640 FE0F ; fully-qualified # 🙍🏽‍♀️ woman frowning: medium skin tone +1F64D 1F3FD 200D 2640 ; minimally-qualified # 🙍🏽‍♀ woman frowning: medium skin tone +1F64D 1F3FE 200D 2640 FE0F ; fully-qualified # 🙍🏾‍♀️ woman frowning: medium-dark skin tone +1F64D 1F3FE 200D 2640 ; minimally-qualified # 🙍🏾‍♀ woman frowning: medium-dark skin tone +1F64D 1F3FF 200D 2640 FE0F ; fully-qualified # 🙍🏿‍♀️ woman frowning: dark skin tone +1F64D 1F3FF 200D 2640 ; minimally-qualified # 🙍🏿‍♀ woman frowning: dark skin tone +1F64E ; fully-qualified # 🙎 person pouting +1F64E 1F3FB ; fully-qualified # 🙎🏻 person pouting: light skin tone +1F64E 1F3FC ; fully-qualified # 🙎🏼 person pouting: medium-light skin tone +1F64E 1F3FD ; fully-qualified # 🙎🏽 person pouting: medium skin tone +1F64E 1F3FE ; fully-qualified # 🙎🏾 person pouting: medium-dark skin tone +1F64E 1F3FF ; fully-qualified # 🙎🏿 person pouting: dark skin tone +1F64E 200D 2642 FE0F ; fully-qualified # 🙎‍♂️ man pouting +1F64E 200D 2642 ; minimally-qualified # 🙎‍♂ man pouting +1F64E 1F3FB 200D 2642 FE0F ; fully-qualified # 🙎🏻‍♂️ man pouting: light skin tone +1F64E 1F3FB 200D 2642 ; minimally-qualified # 🙎🏻‍♂ man pouting: light skin tone +1F64E 1F3FC 200D 2642 FE0F ; fully-qualified # 🙎🏼‍♂️ man pouting: medium-light skin tone +1F64E 1F3FC 200D 2642 ; minimally-qualified # 🙎🏼‍♂ man pouting: medium-light skin tone +1F64E 1F3FD 200D 2642 FE0F ; fully-qualified # 🙎🏽‍♂️ man pouting: medium skin tone +1F64E 1F3FD 200D 2642 ; minimally-qualified # 🙎🏽‍♂ man pouting: medium skin tone +1F64E 1F3FE 200D 2642 FE0F ; fully-qualified # 🙎🏾‍♂️ man pouting: medium-dark skin tone +1F64E 1F3FE 200D 2642 ; minimally-qualified # 🙎🏾‍♂ man pouting: medium-dark skin tone +1F64E 1F3FF 200D 2642 FE0F ; fully-qualified # 🙎🏿‍♂️ man pouting: dark skin tone +1F64E 1F3FF 200D 2642 ; minimally-qualified # 🙎🏿‍♂ man pouting: dark skin tone +1F64E 200D 2640 FE0F ; fully-qualified # 🙎‍♀️ woman pouting +1F64E 200D 2640 ; minimally-qualified # 🙎‍♀ woman pouting +1F64E 1F3FB 200D 2640 FE0F ; fully-qualified # 🙎🏻‍♀️ woman pouting: light skin tone +1F64E 1F3FB 200D 2640 ; minimally-qualified # 🙎🏻‍♀ woman pouting: light skin tone +1F64E 1F3FC 200D 2640 FE0F ; fully-qualified # 🙎🏼‍♀️ woman pouting: medium-light skin tone +1F64E 1F3FC 200D 2640 ; minimally-qualified # 🙎🏼‍♀ woman pouting: medium-light skin tone +1F64E 1F3FD 200D 2640 FE0F ; fully-qualified # 🙎🏽‍♀️ woman pouting: medium skin tone +1F64E 1F3FD 200D 2640 ; minimally-qualified # 🙎🏽‍♀ woman pouting: medium skin tone +1F64E 1F3FE 200D 2640 FE0F ; fully-qualified # 🙎🏾‍♀️ woman pouting: medium-dark skin tone +1F64E 1F3FE 200D 2640 ; minimally-qualified # 🙎🏾‍♀ woman pouting: medium-dark skin tone +1F64E 1F3FF 200D 2640 FE0F ; fully-qualified # 🙎🏿‍♀️ woman pouting: dark skin tone +1F64E 1F3FF 200D 2640 ; minimally-qualified # 🙎🏿‍♀ woman pouting: dark skin tone +1F645 ; fully-qualified # 🙅 person gesturing NO +1F645 1F3FB ; fully-qualified # 🙅🏻 person gesturing NO: light skin tone +1F645 1F3FC ; fully-qualified # 🙅🏼 person gesturing NO: medium-light skin tone +1F645 1F3FD ; fully-qualified # 🙅🏽 person gesturing NO: medium skin tone +1F645 1F3FE ; fully-qualified # 🙅🏾 person gesturing NO: medium-dark skin tone +1F645 1F3FF ; fully-qualified # 🙅🏿 person gesturing NO: dark skin tone +1F645 200D 2642 FE0F ; fully-qualified # 🙅‍♂️ man gesturing NO +1F645 200D 2642 ; minimally-qualified # 🙅‍♂ man gesturing NO +1F645 1F3FB 200D 2642 FE0F ; fully-qualified # 🙅🏻‍♂️ man gesturing NO: light skin tone +1F645 1F3FB 200D 2642 ; minimally-qualified # 🙅🏻‍♂ man gesturing NO: light skin tone +1F645 1F3FC 200D 2642 FE0F ; fully-qualified # 🙅🏼‍♂️ man gesturing NO: medium-light skin tone +1F645 1F3FC 200D 2642 ; minimally-qualified # 🙅🏼‍♂ man gesturing NO: medium-light skin tone +1F645 1F3FD 200D 2642 FE0F ; fully-qualified # 🙅🏽‍♂️ man gesturing NO: medium skin tone +1F645 1F3FD 200D 2642 ; minimally-qualified # 🙅🏽‍♂ man gesturing NO: medium skin tone +1F645 1F3FE 200D 2642 FE0F ; fully-qualified # 🙅🏾‍♂️ man gesturing NO: medium-dark skin tone +1F645 1F3FE 200D 2642 ; minimally-qualified # 🙅🏾‍♂ man gesturing NO: medium-dark skin tone +1F645 1F3FF 200D 2642 FE0F ; fully-qualified # 🙅🏿‍♂️ man gesturing NO: dark skin tone +1F645 1F3FF 200D 2642 ; minimally-qualified # 🙅🏿‍♂ man gesturing NO: dark skin tone +1F645 200D 2640 FE0F ; fully-qualified # 🙅‍♀️ woman gesturing NO +1F645 200D 2640 ; minimally-qualified # 🙅‍♀ woman gesturing NO +1F645 1F3FB 200D 2640 FE0F ; fully-qualified # 🙅🏻‍♀️ woman gesturing NO: light skin tone +1F645 1F3FB 200D 2640 ; minimally-qualified # 🙅🏻‍♀ woman gesturing NO: light skin tone +1F645 1F3FC 200D 2640 FE0F ; fully-qualified # 🙅🏼‍♀️ woman gesturing NO: medium-light skin tone +1F645 1F3FC 200D 2640 ; minimally-qualified # 🙅🏼‍♀ woman gesturing NO: medium-light skin tone +1F645 1F3FD 200D 2640 FE0F ; fully-qualified # 🙅🏽‍♀️ woman gesturing NO: medium skin tone +1F645 1F3FD 200D 2640 ; minimally-qualified # 🙅🏽‍♀ woman gesturing NO: medium skin tone +1F645 1F3FE 200D 2640 FE0F ; fully-qualified # 🙅🏾‍♀️ woman gesturing NO: medium-dark skin tone +1F645 1F3FE 200D 2640 ; minimally-qualified # 🙅🏾‍♀ woman gesturing NO: medium-dark skin tone +1F645 1F3FF 200D 2640 FE0F ; fully-qualified # 🙅🏿‍♀️ woman gesturing NO: dark skin tone +1F645 1F3FF 200D 2640 ; minimally-qualified # 🙅🏿‍♀ woman gesturing NO: dark skin tone +1F646 ; fully-qualified # 🙆 person gesturing OK +1F646 1F3FB ; fully-qualified # 🙆🏻 person gesturing OK: light skin tone +1F646 1F3FC ; fully-qualified # 🙆🏼 person gesturing OK: medium-light skin tone +1F646 1F3FD ; fully-qualified # 🙆🏽 person gesturing OK: medium skin tone +1F646 1F3FE ; fully-qualified # 🙆🏾 person gesturing OK: medium-dark skin tone +1F646 1F3FF ; fully-qualified # 🙆🏿 person gesturing OK: dark skin tone +1F646 200D 2642 FE0F ; fully-qualified # 🙆‍♂️ man gesturing OK +1F646 200D 2642 ; minimally-qualified # 🙆‍♂ man gesturing OK +1F646 1F3FB 200D 2642 FE0F ; fully-qualified # 🙆🏻‍♂️ man gesturing OK: light skin tone +1F646 1F3FB 200D 2642 ; minimally-qualified # 🙆🏻‍♂ man gesturing OK: light skin tone +1F646 1F3FC 200D 2642 FE0F ; fully-qualified # 🙆🏼‍♂️ man gesturing OK: medium-light skin tone +1F646 1F3FC 200D 2642 ; minimally-qualified # 🙆🏼‍♂ man gesturing OK: medium-light skin tone +1F646 1F3FD 200D 2642 FE0F ; fully-qualified # 🙆🏽‍♂️ man gesturing OK: medium skin tone +1F646 1F3FD 200D 2642 ; minimally-qualified # 🙆🏽‍♂ man gesturing OK: medium skin tone +1F646 1F3FE 200D 2642 FE0F ; fully-qualified # 🙆🏾‍♂️ man gesturing OK: medium-dark skin tone +1F646 1F3FE 200D 2642 ; minimally-qualified # 🙆🏾‍♂ man gesturing OK: medium-dark skin tone +1F646 1F3FF 200D 2642 FE0F ; fully-qualified # 🙆🏿‍♂️ man gesturing OK: dark skin tone +1F646 1F3FF 200D 2642 ; minimally-qualified # 🙆🏿‍♂ man gesturing OK: dark skin tone +1F646 200D 2640 FE0F ; fully-qualified # 🙆‍♀️ woman gesturing OK +1F646 200D 2640 ; minimally-qualified # 🙆‍♀ woman gesturing OK +1F646 1F3FB 200D 2640 FE0F ; fully-qualified # 🙆🏻‍♀️ woman gesturing OK: light skin tone +1F646 1F3FB 200D 2640 ; minimally-qualified # 🙆🏻‍♀ woman gesturing OK: light skin tone +1F646 1F3FC 200D 2640 FE0F ; fully-qualified # 🙆🏼‍♀️ woman gesturing OK: medium-light skin tone +1F646 1F3FC 200D 2640 ; minimally-qualified # 🙆🏼‍♀ woman gesturing OK: medium-light skin tone +1F646 1F3FD 200D 2640 FE0F ; fully-qualified # 🙆🏽‍♀️ woman gesturing OK: medium skin tone +1F646 1F3FD 200D 2640 ; minimally-qualified # 🙆🏽‍♀ woman gesturing OK: medium skin tone +1F646 1F3FE 200D 2640 FE0F ; fully-qualified # 🙆🏾‍♀️ woman gesturing OK: medium-dark skin tone +1F646 1F3FE 200D 2640 ; minimally-qualified # 🙆🏾‍♀ woman gesturing OK: medium-dark skin tone +1F646 1F3FF 200D 2640 FE0F ; fully-qualified # 🙆🏿‍♀️ woman gesturing OK: dark skin tone +1F646 1F3FF 200D 2640 ; minimally-qualified # 🙆🏿‍♀ woman gesturing OK: dark skin tone +1F481 ; fully-qualified # 💁 person tipping hand +1F481 1F3FB ; fully-qualified # 💁🏻 person tipping hand: light skin tone +1F481 1F3FC ; fully-qualified # 💁🏼 person tipping hand: medium-light skin tone +1F481 1F3FD ; fully-qualified # 💁🏽 person tipping hand: medium skin tone +1F481 1F3FE ; fully-qualified # 💁🏾 person tipping hand: medium-dark skin tone +1F481 1F3FF ; fully-qualified # 💁🏿 person tipping hand: dark skin tone +1F481 200D 2642 FE0F ; fully-qualified # 💁‍♂️ man tipping hand +1F481 200D 2642 ; minimally-qualified # 💁‍♂ man tipping hand +1F481 1F3FB 200D 2642 FE0F ; fully-qualified # 💁🏻‍♂️ man tipping hand: light skin tone +1F481 1F3FB 200D 2642 ; minimally-qualified # 💁🏻‍♂ man tipping hand: light skin tone +1F481 1F3FC 200D 2642 FE0F ; fully-qualified # 💁🏼‍♂️ man tipping hand: medium-light skin tone +1F481 1F3FC 200D 2642 ; minimally-qualified # 💁🏼‍♂ man tipping hand: medium-light skin tone +1F481 1F3FD 200D 2642 FE0F ; fully-qualified # 💁🏽‍♂️ man tipping hand: medium skin tone +1F481 1F3FD 200D 2642 ; minimally-qualified # 💁🏽‍♂ man tipping hand: medium skin tone +1F481 1F3FE 200D 2642 FE0F ; fully-qualified # 💁🏾‍♂️ man tipping hand: medium-dark skin tone +1F481 1F3FE 200D 2642 ; minimally-qualified # 💁🏾‍♂ man tipping hand: medium-dark skin tone +1F481 1F3FF 200D 2642 FE0F ; fully-qualified # 💁🏿‍♂️ man tipping hand: dark skin tone +1F481 1F3FF 200D 2642 ; minimally-qualified # 💁🏿‍♂ man tipping hand: dark skin tone +1F481 200D 2640 FE0F ; fully-qualified # 💁‍♀️ woman tipping hand +1F481 200D 2640 ; minimally-qualified # 💁‍♀ woman tipping hand +1F481 1F3FB 200D 2640 FE0F ; fully-qualified # 💁🏻‍♀️ woman tipping hand: light skin tone +1F481 1F3FB 200D 2640 ; minimally-qualified # 💁🏻‍♀ woman tipping hand: light skin tone +1F481 1F3FC 200D 2640 FE0F ; fully-qualified # 💁🏼‍♀️ woman tipping hand: medium-light skin tone +1F481 1F3FC 200D 2640 ; minimally-qualified # 💁🏼‍♀ woman tipping hand: medium-light skin tone +1F481 1F3FD 200D 2640 FE0F ; fully-qualified # 💁🏽‍♀️ woman tipping hand: medium skin tone +1F481 1F3FD 200D 2640 ; minimally-qualified # 💁🏽‍♀ woman tipping hand: medium skin tone +1F481 1F3FE 200D 2640 FE0F ; fully-qualified # 💁🏾‍♀️ woman tipping hand: medium-dark skin tone +1F481 1F3FE 200D 2640 ; minimally-qualified # 💁🏾‍♀ woman tipping hand: medium-dark skin tone +1F481 1F3FF 200D 2640 FE0F ; fully-qualified # 💁🏿‍♀️ woman tipping hand: dark skin tone +1F481 1F3FF 200D 2640 ; minimally-qualified # 💁🏿‍♀ woman tipping hand: dark skin tone +1F64B ; fully-qualified # 🙋 person raising hand +1F64B 1F3FB ; fully-qualified # 🙋🏻 person raising hand: light skin tone +1F64B 1F3FC ; fully-qualified # 🙋🏼 person raising hand: medium-light skin tone +1F64B 1F3FD ; fully-qualified # 🙋🏽 person raising hand: medium skin tone +1F64B 1F3FE ; fully-qualified # 🙋🏾 person raising hand: medium-dark skin tone +1F64B 1F3FF ; fully-qualified # 🙋🏿 person raising hand: dark skin tone +1F64B 200D 2642 FE0F ; fully-qualified # 🙋‍♂️ man raising hand +1F64B 200D 2642 ; minimally-qualified # 🙋‍♂ man raising hand +1F64B 1F3FB 200D 2642 FE0F ; fully-qualified # 🙋🏻‍♂️ man raising hand: light skin tone +1F64B 1F3FB 200D 2642 ; minimally-qualified # 🙋🏻‍♂ man raising hand: light skin tone +1F64B 1F3FC 200D 2642 FE0F ; fully-qualified # 🙋🏼‍♂️ man raising hand: medium-light skin tone +1F64B 1F3FC 200D 2642 ; minimally-qualified # 🙋🏼‍♂ man raising hand: medium-light skin tone +1F64B 1F3FD 200D 2642 FE0F ; fully-qualified # 🙋🏽‍♂️ man raising hand: medium skin tone +1F64B 1F3FD 200D 2642 ; minimally-qualified # 🙋🏽‍♂ man raising hand: medium skin tone +1F64B 1F3FE 200D 2642 FE0F ; fully-qualified # 🙋🏾‍♂️ man raising hand: medium-dark skin tone +1F64B 1F3FE 200D 2642 ; minimally-qualified # 🙋🏾‍♂ man raising hand: medium-dark skin tone +1F64B 1F3FF 200D 2642 FE0F ; fully-qualified # 🙋🏿‍♂️ man raising hand: dark skin tone +1F64B 1F3FF 200D 2642 ; minimally-qualified # 🙋🏿‍♂ man raising hand: dark skin tone +1F64B 200D 2640 FE0F ; fully-qualified # 🙋‍♀️ woman raising hand +1F64B 200D 2640 ; minimally-qualified # 🙋‍♀ woman raising hand +1F64B 1F3FB 200D 2640 FE0F ; fully-qualified # 🙋🏻‍♀️ woman raising hand: light skin tone +1F64B 1F3FB 200D 2640 ; minimally-qualified # 🙋🏻‍♀ woman raising hand: light skin tone +1F64B 1F3FC 200D 2640 FE0F ; fully-qualified # 🙋🏼‍♀️ woman raising hand: medium-light skin tone +1F64B 1F3FC 200D 2640 ; minimally-qualified # 🙋🏼‍♀ woman raising hand: medium-light skin tone +1F64B 1F3FD 200D 2640 FE0F ; fully-qualified # 🙋🏽‍♀️ woman raising hand: medium skin tone +1F64B 1F3FD 200D 2640 ; minimally-qualified # 🙋🏽‍♀ woman raising hand: medium skin tone +1F64B 1F3FE 200D 2640 FE0F ; fully-qualified # 🙋🏾‍♀️ woman raising hand: medium-dark skin tone +1F64B 1F3FE 200D 2640 ; minimally-qualified # 🙋🏾‍♀ woman raising hand: medium-dark skin tone +1F64B 1F3FF 200D 2640 FE0F ; fully-qualified # 🙋🏿‍♀️ woman raising hand: dark skin tone +1F64B 1F3FF 200D 2640 ; minimally-qualified # 🙋🏿‍♀ woman raising hand: dark skin tone +1F9CF ; fully-qualified # 🧏 deaf person +1F9CF 1F3FB ; fully-qualified # 🧏🏻 deaf person: light skin tone +1F9CF 1F3FC ; fully-qualified # 🧏🏼 deaf person: medium-light skin tone +1F9CF 1F3FD ; fully-qualified # 🧏🏽 deaf person: medium skin tone +1F9CF 1F3FE ; fully-qualified # 🧏🏾 deaf person: medium-dark skin tone +1F9CF 1F3FF ; fully-qualified # 🧏🏿 deaf person: dark skin tone +1F9CF 200D 2642 FE0F ; fully-qualified # 🧏‍♂️ deaf man +1F9CF 200D 2642 ; minimally-qualified # 🧏‍♂ deaf man +1F9CF 1F3FB 200D 2642 FE0F ; fully-qualified # 🧏🏻‍♂️ deaf man: light skin tone +1F9CF 1F3FB 200D 2642 ; minimally-qualified # 🧏🏻‍♂ deaf man: light skin tone +1F9CF 1F3FC 200D 2642 FE0F ; fully-qualified # 🧏🏼‍♂️ deaf man: medium-light skin tone +1F9CF 1F3FC 200D 2642 ; minimally-qualified # 🧏🏼‍♂ deaf man: medium-light skin tone +1F9CF 1F3FD 200D 2642 FE0F ; fully-qualified # 🧏🏽‍♂️ deaf man: medium skin tone +1F9CF 1F3FD 200D 2642 ; minimally-qualified # 🧏🏽‍♂ deaf man: medium skin tone +1F9CF 1F3FE 200D 2642 FE0F ; fully-qualified # 🧏🏾‍♂️ deaf man: medium-dark skin tone +1F9CF 1F3FE 200D 2642 ; minimally-qualified # 🧏🏾‍♂ deaf man: medium-dark skin tone +1F9CF 1F3FF 200D 2642 FE0F ; fully-qualified # 🧏🏿‍♂️ deaf man: dark skin tone +1F9CF 1F3FF 200D 2642 ; minimally-qualified # 🧏🏿‍♂ deaf man: dark skin tone +1F9CF 200D 2640 FE0F ; fully-qualified # 🧏‍♀️ deaf woman +1F9CF 200D 2640 ; minimally-qualified # 🧏‍♀ deaf woman +1F9CF 1F3FB 200D 2640 FE0F ; fully-qualified # 🧏🏻‍♀️ deaf woman: light skin tone +1F9CF 1F3FB 200D 2640 ; minimally-qualified # 🧏🏻‍♀ deaf woman: light skin tone +1F9CF 1F3FC 200D 2640 FE0F ; fully-qualified # 🧏🏼‍♀️ deaf woman: medium-light skin tone +1F9CF 1F3FC 200D 2640 ; minimally-qualified # 🧏🏼‍♀ deaf woman: medium-light skin tone +1F9CF 1F3FD 200D 2640 FE0F ; fully-qualified # 🧏🏽‍♀️ deaf woman: medium skin tone +1F9CF 1F3FD 200D 2640 ; minimally-qualified # 🧏🏽‍♀ deaf woman: medium skin tone +1F9CF 1F3FE 200D 2640 FE0F ; fully-qualified # 🧏🏾‍♀️ deaf woman: medium-dark skin tone +1F9CF 1F3FE 200D 2640 ; minimally-qualified # 🧏🏾‍♀ deaf woman: medium-dark skin tone +1F9CF 1F3FF 200D 2640 FE0F ; fully-qualified # 🧏🏿‍♀️ deaf woman: dark skin tone +1F9CF 1F3FF 200D 2640 ; minimally-qualified # 🧏🏿‍♀ deaf woman: dark skin tone +1F647 ; fully-qualified # 🙇 person bowing +1F647 1F3FB ; fully-qualified # 🙇🏻 person bowing: light skin tone +1F647 1F3FC ; fully-qualified # 🙇🏼 person bowing: medium-light skin tone +1F647 1F3FD ; fully-qualified # 🙇🏽 person bowing: medium skin tone +1F647 1F3FE ; fully-qualified # 🙇🏾 person bowing: medium-dark skin tone +1F647 1F3FF ; fully-qualified # 🙇🏿 person bowing: dark skin tone +1F647 200D 2642 FE0F ; fully-qualified # 🙇‍♂️ man bowing +1F647 200D 2642 ; minimally-qualified # 🙇‍♂ man bowing +1F647 1F3FB 200D 2642 FE0F ; fully-qualified # 🙇🏻‍♂️ man bowing: light skin tone +1F647 1F3FB 200D 2642 ; minimally-qualified # 🙇🏻‍♂ man bowing: light skin tone +1F647 1F3FC 200D 2642 FE0F ; fully-qualified # 🙇🏼‍♂️ man bowing: medium-light skin tone +1F647 1F3FC 200D 2642 ; minimally-qualified # 🙇🏼‍♂ man bowing: medium-light skin tone +1F647 1F3FD 200D 2642 FE0F ; fully-qualified # 🙇🏽‍♂️ man bowing: medium skin tone +1F647 1F3FD 200D 2642 ; minimally-qualified # 🙇🏽‍♂ man bowing: medium skin tone +1F647 1F3FE 200D 2642 FE0F ; fully-qualified # 🙇🏾‍♂️ man bowing: medium-dark skin tone +1F647 1F3FE 200D 2642 ; minimally-qualified # 🙇🏾‍♂ man bowing: medium-dark skin tone +1F647 1F3FF 200D 2642 FE0F ; fully-qualified # 🙇🏿‍♂️ man bowing: dark skin tone +1F647 1F3FF 200D 2642 ; minimally-qualified # 🙇🏿‍♂ man bowing: dark skin tone +1F647 200D 2640 FE0F ; fully-qualified # 🙇‍♀️ woman bowing +1F647 200D 2640 ; minimally-qualified # 🙇‍♀ woman bowing +1F647 1F3FB 200D 2640 FE0F ; fully-qualified # 🙇🏻‍♀️ woman bowing: light skin tone +1F647 1F3FB 200D 2640 ; minimally-qualified # 🙇🏻‍♀ woman bowing: light skin tone +1F647 1F3FC 200D 2640 FE0F ; fully-qualified # 🙇🏼‍♀️ woman bowing: medium-light skin tone +1F647 1F3FC 200D 2640 ; minimally-qualified # 🙇🏼‍♀ woman bowing: medium-light skin tone +1F647 1F3FD 200D 2640 FE0F ; fully-qualified # 🙇🏽‍♀️ woman bowing: medium skin tone +1F647 1F3FD 200D 2640 ; minimally-qualified # 🙇🏽‍♀ woman bowing: medium skin tone +1F647 1F3FE 200D 2640 FE0F ; fully-qualified # 🙇🏾‍♀️ woman bowing: medium-dark skin tone +1F647 1F3FE 200D 2640 ; minimally-qualified # 🙇🏾‍♀ woman bowing: medium-dark skin tone +1F647 1F3FF 200D 2640 FE0F ; fully-qualified # 🙇🏿‍♀️ woman bowing: dark skin tone +1F647 1F3FF 200D 2640 ; minimally-qualified # 🙇🏿‍♀ woman bowing: dark skin tone +1F926 ; fully-qualified # 🤦 person facepalming +1F926 1F3FB ; fully-qualified # 🤦🏻 person facepalming: light skin tone +1F926 1F3FC ; fully-qualified # 🤦🏼 person facepalming: medium-light skin tone +1F926 1F3FD ; fully-qualified # 🤦🏽 person facepalming: medium skin tone +1F926 1F3FE ; fully-qualified # 🤦🏾 person facepalming: medium-dark skin tone +1F926 1F3FF ; fully-qualified # 🤦🏿 person facepalming: dark skin tone +1F926 200D 2642 FE0F ; fully-qualified # 🤦‍♂️ man facepalming +1F926 200D 2642 ; minimally-qualified # 🤦‍♂ man facepalming +1F926 1F3FB 200D 2642 FE0F ; fully-qualified # 🤦🏻‍♂️ man facepalming: light skin tone +1F926 1F3FB 200D 2642 ; minimally-qualified # 🤦🏻‍♂ man facepalming: light skin tone +1F926 1F3FC 200D 2642 FE0F ; fully-qualified # 🤦🏼‍♂️ man facepalming: medium-light skin tone +1F926 1F3FC 200D 2642 ; minimally-qualified # 🤦🏼‍♂ man facepalming: medium-light skin tone +1F926 1F3FD 200D 2642 FE0F ; fully-qualified # 🤦🏽‍♂️ man facepalming: medium skin tone +1F926 1F3FD 200D 2642 ; minimally-qualified # 🤦🏽‍♂ man facepalming: medium skin tone +1F926 1F3FE 200D 2642 FE0F ; fully-qualified # 🤦🏾‍♂️ man facepalming: medium-dark skin tone +1F926 1F3FE 200D 2642 ; minimally-qualified # 🤦🏾‍♂ man facepalming: medium-dark skin tone +1F926 1F3FF 200D 2642 FE0F ; fully-qualified # 🤦🏿‍♂️ man facepalming: dark skin tone +1F926 1F3FF 200D 2642 ; minimally-qualified # 🤦🏿‍♂ man facepalming: dark skin tone +1F926 200D 2640 FE0F ; fully-qualified # 🤦‍♀️ woman facepalming +1F926 200D 2640 ; minimally-qualified # 🤦‍♀ woman facepalming +1F926 1F3FB 200D 2640 FE0F ; fully-qualified # 🤦🏻‍♀️ woman facepalming: light skin tone +1F926 1F3FB 200D 2640 ; minimally-qualified # 🤦🏻‍♀ woman facepalming: light skin tone +1F926 1F3FC 200D 2640 FE0F ; fully-qualified # 🤦🏼‍♀️ woman facepalming: medium-light skin tone +1F926 1F3FC 200D 2640 ; minimally-qualified # 🤦🏼‍♀ woman facepalming: medium-light skin tone +1F926 1F3FD 200D 2640 FE0F ; fully-qualified # 🤦🏽‍♀️ woman facepalming: medium skin tone +1F926 1F3FD 200D 2640 ; minimally-qualified # 🤦🏽‍♀ woman facepalming: medium skin tone +1F926 1F3FE 200D 2640 FE0F ; fully-qualified # 🤦🏾‍♀️ woman facepalming: medium-dark skin tone +1F926 1F3FE 200D 2640 ; minimally-qualified # 🤦🏾‍♀ woman facepalming: medium-dark skin tone +1F926 1F3FF 200D 2640 FE0F ; fully-qualified # 🤦🏿‍♀️ woman facepalming: dark skin tone +1F926 1F3FF 200D 2640 ; minimally-qualified # 🤦🏿‍♀ woman facepalming: dark skin tone +1F937 ; fully-qualified # 🤷 person shrugging +1F937 1F3FB ; fully-qualified # 🤷🏻 person shrugging: light skin tone +1F937 1F3FC ; fully-qualified # 🤷🏼 person shrugging: medium-light skin tone +1F937 1F3FD ; fully-qualified # 🤷🏽 person shrugging: medium skin tone +1F937 1F3FE ; fully-qualified # 🤷🏾 person shrugging: medium-dark skin tone +1F937 1F3FF ; fully-qualified # 🤷🏿 person shrugging: dark skin tone +1F937 200D 2642 FE0F ; fully-qualified # 🤷‍♂️ man shrugging +1F937 200D 2642 ; minimally-qualified # 🤷‍♂ man shrugging +1F937 1F3FB 200D 2642 FE0F ; fully-qualified # 🤷🏻‍♂️ man shrugging: light skin tone +1F937 1F3FB 200D 2642 ; minimally-qualified # 🤷🏻‍♂ man shrugging: light skin tone +1F937 1F3FC 200D 2642 FE0F ; fully-qualified # 🤷🏼‍♂️ man shrugging: medium-light skin tone +1F937 1F3FC 200D 2642 ; minimally-qualified # 🤷🏼‍♂ man shrugging: medium-light skin tone +1F937 1F3FD 200D 2642 FE0F ; fully-qualified # 🤷🏽‍♂️ man shrugging: medium skin tone +1F937 1F3FD 200D 2642 ; minimally-qualified # 🤷🏽‍♂ man shrugging: medium skin tone +1F937 1F3FE 200D 2642 FE0F ; fully-qualified # 🤷🏾‍♂️ man shrugging: medium-dark skin tone +1F937 1F3FE 200D 2642 ; minimally-qualified # 🤷🏾‍♂ man shrugging: medium-dark skin tone +1F937 1F3FF 200D 2642 FE0F ; fully-qualified # 🤷🏿‍♂️ man shrugging: dark skin tone +1F937 1F3FF 200D 2642 ; minimally-qualified # 🤷🏿‍♂ man shrugging: dark skin tone +1F937 200D 2640 FE0F ; fully-qualified # 🤷‍♀️ woman shrugging +1F937 200D 2640 ; minimally-qualified # 🤷‍♀ woman shrugging +1F937 1F3FB 200D 2640 FE0F ; fully-qualified # 🤷🏻‍♀️ woman shrugging: light skin tone +1F937 1F3FB 200D 2640 ; minimally-qualified # 🤷🏻‍♀ woman shrugging: light skin tone +1F937 1F3FC 200D 2640 FE0F ; fully-qualified # 🤷🏼‍♀️ woman shrugging: medium-light skin tone +1F937 1F3FC 200D 2640 ; minimally-qualified # 🤷🏼‍♀ woman shrugging: medium-light skin tone +1F937 1F3FD 200D 2640 FE0F ; fully-qualified # 🤷🏽‍♀️ woman shrugging: medium skin tone +1F937 1F3FD 200D 2640 ; minimally-qualified # 🤷🏽‍♀ woman shrugging: medium skin tone +1F937 1F3FE 200D 2640 FE0F ; fully-qualified # 🤷🏾‍♀️ woman shrugging: medium-dark skin tone +1F937 1F3FE 200D 2640 ; minimally-qualified # 🤷🏾‍♀ woman shrugging: medium-dark skin tone +1F937 1F3FF 200D 2640 FE0F ; fully-qualified # 🤷🏿‍♀️ woman shrugging: dark skin tone +1F937 1F3FF 200D 2640 ; minimally-qualified # 🤷🏿‍♀ woman shrugging: dark skin tone + +# subgroup: person-role +1F468 200D 2695 FE0F ; fully-qualified # 👨‍⚕️ man health worker +1F468 200D 2695 ; minimally-qualified # 👨‍⚕ man health worker +1F468 1F3FB 200D 2695 FE0F ; fully-qualified # 👨🏻‍⚕️ man health worker: light skin tone +1F468 1F3FB 200D 2695 ; minimally-qualified # 👨🏻‍⚕ man health worker: light skin tone +1F468 1F3FC 200D 2695 FE0F ; fully-qualified # 👨🏼‍⚕️ man health worker: medium-light skin tone +1F468 1F3FC 200D 2695 ; minimally-qualified # 👨🏼‍⚕ man health worker: medium-light skin tone +1F468 1F3FD 200D 2695 FE0F ; fully-qualified # 👨🏽‍⚕️ man health worker: medium skin tone +1F468 1F3FD 200D 2695 ; minimally-qualified # 👨🏽‍⚕ man health worker: medium skin tone +1F468 1F3FE 200D 2695 FE0F ; fully-qualified # 👨🏾‍⚕️ man health worker: medium-dark skin tone +1F468 1F3FE 200D 2695 ; minimally-qualified # 👨🏾‍⚕ man health worker: medium-dark skin tone +1F468 1F3FF 200D 2695 FE0F ; fully-qualified # 👨🏿‍⚕️ man health worker: dark skin tone +1F468 1F3FF 200D 2695 ; minimally-qualified # 👨🏿‍⚕ man health worker: dark skin tone +1F469 200D 2695 FE0F ; fully-qualified # 👩‍⚕️ woman health worker +1F469 200D 2695 ; minimally-qualified # 👩‍⚕ woman health worker +1F469 1F3FB 200D 2695 FE0F ; fully-qualified # 👩🏻‍⚕️ woman health worker: light skin tone +1F469 1F3FB 200D 2695 ; minimally-qualified # 👩🏻‍⚕ woman health worker: light skin tone +1F469 1F3FC 200D 2695 FE0F ; fully-qualified # 👩🏼‍⚕️ woman health worker: medium-light skin tone +1F469 1F3FC 200D 2695 ; minimally-qualified # 👩🏼‍⚕ woman health worker: medium-light skin tone +1F469 1F3FD 200D 2695 FE0F ; fully-qualified # 👩🏽‍⚕️ woman health worker: medium skin tone +1F469 1F3FD 200D 2695 ; minimally-qualified # 👩🏽‍⚕ woman health worker: medium skin tone +1F469 1F3FE 200D 2695 FE0F ; fully-qualified # 👩🏾‍⚕️ woman health worker: medium-dark skin tone +1F469 1F3FE 200D 2695 ; minimally-qualified # 👩🏾‍⚕ woman health worker: medium-dark skin tone +1F469 1F3FF 200D 2695 FE0F ; fully-qualified # 👩🏿‍⚕️ woman health worker: dark skin tone +1F469 1F3FF 200D 2695 ; minimally-qualified # 👩🏿‍⚕ woman health worker: dark skin tone +1F468 200D 1F393 ; fully-qualified # 👨‍🎓 man student +1F468 1F3FB 200D 1F393 ; fully-qualified # 👨🏻‍🎓 man student: light skin tone +1F468 1F3FC 200D 1F393 ; fully-qualified # 👨🏼‍🎓 man student: medium-light skin tone +1F468 1F3FD 200D 1F393 ; fully-qualified # 👨🏽‍🎓 man student: medium skin tone +1F468 1F3FE 200D 1F393 ; fully-qualified # 👨🏾‍🎓 man student: medium-dark skin tone +1F468 1F3FF 200D 1F393 ; fully-qualified # 👨🏿‍🎓 man student: dark skin tone +1F469 200D 1F393 ; fully-qualified # 👩‍🎓 woman student +1F469 1F3FB 200D 1F393 ; fully-qualified # 👩🏻‍🎓 woman student: light skin tone +1F469 1F3FC 200D 1F393 ; fully-qualified # 👩🏼‍🎓 woman student: medium-light skin tone +1F469 1F3FD 200D 1F393 ; fully-qualified # 👩🏽‍🎓 woman student: medium skin tone +1F469 1F3FE 200D 1F393 ; fully-qualified # 👩🏾‍🎓 woman student: medium-dark skin tone +1F469 1F3FF 200D 1F393 ; fully-qualified # 👩🏿‍🎓 woman student: dark skin tone +1F468 200D 1F3EB ; fully-qualified # 👨‍🏫 man teacher +1F468 1F3FB 200D 1F3EB ; fully-qualified # 👨🏻‍🏫 man teacher: light skin tone +1F468 1F3FC 200D 1F3EB ; fully-qualified # 👨🏼‍🏫 man teacher: medium-light skin tone +1F468 1F3FD 200D 1F3EB ; fully-qualified # 👨🏽‍🏫 man teacher: medium skin tone +1F468 1F3FE 200D 1F3EB ; fully-qualified # 👨🏾‍🏫 man teacher: medium-dark skin tone +1F468 1F3FF 200D 1F3EB ; fully-qualified # 👨🏿‍🏫 man teacher: dark skin tone +1F469 200D 1F3EB ; fully-qualified # 👩‍🏫 woman teacher +1F469 1F3FB 200D 1F3EB ; fully-qualified # 👩🏻‍🏫 woman teacher: light skin tone +1F469 1F3FC 200D 1F3EB ; fully-qualified # 👩🏼‍🏫 woman teacher: medium-light skin tone +1F469 1F3FD 200D 1F3EB ; fully-qualified # 👩🏽‍🏫 woman teacher: medium skin tone +1F469 1F3FE 200D 1F3EB ; fully-qualified # 👩🏾‍🏫 woman teacher: medium-dark skin tone +1F469 1F3FF 200D 1F3EB ; fully-qualified # 👩🏿‍🏫 woman teacher: dark skin tone +1F468 200D 2696 FE0F ; fully-qualified # 👨‍⚖️ man judge +1F468 200D 2696 ; minimally-qualified # 👨‍⚖ man judge +1F468 1F3FB 200D 2696 FE0F ; fully-qualified # 👨🏻‍⚖️ man judge: light skin tone +1F468 1F3FB 200D 2696 ; minimally-qualified # 👨🏻‍⚖ man judge: light skin tone +1F468 1F3FC 200D 2696 FE0F ; fully-qualified # 👨🏼‍⚖️ man judge: medium-light skin tone +1F468 1F3FC 200D 2696 ; minimally-qualified # 👨🏼‍⚖ man judge: medium-light skin tone +1F468 1F3FD 200D 2696 FE0F ; fully-qualified # 👨🏽‍⚖️ man judge: medium skin tone +1F468 1F3FD 200D 2696 ; minimally-qualified # 👨🏽‍⚖ man judge: medium skin tone +1F468 1F3FE 200D 2696 FE0F ; fully-qualified # 👨🏾‍⚖️ man judge: medium-dark skin tone +1F468 1F3FE 200D 2696 ; minimally-qualified # 👨🏾‍⚖ man judge: medium-dark skin tone +1F468 1F3FF 200D 2696 FE0F ; fully-qualified # 👨🏿‍⚖️ man judge: dark skin tone +1F468 1F3FF 200D 2696 ; minimally-qualified # 👨🏿‍⚖ man judge: dark skin tone +1F469 200D 2696 FE0F ; fully-qualified # 👩‍⚖️ woman judge +1F469 200D 2696 ; minimally-qualified # 👩‍⚖ woman judge +1F469 1F3FB 200D 2696 FE0F ; fully-qualified # 👩🏻‍⚖️ woman judge: light skin tone +1F469 1F3FB 200D 2696 ; minimally-qualified # 👩🏻‍⚖ woman judge: light skin tone +1F469 1F3FC 200D 2696 FE0F ; fully-qualified # 👩🏼‍⚖️ woman judge: medium-light skin tone +1F469 1F3FC 200D 2696 ; minimally-qualified # 👩🏼‍⚖ woman judge: medium-light skin tone +1F469 1F3FD 200D 2696 FE0F ; fully-qualified # 👩🏽‍⚖️ woman judge: medium skin tone +1F469 1F3FD 200D 2696 ; minimally-qualified # 👩🏽‍⚖ woman judge: medium skin tone +1F469 1F3FE 200D 2696 FE0F ; fully-qualified # 👩🏾‍⚖️ woman judge: medium-dark skin tone +1F469 1F3FE 200D 2696 ; minimally-qualified # 👩🏾‍⚖ woman judge: medium-dark skin tone +1F469 1F3FF 200D 2696 FE0F ; fully-qualified # 👩🏿‍⚖️ woman judge: dark skin tone +1F469 1F3FF 200D 2696 ; minimally-qualified # 👩🏿‍⚖ woman judge: dark skin tone +1F468 200D 1F33E ; fully-qualified # 👨‍🌾 man farmer +1F468 1F3FB 200D 1F33E ; fully-qualified # 👨🏻‍🌾 man farmer: light skin tone +1F468 1F3FC 200D 1F33E ; fully-qualified # 👨🏼‍🌾 man farmer: medium-light skin tone +1F468 1F3FD 200D 1F33E ; fully-qualified # 👨🏽‍🌾 man farmer: medium skin tone +1F468 1F3FE 200D 1F33E ; fully-qualified # 👨🏾‍🌾 man farmer: medium-dark skin tone +1F468 1F3FF 200D 1F33E ; fully-qualified # 👨🏿‍🌾 man farmer: dark skin tone +1F469 200D 1F33E ; fully-qualified # 👩‍🌾 woman farmer +1F469 1F3FB 200D 1F33E ; fully-qualified # 👩🏻‍🌾 woman farmer: light skin tone +1F469 1F3FC 200D 1F33E ; fully-qualified # 👩🏼‍🌾 woman farmer: medium-light skin tone +1F469 1F3FD 200D 1F33E ; fully-qualified # 👩🏽‍🌾 woman farmer: medium skin tone +1F469 1F3FE 200D 1F33E ; fully-qualified # 👩🏾‍🌾 woman farmer: medium-dark skin tone +1F469 1F3FF 200D 1F33E ; fully-qualified # 👩🏿‍🌾 woman farmer: dark skin tone +1F468 200D 1F373 ; fully-qualified # 👨‍🍳 man cook +1F468 1F3FB 200D 1F373 ; fully-qualified # 👨🏻‍🍳 man cook: light skin tone +1F468 1F3FC 200D 1F373 ; fully-qualified # 👨🏼‍🍳 man cook: medium-light skin tone +1F468 1F3FD 200D 1F373 ; fully-qualified # 👨🏽‍🍳 man cook: medium skin tone +1F468 1F3FE 200D 1F373 ; fully-qualified # 👨🏾‍🍳 man cook: medium-dark skin tone +1F468 1F3FF 200D 1F373 ; fully-qualified # 👨🏿‍🍳 man cook: dark skin tone +1F469 200D 1F373 ; fully-qualified # 👩‍🍳 woman cook +1F469 1F3FB 200D 1F373 ; fully-qualified # 👩🏻‍🍳 woman cook: light skin tone +1F469 1F3FC 200D 1F373 ; fully-qualified # 👩🏼‍🍳 woman cook: medium-light skin tone +1F469 1F3FD 200D 1F373 ; fully-qualified # 👩🏽‍🍳 woman cook: medium skin tone +1F469 1F3FE 200D 1F373 ; fully-qualified # 👩🏾‍🍳 woman cook: medium-dark skin tone +1F469 1F3FF 200D 1F373 ; fully-qualified # 👩🏿‍🍳 woman cook: dark skin tone +1F468 200D 1F527 ; fully-qualified # 👨‍🔧 man mechanic +1F468 1F3FB 200D 1F527 ; fully-qualified # 👨🏻‍🔧 man mechanic: light skin tone +1F468 1F3FC 200D 1F527 ; fully-qualified # 👨🏼‍🔧 man mechanic: medium-light skin tone +1F468 1F3FD 200D 1F527 ; fully-qualified # 👨🏽‍🔧 man mechanic: medium skin tone +1F468 1F3FE 200D 1F527 ; fully-qualified # 👨🏾‍🔧 man mechanic: medium-dark skin tone +1F468 1F3FF 200D 1F527 ; fully-qualified # 👨🏿‍🔧 man mechanic: dark skin tone +1F469 200D 1F527 ; fully-qualified # 👩‍🔧 woman mechanic +1F469 1F3FB 200D 1F527 ; fully-qualified # 👩🏻‍🔧 woman mechanic: light skin tone +1F469 1F3FC 200D 1F527 ; fully-qualified # 👩🏼‍🔧 woman mechanic: medium-light skin tone +1F469 1F3FD 200D 1F527 ; fully-qualified # 👩🏽‍🔧 woman mechanic: medium skin tone +1F469 1F3FE 200D 1F527 ; fully-qualified # 👩🏾‍🔧 woman mechanic: medium-dark skin tone +1F469 1F3FF 200D 1F527 ; fully-qualified # 👩🏿‍🔧 woman mechanic: dark skin tone +1F468 200D 1F3ED ; fully-qualified # 👨‍🏭 man factory worker +1F468 1F3FB 200D 1F3ED ; fully-qualified # 👨🏻‍🏭 man factory worker: light skin tone +1F468 1F3FC 200D 1F3ED ; fully-qualified # 👨🏼‍🏭 man factory worker: medium-light skin tone +1F468 1F3FD 200D 1F3ED ; fully-qualified # 👨🏽‍🏭 man factory worker: medium skin tone +1F468 1F3FE 200D 1F3ED ; fully-qualified # 👨🏾‍🏭 man factory worker: medium-dark skin tone +1F468 1F3FF 200D 1F3ED ; fully-qualified # 👨🏿‍🏭 man factory worker: dark skin tone +1F469 200D 1F3ED ; fully-qualified # 👩‍🏭 woman factory worker +1F469 1F3FB 200D 1F3ED ; fully-qualified # 👩🏻‍🏭 woman factory worker: light skin tone +1F469 1F3FC 200D 1F3ED ; fully-qualified # 👩🏼‍🏭 woman factory worker: medium-light skin tone +1F469 1F3FD 200D 1F3ED ; fully-qualified # 👩🏽‍🏭 woman factory worker: medium skin tone +1F469 1F3FE 200D 1F3ED ; fully-qualified # 👩🏾‍🏭 woman factory worker: medium-dark skin tone +1F469 1F3FF 200D 1F3ED ; fully-qualified # 👩🏿‍🏭 woman factory worker: dark skin tone +1F468 200D 1F4BC ; fully-qualified # 👨‍💼 man office worker +1F468 1F3FB 200D 1F4BC ; fully-qualified # 👨🏻‍💼 man office worker: light skin tone +1F468 1F3FC 200D 1F4BC ; fully-qualified # 👨🏼‍💼 man office worker: medium-light skin tone +1F468 1F3FD 200D 1F4BC ; fully-qualified # 👨🏽‍💼 man office worker: medium skin tone +1F468 1F3FE 200D 1F4BC ; fully-qualified # 👨🏾‍💼 man office worker: medium-dark skin tone +1F468 1F3FF 200D 1F4BC ; fully-qualified # 👨🏿‍💼 man office worker: dark skin tone +1F469 200D 1F4BC ; fully-qualified # 👩‍💼 woman office worker +1F469 1F3FB 200D 1F4BC ; fully-qualified # 👩🏻‍💼 woman office worker: light skin tone +1F469 1F3FC 200D 1F4BC ; fully-qualified # 👩🏼‍💼 woman office worker: medium-light skin tone +1F469 1F3FD 200D 1F4BC ; fully-qualified # 👩🏽‍💼 woman office worker: medium skin tone +1F469 1F3FE 200D 1F4BC ; fully-qualified # 👩🏾‍💼 woman office worker: medium-dark skin tone +1F469 1F3FF 200D 1F4BC ; fully-qualified # 👩🏿‍💼 woman office worker: dark skin tone +1F468 200D 1F52C ; fully-qualified # 👨‍🔬 man scientist +1F468 1F3FB 200D 1F52C ; fully-qualified # 👨🏻‍🔬 man scientist: light skin tone +1F468 1F3FC 200D 1F52C ; fully-qualified # 👨🏼‍🔬 man scientist: medium-light skin tone +1F468 1F3FD 200D 1F52C ; fully-qualified # 👨🏽‍🔬 man scientist: medium skin tone +1F468 1F3FE 200D 1F52C ; fully-qualified # 👨🏾‍🔬 man scientist: medium-dark skin tone +1F468 1F3FF 200D 1F52C ; fully-qualified # 👨🏿‍🔬 man scientist: dark skin tone +1F469 200D 1F52C ; fully-qualified # 👩‍🔬 woman scientist +1F469 1F3FB 200D 1F52C ; fully-qualified # 👩🏻‍🔬 woman scientist: light skin tone +1F469 1F3FC 200D 1F52C ; fully-qualified # 👩🏼‍🔬 woman scientist: medium-light skin tone +1F469 1F3FD 200D 1F52C ; fully-qualified # 👩🏽‍🔬 woman scientist: medium skin tone +1F469 1F3FE 200D 1F52C ; fully-qualified # 👩🏾‍🔬 woman scientist: medium-dark skin tone +1F469 1F3FF 200D 1F52C ; fully-qualified # 👩🏿‍🔬 woman scientist: dark skin tone +1F468 200D 1F4BB ; fully-qualified # 👨‍💻 man technologist +1F468 1F3FB 200D 1F4BB ; fully-qualified # 👨🏻‍💻 man technologist: light skin tone +1F468 1F3FC 200D 1F4BB ; fully-qualified # 👨🏼‍💻 man technologist: medium-light skin tone +1F468 1F3FD 200D 1F4BB ; fully-qualified # 👨🏽‍💻 man technologist: medium skin tone +1F468 1F3FE 200D 1F4BB ; fully-qualified # 👨🏾‍💻 man technologist: medium-dark skin tone +1F468 1F3FF 200D 1F4BB ; fully-qualified # 👨🏿‍💻 man technologist: dark skin tone +1F469 200D 1F4BB ; fully-qualified # 👩‍💻 woman technologist +1F469 1F3FB 200D 1F4BB ; fully-qualified # 👩🏻‍💻 woman technologist: light skin tone +1F469 1F3FC 200D 1F4BB ; fully-qualified # 👩🏼‍💻 woman technologist: medium-light skin tone +1F469 1F3FD 200D 1F4BB ; fully-qualified # 👩🏽‍💻 woman technologist: medium skin tone +1F469 1F3FE 200D 1F4BB ; fully-qualified # 👩🏾‍💻 woman technologist: medium-dark skin tone +1F469 1F3FF 200D 1F4BB ; fully-qualified # 👩🏿‍💻 woman technologist: dark skin tone +1F468 200D 1F3A4 ; fully-qualified # 👨‍🎤 man singer +1F468 1F3FB 200D 1F3A4 ; fully-qualified # 👨🏻‍🎤 man singer: light skin tone +1F468 1F3FC 200D 1F3A4 ; fully-qualified # 👨🏼‍🎤 man singer: medium-light skin tone +1F468 1F3FD 200D 1F3A4 ; fully-qualified # 👨🏽‍🎤 man singer: medium skin tone +1F468 1F3FE 200D 1F3A4 ; fully-qualified # 👨🏾‍🎤 man singer: medium-dark skin tone +1F468 1F3FF 200D 1F3A4 ; fully-qualified # 👨🏿‍🎤 man singer: dark skin tone +1F469 200D 1F3A4 ; fully-qualified # 👩‍🎤 woman singer +1F469 1F3FB 200D 1F3A4 ; fully-qualified # 👩🏻‍🎤 woman singer: light skin tone +1F469 1F3FC 200D 1F3A4 ; fully-qualified # 👩🏼‍🎤 woman singer: medium-light skin tone +1F469 1F3FD 200D 1F3A4 ; fully-qualified # 👩🏽‍🎤 woman singer: medium skin tone +1F469 1F3FE 200D 1F3A4 ; fully-qualified # 👩🏾‍🎤 woman singer: medium-dark skin tone +1F469 1F3FF 200D 1F3A4 ; fully-qualified # 👩🏿‍🎤 woman singer: dark skin tone +1F468 200D 1F3A8 ; fully-qualified # 👨‍🎨 man artist +1F468 1F3FB 200D 1F3A8 ; fully-qualified # 👨🏻‍🎨 man artist: light skin tone +1F468 1F3FC 200D 1F3A8 ; fully-qualified # 👨🏼‍🎨 man artist: medium-light skin tone +1F468 1F3FD 200D 1F3A8 ; fully-qualified # 👨🏽‍🎨 man artist: medium skin tone +1F468 1F3FE 200D 1F3A8 ; fully-qualified # 👨🏾‍🎨 man artist: medium-dark skin tone +1F468 1F3FF 200D 1F3A8 ; fully-qualified # 👨🏿‍🎨 man artist: dark skin tone +1F469 200D 1F3A8 ; fully-qualified # 👩‍🎨 woman artist +1F469 1F3FB 200D 1F3A8 ; fully-qualified # 👩🏻‍🎨 woman artist: light skin tone +1F469 1F3FC 200D 1F3A8 ; fully-qualified # 👩🏼‍🎨 woman artist: medium-light skin tone +1F469 1F3FD 200D 1F3A8 ; fully-qualified # 👩🏽‍🎨 woman artist: medium skin tone +1F469 1F3FE 200D 1F3A8 ; fully-qualified # 👩🏾‍🎨 woman artist: medium-dark skin tone +1F469 1F3FF 200D 1F3A8 ; fully-qualified # 👩🏿‍🎨 woman artist: dark skin tone +1F468 200D 2708 FE0F ; fully-qualified # 👨‍✈️ man pilot +1F468 200D 2708 ; minimally-qualified # 👨‍✈ man pilot +1F468 1F3FB 200D 2708 FE0F ; fully-qualified # 👨🏻‍✈️ man pilot: light skin tone +1F468 1F3FB 200D 2708 ; minimally-qualified # 👨🏻‍✈ man pilot: light skin tone +1F468 1F3FC 200D 2708 FE0F ; fully-qualified # 👨🏼‍✈️ man pilot: medium-light skin tone +1F468 1F3FC 200D 2708 ; minimally-qualified # 👨🏼‍✈ man pilot: medium-light skin tone +1F468 1F3FD 200D 2708 FE0F ; fully-qualified # 👨🏽‍✈️ man pilot: medium skin tone +1F468 1F3FD 200D 2708 ; minimally-qualified # 👨🏽‍✈ man pilot: medium skin tone +1F468 1F3FE 200D 2708 FE0F ; fully-qualified # 👨🏾‍✈️ man pilot: medium-dark skin tone +1F468 1F3FE 200D 2708 ; minimally-qualified # 👨🏾‍✈ man pilot: medium-dark skin tone +1F468 1F3FF 200D 2708 FE0F ; fully-qualified # 👨🏿‍✈️ man pilot: dark skin tone +1F468 1F3FF 200D 2708 ; minimally-qualified # 👨🏿‍✈ man pilot: dark skin tone +1F469 200D 2708 FE0F ; fully-qualified # 👩‍✈️ woman pilot +1F469 200D 2708 ; minimally-qualified # 👩‍✈ woman pilot +1F469 1F3FB 200D 2708 FE0F ; fully-qualified # 👩🏻‍✈️ woman pilot: light skin tone +1F469 1F3FB 200D 2708 ; minimally-qualified # 👩🏻‍✈ woman pilot: light skin tone +1F469 1F3FC 200D 2708 FE0F ; fully-qualified # 👩🏼‍✈️ woman pilot: medium-light skin tone +1F469 1F3FC 200D 2708 ; minimally-qualified # 👩🏼‍✈ woman pilot: medium-light skin tone +1F469 1F3FD 200D 2708 FE0F ; fully-qualified # 👩🏽‍✈️ woman pilot: medium skin tone +1F469 1F3FD 200D 2708 ; minimally-qualified # 👩🏽‍✈ woman pilot: medium skin tone +1F469 1F3FE 200D 2708 FE0F ; fully-qualified # 👩🏾‍✈️ woman pilot: medium-dark skin tone +1F469 1F3FE 200D 2708 ; minimally-qualified # 👩🏾‍✈ woman pilot: medium-dark skin tone +1F469 1F3FF 200D 2708 FE0F ; fully-qualified # 👩🏿‍✈️ woman pilot: dark skin tone +1F469 1F3FF 200D 2708 ; minimally-qualified # 👩🏿‍✈ woman pilot: dark skin tone +1F468 200D 1F680 ; fully-qualified # 👨‍🚀 man astronaut +1F468 1F3FB 200D 1F680 ; fully-qualified # 👨🏻‍🚀 man astronaut: light skin tone +1F468 1F3FC 200D 1F680 ; fully-qualified # 👨🏼‍🚀 man astronaut: medium-light skin tone +1F468 1F3FD 200D 1F680 ; fully-qualified # 👨🏽‍🚀 man astronaut: medium skin tone +1F468 1F3FE 200D 1F680 ; fully-qualified # 👨🏾‍🚀 man astronaut: medium-dark skin tone +1F468 1F3FF 200D 1F680 ; fully-qualified # 👨🏿‍🚀 man astronaut: dark skin tone +1F469 200D 1F680 ; fully-qualified # 👩‍🚀 woman astronaut +1F469 1F3FB 200D 1F680 ; fully-qualified # 👩🏻‍🚀 woman astronaut: light skin tone +1F469 1F3FC 200D 1F680 ; fully-qualified # 👩🏼‍🚀 woman astronaut: medium-light skin tone +1F469 1F3FD 200D 1F680 ; fully-qualified # 👩🏽‍🚀 woman astronaut: medium skin tone +1F469 1F3FE 200D 1F680 ; fully-qualified # 👩🏾‍🚀 woman astronaut: medium-dark skin tone +1F469 1F3FF 200D 1F680 ; fully-qualified # 👩🏿‍🚀 woman astronaut: dark skin tone +1F468 200D 1F692 ; fully-qualified # 👨‍🚒 man firefighter +1F468 1F3FB 200D 1F692 ; fully-qualified # 👨🏻‍🚒 man firefighter: light skin tone +1F468 1F3FC 200D 1F692 ; fully-qualified # 👨🏼‍🚒 man firefighter: medium-light skin tone +1F468 1F3FD 200D 1F692 ; fully-qualified # 👨🏽‍🚒 man firefighter: medium skin tone +1F468 1F3FE 200D 1F692 ; fully-qualified # 👨🏾‍🚒 man firefighter: medium-dark skin tone +1F468 1F3FF 200D 1F692 ; fully-qualified # 👨🏿‍🚒 man firefighter: dark skin tone +1F469 200D 1F692 ; fully-qualified # 👩‍🚒 woman firefighter +1F469 1F3FB 200D 1F692 ; fully-qualified # 👩🏻‍🚒 woman firefighter: light skin tone +1F469 1F3FC 200D 1F692 ; fully-qualified # 👩🏼‍🚒 woman firefighter: medium-light skin tone +1F469 1F3FD 200D 1F692 ; fully-qualified # 👩🏽‍🚒 woman firefighter: medium skin tone +1F469 1F3FE 200D 1F692 ; fully-qualified # 👩🏾‍🚒 woman firefighter: medium-dark skin tone +1F469 1F3FF 200D 1F692 ; fully-qualified # 👩🏿‍🚒 woman firefighter: dark skin tone +1F46E ; fully-qualified # 👮 police officer +1F46E 1F3FB ; fully-qualified # 👮🏻 police officer: light skin tone +1F46E 1F3FC ; fully-qualified # 👮🏼 police officer: medium-light skin tone +1F46E 1F3FD ; fully-qualified # 👮🏽 police officer: medium skin tone +1F46E 1F3FE ; fully-qualified # 👮🏾 police officer: medium-dark skin tone +1F46E 1F3FF ; fully-qualified # 👮🏿 police officer: dark skin tone +1F46E 200D 2642 FE0F ; fully-qualified # 👮‍♂️ man police officer +1F46E 200D 2642 ; minimally-qualified # 👮‍♂ man police officer +1F46E 1F3FB 200D 2642 FE0F ; fully-qualified # 👮🏻‍♂️ man police officer: light skin tone +1F46E 1F3FB 200D 2642 ; minimally-qualified # 👮🏻‍♂ man police officer: light skin tone +1F46E 1F3FC 200D 2642 FE0F ; fully-qualified # 👮🏼‍♂️ man police officer: medium-light skin tone +1F46E 1F3FC 200D 2642 ; minimally-qualified # 👮🏼‍♂ man police officer: medium-light skin tone +1F46E 1F3FD 200D 2642 FE0F ; fully-qualified # 👮🏽‍♂️ man police officer: medium skin tone +1F46E 1F3FD 200D 2642 ; minimally-qualified # 👮🏽‍♂ man police officer: medium skin tone +1F46E 1F3FE 200D 2642 FE0F ; fully-qualified # 👮🏾‍♂️ man police officer: medium-dark skin tone +1F46E 1F3FE 200D 2642 ; minimally-qualified # 👮🏾‍♂ man police officer: medium-dark skin tone +1F46E 1F3FF 200D 2642 FE0F ; fully-qualified # 👮🏿‍♂️ man police officer: dark skin tone +1F46E 1F3FF 200D 2642 ; minimally-qualified # 👮🏿‍♂ man police officer: dark skin tone +1F46E 200D 2640 FE0F ; fully-qualified # 👮‍♀️ woman police officer +1F46E 200D 2640 ; minimally-qualified # 👮‍♀ woman police officer +1F46E 1F3FB 200D 2640 FE0F ; fully-qualified # 👮🏻‍♀️ woman police officer: light skin tone +1F46E 1F3FB 200D 2640 ; minimally-qualified # 👮🏻‍♀ woman police officer: light skin tone +1F46E 1F3FC 200D 2640 FE0F ; fully-qualified # 👮🏼‍♀️ woman police officer: medium-light skin tone +1F46E 1F3FC 200D 2640 ; minimally-qualified # 👮🏼‍♀ woman police officer: medium-light skin tone +1F46E 1F3FD 200D 2640 FE0F ; fully-qualified # 👮🏽‍♀️ woman police officer: medium skin tone +1F46E 1F3FD 200D 2640 ; minimally-qualified # 👮🏽‍♀ woman police officer: medium skin tone +1F46E 1F3FE 200D 2640 FE0F ; fully-qualified # 👮🏾‍♀️ woman police officer: medium-dark skin tone +1F46E 1F3FE 200D 2640 ; minimally-qualified # 👮🏾‍♀ woman police officer: medium-dark skin tone +1F46E 1F3FF 200D 2640 FE0F ; fully-qualified # 👮🏿‍♀️ woman police officer: dark skin tone +1F46E 1F3FF 200D 2640 ; minimally-qualified # 👮🏿‍♀ woman police officer: dark skin tone +1F575 FE0F ; fully-qualified # 🕵️ detective +1F575 ; unqualified # 🕵 detective +1F575 1F3FB ; fully-qualified # 🕵🏻 detective: light skin tone +1F575 1F3FC ; fully-qualified # 🕵🏼 detective: medium-light skin tone +1F575 1F3FD ; fully-qualified # 🕵🏽 detective: medium skin tone +1F575 1F3FE ; fully-qualified # 🕵🏾 detective: medium-dark skin tone +1F575 1F3FF ; fully-qualified # 🕵🏿 detective: dark skin tone +1F575 FE0F 200D 2642 FE0F ; fully-qualified # 🕵️‍♂️ man detective +1F575 200D 2642 FE0F ; unqualified # 🕵‍♂️ man detective +1F575 FE0F 200D 2642 ; unqualified # 🕵️‍♂ man detective +1F575 200D 2642 ; unqualified # 🕵‍♂ man detective +1F575 1F3FB 200D 2642 FE0F ; fully-qualified # 🕵🏻‍♂️ man detective: light skin tone +1F575 1F3FB 200D 2642 ; minimally-qualified # 🕵🏻‍♂ man detective: light skin tone +1F575 1F3FC 200D 2642 FE0F ; fully-qualified # 🕵🏼‍♂️ man detective: medium-light skin tone +1F575 1F3FC 200D 2642 ; minimally-qualified # 🕵🏼‍♂ man detective: medium-light skin tone +1F575 1F3FD 200D 2642 FE0F ; fully-qualified # 🕵🏽‍♂️ man detective: medium skin tone +1F575 1F3FD 200D 2642 ; minimally-qualified # 🕵🏽‍♂ man detective: medium skin tone +1F575 1F3FE 200D 2642 FE0F ; fully-qualified # 🕵🏾‍♂️ man detective: medium-dark skin tone +1F575 1F3FE 200D 2642 ; minimally-qualified # 🕵🏾‍♂ man detective: medium-dark skin tone +1F575 1F3FF 200D 2642 FE0F ; fully-qualified # 🕵🏿‍♂️ man detective: dark skin tone +1F575 1F3FF 200D 2642 ; minimally-qualified # 🕵🏿‍♂ man detective: dark skin tone +1F575 FE0F 200D 2640 FE0F ; fully-qualified # 🕵️‍♀️ woman detective +1F575 200D 2640 FE0F ; unqualified # 🕵‍♀️ woman detective +1F575 FE0F 200D 2640 ; unqualified # 🕵️‍♀ woman detective +1F575 200D 2640 ; unqualified # 🕵‍♀ woman detective +1F575 1F3FB 200D 2640 FE0F ; fully-qualified # 🕵🏻‍♀️ woman detective: light skin tone +1F575 1F3FB 200D 2640 ; minimally-qualified # 🕵🏻‍♀ woman detective: light skin tone +1F575 1F3FC 200D 2640 FE0F ; fully-qualified # 🕵🏼‍♀️ woman detective: medium-light skin tone +1F575 1F3FC 200D 2640 ; minimally-qualified # 🕵🏼‍♀ woman detective: medium-light skin tone +1F575 1F3FD 200D 2640 FE0F ; fully-qualified # 🕵🏽‍♀️ woman detective: medium skin tone +1F575 1F3FD 200D 2640 ; minimally-qualified # 🕵🏽‍♀ woman detective: medium skin tone +1F575 1F3FE 200D 2640 FE0F ; fully-qualified # 🕵🏾‍♀️ woman detective: medium-dark skin tone +1F575 1F3FE 200D 2640 ; minimally-qualified # 🕵🏾‍♀ woman detective: medium-dark skin tone +1F575 1F3FF 200D 2640 FE0F ; fully-qualified # 🕵🏿‍♀️ woman detective: dark skin tone +1F575 1F3FF 200D 2640 ; minimally-qualified # 🕵🏿‍♀ woman detective: dark skin tone +1F482 ; fully-qualified # 💂 guard +1F482 1F3FB ; fully-qualified # 💂🏻 guard: light skin tone +1F482 1F3FC ; fully-qualified # 💂🏼 guard: medium-light skin tone +1F482 1F3FD ; fully-qualified # 💂🏽 guard: medium skin tone +1F482 1F3FE ; fully-qualified # 💂🏾 guard: medium-dark skin tone +1F482 1F3FF ; fully-qualified # 💂🏿 guard: dark skin tone +1F482 200D 2642 FE0F ; fully-qualified # 💂‍♂️ man guard +1F482 200D 2642 ; minimally-qualified # 💂‍♂ man guard +1F482 1F3FB 200D 2642 FE0F ; fully-qualified # 💂🏻‍♂️ man guard: light skin tone +1F482 1F3FB 200D 2642 ; minimally-qualified # 💂🏻‍♂ man guard: light skin tone +1F482 1F3FC 200D 2642 FE0F ; fully-qualified # 💂🏼‍♂️ man guard: medium-light skin tone +1F482 1F3FC 200D 2642 ; minimally-qualified # 💂🏼‍♂ man guard: medium-light skin tone +1F482 1F3FD 200D 2642 FE0F ; fully-qualified # 💂🏽‍♂️ man guard: medium skin tone +1F482 1F3FD 200D 2642 ; minimally-qualified # 💂🏽‍♂ man guard: medium skin tone +1F482 1F3FE 200D 2642 FE0F ; fully-qualified # 💂🏾‍♂️ man guard: medium-dark skin tone +1F482 1F3FE 200D 2642 ; minimally-qualified # 💂🏾‍♂ man guard: medium-dark skin tone +1F482 1F3FF 200D 2642 FE0F ; fully-qualified # 💂🏿‍♂️ man guard: dark skin tone +1F482 1F3FF 200D 2642 ; minimally-qualified # 💂🏿‍♂ man guard: dark skin tone +1F482 200D 2640 FE0F ; fully-qualified # 💂‍♀️ woman guard +1F482 200D 2640 ; minimally-qualified # 💂‍♀ woman guard +1F482 1F3FB 200D 2640 FE0F ; fully-qualified # 💂🏻‍♀️ woman guard: light skin tone +1F482 1F3FB 200D 2640 ; minimally-qualified # 💂🏻‍♀ woman guard: light skin tone +1F482 1F3FC 200D 2640 FE0F ; fully-qualified # 💂🏼‍♀️ woman guard: medium-light skin tone +1F482 1F3FC 200D 2640 ; minimally-qualified # 💂🏼‍♀ woman guard: medium-light skin tone +1F482 1F3FD 200D 2640 FE0F ; fully-qualified # 💂🏽‍♀️ woman guard: medium skin tone +1F482 1F3FD 200D 2640 ; minimally-qualified # 💂🏽‍♀ woman guard: medium skin tone +1F482 1F3FE 200D 2640 FE0F ; fully-qualified # 💂🏾‍♀️ woman guard: medium-dark skin tone +1F482 1F3FE 200D 2640 ; minimally-qualified # 💂🏾‍♀ woman guard: medium-dark skin tone +1F482 1F3FF 200D 2640 FE0F ; fully-qualified # 💂🏿‍♀️ woman guard: dark skin tone +1F482 1F3FF 200D 2640 ; minimally-qualified # 💂🏿‍♀ woman guard: dark skin tone +1F477 ; fully-qualified # 👷 construction worker +1F477 1F3FB ; fully-qualified # 👷🏻 construction worker: light skin tone +1F477 1F3FC ; fully-qualified # 👷🏼 construction worker: medium-light skin tone +1F477 1F3FD ; fully-qualified # 👷🏽 construction worker: medium skin tone +1F477 1F3FE ; fully-qualified # 👷🏾 construction worker: medium-dark skin tone +1F477 1F3FF ; fully-qualified # 👷🏿 construction worker: dark skin tone +1F477 200D 2642 FE0F ; fully-qualified # 👷‍♂️ man construction worker +1F477 200D 2642 ; minimally-qualified # 👷‍♂ man construction worker +1F477 1F3FB 200D 2642 FE0F ; fully-qualified # 👷🏻‍♂️ man construction worker: light skin tone +1F477 1F3FB 200D 2642 ; minimally-qualified # 👷🏻‍♂ man construction worker: light skin tone +1F477 1F3FC 200D 2642 FE0F ; fully-qualified # 👷🏼‍♂️ man construction worker: medium-light skin tone +1F477 1F3FC 200D 2642 ; minimally-qualified # 👷🏼‍♂ man construction worker: medium-light skin tone +1F477 1F3FD 200D 2642 FE0F ; fully-qualified # 👷🏽‍♂️ man construction worker: medium skin tone +1F477 1F3FD 200D 2642 ; minimally-qualified # 👷🏽‍♂ man construction worker: medium skin tone +1F477 1F3FE 200D 2642 FE0F ; fully-qualified # 👷🏾‍♂️ man construction worker: medium-dark skin tone +1F477 1F3FE 200D 2642 ; minimally-qualified # 👷🏾‍♂ man construction worker: medium-dark skin tone +1F477 1F3FF 200D 2642 FE0F ; fully-qualified # 👷🏿‍♂️ man construction worker: dark skin tone +1F477 1F3FF 200D 2642 ; minimally-qualified # 👷🏿‍♂ man construction worker: dark skin tone +1F477 200D 2640 FE0F ; fully-qualified # 👷‍♀️ woman construction worker +1F477 200D 2640 ; minimally-qualified # 👷‍♀ woman construction worker +1F477 1F3FB 200D 2640 FE0F ; fully-qualified # 👷🏻‍♀️ woman construction worker: light skin tone +1F477 1F3FB 200D 2640 ; minimally-qualified # 👷🏻‍♀ woman construction worker: light skin tone +1F477 1F3FC 200D 2640 FE0F ; fully-qualified # 👷🏼‍♀️ woman construction worker: medium-light skin tone +1F477 1F3FC 200D 2640 ; minimally-qualified # 👷🏼‍♀ woman construction worker: medium-light skin tone +1F477 1F3FD 200D 2640 FE0F ; fully-qualified # 👷🏽‍♀️ woman construction worker: medium skin tone +1F477 1F3FD 200D 2640 ; minimally-qualified # 👷🏽‍♀ woman construction worker: medium skin tone +1F477 1F3FE 200D 2640 FE0F ; fully-qualified # 👷🏾‍♀️ woman construction worker: medium-dark skin tone +1F477 1F3FE 200D 2640 ; minimally-qualified # 👷🏾‍♀ woman construction worker: medium-dark skin tone +1F477 1F3FF 200D 2640 FE0F ; fully-qualified # 👷🏿‍♀️ woman construction worker: dark skin tone +1F477 1F3FF 200D 2640 ; minimally-qualified # 👷🏿‍♀ woman construction worker: dark skin tone +1F934 ; fully-qualified # 🤴 prince +1F934 1F3FB ; fully-qualified # 🤴🏻 prince: light skin tone +1F934 1F3FC ; fully-qualified # 🤴🏼 prince: medium-light skin tone +1F934 1F3FD ; fully-qualified # 🤴🏽 prince: medium skin tone +1F934 1F3FE ; fully-qualified # 🤴🏾 prince: medium-dark skin tone +1F934 1F3FF ; fully-qualified # 🤴🏿 prince: dark skin tone +1F478 ; fully-qualified # 👸 princess +1F478 1F3FB ; fully-qualified # 👸🏻 princess: light skin tone +1F478 1F3FC ; fully-qualified # 👸🏼 princess: medium-light skin tone +1F478 1F3FD ; fully-qualified # 👸🏽 princess: medium skin tone +1F478 1F3FE ; fully-qualified # 👸🏾 princess: medium-dark skin tone +1F478 1F3FF ; fully-qualified # 👸🏿 princess: dark skin tone +1F473 ; fully-qualified # 👳 person wearing turban +1F473 1F3FB ; fully-qualified # 👳🏻 person wearing turban: light skin tone +1F473 1F3FC ; fully-qualified # 👳🏼 person wearing turban: medium-light skin tone +1F473 1F3FD ; fully-qualified # 👳🏽 person wearing turban: medium skin tone +1F473 1F3FE ; fully-qualified # 👳🏾 person wearing turban: medium-dark skin tone +1F473 1F3FF ; fully-qualified # 👳🏿 person wearing turban: dark skin tone +1F473 200D 2642 FE0F ; fully-qualified # 👳‍♂️ man wearing turban +1F473 200D 2642 ; minimally-qualified # 👳‍♂ man wearing turban +1F473 1F3FB 200D 2642 FE0F ; fully-qualified # 👳🏻‍♂️ man wearing turban: light skin tone +1F473 1F3FB 200D 2642 ; minimally-qualified # 👳🏻‍♂ man wearing turban: light skin tone +1F473 1F3FC 200D 2642 FE0F ; fully-qualified # 👳🏼‍♂️ man wearing turban: medium-light skin tone +1F473 1F3FC 200D 2642 ; minimally-qualified # 👳🏼‍♂ man wearing turban: medium-light skin tone +1F473 1F3FD 200D 2642 FE0F ; fully-qualified # 👳🏽‍♂️ man wearing turban: medium skin tone +1F473 1F3FD 200D 2642 ; minimally-qualified # 👳🏽‍♂ man wearing turban: medium skin tone +1F473 1F3FE 200D 2642 FE0F ; fully-qualified # 👳🏾‍♂️ man wearing turban: medium-dark skin tone +1F473 1F3FE 200D 2642 ; minimally-qualified # 👳🏾‍♂ man wearing turban: medium-dark skin tone +1F473 1F3FF 200D 2642 FE0F ; fully-qualified # 👳🏿‍♂️ man wearing turban: dark skin tone +1F473 1F3FF 200D 2642 ; minimally-qualified # 👳🏿‍♂ man wearing turban: dark skin tone +1F473 200D 2640 FE0F ; fully-qualified # 👳‍♀️ woman wearing turban +1F473 200D 2640 ; minimally-qualified # 👳‍♀ woman wearing turban +1F473 1F3FB 200D 2640 FE0F ; fully-qualified # 👳🏻‍♀️ woman wearing turban: light skin tone +1F473 1F3FB 200D 2640 ; minimally-qualified # 👳🏻‍♀ woman wearing turban: light skin tone +1F473 1F3FC 200D 2640 FE0F ; fully-qualified # 👳🏼‍♀️ woman wearing turban: medium-light skin tone +1F473 1F3FC 200D 2640 ; minimally-qualified # 👳🏼‍♀ woman wearing turban: medium-light skin tone +1F473 1F3FD 200D 2640 FE0F ; fully-qualified # 👳🏽‍♀️ woman wearing turban: medium skin tone +1F473 1F3FD 200D 2640 ; minimally-qualified # 👳🏽‍♀ woman wearing turban: medium skin tone +1F473 1F3FE 200D 2640 FE0F ; fully-qualified # 👳🏾‍♀️ woman wearing turban: medium-dark skin tone +1F473 1F3FE 200D 2640 ; minimally-qualified # 👳🏾‍♀ woman wearing turban: medium-dark skin tone +1F473 1F3FF 200D 2640 FE0F ; fully-qualified # 👳🏿‍♀️ woman wearing turban: dark skin tone +1F473 1F3FF 200D 2640 ; minimally-qualified # 👳🏿‍♀ woman wearing turban: dark skin tone +1F472 ; fully-qualified # 👲 man with Chinese cap +1F472 1F3FB ; fully-qualified # 👲🏻 man with Chinese cap: light skin tone +1F472 1F3FC ; fully-qualified # 👲🏼 man with Chinese cap: medium-light skin tone +1F472 1F3FD ; fully-qualified # 👲🏽 man with Chinese cap: medium skin tone +1F472 1F3FE ; fully-qualified # 👲🏾 man with Chinese cap: medium-dark skin tone +1F472 1F3FF ; fully-qualified # 👲🏿 man with Chinese cap: dark skin tone +1F9D5 ; fully-qualified # 🧕 woman with headscarf +1F9D5 1F3FB ; fully-qualified # 🧕🏻 woman with headscarf: light skin tone +1F9D5 1F3FC ; fully-qualified # 🧕🏼 woman with headscarf: medium-light skin tone +1F9D5 1F3FD ; fully-qualified # 🧕🏽 woman with headscarf: medium skin tone +1F9D5 1F3FE ; fully-qualified # 🧕🏾 woman with headscarf: medium-dark skin tone +1F9D5 1F3FF ; fully-qualified # 🧕🏿 woman with headscarf: dark skin tone +1F935 ; fully-qualified # 🤵 man in tuxedo +1F935 1F3FB ; fully-qualified # 🤵🏻 man in tuxedo: light skin tone +1F935 1F3FC ; fully-qualified # 🤵🏼 man in tuxedo: medium-light skin tone +1F935 1F3FD ; fully-qualified # 🤵🏽 man in tuxedo: medium skin tone +1F935 1F3FE ; fully-qualified # 🤵🏾 man in tuxedo: medium-dark skin tone +1F935 1F3FF ; fully-qualified # 🤵🏿 man in tuxedo: dark skin tone +1F470 ; fully-qualified # 👰 bride with veil +1F470 1F3FB ; fully-qualified # 👰🏻 bride with veil: light skin tone +1F470 1F3FC ; fully-qualified # 👰🏼 bride with veil: medium-light skin tone +1F470 1F3FD ; fully-qualified # 👰🏽 bride with veil: medium skin tone +1F470 1F3FE ; fully-qualified # 👰🏾 bride with veil: medium-dark skin tone +1F470 1F3FF ; fully-qualified # 👰🏿 bride with veil: dark skin tone +1F930 ; fully-qualified # 🤰 pregnant woman +1F930 1F3FB ; fully-qualified # 🤰🏻 pregnant woman: light skin tone +1F930 1F3FC ; fully-qualified # 🤰🏼 pregnant woman: medium-light skin tone +1F930 1F3FD ; fully-qualified # 🤰🏽 pregnant woman: medium skin tone +1F930 1F3FE ; fully-qualified # 🤰🏾 pregnant woman: medium-dark skin tone +1F930 1F3FF ; fully-qualified # 🤰🏿 pregnant woman: dark skin tone +1F931 ; fully-qualified # 🤱 breast-feeding +1F931 1F3FB ; fully-qualified # 🤱🏻 breast-feeding: light skin tone +1F931 1F3FC ; fully-qualified # 🤱🏼 breast-feeding: medium-light skin tone +1F931 1F3FD ; fully-qualified # 🤱🏽 breast-feeding: medium skin tone +1F931 1F3FE ; fully-qualified # 🤱🏾 breast-feeding: medium-dark skin tone +1F931 1F3FF ; fully-qualified # 🤱🏿 breast-feeding: dark skin tone + +# subgroup: person-fantasy +1F47C ; fully-qualified # 👼 baby angel +1F47C 1F3FB ; fully-qualified # 👼🏻 baby angel: light skin tone +1F47C 1F3FC ; fully-qualified # 👼🏼 baby angel: medium-light skin tone +1F47C 1F3FD ; fully-qualified # 👼🏽 baby angel: medium skin tone +1F47C 1F3FE ; fully-qualified # 👼🏾 baby angel: medium-dark skin tone +1F47C 1F3FF ; fully-qualified # 👼🏿 baby angel: dark skin tone +1F385 ; fully-qualified # 🎅 Santa Claus +1F385 1F3FB ; fully-qualified # 🎅🏻 Santa Claus: light skin tone +1F385 1F3FC ; fully-qualified # 🎅🏼 Santa Claus: medium-light skin tone +1F385 1F3FD ; fully-qualified # 🎅🏽 Santa Claus: medium skin tone +1F385 1F3FE ; fully-qualified # 🎅🏾 Santa Claus: medium-dark skin tone +1F385 1F3FF ; fully-qualified # 🎅🏿 Santa Claus: dark skin tone +1F936 ; fully-qualified # 🤶 Mrs. Claus +1F936 1F3FB ; fully-qualified # 🤶🏻 Mrs. Claus: light skin tone +1F936 1F3FC ; fully-qualified # 🤶🏼 Mrs. Claus: medium-light skin tone +1F936 1F3FD ; fully-qualified # 🤶🏽 Mrs. Claus: medium skin tone +1F936 1F3FE ; fully-qualified # 🤶🏾 Mrs. Claus: medium-dark skin tone +1F936 1F3FF ; fully-qualified # 🤶🏿 Mrs. Claus: dark skin tone +1F9B8 ; fully-qualified # 🦸 superhero +1F9B8 1F3FB ; fully-qualified # 🦸🏻 superhero: light skin tone +1F9B8 1F3FC ; fully-qualified # 🦸🏼 superhero: medium-light skin tone +1F9B8 1F3FD ; fully-qualified # 🦸🏽 superhero: medium skin tone +1F9B8 1F3FE ; fully-qualified # 🦸🏾 superhero: medium-dark skin tone +1F9B8 1F3FF ; fully-qualified # 🦸🏿 superhero: dark skin tone +1F9B8 200D 2642 FE0F ; fully-qualified # 🦸‍♂️ man superhero +1F9B8 200D 2642 ; minimally-qualified # 🦸‍♂ man superhero +1F9B8 1F3FB 200D 2642 FE0F ; fully-qualified # 🦸🏻‍♂️ man superhero: light skin tone +1F9B8 1F3FB 200D 2642 ; minimally-qualified # 🦸🏻‍♂ man superhero: light skin tone +1F9B8 1F3FC 200D 2642 FE0F ; fully-qualified # 🦸🏼‍♂️ man superhero: medium-light skin tone +1F9B8 1F3FC 200D 2642 ; minimally-qualified # 🦸🏼‍♂ man superhero: medium-light skin tone +1F9B8 1F3FD 200D 2642 FE0F ; fully-qualified # 🦸🏽‍♂️ man superhero: medium skin tone +1F9B8 1F3FD 200D 2642 ; minimally-qualified # 🦸🏽‍♂ man superhero: medium skin tone +1F9B8 1F3FE 200D 2642 FE0F ; fully-qualified # 🦸🏾‍♂️ man superhero: medium-dark skin tone +1F9B8 1F3FE 200D 2642 ; minimally-qualified # 🦸🏾‍♂ man superhero: medium-dark skin tone +1F9B8 1F3FF 200D 2642 FE0F ; fully-qualified # 🦸🏿‍♂️ man superhero: dark skin tone +1F9B8 1F3FF 200D 2642 ; minimally-qualified # 🦸🏿‍♂ man superhero: dark skin tone +1F9B8 200D 2640 FE0F ; fully-qualified # 🦸‍♀️ woman superhero +1F9B8 200D 2640 ; minimally-qualified # 🦸‍♀ woman superhero +1F9B8 1F3FB 200D 2640 FE0F ; fully-qualified # 🦸🏻‍♀️ woman superhero: light skin tone +1F9B8 1F3FB 200D 2640 ; minimally-qualified # 🦸🏻‍♀ woman superhero: light skin tone +1F9B8 1F3FC 200D 2640 FE0F ; fully-qualified # 🦸🏼‍♀️ woman superhero: medium-light skin tone +1F9B8 1F3FC 200D 2640 ; minimally-qualified # 🦸🏼‍♀ woman superhero: medium-light skin tone +1F9B8 1F3FD 200D 2640 FE0F ; fully-qualified # 🦸🏽‍♀️ woman superhero: medium skin tone +1F9B8 1F3FD 200D 2640 ; minimally-qualified # 🦸🏽‍♀ woman superhero: medium skin tone +1F9B8 1F3FE 200D 2640 FE0F ; fully-qualified # 🦸🏾‍♀️ woman superhero: medium-dark skin tone +1F9B8 1F3FE 200D 2640 ; minimally-qualified # 🦸🏾‍♀ woman superhero: medium-dark skin tone +1F9B8 1F3FF 200D 2640 FE0F ; fully-qualified # 🦸🏿‍♀️ woman superhero: dark skin tone +1F9B8 1F3FF 200D 2640 ; minimally-qualified # 🦸🏿‍♀ woman superhero: dark skin tone +1F9B9 ; fully-qualified # 🦹 supervillain +1F9B9 1F3FB ; fully-qualified # 🦹🏻 supervillain: light skin tone +1F9B9 1F3FC ; fully-qualified # 🦹🏼 supervillain: medium-light skin tone +1F9B9 1F3FD ; fully-qualified # 🦹🏽 supervillain: medium skin tone +1F9B9 1F3FE ; fully-qualified # 🦹🏾 supervillain: medium-dark skin tone +1F9B9 1F3FF ; fully-qualified # 🦹🏿 supervillain: dark skin tone +1F9B9 200D 2642 FE0F ; fully-qualified # 🦹‍♂️ man supervillain +1F9B9 200D 2642 ; minimally-qualified # 🦹‍♂ man supervillain +1F9B9 1F3FB 200D 2642 FE0F ; fully-qualified # 🦹🏻‍♂️ man supervillain: light skin tone +1F9B9 1F3FB 200D 2642 ; minimally-qualified # 🦹🏻‍♂ man supervillain: light skin tone +1F9B9 1F3FC 200D 2642 FE0F ; fully-qualified # 🦹🏼‍♂️ man supervillain: medium-light skin tone +1F9B9 1F3FC 200D 2642 ; minimally-qualified # 🦹🏼‍♂ man supervillain: medium-light skin tone +1F9B9 1F3FD 200D 2642 FE0F ; fully-qualified # 🦹🏽‍♂️ man supervillain: medium skin tone +1F9B9 1F3FD 200D 2642 ; minimally-qualified # 🦹🏽‍♂ man supervillain: medium skin tone +1F9B9 1F3FE 200D 2642 FE0F ; fully-qualified # 🦹🏾‍♂️ man supervillain: medium-dark skin tone +1F9B9 1F3FE 200D 2642 ; minimally-qualified # 🦹🏾‍♂ man supervillain: medium-dark skin tone +1F9B9 1F3FF 200D 2642 FE0F ; fully-qualified # 🦹🏿‍♂️ man supervillain: dark skin tone +1F9B9 1F3FF 200D 2642 ; minimally-qualified # 🦹🏿‍♂ man supervillain: dark skin tone +1F9B9 200D 2640 FE0F ; fully-qualified # 🦹‍♀️ woman supervillain +1F9B9 200D 2640 ; minimally-qualified # 🦹‍♀ woman supervillain +1F9B9 1F3FB 200D 2640 FE0F ; fully-qualified # 🦹🏻‍♀️ woman supervillain: light skin tone +1F9B9 1F3FB 200D 2640 ; minimally-qualified # 🦹🏻‍♀ woman supervillain: light skin tone +1F9B9 1F3FC 200D 2640 FE0F ; fully-qualified # 🦹🏼‍♀️ woman supervillain: medium-light skin tone +1F9B9 1F3FC 200D 2640 ; minimally-qualified # 🦹🏼‍♀ woman supervillain: medium-light skin tone +1F9B9 1F3FD 200D 2640 FE0F ; fully-qualified # 🦹🏽‍♀️ woman supervillain: medium skin tone +1F9B9 1F3FD 200D 2640 ; minimally-qualified # 🦹🏽‍♀ woman supervillain: medium skin tone +1F9B9 1F3FE 200D 2640 FE0F ; fully-qualified # 🦹🏾‍♀️ woman supervillain: medium-dark skin tone +1F9B9 1F3FE 200D 2640 ; minimally-qualified # 🦹🏾‍♀ woman supervillain: medium-dark skin tone +1F9B9 1F3FF 200D 2640 FE0F ; fully-qualified # 🦹🏿‍♀️ woman supervillain: dark skin tone +1F9B9 1F3FF 200D 2640 ; minimally-qualified # 🦹🏿‍♀ woman supervillain: dark skin tone +1F9D9 ; fully-qualified # 🧙 mage +1F9D9 1F3FB ; fully-qualified # 🧙🏻 mage: light skin tone +1F9D9 1F3FC ; fully-qualified # 🧙🏼 mage: medium-light skin tone +1F9D9 1F3FD ; fully-qualified # 🧙🏽 mage: medium skin tone +1F9D9 1F3FE ; fully-qualified # 🧙🏾 mage: medium-dark skin tone +1F9D9 1F3FF ; fully-qualified # 🧙🏿 mage: dark skin tone +1F9D9 200D 2642 FE0F ; fully-qualified # 🧙‍♂️ man mage +1F9D9 200D 2642 ; minimally-qualified # 🧙‍♂ man mage +1F9D9 1F3FB 200D 2642 FE0F ; fully-qualified # 🧙🏻‍♂️ man mage: light skin tone +1F9D9 1F3FB 200D 2642 ; minimally-qualified # 🧙🏻‍♂ man mage: light skin tone +1F9D9 1F3FC 200D 2642 FE0F ; fully-qualified # 🧙🏼‍♂️ man mage: medium-light skin tone +1F9D9 1F3FC 200D 2642 ; minimally-qualified # 🧙🏼‍♂ man mage: medium-light skin tone +1F9D9 1F3FD 200D 2642 FE0F ; fully-qualified # 🧙🏽‍♂️ man mage: medium skin tone +1F9D9 1F3FD 200D 2642 ; minimally-qualified # 🧙🏽‍♂ man mage: medium skin tone +1F9D9 1F3FE 200D 2642 FE0F ; fully-qualified # 🧙🏾‍♂️ man mage: medium-dark skin tone +1F9D9 1F3FE 200D 2642 ; minimally-qualified # 🧙🏾‍♂ man mage: medium-dark skin tone +1F9D9 1F3FF 200D 2642 FE0F ; fully-qualified # 🧙🏿‍♂️ man mage: dark skin tone +1F9D9 1F3FF 200D 2642 ; minimally-qualified # 🧙🏿‍♂ man mage: dark skin tone +1F9D9 200D 2640 FE0F ; fully-qualified # 🧙‍♀️ woman mage +1F9D9 200D 2640 ; minimally-qualified # 🧙‍♀ woman mage +1F9D9 1F3FB 200D 2640 FE0F ; fully-qualified # 🧙🏻‍♀️ woman mage: light skin tone +1F9D9 1F3FB 200D 2640 ; minimally-qualified # 🧙🏻‍♀ woman mage: light skin tone +1F9D9 1F3FC 200D 2640 FE0F ; fully-qualified # 🧙🏼‍♀️ woman mage: medium-light skin tone +1F9D9 1F3FC 200D 2640 ; minimally-qualified # 🧙🏼‍♀ woman mage: medium-light skin tone +1F9D9 1F3FD 200D 2640 FE0F ; fully-qualified # 🧙🏽‍♀️ woman mage: medium skin tone +1F9D9 1F3FD 200D 2640 ; minimally-qualified # 🧙🏽‍♀ woman mage: medium skin tone +1F9D9 1F3FE 200D 2640 FE0F ; fully-qualified # 🧙🏾‍♀️ woman mage: medium-dark skin tone +1F9D9 1F3FE 200D 2640 ; minimally-qualified # 🧙🏾‍♀ woman mage: medium-dark skin tone +1F9D9 1F3FF 200D 2640 FE0F ; fully-qualified # 🧙🏿‍♀️ woman mage: dark skin tone +1F9D9 1F3FF 200D 2640 ; minimally-qualified # 🧙🏿‍♀ woman mage: dark skin tone +1F9DA ; fully-qualified # 🧚 fairy +1F9DA 1F3FB ; fully-qualified # 🧚🏻 fairy: light skin tone +1F9DA 1F3FC ; fully-qualified # 🧚🏼 fairy: medium-light skin tone +1F9DA 1F3FD ; fully-qualified # 🧚🏽 fairy: medium skin tone +1F9DA 1F3FE ; fully-qualified # 🧚🏾 fairy: medium-dark skin tone +1F9DA 1F3FF ; fully-qualified # 🧚🏿 fairy: dark skin tone +1F9DA 200D 2642 FE0F ; fully-qualified # 🧚‍♂️ man fairy +1F9DA 200D 2642 ; minimally-qualified # 🧚‍♂ man fairy +1F9DA 1F3FB 200D 2642 FE0F ; fully-qualified # 🧚🏻‍♂️ man fairy: light skin tone +1F9DA 1F3FB 200D 2642 ; minimally-qualified # 🧚🏻‍♂ man fairy: light skin tone +1F9DA 1F3FC 200D 2642 FE0F ; fully-qualified # 🧚🏼‍♂️ man fairy: medium-light skin tone +1F9DA 1F3FC 200D 2642 ; minimally-qualified # 🧚🏼‍♂ man fairy: medium-light skin tone +1F9DA 1F3FD 200D 2642 FE0F ; fully-qualified # 🧚🏽‍♂️ man fairy: medium skin tone +1F9DA 1F3FD 200D 2642 ; minimally-qualified # 🧚🏽‍♂ man fairy: medium skin tone +1F9DA 1F3FE 200D 2642 FE0F ; fully-qualified # 🧚🏾‍♂️ man fairy: medium-dark skin tone +1F9DA 1F3FE 200D 2642 ; minimally-qualified # 🧚🏾‍♂ man fairy: medium-dark skin tone +1F9DA 1F3FF 200D 2642 FE0F ; fully-qualified # 🧚🏿‍♂️ man fairy: dark skin tone +1F9DA 1F3FF 200D 2642 ; minimally-qualified # 🧚🏿‍♂ man fairy: dark skin tone +1F9DA 200D 2640 FE0F ; fully-qualified # 🧚‍♀️ woman fairy +1F9DA 200D 2640 ; minimally-qualified # 🧚‍♀ woman fairy +1F9DA 1F3FB 200D 2640 FE0F ; fully-qualified # 🧚🏻‍♀️ woman fairy: light skin tone +1F9DA 1F3FB 200D 2640 ; minimally-qualified # 🧚🏻‍♀ woman fairy: light skin tone +1F9DA 1F3FC 200D 2640 FE0F ; fully-qualified # 🧚🏼‍♀️ woman fairy: medium-light skin tone +1F9DA 1F3FC 200D 2640 ; minimally-qualified # 🧚🏼‍♀ woman fairy: medium-light skin tone +1F9DA 1F3FD 200D 2640 FE0F ; fully-qualified # 🧚🏽‍♀️ woman fairy: medium skin tone +1F9DA 1F3FD 200D 2640 ; minimally-qualified # 🧚🏽‍♀ woman fairy: medium skin tone +1F9DA 1F3FE 200D 2640 FE0F ; fully-qualified # 🧚🏾‍♀️ woman fairy: medium-dark skin tone +1F9DA 1F3FE 200D 2640 ; minimally-qualified # 🧚🏾‍♀ woman fairy: medium-dark skin tone +1F9DA 1F3FF 200D 2640 FE0F ; fully-qualified # 🧚🏿‍♀️ woman fairy: dark skin tone +1F9DA 1F3FF 200D 2640 ; minimally-qualified # 🧚🏿‍♀ woman fairy: dark skin tone +1F9DB ; fully-qualified # 🧛 vampire +1F9DB 1F3FB ; fully-qualified # 🧛🏻 vampire: light skin tone +1F9DB 1F3FC ; fully-qualified # 🧛🏼 vampire: medium-light skin tone +1F9DB 1F3FD ; fully-qualified # 🧛🏽 vampire: medium skin tone +1F9DB 1F3FE ; fully-qualified # 🧛🏾 vampire: medium-dark skin tone +1F9DB 1F3FF ; fully-qualified # 🧛🏿 vampire: dark skin tone +1F9DB 200D 2642 FE0F ; fully-qualified # 🧛‍♂️ man vampire +1F9DB 200D 2642 ; minimally-qualified # 🧛‍♂ man vampire +1F9DB 1F3FB 200D 2642 FE0F ; fully-qualified # 🧛🏻‍♂️ man vampire: light skin tone +1F9DB 1F3FB 200D 2642 ; minimally-qualified # 🧛🏻‍♂ man vampire: light skin tone +1F9DB 1F3FC 200D 2642 FE0F ; fully-qualified # 🧛🏼‍♂️ man vampire: medium-light skin tone +1F9DB 1F3FC 200D 2642 ; minimally-qualified # 🧛🏼‍♂ man vampire: medium-light skin tone +1F9DB 1F3FD 200D 2642 FE0F ; fully-qualified # 🧛🏽‍♂️ man vampire: medium skin tone +1F9DB 1F3FD 200D 2642 ; minimally-qualified # 🧛🏽‍♂ man vampire: medium skin tone +1F9DB 1F3FE 200D 2642 FE0F ; fully-qualified # 🧛🏾‍♂️ man vampire: medium-dark skin tone +1F9DB 1F3FE 200D 2642 ; minimally-qualified # 🧛🏾‍♂ man vampire: medium-dark skin tone +1F9DB 1F3FF 200D 2642 FE0F ; fully-qualified # 🧛🏿‍♂️ man vampire: dark skin tone +1F9DB 1F3FF 200D 2642 ; minimally-qualified # 🧛🏿‍♂ man vampire: dark skin tone +1F9DB 200D 2640 FE0F ; fully-qualified # 🧛‍♀️ woman vampire +1F9DB 200D 2640 ; minimally-qualified # 🧛‍♀ woman vampire +1F9DB 1F3FB 200D 2640 FE0F ; fully-qualified # 🧛🏻‍♀️ woman vampire: light skin tone +1F9DB 1F3FB 200D 2640 ; minimally-qualified # 🧛🏻‍♀ woman vampire: light skin tone +1F9DB 1F3FC 200D 2640 FE0F ; fully-qualified # 🧛🏼‍♀️ woman vampire: medium-light skin tone +1F9DB 1F3FC 200D 2640 ; minimally-qualified # 🧛🏼‍♀ woman vampire: medium-light skin tone +1F9DB 1F3FD 200D 2640 FE0F ; fully-qualified # 🧛🏽‍♀️ woman vampire: medium skin tone +1F9DB 1F3FD 200D 2640 ; minimally-qualified # 🧛🏽‍♀ woman vampire: medium skin tone +1F9DB 1F3FE 200D 2640 FE0F ; fully-qualified # 🧛🏾‍♀️ woman vampire: medium-dark skin tone +1F9DB 1F3FE 200D 2640 ; minimally-qualified # 🧛🏾‍♀ woman vampire: medium-dark skin tone +1F9DB 1F3FF 200D 2640 FE0F ; fully-qualified # 🧛🏿‍♀️ woman vampire: dark skin tone +1F9DB 1F3FF 200D 2640 ; minimally-qualified # 🧛🏿‍♀ woman vampire: dark skin tone +1F9DC ; fully-qualified # 🧜 merperson +1F9DC 1F3FB ; fully-qualified # 🧜🏻 merperson: light skin tone +1F9DC 1F3FC ; fully-qualified # 🧜🏼 merperson: medium-light skin tone +1F9DC 1F3FD ; fully-qualified # 🧜🏽 merperson: medium skin tone +1F9DC 1F3FE ; fully-qualified # 🧜🏾 merperson: medium-dark skin tone +1F9DC 1F3FF ; fully-qualified # 🧜🏿 merperson: dark skin tone +1F9DC 200D 2642 FE0F ; fully-qualified # 🧜‍♂️ merman +1F9DC 200D 2642 ; minimally-qualified # 🧜‍♂ merman +1F9DC 1F3FB 200D 2642 FE0F ; fully-qualified # 🧜🏻‍♂️ merman: light skin tone +1F9DC 1F3FB 200D 2642 ; minimally-qualified # 🧜🏻‍♂ merman: light skin tone +1F9DC 1F3FC 200D 2642 FE0F ; fully-qualified # 🧜🏼‍♂️ merman: medium-light skin tone +1F9DC 1F3FC 200D 2642 ; minimally-qualified # 🧜🏼‍♂ merman: medium-light skin tone +1F9DC 1F3FD 200D 2642 FE0F ; fully-qualified # 🧜🏽‍♂️ merman: medium skin tone +1F9DC 1F3FD 200D 2642 ; minimally-qualified # 🧜🏽‍♂ merman: medium skin tone +1F9DC 1F3FE 200D 2642 FE0F ; fully-qualified # 🧜🏾‍♂️ merman: medium-dark skin tone +1F9DC 1F3FE 200D 2642 ; minimally-qualified # 🧜🏾‍♂ merman: medium-dark skin tone +1F9DC 1F3FF 200D 2642 FE0F ; fully-qualified # 🧜🏿‍♂️ merman: dark skin tone +1F9DC 1F3FF 200D 2642 ; minimally-qualified # 🧜🏿‍♂ merman: dark skin tone +1F9DC 200D 2640 FE0F ; fully-qualified # 🧜‍♀️ mermaid +1F9DC 200D 2640 ; minimally-qualified # 🧜‍♀ mermaid +1F9DC 1F3FB 200D 2640 FE0F ; fully-qualified # 🧜🏻‍♀️ mermaid: light skin tone +1F9DC 1F3FB 200D 2640 ; minimally-qualified # 🧜🏻‍♀ mermaid: light skin tone +1F9DC 1F3FC 200D 2640 FE0F ; fully-qualified # 🧜🏼‍♀️ mermaid: medium-light skin tone +1F9DC 1F3FC 200D 2640 ; minimally-qualified # 🧜🏼‍♀ mermaid: medium-light skin tone +1F9DC 1F3FD 200D 2640 FE0F ; fully-qualified # 🧜🏽‍♀️ mermaid: medium skin tone +1F9DC 1F3FD 200D 2640 ; minimally-qualified # 🧜🏽‍♀ mermaid: medium skin tone +1F9DC 1F3FE 200D 2640 FE0F ; fully-qualified # 🧜🏾‍♀️ mermaid: medium-dark skin tone +1F9DC 1F3FE 200D 2640 ; minimally-qualified # 🧜🏾‍♀ mermaid: medium-dark skin tone +1F9DC 1F3FF 200D 2640 FE0F ; fully-qualified # 🧜🏿‍♀️ mermaid: dark skin tone +1F9DC 1F3FF 200D 2640 ; minimally-qualified # 🧜🏿‍♀ mermaid: dark skin tone +1F9DD ; fully-qualified # 🧝 elf +1F9DD 1F3FB ; fully-qualified # 🧝🏻 elf: light skin tone +1F9DD 1F3FC ; fully-qualified # 🧝🏼 elf: medium-light skin tone +1F9DD 1F3FD ; fully-qualified # 🧝🏽 elf: medium skin tone +1F9DD 1F3FE ; fully-qualified # 🧝🏾 elf: medium-dark skin tone +1F9DD 1F3FF ; fully-qualified # 🧝🏿 elf: dark skin tone +1F9DD 200D 2642 FE0F ; fully-qualified # 🧝‍♂️ man elf +1F9DD 200D 2642 ; minimally-qualified # 🧝‍♂ man elf +1F9DD 1F3FB 200D 2642 FE0F ; fully-qualified # 🧝🏻‍♂️ man elf: light skin tone +1F9DD 1F3FB 200D 2642 ; minimally-qualified # 🧝🏻‍♂ man elf: light skin tone +1F9DD 1F3FC 200D 2642 FE0F ; fully-qualified # 🧝🏼‍♂️ man elf: medium-light skin tone +1F9DD 1F3FC 200D 2642 ; minimally-qualified # 🧝🏼‍♂ man elf: medium-light skin tone +1F9DD 1F3FD 200D 2642 FE0F ; fully-qualified # 🧝🏽‍♂️ man elf: medium skin tone +1F9DD 1F3FD 200D 2642 ; minimally-qualified # 🧝🏽‍♂ man elf: medium skin tone +1F9DD 1F3FE 200D 2642 FE0F ; fully-qualified # 🧝🏾‍♂️ man elf: medium-dark skin tone +1F9DD 1F3FE 200D 2642 ; minimally-qualified # 🧝🏾‍♂ man elf: medium-dark skin tone +1F9DD 1F3FF 200D 2642 FE0F ; fully-qualified # 🧝🏿‍♂️ man elf: dark skin tone +1F9DD 1F3FF 200D 2642 ; minimally-qualified # 🧝🏿‍♂ man elf: dark skin tone +1F9DD 200D 2640 FE0F ; fully-qualified # 🧝‍♀️ woman elf +1F9DD 200D 2640 ; minimally-qualified # 🧝‍♀ woman elf +1F9DD 1F3FB 200D 2640 FE0F ; fully-qualified # 🧝🏻‍♀️ woman elf: light skin tone +1F9DD 1F3FB 200D 2640 ; minimally-qualified # 🧝🏻‍♀ woman elf: light skin tone +1F9DD 1F3FC 200D 2640 FE0F ; fully-qualified # 🧝🏼‍♀️ woman elf: medium-light skin tone +1F9DD 1F3FC 200D 2640 ; minimally-qualified # 🧝🏼‍♀ woman elf: medium-light skin tone +1F9DD 1F3FD 200D 2640 FE0F ; fully-qualified # 🧝🏽‍♀️ woman elf: medium skin tone +1F9DD 1F3FD 200D 2640 ; minimally-qualified # 🧝🏽‍♀ woman elf: medium skin tone +1F9DD 1F3FE 200D 2640 FE0F ; fully-qualified # 🧝🏾‍♀️ woman elf: medium-dark skin tone +1F9DD 1F3FE 200D 2640 ; minimally-qualified # 🧝🏾‍♀ woman elf: medium-dark skin tone +1F9DD 1F3FF 200D 2640 FE0F ; fully-qualified # 🧝🏿‍♀️ woman elf: dark skin tone +1F9DD 1F3FF 200D 2640 ; minimally-qualified # 🧝🏿‍♀ woman elf: dark skin tone +1F9DE ; fully-qualified # 🧞 genie +1F9DE 200D 2642 FE0F ; fully-qualified # 🧞‍♂️ man genie +1F9DE 200D 2642 ; minimally-qualified # 🧞‍♂ man genie +1F9DE 200D 2640 FE0F ; fully-qualified # 🧞‍♀️ woman genie +1F9DE 200D 2640 ; minimally-qualified # 🧞‍♀ woman genie +1F9DF ; fully-qualified # 🧟 zombie +1F9DF 200D 2642 FE0F ; fully-qualified # 🧟‍♂️ man zombie +1F9DF 200D 2642 ; minimally-qualified # 🧟‍♂ man zombie +1F9DF 200D 2640 FE0F ; fully-qualified # 🧟‍♀️ woman zombie +1F9DF 200D 2640 ; minimally-qualified # 🧟‍♀ woman zombie + +# subgroup: person-activity +1F486 ; fully-qualified # 💆 person getting massage +1F486 1F3FB ; fully-qualified # 💆🏻 person getting massage: light skin tone +1F486 1F3FC ; fully-qualified # 💆🏼 person getting massage: medium-light skin tone +1F486 1F3FD ; fully-qualified # 💆🏽 person getting massage: medium skin tone +1F486 1F3FE ; fully-qualified # 💆🏾 person getting massage: medium-dark skin tone +1F486 1F3FF ; fully-qualified # 💆🏿 person getting massage: dark skin tone +1F486 200D 2642 FE0F ; fully-qualified # 💆‍♂️ man getting massage +1F486 200D 2642 ; minimally-qualified # 💆‍♂ man getting massage +1F486 1F3FB 200D 2642 FE0F ; fully-qualified # 💆🏻‍♂️ man getting massage: light skin tone +1F486 1F3FB 200D 2642 ; minimally-qualified # 💆🏻‍♂ man getting massage: light skin tone +1F486 1F3FC 200D 2642 FE0F ; fully-qualified # 💆🏼‍♂️ man getting massage: medium-light skin tone +1F486 1F3FC 200D 2642 ; minimally-qualified # 💆🏼‍♂ man getting massage: medium-light skin tone +1F486 1F3FD 200D 2642 FE0F ; fully-qualified # 💆🏽‍♂️ man getting massage: medium skin tone +1F486 1F3FD 200D 2642 ; minimally-qualified # 💆🏽‍♂ man getting massage: medium skin tone +1F486 1F3FE 200D 2642 FE0F ; fully-qualified # 💆🏾‍♂️ man getting massage: medium-dark skin tone +1F486 1F3FE 200D 2642 ; minimally-qualified # 💆🏾‍♂ man getting massage: medium-dark skin tone +1F486 1F3FF 200D 2642 FE0F ; fully-qualified # 💆🏿‍♂️ man getting massage: dark skin tone +1F486 1F3FF 200D 2642 ; minimally-qualified # 💆🏿‍♂ man getting massage: dark skin tone +1F486 200D 2640 FE0F ; fully-qualified # 💆‍♀️ woman getting massage +1F486 200D 2640 ; minimally-qualified # 💆‍♀ woman getting massage +1F486 1F3FB 200D 2640 FE0F ; fully-qualified # 💆🏻‍♀️ woman getting massage: light skin tone +1F486 1F3FB 200D 2640 ; minimally-qualified # 💆🏻‍♀ woman getting massage: light skin tone +1F486 1F3FC 200D 2640 FE0F ; fully-qualified # 💆🏼‍♀️ woman getting massage: medium-light skin tone +1F486 1F3FC 200D 2640 ; minimally-qualified # 💆🏼‍♀ woman getting massage: medium-light skin tone +1F486 1F3FD 200D 2640 FE0F ; fully-qualified # 💆🏽‍♀️ woman getting massage: medium skin tone +1F486 1F3FD 200D 2640 ; minimally-qualified # 💆🏽‍♀ woman getting massage: medium skin tone +1F486 1F3FE 200D 2640 FE0F ; fully-qualified # 💆🏾‍♀️ woman getting massage: medium-dark skin tone +1F486 1F3FE 200D 2640 ; minimally-qualified # 💆🏾‍♀ woman getting massage: medium-dark skin tone +1F486 1F3FF 200D 2640 FE0F ; fully-qualified # 💆🏿‍♀️ woman getting massage: dark skin tone +1F486 1F3FF 200D 2640 ; minimally-qualified # 💆🏿‍♀ woman getting massage: dark skin tone +1F487 ; fully-qualified # 💇 person getting haircut +1F487 1F3FB ; fully-qualified # 💇🏻 person getting haircut: light skin tone +1F487 1F3FC ; fully-qualified # 💇🏼 person getting haircut: medium-light skin tone +1F487 1F3FD ; fully-qualified # 💇🏽 person getting haircut: medium skin tone +1F487 1F3FE ; fully-qualified # 💇🏾 person getting haircut: medium-dark skin tone +1F487 1F3FF ; fully-qualified # 💇🏿 person getting haircut: dark skin tone +1F487 200D 2642 FE0F ; fully-qualified # 💇‍♂️ man getting haircut +1F487 200D 2642 ; minimally-qualified # 💇‍♂ man getting haircut +1F487 1F3FB 200D 2642 FE0F ; fully-qualified # 💇🏻‍♂️ man getting haircut: light skin tone +1F487 1F3FB 200D 2642 ; minimally-qualified # 💇🏻‍♂ man getting haircut: light skin tone +1F487 1F3FC 200D 2642 FE0F ; fully-qualified # 💇🏼‍♂️ man getting haircut: medium-light skin tone +1F487 1F3FC 200D 2642 ; minimally-qualified # 💇🏼‍♂ man getting haircut: medium-light skin tone +1F487 1F3FD 200D 2642 FE0F ; fully-qualified # 💇🏽‍♂️ man getting haircut: medium skin tone +1F487 1F3FD 200D 2642 ; minimally-qualified # 💇🏽‍♂ man getting haircut: medium skin tone +1F487 1F3FE 200D 2642 FE0F ; fully-qualified # 💇🏾‍♂️ man getting haircut: medium-dark skin tone +1F487 1F3FE 200D 2642 ; minimally-qualified # 💇🏾‍♂ man getting haircut: medium-dark skin tone +1F487 1F3FF 200D 2642 FE0F ; fully-qualified # 💇🏿‍♂️ man getting haircut: dark skin tone +1F487 1F3FF 200D 2642 ; minimally-qualified # 💇🏿‍♂ man getting haircut: dark skin tone +1F487 200D 2640 FE0F ; fully-qualified # 💇‍♀️ woman getting haircut +1F487 200D 2640 ; minimally-qualified # 💇‍♀ woman getting haircut +1F487 1F3FB 200D 2640 FE0F ; fully-qualified # 💇🏻‍♀️ woman getting haircut: light skin tone +1F487 1F3FB 200D 2640 ; minimally-qualified # 💇🏻‍♀ woman getting haircut: light skin tone +1F487 1F3FC 200D 2640 FE0F ; fully-qualified # 💇🏼‍♀️ woman getting haircut: medium-light skin tone +1F487 1F3FC 200D 2640 ; minimally-qualified # 💇🏼‍♀ woman getting haircut: medium-light skin tone +1F487 1F3FD 200D 2640 FE0F ; fully-qualified # 💇🏽‍♀️ woman getting haircut: medium skin tone +1F487 1F3FD 200D 2640 ; minimally-qualified # 💇🏽‍♀ woman getting haircut: medium skin tone +1F487 1F3FE 200D 2640 FE0F ; fully-qualified # 💇🏾‍♀️ woman getting haircut: medium-dark skin tone +1F487 1F3FE 200D 2640 ; minimally-qualified # 💇🏾‍♀ woman getting haircut: medium-dark skin tone +1F487 1F3FF 200D 2640 FE0F ; fully-qualified # 💇🏿‍♀️ woman getting haircut: dark skin tone +1F487 1F3FF 200D 2640 ; minimally-qualified # 💇🏿‍♀ woman getting haircut: dark skin tone +1F6B6 ; fully-qualified # 🚶 person walking +1F6B6 1F3FB ; fully-qualified # 🚶🏻 person walking: light skin tone +1F6B6 1F3FC ; fully-qualified # 🚶🏼 person walking: medium-light skin tone +1F6B6 1F3FD ; fully-qualified # 🚶🏽 person walking: medium skin tone +1F6B6 1F3FE ; fully-qualified # 🚶🏾 person walking: medium-dark skin tone +1F6B6 1F3FF ; fully-qualified # 🚶🏿 person walking: dark skin tone +1F6B6 200D 2642 FE0F ; fully-qualified # 🚶‍♂️ man walking +1F6B6 200D 2642 ; minimally-qualified # 🚶‍♂ man walking +1F6B6 1F3FB 200D 2642 FE0F ; fully-qualified # 🚶🏻‍♂️ man walking: light skin tone +1F6B6 1F3FB 200D 2642 ; minimally-qualified # 🚶🏻‍♂ man walking: light skin tone +1F6B6 1F3FC 200D 2642 FE0F ; fully-qualified # 🚶🏼‍♂️ man walking: medium-light skin tone +1F6B6 1F3FC 200D 2642 ; minimally-qualified # 🚶🏼‍♂ man walking: medium-light skin tone +1F6B6 1F3FD 200D 2642 FE0F ; fully-qualified # 🚶🏽‍♂️ man walking: medium skin tone +1F6B6 1F3FD 200D 2642 ; minimally-qualified # 🚶🏽‍♂ man walking: medium skin tone +1F6B6 1F3FE 200D 2642 FE0F ; fully-qualified # 🚶🏾‍♂️ man walking: medium-dark skin tone +1F6B6 1F3FE 200D 2642 ; minimally-qualified # 🚶🏾‍♂ man walking: medium-dark skin tone +1F6B6 1F3FF 200D 2642 FE0F ; fully-qualified # 🚶🏿‍♂️ man walking: dark skin tone +1F6B6 1F3FF 200D 2642 ; minimally-qualified # 🚶🏿‍♂ man walking: dark skin tone +1F6B6 200D 2640 FE0F ; fully-qualified # 🚶‍♀️ woman walking +1F6B6 200D 2640 ; minimally-qualified # 🚶‍♀ woman walking +1F6B6 1F3FB 200D 2640 FE0F ; fully-qualified # 🚶🏻‍♀️ woman walking: light skin tone +1F6B6 1F3FB 200D 2640 ; minimally-qualified # 🚶🏻‍♀ woman walking: light skin tone +1F6B6 1F3FC 200D 2640 FE0F ; fully-qualified # 🚶🏼‍♀️ woman walking: medium-light skin tone +1F6B6 1F3FC 200D 2640 ; minimally-qualified # 🚶🏼‍♀ woman walking: medium-light skin tone +1F6B6 1F3FD 200D 2640 FE0F ; fully-qualified # 🚶🏽‍♀️ woman walking: medium skin tone +1F6B6 1F3FD 200D 2640 ; minimally-qualified # 🚶🏽‍♀ woman walking: medium skin tone +1F6B6 1F3FE 200D 2640 FE0F ; fully-qualified # 🚶🏾‍♀️ woman walking: medium-dark skin tone +1F6B6 1F3FE 200D 2640 ; minimally-qualified # 🚶🏾‍♀ woman walking: medium-dark skin tone +1F6B6 1F3FF 200D 2640 FE0F ; fully-qualified # 🚶🏿‍♀️ woman walking: dark skin tone +1F6B6 1F3FF 200D 2640 ; minimally-qualified # 🚶🏿‍♀ woman walking: dark skin tone +1F9CD ; fully-qualified # 🧍 person standing +1F9CD 1F3FB ; fully-qualified # 🧍🏻 person standing: light skin tone +1F9CD 1F3FC ; fully-qualified # 🧍🏼 person standing: medium-light skin tone +1F9CD 1F3FD ; fully-qualified # 🧍🏽 person standing: medium skin tone +1F9CD 1F3FE ; fully-qualified # 🧍🏾 person standing: medium-dark skin tone +1F9CD 1F3FF ; fully-qualified # 🧍🏿 person standing: dark skin tone +1F9CD 200D 2642 FE0F ; fully-qualified # 🧍‍♂️ man standing +1F9CD 200D 2642 ; minimally-qualified # 🧍‍♂ man standing +1F9CD 1F3FB 200D 2642 FE0F ; fully-qualified # 🧍🏻‍♂️ man standing: light skin tone +1F9CD 1F3FB 200D 2642 ; minimally-qualified # 🧍🏻‍♂ man standing: light skin tone +1F9CD 1F3FC 200D 2642 FE0F ; fully-qualified # 🧍🏼‍♂️ man standing: medium-light skin tone +1F9CD 1F3FC 200D 2642 ; minimally-qualified # 🧍🏼‍♂ man standing: medium-light skin tone +1F9CD 1F3FD 200D 2642 FE0F ; fully-qualified # 🧍🏽‍♂️ man standing: medium skin tone +1F9CD 1F3FD 200D 2642 ; minimally-qualified # 🧍🏽‍♂ man standing: medium skin tone +1F9CD 1F3FE 200D 2642 FE0F ; fully-qualified # 🧍🏾‍♂️ man standing: medium-dark skin tone +1F9CD 1F3FE 200D 2642 ; minimally-qualified # 🧍🏾‍♂ man standing: medium-dark skin tone +1F9CD 1F3FF 200D 2642 FE0F ; fully-qualified # 🧍🏿‍♂️ man standing: dark skin tone +1F9CD 1F3FF 200D 2642 ; minimally-qualified # 🧍🏿‍♂ man standing: dark skin tone +1F9CD 200D 2640 FE0F ; fully-qualified # 🧍‍♀️ woman standing +1F9CD 200D 2640 ; minimally-qualified # 🧍‍♀ woman standing +1F9CD 1F3FB 200D 2640 FE0F ; fully-qualified # 🧍🏻‍♀️ woman standing: light skin tone +1F9CD 1F3FB 200D 2640 ; minimally-qualified # 🧍🏻‍♀ woman standing: light skin tone +1F9CD 1F3FC 200D 2640 FE0F ; fully-qualified # 🧍🏼‍♀️ woman standing: medium-light skin tone +1F9CD 1F3FC 200D 2640 ; minimally-qualified # 🧍🏼‍♀ woman standing: medium-light skin tone +1F9CD 1F3FD 200D 2640 FE0F ; fully-qualified # 🧍🏽‍♀️ woman standing: medium skin tone +1F9CD 1F3FD 200D 2640 ; minimally-qualified # 🧍🏽‍♀ woman standing: medium skin tone +1F9CD 1F3FE 200D 2640 FE0F ; fully-qualified # 🧍🏾‍♀️ woman standing: medium-dark skin tone +1F9CD 1F3FE 200D 2640 ; minimally-qualified # 🧍🏾‍♀ woman standing: medium-dark skin tone +1F9CD 1F3FF 200D 2640 FE0F ; fully-qualified # 🧍🏿‍♀️ woman standing: dark skin tone +1F9CD 1F3FF 200D 2640 ; minimally-qualified # 🧍🏿‍♀ woman standing: dark skin tone +1F9CE ; fully-qualified # 🧎 person kneeling +1F9CE 1F3FB ; fully-qualified # 🧎🏻 person kneeling: light skin tone +1F9CE 1F3FC ; fully-qualified # 🧎🏼 person kneeling: medium-light skin tone +1F9CE 1F3FD ; fully-qualified # 🧎🏽 person kneeling: medium skin tone +1F9CE 1F3FE ; fully-qualified # 🧎🏾 person kneeling: medium-dark skin tone +1F9CE 1F3FF ; fully-qualified # 🧎🏿 person kneeling: dark skin tone +1F9CE 200D 2642 FE0F ; fully-qualified # 🧎‍♂️ man kneeling +1F9CE 200D 2642 ; minimally-qualified # 🧎‍♂ man kneeling +1F9CE 1F3FB 200D 2642 FE0F ; fully-qualified # 🧎🏻‍♂️ man kneeling: light skin tone +1F9CE 1F3FB 200D 2642 ; minimally-qualified # 🧎🏻‍♂ man kneeling: light skin tone +1F9CE 1F3FC 200D 2642 FE0F ; fully-qualified # 🧎🏼‍♂️ man kneeling: medium-light skin tone +1F9CE 1F3FC 200D 2642 ; minimally-qualified # 🧎🏼‍♂ man kneeling: medium-light skin tone +1F9CE 1F3FD 200D 2642 FE0F ; fully-qualified # 🧎🏽‍♂️ man kneeling: medium skin tone +1F9CE 1F3FD 200D 2642 ; minimally-qualified # 🧎🏽‍♂ man kneeling: medium skin tone +1F9CE 1F3FE 200D 2642 FE0F ; fully-qualified # 🧎🏾‍♂️ man kneeling: medium-dark skin tone +1F9CE 1F3FE 200D 2642 ; minimally-qualified # 🧎🏾‍♂ man kneeling: medium-dark skin tone +1F9CE 1F3FF 200D 2642 FE0F ; fully-qualified # 🧎🏿‍♂️ man kneeling: dark skin tone +1F9CE 1F3FF 200D 2642 ; minimally-qualified # 🧎🏿‍♂ man kneeling: dark skin tone +1F9CE 200D 2640 FE0F ; fully-qualified # 🧎‍♀️ woman kneeling +1F9CE 200D 2640 ; minimally-qualified # 🧎‍♀ woman kneeling +1F9CE 1F3FB 200D 2640 FE0F ; fully-qualified # 🧎🏻‍♀️ woman kneeling: light skin tone +1F9CE 1F3FB 200D 2640 ; minimally-qualified # 🧎🏻‍♀ woman kneeling: light skin tone +1F9CE 1F3FC 200D 2640 FE0F ; fully-qualified # 🧎🏼‍♀️ woman kneeling: medium-light skin tone +1F9CE 1F3FC 200D 2640 ; minimally-qualified # 🧎🏼‍♀ woman kneeling: medium-light skin tone +1F9CE 1F3FD 200D 2640 FE0F ; fully-qualified # 🧎🏽‍♀️ woman kneeling: medium skin tone +1F9CE 1F3FD 200D 2640 ; minimally-qualified # 🧎🏽‍♀ woman kneeling: medium skin tone +1F9CE 1F3FE 200D 2640 FE0F ; fully-qualified # 🧎🏾‍♀️ woman kneeling: medium-dark skin tone +1F9CE 1F3FE 200D 2640 ; minimally-qualified # 🧎🏾‍♀ woman kneeling: medium-dark skin tone +1F9CE 1F3FF 200D 2640 FE0F ; fully-qualified # 🧎🏿‍♀️ woman kneeling: dark skin tone +1F9CE 1F3FF 200D 2640 ; minimally-qualified # 🧎🏿‍♀ woman kneeling: dark skin tone +1F468 200D 1F9AF ; fully-qualified # 👨‍🦯 man with probing cane +1F468 1F3FB 200D 1F9AF ; fully-qualified # 👨🏻‍🦯 man with probing cane: light skin tone +1F468 1F3FC 200D 1F9AF ; fully-qualified # 👨🏼‍🦯 man with probing cane: medium-light skin tone +1F468 1F3FD 200D 1F9AF ; fully-qualified # 👨🏽‍🦯 man with probing cane: medium skin tone +1F468 1F3FE 200D 1F9AF ; fully-qualified # 👨🏾‍🦯 man with probing cane: medium-dark skin tone +1F468 1F3FF 200D 1F9AF ; fully-qualified # 👨🏿‍🦯 man with probing cane: dark skin tone +1F469 200D 1F9AF ; fully-qualified # 👩‍🦯 woman with probing cane +1F469 1F3FB 200D 1F9AF ; fully-qualified # 👩🏻‍🦯 woman with probing cane: light skin tone +1F469 1F3FC 200D 1F9AF ; fully-qualified # 👩🏼‍🦯 woman with probing cane: medium-light skin tone +1F469 1F3FD 200D 1F9AF ; fully-qualified # 👩🏽‍🦯 woman with probing cane: medium skin tone +1F469 1F3FE 200D 1F9AF ; fully-qualified # 👩🏾‍🦯 woman with probing cane: medium-dark skin tone +1F469 1F3FF 200D 1F9AF ; fully-qualified # 👩🏿‍🦯 woman with probing cane: dark skin tone +1F468 200D 1F9BC ; fully-qualified # 👨‍🦼 man in motorized wheelchair +1F468 1F3FB 200D 1F9BC ; fully-qualified # 👨🏻‍🦼 man in motorized wheelchair: light skin tone +1F468 1F3FC 200D 1F9BC ; fully-qualified # 👨🏼‍🦼 man in motorized wheelchair: medium-light skin tone +1F468 1F3FD 200D 1F9BC ; fully-qualified # 👨🏽‍🦼 man in motorized wheelchair: medium skin tone +1F468 1F3FE 200D 1F9BC ; fully-qualified # 👨🏾‍🦼 man in motorized wheelchair: medium-dark skin tone +1F468 1F3FF 200D 1F9BC ; fully-qualified # 👨🏿‍🦼 man in motorized wheelchair: dark skin tone +1F469 200D 1F9BC ; fully-qualified # 👩‍🦼 woman in motorized wheelchair +1F469 1F3FB 200D 1F9BC ; fully-qualified # 👩🏻‍🦼 woman in motorized wheelchair: light skin tone +1F469 1F3FC 200D 1F9BC ; fully-qualified # 👩🏼‍🦼 woman in motorized wheelchair: medium-light skin tone +1F469 1F3FD 200D 1F9BC ; fully-qualified # 👩🏽‍🦼 woman in motorized wheelchair: medium skin tone +1F469 1F3FE 200D 1F9BC ; fully-qualified # 👩🏾‍🦼 woman in motorized wheelchair: medium-dark skin tone +1F469 1F3FF 200D 1F9BC ; fully-qualified # 👩🏿‍🦼 woman in motorized wheelchair: dark skin tone +1F468 200D 1F9BD ; fully-qualified # 👨‍🦽 man in manual wheelchair +1F468 1F3FB 200D 1F9BD ; fully-qualified # 👨🏻‍🦽 man in manual wheelchair: light skin tone +1F468 1F3FC 200D 1F9BD ; fully-qualified # 👨🏼‍🦽 man in manual wheelchair: medium-light skin tone +1F468 1F3FD 200D 1F9BD ; fully-qualified # 👨🏽‍🦽 man in manual wheelchair: medium skin tone +1F468 1F3FE 200D 1F9BD ; fully-qualified # 👨🏾‍🦽 man in manual wheelchair: medium-dark skin tone +1F468 1F3FF 200D 1F9BD ; fully-qualified # 👨🏿‍🦽 man in manual wheelchair: dark skin tone +1F469 200D 1F9BD ; fully-qualified # 👩‍🦽 woman in manual wheelchair +1F469 1F3FB 200D 1F9BD ; fully-qualified # 👩🏻‍🦽 woman in manual wheelchair: light skin tone +1F469 1F3FC 200D 1F9BD ; fully-qualified # 👩🏼‍🦽 woman in manual wheelchair: medium-light skin tone +1F469 1F3FD 200D 1F9BD ; fully-qualified # 👩🏽‍🦽 woman in manual wheelchair: medium skin tone +1F469 1F3FE 200D 1F9BD ; fully-qualified # 👩🏾‍🦽 woman in manual wheelchair: medium-dark skin tone +1F469 1F3FF 200D 1F9BD ; fully-qualified # 👩🏿‍🦽 woman in manual wheelchair: dark skin tone +1F3C3 ; fully-qualified # 🏃 person running +1F3C3 1F3FB ; fully-qualified # 🏃🏻 person running: light skin tone +1F3C3 1F3FC ; fully-qualified # 🏃🏼 person running: medium-light skin tone +1F3C3 1F3FD ; fully-qualified # 🏃🏽 person running: medium skin tone +1F3C3 1F3FE ; fully-qualified # 🏃🏾 person running: medium-dark skin tone +1F3C3 1F3FF ; fully-qualified # 🏃🏿 person running: dark skin tone +1F3C3 200D 2642 FE0F ; fully-qualified # 🏃‍♂️ man running +1F3C3 200D 2642 ; minimally-qualified # 🏃‍♂ man running +1F3C3 1F3FB 200D 2642 FE0F ; fully-qualified # 🏃🏻‍♂️ man running: light skin tone +1F3C3 1F3FB 200D 2642 ; minimally-qualified # 🏃🏻‍♂ man running: light skin tone +1F3C3 1F3FC 200D 2642 FE0F ; fully-qualified # 🏃🏼‍♂️ man running: medium-light skin tone +1F3C3 1F3FC 200D 2642 ; minimally-qualified # 🏃🏼‍♂ man running: medium-light skin tone +1F3C3 1F3FD 200D 2642 FE0F ; fully-qualified # 🏃🏽‍♂️ man running: medium skin tone +1F3C3 1F3FD 200D 2642 ; minimally-qualified # 🏃🏽‍♂ man running: medium skin tone +1F3C3 1F3FE 200D 2642 FE0F ; fully-qualified # 🏃🏾‍♂️ man running: medium-dark skin tone +1F3C3 1F3FE 200D 2642 ; minimally-qualified # 🏃🏾‍♂ man running: medium-dark skin tone +1F3C3 1F3FF 200D 2642 FE0F ; fully-qualified # 🏃🏿‍♂️ man running: dark skin tone +1F3C3 1F3FF 200D 2642 ; minimally-qualified # 🏃🏿‍♂ man running: dark skin tone +1F3C3 200D 2640 FE0F ; fully-qualified # 🏃‍♀️ woman running +1F3C3 200D 2640 ; minimally-qualified # 🏃‍♀ woman running +1F3C3 1F3FB 200D 2640 FE0F ; fully-qualified # 🏃🏻‍♀️ woman running: light skin tone +1F3C3 1F3FB 200D 2640 ; minimally-qualified # 🏃🏻‍♀ woman running: light skin tone +1F3C3 1F3FC 200D 2640 FE0F ; fully-qualified # 🏃🏼‍♀️ woman running: medium-light skin tone +1F3C3 1F3FC 200D 2640 ; minimally-qualified # 🏃🏼‍♀ woman running: medium-light skin tone +1F3C3 1F3FD 200D 2640 FE0F ; fully-qualified # 🏃🏽‍♀️ woman running: medium skin tone +1F3C3 1F3FD 200D 2640 ; minimally-qualified # 🏃🏽‍♀ woman running: medium skin tone +1F3C3 1F3FE 200D 2640 FE0F ; fully-qualified # 🏃🏾‍♀️ woman running: medium-dark skin tone +1F3C3 1F3FE 200D 2640 ; minimally-qualified # 🏃🏾‍♀ woman running: medium-dark skin tone +1F3C3 1F3FF 200D 2640 FE0F ; fully-qualified # 🏃🏿‍♀️ woman running: dark skin tone +1F3C3 1F3FF 200D 2640 ; minimally-qualified # 🏃🏿‍♀ woman running: dark skin tone +1F483 ; fully-qualified # 💃 woman dancing +1F483 1F3FB ; fully-qualified # 💃🏻 woman dancing: light skin tone +1F483 1F3FC ; fully-qualified # 💃🏼 woman dancing: medium-light skin tone +1F483 1F3FD ; fully-qualified # 💃🏽 woman dancing: medium skin tone +1F483 1F3FE ; fully-qualified # 💃🏾 woman dancing: medium-dark skin tone +1F483 1F3FF ; fully-qualified # 💃🏿 woman dancing: dark skin tone +1F57A ; fully-qualified # 🕺 man dancing +1F57A 1F3FB ; fully-qualified # 🕺🏻 man dancing: light skin tone +1F57A 1F3FC ; fully-qualified # 🕺🏼 man dancing: medium-light skin tone +1F57A 1F3FD ; fully-qualified # 🕺🏽 man dancing: medium skin tone +1F57A 1F3FE ; fully-qualified # 🕺🏾 man dancing: medium-dark skin tone +1F57A 1F3FF ; fully-qualified # 🕺🏿 man dancing: dark skin tone +1F574 FE0F ; fully-qualified # 🕴️ man in suit levitating +1F574 ; unqualified # 🕴 man in suit levitating +1F574 1F3FB ; fully-qualified # 🕴🏻 man in suit levitating: light skin tone +1F574 1F3FC ; fully-qualified # 🕴🏼 man in suit levitating: medium-light skin tone +1F574 1F3FD ; fully-qualified # 🕴🏽 man in suit levitating: medium skin tone +1F574 1F3FE ; fully-qualified # 🕴🏾 man in suit levitating: medium-dark skin tone +1F574 1F3FF ; fully-qualified # 🕴🏿 man in suit levitating: dark skin tone +1F46F ; fully-qualified # 👯 people with bunny ears +1F46F 200D 2642 FE0F ; fully-qualified # 👯‍♂️ men with bunny ears +1F46F 200D 2642 ; minimally-qualified # 👯‍♂ men with bunny ears +1F46F 200D 2640 FE0F ; fully-qualified # 👯‍♀️ women with bunny ears +1F46F 200D 2640 ; minimally-qualified # 👯‍♀ women with bunny ears +1F9D6 ; fully-qualified # 🧖 person in steamy room +1F9D6 1F3FB ; fully-qualified # 🧖🏻 person in steamy room: light skin tone +1F9D6 1F3FC ; fully-qualified # 🧖🏼 person in steamy room: medium-light skin tone +1F9D6 1F3FD ; fully-qualified # 🧖🏽 person in steamy room: medium skin tone +1F9D6 1F3FE ; fully-qualified # 🧖🏾 person in steamy room: medium-dark skin tone +1F9D6 1F3FF ; fully-qualified # 🧖🏿 person in steamy room: dark skin tone +1F9D6 200D 2642 FE0F ; fully-qualified # 🧖‍♂️ man in steamy room +1F9D6 200D 2642 ; minimally-qualified # 🧖‍♂ man in steamy room +1F9D6 1F3FB 200D 2642 FE0F ; fully-qualified # 🧖🏻‍♂️ man in steamy room: light skin tone +1F9D6 1F3FB 200D 2642 ; minimally-qualified # 🧖🏻‍♂ man in steamy room: light skin tone +1F9D6 1F3FC 200D 2642 FE0F ; fully-qualified # 🧖🏼‍♂️ man in steamy room: medium-light skin tone +1F9D6 1F3FC 200D 2642 ; minimally-qualified # 🧖🏼‍♂ man in steamy room: medium-light skin tone +1F9D6 1F3FD 200D 2642 FE0F ; fully-qualified # 🧖🏽‍♂️ man in steamy room: medium skin tone +1F9D6 1F3FD 200D 2642 ; minimally-qualified # 🧖🏽‍♂ man in steamy room: medium skin tone +1F9D6 1F3FE 200D 2642 FE0F ; fully-qualified # 🧖🏾‍♂️ man in steamy room: medium-dark skin tone +1F9D6 1F3FE 200D 2642 ; minimally-qualified # 🧖🏾‍♂ man in steamy room: medium-dark skin tone +1F9D6 1F3FF 200D 2642 FE0F ; fully-qualified # 🧖🏿‍♂️ man in steamy room: dark skin tone +1F9D6 1F3FF 200D 2642 ; minimally-qualified # 🧖🏿‍♂ man in steamy room: dark skin tone +1F9D6 200D 2640 FE0F ; fully-qualified # 🧖‍♀️ woman in steamy room +1F9D6 200D 2640 ; minimally-qualified # 🧖‍♀ woman in steamy room +1F9D6 1F3FB 200D 2640 FE0F ; fully-qualified # 🧖🏻‍♀️ woman in steamy room: light skin tone +1F9D6 1F3FB 200D 2640 ; minimally-qualified # 🧖🏻‍♀ woman in steamy room: light skin tone +1F9D6 1F3FC 200D 2640 FE0F ; fully-qualified # 🧖🏼‍♀️ woman in steamy room: medium-light skin tone +1F9D6 1F3FC 200D 2640 ; minimally-qualified # 🧖🏼‍♀ woman in steamy room: medium-light skin tone +1F9D6 1F3FD 200D 2640 FE0F ; fully-qualified # 🧖🏽‍♀️ woman in steamy room: medium skin tone +1F9D6 1F3FD 200D 2640 ; minimally-qualified # 🧖🏽‍♀ woman in steamy room: medium skin tone +1F9D6 1F3FE 200D 2640 FE0F ; fully-qualified # 🧖🏾‍♀️ woman in steamy room: medium-dark skin tone +1F9D6 1F3FE 200D 2640 ; minimally-qualified # 🧖🏾‍♀ woman in steamy room: medium-dark skin tone +1F9D6 1F3FF 200D 2640 FE0F ; fully-qualified # 🧖🏿‍♀️ woman in steamy room: dark skin tone +1F9D6 1F3FF 200D 2640 ; minimally-qualified # 🧖🏿‍♀ woman in steamy room: dark skin tone +1F9D7 ; fully-qualified # 🧗 person climbing +1F9D7 1F3FB ; fully-qualified # 🧗🏻 person climbing: light skin tone +1F9D7 1F3FC ; fully-qualified # 🧗🏼 person climbing: medium-light skin tone +1F9D7 1F3FD ; fully-qualified # 🧗🏽 person climbing: medium skin tone +1F9D7 1F3FE ; fully-qualified # 🧗🏾 person climbing: medium-dark skin tone +1F9D7 1F3FF ; fully-qualified # 🧗🏿 person climbing: dark skin tone +1F9D7 200D 2642 FE0F ; fully-qualified # 🧗‍♂️ man climbing +1F9D7 200D 2642 ; minimally-qualified # 🧗‍♂ man climbing +1F9D7 1F3FB 200D 2642 FE0F ; fully-qualified # 🧗🏻‍♂️ man climbing: light skin tone +1F9D7 1F3FB 200D 2642 ; minimally-qualified # 🧗🏻‍♂ man climbing: light skin tone +1F9D7 1F3FC 200D 2642 FE0F ; fully-qualified # 🧗🏼‍♂️ man climbing: medium-light skin tone +1F9D7 1F3FC 200D 2642 ; minimally-qualified # 🧗🏼‍♂ man climbing: medium-light skin tone +1F9D7 1F3FD 200D 2642 FE0F ; fully-qualified # 🧗🏽‍♂️ man climbing: medium skin tone +1F9D7 1F3FD 200D 2642 ; minimally-qualified # 🧗🏽‍♂ man climbing: medium skin tone +1F9D7 1F3FE 200D 2642 FE0F ; fully-qualified # 🧗🏾‍♂️ man climbing: medium-dark skin tone +1F9D7 1F3FE 200D 2642 ; minimally-qualified # 🧗🏾‍♂ man climbing: medium-dark skin tone +1F9D7 1F3FF 200D 2642 FE0F ; fully-qualified # 🧗🏿‍♂️ man climbing: dark skin tone +1F9D7 1F3FF 200D 2642 ; minimally-qualified # 🧗🏿‍♂ man climbing: dark skin tone +1F9D7 200D 2640 FE0F ; fully-qualified # 🧗‍♀️ woman climbing +1F9D7 200D 2640 ; minimally-qualified # 🧗‍♀ woman climbing +1F9D7 1F3FB 200D 2640 FE0F ; fully-qualified # 🧗🏻‍♀️ woman climbing: light skin tone +1F9D7 1F3FB 200D 2640 ; minimally-qualified # 🧗🏻‍♀ woman climbing: light skin tone +1F9D7 1F3FC 200D 2640 FE0F ; fully-qualified # 🧗🏼‍♀️ woman climbing: medium-light skin tone +1F9D7 1F3FC 200D 2640 ; minimally-qualified # 🧗🏼‍♀ woman climbing: medium-light skin tone +1F9D7 1F3FD 200D 2640 FE0F ; fully-qualified # 🧗🏽‍♀️ woman climbing: medium skin tone +1F9D7 1F3FD 200D 2640 ; minimally-qualified # 🧗🏽‍♀ woman climbing: medium skin tone +1F9D7 1F3FE 200D 2640 FE0F ; fully-qualified # 🧗🏾‍♀️ woman climbing: medium-dark skin tone +1F9D7 1F3FE 200D 2640 ; minimally-qualified # 🧗🏾‍♀ woman climbing: medium-dark skin tone +1F9D7 1F3FF 200D 2640 FE0F ; fully-qualified # 🧗🏿‍♀️ woman climbing: dark skin tone +1F9D7 1F3FF 200D 2640 ; minimally-qualified # 🧗🏿‍♀ woman climbing: dark skin tone + +# subgroup: person-sport +1F93A ; fully-qualified # 🤺 person fencing +1F3C7 ; fully-qualified # 🏇 horse racing +1F3C7 1F3FB ; fully-qualified # 🏇🏻 horse racing: light skin tone +1F3C7 1F3FC ; fully-qualified # 🏇🏼 horse racing: medium-light skin tone +1F3C7 1F3FD ; fully-qualified # 🏇🏽 horse racing: medium skin tone +1F3C7 1F3FE ; fully-qualified # 🏇🏾 horse racing: medium-dark skin tone +1F3C7 1F3FF ; fully-qualified # 🏇🏿 horse racing: dark skin tone +26F7 FE0F ; fully-qualified # ⛷️ skier +26F7 ; unqualified # ⛷ skier +1F3C2 ; fully-qualified # 🏂 snowboarder +1F3C2 1F3FB ; fully-qualified # 🏂🏻 snowboarder: light skin tone +1F3C2 1F3FC ; fully-qualified # 🏂🏼 snowboarder: medium-light skin tone +1F3C2 1F3FD ; fully-qualified # 🏂🏽 snowboarder: medium skin tone +1F3C2 1F3FE ; fully-qualified # 🏂🏾 snowboarder: medium-dark skin tone +1F3C2 1F3FF ; fully-qualified # 🏂🏿 snowboarder: dark skin tone +1F3CC FE0F ; fully-qualified # 🏌️ person golfing +1F3CC ; unqualified # 🏌 person golfing +1F3CC 1F3FB ; fully-qualified # 🏌🏻 person golfing: light skin tone +1F3CC 1F3FC ; fully-qualified # 🏌🏼 person golfing: medium-light skin tone +1F3CC 1F3FD ; fully-qualified # 🏌🏽 person golfing: medium skin tone +1F3CC 1F3FE ; fully-qualified # 🏌🏾 person golfing: medium-dark skin tone +1F3CC 1F3FF ; fully-qualified # 🏌🏿 person golfing: dark skin tone +1F3CC FE0F 200D 2642 FE0F ; fully-qualified # 🏌️‍♂️ man golfing +1F3CC 200D 2642 FE0F ; unqualified # 🏌‍♂️ man golfing +1F3CC FE0F 200D 2642 ; unqualified # 🏌️‍♂ man golfing +1F3CC 200D 2642 ; unqualified # 🏌‍♂ man golfing +1F3CC 1F3FB 200D 2642 FE0F ; fully-qualified # 🏌🏻‍♂️ man golfing: light skin tone +1F3CC 1F3FB 200D 2642 ; minimally-qualified # 🏌🏻‍♂ man golfing: light skin tone +1F3CC 1F3FC 200D 2642 FE0F ; fully-qualified # 🏌🏼‍♂️ man golfing: medium-light skin tone +1F3CC 1F3FC 200D 2642 ; minimally-qualified # 🏌🏼‍♂ man golfing: medium-light skin tone +1F3CC 1F3FD 200D 2642 FE0F ; fully-qualified # 🏌🏽‍♂️ man golfing: medium skin tone +1F3CC 1F3FD 200D 2642 ; minimally-qualified # 🏌🏽‍♂ man golfing: medium skin tone +1F3CC 1F3FE 200D 2642 FE0F ; fully-qualified # 🏌🏾‍♂️ man golfing: medium-dark skin tone +1F3CC 1F3FE 200D 2642 ; minimally-qualified # 🏌🏾‍♂ man golfing: medium-dark skin tone +1F3CC 1F3FF 200D 2642 FE0F ; fully-qualified # 🏌🏿‍♂️ man golfing: dark skin tone +1F3CC 1F3FF 200D 2642 ; minimally-qualified # 🏌🏿‍♂ man golfing: dark skin tone +1F3CC FE0F 200D 2640 FE0F ; fully-qualified # 🏌️‍♀️ woman golfing +1F3CC 200D 2640 FE0F ; unqualified # 🏌‍♀️ woman golfing +1F3CC FE0F 200D 2640 ; unqualified # 🏌️‍♀ woman golfing +1F3CC 200D 2640 ; unqualified # 🏌‍♀ woman golfing +1F3CC 1F3FB 200D 2640 FE0F ; fully-qualified # 🏌🏻‍♀️ woman golfing: light skin tone +1F3CC 1F3FB 200D 2640 ; minimally-qualified # 🏌🏻‍♀ woman golfing: light skin tone +1F3CC 1F3FC 200D 2640 FE0F ; fully-qualified # 🏌🏼‍♀️ woman golfing: medium-light skin tone +1F3CC 1F3FC 200D 2640 ; minimally-qualified # 🏌🏼‍♀ woman golfing: medium-light skin tone +1F3CC 1F3FD 200D 2640 FE0F ; fully-qualified # 🏌🏽‍♀️ woman golfing: medium skin tone +1F3CC 1F3FD 200D 2640 ; minimally-qualified # 🏌🏽‍♀ woman golfing: medium skin tone +1F3CC 1F3FE 200D 2640 FE0F ; fully-qualified # 🏌🏾‍♀️ woman golfing: medium-dark skin tone +1F3CC 1F3FE 200D 2640 ; minimally-qualified # 🏌🏾‍♀ woman golfing: medium-dark skin tone +1F3CC 1F3FF 200D 2640 FE0F ; fully-qualified # 🏌🏿‍♀️ woman golfing: dark skin tone +1F3CC 1F3FF 200D 2640 ; minimally-qualified # 🏌🏿‍♀ woman golfing: dark skin tone +1F3C4 ; fully-qualified # 🏄 person surfing +1F3C4 1F3FB ; fully-qualified # 🏄🏻 person surfing: light skin tone +1F3C4 1F3FC ; fully-qualified # 🏄🏼 person surfing: medium-light skin tone +1F3C4 1F3FD ; fully-qualified # 🏄🏽 person surfing: medium skin tone +1F3C4 1F3FE ; fully-qualified # 🏄🏾 person surfing: medium-dark skin tone +1F3C4 1F3FF ; fully-qualified # 🏄🏿 person surfing: dark skin tone +1F3C4 200D 2642 FE0F ; fully-qualified # 🏄‍♂️ man surfing +1F3C4 200D 2642 ; minimally-qualified # 🏄‍♂ man surfing +1F3C4 1F3FB 200D 2642 FE0F ; fully-qualified # 🏄🏻‍♂️ man surfing: light skin tone +1F3C4 1F3FB 200D 2642 ; minimally-qualified # 🏄🏻‍♂ man surfing: light skin tone +1F3C4 1F3FC 200D 2642 FE0F ; fully-qualified # 🏄🏼‍♂️ man surfing: medium-light skin tone +1F3C4 1F3FC 200D 2642 ; minimally-qualified # 🏄🏼‍♂ man surfing: medium-light skin tone +1F3C4 1F3FD 200D 2642 FE0F ; fully-qualified # 🏄🏽‍♂️ man surfing: medium skin tone +1F3C4 1F3FD 200D 2642 ; minimally-qualified # 🏄🏽‍♂ man surfing: medium skin tone +1F3C4 1F3FE 200D 2642 FE0F ; fully-qualified # 🏄🏾‍♂️ man surfing: medium-dark skin tone +1F3C4 1F3FE 200D 2642 ; minimally-qualified # 🏄🏾‍♂ man surfing: medium-dark skin tone +1F3C4 1F3FF 200D 2642 FE0F ; fully-qualified # 🏄🏿‍♂️ man surfing: dark skin tone +1F3C4 1F3FF 200D 2642 ; minimally-qualified # 🏄🏿‍♂ man surfing: dark skin tone +1F3C4 200D 2640 FE0F ; fully-qualified # 🏄‍♀️ woman surfing +1F3C4 200D 2640 ; minimally-qualified # 🏄‍♀ woman surfing +1F3C4 1F3FB 200D 2640 FE0F ; fully-qualified # 🏄🏻‍♀️ woman surfing: light skin tone +1F3C4 1F3FB 200D 2640 ; minimally-qualified # 🏄🏻‍♀ woman surfing: light skin tone +1F3C4 1F3FC 200D 2640 FE0F ; fully-qualified # 🏄🏼‍♀️ woman surfing: medium-light skin tone +1F3C4 1F3FC 200D 2640 ; minimally-qualified # 🏄🏼‍♀ woman surfing: medium-light skin tone +1F3C4 1F3FD 200D 2640 FE0F ; fully-qualified # 🏄🏽‍♀️ woman surfing: medium skin tone +1F3C4 1F3FD 200D 2640 ; minimally-qualified # 🏄🏽‍♀ woman surfing: medium skin tone +1F3C4 1F3FE 200D 2640 FE0F ; fully-qualified # 🏄🏾‍♀️ woman surfing: medium-dark skin tone +1F3C4 1F3FE 200D 2640 ; minimally-qualified # 🏄🏾‍♀ woman surfing: medium-dark skin tone +1F3C4 1F3FF 200D 2640 FE0F ; fully-qualified # 🏄🏿‍♀️ woman surfing: dark skin tone +1F3C4 1F3FF 200D 2640 ; minimally-qualified # 🏄🏿‍♀ woman surfing: dark skin tone +1F6A3 ; fully-qualified # 🚣 person rowing boat +1F6A3 1F3FB ; fully-qualified # 🚣🏻 person rowing boat: light skin tone +1F6A3 1F3FC ; fully-qualified # 🚣🏼 person rowing boat: medium-light skin tone +1F6A3 1F3FD ; fully-qualified # 🚣🏽 person rowing boat: medium skin tone +1F6A3 1F3FE ; fully-qualified # 🚣🏾 person rowing boat: medium-dark skin tone +1F6A3 1F3FF ; fully-qualified # 🚣🏿 person rowing boat: dark skin tone +1F6A3 200D 2642 FE0F ; fully-qualified # 🚣‍♂️ man rowing boat +1F6A3 200D 2642 ; minimally-qualified # 🚣‍♂ man rowing boat +1F6A3 1F3FB 200D 2642 FE0F ; fully-qualified # 🚣🏻‍♂️ man rowing boat: light skin tone +1F6A3 1F3FB 200D 2642 ; minimally-qualified # 🚣🏻‍♂ man rowing boat: light skin tone +1F6A3 1F3FC 200D 2642 FE0F ; fully-qualified # 🚣🏼‍♂️ man rowing boat: medium-light skin tone +1F6A3 1F3FC 200D 2642 ; minimally-qualified # 🚣🏼‍♂ man rowing boat: medium-light skin tone +1F6A3 1F3FD 200D 2642 FE0F ; fully-qualified # 🚣🏽‍♂️ man rowing boat: medium skin tone +1F6A3 1F3FD 200D 2642 ; minimally-qualified # 🚣🏽‍♂ man rowing boat: medium skin tone +1F6A3 1F3FE 200D 2642 FE0F ; fully-qualified # 🚣🏾‍♂️ man rowing boat: medium-dark skin tone +1F6A3 1F3FE 200D 2642 ; minimally-qualified # 🚣🏾‍♂ man rowing boat: medium-dark skin tone +1F6A3 1F3FF 200D 2642 FE0F ; fully-qualified # 🚣🏿‍♂️ man rowing boat: dark skin tone +1F6A3 1F3FF 200D 2642 ; minimally-qualified # 🚣🏿‍♂ man rowing boat: dark skin tone +1F6A3 200D 2640 FE0F ; fully-qualified # 🚣‍♀️ woman rowing boat +1F6A3 200D 2640 ; minimally-qualified # 🚣‍♀ woman rowing boat +1F6A3 1F3FB 200D 2640 FE0F ; fully-qualified # 🚣🏻‍♀️ woman rowing boat: light skin tone +1F6A3 1F3FB 200D 2640 ; minimally-qualified # 🚣🏻‍♀ woman rowing boat: light skin tone +1F6A3 1F3FC 200D 2640 FE0F ; fully-qualified # 🚣🏼‍♀️ woman rowing boat: medium-light skin tone +1F6A3 1F3FC 200D 2640 ; minimally-qualified # 🚣🏼‍♀ woman rowing boat: medium-light skin tone +1F6A3 1F3FD 200D 2640 FE0F ; fully-qualified # 🚣🏽‍♀️ woman rowing boat: medium skin tone +1F6A3 1F3FD 200D 2640 ; minimally-qualified # 🚣🏽‍♀ woman rowing boat: medium skin tone +1F6A3 1F3FE 200D 2640 FE0F ; fully-qualified # 🚣🏾‍♀️ woman rowing boat: medium-dark skin tone +1F6A3 1F3FE 200D 2640 ; minimally-qualified # 🚣🏾‍♀ woman rowing boat: medium-dark skin tone +1F6A3 1F3FF 200D 2640 FE0F ; fully-qualified # 🚣🏿‍♀️ woman rowing boat: dark skin tone +1F6A3 1F3FF 200D 2640 ; minimally-qualified # 🚣🏿‍♀ woman rowing boat: dark skin tone +1F3CA ; fully-qualified # 🏊 person swimming +1F3CA 1F3FB ; fully-qualified # 🏊🏻 person swimming: light skin tone +1F3CA 1F3FC ; fully-qualified # 🏊🏼 person swimming: medium-light skin tone +1F3CA 1F3FD ; fully-qualified # 🏊🏽 person swimming: medium skin tone +1F3CA 1F3FE ; fully-qualified # 🏊🏾 person swimming: medium-dark skin tone +1F3CA 1F3FF ; fully-qualified # 🏊🏿 person swimming: dark skin tone +1F3CA 200D 2642 FE0F ; fully-qualified # 🏊‍♂️ man swimming +1F3CA 200D 2642 ; minimally-qualified # 🏊‍♂ man swimming +1F3CA 1F3FB 200D 2642 FE0F ; fully-qualified # 🏊🏻‍♂️ man swimming: light skin tone +1F3CA 1F3FB 200D 2642 ; minimally-qualified # 🏊🏻‍♂ man swimming: light skin tone +1F3CA 1F3FC 200D 2642 FE0F ; fully-qualified # 🏊🏼‍♂️ man swimming: medium-light skin tone +1F3CA 1F3FC 200D 2642 ; minimally-qualified # 🏊🏼‍♂ man swimming: medium-light skin tone +1F3CA 1F3FD 200D 2642 FE0F ; fully-qualified # 🏊🏽‍♂️ man swimming: medium skin tone +1F3CA 1F3FD 200D 2642 ; minimally-qualified # 🏊🏽‍♂ man swimming: medium skin tone +1F3CA 1F3FE 200D 2642 FE0F ; fully-qualified # 🏊🏾‍♂️ man swimming: medium-dark skin tone +1F3CA 1F3FE 200D 2642 ; minimally-qualified # 🏊🏾‍♂ man swimming: medium-dark skin tone +1F3CA 1F3FF 200D 2642 FE0F ; fully-qualified # 🏊🏿‍♂️ man swimming: dark skin tone +1F3CA 1F3FF 200D 2642 ; minimally-qualified # 🏊🏿‍♂ man swimming: dark skin tone +1F3CA 200D 2640 FE0F ; fully-qualified # 🏊‍♀️ woman swimming +1F3CA 200D 2640 ; minimally-qualified # 🏊‍♀ woman swimming +1F3CA 1F3FB 200D 2640 FE0F ; fully-qualified # 🏊🏻‍♀️ woman swimming: light skin tone +1F3CA 1F3FB 200D 2640 ; minimally-qualified # 🏊🏻‍♀ woman swimming: light skin tone +1F3CA 1F3FC 200D 2640 FE0F ; fully-qualified # 🏊🏼‍♀️ woman swimming: medium-light skin tone +1F3CA 1F3FC 200D 2640 ; minimally-qualified # 🏊🏼‍♀ woman swimming: medium-light skin tone +1F3CA 1F3FD 200D 2640 FE0F ; fully-qualified # 🏊🏽‍♀️ woman swimming: medium skin tone +1F3CA 1F3FD 200D 2640 ; minimally-qualified # 🏊🏽‍♀ woman swimming: medium skin tone +1F3CA 1F3FE 200D 2640 FE0F ; fully-qualified # 🏊🏾‍♀️ woman swimming: medium-dark skin tone +1F3CA 1F3FE 200D 2640 ; minimally-qualified # 🏊🏾‍♀ woman swimming: medium-dark skin tone +1F3CA 1F3FF 200D 2640 FE0F ; fully-qualified # 🏊🏿‍♀️ woman swimming: dark skin tone +1F3CA 1F3FF 200D 2640 ; minimally-qualified # 🏊🏿‍♀ woman swimming: dark skin tone +26F9 FE0F ; fully-qualified # ⛹️ person bouncing ball +26F9 ; unqualified # ⛹ person bouncing ball +26F9 1F3FB ; fully-qualified # ⛹🏻 person bouncing ball: light skin tone +26F9 1F3FC ; fully-qualified # ⛹🏼 person bouncing ball: medium-light skin tone +26F9 1F3FD ; fully-qualified # ⛹🏽 person bouncing ball: medium skin tone +26F9 1F3FE ; fully-qualified # ⛹🏾 person bouncing ball: medium-dark skin tone +26F9 1F3FF ; fully-qualified # ⛹🏿 person bouncing ball: dark skin tone +26F9 FE0F 200D 2642 FE0F ; fully-qualified # ⛹️‍♂️ man bouncing ball +26F9 200D 2642 FE0F ; unqualified # ⛹‍♂️ man bouncing ball +26F9 FE0F 200D 2642 ; unqualified # ⛹️‍♂ man bouncing ball +26F9 200D 2642 ; unqualified # ⛹‍♂ man bouncing ball +26F9 1F3FB 200D 2642 FE0F ; fully-qualified # ⛹🏻‍♂️ man bouncing ball: light skin tone +26F9 1F3FB 200D 2642 ; minimally-qualified # ⛹🏻‍♂ man bouncing ball: light skin tone +26F9 1F3FC 200D 2642 FE0F ; fully-qualified # ⛹🏼‍♂️ man bouncing ball: medium-light skin tone +26F9 1F3FC 200D 2642 ; minimally-qualified # ⛹🏼‍♂ man bouncing ball: medium-light skin tone +26F9 1F3FD 200D 2642 FE0F ; fully-qualified # ⛹🏽‍♂️ man bouncing ball: medium skin tone +26F9 1F3FD 200D 2642 ; minimally-qualified # ⛹🏽‍♂ man bouncing ball: medium skin tone +26F9 1F3FE 200D 2642 FE0F ; fully-qualified # ⛹🏾‍♂️ man bouncing ball: medium-dark skin tone +26F9 1F3FE 200D 2642 ; minimally-qualified # ⛹🏾‍♂ man bouncing ball: medium-dark skin tone +26F9 1F3FF 200D 2642 FE0F ; fully-qualified # ⛹🏿‍♂️ man bouncing ball: dark skin tone +26F9 1F3FF 200D 2642 ; minimally-qualified # ⛹🏿‍♂ man bouncing ball: dark skin tone +26F9 FE0F 200D 2640 FE0F ; fully-qualified # ⛹️‍♀️ woman bouncing ball +26F9 200D 2640 FE0F ; unqualified # ⛹‍♀️ woman bouncing ball +26F9 FE0F 200D 2640 ; unqualified # ⛹️‍♀ woman bouncing ball +26F9 200D 2640 ; unqualified # ⛹‍♀ woman bouncing ball +26F9 1F3FB 200D 2640 FE0F ; fully-qualified # ⛹🏻‍♀️ woman bouncing ball: light skin tone +26F9 1F3FB 200D 2640 ; minimally-qualified # ⛹🏻‍♀ woman bouncing ball: light skin tone +26F9 1F3FC 200D 2640 FE0F ; fully-qualified # ⛹🏼‍♀️ woman bouncing ball: medium-light skin tone +26F9 1F3FC 200D 2640 ; minimally-qualified # ⛹🏼‍♀ woman bouncing ball: medium-light skin tone +26F9 1F3FD 200D 2640 FE0F ; fully-qualified # ⛹🏽‍♀️ woman bouncing ball: medium skin tone +26F9 1F3FD 200D 2640 ; minimally-qualified # ⛹🏽‍♀ woman bouncing ball: medium skin tone +26F9 1F3FE 200D 2640 FE0F ; fully-qualified # ⛹🏾‍♀️ woman bouncing ball: medium-dark skin tone +26F9 1F3FE 200D 2640 ; minimally-qualified # ⛹🏾‍♀ woman bouncing ball: medium-dark skin tone +26F9 1F3FF 200D 2640 FE0F ; fully-qualified # ⛹🏿‍♀️ woman bouncing ball: dark skin tone +26F9 1F3FF 200D 2640 ; minimally-qualified # ⛹🏿‍♀ woman bouncing ball: dark skin tone +1F3CB FE0F ; fully-qualified # 🏋️ person lifting weights +1F3CB ; unqualified # 🏋 person lifting weights +1F3CB 1F3FB ; fully-qualified # 🏋🏻 person lifting weights: light skin tone +1F3CB 1F3FC ; fully-qualified # 🏋🏼 person lifting weights: medium-light skin tone +1F3CB 1F3FD ; fully-qualified # 🏋🏽 person lifting weights: medium skin tone +1F3CB 1F3FE ; fully-qualified # 🏋🏾 person lifting weights: medium-dark skin tone +1F3CB 1F3FF ; fully-qualified # 🏋🏿 person lifting weights: dark skin tone +1F3CB FE0F 200D 2642 FE0F ; fully-qualified # 🏋️‍♂️ man lifting weights +1F3CB 200D 2642 FE0F ; unqualified # 🏋‍♂️ man lifting weights +1F3CB FE0F 200D 2642 ; unqualified # 🏋️‍♂ man lifting weights +1F3CB 200D 2642 ; unqualified # 🏋‍♂ man lifting weights +1F3CB 1F3FB 200D 2642 FE0F ; fully-qualified # 🏋🏻‍♂️ man lifting weights: light skin tone +1F3CB 1F3FB 200D 2642 ; minimally-qualified # 🏋🏻‍♂ man lifting weights: light skin tone +1F3CB 1F3FC 200D 2642 FE0F ; fully-qualified # 🏋🏼‍♂️ man lifting weights: medium-light skin tone +1F3CB 1F3FC 200D 2642 ; minimally-qualified # 🏋🏼‍♂ man lifting weights: medium-light skin tone +1F3CB 1F3FD 200D 2642 FE0F ; fully-qualified # 🏋🏽‍♂️ man lifting weights: medium skin tone +1F3CB 1F3FD 200D 2642 ; minimally-qualified # 🏋🏽‍♂ man lifting weights: medium skin tone +1F3CB 1F3FE 200D 2642 FE0F ; fully-qualified # 🏋🏾‍♂️ man lifting weights: medium-dark skin tone +1F3CB 1F3FE 200D 2642 ; minimally-qualified # 🏋🏾‍♂ man lifting weights: medium-dark skin tone +1F3CB 1F3FF 200D 2642 FE0F ; fully-qualified # 🏋🏿‍♂️ man lifting weights: dark skin tone +1F3CB 1F3FF 200D 2642 ; minimally-qualified # 🏋🏿‍♂ man lifting weights: dark skin tone +1F3CB FE0F 200D 2640 FE0F ; fully-qualified # 🏋️‍♀️ woman lifting weights +1F3CB 200D 2640 FE0F ; unqualified # 🏋‍♀️ woman lifting weights +1F3CB FE0F 200D 2640 ; unqualified # 🏋️‍♀ woman lifting weights +1F3CB 200D 2640 ; unqualified # 🏋‍♀ woman lifting weights +1F3CB 1F3FB 200D 2640 FE0F ; fully-qualified # 🏋🏻‍♀️ woman lifting weights: light skin tone +1F3CB 1F3FB 200D 2640 ; minimally-qualified # 🏋🏻‍♀ woman lifting weights: light skin tone +1F3CB 1F3FC 200D 2640 FE0F ; fully-qualified # 🏋🏼‍♀️ woman lifting weights: medium-light skin tone +1F3CB 1F3FC 200D 2640 ; minimally-qualified # 🏋🏼‍♀ woman lifting weights: medium-light skin tone +1F3CB 1F3FD 200D 2640 FE0F ; fully-qualified # 🏋🏽‍♀️ woman lifting weights: medium skin tone +1F3CB 1F3FD 200D 2640 ; minimally-qualified # 🏋🏽‍♀ woman lifting weights: medium skin tone +1F3CB 1F3FE 200D 2640 FE0F ; fully-qualified # 🏋🏾‍♀️ woman lifting weights: medium-dark skin tone +1F3CB 1F3FE 200D 2640 ; minimally-qualified # 🏋🏾‍♀ woman lifting weights: medium-dark skin tone +1F3CB 1F3FF 200D 2640 FE0F ; fully-qualified # 🏋🏿‍♀️ woman lifting weights: dark skin tone +1F3CB 1F3FF 200D 2640 ; minimally-qualified # 🏋🏿‍♀ woman lifting weights: dark skin tone +1F6B4 ; fully-qualified # 🚴 person biking +1F6B4 1F3FB ; fully-qualified # 🚴🏻 person biking: light skin tone +1F6B4 1F3FC ; fully-qualified # 🚴🏼 person biking: medium-light skin tone +1F6B4 1F3FD ; fully-qualified # 🚴🏽 person biking: medium skin tone +1F6B4 1F3FE ; fully-qualified # 🚴🏾 person biking: medium-dark skin tone +1F6B4 1F3FF ; fully-qualified # 🚴🏿 person biking: dark skin tone +1F6B4 200D 2642 FE0F ; fully-qualified # 🚴‍♂️ man biking +1F6B4 200D 2642 ; minimally-qualified # 🚴‍♂ man biking +1F6B4 1F3FB 200D 2642 FE0F ; fully-qualified # 🚴🏻‍♂️ man biking: light skin tone +1F6B4 1F3FB 200D 2642 ; minimally-qualified # 🚴🏻‍♂ man biking: light skin tone +1F6B4 1F3FC 200D 2642 FE0F ; fully-qualified # 🚴🏼‍♂️ man biking: medium-light skin tone +1F6B4 1F3FC 200D 2642 ; minimally-qualified # 🚴🏼‍♂ man biking: medium-light skin tone +1F6B4 1F3FD 200D 2642 FE0F ; fully-qualified # 🚴🏽‍♂️ man biking: medium skin tone +1F6B4 1F3FD 200D 2642 ; minimally-qualified # 🚴🏽‍♂ man biking: medium skin tone +1F6B4 1F3FE 200D 2642 FE0F ; fully-qualified # 🚴🏾‍♂️ man biking: medium-dark skin tone +1F6B4 1F3FE 200D 2642 ; minimally-qualified # 🚴🏾‍♂ man biking: medium-dark skin tone +1F6B4 1F3FF 200D 2642 FE0F ; fully-qualified # 🚴🏿‍♂️ man biking: dark skin tone +1F6B4 1F3FF 200D 2642 ; minimally-qualified # 🚴🏿‍♂ man biking: dark skin tone +1F6B4 200D 2640 FE0F ; fully-qualified # 🚴‍♀️ woman biking +1F6B4 200D 2640 ; minimally-qualified # 🚴‍♀ woman biking +1F6B4 1F3FB 200D 2640 FE0F ; fully-qualified # 🚴🏻‍♀️ woman biking: light skin tone +1F6B4 1F3FB 200D 2640 ; minimally-qualified # 🚴🏻‍♀ woman biking: light skin tone +1F6B4 1F3FC 200D 2640 FE0F ; fully-qualified # 🚴🏼‍♀️ woman biking: medium-light skin tone +1F6B4 1F3FC 200D 2640 ; minimally-qualified # 🚴🏼‍♀ woman biking: medium-light skin tone +1F6B4 1F3FD 200D 2640 FE0F ; fully-qualified # 🚴🏽‍♀️ woman biking: medium skin tone +1F6B4 1F3FD 200D 2640 ; minimally-qualified # 🚴🏽‍♀ woman biking: medium skin tone +1F6B4 1F3FE 200D 2640 FE0F ; fully-qualified # 🚴🏾‍♀️ woman biking: medium-dark skin tone +1F6B4 1F3FE 200D 2640 ; minimally-qualified # 🚴🏾‍♀ woman biking: medium-dark skin tone +1F6B4 1F3FF 200D 2640 FE0F ; fully-qualified # 🚴🏿‍♀️ woman biking: dark skin tone +1F6B4 1F3FF 200D 2640 ; minimally-qualified # 🚴🏿‍♀ woman biking: dark skin tone +1F6B5 ; fully-qualified # 🚵 person mountain biking +1F6B5 1F3FB ; fully-qualified # 🚵🏻 person mountain biking: light skin tone +1F6B5 1F3FC ; fully-qualified # 🚵🏼 person mountain biking: medium-light skin tone +1F6B5 1F3FD ; fully-qualified # 🚵🏽 person mountain biking: medium skin tone +1F6B5 1F3FE ; fully-qualified # 🚵🏾 person mountain biking: medium-dark skin tone +1F6B5 1F3FF ; fully-qualified # 🚵🏿 person mountain biking: dark skin tone +1F6B5 200D 2642 FE0F ; fully-qualified # 🚵‍♂️ man mountain biking +1F6B5 200D 2642 ; minimally-qualified # 🚵‍♂ man mountain biking +1F6B5 1F3FB 200D 2642 FE0F ; fully-qualified # 🚵🏻‍♂️ man mountain biking: light skin tone +1F6B5 1F3FB 200D 2642 ; minimally-qualified # 🚵🏻‍♂ man mountain biking: light skin tone +1F6B5 1F3FC 200D 2642 FE0F ; fully-qualified # 🚵🏼‍♂️ man mountain biking: medium-light skin tone +1F6B5 1F3FC 200D 2642 ; minimally-qualified # 🚵🏼‍♂ man mountain biking: medium-light skin tone +1F6B5 1F3FD 200D 2642 FE0F ; fully-qualified # 🚵🏽‍♂️ man mountain biking: medium skin tone +1F6B5 1F3FD 200D 2642 ; minimally-qualified # 🚵🏽‍♂ man mountain biking: medium skin tone +1F6B5 1F3FE 200D 2642 FE0F ; fully-qualified # 🚵🏾‍♂️ man mountain biking: medium-dark skin tone +1F6B5 1F3FE 200D 2642 ; minimally-qualified # 🚵🏾‍♂ man mountain biking: medium-dark skin tone +1F6B5 1F3FF 200D 2642 FE0F ; fully-qualified # 🚵🏿‍♂️ man mountain biking: dark skin tone +1F6B5 1F3FF 200D 2642 ; minimally-qualified # 🚵🏿‍♂ man mountain biking: dark skin tone +1F6B5 200D 2640 FE0F ; fully-qualified # 🚵‍♀️ woman mountain biking +1F6B5 200D 2640 ; minimally-qualified # 🚵‍♀ woman mountain biking +1F6B5 1F3FB 200D 2640 FE0F ; fully-qualified # 🚵🏻‍♀️ woman mountain biking: light skin tone +1F6B5 1F3FB 200D 2640 ; minimally-qualified # 🚵🏻‍♀ woman mountain biking: light skin tone +1F6B5 1F3FC 200D 2640 FE0F ; fully-qualified # 🚵🏼‍♀️ woman mountain biking: medium-light skin tone +1F6B5 1F3FC 200D 2640 ; minimally-qualified # 🚵🏼‍♀ woman mountain biking: medium-light skin tone +1F6B5 1F3FD 200D 2640 FE0F ; fully-qualified # 🚵🏽‍♀️ woman mountain biking: medium skin tone +1F6B5 1F3FD 200D 2640 ; minimally-qualified # 🚵🏽‍♀ woman mountain biking: medium skin tone +1F6B5 1F3FE 200D 2640 FE0F ; fully-qualified # 🚵🏾‍♀️ woman mountain biking: medium-dark skin tone +1F6B5 1F3FE 200D 2640 ; minimally-qualified # 🚵🏾‍♀ woman mountain biking: medium-dark skin tone +1F6B5 1F3FF 200D 2640 FE0F ; fully-qualified # 🚵🏿‍♀️ woman mountain biking: dark skin tone +1F6B5 1F3FF 200D 2640 ; minimally-qualified # 🚵🏿‍♀ woman mountain biking: dark skin tone +1F938 ; fully-qualified # 🤸 person cartwheeling +1F938 1F3FB ; fully-qualified # 🤸🏻 person cartwheeling: light skin tone +1F938 1F3FC ; fully-qualified # 🤸🏼 person cartwheeling: medium-light skin tone +1F938 1F3FD ; fully-qualified # 🤸🏽 person cartwheeling: medium skin tone +1F938 1F3FE ; fully-qualified # 🤸🏾 person cartwheeling: medium-dark skin tone +1F938 1F3FF ; fully-qualified # 🤸🏿 person cartwheeling: dark skin tone +1F938 200D 2642 FE0F ; fully-qualified # 🤸‍♂️ man cartwheeling +1F938 200D 2642 ; minimally-qualified # 🤸‍♂ man cartwheeling +1F938 1F3FB 200D 2642 FE0F ; fully-qualified # 🤸🏻‍♂️ man cartwheeling: light skin tone +1F938 1F3FB 200D 2642 ; minimally-qualified # 🤸🏻‍♂ man cartwheeling: light skin tone +1F938 1F3FC 200D 2642 FE0F ; fully-qualified # 🤸🏼‍♂️ man cartwheeling: medium-light skin tone +1F938 1F3FC 200D 2642 ; minimally-qualified # 🤸🏼‍♂ man cartwheeling: medium-light skin tone +1F938 1F3FD 200D 2642 FE0F ; fully-qualified # 🤸🏽‍♂️ man cartwheeling: medium skin tone +1F938 1F3FD 200D 2642 ; minimally-qualified # 🤸🏽‍♂ man cartwheeling: medium skin tone +1F938 1F3FE 200D 2642 FE0F ; fully-qualified # 🤸🏾‍♂️ man cartwheeling: medium-dark skin tone +1F938 1F3FE 200D 2642 ; minimally-qualified # 🤸🏾‍♂ man cartwheeling: medium-dark skin tone +1F938 1F3FF 200D 2642 FE0F ; fully-qualified # 🤸🏿‍♂️ man cartwheeling: dark skin tone +1F938 1F3FF 200D 2642 ; minimally-qualified # 🤸🏿‍♂ man cartwheeling: dark skin tone +1F938 200D 2640 FE0F ; fully-qualified # 🤸‍♀️ woman cartwheeling +1F938 200D 2640 ; minimally-qualified # 🤸‍♀ woman cartwheeling +1F938 1F3FB 200D 2640 FE0F ; fully-qualified # 🤸🏻‍♀️ woman cartwheeling: light skin tone +1F938 1F3FB 200D 2640 ; minimally-qualified # 🤸🏻‍♀ woman cartwheeling: light skin tone +1F938 1F3FC 200D 2640 FE0F ; fully-qualified # 🤸🏼‍♀️ woman cartwheeling: medium-light skin tone +1F938 1F3FC 200D 2640 ; minimally-qualified # 🤸🏼‍♀ woman cartwheeling: medium-light skin tone +1F938 1F3FD 200D 2640 FE0F ; fully-qualified # 🤸🏽‍♀️ woman cartwheeling: medium skin tone +1F938 1F3FD 200D 2640 ; minimally-qualified # 🤸🏽‍♀ woman cartwheeling: medium skin tone +1F938 1F3FE 200D 2640 FE0F ; fully-qualified # 🤸🏾‍♀️ woman cartwheeling: medium-dark skin tone +1F938 1F3FE 200D 2640 ; minimally-qualified # 🤸🏾‍♀ woman cartwheeling: medium-dark skin tone +1F938 1F3FF 200D 2640 FE0F ; fully-qualified # 🤸🏿‍♀️ woman cartwheeling: dark skin tone +1F938 1F3FF 200D 2640 ; minimally-qualified # 🤸🏿‍♀ woman cartwheeling: dark skin tone +1F93C ; fully-qualified # 🤼 people wrestling +1F93C 200D 2642 FE0F ; fully-qualified # 🤼‍♂️ men wrestling +1F93C 200D 2642 ; minimally-qualified # 🤼‍♂ men wrestling +1F93C 200D 2640 FE0F ; fully-qualified # 🤼‍♀️ women wrestling +1F93C 200D 2640 ; minimally-qualified # 🤼‍♀ women wrestling +1F93D ; fully-qualified # 🤽 person playing water polo +1F93D 1F3FB ; fully-qualified # 🤽🏻 person playing water polo: light skin tone +1F93D 1F3FC ; fully-qualified # 🤽🏼 person playing water polo: medium-light skin tone +1F93D 1F3FD ; fully-qualified # 🤽🏽 person playing water polo: medium skin tone +1F93D 1F3FE ; fully-qualified # 🤽🏾 person playing water polo: medium-dark skin tone +1F93D 1F3FF ; fully-qualified # 🤽🏿 person playing water polo: dark skin tone +1F93D 200D 2642 FE0F ; fully-qualified # 🤽‍♂️ man playing water polo +1F93D 200D 2642 ; minimally-qualified # 🤽‍♂ man playing water polo +1F93D 1F3FB 200D 2642 FE0F ; fully-qualified # 🤽🏻‍♂️ man playing water polo: light skin tone +1F93D 1F3FB 200D 2642 ; minimally-qualified # 🤽🏻‍♂ man playing water polo: light skin tone +1F93D 1F3FC 200D 2642 FE0F ; fully-qualified # 🤽🏼‍♂️ man playing water polo: medium-light skin tone +1F93D 1F3FC 200D 2642 ; minimally-qualified # 🤽🏼‍♂ man playing water polo: medium-light skin tone +1F93D 1F3FD 200D 2642 FE0F ; fully-qualified # 🤽🏽‍♂️ man playing water polo: medium skin tone +1F93D 1F3FD 200D 2642 ; minimally-qualified # 🤽🏽‍♂ man playing water polo: medium skin tone +1F93D 1F3FE 200D 2642 FE0F ; fully-qualified # 🤽🏾‍♂️ man playing water polo: medium-dark skin tone +1F93D 1F3FE 200D 2642 ; minimally-qualified # 🤽🏾‍♂ man playing water polo: medium-dark skin tone +1F93D 1F3FF 200D 2642 FE0F ; fully-qualified # 🤽🏿‍♂️ man playing water polo: dark skin tone +1F93D 1F3FF 200D 2642 ; minimally-qualified # 🤽🏿‍♂ man playing water polo: dark skin tone +1F93D 200D 2640 FE0F ; fully-qualified # 🤽‍♀️ woman playing water polo +1F93D 200D 2640 ; minimally-qualified # 🤽‍♀ woman playing water polo +1F93D 1F3FB 200D 2640 FE0F ; fully-qualified # 🤽🏻‍♀️ woman playing water polo: light skin tone +1F93D 1F3FB 200D 2640 ; minimally-qualified # 🤽🏻‍♀ woman playing water polo: light skin tone +1F93D 1F3FC 200D 2640 FE0F ; fully-qualified # 🤽🏼‍♀️ woman playing water polo: medium-light skin tone +1F93D 1F3FC 200D 2640 ; minimally-qualified # 🤽🏼‍♀ woman playing water polo: medium-light skin tone +1F93D 1F3FD 200D 2640 FE0F ; fully-qualified # 🤽🏽‍♀️ woman playing water polo: medium skin tone +1F93D 1F3FD 200D 2640 ; minimally-qualified # 🤽🏽‍♀ woman playing water polo: medium skin tone +1F93D 1F3FE 200D 2640 FE0F ; fully-qualified # 🤽🏾‍♀️ woman playing water polo: medium-dark skin tone +1F93D 1F3FE 200D 2640 ; minimally-qualified # 🤽🏾‍♀ woman playing water polo: medium-dark skin tone +1F93D 1F3FF 200D 2640 FE0F ; fully-qualified # 🤽🏿‍♀️ woman playing water polo: dark skin tone +1F93D 1F3FF 200D 2640 ; minimally-qualified # 🤽🏿‍♀ woman playing water polo: dark skin tone +1F93E ; fully-qualified # 🤾 person playing handball +1F93E 1F3FB ; fully-qualified # 🤾🏻 person playing handball: light skin tone +1F93E 1F3FC ; fully-qualified # 🤾🏼 person playing handball: medium-light skin tone +1F93E 1F3FD ; fully-qualified # 🤾🏽 person playing handball: medium skin tone +1F93E 1F3FE ; fully-qualified # 🤾🏾 person playing handball: medium-dark skin tone +1F93E 1F3FF ; fully-qualified # 🤾🏿 person playing handball: dark skin tone +1F93E 200D 2642 FE0F ; fully-qualified # 🤾‍♂️ man playing handball +1F93E 200D 2642 ; minimally-qualified # 🤾‍♂ man playing handball +1F93E 1F3FB 200D 2642 FE0F ; fully-qualified # 🤾🏻‍♂️ man playing handball: light skin tone +1F93E 1F3FB 200D 2642 ; minimally-qualified # 🤾🏻‍♂ man playing handball: light skin tone +1F93E 1F3FC 200D 2642 FE0F ; fully-qualified # 🤾🏼‍♂️ man playing handball: medium-light skin tone +1F93E 1F3FC 200D 2642 ; minimally-qualified # 🤾🏼‍♂ man playing handball: medium-light skin tone +1F93E 1F3FD 200D 2642 FE0F ; fully-qualified # 🤾🏽‍♂️ man playing handball: medium skin tone +1F93E 1F3FD 200D 2642 ; minimally-qualified # 🤾🏽‍♂ man playing handball: medium skin tone +1F93E 1F3FE 200D 2642 FE0F ; fully-qualified # 🤾🏾‍♂️ man playing handball: medium-dark skin tone +1F93E 1F3FE 200D 2642 ; minimally-qualified # 🤾🏾‍♂ man playing handball: medium-dark skin tone +1F93E 1F3FF 200D 2642 FE0F ; fully-qualified # 🤾🏿‍♂️ man playing handball: dark skin tone +1F93E 1F3FF 200D 2642 ; minimally-qualified # 🤾🏿‍♂ man playing handball: dark skin tone +1F93E 200D 2640 FE0F ; fully-qualified # 🤾‍♀️ woman playing handball +1F93E 200D 2640 ; minimally-qualified # 🤾‍♀ woman playing handball +1F93E 1F3FB 200D 2640 FE0F ; fully-qualified # 🤾🏻‍♀️ woman playing handball: light skin tone +1F93E 1F3FB 200D 2640 ; minimally-qualified # 🤾🏻‍♀ woman playing handball: light skin tone +1F93E 1F3FC 200D 2640 FE0F ; fully-qualified # 🤾🏼‍♀️ woman playing handball: medium-light skin tone +1F93E 1F3FC 200D 2640 ; minimally-qualified # 🤾🏼‍♀ woman playing handball: medium-light skin tone +1F93E 1F3FD 200D 2640 FE0F ; fully-qualified # 🤾🏽‍♀️ woman playing handball: medium skin tone +1F93E 1F3FD 200D 2640 ; minimally-qualified # 🤾🏽‍♀ woman playing handball: medium skin tone +1F93E 1F3FE 200D 2640 FE0F ; fully-qualified # 🤾🏾‍♀️ woman playing handball: medium-dark skin tone +1F93E 1F3FE 200D 2640 ; minimally-qualified # 🤾🏾‍♀ woman playing handball: medium-dark skin tone +1F93E 1F3FF 200D 2640 FE0F ; fully-qualified # 🤾🏿‍♀️ woman playing handball: dark skin tone +1F93E 1F3FF 200D 2640 ; minimally-qualified # 🤾🏿‍♀ woman playing handball: dark skin tone +1F939 ; fully-qualified # 🤹 person juggling +1F939 1F3FB ; fully-qualified # 🤹🏻 person juggling: light skin tone +1F939 1F3FC ; fully-qualified # 🤹🏼 person juggling: medium-light skin tone +1F939 1F3FD ; fully-qualified # 🤹🏽 person juggling: medium skin tone +1F939 1F3FE ; fully-qualified # 🤹🏾 person juggling: medium-dark skin tone +1F939 1F3FF ; fully-qualified # 🤹🏿 person juggling: dark skin tone +1F939 200D 2642 FE0F ; fully-qualified # 🤹‍♂️ man juggling +1F939 200D 2642 ; minimally-qualified # 🤹‍♂ man juggling +1F939 1F3FB 200D 2642 FE0F ; fully-qualified # 🤹🏻‍♂️ man juggling: light skin tone +1F939 1F3FB 200D 2642 ; minimally-qualified # 🤹🏻‍♂ man juggling: light skin tone +1F939 1F3FC 200D 2642 FE0F ; fully-qualified # 🤹🏼‍♂️ man juggling: medium-light skin tone +1F939 1F3FC 200D 2642 ; minimally-qualified # 🤹🏼‍♂ man juggling: medium-light skin tone +1F939 1F3FD 200D 2642 FE0F ; fully-qualified # 🤹🏽‍♂️ man juggling: medium skin tone +1F939 1F3FD 200D 2642 ; minimally-qualified # 🤹🏽‍♂ man juggling: medium skin tone +1F939 1F3FE 200D 2642 FE0F ; fully-qualified # 🤹🏾‍♂️ man juggling: medium-dark skin tone +1F939 1F3FE 200D 2642 ; minimally-qualified # 🤹🏾‍♂ man juggling: medium-dark skin tone +1F939 1F3FF 200D 2642 FE0F ; fully-qualified # 🤹🏿‍♂️ man juggling: dark skin tone +1F939 1F3FF 200D 2642 ; minimally-qualified # 🤹🏿‍♂ man juggling: dark skin tone +1F939 200D 2640 FE0F ; fully-qualified # 🤹‍♀️ woman juggling +1F939 200D 2640 ; minimally-qualified # 🤹‍♀ woman juggling +1F939 1F3FB 200D 2640 FE0F ; fully-qualified # 🤹🏻‍♀️ woman juggling: light skin tone +1F939 1F3FB 200D 2640 ; minimally-qualified # 🤹🏻‍♀ woman juggling: light skin tone +1F939 1F3FC 200D 2640 FE0F ; fully-qualified # 🤹🏼‍♀️ woman juggling: medium-light skin tone +1F939 1F3FC 200D 2640 ; minimally-qualified # 🤹🏼‍♀ woman juggling: medium-light skin tone +1F939 1F3FD 200D 2640 FE0F ; fully-qualified # 🤹🏽‍♀️ woman juggling: medium skin tone +1F939 1F3FD 200D 2640 ; minimally-qualified # 🤹🏽‍♀ woman juggling: medium skin tone +1F939 1F3FE 200D 2640 FE0F ; fully-qualified # 🤹🏾‍♀️ woman juggling: medium-dark skin tone +1F939 1F3FE 200D 2640 ; minimally-qualified # 🤹🏾‍♀ woman juggling: medium-dark skin tone +1F939 1F3FF 200D 2640 FE0F ; fully-qualified # 🤹🏿‍♀️ woman juggling: dark skin tone +1F939 1F3FF 200D 2640 ; minimally-qualified # 🤹🏿‍♀ woman juggling: dark skin tone + +# subgroup: person-resting +1F9D8 ; fully-qualified # 🧘 person in lotus position +1F9D8 1F3FB ; fully-qualified # 🧘🏻 person in lotus position: light skin tone +1F9D8 1F3FC ; fully-qualified # 🧘🏼 person in lotus position: medium-light skin tone +1F9D8 1F3FD ; fully-qualified # 🧘🏽 person in lotus position: medium skin tone +1F9D8 1F3FE ; fully-qualified # 🧘🏾 person in lotus position: medium-dark skin tone +1F9D8 1F3FF ; fully-qualified # 🧘🏿 person in lotus position: dark skin tone +1F9D8 200D 2642 FE0F ; fully-qualified # 🧘‍♂️ man in lotus position +1F9D8 200D 2642 ; minimally-qualified # 🧘‍♂ man in lotus position +1F9D8 1F3FB 200D 2642 FE0F ; fully-qualified # 🧘🏻‍♂️ man in lotus position: light skin tone +1F9D8 1F3FB 200D 2642 ; minimally-qualified # 🧘🏻‍♂ man in lotus position: light skin tone +1F9D8 1F3FC 200D 2642 FE0F ; fully-qualified # 🧘🏼‍♂️ man in lotus position: medium-light skin tone +1F9D8 1F3FC 200D 2642 ; minimally-qualified # 🧘🏼‍♂ man in lotus position: medium-light skin tone +1F9D8 1F3FD 200D 2642 FE0F ; fully-qualified # 🧘🏽‍♂️ man in lotus position: medium skin tone +1F9D8 1F3FD 200D 2642 ; minimally-qualified # 🧘🏽‍♂ man in lotus position: medium skin tone +1F9D8 1F3FE 200D 2642 FE0F ; fully-qualified # 🧘🏾‍♂️ man in lotus position: medium-dark skin tone +1F9D8 1F3FE 200D 2642 ; minimally-qualified # 🧘🏾‍♂ man in lotus position: medium-dark skin tone +1F9D8 1F3FF 200D 2642 FE0F ; fully-qualified # 🧘🏿‍♂️ man in lotus position: dark skin tone +1F9D8 1F3FF 200D 2642 ; minimally-qualified # 🧘🏿‍♂ man in lotus position: dark skin tone +1F9D8 200D 2640 FE0F ; fully-qualified # 🧘‍♀️ woman in lotus position +1F9D8 200D 2640 ; minimally-qualified # 🧘‍♀ woman in lotus position +1F9D8 1F3FB 200D 2640 FE0F ; fully-qualified # 🧘🏻‍♀️ woman in lotus position: light skin tone +1F9D8 1F3FB 200D 2640 ; minimally-qualified # 🧘🏻‍♀ woman in lotus position: light skin tone +1F9D8 1F3FC 200D 2640 FE0F ; fully-qualified # 🧘🏼‍♀️ woman in lotus position: medium-light skin tone +1F9D8 1F3FC 200D 2640 ; minimally-qualified # 🧘🏼‍♀ woman in lotus position: medium-light skin tone +1F9D8 1F3FD 200D 2640 FE0F ; fully-qualified # 🧘🏽‍♀️ woman in lotus position: medium skin tone +1F9D8 1F3FD 200D 2640 ; minimally-qualified # 🧘🏽‍♀ woman in lotus position: medium skin tone +1F9D8 1F3FE 200D 2640 FE0F ; fully-qualified # 🧘🏾‍♀️ woman in lotus position: medium-dark skin tone +1F9D8 1F3FE 200D 2640 ; minimally-qualified # 🧘🏾‍♀ woman in lotus position: medium-dark skin tone +1F9D8 1F3FF 200D 2640 FE0F ; fully-qualified # 🧘🏿‍♀️ woman in lotus position: dark skin tone +1F9D8 1F3FF 200D 2640 ; minimally-qualified # 🧘🏿‍♀ woman in lotus position: dark skin tone +1F6C0 ; fully-qualified # 🛀 person taking bath +1F6C0 1F3FB ; fully-qualified # 🛀🏻 person taking bath: light skin tone +1F6C0 1F3FC ; fully-qualified # 🛀🏼 person taking bath: medium-light skin tone +1F6C0 1F3FD ; fully-qualified # 🛀🏽 person taking bath: medium skin tone +1F6C0 1F3FE ; fully-qualified # 🛀🏾 person taking bath: medium-dark skin tone +1F6C0 1F3FF ; fully-qualified # 🛀🏿 person taking bath: dark skin tone +1F6CC ; fully-qualified # 🛌 person in bed +1F6CC 1F3FB ; fully-qualified # 🛌🏻 person in bed: light skin tone +1F6CC 1F3FC ; fully-qualified # 🛌🏼 person in bed: medium-light skin tone +1F6CC 1F3FD ; fully-qualified # 🛌🏽 person in bed: medium skin tone +1F6CC 1F3FE ; fully-qualified # 🛌🏾 person in bed: medium-dark skin tone +1F6CC 1F3FF ; fully-qualified # 🛌🏿 person in bed: dark skin tone + +# subgroup: family +1F9D1 200D 1F91D 200D 1F9D1 ; fully-qualified # 🧑‍🤝‍🧑 people holding hands +1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏻‍🤝‍🧑🏻 people holding hands: light skin tone +1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏼‍🤝‍🧑🏻 people holding hands: medium-light skin tone, light skin tone +1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏼‍🤝‍🧑🏼 people holding hands: medium-light skin tone +1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏽‍🤝‍🧑🏻 people holding hands: medium skin tone, light skin tone +1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏽‍🤝‍🧑🏼 people holding hands: medium skin tone, medium-light skin tone +1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏽‍🤝‍🧑🏽 people holding hands: medium skin tone +1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏾‍🤝‍🧑🏻 people holding hands: medium-dark skin tone, light skin tone +1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏾‍🤝‍🧑🏼 people holding hands: medium-dark skin tone, medium-light skin tone +1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏾‍🤝‍🧑🏽 people holding hands: medium-dark skin tone, medium skin tone +1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏾‍🤝‍🧑🏾 people holding hands: medium-dark skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FB ; fully-qualified # 🧑🏿‍🤝‍🧑🏻 people holding hands: dark skin tone, light skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FC ; fully-qualified # 🧑🏿‍🤝‍🧑🏼 people holding hands: dark skin tone, medium-light skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FD ; fully-qualified # 🧑🏿‍🤝‍🧑🏽 people holding hands: dark skin tone, medium skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FE ; fully-qualified # 🧑🏿‍🤝‍🧑🏾 people holding hands: dark skin tone, medium-dark skin tone +1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FF ; fully-qualified # 🧑🏿‍🤝‍🧑🏿 people holding hands: dark skin tone +1F46D ; fully-qualified # 👭 women holding hands +1F46D 1F3FB ; fully-qualified # 👭🏻 women holding hands: light skin tone +1F469 1F3FC 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏼‍🤝‍👩🏻 women holding hands: medium-light skin tone, light skin tone +1F46D 1F3FC ; fully-qualified # 👭🏼 women holding hands: medium-light skin tone +1F469 1F3FD 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏽‍🤝‍👩🏻 women holding hands: medium skin tone, light skin tone +1F469 1F3FD 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏽‍🤝‍👩🏼 women holding hands: medium skin tone, medium-light skin tone +1F46D 1F3FD ; fully-qualified # 👭🏽 women holding hands: medium skin tone +1F469 1F3FE 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏾‍🤝‍👩🏻 women holding hands: medium-dark skin tone, light skin tone +1F469 1F3FE 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏾‍🤝‍👩🏼 women holding hands: medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏾‍🤝‍👩🏽 women holding hands: medium-dark skin tone, medium skin tone +1F46D 1F3FE ; fully-qualified # 👭🏾 women holding hands: medium-dark skin tone +1F469 1F3FF 200D 1F91D 200D 1F469 1F3FB ; fully-qualified # 👩🏿‍🤝‍👩🏻 women holding hands: dark skin tone, light skin tone +1F469 1F3FF 200D 1F91D 200D 1F469 1F3FC ; fully-qualified # 👩🏿‍🤝‍👩🏼 women holding hands: dark skin tone, medium-light skin tone +1F469 1F3FF 200D 1F91D 200D 1F469 1F3FD ; fully-qualified # 👩🏿‍🤝‍👩🏽 women holding hands: dark skin tone, medium skin tone +1F469 1F3FF 200D 1F91D 200D 1F469 1F3FE ; fully-qualified # 👩🏿‍🤝‍👩🏾 women holding hands: dark skin tone, medium-dark skin tone +1F46D 1F3FF ; fully-qualified # 👭🏿 women holding hands: dark skin tone +1F46B ; fully-qualified # 👫 woman and man holding hands +1F46B 1F3FB ; fully-qualified # 👫🏻 woman and man holding hands: light skin tone +1F469 1F3FB 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏻‍🤝‍👨🏼 woman and man holding hands: light skin tone, medium-light skin tone +1F469 1F3FB 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏻‍🤝‍👨🏽 woman and man holding hands: light skin tone, medium skin tone +1F469 1F3FB 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏻‍🤝‍👨🏾 woman and man holding hands: light skin tone, medium-dark skin tone +1F469 1F3FB 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏻‍🤝‍👨🏿 woman and man holding hands: light skin tone, dark skin tone +1F469 1F3FC 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏼‍🤝‍👨🏻 woman and man holding hands: medium-light skin tone, light skin tone +1F46B 1F3FC ; fully-qualified # 👫🏼 woman and man holding hands: medium-light skin tone +1F469 1F3FC 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏼‍🤝‍👨🏽 woman and man holding hands: medium-light skin tone, medium skin tone +1F469 1F3FC 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏼‍🤝‍👨🏾 woman and man holding hands: medium-light skin tone, medium-dark skin tone +1F469 1F3FC 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏼‍🤝‍👨🏿 woman and man holding hands: medium-light skin tone, dark skin tone +1F469 1F3FD 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏽‍🤝‍👨🏻 woman and man holding hands: medium skin tone, light skin tone +1F469 1F3FD 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏽‍🤝‍👨🏼 woman and man holding hands: medium skin tone, medium-light skin tone +1F46B 1F3FD ; fully-qualified # 👫🏽 woman and man holding hands: medium skin tone +1F469 1F3FD 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏽‍🤝‍👨🏾 woman and man holding hands: medium skin tone, medium-dark skin tone +1F469 1F3FD 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏽‍🤝‍👨🏿 woman and man holding hands: medium skin tone, dark skin tone +1F469 1F3FE 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏾‍🤝‍👨🏻 woman and man holding hands: medium-dark skin tone, light skin tone +1F469 1F3FE 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏾‍🤝‍👨🏼 woman and man holding hands: medium-dark skin tone, medium-light skin tone +1F469 1F3FE 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏾‍🤝‍👨🏽 woman and man holding hands: medium-dark skin tone, medium skin tone +1F46B 1F3FE ; fully-qualified # 👫🏾 woman and man holding hands: medium-dark skin tone +1F469 1F3FE 200D 1F91D 200D 1F468 1F3FF ; fully-qualified # 👩🏾‍🤝‍👨🏿 woman and man holding hands: medium-dark skin tone, dark skin tone +1F469 1F3FF 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👩🏿‍🤝‍👨🏻 woman and man holding hands: dark skin tone, light skin tone +1F469 1F3FF 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👩🏿‍🤝‍👨🏼 woman and man holding hands: dark skin tone, medium-light skin tone +1F469 1F3FF 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👩🏿‍🤝‍👨🏽 woman and man holding hands: dark skin tone, medium skin tone +1F469 1F3FF 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👩🏿‍🤝‍👨🏾 woman and man holding hands: dark skin tone, medium-dark skin tone +1F46B 1F3FF ; fully-qualified # 👫🏿 woman and man holding hands: dark skin tone +1F46C ; fully-qualified # 👬 men holding hands +1F46C 1F3FB ; fully-qualified # 👬🏻 men holding hands: light skin tone +1F468 1F3FC 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏼‍🤝‍👨🏻 men holding hands: medium-light skin tone, light skin tone +1F46C 1F3FC ; fully-qualified # 👬🏼 men holding hands: medium-light skin tone +1F468 1F3FD 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏽‍🤝‍👨🏻 men holding hands: medium skin tone, light skin tone +1F468 1F3FD 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏽‍🤝‍👨🏼 men holding hands: medium skin tone, medium-light skin tone +1F46C 1F3FD ; fully-qualified # 👬🏽 men holding hands: medium skin tone +1F468 1F3FE 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏾‍🤝‍👨🏻 men holding hands: medium-dark skin tone, light skin tone +1F468 1F3FE 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏾‍🤝‍👨🏼 men holding hands: medium-dark skin tone, medium-light skin tone +1F468 1F3FE 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏾‍🤝‍👨🏽 men holding hands: medium-dark skin tone, medium skin tone +1F46C 1F3FE ; fully-qualified # 👬🏾 men holding hands: medium-dark skin tone +1F468 1F3FF 200D 1F91D 200D 1F468 1F3FB ; fully-qualified # 👨🏿‍🤝‍👨🏻 men holding hands: dark skin tone, light skin tone +1F468 1F3FF 200D 1F91D 200D 1F468 1F3FC ; fully-qualified # 👨🏿‍🤝‍👨🏼 men holding hands: dark skin tone, medium-light skin tone +1F468 1F3FF 200D 1F91D 200D 1F468 1F3FD ; fully-qualified # 👨🏿‍🤝‍👨🏽 men holding hands: dark skin tone, medium skin tone +1F468 1F3FF 200D 1F91D 200D 1F468 1F3FE ; fully-qualified # 👨🏿‍🤝‍👨🏾 men holding hands: dark skin tone, medium-dark skin tone +1F46C 1F3FF ; fully-qualified # 👬🏿 men holding hands: dark skin tone +1F48F ; fully-qualified # 💏 kiss +1F469 200D 2764 FE0F 200D 1F48B 200D 1F468 ; fully-qualified # 👩‍❤️‍💋‍👨 kiss: woman, man +1F469 200D 2764 200D 1F48B 200D 1F468 ; minimally-qualified # 👩‍❤‍💋‍👨 kiss: woman, man +1F468 200D 2764 FE0F 200D 1F48B 200D 1F468 ; fully-qualified # 👨‍❤️‍💋‍👨 kiss: man, man +1F468 200D 2764 200D 1F48B 200D 1F468 ; minimally-qualified # 👨‍❤‍💋‍👨 kiss: man, man +1F469 200D 2764 FE0F 200D 1F48B 200D 1F469 ; fully-qualified # 👩‍❤️‍💋‍👩 kiss: woman, woman +1F469 200D 2764 200D 1F48B 200D 1F469 ; minimally-qualified # 👩‍❤‍💋‍👩 kiss: woman, woman +1F491 ; fully-qualified # 💑 couple with heart +1F469 200D 2764 FE0F 200D 1F468 ; fully-qualified # 👩‍❤️‍👨 couple with heart: woman, man +1F469 200D 2764 200D 1F468 ; minimally-qualified # 👩‍❤‍👨 couple with heart: woman, man +1F468 200D 2764 FE0F 200D 1F468 ; fully-qualified # 👨‍❤️‍👨 couple with heart: man, man +1F468 200D 2764 200D 1F468 ; minimally-qualified # 👨‍❤‍👨 couple with heart: man, man +1F469 200D 2764 FE0F 200D 1F469 ; fully-qualified # 👩‍❤️‍👩 couple with heart: woman, woman +1F469 200D 2764 200D 1F469 ; minimally-qualified # 👩‍❤‍👩 couple with heart: woman, woman +1F46A ; fully-qualified # 👪 family +1F468 200D 1F469 200D 1F466 ; fully-qualified # 👨‍👩‍👦 family: man, woman, boy +1F468 200D 1F469 200D 1F467 ; fully-qualified # 👨‍👩‍👧 family: man, woman, girl +1F468 200D 1F469 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👩‍👧‍👦 family: man, woman, girl, boy +1F468 200D 1F469 200D 1F466 200D 1F466 ; fully-qualified # 👨‍👩‍👦‍👦 family: man, woman, boy, boy +1F468 200D 1F469 200D 1F467 200D 1F467 ; fully-qualified # 👨‍👩‍👧‍👧 family: man, woman, girl, girl +1F468 200D 1F468 200D 1F466 ; fully-qualified # 👨‍👨‍👦 family: man, man, boy +1F468 200D 1F468 200D 1F467 ; fully-qualified # 👨‍👨‍👧 family: man, man, girl +1F468 200D 1F468 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👨‍👧‍👦 family: man, man, girl, boy +1F468 200D 1F468 200D 1F466 200D 1F466 ; fully-qualified # 👨‍👨‍👦‍👦 family: man, man, boy, boy +1F468 200D 1F468 200D 1F467 200D 1F467 ; fully-qualified # 👨‍👨‍👧‍👧 family: man, man, girl, girl +1F469 200D 1F469 200D 1F466 ; fully-qualified # 👩‍👩‍👦 family: woman, woman, boy +1F469 200D 1F469 200D 1F467 ; fully-qualified # 👩‍👩‍👧 family: woman, woman, girl +1F469 200D 1F469 200D 1F467 200D 1F466 ; fully-qualified # 👩‍👩‍👧‍👦 family: woman, woman, girl, boy +1F469 200D 1F469 200D 1F466 200D 1F466 ; fully-qualified # 👩‍👩‍👦‍👦 family: woman, woman, boy, boy +1F469 200D 1F469 200D 1F467 200D 1F467 ; fully-qualified # 👩‍👩‍👧‍👧 family: woman, woman, girl, girl +1F468 200D 1F466 ; fully-qualified # 👨‍👦 family: man, boy +1F468 200D 1F466 200D 1F466 ; fully-qualified # 👨‍👦‍👦 family: man, boy, boy +1F468 200D 1F467 ; fully-qualified # 👨‍👧 family: man, girl +1F468 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👧‍👦 family: man, girl, boy +1F468 200D 1F467 200D 1F467 ; fully-qualified # 👨‍👧‍👧 family: man, girl, girl +1F469 200D 1F466 ; fully-qualified # 👩‍👦 family: woman, boy +1F469 200D 1F466 200D 1F466 ; fully-qualified # 👩‍👦‍👦 family: woman, boy, boy +1F469 200D 1F467 ; fully-qualified # 👩‍👧 family: woman, girl +1F469 200D 1F467 200D 1F466 ; fully-qualified # 👩‍👧‍👦 family: woman, girl, boy +1F469 200D 1F467 200D 1F467 ; fully-qualified # 👩‍👧‍👧 family: woman, girl, girl + +# subgroup: person-symbol +1F5E3 FE0F ; fully-qualified # 🗣️ speaking head +1F5E3 ; unqualified # 🗣 speaking head +1F464 ; fully-qualified # 👤 bust in silhouette +1F465 ; fully-qualified # 👥 busts in silhouette +1F463 ; fully-qualified # 👣 footprints + +# People & Body subtotal: 2212 +# People & Body subtotal: 447 w/o modifiers + +# group: Component + +# subgroup: skin-tone +1F3FB ; component # 🏻 light skin tone +1F3FC ; component # 🏼 medium-light skin tone +1F3FD ; component # 🏽 medium skin tone +1F3FE ; component # 🏾 medium-dark skin tone +1F3FF ; component # 🏿 dark skin tone + +# subgroup: hair-style +1F9B0 ; component # 🦰 red hair +1F9B1 ; component # 🦱 curly hair +1F9B3 ; component # 🦳 white hair +1F9B2 ; component # 🦲 bald + +# Component subtotal: 9 +# Component subtotal: 4 w/o modifiers + +# group: Animals & Nature + +# subgroup: animal-mammal +1F435 ; fully-qualified # 🐵 monkey face +1F412 ; fully-qualified # 🐒 monkey +1F98D ; fully-qualified # 🦍 gorilla +1F9A7 ; fully-qualified # 🦧 orangutan +1F436 ; fully-qualified # 🐶 dog face +1F415 ; fully-qualified # 🐕 dog +1F9AE ; fully-qualified # 🦮 guide dog +1F415 200D 1F9BA ; fully-qualified # 🐕‍🦺 service dog +1F429 ; fully-qualified # 🐩 poodle +1F43A ; fully-qualified # 🐺 wolf +1F98A ; fully-qualified # 🦊 fox +1F99D ; fully-qualified # 🦝 raccoon +1F431 ; fully-qualified # 🐱 cat face +1F408 ; fully-qualified # 🐈 cat +1F981 ; fully-qualified # 🦁 lion +1F42F ; fully-qualified # 🐯 tiger face +1F405 ; fully-qualified # 🐅 tiger +1F406 ; fully-qualified # 🐆 leopard +1F434 ; fully-qualified # 🐴 horse face +1F40E ; fully-qualified # 🐎 horse +1F984 ; fully-qualified # 🦄 unicorn +1F993 ; fully-qualified # 🦓 zebra +1F98C ; fully-qualified # 🦌 deer +1F42E ; fully-qualified # 🐮 cow face +1F402 ; fully-qualified # 🐂 ox +1F403 ; fully-qualified # 🐃 water buffalo +1F404 ; fully-qualified # 🐄 cow +1F437 ; fully-qualified # 🐷 pig face +1F416 ; fully-qualified # 🐖 pig +1F417 ; fully-qualified # 🐗 boar +1F43D ; fully-qualified # 🐽 pig nose +1F40F ; fully-qualified # 🐏 ram +1F411 ; fully-qualified # 🐑 ewe +1F410 ; fully-qualified # 🐐 goat +1F42A ; fully-qualified # 🐪 camel +1F42B ; fully-qualified # 🐫 two-hump camel +1F999 ; fully-qualified # 🦙 llama +1F992 ; fully-qualified # 🦒 giraffe +1F418 ; fully-qualified # 🐘 elephant +1F98F ; fully-qualified # 🦏 rhinoceros +1F99B ; fully-qualified # 🦛 hippopotamus +1F42D ; fully-qualified # 🐭 mouse face +1F401 ; fully-qualified # 🐁 mouse +1F400 ; fully-qualified # 🐀 rat +1F439 ; fully-qualified # 🐹 hamster +1F430 ; fully-qualified # 🐰 rabbit face +1F407 ; fully-qualified # 🐇 rabbit +1F43F FE0F ; fully-qualified # 🐿️ chipmunk +1F43F ; unqualified # 🐿 chipmunk +1F994 ; fully-qualified # 🦔 hedgehog +1F987 ; fully-qualified # 🦇 bat +1F43B ; fully-qualified # 🐻 bear +1F428 ; fully-qualified # 🐨 koala +1F43C ; fully-qualified # 🐼 panda +1F9A5 ; fully-qualified # 🦥 sloth +1F9A6 ; fully-qualified # 🦦 otter +1F9A8 ; fully-qualified # 🦨 skunk +1F998 ; fully-qualified # 🦘 kangaroo +1F9A1 ; fully-qualified # 🦡 badger +1F43E ; fully-qualified # 🐾 paw prints + +# subgroup: animal-bird +1F983 ; fully-qualified # 🦃 turkey +1F414 ; fully-qualified # 🐔 chicken +1F413 ; fully-qualified # 🐓 rooster +1F423 ; fully-qualified # 🐣 hatching chick +1F424 ; fully-qualified # 🐤 baby chick +1F425 ; fully-qualified # 🐥 front-facing baby chick +1F426 ; fully-qualified # 🐦 bird +1F427 ; fully-qualified # 🐧 penguin +1F54A FE0F ; fully-qualified # 🕊️ dove +1F54A ; unqualified # 🕊 dove +1F985 ; fully-qualified # 🦅 eagle +1F986 ; fully-qualified # 🦆 duck +1F9A2 ; fully-qualified # 🦢 swan +1F989 ; fully-qualified # 🦉 owl +1F9A9 ; fully-qualified # 🦩 flamingo +1F99A ; fully-qualified # 🦚 peacock +1F99C ; fully-qualified # 🦜 parrot + +# subgroup: animal-amphibian +1F438 ; fully-qualified # 🐸 frog + +# subgroup: animal-reptile +1F40A ; fully-qualified # 🐊 crocodile +1F422 ; fully-qualified # 🐢 turtle +1F98E ; fully-qualified # 🦎 lizard +1F40D ; fully-qualified # 🐍 snake +1F432 ; fully-qualified # 🐲 dragon face +1F409 ; fully-qualified # 🐉 dragon +1F995 ; fully-qualified # 🦕 sauropod +1F996 ; fully-qualified # 🦖 T-Rex + +# subgroup: animal-marine +1F433 ; fully-qualified # 🐳 spouting whale +1F40B ; fully-qualified # 🐋 whale +1F42C ; fully-qualified # 🐬 dolphin +1F41F ; fully-qualified # 🐟 fish +1F420 ; fully-qualified # 🐠 tropical fish +1F421 ; fully-qualified # 🐡 blowfish +1F988 ; fully-qualified # 🦈 shark +1F419 ; fully-qualified # 🐙 octopus +1F41A ; fully-qualified # 🐚 spiral shell + +# subgroup: animal-bug +1F40C ; fully-qualified # 🐌 snail +1F98B ; fully-qualified # 🦋 butterfly +1F41B ; fully-qualified # 🐛 bug +1F41C ; fully-qualified # 🐜 ant +1F41D ; fully-qualified # 🐝 honeybee +1F41E ; fully-qualified # 🐞 lady beetle +1F997 ; fully-qualified # 🦗 cricket +1F577 FE0F ; fully-qualified # 🕷️ spider +1F577 ; unqualified # 🕷 spider +1F578 FE0F ; fully-qualified # 🕸️ spider web +1F578 ; unqualified # 🕸 spider web +1F982 ; fully-qualified # 🦂 scorpion +1F99F ; fully-qualified # 🦟 mosquito +1F9A0 ; fully-qualified # 🦠 microbe + +# subgroup: plant-flower +1F490 ; fully-qualified # 💐 bouquet +1F338 ; fully-qualified # 🌸 cherry blossom +1F4AE ; fully-qualified # 💮 white flower +1F3F5 FE0F ; fully-qualified # 🏵️ rosette +1F3F5 ; unqualified # 🏵 rosette +1F339 ; fully-qualified # 🌹 rose +1F940 ; fully-qualified # 🥀 wilted flower +1F33A ; fully-qualified # 🌺 hibiscus +1F33B ; fully-qualified # 🌻 sunflower +1F33C ; fully-qualified # 🌼 blossom +1F337 ; fully-qualified # 🌷 tulip + +# subgroup: plant-other +1F331 ; fully-qualified # 🌱 seedling +1F332 ; fully-qualified # 🌲 evergreen tree +1F333 ; fully-qualified # 🌳 deciduous tree +1F334 ; fully-qualified # 🌴 palm tree +1F335 ; fully-qualified # 🌵 cactus +1F33E ; fully-qualified # 🌾 sheaf of rice +1F33F ; fully-qualified # 🌿 herb +2618 FE0F ; fully-qualified # ☘️ shamrock +2618 ; unqualified # ☘ shamrock +1F340 ; fully-qualified # 🍀 four leaf clover +1F341 ; fully-qualified # 🍁 maple leaf +1F342 ; fully-qualified # 🍂 fallen leaf +1F343 ; fully-qualified # 🍃 leaf fluttering in wind + +# Animals & Nature subtotal: 133 +# Animals & Nature subtotal: 133 w/o modifiers + +# group: Food & Drink + +# subgroup: food-fruit +1F347 ; fully-qualified # 🍇 grapes +1F348 ; fully-qualified # 🍈 melon +1F349 ; fully-qualified # 🍉 watermelon +1F34A ; fully-qualified # 🍊 tangerine +1F34B ; fully-qualified # 🍋 lemon +1F34C ; fully-qualified # 🍌 banana +1F34D ; fully-qualified # 🍍 pineapple +1F96D ; fully-qualified # 🥭 mango +1F34E ; fully-qualified # 🍎 red apple +1F34F ; fully-qualified # 🍏 green apple +1F350 ; fully-qualified # 🍐 pear +1F351 ; fully-qualified # 🍑 peach +1F352 ; fully-qualified # 🍒 cherries +1F353 ; fully-qualified # 🍓 strawberry +1F95D ; fully-qualified # 🥝 kiwi fruit +1F345 ; fully-qualified # 🍅 tomato +1F965 ; fully-qualified # 🥥 coconut + +# subgroup: food-vegetable +1F951 ; fully-qualified # 🥑 avocado +1F346 ; fully-qualified # 🍆 eggplant +1F954 ; fully-qualified # 🥔 potato +1F955 ; fully-qualified # 🥕 carrot +1F33D ; fully-qualified # 🌽 ear of corn +1F336 FE0F ; fully-qualified # 🌶️ hot pepper +1F336 ; unqualified # 🌶 hot pepper +1F952 ; fully-qualified # 🥒 cucumber +1F96C ; fully-qualified # 🥬 leafy green +1F966 ; fully-qualified # 🥦 broccoli +1F9C4 ; fully-qualified # 🧄 garlic +1F9C5 ; fully-qualified # 🧅 onion +1F344 ; fully-qualified # 🍄 mushroom +1F95C ; fully-qualified # 🥜 peanuts +1F330 ; fully-qualified # 🌰 chestnut + +# subgroup: food-prepared +1F35E ; fully-qualified # 🍞 bread +1F950 ; fully-qualified # 🥐 croissant +1F956 ; fully-qualified # 🥖 baguette bread +1F968 ; fully-qualified # 🥨 pretzel +1F96F ; fully-qualified # 🥯 bagel +1F95E ; fully-qualified # 🥞 pancakes +1F9C7 ; fully-qualified # 🧇 waffle +1F9C0 ; fully-qualified # 🧀 cheese wedge +1F356 ; fully-qualified # 🍖 meat on bone +1F357 ; fully-qualified # 🍗 poultry leg +1F969 ; fully-qualified # 🥩 cut of meat +1F953 ; fully-qualified # 🥓 bacon +1F354 ; fully-qualified # 🍔 hamburger +1F35F ; fully-qualified # 🍟 french fries +1F355 ; fully-qualified # 🍕 pizza +1F32D ; fully-qualified # 🌭 hot dog +1F96A ; fully-qualified # 🥪 sandwich +1F32E ; fully-qualified # 🌮 taco +1F32F ; fully-qualified # 🌯 burrito +1F959 ; fully-qualified # 🥙 stuffed flatbread +1F9C6 ; fully-qualified # 🧆 falafel +1F95A ; fully-qualified # 🥚 egg +1F373 ; fully-qualified # 🍳 cooking +1F958 ; fully-qualified # 🥘 shallow pan of food +1F372 ; fully-qualified # 🍲 pot of food +1F963 ; fully-qualified # 🥣 bowl with spoon +1F957 ; fully-qualified # 🥗 green salad +1F37F ; fully-qualified # 🍿 popcorn +1F9C8 ; fully-qualified # 🧈 butter +1F9C2 ; fully-qualified # 🧂 salt +1F96B ; fully-qualified # 🥫 canned food + +# subgroup: food-asian +1F371 ; fully-qualified # 🍱 bento box +1F358 ; fully-qualified # 🍘 rice cracker +1F359 ; fully-qualified # 🍙 rice ball +1F35A ; fully-qualified # 🍚 cooked rice +1F35B ; fully-qualified # 🍛 curry rice +1F35C ; fully-qualified # 🍜 steaming bowl +1F35D ; fully-qualified # 🍝 spaghetti +1F360 ; fully-qualified # 🍠 roasted sweet potato +1F362 ; fully-qualified # 🍢 oden +1F363 ; fully-qualified # 🍣 sushi +1F364 ; fully-qualified # 🍤 fried shrimp +1F365 ; fully-qualified # 🍥 fish cake with swirl +1F96E ; fully-qualified # 🥮 moon cake +1F361 ; fully-qualified # 🍡 dango +1F95F ; fully-qualified # 🥟 dumpling +1F960 ; fully-qualified # 🥠 fortune cookie +1F961 ; fully-qualified # 🥡 takeout box + +# subgroup: food-marine +1F980 ; fully-qualified # 🦀 crab +1F99E ; fully-qualified # 🦞 lobster +1F990 ; fully-qualified # 🦐 shrimp +1F991 ; fully-qualified # 🦑 squid +1F9AA ; fully-qualified # 🦪 oyster + +# subgroup: food-sweet +1F366 ; fully-qualified # 🍦 soft ice cream +1F367 ; fully-qualified # 🍧 shaved ice +1F368 ; fully-qualified # 🍨 ice cream +1F369 ; fully-qualified # 🍩 doughnut +1F36A ; fully-qualified # 🍪 cookie +1F382 ; fully-qualified # 🎂 birthday cake +1F370 ; fully-qualified # 🍰 shortcake +1F9C1 ; fully-qualified # 🧁 cupcake +1F967 ; fully-qualified # 🥧 pie +1F36B ; fully-qualified # 🍫 chocolate bar +1F36C ; fully-qualified # 🍬 candy +1F36D ; fully-qualified # 🍭 lollipop +1F36E ; fully-qualified # 🍮 custard +1F36F ; fully-qualified # 🍯 honey pot + +# subgroup: drink +1F37C ; fully-qualified # 🍼 baby bottle +1F95B ; fully-qualified # 🥛 glass of milk +2615 ; fully-qualified # ☕ hot beverage +1F375 ; fully-qualified # 🍵 teacup without handle +1F376 ; fully-qualified # 🍶 sake +1F37E ; fully-qualified # 🍾 bottle with popping cork +1F377 ; fully-qualified # 🍷 wine glass +1F378 ; fully-qualified # 🍸 cocktail glass +1F379 ; fully-qualified # 🍹 tropical drink +1F37A ; fully-qualified # 🍺 beer mug +1F37B ; fully-qualified # 🍻 clinking beer mugs +1F942 ; fully-qualified # 🥂 clinking glasses +1F943 ; fully-qualified # 🥃 tumbler glass +1F964 ; fully-qualified # 🥤 cup with straw +1F9C3 ; fully-qualified # 🧃 beverage box +1F9C9 ; fully-qualified # 🧉 mate +1F9CA ; fully-qualified # 🧊 ice cube + +# subgroup: dishware +1F962 ; fully-qualified # 🥢 chopsticks +1F37D FE0F ; fully-qualified # 🍽️ fork and knife with plate +1F37D ; unqualified # 🍽 fork and knife with plate +1F374 ; fully-qualified # 🍴 fork and knife +1F944 ; fully-qualified # 🥄 spoon +1F52A ; fully-qualified # 🔪 kitchen knife +1F3FA ; fully-qualified # 🏺 amphora + +# Food & Drink subtotal: 123 +# Food & Drink subtotal: 123 w/o modifiers + +# group: Travel & Places + +# subgroup: place-map +1F30D ; fully-qualified # 🌍 globe showing Europe-Africa +1F30E ; fully-qualified # 🌎 globe showing Americas +1F30F ; fully-qualified # 🌏 globe showing Asia-Australia +1F310 ; fully-qualified # 🌐 globe with meridians +1F5FA FE0F ; fully-qualified # 🗺️ world map +1F5FA ; unqualified # 🗺 world map +1F5FE ; fully-qualified # 🗾 map of Japan +1F9ED ; fully-qualified # 🧭 compass + +# subgroup: place-geographic +1F3D4 FE0F ; fully-qualified # 🏔️ snow-capped mountain +1F3D4 ; unqualified # 🏔 snow-capped mountain +26F0 FE0F ; fully-qualified # ⛰️ mountain +26F0 ; unqualified # ⛰ mountain +1F30B ; fully-qualified # 🌋 volcano +1F5FB ; fully-qualified # 🗻 mount fuji +1F3D5 FE0F ; fully-qualified # 🏕️ camping +1F3D5 ; unqualified # 🏕 camping +1F3D6 FE0F ; fully-qualified # 🏖️ beach with umbrella +1F3D6 ; unqualified # 🏖 beach with umbrella +1F3DC FE0F ; fully-qualified # 🏜️ desert +1F3DC ; unqualified # 🏜 desert +1F3DD FE0F ; fully-qualified # 🏝️ desert island +1F3DD ; unqualified # 🏝 desert island +1F3DE FE0F ; fully-qualified # 🏞️ national park +1F3DE ; unqualified # 🏞 national park + +# subgroup: place-building +1F3DF FE0F ; fully-qualified # 🏟️ stadium +1F3DF ; unqualified # 🏟 stadium +1F3DB FE0F ; fully-qualified # 🏛️ classical building +1F3DB ; unqualified # 🏛 classical building +1F3D7 FE0F ; fully-qualified # 🏗️ building construction +1F3D7 ; unqualified # 🏗 building construction +1F9F1 ; fully-qualified # 🧱 brick +1F3D8 FE0F ; fully-qualified # 🏘️ houses +1F3D8 ; unqualified # 🏘 houses +1F3DA FE0F ; fully-qualified # 🏚️ derelict house +1F3DA ; unqualified # 🏚 derelict house +1F3E0 ; fully-qualified # 🏠 house +1F3E1 ; fully-qualified # 🏡 house with garden +1F3E2 ; fully-qualified # 🏢 office building +1F3E3 ; fully-qualified # 🏣 Japanese post office +1F3E4 ; fully-qualified # 🏤 post office +1F3E5 ; fully-qualified # 🏥 hospital +1F3E6 ; fully-qualified # 🏦 bank +1F3E8 ; fully-qualified # 🏨 hotel +1F3E9 ; fully-qualified # 🏩 love hotel +1F3EA ; fully-qualified # 🏪 convenience store +1F3EB ; fully-qualified # 🏫 school +1F3EC ; fully-qualified # 🏬 department store +1F3ED ; fully-qualified # 🏭 factory +1F3EF ; fully-qualified # 🏯 Japanese castle +1F3F0 ; fully-qualified # 🏰 castle +1F492 ; fully-qualified # 💒 wedding +1F5FC ; fully-qualified # 🗼 Tokyo tower +1F5FD ; fully-qualified # 🗽 Statue of Liberty + +# subgroup: place-religious +26EA ; fully-qualified # ⛪ church +1F54C ; fully-qualified # 🕌 mosque +1F6D5 ; fully-qualified # 🛕 hindu temple +1F54D ; fully-qualified # 🕍 synagogue +26E9 FE0F ; fully-qualified # ⛩️ shinto shrine +26E9 ; unqualified # ⛩ shinto shrine +1F54B ; fully-qualified # 🕋 kaaba + +# subgroup: place-other +26F2 ; fully-qualified # ⛲ fountain +26FA ; fully-qualified # ⛺ tent +1F301 ; fully-qualified # 🌁 foggy +1F303 ; fully-qualified # 🌃 night with stars +1F3D9 FE0F ; fully-qualified # 🏙️ cityscape +1F3D9 ; unqualified # 🏙 cityscape +1F304 ; fully-qualified # 🌄 sunrise over mountains +1F305 ; fully-qualified # 🌅 sunrise +1F306 ; fully-qualified # 🌆 cityscape at dusk +1F307 ; fully-qualified # 🌇 sunset +1F309 ; fully-qualified # 🌉 bridge at night +2668 FE0F ; fully-qualified # ♨️ hot springs +2668 ; unqualified # ♨ hot springs +1F3A0 ; fully-qualified # 🎠 carousel horse +1F3A1 ; fully-qualified # 🎡 ferris wheel +1F3A2 ; fully-qualified # 🎢 roller coaster +1F488 ; fully-qualified # 💈 barber pole +1F3AA ; fully-qualified # 🎪 circus tent + +# subgroup: transport-ground +1F682 ; fully-qualified # 🚂 locomotive +1F683 ; fully-qualified # 🚃 railway car +1F684 ; fully-qualified # 🚄 high-speed train +1F685 ; fully-qualified # 🚅 bullet train +1F686 ; fully-qualified # 🚆 train +1F687 ; fully-qualified # 🚇 metro +1F688 ; fully-qualified # 🚈 light rail +1F689 ; fully-qualified # 🚉 station +1F68A ; fully-qualified # 🚊 tram +1F69D ; fully-qualified # 🚝 monorail +1F69E ; fully-qualified # 🚞 mountain railway +1F68B ; fully-qualified # 🚋 tram car +1F68C ; fully-qualified # 🚌 bus +1F68D ; fully-qualified # 🚍 oncoming bus +1F68E ; fully-qualified # 🚎 trolleybus +1F690 ; fully-qualified # 🚐 minibus +1F691 ; fully-qualified # 🚑 ambulance +1F692 ; fully-qualified # 🚒 fire engine +1F693 ; fully-qualified # 🚓 police car +1F694 ; fully-qualified # 🚔 oncoming police car +1F695 ; fully-qualified # 🚕 taxi +1F696 ; fully-qualified # 🚖 oncoming taxi +1F697 ; fully-qualified # 🚗 automobile +1F698 ; fully-qualified # 🚘 oncoming automobile +1F699 ; fully-qualified # 🚙 sport utility vehicle +1F69A ; fully-qualified # 🚚 delivery truck +1F69B ; fully-qualified # 🚛 articulated lorry +1F69C ; fully-qualified # 🚜 tractor +1F3CE FE0F ; fully-qualified # 🏎️ racing car +1F3CE ; unqualified # 🏎 racing car +1F3CD FE0F ; fully-qualified # 🏍️ motorcycle +1F3CD ; unqualified # 🏍 motorcycle +1F6F5 ; fully-qualified # 🛵 motor scooter +1F9BD ; fully-qualified # 🦽 manual wheelchair +1F9BC ; fully-qualified # 🦼 motorized wheelchair +1F6FA ; fully-qualified # 🛺 auto rickshaw +1F6B2 ; fully-qualified # 🚲 bicycle +1F6F4 ; fully-qualified # 🛴 kick scooter +1F6F9 ; fully-qualified # 🛹 skateboard +1F68F ; fully-qualified # 🚏 bus stop +1F6E3 FE0F ; fully-qualified # 🛣️ motorway +1F6E3 ; unqualified # 🛣 motorway +1F6E4 FE0F ; fully-qualified # 🛤️ railway track +1F6E4 ; unqualified # 🛤 railway track +1F6E2 FE0F ; fully-qualified # 🛢️ oil drum +1F6E2 ; unqualified # 🛢 oil drum +26FD ; fully-qualified # ⛽ fuel pump +1F6A8 ; fully-qualified # 🚨 police car light +1F6A5 ; fully-qualified # 🚥 horizontal traffic light +1F6A6 ; fully-qualified # 🚦 vertical traffic light +1F6D1 ; fully-qualified # 🛑 stop sign +1F6A7 ; fully-qualified # 🚧 construction + +# subgroup: transport-water +2693 ; fully-qualified # ⚓ anchor +26F5 ; fully-qualified # ⛵ sailboat +1F6F6 ; fully-qualified # 🛶 canoe +1F6A4 ; fully-qualified # 🚤 speedboat +1F6F3 FE0F ; fully-qualified # 🛳️ passenger ship +1F6F3 ; unqualified # 🛳 passenger ship +26F4 FE0F ; fully-qualified # ⛴️ ferry +26F4 ; unqualified # ⛴ ferry +1F6E5 FE0F ; fully-qualified # 🛥️ motor boat +1F6E5 ; unqualified # 🛥 motor boat +1F6A2 ; fully-qualified # 🚢 ship + +# subgroup: transport-air +2708 FE0F ; fully-qualified # ✈️ airplane +2708 ; unqualified # ✈ airplane +1F6E9 FE0F ; fully-qualified # 🛩️ small airplane +1F6E9 ; unqualified # 🛩 small airplane +1F6EB ; fully-qualified # 🛫 airplane departure +1F6EC ; fully-qualified # 🛬 airplane arrival +1FA82 ; fully-qualified # 🪂 parachute +1F4BA ; fully-qualified # 💺 seat +1F681 ; fully-qualified # 🚁 helicopter +1F69F ; fully-qualified # 🚟 suspension railway +1F6A0 ; fully-qualified # 🚠 mountain cableway +1F6A1 ; fully-qualified # 🚡 aerial tramway +1F6F0 FE0F ; fully-qualified # 🛰️ satellite +1F6F0 ; unqualified # 🛰 satellite +1F680 ; fully-qualified # 🚀 rocket +1F6F8 ; fully-qualified # 🛸 flying saucer + +# subgroup: hotel +1F6CE FE0F ; fully-qualified # 🛎️ bellhop bell +1F6CE ; unqualified # 🛎 bellhop bell +1F9F3 ; fully-qualified # 🧳 luggage + +# subgroup: time +231B ; fully-qualified # ⌛ hourglass done +23F3 ; fully-qualified # ⏳ hourglass not done +231A ; fully-qualified # ⌚ watch +23F0 ; fully-qualified # ⏰ alarm clock +23F1 FE0F ; fully-qualified # ⏱️ stopwatch +23F1 ; unqualified # ⏱ stopwatch +23F2 FE0F ; fully-qualified # ⏲️ timer clock +23F2 ; unqualified # ⏲ timer clock +1F570 FE0F ; fully-qualified # 🕰️ mantelpiece clock +1F570 ; unqualified # 🕰 mantelpiece clock +1F55B ; fully-qualified # 🕛 twelve o’clock +1F567 ; fully-qualified # 🕧 twelve-thirty +1F550 ; fully-qualified # 🕐 one o’clock +1F55C ; fully-qualified # 🕜 one-thirty +1F551 ; fully-qualified # 🕑 two o’clock +1F55D ; fully-qualified # 🕝 two-thirty +1F552 ; fully-qualified # 🕒 three o’clock +1F55E ; fully-qualified # 🕞 three-thirty +1F553 ; fully-qualified # 🕓 four o’clock +1F55F ; fully-qualified # 🕟 four-thirty +1F554 ; fully-qualified # 🕔 five o’clock +1F560 ; fully-qualified # 🕠 five-thirty +1F555 ; fully-qualified # 🕕 six o’clock +1F561 ; fully-qualified # 🕡 six-thirty +1F556 ; fully-qualified # 🕖 seven o’clock +1F562 ; fully-qualified # 🕢 seven-thirty +1F557 ; fully-qualified # 🕗 eight o’clock +1F563 ; fully-qualified # 🕣 eight-thirty +1F558 ; fully-qualified # 🕘 nine o’clock +1F564 ; fully-qualified # 🕤 nine-thirty +1F559 ; fully-qualified # 🕙 ten o’clock +1F565 ; fully-qualified # 🕥 ten-thirty +1F55A ; fully-qualified # 🕚 eleven o’clock +1F566 ; fully-qualified # 🕦 eleven-thirty + +# subgroup: sky & weather +1F311 ; fully-qualified # 🌑 new moon +1F312 ; fully-qualified # 🌒 waxing crescent moon +1F313 ; fully-qualified # 🌓 first quarter moon +1F314 ; fully-qualified # 🌔 waxing gibbous moon +1F315 ; fully-qualified # 🌕 full moon +1F316 ; fully-qualified # 🌖 waning gibbous moon +1F317 ; fully-qualified # 🌗 last quarter moon +1F318 ; fully-qualified # 🌘 waning crescent moon +1F319 ; fully-qualified # 🌙 crescent moon +1F31A ; fully-qualified # 🌚 new moon face +1F31B ; fully-qualified # 🌛 first quarter moon face +1F31C ; fully-qualified # 🌜 last quarter moon face +1F321 FE0F ; fully-qualified # 🌡️ thermometer +1F321 ; unqualified # 🌡 thermometer +2600 FE0F ; fully-qualified # ☀️ sun +2600 ; unqualified # ☀ sun +1F31D ; fully-qualified # 🌝 full moon face +1F31E ; fully-qualified # 🌞 sun with face +1FA90 ; fully-qualified # 🪐 ringed planet +2B50 ; fully-qualified # ⭐ star +1F31F ; fully-qualified # 🌟 glowing star +1F320 ; fully-qualified # 🌠 shooting star +1F30C ; fully-qualified # 🌌 milky way +2601 FE0F ; fully-qualified # ☁️ cloud +2601 ; unqualified # ☁ cloud +26C5 ; fully-qualified # ⛅ sun behind cloud +26C8 FE0F ; fully-qualified # ⛈️ cloud with lightning and rain +26C8 ; unqualified # ⛈ cloud with lightning and rain +1F324 FE0F ; fully-qualified # 🌤️ sun behind small cloud +1F324 ; unqualified # 🌤 sun behind small cloud +1F325 FE0F ; fully-qualified # 🌥️ sun behind large cloud +1F325 ; unqualified # 🌥 sun behind large cloud +1F326 FE0F ; fully-qualified # 🌦️ sun behind rain cloud +1F326 ; unqualified # 🌦 sun behind rain cloud +1F327 FE0F ; fully-qualified # 🌧️ cloud with rain +1F327 ; unqualified # 🌧 cloud with rain +1F328 FE0F ; fully-qualified # 🌨️ cloud with snow +1F328 ; unqualified # 🌨 cloud with snow +1F329 FE0F ; fully-qualified # 🌩️ cloud with lightning +1F329 ; unqualified # 🌩 cloud with lightning +1F32A FE0F ; fully-qualified # 🌪️ tornado +1F32A ; unqualified # 🌪 tornado +1F32B FE0F ; fully-qualified # 🌫️ fog +1F32B ; unqualified # 🌫 fog +1F32C FE0F ; fully-qualified # 🌬️ wind face +1F32C ; unqualified # 🌬 wind face +1F300 ; fully-qualified # 🌀 cyclone +1F308 ; fully-qualified # 🌈 rainbow +1F302 ; fully-qualified # 🌂 closed umbrella +2602 FE0F ; fully-qualified # ☂️ umbrella +2602 ; unqualified # ☂ umbrella +2614 ; fully-qualified # ☔ umbrella with rain drops +26F1 FE0F ; fully-qualified # ⛱️ umbrella on ground +26F1 ; unqualified # ⛱ umbrella on ground +26A1 ; fully-qualified # ⚡ high voltage +2744 FE0F ; fully-qualified # ❄️ snowflake +2744 ; unqualified # ❄ snowflake +2603 FE0F ; fully-qualified # ☃️ snowman +2603 ; unqualified # ☃ snowman +26C4 ; fully-qualified # ⛄ snowman without snow +2604 FE0F ; fully-qualified # ☄️ comet +2604 ; unqualified # ☄ comet +1F525 ; fully-qualified # 🔥 fire +1F4A7 ; fully-qualified # 💧 droplet +1F30A ; fully-qualified # 🌊 water wave + +# Travel & Places subtotal: 259 +# Travel & Places subtotal: 259 w/o modifiers + +# group: Activities + +# subgroup: event +1F383 ; fully-qualified # 🎃 jack-o-lantern +1F384 ; fully-qualified # 🎄 Christmas tree +1F386 ; fully-qualified # 🎆 fireworks +1F387 ; fully-qualified # 🎇 sparkler +1F9E8 ; fully-qualified # 🧨 firecracker +2728 ; fully-qualified # ✨ sparkles +1F388 ; fully-qualified # 🎈 balloon +1F389 ; fully-qualified # 🎉 party popper +1F38A ; fully-qualified # 🎊 confetti ball +1F38B ; fully-qualified # 🎋 tanabata tree +1F38D ; fully-qualified # 🎍 pine decoration +1F38E ; fully-qualified # 🎎 Japanese dolls +1F38F ; fully-qualified # 🎏 carp streamer +1F390 ; fully-qualified # 🎐 wind chime +1F391 ; fully-qualified # 🎑 moon viewing ceremony +1F9E7 ; fully-qualified # 🧧 red envelope +1F380 ; fully-qualified # 🎀 ribbon +1F381 ; fully-qualified # 🎁 wrapped gift +1F397 FE0F ; fully-qualified # 🎗️ reminder ribbon +1F397 ; unqualified # 🎗 reminder ribbon +1F39F FE0F ; fully-qualified # 🎟️ admission tickets +1F39F ; unqualified # 🎟 admission tickets +1F3AB ; fully-qualified # 🎫 ticket + +# subgroup: award-medal +1F396 FE0F ; fully-qualified # 🎖️ military medal +1F396 ; unqualified # 🎖 military medal +1F3C6 ; fully-qualified # 🏆 trophy +1F3C5 ; fully-qualified # 🏅 sports medal +1F947 ; fully-qualified # 🥇 1st place medal +1F948 ; fully-qualified # 🥈 2nd place medal +1F949 ; fully-qualified # 🥉 3rd place medal + +# subgroup: sport +26BD ; fully-qualified # ⚽ soccer ball +26BE ; fully-qualified # ⚾ baseball +1F94E ; fully-qualified # 🥎 softball +1F3C0 ; fully-qualified # 🏀 basketball +1F3D0 ; fully-qualified # 🏐 volleyball +1F3C8 ; fully-qualified # 🏈 american football +1F3C9 ; fully-qualified # 🏉 rugby football +1F3BE ; fully-qualified # 🎾 tennis +1F94F ; fully-qualified # 🥏 flying disc +1F3B3 ; fully-qualified # 🎳 bowling +1F3CF ; fully-qualified # 🏏 cricket game +1F3D1 ; fully-qualified # 🏑 field hockey +1F3D2 ; fully-qualified # 🏒 ice hockey +1F94D ; fully-qualified # 🥍 lacrosse +1F3D3 ; fully-qualified # 🏓 ping pong +1F3F8 ; fully-qualified # 🏸 badminton +1F94A ; fully-qualified # 🥊 boxing glove +1F94B ; fully-qualified # 🥋 martial arts uniform +1F945 ; fully-qualified # 🥅 goal net +26F3 ; fully-qualified # ⛳ flag in hole +26F8 FE0F ; fully-qualified # ⛸️ ice skate +26F8 ; unqualified # ⛸ ice skate +1F3A3 ; fully-qualified # 🎣 fishing pole +1F93F ; fully-qualified # 🤿 diving mask +1F3BD ; fully-qualified # 🎽 running shirt +1F3BF ; fully-qualified # 🎿 skis +1F6F7 ; fully-qualified # 🛷 sled +1F94C ; fully-qualified # 🥌 curling stone + +# subgroup: game +1F3AF ; fully-qualified # 🎯 direct hit +1FA80 ; fully-qualified # 🪀 yo-yo +1FA81 ; fully-qualified # 🪁 kite +1F3B1 ; fully-qualified # 🎱 pool 8 ball +1F52E ; fully-qualified # 🔮 crystal ball +1F9FF ; fully-qualified # 🧿 nazar amulet +1F3AE ; fully-qualified # 🎮 video game +1F579 FE0F ; fully-qualified # 🕹️ joystick +1F579 ; unqualified # 🕹 joystick +1F3B0 ; fully-qualified # 🎰 slot machine +1F3B2 ; fully-qualified # 🎲 game die +1F9E9 ; fully-qualified # 🧩 puzzle piece +1F9F8 ; fully-qualified # 🧸 teddy bear +2660 FE0F ; fully-qualified # ♠️ spade suit +2660 ; unqualified # ♠ spade suit +2665 FE0F ; fully-qualified # ♥️ heart suit +2665 ; unqualified # ♥ heart suit +2666 FE0F ; fully-qualified # ♦️ diamond suit +2666 ; unqualified # ♦ diamond suit +2663 FE0F ; fully-qualified # ♣️ club suit +2663 ; unqualified # ♣ club suit +265F FE0F ; fully-qualified # ♟️ chess pawn +265F ; unqualified # ♟ chess pawn +1F0CF ; fully-qualified # 🃏 joker +1F004 ; fully-qualified # 🀄 mahjong red dragon +1F3B4 ; fully-qualified # 🎴 flower playing cards + +# subgroup: arts & crafts +1F3AD ; fully-qualified # 🎭 performing arts +1F5BC FE0F ; fully-qualified # 🖼️ framed picture +1F5BC ; unqualified # 🖼 framed picture +1F3A8 ; fully-qualified # 🎨 artist palette +1F9F5 ; fully-qualified # 🧵 thread +1F9F6 ; fully-qualified # 🧶 yarn + +# Activities subtotal: 90 +# Activities subtotal: 90 w/o modifiers + +# group: Objects + +# subgroup: clothing +1F453 ; fully-qualified # 👓 glasses +1F576 FE0F ; fully-qualified # 🕶️ sunglasses +1F576 ; unqualified # 🕶 sunglasses +1F97D ; fully-qualified # 🥽 goggles +1F97C ; fully-qualified # 🥼 lab coat +1F9BA ; fully-qualified # 🦺 safety vest +1F454 ; fully-qualified # 👔 necktie +1F455 ; fully-qualified # 👕 t-shirt +1F456 ; fully-qualified # 👖 jeans +1F9E3 ; fully-qualified # 🧣 scarf +1F9E4 ; fully-qualified # 🧤 gloves +1F9E5 ; fully-qualified # 🧥 coat +1F9E6 ; fully-qualified # 🧦 socks +1F457 ; fully-qualified # 👗 dress +1F458 ; fully-qualified # 👘 kimono +1F97B ; fully-qualified # 🥻 sari +1FA71 ; fully-qualified # 🩱 one-piece swimsuit +1FA72 ; fully-qualified # 🩲 swim brief +1FA73 ; fully-qualified # 🩳 shorts +1F459 ; fully-qualified # 👙 bikini +1F45A ; fully-qualified # 👚 woman’s clothes +1F45B ; fully-qualified # 👛 purse +1F45C ; fully-qualified # 👜 handbag +1F45D ; fully-qualified # 👝 clutch bag +1F6CD FE0F ; fully-qualified # 🛍️ shopping bags +1F6CD ; unqualified # 🛍 shopping bags +1F392 ; fully-qualified # 🎒 backpack +1F45E ; fully-qualified # 👞 man’s shoe +1F45F ; fully-qualified # 👟 running shoe +1F97E ; fully-qualified # 🥾 hiking boot +1F97F ; fully-qualified # 🥿 flat shoe +1F460 ; fully-qualified # 👠 high-heeled shoe +1F461 ; fully-qualified # 👡 woman’s sandal +1FA70 ; fully-qualified # 🩰 ballet shoes +1F462 ; fully-qualified # 👢 woman’s boot +1F451 ; fully-qualified # 👑 crown +1F452 ; fully-qualified # 👒 woman’s hat +1F3A9 ; fully-qualified # 🎩 top hat +1F393 ; fully-qualified # 🎓 graduation cap +1F9E2 ; fully-qualified # 🧢 billed cap +26D1 FE0F ; fully-qualified # ⛑️ rescue worker’s helmet +26D1 ; unqualified # ⛑ rescue worker’s helmet +1F4FF ; fully-qualified # 📿 prayer beads +1F484 ; fully-qualified # 💄 lipstick +1F48D ; fully-qualified # 💍 ring +1F48E ; fully-qualified # 💎 gem stone + +# subgroup: sound +1F507 ; fully-qualified # 🔇 muted speaker +1F508 ; fully-qualified # 🔈 speaker low volume +1F509 ; fully-qualified # 🔉 speaker medium volume +1F50A ; fully-qualified # 🔊 speaker high volume +1F4E2 ; fully-qualified # 📢 loudspeaker +1F4E3 ; fully-qualified # 📣 megaphone +1F4EF ; fully-qualified # 📯 postal horn +1F514 ; fully-qualified # 🔔 bell +1F515 ; fully-qualified # 🔕 bell with slash + +# subgroup: music +1F3BC ; fully-qualified # 🎼 musical score +1F3B5 ; fully-qualified # 🎵 musical note +1F3B6 ; fully-qualified # 🎶 musical notes +1F399 FE0F ; fully-qualified # 🎙️ studio microphone +1F399 ; unqualified # 🎙 studio microphone +1F39A FE0F ; fully-qualified # 🎚️ level slider +1F39A ; unqualified # 🎚 level slider +1F39B FE0F ; fully-qualified # 🎛️ control knobs +1F39B ; unqualified # 🎛 control knobs +1F3A4 ; fully-qualified # 🎤 microphone +1F3A7 ; fully-qualified # 🎧 headphone +1F4FB ; fully-qualified # 📻 radio + +# subgroup: musical-instrument +1F3B7 ; fully-qualified # 🎷 saxophone +1F3B8 ; fully-qualified # 🎸 guitar +1F3B9 ; fully-qualified # 🎹 musical keyboard +1F3BA ; fully-qualified # 🎺 trumpet +1F3BB ; fully-qualified # 🎻 violin +1FA95 ; fully-qualified # 🪕 banjo +1F941 ; fully-qualified # 🥁 drum + +# subgroup: phone +1F4F1 ; fully-qualified # 📱 mobile phone +1F4F2 ; fully-qualified # 📲 mobile phone with arrow +260E FE0F ; fully-qualified # ☎️ telephone +260E ; unqualified # ☎ telephone +1F4DE ; fully-qualified # 📞 telephone receiver +1F4DF ; fully-qualified # 📟 pager +1F4E0 ; fully-qualified # 📠 fax machine + +# subgroup: computer +1F50B ; fully-qualified # 🔋 battery +1F50C ; fully-qualified # 🔌 electric plug +1F4BB ; fully-qualified # 💻 laptop computer +1F5A5 FE0F ; fully-qualified # 🖥️ desktop computer +1F5A5 ; unqualified # 🖥 desktop computer +1F5A8 FE0F ; fully-qualified # 🖨️ printer +1F5A8 ; unqualified # 🖨 printer +2328 FE0F ; fully-qualified # ⌨️ keyboard +2328 ; unqualified # ⌨ keyboard +1F5B1 FE0F ; fully-qualified # 🖱️ computer mouse +1F5B1 ; unqualified # 🖱 computer mouse +1F5B2 FE0F ; fully-qualified # 🖲️ trackball +1F5B2 ; unqualified # 🖲 trackball +1F4BD ; fully-qualified # 💽 computer disk +1F4BE ; fully-qualified # 💾 floppy disk +1F4BF ; fully-qualified # 💿 optical disk +1F4C0 ; fully-qualified # 📀 dvd +1F9EE ; fully-qualified # 🧮 abacus + +# subgroup: light & video +1F3A5 ; fully-qualified # 🎥 movie camera +1F39E FE0F ; fully-qualified # 🎞️ film frames +1F39E ; unqualified # 🎞 film frames +1F4FD FE0F ; fully-qualified # 📽️ film projector +1F4FD ; unqualified # 📽 film projector +1F3AC ; fully-qualified # 🎬 clapper board +1F4FA ; fully-qualified # 📺 television +1F4F7 ; fully-qualified # 📷 camera +1F4F8 ; fully-qualified # 📸 camera with flash +1F4F9 ; fully-qualified # 📹 video camera +1F4FC ; fully-qualified # 📼 videocassette +1F50D ; fully-qualified # 🔍 magnifying glass tilted left +1F50E ; fully-qualified # 🔎 magnifying glass tilted right +1F56F FE0F ; fully-qualified # 🕯️ candle +1F56F ; unqualified # 🕯 candle +1F4A1 ; fully-qualified # 💡 light bulb +1F526 ; fully-qualified # 🔦 flashlight +1F3EE ; fully-qualified # 🏮 red paper lantern +1FA94 ; fully-qualified # 🪔 diya lamp + +# subgroup: book-paper +1F4D4 ; fully-qualified # 📔 notebook with decorative cover +1F4D5 ; fully-qualified # 📕 closed book +1F4D6 ; fully-qualified # 📖 open book +1F4D7 ; fully-qualified # 📗 green book +1F4D8 ; fully-qualified # 📘 blue book +1F4D9 ; fully-qualified # 📙 orange book +1F4DA ; fully-qualified # 📚 books +1F4D3 ; fully-qualified # 📓 notebook +1F4D2 ; fully-qualified # 📒 ledger +1F4C3 ; fully-qualified # 📃 page with curl +1F4DC ; fully-qualified # 📜 scroll +1F4C4 ; fully-qualified # 📄 page facing up +1F4F0 ; fully-qualified # 📰 newspaper +1F5DE FE0F ; fully-qualified # 🗞️ rolled-up newspaper +1F5DE ; unqualified # 🗞 rolled-up newspaper +1F4D1 ; fully-qualified # 📑 bookmark tabs +1F516 ; fully-qualified # 🔖 bookmark +1F3F7 FE0F ; fully-qualified # 🏷️ label +1F3F7 ; unqualified # 🏷 label + +# subgroup: money +1F4B0 ; fully-qualified # 💰 money bag +1F4B4 ; fully-qualified # 💴 yen banknote +1F4B5 ; fully-qualified # 💵 dollar banknote +1F4B6 ; fully-qualified # 💶 euro banknote +1F4B7 ; fully-qualified # 💷 pound banknote +1F4B8 ; fully-qualified # 💸 money with wings +1F4B3 ; fully-qualified # 💳 credit card +1F9FE ; fully-qualified # 🧾 receipt +1F4B9 ; fully-qualified # 💹 chart increasing with yen +1F4B1 ; fully-qualified # 💱 currency exchange +1F4B2 ; fully-qualified # 💲 heavy dollar sign + +# subgroup: mail +2709 FE0F ; fully-qualified # ✉️ envelope +2709 ; unqualified # ✉ envelope +1F4E7 ; fully-qualified # 📧 e-mail +1F4E8 ; fully-qualified # 📨 incoming envelope +1F4E9 ; fully-qualified # 📩 envelope with arrow +1F4E4 ; fully-qualified # 📤 outbox tray +1F4E5 ; fully-qualified # 📥 inbox tray +1F4E6 ; fully-qualified # 📦 package +1F4EB ; fully-qualified # 📫 closed mailbox with raised flag +1F4EA ; fully-qualified # 📪 closed mailbox with lowered flag +1F4EC ; fully-qualified # 📬 open mailbox with raised flag +1F4ED ; fully-qualified # 📭 open mailbox with lowered flag +1F4EE ; fully-qualified # 📮 postbox +1F5F3 FE0F ; fully-qualified # 🗳️ ballot box with ballot +1F5F3 ; unqualified # 🗳 ballot box with ballot + +# subgroup: writing +270F FE0F ; fully-qualified # ✏️ pencil +270F ; unqualified # ✏ pencil +2712 FE0F ; fully-qualified # ✒️ black nib +2712 ; unqualified # ✒ black nib +1F58B FE0F ; fully-qualified # 🖋️ fountain pen +1F58B ; unqualified # 🖋 fountain pen +1F58A FE0F ; fully-qualified # 🖊️ pen +1F58A ; unqualified # 🖊 pen +1F58C FE0F ; fully-qualified # 🖌️ paintbrush +1F58C ; unqualified # 🖌 paintbrush +1F58D FE0F ; fully-qualified # 🖍️ crayon +1F58D ; unqualified # 🖍 crayon +1F4DD ; fully-qualified # 📝 memo + +# subgroup: office +1F4BC ; fully-qualified # 💼 briefcase +1F4C1 ; fully-qualified # 📁 file folder +1F4C2 ; fully-qualified # 📂 open file folder +1F5C2 FE0F ; fully-qualified # 🗂️ card index dividers +1F5C2 ; unqualified # 🗂 card index dividers +1F4C5 ; fully-qualified # 📅 calendar +1F4C6 ; fully-qualified # 📆 tear-off calendar +1F5D2 FE0F ; fully-qualified # 🗒️ spiral notepad +1F5D2 ; unqualified # 🗒 spiral notepad +1F5D3 FE0F ; fully-qualified # 🗓️ spiral calendar +1F5D3 ; unqualified # 🗓 spiral calendar +1F4C7 ; fully-qualified # 📇 card index +1F4C8 ; fully-qualified # 📈 chart increasing +1F4C9 ; fully-qualified # 📉 chart decreasing +1F4CA ; fully-qualified # 📊 bar chart +1F4CB ; fully-qualified # 📋 clipboard +1F4CC ; fully-qualified # 📌 pushpin +1F4CD ; fully-qualified # 📍 round pushpin +1F4CE ; fully-qualified # 📎 paperclip +1F587 FE0F ; fully-qualified # 🖇️ linked paperclips +1F587 ; unqualified # 🖇 linked paperclips +1F4CF ; fully-qualified # 📏 straight ruler +1F4D0 ; fully-qualified # 📐 triangular ruler +2702 FE0F ; fully-qualified # ✂️ scissors +2702 ; unqualified # ✂ scissors +1F5C3 FE0F ; fully-qualified # 🗃️ card file box +1F5C3 ; unqualified # 🗃 card file box +1F5C4 FE0F ; fully-qualified # 🗄️ file cabinet +1F5C4 ; unqualified # 🗄 file cabinet +1F5D1 FE0F ; fully-qualified # 🗑️ wastebasket +1F5D1 ; unqualified # 🗑 wastebasket + +# subgroup: lock +1F512 ; fully-qualified # 🔒 locked +1F513 ; fully-qualified # 🔓 unlocked +1F50F ; fully-qualified # 🔏 locked with pen +1F510 ; fully-qualified # 🔐 locked with key +1F511 ; fully-qualified # 🔑 key +1F5DD FE0F ; fully-qualified # 🗝️ old key +1F5DD ; unqualified # 🗝 old key + +# subgroup: tool +1F528 ; fully-qualified # 🔨 hammer +1FA93 ; fully-qualified # 🪓 axe +26CF FE0F ; fully-qualified # ⛏️ pick +26CF ; unqualified # ⛏ pick +2692 FE0F ; fully-qualified # ⚒️ hammer and pick +2692 ; unqualified # ⚒ hammer and pick +1F6E0 FE0F ; fully-qualified # 🛠️ hammer and wrench +1F6E0 ; unqualified # 🛠 hammer and wrench +1F5E1 FE0F ; fully-qualified # 🗡️ dagger +1F5E1 ; unqualified # 🗡 dagger +2694 FE0F ; fully-qualified # ⚔️ crossed swords +2694 ; unqualified # ⚔ crossed swords +1F52B ; fully-qualified # 🔫 pistol +1F3F9 ; fully-qualified # 🏹 bow and arrow +1F6E1 FE0F ; fully-qualified # 🛡️ shield +1F6E1 ; unqualified # 🛡 shield +1F527 ; fully-qualified # 🔧 wrench +1F529 ; fully-qualified # 🔩 nut and bolt +2699 FE0F ; fully-qualified # ⚙️ gear +2699 ; unqualified # ⚙ gear +1F5DC FE0F ; fully-qualified # 🗜️ clamp +1F5DC ; unqualified # 🗜 clamp +2696 FE0F ; fully-qualified # ⚖️ balance scale +2696 ; unqualified # ⚖ balance scale +1F9AF ; fully-qualified # 🦯 probing cane +1F517 ; fully-qualified # 🔗 link +26D3 FE0F ; fully-qualified # ⛓️ chains +26D3 ; unqualified # ⛓ chains +1F9F0 ; fully-qualified # 🧰 toolbox +1F9F2 ; fully-qualified # 🧲 magnet + +# subgroup: science +2697 FE0F ; fully-qualified # ⚗️ alembic +2697 ; unqualified # ⚗ alembic +1F9EA ; fully-qualified # 🧪 test tube +1F9EB ; fully-qualified # 🧫 petri dish +1F9EC ; fully-qualified # 🧬 dna +1F52C ; fully-qualified # 🔬 microscope +1F52D ; fully-qualified # 🔭 telescope +1F4E1 ; fully-qualified # 📡 satellite antenna + +# subgroup: medical +1F489 ; fully-qualified # 💉 syringe +1FA78 ; fully-qualified # 🩸 drop of blood +1F48A ; fully-qualified # 💊 pill +1FA79 ; fully-qualified # 🩹 adhesive bandage +1FA7A ; fully-qualified # 🩺 stethoscope + +# subgroup: household +1F6AA ; fully-qualified # 🚪 door +1F6CF FE0F ; fully-qualified # 🛏️ bed +1F6CF ; unqualified # 🛏 bed +1F6CB FE0F ; fully-qualified # 🛋️ couch and lamp +1F6CB ; unqualified # 🛋 couch and lamp +1FA91 ; fully-qualified # 🪑 chair +1F6BD ; fully-qualified # 🚽 toilet +1F6BF ; fully-qualified # 🚿 shower +1F6C1 ; fully-qualified # 🛁 bathtub +1FA92 ; fully-qualified # 🪒 razor +1F9F4 ; fully-qualified # 🧴 lotion bottle +1F9F7 ; fully-qualified # 🧷 safety pin +1F9F9 ; fully-qualified # 🧹 broom +1F9FA ; fully-qualified # 🧺 basket +1F9FB ; fully-qualified # 🧻 roll of paper +1F9FC ; fully-qualified # 🧼 soap +1F9FD ; fully-qualified # 🧽 sponge +1F9EF ; fully-qualified # 🧯 fire extinguisher +1F6D2 ; fully-qualified # 🛒 shopping cart + +# subgroup: other-object +1F6AC ; fully-qualified # 🚬 cigarette +26B0 FE0F ; fully-qualified # ⚰️ coffin +26B0 ; unqualified # ⚰ coffin +26B1 FE0F ; fully-qualified # ⚱️ funeral urn +26B1 ; unqualified # ⚱ funeral urn +1F5FF ; fully-qualified # 🗿 moai + +# Objects subtotal: 282 +# Objects subtotal: 282 w/o modifiers + +# group: Symbols + +# subgroup: transport-sign +1F3E7 ; fully-qualified # 🏧 ATM sign +1F6AE ; fully-qualified # 🚮 litter in bin sign +1F6B0 ; fully-qualified # 🚰 potable water +267F ; fully-qualified # ♿ wheelchair symbol +1F6B9 ; fully-qualified # 🚹 men’s room +1F6BA ; fully-qualified # 🚺 women’s room +1F6BB ; fully-qualified # 🚻 restroom +1F6BC ; fully-qualified # 🚼 baby symbol +1F6BE ; fully-qualified # 🚾 water closet +1F6C2 ; fully-qualified # 🛂 passport control +1F6C3 ; fully-qualified # 🛃 customs +1F6C4 ; fully-qualified # 🛄 baggage claim +1F6C5 ; fully-qualified # 🛅 left luggage + +# subgroup: warning +26A0 FE0F ; fully-qualified # ⚠️ warning +26A0 ; unqualified # ⚠ warning +1F6B8 ; fully-qualified # 🚸 children crossing +26D4 ; fully-qualified # ⛔ no entry +1F6AB ; fully-qualified # 🚫 prohibited +1F6B3 ; fully-qualified # 🚳 no bicycles +1F6AD ; fully-qualified # 🚭 no smoking +1F6AF ; fully-qualified # 🚯 no littering +1F6B1 ; fully-qualified # 🚱 non-potable water +1F6B7 ; fully-qualified # 🚷 no pedestrians +1F4F5 ; fully-qualified # 📵 no mobile phones +1F51E ; fully-qualified # 🔞 no one under eighteen +2622 FE0F ; fully-qualified # ☢️ radioactive +2622 ; unqualified # ☢ radioactive +2623 FE0F ; fully-qualified # ☣️ biohazard +2623 ; unqualified # ☣ biohazard + +# subgroup: arrow +2B06 FE0F ; fully-qualified # ⬆️ up arrow +2B06 ; unqualified # ⬆ up arrow +2197 FE0F ; fully-qualified # ↗️ up-right arrow +2197 ; unqualified # ↗ up-right arrow +27A1 FE0F ; fully-qualified # ➡️ right arrow +27A1 ; unqualified # ➡ right arrow +2198 FE0F ; fully-qualified # ↘️ down-right arrow +2198 ; unqualified # ↘ down-right arrow +2B07 FE0F ; fully-qualified # ⬇️ down arrow +2B07 ; unqualified # ⬇ down arrow +2199 FE0F ; fully-qualified # ↙️ down-left arrow +2199 ; unqualified # ↙ down-left arrow +2B05 FE0F ; fully-qualified # ⬅️ left arrow +2B05 ; unqualified # ⬅ left arrow +2196 FE0F ; fully-qualified # ↖️ up-left arrow +2196 ; unqualified # ↖ up-left arrow +2195 FE0F ; fully-qualified # ↕️ up-down arrow +2195 ; unqualified # ↕ up-down arrow +2194 FE0F ; fully-qualified # ↔️ left-right arrow +2194 ; unqualified # ↔ left-right arrow +21A9 FE0F ; fully-qualified # ↩️ right arrow curving left +21A9 ; unqualified # ↩ right arrow curving left +21AA FE0F ; fully-qualified # ↪️ left arrow curving right +21AA ; unqualified # ↪ left arrow curving right +2934 FE0F ; fully-qualified # ⤴️ right arrow curving up +2934 ; unqualified # ⤴ right arrow curving up +2935 FE0F ; fully-qualified # ⤵️ right arrow curving down +2935 ; unqualified # ⤵ right arrow curving down +1F503 ; fully-qualified # 🔃 clockwise vertical arrows +1F504 ; fully-qualified # 🔄 counterclockwise arrows button +1F519 ; fully-qualified # 🔙 BACK arrow +1F51A ; fully-qualified # 🔚 END arrow +1F51B ; fully-qualified # 🔛 ON! arrow +1F51C ; fully-qualified # 🔜 SOON arrow +1F51D ; fully-qualified # 🔝 TOP arrow + +# subgroup: religion +1F6D0 ; fully-qualified # 🛐 place of worship +269B FE0F ; fully-qualified # ⚛️ atom symbol +269B ; unqualified # ⚛ atom symbol +1F549 FE0F ; fully-qualified # 🕉️ om +1F549 ; unqualified # 🕉 om +2721 FE0F ; fully-qualified # ✡️ star of David +2721 ; unqualified # ✡ star of David +2638 FE0F ; fully-qualified # ☸️ wheel of dharma +2638 ; unqualified # ☸ wheel of dharma +262F FE0F ; fully-qualified # ☯️ yin yang +262F ; unqualified # ☯ yin yang +271D FE0F ; fully-qualified # ✝️ latin cross +271D ; unqualified # ✝ latin cross +2626 FE0F ; fully-qualified # ☦️ orthodox cross +2626 ; unqualified # ☦ orthodox cross +262A FE0F ; fully-qualified # ☪️ star and crescent +262A ; unqualified # ☪ star and crescent +262E FE0F ; fully-qualified # ☮️ peace symbol +262E ; unqualified # ☮ peace symbol +1F54E ; fully-qualified # 🕎 menorah +1F52F ; fully-qualified # 🔯 dotted six-pointed star + +# subgroup: zodiac +2648 ; fully-qualified # ♈ Aries +2649 ; fully-qualified # ♉ Taurus +264A ; fully-qualified # ♊ Gemini +264B ; fully-qualified # ♋ Cancer +264C ; fully-qualified # ♌ Leo +264D ; fully-qualified # ♍ Virgo +264E ; fully-qualified # ♎ Libra +264F ; fully-qualified # ♏ Scorpio +2650 ; fully-qualified # ♐ Sagittarius +2651 ; fully-qualified # ♑ Capricorn +2652 ; fully-qualified # ♒ Aquarius +2653 ; fully-qualified # ♓ Pisces +26CE ; fully-qualified # ⛎ Ophiuchus + +# subgroup: av-symbol +1F500 ; fully-qualified # 🔀 shuffle tracks button +1F501 ; fully-qualified # 🔁 repeat button +1F502 ; fully-qualified # 🔂 repeat single button +25B6 FE0F ; fully-qualified # ▶️ play button +25B6 ; unqualified # ▶ play button +23E9 ; fully-qualified # ⏩ fast-forward button +23ED FE0F ; fully-qualified # ⏭️ next track button +23ED ; unqualified # ⏭ next track button +23EF FE0F ; fully-qualified # ⏯️ play or pause button +23EF ; unqualified # ⏯ play or pause button +25C0 FE0F ; fully-qualified # ◀️ reverse button +25C0 ; unqualified # ◀ reverse button +23EA ; fully-qualified # ⏪ fast reverse button +23EE FE0F ; fully-qualified # ⏮️ last track button +23EE ; unqualified # ⏮ last track button +1F53C ; fully-qualified # 🔼 upwards button +23EB ; fully-qualified # ⏫ fast up button +1F53D ; fully-qualified # 🔽 downwards button +23EC ; fully-qualified # ⏬ fast down button +23F8 FE0F ; fully-qualified # ⏸️ pause button +23F8 ; unqualified # ⏸ pause button +23F9 FE0F ; fully-qualified # ⏹️ stop button +23F9 ; unqualified # ⏹ stop button +23FA FE0F ; fully-qualified # ⏺️ record button +23FA ; unqualified # ⏺ record button +23CF FE0F ; fully-qualified # ⏏️ eject button +23CF ; unqualified # ⏏ eject button +1F3A6 ; fully-qualified # 🎦 cinema +1F505 ; fully-qualified # 🔅 dim button +1F506 ; fully-qualified # 🔆 bright button +1F4F6 ; fully-qualified # 📶 antenna bars +1F4F3 ; fully-qualified # 📳 vibration mode +1F4F4 ; fully-qualified # 📴 mobile phone off + +# subgroup: gender +2640 FE0F ; fully-qualified # ♀️ female sign +2640 ; unqualified # ♀ female sign +2642 FE0F ; fully-qualified # ♂️ male sign +2642 ; unqualified # ♂ male sign + +# subgroup: other-symbol +2695 FE0F ; fully-qualified # ⚕️ medical symbol +2695 ; unqualified # ⚕ medical symbol +267E FE0F ; fully-qualified # ♾️ infinity +267E ; unqualified # ♾ infinity +267B FE0F ; fully-qualified # ♻️ recycling symbol +267B ; unqualified # ♻ recycling symbol +269C FE0F ; fully-qualified # ⚜️ fleur-de-lis +269C ; unqualified # ⚜ fleur-de-lis +1F531 ; fully-qualified # 🔱 trident emblem +1F4DB ; fully-qualified # 📛 name badge +1F530 ; fully-qualified # 🔰 Japanese symbol for beginner +2B55 ; fully-qualified # ⭕ hollow red circle +2705 ; fully-qualified # ✅ check mark button +2611 FE0F ; fully-qualified # ☑️ check box with check +2611 ; unqualified # ☑ check box with check +2714 FE0F ; fully-qualified # ✔️ check mark +2714 ; unqualified # ✔ check mark +2716 FE0F ; fully-qualified # ✖️ multiplication sign +2716 ; unqualified # ✖ multiplication sign +274C ; fully-qualified # ❌ cross mark +274E ; fully-qualified # ❎ cross mark button +2795 ; fully-qualified # ➕ plus sign +2796 ; fully-qualified # ➖ minus sign +2797 ; fully-qualified # ➗ division sign +27B0 ; fully-qualified # ➰ curly loop +27BF ; fully-qualified # ➿ double curly loop +303D FE0F ; fully-qualified # 〽️ part alternation mark +303D ; unqualified # 〽 part alternation mark +2733 FE0F ; fully-qualified # ✳️ eight-spoked asterisk +2733 ; unqualified # ✳ eight-spoked asterisk +2734 FE0F ; fully-qualified # ✴️ eight-pointed star +2734 ; unqualified # ✴ eight-pointed star +2747 FE0F ; fully-qualified # ❇️ sparkle +2747 ; unqualified # ❇ sparkle +203C FE0F ; fully-qualified # ‼️ double exclamation mark +203C ; unqualified # ‼ double exclamation mark +2049 FE0F ; fully-qualified # ⁉️ exclamation question mark +2049 ; unqualified # ⁉ exclamation question mark +2753 ; fully-qualified # ❓ question mark +2754 ; fully-qualified # ❔ white question mark +2755 ; fully-qualified # ❕ white exclamation mark +2757 ; fully-qualified # ❗ exclamation mark +3030 FE0F ; fully-qualified # 〰️ wavy dash +3030 ; unqualified # 〰 wavy dash +00A9 FE0F ; fully-qualified # ©️ copyright +00A9 ; unqualified # © copyright +00AE FE0F ; fully-qualified # ®️ registered +00AE ; unqualified # ® registered +2122 FE0F ; fully-qualified # ™️ trade mark +2122 ; unqualified # ™ trade mark + +# subgroup: keycap +0023 FE0F 20E3 ; fully-qualified # #️⃣ keycap: # +0023 20E3 ; unqualified # #⃣ keycap: # +002A FE0F 20E3 ; fully-qualified # *️⃣ keycap: * +002A 20E3 ; unqualified # *⃣ keycap: * +0030 FE0F 20E3 ; fully-qualified # 0️⃣ keycap: 0 +0030 20E3 ; unqualified # 0⃣ keycap: 0 +0031 FE0F 20E3 ; fully-qualified # 1️⃣ keycap: 1 +0031 20E3 ; unqualified # 1⃣ keycap: 1 +0032 FE0F 20E3 ; fully-qualified # 2️⃣ keycap: 2 +0032 20E3 ; unqualified # 2⃣ keycap: 2 +0033 FE0F 20E3 ; fully-qualified # 3️⃣ keycap: 3 +0033 20E3 ; unqualified # 3⃣ keycap: 3 +0034 FE0F 20E3 ; fully-qualified # 4️⃣ keycap: 4 +0034 20E3 ; unqualified # 4⃣ keycap: 4 +0035 FE0F 20E3 ; fully-qualified # 5️⃣ keycap: 5 +0035 20E3 ; unqualified # 5⃣ keycap: 5 +0036 FE0F 20E3 ; fully-qualified # 6️⃣ keycap: 6 +0036 20E3 ; unqualified # 6⃣ keycap: 6 +0037 FE0F 20E3 ; fully-qualified # 7️⃣ keycap: 7 +0037 20E3 ; unqualified # 7⃣ keycap: 7 +0038 FE0F 20E3 ; fully-qualified # 8️⃣ keycap: 8 +0038 20E3 ; unqualified # 8⃣ keycap: 8 +0039 FE0F 20E3 ; fully-qualified # 9️⃣ keycap: 9 +0039 20E3 ; unqualified # 9⃣ keycap: 9 +1F51F ; fully-qualified # 🔟 keycap: 10 + +# subgroup: alphanum +1F520 ; fully-qualified # 🔠 input latin uppercase +1F521 ; fully-qualified # 🔡 input latin lowercase +1F522 ; fully-qualified # 🔢 input numbers +1F523 ; fully-qualified # 🔣 input symbols +1F524 ; fully-qualified # 🔤 input latin letters +1F170 FE0F ; fully-qualified # 🅰️ A button (blood type) +1F170 ; unqualified # 🅰 A button (blood type) +1F18E ; fully-qualified # 🆎 AB button (blood type) +1F171 FE0F ; fully-qualified # 🅱️ B button (blood type) +1F171 ; unqualified # 🅱 B button (blood type) +1F191 ; fully-qualified # 🆑 CL button +1F192 ; fully-qualified # 🆒 COOL button +1F193 ; fully-qualified # 🆓 FREE button +2139 FE0F ; fully-qualified # ℹ️ information +2139 ; unqualified # ℹ information +1F194 ; fully-qualified # 🆔 ID button +24C2 FE0F ; fully-qualified # Ⓜ️ circled M +24C2 ; unqualified # Ⓜ circled M +1F195 ; fully-qualified # 🆕 NEW button +1F196 ; fully-qualified # 🆖 NG button +1F17E FE0F ; fully-qualified # 🅾️ O button (blood type) +1F17E ; unqualified # 🅾 O button (blood type) +1F197 ; fully-qualified # 🆗 OK button +1F17F FE0F ; fully-qualified # 🅿️ P button +1F17F ; unqualified # 🅿 P button +1F198 ; fully-qualified # 🆘 SOS button +1F199 ; fully-qualified # 🆙 UP! button +1F19A ; fully-qualified # 🆚 VS button +1F201 ; fully-qualified # 🈁 Japanese “here” button +1F202 FE0F ; fully-qualified # 🈂️ Japanese “service charge” button +1F202 ; unqualified # 🈂 Japanese “service charge” button +1F237 FE0F ; fully-qualified # 🈷️ Japanese “monthly amount” button +1F237 ; unqualified # 🈷 Japanese “monthly amount” button +1F236 ; fully-qualified # 🈶 Japanese “not free of charge” button +1F22F ; fully-qualified # 🈯 Japanese “reserved” button +1F250 ; fully-qualified # 🉐 Japanese “bargain” button +1F239 ; fully-qualified # 🈹 Japanese “discount” button +1F21A ; fully-qualified # 🈚 Japanese “free of charge” button +1F232 ; fully-qualified # 🈲 Japanese “prohibited” button +1F251 ; fully-qualified # 🉑 Japanese “acceptable” button +1F238 ; fully-qualified # 🈸 Japanese “application” button +1F234 ; fully-qualified # 🈴 Japanese “passing grade” button +1F233 ; fully-qualified # 🈳 Japanese “vacancy” button +3297 FE0F ; fully-qualified # ㊗️ Japanese “congratulations” button +3297 ; unqualified # ㊗ Japanese “congratulations” button +3299 FE0F ; fully-qualified # ㊙️ Japanese “secret” button +3299 ; unqualified # ㊙ Japanese “secret” button +1F23A ; fully-qualified # 🈺 Japanese “open for business” button +1F235 ; fully-qualified # 🈵 Japanese “no vacancy” button + +# subgroup: geometric +1F534 ; fully-qualified # 🔴 red circle +1F7E0 ; fully-qualified # 🟠 orange circle +1F7E1 ; fully-qualified # 🟡 yellow circle +1F7E2 ; fully-qualified # 🟢 green circle +1F535 ; fully-qualified # 🔵 blue circle +1F7E3 ; fully-qualified # 🟣 purple circle +1F7E4 ; fully-qualified # 🟤 brown circle +26AB ; fully-qualified # ⚫ black circle +26AA ; fully-qualified # ⚪ white circle +1F7E5 ; fully-qualified # 🟥 red square +1F7E7 ; fully-qualified # 🟧 orange square +1F7E8 ; fully-qualified # 🟨 yellow square +1F7E9 ; fully-qualified # 🟩 green square +1F7E6 ; fully-qualified # 🟦 blue square +1F7EA ; fully-qualified # 🟪 purple square +1F7EB ; fully-qualified # 🟫 brown square +2B1B ; fully-qualified # ⬛ black large square +2B1C ; fully-qualified # ⬜ white large square +25FC FE0F ; fully-qualified # ◼️ black medium square +25FC ; unqualified # ◼ black medium square +25FB FE0F ; fully-qualified # ◻️ white medium square +25FB ; unqualified # ◻ white medium square +25FE ; fully-qualified # ◾ black medium-small square +25FD ; fully-qualified # ◽ white medium-small square +25AA FE0F ; fully-qualified # ▪️ black small square +25AA ; unqualified # ▪ black small square +25AB FE0F ; fully-qualified # ▫️ white small square +25AB ; unqualified # ▫ white small square +1F536 ; fully-qualified # 🔶 large orange diamond +1F537 ; fully-qualified # 🔷 large blue diamond +1F538 ; fully-qualified # 🔸 small orange diamond +1F539 ; fully-qualified # 🔹 small blue diamond +1F53A ; fully-qualified # 🔺 red triangle pointed up +1F53B ; fully-qualified # 🔻 red triangle pointed down +1F4A0 ; fully-qualified # 💠 diamond with a dot +1F518 ; fully-qualified # 🔘 radio button +1F533 ; fully-qualified # 🔳 white square button +1F532 ; fully-qualified # 🔲 black square button + +# Symbols subtotal: 297 +# Symbols subtotal: 297 w/o modifiers + +# group: Flags + +# subgroup: flag +1F3C1 ; fully-qualified # 🏁 chequered flag +1F6A9 ; fully-qualified # 🚩 triangular flag +1F38C ; fully-qualified # 🎌 crossed flags +1F3F4 ; fully-qualified # 🏴 black flag +1F3F3 FE0F ; fully-qualified # 🏳️ white flag +1F3F3 ; unqualified # 🏳 white flag +1F3F3 FE0F 200D 1F308 ; fully-qualified # 🏳️‍🌈 rainbow flag +1F3F3 200D 1F308 ; unqualified # 🏳‍🌈 rainbow flag +1F3F4 200D 2620 FE0F ; fully-qualified # 🏴‍☠️ pirate flag +1F3F4 200D 2620 ; minimally-qualified # 🏴‍☠ pirate flag + +# subgroup: country-flag +1F1E6 1F1E8 ; fully-qualified # 🇦🇨 flag: Ascension Island +1F1E6 1F1E9 ; fully-qualified # 🇦🇩 flag: Andorra +1F1E6 1F1EA ; fully-qualified # 🇦🇪 flag: United Arab Emirates +1F1E6 1F1EB ; fully-qualified # 🇦🇫 flag: Afghanistan +1F1E6 1F1EC ; fully-qualified # 🇦🇬 flag: Antigua & Barbuda +1F1E6 1F1EE ; fully-qualified # 🇦🇮 flag: Anguilla +1F1E6 1F1F1 ; fully-qualified # 🇦🇱 flag: Albania +1F1E6 1F1F2 ; fully-qualified # 🇦🇲 flag: Armenia +1F1E6 1F1F4 ; fully-qualified # 🇦🇴 flag: Angola +1F1E6 1F1F6 ; fully-qualified # 🇦🇶 flag: Antarctica +1F1E6 1F1F7 ; fully-qualified # 🇦🇷 flag: Argentina +1F1E6 1F1F8 ; fully-qualified # 🇦🇸 flag: American Samoa +1F1E6 1F1F9 ; fully-qualified # 🇦🇹 flag: Austria +1F1E6 1F1FA ; fully-qualified # 🇦🇺 flag: Australia +1F1E6 1F1FC ; fully-qualified # 🇦🇼 flag: Aruba +1F1E6 1F1FD ; fully-qualified # 🇦🇽 flag: Åland Islands +1F1E6 1F1FF ; fully-qualified # 🇦🇿 flag: Azerbaijan +1F1E7 1F1E6 ; fully-qualified # 🇧🇦 flag: Bosnia & Herzegovina +1F1E7 1F1E7 ; fully-qualified # 🇧🇧 flag: Barbados +1F1E7 1F1E9 ; fully-qualified # 🇧🇩 flag: Bangladesh +1F1E7 1F1EA ; fully-qualified # 🇧🇪 flag: Belgium +1F1E7 1F1EB ; fully-qualified # 🇧🇫 flag: Burkina Faso +1F1E7 1F1EC ; fully-qualified # 🇧🇬 flag: Bulgaria +1F1E7 1F1ED ; fully-qualified # 🇧🇭 flag: Bahrain +1F1E7 1F1EE ; fully-qualified # 🇧🇮 flag: Burundi +1F1E7 1F1EF ; fully-qualified # 🇧🇯 flag: Benin +1F1E7 1F1F1 ; fully-qualified # 🇧🇱 flag: St. Barthélemy +1F1E7 1F1F2 ; fully-qualified # 🇧🇲 flag: Bermuda +1F1E7 1F1F3 ; fully-qualified # 🇧🇳 flag: Brunei +1F1E7 1F1F4 ; fully-qualified # 🇧🇴 flag: Bolivia +1F1E7 1F1F6 ; fully-qualified # 🇧🇶 flag: Caribbean Netherlands +1F1E7 1F1F7 ; fully-qualified # 🇧🇷 flag: Brazil +1F1E7 1F1F8 ; fully-qualified # 🇧🇸 flag: Bahamas +1F1E7 1F1F9 ; fully-qualified # 🇧🇹 flag: Bhutan +1F1E7 1F1FB ; fully-qualified # 🇧🇻 flag: Bouvet Island +1F1E7 1F1FC ; fully-qualified # 🇧🇼 flag: Botswana +1F1E7 1F1FE ; fully-qualified # 🇧🇾 flag: Belarus +1F1E7 1F1FF ; fully-qualified # 🇧🇿 flag: Belize +1F1E8 1F1E6 ; fully-qualified # 🇨🇦 flag: Canada +1F1E8 1F1E8 ; fully-qualified # 🇨🇨 flag: Cocos (Keeling) Islands +1F1E8 1F1E9 ; fully-qualified # 🇨🇩 flag: Congo - Kinshasa +1F1E8 1F1EB ; fully-qualified # 🇨🇫 flag: Central African Republic +1F1E8 1F1EC ; fully-qualified # 🇨🇬 flag: Congo - Brazzaville +1F1E8 1F1ED ; fully-qualified # 🇨🇭 flag: Switzerland +1F1E8 1F1EE ; fully-qualified # 🇨🇮 flag: Côte d’Ivoire +1F1E8 1F1F0 ; fully-qualified # 🇨🇰 flag: Cook Islands +1F1E8 1F1F1 ; fully-qualified # 🇨🇱 flag: Chile +1F1E8 1F1F2 ; fully-qualified # 🇨🇲 flag: Cameroon +1F1E8 1F1F3 ; fully-qualified # 🇨🇳 flag: China +1F1E8 1F1F4 ; fully-qualified # 🇨🇴 flag: Colombia +1F1E8 1F1F5 ; fully-qualified # 🇨🇵 flag: Clipperton Island +1F1E8 1F1F7 ; fully-qualified # 🇨🇷 flag: Costa Rica +1F1E8 1F1FA ; fully-qualified # 🇨🇺 flag: Cuba +1F1E8 1F1FB ; fully-qualified # 🇨🇻 flag: Cape Verde +1F1E8 1F1FC ; fully-qualified # 🇨🇼 flag: Curaçao +1F1E8 1F1FD ; fully-qualified # 🇨🇽 flag: Christmas Island +1F1E8 1F1FE ; fully-qualified # 🇨🇾 flag: Cyprus +1F1E8 1F1FF ; fully-qualified # 🇨🇿 flag: Czechia +1F1E9 1F1EA ; fully-qualified # 🇩🇪 flag: Germany +1F1E9 1F1EC ; fully-qualified # 🇩🇬 flag: Diego Garcia +1F1E9 1F1EF ; fully-qualified # 🇩🇯 flag: Djibouti +1F1E9 1F1F0 ; fully-qualified # 🇩🇰 flag: Denmark +1F1E9 1F1F2 ; fully-qualified # 🇩🇲 flag: Dominica +1F1E9 1F1F4 ; fully-qualified # 🇩🇴 flag: Dominican Republic +1F1E9 1F1FF ; fully-qualified # 🇩🇿 flag: Algeria +1F1EA 1F1E6 ; fully-qualified # 🇪🇦 flag: Ceuta & Melilla +1F1EA 1F1E8 ; fully-qualified # 🇪🇨 flag: Ecuador +1F1EA 1F1EA ; fully-qualified # 🇪🇪 flag: Estonia +1F1EA 1F1EC ; fully-qualified # 🇪🇬 flag: Egypt +1F1EA 1F1ED ; fully-qualified # 🇪🇭 flag: Western Sahara +1F1EA 1F1F7 ; fully-qualified # 🇪🇷 flag: Eritrea +1F1EA 1F1F8 ; fully-qualified # 🇪🇸 flag: Spain +1F1EA 1F1F9 ; fully-qualified # 🇪🇹 flag: Ethiopia +1F1EA 1F1FA ; fully-qualified # 🇪🇺 flag: European Union +1F1EB 1F1EE ; fully-qualified # 🇫🇮 flag: Finland +1F1EB 1F1EF ; fully-qualified # 🇫🇯 flag: Fiji +1F1EB 1F1F0 ; fully-qualified # 🇫🇰 flag: Falkland Islands +1F1EB 1F1F2 ; fully-qualified # 🇫🇲 flag: Micronesia +1F1EB 1F1F4 ; fully-qualified # 🇫🇴 flag: Faroe Islands +1F1EB 1F1F7 ; fully-qualified # 🇫🇷 flag: France +1F1EC 1F1E6 ; fully-qualified # 🇬🇦 flag: Gabon +1F1EC 1F1E7 ; fully-qualified # 🇬🇧 flag: United Kingdom +1F1EC 1F1E9 ; fully-qualified # 🇬🇩 flag: Grenada +1F1EC 1F1EA ; fully-qualified # 🇬🇪 flag: Georgia +1F1EC 1F1EB ; fully-qualified # 🇬🇫 flag: French Guiana +1F1EC 1F1EC ; fully-qualified # 🇬🇬 flag: Guernsey +1F1EC 1F1ED ; fully-qualified # 🇬🇭 flag: Ghana +1F1EC 1F1EE ; fully-qualified # 🇬🇮 flag: Gibraltar +1F1EC 1F1F1 ; fully-qualified # 🇬🇱 flag: Greenland +1F1EC 1F1F2 ; fully-qualified # 🇬🇲 flag: Gambia +1F1EC 1F1F3 ; fully-qualified # 🇬🇳 flag: Guinea +1F1EC 1F1F5 ; fully-qualified # 🇬🇵 flag: Guadeloupe +1F1EC 1F1F6 ; fully-qualified # 🇬🇶 flag: Equatorial Guinea +1F1EC 1F1F7 ; fully-qualified # 🇬🇷 flag: Greece +1F1EC 1F1F8 ; fully-qualified # 🇬🇸 flag: South Georgia & South Sandwich Islands +1F1EC 1F1F9 ; fully-qualified # 🇬🇹 flag: Guatemala +1F1EC 1F1FA ; fully-qualified # 🇬🇺 flag: Guam +1F1EC 1F1FC ; fully-qualified # 🇬🇼 flag: Guinea-Bissau +1F1EC 1F1FE ; fully-qualified # 🇬🇾 flag: Guyana +1F1ED 1F1F0 ; fully-qualified # 🇭🇰 flag: Hong Kong SAR China +1F1ED 1F1F2 ; fully-qualified # 🇭🇲 flag: Heard & McDonald Islands +1F1ED 1F1F3 ; fully-qualified # 🇭🇳 flag: Honduras +1F1ED 1F1F7 ; fully-qualified # 🇭🇷 flag: Croatia +1F1ED 1F1F9 ; fully-qualified # 🇭🇹 flag: Haiti +1F1ED 1F1FA ; fully-qualified # 🇭🇺 flag: Hungary +1F1EE 1F1E8 ; fully-qualified # 🇮🇨 flag: Canary Islands +1F1EE 1F1E9 ; fully-qualified # 🇮🇩 flag: Indonesia +1F1EE 1F1EA ; fully-qualified # 🇮🇪 flag: Ireland +1F1EE 1F1F1 ; fully-qualified # 🇮🇱 flag: Israel +1F1EE 1F1F2 ; fully-qualified # 🇮🇲 flag: Isle of Man +1F1EE 1F1F3 ; fully-qualified # 🇮🇳 flag: India +1F1EE 1F1F4 ; fully-qualified # 🇮🇴 flag: British Indian Ocean Territory +1F1EE 1F1F6 ; fully-qualified # 🇮🇶 flag: Iraq +1F1EE 1F1F7 ; fully-qualified # 🇮🇷 flag: Iran +1F1EE 1F1F8 ; fully-qualified # 🇮🇸 flag: Iceland +1F1EE 1F1F9 ; fully-qualified # 🇮🇹 flag: Italy +1F1EF 1F1EA ; fully-qualified # 🇯🇪 flag: Jersey +1F1EF 1F1F2 ; fully-qualified # 🇯🇲 flag: Jamaica +1F1EF 1F1F4 ; fully-qualified # 🇯🇴 flag: Jordan +1F1EF 1F1F5 ; fully-qualified # 🇯🇵 flag: Japan +1F1F0 1F1EA ; fully-qualified # 🇰🇪 flag: Kenya +1F1F0 1F1EC ; fully-qualified # 🇰🇬 flag: Kyrgyzstan +1F1F0 1F1ED ; fully-qualified # 🇰🇭 flag: Cambodia +1F1F0 1F1EE ; fully-qualified # 🇰🇮 flag: Kiribati +1F1F0 1F1F2 ; fully-qualified # 🇰🇲 flag: Comoros +1F1F0 1F1F3 ; fully-qualified # 🇰🇳 flag: St. Kitts & Nevis +1F1F0 1F1F5 ; fully-qualified # 🇰🇵 flag: North Korea +1F1F0 1F1F7 ; fully-qualified # 🇰🇷 flag: South Korea +1F1F0 1F1FC ; fully-qualified # 🇰🇼 flag: Kuwait +1F1F0 1F1FE ; fully-qualified # 🇰🇾 flag: Cayman Islands +1F1F0 1F1FF ; fully-qualified # 🇰🇿 flag: Kazakhstan +1F1F1 1F1E6 ; fully-qualified # 🇱🇦 flag: Laos +1F1F1 1F1E7 ; fully-qualified # 🇱🇧 flag: Lebanon +1F1F1 1F1E8 ; fully-qualified # 🇱🇨 flag: St. Lucia +1F1F1 1F1EE ; fully-qualified # 🇱🇮 flag: Liechtenstein +1F1F1 1F1F0 ; fully-qualified # 🇱🇰 flag: Sri Lanka +1F1F1 1F1F7 ; fully-qualified # 🇱🇷 flag: Liberia +1F1F1 1F1F8 ; fully-qualified # 🇱🇸 flag: Lesotho +1F1F1 1F1F9 ; fully-qualified # 🇱🇹 flag: Lithuania +1F1F1 1F1FA ; fully-qualified # 🇱🇺 flag: Luxembourg +1F1F1 1F1FB ; fully-qualified # 🇱🇻 flag: Latvia +1F1F1 1F1FE ; fully-qualified # 🇱🇾 flag: Libya +1F1F2 1F1E6 ; fully-qualified # 🇲🇦 flag: Morocco +1F1F2 1F1E8 ; fully-qualified # 🇲🇨 flag: Monaco +1F1F2 1F1E9 ; fully-qualified # 🇲🇩 flag: Moldova +1F1F2 1F1EA ; fully-qualified # 🇲🇪 flag: Montenegro +1F1F2 1F1EB ; fully-qualified # 🇲🇫 flag: St. Martin +1F1F2 1F1EC ; fully-qualified # 🇲🇬 flag: Madagascar +1F1F2 1F1ED ; fully-qualified # 🇲🇭 flag: Marshall Islands +1F1F2 1F1F0 ; fully-qualified # 🇲🇰 flag: Macedonia +1F1F2 1F1F1 ; fully-qualified # 🇲🇱 flag: Mali +1F1F2 1F1F2 ; fully-qualified # 🇲🇲 flag: Myanmar (Burma) +1F1F2 1F1F3 ; fully-qualified # 🇲🇳 flag: Mongolia +1F1F2 1F1F4 ; fully-qualified # 🇲🇴 flag: Macao SAR China +1F1F2 1F1F5 ; fully-qualified # 🇲🇵 flag: Northern Mariana Islands +1F1F2 1F1F6 ; fully-qualified # 🇲🇶 flag: Martinique +1F1F2 1F1F7 ; fully-qualified # 🇲🇷 flag: Mauritania +1F1F2 1F1F8 ; fully-qualified # 🇲🇸 flag: Montserrat +1F1F2 1F1F9 ; fully-qualified # 🇲🇹 flag: Malta +1F1F2 1F1FA ; fully-qualified # 🇲🇺 flag: Mauritius +1F1F2 1F1FB ; fully-qualified # 🇲🇻 flag: Maldives +1F1F2 1F1FC ; fully-qualified # 🇲🇼 flag: Malawi +1F1F2 1F1FD ; fully-qualified # 🇲🇽 flag: Mexico +1F1F2 1F1FE ; fully-qualified # 🇲🇾 flag: Malaysia +1F1F2 1F1FF ; fully-qualified # 🇲🇿 flag: Mozambique +1F1F3 1F1E6 ; fully-qualified # 🇳🇦 flag: Namibia +1F1F3 1F1E8 ; fully-qualified # 🇳🇨 flag: New Caledonia +1F1F3 1F1EA ; fully-qualified # 🇳🇪 flag: Niger +1F1F3 1F1EB ; fully-qualified # 🇳🇫 flag: Norfolk Island +1F1F3 1F1EC ; fully-qualified # 🇳🇬 flag: Nigeria +1F1F3 1F1EE ; fully-qualified # 🇳🇮 flag: Nicaragua +1F1F3 1F1F1 ; fully-qualified # 🇳🇱 flag: Netherlands +1F1F3 1F1F4 ; fully-qualified # 🇳🇴 flag: Norway +1F1F3 1F1F5 ; fully-qualified # 🇳🇵 flag: Nepal +1F1F3 1F1F7 ; fully-qualified # 🇳🇷 flag: Nauru +1F1F3 1F1FA ; fully-qualified # 🇳🇺 flag: Niue +1F1F3 1F1FF ; fully-qualified # 🇳🇿 flag: New Zealand +1F1F4 1F1F2 ; fully-qualified # 🇴🇲 flag: Oman +1F1F5 1F1E6 ; fully-qualified # 🇵🇦 flag: Panama +1F1F5 1F1EA ; fully-qualified # 🇵🇪 flag: Peru +1F1F5 1F1EB ; fully-qualified # 🇵🇫 flag: French Polynesia +1F1F5 1F1EC ; fully-qualified # 🇵🇬 flag: Papua New Guinea +1F1F5 1F1ED ; fully-qualified # 🇵🇭 flag: Philippines +1F1F5 1F1F0 ; fully-qualified # 🇵🇰 flag: Pakistan +1F1F5 1F1F1 ; fully-qualified # 🇵🇱 flag: Poland +1F1F5 1F1F2 ; fully-qualified # 🇵🇲 flag: St. Pierre & Miquelon +1F1F5 1F1F3 ; fully-qualified # 🇵🇳 flag: Pitcairn Islands +1F1F5 1F1F7 ; fully-qualified # 🇵🇷 flag: Puerto Rico +1F1F5 1F1F8 ; fully-qualified # 🇵🇸 flag: Palestinian Territories +1F1F5 1F1F9 ; fully-qualified # 🇵🇹 flag: Portugal +1F1F5 1F1FC ; fully-qualified # 🇵🇼 flag: Palau +1F1F5 1F1FE ; fully-qualified # 🇵🇾 flag: Paraguay +1F1F6 1F1E6 ; fully-qualified # 🇶🇦 flag: Qatar +1F1F7 1F1EA ; fully-qualified # 🇷🇪 flag: Réunion +1F1F7 1F1F4 ; fully-qualified # 🇷🇴 flag: Romania +1F1F7 1F1F8 ; fully-qualified # 🇷🇸 flag: Serbia +1F1F7 1F1FA ; fully-qualified # 🇷🇺 flag: Russia +1F1F7 1F1FC ; fully-qualified # 🇷🇼 flag: Rwanda +1F1F8 1F1E6 ; fully-qualified # 🇸🇦 flag: Saudi Arabia +1F1F8 1F1E7 ; fully-qualified # 🇸🇧 flag: Solomon Islands +1F1F8 1F1E8 ; fully-qualified # 🇸🇨 flag: Seychelles +1F1F8 1F1E9 ; fully-qualified # 🇸🇩 flag: Sudan +1F1F8 1F1EA ; fully-qualified # 🇸🇪 flag: Sweden +1F1F8 1F1EC ; fully-qualified # 🇸🇬 flag: Singapore +1F1F8 1F1ED ; fully-qualified # 🇸🇭 flag: St. Helena +1F1F8 1F1EE ; fully-qualified # 🇸🇮 flag: Slovenia +1F1F8 1F1EF ; fully-qualified # 🇸🇯 flag: Svalbard & Jan Mayen +1F1F8 1F1F0 ; fully-qualified # 🇸🇰 flag: Slovakia +1F1F8 1F1F1 ; fully-qualified # 🇸🇱 flag: Sierra Leone +1F1F8 1F1F2 ; fully-qualified # 🇸🇲 flag: San Marino +1F1F8 1F1F3 ; fully-qualified # 🇸🇳 flag: Senegal +1F1F8 1F1F4 ; fully-qualified # 🇸🇴 flag: Somalia +1F1F8 1F1F7 ; fully-qualified # 🇸🇷 flag: Suriname +1F1F8 1F1F8 ; fully-qualified # 🇸🇸 flag: South Sudan +1F1F8 1F1F9 ; fully-qualified # 🇸🇹 flag: São Tomé & Príncipe +1F1F8 1F1FB ; fully-qualified # 🇸🇻 flag: El Salvador +1F1F8 1F1FD ; fully-qualified # 🇸🇽 flag: Sint Maarten +1F1F8 1F1FE ; fully-qualified # 🇸🇾 flag: Syria +1F1F8 1F1FF ; fully-qualified # 🇸🇿 flag: Eswatini +1F1F9 1F1E6 ; fully-qualified # 🇹🇦 flag: Tristan da Cunha +1F1F9 1F1E8 ; fully-qualified # 🇹🇨 flag: Turks & Caicos Islands +1F1F9 1F1E9 ; fully-qualified # 🇹🇩 flag: Chad +1F1F9 1F1EB ; fully-qualified # 🇹🇫 flag: French Southern Territories +1F1F9 1F1EC ; fully-qualified # 🇹🇬 flag: Togo +1F1F9 1F1ED ; fully-qualified # 🇹🇭 flag: Thailand +1F1F9 1F1EF ; fully-qualified # 🇹🇯 flag: Tajikistan +1F1F9 1F1F0 ; fully-qualified # 🇹🇰 flag: Tokelau +1F1F9 1F1F1 ; fully-qualified # 🇹🇱 flag: Timor-Leste +1F1F9 1F1F2 ; fully-qualified # 🇹🇲 flag: Turkmenistan +1F1F9 1F1F3 ; fully-qualified # 🇹🇳 flag: Tunisia +1F1F9 1F1F4 ; fully-qualified # 🇹🇴 flag: Tonga +1F1F9 1F1F7 ; fully-qualified # 🇹🇷 flag: Turkey +1F1F9 1F1F9 ; fully-qualified # 🇹🇹 flag: Trinidad & Tobago +1F1F9 1F1FB ; fully-qualified # 🇹🇻 flag: Tuvalu +1F1F9 1F1FC ; fully-qualified # 🇹🇼 flag: Taiwan +1F1F9 1F1FF ; fully-qualified # 🇹🇿 flag: Tanzania +1F1FA 1F1E6 ; fully-qualified # 🇺🇦 flag: Ukraine +1F1FA 1F1EC ; fully-qualified # 🇺🇬 flag: Uganda +1F1FA 1F1F2 ; fully-qualified # 🇺🇲 flag: U.S. Outlying Islands +1F1FA 1F1F3 ; fully-qualified # 🇺🇳 flag: United Nations +1F1FA 1F1F8 ; fully-qualified # 🇺🇸 flag: United States +1F1FA 1F1FE ; fully-qualified # 🇺🇾 flag: Uruguay +1F1FA 1F1FF ; fully-qualified # 🇺🇿 flag: Uzbekistan +1F1FB 1F1E6 ; fully-qualified # 🇻🇦 flag: Vatican City +1F1FB 1F1E8 ; fully-qualified # 🇻🇨 flag: St. Vincent & Grenadines +1F1FB 1F1EA ; fully-qualified # 🇻🇪 flag: Venezuela +1F1FB 1F1EC ; fully-qualified # 🇻🇬 flag: British Virgin Islands +1F1FB 1F1EE ; fully-qualified # 🇻🇮 flag: U.S. Virgin Islands +1F1FB 1F1F3 ; fully-qualified # 🇻🇳 flag: Vietnam +1F1FB 1F1FA ; fully-qualified # 🇻🇺 flag: Vanuatu +1F1FC 1F1EB ; fully-qualified # 🇼🇫 flag: Wallis & Futuna +1F1FC 1F1F8 ; fully-qualified # 🇼🇸 flag: Samoa +1F1FD 1F1F0 ; fully-qualified # 🇽🇰 flag: Kosovo +1F1FE 1F1EA ; fully-qualified # 🇾🇪 flag: Yemen +1F1FE 1F1F9 ; fully-qualified # 🇾🇹 flag: Mayotte +1F1FF 1F1E6 ; fully-qualified # 🇿🇦 flag: South Africa +1F1FF 1F1F2 ; fully-qualified # 🇿🇲 flag: Zambia +1F1FF 1F1FC ; fully-qualified # 🇿🇼 flag: Zimbabwe + +# subgroup: subdivision-flag +1F3F4 E0067 E0062 E0065 E006E E0067 E007F ; fully-qualified # 🏴󠁧󠁢󠁥󠁮󠁧󠁿 flag: England +1F3F4 E0067 E0062 E0073 E0063 E0074 E007F ; fully-qualified # 🏴󠁧󠁢󠁳󠁣󠁴󠁿 flag: Scotland +1F3F4 E0067 E0062 E0077 E006C E0073 E007F ; fully-qualified # 🏴󠁧󠁢󠁷󠁬󠁳󠁿 flag: Wales + +# Flags subtotal: 271 +# Flags subtotal: 271 w/o modifiers + +# Status Counts +# fully-qualified : 3010 +# minimally-qualified : 571 +# unqualified : 246 +# component : 9 + +#EOF diff --git a/zsh/.oh-my-zsh/plugins/emoji/emoji.plugin.zsh b/zsh/.oh-my-zsh/plugins/emoji/emoji.plugin.zsh new file mode 100644 index 0000000..2e8617c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emoji/emoji.plugin.zsh @@ -0,0 +1,110 @@ +# emoji plugin +# +# Makes emoji support available within ZSH +# +# See the README for documentation. + +# Handle $0 according to the standard: +# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" + +_omz_emoji_plugin_dir="${0:h}" + +() { + +local LC_ALL=en_US.UTF-8 + +typeset -gAH emoji_skintone + +source "$_omz_emoji_plugin_dir/emoji-char-definitions.zsh" +unset _omz_emoji_plugin_dir + +# These additional emoji are not in the definition file, but are useful in conjunction with it + +# This is a combining character that can be placed after any other character to surround +# it in a "keycap" symbol. +# The digits 0-9 are already in the emoji table as keycap_digit_, keycap_ten, etc. +# It's unclear whether this should be in the $emoji array, because those characters are all ones +# which can be displayed on their own. + +emoji[regional_indicator_symbol_letter_d_regional_indicator_symbol_letter_e]=$'\xF0\x9F\x87\xA9\xF0\x9F\x87\xAA' +emoji[regional_indicator_symbol_letter_g_regional_indicator_symbol_letter_b]=$'\xF0\x9F\x87\xAC\xF0\x9F\x87\xA7' +emoji[regional_indicator_symbol_letter_c_regional_indicator_symbol_letter_n]=$'\xF0\x9F\x87\xA8\xF0\x9F\x87\xB3' +emoji[regional_indicator_symbol_letter_j_regional_indicator_symbol_letter_p]=$'\xF0\x9F\x87\xAF\xF0\x9F\x87\xB5' +emoji[regional_indicator_symbol_letter_k_regional_indicator_symbol_letter_r]=$'\xF0\x9F\x87\xB0\xF0\x9F\x87\xB7' +emoji[regional_indicator_symbol_letter_f_regional_indicator_symbol_letter_r]=$'\xF0\x9F\x87\xAB\xF0\x9F\x87\xB7' +emoji[regional_indicator_symbol_letter_e_regional_indicator_symbol_letter_s]=$'\xF0\x9F\x87\xAA\xF0\x9F\x87\xB8' +emoji[regional_indicator_symbol_letter_i_regional_indicator_symbol_letter_t]=$'\xF0\x9F\x87\xAE\xF0\x9F\x87\xB9' +emoji[regional_indicator_symbol_letter_u_regional_indicator_symbol_letter_s]=$'\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8' +emoji[regional_indicator_symbol_letter_r_regional_indicator_symbol_letter_u]=$'\xF0\x9F\x87\xB7\xF0\x9F\x87\xBA' + +# Easier access to skin tone modifiers +emoji_skintone[1_2]=$'\U1F3FB' +emoji_skintone[3]=$'\U1F3FC' +emoji_skintone[4]=$'\U1F3FD' +emoji_skintone[5]=$'\U1F3FE' +emoji_skintone[6]=$'\U1F3FF' +} + +# Prints a random emoji character +# +# random_emoji [group] +# +function random_emoji() { + local group=$1 + local names + if [[ -z "$group" || "$group" == "all" ]]; then + names=(${(k)emoji}) + else + names=(${=emoji_groups[$group]}) + fi + local list_size=${#names} + [[ $list_size -eq 0 ]] && return 1 + local random_index=$(( ( RANDOM % $list_size ) + 1 )) + local name=${names[$random_index]} + if [[ "$group" == "flags" ]]; then + echo ${emoji_flags[$name]} + else + echo ${emoji[$name]} + fi +} + +# Displays a listing of emoji with their names +# +# display_emoji [group] +# +function display_emoji() { + local group=$1 + local names + if [[ -z "$group" || "$group" == "all" ]]; then + names=(${(k)emoji}) + else + names=(${=emoji_groups[$group]}) + fi + # The extra spaces in output here are a hack for readability, since some + # terminals treat these emoji chars as single-width. + local counter=1 + for i in $names; do + if [[ "$group" == "flags" ]]; then + printf '%s ' "$emoji_flags[$i]" + else + printf '%s ' "$emoji[$i]" + fi + # New line every 20 emoji, to avoid weirdnesses + if (($counter % 20 == 0)); then + printf "\n" + fi + let counter=$counter+1 + done + print + for i in $names; do + if [[ "$group" == "flags" ]]; then + echo "${emoji_flags[$i]} = $i" + else + echo "${emoji[$i]} = $i" + fi + done +} + + diff --git a/zsh/.oh-my-zsh/plugins/emoji/gemoji_db.json b/zsh/.oh-my-zsh/plugins/emoji/gemoji_db.json new file mode 100644 index 0000000..7c58c25 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emoji/gemoji_db.json @@ -0,0 +1,21538 @@ +[ + { + "emoji": "😀" + , "description": "grinning face" + , "category": "Smileys & Emotion" + , "aliases": [ + "grinning" + ] + , "tags": [ + "smile" + , "happy" + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😃" + , "description": "grinning face with big eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "smiley" + ] + , "tags": [ + "happy" + , "joy" + , "haha" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😄" + , "description": "grinning face with smiling eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "smile" + ] + , "tags": [ + "happy" + , "joy" + , "laugh" + , "pleased" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😁" + , "description": "beaming face with smiling eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "grin" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😆" + , "description": "grinning squinting face" + , "category": "Smileys & Emotion" + , "aliases": [ + "laughing" + , "satisfied" + ] + , "tags": [ + "happy" + , "haha" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😅" + , "description": "grinning face with sweat" + , "category": "Smileys & Emotion" + , "aliases": [ + "sweat_smile" + ] + , "tags": [ + "hot" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤣" + , "description": "rolling on the floor laughing" + , "category": "Smileys & Emotion" + , "aliases": [ + "rofl" + ] + , "tags": [ + "lol" + , "laughing" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "😂" + , "description": "face with tears of joy" + , "category": "Smileys & Emotion" + , "aliases": [ + "joy" + ] + , "tags": [ + "tears" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🙂" + , "description": "slightly smiling face" + , "category": "Smileys & Emotion" + , "aliases": [ + "slightly_smiling_face" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🙃" + , "description": "upside-down face" + , "category": "Smileys & Emotion" + , "aliases": [ + "upside_down_face" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "😉" + , "description": "winking face" + , "category": "Smileys & Emotion" + , "aliases": [ + "wink" + ] + , "tags": [ + "flirt" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😊" + , "description": "smiling face with smiling eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "blush" + ] + , "tags": [ + "proud" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😇" + , "description": "smiling face with halo" + , "category": "Smileys & Emotion" + , "aliases": [ + "innocent" + ] + , "tags": [ + "angel" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥰" + , "description": "smiling face with hearts" + , "category": "Smileys & Emotion" + , "aliases": [ + "smiling_face_with_three_hearts" + ] + , "tags": [ + "love" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "😍" + , "description": "smiling face with heart-eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "heart_eyes" + ] + , "tags": [ + "love" + , "crush" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤩" + , "description": "star-struck" + , "category": "Smileys & Emotion" + , "aliases": [ + "star_struck" + ] + , "tags": [ + "eyes" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "😘" + , "description": "face blowing a kiss" + , "category": "Smileys & Emotion" + , "aliases": [ + "kissing_heart" + ] + , "tags": [ + "flirt" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😗" + , "description": "kissing face" + , "category": "Smileys & Emotion" + , "aliases": [ + "kissing" + ] + , "tags": [ + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "☺️" + , "description": "smiling face" + , "category": "Smileys & Emotion" + , "aliases": [ + "relaxed" + ] + , "tags": [ + "blush" + , "pleased" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "😚" + , "description": "kissing face with closed eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "kissing_closed_eyes" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😙" + , "description": "kissing face with smiling eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "kissing_smiling_eyes" + ] + , "tags": [ + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😋" + , "description": "face savoring food" + , "category": "Smileys & Emotion" + , "aliases": [ + "yum" + ] + , "tags": [ + "tongue" + , "lick" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😛" + , "description": "face with tongue" + , "category": "Smileys & Emotion" + , "aliases": [ + "stuck_out_tongue" + ] + , "tags": [ + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😜" + , "description": "winking face with tongue" + , "category": "Smileys & Emotion" + , "aliases": [ + "stuck_out_tongue_winking_eye" + ] + , "tags": [ + "prank" + , "silly" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤪" + , "description": "zany face" + , "category": "Smileys & Emotion" + , "aliases": [ + "zany_face" + ] + , "tags": [ + "goofy" + , "wacky" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "😝" + , "description": "squinting face with tongue" + , "category": "Smileys & Emotion" + , "aliases": [ + "stuck_out_tongue_closed_eyes" + ] + , "tags": [ + "prank" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤑" + , "description": "money-mouth face" + , "category": "Smileys & Emotion" + , "aliases": [ + "money_mouth_face" + ] + , "tags": [ + "rich" + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🤗" + , "description": "hugging face" + , "category": "Smileys & Emotion" + , "aliases": [ + "hugs" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🤭" + , "description": "face with hand over mouth" + , "category": "Smileys & Emotion" + , "aliases": [ + "hand_over_mouth" + ] + , "tags": [ + "quiet" + , "whoops" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🤫" + , "description": "shushing face" + , "category": "Smileys & Emotion" + , "aliases": [ + "shushing_face" + ] + , "tags": [ + "silence" + , "quiet" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🤔" + , "description": "thinking face" + , "category": "Smileys & Emotion" + , "aliases": [ + "thinking" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🤐" + , "description": "zipper-mouth face" + , "category": "Smileys & Emotion" + , "aliases": [ + "zipper_mouth_face" + ] + , "tags": [ + "silence" + , "hush" + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🤨" + , "description": "face with raised eyebrow" + , "category": "Smileys & Emotion" + , "aliases": [ + "raised_eyebrow" + ] + , "tags": [ + "suspicious" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "😐" + , "description": "neutral face" + , "category": "Smileys & Emotion" + , "aliases": [ + "neutral_face" + ] + , "tags": [ + "meh" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😑" + , "description": "expressionless face" + , "category": "Smileys & Emotion" + , "aliases": [ + "expressionless" + ] + , "tags": [ + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😶" + , "description": "face without mouth" + , "category": "Smileys & Emotion" + , "aliases": [ + "no_mouth" + ] + , "tags": [ + "mute" + , "silence" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😏" + , "description": "smirking face" + , "category": "Smileys & Emotion" + , "aliases": [ + "smirk" + ] + , "tags": [ + "smug" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😒" + , "description": "unamused face" + , "category": "Smileys & Emotion" + , "aliases": [ + "unamused" + ] + , "tags": [ + "meh" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🙄" + , "description": "face with rolling eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "roll_eyes" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "😬" + , "description": "grimacing face" + , "category": "Smileys & Emotion" + , "aliases": [ + "grimacing" + ] + , "tags": [ + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "🤥" + , "description": "lying face" + , "category": "Smileys & Emotion" + , "aliases": [ + "lying_face" + ] + , "tags": [ + "liar" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "😌" + , "description": "relieved face" + , "category": "Smileys & Emotion" + , "aliases": [ + "relieved" + ] + , "tags": [ + "whew" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😔" + , "description": "pensive face" + , "category": "Smileys & Emotion" + , "aliases": [ + "pensive" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😪" + , "description": "sleepy face" + , "category": "Smileys & Emotion" + , "aliases": [ + "sleepy" + ] + , "tags": [ + "tired" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤤" + , "description": "drooling face" + , "category": "Smileys & Emotion" + , "aliases": [ + "drooling_face" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "😴" + , "description": "sleeping face" + , "category": "Smileys & Emotion" + , "aliases": [ + "sleeping" + ] + , "tags": [ + "zzz" + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😷" + , "description": "face with medical mask" + , "category": "Smileys & Emotion" + , "aliases": [ + "mask" + ] + , "tags": [ + "sick" + , "ill" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤒" + , "description": "face with thermometer" + , "category": "Smileys & Emotion" + , "aliases": [ + "face_with_thermometer" + ] + , "tags": [ + "sick" + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🤕" + , "description": "face with head-bandage" + , "category": "Smileys & Emotion" + , "aliases": [ + "face_with_head_bandage" + ] + , "tags": [ + "hurt" + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🤢" + , "description": "nauseated face" + , "category": "Smileys & Emotion" + , "aliases": [ + "nauseated_face" + ] + , "tags": [ + "sick" + , "barf" + , "disgusted" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🤮" + , "description": "face vomiting" + , "category": "Smileys & Emotion" + , "aliases": [ + "vomiting_face" + ] + , "tags": [ + "barf" + , "sick" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🤧" + , "description": "sneezing face" + , "category": "Smileys & Emotion" + , "aliases": [ + "sneezing_face" + ] + , "tags": [ + "achoo" + , "sick" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥵" + , "description": "hot face" + , "category": "Smileys & Emotion" + , "aliases": [ + "hot_face" + ] + , "tags": [ + "heat" + , "sweating" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥶" + , "description": "cold face" + , "category": "Smileys & Emotion" + , "aliases": [ + "cold_face" + ] + , "tags": [ + "freezing" + , "ice" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥴" + , "description": "woozy face" + , "category": "Smileys & Emotion" + , "aliases": [ + "woozy_face" + ] + , "tags": [ + "groggy" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "😵" + , "description": "dizzy face" + , "category": "Smileys & Emotion" + , "aliases": [ + "dizzy_face" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤯" + , "description": "exploding head" + , "category": "Smileys & Emotion" + , "aliases": [ + "exploding_head" + ] + , "tags": [ + "mind" + , "blown" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🤠" + , "description": "cowboy hat face" + , "category": "Smileys & Emotion" + , "aliases": [ + "cowboy_hat_face" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥳" + , "description": "partying face" + , "category": "Smileys & Emotion" + , "aliases": [ + "partying_face" + ] + , "tags": [ + "celebration" + , "birthday" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "😎" + , "description": "smiling face with sunglasses" + , "category": "Smileys & Emotion" + , "aliases": [ + "sunglasses" + ] + , "tags": [ + "cool" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤓" + , "description": "nerd face" + , "category": "Smileys & Emotion" + , "aliases": [ + "nerd_face" + ] + , "tags": [ + "geek" + , "glasses" + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🧐" + , "description": "face with monocle" + , "category": "Smileys & Emotion" + , "aliases": [ + "monocle_face" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "😕" + , "description": "confused face" + , "category": "Smileys & Emotion" + , "aliases": [ + "confused" + ] + , "tags": [ + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😟" + , "description": "worried face" + , "category": "Smileys & Emotion" + , "aliases": [ + "worried" + ] + , "tags": [ + "nervous" + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "🙁" + , "description": "slightly frowning face" + , "category": "Smileys & Emotion" + , "aliases": [ + "slightly_frowning_face" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "☹" + , "description": "frowning face" + , "category": "Smileys & Emotion" + , "aliases": [ + "frowning_face" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "😮" + , "description": "face with open mouth" + , "category": "Smileys & Emotion" + , "aliases": [ + "open_mouth" + ] + , "tags": [ + "surprise" + , "impressed" + , "wow" + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😯" + , "description": "hushed face" + , "category": "Smileys & Emotion" + , "aliases": [ + "hushed" + ] + , "tags": [ + "silence" + , "speechless" + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😲" + , "description": "astonished face" + , "category": "Smileys & Emotion" + , "aliases": [ + "astonished" + ] + , "tags": [ + "amazed" + , "gasp" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😳" + , "description": "flushed face" + , "category": "Smileys & Emotion" + , "aliases": [ + "flushed" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥺" + , "description": "pleading face" + , "category": "Smileys & Emotion" + , "aliases": [ + "pleading_face" + ] + , "tags": [ + "puppy" + , "eyes" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "😦" + , "description": "frowning face with open mouth" + , "category": "Smileys & Emotion" + , "aliases": [ + "frowning" + ] + , "tags": [ + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😧" + , "description": "anguished face" + , "category": "Smileys & Emotion" + , "aliases": [ + "anguished" + ] + , "tags": [ + "stunned" + ] + , "unicode_version": "6.1" + , "ios_version": "6.0" + } +, { + "emoji": "😨" + , "description": "fearful face" + , "category": "Smileys & Emotion" + , "aliases": [ + "fearful" + ] + , "tags": [ + "scared" + , "shocked" + , "oops" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😰" + , "description": "anxious face with sweat" + , "category": "Smileys & Emotion" + , "aliases": [ + "cold_sweat" + ] + , "tags": [ + "nervous" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😥" + , "description": "sad but relieved face" + , "category": "Smileys & Emotion" + , "aliases": [ + "disappointed_relieved" + ] + , "tags": [ + "phew" + , "sweat" + , "nervous" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😢" + , "description": "crying face" + , "category": "Smileys & Emotion" + , "aliases": [ + "cry" + ] + , "tags": [ + "sad" + , "tear" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😭" + , "description": "loudly crying face" + , "category": "Smileys & Emotion" + , "aliases": [ + "sob" + ] + , "tags": [ + "sad" + , "cry" + , "bawling" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😱" + , "description": "face screaming in fear" + , "category": "Smileys & Emotion" + , "aliases": [ + "scream" + ] + , "tags": [ + "horror" + , "shocked" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😖" + , "description": "confounded face" + , "category": "Smileys & Emotion" + , "aliases": [ + "confounded" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😣" + , "description": "persevering face" + , "category": "Smileys & Emotion" + , "aliases": [ + "persevere" + ] + , "tags": [ + "struggling" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😞" + , "description": "disappointed face" + , "category": "Smileys & Emotion" + , "aliases": [ + "disappointed" + ] + , "tags": [ + "sad" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😓" + , "description": "downcast face with sweat" + , "category": "Smileys & Emotion" + , "aliases": [ + "sweat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😩" + , "description": "weary face" + , "category": "Smileys & Emotion" + , "aliases": [ + "weary" + ] + , "tags": [ + "tired" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😫" + , "description": "tired face" + , "category": "Smileys & Emotion" + , "aliases": [ + "tired_face" + ] + , "tags": [ + "upset" + , "whine" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥱" + , "description": "yawning face" + , "category": "Smileys & Emotion" + , "aliases": [ + "yawning_face" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "😤" + , "description": "face with steam from nose" + , "category": "Smileys & Emotion" + , "aliases": [ + "triumph" + ] + , "tags": [ + "smug" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😡" + , "description": "pouting face" + , "category": "Smileys & Emotion" + , "aliases": [ + "rage" + , "pout" + ] + , "tags": [ + "angry" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😠" + , "description": "angry face" + , "category": "Smileys & Emotion" + , "aliases": [ + "angry" + ] + , "tags": [ + "mad" + , "annoyed" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤬" + , "description": "face with symbols on mouth" + , "category": "Smileys & Emotion" + , "aliases": [ + "cursing_face" + ] + , "tags": [ + "foul" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "😈" + , "description": "smiling face with horns" + , "category": "Smileys & Emotion" + , "aliases": [ + "smiling_imp" + ] + , "tags": [ + "devil" + , "evil" + , "horns" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👿" + , "description": "angry face with horns" + , "category": "Smileys & Emotion" + , "aliases": [ + "imp" + ] + , "tags": [ + "angry" + , "devil" + , "evil" + , "horns" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💀" + , "description": "skull" + , "category": "Smileys & Emotion" + , "aliases": [ + "skull" + ] + , "tags": [ + "dead" + , "danger" + , "poison" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "☠" + , "description": "skull and crossbones" + , "category": "Smileys & Emotion" + , "aliases": [ + "skull_and_crossbones" + ] + , "tags": [ + "danger" + , "pirate" + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "💩" + , "description": "pile of poo" + , "category": "Smileys & Emotion" + , "aliases": [ + "hankey" + , "poop" + , "shit" + ] + , "tags": [ + "crap" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤡" + , "description": "clown face" + , "category": "Smileys & Emotion" + , "aliases": [ + "clown_face" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "👹" + , "description": "ogre" + , "category": "Smileys & Emotion" + , "aliases": [ + "japanese_ogre" + ] + , "tags": [ + "monster" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👺" + , "description": "goblin" + , "category": "Smileys & Emotion" + , "aliases": [ + "japanese_goblin" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👻" + , "description": "ghost" + , "category": "Smileys & Emotion" + , "aliases": [ + "ghost" + ] + , "tags": [ + "halloween" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👽" + , "description": "alien" + , "category": "Smileys & Emotion" + , "aliases": [ + "alien" + ] + , "tags": [ + "ufo" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👾" + , "description": "alien monster" + , "category": "Smileys & Emotion" + , "aliases": [ + "space_invader" + ] + , "tags": [ + "game" + , "retro" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤖" + , "description": "robot" + , "category": "Smileys & Emotion" + , "aliases": [ + "robot" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "😺" + , "description": "grinning cat" + , "category": "Smileys & Emotion" + , "aliases": [ + "smiley_cat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😸" + , "description": "grinning cat with smiling eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "smile_cat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😹" + , "description": "cat with tears of joy" + , "category": "Smileys & Emotion" + , "aliases": [ + "joy_cat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😻" + , "description": "smiling cat with heart-eyes" + , "category": "Smileys & Emotion" + , "aliases": [ + "heart_eyes_cat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😼" + , "description": "cat with wry smile" + , "category": "Smileys & Emotion" + , "aliases": [ + "smirk_cat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😽" + , "description": "kissing cat" + , "category": "Smileys & Emotion" + , "aliases": [ + "kissing_cat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🙀" + , "description": "weary cat" + , "category": "Smileys & Emotion" + , "aliases": [ + "scream_cat" + ] + , "tags": [ + "horror" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😿" + , "description": "crying cat" + , "category": "Smileys & Emotion" + , "aliases": [ + "crying_cat_face" + ] + , "tags": [ + "sad" + , "tear" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "😾" + , "description": "pouting cat" + , "category": "Smileys & Emotion" + , "aliases": [ + "pouting_cat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🙈" + , "description": "see-no-evil monkey" + , "category": "Smileys & Emotion" + , "aliases": [ + "see_no_evil" + ] + , "tags": [ + "monkey" + , "blind" + , "ignore" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🙉" + , "description": "hear-no-evil monkey" + , "category": "Smileys & Emotion" + , "aliases": [ + "hear_no_evil" + ] + , "tags": [ + "monkey" + , "deaf" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🙊" + , "description": "speak-no-evil monkey" + , "category": "Smileys & Emotion" + , "aliases": [ + "speak_no_evil" + ] + , "tags": [ + "monkey" + , "mute" + , "hush" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💋" + , "description": "kiss mark" + , "category": "Smileys & Emotion" + , "aliases": [ + "kiss" + ] + , "tags": [ + "lipstick" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💌" + , "description": "love letter" + , "category": "Smileys & Emotion" + , "aliases": [ + "love_letter" + ] + , "tags": [ + "email" + , "envelope" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💘" + , "description": "heart with arrow" + , "category": "Smileys & Emotion" + , "aliases": [ + "cupid" + ] + , "tags": [ + "love" + , "heart" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💝" + , "description": "heart with ribbon" + , "category": "Smileys & Emotion" + , "aliases": [ + "gift_heart" + ] + , "tags": [ + "chocolates" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💖" + , "description": "sparkling heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "sparkling_heart" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💗" + , "description": "growing heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "heartpulse" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💓" + , "description": "beating heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "heartbeat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💞" + , "description": "revolving hearts" + , "category": "Smileys & Emotion" + , "aliases": [ + "revolving_hearts" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💕" + , "description": "two hearts" + , "category": "Smileys & Emotion" + , "aliases": [ + "two_hearts" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💟" + , "description": "heart decoration" + , "category": "Smileys & Emotion" + , "aliases": [ + "heart_decoration" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "❣️" + , "description": "heart exclamation" + , "category": "Smileys & Emotion" + , "aliases": [ + "heavy_heart_exclamation" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "💔" + , "description": "broken heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "broken_heart" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "❤️" + , "description": "red heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "heart" + ] + , "tags": [ + "love" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🧡" + , "description": "orange heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "orange_heart" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "💛" + , "description": "yellow heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "yellow_heart" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💚" + , "description": "green heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "green_heart" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💙" + , "description": "blue heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "blue_heart" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💜" + , "description": "purple heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "purple_heart" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤎" + , "description": "brown heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "brown_heart" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🖤" + , "description": "black heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "black_heart" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🤍" + , "description": "white heart" + , "category": "Smileys & Emotion" + , "aliases": [ + "white_heart" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "💯" + , "description": "hundred points" + , "category": "Smileys & Emotion" + , "aliases": [ + "100" + ] + , "tags": [ + "score" + , "perfect" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💢" + , "description": "anger symbol" + , "category": "Smileys & Emotion" + , "aliases": [ + "anger" + ] + , "tags": [ + "angry" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💥" + , "description": "collision" + , "category": "Smileys & Emotion" + , "aliases": [ + "boom" + , "collision" + ] + , "tags": [ + "explode" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💫" + , "description": "dizzy" + , "category": "Smileys & Emotion" + , "aliases": [ + "dizzy" + ] + , "tags": [ + "star" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💦" + , "description": "sweat droplets" + , "category": "Smileys & Emotion" + , "aliases": [ + "sweat_drops" + ] + , "tags": [ + "water" + , "workout" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💨" + , "description": "dashing away" + , "category": "Smileys & Emotion" + , "aliases": [ + "dash" + ] + , "tags": [ + "wind" + , "blow" + , "fast" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕳" + , "description": "hole" + , "category": "Smileys & Emotion" + , "aliases": [ + "hole" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "💣" + , "description": "bomb" + , "category": "Smileys & Emotion" + , "aliases": [ + "bomb" + ] + , "tags": [ + "boom" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💬" + , "description": "speech balloon" + , "category": "Smileys & Emotion" + , "aliases": [ + "speech_balloon" + ] + , "tags": [ + "comment" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👁️‍🗨️" + , "description": "eye in speech bubble" + , "category": "Smileys & Emotion" + , "aliases": [ + "eye_speech_bubble" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🗨" + , "description": "left speech bubble" + , "category": "Smileys & Emotion" + , "aliases": [ + "left_speech_bubble" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🗯" + , "description": "right anger bubble" + , "category": "Smileys & Emotion" + , "aliases": [ + "right_anger_bubble" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "💭" + , "description": "thought balloon" + , "category": "Smileys & Emotion" + , "aliases": [ + "thought_balloon" + ] + , "tags": [ + "thinking" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💤" + , "description": "zzz" + , "category": "Smileys & Emotion" + , "aliases": [ + "zzz" + ] + , "tags": [ + "sleeping" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👋" + , "description": "waving hand" + , "category": "People & Body" + , "aliases": [ + "wave" + ] + , "tags": [ + "goodbye" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🤚" + , "description": "raised back of hand" + , "category": "People & Body" + , "aliases": [ + "raised_back_of_hand" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🖐" + , "description": "hand with fingers splayed" + , "category": "People & Body" + , "aliases": [ + "raised_hand_with_fingers_splayed" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "✋" + , "description": "raised hand" + , "category": "People & Body" + , "aliases": [ + "hand" + , "raised_hand" + ] + , "tags": [ + "highfive" + , "stop" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🖖" + , "description": "vulcan salute" + , "category": "People & Body" + , "aliases": [ + "vulcan_salute" + ] + , "tags": [ + "prosper" + , "spock" + ] + , "unicode_version": "7.0" + , "ios_version": "8.3" + , "skin_tones": true + } +, { + "emoji": "👌" + , "description": "OK hand" + , "category": "People & Body" + , "aliases": [ + "ok_hand" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🤏" + , "description": "pinching hand" + , "category": "People & Body" + , "aliases": [ + "pinching_hand" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "✌️" + , "description": "victory hand" + , "category": "People & Body" + , "aliases": [ + "v" + ] + , "tags": [ + "victory" + , "peace" + ] + , "unicode_version": "" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🤞" + , "description": "crossed fingers" + , "category": "People & Body" + , "aliases": [ + "crossed_fingers" + ] + , "tags": [ + "luck" + , "hopeful" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤟" + , "description": "love-you gesture" + , "category": "People & Body" + , "aliases": [ + "love_you_gesture" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤘" + , "description": "sign of the horns" + , "category": "People & Body" + , "aliases": [ + "metal" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "🤙" + , "description": "call me hand" + , "category": "People & Body" + , "aliases": [ + "call_me_hand" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👈" + , "description": "backhand index pointing left" + , "category": "People & Body" + , "aliases": [ + "point_left" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👉" + , "description": "backhand index pointing right" + , "category": "People & Body" + , "aliases": [ + "point_right" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👆" + , "description": "backhand index pointing up" + , "category": "People & Body" + , "aliases": [ + "point_up_2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🖕" + , "description": "middle finger" + , "category": "People & Body" + , "aliases": [ + "middle_finger" + , "fu" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "👇" + , "description": "backhand index pointing down" + , "category": "People & Body" + , "aliases": [ + "point_down" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "☝️" + , "description": "index pointing up" + , "category": "People & Body" + , "aliases": [ + "point_up" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👍" + , "description": "thumbs up" + , "category": "People & Body" + , "aliases": [ + "+1" + , "thumbsup" + ] + , "tags": [ + "approve" + , "ok" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👎" + , "description": "thumbs down" + , "category": "People & Body" + , "aliases": [ + "-1" + , "thumbsdown" + ] + , "tags": [ + "disapprove" + , "bury" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "✊" + , "description": "raised fist" + , "category": "People & Body" + , "aliases": [ + "fist_raised" + , "fist" + ] + , "tags": [ + "power" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👊" + , "description": "oncoming fist" + , "category": "People & Body" + , "aliases": [ + "fist_oncoming" + , "facepunch" + , "punch" + ] + , "tags": [ + "attack" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🤛" + , "description": "left-facing fist" + , "category": "People & Body" + , "aliases": [ + "fist_left" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤜" + , "description": "right-facing fist" + , "category": "People & Body" + , "aliases": [ + "fist_right" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👏" + , "description": "clapping hands" + , "category": "People & Body" + , "aliases": [ + "clap" + ] + , "tags": [ + "praise" + , "applause" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🙌" + , "description": "raising hands" + , "category": "People & Body" + , "aliases": [ + "raised_hands" + ] + , "tags": [ + "hooray" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👐" + , "description": "open hands" + , "category": "People & Body" + , "aliases": [ + "open_hands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🤲" + , "description": "palms up together" + , "category": "People & Body" + , "aliases": [ + "palms_up_together" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤝" + , "description": "handshake" + , "category": "People & Body" + , "aliases": [ + "handshake" + ] + , "tags": [ + "deal" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🙏" + , "description": "folded hands" + , "category": "People & Body" + , "aliases": [ + "pray" + ] + , "tags": [ + "please" + , "hope" + , "wish" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "✍️" + , "description": "writing hand" + , "category": "People & Body" + , "aliases": [ + "writing_hand" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "💅" + , "description": "nail polish" + , "category": "People & Body" + , "aliases": [ + "nail_care" + ] + , "tags": [ + "beauty" + , "manicure" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🤳" + , "description": "selfie" + , "category": "People & Body" + , "aliases": [ + "selfie" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "💪" + , "description": "flexed biceps" + , "category": "People & Body" + , "aliases": [ + "muscle" + ] + , "tags": [ + "flex" + , "bicep" + , "strong" + , "workout" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🦾" + , "description": "mechanical arm" + , "category": "People & Body" + , "aliases": [ + "mechanical_arm" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🦿" + , "description": "mechanical leg" + , "category": "People & Body" + , "aliases": [ + "mechanical_leg" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🦵" + , "description": "leg" + , "category": "People & Body" + , "aliases": [ + "leg" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🦶" + , "description": "foot" + , "category": "People & Body" + , "aliases": [ + "foot" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👂" + , "description": "ear" + , "category": "People & Body" + , "aliases": [ + "ear" + ] + , "tags": [ + "hear" + , "sound" + , "listen" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🦻" + , "description": "ear with hearing aid" + , "category": "People & Body" + , "aliases": [ + "ear_with_hearing_aid" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "👃" + , "description": "nose" + , "category": "People & Body" + , "aliases": [ + "nose" + ] + , "tags": [ + "smell" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🧠" + , "description": "brain" + , "category": "People & Body" + , "aliases": [ + "brain" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦷" + , "description": "tooth" + , "category": "People & Body" + , "aliases": [ + "tooth" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦴" + , "description": "bone" + , "category": "People & Body" + , "aliases": [ + "bone" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "👀" + , "description": "eyes" + , "category": "People & Body" + , "aliases": [ + "eyes" + ] + , "tags": [ + "look" + , "see" + , "watch" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👁" + , "description": "eye" + , "category": "People & Body" + , "aliases": [ + "eye" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "👅" + , "description": "tongue" + , "category": "People & Body" + , "aliases": [ + "tongue" + ] + , "tags": [ + "taste" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👄" + , "description": "mouth" + , "category": "People & Body" + , "aliases": [ + "lips" + ] + , "tags": [ + "kiss" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👶" + , "description": "baby" + , "category": "People & Body" + , "aliases": [ + "baby" + ] + , "tags": [ + "child" + , "newborn" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🧒" + , "description": "child" + , "category": "People & Body" + , "aliases": [ + "child" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👦" + , "description": "boy" + , "category": "People & Body" + , "aliases": [ + "boy" + ] + , "tags": [ + "child" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👧" + , "description": "girl" + , "category": "People & Body" + , "aliases": [ + "girl" + ] + , "tags": [ + "child" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🧑" + , "description": "person" + , "category": "People & Body" + , "aliases": [ + "adult" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👱" + , "description": "person: blond hair" + , "category": "People & Body" + , "aliases": [ + "blond_haired_person" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👨" + , "description": "man" + , "category": "People & Body" + , "aliases": [ + "man" + ] + , "tags": [ + "mustache" + , "father" + , "dad" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🧔" + , "description": "man: beard" + , "category": "People & Body" + , "aliases": [ + "bearded_person" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👱‍♂" + , "description": "man: blond hair" + , "category": "People & Body" + , "aliases": [ + "blond_haired_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👨‍🦰" + , "description": "man: red hair" + , "category": "People & Body" + , "aliases": [ + "red_haired_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👨‍🦱" + , "description": "man: curly hair" + , "category": "People & Body" + , "aliases": [ + "curly_haired_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👨‍🦳" + , "description": "man: white hair" + , "category": "People & Body" + , "aliases": [ + "white_haired_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👨‍🦲" + , "description": "man: bald" + , "category": "People & Body" + , "aliases": [ + "bald_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👩" + , "description": "woman" + , "category": "People & Body" + , "aliases": [ + "woman" + ] + , "tags": [ + "girls" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👱‍♀" + , "description": "woman: blond hair" + , "category": "People & Body" + , "aliases": [ + "blond_haired_woman" + , "blonde_woman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "👩‍🦰" + , "description": "woman: red hair" + , "category": "People & Body" + , "aliases": [ + "red_haired_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👩‍🦱" + , "description": "woman: curly hair" + , "category": "People & Body" + , "aliases": [ + "curly_haired_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👩‍🦳" + , "description": "woman: white hair" + , "category": "People & Body" + , "aliases": [ + "white_haired_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👩‍🦲" + , "description": "woman: bald" + , "category": "People & Body" + , "aliases": [ + "bald_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧓" + , "description": "older person" + , "category": "People & Body" + , "aliases": [ + "older_adult" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👴" + , "description": "old man" + , "category": "People & Body" + , "aliases": [ + "older_man" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👵" + , "description": "old woman" + , "category": "People & Body" + , "aliases": [ + "older_woman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🙍" + , "description": "person frowning" + , "category": "People & Body" + , "aliases": [ + "frowning_person" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🙍‍♂" + , "description": "man frowning" + , "category": "People & Body" + , "aliases": [ + "frowning_man" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🙍‍♀" + , "description": "woman frowning" + , "category": "People & Body" + , "aliases": [ + "frowning_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🙎" + , "description": "person pouting" + , "category": "People & Body" + , "aliases": [ + "pouting_face" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🙎‍♂" + , "description": "man pouting" + , "category": "People & Body" + , "aliases": [ + "pouting_man" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🙎‍♀" + , "description": "woman pouting" + , "category": "People & Body" + , "aliases": [ + "pouting_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🙅" + , "description": "person gesturing NO" + , "category": "People & Body" + , "aliases": [ + "no_good" + ] + , "tags": [ + "stop" + , "halt" + , "denied" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🙅‍♂" + , "description": "man gesturing NO" + , "category": "People & Body" + , "aliases": [ + "no_good_man" + , "ng_man" + ] + , "tags": [ + "stop" + , "halt" + , "denied" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🙅‍♀" + , "description": "woman gesturing NO" + , "category": "People & Body" + , "aliases": [ + "no_good_woman" + , "ng_woman" + ] + , "tags": [ + "stop" + , "halt" + , "denied" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🙆" + , "description": "person gesturing OK" + , "category": "People & Body" + , "aliases": [ + "ok_person" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🙆‍♂" + , "description": "man gesturing OK" + , "category": "People & Body" + , "aliases": [ + "ok_man" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🙆‍♀" + , "description": "woman gesturing OK" + , "category": "People & Body" + , "aliases": [ + "ok_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "💁" + , "description": "person tipping hand" + , "category": "People & Body" + , "aliases": [ + "tipping_hand_person" + , "information_desk_person" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "💁‍♂" + , "description": "man tipping hand" + , "category": "People & Body" + , "aliases": [ + "tipping_hand_man" + , "sassy_man" + ] + , "tags": [ + "information" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "💁‍♀" + , "description": "woman tipping hand" + , "category": "People & Body" + , "aliases": [ + "tipping_hand_woman" + , "sassy_woman" + ] + , "tags": [ + "information" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🙋" + , "description": "person raising hand" + , "category": "People & Body" + , "aliases": [ + "raising_hand" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🙋‍♂" + , "description": "man raising hand" + , "category": "People & Body" + , "aliases": [ + "raising_hand_man" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🙋‍♀" + , "description": "woman raising hand" + , "category": "People & Body" + , "aliases": [ + "raising_hand_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧏" + , "description": "deaf person" + , "category": "People & Body" + , "aliases": [ + "deaf_person" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "🧏‍♂" + , "description": "deaf man" + , "category": "People & Body" + , "aliases": [ + "deaf_man" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "🧏‍♀" + , "description": "deaf woman" + , "category": "People & Body" + , "aliases": [ + "deaf_woman" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "🙇" + , "description": "person bowing" + , "category": "People & Body" + , "aliases": [ + "bow" + ] + , "tags": [ + "respect" + , "thanks" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🙇‍♂" + , "description": "man bowing" + , "category": "People & Body" + , "aliases": [ + "bowing_man" + ] + , "tags": [ + "respect" + , "thanks" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🙇‍♀" + , "description": "woman bowing" + , "category": "People & Body" + , "aliases": [ + "bowing_woman" + ] + , "tags": [ + "respect" + , "thanks" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🤦" + , "description": "person facepalming" + , "category": "People & Body" + , "aliases": [ + "facepalm" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤦‍♂" + , "description": "man facepalming" + , "category": "People & Body" + , "aliases": [ + "man_facepalming" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤦‍♀" + , "description": "woman facepalming" + , "category": "People & Body" + , "aliases": [ + "woman_facepalming" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤷" + , "description": "person shrugging" + , "category": "People & Body" + , "aliases": [ + "shrug" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤷‍♂" + , "description": "man shrugging" + , "category": "People & Body" + , "aliases": [ + "man_shrugging" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤷‍♀" + , "description": "woman shrugging" + , "category": "People & Body" + , "aliases": [ + "woman_shrugging" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍⚕" + , "description": "man health worker" + , "category": "People & Body" + , "aliases": [ + "man_health_worker" + ] + , "tags": [ + "doctor" + , "nurse" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍⚕" + , "description": "woman health worker" + , "category": "People & Body" + , "aliases": [ + "woman_health_worker" + ] + , "tags": [ + "doctor" + , "nurse" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🎓" + , "description": "man student" + , "category": "People & Body" + , "aliases": [ + "man_student" + ] + , "tags": [ + "graduation" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🎓" + , "description": "woman student" + , "category": "People & Body" + , "aliases": [ + "woman_student" + ] + , "tags": [ + "graduation" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🏫" + , "description": "man teacher" + , "category": "People & Body" + , "aliases": [ + "man_teacher" + ] + , "tags": [ + "school" + , "professor" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🏫" + , "description": "woman teacher" + , "category": "People & Body" + , "aliases": [ + "woman_teacher" + ] + , "tags": [ + "school" + , "professor" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍⚖" + , "description": "man judge" + , "category": "People & Body" + , "aliases": [ + "man_judge" + ] + , "tags": [ + "justice" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍⚖" + , "description": "woman judge" + , "category": "People & Body" + , "aliases": [ + "woman_judge" + ] + , "tags": [ + "justice" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🌾" + , "description": "man farmer" + , "category": "People & Body" + , "aliases": [ + "man_farmer" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🌾" + , "description": "woman farmer" + , "category": "People & Body" + , "aliases": [ + "woman_farmer" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🍳" + , "description": "man cook" + , "category": "People & Body" + , "aliases": [ + "man_cook" + ] + , "tags": [ + "chef" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🍳" + , "description": "woman cook" + , "category": "People & Body" + , "aliases": [ + "woman_cook" + ] + , "tags": [ + "chef" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🔧" + , "description": "man mechanic" + , "category": "People & Body" + , "aliases": [ + "man_mechanic" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🔧" + , "description": "woman mechanic" + , "category": "People & Body" + , "aliases": [ + "woman_mechanic" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🏭" + , "description": "man factory worker" + , "category": "People & Body" + , "aliases": [ + "man_factory_worker" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🏭" + , "description": "woman factory worker" + , "category": "People & Body" + , "aliases": [ + "woman_factory_worker" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍💼" + , "description": "man office worker" + , "category": "People & Body" + , "aliases": [ + "man_office_worker" + ] + , "tags": [ + "business" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍💼" + , "description": "woman office worker" + , "category": "People & Body" + , "aliases": [ + "woman_office_worker" + ] + , "tags": [ + "business" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🔬" + , "description": "man scientist" + , "category": "People & Body" + , "aliases": [ + "man_scientist" + ] + , "tags": [ + "research" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🔬" + , "description": "woman scientist" + , "category": "People & Body" + , "aliases": [ + "woman_scientist" + ] + , "tags": [ + "research" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍💻" + , "description": "man technologist" + , "category": "People & Body" + , "aliases": [ + "man_technologist" + ] + , "tags": [ + "coder" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍💻" + , "description": "woman technologist" + , "category": "People & Body" + , "aliases": [ + "woman_technologist" + ] + , "tags": [ + "coder" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🎤" + , "description": "man singer" + , "category": "People & Body" + , "aliases": [ + "man_singer" + ] + , "tags": [ + "rockstar" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🎤" + , "description": "woman singer" + , "category": "People & Body" + , "aliases": [ + "woman_singer" + ] + , "tags": [ + "rockstar" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🎨" + , "description": "man artist" + , "category": "People & Body" + , "aliases": [ + "man_artist" + ] + , "tags": [ + "painter" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🎨" + , "description": "woman artist" + , "category": "People & Body" + , "aliases": [ + "woman_artist" + ] + , "tags": [ + "painter" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍✈" + , "description": "man pilot" + , "category": "People & Body" + , "aliases": [ + "man_pilot" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍✈" + , "description": "woman pilot" + , "category": "People & Body" + , "aliases": [ + "woman_pilot" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🚀" + , "description": "man astronaut" + , "category": "People & Body" + , "aliases": [ + "man_astronaut" + ] + , "tags": [ + "space" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🚀" + , "description": "woman astronaut" + , "category": "People & Body" + , "aliases": [ + "woman_astronaut" + ] + , "tags": [ + "space" + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👨‍🚒" + , "description": "man firefighter" + , "category": "People & Body" + , "aliases": [ + "man_firefighter" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👩‍🚒" + , "description": "woman firefighter" + , "category": "People & Body" + , "aliases": [ + "woman_firefighter" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👮" + , "description": "police officer" + , "category": "People & Body" + , "aliases": [ + "police_officer" + , "cop" + ] + , "tags": [ + "law" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👮‍♂" + , "description": "man police officer" + , "category": "People & Body" + , "aliases": [ + "policeman" + ] + , "tags": [ + "law" + , "cop" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👮‍♀" + , "description": "woman police officer" + , "category": "People & Body" + , "aliases": [ + "policewoman" + ] + , "tags": [ + "law" + , "cop" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🕵" + , "description": "detective" + , "category": "People & Body" + , "aliases": [ + "detective" + ] + , "tags": [ + "sleuth" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "🕵️‍♂️" + , "description": "man detective" + , "category": "People & Body" + , "aliases": [ + "male_detective" + ] + , "tags": [ + "sleuth" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🕵️‍♀️" + , "description": "woman detective" + , "category": "People & Body" + , "aliases": [ + "female_detective" + ] + , "tags": [ + "sleuth" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "💂" + , "description": "guard" + , "category": "People & Body" + , "aliases": [ + "guard" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "💂‍♂" + , "description": "man guard" + , "category": "People & Body" + , "aliases": [ + "guardsman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "💂‍♀" + , "description": "woman guard" + , "category": "People & Body" + , "aliases": [ + "guardswoman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "👷" + , "description": "construction worker" + , "category": "People & Body" + , "aliases": [ + "construction_worker" + ] + , "tags": [ + "helmet" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👷‍♂" + , "description": "man construction worker" + , "category": "People & Body" + , "aliases": [ + "construction_worker_man" + ] + , "tags": [ + "helmet" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👷‍♀" + , "description": "woman construction worker" + , "category": "People & Body" + , "aliases": [ + "construction_worker_woman" + ] + , "tags": [ + "helmet" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🤴" + , "description": "prince" + , "category": "People & Body" + , "aliases": [ + "prince" + ] + , "tags": [ + "crown" + , "royal" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👸" + , "description": "princess" + , "category": "People & Body" + , "aliases": [ + "princess" + ] + , "tags": [ + "crown" + , "royal" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👳" + , "description": "person wearing turban" + , "category": "People & Body" + , "aliases": [ + "person_with_turban" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👳‍♂" + , "description": "man wearing turban" + , "category": "People & Body" + , "aliases": [ + "man_with_turban" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👳‍♀" + , "description": "woman wearing turban" + , "category": "People & Body" + , "aliases": [ + "woman_with_turban" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "👲" + , "description": "man with Chinese cap" + , "category": "People & Body" + , "aliases": [ + "man_with_gua_pi_mao" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🧕" + , "description": "woman with headscarf" + , "category": "People & Body" + , "aliases": [ + "woman_with_headscarf" + ] + , "tags": [ + "hijab" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤵" + , "description": "man in tuxedo" + , "category": "People & Body" + , "aliases": [ + "man_in_tuxedo" + ] + , "tags": [ + "groom" + , "marriage" + , "wedding" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "👰" + , "description": "bride with veil" + , "category": "People & Body" + , "aliases": [ + "bride_with_veil" + ] + , "tags": [ + "marriage" + , "wedding" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🤰" + , "description": "pregnant woman" + , "category": "People & Body" + , "aliases": [ + "pregnant_woman" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤱" + , "description": "breast-feeding" + , "category": "People & Body" + , "aliases": [ + "breast_feeding" + ] + , "tags": [ + "nursing" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "👼" + , "description": "baby angel" + , "category": "People & Body" + , "aliases": [ + "angel" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🎅" + , "description": "Santa Claus" + , "category": "People & Body" + , "aliases": [ + "santa" + ] + , "tags": [ + "christmas" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🤶" + , "description": "Mrs. Claus" + , "category": "People & Body" + , "aliases": [ + "mrs_claus" + ] + , "tags": [ + "santa" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🦸" + , "description": "superhero" + , "category": "People & Body" + , "aliases": [ + "superhero" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🦸‍♂" + , "description": "man superhero" + , "category": "People & Body" + , "aliases": [ + "superhero_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🦸‍♀" + , "description": "woman superhero" + , "category": "People & Body" + , "aliases": [ + "superhero_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🦹" + , "description": "supervillain" + , "category": "People & Body" + , "aliases": [ + "supervillain" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🦹‍♂" + , "description": "man supervillain" + , "category": "People & Body" + , "aliases": [ + "supervillain_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🦹‍♀" + , "description": "woman supervillain" + , "category": "People & Body" + , "aliases": [ + "supervillain_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧙" + , "description": "mage" + , "category": "People & Body" + , "aliases": [ + "mage" + ] + , "tags": [ + "wizard" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧙‍♂" + , "description": "man mage" + , "category": "People & Body" + , "aliases": [ + "mage_man" + ] + , "tags": [ + "wizard" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧙‍♀" + , "description": "woman mage" + , "category": "People & Body" + , "aliases": [ + "mage_woman" + ] + , "tags": [ + "wizard" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧚" + , "description": "fairy" + , "category": "People & Body" + , "aliases": [ + "fairy" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧚‍♂" + , "description": "man fairy" + , "category": "People & Body" + , "aliases": [ + "fairy_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧚‍♀" + , "description": "woman fairy" + , "category": "People & Body" + , "aliases": [ + "fairy_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧛" + , "description": "vampire" + , "category": "People & Body" + , "aliases": [ + "vampire" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧛‍♂" + , "description": "man vampire" + , "category": "People & Body" + , "aliases": [ + "vampire_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧛‍♀" + , "description": "woman vampire" + , "category": "People & Body" + , "aliases": [ + "vampire_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧜" + , "description": "merperson" + , "category": "People & Body" + , "aliases": [ + "merperson" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧜‍♂" + , "description": "merman" + , "category": "People & Body" + , "aliases": [ + "merman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧜‍♀" + , "description": "mermaid" + , "category": "People & Body" + , "aliases": [ + "mermaid" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧝" + , "description": "elf" + , "category": "People & Body" + , "aliases": [ + "elf" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧝‍♂" + , "description": "man elf" + , "category": "People & Body" + , "aliases": [ + "elf_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧝‍♀" + , "description": "woman elf" + , "category": "People & Body" + , "aliases": [ + "elf_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧞" + , "description": "genie" + , "category": "People & Body" + , "aliases": [ + "genie" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧞‍♂" + , "description": "man genie" + , "category": "People & Body" + , "aliases": [ + "genie_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧞‍♀" + , "description": "woman genie" + , "category": "People & Body" + , "aliases": [ + "genie_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧟" + , "description": "zombie" + , "category": "People & Body" + , "aliases": [ + "zombie" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧟‍♂" + , "description": "man zombie" + , "category": "People & Body" + , "aliases": [ + "zombie_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧟‍♀" + , "description": "woman zombie" + , "category": "People & Body" + , "aliases": [ + "zombie_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "💆" + , "description": "person getting massage" + , "category": "People & Body" + , "aliases": [ + "massage" + ] + , "tags": [ + "spa" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "💆‍♂" + , "description": "man getting massage" + , "category": "People & Body" + , "aliases": [ + "massage_man" + ] + , "tags": [ + "spa" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "💆‍♀" + , "description": "woman getting massage" + , "category": "People & Body" + , "aliases": [ + "massage_woman" + ] + , "tags": [ + "spa" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "💇" + , "description": "person getting haircut" + , "category": "People & Body" + , "aliases": [ + "haircut" + ] + , "tags": [ + "beauty" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "💇‍♂" + , "description": "man getting haircut" + , "category": "People & Body" + , "aliases": [ + "haircut_man" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "💇‍♀" + , "description": "woman getting haircut" + , "category": "People & Body" + , "aliases": [ + "haircut_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🚶" + , "description": "person walking" + , "category": "People & Body" + , "aliases": [ + "walking" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🚶‍♂" + , "description": "man walking" + , "category": "People & Body" + , "aliases": [ + "walking_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🚶‍♀" + , "description": "woman walking" + , "category": "People & Body" + , "aliases": [ + "walking_woman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🧍" + , "description": "person standing" + , "category": "People & Body" + , "aliases": [ + "standing_person" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "🧍‍♂" + , "description": "man standing" + , "category": "People & Body" + , "aliases": [ + "standing_man" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "🧍‍♀" + , "description": "woman standing" + , "category": "People & Body" + , "aliases": [ + "standing_woman" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "🧎" + , "description": "person kneeling" + , "category": "People & Body" + , "aliases": [ + "kneeling_person" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "🧎‍♂" + , "description": "man kneeling" + , "category": "People & Body" + , "aliases": [ + "kneeling_man" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "🧎‍♀" + , "description": "woman kneeling" + , "category": "People & Body" + , "aliases": [ + "kneeling_woman" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "👨‍🦯" + , "description": "man with probing cane" + , "category": "People & Body" + , "aliases": [ + "man_with_probing_cane" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "👩‍🦯" + , "description": "woman with probing cane" + , "category": "People & Body" + , "aliases": [ + "woman_with_probing_cane" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "👨‍🦼" + , "description": "man in motorized wheelchair" + , "category": "People & Body" + , "aliases": [ + "man_in_motorized_wheelchair" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "👩‍🦼" + , "description": "woman in motorized wheelchair" + , "category": "People & Body" + , "aliases": [ + "woman_in_motorized_wheelchair" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "👨‍🦽" + , "description": "man in manual wheelchair" + , "category": "People & Body" + , "aliases": [ + "man_in_manual_wheelchair" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "👩‍🦽" + , "description": "woman in manual wheelchair" + , "category": "People & Body" + , "aliases": [ + "woman_in_manual_wheelchair" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "🏃" + , "description": "person running" + , "category": "People & Body" + , "aliases": [ + "runner" + , "running" + ] + , "tags": [ + "exercise" + , "workout" + , "marathon" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🏃‍♂" + , "description": "man running" + , "category": "People & Body" + , "aliases": [ + "running_man" + ] + , "tags": [ + "exercise" + , "workout" + , "marathon" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🏃‍♀" + , "description": "woman running" + , "category": "People & Body" + , "aliases": [ + "running_woman" + ] + , "tags": [ + "exercise" + , "workout" + , "marathon" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "💃" + , "description": "woman dancing" + , "category": "People & Body" + , "aliases": [ + "woman_dancing" + , "dancer" + ] + , "tags": [ + "dress" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🕺" + , "description": "man dancing" + , "category": "People & Body" + , "aliases": [ + "man_dancing" + ] + , "tags": [ + "dancer" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🕴" + , "description": "man in suit levitating" + , "category": "People & Body" + , "aliases": [ + "business_suit_levitating" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "👯" + , "description": "people with bunny ears" + , "category": "People & Body" + , "aliases": [ + "dancers" + ] + , "tags": [ + "bunny" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👯‍♂" + , "description": "men with bunny ears" + , "category": "People & Body" + , "aliases": [ + "dancing_men" + ] + , "tags": [ + "bunny" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👯‍♀" + , "description": "women with bunny ears" + , "category": "People & Body" + , "aliases": [ + "dancing_women" + ] + , "tags": [ + "bunny" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧖" + , "description": "person in steamy room" + , "category": "People & Body" + , "aliases": [ + "sauna_person" + ] + , "tags": [ + "steamy" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧖‍♂" + , "description": "man in steamy room" + , "category": "People & Body" + , "aliases": [ + "sauna_man" + ] + , "tags": [ + "steamy" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧖‍♀" + , "description": "woman in steamy room" + , "category": "People & Body" + , "aliases": [ + "sauna_woman" + ] + , "tags": [ + "steamy" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧗" + , "description": "person climbing" + , "category": "People & Body" + , "aliases": [ + "climbing" + ] + , "tags": [ + "bouldering" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧗‍♂" + , "description": "man climbing" + , "category": "People & Body" + , "aliases": [ + "climbing_man" + ] + , "tags": [ + "bouldering" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧗‍♀" + , "description": "woman climbing" + , "category": "People & Body" + , "aliases": [ + "climbing_woman" + ] + , "tags": [ + "bouldering" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤺" + , "description": "person fencing" + , "category": "People & Body" + , "aliases": [ + "person_fencing" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🏇" + , "description": "horse racing" + , "category": "People & Body" + , "aliases": [ + "horse_racing" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "⛷" + , "description": "skier" + , "category": "People & Body" + , "aliases": [ + "skier" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "🏂" + , "description": "snowboarder" + , "category": "People & Body" + , "aliases": [ + "snowboarder" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🏌" + , "description": "person golfing" + , "category": "People & Body" + , "aliases": [ + "golfing" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "🏌️‍♂️" + , "description": "man golfing" + , "category": "People & Body" + , "aliases": [ + "golfing_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🏌️‍♀️" + , "description": "woman golfing" + , "category": "People & Body" + , "aliases": [ + "golfing_woman" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🏄" + , "description": "person surfing" + , "category": "People & Body" + , "aliases": [ + "surfer" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🏄‍♂" + , "description": "man surfing" + , "category": "People & Body" + , "aliases": [ + "surfing_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🏄‍♀" + , "description": "woman surfing" + , "category": "People & Body" + , "aliases": [ + "surfing_woman" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🚣" + , "description": "person rowing boat" + , "category": "People & Body" + , "aliases": [ + "rowboat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🚣‍♂" + , "description": "man rowing boat" + , "category": "People & Body" + , "aliases": [ + "rowing_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🚣‍♀" + , "description": "woman rowing boat" + , "category": "People & Body" + , "aliases": [ + "rowing_woman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🏊" + , "description": "person swimming" + , "category": "People & Body" + , "aliases": [ + "swimmer" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🏊‍♂" + , "description": "man swimming" + , "category": "People & Body" + , "aliases": [ + "swimming_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🏊‍♀" + , "description": "woman swimming" + , "category": "People & Body" + , "aliases": [ + "swimming_woman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "⛹" + , "description": "person bouncing ball" + , "category": "People & Body" + , "aliases": [ + "bouncing_ball_person" + ] + , "tags": [ + "basketball" + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "⛹️‍♂️" + , "description": "man bouncing ball" + , "category": "People & Body" + , "aliases": [ + "bouncing_ball_man" + , "basketball_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "⛹️‍♀️" + , "description": "woman bouncing ball" + , "category": "People & Body" + , "aliases": [ + "bouncing_ball_woman" + , "basketball_woman" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🏋" + , "description": "person lifting weights" + , "category": "People & Body" + , "aliases": [ + "weight_lifting" + ] + , "tags": [ + "gym" + , "workout" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "🏋️‍♂️" + , "description": "man lifting weights" + , "category": "People & Body" + , "aliases": [ + "weight_lifting_man" + ] + , "tags": [ + "gym" + , "workout" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🏋️‍♀️" + , "description": "woman lifting weights" + , "category": "People & Body" + , "aliases": [ + "weight_lifting_woman" + ] + , "tags": [ + "gym" + , "workout" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🚴" + , "description": "person biking" + , "category": "People & Body" + , "aliases": [ + "bicyclist" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🚴‍♂" + , "description": "man biking" + , "category": "People & Body" + , "aliases": [ + "biking_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🚴‍♀" + , "description": "woman biking" + , "category": "People & Body" + , "aliases": [ + "biking_woman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🚵" + , "description": "person mountain biking" + , "category": "People & Body" + , "aliases": [ + "mountain_bicyclist" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🚵‍♂" + , "description": "man mountain biking" + , "category": "People & Body" + , "aliases": [ + "mountain_biking_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🚵‍♀" + , "description": "woman mountain biking" + , "category": "People & Body" + , "aliases": [ + "mountain_biking_woman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + , "skin_tones": true + } +, { + "emoji": "🤸" + , "description": "person cartwheeling" + , "category": "People & Body" + , "aliases": [ + "cartwheeling" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤸‍♂" + , "description": "man cartwheeling" + , "category": "People & Body" + , "aliases": [ + "man_cartwheeling" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤸‍♀" + , "description": "woman cartwheeling" + , "category": "People & Body" + , "aliases": [ + "woman_cartwheeling" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤼" + , "description": "people wrestling" + , "category": "People & Body" + , "aliases": [ + "wrestling" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🤼‍♂" + , "description": "men wrestling" + , "category": "People & Body" + , "aliases": [ + "men_wrestling" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🤼‍♀" + , "description": "women wrestling" + , "category": "People & Body" + , "aliases": [ + "women_wrestling" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🤽" + , "description": "person playing water polo" + , "category": "People & Body" + , "aliases": [ + "water_polo" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤽‍♂" + , "description": "man playing water polo" + , "category": "People & Body" + , "aliases": [ + "man_playing_water_polo" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤽‍♀" + , "description": "woman playing water polo" + , "category": "People & Body" + , "aliases": [ + "woman_playing_water_polo" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤾" + , "description": "person playing handball" + , "category": "People & Body" + , "aliases": [ + "handball_person" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤾‍♂" + , "description": "man playing handball" + , "category": "People & Body" + , "aliases": [ + "man_playing_handball" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤾‍♀" + , "description": "woman playing handball" + , "category": "People & Body" + , "aliases": [ + "woman_playing_handball" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤹" + , "description": "person juggling" + , "category": "People & Body" + , "aliases": [ + "juggling_person" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🤹‍♂" + , "description": "man juggling" + , "category": "People & Body" + , "aliases": [ + "man_juggling" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🤹‍♀" + , "description": "woman juggling" + , "category": "People & Body" + , "aliases": [ + "woman_juggling" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + , "skin_tones": true + } +, { + "emoji": "🧘" + , "description": "person in lotus position" + , "category": "People & Body" + , "aliases": [ + "lotus_position" + ] + , "tags": [ + "meditation" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧘‍♂" + , "description": "man in lotus position" + , "category": "People & Body" + , "aliases": [ + "lotus_position_man" + ] + , "tags": [ + "meditation" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🧘‍♀" + , "description": "woman in lotus position" + , "category": "People & Body" + , "aliases": [ + "lotus_position_woman" + ] + , "tags": [ + "meditation" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + , "skin_tones": true + } +, { + "emoji": "🛀" + , "description": "person taking bath" + , "category": "People & Body" + , "aliases": [ + "bath" + ] + , "tags": [ + "shower" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "🛌" + , "description": "person in bed" + , "category": "People & Body" + , "aliases": [ + "sleeping_bed" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + , "skin_tones": true + } +, { + "emoji": "🧑‍🤝‍🧑" + , "description": "people holding hands" + , "category": "People & Body" + , "aliases": [ + "people_holding_hands" + ] + , "tags": [ + "couple" + , "date" + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + , "skin_tones": true + } +, { + "emoji": "👭" + , "description": "women holding hands" + , "category": "People & Body" + , "aliases": [ + "two_women_holding_hands" + ] + , "tags": [ + "couple" + , "date" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👫" + , "description": "woman and man holding hands" + , "category": "People & Body" + , "aliases": [ + "couple" + ] + , "tags": [ + "date" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "👬" + , "description": "men holding hands" + , "category": "People & Body" + , "aliases": [ + "two_men_holding_hands" + ] + , "tags": [ + "couple" + , "date" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + , "skin_tones": true + } +, { + "emoji": "💏" + , "description": "kiss" + , "category": "People & Body" + , "aliases": [ + "couplekiss" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👩‍❤️‍💋‍👨" + , "description": "kiss: woman, man" + , "category": "People & Body" + , "aliases": [ + "couplekiss_man_woman" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "👨‍❤️‍💋‍👨" + , "description": "kiss: man, man" + , "category": "People & Body" + , "aliases": [ + "couplekiss_man_man" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👩‍❤️‍💋‍👩" + , "description": "kiss: woman, woman" + , "category": "People & Body" + , "aliases": [ + "couplekiss_woman_woman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "💑" + , "description": "couple with heart" + , "category": "People & Body" + , "aliases": [ + "couple_with_heart" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👩‍❤️‍👨" + , "description": "couple with heart: woman, man" + , "category": "People & Body" + , "aliases": [ + "couple_with_heart_woman_man" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "👨‍❤️‍👨" + , "description": "couple with heart: man, man" + , "category": "People & Body" + , "aliases": [ + "couple_with_heart_man_man" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👩‍❤️‍👩" + , "description": "couple with heart: woman, woman" + , "category": "People & Body" + , "aliases": [ + "couple_with_heart_woman_woman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👪" + , "description": "family" + , "category": "People & Body" + , "aliases": [ + "family" + ] + , "tags": [ + "home" + , "parents" + , "child" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👨‍👩‍👦" + , "description": "family: man, woman, boy" + , "category": "People & Body" + , "aliases": [ + "family_man_woman_boy" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "👨‍👩‍👧" + , "description": "family: man, woman, girl" + , "category": "People & Body" + , "aliases": [ + "family_man_woman_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👨‍👩‍👧‍👦" + , "description": "family: man, woman, girl, boy" + , "category": "People & Body" + , "aliases": [ + "family_man_woman_girl_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👨‍👩‍👦‍👦" + , "description": "family: man, woman, boy, boy" + , "category": "People & Body" + , "aliases": [ + "family_man_woman_boy_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👨‍👩‍👧‍👧" + , "description": "family: man, woman, girl, girl" + , "category": "People & Body" + , "aliases": [ + "family_man_woman_girl_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👨‍👨‍👦" + , "description": "family: man, man, boy" + , "category": "People & Body" + , "aliases": [ + "family_man_man_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👨‍👨‍👧" + , "description": "family: man, man, girl" + , "category": "People & Body" + , "aliases": [ + "family_man_man_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👨‍👨‍👧‍👦" + , "description": "family: man, man, girl, boy" + , "category": "People & Body" + , "aliases": [ + "family_man_man_girl_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👨‍👨‍👦‍👦" + , "description": "family: man, man, boy, boy" + , "category": "People & Body" + , "aliases": [ + "family_man_man_boy_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👨‍👨‍👧‍👧" + , "description": "family: man, man, girl, girl" + , "category": "People & Body" + , "aliases": [ + "family_man_man_girl_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👩‍👩‍👦" + , "description": "family: woman, woman, boy" + , "category": "People & Body" + , "aliases": [ + "family_woman_woman_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👩‍👩‍👧" + , "description": "family: woman, woman, girl" + , "category": "People & Body" + , "aliases": [ + "family_woman_woman_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👩‍👩‍👧‍👦" + , "description": "family: woman, woman, girl, boy" + , "category": "People & Body" + , "aliases": [ + "family_woman_woman_girl_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👩‍👩‍👦‍👦" + , "description": "family: woman, woman, boy, boy" + , "category": "People & Body" + , "aliases": [ + "family_woman_woman_boy_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👩‍👩‍👧‍👧" + , "description": "family: woman, woman, girl, girl" + , "category": "People & Body" + , "aliases": [ + "family_woman_woman_girl_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "👨‍👦" + , "description": "family: man, boy" + , "category": "People & Body" + , "aliases": [ + "family_man_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👨‍👦‍👦" + , "description": "family: man, boy, boy" + , "category": "People & Body" + , "aliases": [ + "family_man_boy_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👨‍👧" + , "description": "family: man, girl" + , "category": "People & Body" + , "aliases": [ + "family_man_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👨‍👧‍👦" + , "description": "family: man, girl, boy" + , "category": "People & Body" + , "aliases": [ + "family_man_girl_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👨‍👧‍👧" + , "description": "family: man, girl, girl" + , "category": "People & Body" + , "aliases": [ + "family_man_girl_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👩‍👦" + , "description": "family: woman, boy" + , "category": "People & Body" + , "aliases": [ + "family_woman_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👩‍👦‍👦" + , "description": "family: woman, boy, boy" + , "category": "People & Body" + , "aliases": [ + "family_woman_boy_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👩‍👧" + , "description": "family: woman, girl" + , "category": "People & Body" + , "aliases": [ + "family_woman_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👩‍👧‍👦" + , "description": "family: woman, girl, boy" + , "category": "People & Body" + , "aliases": [ + "family_woman_girl_boy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "👩‍👧‍👧" + , "description": "family: woman, girl, girl" + , "category": "People & Body" + , "aliases": [ + "family_woman_girl_girl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "🗣" + , "description": "speaking head" + , "category": "People & Body" + , "aliases": [ + "speaking_head" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "👤" + , "description": "bust in silhouette" + , "category": "People & Body" + , "aliases": [ + "bust_in_silhouette" + ] + , "tags": [ + "user" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👥" + , "description": "busts in silhouette" + , "category": "People & Body" + , "aliases": [ + "busts_in_silhouette" + ] + , "tags": [ + "users" + , "group" + , "team" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👣" + , "description": "footprints" + , "category": "People & Body" + , "aliases": [ + "footprints" + ] + , "tags": [ + "feet" + , "tracks" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐵" + , "description": "monkey face" + , "category": "Animals & Nature" + , "aliases": [ + "monkey_face" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐒" + , "description": "monkey" + , "category": "Animals & Nature" + , "aliases": [ + "monkey" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦍" + , "description": "gorilla" + , "category": "Animals & Nature" + , "aliases": [ + "gorilla" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🦧" + , "description": "orangutan" + , "category": "Animals & Nature" + , "aliases": [ + "orangutan" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🐶" + , "description": "dog face" + , "category": "Animals & Nature" + , "aliases": [ + "dog" + ] + , "tags": [ + "pet" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐕" + , "description": "dog" + , "category": "Animals & Nature" + , "aliases": [ + "dog2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦮" + , "description": "guide dog" + , "category": "Animals & Nature" + , "aliases": [ + "guide_dog" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🐕‍🦺" + , "description": "service dog" + , "category": "Animals & Nature" + , "aliases": [ + "service_dog" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🐩" + , "description": "poodle" + , "category": "Animals & Nature" + , "aliases": [ + "poodle" + ] + , "tags": [ + "dog" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐺" + , "description": "wolf" + , "category": "Animals & Nature" + , "aliases": [ + "wolf" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦊" + , "description": "fox" + , "category": "Animals & Nature" + , "aliases": [ + "fox_face" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🦝" + , "description": "raccoon" + , "category": "Animals & Nature" + , "aliases": [ + "raccoon" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🐱" + , "description": "cat face" + , "category": "Animals & Nature" + , "aliases": [ + "cat" + ] + , "tags": [ + "pet" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐈" + , "description": "cat" + , "category": "Animals & Nature" + , "aliases": [ + "cat2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦁" + , "description": "lion" + , "category": "Animals & Nature" + , "aliases": [ + "lion" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🐯" + , "description": "tiger face" + , "category": "Animals & Nature" + , "aliases": [ + "tiger" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐅" + , "description": "tiger" + , "category": "Animals & Nature" + , "aliases": [ + "tiger2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐆" + , "description": "leopard" + , "category": "Animals & Nature" + , "aliases": [ + "leopard" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐴" + , "description": "horse face" + , "category": "Animals & Nature" + , "aliases": [ + "horse" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐎" + , "description": "horse" + , "category": "Animals & Nature" + , "aliases": [ + "racehorse" + ] + , "tags": [ + "speed" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦄" + , "description": "unicorn" + , "category": "Animals & Nature" + , "aliases": [ + "unicorn" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🦓" + , "description": "zebra" + , "category": "Animals & Nature" + , "aliases": [ + "zebra" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦌" + , "description": "deer" + , "category": "Animals & Nature" + , "aliases": [ + "deer" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🐮" + , "description": "cow face" + , "category": "Animals & Nature" + , "aliases": [ + "cow" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐂" + , "description": "ox" + , "category": "Animals & Nature" + , "aliases": [ + "ox" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐃" + , "description": "water buffalo" + , "category": "Animals & Nature" + , "aliases": [ + "water_buffalo" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐄" + , "description": "cow" + , "category": "Animals & Nature" + , "aliases": [ + "cow2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐷" + , "description": "pig face" + , "category": "Animals & Nature" + , "aliases": [ + "pig" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐖" + , "description": "pig" + , "category": "Animals & Nature" + , "aliases": [ + "pig2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐗" + , "description": "boar" + , "category": "Animals & Nature" + , "aliases": [ + "boar" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐽" + , "description": "pig nose" + , "category": "Animals & Nature" + , "aliases": [ + "pig_nose" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐏" + , "description": "ram" + , "category": "Animals & Nature" + , "aliases": [ + "ram" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐑" + , "description": "ewe" + , "category": "Animals & Nature" + , "aliases": [ + "sheep" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐐" + , "description": "goat" + , "category": "Animals & Nature" + , "aliases": [ + "goat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐪" + , "description": "camel" + , "category": "Animals & Nature" + , "aliases": [ + "dromedary_camel" + ] + , "tags": [ + "desert" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐫" + , "description": "two-hump camel" + , "category": "Animals & Nature" + , "aliases": [ + "camel" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦙" + , "description": "llama" + , "category": "Animals & Nature" + , "aliases": [ + "llama" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦒" + , "description": "giraffe" + , "category": "Animals & Nature" + , "aliases": [ + "giraffe" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🐘" + , "description": "elephant" + , "category": "Animals & Nature" + , "aliases": [ + "elephant" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦏" + , "description": "rhinoceros" + , "category": "Animals & Nature" + , "aliases": [ + "rhinoceros" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🦛" + , "description": "hippopotamus" + , "category": "Animals & Nature" + , "aliases": [ + "hippopotamus" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🐭" + , "description": "mouse face" + , "category": "Animals & Nature" + , "aliases": [ + "mouse" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐁" + , "description": "mouse" + , "category": "Animals & Nature" + , "aliases": [ + "mouse2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐀" + , "description": "rat" + , "category": "Animals & Nature" + , "aliases": [ + "rat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐹" + , "description": "hamster" + , "category": "Animals & Nature" + , "aliases": [ + "hamster" + ] + , "tags": [ + "pet" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐰" + , "description": "rabbit face" + , "category": "Animals & Nature" + , "aliases": [ + "rabbit" + ] + , "tags": [ + "bunny" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐇" + , "description": "rabbit" + , "category": "Animals & Nature" + , "aliases": [ + "rabbit2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐿" + , "description": "chipmunk" + , "category": "Animals & Nature" + , "aliases": [ + "chipmunk" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🦔" + , "description": "hedgehog" + , "category": "Animals & Nature" + , "aliases": [ + "hedgehog" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦇" + , "description": "bat" + , "category": "Animals & Nature" + , "aliases": [ + "bat" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🐻" + , "description": "bear" + , "category": "Animals & Nature" + , "aliases": [ + "bear" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐨" + , "description": "koala" + , "category": "Animals & Nature" + , "aliases": [ + "koala" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐼" + , "description": "panda" + , "category": "Animals & Nature" + , "aliases": [ + "panda_face" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦥" + , "description": "sloth" + , "category": "Animals & Nature" + , "aliases": [ + "sloth" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🦦" + , "description": "otter" + , "category": "Animals & Nature" + , "aliases": [ + "otter" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🦨" + , "description": "skunk" + , "category": "Animals & Nature" + , "aliases": [ + "skunk" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🦘" + , "description": "kangaroo" + , "category": "Animals & Nature" + , "aliases": [ + "kangaroo" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦡" + , "description": "badger" + , "category": "Animals & Nature" + , "aliases": [ + "badger" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🐾" + , "description": "paw prints" + , "category": "Animals & Nature" + , "aliases": [ + "feet" + , "paw_prints" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦃" + , "description": "turkey" + , "category": "Animals & Nature" + , "aliases": [ + "turkey" + ] + , "tags": [ + "thanksgiving" + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🐔" + , "description": "chicken" + , "category": "Animals & Nature" + , "aliases": [ + "chicken" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐓" + , "description": "rooster" + , "category": "Animals & Nature" + , "aliases": [ + "rooster" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐣" + , "description": "hatching chick" + , "category": "Animals & Nature" + , "aliases": [ + "hatching_chick" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐤" + , "description": "baby chick" + , "category": "Animals & Nature" + , "aliases": [ + "baby_chick" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐥" + , "description": "front-facing baby chick" + , "category": "Animals & Nature" + , "aliases": [ + "hatched_chick" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐦" + , "description": "bird" + , "category": "Animals & Nature" + , "aliases": [ + "bird" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐧" + , "description": "penguin" + , "category": "Animals & Nature" + , "aliases": [ + "penguin" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕊" + , "description": "dove" + , "category": "Animals & Nature" + , "aliases": [ + "dove" + ] + , "tags": [ + "peace" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🦅" + , "description": "eagle" + , "category": "Animals & Nature" + , "aliases": [ + "eagle" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🦆" + , "description": "duck" + , "category": "Animals & Nature" + , "aliases": [ + "duck" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🦢" + , "description": "swan" + , "category": "Animals & Nature" + , "aliases": [ + "swan" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦉" + , "description": "owl" + , "category": "Animals & Nature" + , "aliases": [ + "owl" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🦩" + , "description": "flamingo" + , "category": "Animals & Nature" + , "aliases": [ + "flamingo" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🦚" + , "description": "peacock" + , "category": "Animals & Nature" + , "aliases": [ + "peacock" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦜" + , "description": "parrot" + , "category": "Animals & Nature" + , "aliases": [ + "parrot" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🐸" + , "description": "frog" + , "category": "Animals & Nature" + , "aliases": [ + "frog" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐊" + , "description": "crocodile" + , "category": "Animals & Nature" + , "aliases": [ + "crocodile" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐢" + , "description": "turtle" + , "category": "Animals & Nature" + , "aliases": [ + "turtle" + ] + , "tags": [ + "slow" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦎" + , "description": "lizard" + , "category": "Animals & Nature" + , "aliases": [ + "lizard" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🐍" + , "description": "snake" + , "category": "Animals & Nature" + , "aliases": [ + "snake" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐲" + , "description": "dragon face" + , "category": "Animals & Nature" + , "aliases": [ + "dragon_face" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐉" + , "description": "dragon" + , "category": "Animals & Nature" + , "aliases": [ + "dragon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦕" + , "description": "sauropod" + , "category": "Animals & Nature" + , "aliases": [ + "sauropod" + ] + , "tags": [ + "dinosaur" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦖" + , "description": "T-Rex" + , "category": "Animals & Nature" + , "aliases": [ + "t-rex" + ] + , "tags": [ + "dinosaur" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🐳" + , "description": "spouting whale" + , "category": "Animals & Nature" + , "aliases": [ + "whale" + ] + , "tags": [ + "sea" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐋" + , "description": "whale" + , "category": "Animals & Nature" + , "aliases": [ + "whale2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐬" + , "description": "dolphin" + , "category": "Animals & Nature" + , "aliases": [ + "dolphin" + , "flipper" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐟" + , "description": "fish" + , "category": "Animals & Nature" + , "aliases": [ + "fish" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐠" + , "description": "tropical fish" + , "category": "Animals & Nature" + , "aliases": [ + "tropical_fish" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐡" + , "description": "blowfish" + , "category": "Animals & Nature" + , "aliases": [ + "blowfish" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦈" + , "description": "shark" + , "category": "Animals & Nature" + , "aliases": [ + "shark" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🐙" + , "description": "octopus" + , "category": "Animals & Nature" + , "aliases": [ + "octopus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐚" + , "description": "spiral shell" + , "category": "Animals & Nature" + , "aliases": [ + "shell" + ] + , "tags": [ + "sea" + , "beach" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐌" + , "description": "snail" + , "category": "Animals & Nature" + , "aliases": [ + "snail" + ] + , "tags": [ + "slow" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦋" + , "description": "butterfly" + , "category": "Animals & Nature" + , "aliases": [ + "butterfly" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🐛" + , "description": "bug" + , "category": "Animals & Nature" + , "aliases": [ + "bug" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐜" + , "description": "ant" + , "category": "Animals & Nature" + , "aliases": [ + "ant" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐝" + , "description": "honeybee" + , "category": "Animals & Nature" + , "aliases": [ + "bee" + , "honeybee" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🐞" + , "description": "lady beetle" + , "category": "Animals & Nature" + , "aliases": [ + "beetle" + ] + , "tags": [ + "bug" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🦗" + , "description": "cricket" + , "category": "Animals & Nature" + , "aliases": [ + "cricket" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🕷" + , "description": "spider" + , "category": "Animals & Nature" + , "aliases": [ + "spider" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🕸" + , "description": "spider web" + , "category": "Animals & Nature" + , "aliases": [ + "spider_web" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🦂" + , "description": "scorpion" + , "category": "Animals & Nature" + , "aliases": [ + "scorpion" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🦟" + , "description": "mosquito" + , "category": "Animals & Nature" + , "aliases": [ + "mosquito" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦠" + , "description": "microbe" + , "category": "Animals & Nature" + , "aliases": [ + "microbe" + ] + , "tags": [ + "germ" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "💐" + , "description": "bouquet" + , "category": "Animals & Nature" + , "aliases": [ + "bouquet" + ] + , "tags": [ + "flowers" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌸" + , "description": "cherry blossom" + , "category": "Animals & Nature" + , "aliases": [ + "cherry_blossom" + ] + , "tags": [ + "flower" + , "spring" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💮" + , "description": "white flower" + , "category": "Animals & Nature" + , "aliases": [ + "white_flower" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏵" + , "description": "rosette" + , "category": "Animals & Nature" + , "aliases": [ + "rosette" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌹" + , "description": "rose" + , "category": "Animals & Nature" + , "aliases": [ + "rose" + ] + , "tags": [ + "flower" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥀" + , "description": "wilted flower" + , "category": "Animals & Nature" + , "aliases": [ + "wilted_flower" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🌺" + , "description": "hibiscus" + , "category": "Animals & Nature" + , "aliases": [ + "hibiscus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌻" + , "description": "sunflower" + , "category": "Animals & Nature" + , "aliases": [ + "sunflower" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌼" + , "description": "blossom" + , "category": "Animals & Nature" + , "aliases": [ + "blossom" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌷" + , "description": "tulip" + , "category": "Animals & Nature" + , "aliases": [ + "tulip" + ] + , "tags": [ + "flower" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌱" + , "description": "seedling" + , "category": "Animals & Nature" + , "aliases": [ + "seedling" + ] + , "tags": [ + "plant" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌲" + , "description": "evergreen tree" + , "category": "Animals & Nature" + , "aliases": [ + "evergreen_tree" + ] + , "tags": [ + "wood" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌳" + , "description": "deciduous tree" + , "category": "Animals & Nature" + , "aliases": [ + "deciduous_tree" + ] + , "tags": [ + "wood" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌴" + , "description": "palm tree" + , "category": "Animals & Nature" + , "aliases": [ + "palm_tree" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌵" + , "description": "cactus" + , "category": "Animals & Nature" + , "aliases": [ + "cactus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌾" + , "description": "sheaf of rice" + , "category": "Animals & Nature" + , "aliases": [ + "ear_of_rice" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌿" + , "description": "herb" + , "category": "Animals & Nature" + , "aliases": [ + "herb" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "☘" + , "description": "shamrock" + , "category": "Animals & Nature" + , "aliases": [ + "shamrock" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "🍀" + , "description": "four leaf clover" + , "category": "Animals & Nature" + , "aliases": [ + "four_leaf_clover" + ] + , "tags": [ + "luck" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍁" + , "description": "maple leaf" + , "category": "Animals & Nature" + , "aliases": [ + "maple_leaf" + ] + , "tags": [ + "canada" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍂" + , "description": "fallen leaf" + , "category": "Animals & Nature" + , "aliases": [ + "fallen_leaf" + ] + , "tags": [ + "autumn" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍃" + , "description": "leaf fluttering in wind" + , "category": "Animals & Nature" + , "aliases": [ + "leaves" + ] + , "tags": [ + "leaf" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍇" + , "description": "grapes" + , "category": "Food & Drink" + , "aliases": [ + "grapes" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍈" + , "description": "melon" + , "category": "Food & Drink" + , "aliases": [ + "melon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍉" + , "description": "watermelon" + , "category": "Food & Drink" + , "aliases": [ + "watermelon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍊" + , "description": "tangerine" + , "category": "Food & Drink" + , "aliases": [ + "tangerine" + , "orange" + , "mandarin" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍋" + , "description": "lemon" + , "category": "Food & Drink" + , "aliases": [ + "lemon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍌" + , "description": "banana" + , "category": "Food & Drink" + , "aliases": [ + "banana" + ] + , "tags": [ + "fruit" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍍" + , "description": "pineapple" + , "category": "Food & Drink" + , "aliases": [ + "pineapple" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥭" + , "description": "mango" + , "category": "Food & Drink" + , "aliases": [ + "mango" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🍎" + , "description": "red apple" + , "category": "Food & Drink" + , "aliases": [ + "apple" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍏" + , "description": "green apple" + , "category": "Food & Drink" + , "aliases": [ + "green_apple" + ] + , "tags": [ + "fruit" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍐" + , "description": "pear" + , "category": "Food & Drink" + , "aliases": [ + "pear" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍑" + , "description": "peach" + , "category": "Food & Drink" + , "aliases": [ + "peach" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍒" + , "description": "cherries" + , "category": "Food & Drink" + , "aliases": [ + "cherries" + ] + , "tags": [ + "fruit" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍓" + , "description": "strawberry" + , "category": "Food & Drink" + , "aliases": [ + "strawberry" + ] + , "tags": [ + "fruit" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥝" + , "description": "kiwi fruit" + , "category": "Food & Drink" + , "aliases": [ + "kiwi_fruit" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🍅" + , "description": "tomato" + , "category": "Food & Drink" + , "aliases": [ + "tomato" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥥" + , "description": "coconut" + , "category": "Food & Drink" + , "aliases": [ + "coconut" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥑" + , "description": "avocado" + , "category": "Food & Drink" + , "aliases": [ + "avocado" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🍆" + , "description": "eggplant" + , "category": "Food & Drink" + , "aliases": [ + "eggplant" + ] + , "tags": [ + "aubergine" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥔" + , "description": "potato" + , "category": "Food & Drink" + , "aliases": [ + "potato" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥕" + , "description": "carrot" + , "category": "Food & Drink" + , "aliases": [ + "carrot" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🌽" + , "description": "ear of corn" + , "category": "Food & Drink" + , "aliases": [ + "corn" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌶" + , "description": "hot pepper" + , "category": "Food & Drink" + , "aliases": [ + "hot_pepper" + ] + , "tags": [ + "spicy" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🥒" + , "description": "cucumber" + , "category": "Food & Drink" + , "aliases": [ + "cucumber" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥬" + , "description": "leafy green" + , "category": "Food & Drink" + , "aliases": [ + "leafy_green" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥦" + , "description": "broccoli" + , "category": "Food & Drink" + , "aliases": [ + "broccoli" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧄" + , "description": "garlic" + , "category": "Food & Drink" + , "aliases": [ + "garlic" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🧅" + , "description": "onion" + , "category": "Food & Drink" + , "aliases": [ + "onion" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🍄" + , "description": "mushroom" + , "category": "Food & Drink" + , "aliases": [ + "mushroom" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥜" + , "description": "peanuts" + , "category": "Food & Drink" + , "aliases": [ + "peanuts" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🌰" + , "description": "chestnut" + , "category": "Food & Drink" + , "aliases": [ + "chestnut" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍞" + , "description": "bread" + , "category": "Food & Drink" + , "aliases": [ + "bread" + ] + , "tags": [ + "toast" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥐" + , "description": "croissant" + , "category": "Food & Drink" + , "aliases": [ + "croissant" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥖" + , "description": "baguette bread" + , "category": "Food & Drink" + , "aliases": [ + "baguette_bread" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥨" + , "description": "pretzel" + , "category": "Food & Drink" + , "aliases": [ + "pretzel" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥯" + , "description": "bagel" + , "category": "Food & Drink" + , "aliases": [ + "bagel" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥞" + , "description": "pancakes" + , "category": "Food & Drink" + , "aliases": [ + "pancakes" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🧇" + , "description": "waffle" + , "category": "Food & Drink" + , "aliases": [ + "waffle" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🧀" + , "description": "cheese wedge" + , "category": "Food & Drink" + , "aliases": [ + "cheese" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🍖" + , "description": "meat on bone" + , "category": "Food & Drink" + , "aliases": [ + "meat_on_bone" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍗" + , "description": "poultry leg" + , "category": "Food & Drink" + , "aliases": [ + "poultry_leg" + ] + , "tags": [ + "meat" + , "chicken" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥩" + , "description": "cut of meat" + , "category": "Food & Drink" + , "aliases": [ + "cut_of_meat" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥓" + , "description": "bacon" + , "category": "Food & Drink" + , "aliases": [ + "bacon" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🍔" + , "description": "hamburger" + , "category": "Food & Drink" + , "aliases": [ + "hamburger" + ] + , "tags": [ + "burger" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍟" + , "description": "french fries" + , "category": "Food & Drink" + , "aliases": [ + "fries" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍕" + , "description": "pizza" + , "category": "Food & Drink" + , "aliases": [ + "pizza" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌭" + , "description": "hot dog" + , "category": "Food & Drink" + , "aliases": [ + "hotdog" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🥪" + , "description": "sandwich" + , "category": "Food & Drink" + , "aliases": [ + "sandwich" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🌮" + , "description": "taco" + , "category": "Food & Drink" + , "aliases": [ + "taco" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌯" + , "description": "burrito" + , "category": "Food & Drink" + , "aliases": [ + "burrito" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🥙" + , "description": "stuffed flatbread" + , "category": "Food & Drink" + , "aliases": [ + "stuffed_flatbread" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🧆" + , "description": "falafel" + , "category": "Food & Drink" + , "aliases": [ + "falafel" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🥚" + , "description": "egg" + , "category": "Food & Drink" + , "aliases": [ + "egg" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🍳" + , "description": "cooking" + , "category": "Food & Drink" + , "aliases": [ + "fried_egg" + ] + , "tags": [ + "breakfast" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥘" + , "description": "shallow pan of food" + , "category": "Food & Drink" + , "aliases": [ + "shallow_pan_of_food" + ] + , "tags": [ + "paella" + , "curry" + ] + , "unicode_version": "" + , "ios_version": "10.2" + } +, { + "emoji": "🍲" + , "description": "pot of food" + , "category": "Food & Drink" + , "aliases": [ + "stew" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥣" + , "description": "bowl with spoon" + , "category": "Food & Drink" + , "aliases": [ + "bowl_with_spoon" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥗" + , "description": "green salad" + , "category": "Food & Drink" + , "aliases": [ + "green_salad" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🍿" + , "description": "popcorn" + , "category": "Food & Drink" + , "aliases": [ + "popcorn" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🧈" + , "description": "butter" + , "category": "Food & Drink" + , "aliases": [ + "butter" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🧂" + , "description": "salt" + , "category": "Food & Drink" + , "aliases": [ + "salt" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥫" + , "description": "canned food" + , "category": "Food & Drink" + , "aliases": [ + "canned_food" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🍱" + , "description": "bento box" + , "category": "Food & Drink" + , "aliases": [ + "bento" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍘" + , "description": "rice cracker" + , "category": "Food & Drink" + , "aliases": [ + "rice_cracker" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍙" + , "description": "rice ball" + , "category": "Food & Drink" + , "aliases": [ + "rice_ball" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍚" + , "description": "cooked rice" + , "category": "Food & Drink" + , "aliases": [ + "rice" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍛" + , "description": "curry rice" + , "category": "Food & Drink" + , "aliases": [ + "curry" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍜" + , "description": "steaming bowl" + , "category": "Food & Drink" + , "aliases": [ + "ramen" + ] + , "tags": [ + "noodle" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍝" + , "description": "spaghetti" + , "category": "Food & Drink" + , "aliases": [ + "spaghetti" + ] + , "tags": [ + "pasta" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍠" + , "description": "roasted sweet potato" + , "category": "Food & Drink" + , "aliases": [ + "sweet_potato" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍢" + , "description": "oden" + , "category": "Food & Drink" + , "aliases": [ + "oden" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍣" + , "description": "sushi" + , "category": "Food & Drink" + , "aliases": [ + "sushi" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍤" + , "description": "fried shrimp" + , "category": "Food & Drink" + , "aliases": [ + "fried_shrimp" + ] + , "tags": [ + "tempura" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍥" + , "description": "fish cake with swirl" + , "category": "Food & Drink" + , "aliases": [ + "fish_cake" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥮" + , "description": "moon cake" + , "category": "Food & Drink" + , "aliases": [ + "moon_cake" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🍡" + , "description": "dango" + , "category": "Food & Drink" + , "aliases": [ + "dango" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥟" + , "description": "dumpling" + , "category": "Food & Drink" + , "aliases": [ + "dumpling" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥠" + , "description": "fortune cookie" + , "category": "Food & Drink" + , "aliases": [ + "fortune_cookie" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥡" + , "description": "takeout box" + , "category": "Food & Drink" + , "aliases": [ + "takeout_box" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦀" + , "description": "crab" + , "category": "Food & Drink" + , "aliases": [ + "crab" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🦞" + , "description": "lobster" + , "category": "Food & Drink" + , "aliases": [ + "lobster" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦐" + , "description": "shrimp" + , "category": "Food & Drink" + , "aliases": [ + "shrimp" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🦑" + , "description": "squid" + , "category": "Food & Drink" + , "aliases": [ + "squid" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🦪" + , "description": "oyster" + , "category": "Food & Drink" + , "aliases": [ + "oyster" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🍦" + , "description": "soft ice cream" + , "category": "Food & Drink" + , "aliases": [ + "icecream" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍧" + , "description": "shaved ice" + , "category": "Food & Drink" + , "aliases": [ + "shaved_ice" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍨" + , "description": "ice cream" + , "category": "Food & Drink" + , "aliases": [ + "ice_cream" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍩" + , "description": "doughnut" + , "category": "Food & Drink" + , "aliases": [ + "doughnut" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍪" + , "description": "cookie" + , "category": "Food & Drink" + , "aliases": [ + "cookie" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎂" + , "description": "birthday cake" + , "category": "Food & Drink" + , "aliases": [ + "birthday" + ] + , "tags": [ + "party" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍰" + , "description": "shortcake" + , "category": "Food & Drink" + , "aliases": [ + "cake" + ] + , "tags": [ + "dessert" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧁" + , "description": "cupcake" + , "category": "Food & Drink" + , "aliases": [ + "cupcake" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥧" + , "description": "pie" + , "category": "Food & Drink" + , "aliases": [ + "pie" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🍫" + , "description": "chocolate bar" + , "category": "Food & Drink" + , "aliases": [ + "chocolate_bar" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍬" + , "description": "candy" + , "category": "Food & Drink" + , "aliases": [ + "candy" + ] + , "tags": [ + "sweet" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍭" + , "description": "lollipop" + , "category": "Food & Drink" + , "aliases": [ + "lollipop" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍮" + , "description": "custard" + , "category": "Food & Drink" + , "aliases": [ + "custard" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍯" + , "description": "honey pot" + , "category": "Food & Drink" + , "aliases": [ + "honey_pot" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍼" + , "description": "baby bottle" + , "category": "Food & Drink" + , "aliases": [ + "baby_bottle" + ] + , "tags": [ + "milk" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥛" + , "description": "glass of milk" + , "category": "Food & Drink" + , "aliases": [ + "milk_glass" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "☕" + , "description": "hot beverage" + , "category": "Food & Drink" + , "aliases": [ + "coffee" + ] + , "tags": [ + "cafe" + , "espresso" + ] + , "unicode_version": "4.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍵" + , "description": "teacup without handle" + , "category": "Food & Drink" + , "aliases": [ + "tea" + ] + , "tags": [ + "green" + , "breakfast" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍶" + , "description": "sake" + , "category": "Food & Drink" + , "aliases": [ + "sake" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍾" + , "description": "bottle with popping cork" + , "category": "Food & Drink" + , "aliases": [ + "champagne" + ] + , "tags": [ + "bottle" + , "bubbly" + , "celebration" + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🍷" + , "description": "wine glass" + , "category": "Food & Drink" + , "aliases": [ + "wine_glass" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍸" + , "description": "cocktail glass" + , "category": "Food & Drink" + , "aliases": [ + "cocktail" + ] + , "tags": [ + "drink" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍹" + , "description": "tropical drink" + , "category": "Food & Drink" + , "aliases": [ + "tropical_drink" + ] + , "tags": [ + "summer" + , "vacation" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍺" + , "description": "beer mug" + , "category": "Food & Drink" + , "aliases": [ + "beer" + ] + , "tags": [ + "drink" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🍻" + , "description": "clinking beer mugs" + , "category": "Food & Drink" + , "aliases": [ + "beers" + ] + , "tags": [ + "drinks" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥂" + , "description": "clinking glasses" + , "category": "Food & Drink" + , "aliases": [ + "clinking_glasses" + ] + , "tags": [ + "cheers" + , "toast" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥃" + , "description": "tumbler glass" + , "category": "Food & Drink" + , "aliases": [ + "tumbler_glass" + ] + , "tags": [ + "whisky" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥤" + , "description": "cup with straw" + , "category": "Food & Drink" + , "aliases": [ + "cup_with_straw" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧃" + , "description": "beverage box" + , "category": "Food & Drink" + , "aliases": [ + "beverage_box" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🧉" + , "description": "mate" + , "category": "Food & Drink" + , "aliases": [ + "mate" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🧊" + , "description": "ice cube" + , "category": "Food & Drink" + , "aliases": [ + "ice_cube" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🥢" + , "description": "chopsticks" + , "category": "Food & Drink" + , "aliases": [ + "chopsticks" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🍽" + , "description": "fork and knife with plate" + , "category": "Food & Drink" + , "aliases": [ + "plate_with_cutlery" + ] + , "tags": [ + "dining" + , "dinner" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🍴" + , "description": "fork and knife" + , "category": "Food & Drink" + , "aliases": [ + "fork_and_knife" + ] + , "tags": [ + "cutlery" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥄" + , "description": "spoon" + , "category": "Food & Drink" + , "aliases": [ + "spoon" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🔪" + , "description": "kitchen knife" + , "category": "Food & Drink" + , "aliases": [ + "hocho" + , "knife" + ] + , "tags": [ + "cut" + , "chop" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏺" + , "description": "amphora" + , "category": "Food & Drink" + , "aliases": [ + "amphora" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌍" + , "description": "globe showing Europe-Africa" + , "category": "Travel & Places" + , "aliases": [ + "earth_africa" + ] + , "tags": [ + "globe" + , "world" + , "international" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌎" + , "description": "globe showing Americas" + , "category": "Travel & Places" + , "aliases": [ + "earth_americas" + ] + , "tags": [ + "globe" + , "world" + , "international" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌏" + , "description": "globe showing Asia-Australia" + , "category": "Travel & Places" + , "aliases": [ + "earth_asia" + ] + , "tags": [ + "globe" + , "world" + , "international" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌐" + , "description": "globe with meridians" + , "category": "Travel & Places" + , "aliases": [ + "globe_with_meridians" + ] + , "tags": [ + "world" + , "global" + , "international" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🗺" + , "description": "world map" + , "category": "Travel & Places" + , "aliases": [ + "world_map" + ] + , "tags": [ + "travel" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🗾" + , "description": "map of Japan" + , "category": "Travel & Places" + , "aliases": [ + "japan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧭" + , "description": "compass" + , "category": "Travel & Places" + , "aliases": [ + "compass" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🏔" + , "description": "snow-capped mountain" + , "category": "Travel & Places" + , "aliases": [ + "mountain_snow" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "⛰" + , "description": "mountain" + , "category": "Travel & Places" + , "aliases": [ + "mountain" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "🌋" + , "description": "volcano" + , "category": "Travel & Places" + , "aliases": [ + "volcano" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🗻" + , "description": "mount fuji" + , "category": "Travel & Places" + , "aliases": [ + "mount_fuji" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏕" + , "description": "camping" + , "category": "Travel & Places" + , "aliases": [ + "camping" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏖" + , "description": "beach with umbrella" + , "category": "Travel & Places" + , "aliases": [ + "beach_umbrella" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏜" + , "description": "desert" + , "category": "Travel & Places" + , "aliases": [ + "desert" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏝" + , "description": "desert island" + , "category": "Travel & Places" + , "aliases": [ + "desert_island" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏞" + , "description": "national park" + , "category": "Travel & Places" + , "aliases": [ + "national_park" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏟" + , "description": "stadium" + , "category": "Travel & Places" + , "aliases": [ + "stadium" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏛" + , "description": "classical building" + , "category": "Travel & Places" + , "aliases": [ + "classical_building" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏗" + , "description": "building construction" + , "category": "Travel & Places" + , "aliases": [ + "building_construction" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🧱" + , "description": "brick" + , "category": "Travel & Places" + , "aliases": [ + "bricks" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🏘" + , "description": "houses" + , "category": "Travel & Places" + , "aliases": [ + "houses" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏚" + , "description": "derelict house" + , "category": "Travel & Places" + , "aliases": [ + "derelict_house" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏠" + , "description": "house" + , "category": "Travel & Places" + , "aliases": [ + "house" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏡" + , "description": "house with garden" + , "category": "Travel & Places" + , "aliases": [ + "house_with_garden" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏢" + , "description": "office building" + , "category": "Travel & Places" + , "aliases": [ + "office" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏣" + , "description": "Japanese post office" + , "category": "Travel & Places" + , "aliases": [ + "post_office" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏤" + , "description": "post office" + , "category": "Travel & Places" + , "aliases": [ + "european_post_office" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏥" + , "description": "hospital" + , "category": "Travel & Places" + , "aliases": [ + "hospital" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏦" + , "description": "bank" + , "category": "Travel & Places" + , "aliases": [ + "bank" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏨" + , "description": "hotel" + , "category": "Travel & Places" + , "aliases": [ + "hotel" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏩" + , "description": "love hotel" + , "category": "Travel & Places" + , "aliases": [ + "love_hotel" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏪" + , "description": "convenience store" + , "category": "Travel & Places" + , "aliases": [ + "convenience_store" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏫" + , "description": "school" + , "category": "Travel & Places" + , "aliases": [ + "school" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏬" + , "description": "department store" + , "category": "Travel & Places" + , "aliases": [ + "department_store" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏭" + , "description": "factory" + , "category": "Travel & Places" + , "aliases": [ + "factory" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏯" + , "description": "Japanese castle" + , "category": "Travel & Places" + , "aliases": [ + "japanese_castle" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏰" + , "description": "castle" + , "category": "Travel & Places" + , "aliases": [ + "european_castle" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💒" + , "description": "wedding" + , "category": "Travel & Places" + , "aliases": [ + "wedding" + ] + , "tags": [ + "marriage" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🗼" + , "description": "Tokyo tower" + , "category": "Travel & Places" + , "aliases": [ + "tokyo_tower" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🗽" + , "description": "Statue of Liberty" + , "category": "Travel & Places" + , "aliases": [ + "statue_of_liberty" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⛪" + , "description": "church" + , "category": "Travel & Places" + , "aliases": [ + "church" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "🕌" + , "description": "mosque" + , "category": "Travel & Places" + , "aliases": [ + "mosque" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🛕" + , "description": "hindu temple" + , "category": "Travel & Places" + , "aliases": [ + "hindu_temple" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🕍" + , "description": "synagogue" + , "category": "Travel & Places" + , "aliases": [ + "synagogue" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "⛩" + , "description": "shinto shrine" + , "category": "Travel & Places" + , "aliases": [ + "shinto_shrine" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "🕋" + , "description": "kaaba" + , "category": "Travel & Places" + , "aliases": [ + "kaaba" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "⛲" + , "description": "fountain" + , "category": "Travel & Places" + , "aliases": [ + "fountain" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "⛺" + , "description": "tent" + , "category": "Travel & Places" + , "aliases": [ + "tent" + ] + , "tags": [ + "camping" + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "🌁" + , "description": "foggy" + , "category": "Travel & Places" + , "aliases": [ + "foggy" + ] + , "tags": [ + "karl" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌃" + , "description": "night with stars" + , "category": "Travel & Places" + , "aliases": [ + "night_with_stars" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏙" + , "description": "cityscape" + , "category": "Travel & Places" + , "aliases": [ + "cityscape" + ] + , "tags": [ + "skyline" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌄" + , "description": "sunrise over mountains" + , "category": "Travel & Places" + , "aliases": [ + "sunrise_over_mountains" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌅" + , "description": "sunrise" + , "category": "Travel & Places" + , "aliases": [ + "sunrise" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌆" + , "description": "cityscape at dusk" + , "category": "Travel & Places" + , "aliases": [ + "city_sunset" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌇" + , "description": "sunset" + , "category": "Travel & Places" + , "aliases": [ + "city_sunrise" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌉" + , "description": "bridge at night" + , "category": "Travel & Places" + , "aliases": [ + "bridge_at_night" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "♨️" + , "description": "hot springs" + , "category": "Travel & Places" + , "aliases": [ + "hotsprings" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🎠" + , "description": "carousel horse" + , "category": "Travel & Places" + , "aliases": [ + "carousel_horse" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎡" + , "description": "ferris wheel" + , "category": "Travel & Places" + , "aliases": [ + "ferris_wheel" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎢" + , "description": "roller coaster" + , "category": "Travel & Places" + , "aliases": [ + "roller_coaster" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💈" + , "description": "barber pole" + , "category": "Travel & Places" + , "aliases": [ + "barber" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎪" + , "description": "circus tent" + , "category": "Travel & Places" + , "aliases": [ + "circus_tent" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚂" + , "description": "locomotive" + , "category": "Travel & Places" + , "aliases": [ + "steam_locomotive" + ] + , "tags": [ + "train" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚃" + , "description": "railway car" + , "category": "Travel & Places" + , "aliases": [ + "railway_car" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚄" + , "description": "high-speed train" + , "category": "Travel & Places" + , "aliases": [ + "bullettrain_side" + ] + , "tags": [ + "train" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚅" + , "description": "bullet train" + , "category": "Travel & Places" + , "aliases": [ + "bullettrain_front" + ] + , "tags": [ + "train" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚆" + , "description": "train" + , "category": "Travel & Places" + , "aliases": [ + "train2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚇" + , "description": "metro" + , "category": "Travel & Places" + , "aliases": [ + "metro" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚈" + , "description": "light rail" + , "category": "Travel & Places" + , "aliases": [ + "light_rail" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚉" + , "description": "station" + , "category": "Travel & Places" + , "aliases": [ + "station" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚊" + , "description": "tram" + , "category": "Travel & Places" + , "aliases": [ + "tram" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚝" + , "description": "monorail" + , "category": "Travel & Places" + , "aliases": [ + "monorail" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚞" + , "description": "mountain railway" + , "category": "Travel & Places" + , "aliases": [ + "mountain_railway" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚋" + , "description": "tram car" + , "category": "Travel & Places" + , "aliases": [ + "train" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚌" + , "description": "bus" + , "category": "Travel & Places" + , "aliases": [ + "bus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚍" + , "description": "oncoming bus" + , "category": "Travel & Places" + , "aliases": [ + "oncoming_bus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚎" + , "description": "trolleybus" + , "category": "Travel & Places" + , "aliases": [ + "trolleybus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚐" + , "description": "minibus" + , "category": "Travel & Places" + , "aliases": [ + "minibus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚑" + , "description": "ambulance" + , "category": "Travel & Places" + , "aliases": [ + "ambulance" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚒" + , "description": "fire engine" + , "category": "Travel & Places" + , "aliases": [ + "fire_engine" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚓" + , "description": "police car" + , "category": "Travel & Places" + , "aliases": [ + "police_car" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚔" + , "description": "oncoming police car" + , "category": "Travel & Places" + , "aliases": [ + "oncoming_police_car" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚕" + , "description": "taxi" + , "category": "Travel & Places" + , "aliases": [ + "taxi" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚖" + , "description": "oncoming taxi" + , "category": "Travel & Places" + , "aliases": [ + "oncoming_taxi" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚗" + , "description": "automobile" + , "category": "Travel & Places" + , "aliases": [ + "car" + , "red_car" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚘" + , "description": "oncoming automobile" + , "category": "Travel & Places" + , "aliases": [ + "oncoming_automobile" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚙" + , "description": "sport utility vehicle" + , "category": "Travel & Places" + , "aliases": [ + "blue_car" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚚" + , "description": "delivery truck" + , "category": "Travel & Places" + , "aliases": [ + "truck" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚛" + , "description": "articulated lorry" + , "category": "Travel & Places" + , "aliases": [ + "articulated_lorry" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚜" + , "description": "tractor" + , "category": "Travel & Places" + , "aliases": [ + "tractor" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏎" + , "description": "racing car" + , "category": "Travel & Places" + , "aliases": [ + "racing_car" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏍" + , "description": "motorcycle" + , "category": "Travel & Places" + , "aliases": [ + "motorcycle" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🛵" + , "description": "motor scooter" + , "category": "Travel & Places" + , "aliases": [ + "motor_scooter" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🦽" + , "description": "manual wheelchair" + , "category": "Travel & Places" + , "aliases": [ + "manual_wheelchair" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🦼" + , "description": "motorized wheelchair" + , "category": "Travel & Places" + , "aliases": [ + "motorized_wheelchair" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🛺" + , "description": "auto rickshaw" + , "category": "Travel & Places" + , "aliases": [ + "auto_rickshaw" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🚲" + , "description": "bicycle" + , "category": "Travel & Places" + , "aliases": [ + "bike" + ] + , "tags": [ + "bicycle" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛴" + , "description": "kick scooter" + , "category": "Travel & Places" + , "aliases": [ + "kick_scooter" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🛹" + , "description": "skateboard" + , "category": "Travel & Places" + , "aliases": [ + "skateboard" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🚏" + , "description": "bus stop" + , "category": "Travel & Places" + , "aliases": [ + "busstop" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛣" + , "description": "motorway" + , "category": "Travel & Places" + , "aliases": [ + "motorway" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🛤" + , "description": "railway track" + , "category": "Travel & Places" + , "aliases": [ + "railway_track" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🛢" + , "description": "oil drum" + , "category": "Travel & Places" + , "aliases": [ + "oil_drum" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "⛽" + , "description": "fuel pump" + , "category": "Travel & Places" + , "aliases": [ + "fuelpump" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "🚨" + , "description": "police car light" + , "category": "Travel & Places" + , "aliases": [ + "rotating_light" + ] + , "tags": [ + "911" + , "emergency" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚥" + , "description": "horizontal traffic light" + , "category": "Travel & Places" + , "aliases": [ + "traffic_light" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚦" + , "description": "vertical traffic light" + , "category": "Travel & Places" + , "aliases": [ + "vertical_traffic_light" + ] + , "tags": [ + "semaphore" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛑" + , "description": "stop sign" + , "category": "Travel & Places" + , "aliases": [ + "stop_sign" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🚧" + , "description": "construction" + , "category": "Travel & Places" + , "aliases": [ + "construction" + ] + , "tags": [ + "wip" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⚓" + , "description": "anchor" + , "category": "Travel & Places" + , "aliases": [ + "anchor" + ] + , "tags": [ + "ship" + ] + , "unicode_version": "4.1" + , "ios_version": "6.0" + } +, { + "emoji": "⛵" + , "description": "sailboat" + , "category": "Travel & Places" + , "aliases": [ + "boat" + , "sailboat" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "🛶" + , "description": "canoe" + , "category": "Travel & Places" + , "aliases": [ + "canoe" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🚤" + , "description": "speedboat" + , "category": "Travel & Places" + , "aliases": [ + "speedboat" + ] + , "tags": [ + "ship" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛳" + , "description": "passenger ship" + , "category": "Travel & Places" + , "aliases": [ + "passenger_ship" + ] + , "tags": [ + "cruise" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "⛴" + , "description": "ferry" + , "category": "Travel & Places" + , "aliases": [ + "ferry" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "🛥" + , "description": "motor boat" + , "category": "Travel & Places" + , "aliases": [ + "motor_boat" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🚢" + , "description": "ship" + , "category": "Travel & Places" + , "aliases": [ + "ship" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "✈️" + , "description": "airplane" + , "category": "Travel & Places" + , "aliases": [ + "airplane" + ] + , "tags": [ + "flight" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🛩" + , "description": "small airplane" + , "category": "Travel & Places" + , "aliases": [ + "small_airplane" + ] + , "tags": [ + "flight" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🛫" + , "description": "airplane departure" + , "category": "Travel & Places" + , "aliases": [ + "flight_departure" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🛬" + , "description": "airplane arrival" + , "category": "Travel & Places" + , "aliases": [ + "flight_arrival" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🪂" + , "description": "parachute" + , "category": "Travel & Places" + , "aliases": [ + "parachute" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "💺" + , "description": "seat" + , "category": "Travel & Places" + , "aliases": [ + "seat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚁" + , "description": "helicopter" + , "category": "Travel & Places" + , "aliases": [ + "helicopter" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚟" + , "description": "suspension railway" + , "category": "Travel & Places" + , "aliases": [ + "suspension_railway" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚠" + , "description": "mountain cableway" + , "category": "Travel & Places" + , "aliases": [ + "mountain_cableway" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚡" + , "description": "aerial tramway" + , "category": "Travel & Places" + , "aliases": [ + "aerial_tramway" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛰" + , "description": "satellite" + , "category": "Travel & Places" + , "aliases": [ + "artificial_satellite" + ] + , "tags": [ + "orbit" + , "space" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🚀" + , "description": "rocket" + , "category": "Travel & Places" + , "aliases": [ + "rocket" + ] + , "tags": [ + "ship" + , "launch" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛸" + , "description": "flying saucer" + , "category": "Travel & Places" + , "aliases": [ + "flying_saucer" + ] + , "tags": [ + "ufo" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🛎" + , "description": "bellhop bell" + , "category": "Travel & Places" + , "aliases": [ + "bellhop_bell" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🧳" + , "description": "luggage" + , "category": "Travel & Places" + , "aliases": [ + "luggage" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "⌛" + , "description": "hourglass done" + , "category": "Travel & Places" + , "aliases": [ + "hourglass" + ] + , "tags": [ + "time" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⏳" + , "description": "hourglass not done" + , "category": "Travel & Places" + , "aliases": [ + "hourglass_flowing_sand" + ] + , "tags": [ + "time" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⌚" + , "description": "watch" + , "category": "Travel & Places" + , "aliases": [ + "watch" + ] + , "tags": [ + "time" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⏰" + , "description": "alarm clock" + , "category": "Travel & Places" + , "aliases": [ + "alarm_clock" + ] + , "tags": [ + "morning" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⏱" + , "description": "stopwatch" + , "category": "Travel & Places" + , "aliases": [ + "stopwatch" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.1" + } +, { + "emoji": "⏲" + , "description": "timer clock" + , "category": "Travel & Places" + , "aliases": [ + "timer_clock" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.1" + } +, { + "emoji": "🕰" + , "description": "mantelpiece clock" + , "category": "Travel & Places" + , "aliases": [ + "mantelpiece_clock" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🕛" + , "description": "twelve o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock12" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕧" + , "description": "twelve-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock1230" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕐" + , "description": "one o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock1" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕜" + , "description": "one-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock130" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕑" + , "description": "two o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕝" + , "description": "two-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock230" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕒" + , "description": "three o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock3" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕞" + , "description": "three-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock330" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕓" + , "description": "four o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock4" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕟" + , "description": "four-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock430" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕔" + , "description": "five o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock5" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕠" + , "description": "five-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock530" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕕" + , "description": "six o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock6" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕡" + , "description": "six-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock630" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕖" + , "description": "seven o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock7" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕢" + , "description": "seven-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock730" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕗" + , "description": "eight o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock8" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕣" + , "description": "eight-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock830" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕘" + , "description": "nine o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock9" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕤" + , "description": "nine-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock930" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕙" + , "description": "ten o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock10" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕥" + , "description": "ten-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock1030" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕚" + , "description": "eleven o’clock" + , "category": "Travel & Places" + , "aliases": [ + "clock11" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕦" + , "description": "eleven-thirty" + , "category": "Travel & Places" + , "aliases": [ + "clock1130" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌑" + , "description": "new moon" + , "category": "Travel & Places" + , "aliases": [ + "new_moon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌒" + , "description": "waxing crescent moon" + , "category": "Travel & Places" + , "aliases": [ + "waxing_crescent_moon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌓" + , "description": "first quarter moon" + , "category": "Travel & Places" + , "aliases": [ + "first_quarter_moon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌔" + , "description": "waxing gibbous moon" + , "category": "Travel & Places" + , "aliases": [ + "moon" + , "waxing_gibbous_moon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌕" + , "description": "full moon" + , "category": "Travel & Places" + , "aliases": [ + "full_moon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌖" + , "description": "waning gibbous moon" + , "category": "Travel & Places" + , "aliases": [ + "waning_gibbous_moon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌗" + , "description": "last quarter moon" + , "category": "Travel & Places" + , "aliases": [ + "last_quarter_moon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌘" + , "description": "waning crescent moon" + , "category": "Travel & Places" + , "aliases": [ + "waning_crescent_moon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌙" + , "description": "crescent moon" + , "category": "Travel & Places" + , "aliases": [ + "crescent_moon" + ] + , "tags": [ + "night" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌚" + , "description": "new moon face" + , "category": "Travel & Places" + , "aliases": [ + "new_moon_with_face" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌛" + , "description": "first quarter moon face" + , "category": "Travel & Places" + , "aliases": [ + "first_quarter_moon_with_face" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌜" + , "description": "last quarter moon face" + , "category": "Travel & Places" + , "aliases": [ + "last_quarter_moon_with_face" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌡" + , "description": "thermometer" + , "category": "Travel & Places" + , "aliases": [ + "thermometer" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "☀️" + , "description": "sun" + , "category": "Travel & Places" + , "aliases": [ + "sunny" + ] + , "tags": [ + "weather" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🌝" + , "description": "full moon face" + , "category": "Travel & Places" + , "aliases": [ + "full_moon_with_face" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌞" + , "description": "sun with face" + , "category": "Travel & Places" + , "aliases": [ + "sun_with_face" + ] + , "tags": [ + "summer" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🪐" + , "description": "ringed planet" + , "category": "Travel & Places" + , "aliases": [ + "ringed_planet" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "⭐" + , "description": "star" + , "category": "Travel & Places" + , "aliases": [ + "star" + ] + , "tags": [ + ] + , "unicode_version": "5.1" + , "ios_version": "6.0" + } +, { + "emoji": "🌟" + , "description": "glowing star" + , "category": "Travel & Places" + , "aliases": [ + "star2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌠" + , "description": "shooting star" + , "category": "Travel & Places" + , "aliases": [ + "stars" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌌" + , "description": "milky way" + , "category": "Travel & Places" + , "aliases": [ + "milky_way" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "☁️" + , "description": "cloud" + , "category": "Travel & Places" + , "aliases": [ + "cloud" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⛅" + , "description": "sun behind cloud" + , "category": "Travel & Places" + , "aliases": [ + "partly_sunny" + ] + , "tags": [ + "weather" + , "cloud" + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "⛈" + , "description": "cloud with lightning and rain" + , "category": "Travel & Places" + , "aliases": [ + "cloud_with_lightning_and_rain" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "🌤" + , "description": "sun behind small cloud" + , "category": "Travel & Places" + , "aliases": [ + "sun_behind_small_cloud" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌥" + , "description": "sun behind large cloud" + , "category": "Travel & Places" + , "aliases": [ + "sun_behind_large_cloud" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌦" + , "description": "sun behind rain cloud" + , "category": "Travel & Places" + , "aliases": [ + "sun_behind_rain_cloud" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌧" + , "description": "cloud with rain" + , "category": "Travel & Places" + , "aliases": [ + "cloud_with_rain" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌨" + , "description": "cloud with snow" + , "category": "Travel & Places" + , "aliases": [ + "cloud_with_snow" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌩" + , "description": "cloud with lightning" + , "category": "Travel & Places" + , "aliases": [ + "cloud_with_lightning" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌪" + , "description": "tornado" + , "category": "Travel & Places" + , "aliases": [ + "tornado" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌫" + , "description": "fog" + , "category": "Travel & Places" + , "aliases": [ + "fog" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌬" + , "description": "wind face" + , "category": "Travel & Places" + , "aliases": [ + "wind_face" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🌀" + , "description": "cyclone" + , "category": "Travel & Places" + , "aliases": [ + "cyclone" + ] + , "tags": [ + "swirl" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌈" + , "description": "rainbow" + , "category": "Travel & Places" + , "aliases": [ + "rainbow" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌂" + , "description": "closed umbrella" + , "category": "Travel & Places" + , "aliases": [ + "closed_umbrella" + ] + , "tags": [ + "weather" + , "rain" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "☂️" + , "description": "umbrella" + , "category": "Travel & Places" + , "aliases": [ + "open_umbrella" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "☔" + , "description": "umbrella with rain drops" + , "category": "Travel & Places" + , "aliases": [ + "umbrella" + ] + , "tags": [ + "rain" + , "weather" + ] + , "unicode_version": "4.0" + , "ios_version": "6.0" + } +, { + "emoji": "⛱" + , "description": "umbrella on ground" + , "category": "Travel & Places" + , "aliases": [ + "parasol_on_ground" + ] + , "tags": [ + "beach_umbrella" + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "⚡" + , "description": "high voltage" + , "category": "Travel & Places" + , "aliases": [ + "zap" + ] + , "tags": [ + "lightning" + , "thunder" + ] + , "unicode_version": "4.0" + , "ios_version": "6.0" + } +, { + "emoji": "❄️" + , "description": "snowflake" + , "category": "Travel & Places" + , "aliases": [ + "snowflake" + ] + , "tags": [ + "winter" + , "cold" + , "weather" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "☃️" + , "description": "snowman" + , "category": "Travel & Places" + , "aliases": [ + "snowman_with_snow" + ] + , "tags": [ + "winter" + , "christmas" + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "⛄" + , "description": "snowman without snow" + , "category": "Travel & Places" + , "aliases": [ + "snowman" + ] + , "tags": [ + "winter" + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "☄" + , "description": "comet" + , "category": "Travel & Places" + , "aliases": [ + "comet" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "🔥" + , "description": "fire" + , "category": "Travel & Places" + , "aliases": [ + "fire" + ] + , "tags": [ + "burn" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💧" + , "description": "droplet" + , "category": "Travel & Places" + , "aliases": [ + "droplet" + ] + , "tags": [ + "water" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🌊" + , "description": "water wave" + , "category": "Travel & Places" + , "aliases": [ + "ocean" + ] + , "tags": [ + "sea" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎃" + , "description": "jack-o-lantern" + , "category": "Activities" + , "aliases": [ + "jack_o_lantern" + ] + , "tags": [ + "halloween" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎄" + , "description": "Christmas tree" + , "category": "Activities" + , "aliases": [ + "christmas_tree" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎆" + , "description": "fireworks" + , "category": "Activities" + , "aliases": [ + "fireworks" + ] + , "tags": [ + "festival" + , "celebration" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎇" + , "description": "sparkler" + , "category": "Activities" + , "aliases": [ + "sparkler" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧨" + , "description": "firecracker" + , "category": "Activities" + , "aliases": [ + "firecracker" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "✨" + , "description": "sparkles" + , "category": "Activities" + , "aliases": [ + "sparkles" + ] + , "tags": [ + "shiny" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎈" + , "description": "balloon" + , "category": "Activities" + , "aliases": [ + "balloon" + ] + , "tags": [ + "party" + , "birthday" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎉" + , "description": "party popper" + , "category": "Activities" + , "aliases": [ + "tada" + ] + , "tags": [ + "hooray" + , "party" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎊" + , "description": "confetti ball" + , "category": "Activities" + , "aliases": [ + "confetti_ball" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎋" + , "description": "tanabata tree" + , "category": "Activities" + , "aliases": [ + "tanabata_tree" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎍" + , "description": "pine decoration" + , "category": "Activities" + , "aliases": [ + "bamboo" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎎" + , "description": "Japanese dolls" + , "category": "Activities" + , "aliases": [ + "dolls" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎏" + , "description": "carp streamer" + , "category": "Activities" + , "aliases": [ + "flags" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎐" + , "description": "wind chime" + , "category": "Activities" + , "aliases": [ + "wind_chime" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎑" + , "description": "moon viewing ceremony" + , "category": "Activities" + , "aliases": [ + "rice_scene" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧧" + , "description": "red envelope" + , "category": "Activities" + , "aliases": [ + "red_envelope" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🎀" + , "description": "ribbon" + , "category": "Activities" + , "aliases": [ + "ribbon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎁" + , "description": "wrapped gift" + , "category": "Activities" + , "aliases": [ + "gift" + ] + , "tags": [ + "present" + , "birthday" + , "christmas" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎗" + , "description": "reminder ribbon" + , "category": "Activities" + , "aliases": [ + "reminder_ribbon" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🎟" + , "description": "admission tickets" + , "category": "Activities" + , "aliases": [ + "tickets" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🎫" + , "description": "ticket" + , "category": "Activities" + , "aliases": [ + "ticket" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎖" + , "description": "military medal" + , "category": "Activities" + , "aliases": [ + "medal_military" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏆" + , "description": "trophy" + , "category": "Activities" + , "aliases": [ + "trophy" + ] + , "tags": [ + "award" + , "contest" + , "winner" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏅" + , "description": "sports medal" + , "category": "Activities" + , "aliases": [ + "medal_sports" + ] + , "tags": [ + "gold" + , "winner" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🥇" + , "description": "1st place medal" + , "category": "Activities" + , "aliases": [ + "1st_place_medal" + ] + , "tags": [ + "gold" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥈" + , "description": "2nd place medal" + , "category": "Activities" + , "aliases": [ + "2nd_place_medal" + ] + , "tags": [ + "silver" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥉" + , "description": "3rd place medal" + , "category": "Activities" + , "aliases": [ + "3rd_place_medal" + ] + , "tags": [ + "bronze" + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "⚽" + , "description": "soccer ball" + , "category": "Activities" + , "aliases": [ + "soccer" + ] + , "tags": [ + "sports" + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "⚾" + , "description": "baseball" + , "category": "Activities" + , "aliases": [ + "baseball" + ] + , "tags": [ + "sports" + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "🥎" + , "description": "softball" + , "category": "Activities" + , "aliases": [ + "softball" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🏀" + , "description": "basketball" + , "category": "Activities" + , "aliases": [ + "basketball" + ] + , "tags": [ + "sports" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏐" + , "description": "volleyball" + , "category": "Activities" + , "aliases": [ + "volleyball" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏈" + , "description": "american football" + , "category": "Activities" + , "aliases": [ + "football" + ] + , "tags": [ + "sports" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏉" + , "description": "rugby football" + , "category": "Activities" + , "aliases": [ + "rugby_football" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎾" + , "description": "tennis" + , "category": "Activities" + , "aliases": [ + "tennis" + ] + , "tags": [ + "sports" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥏" + , "description": "flying disc" + , "category": "Activities" + , "aliases": [ + "flying_disc" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🎳" + , "description": "bowling" + , "category": "Activities" + , "aliases": [ + "bowling" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏏" + , "description": "cricket game" + , "category": "Activities" + , "aliases": [ + "cricket_game" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏑" + , "description": "field hockey" + , "category": "Activities" + , "aliases": [ + "field_hockey" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏒" + , "description": "ice hockey" + , "category": "Activities" + , "aliases": [ + "ice_hockey" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🥍" + , "description": "lacrosse" + , "category": "Activities" + , "aliases": [ + "lacrosse" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🏓" + , "description": "ping pong" + , "category": "Activities" + , "aliases": [ + "ping_pong" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏸" + , "description": "badminton" + , "category": "Activities" + , "aliases": [ + "badminton" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🥊" + , "description": "boxing glove" + , "category": "Activities" + , "aliases": [ + "boxing_glove" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥋" + , "description": "martial arts uniform" + , "category": "Activities" + , "aliases": [ + "martial_arts_uniform" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🥅" + , "description": "goal net" + , "category": "Activities" + , "aliases": [ + "goal_net" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "⛳" + , "description": "flag in hole" + , "category": "Activities" + , "aliases": [ + "golf" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "⛸" + , "description": "ice skate" + , "category": "Activities" + , "aliases": [ + "ice_skate" + ] + , "tags": [ + "skating" + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "🎣" + , "description": "fishing pole" + , "category": "Activities" + , "aliases": [ + "fishing_pole_and_fish" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🤿" + , "description": "diving mask" + , "category": "Activities" + , "aliases": [ + "diving_mask" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🎽" + , "description": "running shirt" + , "category": "Activities" + , "aliases": [ + "running_shirt_with_sash" + ] + , "tags": [ + "marathon" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎿" + , "description": "skis" + , "category": "Activities" + , "aliases": [ + "ski" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛷" + , "description": "sled" + , "category": "Activities" + , "aliases": [ + "sled" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥌" + , "description": "curling stone" + , "category": "Activities" + , "aliases": [ + "curling_stone" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🎯" + , "description": "direct hit" + , "category": "Activities" + , "aliases": [ + "dart" + ] + , "tags": [ + "target" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🪀" + , "description": "yo-yo" + , "category": "Activities" + , "aliases": [ + "yo_yo" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🪁" + , "description": "kite" + , "category": "Activities" + , "aliases": [ + "kite" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🎱" + , "description": "pool 8 ball" + , "category": "Activities" + , "aliases": [ + "8ball" + ] + , "tags": [ + "pool" + , "billiards" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔮" + , "description": "crystal ball" + , "category": "Activities" + , "aliases": [ + "crystal_ball" + ] + , "tags": [ + "fortune" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧿" + , "description": "nazar amulet" + , "category": "Activities" + , "aliases": [ + "nazar_amulet" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🎮" + , "description": "video game" + , "category": "Activities" + , "aliases": [ + "video_game" + ] + , "tags": [ + "play" + , "controller" + , "console" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕹" + , "description": "joystick" + , "category": "Activities" + , "aliases": [ + "joystick" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🎰" + , "description": "slot machine" + , "category": "Activities" + , "aliases": [ + "slot_machine" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎲" + , "description": "game die" + , "category": "Activities" + , "aliases": [ + "game_die" + ] + , "tags": [ + "dice" + , "gambling" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧩" + , "description": "puzzle piece" + , "category": "Activities" + , "aliases": [ + "jigsaw" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧸" + , "description": "teddy bear" + , "category": "Activities" + , "aliases": [ + "teddy_bear" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "♠️" + , "description": "spade suit" + , "category": "Activities" + , "aliases": [ + "spades" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♥️" + , "description": "heart suit" + , "category": "Activities" + , "aliases": [ + "hearts" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♦️" + , "description": "diamond suit" + , "category": "Activities" + , "aliases": [ + "diamonds" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♣️" + , "description": "club suit" + , "category": "Activities" + , "aliases": [ + "clubs" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♟" + , "description": "chess pawn" + , "category": "Activities" + , "aliases": [ + "chess_pawn" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🃏" + , "description": "joker" + , "category": "Activities" + , "aliases": [ + "black_joker" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🀄" + , "description": "mahjong red dragon" + , "category": "Activities" + , "aliases": [ + "mahjong" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🎴" + , "description": "flower playing cards" + , "category": "Activities" + , "aliases": [ + "flower_playing_cards" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎭" + , "description": "performing arts" + , "category": "Activities" + , "aliases": [ + "performing_arts" + ] + , "tags": [ + "theater" + , "drama" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🖼" + , "description": "framed picture" + , "category": "Activities" + , "aliases": [ + "framed_picture" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🎨" + , "description": "artist palette" + , "category": "Activities" + , "aliases": [ + "art" + ] + , "tags": [ + "design" + , "paint" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧵" + , "description": "thread" + , "category": "Activities" + , "aliases": [ + "thread" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧶" + , "description": "yarn" + , "category": "Activities" + , "aliases": [ + "yarn" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "👓" + , "description": "glasses" + , "category": "Objects" + , "aliases": [ + "eyeglasses" + ] + , "tags": [ + "glasses" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕶" + , "description": "sunglasses" + , "category": "Objects" + , "aliases": [ + "dark_sunglasses" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🥽" + , "description": "goggles" + , "category": "Objects" + , "aliases": [ + "goggles" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥼" + , "description": "lab coat" + , "category": "Objects" + , "aliases": [ + "lab_coat" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🦺" + , "description": "safety vest" + , "category": "Objects" + , "aliases": [ + "safety_vest" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "👔" + , "description": "necktie" + , "category": "Objects" + , "aliases": [ + "necktie" + ] + , "tags": [ + "shirt" + , "formal" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👕" + , "description": "t-shirt" + , "category": "Objects" + , "aliases": [ + "shirt" + , "tshirt" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👖" + , "description": "jeans" + , "category": "Objects" + , "aliases": [ + "jeans" + ] + , "tags": [ + "pants" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧣" + , "description": "scarf" + , "category": "Objects" + , "aliases": [ + "scarf" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧤" + , "description": "gloves" + , "category": "Objects" + , "aliases": [ + "gloves" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧥" + , "description": "coat" + , "category": "Objects" + , "aliases": [ + "coat" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧦" + , "description": "socks" + , "category": "Objects" + , "aliases": [ + "socks" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "👗" + , "description": "dress" + , "category": "Objects" + , "aliases": [ + "dress" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👘" + , "description": "kimono" + , "category": "Objects" + , "aliases": [ + "kimono" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥻" + , "description": "sari" + , "category": "Objects" + , "aliases": [ + "sari" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🩱" + , "description": "one-piece swimsuit" + , "category": "Objects" + , "aliases": [ + "one_piece_swimsuit" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🩲" + , "description": "swim brief" + , "category": "Objects" + , "aliases": [ + "swim_brief" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🩳" + , "description": "shorts" + , "category": "Objects" + , "aliases": [ + "shorts" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "👙" + , "description": "bikini" + , "category": "Objects" + , "aliases": [ + "bikini" + ] + , "tags": [ + "beach" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👚" + , "description": "woman’s clothes" + , "category": "Objects" + , "aliases": [ + "womans_clothes" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👛" + , "description": "purse" + , "category": "Objects" + , "aliases": [ + "purse" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👜" + , "description": "handbag" + , "category": "Objects" + , "aliases": [ + "handbag" + ] + , "tags": [ + "bag" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👝" + , "description": "clutch bag" + , "category": "Objects" + , "aliases": [ + "pouch" + ] + , "tags": [ + "bag" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛍" + , "description": "shopping bags" + , "category": "Objects" + , "aliases": [ + "shopping" + ] + , "tags": [ + "bags" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🎒" + , "description": "backpack" + , "category": "Objects" + , "aliases": [ + "school_satchel" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👞" + , "description": "man’s shoe" + , "category": "Objects" + , "aliases": [ + "mans_shoe" + , "shoe" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👟" + , "description": "running shoe" + , "category": "Objects" + , "aliases": [ + "athletic_shoe" + ] + , "tags": [ + "sneaker" + , "sport" + , "running" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🥾" + , "description": "hiking boot" + , "category": "Objects" + , "aliases": [ + "hiking_boot" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🥿" + , "description": "flat shoe" + , "category": "Objects" + , "aliases": [ + "flat_shoe" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "👠" + , "description": "high-heeled shoe" + , "category": "Objects" + , "aliases": [ + "high_heel" + ] + , "tags": [ + "shoe" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👡" + , "description": "woman’s sandal" + , "category": "Objects" + , "aliases": [ + "sandal" + ] + , "tags": [ + "shoe" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🩰" + , "description": "ballet shoes" + , "category": "Objects" + , "aliases": [ + "ballet_shoes" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "👢" + , "description": "woman’s boot" + , "category": "Objects" + , "aliases": [ + "boot" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👑" + , "description": "crown" + , "category": "Objects" + , "aliases": [ + "crown" + ] + , "tags": [ + "king" + , "queen" + , "royal" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "👒" + , "description": "woman’s hat" + , "category": "Objects" + , "aliases": [ + "womans_hat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎩" + , "description": "top hat" + , "category": "Objects" + , "aliases": [ + "tophat" + ] + , "tags": [ + "hat" + , "classy" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎓" + , "description": "graduation cap" + , "category": "Objects" + , "aliases": [ + "mortar_board" + ] + , "tags": [ + "education" + , "college" + , "university" + , "graduation" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧢" + , "description": "billed cap" + , "category": "Objects" + , "aliases": [ + "billed_cap" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "⛑" + , "description": "rescue worker’s helmet" + , "category": "Objects" + , "aliases": [ + "rescue_worker_helmet" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "📿" + , "description": "prayer beads" + , "category": "Objects" + , "aliases": [ + "prayer_beads" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "💄" + , "description": "lipstick" + , "category": "Objects" + , "aliases": [ + "lipstick" + ] + , "tags": [ + "makeup" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💍" + , "description": "ring" + , "category": "Objects" + , "aliases": [ + "ring" + ] + , "tags": [ + "wedding" + , "marriage" + , "engaged" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💎" + , "description": "gem stone" + , "category": "Objects" + , "aliases": [ + "gem" + ] + , "tags": [ + "diamond" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔇" + , "description": "muted speaker" + , "category": "Objects" + , "aliases": [ + "mute" + ] + , "tags": [ + "sound" + , "volume" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔈" + , "description": "speaker low volume" + , "category": "Objects" + , "aliases": [ + "speaker" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔉" + , "description": "speaker medium volume" + , "category": "Objects" + , "aliases": [ + "sound" + ] + , "tags": [ + "volume" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔊" + , "description": "speaker high volume" + , "category": "Objects" + , "aliases": [ + "loud_sound" + ] + , "tags": [ + "volume" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📢" + , "description": "loudspeaker" + , "category": "Objects" + , "aliases": [ + "loudspeaker" + ] + , "tags": [ + "announcement" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📣" + , "description": "megaphone" + , "category": "Objects" + , "aliases": [ + "mega" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📯" + , "description": "postal horn" + , "category": "Objects" + , "aliases": [ + "postal_horn" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔔" + , "description": "bell" + , "category": "Objects" + , "aliases": [ + "bell" + ] + , "tags": [ + "sound" + , "notification" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔕" + , "description": "bell with slash" + , "category": "Objects" + , "aliases": [ + "no_bell" + ] + , "tags": [ + "volume" + , "off" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎼" + , "description": "musical score" + , "category": "Objects" + , "aliases": [ + "musical_score" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎵" + , "description": "musical note" + , "category": "Objects" + , "aliases": [ + "musical_note" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎶" + , "description": "musical notes" + , "category": "Objects" + , "aliases": [ + "notes" + ] + , "tags": [ + "music" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎙" + , "description": "studio microphone" + , "category": "Objects" + , "aliases": [ + "studio_microphone" + ] + , "tags": [ + "podcast" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🎚" + , "description": "level slider" + , "category": "Objects" + , "aliases": [ + "level_slider" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🎛" + , "description": "control knobs" + , "category": "Objects" + , "aliases": [ + "control_knobs" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🎤" + , "description": "microphone" + , "category": "Objects" + , "aliases": [ + "microphone" + ] + , "tags": [ + "sing" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎧" + , "description": "headphone" + , "category": "Objects" + , "aliases": [ + "headphones" + ] + , "tags": [ + "music" + , "earphones" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📻" + , "description": "radio" + , "category": "Objects" + , "aliases": [ + "radio" + ] + , "tags": [ + "podcast" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎷" + , "description": "saxophone" + , "category": "Objects" + , "aliases": [ + "saxophone" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎸" + , "description": "guitar" + , "category": "Objects" + , "aliases": [ + "guitar" + ] + , "tags": [ + "rock" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎹" + , "description": "musical keyboard" + , "category": "Objects" + , "aliases": [ + "musical_keyboard" + ] + , "tags": [ + "piano" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎺" + , "description": "trumpet" + , "category": "Objects" + , "aliases": [ + "trumpet" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎻" + , "description": "violin" + , "category": "Objects" + , "aliases": [ + "violin" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🪕" + , "description": "banjo" + , "category": "Objects" + , "aliases": [ + "banjo" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🥁" + , "description": "drum" + , "category": "Objects" + , "aliases": [ + "drum" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "10.2" + } +, { + "emoji": "📱" + , "description": "mobile phone" + , "category": "Objects" + , "aliases": [ + "iphone" + ] + , "tags": [ + "smartphone" + , "mobile" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📲" + , "description": "mobile phone with arrow" + , "category": "Objects" + , "aliases": [ + "calling" + ] + , "tags": [ + "call" + , "incoming" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "☎️" + , "description": "telephone" + , "category": "Objects" + , "aliases": [ + "phone" + , "telephone" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "📞" + , "description": "telephone receiver" + , "category": "Objects" + , "aliases": [ + "telephone_receiver" + ] + , "tags": [ + "phone" + , "call" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📟" + , "description": "pager" + , "category": "Objects" + , "aliases": [ + "pager" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📠" + , "description": "fax machine" + , "category": "Objects" + , "aliases": [ + "fax" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔋" + , "description": "battery" + , "category": "Objects" + , "aliases": [ + "battery" + ] + , "tags": [ + "power" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔌" + , "description": "electric plug" + , "category": "Objects" + , "aliases": [ + "electric_plug" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💻" + , "description": "laptop computer" + , "category": "Objects" + , "aliases": [ + "computer" + ] + , "tags": [ + "desktop" + , "screen" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🖥" + , "description": "desktop computer" + , "category": "Objects" + , "aliases": [ + "desktop_computer" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🖨" + , "description": "printer" + , "category": "Objects" + , "aliases": [ + "printer" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "⌨" + , "description": "keyboard" + , "category": "Objects" + , "aliases": [ + "keyboard" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "🖱" + , "description": "computer mouse" + , "category": "Objects" + , "aliases": [ + "computer_mouse" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🖲" + , "description": "trackball" + , "category": "Objects" + , "aliases": [ + "trackball" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "💽" + , "description": "computer disk" + , "category": "Objects" + , "aliases": [ + "minidisc" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💾" + , "description": "floppy disk" + , "category": "Objects" + , "aliases": [ + "floppy_disk" + ] + , "tags": [ + "save" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💿" + , "description": "optical disk" + , "category": "Objects" + , "aliases": [ + "cd" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📀" + , "description": "dvd" + , "category": "Objects" + , "aliases": [ + "dvd" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧮" + , "description": "abacus" + , "category": "Objects" + , "aliases": [ + "abacus" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🎥" + , "description": "movie camera" + , "category": "Objects" + , "aliases": [ + "movie_camera" + ] + , "tags": [ + "film" + , "video" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎞" + , "description": "film frames" + , "category": "Objects" + , "aliases": [ + "film_strip" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "📽" + , "description": "film projector" + , "category": "Objects" + , "aliases": [ + "film_projector" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🎬" + , "description": "clapper board" + , "category": "Objects" + , "aliases": [ + "clapper" + ] + , "tags": [ + "film" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📺" + , "description": "television" + , "category": "Objects" + , "aliases": [ + "tv" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📷" + , "description": "camera" + , "category": "Objects" + , "aliases": [ + "camera" + ] + , "tags": [ + "photo" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📸" + , "description": "camera with flash" + , "category": "Objects" + , "aliases": [ + "camera_flash" + ] + , "tags": [ + "photo" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "📹" + , "description": "video camera" + , "category": "Objects" + , "aliases": [ + "video_camera" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📼" + , "description": "videocassette" + , "category": "Objects" + , "aliases": [ + "vhs" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔍" + , "description": "magnifying glass tilted left" + , "category": "Objects" + , "aliases": [ + "mag" + ] + , "tags": [ + "search" + , "zoom" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔎" + , "description": "magnifying glass tilted right" + , "category": "Objects" + , "aliases": [ + "mag_right" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🕯" + , "description": "candle" + , "category": "Objects" + , "aliases": [ + "candle" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "💡" + , "description": "light bulb" + , "category": "Objects" + , "aliases": [ + "bulb" + ] + , "tags": [ + "idea" + , "light" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔦" + , "description": "flashlight" + , "category": "Objects" + , "aliases": [ + "flashlight" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏮" + , "description": "red paper lantern" + , "category": "Objects" + , "aliases": [ + "izakaya_lantern" + , "lantern" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🪔" + , "description": "diya lamp" + , "category": "Objects" + , "aliases": [ + "diya_lamp" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "📔" + , "description": "notebook with decorative cover" + , "category": "Objects" + , "aliases": [ + "notebook_with_decorative_cover" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📕" + , "description": "closed book" + , "category": "Objects" + , "aliases": [ + "closed_book" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📖" + , "description": "open book" + , "category": "Objects" + , "aliases": [ + "book" + , "open_book" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📗" + , "description": "green book" + , "category": "Objects" + , "aliases": [ + "green_book" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📘" + , "description": "blue book" + , "category": "Objects" + , "aliases": [ + "blue_book" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📙" + , "description": "orange book" + , "category": "Objects" + , "aliases": [ + "orange_book" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📚" + , "description": "books" + , "category": "Objects" + , "aliases": [ + "books" + ] + , "tags": [ + "library" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📓" + , "description": "notebook" + , "category": "Objects" + , "aliases": [ + "notebook" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📒" + , "description": "ledger" + , "category": "Objects" + , "aliases": [ + "ledger" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📃" + , "description": "page with curl" + , "category": "Objects" + , "aliases": [ + "page_with_curl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📜" + , "description": "scroll" + , "category": "Objects" + , "aliases": [ + "scroll" + ] + , "tags": [ + "document" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📄" + , "description": "page facing up" + , "category": "Objects" + , "aliases": [ + "page_facing_up" + ] + , "tags": [ + "document" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📰" + , "description": "newspaper" + , "category": "Objects" + , "aliases": [ + "newspaper" + ] + , "tags": [ + "press" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🗞" + , "description": "rolled-up newspaper" + , "category": "Objects" + , "aliases": [ + "newspaper_roll" + ] + , "tags": [ + "press" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "📑" + , "description": "bookmark tabs" + , "category": "Objects" + , "aliases": [ + "bookmark_tabs" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔖" + , "description": "bookmark" + , "category": "Objects" + , "aliases": [ + "bookmark" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏷" + , "description": "label" + , "category": "Objects" + , "aliases": [ + "label" + ] + , "tags": [ + "tag" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "💰" + , "description": "money bag" + , "category": "Objects" + , "aliases": [ + "moneybag" + ] + , "tags": [ + "dollar" + , "cream" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💴" + , "description": "yen banknote" + , "category": "Objects" + , "aliases": [ + "yen" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💵" + , "description": "dollar banknote" + , "category": "Objects" + , "aliases": [ + "dollar" + ] + , "tags": [ + "money" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💶" + , "description": "euro banknote" + , "category": "Objects" + , "aliases": [ + "euro" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💷" + , "description": "pound banknote" + , "category": "Objects" + , "aliases": [ + "pound" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💸" + , "description": "money with wings" + , "category": "Objects" + , "aliases": [ + "money_with_wings" + ] + , "tags": [ + "dollar" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💳" + , "description": "credit card" + , "category": "Objects" + , "aliases": [ + "credit_card" + ] + , "tags": [ + "subscription" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🧾" + , "description": "receipt" + , "category": "Objects" + , "aliases": [ + "receipt" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "💹" + , "description": "chart increasing with yen" + , "category": "Objects" + , "aliases": [ + "chart" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💱" + , "description": "currency exchange" + , "category": "Objects" + , "aliases": [ + "currency_exchange" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💲" + , "description": "heavy dollar sign" + , "category": "Objects" + , "aliases": [ + "heavy_dollar_sign" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "✉️" + , "description": "envelope" + , "category": "Objects" + , "aliases": [ + "email" + , "envelope" + ] + , "tags": [ + "letter" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "📧" + , "description": "e-mail" + , "category": "Objects" + , "aliases": [ + "e-mail" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📨" + , "description": "incoming envelope" + , "category": "Objects" + , "aliases": [ + "incoming_envelope" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📩" + , "description": "envelope with arrow" + , "category": "Objects" + , "aliases": [ + "envelope_with_arrow" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📤" + , "description": "outbox tray" + , "category": "Objects" + , "aliases": [ + "outbox_tray" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📥" + , "description": "inbox tray" + , "category": "Objects" + , "aliases": [ + "inbox_tray" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📦" + , "description": "package" + , "category": "Objects" + , "aliases": [ + "package" + ] + , "tags": [ + "shipping" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📫" + , "description": "closed mailbox with raised flag" + , "category": "Objects" + , "aliases": [ + "mailbox" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📪" + , "description": "closed mailbox with lowered flag" + , "category": "Objects" + , "aliases": [ + "mailbox_closed" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📬" + , "description": "open mailbox with raised flag" + , "category": "Objects" + , "aliases": [ + "mailbox_with_mail" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📭" + , "description": "open mailbox with lowered flag" + , "category": "Objects" + , "aliases": [ + "mailbox_with_no_mail" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📮" + , "description": "postbox" + , "category": "Objects" + , "aliases": [ + "postbox" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🗳" + , "description": "ballot box with ballot" + , "category": "Objects" + , "aliases": [ + "ballot_box" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "✏️" + , "description": "pencil" + , "category": "Objects" + , "aliases": [ + "pencil2" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "✒️" + , "description": "black nib" + , "category": "Objects" + , "aliases": [ + "black_nib" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🖋" + , "description": "fountain pen" + , "category": "Objects" + , "aliases": [ + "fountain_pen" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🖊" + , "description": "pen" + , "category": "Objects" + , "aliases": [ + "pen" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🖌" + , "description": "paintbrush" + , "category": "Objects" + , "aliases": [ + "paintbrush" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🖍" + , "description": "crayon" + , "category": "Objects" + , "aliases": [ + "crayon" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "📝" + , "description": "memo" + , "category": "Objects" + , "aliases": [ + "memo" + , "pencil" + ] + , "tags": [ + "document" + , "note" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💼" + , "description": "briefcase" + , "category": "Objects" + , "aliases": [ + "briefcase" + ] + , "tags": [ + "business" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📁" + , "description": "file folder" + , "category": "Objects" + , "aliases": [ + "file_folder" + ] + , "tags": [ + "directory" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📂" + , "description": "open file folder" + , "category": "Objects" + , "aliases": [ + "open_file_folder" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🗂" + , "description": "card index dividers" + , "category": "Objects" + , "aliases": [ + "card_index_dividers" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "📅" + , "description": "calendar" + , "category": "Objects" + , "aliases": [ + "date" + ] + , "tags": [ + "calendar" + , "schedule" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📆" + , "description": "tear-off calendar" + , "category": "Objects" + , "aliases": [ + "calendar" + ] + , "tags": [ + "schedule" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🗒" + , "description": "spiral notepad" + , "category": "Objects" + , "aliases": [ + "spiral_notepad" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🗓" + , "description": "spiral calendar" + , "category": "Objects" + , "aliases": [ + "spiral_calendar" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "📇" + , "description": "card index" + , "category": "Objects" + , "aliases": [ + "card_index" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📈" + , "description": "chart increasing" + , "category": "Objects" + , "aliases": [ + "chart_with_upwards_trend" + ] + , "tags": [ + "graph" + , "metrics" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📉" + , "description": "chart decreasing" + , "category": "Objects" + , "aliases": [ + "chart_with_downwards_trend" + ] + , "tags": [ + "graph" + , "metrics" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📊" + , "description": "bar chart" + , "category": "Objects" + , "aliases": [ + "bar_chart" + ] + , "tags": [ + "stats" + , "metrics" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📋" + , "description": "clipboard" + , "category": "Objects" + , "aliases": [ + "clipboard" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📌" + , "description": "pushpin" + , "category": "Objects" + , "aliases": [ + "pushpin" + ] + , "tags": [ + "location" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📍" + , "description": "round pushpin" + , "category": "Objects" + , "aliases": [ + "round_pushpin" + ] + , "tags": [ + "location" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📎" + , "description": "paperclip" + , "category": "Objects" + , "aliases": [ + "paperclip" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🖇" + , "description": "linked paperclips" + , "category": "Objects" + , "aliases": [ + "paperclips" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "📏" + , "description": "straight ruler" + , "category": "Objects" + , "aliases": [ + "straight_ruler" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📐" + , "description": "triangular ruler" + , "category": "Objects" + , "aliases": [ + "triangular_ruler" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "✂️" + , "description": "scissors" + , "category": "Objects" + , "aliases": [ + "scissors" + ] + , "tags": [ + "cut" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🗃" + , "description": "card file box" + , "category": "Objects" + , "aliases": [ + "card_file_box" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🗄" + , "description": "file cabinet" + , "category": "Objects" + , "aliases": [ + "file_cabinet" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🗑" + , "description": "wastebasket" + , "category": "Objects" + , "aliases": [ + "wastebasket" + ] + , "tags": [ + "trash" + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🔒" + , "description": "locked" + , "category": "Objects" + , "aliases": [ + "lock" + ] + , "tags": [ + "security" + , "private" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔓" + , "description": "unlocked" + , "category": "Objects" + , "aliases": [ + "unlock" + ] + , "tags": [ + "security" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔏" + , "description": "locked with pen" + , "category": "Objects" + , "aliases": [ + "lock_with_ink_pen" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔐" + , "description": "locked with key" + , "category": "Objects" + , "aliases": [ + "closed_lock_with_key" + ] + , "tags": [ + "security" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔑" + , "description": "key" + , "category": "Objects" + , "aliases": [ + "key" + ] + , "tags": [ + "lock" + , "password" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🗝" + , "description": "old key" + , "category": "Objects" + , "aliases": [ + "old_key" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🔨" + , "description": "hammer" + , "category": "Objects" + , "aliases": [ + "hammer" + ] + , "tags": [ + "tool" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🪓" + , "description": "axe" + , "category": "Objects" + , "aliases": [ + "axe" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "⛏" + , "description": "pick" + , "category": "Objects" + , "aliases": [ + "pick" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "⚒" + , "description": "hammer and pick" + , "category": "Objects" + , "aliases": [ + "hammer_and_pick" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "🛠" + , "description": "hammer and wrench" + , "category": "Objects" + , "aliases": [ + "hammer_and_wrench" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🗡" + , "description": "dagger" + , "category": "Objects" + , "aliases": [ + "dagger" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "⚔" + , "description": "crossed swords" + , "category": "Objects" + , "aliases": [ + "crossed_swords" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "🔫" + , "description": "pistol" + , "category": "Objects" + , "aliases": [ + "gun" + ] + , "tags": [ + "shoot" + , "weapon" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏹" + , "description": "bow and arrow" + , "category": "Objects" + , "aliases": [ + "bow_and_arrow" + ] + , "tags": [ + "archery" + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🛡" + , "description": "shield" + , "category": "Objects" + , "aliases": [ + "shield" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🔧" + , "description": "wrench" + , "category": "Objects" + , "aliases": [ + "wrench" + ] + , "tags": [ + "tool" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔩" + , "description": "nut and bolt" + , "category": "Objects" + , "aliases": [ + "nut_and_bolt" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⚙" + , "description": "gear" + , "category": "Objects" + , "aliases": [ + "gear" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "🗜" + , "description": "clamp" + , "category": "Objects" + , "aliases": [ + "clamp" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "⚖" + , "description": "balance scale" + , "category": "Objects" + , "aliases": [ + "balance_scale" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "🦯" + , "description": "probing cane" + , "category": "Objects" + , "aliases": [ + "probing_cane" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🔗" + , "description": "link" + , "category": "Objects" + , "aliases": [ + "link" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⛓" + , "description": "chains" + , "category": "Objects" + , "aliases": [ + "chains" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "9.1" + } +, { + "emoji": "🧰" + , "description": "toolbox" + , "category": "Objects" + , "aliases": [ + "toolbox" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧲" + , "description": "magnet" + , "category": "Objects" + , "aliases": [ + "magnet" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "⚗" + , "description": "alembic" + , "category": "Objects" + , "aliases": [ + "alembic" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "🧪" + , "description": "test tube" + , "category": "Objects" + , "aliases": [ + "test_tube" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧫" + , "description": "petri dish" + , "category": "Objects" + , "aliases": [ + "petri_dish" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧬" + , "description": "dna" + , "category": "Objects" + , "aliases": [ + "dna" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🔬" + , "description": "microscope" + , "category": "Objects" + , "aliases": [ + "microscope" + ] + , "tags": [ + "science" + , "laboratory" + , "investigate" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔭" + , "description": "telescope" + , "category": "Objects" + , "aliases": [ + "telescope" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📡" + , "description": "satellite antenna" + , "category": "Objects" + , "aliases": [ + "satellite" + ] + , "tags": [ + "signal" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💉" + , "description": "syringe" + , "category": "Objects" + , "aliases": [ + "syringe" + ] + , "tags": [ + "health" + , "hospital" + , "needle" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🩸" + , "description": "drop of blood" + , "category": "Objects" + , "aliases": [ + "drop_of_blood" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "💊" + , "description": "pill" + , "category": "Objects" + , "aliases": [ + "pill" + ] + , "tags": [ + "health" + , "medicine" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🩹" + , "description": "adhesive bandage" + , "category": "Objects" + , "aliases": [ + "adhesive_bandage" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🩺" + , "description": "stethoscope" + , "category": "Objects" + , "aliases": [ + "stethoscope" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🚪" + , "description": "door" + , "category": "Objects" + , "aliases": [ + "door" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛏" + , "description": "bed" + , "category": "Objects" + , "aliases": [ + "bed" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🛋" + , "description": "couch and lamp" + , "category": "Objects" + , "aliases": [ + "couch_and_lamp" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🪑" + , "description": "chair" + , "category": "Objects" + , "aliases": [ + "chair" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🚽" + , "description": "toilet" + , "category": "Objects" + , "aliases": [ + "toilet" + ] + , "tags": [ + "wc" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚿" + , "description": "shower" + , "category": "Objects" + , "aliases": [ + "shower" + ] + , "tags": [ + "bath" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛁" + , "description": "bathtub" + , "category": "Objects" + , "aliases": [ + "bathtub" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🪒" + , "description": "razor" + , "category": "Objects" + , "aliases": [ + "razor" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🧴" + , "description": "lotion bottle" + , "category": "Objects" + , "aliases": [ + "lotion_bottle" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧷" + , "description": "safety pin" + , "category": "Objects" + , "aliases": [ + "safety_pin" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧹" + , "description": "broom" + , "category": "Objects" + , "aliases": [ + "broom" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧺" + , "description": "basket" + , "category": "Objects" + , "aliases": [ + "basket" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧻" + , "description": "roll of paper" + , "category": "Objects" + , "aliases": [ + "roll_of_paper" + ] + , "tags": [ + "toilet" + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧼" + , "description": "soap" + , "category": "Objects" + , "aliases": [ + "soap" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧽" + , "description": "sponge" + , "category": "Objects" + , "aliases": [ + "sponge" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🧯" + , "description": "fire extinguisher" + , "category": "Objects" + , "aliases": [ + "fire_extinguisher" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🛒" + , "description": "shopping cart" + , "category": "Objects" + , "aliases": [ + "shopping_cart" + ] + , "tags": [ + ] + , "unicode_version": "9.0" + , "ios_version": "10.2" + } +, { + "emoji": "🚬" + , "description": "cigarette" + , "category": "Objects" + , "aliases": [ + "smoking" + ] + , "tags": [ + "cigarette" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⚰" + , "description": "coffin" + , "category": "Objects" + , "aliases": [ + "coffin" + ] + , "tags": [ + "funeral" + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "⚱" + , "description": "funeral urn" + , "category": "Objects" + , "aliases": [ + "funeral_urn" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "🗿" + , "description": "moai" + , "category": "Objects" + , "aliases": [ + "moyai" + ] + , "tags": [ + "stone" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏧" + , "description": "ATM sign" + , "category": "Symbols" + , "aliases": [ + "atm" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚮" + , "description": "litter in bin sign" + , "category": "Symbols" + , "aliases": [ + "put_litter_in_its_place" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚰" + , "description": "potable water" + , "category": "Symbols" + , "aliases": [ + "potable_water" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "♿" + , "description": "wheelchair symbol" + , "category": "Symbols" + , "aliases": [ + "wheelchair" + ] + , "tags": [ + "accessibility" + ] + , "unicode_version": "4.1" + , "ios_version": "6.0" + } +, { + "emoji": "🚹" + , "description": "men’s room" + , "category": "Symbols" + , "aliases": [ + "mens" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚺" + , "description": "women’s room" + , "category": "Symbols" + , "aliases": [ + "womens" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚻" + , "description": "restroom" + , "category": "Symbols" + , "aliases": [ + "restroom" + ] + , "tags": [ + "toilet" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚼" + , "description": "baby symbol" + , "category": "Symbols" + , "aliases": [ + "baby_symbol" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚾" + , "description": "water closet" + , "category": "Symbols" + , "aliases": [ + "wc" + ] + , "tags": [ + "toilet" + , "restroom" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛂" + , "description": "passport control" + , "category": "Symbols" + , "aliases": [ + "passport_control" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛃" + , "description": "customs" + , "category": "Symbols" + , "aliases": [ + "customs" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛄" + , "description": "baggage claim" + , "category": "Symbols" + , "aliases": [ + "baggage_claim" + ] + , "tags": [ + "airport" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛅" + , "description": "left luggage" + , "category": "Symbols" + , "aliases": [ + "left_luggage" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⚠️" + , "description": "warning" + , "category": "Symbols" + , "aliases": [ + "warning" + ] + , "tags": [ + "wip" + ] + , "unicode_version": "4.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚸" + , "description": "children crossing" + , "category": "Symbols" + , "aliases": [ + "children_crossing" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⛔" + , "description": "no entry" + , "category": "Symbols" + , "aliases": [ + "no_entry" + ] + , "tags": [ + "limit" + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "🚫" + , "description": "prohibited" + , "category": "Symbols" + , "aliases": [ + "no_entry_sign" + ] + , "tags": [ + "block" + , "forbidden" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚳" + , "description": "no bicycles" + , "category": "Symbols" + , "aliases": [ + "no_bicycles" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚭" + , "description": "no smoking" + , "category": "Symbols" + , "aliases": [ + "no_smoking" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚯" + , "description": "no littering" + , "category": "Symbols" + , "aliases": [ + "do_not_litter" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚱" + , "description": "non-potable water" + , "category": "Symbols" + , "aliases": [ + "non-potable_water" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚷" + , "description": "no pedestrians" + , "category": "Symbols" + , "aliases": [ + "no_pedestrians" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📵" + , "description": "no mobile phones" + , "category": "Symbols" + , "aliases": [ + "no_mobile_phones" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔞" + , "description": "no one under eighteen" + , "category": "Symbols" + , "aliases": [ + "underage" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "☢" + , "description": "radioactive" + , "category": "Symbols" + , "aliases": [ + "radioactive" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "☣" + , "description": "biohazard" + , "category": "Symbols" + , "aliases": [ + "biohazard" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "⬆️" + , "description": "up arrow" + , "category": "Symbols" + , "aliases": [ + "arrow_up" + ] + , "tags": [ + ] + , "unicode_version": "4.0" + , "ios_version": "6.0" + } +, { + "emoji": "↗️" + , "description": "up-right arrow" + , "category": "Symbols" + , "aliases": [ + "arrow_upper_right" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "➡️" + , "description": "right arrow" + , "category": "Symbols" + , "aliases": [ + "arrow_right" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "↘️" + , "description": "down-right arrow" + , "category": "Symbols" + , "aliases": [ + "arrow_lower_right" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⬇️" + , "description": "down arrow" + , "category": "Symbols" + , "aliases": [ + "arrow_down" + ] + , "tags": [ + ] + , "unicode_version": "4.0" + , "ios_version": "6.0" + } +, { + "emoji": "↙️" + , "description": "down-left arrow" + , "category": "Symbols" + , "aliases": [ + "arrow_lower_left" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⬅️" + , "description": "left arrow" + , "category": "Symbols" + , "aliases": [ + "arrow_left" + ] + , "tags": [ + ] + , "unicode_version": "4.0" + , "ios_version": "6.0" + } +, { + "emoji": "↖️" + , "description": "up-left arrow" + , "category": "Symbols" + , "aliases": [ + "arrow_upper_left" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "↕️" + , "description": "up-down arrow" + , "category": "Symbols" + , "aliases": [ + "arrow_up_down" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "↔️" + , "description": "left-right arrow" + , "category": "Symbols" + , "aliases": [ + "left_right_arrow" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "↩️" + , "description": "right arrow curving left" + , "category": "Symbols" + , "aliases": [ + "leftwards_arrow_with_hook" + ] + , "tags": [ + "return" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "↪️" + , "description": "left arrow curving right" + , "category": "Symbols" + , "aliases": [ + "arrow_right_hook" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⤴️" + , "description": "right arrow curving up" + , "category": "Symbols" + , "aliases": [ + "arrow_heading_up" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⤵️" + , "description": "right arrow curving down" + , "category": "Symbols" + , "aliases": [ + "arrow_heading_down" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🔃" + , "description": "clockwise vertical arrows" + , "category": "Symbols" + , "aliases": [ + "arrows_clockwise" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔄" + , "description": "counterclockwise arrows button" + , "category": "Symbols" + , "aliases": [ + "arrows_counterclockwise" + ] + , "tags": [ + "sync" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔙" + , "description": "BACK arrow" + , "category": "Symbols" + , "aliases": [ + "back" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔚" + , "description": "END arrow" + , "category": "Symbols" + , "aliases": [ + "end" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔛" + , "description": "ON! arrow" + , "category": "Symbols" + , "aliases": [ + "on" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔜" + , "description": "SOON arrow" + , "category": "Symbols" + , "aliases": [ + "soon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔝" + , "description": "TOP arrow" + , "category": "Symbols" + , "aliases": [ + "top" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🛐" + , "description": "place of worship" + , "category": "Symbols" + , "aliases": [ + "place_of_worship" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "⚛" + , "description": "atom symbol" + , "category": "Symbols" + , "aliases": [ + "atom_symbol" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "🕉" + , "description": "om" + , "category": "Symbols" + , "aliases": [ + "om" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "✡️" + , "description": "star of David" + , "category": "Symbols" + , "aliases": [ + "star_of_david" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "☸" + , "description": "wheel of dharma" + , "category": "Symbols" + , "aliases": [ + "wheel_of_dharma" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "☯️" + , "description": "yin yang" + , "category": "Symbols" + , "aliases": [ + "yin_yang" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "✝️" + , "description": "latin cross" + , "category": "Symbols" + , "aliases": [ + "latin_cross" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "☦" + , "description": "orthodox cross" + , "category": "Symbols" + , "aliases": [ + "orthodox_cross" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "☪" + , "description": "star and crescent" + , "category": "Symbols" + , "aliases": [ + "star_and_crescent" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "☮" + , "description": "peace symbol" + , "category": "Symbols" + , "aliases": [ + "peace_symbol" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "🕎" + , "description": "menorah" + , "category": "Symbols" + , "aliases": [ + "menorah" + ] + , "tags": [ + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🔯" + , "description": "dotted six-pointed star" + , "category": "Symbols" + , "aliases": [ + "six_pointed_star" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "♈" + , "description": "Aries" + , "category": "Symbols" + , "aliases": [ + "aries" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♉" + , "description": "Taurus" + , "category": "Symbols" + , "aliases": [ + "taurus" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♊" + , "description": "Gemini" + , "category": "Symbols" + , "aliases": [ + "gemini" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♋" + , "description": "Cancer" + , "category": "Symbols" + , "aliases": [ + "cancer" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♌" + , "description": "Leo" + , "category": "Symbols" + , "aliases": [ + "leo" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♍" + , "description": "Virgo" + , "category": "Symbols" + , "aliases": [ + "virgo" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♎" + , "description": "Libra" + , "category": "Symbols" + , "aliases": [ + "libra" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♏" + , "description": "Scorpio" + , "category": "Symbols" + , "aliases": [ + "scorpius" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♐" + , "description": "Sagittarius" + , "category": "Symbols" + , "aliases": [ + "sagittarius" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♑" + , "description": "Capricorn" + , "category": "Symbols" + , "aliases": [ + "capricorn" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♒" + , "description": "Aquarius" + , "category": "Symbols" + , "aliases": [ + "aquarius" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "♓" + , "description": "Pisces" + , "category": "Symbols" + , "aliases": [ + "pisces" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⛎" + , "description": "Ophiuchus" + , "category": "Symbols" + , "aliases": [ + "ophiuchus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔀" + , "description": "shuffle tracks button" + , "category": "Symbols" + , "aliases": [ + "twisted_rightwards_arrows" + ] + , "tags": [ + "shuffle" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔁" + , "description": "repeat button" + , "category": "Symbols" + , "aliases": [ + "repeat" + ] + , "tags": [ + "loop" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔂" + , "description": "repeat single button" + , "category": "Symbols" + , "aliases": [ + "repeat_one" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "▶️" + , "description": "play button" + , "category": "Symbols" + , "aliases": [ + "arrow_forward" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⏩" + , "description": "fast-forward button" + , "category": "Symbols" + , "aliases": [ + "fast_forward" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⏭" + , "description": "next track button" + , "category": "Symbols" + , "aliases": [ + "next_track_button" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.1" + } +, { + "emoji": "⏯" + , "description": "play or pause button" + , "category": "Symbols" + , "aliases": [ + "play_or_pause_button" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.1" + } +, { + "emoji": "◀️" + , "description": "reverse button" + , "category": "Symbols" + , "aliases": [ + "arrow_backward" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⏪" + , "description": "fast reverse button" + , "category": "Symbols" + , "aliases": [ + "rewind" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⏮" + , "description": "last track button" + , "category": "Symbols" + , "aliases": [ + "previous_track_button" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.1" + } +, { + "emoji": "🔼" + , "description": "upwards button" + , "category": "Symbols" + , "aliases": [ + "arrow_up_small" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⏫" + , "description": "fast up button" + , "category": "Symbols" + , "aliases": [ + "arrow_double_up" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔽" + , "description": "downwards button" + , "category": "Symbols" + , "aliases": [ + "arrow_down_small" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⏬" + , "description": "fast down button" + , "category": "Symbols" + , "aliases": [ + "arrow_double_down" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⏸" + , "description": "pause button" + , "category": "Symbols" + , "aliases": [ + "pause_button" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "⏹" + , "description": "stop button" + , "category": "Symbols" + , "aliases": [ + "stop_button" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "⏺" + , "description": "record button" + , "category": "Symbols" + , "aliases": [ + "record_button" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "⏏️" + , "description": "eject button" + , "category": "Symbols" + , "aliases": [ + "eject_button" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🎦" + , "description": "cinema" + , "category": "Symbols" + , "aliases": [ + "cinema" + ] + , "tags": [ + "film" + , "movie" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔅" + , "description": "dim button" + , "category": "Symbols" + , "aliases": [ + "low_brightness" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔆" + , "description": "bright button" + , "category": "Symbols" + , "aliases": [ + "high_brightness" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📶" + , "description": "antenna bars" + , "category": "Symbols" + , "aliases": [ + "signal_strength" + ] + , "tags": [ + "wifi" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📳" + , "description": "vibration mode" + , "category": "Symbols" + , "aliases": [ + "vibration_mode" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📴" + , "description": "mobile phone off" + , "category": "Symbols" + , "aliases": [ + "mobile_phone_off" + ] + , "tags": [ + "mute" + , "off" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "♀️" + , "description": "female sign" + , "category": "Symbols" + , "aliases": [ + "female_sign" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "♂️" + , "description": "male sign" + , "category": "Symbols" + , "aliases": [ + "male_sign" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "⚕" + , "description": "medical symbol" + , "category": "Symbols" + , "aliases": [ + "medical_symbol" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "♾" + , "description": "infinity" + , "category": "Symbols" + , "aliases": [ + "infinity" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "♻️" + , "description": "recycling symbol" + , "category": "Symbols" + , "aliases": [ + "recycle" + ] + , "tags": [ + "environment" + , "green" + ] + , "unicode_version": "3.2" + , "ios_version": "6.0" + } +, { + "emoji": "⚜" + , "description": "fleur-de-lis" + , "category": "Symbols" + , "aliases": [ + "fleur_de_lis" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "9.1" + } +, { + "emoji": "🔱" + , "description": "trident emblem" + , "category": "Symbols" + , "aliases": [ + "trident" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "📛" + , "description": "name badge" + , "category": "Symbols" + , "aliases": [ + "name_badge" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔰" + , "description": "Japanese symbol for beginner" + , "category": "Symbols" + , "aliases": [ + "beginner" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "⭕" + , "description": "hollow red circle" + , "category": "Symbols" + , "aliases": [ + "o" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "✅" + , "description": "check mark button" + , "category": "Symbols" + , "aliases": [ + "white_check_mark" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "☑️" + , "description": "check box with check" + , "category": "Symbols" + , "aliases": [ + "ballot_box_with_check" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "✔️" + , "description": "check mark" + , "category": "Symbols" + , "aliases": [ + "heavy_check_mark" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "✖️" + , "description": "multiplication sign" + , "category": "Symbols" + , "aliases": [ + "heavy_multiplication_x" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "❌" + , "description": "cross mark" + , "category": "Symbols" + , "aliases": [ + "x" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "❎" + , "description": "cross mark button" + , "category": "Symbols" + , "aliases": [ + "negative_squared_cross_mark" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "➕" + , "description": "plus sign" + , "category": "Symbols" + , "aliases": [ + "heavy_plus_sign" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "➖" + , "description": "minus sign" + , "category": "Symbols" + , "aliases": [ + "heavy_minus_sign" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "➗" + , "description": "division sign" + , "category": "Symbols" + , "aliases": [ + "heavy_division_sign" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "➰" + , "description": "curly loop" + , "category": "Symbols" + , "aliases": [ + "curly_loop" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "➿" + , "description": "double curly loop" + , "category": "Symbols" + , "aliases": [ + "loop" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "〽️" + , "description": "part alternation mark" + , "category": "Symbols" + , "aliases": [ + "part_alternation_mark" + ] + , "tags": [ + ] + , "unicode_version": "3.2" + , "ios_version": "6.0" + } +, { + "emoji": "✳️" + , "description": "eight-spoked asterisk" + , "category": "Symbols" + , "aliases": [ + "eight_spoked_asterisk" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "✴️" + , "description": "eight-pointed star" + , "category": "Symbols" + , "aliases": [ + "eight_pointed_black_star" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "❇️" + , "description": "sparkle" + , "category": "Symbols" + , "aliases": [ + "sparkle" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "‼️" + , "description": "double exclamation mark" + , "category": "Symbols" + , "aliases": [ + "bangbang" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "⁉️" + , "description": "exclamation question mark" + , "category": "Symbols" + , "aliases": [ + "interrobang" + ] + , "tags": [ + ] + , "unicode_version": "3.0" + , "ios_version": "6.0" + } +, { + "emoji": "❓" + , "description": "question mark" + , "category": "Symbols" + , "aliases": [ + "question" + ] + , "tags": [ + "confused" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "❔" + , "description": "white question mark" + , "category": "Symbols" + , "aliases": [ + "grey_question" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "❕" + , "description": "white exclamation mark" + , "category": "Symbols" + , "aliases": [ + "grey_exclamation" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "❗" + , "description": "exclamation mark" + , "category": "Symbols" + , "aliases": [ + "exclamation" + , "heavy_exclamation_mark" + ] + , "tags": [ + "bang" + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "〰️" + , "description": "wavy dash" + , "category": "Symbols" + , "aliases": [ + "wavy_dash" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "©️" + , "description": "copyright" + , "category": "Symbols" + , "aliases": [ + "copyright" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "®️" + , "description": "registered" + , "category": "Symbols" + , "aliases": [ + "registered" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "™️" + , "description": "trade mark" + , "category": "Symbols" + , "aliases": [ + "tm" + ] + , "tags": [ + "trademark" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "#️⃣" + , "description": "keycap: #" + , "category": "Symbols" + , "aliases": [ + "hash" + ] + , "tags": [ + "number" + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "*️⃣" + , "description": "keycap: *" + , "category": "Symbols" + , "aliases": [ + "asterisk" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "9.1" + } +, { + "emoji": "0️⃣" + , "description": "keycap: 0" + , "category": "Symbols" + , "aliases": [ + "zero" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "1️⃣" + , "description": "keycap: 1" + , "category": "Symbols" + , "aliases": [ + "one" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "2️⃣" + , "description": "keycap: 2" + , "category": "Symbols" + , "aliases": [ + "two" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "3️⃣" + , "description": "keycap: 3" + , "category": "Symbols" + , "aliases": [ + "three" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "4️⃣" + , "description": "keycap: 4" + , "category": "Symbols" + , "aliases": [ + "four" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "5️⃣" + , "description": "keycap: 5" + , "category": "Symbols" + , "aliases": [ + "five" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "6️⃣" + , "description": "keycap: 6" + , "category": "Symbols" + , "aliases": [ + "six" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "7️⃣" + , "description": "keycap: 7" + , "category": "Symbols" + , "aliases": [ + "seven" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "8️⃣" + , "description": "keycap: 8" + , "category": "Symbols" + , "aliases": [ + "eight" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "9️⃣" + , "description": "keycap: 9" + , "category": "Symbols" + , "aliases": [ + "nine" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🔟" + , "description": "keycap: 10" + , "category": "Symbols" + , "aliases": [ + "keycap_ten" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔠" + , "description": "input latin uppercase" + , "category": "Symbols" + , "aliases": [ + "capital_abcd" + ] + , "tags": [ + "letters" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔡" + , "description": "input latin lowercase" + , "category": "Symbols" + , "aliases": [ + "abcd" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔢" + , "description": "input numbers" + , "category": "Symbols" + , "aliases": [ + "1234" + ] + , "tags": [ + "numbers" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔣" + , "description": "input symbols" + , "category": "Symbols" + , "aliases": [ + "symbols" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔤" + , "description": "input latin letters" + , "category": "Symbols" + , "aliases": [ + "abc" + ] + , "tags": [ + "alphabet" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🅰️" + , "description": "A button (blood type)" + , "category": "Symbols" + , "aliases": [ + "a" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🆎" + , "description": "AB button (blood type)" + , "category": "Symbols" + , "aliases": [ + "ab" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🅱️" + , "description": "B button (blood type)" + , "category": "Symbols" + , "aliases": [ + "b" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🆑" + , "description": "CL button" + , "category": "Symbols" + , "aliases": [ + "cl" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🆒" + , "description": "COOL button" + , "category": "Symbols" + , "aliases": [ + "cool" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🆓" + , "description": "FREE button" + , "category": "Symbols" + , "aliases": [ + "free" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "ℹ️" + , "description": "information" + , "category": "Symbols" + , "aliases": [ + "information_source" + ] + , "tags": [ + ] + , "unicode_version": "3.0" + , "ios_version": "6.0" + } +, { + "emoji": "🆔" + , "description": "ID button" + , "category": "Symbols" + , "aliases": [ + "id" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "Ⓜ️" + , "description": "circled M" + , "category": "Symbols" + , "aliases": [ + "m" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🆕" + , "description": "NEW button" + , "category": "Symbols" + , "aliases": [ + "new" + ] + , "tags": [ + "fresh" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🆖" + , "description": "NG button" + , "category": "Symbols" + , "aliases": [ + "ng" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🅾️" + , "description": "O button (blood type)" + , "category": "Symbols" + , "aliases": [ + "o2" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🆗" + , "description": "OK button" + , "category": "Symbols" + , "aliases": [ + "ok" + ] + , "tags": [ + "yes" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🅿️" + , "description": "P button" + , "category": "Symbols" + , "aliases": [ + "parking" + ] + , "tags": [ + ] + , "unicode_version": "5.2" + , "ios_version": "6.0" + } +, { + "emoji": "🆘" + , "description": "SOS button" + , "category": "Symbols" + , "aliases": [ + "sos" + ] + , "tags": [ + "help" + , "emergency" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🆙" + , "description": "UP! button" + , "category": "Symbols" + , "aliases": [ + "up" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🆚" + , "description": "VS button" + , "category": "Symbols" + , "aliases": [ + "vs" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈁" + , "description": "Japanese “here” button" + , "category": "Symbols" + , "aliases": [ + "koko" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈂️" + , "description": "Japanese “service charge” button" + , "category": "Symbols" + , "aliases": [ + "sa" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈷️" + , "description": "Japanese “monthly amount” button" + , "category": "Symbols" + , "aliases": [ + "u6708" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈶" + , "description": "Japanese “not free of charge” button" + , "category": "Symbols" + , "aliases": [ + "u6709" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈯" + , "description": "Japanese “reserved” button" + , "category": "Symbols" + , "aliases": [ + "u6307" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🉐" + , "description": "Japanese “bargain” button" + , "category": "Symbols" + , "aliases": [ + "ideograph_advantage" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈹" + , "description": "Japanese “discount” button" + , "category": "Symbols" + , "aliases": [ + "u5272" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈚" + , "description": "Japanese “free of charge” button" + , "category": "Symbols" + , "aliases": [ + "u7121" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🈲" + , "description": "Japanese “prohibited” button" + , "category": "Symbols" + , "aliases": [ + "u7981" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🉑" + , "description": "Japanese “acceptable” button" + , "category": "Symbols" + , "aliases": [ + "accept" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈸" + , "description": "Japanese “application” button" + , "category": "Symbols" + , "aliases": [ + "u7533" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈴" + , "description": "Japanese “passing grade” button" + , "category": "Symbols" + , "aliases": [ + "u5408" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈳" + , "description": "Japanese “vacancy” button" + , "category": "Symbols" + , "aliases": [ + "u7a7a" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "㊗️" + , "description": "Japanese “congratulations” button" + , "category": "Symbols" + , "aliases": [ + "congratulations" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "㊙️" + , "description": "Japanese “secret” button" + , "category": "Symbols" + , "aliases": [ + "secret" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🈺" + , "description": "Japanese “open for business” button" + , "category": "Symbols" + , "aliases": [ + "u55b6" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🈵" + , "description": "Japanese “no vacancy” button" + , "category": "Symbols" + , "aliases": [ + "u6e80" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔴" + , "description": "red circle" + , "category": "Symbols" + , "aliases": [ + "red_circle" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🟠" + , "description": "orange circle" + , "category": "Symbols" + , "aliases": [ + "orange_circle" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🟡" + , "description": "yellow circle" + , "category": "Symbols" + , "aliases": [ + "yellow_circle" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🟢" + , "description": "green circle" + , "category": "Symbols" + , "aliases": [ + "green_circle" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🔵" + , "description": "blue circle" + , "category": "Symbols" + , "aliases": [ + "large_blue_circle" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🟣" + , "description": "purple circle" + , "category": "Symbols" + , "aliases": [ + "purple_circle" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🟤" + , "description": "brown circle" + , "category": "Symbols" + , "aliases": [ + "brown_circle" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "⚫" + , "description": "black circle" + , "category": "Symbols" + , "aliases": [ + "black_circle" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "6.0" + } +, { + "emoji": "⚪" + , "description": "white circle" + , "category": "Symbols" + , "aliases": [ + "white_circle" + ] + , "tags": [ + ] + , "unicode_version": "4.1" + , "ios_version": "6.0" + } +, { + "emoji": "🟥" + , "description": "red square" + , "category": "Symbols" + , "aliases": [ + "red_square" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🟧" + , "description": "orange square" + , "category": "Symbols" + , "aliases": [ + "orange_square" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🟨" + , "description": "yellow square" + , "category": "Symbols" + , "aliases": [ + "yellow_square" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🟩" + , "description": "green square" + , "category": "Symbols" + , "aliases": [ + "green_square" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🟦" + , "description": "blue square" + , "category": "Symbols" + , "aliases": [ + "blue_square" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🟪" + , "description": "purple square" + , "category": "Symbols" + , "aliases": [ + "purple_square" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "🟫" + , "description": "brown square" + , "category": "Symbols" + , "aliases": [ + "brown_square" + ] + , "tags": [ + ] + , "unicode_version": "12.0" + , "ios_version": "13.0" + } +, { + "emoji": "⬛" + , "description": "black large square" + , "category": "Symbols" + , "aliases": [ + "black_large_square" + ] + , "tags": [ + ] + , "unicode_version": "5.1" + , "ios_version": "6.0" + } +, { + "emoji": "⬜" + , "description": "white large square" + , "category": "Symbols" + , "aliases": [ + "white_large_square" + ] + , "tags": [ + ] + , "unicode_version": "5.1" + , "ios_version": "6.0" + } +, { + "emoji": "◼️" + , "description": "black medium square" + , "category": "Symbols" + , "aliases": [ + "black_medium_square" + ] + , "tags": [ + ] + , "unicode_version": "3.2" + , "ios_version": "6.0" + } +, { + "emoji": "◻️" + , "description": "white medium square" + , "category": "Symbols" + , "aliases": [ + "white_medium_square" + ] + , "tags": [ + ] + , "unicode_version": "3.2" + , "ios_version": "6.0" + } +, { + "emoji": "◾" + , "description": "black medium-small square" + , "category": "Symbols" + , "aliases": [ + "black_medium_small_square" + ] + , "tags": [ + ] + , "unicode_version": "3.2" + , "ios_version": "6.0" + } +, { + "emoji": "◽" + , "description": "white medium-small square" + , "category": "Symbols" + , "aliases": [ + "white_medium_small_square" + ] + , "tags": [ + ] + , "unicode_version": "3.2" + , "ios_version": "6.0" + } +, { + "emoji": "▪️" + , "description": "black small square" + , "category": "Symbols" + , "aliases": [ + "black_small_square" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "▫️" + , "description": "white small square" + , "category": "Symbols" + , "aliases": [ + "white_small_square" + ] + , "tags": [ + ] + , "unicode_version": "" + , "ios_version": "6.0" + } +, { + "emoji": "🔶" + , "description": "large orange diamond" + , "category": "Symbols" + , "aliases": [ + "large_orange_diamond" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔷" + , "description": "large blue diamond" + , "category": "Symbols" + , "aliases": [ + "large_blue_diamond" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔸" + , "description": "small orange diamond" + , "category": "Symbols" + , "aliases": [ + "small_orange_diamond" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔹" + , "description": "small blue diamond" + , "category": "Symbols" + , "aliases": [ + "small_blue_diamond" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔺" + , "description": "red triangle pointed up" + , "category": "Symbols" + , "aliases": [ + "small_red_triangle" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔻" + , "description": "red triangle pointed down" + , "category": "Symbols" + , "aliases": [ + "small_red_triangle_down" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "💠" + , "description": "diamond with a dot" + , "category": "Symbols" + , "aliases": [ + "diamond_shape_with_a_dot_inside" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔘" + , "description": "radio button" + , "category": "Symbols" + , "aliases": [ + "radio_button" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔳" + , "description": "white square button" + , "category": "Symbols" + , "aliases": [ + "white_square_button" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🔲" + , "description": "black square button" + , "category": "Symbols" + , "aliases": [ + "black_square_button" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏁" + , "description": "chequered flag" + , "category": "Flags" + , "aliases": [ + "checkered_flag" + ] + , "tags": [ + "milestone" + , "finish" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🚩" + , "description": "triangular flag" + , "category": "Flags" + , "aliases": [ + "triangular_flag_on_post" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🎌" + , "description": "crossed flags" + , "category": "Flags" + , "aliases": [ + "crossed_flags" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🏴" + , "description": "black flag" + , "category": "Flags" + , "aliases": [ + "black_flag" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏳" + , "description": "white flag" + , "category": "Flags" + , "aliases": [ + "white_flag" + ] + , "tags": [ + ] + , "unicode_version": "7.0" + , "ios_version": "9.1" + } +, { + "emoji": "🏳️‍🌈" + , "description": "rainbow flag" + , "category": "Flags" + , "aliases": [ + "rainbow_flag" + ] + , "tags": [ + "pride" + ] + , "unicode_version": "6.0" + , "ios_version": "10.0" + } +, { + "emoji": "🏴‍☠" + , "description": "pirate flag" + , "category": "Flags" + , "aliases": [ + "pirate_flag" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇦🇨" + , "description": "flag: Ascension Island" + , "category": "Flags" + , "aliases": [ + "ascension_island" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇦🇩" + , "description": "flag: Andorra" + , "category": "Flags" + , "aliases": [ + "andorra" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇪" + , "description": "flag: United Arab Emirates" + , "category": "Flags" + , "aliases": [ + "united_arab_emirates" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇫" + , "description": "flag: Afghanistan" + , "category": "Flags" + , "aliases": [ + "afghanistan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇬" + , "description": "flag: Antigua & Barbuda" + , "category": "Flags" + , "aliases": [ + "antigua_barbuda" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇮" + , "description": "flag: Anguilla" + , "category": "Flags" + , "aliases": [ + "anguilla" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇱" + , "description": "flag: Albania" + , "category": "Flags" + , "aliases": [ + "albania" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇲" + , "description": "flag: Armenia" + , "category": "Flags" + , "aliases": [ + "armenia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇴" + , "description": "flag: Angola" + , "category": "Flags" + , "aliases": [ + "angola" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇶" + , "description": "flag: Antarctica" + , "category": "Flags" + , "aliases": [ + "antarctica" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇦🇷" + , "description": "flag: Argentina" + , "category": "Flags" + , "aliases": [ + "argentina" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇸" + , "description": "flag: American Samoa" + , "category": "Flags" + , "aliases": [ + "american_samoa" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇹" + , "description": "flag: Austria" + , "category": "Flags" + , "aliases": [ + "austria" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇺" + , "description": "flag: Australia" + , "category": "Flags" + , "aliases": [ + "australia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇼" + , "description": "flag: Aruba" + , "category": "Flags" + , "aliases": [ + "aruba" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇦🇽" + , "description": "flag: Åland Islands" + , "category": "Flags" + , "aliases": [ + "aland_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇦🇿" + , "description": "flag: Azerbaijan" + , "category": "Flags" + , "aliases": [ + "azerbaijan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇦" + , "description": "flag: Bosnia & Herzegovina" + , "category": "Flags" + , "aliases": [ + "bosnia_herzegovina" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇧" + , "description": "flag: Barbados" + , "category": "Flags" + , "aliases": [ + "barbados" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇩" + , "description": "flag: Bangladesh" + , "category": "Flags" + , "aliases": [ + "bangladesh" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇪" + , "description": "flag: Belgium" + , "category": "Flags" + , "aliases": [ + "belgium" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇫" + , "description": "flag: Burkina Faso" + , "category": "Flags" + , "aliases": [ + "burkina_faso" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇬" + , "description": "flag: Bulgaria" + , "category": "Flags" + , "aliases": [ + "bulgaria" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇭" + , "description": "flag: Bahrain" + , "category": "Flags" + , "aliases": [ + "bahrain" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇮" + , "description": "flag: Burundi" + , "category": "Flags" + , "aliases": [ + "burundi" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇯" + , "description": "flag: Benin" + , "category": "Flags" + , "aliases": [ + "benin" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇱" + , "description": "flag: St. Barthélemy" + , "category": "Flags" + , "aliases": [ + "st_barthelemy" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇧🇲" + , "description": "flag: Bermuda" + , "category": "Flags" + , "aliases": [ + "bermuda" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇳" + , "description": "flag: Brunei" + , "category": "Flags" + , "aliases": [ + "brunei" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇴" + , "description": "flag: Bolivia" + , "category": "Flags" + , "aliases": [ + "bolivia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇶" + , "description": "flag: Caribbean Netherlands" + , "category": "Flags" + , "aliases": [ + "caribbean_netherlands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇧🇷" + , "description": "flag: Brazil" + , "category": "Flags" + , "aliases": [ + "brazil" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇸" + , "description": "flag: Bahamas" + , "category": "Flags" + , "aliases": [ + "bahamas" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇹" + , "description": "flag: Bhutan" + , "category": "Flags" + , "aliases": [ + "bhutan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇻" + , "description": "flag: Bouvet Island" + , "category": "Flags" + , "aliases": [ + "bouvet_island" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇧🇼" + , "description": "flag: Botswana" + , "category": "Flags" + , "aliases": [ + "botswana" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇾" + , "description": "flag: Belarus" + , "category": "Flags" + , "aliases": [ + "belarus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇧🇿" + , "description": "flag: Belize" + , "category": "Flags" + , "aliases": [ + "belize" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇦" + , "description": "flag: Canada" + , "category": "Flags" + , "aliases": [ + "canada" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇨" + , "description": "flag: Cocos (Keeling) Islands" + , "category": "Flags" + , "aliases": [ + "cocos_islands" + ] + , "tags": [ + "keeling" + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇨🇩" + , "description": "flag: Congo - Kinshasa" + , "category": "Flags" + , "aliases": [ + "congo_kinshasa" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇫" + , "description": "flag: Central African Republic" + , "category": "Flags" + , "aliases": [ + "central_african_republic" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇬" + , "description": "flag: Congo - Brazzaville" + , "category": "Flags" + , "aliases": [ + "congo_brazzaville" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇭" + , "description": "flag: Switzerland" + , "category": "Flags" + , "aliases": [ + "switzerland" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇮" + , "description": "flag: Côte d’Ivoire" + , "category": "Flags" + , "aliases": [ + "cote_divoire" + ] + , "tags": [ + "ivory" + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇰" + , "description": "flag: Cook Islands" + , "category": "Flags" + , "aliases": [ + "cook_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇱" + , "description": "flag: Chile" + , "category": "Flags" + , "aliases": [ + "chile" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇲" + , "description": "flag: Cameroon" + , "category": "Flags" + , "aliases": [ + "cameroon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇳" + , "description": "flag: China" + , "category": "Flags" + , "aliases": [ + "cn" + ] + , "tags": [ + "china" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇨🇴" + , "description": "flag: Colombia" + , "category": "Flags" + , "aliases": [ + "colombia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇵" + , "description": "flag: Clipperton Island" + , "category": "Flags" + , "aliases": [ + "clipperton_island" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇨🇷" + , "description": "flag: Costa Rica" + , "category": "Flags" + , "aliases": [ + "costa_rica" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇺" + , "description": "flag: Cuba" + , "category": "Flags" + , "aliases": [ + "cuba" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇻" + , "description": "flag: Cape Verde" + , "category": "Flags" + , "aliases": [ + "cape_verde" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇼" + , "description": "flag: Curaçao" + , "category": "Flags" + , "aliases": [ + "curacao" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇽" + , "description": "flag: Christmas Island" + , "category": "Flags" + , "aliases": [ + "christmas_island" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇨🇾" + , "description": "flag: Cyprus" + , "category": "Flags" + , "aliases": [ + "cyprus" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇨🇿" + , "description": "flag: Czechia" + , "category": "Flags" + , "aliases": [ + "czech_republic" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇩🇪" + , "description": "flag: Germany" + , "category": "Flags" + , "aliases": [ + "de" + ] + , "tags": [ + "flag" + , "germany" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇩🇬" + , "description": "flag: Diego Garcia" + , "category": "Flags" + , "aliases": [ + "diego_garcia" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇩🇯" + , "description": "flag: Djibouti" + , "category": "Flags" + , "aliases": [ + "djibouti" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇩🇰" + , "description": "flag: Denmark" + , "category": "Flags" + , "aliases": [ + "denmark" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇩🇲" + , "description": "flag: Dominica" + , "category": "Flags" + , "aliases": [ + "dominica" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇩🇴" + , "description": "flag: Dominican Republic" + , "category": "Flags" + , "aliases": [ + "dominican_republic" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇩🇿" + , "description": "flag: Algeria" + , "category": "Flags" + , "aliases": [ + "algeria" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇪🇦" + , "description": "flag: Ceuta & Melilla" + , "category": "Flags" + , "aliases": [ + "ceuta_melilla" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇪🇨" + , "description": "flag: Ecuador" + , "category": "Flags" + , "aliases": [ + "ecuador" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇪🇪" + , "description": "flag: Estonia" + , "category": "Flags" + , "aliases": [ + "estonia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇪🇬" + , "description": "flag: Egypt" + , "category": "Flags" + , "aliases": [ + "egypt" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇪🇭" + , "description": "flag: Western Sahara" + , "category": "Flags" + , "aliases": [ + "western_sahara" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇪🇷" + , "description": "flag: Eritrea" + , "category": "Flags" + , "aliases": [ + "eritrea" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇪🇸" + , "description": "flag: Spain" + , "category": "Flags" + , "aliases": [ + "es" + ] + , "tags": [ + "spain" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇪🇹" + , "description": "flag: Ethiopia" + , "category": "Flags" + , "aliases": [ + "ethiopia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇪🇺" + , "description": "flag: European Union" + , "category": "Flags" + , "aliases": [ + "eu" + , "european_union" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇫🇮" + , "description": "flag: Finland" + , "category": "Flags" + , "aliases": [ + "finland" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇫🇯" + , "description": "flag: Fiji" + , "category": "Flags" + , "aliases": [ + "fiji" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇫🇰" + , "description": "flag: Falkland Islands" + , "category": "Flags" + , "aliases": [ + "falkland_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇫🇲" + , "description": "flag: Micronesia" + , "category": "Flags" + , "aliases": [ + "micronesia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇫🇴" + , "description": "flag: Faroe Islands" + , "category": "Flags" + , "aliases": [ + "faroe_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇫🇷" + , "description": "flag: France" + , "category": "Flags" + , "aliases": [ + "fr" + ] + , "tags": [ + "france" + , "french" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇬🇦" + , "description": "flag: Gabon" + , "category": "Flags" + , "aliases": [ + "gabon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇧" + , "description": "flag: United Kingdom" + , "category": "Flags" + , "aliases": [ + "gb" + , "uk" + ] + , "tags": [ + "flag" + , "british" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇬🇩" + , "description": "flag: Grenada" + , "category": "Flags" + , "aliases": [ + "grenada" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇪" + , "description": "flag: Georgia" + , "category": "Flags" + , "aliases": [ + "georgia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇫" + , "description": "flag: French Guiana" + , "category": "Flags" + , "aliases": [ + "french_guiana" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇬" + , "description": "flag: Guernsey" + , "category": "Flags" + , "aliases": [ + "guernsey" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇬🇭" + , "description": "flag: Ghana" + , "category": "Flags" + , "aliases": [ + "ghana" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇮" + , "description": "flag: Gibraltar" + , "category": "Flags" + , "aliases": [ + "gibraltar" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇱" + , "description": "flag: Greenland" + , "category": "Flags" + , "aliases": [ + "greenland" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇬🇲" + , "description": "flag: Gambia" + , "category": "Flags" + , "aliases": [ + "gambia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇳" + , "description": "flag: Guinea" + , "category": "Flags" + , "aliases": [ + "guinea" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇵" + , "description": "flag: Guadeloupe" + , "category": "Flags" + , "aliases": [ + "guadeloupe" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇬🇶" + , "description": "flag: Equatorial Guinea" + , "category": "Flags" + , "aliases": [ + "equatorial_guinea" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇷" + , "description": "flag: Greece" + , "category": "Flags" + , "aliases": [ + "greece" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇸" + , "description": "flag: South Georgia & South Sandwich Islands" + , "category": "Flags" + , "aliases": [ + "south_georgia_south_sandwich_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇬🇹" + , "description": "flag: Guatemala" + , "category": "Flags" + , "aliases": [ + "guatemala" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇺" + , "description": "flag: Guam" + , "category": "Flags" + , "aliases": [ + "guam" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇼" + , "description": "flag: Guinea-Bissau" + , "category": "Flags" + , "aliases": [ + "guinea_bissau" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇬🇾" + , "description": "flag: Guyana" + , "category": "Flags" + , "aliases": [ + "guyana" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇭🇰" + , "description": "flag: Hong Kong SAR China" + , "category": "Flags" + , "aliases": [ + "hong_kong" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇭🇲" + , "description": "flag: Heard & McDonald Islands" + , "category": "Flags" + , "aliases": [ + "heard_mcdonald_islands" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇭🇳" + , "description": "flag: Honduras" + , "category": "Flags" + , "aliases": [ + "honduras" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇭🇷" + , "description": "flag: Croatia" + , "category": "Flags" + , "aliases": [ + "croatia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇭🇹" + , "description": "flag: Haiti" + , "category": "Flags" + , "aliases": [ + "haiti" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇭🇺" + , "description": "flag: Hungary" + , "category": "Flags" + , "aliases": [ + "hungary" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇮🇨" + , "description": "flag: Canary Islands" + , "category": "Flags" + , "aliases": [ + "canary_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇮🇩" + , "description": "flag: Indonesia" + , "category": "Flags" + , "aliases": [ + "indonesia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇮🇪" + , "description": "flag: Ireland" + , "category": "Flags" + , "aliases": [ + "ireland" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇮🇱" + , "description": "flag: Israel" + , "category": "Flags" + , "aliases": [ + "israel" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇮🇲" + , "description": "flag: Isle of Man" + , "category": "Flags" + , "aliases": [ + "isle_of_man" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇮🇳" + , "description": "flag: India" + , "category": "Flags" + , "aliases": [ + "india" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇮🇴" + , "description": "flag: British Indian Ocean Territory" + , "category": "Flags" + , "aliases": [ + "british_indian_ocean_territory" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇮🇶" + , "description": "flag: Iraq" + , "category": "Flags" + , "aliases": [ + "iraq" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇮🇷" + , "description": "flag: Iran" + , "category": "Flags" + , "aliases": [ + "iran" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇮🇸" + , "description": "flag: Iceland" + , "category": "Flags" + , "aliases": [ + "iceland" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇮🇹" + , "description": "flag: Italy" + , "category": "Flags" + , "aliases": [ + "it" + ] + , "tags": [ + "italy" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇯🇪" + , "description": "flag: Jersey" + , "category": "Flags" + , "aliases": [ + "jersey" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇯🇲" + , "description": "flag: Jamaica" + , "category": "Flags" + , "aliases": [ + "jamaica" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇯🇴" + , "description": "flag: Jordan" + , "category": "Flags" + , "aliases": [ + "jordan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇯🇵" + , "description": "flag: Japan" + , "category": "Flags" + , "aliases": [ + "jp" + ] + , "tags": [ + "japan" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇰🇪" + , "description": "flag: Kenya" + , "category": "Flags" + , "aliases": [ + "kenya" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇰🇬" + , "description": "flag: Kyrgyzstan" + , "category": "Flags" + , "aliases": [ + "kyrgyzstan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇰🇭" + , "description": "flag: Cambodia" + , "category": "Flags" + , "aliases": [ + "cambodia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇰🇮" + , "description": "flag: Kiribati" + , "category": "Flags" + , "aliases": [ + "kiribati" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇰🇲" + , "description": "flag: Comoros" + , "category": "Flags" + , "aliases": [ + "comoros" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇰🇳" + , "description": "flag: St. Kitts & Nevis" + , "category": "Flags" + , "aliases": [ + "st_kitts_nevis" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇰🇵" + , "description": "flag: North Korea" + , "category": "Flags" + , "aliases": [ + "north_korea" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇰🇷" + , "description": "flag: South Korea" + , "category": "Flags" + , "aliases": [ + "kr" + ] + , "tags": [ + "korea" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇰🇼" + , "description": "flag: Kuwait" + , "category": "Flags" + , "aliases": [ + "kuwait" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇰🇾" + , "description": "flag: Cayman Islands" + , "category": "Flags" + , "aliases": [ + "cayman_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇰🇿" + , "description": "flag: Kazakhstan" + , "category": "Flags" + , "aliases": [ + "kazakhstan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇦" + , "description": "flag: Laos" + , "category": "Flags" + , "aliases": [ + "laos" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇧" + , "description": "flag: Lebanon" + , "category": "Flags" + , "aliases": [ + "lebanon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇨" + , "description": "flag: St. Lucia" + , "category": "Flags" + , "aliases": [ + "st_lucia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇮" + , "description": "flag: Liechtenstein" + , "category": "Flags" + , "aliases": [ + "liechtenstein" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇰" + , "description": "flag: Sri Lanka" + , "category": "Flags" + , "aliases": [ + "sri_lanka" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇷" + , "description": "flag: Liberia" + , "category": "Flags" + , "aliases": [ + "liberia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇸" + , "description": "flag: Lesotho" + , "category": "Flags" + , "aliases": [ + "lesotho" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇹" + , "description": "flag: Lithuania" + , "category": "Flags" + , "aliases": [ + "lithuania" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇺" + , "description": "flag: Luxembourg" + , "category": "Flags" + , "aliases": [ + "luxembourg" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇻" + , "description": "flag: Latvia" + , "category": "Flags" + , "aliases": [ + "latvia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇱🇾" + , "description": "flag: Libya" + , "category": "Flags" + , "aliases": [ + "libya" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇦" + , "description": "flag: Morocco" + , "category": "Flags" + , "aliases": [ + "morocco" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇨" + , "description": "flag: Monaco" + , "category": "Flags" + , "aliases": [ + "monaco" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇲🇩" + , "description": "flag: Moldova" + , "category": "Flags" + , "aliases": [ + "moldova" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇪" + , "description": "flag: Montenegro" + , "category": "Flags" + , "aliases": [ + "montenegro" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇫" + , "description": "flag: St. Martin" + , "category": "Flags" + , "aliases": [ + "st_martin" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇲🇬" + , "description": "flag: Madagascar" + , "category": "Flags" + , "aliases": [ + "madagascar" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇭" + , "description": "flag: Marshall Islands" + , "category": "Flags" + , "aliases": [ + "marshall_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇲🇰" + , "description": "flag: Macedonia" + , "category": "Flags" + , "aliases": [ + "macedonia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇱" + , "description": "flag: Mali" + , "category": "Flags" + , "aliases": [ + "mali" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇲" + , "description": "flag: Myanmar (Burma)" + , "category": "Flags" + , "aliases": [ + "myanmar" + ] + , "tags": [ + "burma" + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇳" + , "description": "flag: Mongolia" + , "category": "Flags" + , "aliases": [ + "mongolia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇴" + , "description": "flag: Macao SAR China" + , "category": "Flags" + , "aliases": [ + "macau" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇵" + , "description": "flag: Northern Mariana Islands" + , "category": "Flags" + , "aliases": [ + "northern_mariana_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇶" + , "description": "flag: Martinique" + , "category": "Flags" + , "aliases": [ + "martinique" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇲🇷" + , "description": "flag: Mauritania" + , "category": "Flags" + , "aliases": [ + "mauritania" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇸" + , "description": "flag: Montserrat" + , "category": "Flags" + , "aliases": [ + "montserrat" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇹" + , "description": "flag: Malta" + , "category": "Flags" + , "aliases": [ + "malta" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇺" + , "description": "flag: Mauritius" + , "category": "Flags" + , "aliases": [ + "mauritius" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇲🇻" + , "description": "flag: Maldives" + , "category": "Flags" + , "aliases": [ + "maldives" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇼" + , "description": "flag: Malawi" + , "category": "Flags" + , "aliases": [ + "malawi" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇽" + , "description": "flag: Mexico" + , "category": "Flags" + , "aliases": [ + "mexico" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇾" + , "description": "flag: Malaysia" + , "category": "Flags" + , "aliases": [ + "malaysia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇲🇿" + , "description": "flag: Mozambique" + , "category": "Flags" + , "aliases": [ + "mozambique" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇦" + , "description": "flag: Namibia" + , "category": "Flags" + , "aliases": [ + "namibia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇨" + , "description": "flag: New Caledonia" + , "category": "Flags" + , "aliases": [ + "new_caledonia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇪" + , "description": "flag: Niger" + , "category": "Flags" + , "aliases": [ + "niger" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇫" + , "description": "flag: Norfolk Island" + , "category": "Flags" + , "aliases": [ + "norfolk_island" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇳🇬" + , "description": "flag: Nigeria" + , "category": "Flags" + , "aliases": [ + "nigeria" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇮" + , "description": "flag: Nicaragua" + , "category": "Flags" + , "aliases": [ + "nicaragua" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇱" + , "description": "flag: Netherlands" + , "category": "Flags" + , "aliases": [ + "netherlands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇴" + , "description": "flag: Norway" + , "category": "Flags" + , "aliases": [ + "norway" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇵" + , "description": "flag: Nepal" + , "category": "Flags" + , "aliases": [ + "nepal" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇷" + , "description": "flag: Nauru" + , "category": "Flags" + , "aliases": [ + "nauru" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇳🇺" + , "description": "flag: Niue" + , "category": "Flags" + , "aliases": [ + "niue" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇳🇿" + , "description": "flag: New Zealand" + , "category": "Flags" + , "aliases": [ + "new_zealand" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇴🇲" + , "description": "flag: Oman" + , "category": "Flags" + , "aliases": [ + "oman" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇦" + , "description": "flag: Panama" + , "category": "Flags" + , "aliases": [ + "panama" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇪" + , "description": "flag: Peru" + , "category": "Flags" + , "aliases": [ + "peru" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇫" + , "description": "flag: French Polynesia" + , "category": "Flags" + , "aliases": [ + "french_polynesia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇵🇬" + , "description": "flag: Papua New Guinea" + , "category": "Flags" + , "aliases": [ + "papua_new_guinea" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇭" + , "description": "flag: Philippines" + , "category": "Flags" + , "aliases": [ + "philippines" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇰" + , "description": "flag: Pakistan" + , "category": "Flags" + , "aliases": [ + "pakistan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇱" + , "description": "flag: Poland" + , "category": "Flags" + , "aliases": [ + "poland" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇲" + , "description": "flag: St. Pierre & Miquelon" + , "category": "Flags" + , "aliases": [ + "st_pierre_miquelon" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇵🇳" + , "description": "flag: Pitcairn Islands" + , "category": "Flags" + , "aliases": [ + "pitcairn_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇵🇷" + , "description": "flag: Puerto Rico" + , "category": "Flags" + , "aliases": [ + "puerto_rico" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇸" + , "description": "flag: Palestinian Territories" + , "category": "Flags" + , "aliases": [ + "palestinian_territories" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇹" + , "description": "flag: Portugal" + , "category": "Flags" + , "aliases": [ + "portugal" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇼" + , "description": "flag: Palau" + , "category": "Flags" + , "aliases": [ + "palau" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇵🇾" + , "description": "flag: Paraguay" + , "category": "Flags" + , "aliases": [ + "paraguay" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇶🇦" + , "description": "flag: Qatar" + , "category": "Flags" + , "aliases": [ + "qatar" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇷🇪" + , "description": "flag: Réunion" + , "category": "Flags" + , "aliases": [ + "reunion" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇷🇴" + , "description": "flag: Romania" + , "category": "Flags" + , "aliases": [ + "romania" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇷🇸" + , "description": "flag: Serbia" + , "category": "Flags" + , "aliases": [ + "serbia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇷🇺" + , "description": "flag: Russia" + , "category": "Flags" + , "aliases": [ + "ru" + ] + , "tags": [ + "russia" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇷🇼" + , "description": "flag: Rwanda" + , "category": "Flags" + , "aliases": [ + "rwanda" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇦" + , "description": "flag: Saudi Arabia" + , "category": "Flags" + , "aliases": [ + "saudi_arabia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇧" + , "description": "flag: Solomon Islands" + , "category": "Flags" + , "aliases": [ + "solomon_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇨" + , "description": "flag: Seychelles" + , "category": "Flags" + , "aliases": [ + "seychelles" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇩" + , "description": "flag: Sudan" + , "category": "Flags" + , "aliases": [ + "sudan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇪" + , "description": "flag: Sweden" + , "category": "Flags" + , "aliases": [ + "sweden" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇬" + , "description": "flag: Singapore" + , "category": "Flags" + , "aliases": [ + "singapore" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇭" + , "description": "flag: St. Helena" + , "category": "Flags" + , "aliases": [ + "st_helena" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇸🇮" + , "description": "flag: Slovenia" + , "category": "Flags" + , "aliases": [ + "slovenia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇯" + , "description": "flag: Svalbard & Jan Mayen" + , "category": "Flags" + , "aliases": [ + "svalbard_jan_mayen" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇸🇰" + , "description": "flag: Slovakia" + , "category": "Flags" + , "aliases": [ + "slovakia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇱" + , "description": "flag: Sierra Leone" + , "category": "Flags" + , "aliases": [ + "sierra_leone" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇲" + , "description": "flag: San Marino" + , "category": "Flags" + , "aliases": [ + "san_marino" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇳" + , "description": "flag: Senegal" + , "category": "Flags" + , "aliases": [ + "senegal" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇴" + , "description": "flag: Somalia" + , "category": "Flags" + , "aliases": [ + "somalia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇷" + , "description": "flag: Suriname" + , "category": "Flags" + , "aliases": [ + "suriname" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇸" + , "description": "flag: South Sudan" + , "category": "Flags" + , "aliases": [ + "south_sudan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇹" + , "description": "flag: São Tomé & Príncipe" + , "category": "Flags" + , "aliases": [ + "sao_tome_principe" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇻" + , "description": "flag: El Salvador" + , "category": "Flags" + , "aliases": [ + "el_salvador" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇽" + , "description": "flag: Sint Maarten" + , "category": "Flags" + , "aliases": [ + "sint_maarten" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇾" + , "description": "flag: Syria" + , "category": "Flags" + , "aliases": [ + "syria" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇸🇿" + , "description": "flag: Eswatini" + , "category": "Flags" + , "aliases": [ + "swaziland" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇦" + , "description": "flag: Tristan da Cunha" + , "category": "Flags" + , "aliases": [ + "tristan_da_cunha" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇹🇨" + , "description": "flag: Turks & Caicos Islands" + , "category": "Flags" + , "aliases": [ + "turks_caicos_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇩" + , "description": "flag: Chad" + , "category": "Flags" + , "aliases": [ + "chad" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇹🇫" + , "description": "flag: French Southern Territories" + , "category": "Flags" + , "aliases": [ + "french_southern_territories" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇬" + , "description": "flag: Togo" + , "category": "Flags" + , "aliases": [ + "togo" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇭" + , "description": "flag: Thailand" + , "category": "Flags" + , "aliases": [ + "thailand" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇯" + , "description": "flag: Tajikistan" + , "category": "Flags" + , "aliases": [ + "tajikistan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇰" + , "description": "flag: Tokelau" + , "category": "Flags" + , "aliases": [ + "tokelau" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇹🇱" + , "description": "flag: Timor-Leste" + , "category": "Flags" + , "aliases": [ + "timor_leste" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇲" + , "description": "flag: Turkmenistan" + , "category": "Flags" + , "aliases": [ + "turkmenistan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇳" + , "description": "flag: Tunisia" + , "category": "Flags" + , "aliases": [ + "tunisia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇴" + , "description": "flag: Tonga" + , "category": "Flags" + , "aliases": [ + "tonga" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇷" + , "description": "flag: Turkey" + , "category": "Flags" + , "aliases": [ + "tr" + ] + , "tags": [ + "turkey" + ] + , "unicode_version": "8.0" + , "ios_version": "9.1" + } +, { + "emoji": "🇹🇹" + , "description": "flag: Trinidad & Tobago" + , "category": "Flags" + , "aliases": [ + "trinidad_tobago" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇻" + , "description": "flag: Tuvalu" + , "category": "Flags" + , "aliases": [ + "tuvalu" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇹🇼" + , "description": "flag: Taiwan" + , "category": "Flags" + , "aliases": [ + "taiwan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇹🇿" + , "description": "flag: Tanzania" + , "category": "Flags" + , "aliases": [ + "tanzania" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇺🇦" + , "description": "flag: Ukraine" + , "category": "Flags" + , "aliases": [ + "ukraine" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇺🇬" + , "description": "flag: Uganda" + , "category": "Flags" + , "aliases": [ + "uganda" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇺🇲" + , "description": "flag: U.S. Outlying Islands" + , "category": "Flags" + , "aliases": [ + "us_outlying_islands" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇺🇳" + , "description": "flag: United Nations" + , "category": "Flags" + , "aliases": [ + "united_nations" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🇺🇸" + , "description": "flag: United States" + , "category": "Flags" + , "aliases": [ + "us" + ] + , "tags": [ + "flag" + , "united" + , "america" + ] + , "unicode_version": "6.0" + , "ios_version": "6.0" + } +, { + "emoji": "🇺🇾" + , "description": "flag: Uruguay" + , "category": "Flags" + , "aliases": [ + "uruguay" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇺🇿" + , "description": "flag: Uzbekistan" + , "category": "Flags" + , "aliases": [ + "uzbekistan" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇻🇦" + , "description": "flag: Vatican City" + , "category": "Flags" + , "aliases": [ + "vatican_city" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇻🇨" + , "description": "flag: St. Vincent & Grenadines" + , "category": "Flags" + , "aliases": [ + "st_vincent_grenadines" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇻🇪" + , "description": "flag: Venezuela" + , "category": "Flags" + , "aliases": [ + "venezuela" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇻🇬" + , "description": "flag: British Virgin Islands" + , "category": "Flags" + , "aliases": [ + "british_virgin_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇻🇮" + , "description": "flag: U.S. Virgin Islands" + , "category": "Flags" + , "aliases": [ + "us_virgin_islands" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇻🇳" + , "description": "flag: Vietnam" + , "category": "Flags" + , "aliases": [ + "vietnam" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇻🇺" + , "description": "flag: Vanuatu" + , "category": "Flags" + , "aliases": [ + "vanuatu" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇼🇫" + , "description": "flag: Wallis & Futuna" + , "category": "Flags" + , "aliases": [ + "wallis_futuna" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇼🇸" + , "description": "flag: Samoa" + , "category": "Flags" + , "aliases": [ + "samoa" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇽🇰" + , "description": "flag: Kosovo" + , "category": "Flags" + , "aliases": [ + "kosovo" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇾🇪" + , "description": "flag: Yemen" + , "category": "Flags" + , "aliases": [ + "yemen" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇾🇹" + , "description": "flag: Mayotte" + , "category": "Flags" + , "aliases": [ + "mayotte" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "9.0" + } +, { + "emoji": "🇿🇦" + , "description": "flag: South Africa" + , "category": "Flags" + , "aliases": [ + "south_africa" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇿🇲" + , "description": "flag: Zambia" + , "category": "Flags" + , "aliases": [ + "zambia" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🇿🇼" + , "description": "flag: Zimbabwe" + , "category": "Flags" + , "aliases": [ + "zimbabwe" + ] + , "tags": [ + ] + , "unicode_version": "6.0" + , "ios_version": "8.3" + } +, { + "emoji": "🏴󠁧󠁢󠁥󠁮󠁧󠁿" + , "description": "flag: England" + , "category": "Flags" + , "aliases": [ + "england" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🏴󠁧󠁢󠁳󠁣󠁴󠁿" + , "description": "flag: Scotland" + , "category": "Flags" + , "aliases": [ + "scotland" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +, { + "emoji": "🏴󠁧󠁢󠁷󠁬󠁳󠁿" + , "description": "flag: Wales" + , "category": "Flags" + , "aliases": [ + "wales" + ] + , "tags": [ + ] + , "unicode_version": "11.0" + , "ios_version": "12.1" + } +] diff --git a/zsh/.oh-my-zsh/plugins/emoji/update_emoji.py b/zsh/.oh-my-zsh/plugins/emoji/update_emoji.py new file mode 100644 index 0000000..fbb633c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emoji/update_emoji.py @@ -0,0 +1,213 @@ +""" +Update Emoji.py +Refeshes OMZ emoji database based on the latest Unicode spec +""" +import re +import json + +spec = open("emoji-data.txt", "r") + +# Regexes +# regex_emoji will return, respectively: +# the code points, its type (status), the actual emoji, and its official name +regex_emoji = r"^([\w ].*?\S)\s*;\s*([\w-]+)\s*#\s*(.*?)\s(\S.*).*$" +# regex_group returns the group of subgroup that a line opens +regex_group = r"^#\s*(group|subgroup):\s*(.*)$" + +headers = """ +# emoji-char-definitions.zsh - Emoji definitions for oh-my-zsh emoji plugin +# +# This file is auto-generated by update_emoji.py. Do not edit it manually. +# +# This contains the definition for: +# $emoji - which maps character names to Unicode characters +# $emoji_flags - maps country names to Unicode flag characters using region +# indicators +# $emoji_mod - maps modifier components to Unicode characters +# $emoji_groups - a single associative array to avoid cluttering up the +# global namespace, and to allow adding additional group +# definitions at run time. The keys are the group names, and +# the values are whitespace-separated lists of emoji +# character names. + +# Main emoji +typeset -gAH emoji +# National flags +typeset -gAH emoji_flags +# Combining modifiers +typeset -gAH emoji_mod +# Emoji groups +typeset -gAH emoji_groups +""" + +####### +# Adding country codes +####### +# This is the only part of this script that relies on an external library +# (country_converter), and is hence commented out by default. +# You can uncomment it to have country codes added as aliases for flag +# emojis. (By default, when you install this extension, country codes are +# included as aliases, but not if you re-run this script without uncommenting.) +# Warning: country_converter is very verbose, and will print warnings all over +# your terminal. + +# import country_converter as coco # pylint: disable=wrong-import-position +# cc = coco.CountryConverter() + +# def country_iso(_all_names, _omz_name): +# """ Using the external library country_converter, +# this function can detect the ISO2 and ISO3 codes +# of the country. It takes as argument the array +# with all the names of the emoji, and returns that array.""" +# omz_no_underscore = re.sub(r'_', r' ', _omz_name) +# iso2 = cc.convert(names=[omz_no_underscore], to='ISO2') +# if iso2 != 'not found': +# _all_names.append(iso2) +# iso3 = cc.convert(names=[omz_no_underscore], to='ISO3') +# _all_names.append(iso3) +# return _all_names + + +####### +# Helper functions +####### + +def code_to_omz(_code_points): + """ Returns a ZSH-compatible Unicode string from the code point(s) """ + return r'\U' + r'\U'.join(_code_points.split(' ')) + +def name_to_omz(_name, _group, _subgroup, _status): + """ Returns a reasonable snake_case name for the emoji. """ + def snake_case(_string): + """ Does the regex work of snake_case """ + remove_dots = re.sub(r'\.\(\)', r'', _string) + replace_ands = re.sub(r'\&', r'and', remove_dots) + remove_whitespace = re.sub(r'[^\#\*\w]', r'_', replace_ands) + return re.sub(r'__', r'_', remove_whitespace) + + shortname = "" + split_at_colon = lambda s: s.split(": ") + # Special treatment by group and subgroup + # If the emoji is a flag, we strip "flag" from its name + if _group == "Flags" and len(split_at_colon(_name)) > 1: + shortname = snake_case(split_at_colon(_name)[1]) + else: + shortname = snake_case(_name) + # Special treatment by status + # Enables us to have every emoji combination, + # even the one that are not officially sanctionned + # and are implemented by, say, only one vendor + if _status == "unqualified": + shortname += "_unqualified" + elif _status == "minimally-qualified": + shortname += "_minimally" + return shortname + +def increment_name(_shortname): + """ Increment the short name by 1. If you get, say, + 'woman_detective_unqualified', it returns + 'woman_detective_unqualified_1', and then + 'woman_detective_unqualified_2', etc. """ + last_char = _shortname[-1] + if last_char.isdigit(): + num = int(last_char) + return _shortname[:-1] + str(num + 1) + return _shortname + "_1" + +######## +# Going through every line +######## + +group, subgroup, short_name_buffer = "", "", "" +emoji_database = [] +for line in spec: + # First, test if this line opens a group or subgroup + group_match = re.findall(regex_group, line) + if group_match != []: + gr_or_sub, name = group_match[0] + if gr_or_sub == "group": + group = name + elif gr_or_sub == "subgroup": + subgroup = name + continue # Moving on... + # Second, test if this line references one emoji + emoji_match = re.findall(regex_emoji, line) + if emoji_match != []: + code_points, status, emoji, name = emoji_match[0] + omz_codes = code_to_omz(code_points) + omz_name = name_to_omz(name, group, subgroup, status) + # If this emoji has the same shortname as the preceding one + if omz_name in short_name_buffer: + omz_name = increment_name(short_name_buffer) + short_name_buffer = omz_name + emoji_database.append( + [omz_codes, status, emoji, omz_name, group, subgroup]) +spec.close() + +######## +# Write to emoji-char-definitions.zsh +######## + +# Aliases for emojis are retrieved through the DB of Gemoji +# Retrieved on Aug 9 2019 from the following URL: +# https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json + +gemoji_db = open("gemoji_db.json") +j = json.load(gemoji_db) +aliases_map = {entry['emoji']: entry['aliases'] for entry in j} +all_omz_names = [emoji_data[3] for emoji_data in emoji_database] + +# Let's begin writing to this file +output = open("emoji-char-definitions.zsh", "w") +output.write(headers) + +emoji_groups = {"fruits": "\n", "vehicles": "\n", "hands": "\n", + "people": "\n", "animals": "\n", "faces": "\n", + "flags": "\n"} + +# First, write every emoji down +for _omz_codes, _status, _emoji, _omz_name, _group, _subgroup in emoji_database: + + # One emoji can be mapped to multiple names (aliases or country codes) + names_for_this_emoji = [_omz_name] + + # Variable that indicates in which map the emoji will be located + emoji_map = "emoji" + if _status == "component": + emoji_map = "emoji_mod" + if _group == "Flags": + emoji_map = "emoji_flags" + # Adding country codes (Optional, see above) + # names_for_this_emoji = country_iso(names_for_this_emoji, _omz_name) + + # Check if there is an alias available in the Gemoji DB + if _emoji in aliases_map.keys(): + for alias in aliases_map[_emoji]: + if alias not in all_omz_names: + names_for_this_emoji.append(alias) + + # And now we write to the definitions file + for one_name in names_for_this_emoji: + output.write(f"{emoji_map}[{one_name}]=$'{_omz_codes}'\n") + + # Storing the emoji in defined subgroups for the next step + if _status == "fully-qualified": + if _subgroup == "food-fruit": + emoji_groups["fruits"] += f" {_omz_name}\n" + elif "transport-" in _subgroup: + emoji_groups["vehicles"] += f" {_omz_name}\n" + elif "hand-" in _subgroup: + emoji_groups["hands"] += f" {_omz_name}\n" + elif "person-" in _subgroup or _subgroup == "family": + emoji_groups["people"] += f" {_omz_name}\n" + elif "animal-" in _subgroup: + emoji_groups["animals"] += f" {_omz_name}\n" + elif "face-" in _subgroup: + emoji_groups["faces"] += f" {_omz_name}\n" + elif _group == "Flags": + emoji_groups["flags"] += f" {_omz_name}\n" + +# Second, write the subgroups to the end of the file +for name, string in emoji_groups.items(): + output.write(f'\nemoji_groups[{name}]="{string}"\n') +output.close() diff --git a/zsh/.oh-my-zsh/plugins/emotty/README.md b/zsh/.oh-my-zsh/plugins/emotty/README.md new file mode 100644 index 0000000..60f7f01 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emotty/README.md @@ -0,0 +1,39 @@ +# emotty plugin + +This plugin returns an emoji for the current $TTY number so it can be used +in a prompt. + +To use it, add emotty to the plugins array in your zshrc file: +``` +plugins=(... emotty) +``` + +**NOTE:** it requires the [emoji plugin](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/emoji). + +## Usage + +The function `emotty` displays an emoji from the current character set (default: `emoji`), based +on the number associated to the `$TTY`. + +There are different sets of emoji characters available, to choose a different +set, set `$emotty_set` to the name of the set you would like to use, e.g.: +``` +emotty_set=nature +``` + +### Character Sets + +- emoji +- loral +- love +- nature +- stellar +- zodiac + +Use the `display_emotty` function to list the emojis in the current character set, or +the character set passed as the first argument. For example: + +``` +$ display_emotty zodiac + +``` diff --git a/zsh/.oh-my-zsh/plugins/emotty/emotty.plugin.zsh b/zsh/.oh-my-zsh/plugins/emotty/emotty.plugin.zsh new file mode 100644 index 0000000..be82b11 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emotty/emotty.plugin.zsh @@ -0,0 +1,55 @@ +# ------------------------------------------------------------------------------ +# FILE: emotty.plugin.zsh +# DESCRIPTION: Return an emoji for the current $TTY number. +# AUTHOR: Alexis Hildebrandt (afh[at]surryhill.net) +# VERSION: 1.0.0 +# DEPENDS: emoji plugin +# +# There are different sets of emoji characters available, to choose a different +# set export emotty_set to the name of the set you would like to use, e.g.: +# % export emotty_set=nature +# ------------------------------------------------------------------------------ + +# Handle $0 according to the standard: +# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" + +typeset -gAH _emotty_sets +local _emotty_plugin_dir="${0:h}" +source "$_emotty_plugin_dir/emotty_stellar_set.zsh" +source "$_emotty_plugin_dir/emotty_floral_set.zsh" +source "$_emotty_plugin_dir/emotty_zodiac_set.zsh" +source "$_emotty_plugin_dir/emotty_nature_set.zsh" +source "$_emotty_plugin_dir/emotty_emoji_set.zsh" +source "$_emotty_plugin_dir/emotty_love_set.zsh" +unset _emotty_plugin_dir + +emotty_default_set=emoji + +function emotty() { + # Use emotty set defined by user, fallback to default + local emotty=${_emotty_sets[${emotty_set:-$emotty_default_set}]} + + # Parse tty number via prompt expansion. %l equals: + # - N if tty = /dev/ttyN + # - pts/N if tty = /dev/pts/N + local tty=${${(%):-%l}##pts/} + # Normalize it to an emotty set index + (( tty = (tty % ${#${=emotty}}) + 1 )) + + local character_name=${${=emotty}[tty]} + echo "${emoji[${character_name}]}${emoji2[emoji_style]}" +} + +function display_emotty() { + local name=${1:-$emotty_set} + echo $name + for i in ${=_emotty_sets[$name]}; do + printf "${emoji[$i]}${emoji2[emoji_style]} " + done + print + for i in ${=_emotty_sets[$name]}; do + print "${emoji[$i]}${emoji2[emoji_style]} = $i" + done +} diff --git a/zsh/.oh-my-zsh/plugins/emotty/emotty_emoji_set.zsh b/zsh/.oh-my-zsh/plugins/emotty/emotty_emoji_set.zsh new file mode 100644 index 0000000..fd57cda --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emotty/emotty_emoji_set.zsh @@ -0,0 +1,24 @@ +#!/usr/bin/env zsh +# vim:ft=zsh ts=2 sw=2 sts=2 + +_emotty_sets[emoji]=" + crystal_ball + ghost + jack_o_lantern + see_no_evil_monkey + hear_no_evil_monkey + speak_no_evil_monkey + smiling_cat_face_with_open_mouth + extraterrestrial_alien + rocket + billiards + bomb + pill + japanese_symbol_for_beginner + direct_hit + cyclone + diamond_shape_with_a_dot_inside + sparkle + eight_spoked_asterisk + eight_pointed_black_star + " diff --git a/zsh/.oh-my-zsh/plugins/emotty/emotty_floral_set.zsh b/zsh/.oh-my-zsh/plugins/emotty/emotty_floral_set.zsh new file mode 100644 index 0000000..2319046 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emotty/emotty_floral_set.zsh @@ -0,0 +1,18 @@ +#!/usr/bin/env zsh +# vim:ft=zsh ts=2 sw=2 sts=2 + +_emotty_sets[floral]=" + hibiscus + cherry_blossom + blossom + sunflower + bouquet + tulip + rose + four_leaf_clover + seedling + herb + palm_tree + evergreen_tree + deciduous_tree + " diff --git a/zsh/.oh-my-zsh/plugins/emotty/emotty_love_set.zsh b/zsh/.oh-my-zsh/plugins/emotty/emotty_love_set.zsh new file mode 100644 index 0000000..e82c46a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emotty/emotty_love_set.zsh @@ -0,0 +1,34 @@ +#!/usr/bin/env zsh +# vim:ft=zsh ts=2 sw=2 sts=2 + +# Note: The heavy_black_heart emoji requires $emoji2[emoji_style] +# to be rendered as the emoji red heart. +_emotty_sets[love]=" + green_heart + blue_heart + purple_heart + yellow_heart + heavy_black_heart + broken_heart + heart_with_arrow + heart_with_ribbon + sparkling_heart + two_hearts + revolving_hearts + growing_heart + beating_heart + heart_decoration + couple_with_heart + kiss + man_and_woman_holding_hands + two_women_holding_hands + two_men_holding_hands + kiss_mark + smiling_face_with_heart_shaped_eyes + kissing_face + face_throwing_a_kiss + kissing_face_with_smiling_eyes + kissing_face_with_closed_eyes + smiling_cat_face_with_heart_shaped_eyes + kissing_cat_face_with_closed_eyes + " diff --git a/zsh/.oh-my-zsh/plugins/emotty/emotty_nature_set.zsh b/zsh/.oh-my-zsh/plugins/emotty/emotty_nature_set.zsh new file mode 100644 index 0000000..02fa229 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emotty/emotty_nature_set.zsh @@ -0,0 +1,58 @@ +#!/usr/bin/env zsh +# vim:ft=zsh ts=2 sw=2 sts=2 + +_emotty_sets[nature]=" + mouse_face + hamster_face + rabbit_face + dog_face + cat_face + tiger_face + bear_face + monkey_face + koala + panda_face + chicken + baby_chick + bird + penguin + cow_face + pig_face + frog_face + boar + wolf_face + horse_face + snail + bug + ant + honeybee + lady_beetle + spouting_whale + dolphin + octopus + fish + tropical_fish + snake + turtle + lemon + tangerine + peach + mushroom + tomato + strawberry + red_apple + cherries + grapes + aubergine + watermelon + banana + pineapple + melon + pear + green_apple + ear_of_maize + sunflower + seedling + herb + four_leaf_clover + " diff --git a/zsh/.oh-my-zsh/plugins/emotty/emotty_stellar_set.zsh b/zsh/.oh-my-zsh/plugins/emotty/emotty_stellar_set.zsh new file mode 100644 index 0000000..5079bf6 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emotty/emotty_stellar_set.zsh @@ -0,0 +1,25 @@ +#!/usr/bin/env zsh +# vim:ft=zsh ts=2 sw=2 sts=2 + +# NOTE: The following emoji show as $'character' in the title +# white_medium_star +# sparkles +# dizzy_symbol + +_emotty_sets[stellar]=" + full_moon_symbol + waning_gibbous_moon_symbol + waning_crescent_moon_symbol + last_quarter_moon_symbol + new_moon_symbol + new_moon_with_face + waxing_crescent_moon_symbol + first_quarter_moon_symbol + waxing_gibbous_moon_symbol + full_moon_with_face + sun_with_face + glowing_star + crescent_moon + first_quarter_moon_with_face + last_quarter_moon_with_face + " diff --git a/zsh/.oh-my-zsh/plugins/emotty/emotty_zodiac_set.zsh b/zsh/.oh-my-zsh/plugins/emotty/emotty_zodiac_set.zsh new file mode 100644 index 0000000..04762a6 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/emotty/emotty_zodiac_set.zsh @@ -0,0 +1,29 @@ +#!/usr/bin/env zsh +# vim:ft=zsh ts=2 sw=2 sts=2 + +_emotty_sets[zodiac]=" + aries + taurus + gemini + cancer + leo + virgo + libra + scorpius + sagittarius + capricorn + aquarius + pisces + rat + ox + tiger + rabbit + dragon + snake + horse + goat + monkey + rooster + dog + pig + " diff --git a/zsh/.oh-my-zsh/plugins/encode64/README.md b/zsh/.oh-my-zsh/plugins/encode64/README.md new file mode 100644 index 0000000..8a7dd40 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/encode64/README.md @@ -0,0 +1,73 @@ +# encode64 + +Alias plugin for encoding or decoding using `base64` command. + +To use it, add `encode64` to the plugins array in your zshrc file: + +```zsh +plugins=(... encode64) +``` + +## Functions and Aliases + +| Function | Alias | Description | +| -------------- | ------ | -------------------------------------- | +| `encode64` | `e64` | Encodes given data to base64 | +| `encodefile64` | `ef64` | Encodes given file's content to base64 | +| `decode64` | `d64` | Decodes given data from base64 | + +## Usage and examples + +### Encoding + +- From parameter + + ```console + $ encode64 "oh-my-zsh" + b2gtbXktenNo + $ e64 "oh-my-zsh" + b2gtbXktenNo + ``` + +- From piping + + ```console + $ echo "oh-my-zsh" | encode64 + b2gtbXktenNo== + $ echo "oh-my-zsh" | e64 + b2gtbXktenNo== + ``` + +### Encoding a file + +Encode a file's contents to base64 and save output to text file. +**NOTE:** Takes provided file and saves encoded content as new file with `.txt` extension + +- From parameter + + ```console + $ encodefile64 ohmyzsh.icn + ohmyzsh.icn's content encoded in base64 and saved as ohmyzsh.icn.txt + $ ef64 "oh-my-zsh" + ohmyzsh.icn's content encoded in base64 and saved as ohmyzsh.icn.txt + ``` + +### Decoding + +- From parameter + + ```console + $ decode64 b2gtbXktenNo + oh-my-zsh% + $ d64 b2gtbXktenNo + oh-my-zsh% + ``` + +- From piping + + ```console + $ echo "b2gtbXktenNoCg==" | decode64 + oh-my-zsh + $ echo "b2gtbXktenNoCg==" | d64 + oh-my-zsh + ``` diff --git a/zsh/.oh-my-zsh/plugins/encode64/encode64.plugin.zsh b/zsh/.oh-my-zsh/plugins/encode64/encode64.plugin.zsh new file mode 100644 index 0000000..c864ed4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/encode64/encode64.plugin.zsh @@ -0,0 +1,27 @@ +encode64() { + if [[ $# -eq 0 ]]; then + cat | base64 + else + printf '%s' $1 | base64 + fi +} + +encodefile64() { + if [[ $# -eq 0 ]]; then + echo "You must provide a filename" + else + base64 -i $1 -o $1.txt + echo "${1}'s content encoded in base64 and saved as ${1}.txt" + fi +} + +decode64() { + if [[ $# -eq 0 ]]; then + cat | base64 --decode + else + printf '%s' $1 | base64 --decode + fi +} +alias e64=encode64 +alias ef64=encodefile64 +alias d64=decode64 diff --git a/zsh/.oh-my-zsh/plugins/extract/README.md b/zsh/.oh-my-zsh/plugins/extract/README.md new file mode 100644 index 0000000..6b7ceeb --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/extract/README.md @@ -0,0 +1,65 @@ +# extract plugin + +This plugin defines a function called `extract` that extracts the archive file you pass it, and it supports a +wide variety of archive filetypes. + +This way you don't have to know what specific command extracts a file, you just do `extract ` and +the function takes care of the rest. + +To use it, add `extract` to the plugins array in your zshrc file: + +```zsh +plugins=(... extract) +``` + +## Supported file extensions + +| Extension | Description | +| :---------------- | :----------------------------------- | +| `7z` | 7zip file | +| `Z` | Z archive (LZW) | +| `apk` | Android app file | +| `aar` | Android library file | +| `bz2` | Bzip2 file | +| `cab` | Microsoft cabinet archive | +| `cpio` | Cpio archive | +| `deb` | Debian package | +| `ear` | Enterprise Application aRchive | +| `exe` | Windows executable file | +| `gz` | Gzip file | +| `ipa` | iOS app package | +| `ipsw` | iOS firmware file | +| `jar` | Java Archive | +| `lrz` | LRZ archive | +| `lz4` | LZ4 archive | +| `lzma` | LZMA archive | +| `obscpio` | cpio archive used on OBS | +| `rar` | WinRAR archive | +| `rpm` | RPM package | +| `sublime-package` | Sublime Text package | +| `tar` | Tarball | +| `tar.bz2` | Tarball with bzip2 compression | +| `tar.gz` | Tarball with gzip compression | +| `tar.lrz` | Tarball with lrzip compression | +| `tar.lz` | Tarball with lzip compression | +| `tar.lz4` | Tarball with lz4 compression | +| `tar.xz` | Tarball with lzma2 compression | +| `tar.zma` | Tarball with lzma compression | +| `tar.zst` | Tarball with zstd compression | +| `tbz` | Tarball with bzip compression | +| `tbz2` | Tarball with bzip2 compression | +| `tgz` | Tarball with gzip compression | +| `tlz` | Tarball with lzma compression | +| `txz` | Tarball with lzma2 compression | +| `tzst` | Tarball with zstd compression | +| `war` | Web Application archive (Java-based) | +| `whl` | Python wheel file | +| `xpi` | Mozilla XPI module file | +| `xz` | LZMA2 archive | +| `zip` | Zip archive | +| `zlib` | zlib archive | +| `zst` | Zstandard file (zstd) | +| `zpaq` | Zpaq file | + +See [list of archive formats](https://en.wikipedia.org/wiki/List_of_archive_formats) for more information +regarding archive formats. diff --git a/zsh/.oh-my-zsh/plugins/extract/_extract b/zsh/.oh-my-zsh/plugins/extract/_extract new file mode 100644 index 0000000..9118434 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/extract/_extract @@ -0,0 +1,7 @@ +#compdef extract +#autoload + +_arguments \ + '(-r --remove)'{-r,--remove}'[Remove archive.]' \ + "*::archive file:_files -g '(#i)*.(7z|Z|apk|aar|bz2|cab|cpio|deb|ear|gz|ipa|ipsw|jar|lrz|lz4|lzma|obscpio|rar|rpm|sublime-package|tar|tar.bz2|tar.gz|tar.lrz|tar.lz|tar.lz4|tar.xz|tar.zma|tar.zst|tbz|tbz2|tgz|tlz|txz|tzst|war|whl|xpi|xz|zip|zst|zpaq)(-.)'" \ + && return 0 diff --git a/zsh/.oh-my-zsh/plugins/extract/extract.plugin.zsh b/zsh/.oh-my-zsh/plugins/extract/extract.plugin.zsh new file mode 100644 index 0000000..59742ac --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/extract/extract.plugin.zsh @@ -0,0 +1,137 @@ +alias x=extract + +extract() { + setopt localoptions noautopushd + + if (( $# == 0 )); then + cat >&2 <<'EOF' +Usage: extract [-option] [file ...] + +Options: + -r, --remove Remove archive after unpacking. +EOF + fi + + local remove_archive=1 + if [[ "$1" == "-r" ]] || [[ "$1" == "--remove" ]]; then + remove_archive=0 + shift + fi + + local pwd="$PWD" + while (( $# > 0 )); do + if [[ ! -f "$1" ]]; then + echo "extract: '$1' is not a valid file" >&2 + shift + continue + fi + + local success=0 + local file="$1" full_path="${1:A}" + local extract_dir="${1:t:r}" + + # Remove the .tar extension if the file name is .tar.* + if [[ $extract_dir =~ '\.tar$' ]]; then + extract_dir="${extract_dir:r}" + fi + + # If there's a file or directory with the same name as the archive + # add a random string to the end of the extract directory + if [[ -e "$extract_dir" ]]; then + local rnd="${(L)"${$(( [##36]$RANDOM*$RANDOM ))}":1:5}" + extract_dir="${extract_dir}-${rnd}" + fi + + # Create an extraction directory based on the file name + command mkdir -p "$extract_dir" + builtin cd -q "$extract_dir" + echo "extract: extracting to $extract_dir" >&2 + + case "${file:l}" in + (*.tar.gz|*.tgz) + (( $+commands[pigz] )) && { tar -I pigz -xvf "$full_path" } || tar zxvf "$full_path" ;; + (*.tar.bz2|*.tbz|*.tbz2) + (( $+commands[pbzip2] )) && { tar -I pbzip2 -xvf "$full_path" } || tar xvjf "$full_path" ;; + (*.tar.xz|*.txz) + (( $+commands[pixz] )) && { tar -I pixz -xvf "$full_path" } || { + tar --xz --help &> /dev/null \ + && tar --xz -xvf "$full_path" \ + || xzcat "$full_path" | tar xvf - } ;; + (*.tar.zma|*.tlz) + tar --lzma --help &> /dev/null \ + && tar --lzma -xvf "$full_path" \ + || lzcat "$full_path" | tar xvf - ;; + (*.tar.zst|*.tzst) + tar --zstd --help &> /dev/null \ + && tar --zstd -xvf "$full_path" \ + || zstdcat "$full_path" | tar xvf - ;; + (*.tar) tar xvf "$full_path" ;; + (*.tar.lz) (( $+commands[lzip] )) && tar xvf "$full_path" ;; + (*.tar.lz4) lz4 -c -d "$full_path" | tar xvf - ;; + (*.tar.lrz) (( $+commands[lrzuntar] )) && lrzuntar "$full_path" ;; + (*.gz) (( $+commands[pigz] )) && pigz -cdk "$full_path" > "${file:t:r}" || gunzip -ck "$full_path" > "${file:t:r}" ;; + (*.bz2) (( $+commands[pbzip2] )) && pbzip2 -d "$full_path" || bunzip2 "$full_path" ;; + (*.xz) unxz "$full_path" ;; + (*.lrz) (( $+commands[lrunzip] )) && lrunzip "$full_path" ;; + (*.lz4) lz4 -d "$full_path" ;; + (*.lzma) unlzma "$full_path" ;; + (*.z) uncompress "$full_path" ;; + (*.zip|*.war|*.jar|*.ear|*.sublime-package|*.ipa|*.ipsw|*.xpi|*.apk|*.aar|*.whl) unzip "$full_path" ;; + (*.rar) unrar x -ad "$full_path" ;; + (*.rpm) + rpm2cpio "$full_path" | cpio --quiet -id ;; + (*.7z | *.7z.[0-9]*) 7za x "$full_path" ;; + (*.deb) + command mkdir -p "control" "data" + ar vx "$full_path" > /dev/null + builtin cd -q control; extract ../control.tar.* + builtin cd -q ../data; extract ../data.tar.* + builtin cd -q ..; command rm *.tar.* debian-binary ;; + (*.zst) unzstd --stdout "$full_path" > "${file:t:r}" ;; + (*.cab|*.exe) cabextract "$full_path" ;; + (*.cpio|*.obscpio) cpio -idmvF "$full_path" ;; + (*.zpaq) zpaq x "$full_path" ;; + (*.zlib) zlib-flate -uncompress < "$full_path" > "${file:r}" ;; + (*) + echo "extract: '$file' cannot be extracted" >&2 + success=1 ;; + esac + + (( success = success > 0 ? success : $? )) + (( success == 0 && remove_archive == 0 )) && command rm "$full_path" + shift + + # Go back to original working directory + builtin cd -q "$pwd" + + # If content of extract dir is a single directory, move its contents up + # Glob flags: + # - D: include files starting with . + # - N: no error if directory is empty + # - Y2: at most give 2 files + local -a content + content=("${extract_dir}"/*(DNY2)) + if [[ ${#content} -eq 1 && -e "${content[1]}" ]]; then + # The extracted file/folder (${content[1]}) may have the same name as $extract_dir + # If so, we need to rename it to avoid conflicts in a 3-step process + # + # 1. Move and rename the extracted file/folder to a temporary random name + # 2. Delete the empty folder + # 3. Rename the extracted file/folder to the original name + if [[ "${content[1]:t}" == "$extract_dir" ]]; then + # =(:) gives /tmp/zsh, with :t it gives zsh + local tmp_name==(:); tmp_name="${tmp_name:t}" + command mv "${content[1]}" "$tmp_name" \ + && command rmdir "$extract_dir" \ + && command mv "$tmp_name" "$extract_dir" + # Otherwise, if the extracted folder name already exists in the current + # directory (because of a previous file / folder), keep the extract_dir + elif [[ ! -e "${content[1]:t}" ]]; then + command mv "${content[1]}" . \ + && command rmdir "$extract_dir" + fi + elif [[ ${#content} -eq 0 ]]; then + command rmdir "$extract_dir" + fi + done +} diff --git a/zsh/.oh-my-zsh/plugins/eza/README.md b/zsh/.oh-my-zsh/plugins/eza/README.md new file mode 100644 index 0000000..6b82503 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/eza/README.md @@ -0,0 +1,111 @@ +# eza plugin + +This provides aliases that invoke the [`eza`](https://github.com/eza-community/eza) utility rather than `ls` + +To use it add `eza` to the plugins array in your zshrc file: + +```zsh +plugins=(... eza) +``` + +## Configuration + +All configurations are done using the `zstyle` command in the `:omz:plugins:eza` namespace. + +**NOTE:** The configuring needs to be done prior to OMZ loading the plugins. When the plugin is loaded, +changing the `zstyle` won't have any effect. + +### `dirs-first` + +```zsh +zstyle ':omz:plugins:eza' 'dirs-first' yes|no +``` + +If `yes`, directories will be grouped first. + +Default: `no` + +### `git-status` + +```zsh +zstyle ':omz:plugins:eza' 'git-status' yes|no +``` + +If `yes`, always add `--git` flag to indicate git status (if tracked / in a git repo). + +Default: `no` + +### `header` + +```zsh +zstyle ':omz:plugins:eza' 'header' yes|no +``` + +If `yes`, always add `-h` flag to add a header row for each column. + +Default: `no` + +### `show-group` + +```zsh +zstyle ':omz:plugins:eza' 'show-group' yes|no +``` + +If `yes` (default), always add `-g` flag to show the group ownership. + +Default: `yes` + +### `icons` + +```zsh +zstyle ':omz:plugins:eza' 'icons' yes|no +``` + +If `yes`, sets the `--icons` option of `eza`, adding icons for files and folders. + +Default: `no` + +### `size-prefix` + +```zsh +zstyle ':omz:plugins:eza' 'size-prefix' (binary|none|si) +``` + +Choose the prefix to be used in displaying file size: + +- `binary` -- use [binary prefixes](https://en.wikipedia.org/wiki/Binary_prefix) such as "Ki", "Mi", "Gi" and + so on +- `none` -- don't use any prefix, show size in bytes +- `si` (default) -- use [Metric/S.I. prefixes](https://en.wikipedia.org/wiki/Metric_prefix) + +Default: `si` + +### `time-style` + +```zsh +zstyle ':omz:plugins:eza' 'time-style' $TIME_STYLE +``` + +Sets the `--time-style` option of `eza`. (See `man eza` for the options) + +Default: Not set, which means the default behavior of `eza` will take place. + +## Aliases + +**Notes:** + +- Aliases may be modified by Configuration +- The term "files" without "only" qualifier means both files & directories + +| Alias | Command | Description | +| ------ | ----------------- | -------------------------------------------------------------------------- | +| `la` | `eza -la` | List all files (except . and ..) as a long list | +| `ldot` | `eza -ld .*` | List dotfiles only (directories shown as entries instead of recursed into) | +| `lD` | `eza -lD` | List only directories (excluding dotdirs) as a long list | +| `lDD` | `eza -laD` | List only directories (including dotdirs) as a long list | +| `ll` | `eza -l` | List files as a long list | +| `ls` | `eza` | Plain eza call | +| `lsd` | `eza -d` | List specified files with directories as entries, in a grid | +| `lsdl` | `eza -dl` | List specified files with directories as entries, in a long list | +| `lS` | `eza -l -ssize` | List files as a long list, sorted by size | +| `lT` | `eza -l -snewest` | List files as a long list, sorted by date (newest last) | diff --git a/zsh/.oh-my-zsh/plugins/eza/eza.plugin.zsh b/zsh/.oh-my-zsh/plugins/eza/eza.plugin.zsh new file mode 100644 index 0000000..3a60490 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/eza/eza.plugin.zsh @@ -0,0 +1,65 @@ +if ! (( $+commands[eza] )); then + print "zsh eza plugin: eza not found. Please install eza before using this plugin." >&2 + return 1 +fi + +typeset -a _EZA_HEAD +typeset -a _EZA_TAIL + +function _configure_eza() { + local _val + # Get the head flags + if zstyle -T ':omz:plugins:eza' 'show-group'; then + _EZA_HEAD+=("g") + fi + if zstyle -t ':omz:plugins:eza' 'header'; then + _EZA_HEAD+=("h") + fi + zstyle -s ':omz:plugins:eza' 'size-prefix' _val + case "${_val:l}" in + binary) + _EZA_HEAD+=("b") + ;; + none) + _EZA_HEAD+=("B") + ;; + esac + # Get the tail long-options + if zstyle -t ':omz:plugins:eza' 'dirs-first'; then + _EZA_TAIL+=("--group-directories-first") + fi + if zstyle -t ':omz:plugins:eza' 'git-status'; then + _EZA_TAIL+=("--git") + fi + if zstyle -t ':omz:plugins:eza' 'icons'; then + _EZA_TAIL+=("--icons=auto") + fi + zstyle -s ':omz:plugins:eza' 'time-style' _val + if [[ $_val ]]; then + _EZA_TAIL+=("--time-style='$_val'") + fi +} + +_configure_eza + +function _alias_eza() { + local _head="${(j::)_EZA_HEAD}$2" + local _tail="${(j: :)_EZA_TAIL}" + alias "$1"="eza${_head:+ -}${_head}${_tail:+ }${_tail}${3:+ }$3" +} + +_alias_eza la la +_alias_eza ldot ld ".*" +_alias_eza lD lD +_alias_eza lDD lDa +_alias_eza ll l +_alias_eza ls +_alias_eza lsd d +_alias_eza lsdl dl +_alias_eza lS "l -ssize" +_alias_eza lT "l -snewest" + +unfunction _alias_eza +unfunction _configure_eza +unset _EZA_HEAD +unset _EZA_TAIL diff --git a/zsh/.oh-my-zsh/plugins/fabric/README.md b/zsh/.oh-my-zsh/plugins/fabric/README.md new file mode 100644 index 0000000..f4133d5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fabric/README.md @@ -0,0 +1,9 @@ +# Fabric + +This plugin provides completion for [Fabric](https://www.fabfile.org/). + +To use it add fabric to the plugins array in your zshrc file. + +```zsh +plugins=(... fabric) +``` diff --git a/zsh/.oh-my-zsh/plugins/fabric/_fab b/zsh/.oh-my-zsh/plugins/fabric/_fab new file mode 100644 index 0000000..da7a114 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fabric/_fab @@ -0,0 +1,69 @@ +#compdef fab +#autoload + +local curcontext=$curcontext state line +declare -A opt_args + +declare -a target_list +target_list=("${(@f)$(fab -l 2>/dev/null | awk '{ + if (NF == 0 || NR == 1) next + if (NF < 2) print $1 + else { + docstring=substr($0, index($0,$2)) + gsub(":", "\\:", docstring) + print $1":"docstring + } +}')}") + +_fab_targets() { + [[ -n "$target_list" ]] || return + _describe -t commands "fabric targets" target_list +} + +output_levels=( + 'status: Status messages, i.e. noting when Fabric is done running, if the user used a keyboard interrupt, or when servers are disconnected from. These messages are almost always relevant and rarely verbose.' + 'aborts: Abort messages. Like status messages, these should really only be turned off when using Fabric as a library, and possibly not even then. Note that even if this output group is turned off, aborts will still occur – there just won’t be any output about why Fabric aborted!' + 'warnings: Warning messages. These are often turned off when one expects a given operation to fail, such as when using grep to test existence of text in a file. If paired with setting env.warn_only to True, this can result in fully silent warnings when remote programs fail. As with aborts, this setting does not control actual warning behavior, only whether warning messages are printed or hidden.' + 'running: Printouts of commands being executed or files transferred, e.g. [myserver] run: ls /var/www. Also controls printing of tasks being run, e.g. [myserver] Executing task ''foo''.' + 'stdout: Local, or remote, stdout, i.e. non-error output from commands.' + 'stderr: Local, or remote, stderr, i.e. error-related output from commands.' + 'user: User-generated output, i.e. local output printed by fabfile code via use of the fastprint or puts functions.' +) + +_arguments -w -S -C \ + '(-)'{-h,--help}'[show this help message and exit]: :->noargs' \ + '(-)'{-V,--version}'[show program''s version number and exit]: :->noargs' \ + '(-)--list[print list of possible commands and exit]: :->noargs' \ + '(-)--shortlist[print non-verbose list of possible commands and exit]: :->noargs' \ + '(--reject-unknown-hosts)--reject-unknown-hosts[reject unknown hosts]' \ + '(--no-pty)--no-pty[do not use pseudo-terminal in run/sudo]' \ + "(-d+ --display=-)"{-d+,--display=-}"[print detailed info about a given command]: :_fab_targets" \ + '(-D --disable-known-hosts)'{-D,--disable-known-hosts}'[do not load user known_hosts file]' \ + '(-r --reject-unknown-hosts)'{-r,--reject-unknown-hosts}'[reject unknown hosts]' \ + '(-u+ --user=-)'{-u+,--user=-}'[username to use when connecting to remote hosts]: :' \ + '(-p+ --password=-)'{-p+,--password=-}'[password for use with authentication and/or sudo]: :' \ + '(-H+ --hosts=-)'{-H+,--hosts=-}'[comma separated list of hosts to operate on]: :' \ + '(-R+ --roles=-)'{-R+,--roles=-}'[comma separated list of roles to operate on]: :' \ + '(-a --no-agent)'{-a,--no-agent}'[don''t use the running SSH agent]' \ + '(-k --no-keys)'{-k,--no-keys}'[don''t load private key files from ~/.ssh/]' \ + '(-w --warn-only)'{-w,--warn-only}'[warn instead of abort, when commands fail]' \ + '-i+[path to SSH private key file. May be repeated]: :_files' \ + "(-f+ --fabfile=)"{-f+,--fabfile=}"[Python module file to import]: :_files -g *.py" \ + '(-c+ --config=-)'{-c+,--config=-}'[specify location of config file to use]: :_files' \ + '(-s+ --shell=-)'{-s+,--shell=-}'[specify a new shell, defaults to ''/bin/bash -l -c'']: :' \ + '(--hide=-)--hide=-[comma-separated list of output levels to hide]: :->levels' \ + '(--show=-)--show=-[comma-separated list of output levels to show]: :->levels' \ + '*::: :->subcmds' && return 0 + +if [[ CURRENT -ge 1 ]]; then + case $state in + noargs) + _message "nothing to complete";; + levels) + _describe -t commands "output levels" output_levels;; + *) + _fab_targets;; + esac + + return +fi diff --git a/zsh/.oh-my-zsh/plugins/fabric/fabric.plugin.zsh b/zsh/.oh-my-zsh/plugins/fabric/fabric.plugin.zsh new file mode 100644 index 0000000..473a0f4 diff --git a/zsh/.oh-my-zsh/plugins/fancy-ctrl-z/README.md b/zsh/.oh-my-zsh/plugins/fancy-ctrl-z/README.md new file mode 100644 index 0000000..cd06049 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fancy-ctrl-z/README.md @@ -0,0 +1,14 @@ +# Use Ctrl-Z to switch back to Vim + +I frequently need to execute random commands in my shell. To achieve it I pause +Vim by pressing Ctrl-z, type command and press fg to switch back to Vim. +The fg part really hurts me. I just wanted to hit Ctrl-z once again to get back +to Vim. I could not find a solution, so I developed one on my own that +works wonderfully with ZSH. + +Source: http://sheerun.net/2014/03/21/how-to-boost-your-vim-productivity/ + +Credits: +- original idea by @sheerun +- added to OMZ by @mbologna + diff --git a/zsh/.oh-my-zsh/plugins/fancy-ctrl-z/fancy-ctrl-z.plugin.zsh b/zsh/.oh-my-zsh/plugins/fancy-ctrl-z/fancy-ctrl-z.plugin.zsh new file mode 100644 index 0000000..d2f2ef8 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fancy-ctrl-z/fancy-ctrl-z.plugin.zsh @@ -0,0 +1,12 @@ +fancy-ctrl-z () { + if [[ $#BUFFER -eq 0 ]]; then + BUFFER="fg" + zle accept-line -w + else + zle push-input -w + zle clear-screen -w + fi +} +zle -N fancy-ctrl-z +bindkey '^Z' fancy-ctrl-z + diff --git a/zsh/.oh-my-zsh/plugins/fasd/README.md b/zsh/.oh-my-zsh/plugins/fasd/README.md new file mode 100644 index 0000000..e480562 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fasd/README.md @@ -0,0 +1,21 @@ +# fasd + +[`Fasd`](https://github.com/clvv/fasd) (pronounced similar to "fast") is a command-line productivity booster. Fasd offers quick access to files and directories for POSIX shells. + +To use it, add `fasd` to the plugins array in your zshrc file: + +```zsh +plugins=(... fasd) +``` + +## Installation + +Please find detailed installation guide [`here`](https://github.com/whjvenyl/fasd#install) + +## Aliases + +| Alias | Command | Description | +|-------|-------------------------------------------|-------------------------------------------------------------| +| v | `fasd -f -e "$EDITOR"` | List frequent/recent files matching the given filename. | +| o | `fasd -a -e xdg-open` | List frequent/recent files and directories matching. | +| j | `fasd_cd -d -i` | cd with interactive selection | diff --git a/zsh/.oh-my-zsh/plugins/fasd/fasd.plugin.zsh b/zsh/.oh-my-zsh/plugins/fasd/fasd.plugin.zsh new file mode 100644 index 0000000..7842261 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fasd/fasd.plugin.zsh @@ -0,0 +1,16 @@ +# check if fasd is installed +if (( ! ${+commands[fasd]} )); then + return +fi + +fasd_cache="${ZSH_CACHE_DIR}/fasd-init-cache" +if [[ "$commands[fasd]" -nt "$fasd_cache" || ! -s "$fasd_cache" ]]; then + fasd --init posix-alias zsh-hook zsh-ccomp zsh-ccomp-install \ + zsh-wcomp zsh-wcomp-install >| "$fasd_cache" +fi +source "$fasd_cache" +unset fasd_cache + +alias v='f -e "$EDITOR"' +alias o='a -e xdg-open' +alias j='zz' diff --git a/zsh/.oh-my-zsh/plugins/fastfile/README.md b/zsh/.oh-my-zsh/plugins/fastfile/README.md new file mode 100644 index 0000000..4740a8c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fastfile/README.md @@ -0,0 +1,85 @@ +# Fastfile plugin + +This plugin adds a way to reference certain files or folders used frequently using +a global alias or shortcut. + +To use it, add `fastfile` to the plugins array in your zshrc file: + +```zsh +plugins=(... fastfile) +``` + +## Usage + +Example: you access folder `/code/project/backend/database` very frequently. + +First, generate a shortcut with the name `pjdb`: + +```zsh +$ fastfile pjdb /code/project/backend/database +``` + +Next time you want to access it, use `§pjdb`. For example: + +```zsh +$ cd §pjdb +$ subl §pjdb +``` + +where § is the fastfile prefix (see [below](#options) for how to change). + +**Note:** shortcuts with spaces in the name are assigned a global alias +where the spaces have been substituted with underscores (`_`). For example: +a shortcut named `"hello world"` corresponds with `§hello_world`. + +## Functions + +- `fastfile [path/to/file/or/folder]`: generate a shortcut. + If the second argument is not provided, the current directory is used. + +- `fastfile_print `: prints a shortcut, with the format + ` -> `. + +- `fastfile_ls`: lists all shortcuts. + +- `fastfile_rm `: remove a shortcut. + +- `fastfile_sync`: generates the global aliases for the shortcuts. + +### Internal functions + +- `fastfile_resolv `: resolves the location of the shortcut + file, i.e., the file in the fastfile directory where the shortcut path + is stored. + +- `fastfile_get `: get the real path of the shortcut. + +## Aliases + +| Alias | Function | +|--------|------------------| +| ff | `fastfile` | +| ffp | `fastfile_print` | +| ffrm | `fastfile_rm` | +| ffls | `fastfile_ls` | +| ffsync | `fastfile_sync` | + +## Options + +These are options you can set to change certain parts of the plugin. To change +them, add `=` to your zshrc file, before Oh My Zsh is sourced. +For example: `fastfile_var_prefix='@'`. + +- `fastfile_var_prefix`: prefix for the global aliases created. Controls the prefix of the + created global aliases. + **Default:** `§` (section sign), easy to type in a german keyboard via the combination + [`⇧ Shift`+`3`](https://en.wikipedia.org/wiki/German_keyboard_layout#/media/File:KB_Germany.svg), + or using `⌥ Option`+`6` in macOS. + +- `fastfile_dir`: directory where the fastfile shortcuts are stored. Needs to end + with a trailing slash. + **Default:** `$HOME/.fastfile/`. + +## Author + +- [Karolin Varner](https://github.com/koraa) diff --git a/zsh/.oh-my-zsh/plugins/fastfile/fastfile.plugin.zsh b/zsh/.oh-my-zsh/plugins/fastfile/fastfile.plugin.zsh new file mode 100644 index 0000000..2a9470f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fastfile/fastfile.plugin.zsh @@ -0,0 +1,128 @@ +########################### +# Settings + +# These can be overwritten any time. +# If they are not set yet, they will be +# overwritten with their default values + +default fastfile_dir "${HOME}/.fastfile" +default fastfile_var_prefix "§" + +########################### +# Impl + +# +# Generate a shortcut +# +# Arguments: +# 1. name - The name of the shortcut (default: name of the file) +# 2. file - The file or directory to make the shortcut for +# STDOUT: +# => fastfile_print +# +function fastfile() { + test "$2" || 2="." + file=$(readlink -f "$2") + + test "$1" || 1="$(basename "$file")" + name=$(echo "$1" | tr " " "_") + + + mkdir -p "${fastfile_dir}" + echo "$file" > "$(fastfile_resolv "$name")" + + fastfile_sync + fastfile_print "$name" +} + +# +# Resolve the location of a shortcut file (the database file, where the value is written!) +# +# Arguments: +# 1. name - The name of the shortcut +# STDOUT: +# The path to the shortcut file +# +function fastfile_resolv() { + echo "${fastfile_dir}/${1}" +} + +# +# Get the real path of a shortcut +# +# Arguments: +# 1. name - The name of the shortcut +# STDOUT: +# The path +# +function fastfile_get() { + cat "$(fastfile_resolv "$1")" +} + +# +# Print a shortcut +# +# Arguments: +# 1. name - The name of the shortcut +# STDOUT: +# Name and value of the shortcut +# +function fastfile_print() { + echo "${fastfile_var_prefix}${1} -> $(fastfile_get "$1")" +} + +# +# List all shortcuts +# +# STDOUT: +# (=> fastfile_print) for each shortcut +# +function fastfile_ls() { + for f in "${fastfile_dir}"/*(N); do + file=$(basename "$f") # To enable simpler handling of spaces in file names + varkey=$(echo "$file" | tr " " "_") + + # Special format for columns + echo "${fastfile_var_prefix}${varkey}|->|$(fastfile_get "$file")" + done | column -t -s "|" +} + +# +# Remove a shortcut +# +# Arguments: +# 1. name - The name of the shortcut (default: name of the file) +# STDOUT: +# => fastfile_print +# +function fastfile_rm() { + fastfile_print "$1" + rm "$(fastfile_resolv "$1")" + unalias "${fastfile_var_prefix}${1}" +} + +# +# Generate the aliases for the shortcuts +# +function fastfile_sync() { + for f in "${fastfile_dir}"/*(N); do + file=$(basename "$f") # To enable simpler handling of spaces in file names + varkey=$(echo "$file" | tr " " "_") + + alias -g "${fastfile_var_prefix}${varkey}"="'$(fastfile_get "$file")'" + done +} + +################################## +# Shortcuts + +alias ff=fastfile +alias ffp=fastfile_print +alias ffrm=fastfile_rm +alias ffls=fastfile_ls +alias ffsync=fastfile_sync + +################################## +# Init + +fastfile_sync diff --git a/zsh/.oh-my-zsh/plugins/fbterm/README.md b/zsh/.oh-my-zsh/plugins/fbterm/README.md new file mode 100644 index 0000000..1398c54 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fbterm/README.md @@ -0,0 +1,10 @@ +# fbterm + +This plugin automatically starts [fbterm](https://github.com/zhangyuanwei/fbterm) +if on a real TTY (`/dev/tty*`). + +To use it, add `fbterm` to the plugins array of your zshrc file: + +```zsh +plugins=(... fbterm) +``` diff --git a/zsh/.oh-my-zsh/plugins/fbterm/fbterm.plugin.zsh b/zsh/.oh-my-zsh/plugins/fbterm/fbterm.plugin.zsh new file mode 100644 index 0000000..5b36aa8 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fbterm/fbterm.plugin.zsh @@ -0,0 +1,7 @@ +# start fbterm automatically in /dev/tty* + +if (( ${+commands[fbterm]} )); then + if [[ "$TTY" = /dev/tty* ]] ; then + fbterm && exit + fi +fi diff --git a/zsh/.oh-my-zsh/plugins/fd/README.md b/zsh/.oh-my-zsh/plugins/fd/README.md new file mode 100644 index 0000000..4617a63 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fd/README.md @@ -0,0 +1,9 @@ +# fd + +This plugin adds completion for the file search tool [`fd`](https://github.com/sharkdp/fd), also known as `fd-find`. + +To use it, add `fd` to the plugins array in your zshrc file: + +```zsh +plugins=(... fd) +``` diff --git a/zsh/.oh-my-zsh/plugins/fd/_fd b/zsh/.oh-my-zsh/plugins/fd/_fd new file mode 100644 index 0000000..2117e7c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fd/_fd @@ -0,0 +1,273 @@ +#compdef fd + +## +# zsh completion function for fd +# +# Based on ripgrep completion function. +# Originally based on code from the zsh-users project — see copyright notice +# below. + +autoload -U is-at-least + +_fd() { + local curcontext="$curcontext" no='!' ret=1 + local -a context line state state_descr _arguments_options fd_types fd_args + local -A opt_args + + if is-at-least 5.2; then + _arguments_options=( -s -S ) + else + _arguments_options=( -s ) + fi + + fd_types=( + {f,file}'\:"regular files"' + {d,directory}'\:"directories"' + {l,symlink}'\:"symbolic links"' + {e,empty}'\:"empty files or directories"' + {x,executable}'\:"executable (files)"' + {s,socket}'\:"sockets"' + {p,pipe}'\:"named pipes (FIFOs)"' + ) + + # Do not complete rare options unless either the current prefix + # matches one of those options or the user has the `complete-all` + # style set. Note that this prefix check has to be updated manually to account + # for all of the potential negation options listed below! + if + # (--[bpsu]* => match all options marked with '$no') + [[ $PREFIX$SUFFIX == --[bopsu]* ]] || + zstyle -t ":complete:$curcontext:*" complete-all + then + no= + fi + + # We make heavy use of argument groups here to prevent the option specs from + # growing unwieldy. These aren't supported in zsh <5.4, though, so we'll strip + # them out below if necessary. This makes the exclusions inaccurate on those + # older versions, but oh well — it's not that big a deal + fd_args=( + + '(hidden)' # hidden files + {-H,--hidden}'[search hidden files/directories]' + + + '(no-ignore-full)' # all ignore files + '(no-ignore-partial)'{-I,--no-ignore}"[don't respect .(git|fd)ignore and global ignore files]" + $no'(no-ignore-partial)*'{-u,--unrestricted}'[alias for --no-ignore, when repeated also alias for --hidden]' + + + no-ignore-partial # some ignore files + "(no-ignore-full --no-ignore-vcs)--no-ignore-vcs[don't respect .gitignore files]" + "!(no-ignore-full --no-global-ignore-file)--no-global-ignore-file[don't respect the global ignore file]" + $no'(no-ignore-full --no-ignore-parent)--no-ignore-parent[]' + + + '(case)' # case-sensitivity + {-s,--case-sensitive}'[perform a case-sensitive search]' + {-i,--ignore-case}'[perform a case-insensitive search]' + + + '(regex-pattern)' # regex-based search pattern + '(no-regex-pattern)--regex[perform a regex-based search (default)]' + + + '(no-regex-pattern)' # non-regex-based search pattern + {-g,--glob}'[perform a glob-based search]' + {-F,--fixed-strings}'[treat pattern as literal string instead of a regex]' + + + '(match-full)' # match against full path + {-p,--full-path}'[match the pattern against the full path instead of the basename]' + + + '(follow)' # follow symlinks + {-L,--follow}'[follow symbolic links to directories]' + + + '(abs-path)' # show absolute paths + '(long-listing)'{-a,--absolute-path}'[show absolute paths instead of relative paths]' + + + '(null-sep)' # use null separator for output + '(long-listing)'{-0,--print0}'[separate search results by the null character]' + + + '(long-listing)' # long-listing output + '(abs-path null-sep max-results exec-cmds)'{-l,--list-details}'[use a long listing format with file metadata]' + + + '(max-results)' # max number of results + '(long-listing exec-cmds)--max-results=[limit number of search results to given count and quit]:count' + '(long-listing exec-cmds)-1[limit to a single search result and quit]' + + + '(fs-errors)' # file-system errors + $no'--show-errors[enable the display of filesystem errors]' + + + '(fs-traversal)' # file-system traversal + $no"--one-file-system[don't descend into directories on other file systems]" + '!--mount' + '!--xdev' + + + dir-depth # directory depth + '(--exact-depth -d --max-depth)'{-d+,--max-depth=}'[set max directory depth to descend when searching]:depth' + '!(--exact-depth -d --max-depth)--maxdepth:depth' + '(--exact-depth --min-depth)--min-depth=[set directory depth to descend before start searching]:depth' + '(--exact-depth -d --max-depth --maxdepth --min-depth)--exact-depth=[only search at the exact given directory depth]:depth' + + + prune # pruning + "--prune[don't traverse into matching directories]" + + + filter-misc # filter search + '*'{-t+,--type=}"[filter search by type]:type:(($fd_types))" + '*'{-e+,--extension=}'[filter search by file extension]:extension' + '*'{-E+,--exclude=}'[exclude files/directories that match the given glob pattern]:glob pattern' + '*'{-S+,--size=}'[limit search by file size]:size limit:->size' + '(-o --owner)'{-o+,--owner=}'[filter by owning user and/or group]:owner and/or group:->owner' + + + ignore-file # extra ignore files + '*--ignore-file=[add a custom, low-precedence ignore-file with .gitignore format]: :_files' + + + '(filter-mtime-newer)' # filter by files modified after than + '--changed-within=[limit search to files/directories modified within the given date/duration]:date or duration' + '!--change-newer-than=:date/duration' + '!--newer=:date/duration' + + + '(filter-mtime-older)' # filter by files modified before than + '--changed-before=[limit search to files/directories modified before the given date/duration]:date or duration' + '!--change-older-than=:date/duration' + '!--older=:date/duration' + + + '(color)' # colorize output + {-c+,--color=}'[declare when to colorize search results]:when to colorize:(( + auto\:"show colors if the output goes to an interactive console (default)" + never\:"do not use colorized output" + always\:"always use colorized output" + ))' + + + '(threads)' + {-j+,--threads=}'[set the number of threads for searching and executing]:number of threads' + + + '(exec-cmds)' # execute command + '(long-listing max-results)'{-x+,--exec=}'[execute command for each search result]:command: _command_names -e:*\;::program arguments: _normal' + '(long-listing max-results)'{-X+,--exec-batch=}'[execute command for all search results at once]:command: _command_names -e:*\;::program arguments: _normal' + '(long-listing max-results)--batch-size=[max number of args for each -X call]:size' + + + other + '!(--max-buffer-time)--max-buffer-time=[set amount of time to buffer before showing output]:time (ms)' + + + '(about)' # about flags + '(: * -)'{-h,--help}'[display help message]' + '(: * -)'{-v,--version}'[display version information]' + + + path-sep # set path separator for output + $no'(--path-separator)--path-separator=[set the path separator to use when printing file paths]:path separator' + + + search-path + $no'(--base-directory)--base-directory=[change the current working directory to the given path]:directory:_files -/' + $no'(*)*--search-path=[set search path (instead of positional arguments)]:directory:_files -/' + + + strip-cwd-prefix + $no'(strip-cwd-prefix exec-cmds)--strip-cwd-prefix[Strip ./ prefix when output is redirected]' + + + args # positional arguments + '1: :_guard "^-*" pattern' + '(--search-path)*:directory:_files -/' + ) + + # Strip out argument groups where unsupported (see above) + is-at-least 5.4 || + fd_args=( ${(@)args:#(#i)(+|[a-z0-9][a-z0-9_-]#|\([a-z0-9][a-z0-9_-]#\))} ) + + _arguments $_arguments_options : $fd_args && ret=0 + + case ${state} in + owner) + compset -P '(\\|)\!' + if compset -P '*:'; then + _groups && ret=0 + else + if + compset -S ':*' || + # Do not add the colon suffix when completing "!user + # (with a starting double-quote) otherwise pressing tab again + # after the inserted colon "!user: will complete history modifiers + [[ $IPREFIX == (\\|\!)* && ($QIPREFIX == \"* && -z $QISUFFIX) ]] + then + _users && ret=0 + else + local q + # Since quotes are needed when using the negation prefix !, + # automatically remove the colon suffix also when closing the quote + if [[ $QIPREFIX == [\'\"]* ]]; then + q=${QIPREFIX:0:1} + fi + _users -r ": \t\n\-$q" -S : && ret=0 + fi + fi + ;; + + size) + if compset -P '[-+][0-9]##'; then + local -a suff=( + 'B:bytes' + 'K:kilobytes (10^3 = 1000 bytes)' + 'M:megabytes (10^6 = 1000^2 bytes)' + 'G:gigabytes (10^9 = 1000^3 bytes)' + 'T:terabytes (10^12 = 1000^4 bytes)' + 'Ki:kibibytes ( 2^10 = 1024 bytes)' + 'Mi:mebibytes ( 2^20 = 1024^2 bytes)' + 'Gi:gigibytes ( 2^30 = 1024^3 bytes)' + 'Ti:tebibytes ( 2^40 = 1024^4 bytes)' + ) + _describe -t units 'size limit units' suff -V 'units' + elif compset -P '[-+]'; then + _message -e 'size limit number (full format: <+->)' + else + _values 'size limit prefix (full format: )' \ + '\+[file size must be greater or equal to]'\ + '-[file size must be less than or equal to]' && ret=0 + fi + ;; + esac + + return ret +} + +_fd "$@" + +# ------------------------------------------------------------------------------ +# Copyright (c) 2011 GitHub zsh-users - http://github.com/zsh-users +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the zsh-users nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL ZSH-USERS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ------------------------------------------------------------------------------ +# Description +# ----------- +# +# Completion script for fd +# +# ------------------------------------------------------------------------------ +# Authors +# ------- +# +# * smancill (https://github.com/smancill) +# +# ------------------------------------------------------------------------------ + +# Local Variables: +# mode: shell-script +# coding: utf-8-unix +# indent-tabs-mode: nil +# sh-indentation: 2 +# sh-basic-offset: 2 +# End: +# vim: ft=zsh sw=2 ts=2 et diff --git a/zsh/.oh-my-zsh/plugins/fig/README.md b/zsh/.oh-my-zsh/plugins/fig/README.md new file mode 100644 index 0000000..0728ec2 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fig/README.md @@ -0,0 +1,9 @@ +# Fig plugin + +This plugin sets up completion for [Fig](https://fig.io/). + +To use it, add `fig` to the plugins array in your zshrc file: + +```zsh +plugins=(... fig) +``` diff --git a/zsh/.oh-my-zsh/plugins/fig/fig.plugin.zsh b/zsh/.oh-my-zsh/plugins/fig/fig.plugin.zsh new file mode 100644 index 0000000..ed4019d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fig/fig.plugin.zsh @@ -0,0 +1,13 @@ +if ! (( $+commands[fig] )); then + return +fi + +# If the completion file doesn't exist yet, we need to autoload it and +# bind it to `fig`. Otherwise, compinit will have already done that +if [[ ! -f "$ZSH_CACHE_DIR/completions/_fig" ]]; then + autoload -Uz _fig + typeset -g -A _comps + _comps[fig]=_fig +fi + +fig completion zsh >| "$ZSH_CACHE_DIR/completions/_fig" &| diff --git a/zsh/.oh-my-zsh/plugins/firewalld/README.md b/zsh/.oh-my-zsh/plugins/firewalld/README.md new file mode 100644 index 0000000..e081323 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/firewalld/README.md @@ -0,0 +1,22 @@ +# FirewallD Plugin + +This plugin adds some aliases and functions for FirewallD using the `firewalld-cmd` command. To use it, add firewalld to your plugins array. + +```zsh +plugins=(... firewalld) +``` + +## Aliases + +| Alias | Command | Description | +| :---- | :----------------------------------------- | :--------------------------- | +| fw | `sudo firewall-cmd` | Shorthand | +| fwr | `sudo firewall-cmd --reload` | Reload current configuration | +| fwp | `sudo firewall-cmd --permanent` | Create permanent rule | +| fwrp | `sudo firewall-cmd --runtime-to-permanent` | Save current configuration | + +## Functions + +| Function | Description | +| :------- | :--------------------------------------------------------- | +| fwl | Lists configuration from all active zones and direct rules | diff --git a/zsh/.oh-my-zsh/plugins/firewalld/firewalld.plugin.zsh b/zsh/.oh-my-zsh/plugins/firewalld/firewalld.plugin.zsh new file mode 100644 index 0000000..815294a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/firewalld/firewalld.plugin.zsh @@ -0,0 +1,17 @@ +alias fw="sudo firewall-cmd" +alias fwp="sudo firewall-cmd --permanent" +alias fwr="sudo firewall-cmd --reload" +alias fwrp="sudo firewall-cmd --runtime-to-permanent" + +function fwl () { + # converts output to zsh array () + # @f flag split on new line + zones=("${(@f)$(sudo firewall-cmd --get-active-zones | grep -v 'interfaces\|sources')}") + + for i in $zones; do + sudo firewall-cmd --zone ${i/ \(default\)} --list-all + done + + echo 'Direct Rules:' + sudo firewall-cmd --direct --get-all-rules +} diff --git a/zsh/.oh-my-zsh/plugins/flutter/README.md b/zsh/.oh-my-zsh/plugins/flutter/README.md new file mode 100644 index 0000000..b6da87d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/flutter/README.md @@ -0,0 +1,28 @@ +## Flutter plugin + +The Flutter plugin provides completion and useful aliases + +To use it, add `flutter` to the plugins array of your zshrc file: + +```zsh +plugins=(... flutter) +``` + +## Aliases + +| Alias | Command | Description | +| :--------- | :---------------------- | :------------------------------------------------------------------------- | +| `fl` | `flutter` | Shorthand for flutter command | +| `flattach` | `flutter attach` | Attaches flutter to a running flutter application with enabled observatory | +| `flb` | `flutter build` | Build flutter application | +| `flchnl` | `flutter channel` | Switches flutter channel (requires input of desired channel) | +| `flc` | `flutter clean` | Cleans flutter project | +| `fldvcs` | `flutter devices` | List connected devices (if any) | +| `fldoc` | `flutter doctor` | Runs flutter doctor | +| `flpub` | `flutter pub` | Shorthand for flutter pub command | +| `flget` | `flutter pub get` | Installs dependencies | +| `flr` | `flutter run` | Runs flutter app | +| `flrd` | `flutter run --debug` | Runs flutter app in debug mode (default mode) | +| `flrp` | `flutter run --profile` | Runs flutter app in profile mode | +| `flrr` | `flutter run --release` | Runs flutter app in release mode | +| `flupgrd` | `flutter upgrade` | Upgrades flutter version depending on the current channel | diff --git a/zsh/.oh-my-zsh/plugins/flutter/flutter.plugin.zsh b/zsh/.oh-my-zsh/plugins/flutter/flutter.plugin.zsh new file mode 100644 index 0000000..fe488be --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/flutter/flutter.plugin.zsh @@ -0,0 +1,29 @@ +alias fl="flutter" +alias flattach="flutter attach" +alias flb="flutter build" +alias flchnl="flutter channel" +alias flc="flutter clean" +alias fldvcs="flutter devices" +alias fldoc="flutter doctor" +alias flpub="flutter pub" +alias flget="flutter pub get" +alias flr="flutter run" +alias flrd="flutter run --debug" +alias flrp="flutter run --profile" +alias flrr="flutter run --release" +alias flupgrd="flutter upgrade" + +# COMPLETION FUNCTION +if (( ! $+commands[flutter] )); then + return +fi + +# If the completion file doesn't exist yet, we need to autoload it and +# bind it to `flutter`. Otherwise, compinit will have already done that. +if [[ ! -f "$ZSH_CACHE_DIR/completions/_flutter" ]]; then + typeset -g -A _comps + autoload -Uz _flutter + _comps[flutter]=_flutter +fi + +flutter zsh-completion >| "$ZSH_CACHE_DIR/completions/_flutter" &| \ No newline at end of file diff --git a/zsh/.oh-my-zsh/plugins/fluxcd/README.md b/zsh/.oh-my-zsh/plugins/fluxcd/README.md new file mode 100644 index 0000000..61afdae --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fluxcd/README.md @@ -0,0 +1,9 @@ +# FluxCD plugin + +This plugin adds completion for [FluxCD](https://fluxcd.io), an open and extensible continuous delivery solution for Kubernetes. Powered by GitOps Toolkit. + +To use it, add `fluxcd` to the plugins array in your zshrc file: + +```zsh +plugins=(... fluxcd) +``` diff --git a/zsh/.oh-my-zsh/plugins/fluxcd/fluxcd.plugin.zsh b/zsh/.oh-my-zsh/plugins/fluxcd/fluxcd.plugin.zsh new file mode 100644 index 0000000..d7841e1 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fluxcd/fluxcd.plugin.zsh @@ -0,0 +1,14 @@ +# Autocompletion for the FluxCD CLI (flux). +if (( ! $+commands[flux] )); then + return +fi + +# If the completion file doesn't exist yet, we need to autoload it and +# bind it to `flux`. Otherwise, compinit will have already done that. +if [[ ! -f "$ZSH_CACHE_DIR/completions/_flux" ]]; then + typeset -g -A _comps + autoload -Uz _flux + _comps[flux]=_flux +fi + +flux completion zsh >| "$ZSH_CACHE_DIR/completions/_flux" &| diff --git a/zsh/.oh-my-zsh/plugins/fnm/README.md b/zsh/.oh-my-zsh/plugins/fnm/README.md new file mode 100644 index 0000000..ac45a1e --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fnm/README.md @@ -0,0 +1,9 @@ +# fnm plugin + +This plugin adds autocompletion for [fnm](https://github.com/Schniz/fnm) - a Node.js version manager. + +To use it, add `fnm` to the plugins array in your zshrc file: + +```zsh +plugins=(... fnm) +``` diff --git a/zsh/.oh-my-zsh/plugins/fnm/fnm.plugin.zsh b/zsh/.oh-my-zsh/plugins/fnm/fnm.plugin.zsh new file mode 100644 index 0000000..5e6582c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fnm/fnm.plugin.zsh @@ -0,0 +1,13 @@ +if (( ! $+commands[fnm] )); then + return +fi + +# If the completion file doesn't exist yet, we need to autoload it and +# bind it to `fnm`. Otherwise, compinit will have already done that. +if [[ ! -f "$ZSH_CACHE_DIR/completions/_fnm" ]]; then + typeset -g -A _comps + autoload -Uz _fnm + _comps[fnm]=_fnm +fi + +fnm completions --shell=zsh >| "$ZSH_CACHE_DIR/completions/_fnm" &| diff --git a/zsh/.oh-my-zsh/plugins/forklift/README.md b/zsh/.oh-my-zsh/plugins/forklift/README.md new file mode 100644 index 0000000..484f69e --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/forklift/README.md @@ -0,0 +1,23 @@ +# forklift + +Plugin for ForkLift, an FTP application for OS X. + +To use it, add `forklift` to the plugins array in your zshrc file: + +```zsh +plugins=(... forklift) +``` + +## Requirements + +* [ForkLift](https://binarynights.com/) + +## Usage + +`fl []` + +* If `fl` is called without arguments then the current folder is opened in ForkLift. This is equivalent to `fl .`. + +* If `fl` is called with a directory as the argument, then that directory is opened in ForkLift + +* If `fl` is called with a non-directory file as the argument, then the file's parent directory is opened. diff --git a/zsh/.oh-my-zsh/plugins/forklift/forklift.plugin.zsh b/zsh/.oh-my-zsh/plugins/forklift/forklift.plugin.zsh new file mode 100644 index 0000000..092fec0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/forklift/forklift.plugin.zsh @@ -0,0 +1,128 @@ +# Open folder in ForkLift.app or ForkLift2.app from console +# Author: Adam Strzelecki nanoant.com, modified by Bodo Tasche bitboxer.de +# Updated to support ForkLift 2 and ForkLift 3 by Johan Kaving +# Updated to support ForkLift from Setapp by Paul Rudkin +# Updated to support ForkLift 4 by Michal Szymanski (misiektoja) +# +# Usage: +# fl [] +# +# Opens specified directory or current working directory in ForkLift.app +# +# Notes: +# It assumes Shift+Cmd+G launches go to folder panel and Cmd+N opens new +# app window. +# +# https://gist.github.com/3313481 +function fl { + if [ ! -z "$1" ]; then + DIR=$1 + if [ ! -d "$DIR" ]; then + DIR=$(dirname $DIR) + fi + if [ "$DIR" != "." ]; then + PWD=`cd "$DIR";pwd` + fi + fi + osascript 2>&1 1>/dev/null <command'\ + '2: :->subcommand' + + case $state in + command) + local _OUTPUT=$(fossil branch 2>&1 | grep "use --repo") + if [[ -z "$_OUTPUT" ]]; then + compadd "$(_fossil_get_command_list)" + else + compadd clone init import help version + fi ;; + subcommand) + case "$words[2]" in + help) compadd "$(_fossil_get_command_list)" ;; + add) compadd "$(fossil extra)" ;; + *) compcall -D ;; + esac ;; + esac +} + +_fossil "$@" diff --git a/zsh/.oh-my-zsh/plugins/fossil/fossil.plugin.zsh b/zsh/.oh-my-zsh/plugins/fossil/fossil.plugin.zsh new file mode 100644 index 0000000..0e8c5ca --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fossil/fossil.plugin.zsh @@ -0,0 +1,56 @@ +_FOSSIL_PROMPT="" + +# Prefix at the very beginning of the prompt, before the branch name +ZSH_THEME_FOSSIL_PROMPT_PREFIX="%{$fg_bold[blue]%}fossil:(%{$fg_bold[red]%}" + +# At the very end of the prompt +ZSH_THEME_FOSSIL_PROMPT_SUFFIX="%{$fg_bold[blue]%})" + +# Text to display if the branch is dirty +ZSH_THEME_FOSSIL_PROMPT_DIRTY=" %{$fg_bold[red]%}✖" + +# Text to display if the branch is clean +ZSH_THEME_FOSSIL_PROMPT_CLEAN=" %{$fg_bold[green]%}✔" + +function fossil_prompt_info() { + local branch=$(fossil branch current 2>&1) + + # if we're not in a fossil repo, don't show anything + ! command grep -q "use --repo" <<< "$branch" || return + + local changes=$(fossil changes) + local dirty="$ZSH_THEME_FOSSIL_PROMPT_CLEAN" + + if [[ -n "$changes" ]]; then + dirty="$ZSH_THEME_FOSSIL_PROMPT_DIRTY" + fi + + printf '%s %s %s %s %s' \ + "$ZSH_THEME_FOSSIL_PROMPT_PREFIX" \ + "${branch:gs/%/%%}" \ + "$ZSH_THEME_FOSSIL_PROMPT_SUFFIX" \ + "$dirty" \ + "%{$reset_color%}" +} + +function _fossil_prompt () { + local current=`echo $PROMPT $RPROMPT | grep fossil` + + if [ "$_FOSSIL_PROMPT" = "" -o "$current" = "" ]; then + local _prompt=${PROMPT} + local _rprompt=${RPROMPT} + + local is_prompt=`echo $PROMPT | grep git` + + if [ "$is_prompt" = "" ]; then + RPROMPT="$_rprompt"'$(fossil_prompt_info)' + else + PROMPT="$_prompt"'$(fossil_prompt_info) ' + fi + + _FOSSIL_PROMPT="1" + fi +} + +autoload -U add-zsh-hook +add-zsh-hook precmd _fossil_prompt diff --git a/zsh/.oh-my-zsh/plugins/frontend-search/README.md b/zsh/.oh-my-zsh/plugins/frontend-search/README.md new file mode 100644 index 0000000..6335bc6 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/frontend-search/README.md @@ -0,0 +1,85 @@ +## Introduction + +> Searches for your frontend web development made easier + +## Installation + +Open your `~/.zshrc` file and enable the `frontend-search` plugin: + +```zsh + +plugins=( ... frontend-search) + +``` + +## Usage + +You can use the frontend-search plugin in these two forms: + +- `frontend [more terms if you want]` +- ` [more terms if you want]` + +For example, these two are equivalent: + +```zsh +$ angular dependency injection +# Will turn into ... +$ frontend angular dependency injection +``` + +Available search contexts are: + +| context | URL | +| ------------- | --------------------------------------------------------------------------- | +| angular | `https://angular.io/?search=` | +| angularjs | `https://google.com/search?as_sitesearch=angularjs.org&as_q=` | +| bem | `https://google.com/search?as_sitesearch=bem.info&as_q=` | +| bootsnipp | `https://bootsnipp.com/search?q=` | +| bundlephobia | `https://bundlephobia.com/result?p=` | +| caniuse | `https://caniuse.com/#search=` | +| codepen | `https://codepen.io/search?q=` | +| compassdoc | `http://compass-style.org/search?q=` | +| cssflow | `http://www.cssflow.com/search?q=` | +| dartlang | `https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:` | +| emberjs | `https://www.google.com/search?as_sitesearch=emberjs.com/&as_q=` | +| flowtype | `https://google.com/search?as_sitesearch=flow.org/en/docs/&as_q=` | +| fontello | `http://fontello.com/#search=` | +| github | `https://github.com/search?q=` | +| html5please | `https://html5please.com/#` | +| jestjs | `https://www.google.com/search?as_sitesearch=jestjs.io&as_q=` | +| jquery | `https://api.jquery.com/?s=` | +| lodash | `https://devdocs.io/lodash/index#` | +| mdn | `https://developer.mozilla.org/search?q=` | +| nodejs | `https://www.google.com/search?as_sitesearch=nodejs.org/en/docs/&as_q=` | +| npmjs | `https://www.npmjs.com/search?q=` | +| packagephobia | `https://packagephobia.now.sh/result?p=` | +| qunit | `https://api.qunitjs.com/?s=` | +| reactjs | `https://google.com/search?as_sitesearch=facebook.github.io/react&as_q=` | +| smacss | `https://google.com/search?as_sitesearch=smacss.com&as_q=` | +| stackoverflow | `https://stackoverflow.com/search?q=` | +| typescript | `https://google.com/search?as_sitesearch=www.typescriptlang.org/docs&as_q=` | +| unheap | `http://www.unheap.com/?s=` | +| vuejs | `https://www.google.com/search?as_sitesearch=vuejs.org&as_q=` | +| nextjs | `https://www.google.com/search?as_sitesearch=nextjs.org&as_q=` | + +If you want to have another context, open an Issue and tell us! + +## Fallback search behaviour + +The plugin will use Google as a fallback if the docs site for a search context does not have a search +function. You can set the fallback search engine to DuckDuckGo by setting +`FRONTEND_SEARCH_FALLBACK='duckduckgo'` in your `~/.zshrc` file before Oh My Zsh is sourced. + +## DuckDuckGo Lucky Search + +Enable DuckDuckGo's "ducky" (lucky) search feature to automatically access the top search result. This feature +is optimized for DuckDuckGo, as Google redirects to an intermediate page. The FRONTEND_SEARCH_FALLBACK_LUCKY +environment variable triggers the use of DuckDuckGo's lucky search, rendering the FRONTEND_SEARCH_FALLBACK +setting unnecessary in this context. + +## Author + +**Wilson Mendes (willmendesneto)** + +- +- diff --git a/zsh/.oh-my-zsh/plugins/frontend-search/_frontend b/zsh/.oh-my-zsh/plugins/frontend-search/_frontend new file mode 100644 index 0000000..ecbda7d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/frontend-search/_frontend @@ -0,0 +1,161 @@ +#compdef frontend + +zstyle ':completion:*:descriptions' format '%B%d%b' +zstyle ':completion::complete:frontend:*:commands' group-name commands +zstyle ':completion::complete:frontend:*:frontend_points' group-name frontend_points +zstyle ':completion::complete:frontend::' list-grouped + +zmodload zsh/mapfile + +function _frontend() { + local CONFIG=$HOME/.frontend-search + local ret=1 + + local -a commands + local -a frontend_points + + frontend_points=( "${(f)mapfile[$CONFIG]//$HOME/~}" ) + + commands=( + 'angular: Search in Angular.io website' + 'angularjs: Search in docs.angularjs.org website' + 'bem: Search in BEM website' + 'bootsnipp: Search in bootsnipp website' + 'bundlephobia: Search in Bundlephobia website' + 'caniuse: Search in Can I Use website' + 'codepen: Search in codepen website' + 'compassdoc: Search in COMPASS website' + 'cssflow: Search in cssflow website' + 'dartlang: Search in Dart website' + 'emberjs: Search in Ember website' + 'flowtype: Search in Flowtype website' + 'fontello: Search in fontello website' + 'github: Search in GitHub website' + 'html5please: Search in HTML5 Please website' + 'jestjs: Search in Jest website' + 'jquery: Search in jQuery website' + 'lodash: Search in Lo-Dash website' + 'mdn: Search in MDN website' + 'nodejs: Search in NodeJS website' + 'npmjs: Search in npmjs website' + 'packagephobia: Search in Packagephobia website' + 'qunit: Search in Qunit website' + 'reactjs: Search in React website' + 'smacss: Search in SMACSS website' + 'stackoverflow: Search in StackOverflow website' + 'typescript: Search in TypeScript website' + 'unheap: Search in unheap website' + 'vuejs: Search in VueJS website' + ) + + _arguments -C \ + '1: :->first_arg' \ + '2: :->second_arg' && ret=0 + + case $state in + first_arg) + _describe -t frontend_points "Warp points" frontend_points && ret=0 + _describe -t commands "Commands" commands && ret=0 + ;; + second_arg) + case $words[2] in + jquery) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + mdn) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + compassdoc) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + html5please) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + caniuse) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + dartlang) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + lodash) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + qunit) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + fontello) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + github) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + bootsnipp) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + cssflow) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + codepen) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + unheap) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + bem) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + smacss) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + angularjs) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + reactjs) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + emberjs) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + stackoverflow) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + npmjs) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + bundlephobia) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + packagephobia) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + flowtype) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + typescript) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + vuejs) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + nodejs) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + jestjs) + _describe -t points "Warp points" frontend_points && ret=0 + ;; + esac + ;; + esac + + return $ret +} + +_frontend "$@" + +# Local Variables: +# mode: Shell-Script +# sh-indentation: 2 +# indent-tabs-mode: nil +# sh-basic-offset: 2 +# End: +# vim: ft=zsh sw=2 ts=2 et diff --git a/zsh/.oh-my-zsh/plugins/frontend-search/frontend-search.plugin.zsh b/zsh/.oh-my-zsh/plugins/frontend-search/frontend-search.plugin.zsh new file mode 100644 index 0000000..20d306d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/frontend-search/frontend-search.plugin.zsh @@ -0,0 +1,119 @@ +alias angular='frontend angular' +alias angularjs='frontend angularjs' +alias bem='frontend bem' +alias bootsnipp='frontend bootsnipp' +alias bundlephobia='frontend bundlephobia' +alias caniuse='frontend caniuse' +alias codepen='frontend codepen' +alias compassdoc='frontend compassdoc' +alias cssflow='frontend cssflow' +alias dartlang='frontend dartlang' +alias emberjs='frontend emberjs' +alias flowtype='frontend flowtype' +alias fontello='frontend fontello' +alias github='frontend github' +alias html5please='frontend html5please' +alias jestjs='frontend jestjs' +alias jquery='frontend jquery' +alias lodash='frontend lodash' +alias mdn='frontend mdn' +alias nodejs='frontend nodejs' +alias npmjs='frontend npmjs' +alias packagephobia='frontend packagephobia' +alias qunit='frontend qunit' +alias reactjs='frontend reactjs' +alias smacss='frontend smacss' +alias stackoverflow='frontend stackoverflow' +alias typescript='frontend typescript' +alias unheap='frontend unheap' +alias vuejs='frontend vuejs' +alias nextjs='frontend nextjs' + +function _frontend_fallback() { + if [[ "$FRONTEND_SEARCH_FALLBACK_LUCKY" == "true" ]]; then + case true in + *) echo "https://duckduckgo.com/?q=!ducky+site%3A$1+" ;; + esac + else + case "$FRONTEND_SEARCH_FALLBACK" in + duckduckgo) echo "https://duckduckgo.com/?sites=$1&q=" ;; + *) echo "https://google.com/search?as_sitesearch=$1&as_q=" ;; + esac + fi +} + +function frontend() { + emulate -L zsh + + # define search context URLS + local -A urls + urls=( + angular 'https://angular.io/?search=' + angularjs $(_frontend_fallback 'angularjs.org') + bem $(_frontend_fallback 'bem.info') + bootsnipp 'https://bootsnipp.com/search?q=' + bundlephobia 'https://bundlephobia.com/result?p=' + caniuse 'https://caniuse.com/#search=' + codepen 'https://codepen.io/search/pens?q=' + compassdoc 'http://compass-style.org/search?q=' + cssflow 'http://www.cssflow.com/search?q=' + dartlang 'https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:' + emberjs $(_frontend_fallback 'emberjs.com/') + flowtype $(_frontend_fallback 'flow.org/en/docs/') + fontello 'http://fontello.com/#search=' + github 'https://github.com/search?q=' + html5please 'https://html5please.com/#' + jestjs $(_frontend_fallback 'jestjs.io') + jquery 'https://api.jquery.com/?s=' + lodash 'https://devdocs.io/lodash/index#' + mdn 'https://developer.mozilla.org/search?q=' + nodejs $(_frontend_fallback 'nodejs.org/en/docs/') + npmjs 'https://www.npmjs.com/search?q=' + packagephobia 'https://packagephobia.now.sh/result?p=' + qunit 'https://api.qunitjs.com/?s=' + reactjs $(_frontend_fallback 'reactjs.org/') + smacss $(_frontend_fallback 'smacss.com') + stackoverflow 'https://stackoverflow.com/search?q=' + typescript $(_frontend_fallback 'www.typescriptlang.org/docs') + unheap 'http://www.unheap.com/?s=' + vuejs $(_frontend_fallback 'vuejs.org') + nextjs $(_frontend_fallback 'nextjs.org') + ) + + # show help for command list + if [[ $# -lt 2 ]]; then + print -P "Usage: frontend %Ucontext%u %Uterm%u [...%Umore%u] (or just: %Ucontext%u %Uterm%u [...%Umore%u])" + print -P "" + print -P "%Uterm%u and what follows is what will be searched for in the %Ucontext%u website," + print -P "and %Ucontext%u is one of the following:" + print -P "" + print -P " angular, angularjs, bem, bootsnipp, caniuse, codepen, compassdoc, cssflow, packagephobia" + print -P " dartlang, emberjs, fontello, flowtype, github, html5please, jestjs, jquery, lodash," + print -P " mdn, npmjs, nodejs, qunit, reactjs, smacss, stackoverflow, unheap, vuejs, bundlephobia, nextjs" + print -P "" + print -P "For example: frontend npmjs mocha (or just: npmjs mocha)." + print -P "" + return 1 + fi + + # check whether the search context is supported + if [[ -z "$urls[$1]" ]]; then + echo "Search context \"$1\" currently not supported." + echo "" + echo "Valid contexts are:" + echo "" + echo " angular, angularjs, bem, bootsnipp, caniuse, codepen, compassdoc, cssflow, packagephobia" + echo " dartlang, emberjs, fontello, github, html5please, jest, jquery, lodash," + echo " mdn, npmjs, nodejs, qunit, reactjs, smacss, stackoverflow, unheap, vuejs, bundlephobia, nextjs" + echo "" + return 1 + fi + + # build search url: + # join arguments passed with '%20', then append to search context URL + url="${urls[$1]}$(omz_urlencode -P ${@[2,-1]})" + + echo "Opening $url ..." + + open_command "$url" +} diff --git a/zsh/.oh-my-zsh/plugins/fzf/README.md b/zsh/.oh-my-zsh/plugins/fzf/README.md new file mode 100644 index 0000000..0fa6c8c --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fzf/README.md @@ -0,0 +1,52 @@ +# fzf + +This plugin tries to find [junegunn's fzf](https://github.com/junegunn/fzf) based on where +it's been installed, and enables its fuzzy auto-completion and key bindings. + +To use it, add `fzf` to the plugins array in your zshrc file: + +```zsh +plugins=(... fzf) +``` + +## Settings + +All these settings should go in your zshrc file, before Oh My Zsh is sourced. + +### `FZF_BASE` + +Set to fzf installation directory path: + +```zsh +export FZF_BASE=/path/to/fzf/install/dir +``` + +### `FZF_DEFAULT_COMMAND` + +Set default command to use when input is tty: + +```zsh +export FZF_DEFAULT_COMMAND='' +``` + +If not set, the plugin will try to set it to these, in the order in which they're found: + +- [`fd`](https://github.com/sharkdp/fd) +- [`rg`](https://github.com/BurntSushi/ripgrep) +- [`ag`](https://github.com/ggreer/the_silver_searcher) + +### `DISABLE_FZF_AUTO_COMPLETION` + +Set whether to load fzf auto-completion: + +```zsh +DISABLE_FZF_AUTO_COMPLETION="true" +``` + +### `DISABLE_FZF_KEY_BINDINGS` + +Set whether to disable key bindings (CTRL-T, CTRL-R, ALT-C): + +```zsh +DISABLE_FZF_KEY_BINDINGS="true" +``` diff --git a/zsh/.oh-my-zsh/plugins/fzf/fzf.plugin.zsh b/zsh/.oh-my-zsh/plugins/fzf/fzf.plugin.zsh new file mode 100644 index 0000000..d3f3f6d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/fzf/fzf.plugin.zsh @@ -0,0 +1,274 @@ +function fzf_setup_using_fzf() { + (( ${+commands[fzf]} )) || return 1 + + # we remove "fzf " prefix, this fixes really old fzf versions behaviour + # see https://github.com/ohmyzsh/ohmyzsh/issues/12387 + local fzf_ver=${"$(fzf --version)"#fzf } + + autoload -Uz is-at-least + is-at-least 0.48.0 ${${(s: :)fzf_ver}[1]} || return 1 + + eval "$(fzf --zsh)" +} + +function fzf_setup_using_base_dir() { + local fzf_base fzf_shell fzfdirs dir + + test -d "${FZF_BASE}" && fzf_base="${FZF_BASE}" + + if [[ -z "${fzf_base}" ]]; then + fzfdirs=( + "${HOME}/.fzf" + "${HOME}/.nix-profile/share/fzf" + "${XDG_DATA_HOME:-$HOME/.local/share}/fzf" + "${MSYSTEM_PREFIX}/share/fzf" + "/usr/local/opt/fzf" + "/opt/homebrew/opt/fzf" + "/usr/share/fzf" + "/usr/local/share/examples/fzf" + ) + for dir in ${fzfdirs}; do + if [[ -d "${dir}" ]]; then + fzf_base="${dir}" + break + fi + done + + if [[ -z "${fzf_base}" ]]; then + if (( ${+commands[fzf-share]} )) && dir="$(fzf-share)" && [[ -d "${dir}" ]]; then + fzf_base="${dir}" + elif (( ${+commands[brew]} )) && dir="$(brew --prefix fzf 2>/dev/null)"; then + if [[ -d "${dir}" ]]; then + fzf_base="${dir}" + fi + fi + fi + fi + + if [[ ! -d "${fzf_base}" ]]; then + return 1 + fi + + # Fix fzf shell directory for Arch Linux, NixOS or Void Linux packages + if [[ ! -d "${fzf_base}/shell" ]]; then + fzf_shell="${fzf_base}" + else + fzf_shell="${fzf_base}/shell" + fi + + # Setup fzf binary path + if (( ! ${+commands[fzf]} )) && [[ "$PATH" != *$fzf_base/bin* ]]; then + export PATH="$PATH:$fzf_base/bin" + fi + + # Auto-completion + if [[ -o interactive && "$DISABLE_FZF_AUTO_COMPLETION" != "true" ]]; then + source "${fzf_shell}/completion.zsh" 2> /dev/null + fi + + # Key bindings + if [[ "$DISABLE_FZF_KEY_BINDINGS" != "true" ]]; then + source "${fzf_shell}/key-bindings.zsh" + fi +} + + +function fzf_setup_using_debian() { + if (( ! $+commands[apt] && ! $+commands[apt-get] )); then + # Not a debian based distro + return 1 + fi + + # NOTE: There is no need to configure PATH for debian package, all binaries + # are installed to /usr/bin by default + + local completions key_bindings + + case $PREFIX in + *com.termux*) + if [[ ! -f "${PREFIX}/bin/fzf" ]]; then + # fzf not installed + return 1 + fi + # Support Termux package + completions="${PREFIX}/share/fzf/completion.zsh" + key_bindings="${PREFIX}/share/fzf/key-bindings.zsh" + ;; + *) + if [[ ! -d /usr/share/doc/fzf/examples ]]; then + # fzf not installed + return 1 + fi + # Determine completion file path: first bullseye/sid, then buster/stretch + completions="/usr/share/doc/fzf/examples/completion.zsh" + [[ -f "$completions" ]] || completions="/usr/share/zsh/vendor-completions/_fzf" + key_bindings="/usr/share/doc/fzf/examples/key-bindings.zsh" + ;; + esac + + # Auto-completion + if [[ -o interactive && "$DISABLE_FZF_AUTO_COMPLETION" != "true" ]]; then + source $completions 2> /dev/null + fi + + # Key bindings + if [[ ! "$DISABLE_FZF_KEY_BINDINGS" == "true" ]]; then + source $key_bindings + fi + + return 0 +} + +function fzf_setup_using_opensuse() { + # OpenSUSE installs fzf in /usr/bin/fzf + # If the command is not found, the package isn't installed + (( $+commands[fzf] )) || return 1 + + # The fzf-zsh-completion package installs the auto-completion in + local completions="/usr/share/zsh/site-functions/_fzf" + # The fzf-zsh-completion package installs the key-bindings file in + local key_bindings="/etc/zsh_completion.d/fzf-key-bindings" + + # If these are not found: (1) maybe we're not on OpenSUSE, or + # (2) maybe the fzf-zsh-completion package isn't installed. + if [[ ! -f "$completions" || ! -f "$key_bindings" ]]; then + return 1 + fi + + # Auto-completion + if [[ -o interactive && "$DISABLE_FZF_AUTO_COMPLETION" != "true" ]]; then + source "$completions" 2>/dev/null + fi + + # Key bindings + if [[ "$DISABLE_FZF_KEY_BINDINGS" != "true" ]]; then + source "$key_bindings" 2>/dev/null + fi + + return 0 +} + +function fzf_setup_using_fedora() { + (( $+commands[fzf] )) || return 1 + + local completions="/usr/share/zsh/site-functions/fzf" + local key_bindings="/usr/share/fzf/shell/key-bindings.zsh" + + if [[ ! -f "$completions" || ! -f "$key_bindings" ]]; then + return 1 + fi + + if [[ -o interactive && "$DISABLE_FZF_AUTO_COMPLETION" != "true" ]]; then + source "$completions" 2>/dev/null + fi + + if [[ "$DISABLE_FZF_KEY_BINDINGS" != "true" ]]; then + source "$key_bindings" 2>/dev/null + fi + + return 0 +} + +function fzf_setup_using_openbsd() { + # openBSD installs fzf in /usr/local/bin/fzf + if [[ "$OSTYPE" != openbsd* ]] || (( ! $+commands[fzf] )); then + return 1 + fi + + # The fzf package installs the auto-completion in + local completions="/usr/local/share/zsh/site-functions/_fzf_completion" + # The fzf package installs the key-bindings file in + local key_bindings="/usr/local/share/zsh/site-functions/_fzf_key_bindings" + + # Auto-completion + if [[ -o interactive && "$DISABLE_FZF_AUTO_COMPLETION" != "true" ]]; then + source "$completions" 2>/dev/null + fi + + # Key bindings + if [[ "$DISABLE_FZF_KEY_BINDINGS" != "true" ]]; then + source "$key_bindings" 2>/dev/null + fi + + return 0 +} + +function fzf_setup_using_cygwin() { + # Cygwin installs fzf in /usr/local/bin/fzf + if [[ "$OSTYPE" != cygwin* ]] || (( ! $+commands[fzf] )); then + return 1 + fi + + # The fzf-zsh-completion package installs the auto-completion in + local completions="/etc/profile.d/fzf-completion.zsh" + # The fzf-zsh package installs the key-bindings file in + local key_bindings="/etc/profile.d/fzf.zsh" + + # Auto-completion + if [[ -o interactive && "$DISABLE_FZF_AUTO_COMPLETION" != "true" ]]; then + source "$completions" 2>/dev/null + fi + + # Key bindings + if [[ "$DISABLE_FZF_KEY_BINDINGS" != "true" ]]; then + source "$key_bindings" 2>/dev/null + fi + + return 0 +} + +function fzf_setup_using_macports() { + # If the command is not found, the package isn't installed + (( $+commands[fzf] )) || return 1 + + # The fzf-zsh-completion package installs the auto-completion in + local completions="/opt/local/share/fzf/shell/completion.zsh" + # The fzf-zsh-completion package installs the key-bindings file in + local key_bindings="/opt/local/share/fzf/shell/key-bindings.zsh" + + if [[ ! -f "$completions" || ! -f "$key_bindings" ]]; then + return 1 + fi + + # Auto-completion + if [[ -o interactive && "$DISABLE_FZF_AUTO_COMPLETION" != "true" ]]; then + source "$completions" 2>/dev/null + fi + + # Key bindings + if [[ "$DISABLE_FZF_KEY_BINDINGS" != "true" ]]; then + source "$key_bindings" 2>/dev/null + fi + + return 0 +} + +# Indicate to user that fzf installation not found if nothing worked +function fzf_setup_error() { + cat >&2 <<'EOF' +[oh-my-zsh] fzf plugin: Cannot find fzf installation directory. +Please add `export FZF_BASE=/path/to/fzf/install/dir` to your .zshrc +EOF +} + +fzf_setup_using_fzf \ + || fzf_setup_using_openbsd \ + || fzf_setup_using_debian \ + || fzf_setup_using_opensuse \ + || fzf_setup_using_fedora \ + || fzf_setup_using_cygwin \ + || fzf_setup_using_macports \ + || fzf_setup_using_base_dir \ + || fzf_setup_error + +unset -f -m 'fzf_setup_*' + +if [[ -z "$FZF_DEFAULT_COMMAND" ]]; then + if (( $+commands[fd] )); then + export FZF_DEFAULT_COMMAND='fd --type f --hidden --exclude .git' + elif (( $+commands[rg] )); then + export FZF_DEFAULT_COMMAND='rg --files --hidden --glob "!.git/*"' + elif (( $+commands[ag] )); then + export FZF_DEFAULT_COMMAND='ag -l --hidden -g "" --ignore .git' + fi +fi diff --git a/zsh/.oh-my-zsh/plugins/gas/README.md b/zsh/.oh-my-zsh/plugins/gas/README.md new file mode 100644 index 0000000..8c5155f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gas/README.md @@ -0,0 +1,10 @@ +# Gas plugin + +This plugin adds autocompletion for the [gas](http://ramblingsby.me/gas/) command, +a utility to manage Git authors. + +To use it, add `gas` to the plugins array of your zshrc file: + +```zsh +plugins=(... gas) +``` diff --git a/zsh/.oh-my-zsh/plugins/gas/_gas b/zsh/.oh-my-zsh/plugins/gas/_gas new file mode 100644 index 0000000..521890f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gas/_gas @@ -0,0 +1,39 @@ +#compdef gas + +local curcontext="$curcontext" state line cmds ret=1 + +_arguments -C \ + '(- 1 *)'{-v,--version}'[display version information]' \ + '(-h|--help)'{-h,--help}'[show help information]' \ + '1: :->cmds' \ + '*: :->args' && ret=0 + +case $state in + cmds) + cmds=( + "version:Prints Gas's version" + "use:Uses author" + "ssh:Creates a new ssh key for an existing gas author" + "show:Shows your current user" + "list:Lists your authors" + "import:Imports current user to gasconfig" + "help:Describe available tasks or one specific task" + "delete:Deletes author" + "add:Adds author to gasconfig" + ) + _describe -t commands 'gas command' cmds && ret=0 + ;; + args) + case $line[1] in + (use|delete) + VERSION=$(gas -v) + if [[ $VERSION == <1->.*.* ]] || [[ $VERSION == 0.<2->.* ]] || [[ $VERSION == 0.1.<6-> ]] then + _values -S , 'authors' $(cat ~/.gas/gas.authors | sed -n -e 's/^.*\[\(.*\)\]/\1/p') && ret=0 + else + _values -S , 'authors' $(cat ~/.gas | sed -n -e 's/^\[\(.*\)\]/\1/p') && ret=0 + fi + esac + ;; +esac + +return ret diff --git a/zsh/.oh-my-zsh/plugins/gatsby/README.md b/zsh/.oh-my-zsh/plugins/gatsby/README.md new file mode 100644 index 0000000..58b79cc --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gatsby/README.md @@ -0,0 +1,7 @@ +# gatsby autocomplete plugin + +* Adds autocomplete options for all gatsby commands. + +## Requirements + +In order to make this work, you will need to have gatsby set up in your path. diff --git a/zsh/.oh-my-zsh/plugins/gatsby/_gatsby b/zsh/.oh-my-zsh/plugins/gatsby/_gatsby new file mode 100644 index 0000000..1312c28 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gatsby/_gatsby @@ -0,0 +1,24 @@ +#compdef gatsby +#autoload + +# in order to make this work, you will need to have gatsby +# https://www.gatsbyjs.org/ + +local -a _1st_arguments +_1st_arguments=( +'develop:Start development server. Watches files, rebuilds, and hot reloads if something changes' +'build:Build a Gatsby project.' +'serve:Serve previously built Gatsby site.' +'info:Get environment information for debugging and issue reporting' +'clean:Wipe the local gatsby environment including built assets and cache' +'repl:Get a node repl with context of Gatsby environment, see (add docs link here)' +'new: [rootPath] [starter] Create new Gatsby project.' +'telemetry:Enable or disable Gatsby anonymous analytics collection.' +) + +_arguments -C '*:: :->subcmds' && return 0 + +if (( CURRENT == 1 )); then + _describe -t commands "gatsby subcommand" _1st_arguments + return +fi diff --git a/zsh/.oh-my-zsh/plugins/gcloud/README.md b/zsh/.oh-my-zsh/plugins/gcloud/README.md new file mode 100644 index 0000000..c2c7bbc --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gcloud/README.md @@ -0,0 +1,24 @@ +# gcloud + +This plugin provides completion support for the +[Google Cloud SDK CLI](https://cloud.google.com/sdk/gcloud/). + +To use it, add `gcloud` to the plugins array in your zshrc file. + +```zsh +plugins=(... gcloud) +``` + +It relies on you having installed the SDK using one of the supported options +listed [here](https://cloud.google.com/sdk/install). + +## Plugin Options + +* Set `CLOUDSDK_HOME` in your `zshrc` file before you load oh-my-zsh if you have +your GCloud SDK installed in a non-standard location. The plugin will use this +as the base for your SDK if it finds it set already. + +* If you do not have a `python2` in your `PATH` you'll also need to set the +`CLOUDSDK_PYTHON` environment variable at the end of your `.zshrc`. This is +used by the SDK to call a compatible interpreter when you run one of the +SDK commands. diff --git a/zsh/.oh-my-zsh/plugins/gcloud/gcloud.plugin.zsh b/zsh/.oh-my-zsh/plugins/gcloud/gcloud.plugin.zsh new file mode 100644 index 0000000..6f3e79b --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gcloud/gcloud.plugin.zsh @@ -0,0 +1,52 @@ +##################################################### +# gcloud plugin for oh-my-zsh # +# Author: Ian Chesal (github.com/ianchesal) # +##################################################### + +if [[ -z "${CLOUDSDK_HOME}" ]]; then + search_locations=( + "$HOME/google-cloud-sdk" + "/usr/local/share/google-cloud-sdk" + "/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk" + "/opt/homebrew/Caskroom/google-cloud-sdk/latest/google-cloud-sdk" + "/opt/homebrew/share/google-cloud-sdk" + "/usr/share/google-cloud-sdk" + "/snap/google-cloud-sdk/current" + "/snap/google-cloud-cli/current" + "/usr/lib/google-cloud-sdk" + "/usr/lib64/google-cloud-sdk" + "/opt/google-cloud-sdk" + "/opt/google-cloud-cli" + "/opt/local/libexec/google-cloud-sdk" + "$HOME/.asdf/installs/gcloud/*/" + ) + + for gcloud_sdk_location in $search_locations; do + if [[ -d "${gcloud_sdk_location}" ]]; then + CLOUDSDK_HOME="${gcloud_sdk_location}" + break + fi + done + unset search_locations gcloud_sdk_location +fi + +if (( ${+CLOUDSDK_HOME} )); then + # Source path file + if [[ -f "${CLOUDSDK_HOME}/path.zsh.inc" ]]; then + source "${CLOUDSDK_HOME}/path.zsh.inc" + fi + + # Look for completion file in different paths + for comp_file ( + "${CLOUDSDK_HOME}/completion.zsh.inc" # default location + "/usr/share/google-cloud-sdk/completion.zsh.inc" # apt-based location + ); do + if [[ -f "${comp_file}" ]]; then + source "${comp_file}" + break + fi + done + unset comp_file + + export CLOUDSDK_HOME +fi diff --git a/zsh/.oh-my-zsh/plugins/geeknote/README.md b/zsh/.oh-my-zsh/plugins/geeknote/README.md new file mode 100644 index 0000000..420c625 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/geeknote/README.md @@ -0,0 +1,10 @@ +# Geeknote plugin + +This plugin provides autocompletion for [Geeknote](https://github.com/VitaliyRodnenko/geeknote) +and an alias for `geeknote` called `gn`. + +To use it, add `geeknote` to the plugins array in your zshrc file: + +```zsh +plugins=( ... geeknote ...) +``` diff --git a/zsh/.oh-my-zsh/plugins/geeknote/_geeknote b/zsh/.oh-my-zsh/plugins/geeknote/_geeknote new file mode 100644 index 0000000..f176736 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/geeknote/_geeknote @@ -0,0 +1,157 @@ +#compdef geeknote + +# Geeknote Autocomplete plugin for Zsh +# Requires: Geeknote installed +# Author : Ján Koščo (@s7anley) + +__login() { + # no arguments +} + +__logout() { + _arguments \ + '--force[Do not ask about logging out.]' +} + +__settings() { + _arguments \ + "--editor+[Set the editor, which use to edit and create notes.]::" +} + +__create() { + _arguments \ + '--title+[The note title.]::' \ + '--content+[The note content.]::' \ + '--tags+[One tag or the list of tags which will be added to the note.]::' \ + '--notebook+[Set the notebook where to save note.]::' \ + '--resource+[Add a resource to the note.]::' +} + +__edit() { + _arguments \ + '--note+[The name or ID from the previous search of a note to edit.]::' \ + '--title+[Set new title of the note.]::' \ + '--content+[Set new content of the note.]::' \ + '--tags+[Set new list o tags for the note.]::' \ + '--notebook+[Assign new notebook for the note.]::' \ + '--resource+[Add a resource to the note.]::' +} + +__find() { + _arguments \ + '--search+[Text to search.]::' \ + '--tags+[Notes with which tag/tags to search.]::' \ + '--notebook+[In which notebook search the note.]::' \ + '--date+[Set date in format dd.mm.yyyy or date range dd.mm.yyyy-dd.mm.yyyy.]::' \ + '--count+[How many notes show in the result list.]::' \ + '--with-url[Add direct url of each note in results to Evernote web-version.]' \ + '--content-search[Search by content, not by title.]' \ + '--exact-entry[Search for exact entry of the request.]' +} + +__show() { + _arguments \ + '--note+[The name or ID from the previous search of a note to show.]::' \ + '--raw[Show the raw note body.]' +} + +__remove() { + _arguments \ + '--note+[The name or ID from the previous search of a note to remove.]::' \ + '--force[Do not ask about removing.]' +} + +__notebook-list() { + # no arguments +} + +__notebook-create() { + _arguments \ + '--title+[Set the title of new notebook.]::' +} + +__notebook-edit() { + _arguments \ + '--title+[Set the title of new notebook.]::' \ + '--notebook+[The name of a notebook to rename.]::' +} + +__tag-list() { + # no arguments +} + +__tag-create() { + _arguments \ + '--title+[Set the title of new tag.]::' +} + +__tag-edit() { + _arguments \ + '--tagname+[The name of a tag to rename.]::' \ + '--title+[Set the new name of tag.]::' +} + +__user() { + _arguments \ + '--full[Show full information.]' +} + +local -a _1st_arguments +_1st_arguments=( + 'login':'Authorize in Evernote.' + 'logout':'Logout from Evernote.' + 'settings':'Show and edit current settings.' + 'create':'Create note in Evernote.' + 'edit':'Edit note in Evernote.' + 'find':'Search notes in Evernote.' + 'show':'Output note in the terminal.' + 'remove':'Remove note from Evernote.' + 'notebook-list':'Show the list of existing notebooks in your Evernote.' + 'notebook-create':'Create new notebook.' + 'notebook-edit':'Edit/rename notebook.' + 'tag-list':'Show the list of existing tags in your Evernote.' + 'tag-create':'Create new tag.' + 'tag-edit':'Edit/rename tag.' + 'user':'Show information about active user.' +) + +_arguments '*:: :->command' + +if (( CURRENT == 1 )); then + _describe -t commands "geeknote command" _1st_arguments + return +fi + +local -a _command_args +case "$words[1]" in + login) + __login ;; + logout) + __logout ;; + settings) + __settings ;; + create) + __create ;; + edit) + __edit ;; + find) + __find ;; + show) + __show ;; + remove) + __remove ;; + notebook-list) + __notebook-list ;; + notebook-create) + __notebook-create ;; + notebook-edit) + __notebook-edit ;; + tag-list) + __tag-list ;; + tag-create) + __tag-create ;; + tag-edit) + __tag-edit ;; + user) + __user ;; +esac diff --git a/zsh/.oh-my-zsh/plugins/geeknote/geeknote.plugin.zsh b/zsh/.oh-my-zsh/plugins/geeknote/geeknote.plugin.zsh new file mode 100644 index 0000000..31b693a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/geeknote/geeknote.plugin.zsh @@ -0,0 +1,2 @@ +#Alias +alias gn='geeknote' diff --git a/zsh/.oh-my-zsh/plugins/gem/README.md b/zsh/.oh-my-zsh/plugins/gem/README.md new file mode 100644 index 0000000..754c976 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gem/README.md @@ -0,0 +1,17 @@ +# Gem plugin + +This plugin adds completions and aliases for [Gem](https://rubygems.org/). The completions include the common `gem` subcommands as well as the installed gems in the current directory. + +To use it, add `gem` to the plugins array in your zshrc file: + +```zsh +plugins=(... gem) +``` + +## Aliases + +| Alias | Command | Description | +|----------------------|-------------------------------|--------------------------------------------| +| gemb | `gem build *.gemspec` | Build a gem from a gemspec | +| gemp | `gem push *.gem` | Push a gem up to the gem server | +| gemy [gem] [version] | `gem yank [gem] -v [version]` | Remove a pushed gem version from the index | diff --git a/zsh/.oh-my-zsh/plugins/gem/_gem b/zsh/.oh-my-zsh/plugins/gem/_gem new file mode 100644 index 0000000..0c86678 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gem/_gem @@ -0,0 +1,72 @@ +#compdef gem +#autoload + +# gem zsh completion, based on homebrew completion + +_gem_installed() { + installed_gems=(${(f)"$(gem list --local --no-versions)"}) +} + +local -a _1st_arguments + +_1st_arguments=( + 'build:Build a gem from a gemspec' + 'cert:Manage RubyGems certificates and signing settings' + 'check:Check a gem repository for added or missing files' + 'cleanup:Clean up old versions of installed gems in the local repository' + 'contents:Display the contents of the installed gems' + 'dependency:Show the dependencies of an installed gem' + 'environment:Display information about the RubyGems environment' + 'fetch:Download a gem and place it in the current directory' + 'generate_index:Generates the index files for a gem server directory' + 'help:Provide help on the `gem` command' + 'install:Install a gem into the local repository' + 'list:Display gems whose name starts with STRING' + 'lock:Generate a lockdown list of gems' + 'mirror:Mirror all gem files (requires rubygems-mirror)' + 'outdated:Display all gems that need updates' + 'owner:Manage gem owners on RubyGems.org.' + 'pristine:Restores installed gems to pristine condition from files located in the gem cache' + 'push:Push a gem up to RubyGems.org' + 'query:Query gem information in local or remote repositories' + 'rdoc:Generates RDoc for pre-installed gems' + 'search:Display all gems whose name contains STRING' + 'server:Documentation and gem repository HTTP server' + 'sources:Manage the sources and cache file RubyGems uses to search for gems' + 'specification:Display gem specification (in yaml)' + 'stale:List gems along with access times' + 'uninstall:Uninstall gems from the local repository' + 'unpack:Unpack an installed gem to the current directory' + 'update:Update installed gems to the latest version' + 'which:Find the location of a library file you can require' + 'yank:Remove a specific gem version release from RubyGems.org' +) + +local expl +local -a gems installed_gems + +_arguments \ + '(-v --version)'{-v,--version}'[show version]' \ + '(-h --help)'{-h,--help}'[show help]' \ + '*:: :->subcmds' && return 0 + +if (( CURRENT == 1 )); then + _describe -t commands "gem subcommand" _1st_arguments + return +fi + +case "$words[1]" in + build) + _files -g "*.gemspec" + ;; + install) + _files ;; + list) + if [[ "$state" == forms ]]; then + _gem_installed + _requested installed_gems expl 'installed gems' compadd -a installed_gems + fi ;; + uninstall|update) + _gem_installed + _wanted installed_gems expl 'installed gems' compadd -a installed_gems ;; +esac diff --git a/zsh/.oh-my-zsh/plugins/gem/gem.plugin.zsh b/zsh/.oh-my-zsh/plugins/gem/gem.plugin.zsh new file mode 100644 index 0000000..86a37a4 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gem/gem.plugin.zsh @@ -0,0 +1,7 @@ +alias gemb="gem build *.gemspec" +alias gemp="gem push *.gem" + +# gemy GEM 0.0.0 = gem yank GEM -v 0.0.0 +function gemy { + gem yank $1 -v $2 +} \ No newline at end of file diff --git a/zsh/.oh-my-zsh/plugins/genpass/README.md b/zsh/.oh-my-zsh/plugins/genpass/README.md new file mode 100644 index 0000000..21abe83 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/genpass/README.md @@ -0,0 +1,66 @@ +# genpass + +This plugin provides three unique password generators for ZSH. Each generator +has at least a 128-bit security margin and generates passwords from the +cryptographically secure `/dev/urandom`. Each generator can also take an +optional numeric argument to generate multiple passwords. + +To use it from an interactive ZSH, add `genpass` to the plugins array in your +zshrc file: + + plugins=(... genpass) + +You can also invoke password generators directly (they are implemented as +standalone executable files), which can be handy when you need to generate +passwords in a script: + + ~/.oh-my-zsh/plugins/genpass/genpass-apple 3 + +## genpass-apple + +Generates a pronounceable pseudoword passphrase of the "cvccvc" consonant/vowel +syntax, inspired by [Apple's iCloud Keychain password generator][1]. Each +password has exactly 1 digit placed at the edge of a "word" and exactly 1 +capital letter to satisfy most password security requirements. + + % genpass-apple + gelcyv-foqtam-fotqoh-viMleb-lexduv-6ixfuk + + % genpass-apple 3 + japvyz-qyjti4-kajrod-nubxaW-hukkan-dijcaf + vydpig-fucnul-3ukpog-voggom-zygNad-jepgad + zocmez-byznis-hegTaj-jecdyq-qiqmiq-5enwom + +[1]: https://developer.apple.com/password-rules/ + +## genpass-monkey + +Generates visually unambiguous random meaningless strings using [Crockford's +base32][2]. + + % genpass-monkey + xt7gn976e7jj3fstgpy27330x3 + + % genpass-monkey 3 + n1qqwtzgejwgqve9yzf2gxvx4m + r2n3f5s6vbqs2yx7xjnmahqewy + 296w9y9rts3p5r9yay0raek8e5 + +[2]: https://www.crockford.com/base32.html + +## genpass-xkcd + +Generates passphrases from `/usr/share/dict/words` inspired by the [famous (and +slightly misleading) XKCD comic][3]. Each passphrase is prepended with a digit +showing the number of words in the passphrase to adhere to password security +requirements that require digits. Each word is 6 characters or less. + + % genpass-xkcd + 9-eaten-Slav-rife-aired-hill-cordon-splits-welsh-napes + + % genpass-xkcd 3 + 9-worker-Vlad-horde-shrubs-smite-thwart-paw-alters-prawns + 9-tutors-stink-rhythm-junk-snappy-hooray-barbs-mewl-clomp + 9-vital-escape-Angkor-Huff-wet-Mayra-abbés-putts-guzzle + +[3]: https://xkcd.com/936/ diff --git a/zsh/.oh-my-zsh/plugins/genpass/genpass-apple b/zsh/.oh-my-zsh/plugins/genpass/genpass-apple new file mode 100755 index 0000000..a2ce7ed --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/genpass/genpass-apple @@ -0,0 +1,79 @@ +#!/usr/bin/env zsh +# +# Usage: genpass-apple [NUM] +# +# Generate a password made of 6 pseudowords of 6 characters each +# with the security margin of at least 128 bits. +# +# Example password: xudmec-4ambyj-tavric-mumpub-mydVop-bypjyp +# +# If given a numerical argument, generate that many passwords. + +emulate -L zsh -o no_unset -o warn_create_global -o warn_nested_var + +if [[ ARGC -gt 1 || ${1-1} != ${~:-<1-$((16#7FFFFFFF))>} ]]; then + print -ru2 -- "usage: $0 [NUM]" + return 1 +fi + +zmodload zsh/system zsh/mathfunc || return + +{ + local -r vowels=aeiouy + local -r consonants=bcdfghjklmnpqrstvwxz + local -r digits=0123456789 + + # Sets REPLY to a uniformly distributed random number in [1, $1]. + # Requires: $1 <= 256. + function -$0-rand() { + local c + while true; do + sysread -s1 c || return + # Avoid bias towards smaller numbers. + (( #c < 256 / $1 * $1 )) && break + done + typeset -g REPLY=$((#c % $1 + 1)) + } + + local REPLY chars + + repeat ${1-1}; do + # Generate 6 pseudowords of the form cvccvc where c and v + # denote random consonants and vowels respectively. + local words=() + repeat 6; do + words+=('') + repeat 2; do + for chars in $consonants $vowels $consonants; do + -$0-rand $#chars || return + words[-1]+=$chars[REPLY] + done + done + done + + local pwd=${(j:-:)words} + + # Replace either the first or the last character in one of + # the words with a random digit. + -$0-rand $#digits || return + local digit=$digits[REPLY] + -$0-rand $((2 * $#words)) || return + pwd[REPLY/2*7+2*(REPLY%2)-1]=$digit + + # Convert one lower-case character to upper case. + while true; do + -$0-rand $#pwd || return + [[ $vowels$consonants == *$pwd[REPLY]* ]] && break + done + # NOTE: We aren't using ${(U)c} here because its results are + # locale-dependent. For example, when upper-casing 'i' in Turkish + # locale we would get 'İ', a.k.a. latin capital letter i with dot + # above. We could set LC_CTYPE=C locally but then we would run afoul + # of this zsh bug: https://www.zsh.org/mla/workers/2020/msg00588.html. + local c=$pwd[REPLY] + printf -v c '%o' $((#c - 32)) + printf "%s\\$c%s\\n" "$pwd[1,REPLY-1]" "$pwd[REPLY+1,-1]" || return + done +} always { + unfunction -m -- "-${(b)0}-*" +} } ]]; then + print -ru2 -- "usage: $0 [NUM]" + return 1 +fi + +zmodload zsh/system || return + +{ + local -r chars=abcdefghjkmnpqrstvwxyz0123456789 + local c + repeat ${1-1}; do + repeat 26; do + sysread -s1 c || return + # There is uniform because $#chars divides 256. + print -rn -- $chars[#c%$#chars+1] + done + print + done +} } ]]; then + print -ru2 -- "usage: $0 [NUM]" + return 1 +fi + +zmodload zsh/system zsh/mathfunc || return + +local -r dict=/usr/share/dict/words + +if [[ ! -e $dict ]]; then + print -ru2 -- "$0: file not found: $dict" + return 1 +fi + +# Read all dictionary words and leave only those made of 1-6 characters. +local -a words +words=(${(M)${(f)"$(<$dict)"}:#[a-zA-Z](#c1,6)}) || return + +if (( $#words < 2 )); then + print -ru2 -- "$0: not enough suitable words in $dict" + return 1 +fi + +if (( $#words > 16#7FFFFFFF )); then + print -ru2 -- "$0: too many words in $dict" + return 1 +fi + +# Figure out how many words we need for 128 bits of security margin. +# Each word adds log2($#words) bits. +local -i n=$((ceil(128. / (log($#words) / log(2))))) + +{ + local c + repeat ${1-1}; do + print -rn -- $n + repeat $n; do + while true; do + # Generate a random number in [0, 2**31). + local -i rnd=0 + repeat 4; do + sysread -s1 c || return + (( rnd = (~(1 << 23) & rnd) << 8 | #c )) + done + # Avoid bias towards words in the beginning of the list. + (( rnd < 16#7FFFFFFF / $#words * $#words )) || continue + print -rn -- -$words[rnd%$#words+1] + break + done + done + print + done +} | "$ZSH_CACHE_DIR/completions/_gh" &| diff --git a/zsh/.oh-my-zsh/plugins/git-auto-fetch/README.md b/zsh/.oh-my-zsh/plugins/git-auto-fetch/README.md new file mode 100644 index 0000000..2939deb --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-auto-fetch/README.md @@ -0,0 +1,50 @@ +# Git auto-fetch + +Automatically fetches all changes from all remotes while you are working in a git-initialized directory. + +To use it, add `git-auto-fetch` to the plugins array in your zshrc file: + +```shell +plugins=(... git-auto-fetch) +``` + +## Usage + +Every time the command prompt is shown all remotes will be fetched in the background. By default, +`git-auto-fetch` will be triggered only if the last auto-fetch was done at least 60 seconds ago. +You can change the fetch interval in your .zshrc: + +```sh +GIT_AUTO_FETCH_INTERVAL=1200 # in seconds +``` + +A log of `git fetch --all` will be saved in `.git/FETCH_LOG`. + +## Toggle auto-fetch per folder + +If you are using a mobile connection or for any other reason you can disable git-auto-fetch +for any folder: + +```shell +$ cd to/your/project +$ git-auto-fetch +disabled +$ git-auto-fetch +enabled +``` + +## Caveats + +Automatically fetching all changes defeats the purpose of `git push --force-with-lease`, +and makes it behave like `git push --force` in some cases. For example: + +Consider that you made some changes and possibly rebased some stuff, which means you'll +need to use `--force-with-lease` to overwrite the remote history of a branch. Between the +time when you make the changes (maybe do a `git log`) and the time when you `git push`, +it's possible that someone else updates the branch you're working on. + +If `git-auto-fetch` triggers then, you'll have fetched the remote changes without knowing +it, and even though you're running the push with `--force-with-lease`, git will overwrite +the recent changes because you already have them in your local repository. The +[`git push --force-with-lease` docs](https://git-scm.com/docs/git-push) talk about possible +solutions to this problem. diff --git a/zsh/.oh-my-zsh/plugins/git-auto-fetch/git-auto-fetch.plugin.zsh b/zsh/.oh-my-zsh/plugins/git-auto-fetch/git-auto-fetch.plugin.zsh new file mode 100644 index 0000000..ca9d5ce --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-auto-fetch/git-auto-fetch.plugin.zsh @@ -0,0 +1,65 @@ +# Default auto-fetch interval: 60 seconds +: ${GIT_AUTO_FETCH_INTERVAL:=60} + +# Necessary for the git-fetch-all function +zmodload zsh/datetime +zmodload -F zsh/stat b:zstat # only zstat command, not stat command + +function git-fetch-all { + ( + # Get git root directory + if ! gitdir="$(command git rev-parse --git-dir 2>/dev/null)"; then + return 0 + fi + + # Do nothing if auto-fetch is disabled or don't have permissions + if [[ ! -w "$gitdir" || -f "$gitdir/NO_AUTO_FETCH" ]] || + [[ -f "$gitdir/FETCH_LOG" && ! -w "$gitdir/FETCH_LOG" ]]; then + return 0 + fi + + # Get time (seconds) when auto-fetch was last run + lastrun="$(zstat +mtime "$gitdir/FETCH_LOG" 2>/dev/null || echo 0)" + # Do nothing if not enough time has passed since last auto-fetch + if (( EPOCHSECONDS - lastrun < $GIT_AUTO_FETCH_INTERVAL )); then + return 0 + fi + + # Fetch all remotes (avoid ssh passphrase prompt) + date -R &>! "$gitdir/FETCH_LOG" + GIT_SSH_COMMAND="command ssh -o BatchMode=yes" \ + GIT_TERMINAL_PROMPT=0 \ + command git fetch --all --recurse-submodules=yes 2>/dev/null &>> "$gitdir/FETCH_LOG" + ) &| +} + +function git-auto-fetch { + # Do nothing if not in a git repository + command git rev-parse --is-inside-work-tree &>/dev/null || return 0 + + # Remove or create guard file depending on its existence + local guard="$(command git rev-parse --git-dir)/NO_AUTO_FETCH" + if [[ -f "$guard" ]]; then + command rm "$guard" && echo "${fg_bold[green]}enabled${reset_color}" + else + command touch "$guard" && echo "${fg_bold[red]}disabled${reset_color}" + fi +} + +# zle-line-init widget (don't redefine if already defined) +(( ! ${+functions[_git-auto-fetch_zle-line-init]} )) || return 0 + +case "$widgets[zle-line-init]" in + # Simply define the function if zle-line-init doesn't yet exist + builtin|"") function _git-auto-fetch_zle-line-init() { + git-fetch-all + } ;; + # Override the current zle-line-init widget, calling the old one + user:*) zle -N _git-auto-fetch_orig_zle-line-init "${widgets[zle-line-init]#user:}" + function _git-auto-fetch_zle-line-init() { + git-fetch-all + zle _git-auto-fetch_orig_zle-line-init -- "$@" + } ;; +esac + +zle -N zle-line-init _git-auto-fetch_zle-line-init diff --git a/zsh/.oh-my-zsh/plugins/git-commit/README.md b/zsh/.oh-my-zsh/plugins/git-commit/README.md new file mode 100644 index 0000000..722a027 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-commit/README.md @@ -0,0 +1,47 @@ +# git-commit plugin + +The git-commit plugin adds several +[git aliases](https://www.git-scm.com/docs/git-config#Documentation/git-config.txt-alias) for +[conventional commit](https://www.conventionalcommits.org/en/v1.0.0/#summary) messages. + +To use it, add `git-commit` to the plugins array in your zshrc file: + +```zsh +plugins=(... git-commit) +``` + +## Syntax + +```zsh +git [(-s, --scope) ""] [(-a, --attention)] "" +``` + +Where `type` is one of the following: + +- `build` +- `chore` +- `ci` +- `docs` +- `feat` +- `fix` +- `perf` +- `refactor` +- `rev` +- `style` +- `test` +- `wip` + +> NOTE: the alias for `revert` type is `rev`, as otherwise it conflicts with the git command of the same name. +> It will still generate a commit message in the format `revert: ` + +> ⚠️ Enabling this plugin will (potentially) overwrite all `alias.` that you manually set. Use with +> care! + +## Examples + +| Git alias | Command | +| --------------------------------------------- | ---------------------------------------------------- | +| `git style "remove trailing whitespace"` | `git commit -m "style: remove trailing whitespace"` | +| `git wip "work in progress"` | `git commit -m "work in progress"` | +| `git fix -s "router" "correct redirect link"` | `git commit -m "fix(router): correct redirect link"` | +| `git rev -s "api" "rollback v2"` | `git commit -m "revert(api): rollback v2"` | diff --git a/zsh/.oh-my-zsh/plugins/git-commit/git-commit.plugin.zsh b/zsh/.oh-my-zsh/plugins/git-commit/git-commit.plugin.zsh new file mode 100644 index 0000000..b8307ab --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-commit/git-commit.plugin.zsh @@ -0,0 +1,58 @@ +local _rev="$(git -C $ZSH rev-parse HEAD 2> /dev/null)" +if [[ $_rev == $(git config --global --get oh-my-zsh.git-commit-alias 2> /dev/null) ]]; then + return +fi +git config --global oh-my-zsh.git-commit-alias "$_rev" + +local -a _git_commit_aliases +_git_commit_aliases=( + 'build' + 'chore' + 'ci' + 'docs' + 'feat' + 'fix' + 'perf' + 'refactor' + 'revert' + 'style' + 'test' + 'wip' +) + +local _alias _type +for _type in "${_git_commit_aliases[@]}"; do + # an alias can't be named "revert" because the git command takes precedence + # https://stackoverflow.com/a/3538791 + case "$_type" in + revert) _alias=rev ;; + *) _alias=$_type ;; + esac + + local _func='!a() { +local _scope _attention _message +while [ $# -ne 0 ]; do +case $1 in + -s | --scope ) + if [ -z $2 ]; then + echo "Missing scope!" + return 1 + fi + _scope="$2" + shift 2 + ;; + -a | --attention ) + _attention="!" + shift 1 + ;; + * ) + _message="${_message} $1" + shift 1 + ;; +esac +done +git commit -m "'$_type'${_scope:+(${_scope})}${_attention}:${_message}" +}; a' + + git config --global alias.$_alias "$_func" +done diff --git a/zsh/.oh-my-zsh/plugins/git-escape-magic/README.md b/zsh/.oh-my-zsh/plugins/git-escape-magic/README.md new file mode 100644 index 0000000..e426f6b --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-escape-magic/README.md @@ -0,0 +1,16 @@ +# Git Escape Magic + +This plugin is copied from the original at +https://github.com/knu/zsh-git-escape-magic. All credit for the +functionality enabled by this plugin should go to @knu. + +An excerpt from that project's readme explains its purpose. + +> It eliminates the need for manually escaping those meta-characters. The zle function it provides is context aware and recognizes the characteristics of each subcommand of git. Every time you type one of these meta-characters on a git command line, it automatically escapes the meta-character with a backslash as necessary and as appropriate. + +## Usage + +To use this plugin, add it to your list of plugins in your `.zshrc` file. + +**NOTE**: If you use url-quote-magic, it must be included before this +plugin runs to prevent any conflicts. diff --git a/zsh/.oh-my-zsh/plugins/git-escape-magic/git-escape-magic b/zsh/.oh-my-zsh/plugins/git-escape-magic/git-escape-magic new file mode 100644 index 0000000..f7af3f0 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-escape-magic/git-escape-magic @@ -0,0 +1,135 @@ +# -*- mode: sh -*- +# +# git-escape-magic - zle tweak for git command line arguments +# +# Copyright (c) 2011, 2012, 2014 Akinori MUSHA +# Licensed under the 2-clause BSD license. +# +# This tweak eliminates the need for manually escaping shell +# meta-characters such as [~^{}] that are used for specifying a git +# object (commit or tree). Every time you type one of these +# characters on a git command line, it is automatically escaped with a +# backslash as necessary and as appropriate. +# +# If you want to use this with url-quote-magic, make sure to enable it +# first. +# +# Usage: +# autoload -Uz git-escape-magic +# git-escape-magic +# + +git-escape-magic.self-insert() { + emulate -L zsh + setopt extendedglob + local self_insert_function + zstyle -s ':git-escape-magic' self-insert-function self_insert_function + + if [[ "$KEYS" == [{}~^]* ]] && { + local qkey="${(q)KEYS}" + [[ "$KEYS" != "$qkey" ]] + } && { + local lbuf="$LBUFFER$qkey" + [[ "${(Q)LBUFFER}$KEYS" == "${(Q)lbuf}" ]] + } && { + local -a words + words=("${(@Q)${(z)lbuf}}") + [[ "$words[(i)(*/|)git(|-[^/]##)]" -le $#words ]] + } + then + local i + i="$words[(I)([;(){\&]|\&[\&\!]|\|\||[=<>]\(*)]" + if [[ $i -gt 0 ]]; then + shift $((i-1)) words + if [[ "$words[1]" == [\=\<\>]\(* ]]; then + words[1]="${words[1]#[=<>]\(}" + else + [[ "$words[1]" == \; && $words[2] == (then|else|elif|do) ]] && shift words + shift words + fi + fi + while [[ "$words[1]" == (if|while|until|\!) ]]; do + shift words + done + while [[ "$words[1]" == [A-Za-z_][A-Za-z0-9_]#=* ]]; do + shift words + done + [[ "$words[1]" == (*/|)git(|-[^/]##) ]] && { + local subcommand + subcommand="${words[1]##*/git-}" + if [[ -z "$subcommand" ]]; then + shift words + subcommand="$words[1]" + fi + [[ $#words -ge 2 ]] + } && + case "$subcommand" in + # commands that may take pathspec but never take refspec with [{}~^] + (add|rm|am|apply|check-attr|checkout-index|clean|clone|config|diff-files|hash-object|help|index-pack|mailinfo|mailsplit|merge-file|merge-index|mergetool|mktag|mv|pack-objects|pack-redundant|relink|send-email|show-index|show-ref|stage|status|verify-pack) + false ;; + # commands that may take pathspec but rarely take refspec with [{}~^] + (for-each-ref|grep|ls-files|update-index) + false ;; + (archive|ls-tree) + ! [[ $#words -ge 3 && + "$words[-2]" == [^-]* ]] ;; + (diff-tree) + ! [[ $#words -ge 4 && + "$words[-2]" == [^-]* && + "$words[-3]" == [^-]* ]] ;; + (*) + [[ $words[(i)--] -gt $#words ]] ;; + esac && + case "${words[-1]%%"$KEYS"}" in + (*[@^]) + [[ "$KEYS" == [{~^]* ]] ;; + (*[@^]\{[^}]##) + [[ "$KEYS" == \}* ]] ;; + (?*) + [[ "$KEYS" == [~^]* ]] ;; + (*) + false ;; + esac && + LBUFFER="$LBUFFER\\" + fi + + zle "$self_insert_function" +} + +git-escape-magic.on() { + emulate -L zsh + local self_insert_function="${$(zle -lL | awk \ + '$1=="zle"&&$2=="-N"&&$3=="self-insert"{print $4;exit}'):-.self-insert}" + + [[ "$self_insert_function" == git-escape-magic.self-insert ]] && + return 0 + + # For url-quote-magic which does not zle -N itself + zle -la "$self_insert_function" || zle -N "$self_insert_function" + + zstyle ':git-escape-magic' self-insert-function "$self_insert_function" + + zle -A git-escape-magic.self-insert self-insert + return 0 +} + +git-escape-magic.off() { + emulate -L zsh + local self_insert_function + zstyle -s ':git-escape-magic' self-insert-function self_insert_function + + [[ -n "$self_insert_function" ]] && + zle -A "$self_insert_function" self-insert + return 0 +} + +zle -N git-escape-magic.self-insert +zle -N git-escape-magic.on +zle -N git-escape-magic.off + +git-escape-magic() { + git-escape-magic.on +} + +[[ -o kshautoload ]] || git-escape-magic "$@" + diff --git a/zsh/.oh-my-zsh/plugins/git-escape-magic/git-escape-magic.plugin.zsh b/zsh/.oh-my-zsh/plugins/git-escape-magic/git-escape-magic.plugin.zsh new file mode 100644 index 0000000..fdaee2a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-escape-magic/git-escape-magic.plugin.zsh @@ -0,0 +1,9 @@ +# Automatically detect and escape zsh globbing meta-characters when used with +# git refspec characters like `[^~{}]`. NOTE: This must be loaded _after_ +# url-quote-magic. +# +# This trick is detailed at https://github.com/knu/zsh-git-escape-magic and is +# what allowed this plugin to exist. + +autoload -Uz git-escape-magic +git-escape-magic diff --git a/zsh/.oh-my-zsh/plugins/git-extras/README.md b/zsh/.oh-my-zsh/plugins/git-extras/README.md new file mode 100644 index 0000000..e941f9f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-extras/README.md @@ -0,0 +1,17 @@ +# git-extras + +This plugin provides completion definitions for some of the commands defined by [git-extras](https://github.com/tj/git-extras), which must already be installed. + +To use it, add `git-extras` to the plugins array in your zshrc file: + +```zsh +plugins=(... git-extras) +``` + +## Setup notes + +The completions work by augmenting the `_git` completion provided by `zsh`. This only works with the `zsh`-provided `_git`, not the `_git` provided by `git` itself. If you have both `zsh` and `git` installed, you need to make sure that the `zsh`-provided `_git` takes precedence. + +### OS X Homebrew Setup + +**NOTE:** this no longer works on current Homebrew distributions of git. ~~On OS X with Homebrew, you need to install `git` with `brew install git --without-completions`. Otherwise, `git`'s `_git` will take precedence, and you won't see the completions for `git-extras` commands.~~ diff --git a/zsh/.oh-my-zsh/plugins/git-extras/git-extras.plugin.zsh b/zsh/.oh-my-zsh/plugins/git-extras/git-extras.plugin.zsh new file mode 100644 index 0000000..4bc81a5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-extras/git-extras.plugin.zsh @@ -0,0 +1,418 @@ +# ------------------------------------------------------------------------------ +# Description +# ----------- +# +# Completion script for git-extras (https://github.com/tj/git-extras). +# +# This depends on and reuses some of the internals of the _git completion +# function that ships with zsh itself. It will not work with the _git that ships +# with git. +# +# ------------------------------------------------------------------------------ +# Authors +# ------- +# +# * Alexis GRIMALDI (https://github.com/agrimaldi) +# * spacewander (https://github.com/spacewander) +# +# ------------------------------------------------------------------------------ +# Inspirations +# ----------- +# +# * git-extras (https://github.com/tj/git-extras) +# * git-flow-completion (https://github.com/bobthecow/git-flow-completion) +# +# ------------------------------------------------------------------------------ + + +# Internal functions +# These are a lot like their __git_* equivalents inside _git + +__gitex_command_successful () { + if (( ${#*:#0} > 0 )); then + _message 'not a git repository' + return 1 + fi + return 0 +} + +__gitex_commits() { + declare -A commits + git log --oneline -15 | sed 's/\([[:alnum:]]\{7\}\) /\1:/' | while read commit + do + hash=$(echo $commit | cut -d':' -f1) + commits[$hash]="$commit" + done + local ret=1 + _describe -t commits commit commits && ret=0 +} + +__gitex_remote_names() { + local expl + declare -a remote_names + remote_names=(${(f)"$(_call_program remotes git remote 2>/dev/null)"}) + __gitex_command_successful || return + _wanted remote-names expl remote-name compadd $* - $remote_names +} + +__gitex_tag_names() { + local expl + declare -a tag_names + tag_names=(${${(f)"$(_call_program tags git for-each-ref --format='"%(refname)"' refs/tags 2>/dev/null)"}#refs/tags/}) + __gitex_command_successful || return + _wanted tag-names expl tag-name compadd $* - $tag_names +} + + +__gitex_branch_names() { + local expl + declare -a branch_names + branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}) + __gitex_command_successful || return + _wanted branch-names expl branch-name compadd $* - $branch_names +} + +__gitex_specific_branch_names() { + local expl + declare -a branch_names + branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads/"$1" 2>/dev/null)"}#refs/heads/$1/}) + __gitex_command_successful || return + _wanted branch-names expl branch-name compadd - $branch_names +} + +__gitex_feature_branch_names() { + __gitex_specific_branch_names 'feature' +} + +__gitex_submodule_names() { + local expl + declare -a submodule_names + submodule_names=(${(f)"$(_call_program branchrefs git submodule status | awk '{print $2}')"}) # ' + __gitex_command_successful || return + _wanted submodule-names expl submodule-name compadd $* - $submodule_names +} + + +__gitex_author_names() { + local expl + declare -a author_names + author_names=(${(f)"$(_call_program branchrefs git log --format='%aN' | sort -u)"}) + __gitex_command_successful || return + _wanted author-names expl author-name compadd $* - $author_names +} + +# subcommands +# new subcommand should be added in alphabetical order +_git-authors() { + _arguments -C \ + '(--list -l)'{--list,-l}'[show authors]' \ + '--no-email[without email]' \ +} + +_git-changelog() { + _arguments \ + '(-l --list)'{-l,--list}'[list commits]' \ +} + +_git-clear() { + _arguments \ + '(-f --force)'{-f,--force}'[force clear]' \ + '(-h --help)'{-h,--help}'[help message]' \ +} + +_git-coauthor() { + _arguments \ + ':co-author[co-author to add]' \ + ':co-author-email[email address of co-author to add]' +} + +_git-contrib() { + _arguments \ + ':author:__gitex_author_names' +} + + +_git-count() { + _arguments \ + '--all[detailed commit count]' +} + +_git-create-branch() { + local curcontext=$curcontext state line + _arguments -C \ + ': :->command' \ + '*:: :->option-or-argument' + + case "$state" in + (command) + _arguments \ + '(--remote -r)'{--remote,-r}'[setup remote tracking branch]' + ;; + (option-or-argument) + curcontext=${curcontext%:*}-$line[1]: + case $line[1] in + -r|--remote ) + _arguments -C \ + ':remote-name:__gitex_remote_names' + ;; + esac + esac +} + +_git-delete-branch() { + _arguments \ + ':branch-name:__gitex_branch_names' +} + +_git-delete-squashed-branches() { + _arguments \ + ':branch-name:__gitex_branch_names' +} + + +_git-delete-submodule() { + _arguments \ + ':submodule-name:__gitex_submodule_names' +} + + +_git-delete-tag() { + _arguments \ + ':tag-name:__gitex_tag_names' +} + + +_git-effort() { + _arguments \ + '--above[ignore file with less than x commits]' +} + + +_git-extras() { + local curcontext=$curcontext state line ret=1 + declare -A opt_args + + _arguments -C \ + ': :->command' \ + '*:: :->option-or-argument' && ret=0 + + case $state in + (command) + declare -a commands + commands=( + 'update:update git-extras' + ) + _describe -t commands command commands && ret=0 + ;; + esac + + _arguments \ + '(-v --version)'{-v,--version}'[show current version]' +} + + +_git-feature() { + local curcontext=$curcontext state line ret=1 + declare -A opt_args + + _arguments -C \ + ': :->command' \ + '*:: :->option-or-argument' && ret=0 + + case $state in + (command) + declare -a commands + commands=( + 'finish:merge feature into the current branch' + ) + _describe -t commands command commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*}-$line[1]: + case $line[1] in + (finish) + _arguments -C \ + '--squash[Use squash merge]' \ + ':branch-name:__gitex_feature_branch_names' + ;; + -r|--remote ) + _arguments -C \ + ':remote-name:__gitex_remote_names' + ;; + esac + return 0 + esac + + _arguments \ + '(--remote -r)'{--remote,-r}'[setup remote tracking branch]' +} + +_git-graft() { + _arguments \ + ':src-branch-name:__gitex_branch_names' \ + ':dest-branch-name:__gitex_branch_names' +} + +_git-guilt() { + _arguments -C \ + '(--email -e)'{--email,-e}'[display author emails instead of names]' \ + '(--ignore-whitespace -w)'{--ignore-whitespace,-w}'[ignore whitespace only changes]' \ + '(--debug -d)'{--debug,-d}'[output debug information]' \ + '-h[output usage information]' +} + +_git-ignore() { + _arguments -C \ + '(--local -l)'{--local,-l}'[show local gitignore]' \ + '(--global -g)'{--global,-g}'[show global gitignore]' \ + '(--private -p)'{--private,-p}'[show repo gitignore]' +} + + +_git-info() { + _arguments -C \ + '(--color -c)'{--color,-c}'[use color for information titles]' \ + '--no-config[do not show list all variables set in config file, along with their values]' +} + + +_git-merge-into() { + _arguments '--ff-only[merge only fast-forward]' + _arguments \ + ':src:__gitex_branch_names' \ + ':dest:__gitex_branch_names' +} + +_git-missing() { + _arguments \ + ':first-branch-name:__gitex_branch_names' \ + ':second-branch-name:__gitex_branch_names' +} + +_git-release() { + _arguments -C \ + '-c[Generates/populates the changelog with all commit message since the last tag.]' \ + '-r[The "remote" repository that is destination of a push operation.]' \ + '-m[use the custom commit information instead of the default message.]' \ + '-s[Create a signed and annotated tag.]' \ + '-u[Create a tag, annotated and signed with the given key.]' \ + '--semver[If the latest tag in your repo matches the semver format requirement, you could increase part of it as the new release tag.]' \ + '--prefix[Add a prefix string to semver to allow more complex tags.]' \ + '--no-empty-commit[Avoid creating empty commit if nothing could be committed.]' \ + '--[The arguments listed after "--" separator will be passed to pre/post-release hook.]' +} + +_git-squash() { + _arguments '--squash-msg[commit with the squashed commit messages]' + _arguments \ + ':branch-name:__gitex_branch_names' +} + +_git-stamp() { + _arguments -C \ + '(--replace -r)'{--replace,-r}'[replace stamps with same id]' +} + +_git-standup() { + _arguments -C \ + '-a[Specify the author of commits. Use "all" to specify all authors.]' \ + '-d[Show history since N days ago]' \ + '-D[Specify the date format displayed in commit history]' \ + '-f[Fetch commits before showing history]' \ + '-g[Display GPG signed info]' \ + '-h[Display help message]' \ + '-L[Enable the inclusion of symbolic links]' \ + '-m[The depth of recursive directory search]' \ + '-B[Display the commits in branch groups]' +} + +_git-summary() { + _arguments '--line[summarize with lines rather than commits]' + _arguments '--dedup-by-email[remove duplicate users by the email address]' + _arguments '--no-merges[exclude merge commits]' + __gitex_commits +} + +_git-undo(){ + _arguments -C \ + '(--soft -s)'{--soft,-s}'[only rolls back the commit but changes remain un-staged]' \ + '(--hard -h)'{--hard,-h}'[wipes your commit(s)]' +} + +zstyle -g existing_user_commands ':completion:*:*:git:*' user-commands + +zstyle ':completion:*:*:git:*' user-commands $existing_user_commands \ + alias:'define, search and show aliases' \ + abort:'abort current revert, merge, rebase, or cherry-pick process' \ + archive-file:'export the current head of the git repository to an archive' \ + authors:'generate authors report' \ + browse:'open repo website in browser' \ + browse-ci:'open repo CI page in browser' \ + bug:'create bug branch' \ + bulk:'run bulk commands' \ + brv:'list branches sorted by their last commit date'\ + changelog:'generate a changelog report' \ + chore:'create chore branch' \ + clear-soft:'soft clean up a repository' \ + clear:'rigorously clean up a repository' \ + coauthor:'add a co-author to the last commit' \ + commits-since:'show commit logs since some date' \ + contrib:'show user contributions' \ + count:'show commit count' \ + create-branch:'create branches' \ + delete-branch:'delete branches' \ + delete-merged-branches:'delete merged branches' \ + delete-squashed-branches:'delete squashed branches' \ + delete-submodule:'delete submodules' \ + delete-tag:'delete tags' \ + delta:'lists changed files' \ + effort:'show effort statistics on file(s)' \ + extras:'awesome git utilities' \ + feature:'create/merge feature branch' \ + force-clone:'overwrite local repositories with clone' \ + fork:'fork a repo on GitHub' \ + fresh-branch:'create fresh branches' \ + gh-pages:'create the GitHub pages branch' \ + graft:'merge and destroy a given branch' \ + guilt:'calculate change between two revisions' \ + ignore-io:'get sample gitignore file' \ + ignore:'add .gitignore patterns' \ + info:'returns information on current repository' \ + local-commits:'list local commits' \ + lock:'lock a file excluded from version control' \ + locked:'ls files that have been locked' \ + magic:'commits everything with a generated message' \ + merge-into:'merge one branch into another' \ + merge-repo:'merge two repo histories' \ + missing:'show commits missing from another branch' \ + mr:'checks out a merge request locally' \ + obliterate:'rewrite past commits to remove some files' \ + paste:'send patches to pastebin sites' \ + pr:'checks out a pull request locally' \ + psykorebase:'rebase a branch with a merge commit' \ + pull-request:'create pull request to GitHub project' \ + reauthor:'replace the author and/or committer identities in commits and tags' \ + rebase-patch:'rebases a patch' \ + refactor:'create refactor branch' \ + release:'commit, tag and push changes to the repository' \ + rename-branch:'rename a branch' \ + rename-tag:'rename a tag' \ + rename-remote:'rename a remote' \ + repl:'git read-eval-print-loop' \ + reset-file:'reset one file' \ + root:'show path of root' \ + scp:'copy files to ssh compatible `git-remote`' \ + sed:'replace patterns in git-controlled files' \ + setup:'set up a git repository' \ + show-merged-branches:'show merged branches' \ + show-tree:'show branch tree of commit history' \ + show-unmerged-branches:'show unmerged branches' \ + squash:'import changes from a branch' \ + stamp:'stamp the last commit message' \ + standup:'recall the commit history' \ + summary:'show repository summary' \ + sync:'sync local branch with remote branch' \ + touch:'touch and add file to the index' \ + undo:'remove latest commits' \ + unlock:'unlock a file excluded from version control' \ + utimes:'change files modification time to their last commit date' diff --git a/zsh/.oh-my-zsh/plugins/git-flow-avh/README.md b/zsh/.oh-my-zsh/plugins/git-flow-avh/README.md new file mode 100644 index 0000000..4edcb91 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-flow-avh/README.md @@ -0,0 +1,19 @@ +# git-flow (AVH Edition) plugin + +This plugin adds completion for the [git-flow (AVH Edition)](https://github.com/petervanderdoes/gitflow-avh). +The AVH Edition of the git extensions that provides high-level repository operations for [Vincent Driessen's branching model](https://nvie.com/posts/a-successful-git-branching-model/). + +To use it, add `git-flow-avh` to the plugins array in your zshrc file: + +```zsh +plugins=(... git-flow-avh) +``` + +## Requirements + +1. The git-flow tool has to be [installed](https://github.com/petervanderdoes/gitflow-avh#installing-git-flow) + separately. + +2. You have to use zsh's git completion instead of the git project's git completion. This is typically + done by default so you don't need to do anything else. If you installed git with Homebrew you + might have to uninstall the git completion it's bundled with. diff --git a/zsh/.oh-my-zsh/plugins/git-flow-avh/git-flow-avh.plugin.zsh b/zsh/.oh-my-zsh/plugins/git-flow-avh/git-flow-avh.plugin.zsh new file mode 100644 index 0000000..1e5884f --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-flow-avh/git-flow-avh.plugin.zsh @@ -0,0 +1,526 @@ +_git-flow () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'init:Initialize a new git repo with support for the branching model.' + 'feature:Manage your feature branches.' + 'bugfix:Manage your bugfix branches.' + 'config:Manage your configuration.' + 'release:Manage your release branches.' + 'hotfix:Manage your hotfix branches.' + 'support:Manage your support branches.' + 'version:Shows version information.' + 'finish:Finish the branch you are currently on.' + 'delete:Delete the branch you are currently on.' + 'publish:Publish the branch you are currently on.' + 'rebase:Rebase the branch you are currently on.' + ) + _describe -t commands 'git flow' subcommands + ;; + + (options) + case $line[1] in + + (init) + _arguments \ + -f'[Force setting of gitflow branches, even if already configured]' + ;; + + (version) + ;; + + (hotfix) + __git-flow-hotfix + ;; + + (release) + __git-flow-release + ;; + + (feature) + __git-flow-feature + ;; + (bugfix) + __git-flow-bugfix + ;; + + (config) + __git-flow-config + ;; + + esac + ;; + esac +} + +__git-flow-release () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'start:Start a new release branch.' + 'finish:Finish a release branch.' + 'list:List all your release branches. (Alias to `git flow release`)' + 'publish:Publish release branch to remote.' + 'track:Checkout remote release branch.' + 'rebase:Rebase from integration branch.' + 'delete:Delete a release branch.' + ) + _describe -t commands 'git flow release' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':version:__git_flow_version_list' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -s'[Sign the release tag cryptographically]'\ + -u'[Use the given GPG-key for the digital signature (implies -s)]'\ + -m'[Use the given tag message]'\ + -p'[Push to $ORIGIN after performing finish]'\ + ':version:__git_flow_version_list' + ;; + + (delete) + _arguments \ + -f'[Force deletion]' \ + -r'[Delete remote branch]' \ + ':version:__git_flow_version_list' + ;; + + (publish) + _arguments \ + ':version:__git_flow_version_list' + ;; + + (track) + _arguments \ + ':version:__git_flow_version_list' + ;; + + (rebase) + _arguments \ + -i'[Do an interactive rebase]' \ + ':branch:__git_branch_names' + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git-flow-hotfix () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'start:Start a new hotfix branch.' + 'finish:Finish a hotfix branch.' + 'delete:Delete a hotfix branch.' + 'rebase:Rebase from integration branch.' + 'list:List all your hotfix branches. (Alias to `git flow hotfix`)' + 'rename:Rename a hotfix branch.' + ) + _describe -t commands 'git flow hotfix' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':hotfix:__git_flow_version_list'\ + ':branch-name:__git_branch_names' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -s'[Sign the release tag cryptographically]'\ + -u'[Use the given GPG-key for the digital signature (implies -s)]'\ + -m'[Use the given tag message]'\ + -p'[Push to $ORIGIN after performing finish]'\ + ':hotfix:__git_flow_hotfix_list' + ;; + + (delete) + _arguments \ + -f'[Force deletion]' \ + -r'[Delete remote branch]' \ + ':hotfix:__git_flow_hotfix_list' + ;; + + (rebase) + _arguments \ + -i'[Do an interactive rebase]' \ + ':branch:__git_branch_names' + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git-flow-feature () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'start:Start a new feature branch.' + 'finish:Finish a feature branch.' + 'delete:Delete a feature branch.' + 'list:List all your feature branches. (Alias to `git flow feature`)' + 'publish:Publish feature branch to remote.' + 'track:Checkout remote feature branch.' + 'diff:Show all changes.' + 'rebase:Rebase from integration branch.' + 'checkout:Checkout local feature branch.' + 'pull:Pull changes from remote.' + 'rename:Rename a feature branch.' + ) + _describe -t commands 'git flow feature' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':feature:__git_flow_feature_list'\ + ':branch-name:__git_branch_names' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -r'[Rebase instead of merge]'\ + ':feature:__git_flow_feature_list' + ;; + + (delete) + _arguments \ + -f'[Force deletion]' \ + -r'[Delete remote branch]' \ + ':feature:__git_flow_feature_list' + ;; + + (publish) + _arguments \ + ':feature:__git_flow_feature_list'\ + ;; + + (track) + _arguments \ + ':feature:__git_flow_feature_list'\ + ;; + + (diff) + _arguments \ + ':branch:__git_branch_names'\ + ;; + + (rebase) + _arguments \ + -i'[Do an interactive rebase]' \ + ':branch:__git_branch_names' + ;; + + (checkout) + _arguments \ + ':branch:__git_flow_feature_list'\ + ;; + + (pull) + _arguments \ + ':remote:__git_remotes'\ + ':branch:__git_branch_names' + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git-flow-bugfix () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'start:Start a new bugfix branch.' + 'finish:Finish a bugfix branch.' + 'delete:Delete a bugfix branch.' + 'list:List all your bugfix branches. (Alias to `git flow bugfix`)' + 'publish:Publish bugfix branch to remote.' + 'track:Checkout remote bugfix branch.' + 'diff:Show all changes.' + 'rebase:Rebase from integration branch.' + 'checkout:Checkout local bugfix branch.' + 'pull:Pull changes from remote.' + 'rename:Rename a bugfix branch.' + ) + _describe -t commands 'git flow bugfix' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':bugfix:__git_flow_bugfix_list'\ + ':branch-name:__git_branch_names' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -r'[Rebase instead of merge]'\ + ':bugfix:__git_flow_bugfix_list' + ;; + + (delete) + _arguments \ + -f'[Force deletion]' \ + -r'[Delete remote branch]' \ + ':bugfix:__git_flow_bugfix_list' + ;; + + (publish) + _arguments \ + ':bugfix:__git_flow_bugfix_list'\ + ;; + + (track) + _arguments \ + ':bugfix:__git_flow_bugfix_list'\ + ;; + + (diff) + _arguments \ + ':branch:__git_branch_names'\ + ;; + + (rebase) + _arguments \ + -i'[Do an interactive rebase]' \ + ':branch:__git_branch_names' + ;; + + (checkout) + _arguments \ + ':branch:__git_flow_bugfix_list'\ + ;; + + (pull) + _arguments \ + ':remote:__git_remotes'\ + ':branch:__git_branch_names' + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git-flow-config () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'list:List the configuration. (Alias to `git flow config`)' + 'set:Set the configuration option' + ) + _describe -t commands 'git flow config' subcommands + ;; + + (options) + case $line[1] in + + (set) + _arguments \ + --local'[Use repository config file]' \ + --global'[Use global config file]'\ + --system'[Use system config file]'\ + --file'[Use given config file]'\ + ':option:(master develop feature hotfix release support versiontagprefix)' + ;; + + *) + _arguments \ + --local'[Use repository config file]' \ + --global'[Use global config file]'\ + --system'[Use system config file]'\ + --file'[Use given config file]' + ;; + esac + ;; + esac +} +__git_flow_version_list () +{ + local expl + declare -a versions + + versions=(${${(f)"$(_call_program versions git flow release list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted versions expl 'version' compadd $versions +} + +__git_flow_feature_list () +{ + local expl + declare -a features + + features=(${${(f)"$(_call_program features git flow feature list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted features expl 'feature' compadd $features +} + +__git_flow_bugfix_list () +{ + local expl + declare -a bugfixes + + bugfixes=(${${(f)"$(_call_program bugfixes git flow bugfix list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted bugfixes expl 'bugfix' compadd $bugfixes +} + +__git_remotes () { + local expl gitdir remotes + + gitdir=$(_call_program gitdir git rev-parse --git-dir 2>/dev/null) + __git_command_successful || return + + remotes=(${${(f)"$(_call_program remotes git config --get-regexp '"^remote\..*\.url$"')"}//#(#b)remote.(*).url */$match[1]}) + __git_command_successful || return + + # TODO: Should combine the two instead of either or. + if (( $#remotes > 0 )); then + _wanted remotes expl remote compadd $* - $remotes + else + _wanted remotes expl remote _files $* - -W "($gitdir/remotes)" -g "$gitdir/remotes/*" + fi +} + +__git_flow_hotfix_list () +{ + local expl + declare -a hotfixes + + hotfixes=(${${(f)"$(_call_program hotfixes git flow hotfix list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted hotfixes expl 'hotfix' compadd $hotfixes +} + +__git_branch_names () { + local expl + declare -a branch_names + + branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}) + __git_command_successful || return + + _wanted branch-names expl branch-name compadd $* - $branch_names +} + +__git_command_successful () { + if (( ${#pipestatus:#0} > 0 )); then + _message 'not a git repository' + return 1 + fi + return 0 +} + +zstyle ':completion:*:*:git:*' user-commands flow:'provide high-level repository operations' diff --git a/zsh/.oh-my-zsh/plugins/git-flow/README.md b/zsh/.oh-my-zsh/plugins/git-flow/README.md new file mode 100644 index 0000000..dd90a18 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-flow/README.md @@ -0,0 +1,40 @@ +# Git-Flow plugin + +This plugin adds completion and aliases for the [`git-flow` command](https://github.com/nvie/gitflow). + +To use it, add `git-flow` to the plugins array in your zshrc file: + +```zsh +plugins=(... git-flow) +``` + +## Aliases + +| Alias | Command | Description | +| --------- | ----------------------------------------- | ---------------------------------------------- | +| `gcd` | `git checkout develop` | Check out develop branch | +| `gch` | `git checkout hotfix` | Check out hotfix branch | +| `gcr` | `git checkout release` | Check out release branch | +| `gfl` | `git flow` | Git-Flow command | +| `gflf` | `git flow feature` | List existing feature branches | +| `gflff` | `git flow feature finish` | Finish feature: `gflff ` | +| `gflffc` | `gflff ${$(git_current_branch)#feature/}` | Finish current feature | +| `gflfp` | `git flow feature publish` | Publish feature: `gflfp ` | +| `gflfpc` | `gflfp ${$(git_current_branch)#feature/}` | Publish current feature | +| `gflfpll` | `git flow feature pull` | Pull remote feature: `gflfpll ` | +| `gflfs` | `git flow feature start` | Start a new feature: `gflfs ` | +| `gflh` | `git flow hotfix` | List existing hotfix branches | +| `gflhf` | `git flow hotfix finish` | Finish hotfix: `gflhf ` | +| `gflhfc` | `gflhf ${$(git_current_branch)#hotfix/}` | Finish current hotfix | +| `gflhp` | `git flow hotfix publish` | Publish hostfix: `gflhp ` | +| `gflhpc` | `gflhp ${$(git_current_branch)#hotfix/}` | Finish current hotfix | +| `gflhs` | `git flow hotfix start` | Start a new hotfix: `gflhs ` | +| `gfli` | `git flow init` | Initialize git-flow repository | +| `gflr` | `git flow release` | List existing release branches | +| `gflrf` | `git flow release finish` | Finish release: `gflrf ` | +| `gflrfc` | `gflrf ${$(git_current_branch)#release/}` | Finish current release | +| `gflrp` | `git flow release publish` | Publish release: `gflrp ` | +| `gflrpc` | `gflrp ${$(git_current_branch)#release/}` | Publish current release | +| `gflrs` | `git flow release start` | Start a new release: `gflrs ` | + +[More information about `git-flow` commands](https://github.com/nvie/gitflow/wiki/Command-Line-Arguments). diff --git a/zsh/.oh-my-zsh/plugins/git-flow/_git-flow b/zsh/.oh-my-zsh/plugins/git-flow/_git-flow new file mode 100644 index 0000000..a01d963 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-flow/_git-flow @@ -0,0 +1,327 @@ +#compdef git-flow + +_git-flow () { + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'init:Initialize a new git repo with support for the branching model.' + 'feature:Manage your feature branches.' + 'release:Manage your release branches.' + 'hotfix:Manage your hotfix branches.' + 'support:Manage your support branches.' + 'version:Shows version information.' + ) + _describe -t commands 'git flow' subcommands + ;; + + (options) + case $line[1] in + + (init) + _arguments \ + -f'[Force setting of gitflow branches, even if already configured]' + ;; + + (version) + ;; + + (hotfix) + __git-flow-hotfix + ;; + + (release) + __git-flow-release + ;; + + (feature) + __git-flow-feature + ;; + esac + ;; + esac +} + +__git-flow-release () { + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'start:Start a new release branch.' + 'finish:Finish a release branch.' + 'list:List all your release branches. (Alias to `git flow release`)' + 'publish: public' + 'track: track' + ) + _describe -t commands 'git flow release' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':version:__git_flow_version_list' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -s'[Sign the release tag cryptographically]'\ + -u'[Use the given GPG-key for the digital signature (implies -s)]'\ + -m'[Use the given tag message]'\ + -p'[Push to $ORIGIN after performing finish]'\ + -k'[Keep branch after performing finish]'\ + -n"[Don't tag this release]"\ + ':version:__git_flow_version_list' + ;; + + (publish) + _arguments \ + ':version:__git_flow_version_list'\ + ;; + + (track) + _arguments \ + ':version:__git_flow_version_list'\ + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git-flow-hotfix () { + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'start:Start a new hotfix branch.' + 'finish:Finish a hotfix branch.' + 'list:List all your hotfix branches. (Alias to `git flow hotfix`)' + ) + _describe -t commands 'git flow hotfix' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':hotfix:__git_flow_version_list'\ + ':branch-name:__git_branch_names' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -s'[Sign the release tag cryptographically]'\ + -u'[Use the given GPG-key for the digital signature (implies -s)]'\ + -m'[Use the given tag message]'\ + -p'[Push to $ORIGIN after performing finish]'\ + -k'[Keep branch after performing finish]'\ + -n"[Don't tag this release]"\ + ':hotfix:__git_flow_hotfix_list' + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git-flow-feature () { + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'start:Start a new feature branch.' + 'finish:Finish a feature branch.' + 'list:List all your feature branches. (Alias to `git flow feature`)' + 'publish: publish' + 'track: track' + 'diff: diff' + 'rebase: rebase' + 'checkout: checkout' + 'pull: pull' + ) + _describe -t commands 'git flow feature' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':feature:__git_flow_feature_list'\ + ':branch-name:__git_branch_names' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -r'[Rebase instead of merge]'\ + -k'[Keep branch after performing finish]'\ + ':feature:__git_flow_feature_list' + ;; + + (publish) + _arguments \ + ':feature:__git_flow_feature_list'\ + ;; + + (track) + _arguments \ + ':feature:__git_flow_feature_list'\ + ;; + + (diff) + _arguments \ + ':branch:__git_flow_feature_list'\ + ;; + + (rebase) + _arguments \ + -i'[Do an interactive rebase]' \ + ':branch:__git_flow_feature_list' + ;; + + (checkout) + _arguments \ + ':branch:__git_flow_feature_list'\ + ;; + + (pull) + _arguments \ + ':remote:__git_remotes'\ + ':branch:__git_flow_feature_list' + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git_flow_version_list () { + local expl + declare -a versions + + versions=(${${(f)"$(_call_program versions git flow release list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted versions expl 'version' compadd $versions +} + +__git_flow_feature_list () { + local expl + declare -a features + + features=(${${(f)"$(_call_program features git flow feature list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted features expl 'feature' compadd $features +} + +__git_remotes () { + local expl gitdir remotes + + gitdir=$(_call_program gitdir git rev-parse --git-dir 2>/dev/null) + __git_command_successful || return + + remotes=(${${(f)"$(_call_program remotes git config --get-regexp '"^remote\..*\.url$"')"}//#(#b)remote.(*).url */$match[1]}) + __git_command_successful || return + + # TODO: Should combine the two instead of either or. + if (( $#remotes > 0 )); then + _wanted remotes expl remote compadd $* - $remotes + else + _wanted remotes expl remote _files $* - -W "($gitdir/remotes)" -g "$gitdir/remotes/*" + fi +} + +__git_flow_hotfix_list () { + local expl + declare -a hotfixes + + hotfixes=(${${(f)"$(_call_program hotfixes git flow hotfix list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted hotfixes expl 'hotfix' compadd $hotfixes +} + +__git_branch_names () { + local expl + declare -a branch_names + + branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}) + __git_command_successful || return + + _wanted branch-names expl branch-name compadd $* - $branch_names +} + +__git_command_successful () { + if (( ${#pipestatus:#0} > 0 )); then + _message 'not a git repository' + return 1 + fi + return 0 +} + +zstyle ':completion:*:*:git:*' user-commands flow:'description for foo' + +# Detect if script is sourced or called via autoload +[[ "$ZSH_EVAL_CONTEXT" != *:file ]] || return + +_git-flow "$@" diff --git a/zsh/.oh-my-zsh/plugins/git-flow/git-flow.plugin.zsh b/zsh/.oh-my-zsh/plugins/git-flow/git-flow.plugin.zsh new file mode 100644 index 0000000..a69dc9a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-flow/git-flow.plugin.zsh @@ -0,0 +1,32 @@ +# Aliases +alias gcd='git checkout $(git config gitflow.branch.develop)' +alias gch='git checkout $(git config gitflow.prefix.hotfix)' +alias gcr='git checkout $(git config gitflow.prefix.release)' +alias gfl='git flow' +alias gflf='git flow feature' +alias gflff='git flow feature finish' +alias gflffc='git flow feature finish ${$(git_current_branch)#feature/}' +alias gflfp='git flow feature publish' +alias gflfpc='git flow feature publish ${$(git_current_branch)#feature/}' +alias gflfpll='git flow feature pull' +alias gflfs='git flow feature start' +alias gflh='git flow hotfix' +alias gflhf='git flow hotfix finish' +alias gflhfc='git flow hotfix finish ${$(git_current_branch)#hotfix/}' +alias gflhp='git flow hotfix publish' +alias gflhpc='git flow hotfix publish ${$(git_current_branch)#hotfix/}' +alias gflhs='git flow hotfix start' +alias gfli='git flow init' +alias gflr='git flow release' +alias gflrf='git flow release finish' +alias gflrfc='git flow release finish ${$(git_current_branch)#release/}' +alias gflrp='git flow release publish' +alias gflrpc='git flow release publish ${$(git_current_branch)#release/}' +alias gflrs='git flow release start' + +# Source completion script +# Handle $0 according to the standard: +# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" +source "${0:A:h}/_git-flow" diff --git a/zsh/.oh-my-zsh/plugins/git-hubflow/README.md b/zsh/.oh-my-zsh/plugins/git-hubflow/README.md new file mode 100644 index 0000000..e861313 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-hubflow/README.md @@ -0,0 +1,24 @@ +# git-hubflow plugin + +This plugin adds completion for [HubFlow](https://datasift.github.io/gitflow/) (GitFlow for GitHub), as well as some +aliases for common commands. HubFlow is a git extension to make it easy to use GitFlow with GitHub. Based on the +original gitflow extension for git. + +The hubflow tool has to be [installed](https://github.com/datasift/gitflow#installation) separately. + +To use it, add `git-hubflow` to the plugins array in your zshrc file: + +```zsh +plugins=(... git-hubflow) +``` + +## Aliases + +| Alias | Command | Description | +|-------|------------------|------------------------------------------------------------------| +| ghf | `git hf` | Print command overview | +| ghff | `git hf feature` | Manage your feature branches | +| ghfr | `git hf release` | Manage your release branches | +| ghfh | `git hf hotfix` | Manage your hotfix branches | +| ghfs | `git hf support` | Manage your support branches | +| ghfu | `git hf update` | Pull upstream changes down into your master and develop branches | diff --git a/zsh/.oh-my-zsh/plugins/git-hubflow/git-hubflow.plugin.zsh b/zsh/.oh-my-zsh/plugins/git-hubflow/git-hubflow.plugin.zsh new file mode 100644 index 0000000..3ba69f2 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-hubflow/git-hubflow.plugin.zsh @@ -0,0 +1,333 @@ +alias ghf='git hf' +alias ghff='git hf feature' +alias ghfr='git hf release' +alias ghfh='git hf hotfix' +alias ghfs='git hf support' +alias ghfu='git hf update' + +_git-hf () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'init:Initialize a new git repo with support for the branching model.' + 'feature:Manage your feature branches.' + 'release:Manage your release branches.' + 'hotfix:Manage your hotfix branches.' + 'support:Manage your support branches.' + 'update:Pull upstream changes down into your master and develop branches.' + 'version:Shows version information.' + ) + _describe -t commands 'git hf' subcommands + ;; + + (options) + case $line[1] in + + (init) + _arguments \ + -f'[Force setting of gitflow branches, even if already configured]' + ;; + + (version) + ;; + + (hotfix) + __git-hf-hotfix + ;; + + (release) + __git-hf-release + ;; + + (feature) + __git-hf-feature + ;; + esac + ;; + esac +} + +__git-hf-release () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'start:Start a new release branch.' + 'finish:Finish a release branch.' + 'list:List all your release branches. (Alias to `git hf release`)' + 'cancel:Cancel release' + 'push:Push release to GitHub' + 'pull:Pull release from GitHub' + 'track:Track release' + ) + _describe -t commands 'git hf release' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':version:__git_hf_version_list' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -s'[Sign the release tag cryptographically]'\ + -u'[Use the given GPG-key for the digital signature (implies -s)]'\ + -m'[Use the given tag message]'\ + -p'[Push to $ORIGIN after performing finish]'\ + -k'[Keep branch after performing finish]'\ + -n"[Don't tag this release]"\ + ':version:__git_hf_version_list' + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git-hf-hotfix () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'start:Start a new hotfix branch.' + 'finish:Finish a hotfix branch.' + 'list:List all your hotfix branches. (Alias to `git hf hotfix`)' + 'publish:Publish the hotfix branch.' + 'track:Track the hotfix branch.' + 'pull:Pull the hotfix from GitHub.' + 'push:Push the hotfix to GitHub.' + 'cancel:Cancel the hotfix.' + ) + _describe -t commands 'git hf hotfix' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':hotfix:__git_hf_version_list'\ + ':branch-name:__git_branch_names' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -s'[Sign the release tag cryptographically]'\ + -u'[Use the given GPG-key for the digital signature (implies -s)]'\ + -m'[Use the given tag message]'\ + -p'[Push to $ORIGIN after performing finish]'\ + -k'[Keep branch after performing finish]'\ + -n"[Don't tag this release]"\ + ':hotfix:__git_hf_hotfix_list' + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git-hf-feature () +{ + local curcontext="$curcontext" state line + typeset -A opt_args + + _arguments -C \ + ':command:->command' \ + '*::options:->options' + + case $state in + (command) + + local -a subcommands + subcommands=( + 'list:List all your feature branches. (Alias to `git hf feature`)' + 'start:Start a new feature branch' + 'finish:Finish a feature branch' + 'submit:submit' + 'track:track' + 'diff:Diff' + 'rebase:Rebase feature branch against develop' + 'checkout:Checkout feature' + 'pull:Pull feature branch from GitHub' + 'push:Push feature branch to GitHub' + 'cancel:Cancel feature' + ) + _describe -t commands 'git hf feature' subcommands + _arguments \ + -v'[Verbose (more) output]' + ;; + + (options) + case $line[1] in + + (start) + _arguments \ + -F'[Fetch from origin before performing finish]'\ + ':feature:__git_hf_feature_list'\ + ':branch-name:__git_branch_names' + ;; + + (finish) + _arguments \ + -F'[Fetch from origin before performing finish]' \ + -r'[Rebase instead of merge]'\ + ':feature:__git_hf_feature_list' + ;; + + (publish) + _arguments \ + ':feature:__git_hf_feature_list'\ + ;; + + (track) + _arguments \ + ':feature:__git_hf_feature_list'\ + ;; + + (diff) + _arguments \ + ':branch:__git_branch_names'\ + ;; + + (rebase) + _arguments \ + -i'[Do an interactive rebase]' \ + ':branch:__git_branch_names' + ;; + + (checkout) + _arguments \ + ':branch:__git_hf_feature_list'\ + ;; + + (pull) + _arguments \ + ':remote:__git_remotes'\ + ':branch:__git_branch_names' + ;; + + *) + _arguments \ + -v'[Verbose (more) output]' + ;; + esac + ;; + esac +} + +__git_hf_version_list () +{ + local expl + declare -a versions + + versions=(${${(f)"$(_call_program versions git hf release list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted versions expl 'version' compadd $versions +} + +__git_hf_feature_list () +{ + local expl + declare -a features + + features=(${${(f)"$(_call_program features git hf feature list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted features expl 'feature' compadd $features +} + +__git_remotes () { + local expl gitdir remotes + + gitdir=$(_call_program gitdir git rev-parse --git-dir 2>/dev/null) + __git_command_successful || return + + remotes=(${${(f)"$(_call_program remotes git config --get-regexp '"^remote\..*\.url$"')"}//#(#b)remote.(*).url */$match[1]}) + __git_command_successful || return + + # TODO: Should combine the two instead of either or. + if (( $#remotes > 0 )); then + _wanted remotes expl remote compadd $* - $remotes + else + _wanted remotes expl remote _files $* - -W "($gitdir/remotes)" -g "$gitdir/remotes/*" + fi +} + +__git_hf_hotfix_list () +{ + local expl + declare -a hotfixes + + hotfixes=(${${(f)"$(_call_program hotfixes git hf hotfix list 2> /dev/null | tr -d ' |*')"}}) + __git_command_successful || return + + _wanted hotfixes expl 'hotfix' compadd $hotfixes +} + +__git_branch_names () { + local expl + declare -a branch_names + + branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}) + __git_command_successful || return + + _wanted branch-names expl branch-name compadd $* - $branch_names +} + +__git_command_successful () { + if (( ${#pipestatus:#0} > 0 )); then + _message 'not a git repository' + return 1 + fi + return 0 +} + +zstyle ':completion:*:*:git:*' user-commands flow:'description for foo' diff --git a/zsh/.oh-my-zsh/plugins/git-lfs/README.md b/zsh/.oh-my-zsh/plugins/git-lfs/README.md new file mode 100644 index 0000000..31caa81 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-lfs/README.md @@ -0,0 +1,24 @@ +# git lfs plugin + +The git lfs plugin provides [aliases](#aliases) and [functions](#functions) for [git-lfs](https://github.com/git-lfs/git-lfs). + +To use it, add `git-lfs` to the plugins array in your zshrc file: + +```zsh +plugins=(... git-lfs) +``` + +## Aliases + +| Alias | Command | +| :------- | :---------------------------------- | +| `glfsi` | `git lfs install` | +| `glfst` | `git lfs track` | +| `glfsls` | `git lfs ls-files` | +| `glfsmi` | `git lfs migrate import --include=` | + +## Functions + +| Function | Command | +| :------- | :---------------------------------------------- | +| `gplfs` | `git lfs push origin "$(current_branch)" --all` | diff --git a/zsh/.oh-my-zsh/plugins/git-lfs/git-lfs.plugin.zsh b/zsh/.oh-my-zsh/plugins/git-lfs/git-lfs.plugin.zsh new file mode 100644 index 0000000..a9291ee --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-lfs/git-lfs.plugin.zsh @@ -0,0 +1,17 @@ +# +# Aliases +# + +alias glfsi='git lfs install' +alias glfst='git lfs track' +alias glfsls='git lfs ls-files' +alias glfsmi='git lfs migrate import --include=' + +# +# Functions +# + +function gplfs() { + local b="$(git_current_branch)" + git lfs push origin "$b" --all +} diff --git a/zsh/.oh-my-zsh/plugins/git-prompt/README.md b/zsh/.oh-my-zsh/plugins/git-prompt/README.md new file mode 100644 index 0000000..093ec0d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-prompt/README.md @@ -0,0 +1,72 @@ +# git-prompt plugin + +A `zsh` prompt that displays information about the current git repository. In particular: +the branch name, difference with remote branch, number of files staged or changed, etc. + +To use it, add `git-prompt` to the plugins array in your zshrc file: + +```zsh +plugins=(... git-prompt) +``` + +You may also need to [customize your theme](https://github.com/ohmyzsh/ohmyzsh/issues/9395#issuecomment-1027130429) +to change the way the prompt is built. See the +[OMZ wiki on customizing themes](https://github.com/ohmyzsh/ohmyzsh/wiki/Customization#overriding-and-adding-themes). + +See the [original repository](https://github.com/olivierverdier/zsh-git-prompt). + +## Requirements + +This plugin uses `python3`, so your host needs to have it installed. + +## Examples + +The prompt may look like the following: + +- `(master↑3|✚1)`: on branch `master`, ahead of remote by 3 commits, 1 file changed but not staged +- `(status|●2)`: on branch `status`, 2 files staged +- `(master|✚7…)`: on branch `master`, 7 files changed, some files untracked +- `(master|✖2✚3)`: on branch `master`, 2 conflicts, 3 files changed +- `(experimental↓2↑3|✔)`: on branch `experimental`; your branch has diverged by 3 commits, remote by 2 commits; the repository is otherwise clean +- `(:70c2952|✔)`: not on any branch; parent commit has hash `70c2952`; the repository is otherwise clean +- `(master|⚑2)`: on branch `master`, there are 2 stashed changes + +## Prompt Structure + +By default, the general appearance of the prompt is: + +```text +(|) +``` + +The symbols are as follows: + +### Local Status Symbols + +| Symbol | Meaning | +|--------|--------------------------------| +| ✔ | repository clean | +| ●n | there are `n` staged files | +| ✖n | there are `n` unmerged files | +| ✚n | there are `n` unstaged files | +| -n | there are `n` deleted files | +| ⚑n | there are `n` stashed changes | +| … | there are some untracked files | + +### Branch Tracking Symbols + +| Symbol | Meaning | +|--------|---------------------------------------------------------------| +| ↑n | ahead of remote by `n` commits | +| ↓n | behind remote by `n` commits | +| ↓m↑n | branches diverged: other by `m` commits, yours by `n` commits | + +## Customisation + +- Set the variable `ZSH_THEME_GIT_PROMPT_CACHE` to any value in order to enable caching. +- Set the variable `ZSH_THEME_GIT_SHOW_UPSTREAM` to any value to display the upstream branch. +- You may also change a number of variables (whose name start with `ZSH_THEME_GIT_PROMPT_`) + to change the appearance of the prompt. Take a look at the bottom of the [plugin file](git-prompt.plugin.zsh)` + to see what variables are available. + +**Enjoy!** diff --git a/zsh/.oh-my-zsh/plugins/git-prompt/git-prompt.plugin.zsh b/zsh/.oh-my-zsh/plugins/git-prompt/git-prompt.plugin.zsh new file mode 100644 index 0000000..08b443a --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-prompt/git-prompt.plugin.zsh @@ -0,0 +1,113 @@ +# Handle $0 according to the standard: +# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" + +__GIT_PROMPT_DIR="${0:A:h}" + +## Hook function definitions +function chpwd_update_git_vars() { + update_current_git_vars +} + +function preexec_update_git_vars() { + case "$2" in + git*|hub*|gh*|stg*) + __EXECUTED_GIT_COMMAND=1 + ;; + esac +} + +function precmd_update_git_vars() { + if [ -n "$__EXECUTED_GIT_COMMAND" ] || [ ! -n "$ZSH_THEME_GIT_PROMPT_CACHE" ]; then + update_current_git_vars + unset __EXECUTED_GIT_COMMAND + fi +} + +autoload -U add-zsh-hook +add-zsh-hook chpwd chpwd_update_git_vars +add-zsh-hook precmd precmd_update_git_vars +add-zsh-hook preexec preexec_update_git_vars + + +## Function definitions +function update_current_git_vars() { + unset __CURRENT_GIT_STATUS + + local gitstatus="$__GIT_PROMPT_DIR/gitstatus.py" + _GIT_STATUS=$(python3 ${gitstatus} 2>/dev/null) + __CURRENT_GIT_STATUS=("${(@s: :)_GIT_STATUS}") + GIT_BRANCH=$__CURRENT_GIT_STATUS[1] + GIT_AHEAD=$__CURRENT_GIT_STATUS[2] + GIT_BEHIND=$__CURRENT_GIT_STATUS[3] + GIT_STAGED=$__CURRENT_GIT_STATUS[4] + GIT_CONFLICTS=$__CURRENT_GIT_STATUS[5] + GIT_CHANGED=$__CURRENT_GIT_STATUS[6] + GIT_UNTRACKED=$__CURRENT_GIT_STATUS[7] + GIT_STASHED=$__CURRENT_GIT_STATUS[8] + GIT_CLEAN=$__CURRENT_GIT_STATUS[9] + GIT_DELETED=$__CURRENT_GIT_STATUS[10] + + if [ -z ${ZSH_THEME_GIT_SHOW_UPSTREAM+x} ]; then + GIT_UPSTREAM= + else + GIT_UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name "@{upstream}" 2>/dev/null) && GIT_UPSTREAM="${ZSH_THEME_GIT_PROMPT_UPSTREAM_SEPARATOR}${GIT_UPSTREAM}" + fi +} + +git_super_status() { + precmd_update_git_vars + if [ -n "$__CURRENT_GIT_STATUS" ]; then + STATUS="$ZSH_THEME_GIT_PROMPT_PREFIX$ZSH_THEME_GIT_PROMPT_BRANCH$GIT_BRANCH$GIT_UPSTREAM%{${reset_color}%}" + if [ "$GIT_BEHIND" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_BEHIND$GIT_BEHIND%{${reset_color}%}" + fi + if [ "$GIT_AHEAD" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_AHEAD$GIT_AHEAD%{${reset_color}%}" + fi + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_SEPARATOR" + if [ "$GIT_STAGED" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STAGED$GIT_STAGED%{${reset_color}%}" + fi + if [ "$GIT_CONFLICTS" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CONFLICTS$GIT_CONFLICTS%{${reset_color}%}" + fi + if [ "$GIT_CHANGED" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CHANGED$GIT_CHANGED%{${reset_color}%}" + fi + if [ "$GIT_DELETED" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_DELETED$GIT_DELETED%{${reset_color}%}" + fi + if [ "$GIT_UNTRACKED" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED$GIT_UNTRACKED%{${reset_color}%}" + fi + if [ "$GIT_STASHED" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STASHED$GIT_STASHED%{${reset_color}%}" + fi + if [ "$GIT_CLEAN" -eq "1" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN" + fi + STATUS="$STATUS%{${reset_color}%}$ZSH_THEME_GIT_PROMPT_SUFFIX" + echo "$STATUS" + fi +} + +# Default values for the appearance of the prompt. +ZSH_THEME_GIT_PROMPT_PREFIX="(" +ZSH_THEME_GIT_PROMPT_SUFFIX=")" +ZSH_THEME_GIT_PROMPT_SEPARATOR="|" +ZSH_THEME_GIT_PROMPT_BRANCH="%{$fg_bold[magenta]%}" +ZSH_THEME_GIT_PROMPT_STAGED="%{$fg[red]%}%{●%G%}" +ZSH_THEME_GIT_PROMPT_CONFLICTS="%{$fg[red]%}%{✖%G%}" +ZSH_THEME_GIT_PROMPT_CHANGED="%{$fg[blue]%}%{✚%G%}" +ZSH_THEME_GIT_PROMPT_DELETED="%{$fg[blue]%}%{-%G%}" +ZSH_THEME_GIT_PROMPT_BEHIND="%{↓%G%}" +ZSH_THEME_GIT_PROMPT_AHEAD="%{↑%G%}" +ZSH_THEME_GIT_PROMPT_UNTRACKED="%{$fg[cyan]%}%{…%G%}" +ZSH_THEME_GIT_PROMPT_STASHED="%{$fg_bold[blue]%}%{⚑%G%}" +ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[green]%}%{✔%G%}" +ZSH_THEME_GIT_PROMPT_UPSTREAM_SEPARATOR="->" + +# Set the prompt. +RPROMPT='$(git_super_status)' diff --git a/zsh/.oh-my-zsh/plugins/git-prompt/gitstatus.py b/zsh/.oh-my-zsh/plugins/git-prompt/gitstatus.py new file mode 100644 index 0000000..9792092 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git-prompt/gitstatus.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +from __future__ import print_function + +import os +import sys +import re +from subprocess import Popen, PIPE, check_output + + +def get_tagname_or_hash(): + """return tagname if exists else hash""" + # get hash + hash_cmd = ['git', 'rev-parse', '--short', 'HEAD'] + hash_ = check_output(hash_cmd).decode('utf-8').strip() + + # get tagname + tags_cmd = ['git', 'for-each-ref', '--points-at=HEAD', '--count=2', '--sort=-version:refname', '--format=%(refname:short)', 'refs/tags'] + tags = check_output(tags_cmd).decode('utf-8').split() + + if tags: + return tags[0] + ('+' if len(tags) > 1 else '') + elif hash_: + return hash_ + return None + +# Re-use method from https://github.com/magicmonty/bash-git-prompt to get stashs count +def get_stash(): + cmd = Popen(['git', 'rev-parse', '--git-dir'], stdout=PIPE, stderr=PIPE) + so, se = cmd.communicate() + stash_file = '%s%s' % (so.decode('utf-8').rstrip(), '/logs/refs/stash') + + try: + with open(stash_file) as f: + return sum(1 for _ in f) + except IOError: + return 0 + + +# `git status --porcelain --branch` can collect all information +# branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind +po = Popen(['git', 'status', '--porcelain', '--branch'], env=dict(os.environ, LANG="C"), stdout=PIPE, stderr=PIPE) +stdout, sterr = po.communicate() +if po.returncode != 0: + sys.exit(0) # Not a git repository + +# collect git status information +untracked, staged, changed, deleted, conflicts = [], [], [], [], [] +ahead, behind = 0, 0 +status = [(line[0], line[1], line[2:]) for line in stdout.decode('utf-8').splitlines()] +for st in status: + if st[0] == '#' and st[1] == '#': + if re.search('Initial commit on', st[2]) or re.search('No commits yet on', st[2]): + branch = st[2].split(' ')[-1] + elif re.search('no branch', st[2]): # detached status + branch = get_tagname_or_hash() + elif len(st[2].strip().split('...')) == 1: + branch = st[2].strip() + else: + # current and remote branch info + branch, rest = st[2].strip().split('...') + if len(rest.split(' ')) == 1: + # remote_branch = rest.split(' ')[0] + pass + else: + # ahead or behind + divergence = ' '.join(rest.split(' ')[1:]) + divergence = divergence.lstrip('[').rstrip(']') + for div in divergence.split(', '): + if 'ahead' in div: + ahead = int(div[len('ahead '):].strip()) + elif 'behind' in div: + behind = int(div[len('behind '):].strip()) + elif st[0] == '?' and st[1] == '?': + untracked.append(st) + else: + if st[1] == 'M': + changed.append(st) + if st[1] == 'D': + deleted.append(st) + if st[0] == 'U': + conflicts.append(st) + elif st[0] != ' ': + staged.append(st) + +stashed = get_stash() +if not changed and not deleted and not staged and not conflicts and not untracked: + clean = 1 +else: + clean = 0 + +out = ' '.join([ + branch, + str(ahead), + str(behind), + str(len(staged)), + str(len(conflicts)), + str(len(changed)), + str(len(untracked)), + str(stashed), + str(clean), + str(len(deleted)) +]) +print(out, end='') diff --git a/zsh/.oh-my-zsh/plugins/git/README.md b/zsh/.oh-my-zsh/plugins/git/README.md new file mode 100644 index 0000000..036ec47 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git/README.md @@ -0,0 +1,283 @@ +# git plugin + +The git plugin provides many [aliases](#aliases) and a few useful [functions](#functions). + +To use it, add `git` to the plugins array in your zshrc file: + +```zsh +plugins=(... git) +``` + +## Aliases + +| Alias | Command | +| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------ | +| `grt` | `cd "$(git rev-parse --show-toplevel \|\| echo .)"` | +| `ggpnp` | `ggl && ggp` | +| `ggpur` | `ggu` | +| `g` | `git` | +| `ga` | `git add` | +| `gaa` | `git add --all` | +| `gapa` | `git add --patch` | +| `gau` | `git add --update` | +| `gav` | `git add --verbose` | +| `gwip` | `git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"` | +| `gam` | `git am` | +| `gama` | `git am --abort` | +| `gamc` | `git am --continue` | +| `gamscp` | `git am --show-current-patch` | +| `gams` | `git am --skip` | +| `gap` | `git apply` | +| `gapt` | `git apply --3way` | +| `gbs` | `git bisect` | +| `gbsb` | `git bisect bad` | +| `gbsg` | `git bisect good` | +| `gbsn` | `git bisect new` | +| `gbso` | `git bisect old` | +| `gbsr` | `git bisect reset` | +| `gbss` | `git bisect start` | +| `gbl` | `git blame -w` | +| `gb` | `git branch` | +| `gba` | `git branch --all` | +| `gbd` | `git branch --delete` | +| `gbD` | `git branch --delete --force` | +| `gbgd` | `LANG=C git branch --no-color -vv \| grep ": gone\]" \| cut -c 3- \| awk '"'"'{print $1}'"'"' \| xargs git branch -d` | +| `gbgD` | `LANG=C git branch --no-color -vv \| grep ": gone\]" \| cut -c 3- \| awk '"'"'{print $1}'"'"' \| xargs git branch -D` | +| `gbm` | `git branch --move` | +| `gbnm` | `git branch --no-merged` | +| `gbr` | `git branch --remote` | +| `ggsup` | `git branch --set-upstream-to=origin/$(git_current_branch)` | +| `gbg` | `LANG=C git branch -vv \| grep ": gone\]"` | +| `gco` | `git checkout` | +| `gcor` | `git checkout --recurse-submodules` | +| `gcb` | `git checkout -b` | +| `gcB` | `git checkout -B` | +| `gcd` | `git checkout $(git_develop_branch)` | +| `gcm` | `git checkout $(git_main_branch)` | +| `gcp` | `git cherry-pick` | +| `gcpa` | `git cherry-pick --abort` | +| `gcpc` | `git cherry-pick --continue` | +| `gclean` | `git clean --interactive -d` | +| `gcl` | `git clone --recurse-submodules` | +| `gccd` | `git clone --recurse-submodules "$@" && cd "$(basename $\_ .git)"` | +| `gcam` | `git commit --all --message` | +| `gcas` | `git commit --all --signoff` | +| `gcasm` | `git commit --all --signoff --message` | +| `gcmsg` | `git commit --message` | +| `gcsm` | `git commit --signoff --message` | +| `gc` | `git commit --verbose` | +| `gca` | `git commit --verbose --all` | +| `gca!` | `git commit --verbose --all --amend` | +| `gcan!` | `git commit --verbose --all --no-edit --amend` | +| `gcans!` | `git commit --verbose --all --signoff --no-edit --amend` | +| `gcann!` | `git commit --verbose --all --date=now --no-edit --amend` | +| `gc!` | `git commit --verbose --amend` | +| `gcn!` | `git commit --verbose --no-edit --amend` | +| `gcs` | `git commit -S` | +| `gcss` | `git commit -S -s` | +| `gcssm` | `git commit -S -s -m` | +| `gcf` | `git config --list` | +| `gdct` | `git describe --tags $(git rev-list --tags --max-count=1)` | +| `gd` | `git diff` | +| `gdca` | `git diff --cached` | +| `gdcw` | `git diff --cached --word-diff` | +| `gds` | `git diff --staged` | +| `gdw` | `git diff --word-diff` | +| `gdv` | `git diff -w "$@" \| view -` | +| `gdup` | `git diff @{upstream}` | +| `gdnolock` | `git diff $@ ":(exclude)package-lock.json" ":(exclude)\*.lock"` | +| `gdt` | `git diff-tree --no-commit-id --name-only -r` | +| `gf` | `git fetch` | +| `gfa` | `git fetch --all --prune` | +| `gfo` | `git fetch origin` | +| `gg` | `git gui citool` | +| `gga` | `git gui citool --amend` | +| `ghh` | `git help` | +| `glgg` | `git log --graph` | +| `glgga` | `git log --graph --decorate --all` | +| `glgm` | `git log --graph --max-count=10` | +| `glod` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset'` | +| `glods` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset' --date=short` | +| `glol` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset'` | +| `glola` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset' --all` | +| `glols` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset' --stat` | +| `glo` | `git log --oneline --decorate` | +| `glog` | `git log --oneline --decorate --graph` | +| `gloga` | `git log --oneline --decorate --graph --all` | +| `glp` | `git log --pretty=` | +| `glg` | `git log --stat` | +| `glgp` | `git log --stat --patch` | +| `gignored` | `git ls-files -v \| grep "^[[:lower:]]"` | +| `gfg` | `git ls-files \| grep` | +| `gm` | `git merge` | +| `gma` | `git merge --abort` | +| `gmc` | `git merge --continue` | +| `gms` | `git merge --squash` | +| `gmom` | `git merge origin/$(git_main_branch)` | +| `gmum` | `git merge upstream/$(git_main_branch)` | +| `gmtl` | `git mergetool --no-prompt` | +| `gmtlvim` | `git mergetool --no-prompt --tool=vimdiff` | +| `gl` | `git pull` | +| `gpr` | `git pull --rebase` | +| `gprv` | `git pull --rebase -v` | +| `gpra` | `git pull --rebase --autostash` | +| `gprav` | `git pull --rebase --autostash -v` | +| `gprom` | `git pull --rebase origin $(git_main_branch)` | +| `gpromi` | `git pull --rebase=interactive origin $(git_main_branch)` | +| `ggpull` | `git pull origin "$(git_current_branch)"` | +| `ggl` | `git pull origin $(current_branch)` | +| `gluc` | `git pull upstream $(git_current_branch)` | +| `glum` | `git pull upstream $(git_main_branch)` | +| `gp` | `git push` | +| `gpd` | `git push --dry-run` | +| `gpf!` | `git push --force` | +| `ggf` | `git push --force origin $(current_branch)` | +| `gpf` | On Git >= 2.30: `git push --force-with-lease --force-if-includes` | +| `gpf` | On Git < 2.30: `git push --force-with-lease` | +| `ggfl` | `git push --force-with-lease origin $(current_branch)` | +| `gpsup` | `git push --set-upstream origin $(git_current_branch)` | +| `gpsupf` | On Git >= 2.30: `git push --set-upstream origin $(git_current_branch) --force-with-lease --force-if-includes` | +| `gpsupf` | On Git < 2.30: `git push --set-upstream origin $(git_current_branch) --force-with-lease` | +| `gpv` | `git push --verbose` | +| `gpoat` | `git push origin --all && git push origin --tags` | +| `gpod` | `git push origin --delete` | +| `ggpush` | `git push origin "$(git_current_branch)"` | +| `ggp` | `git push origin $(current_branch)` | +| `gpu` | `git push upstream` | +| `grb` | `git rebase` | +| `grba` | `git rebase --abort` | +| `grbc` | `git rebase --continue` | +| `grbi` | `git rebase --interactive` | +| `grbo` | `git rebase --onto` | +| `grbs` | `git rebase --skip` | +| `grbd` | `git rebase $(git_develop_branch)` | +| `grbm` | `git rebase $(git_main_branch)` | +| `grbom` | `git rebase origin/$(git_main_branch)` | +| `grf` | `git reflog` | +| `gr` | `git remote` | +| `grv` | `git remote --verbose` | +| `gra` | `git remote add` | +| `grrm` | `git remote remove` | +| `grmv` | `git remote rename` | +| `grset` | `git remote set-url` | +| `grup` | `git remote update` | +| `grh` | `git reset` | +| `gru` | `git reset --` | +| `grhh` | `git reset --hard` | +| `grhk` | `git reset --keep` | +| `grhs` | `git reset --soft` | +| `gpristine` | `git reset --hard && git clean --force -dfx` | +| `gwipe` | `git reset --hard && git clean --force -df` | +| `groh` | `git reset origin/$(git_current_branch) --hard` | +| `grs` | `git restore` | +| `grss` | `git restore --source` | +| `grst` | `git restore --staged` | +| `gunwip` | `git rev-list --max-count=1 --format="%s" HEAD \| grep -q "--wip--" && git reset HEAD~1` | +| `grev` | `git revert` | +| `grm` | `git rm` | +| `grmc` | `git rm --cached` | +| `gcount` | `git shortlog --summary -n` | +| `gsh` | `git show` | +| `gsps` | `git show --pretty=short --show-signature` | +| `gstall` | `git stash --all` | +| `gstu` | `git stash --include-untracked` | +| `gstaa` | `git stash apply` | +| `gstc` | `git stash clear` | +| `gstd` | `git stash drop` | +| `gstl` | `git stash list` | +| `gstp` | `git stash pop` | +| `gsta` | On Git >= 2.13: `git stash push` | +| `gsta` | On Git < 2.13: `git stash save` | +| `gsts` | `git stash show --patch` | +| `gst` | `git status` | +| `gss` | `git status --short` | +| `gsb` | `git status --short -b` | +| `gsi` | `git submodule init` | +| `gsu` | `git submodule update` | +| `gsd` | `git svn dcommit` | +| `git-svn-dcommit-push` | `git svn dcommit && git push github $(git_main_branch):svntrunk` | +| `gsr` | `git svn rebase` | +| `gsw` | `git switch` | +| `gswc` | `git switch -c` | +| `gswd` | `git switch $(git_develop_branch)` | +| `gswm` | `git switch $(git_main_branch)` | +| `gta` | `git tag --annotate` | +| `gts` | `git tag -s` | +| `gtv` | `git tag \| sort -V` | +| `gignore` | `git update-index --assume-unchanged` | +| `gunignore` | `git update-index --no-assume-unchanged` | +| `gwch` | `git whatchanged -p --abbrev-commit --pretty=medium` | +| `gwt` | `git worktree` | +| `gwtls` | `git worktree list` | +| `gwtmv` | `git worktree move` | +| `gwtrm` | `git worktree remove` | +| `gk` | `gitk --all --branches &!` | +| `gke` | `gitk --all $(git log --walk-reflogs --pretty=%h) &!` | +| `gtl` | `gtl(){ git tag --sort=-v:refname -n --list ${1}\* }; noglob gtl` | + +### Main branch preference + +Following the recent push for removing racially-charged words from our technical vocabulary, the git plugin +favors using a branch name other than `master`. In this case, we favor the shorter, neutral and descriptive +term `main`. This means that any aliases and functions that previously used `master`, will use `main` if that +branch exists. We do this via the function `git_main_branch`. + +### Deprecated aliases + +These are aliases that have been removed, renamed, or otherwise modified in a way that may, or may not, +receive further support. + +| Alias | Command | Modification | +| :------- | :-------------------------------------------------------- | :-------------------------------------------------------- | +| `gap` | `git add --patch` | New alias: `gapa`. | +| `gcl` | `git config --list` | New alias: `gcf`. | +| `gdc` | `git diff --cached` | New alias: `gdca`. | +| `gdt` | `git difftool` | No replacement. | +| `ggpull` | `git pull origin $(current_branch)` | New alias: `ggl`. (`ggpull` still exists for now though.) | +| `ggpur` | `git pull --rebase origin $(current_branch)` | New alias: `ggu`. (`ggpur` still exists for now though.) | +| `ggpush` | `git push origin $(current_branch)` | New alias: `ggp`. (`ggpush` still exists for now though.) | +| `gk` | `gitk --all --branches` | Now aliased to `gitk --all --branches`. | +| `glg` | `git log --stat --max-count=10` | Now aliased to `git log --stat --color`. | +| `glgg` | `git log --graph --max-count=10` | Now aliased to `git log --graph --color`. | +| `gwc` | `git whatchanged -p --abbrev-commit --pretty = medium` | New alias: `gwch`. | +| `gup` | `git pull --rebase` | now alias `gpr` | +| `gupv` | `git pull --rebase -v` | now alias `gprv` | +| `gupa` | `git pull --rebase --autostash` | now alias `gpra` | +| `gupav` | `git pull --rebase --autostash -v` | now alias `gprav` | +| `gupom` | `git pull --rebase origin $(git_main_branch)` | now alias `gprom` | +| `gupomi` | `git pull --rebase=interactive origin $(git_main_branch)` | now alias `gpromi` | + +## Functions + +### Current + +| Command | Description | +| :----------------------- | :-------------------------------------------------------------------------------------------------------------- | +| `current_branch` | Returns the name of the current branch. | +| `git_current_user_email` | Returns the `user.email` config value. (Lives in `lib/git.zsh`.) | +| `git_current_user_name` | Returns the `user.name` config value. (Lives in `lib/git.zsh`.) | +| `git_develop_branch` | Returns the name of the “development” branch: `dev`, `devel`, `development` if they exist, `develop` otherwise. | +| `git_main_branch` | Returns the name of the main branch: `main` if it exists, `master` otherwise. | +| `grename ` | Renames branch `` to ``, including on the origin remote. | +| `gbda` | Deletes all merged branches | +| `gbds` | Deletes all squash-merged branches (**Note: performance degrades with number of branches**) | + +### Work in Progress (WIP) + +These features allow you to pause developing one branch and switch to another one (_"Work in Progress"_, or +“wip”). When you want to go back to work, just “unwip” it. + +| Command | Description | +| :----------------- | :---------------------------------------------- | +| `gwip` | Commit wip branch | +| `gunwip` | Uncommit wip branch | +| `gunwipall` | Uncommit all recent `--wip--` commits | +| `work_in_progress` | Echoes a warning if the current branch is a wip | + +Note that `gwip` and `gunwip` are aliases, but are also documented here to group all related WIP features. + +### Deprecated functions + +| Command | Description | Reason | +| :------------------- | :-------------------------------------- | :--------------------------------------------------------------- | +| `current_repository` | Return the names of the current remotes | Didn't work properly. Use `git remote -v` instead (`grv` alias). | diff --git a/zsh/.oh-my-zsh/plugins/git/git.plugin.zsh b/zsh/.oh-my-zsh/plugins/git/git.plugin.zsh new file mode 100644 index 0000000..1a978c5 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/git/git.plugin.zsh @@ -0,0 +1,423 @@ +# Git version checking +autoload -Uz is-at-least +git_version="${${(As: :)$(git version 2>/dev/null)}[3]}" + +# +# Functions Current +# (sorted alphabetically by function name) +# (order should follow README) +# + +# The name of the current branch +# Back-compatibility wrapper for when this function was defined here in +# the plugin, before being pulled in to core lib/git.zsh as git_current_branch() +# to fix the core -> git plugin dependency. +function current_branch() { + git_current_branch +} + +# Check for develop and similarly named branches +function git_develop_branch() { + command git rev-parse --git-dir &>/dev/null || return + local branch + for branch in dev devel develop development; do + if command git show-ref -q --verify refs/heads/$branch; then + echo $branch + return 0 + fi + done + + echo develop + return 1 +} + +# Check if main exists and use instead of master +function git_main_branch() { + command git rev-parse --git-dir &>/dev/null || return + local ref + for ref in refs/{heads,remotes/{origin,upstream}}/{main,trunk,mainline,default,stable,master}; do + if command git show-ref -q --verify $ref; then + echo ${ref:t} + return 0 + fi + done + + # If no main branch was found, fall back to master but return error + echo master + return 1 +} + +function grename() { + if [[ -z "$1" || -z "$2" ]]; then + echo "Usage: $0 old_branch new_branch" + return 1 + fi + + # Rename branch locally + git branch -m "$1" "$2" + # Rename branch in origin remote + if git push origin :"$1"; then + git push --set-upstream origin "$2" + fi +} + +# +# Functions Work in Progress (WIP) +# (sorted alphabetically by function name) +# (order should follow README) +# + +# Similar to `gunwip` but recursive "Unwips" all recent `--wip--` commits not just the last one +function gunwipall() { + local _commit=$(git log --grep='--wip--' --invert-grep --max-count=1 --format=format:%H) + + # Check if a commit without "--wip--" was found and it's not the same as HEAD + if [[ "$_commit" != "$(git rev-parse HEAD)" ]]; then + git reset $_commit || return 1 + fi +} + +# Warn if the current branch is a WIP +function work_in_progress() { + command git -c log.showSignature=false log -n 1 2>/dev/null | grep -q -- "--wip--" && echo "WIP!!" +} + +# +# Aliases +# (sorted alphabetically by command) +# (order should follow README) +# (in some cases force the alisas order to match README, like for example gke and gk) +# + +alias grt='cd "$(git rev-parse --show-toplevel || echo .)"' + +function ggpnp() { + if [[ "$#" == 0 ]]; then + ggl && ggp + else + ggl "${*}" && ggp "${*}" + fi +} +compdef _git ggpnp=git-checkout + +alias ggpur='ggu' +alias g='git' +alias ga='git add' +alias gaa='git add --all' +alias gapa='git add --patch' +alias gau='git add --update' +alias gav='git add --verbose' +alias gwip='git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"' +alias gam='git am' +alias gama='git am --abort' +alias gamc='git am --continue' +alias gamscp='git am --show-current-patch' +alias gams='git am --skip' +alias gap='git apply' +alias gapt='git apply --3way' +alias gbs='git bisect' +alias gbsb='git bisect bad' +alias gbsg='git bisect good' +alias gbsn='git bisect new' +alias gbso='git bisect old' +alias gbsr='git bisect reset' +alias gbss='git bisect start' +alias gbl='git blame -w' +alias gb='git branch' +alias gba='git branch --all' +alias gbd='git branch --delete' +alias gbD='git branch --delete --force' + +function gbda() { + git branch --no-color --merged | command grep -vE "^([+*]|\s*($(git_main_branch)|$(git_develop_branch))\s*$)" | command xargs git branch --delete 2>/dev/null +} + +# Copied and modified from James Roeder (jmaroeder) under MIT License +# https://github.com/jmaroeder/plugin-git/blob/216723ef4f9e8dde399661c39c80bdf73f4076c4/functions/gbda.fish +function gbds() { + local default_branch=$(git_main_branch) + (( ! $? )) || default_branch=$(git_develop_branch) + + git for-each-ref refs/heads/ "--format=%(refname:short)" | \ + while read branch; do + local merge_base=$(git merge-base $default_branch $branch) + if [[ $(git cherry $default_branch $(git commit-tree $(git rev-parse $branch\^{tree}) -p $merge_base -m _)) = -* ]]; then + git branch -D $branch + fi + done +} + +alias gbgd='LANG=C git branch --no-color -vv | grep ": gone\]" | cut -c 3- | awk '"'"'{print $1}'"'"' | xargs git branch -d' +alias gbgD='LANG=C git branch --no-color -vv | grep ": gone\]" | cut -c 3- | awk '"'"'{print $1}'"'"' | xargs git branch -D' +alias gbm='git branch --move' +alias gbnm='git branch --no-merged' +alias gbr='git branch --remote' +alias ggsup='git branch --set-upstream-to=origin/$(git_current_branch)' +alias gbg='LANG=C git branch -vv | grep ": gone\]"' +alias gco='git checkout' +alias gcor='git checkout --recurse-submodules' +alias gcb='git checkout -b' +alias gcB='git checkout -B' +alias gcd='git checkout $(git_develop_branch)' +alias gcm='git checkout $(git_main_branch)' +alias gcp='git cherry-pick' +alias gcpa='git cherry-pick --abort' +alias gcpc='git cherry-pick --continue' +alias gclean='git clean --interactive -d' +alias gcl='git clone --recurse-submodules' + +function gccd() { + setopt localoptions extendedglob + + # get repo URI from args based on valid formats: https://git-scm.com/docs/git-clone#URLS + local repo="${${@[(r)(ssh://*|git://*|ftp(s)#://*|http(s)#://*|*@*)(.git/#)#]}:-$_}" + + # clone repository and exit if it fails + command git clone --recurse-submodules "$@" || return + + # if last arg passed was a directory, that's where the repo was cloned + # otherwise parse the repo URI and use the last part as the directory + [[ -d "$_" ]] && cd "$_" || cd "${${repo:t}%.git/#}" +} +compdef _git gccd=git-clone + +alias gcam='git commit --all --message' +alias gcas='git commit --all --signoff' +alias gcasm='git commit --all --signoff --message' +alias gcs='git commit --gpg-sign' +alias gcss='git commit --gpg-sign --signoff' +alias gcssm='git commit --gpg-sign --signoff --message' +alias gcmsg='git commit --message' +alias gcsm='git commit --signoff --message' +alias gc='git commit --verbose' +alias gca='git commit --verbose --all' +alias gca!='git commit --verbose --all --amend' +alias gcan!='git commit --verbose --all --no-edit --amend' +alias gcans!='git commit --verbose --all --signoff --no-edit --amend' +alias gcann!='git commit --verbose --all --date=now --no-edit --amend' +alias gc!='git commit --verbose --amend' +alias gcn!='git commit --verbose --no-edit --amend' +alias gcf='git config --list' +alias gdct='git describe --tags $(git rev-list --tags --max-count=1)' +alias gd='git diff' +alias gdca='git diff --cached' +alias gdcw='git diff --cached --word-diff' +alias gds='git diff --staged' +alias gdw='git diff --word-diff' + +function gdv() { git diff -w "$@" | view - } +compdef _git gdv=git-diff + +alias gdup='git diff @{upstream}' + +function gdnolock() { + git diff "$@" ":(exclude)package-lock.json" ":(exclude)*.lock" +} +compdef _git gdnolock=git-diff + +alias gdt='git diff-tree --no-commit-id --name-only -r' +alias gf='git fetch' +# --jobs= was added in git 2.8 +is-at-least 2.8 "$git_version" \ + && alias gfa='git fetch --all --prune --jobs=10' \ + || alias gfa='git fetch --all --prune' +alias gfo='git fetch origin' +alias gg='git gui citool' +alias gga='git gui citool --amend' +alias ghh='git help' +alias glgg='git log --graph' +alias glgga='git log --graph --decorate --all' +alias glgm='git log --graph --max-count=10' +alias glods='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset" --date=short' +alias glod='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset"' +alias glola='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --all' +alias glols='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --stat' +alias glol='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset"' +alias glo='git log --oneline --decorate' +alias glog='git log --oneline --decorate --graph' +alias gloga='git log --oneline --decorate --graph --all' + +# Pretty log messages +function _git_log_prettily(){ + if ! [ -z $1 ]; then + git log --pretty=$1 + fi +} +compdef _git _git_log_prettily=git-log + +alias glp='_git_log_prettily' +alias glg='git log --stat' +alias glgp='git log --stat --patch' +alias gignored='git ls-files -v | grep "^[[:lower:]]"' +alias gfg='git ls-files | grep' +alias gm='git merge' +alias gma='git merge --abort' +alias gmc='git merge --continue' +alias gms="git merge --squash" +alias gmom='git merge origin/$(git_main_branch)' +alias gmum='git merge upstream/$(git_main_branch)' +alias gmtl='git mergetool --no-prompt' +alias gmtlvim='git mergetool --no-prompt --tool=vimdiff' + +alias gl='git pull' +alias gpr='git pull --rebase' +alias gprv='git pull --rebase -v' +alias gpra='git pull --rebase --autostash' +alias gprav='git pull --rebase --autostash -v' + +function ggu() { + [[ "$#" != 1 ]] && local b="$(git_current_branch)" + git pull --rebase origin "${b:=$1}" +} +compdef _git ggu=git-checkout + +alias gprom='git pull --rebase origin $(git_main_branch)' +alias gpromi='git pull --rebase=interactive origin $(git_main_branch)' +alias ggpull='git pull origin "$(git_current_branch)"' + +function ggl() { + if [[ "$#" != 0 ]] && [[ "$#" != 1 ]]; then + git pull origin "${*}" + else + [[ "$#" == 0 ]] && local b="$(git_current_branch)" + git pull origin "${b:=$1}" + fi +} +compdef _git ggl=git-checkout + +alias gluc='git pull upstream $(git_current_branch)' +alias glum='git pull upstream $(git_main_branch)' +alias gp='git push' +alias gpd='git push --dry-run' + +function ggf() { + [[ "$#" != 1 ]] && local b="$(git_current_branch)" + git push --force origin "${b:=$1}" +} +compdef _git ggf=git-checkout + +alias gpf!='git push --force' +is-at-least 2.30 "$git_version" \ + && alias gpf='git push --force-with-lease --force-if-includes' \ + || alias gpf='git push --force-with-lease' + +function ggfl() { + [[ "$#" != 1 ]] && local b="$(git_current_branch)" + git push --force-with-lease origin "${b:=$1}" +} +compdef _git ggfl=git-checkout + +alias gpsup='git push --set-upstream origin $(git_current_branch)' +is-at-least 2.30 "$git_version" \ + && alias gpsupf='git push --set-upstream origin $(git_current_branch) --force-with-lease --force-if-includes' \ + || alias gpsupf='git push --set-upstream origin $(git_current_branch) --force-with-lease' +alias gpv='git push --verbose' +alias gpoat='git push origin --all && git push origin --tags' +alias gpod='git push origin --delete' +alias ggpush='git push origin "$(git_current_branch)"' + +function ggp() { + if [[ "$#" != 0 ]] && [[ "$#" != 1 ]]; then + git push origin "${*}" + else + [[ "$#" == 0 ]] && local b="$(git_current_branch)" + git push origin "${b:=$1}" + fi +} +compdef _git ggp=git-checkout + +alias gpu='git push upstream' +alias grb='git rebase' +alias grba='git rebase --abort' +alias grbc='git rebase --continue' +alias grbi='git rebase --interactive' +alias grbo='git rebase --onto' +alias grbs='git rebase --skip' +alias grbd='git rebase $(git_develop_branch)' +alias grbm='git rebase $(git_main_branch)' +alias grbom='git rebase origin/$(git_main_branch)' +alias grf='git reflog' +alias gr='git remote' +alias grv='git remote --verbose' +alias gra='git remote add' +alias grrm='git remote remove' +alias grmv='git remote rename' +alias grset='git remote set-url' +alias grup='git remote update' +alias grh='git reset' +alias gru='git reset --' +alias grhh='git reset --hard' +alias grhk='git reset --keep' +alias grhs='git reset --soft' +alias gpristine='git reset --hard && git clean --force -dfx' +alias gwipe='git reset --hard && git clean --force -df' +alias groh='git reset origin/$(git_current_branch) --hard' +alias grs='git restore' +alias grss='git restore --source' +alias grst='git restore --staged' +alias gunwip='git rev-list --max-count=1 --format="%s" HEAD | grep -q "\--wip--" && git reset HEAD~1' +alias grev='git revert' +alias greva='git revert --abort' +alias grevc='git revert --continue' +alias grm='git rm' +alias grmc='git rm --cached' +alias gcount='git shortlog --summary --numbered' +alias gsh='git show' +alias gsps='git show --pretty=short --show-signature' +alias gstall='git stash --all' +alias gstaa='git stash apply' +alias gstc='git stash clear' +alias gstd='git stash drop' +alias gstl='git stash list' +alias gstp='git stash pop' +# use the default stash push on git 2.13 and newer +is-at-least 2.13 "$git_version" \ + && alias gsta='git stash push' \ + || alias gsta='git stash save' +alias gsts='git stash show --patch' +alias gst='git status' +alias gss='git status --short' +alias gsb='git status --short --branch' +alias gsi='git submodule init' +alias gsu='git submodule update' +alias gsd='git svn dcommit' +alias git-svn-dcommit-push='git svn dcommit && git push github $(git_main_branch):svntrunk' +alias gsr='git svn rebase' +alias gsw='git switch' +alias gswc='git switch --create' +alias gswd='git switch $(git_develop_branch)' +alias gswm='git switch $(git_main_branch)' +alias gta='git tag --annotate' +alias gts='git tag --sign' +alias gtv='git tag | sort -V' +alias gignore='git update-index --assume-unchanged' +alias gunignore='git update-index --no-assume-unchanged' +alias gwch='git whatchanged -p --abbrev-commit --pretty=medium' +alias gwt='git worktree' +alias gwta='git worktree add' +alias gwtls='git worktree list' +alias gwtmv='git worktree move' +alias gwtrm='git worktree remove' +alias gstu='gsta --include-untracked' +alias gtl='gtl(){ git tag --sort=-v:refname -n --list "${1}*" }; noglob gtl' +alias gk='\gitk --all --branches &!' +alias gke='\gitk --all $(git log --walk-reflogs --pretty=%h) &!' + +unset git_version + +# Logic for adding warnings on deprecated aliases +local old_alias new_alias +for old_alias new_alias ( + # TODO(2023-10-19): remove deprecated `git pull --rebase` aliases + gup gpr + gupv gprv + gupa gpra + gupav gprav + gupom gprom + gupomi gpromi +); do + aliases[$old_alias]=" + print -Pu2 \"%F{yellow}[oh-my-zsh] '%F{red}${old_alias}%F{yellow}' is a deprecated alias, using '%F{green}${new_alias}%F{yellow}' instead.%f\" + $new_alias" +done +unset old_alias new_alias diff --git a/zsh/.oh-my-zsh/plugins/gitfast/README.md b/zsh/.oh-my-zsh/plugins/gitfast/README.md new file mode 100644 index 0000000..26f218d --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gitfast/README.md @@ -0,0 +1,9 @@ +# Gitfast plugin + +This plugin adds completion for Git, using the zsh completion from git.git folks, which is much faster than the official one from zsh. A lot of zsh-specific features are not supported, like descriptions for every argument, but everything the bash completion has, this one does too (as it is using it behind the scenes). Not only is it faster, it should be more robust, and updated regularly to the latest git upstream version. + +To use it, add `gitfast` to the plugins array in your zshrc file: + +```zsh +plugins=(... gitfast) +``` diff --git a/zsh/.oh-my-zsh/plugins/gitfast/_git b/zsh/.oh-my-zsh/plugins/gitfast/_git new file mode 100644 index 0000000..3f6f343 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gitfast/_git @@ -0,0 +1,286 @@ +#compdef git gitk + +# zsh completion wrapper for git +# +# Copyright (c) 2012-2020 Felipe Contreras +# +# The recommended way to install this script is to make a copy of it as a +# file named '_git' inside any directory in your fpath. +# +# For example, create a directory '~/.zsh/', copy this file to '~/.zsh/_git', +# and then add the following to your ~/.zshrc file: +# +# fpath=(~/.zsh $fpath) +# +# You need git's bash completion script installed. By default bash-completion's +# location will be used (e.g. pkg-config --variable=completionsdir bash-completion). +# +# If your bash completion script is somewhere else, you can specify the +# location in your ~/.zshrc: +# +# zstyle ':completion:*:*:git:*' script ~/.git-completion.bash +# + +zstyle -T ':completion:*:*:git:*' tag-order && \ + zstyle ':completion:*:*:git:*' tag-order 'common-commands' + +zstyle -s ":completion:*:*:git:*" script script +if [ -z "$script" ]; then + local -a locations + local e bash_completion + + bash_completion=$(pkg-config --variable=completionsdir bash-completion 2>/dev/null) || + bash_completion='/usr/share/bash-completion/completions/' + + locations=( + "${${funcsourcetrace[1]%:*}:A:h}"/git-completion.bash + "$HOME/.local/share/bash-completion/completions/git" + '/usr/local/share/bash-completion/completions/git' + "$bash_completion/git" + '/etc/bash_completion.d/git' # old debian + ) + for e in $locations; do + test -f $e && script="$e" && break + done +fi + +local old_complete="$functions[complete]" +functions[complete]=: +COMP_WORDBREAKS=':' +GIT_SOURCING_ZSH_COMPLETION=y . "$script" +functions[complete]="$old_complete" + +__gitcompadd () +{ + compadd -p "${2-}" -S "${3- }" -q -- ${=1} && _ret=0 +} + +__gitcomp () +{ + emulate -L zsh + + IFS=$' \t\n' __gitcompadd "$1" "${2-}" "${4- }" +} + +__gitcomp_opts () +{ + emulate -L zsh + + local cur_="${3-$cur}" + + [[ "$cur_" == *= ]] && return + + local c IFS=$' \t\n' sfx + for c in ${=1}; do + if [[ $c == "--" ]]; then + [[ "$cur_" == --no-* ]] && continue + __gitcompadd "--no-..." + break + fi + + if [[ -z "${4+set}" ]]; then + case $c in + *=) c="${c%=}"; sfx="=" ;; + *.) sfx="" ;; + *) sfx=" " ;; + esac + else + sfx="$4" + fi + __gitcompadd "$c" "${2-}" "$sfx" + done +} + +__gitcomp_nl () +{ + emulate -L zsh + + # words that don't end up in space + compadd -p "${2-}" -S "${4- }" -q -- ${${(f)1}:#*\ } && _ret=0 + # words that end in space + compadd -p "${2-}" -S " ${4- }" -q -- ${${(M)${(f)1}:#*\ }% } && _ret=0 +} + +__gitcomp_file () +{ + emulate -L zsh + + compadd -f -p "${2-}" -- ${(f)1} && _ret=0 +} + +__gitcomp_direct () +{ + __gitcomp_nl "$1" "" "" "" +} + +__gitcomp_file_direct () +{ + __gitcomp_file "$1" "" +} + +__git_complete_command () +{ + emulate -L zsh + + compset -P '*[=:]' + + local command="$1" + local completion_func="_git_${command//-/_}" + if (( $+functions[$completion_func] )); then + emulate ksh -c $completion_func + return 0 + elif emulate ksh -c "__git_support_parseopt_helper $command"; then + emulate ksh -c "__git_complete_common $command" + return 0 + else + return 1 + fi +} + +__git_zsh_bash_func () +{ + emulate -L ksh + + local command=$1 + + __git_complete_command "$command" && return + + local expansion=$(__git_aliased_command "$command") + if [ -n "$expansion" ]; then + words[1]=$expansion + __git_complete_command "$expansion" + fi +} + +__git_zsh_cmd_common () +{ + local -a list + list=( + add:'add file contents to the index' + bisect:'find by binary search the change that introduced a bug' + branch:'list, create, or delete branches' + checkout:'checkout a branch or paths to the working tree' + clone:'clone a repository into a new directory' + commit:'record changes to the repository' + diff:'show changes between commits, commit and working tree, etc' + fetch:'download objects and refs from another repository' + grep:'print lines matching a pattern' + init:'create an empty Git repository or reinitialize an existing one' + log:'show commit logs' + merge:'join two or more development histories together' + mv:'move or rename a file, a directory, or a symlink' + pull:'fetch from and merge with another repository or a local branch' + push:'update remote refs along with associated objects' + rebase:'forward-port local commits to the updated upstream head' + reset:'reset current HEAD to the specified state' + restore:'restore working tree files' + rm:'remove files from the working tree and from the index' + show:'show various types of objects' + status:'show the working tree status' + switch:'switch branches' + tag:'create, list, delete or verify a tag object signed with GPG') + _describe -t common-commands 'common commands' list && _ret=0 +} + +__git_zsh_cmd_alias () +{ + local -a list + list=(${${(0)"$(git config -z --get-regexp '^alias\.*')"}#alias.}) + list=(${(f)"$(printf "%s:alias for '%s'\n" ${(f@)list})"}) + _describe -t alias-commands 'aliases' list && _ret=0 +} + +__git_zsh_cmd_all () +{ + local -a list + emulate ksh -c __git_compute_all_commands + list=( ${=__git_all_commands} ) + _describe -t all-commands 'all commands' list && _ret=0 +} + +__git_zsh_main () +{ + local curcontext="$curcontext" state state_descr line + typeset -A opt_args + local -a __git_C_args + + _arguments -C \ + '(-p --paginate -P --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \ + '(-p --paginate -P --no-pager)'{-P,--no-pager}'[do not pipe git output into a pager]' \ + '(--bare)--git-dir=[set the path to the repository]: :_directories' \ + '(--git-dir)--bare[treat the repository as a bare repository]' \ + '(- :)--version[prints the git suite version]' \ + '--exec-path=[path to where your core git programs are installed]: :_directories' \ + '(- :)--exec-path[print the path where your core git programs are installed]' \ + '(- :)--html-path[print the path where git''s HTML documentation is installed]' \ + '(- :)--info-path[print the path where the Info files are installed]' \ + '(- :)--man-path[print the manpath (see `man(1)`) for the man pages]' \ + '--work-tree=[set the path to the working tree]: :_directories' \ + '--namespace=[set the git namespace]:' \ + '--no-replace-objects[do not use replacement refs to replace git objects]' \ + '(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg' \ + '*-C[run as if git was started in the given path]: :_directories' \ + '*-c[pass a configuration parameter to the command]: :->config' \ + '(-): :->command' \ + '(-)*:: :->arg' && return + + case $state in + (command) + _tags common-commands alias-commands all-commands + while _tags; do + _requested common-commands && __git_zsh_cmd_common + _requested alias-commands && __git_zsh_cmd_alias + _requested all-commands && __git_zsh_cmd_all + let _ret || break + done + ;; + (config) + compset -P '*[=:]' + emulate ksh -c __git_complete_config_variable_name_and_value + ;; + (arg) + local command="${words[1]}" __git_dir __git_cmd_idx=1 + + if (( $+opt_args[--bare] )); then + __git_dir='.' + else + __git_dir=${~opt_args[--git-dir]} + fi + + for x in ${(s.:.)opt_args[-C]}; do + __git_C_args+=('-C' ${~x}) + done + + (( $+opt_args[--help] )) && command='help' + + words=( git ${words[@]} ) + + __git_zsh_bash_func $command + ;; + esac +} + +_git () +{ + local _ret=1 + local cur cword prev __git_cmd_idx=0 + + cur=${words[CURRENT]} + prev=${words[CURRENT-1]} + let cword=CURRENT-1 + + if (( $+functions[__${service}_zsh_main] )); then + __${service}_zsh_main + elif (( $+functions[__${service}_main] )); then + emulate ksh -c __${service}_main + elif (( $+functions[_${service}] )); then + emulate ksh -c _${service} + elif (( $+functions[_${service//-/_}] )); then + emulate ksh -c _${service//-/_} + fi + + let _ret && _default && _ret=0 + return _ret +} + +_git diff --git a/zsh/.oh-my-zsh/plugins/gitfast/git-completion.bash b/zsh/.oh-my-zsh/plugins/gitfast/git-completion.bash new file mode 100644 index 0000000..2e96482 --- /dev/null +++ b/zsh/.oh-my-zsh/plugins/gitfast/git-completion.bash @@ -0,0 +1,3560 @@ +# bash/zsh completion support for core Git. +# +# Copyright (C) 2006,2007 Shawn O. Pearce +# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/). +# Distributed under the GNU General Public License, version 2.0. +# +# The contained completion routines provide support for completing: +# +# *) local and remote branch names +# *) local and remote tag names +# *) .git/remotes file names +# *) git 'subcommands' +# *) git email aliases for git-send-email +# *) tree paths within 'ref:path/to/file' expressions +# *) file paths within current working directory and index +# *) common --long-options +# +# To use these routines: +# +# 1) Copy this file to somewhere (e.g. ~/.git-completion.bash). +# 2) Add the following line to your .bashrc/.zshrc: +# source ~/.git-completion.bash +# 3) Consider changing your PS1 to also show the current branch, +# see git-prompt.sh for details. +# +# If you use complex aliases of form '!f() { ... }; f', you can use the null +# command ':' as the first command in the function body to declare the desired +# completion style. For example '!f() { : git commit ; ... }; f' will +# tell the completion to use commit completion. This also works with aliases +# of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '". +# +# If you have a command that is not part of git, but you would still +# like completion, you can use __git_complete: +# +# __git_complete gl git_log +# +# Or if it's a main command (i.e. git or gitk): +# +# __git_complete gk gitk +# +# Compatible with bash 3.2.57. +# +# You can set the following environment variables to influence the behavior of +# the completion routines: +# +# GIT_COMPLETION_CHECKOUT_NO_GUESS +# +# When set to "1", do not include "DWIM" suggestions in git-checkout +# and git-switch completion (e.g., completing "foo" when "origin/foo" +# exists). +# +# GIT_COMPLETION_SHOW_ALL_COMMANDS +# +# When set to "1" suggest all commands, including plumbing commands +# which are hidden by default (e.g. "cat-file" on "git ca"). +# +# GIT_COMPLETION_SHOW_ALL +# +# When set to "1" suggest all options, including options which are +# typically hidden (e.g. '--allow-empty' for 'git commit'). +# +# GIT_COMPLETION_IGNORE_CASE +# +# When set, uses for-each-ref '--ignore-case' to find refs that match +# case insensitively, even on systems with case sensitive file systems +# (e.g., completing tag name "FOO" on "git checkout f"). + +# The following functions are meant to modify COMPREPLY, which should not be +# modified directly. The purpose is to localize the modifications so it's +# easier to emulate it in Zsh. Every time a new __gitcomp* function is added, +# the corresponding function should be added to Zsh. + +__gitcompadd () +{ + local x i=${#COMPREPLY[@]} + for x in $1; do + if [[ "$x" == "$3"* ]]; then + COMPREPLY[i++]="$2$x$4" + fi + done +} + +# Creates completion replies. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word (optional). +__gitcomp () +{ + local IFS=$' \t\n' + __gitcompadd "$1" "${2-}" "${3-$cur}" "${4- }" +} + +# Generates completion reply from newline-separated possible completion words +# by appending a space to all of them. The result is appended to COMPREPLY. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words, separated by a single newline. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word instead of +# the default space (optional). If specified but empty, nothing is +# appended. +__gitcomp_nl () +{ + local IFS=$'\n' + __gitcompadd "$1" "${2-}" "${3-$cur}" "${4- }" +} + +# Appends prefiltered words to COMPREPLY without any additional processing. +# Callers must take care of providing only words that match the current word +# to be completed and adding any prefix and/or suffix (trailing space!), if +# necessary. +# 1: List of newline-separated matching completion words, complete with +# prefix and suffix. +__gitcomp_direct () +{ + local IFS=$'\n' + + COMPREPLY+=($1) +} + +# Generates completion reply with compgen from newline-separated possible +# completion filenames. +# It accepts 1 to 3 arguments: +# 1: List of possible completion filenames, separated by a single newline. +# 2: A directory prefix to be added to each possible completion filename +# (optional). +# 3: Generate possible completion matches for this word (optional). +__gitcomp_file () +{ + local IFS=$'\n' + + # XXX does not work when the directory prefix contains a tilde, + # since tilde expansion is not applied. + # This means that COMPREPLY will be empty and Bash default + # completion will be used. + __gitcompadd "$1" "${2-}" "${3-$cur}" "" + + # use a hack to enable file mode in bash < 4 + compopt -o filenames +o nospace 2>/dev/null || + compgen -f /non-existing-dir/ >/dev/null || + true +} + +# Fills the COMPREPLY array with prefiltered paths without any additional +# processing. +# Callers must take care of providing only paths that match the current path +# to be completed and adding any prefix path components, if necessary. +# 1: List of newline-separated matching paths, complete with all prefix +# path components. +__gitcomp_file_direct () +{ + local IFS=$'\n' + + COMPREPLY+=($1) + + # use a hack to enable file mode in bash < 4 + compopt -o filenames +o nospace 2>/dev/null || + compgen -f /non-existing-dir/ >/dev/null || + true +} + +# Creates completion replies, reorganizing options and adding suffixes as needed. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word (optional). +__gitcomp_opts () +{ + local cur_="${3-$cur}" + + if [[ "$cur_" == *= ]]; then + return + fi + + local c i=0 IFS=$' \t\n' sfx + for c in $1; do + if [[ $c == "--" ]]; then + if [[ "$cur_" == --no-* ]]; then + continue + fi + + if [[ --no == "$cur_"* ]]; then + COMPREPLY[i++]="--no-... " + fi + break + fi + if [[ $c == "$cur_"* ]]; then + if [[ -z "${4+set}" ]]; then + case $c in + *=|*.) sfx="" ;; + *) sfx=" " ;; + esac + else + sfx="$4" + fi + COMPREPLY[i++]="${2-}$c$sfx" + fi + done +} + +# __gitcomp functions end here +# ============================================================================== + +# Discovers the path to the git repository taking any '--git-dir=' and +# '-C ' options into account and stores it in the $__git_repo_path +# variable. +__git_find_repo_path () +{ + if [ -n "${__git_repo_path-}" ]; then + # we already know where it is + return + fi + + if [ -n "${__git_C_args-}" ]; then + __git_repo_path="$(git "${__git_C_args[@]}" \ + ${__git_dir:+--git-dir="$__git_dir"} \ + rev-parse --absolute-git-dir 2>/dev/null)" + elif [ -n "${__git_dir-}" ]; then + test -d "$__git_dir" && + __git_repo_path="$__git_dir" + elif [ -n "${GIT_DIR-}" ]; then + test -d "$GIT_DIR" && + __git_repo_path="$GIT_DIR" + elif [ -d .git ]; then + __git_repo_path=.git + else + __git_repo_path="$(git rev-parse --git-dir 2>/dev/null)" + fi +} + +# Deprecated: use __git_find_repo_path() and $__git_repo_path instead +# __gitdir accepts 0 or 1 arguments (i.e., location) +# returns location of .git repo +__gitdir () +{ + if [ -z "${1-}" ]; then + __git_find_repo_path || return 1 + echo "$__git_repo_path" + elif [ -d "$1/.git" ]; then + echo "$1/.git" + else + echo "$1" + fi +} + +# Runs git with all the options given as argument, respecting any +# '--git-dir=' and '-C ' options present on the command line +__git () +{ + git ${__git_C_args:+"${__git_C_args[@]}"} \ + ${__git_dir:+--git-dir="$__git_dir"} "$@" 2>/dev/null +} + +# Removes backslash escaping, single quotes and double quotes from a word, +# stores the result in the variable $dequoted_word. +# 1: The word to dequote. +__git_dequote () +{ + local rest="$1" len ch + + dequoted_word="" + + while test -n "$rest"; do + len=${#dequoted_word} + dequoted_word="$dequoted_word${rest%%[\\\'\"]*}" + rest="${rest:$((${#dequoted_word}-$len))}" + + case "${rest:0:1}" in + \\) + ch="${rest:1:1}" + case "$ch" in + $'\n') + ;; + *) + dequoted_word="$dequoted_word$ch" + ;; + esac + rest="${rest:2}" + ;; + \') + rest="${rest:1}" + len=${#dequoted_word} + dequoted_word="$dequoted_word${rest%%\'*}" + rest="${rest:$((${#dequoted_word}-$len+1))}" + ;; + \") + rest="${rest:1}" + while test -n "$rest" ; do + len=${#dequoted_word} + dequoted_word="$dequoted_word${rest%%[\\\"]*}" + rest="${rest:$((${#dequoted_word}-$len))}" + case "${rest:0:1}" in + \\) + ch="${rest:1:1}" + case "$ch" in + \"|\\|\$|\`) + dequoted_word="$dequoted_word$ch" + ;; + $'\n') + ;; + *) + dequoted_word="$dequoted_word\\$ch" + ;; + esac + rest="${rest:2}" + ;; + \") + rest="${rest:1}" + break + ;; + esac + done + ;; + esac + done +} + +# Clear the variables caching builtins' options when (re-)sourcing +# the completion script. +if [[ -n ${ZSH_VERSION-} ]]; then + unset ${(M)${(k)parameters[@]}:#__gitcomp_builtin_*} 2>/dev/null +else + unset $(compgen -v __gitcomp_builtin_) +fi + +# This function is equivalent to +# +# __gitcomp_opts "$(git xxx --git-completion-helper) ..." +# +# except that the output is cached. Accept 1-3 arguments: +# 1: the git command to execute, this is also the cache key +# 2: extra options to be added on top (e.g. negative forms) +# 3: options to be excluded +__gitcomp_builtin () +{ + # spaces must be replaced with underscore for multi-word + # commands, e.g. "git remote add" becomes remote_add. + local cmd="$1" + local incl="${2-}" + local excl="${3-}" + + local var=__gitcomp_builtin_"${cmd//-/_}" + local options + eval "options=\${$var-}" + + if [ -z "$options" ]; then + local completion_helper + if [ "${GIT_COMPLETION_SHOW_ALL-}" = "1" ]; then + completion_helper="--git-completion-helper-all" + else + completion_helper="--git-completion-helper" + fi + # leading and trailing spaces are significant to make + # option removal work correctly. + options=" $incl $(__git ${cmd/_/ } $completion_helper) " || return + + for i in $excl; do + options="${options/ $i / }" + done + eval "$var=\"$options\"" + fi + + __gitcomp_opts "$options" +} + +# Execute 'git ls-files', unless the --committable option is specified, in +# which case it runs 'git diff-index' to find out the files that can be +# committed. It return paths relative to the directory specified in the first +# argument, and using the options specified in the second argument. +__git_ls_files_helper () +{ + if [ "$2" = "--committable" ]; then + __git -C "$1" -c core.quotePath=false diff-index \ + --name-only --relative HEAD -- "${3//\\/\\\\}*" + else + # NOTE: $2 is not quoted in order to support multiple options + __git -C "$1" -c core.quotePath=false ls-files \ + --exclude-standard $2 -- "${3//\\/\\\\}*" + fi +} + + +# __git_index_files accepts 1 or 2 arguments: +# 1: Options to pass to ls-files (required). +# 2: A directory path (optional). +# If provided, only files within the specified directory are listed. +# Sub directories are never recursed. Path must have a trailing +# slash. +# 3: List only paths matching this path component (optional). +__git_index_files () +{ + local root="$2" match="$3" + + __git_ls_files_helper "$root" "$1" "${match:-?}" | + awk -F / -v pfx="${2//\\/\\\\}" '{ + paths[$1] = 1 + } + END { + for (p in paths) { + if (substr(p, 1, 1) != "\"") { + # No special characters, easy! + print pfx p + continue + } + + # The path is quoted. + p = dequote(p) + if (p == "") + continue + + # Even when a directory name itself does not contain + # any special characters, it will still be quoted if + # any of its (stripped) trailing path components do. + # Because of this we may have seen the same directory + # both quoted and unquoted. + if (p in paths) + # We have seen the same directory unquoted, + # skip it. + continue + else + print pfx p + } + } + function dequote(p, bs_idx, out, esc, esc_idx, dec) { + # Skip opening double quote. + p = substr(p, 2) + + # Interpret backslash escape sequences. + while ((bs_idx = index(p, "\\")) != 0) { + out = out substr(p, 1, bs_idx - 1) + esc = substr(p, bs_idx + 1, 1) + p = substr(p, bs_idx + 2) + + if ((esc_idx = index("abtvfr\"\\", esc)) != 0) { + # C-style one-character escape sequence. + out = out substr("\a\b\t\v\f\r\"\\", + esc_idx, 1) + } else if (esc == "n") { + # Uh-oh, a newline character. + # We cannot reliably put a pathname + # containing a newline into COMPREPLY, + # and the newline would create a mess. + # Skip this path. + return "" + } else { + # Must be a \nnn octal value, then. + dec = esc * 64 + \ + substr(p, 1, 1) * 8 + \ + substr(p, 2, 1) + out = out sprintf("%c", dec) + p = substr(p, 3) + } + } + # Drop closing double quote, if there is one. + # (There is not any if this is a directory, as it was + # already stripped with the trailing path components.) + if (substr(p, length(p), 1) == "\"") + out = out substr(p, 1, length(p) - 1) + else + out = out p + + return out + }' +} + +# __git_complete_index_file requires 1 argument: +# 1: the options to pass to ls-file +# +# The exception is --committable, which finds the files appropriate commit. +__git_complete_index_file () +{ + local dequoted_word pfx="" cur_ + + __git_dequote "$cur" + + case "$dequoted_word" in + ?*/*) + pfx="${dequoted_word%/*}/" + cur_="${dequoted_word##*/}" + ;; + *) + cur_="$dequoted_word" + esac + + __gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_")" +} + +# Lists branches from the local repository. +# 1: A prefix to be added to each listed branch (optional). +# 2: List only branches matching this word (optional; list all branches if +# unset or empty). +# 3: A suffix to be appended to each listed branch (optional). +__git_heads () +{ + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \ + "refs/heads/$cur_*" "refs/heads/$cur_*/**" +} + +# Lists branches from remote repositories. +# 1: A prefix to be added to each listed branch (optional). +# 2: List only branches matching this word (optional; list all branches if +# unset or empty). +# 3: A suffix to be appended to each listed branch (optional). +__git_remote_heads () +{ + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \ + "refs/remotes/$cur_*" "refs/remotes/$cur_*/**" +} + +# Lists tags from the local repository. +# Accepts the same positional parameters as __git_heads() above. +__git_tags () +{ + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \ + "refs/tags/$cur_*" "refs/tags/$cur_*/**" +} + +# List unique branches from refs/remotes used for 'git checkout' and 'git +# switch' tracking DWIMery. +# 1: A prefix to be added to each listed branch (optional) +# 2: List only branches matching this word (optional; list all branches if +# unset or empty). +# 3: A suffix to be appended to each listed branch (optional). +__git_dwim_remote_heads () +{ + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers + + # employ the heuristic used by git checkout and git switch + # Try to find a remote branch that cur_es the completion word + # but only output if the branch name is unique + __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ + --sort="refname:strip=3" \ + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \ + "refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \ + uniq -u +} + +# Lists refs from the local (by default) or from a remote repository. +# It accepts 0, 1 or 2 arguments: +# 1: The remote to list refs from (optional; ignored, if set but empty). +# Can be the name of a configured remote, a path, or a URL. +# 2: In addition to local refs, list unique branches from refs/remotes/ for +# 'git checkout's tracking DWIMery (optional; ignored, if set but empty). +# 3: A prefix to be added to each listed ref (optional). +# 4: List only refs matching this word (optional; list all refs if unset or +# empty). +# 5: A suffix to be appended to each listed ref (optional; ignored, if set +# but empty). +# +# Use __git_complete_refs() instead. +__git_refs () +{ + local i hash dir track="${2-}" + local list_refs_from=path remote="${1-}" + local format refs + local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}" + local match="${4-}" + local umatch="${4-}" + local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers + + __git_find_repo_path + dir="$__git_repo_path" + + if [ -z "$remote" ]; then + if [ -z "$dir" ]; then + return + fi + else + if __git_is_configured_remote "$remote"; then + # configured remote takes precedence over a + # local directory with the same name + list_refs_from=remote + elif [ -d "$remote/.git" ]; then + dir="$remote/.git" + elif [ -d "$remote" ]; then + dir="$remote" + else + list_refs_from=url + fi + fi + + if test "${GIT_COMPLETION_IGNORE_CASE:+1}" = "1" + then + # uppercase with tr instead of ${match,^^} for bash 3.2 compatibility + umatch=$(echo "$match" | tr a-z A-Z 2>/dev/null || echo "$match") + fi + + if [ "$list_refs_from" = path ]; then + if [[ "$cur_" == ^* ]]; then + pfx="$pfx^" + fer_pfx="$fer_pfx^" + cur_=${cur_#^} + match=${match#^} + umatch=${umatch#^} + fi + case "$cur_" in + refs|refs/*) + format="refname" + refs=("$match*" "$match*/**") + track="" + ;; + *) + for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD REBASE_HEAD CHERRY_PICK_HEAD; do + case "$i" in + $match*|$umatch*) + if [ -e "$dir/$i" ]; then + echo "$pfx$i$sfx" + fi + ;; + esac + done + format="refname:strip=2" + refs=("refs/tags/$match*" "refs/tags/$match*/**" + "refs/heads/$match*" "refs/heads/$match*/**" + "refs/remotes/$match*" "refs/remotes/$match*/**") + ;; + esac + __git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \ + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \ + "${refs[@]}" + if [ -n "$track" ]; then + __git_dwim_remote_heads "$pfx" "$match" "$sfx" + fi + return + fi + case "$cur_" in + refs|refs/*) + __git ls-remote "$remote" "$match*" | \ + while read -r hash i; do + case "$i" in + *^{}) ;; + *) echo "$pfx$i$sfx" ;; + esac + done + ;; + *) + if [ "$list_refs_from" = remote ]; then + case "HEAD" in + $match*|$umatch*) echo "${pfx}HEAD$sfx" ;; + esac + __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \ + "refs/remotes/$remote/$match*" \ + "refs/remotes/$remote/$match*/**" + else + local query_symref + case "HEAD" in + $match*|$umatch*) query_symref="HEAD" ;; + esac + __git ls-remote "$remote" $query_symref \ + "refs/tags/$match*" "refs/heads/$match*" \ + "refs/remotes/$match*" | + while read -r hash i; do + case "$i" in + *^{}) ;; + refs/*) echo "$pfx${i#refs/*/}$sfx" ;; + *) echo "$pfx$i$sfx" ;; # symbolic refs + esac + done + fi + ;; + esac +} + +# Completes refs, short and long, local and remote, symbolic and pseudo. +# +# Usage: __git_complete_refs [

    {tsjFUrMmWH|wF{vEY{Tvu2k)q| zULTby^zb6OpOFHVV@)0*^YcT7rCH*#(sS+b8}|}F4!lMD!aX=^$8>&g3$N74Y~uB6 zwDMmsM_X?rt)=#k(|_%Y+uG2Ta?PInyGM@qw znrKAWJIg<=fd$=plFnBh%O8i;@mWiVeFdTE0DovC0a730oXOkKuCU_qLgkBNrR&Oq zG)NK76-^a$_IC&=Ig$ruh&U0F;}^ zCk+x56;bvB+kf$^dOj`rCSiNoFk+?GTkod6SV-OtY2Hw6M$n37hz<06F}hD3DTDQ& z0h<;_$H-O{(pt>H67zD(o{qmIC>62bNt_fdey-H3vw$#1SlJqjo~s}kZ((?o!;4p^9V zSnQ+a7K@%f$+&!0|K&u$*YMZiiquW~y)_=rS>u*|`U!@yFFG&0JNx)|H{tZ9qHfY@ zLFxrx{rBB@->q#_TDLS9SQ-ZhRQ=7QJzuI}x(0fp^oX^G!q{Wjqw+ELLlojP=5x=3 zo~^{9s$jAJedy3YdsAlYJo^*=VQVnjX_hWbt$}sop{Xdqp2%ZbY*|%*WjXya;bgNl zrASeovpNSFXew5feC|~=wWWa*pkwZ!IR!6C8wp0j{RghWJKj1So3#B{iRHFbqgOo2 z8F3P;7KCzO0m~{pv>E5S9>_pjbR*VDI#no&Qu^6mk={&56_{!TAr(6LUehMyl5KMI z3}g}4XbIGP5;bZWgta_pcWZ)9M^GfU-boX4) zP2CKuTm-(XDDkL+r=Pm-^J`TG*`JO3raLS~OTNTf>22Nj!=%Zf$wb%(g~52GB~Ft| zt01{s!qhd@J4y!P#M#eyb4kBK5#Jxqw3M*ag8zv>t%VU8>zkELM1b=Q_H^L z3=L?l5q~0p;dDapVLN5nta;wo=h4E~*4AeGvSgr`E{O9nTpZqE87Lm0`>(%}2nWDH zRh zk_c9zEY4*;q7)C!g$E)ULO8FY7H`N?P-V5Y6)FJSLZylV>(C%9sB}J6v4>%XigVuUL8WCu;x7 zF71sQJnL&{*X1J8vYK+(_f~zodBaNmj_WR5;yx?Rmb4&m%g+kX;m&qPZ(-P~?sZcs z>UL9GW4pe19DSRO@9vWIw~NZ!D)%zaw2n-Ud6Y8BFw(%+Pk3x1y2Xk@Pbh-NLbJ{t9xe13R4?_9b6ls~|JJ|(L0+s-VC|F8eF~dyr z25J!_-_bm2!e4bYRh1=3+ydKEsGEw!i;oXYH5}bKJP508lyvJQ&-cI3k#j+$uz;jT zM}_9k=itS7%+=|TJ+vj+%!O~{OI|5Dwvnj9|8{c~HNRdFkvkMv`S)VvxW^YjBy%jxOFOLvT!hr?t-9ujtYI61xiyb|GYdw-;xEO8g|weGAP*iz&Cb?S8X1UgaErj7IYs#NP9sKnm=uPlaLKFk*Ix4(N zUo029*ZYsp8DfN=6;V=&`J$2AkKn`!w^*jD=t?-=@+^Is2JaQa86`gO_d59eE)cd# zx)};W^z@+SZ=mXjLrs+wvE#|X$L^G`8%S|j@D#K0zZUV2OTgk#vm$h93G*iLTdi=l z5k1BcnEr9L#A_?qDQe^9ZI!{RmyLfif8XAQx3AP+S--2S%1^I$p=82gOXNc5<&IY- zD_yinIXs*Dq(uEgC9Td%i`>QyT{Sl0?Y;rb`gLJ}Ykr){JDOpx!M6)N1bIt)(lcVKqqd z(HN)oPQ4EI;4gB~i;j@XA?CLQ zpJVua=90Qz18&AuSWQ;@ZZ(s59ESs>jw#pX1zY{JdS-JlIJpbZCXEDWV8R>J`WsuN zrt0i~?cVmoTdB*&Fde0Np{WBm{Iq)WI!=6hhYIOpvcsXirnA6}M3s+3v9>l*$?u;T z6(&8FCu$MnaMNbSqS#HW;r1GMpjfCC(L(KE)UQQ*7ufR8s=DSb{Ah}o(mE-{dAJq7 zXG|cqVO0rf2_e)D8>n=eH~-D(l_(<&haF%oXX4XM0VZZv*RBbl*m$4_5*^Xhb?c)JEgF7mY|k<%>>dAEmsE=$$>E@Cbctd@aBZcuJd z+tSYW*%qPSE!K#pCvUUoFk9LI=-an#Ocm&gB_4byklG?oq2_A4aFdU(FKB+n{!eYV zR}mRNnxofC4Q9t}<4LT6rfVi=5bPEyCjmoE-&9pe?NCD~rB6-!R5N2@ z>wRon>B$|jk69lt042-}Vd0@tDc6^EDVR#fM7?uUwDYBSqp4Tns@b7B^p%?L7ZPGV z`UJKabL@@`t%AU_l}KOVl_lUwTFYzJ0aL%c|ynJZ|AJ7CB3zJjpx+MnDP{4L1?f?5Y$MTTY-S@RshST$oM9Y@}m- zy)5zWbVFUazzGV)TU@D5S~FGplI;&|!U7U;`8JW{ABrGDEq`Jz@(W@3D2eLw%ft{7 zyD5N=xD$seux78!XU>YUWd|<`9hM-CKYK)9w*ox46Urq0*7EId%78^@9P%N14QjyK zy8(98al+Q2aS`Aa?>mTZ)++jPz&`U#?$5@BYm4$%)7k1Z42HoZVIylNy)U9ClJW3U zEMsud+GC3pJ3f5UY1v#>EfaI?;+GsHL6i1wP|qY4cB`B?^_l>y8vZdWzZ!YTTVSD~ z-@I_{JL{3PfUG_XyJqjq&o63SJGvgt4R^D9Sa|h*Gwb_>NkS);l%}xt5!=%EsT0=Y9ipq|{S^T^0e_t^MieL{Svjn^sfAkPn2W)yW`n)jSkH#1=e(2|N!Rh2^IeJS zrw43?PoR;Le8-@)wpX75U00%NxR5LuBp-{3a?F*>FH}<5jJx@=gS}FXsSAdy<8Zqw z1-94CkRtG+MV0v;Mer1w@>{P{%2&>Qgj%Rnq#Ji~E#fWth>)bZBP}QtJmTlP7i7PR z`ufU}9j6*_-n`pg(M zBM>k1-(>O@QQIKRb76EVWks(Au)873(xrUD-IJ%X6T|PJscGnrn=;LPKnt_@XVQK> zft3?POr?{1$59P>ew4Om-3FD$&s!v(DjerLLoHy%3tFee+(v=!7PY$GT|eU2>va9^qC#m;Vyv?4NRp~*M+g5%3CDXL=e~^G${yND zoPSxCxe)2FScm9&a?!aBvM^T)F*uM(Xqu8gNWQlCmG1BhD)(k?V9sA@m)}P<4Bq(+ zb$xnkc-2*fWb`pl_J{flbaQO`sc)cibLwy1*7?Fxoj`?*O&<$;-j9kR>$|@8FqYg~ zq*j)-WqQS}0|OfxqkD>IQ6+mXpBBlRNt2A#{50s|Ra?aFrdX%%Qeob2pf53s12qd+ zp7A?~8E7d@F+2rax*1PS97SH96Y_@$OMF*60$$jtOaXA~bsm)5u7p=-qnq&bZDa=} zP$Tp3&J%RLzFXp|Fx9R=Ac&F`Wri=I@2+@TLN6vV8^KdSu?&9YaI(GR`zPhIPj_S& z3tFb~XiYDgZ4EY_vo!{PsZ2G=Ia5j<){bQw2i#Olt1u^AezhH^>XuZqA)>v+<$)Mp zT1TehzPSv-EjYXj*5y9Qw_|RwAgj_T+lbnehCpNX5tVS|U6VB4Jn1B5o#b=z%`x=* zRy_4ejMb}|!f1T&gfDrKB2yL7tsWtltnY=>l@(IdDc(X|Kl1N<%F2<~^F}*+TIUm=&;T35<_xOWi;D8-zlWu(ySwl4SV|y$o^$nN_$}6~aQut9o z*aaOu2;c!P;Qp0eI10l2w^HIk64qH{{|2nWaV!9Cu6@~DWTP}lljtoK{m7?yi!9}( zXD^sC_09^6;-Tw5wCPglnO0N)f$wikUZ0J8KY1I_!pyhy*)KQw?>xiYX8WRd3EpHy zXEGx7Q9Aw7RP~U_qUE;TqRaMCt^L*~z-#5@&K~zao>$a0`^kK(o=V8xTNj9$YEKk; zY)pRI{UUVF{k_4y2c9(9$XLC5CVX?naV5F<@0?VU3}}y9^!i$ZB4=l)IT^2r=Zq#O zUX8*Eimc)-k=`Elx+&WU7F$<4j%t?107aVvYVxc4di*m{Dx8ORu94ir2I~_##nTNxP5|bU?SuDpDFnFfydbp} zOO~j|9u-U5<4{#y(7cXOJn#4p%xPof6$?G-0KSA5byB8PdD+nY@8r#m*G2I3Hc$Sa zHX077DyS3_9(G5xEv0s#NA>9W0^0_`>WZN)frME8uT|ihm~{!qj+Q+74kjX(&cyGW z`KpQZ9bPwobQ5w4m6bs-ky1^Ax*q&g%hw}LJodp+n;EyOKFdeOKu8>3eH*a532Njf zc%=t=fJ3n-J}aJBo3mU9U$e@5hir(J$Ocmi{?HU`2vkbrF9_K{B+?AcC0gfn!5^Gk z8rfitsVjx0P45I+g?M^MHP&b7ZWvi#Ac>abJ^dO^ZV>E}rr5SaKR-tnTg=Unz*f)! zC^m#ur2P0I$v~wQfIbjllH{{CCioQHs+SIM;M93RYbU5h3-*!`qzH)N~ zvNIprI-}ewbwCTr#*GzqNXjYAA*E(?_MdijZHOLCi_{zhCyz(TzLq)Uc9t6Q_hWb- z-W^?=iX4^c2;Y-4Oa4!_z6a=W6oyZFBBhpl&ASq18*bq@tO-Ev7d;PiTjz|Qj={&S zO}MNqKIVcZU9NS$xSVWjtngiKhr--1`mUp^A9|Dc)D5hxglaVfD^1cGNKb~Sw6(D5 z&8v%8K6C6DStLR=OD~al@6(CWfyILDXSz3&Li1OXjH~%4cb<+=y{>T*FJ1DZ>42#M zCA!q*S$OvdGiWUAOOfET<}V=j?C${rGuL<54h_yU0XTzjME<$Nn792Kn55xcz=Bqm;|jt>^m+$r=l*^XI!Cz+4rM7v$h{Ly-~{`Bc`lB^RMiGiuUt z2L_x!)q;LXK4k|e$x6ppX-+IH9eTDD%~=VyfvjS*AIg(ecm(IqYSl1Ia)6X5&*T}1 zST(bM9o<0Fci13X@kI?xIuBXZNYR6$JiD8iaD^eV1vhj0qtzEtcMOn450Vt@_7WDT z(`1!hP-$PX9#L)8V#s4%xDxkaFOHr6600WYN;JK$zml$Mfcg@fqKXLbU^={)CUTj^9VaV8>QUBZb@ zGv^WaZMQGGE`^t}a5ZhovFks4mN&w^Yd3jSznh|qpWu_0DSp#Sc?Q+(*{y3IBxG%vPU-^%(wO_U;VPrt7Cmc7=<7pretC!5Z{l{xdV9&@^zU+ntxmQRGD z;-oQh%urKy6@6E9JEU2!n&LOlUSnL!Y1)Fx75cj^ktJY$3$`(H4b9%nH<1BNrX5Y$ zfZ&Ok5>-0U1eSB6Sd&8wk=j1%ja&oJfxbK)=)a2b_B~ zvCZ%^XoZ*1WDDx$hkVOIkNt)hZ3Ri{)E$>?(0&ehxP9sf@?=mnI;1cs<1V3_fjV6D zG0wRx@j-)xrgGjW^ezjY_|FTJ$Wlu1367NOk*fHIA8o1{fN32g0e`6b3OF>cuFY9x zj~?9v@VHyKd%zg3zALusizKmwnXf7;&Yw5(W!~#VUw=fUUGX*2i*~a zZVmDEshD?j8fg2}Mw3Uii7MB{Ps3S#k5K(av@&miqm9G)SAS`wCZrQz@ zRBIpU*3e`c#_Sdr5SMKDH6wm`L)SAfh~|5EQ=_~lIiXrvwkJ6xulodigjMV{-CXmu z@9=w3=x&=>O`wvn8@_y^se$KXo?L*F3$m3R6Re<%Q}@JL-#8tX^Y)b7%gKQD--{)= zjw9+BLQ*jj|1O+iwRIJz-K3R7O?r$8k`xueiY$R~49htmr0k;pIRy@DaLi69pZuVJ zzoBp(FYV`?l0iAAh>JBtE{YnETu3yc*Vl3xJ_J%lEWO&-#e z9dGN<@TpiA@#s+CDpQM}6lTK(HPtH$W@wZ$GY1zCBgKqDu5>4t05es*+tVf^mwsCU z`a}+vlO(o+J01b6xxeDKqfKW3UClItl#O<21Ld)C@&(}AVGsmyPJoFg-omsd)m_n# ztkKUCjPjiwY_B|MxghcZ>Kcyt+L?o}@ADvZnwE6=3}h2xzkg8P-fi%sy=Q9K4CBeRjxE(iY0}sKeZ!p_RLsaw=ZHA28z} zPd7}fIB^K^5t+mUgR4pJq4iNjtXuJCA9J7Aya`msh{JDbdNT%Vt4$1DSSCm51lg)s zh4yIv^9+1&=Bpcp+_x6E2$X#(=Y_>__`m}8%e*%U7%ND)1b|Fk5E8ZxrH$?Gfjl_G zX5C0R@$;al8G2`=6`<>)XQ{Kvj7tb(y_#T_O8OBLwYHyqy_m2mEmBeOCLRcXYBVdJ zK&x)520p;1c6m44kZM4`6-D?!uv-sUb9@&(Wv`e+*$%nU15m z5FOtG0#$r>gftupYEhv$rDoPouh#0zdS-i8t0-i)DtA*3K}-4^+5T@|)Gl>AJ;iF} zH?!YM>wyKizgv7( zeuMi0Is5eXM0beEuEW(_(V1{g4Jt zC163MD?-aiGe(FOiH;n@5e6P%d*gI(=&69=h|pz6B$d8&lgd(} zoKaHBj$5hdq*OLtlB<%VYnK#Vjt+#fxpUvv+THoh?@#}%-N)|Cyg#q^>-Bsgl(A1N z;_*-VhaZrcvLu>Prdj>lTUkfJWITfU;!|l{MMu^JQjIsJMfjU=D1-*qVD=&UjqrF( zg(MMs+WL%;r*ZjAVSAOSMo;&~YD{!+{MuDaY_SwXH-LQWknct>JuXJP2?*LqNH+dwomgW5)B!hhUz4B%E4Ely%_btke zy{G%@uc(7d_9Kwv&(j`4omsn2GPKN@(c`a~S)`+X((r#y`ny$IF2JkeQhy`f8T`c} zMq7wQ_v^R>wtUX~O)^@V{S}{b)upDZy)v|?l!J?!_}_Hf#n)Z#Qv*(CGSsKee3E); z9mi}Bq-M)FmudKi-~O106z41CQ!o2rhK#5EYaRFqwen?tw$eJ1(s%B8>FVU&_&-hX zB<`x$>Qd?Lv#)tA;v^@qk~yjt^FrtqcLBdyM(#TPQsSlL2Vi884S({6=lUu;A2PF* zqoUz{=ygxX`X_kTij}lchqzAv67rAC2?4IXhZ*xX6 z{<1dpcIIdcs}4z93T>N7uRa2Ko1xV}xb^nuv%h)I#1lkWG-XX!(?S)t@?QuGFE+xK z15HKr1>DyD4Pxs@&n>$NcBpZ`NK?m{%qv4+Q=d&%IMtd=+Ks7Byp*XAhn-4)2Zq^H zL8Pu_Dn54_@uyno%^CfaiOyX0&{c1BUx?pn^4-pzdOJjDZ~e#fj6)ZY>|$X9D)=qV z6!4mle%-Qx!20g9gbse-FgxI>yO~hIv%5fTZebkh$Q&AdJD;GQSf$nc-$fkCPbXcbvzvRJP7AW2P$mj|vr*1j6s0=0+= zgYd7t=Egv2_Dv!gv!2^m^v~oZ=hT01OQ{A>!@aoo(a(oU-NBpxqI&e#LwOLUA*KgI zn#IrH_<9os@DawwFoolkG;h#4Y%|HJlLe;A zsNr;l6HlWPa?@mQkb@%#jr=)m0MIsoh2t+Np<4aYoT7d1Q)hnM2|g%X(vY7p?UWU_ z^R)JmTaDG;5bqt`Ph%3fy`NXHW}Qo?WQBg6OOb9F=grnuX|)OK_f!_{J8Q6|t~9K5 z{XwKQ{?Nm6$p3)ZK-al>8a0O!y@I6^852O!qS$)L5kbB9*^f~K5i zBj+a=J-^RO$rvQyYL>cWw+PPhp&eBSNf;tCjwd5&w}rdFBGF+>{t;Ol)NpwBud(Za zK$n`_fOn(JF7f(5`ZS3-&34>6`U4eZpz4TitQ^=2nZ{s8M+po5{WRXM1%Y#qYqFw* z?VSROTWj=u;jbdW{HJ5ptq@nDA2>I0RgreA7LSQuYkVA2Qb5T-wN+}7Bh3t@v6E$J z>R1I-^bxn%fW0Rt`{E-xCD=dr@3-5|@re7ug zTJ(D+7C*FpP9q4cg0Ucc=XOjDGT#FwwuxAGLs?2>E`rhXksTg*Kyy#~sl65@(%k`n zISFg_M;~?qK}6Foiw<2?!puQNARP%TNOhdb(qXt?=Lm1wLLVqpHsNbImGrRBkNQ>G z#N~5pzwpwm$dCJm@QfyP;I-q{^+(!q4q1tWr623pLYL)rA9@u` z8uc95*o-B$*%dswQULaPYt;2e9c3xqid_hc#&SUE>;d=o{_Hjh(3XyTbf^8 zZYE_?7`K4-TulyNBOh4qqic46UETV6U^D{Up7pEe(TI({#MNV(vtED&&SlZvx%24F zwd2c%B@tT_-Nbs(JW^LzTqXwBLt3{&a$&Igyzd&LwFl`6g?=`&rrkE)}-y#KQPDoB-uR9 z(WJG>Gl{`2y@NxUkIj?>lEEmiL01ndiUj>_K_$PlmX`v~*HUSzM~~NgaKD=qY1sjo z*;#M(KG#(+_>To3(!QO>SwUiYaJI@iCqb<{q5TLzqs+M;1kpd^Q%r^1YKWm}PCkkA zsYU&GL8G>KvF8S;*phFT%_;7=2{oGweD+Zz>1ool+u5NXF_7qu6-(Yh zsKG6Wt|Y9Iwo|WRug6Eysu6zpBJnjs$aGyqp80BuW#c9-f7%Z)(BRqhOQ3}&NCLW_ zJC=2Vy_4JT>c{i+l-b{Kt(U+`8`}kj`@K=09k`K&I(7(g_vEaU>$_36yGv;W=!?XT zkwa0oVavt^%xyC>Ve&Raqcgz3Mo0S{)F6`kIeFe!sAv%`{J<&TV&1K;dtor0jyZuH zhRx)9z5w{gA9-2PkwF(;UQf=^-5*QRP`UiEE^X+JyY%bd3a1q+>NJXG+`aF#Urc z!ao`~)6-n*#b@@$tP^h&?5#m1UQU0L+s+hy+GKw_HLyIK*=V`B?V4M%#)s+h8vk8y ztmYpjt5g^TY86>dJgCqwvT05TU7-4q`LHc+o0a<2{OfbaQ{4Upsf~5-%JOTp%(f&&+j>R-pcEN1SB?}b)Is5Xn`^Dbkx&)Q2~*t+3~CXb($w@9#<_em*{4P6nsTA-)3` zz7gsG%`}(rntof_V@FW12pThIzgmSVKyukxHb|&B*J$wZS1%_-1SV~q8&5IW!LuhN zUWFeei^p-TSm`N3p|@MZ92rX9g9>1`CU0G4ooEKqF@M|%jH%pie}Jt~K$l3C8yETO z%MCL4S@Cehv9(-fT$d?b9bPi4sD_m%(|#-=3bOTgK!;)`3(ZEjOHf1{xkTXe^6#-I z?=yaxQ^z`OdQ*z4esZ>tuGluHijKvuUlc%}J;bqiAp{X>cj+dikw;#O4?Z+pw?w0H zsI4SdBmaij^4f@EMDUHnsUagN$)-!P6`v|UxIRWV!n3|x6Y~k0O`pt4*ZmpYnYf? z%+oz+(NKHKG;h5sI2%18GrBVR&Ya@Tm@y*0DM;@PS^kL^h5#D-NHYF|5Xa*X@VGha znLGcur;xYA7-h_SPp(gr1NY!GdBo*2OBVKsJ z$%A;9CU-ukqx}A?_7@PLTLnbK(_8-njZumfNlb`n-hwEzI+l6W+cT2xap|O(`4{Ck zUf}647L*urOoGIjzow|6>CummOw#E@1G&u6iAy_Ur)KUy5m!cdbiebvG*Pbp zvwqi|_d|mg(5v7WiuxkOXo?P$vwDBeRJYTbGG#_Dcixe{n02?#rQVWF(7akR9rNPp zgJto_jqJDIY6ZMWNRV)zp9-akM|xdQqYE@=y|WQHJg)I{h zDmHt)JFqVcu^kOjpGR^zZpQvcg)R)WYf@as%H8OZ9k-#d&pe+MG2*soMlwZP)(Q;1 z!9}W`c)11O7d|mXeWyYap)Hmm2HEC>aXDdAv()78QKwF@d?dsXK6HONHAJKjTZHTcVgI3l6J9HkVS9D#2q~j^CuXY5 zA2yVShSWI=q$9cNKtg9#6vLR^f?F7m|->Y!wd80M^I zE`MPKkTqq#v4S9Wt3-R+4Wmo6TOFVc&2+{yyy*o3K>8za-yM;&4f68eJ(Az1+HDKZN+;6o&1VbR#S+99NIQyu{6zD>862ag; zdt@Uz<*D!ZD%aqPTuDsv+@mEsaLVuo`c#dzqCLmg%GIkl z@b}j(VFhzNC)RgoQv14@u34U$5~202=%IC>hZ{*90?uwDH;>KnPiJKkM&Ng38OcZ0RZ>Xge2mb*34D64;5yE{*oAmTp9FXZ$hv0rz& zfML1FhXDwg#^}KxSr}svB_S&SQwamKA1m?59{n<4HkPGZ>IAv}VV&vkIn0nw@;h+a zE}WQui{@MhX;>hIy%o@q)93F2m8iKaS3QTng+mg)nt8>$7zV^x3Sju41LkbVcljax z_=WW<$z2kDg&fLxm5(=H1m?!r)-jWW=wv|rF_FPF#-{Bnj-{AlYYtAcR3@}EU+43U7g}&8`O6}@fXglD(e}Lsxm_BpUtLo zQ6PJMC1j=ml=0JU>|}}hD^{!Y$roIW4BwJln&J-h2?GXB+auOa;v2n?goNSBlYR=c zQwNzu637xKa>%I*Ffh07$LFTKV*R2Z-WoF^0lyLom3r}P-bzwGkY1j8mpThx$-$Zd zNZ*yZ=9fg9F_d@Vts0Vi3BTLjehgS0g%(bq*eK6tOe0lv=f)2xzXT6(7o4*t75&tA zBCitd&9a3~QH0Cvw}5>pp017GCZ`~MfxH6pj$fQ3l93%hvD|ssp1A-8R3lLO>bf=v zlq^&=|3}gkth~l^)ppk{6%{^X3N=2_nKnI%D_HMeoP1c575nmyl_M=h>b~I`n-b1(t9;>6wFr#A0_Ktd5s_4GQ;VAf9Cj_ z7eT}gZHBZ1*ZtX>dj11us5lmP3A4~rXbuK4$oWd#_*f_BpaS$|h?7gK>DONAp{?Tt z7s15pco+DO;5KGY;Eib*&+8mcZQTvQOr|c}N5SUeiLy0mraTzcVub97I2~P$xKbq*|-Qb5P3XkPe=~!&1N}L{HOE_<%?@@)6Tl}Yk7q&gQY8g zPSGkp^jPNLQD7`Rs*Sq3OWz&XEYIHHE?IrLvt4>xzC;q$pblh3)joj!0v|YnE)g%8 z<3uXvO0^dZ5dYz)jKFJR5#R1Othu2*9zWYO+NR#hsUr7LG*F*3>65=u0Y2cNhJBMS zGOWR0gpR~ez(;@%5irX-9q^XS)+0Jw<?zi_t4EZMp!eI45~nFjKupEupXv)1?H zd?wrIChV>&aPh-a2vd5YG}EV*_e+j{1a_@VV|Kpa$cQwKL-qC*Ps7M&&MO3!p(L}1 z)pv#qOQo)NB}A9c%^+MzOT*(fv#p^Qm=BHlQ5tP)uCO9D`ibkHw0x^#hO8Y>6Pr#f zvynJ=MJ4eatKkJI%whzy27hJJvb|)Y>`0M0)_99NQxn=GOrc;w6!^f^AzmGb)&a?n zac>6S16Y>-PAZ93l`VVc9b;%nVIBbvJ-9+DbUx%sud+B@NmFoj6=J5zJuVkga#?yn z4cpddXv&UU+5s8%%P_WpY$JBA52Pg2_W|Zi!SRyWESfu)1S$zwB?WrjvF&8^=0302 z!z1T5CqM2jw&-Mx#mk50P*;zC^wrLzYZQw|oI>}+dBzx^}4eXMW~=woBP_{_#04uRX8J~pgh1^Py@pJc68>DwB7CR3i{ z7qknRe)TH2{%1BzC(3xXT}#eX1JsCY4ISNgOS-lV0^@i=e^&k0Q zL9(Onxp}qS&yA4)w@U}oxa!|e%hqM3x17t$qAS0Bf5`Mr3Z!WGNj>uKyu^`tZfJ{H z1t;QkO+1!xOmk~8ull#ndihP(MVB)gk>s?8kim9_Wy@ zY0+7V`!t?5rV)oNd?5+njT(tvU1e~$w+a4Y!vztYrAT`Z#x>0@P4I4sP3B7-V` zs~2P3=4KrEQUabNPdf4{noU`w@D8ZRnVR7$#eWMgp8S02N(-;&sQnS>-}S5wKyO?N zJ>}Z+Oya6PUJ^TDfMprGJca!)=MxhN;?XommMY5e*o4%a1HagFJs;;Z7l;Q z-bZA~0jCdudzPN#%nxdygeF;$>m&I~{?O2VINu$8O-5xzp6kTz9lc6Ap^a+4uj!4$7AvWvo`3KopBaKh z?IOe)%a&{?1Iy$gRU~Hm2x>p4L47WXYhmfp1t&S5Aa(&zo5xK0B-QV0L2H05gGz-@ zDWJP$@U&TdT1DMGI4T=rXDQ*2hltPRzXn4j)2gF&u{il}Ar-tkSg0ak_%5k6{HjR{IbyNBrF9vIZjCj1DW?HtPePq)(%NJoY z*aoF|&O8hTuY7F5O>m#z^c8R^^+kjO65(D1@d~F(j+v1yw0Otf*i(rsfrXp9+5UFw_LLSp0QU z34Cer>z}!8^i%Y%?JG|Hx{>?%dC;KIG0P0WEAf{v_wH>u_WDkN)wAgb8$T|)3L3M2 zfBJZ!+G%wb*lln}DLsK4;Fz_0Q4gFw((0vX<6_#B>>-IfB=^v9C_DEmNr|9h)L7po zNWqZrdZLLtPt3;TAn}UgA?i`=aVX-L0X{F(lOxcX`vy$bvyQ-A1xQ=u2jRK5Sa##q zEi5%*<#=kKbWk&(f#q-stY8vQw*`!}TbZOwSxwjR^;Od$)xcJpfbxzRgNTb~r5nmb zA#gu*;URWIi&TsNuS8+UdT3nL9j`8L;Yg0H|pTatjch{lCvC7VVSb{hNsi*cqHa{MA9J$g5Ev)To)$VmVc2 z5~Wh&+db0Ie(Q=S$9P)hFF=psU5p=OJ(5tLurb@B;c^=tuxkUmr#NftFNgCif&%dw);>2)yld} zi&G+&mj1B5%}b7H8>bDrej7OJ-1hatg*66MPv*xJL^{lD<#G$M-WlwZ>8L!fBbbvJ z^Q)*V*}<&vNxU`hX_@2ZHt&c-cBN&|uC|JfwSAweEStGlt~AHFiDj~O$7nfYkf11sB_r!-5*5#epiR3p~4&eDERllvy;lGt)>JY-7Kskk4^OZ#vuQ-XzE>Z>uK;Kq6 zM^?+<5i%7PzN#C?kG*2`C7dRNZT~se1BvB0OP7|jh=1n##K_r~tPcu(!*p}O(z3$4 zV+Z_D)~_dbIa576Vr>)kLIw52FIi#@_^V?~Y}oV3P1K6!b`h)6QmFbH{bp&cWTt!L*iueGIb`}yKLeQ0>7T5<2g2Ls_(S5C zGHEY?scn&xaDU$k60Jz(CRF?M7Uz@Y&=?Qgvb*0hui_Khvqc?9)cH$}0?|n8) zzWwL)V%bxwyZnDOR-Bo=G4F{f!`{oc_w&%;#LA8(&L?7m)l3ihZZ^b%-Q9-de@tCE zfU==mI?}q^w{IZE3&xw$R`8Sb$X%N>S?|PhyYUo7TTomFy8$+XDO1 z@8?;*&>AHd?7BK=mO*a#L5F1j^^Rj#!ysIt45_)ElEon!t#atF~6cvz; zYF!<==8837!SqNd1-uZZ47Aai`I1tPpI#*wrZ{b(Fy_hDe#JSjhKA$WTINQhynl>h zIL8T`iC%1ieVW}a$daGA=MZx?GJb|O&OvYjwY+?$j(`HS2I18hVt#!KI71g9<@lb# z=Sz56jJ?)FxZyW-zJL=KbQ`1}8Rxv2C05NhX7!z0IRtp)!4&aOK8Ro>>Zg9z9y*PS z?Q%pbz?CxshX0_13Jq3coH>`SnX4D{*TYs4p5g#*j&PT0L0>kZbkTM=OOfpImuIAz z);pUZOnnJ8CaUmDW@h%sic)pK*E7fNc~$KLPCMC^wqWsF$%x<VF-cz!5*b9+b-bWgF2KAT zUhj57&S}2FKA0|#TJ2>z@HQ{h>~CFxc{bfbCj4K7%+(DtmbLQ#R z2Z1Lpt&;GuW;sgOGGW%U`Dkz;-rK+GF-%Nc<=sGY_q(`xx#BCHIQ@^*28lg+Y6m@f zndnJ1dyZw0l!$vEF{iUvf(!M#-Oy)KSC5sIXusCmu0} z0tpO{X6Okl6_P8fC&ajvcLBi9uI)_ZlEE$F67KQC{P(zX{)IQ1l@Fj+fGUTnIW${ zd2keJZcqva29t3$%gPM-=V-^O*jN=%-a40_Yzz(!jhqX@FBVW-YGwhlcll`64Sd5A zK%!)r3)?G0#KcUi0BI$GAjG*Z>etD)V~;L@VN5z2T62vjIQG=~BuRXMM`{ z?2NxL7bCXxaTIsi@vs|Fe?iS2Ey{9c*YjLw(K-JDa!Mx%Vynu?l%Upt@ zPk$wa@;xz;{!!q*1u|5i9-PJJ`@vQg*gtb+YVtSSUI(*4a)i9vB>3JyJ(=-*c4EN) ziGCb%WCOqCDfmR@_PW<*mBA$?v!A0V2C#YB5|A#wp4EaMmSnY!T8=FX!d;rLY`8i% za@Q8<(W(G;%DqURi0aW8wRhLB{J;+ctWc$C<9bh^How@ckm(sK;C9EAq{4k3V2zk| zaGsgu;qJoE`F4akKA?WO@HT*y{Z~Ub1Ag}K@)y-70#SZ+r9CEDAO}UtvsDyLum0rm zj6fRiLlD?GoTY&5>S<(I)E<6X7sL6jTl8;3;m#dc>)b0-y#4G}X*i!IZ~&+3%Ip1j zTU$j&M!4&e=Jv$)5PH<*x5s-3C7i?$H#5Pgr2 z;d|%p{!-iacN`i1@VEN+@5QVEy+6Xst6xrS9&Wg>tbBl~Pi^gb_Wq7n|9Q^Eyrz-| zJP;9dJ0<=0nA3hcR%=Jwyn~=BiEb3QgsEX}bcLs@;>;tlwpuxh&eO@Vv*a{LU>=`Q; zIlmJY*+a#%thoO$V$&#xp}OR>P}D=V40ga|#!a3{6J`0zbK%7j{qPo?APj2%EhxB< znz5M(VpeOx&ZYQDuB7)$b+Fyxc>I#5aEN1DosXwp2#;hGIj0J*>vu^WuV&g9fMd46 z6EaRse&OW+AHKtqqt<`G=jT8RGNZ}V(>IpjYhmPd-D2Qt#C?Q^_vveq{DtkehXQfK z&68J#>;kAoI#4NOgLO%(U-yT6S_F?U{w`evSC{@OVYTMcF*!Lm5?fPcI(s^`1t+rI zx(V{EeDbZ!7g&X)w(HcQZh%%%iut_6Qasu{^ye4+fC*pi3c@AZrBZ4J4y4Vb>tOU8 zNN%LO>KU%`k)AAv7<bk3z5J zLYgz&CTAm(Ye1FNWbO+c4_d{aTZJD|hH&bRD@mm)<2DaMEGwZrS(7o6;i4AE` zL#0PMxL2bV${I1T=CByd?C5JTgDhXt{U2+KEHZ$$!pwo9V&>`To{^&(O@%L4zo=(L z3AKmcxN@2#eINDDbt<-{-jUv&YxvGOHgZawIoy*_*Q`5yo#v$21k~6P}rVl;>hSCs7WBs zjR1LP7qhQW!!Of8`j8Gb_*{ zBKasO_r~jfHhTSlFKRzR%dDS|_faLTbXqq|oLbzMib4|~5qCvfOA0u&ouAP-_hJk(8{pV(SPVVh&b*h& zfob=fDltI;M$Xnmql~zTBxOy3<0y1>G1C_I|Ji=^C;SIaLm}A88ecTmo-BR3rs*4r zZ40T&r2$+Vu!^bq2e5hWQbOu-F~KxdU3NI2InXV+oUbh6w|Q08yzEmV*kZ(0#edEf zG>*Jei`gNVh$=yl@xR!Yx$hC!=AKZtOCsdfr6~NMzXIfhBhf*Qfl`N}+1&^**Kym$ zsf4gKn4=;h;!@J~4d{v%v7%EoX~$;lUBC|5z?uD~yU>6XHK=ofObj6_X^f=2nSfUD z%&S)gO&-*GuMl3WWW6rrE+}0I=e+l_Ay@4IGE1h(pvcdPB6q)UL^apWtx39d%!@I{ zx(&c^y{*F)Xm9<((2F};A0&?Yx$)&yzRDg=g=tRKBQh^-$b&HpTlzxc^S##5&dSbzZnu2{ z<>p=fk#p>b2d$aB>V3cFj-HqquX}kflh^m>%w#6o*HryD@_rm9nw2~$ym4mwnCGj^ zfr2RQ7L(_HUT#FMOg;UK1t+H5Q146l^lxHj_!ERCKIt^&|F>0WRJHWo@iSx}g|0?p zZTi%==8n#wx9T5C9%Qw4Ky|2`VMKV>DS^ClaW@xrkoh&8mQWX5DokN{Ee*$waughK zyJGFQaSc-E$j!8E2i0H-x@dw?SwCP-BczVmU5B9v=~XV_ z=>3w~0t>(WTFDti4%cBsUtIL$f*pJ>^%wz(iBJ&vj8cXIf-UsQcv-)`8YD z{c>gRJE3DVi~=24tPmPLCnf-sn(Z>bq5*XO9d>o?xrsa(w@Roq9Jsvi;VdsRuDx`( z!c>lIjBJ_>se0=V{1p}ncghJqsc!+7=|u@ON#*$BdIFY+r+fU#x~&of?paeoxT3oQ zmJ;n=ze7U4#JQ9v$(+w8FKscRGA}i9AUP{8_V*>hAFgX~W0O0&&ypo|ByDs;afRKrTwWfAV$6Q;?&=50T2Evm4@K z;Vx;@p|4r0(zt{9CDLP{e*3$)JzXXVxv*Te9U&APAw`+tyx39R!K4Y$?8aT31j&ZA z$CksYlZA%M@zsQOsuBs_)W-UX9JKkdkdz1*QFnrG6wKU(ri9Tk$)!_kgXfkdAm}bK z(bw2244K6E&-!JZ+c))yE!Wz*n``qlWez?#^%isyNOwJM_K6Uw-U+-vV0f^?=0>Dq z-N0ArNBuIzTRwLcsqj=3!DhWxa-i4m%jLI}PlfF>pGtPlar&)SevVb@*!>mcH@iGwW|@o zdxYv{flWd=$d4j^`o}pNAG`EQuPTHw#L{km@=rPwd4Mm}i-S7E`1BT_LvfzZNfhY+ zR#1!CWrgj+Ell`JtZ8m}pm5u96x&I%zJx6a$Jy@ndpF;_ zz#@QZ20u9){r-s#9pJ|XN)HcUG?>nQzTwkS1wI+oh3?3tGK`kEYRR? z8y>!vm7nnXI7T@2MbuW_@w%uiX#sJ^ZtV-Cs)xFpxcfxz(<{Y1)lSur`F~H31=^`6 zI~`c3&@UQq&hqH3pYOaidVjDbBhX&|tR7a!K7Q&3v2=95Yrz0senH|WwDp9l$=0+_ zUwULR9F+eZsi^}tcYg$u-L`+E!rBytDkW@rv-H=rmnDc?%(vV|bAbf}f#Anv74HVh zeO{f){?^iz$+MZR1Jzgkr2oo$-U7V!4?S)37^}enmI3#-0(UjrlSFv;3RBp7Wy5QE z<_kmc#VE~g!BH&9rLS`lIvL68pq2R*!)^^6uNZJxj^CcrhhM3eWuDQpISn#tMD)32mOx@sn_z2oe15ZZE_~k-(c{sOa5|}B znJ#3dfc^#nYc+}FRiZ5SQJ^H?ZAHjq(Uk~JbRH3Uxr}@4V+K*uDzjoh`djHTM;eJn z_-aNpSHyf$V!Mma7TI`!OEIWx80<{qE{QoUBxO9*{DSu<;hPTkLE@XRlI15cTbOH z8Hl{i_@_8(WPa?EczAnDZ&Q%&q?_~gPd7s*sGGh}*j*<+y z;9Cwh5AoB=CIC=pFR!%hn&Ag%Y_|O1{d4GJS*7(42`o4cr$9pCU659kz~dr$B)*iQGLI<7WwfV7R#y@N^ptkqgYs#BcB zbm`~+UXRWo*yQ8PE8gf*3UpVV;1gvLA=(8h=qe<;x|xgH=wMIdab0^mv}TsIwS;pM z_ez%Mgm00RHZui%4_b(X1Fi%p6g~beCn!UkDM#vwMYtq8Z3Tupn%fDks-d^RbdSC{ zv_@NSM+wQX5gmK(ngkt?fgKS7Si0A^1^U6{{_N+RkQHV%P?&_S=1J_@AdYy0&ILJc>w*a#d&i9n4O%m6Is%iElM1^o2xU`l?8!MdgNJf1b?7p6PTt;sF z7G?q>3b-jxB(Sg7mu7>`Xl+Hovw4b|vTT7nh8u@5>Zv8>Gto{1GA$m1O(sb(nF?|XNX$Cm}!ymyarRgp;& zav>*a9>>BIy9mg%1rFen#IIFa@EcA$c5DfkO4&w)2)lIO< zRx1qv=5grOL_KRyYx+3~Sl8XO?(~61_}d|H&tZuiakg zudC)`vn<+4_Ox*u&M*5DcB`X;|9lR24=O%kAALJGC{Ci6@@d_V8Z~gII#6`u5M4F@ zXY8r(`ub*Uf3IT#djoKDpIcY~N_iV`F=r-c{a?8s!kCIpwfK;K(}x@Lb2kqiBJ{c> zn4DtzIyEJ7z)y!{)1#NS)5>8T@QrhLY^U!;QLSNALxTr8lc4j%in(An!B-!E?A6%! z;WPzu-|T}hz}Dk$d-E`Y^A8q0#Ws!VHx=bd9O)@}h~#Gg^5P+3dcTUJbS)F5;#*rjNC z1lg`9&;5_cKk!?jn>4iI7+EP zQ9(r}(&Pu_;vNckYL6YGqy>C`DuB-im;W<|#R027IIUo6k+7F&BZ+yJP#%NMZ%U{y%%Vo|ng?fmwSmU0MT0AuP*=Kq z^c*2)Ly$=Iu@&U37rXWkvR(+^#kE<2MvekR@;qa`p#BBtXVY0nkke;F0Ty#CZ5f&! zv7cMRSHl9CMJDkqebOXT;#CT>sf0S_egg;MRwN(%7+yB=AUk^5Dq8(0PgqYRFV*`L zd-0(~sIh3ZV2?o}RkvP2K*W}6vy#R49rC3er_+m}V-CNwVx`bndl^t>s1X%G^pk^7 zE2q$~4XTtE6b_kHM(_;p+*8N?(~)lY1+|SA{sO(+QT1z>o;aPL(-K=j^H0)6NR}@x zdc>~gegbdDwYbejlfJc_xJ>fH2cBDO*oJ%7t)6;yG5X5Exr7>)YxY(4g-?56^t@@7k+dqU7J-esP$Ev>s(*;jKpstJZdqlU+C#DQ%W1 ztLg58^H;~cnWo*W$y7Msh{?H4UrMfPvH2J9BZHYM-z4)x<7~>oOa3)qD8|;Dp5JZB zzG)TJ!52&M8jo*fP~<+gCLq~+E$U}=z9n7mw+2NKh?yZ1)rS}! z_|ARuWiGRg`gG21JT)BnoCd10HThp~&9hR&oluPcs}YUZNbQA|W3Gn4=R0e6D{i<~ zViQyd4pyrY$leO#*dxcij+fgKP4f=mq@;cCI_P^+%e=Jl7`{soK4lmIM(t6%lWrck zSGKWRi|F`TW_iz$cqXBnMKD#lYTTzYoiF*TJ@tft9&5~qUnGgQnsRd}a!)bOHY0Nd zbAJANyw5lkYJ)vFtIXd@njOsDi-ipn5KIfppU%E!0C@;f9-hn31Dw43VJ#Q{WXYD&WGXMM$k_a(lSNL2V@Rj}ZW?i}-z24?l zLe04g9o5czrc4xtdU);L$BPz@rMGoy2V>h2;9o^A7(C;G^#;CN^ZBN1i)arf+3{O9 zC&@wm)MAZ`hbOEv7%^Sv8t<SJB@&%~CB(1-7>!YBv*tUH-1!7}$^Q}^@) zEoX^r9#i!j*V6X8J7Ni^x$G6{nyi57kcUD&(Z zm!*GxjMcKVuOayE^rT+%fMtXanxbrU&cjCW=zo9lG5Qaall~4y*zlT*? z@%Rm-@ku3>xj+U=FdiC6=tw$)U$O~ZIJ%NFYJU}B-UAubQ2m4W#}!(1Cg2BtvB531 z5Vw3V#peE*Ze0SYN>AAQCrP!1wHjQ5@MI-)F??gxZ$*rgJoAa{f>f90lwO*gzs~t_ z0ylZru87zG+~oh2Up+H&0J1Uv<)vFA4f!Q5ObKr~E{C3z9&$4e^nn`Lf^(3JRU5Rz zlHVd87-E$t2I7|?K?Ub;^x~0ab)H+GZ9>K5(ex$YT}cb8i{k7^LgnC$srJ&v_2RKtaG?Ea+%TpXQ^j7Tqzk7i39~PrUA;!-T(7auqs6;oB81{LE*A+dU8yHft z;OP@*^|kZ+5jh3|b*f8Efa!+O%f?USf?EO~yf};(iUKn2X|DYTl$`8b_cY zco+BJ9Am+^VZ}1gcWT{`^g?sH(oSq}4Zx3|U&OD8%Hb1lbkd?xi?0K6YC|m62ZHju z?K$CtBGulJv55=k=2?x!B#;yiiQcG^%I-UIzP~K6xk z^Nb&-eEnC@@T%Zh=j@H3AU`)2^2Lu@gt-&(g!F{Pg5`gvJ+EO^bn^xC@E*;nWik~U3joQFu^i3O3MzYPO#B|H{bsC9 zy1CxV^#ekL?2>1ZHB5$DOydV46nCIE>X0_dm_jU6`yLZ8cWKmlDRJrSnDlJqbc4SB z|B-Yi{!q35|G&7gcLHC?fMudbv)9dIG|I3>3`?DUk1E!iijKim8F zf7{;pKaR9(8h_u>(mRAey2KrVv4N5*E>Mn`eI2&{{NAK|8+dGKVf(v;-4Q=l%2RX( z+=>Nb0fJD^kP0>Zue{-xH#k1Wo1}wxeoB(utqc1{(!35-kQprA z##2-iRe`BIArGKYs_uTH0HKi@zN7!0hD?4i&k+rOC>7t#wjY%=HSr*c&V-NFbD=j4 z^_=Y{6SPj+fMv9X+AIr1Zz3x`8T+ktL_9Ya0R&2i#LV6^u_FtImB7tnK6VOO;ONyG zC&K6R)J+_$Q8NZ3nMBoR_`=od$N~9q9~z~vi5Emi&Bd{5p?l>C9~(&SK67U5E>#o4 zHjpFBua-2Q$Av6Jx&^%E1v8hRnUc>#;q{rw+l5+t2}e$vJL3~P|EWO%9hLNyKmp*x z0B1dtd|<+1An$*M{Dyd{hOLMBVD!k~8M#PwK`7OYx?U0TgbX7|8D2_w8fGM5nlE{`~({$868 zDILXpevig{Qe1E$(OmP?ZNHH4VHN@+4-lv=P(0X2(MQ=|dyW4<<@g=Q;18%>eW*Kq z@#kf4SHEpOOG%!t)LjK?WLGm^YM}zc^zDA6%zm%x>AEm=WM_Bg?^=5g(7xwDo4b{+ z*V(BboxItFHNWI5MU?GW;fh~)jbam_^4QzqN#;}Yo5yqq55g%MpJmF#$IgC>f}l{A z>7A(-`$N)SOz+3Y{hZ5D{XV0tA$7hSXI3vc{C@WynSo<#p1AW>6B?J`Ux#WWv#nG; zRja;#&xMj1X%!@oH?Eg;QoV-8&zm##&PMliRa1e-$8ATCu}TX0fT0S1&8GYdl4Nh!E1hpXi}iX! z?(7Xly(&`QXOlU%h+7y2^D(2rQ4BYrAkf5`$zC)Cr334;l; z^yB2}oqbgQO7Q`zMCRVXQ_vVxgT1}otKB_cd!m}7C9Qg|TV2{j(7mh&_E%F)-O|O> z;JFSk*HhiCfsPQuCDAk!hfqXWrX=V82#|53OlwLf)ZE+7zO|UC%RarV8G6yY_nR#u zosSJ2+%CyvAX22t31;-=p!wt9wLQc**V_d5zpu+M4#QO5h<)S;=@Z%?*FZfR(-+*F zk7~;jA})5!8moeezwF#UnDFag{0WaO*AN`B1e?jC4}{n+o6$RPMK7-apvsf@eDCx} zUU&aJt(2Hi;*d-;P$zPg(TD1Fr=X!kH15s^BgkPB-Q*+5dAYTF8MI|NUM`4uZiZe7 zl&|aUHYe11q9|!43qf_k{vjm_fBT&oCl*2{3`sd5nZe?!0iU2nhmG75Qs6R_4RI4@ z5^d*|b>-ZXV|tXi*HNXyPF&aVR=jG^w3Axsy3Pd+Q84nnO+Qh(vQy>dsu9;s&(ee*Z`Gr7F!Jwn@TZK`Pm2g;-7je2c~X}GEY&$o%nqjCuDA> zIP*12@GKoan+B;Op?G4W$x?r!b$HQHh96B(4)@tyGzmgCfoIs^Y@kdkk$DQfLHvXy zb}xwg&jVD@nlCOtwTj8NQf-7PjB|3FV$p8ZwxIF)~nHB zLEwxb;zZ1Qh*r<~6cJN>*8wT;=2^bvm3k$ENI{1=U#bty!#Mskvhi*diJZ z2b9Hs+IXjB^v%&HQm;(04db;{LWi9r_s^oSD71!*z-@r#g7=K)3@`FyPrySOYoVia z`Y*MXrEYx#Tl2x(sF2D_J9w-kNzr+_n3YFiu)1XU4AOIZb$3qI0Vjz63<2?D?H zv}m5Y(fuPTMPer8f%+}lB559&jPImzSoa%cz68@`iZ|9)fyRn$wzT$RE;Qb2Pzn|^gdiQmsjpNCX+J2Qw zf76}}_N^=Day?0Ms|AEFi6a{QTei(s3uy=6Er zn3qJC+-D$Pj+^wvTdX`(OcRtj+U#0g97^N1NX?%Ezt&uP&AkYb{JE?k@X}cZ-&G6p z!HHjPo}j4T#}rC$$&82BNN|0v@0LWczC9!m`_CJ{U>0E`GCpg0)^T$!a-dU-dk1Qha3c5e zlP~Cyw60av_5Y)Q`7;`!bf8--~4UVT?On6C9r|(E_NRH0@1S@S^z( z>?(AEQ1TE$1=(6)|Ap6RnJwPL_fngGaS|`=F+xkPkgCnV@_9=c5GBHZw$w&<^h$A@B%*HPJ`0*5kYW=8EbPJx*)3oN*p|9Q7GesN#XVZ(nPgj(O^ z)pUAcxshilKXo_-M}3K&?W!#|zZ+8(J=*tlEZ}uD)^hdX)a|-+iBZR&Gvd6+zBxGj-o4?3sXf(eI7Ma6dR%{myZad}TC; zt$XKU^xHe=X-3sszk7GeWeuMppI?kz=*jk9Jh#X54Eucc6Jw+KSM@nb8wk~hpmPbK zx!PEH@p9x<_+vq-r964Fl4!Wy8nhx3Y#u_(;9D{RzXNUQ2I>a zqWtuk<_7Gd;Ueeh4V(t6H-~f0joWcDnKmB_)kElFH3D>sf|R7mVD7Tv7uP{YuTp8D zua=E6XCu~BaDW)XMP3R+|~~NiCmQ+#XW_^2Y}ggvYuiiGJh$bz#q&V)+&`~)5X!&U}A3hH#2P-v3i#GnB1o!ky(QkIPk*1RWfrV zDN&fa9PNQAvKy=4io_ENs~+-3&!ja%Csv|;gz4%?^5=IN5tF>}3s^dh=<5m&kUY&H zaFXddizM>iO5~G;O}5AnIcYq-aPZi&G^oLjXh9otr?PB`QMN4hD>eQTq4%vq%!|z_^lRFGv)KX+Y!;-qHU#x zd%Yuwk}NM1zPpS*4piWx6*0RB{51yWzgsYO?mqdv?N$6jd58F|eCgc&g@5Lh%-L;k zW2RT&@Dx5TU?ADB3UBzqNvDAMr#ind>g|1aCx8%seur=AtP}T)gtDgTA z6jNbeD7!uN$luYsi>j61{Yiz~1jZPhm7ttH_O&I!35m3nlr9lOW+*6?>)3uW>-{b# ziDbzh3^cQQj3<@QA~VL7lN8yrD~IymsRBO$Q}4n0gS@-DDS03epr%IiM`&Ee88k;L zJw)8fV0|%_)ZCUuF5qO3ud7y_ndPa2U4vJKrx-BW0^W}mPza;#?A=QG4p_^J`JYou zheAFViQPUk1gpD+ZVt=&dl!FC#h9eqOg6E{X-GWC=y$S1c{R4?i{U19)N@@_6LXS8 zFKi0m>BLDP5L&UBe+PuC))n=z3mr`Po86Z>&x53;CXflTo_G^F>GM|G3Eo9yMHRRG zeHo6_AbfcUZ(FgA?wbB!CKLUB0qASqSLPY`l_l`B7OXruqoJV=*4^akiwB^uv&_otXs(ufCxwshnonEI z?96SI6jxyX%Jc~@P#JYsNE130BqL$QJY||)C5>0{>v4kT_%hU%|4vDo@ z^$fz7BkX&Jq1~@pE@Ry%h$iYl*oiDOdq@3|_AIu7*60{(KqD4Fle(Nd+D(u&xpugi zAx}4Pcbe2Ng9y~Y)dW@*1vRPEX; zEev8`iTGiA!%`*=tLVD;|Ib}Xh06RM&ZWhjb|dk&pv*YxyN0CW*mlXjlo@R&!rjhA zFQee^UPaG?}&s{`BjwR%KV6ORsZy6(k1J6@Y1$*2`zIwon@@(_b+@lr`}_m zH^-;LmpXm~9zYu-jxN*6ZLD$LrTd9Sk|f=d&1V}cJS3{uO>`H}3ml(I<$kc09S(oj zEf1}?q3bW#!1YZ1?yP=@eRdi5G${|z3-guTt)Lq}cm6vbQY7-FyPJZ6tG^EZMI|LkuNurG*?D1v~UnM;9|c!KPTOU9ko^ zd!Rv5AEqplUzRfMyb(4z$G>I@PTd$}SFV8{6Tluq)BC&Ki|I#191ff=yjj@;YSSK2w?c^o1t1g0OhYe^v z^wgR;2s4zCC@RAM3mwzmOK77kBRdaqmWW=d(@RMf<^sjXbLD>0Y#O056`ZD}Hn$1c zI(IR*(_=mr&|_1ygp}As=a$z3^pX;z4e~O_I^X*1A#S^{nZ8iaCV4vb;ppNx1v<2- zy^L6m7bU>ZxpUqxB#|dnS(Z>AUvT6FCiHq+}9g)_*t<6l@ZfrkoR|; zfRHX%l2FLE$%jW;?)l*DT1|JVcx;Cq#vd*mEv682q*xU!^a%-}VmMXdJcTb83r_ur zd2BxqzW^Xxz5!lqr~)lyH|~-r?V*ocTx@=9VVTXV5f3${MH(>M{?vr|;|pp+-7Ndb z9q6>X`$?!MmmElj9XgQDsB+9!@ut`MXE;n#hc+)i$E+oi1+X&*nqtm0u!z zbR5m;(zSDZ86P@lMCuVf(yJQI53V1kI?|9qiZ(Zcl#*xiJ$riGu4Zqat=5@Ea6 z4uSCxB_-V02w9Gddo~cZmNU;n)eyJzKr0TM5@mNbSW}|Fv;DF@W3$0-V*Yia`OdWByO5`)vQ1r zh=vX7V?hWxsa;ZRX{gFbAxs-5Z(|NZ?rZtE?0;m~CRBWwT53BEr%1U!;^(^k#ooyZ zblZjZbNFDh%5%`J#_hqO0WKOCaxkSs10SdSicuw=hNy+*wLxNEi@IU2Y4&k(w|ppH zC}OnYo^{*8#jC2IdwP8MGUlQwUi)1%XS)+zqD;ghx$uLTnArjLHX9WhQMWNRx<_t^ zFyV7ejr&4$;i2%{^nkW3O_iE{$LCT6@|931*S-``u}v9Ym`~M1Db@vd-~(QiAyV{A z8RaiF-8FXQEG_%0Zdda}JsBKXC8=jrYE)ls>(qr3M0uk|9e?#q`?q_zP-->cobm=t?kOf0Y?ZshN|BJ^he6 zwJvh=lgoBRF>lwcmDRAw|Ht}+AEr4)y`;bYnP2zISG9KhgZ5mNx>zJ{UTv&w&<@-> zXKZV~C8W~(@#4`lI+*3i0LyvHynMqxyvrZ3;j6wbz0z}e4lAGBRA^VZZGDX-jad#B zu-EvgacX_i{JsN9`drj?=&C28qX}qai=PYFdjaHW!rwa2`PY?av2xo0R&s{Qw*(oN zknqr6_PeD-`b+54Mk@6K>Ns!Q*u>19V(=r}O)koT4NDlx*tI5VqCQBGOWMYKEe@ax zJYLCi6-RE9kP0-62tTll`3m*Y|qoZ1(?4b%G{2cXyP~aBu6wk6{bClb^PB=Fj*APXZoxMid6?J z2KT$T#tb!C(sGu{aA2+yU-d#({w4Qfi=bnc*$ZIQ+GmMH+I{Q z>r}RZj?IO>fv62EK6Cj5|4PiaHc*x$G(N6`=}RM;K& zTQ{4t#OB;8PFMTUx#F(FC!v@>eH@K-z(#c*sFC+GMXSqi7;k#{dG@tCUaB5KiY`a< zQd>T}-fTnezmIJ43Q9`of7bX9a}(ip{D03H;?YfStJc!Gkon?cQq!K+`1~xUE;)T4 zi~l3xcU2Nb3ib00zNmkzJ8)AW*)>-UF||DXmFS7}AS}CkKm#Ti?w0se!F{EzrXI3M zRW^B~YD%0}f zu+m9+Wi|vamxcDYpcL_chmyD&@Cbyy5Z_-3PReeCCTuGX_%CuQRQa8mVX*5#SehCD zg~Ydjqo7&`Nusv&GE-y;iL%pa*7tDW69Lt0W%`f7LDCA?FGX_dds zPR2q4$eqkbTOAs35xlxZ0AqZA~d#ZEVLMHQO2R6F(4-zvF$LA9T*U zzLL1@(hvLymGb|6>;^l&4;#2K_>OEd7hq%;XUuu?yQ_f3KB+3WQ^RTW_IG(ONLFA5 zwEz1nf2^(T)Ul66o6??>+&3P4OjamgXgzyb4yOcW=GWQr)M~eGTc|avu~HAe=HcN| zk$QpT^tBdsUaPa~`9eqMe)gUmb*1G7IhEIA*K7SdJWHb4y~>uE?cR9QZO9g=lk;TB zKwB{#0Goq-E( z?FT>@mC(@6e%1e|HuJ{-=TaUI2Y&0QVWH7?wK6PhOPs8rn?sx(k5DrFRRwCsw%@=a^NItg*Yy(I*T!c4tnS%f@dGQlSr?@?mL}m zmfs$`QB$!nf=Q58?SQ;Z;D66-7&guVEhdb|cjf<$YnhU1A~S}8n8jFqx=Gtcv6t8J z$NUW1IbpTV3*4T&xeYqlVtj@G)a0gM4F}5AHs@S$;!w+2*57r`=QbCbjTy zN5>>rT*xqbyG+cO>r?*fwnf3ETG4&xVob3WCo4jV4j z$?e;(LARGeHc-MWFP$1vM`o=leQXl>K_hB4m$n8zVvX)41bgL4w#-L9-yVcL@};vT zz{(AZp<5DcPQnj9eGzsyz(wV7I1PcJsei0>aTL~}VV~r=!$qTedpQ}{YYo;vmE!#+ zP}Dc=$5MXp*%5tN;5I(EUq)MkHw@Db=^@+44(V!JLMzJ@(;F$5$f#wCv?`@tbWs%- zv3;$a)i#IeIr3!UWj(>Dbj(*`p)x_LHg$LF{!P{cmPGPrtH8x? z)@)lec81K`X@4lT&8Sc}?afjEiG`gvE+OuEL$+w3XJOoSG(lFue>uxmOJ&6R3NSpR z$$dnIW9Ms!uwJVg(N0G+32c~V;|}#**yX~ZtJ2I`GQ%!bN@Zar?4c+ut`Tz$+TM89 z@>AtGqZ73qZe5b&Z{9K+OR<)-+DC-f;{~reJs7+uH!W=E-2F$~+3{;MKvfb94H!2u z5Sqw)u!+G<#V=hJXwlVAxsnyBQcK)jFWExEsE@M9(vu~(Yq7=8-vzT-K{+o?H-de| z?tk;2Y#Mq6MxdENr+Z#B<2+9O#^nM`IXuPgki;AE-R}T}XXntnvo4{2%9_s;vcYcS zTRj$N9>p&nRqLKGFh|I`(0hoVi?g)cLxeg10LalQGp*YkU`*dB|YbV2Ow_^23}_&I75-AQE+kZ)=| zAC71*fY4GM(S6+Vp+_Yq@R<N27H1BZX>0&qvu;7sl(&z(x!GT{1{mNSgI5I?8Dm zYGicLpgq!ZE#oI9zXwWSa8tjBw`9B-=iou_lDol#{g9%8pt_MLa7WM~= zI|<6TOTk~*Y8$?a9Zr!d82`02Mx%=2`5;az{ZB4(SX_`R+2Y>6{?Y!p%S`C5RJrha zV`NUXc~4A+CqIkaCl5*b!Yb+hV+$RV1?6)bk&H8*wZuY>}b*lY{zB+uAJT_E#fU-t0 zgvh5*&}!^D%6v8@J_HIu9gn064EqsuK=SiZ0%>BGIh=HO`w8gQ3^RJi-l@rNn6)~o z<+}uL{#l*?=oyqT?skEB{y`CDsY(l9WUui8JARY-48HYs0=z^fDP%!S8*N=2SE}xg ze(`Ov*^k7ykI86(6o`s22n4fxF{jLfu}2e3qGYEXx=D9YJ{<4d@{~vIrmY|X z*nvHw5HIqZ*!*x1?Jm=jsR{lNhsI=%A$}%En0U{uPbr>X<`Df)SuKB#uDcue?pd-VqWx*u=zoghfLHysXKbQ3+ZBcHH=>e` z2BUvY9bkIWbDoqap4TiXzESvAL<|0MBo!$)+S-3je@Q9ksxTF#zR92SP9vK< z_}o81F8Sw_=yh|@vrGG@G*6qxon_DC)hpO}QoDUVUY~zy^C}Z$-4f639|oAzXolog z?w~urw2E|d;t)T3H+DzxEvAelkI;xi1I)ce?2IXu)7aK&?G!41ohI3^ht5b6^-oLH z&c~BMso2R7NH2QR83H&^q5_1OGUaSTWjxip@DO``3e*+hBsR1$rthQ~Bnv4SiOw$* z*!j=Mn_&;(bQ)<#1x=M=j+Cs;0=`#37pObyOhLl21DOs6K;s@}b{*}z+0h95NX0;e z<=11%)=w1m!hV&r90gCVvaonGmQUX&I?~Ufi+;@`3=)gKs|9;Y0HwguJYj+deRuGJ z$PctaPailYip}>qn5EjQy&ksLK+j5fE?~F@i7pv>17NuVeG0e?Qg0R(|Hh)G(*8ij zEU+9FH4kQhHPiV?Xq-4G1G_k=Bmi6#iC5vm9+Jirkw&0Dg-0yx`8zzO%W0|6%KdEP@kS%2Rg%sCnFK*f}<;Ru7_}KLEOYxoRFau>|O0sN> zh}eN9vU@2(GTX7<02|zrG{1XgzF2j-*@Ci1?Iig@mh_l;|4i_@B<(Lsd|jBhJ7JdB zX=i(F=X4T0ZWbaH&=VakqqYVE!(?K zuZCAe;%-DYNTWrV{m9fIz9}RfHGq%%=4@jpaiblFAwlk zjd4s4J#0G1bJoaV2L=l>yA;qotatyV0+$?KU@thOnl9~xJjr3_DzL6R0gwEsCYvv9 zfHc+cA!j0}Cz>Ri!yDRT{KqrTV^YC{i9u1MR$-*y3dZZX_SbA(MV1_C>=pxQ)lA0+ zPU}s$GqLUsZev^4f-7)GeJOhbU9~g08GZpltz$doP!(~uZ2I|OEQn7;g3&C6W9akA zx!q_n4RGJg;c~^gH<*{<;oMfUlIieS#G6*dpk~8CPK8gn(gp!$hUUdLO8trZ-ue`U${WV#&cF}PY zGM;`XfM|0{Y8rRzHUh1WJ?I82Kx7_+G*MZ0`|xIE*&!*w&0COZ7agUB^0UEy(G(QB zLUPdqVSJa!UuX#lAo(+5Uo1tWqesaM4T)d#;Jkt+Ln6QhLvoU`kBY_K30=n^Pa@=p#ce@8{d=<%t)S{m8KiKEbe^q#WavF2*m zN}j_(om2CCF2K5a+;u}1#Gelb$v@}G|2>y6%yXHa%e;RGmWYkrPglheE{!tFihYml zs@=TDlL01mmCUL#N zD}mD-chIoAwimianV^;tPpQgK>ByM}^7dhfMZrE0VKQ-Q6wF;SKtIC1sc5SO4bnG2 zt8grp!zM&*QBNQ&r6g4W-$}5ZKB0>vtdF?h1BIhM#q5o1_@t(2(tY zP&OdH0WNGqtf@C~p3|Q<*3Yt*#;$=)XjvE@hFwOUhy_>3o}tWLluy6raM>;?BU{F^~K zq4}Jp24V&mR>XGw8JvJ!Iue0L^fEhJCP8@Mhi~i2(FJxth5 zYlCceeGMFb@gQBL^<(tHkW2U`V_hIEP*E86F@5&4R^kk@^MP|GIoA1jp{8Navs>iqgU05Q4l6sMmXAKFsmbtj z*}pH1SeNGKw4+0Q2-ED@Nu;C^p7qfOs~H3?qD;!Yz!v5yPu7;?a`0XAl1jMY2DZyq zGVnMM;$A@ylclcR!Y*h6oRd2sO?}VdM6MaZOHRhu8#&A`I*0~^WlJXPs0_=&cF7V3 z?g{0$K##KLLk6*SRj@}^@T!nSe*Va}xF*9{Jp|JW>9uXQa{z*nq z_P1FZ^IHICILHHgv34jS)IzY#Re0>v0Y$aKV)4!vMTXoTm|Kso!=aKEVxNta4!G9_ zrvTW+p7h=(Flr>5{1*fsECU+})j>>cIqF}meE?#3GERV!FS_8a2LCp6f((|<#}@@* zHGx=xV<%Wc=AMwOo%+T$rUB0Zp7B1wm8Ls@RDDEMm+rzoWm`({w@2E<*IoF&@U-qa zz=se5`mW`#Ji}N35Q$u2Zb(8@T6gzVL!c|kx{0JIVoG->wM|y>pSyqufCtZF|9FP%!}h*I-M zLVX-mzC?msA&gplMq2jydt=+_qPO4QzYt!H<;Rr)34TO+#TfT3n%|S8geCrtd%Tws*qu^W1%6FgrT7>PNZr_JpXeCY%TO^#^2>!s` z^IH?)ZFb1kzu4oma6%w+nQGuKA{Az5XhA30_G`d!*iJymu4`ikjn^J0aa-vV>9XY9 z!ee&uM@l%W1kx%@0^b&PJ}-ERY3XNSHFD5;C242-=sYP_UJo0u^5kPm0o2gUUHA)G zmYf}N7wPL-S15kDhTq;nLM})=Eg)nW3tyna(5O1!>>{!?5&Bn(PljMx%i7rsGDs&| z7Jz_EzCeAGd5{48F=p%yaZLq(+Wkp&MKQx|;Wc|e6|71Z_;5nRP7JciADQ-tl|pO4(c&*=!Qhw#0)&a6_o5Up}Z`yF6=bk z33U{i4*A4&Lb)qgi-*nsMl?Ub0v!1VuSuCW51DZ`5sDs@AJ{=ryq4MKdaz0N(u zB79AXZyS5z(A1#Q?x~9%@O6QkAC5Lo6jkW(uV_jW>uWE~uYsVr*De$f#@`Cn#$|RJ zX$(7@HRxG;`vy3)P;2%?5@H!WpnSYVvbSL7hL0REuLm7~@NX|wnxWpt*f3r{(_@Ra zCE=?y@_eB=&PO^rdizmq-Mm|{X!Qc;&9lSswgGnXh{SOt>nb)k_(*a7;tA;22hs~}~?kPyd8vYg#nQ_GJr~yKgx>m&*zyekx-|d;&)S-a6Vw?4)Gn|f9y*_)0 zT@)PYG!jsZZU*V4>{HRpy@20xv`_SCj{)vw5U=wi`{!M zqqm6h{qd4q1V4ub)k!lWVyJ82ELn_R1xMUdG^uZ5-@>$~<)T(_zv6rl{@rC#&RcMB z-h%jffxNPU1ziDX2v-e58|k6VEz|A$aUZyUk;ub>^@5Bdbc%_&_{NNn6NJx7lduP! zE9!=KeTbdV>Y~^6VKbKZA#T84@{4NRaWS9IZdR6TZjmlzoCJ4f_D*AWjLfkg_$(Vz zocB>wSiG%Zf-93H>}>DtH6j1BVeg&5mdhL!32X6Eak}Go&xZKVvd3esM#5fsL=D)S z84O!lfqhdd@0Bkl)G6a?wGJqxh$gE}7kn7@IbFOqrtN^CP2ZlMN||ZeWUu_bZMHZ&{KEZL@v z+gsYt%I}wJ*qG72R@(A3t34S0WkAo-j&?jsJDkcncBn*&QCBZ2J>~LFxOrnmy7APa z&!wIVSM-;t0r(3(A|{n=*@*VFof76Lif}h=LoY{0e9W`&sSYR>88=$mO3d59z$;nS z7CnOfG@egyhyz-STlo%a@+F^wEjK?VMJ*zTBf)jDb_8=9(Odc*D9eVc7m1f!2^@si zc1p6$aO;pt##a6XOKKAC@~S}A;)EVx!bws`(nmS#VlnC^(XGNMmwGpIk)e9}kE#75 zKTGf>>27P*n{N!nbFt$5XZU7D1hP!27-F{M@HtfC%HIkSDar41($Ih;HBF zfk-NAJt)J;y()3tNg-EIN#~w?DO>xLCl32Pcak2-!h0y;v5RR%o=6 z;p202bJ*19j4boF?XM?rZH-u2NlZIDb0Rw?t+=BsE~U@;geO~z{MYln1h!_ zUG3=j^kUjQb+uf=lK1R8DTh$H*kRB59_Z$LVcEVkK3)m7lkUJ5Qhix-t z1TMNUM%=bwu#8}JIp>ma_u2RU*o}$7cJ? zvdL{!f?om~;FS%%Y<*2Us9Ki>;MPL!sx?6GI!dUJ8GVTKor;|X}9*#WAnL+iwNfcw)uNEhRo4kF0OkvHoX zzlGJj5@~+JcD87LI})I46&I=Vd~aLBnQI@+a(ge(100G@K2ot!d_Di^l+efYFmzLG zVr8gGRQ{19gu`rGMBc`3I$87Els8#WDO0$^uDtx~Sr_Vo*1MCn?FpK&ly2MGx95xg zjvb0m!S2em25~rQdxVPT+IF72dp`n^-fV5kI@j_n%@8y3HomERBiv_DS*GXfl7?5O zo}={yR-@Ax?0L)6@emsuW@9eyNA|tY2Vq3N_0k9uyJh-iK6dSrWT!6{QYkVmnGCrN z8JeTd@bV-gC)6uwoyBlc-uziC;WgAUi>u_^D(lxuMpgOGmqE^!^57F`C=ru7AN7O` zO&u@U-U)7$_&hM9ryr~-CW~8}S5weSF}nz=cf;Cw>}+e_%ix*}`Vz~LPXB;ut$)v^ zW6F~p6#DeWEIoMfC)$v1wV$1Ck`Bb!=NDtqe9BrdnV%G~P)N2Qk z8F6e^Ted6{4TD7KEc^W+okZUcZUJy~&pS?+`I}ZK65{Q-@M4~Srx;6I0J01PU&Gf=-@Zk<3We01vrh#ySy*O0?grt6-I(uD5^ zjDKUjcQf|M=T>1_y@K08>by}iY^sXK0tg}_1;l*tn2JEbZqT$xX_+Q6uy29RVVSil49-* zHd~{fM0`R!REQ2P;72l(8uMLdsJ@M<`)Bcqvb%KTEzIY|U}NM+8PiJBS$7?p2nnj# zDtzdi#U#fJp0;8wcCT9l5SEvr3o<1EypCUT; zOGHxhp*~Ad43xMWXuNq6(b8_Hth71G2sOWm+83QtlEknv8I$V2zRX`VeBmq5V9OE> zUtIRymfY_XBys!fjtq*7R-pxy?4;($&qxn^eRji&?Y!>!oleM?f3Pk!ljl>|^@)N? z$qAWBp2@+TJ@1GbY%{vEhoL|!iI^}I1-J&-o1wjQ{;E8Mrp<1|kinw*m9y7M_#=yt`j}8Axp_0nNy$Hc5P7XI6C3ZysKa5|zeY zp%yN#m<~xo(Dow2{_~IRLd54KK2`)zd+@JlMsFFJmOjIytjD6=rCNB-_Dr^B@Kr2x zH|nQvGU7wMg=t-ZLWi-OhuFEf-7#TNqEP140fUS-YCzf65I=m4UReq}-GK$cu zIrhmu?_qmEyC8CTN^tCSUJk7-;yzpZ!t2)WMlRKlJQUf3Nk)v` zcI?5S(Tw|AgNnJbC7P$9V7QB$c~Z+ZrszQG^346o>m}v0bCSgn08Hr=77fS|{WP%0 zg^SJYQ9>^{$Z#I#xcXa!-pgT=heFmV6yUM!qmq3~_;krZ(Xmy**LSB~mSMPKZg1** zRPE4kLu3%kFG7zzSjT6&aS9!QamVEo$N-te;G57qZ$3jm;d~=-kJ%kZ!pAp=2A&W9 zx^IafM^)KhnIGtDhm|yHQzaW-5vr>}r(`fydt&xB*hNI_p|Ae@n`Q7=gbGLj?&ZA6 zjsehd*#eBcF}!O4uE1sKwV|N3SCmexEyZgi%1zeAPfS zBcLAR{L7VeRE|VWR>q>*Lt3#(I@p5+EtP7yuo123!aY1A$Di_8aKeWda|PeNASDZ{ zyxH0$ZU(5M*0n5L*W;(0`MreR%d0V$OrHtces}I(_a-7D%PpR}I5%BxV6LS+)^;6d zipLL+MUTH7wpmEln`;|%>m2s!Drx4uIqCB_t(hlE&5rzkb)8pS6KfZ*-$^4tAoO0M z*p((qQ89xkuvG*V5dk4sQCbiwiZBx_AQo`jP}nBw-hu@wQl%s!3RXaoB47fj6zMgP zGH1SXcP`EqSNU->v)*^DS^wwxUA>DhA5U{USsJnb_bSx*U&C`KC%^saCdIPr z%^hV9A>IC=ua>6-u6%_OBD$5mhBNg2=8;Ar;y;%?ET8y(K?SFQ!8}Q_Yjk@2t-n=R zRQX|LIxe1n1G7#XNP-L-g=bFG;1otpvdo!=zBSH&U-Jn0h7Sr!uyT9=S=`K~Y&ahZ zHe-P+>VSg6XB;-Y<4skY{OdsrBPfWf_7q#Mv4LY&JSS0DSnxFOQlPz^I=e?pd zegbLsSaF(lgq(iUAD1ftsox`9erhGiBX3V` zbvEbiqf|sOIN#L99_^$rQ-BnrSj>jTm?~0c zi%rmI#L}wK-{!1xqllsQn2qZ@YIa5Jm1w&h5**NY_K>*HVcDtjx18U?d!I7xcT0&y zuaZwC)Oy!9@xvT0FXQaKA8P!i-hAE{(%$x|(F!2-pE3HRgdU8&ZQ%zI>zAP4ruK!+ z2}wbL%;%5bsTWG{4~hUrnsSj8!q@`A#V4e!>=_2HeGDINqXY{ejkvb!0rIo{>N}W) z`)f7UfK|=upp+=O0E~%^?a27|9O}P*h~nI9Pk6s_Mr)q|ho50mbx6*20Vb{O$SG4} z+6GE4IH!ysoYj8`@Ww6^6DY^+GWYurfR)LAZFcfvh0Bg=s*;PI5d9uw0y6IjSh`81 zc^g-Q1Y5C7wL!{3aMFjZFbM%EJxuOML}{cN2HZ?uJ&*9@@p>YkI!MH31?K~wJtFre zE!HLZjeAE`AyxUq0>E6v@DzC2LysO93vmAf3oRrwXo_0hrlGTkjbK&EcY0Ab-=LdV zo3=#AJU~M~g#XJ!jBso}m~#o-LR`p#_Y>XzK$iJ^#DX~-h|PI6d-e*bkqg&1yKaJz zd4JrPMip^8r?y>VPB|wfL^H1_!5hIl+0(mx5)9tK0t1q$lIb7}i6zi3*4L>*3kMSx zv10!?|G-yN4&b|1giSv`*rV5GO9w&swa|8r#^v?{ra;yl66vwf9#pR76^_{*z?LQs zU6a)Gd6ehqDy*M`Ca;G5%Ly+1Q~T~F!bq}_zIb<>=(J%ZnBc|-Qk z&XF3O23DZu^HSQnO%Tk+fxYbf3z7rTHj$d2)v^!sqT*B!?$!^?aLA|mGlxtj@5l^- z6B7kF0IQ2-o~uAwph{#{UKrPn1=%)PMdcUDq2hM@)T51q?Y-lBYrQz zqmN_;%+WkePlLQh%eM$nbp`n6O9K)Ohg7SQQZ&&^r^03Q=gbz6A$v;qnZE(UaqXu^h52{Lml%kH6`S zp+m>QSaA`SN9GjHa*n^?+xkLE8yRk%C8m3@i%w`P_1T$dUJOOA7{U2f`ng^IE3Fb? zY-_^(k}>3b*l2mq-X1J^gAw%>GUw26Lz$S6y|R$K78E+oelF zJCclZX-M@aNzt!L{jFNpoKoCB>%x^rbPJ{BsaKTvdL5ii`pSpvEKAu;MyWvm@^LFe zz2S${gER%^|&DU|cBRPY$1THg)cQ*sEuP2*qPa#B_J-$c$ z_&p|EsLt_QXn?K&SE8ORhFhdvYX%8sFw8c;xerrM0`EBjl@~5*<=|1r1PES(hDq|C zrotq7FAc@{>Bj!r#Ym(oFjniI=le?ST+O8F3cT3I>*jAudBB^X6bt81)RCEZ*N_3) zrL&PO+&9F^eBCSHgqnbYdv#L$fGTSXOHawjY6&dNm(m3#-0HWD{IhBb{Ug@(rb(cN z13&l+-x_ZqGsEyaEp|VLYE;7!SQydbmhtTQpR5Egb%?U!O+b;R_LiVApp z{axe6hkMXM2pt140q^jGzFcz6R9{~2FfUwZDfG!a(5!QO>&L#Do^8SXTi%|}dY^ps zzo79FIM^`u*!Yf$@1rL#J*nR9K9_7x$X%Nhu{lIRxMA*zWNg~QzSc4Z);F}Nb_N`nZRUANGHg(8vbYB1d z8O`s?w#Ml(r5Etlob`>6>Vhi9P|o?nKM3%f1he^HX2L0Aw?`EAaRJIh>W+*EOXmDq zu%(A2X=WhmZbzOmq(#tME%RO^avLY;9QeR@D;CYRX2)prE|VHRVn#nDO={pRe%OQG z_>C2>kCc2WzUjc8;Ip912d|>Hi!tFrXHYf3cO8_CJpHs$Q&ymdE|$8+PN~5TB(yCe zSUzO3k(SYtiMU8^ZvgK}dXulv^6@ki-jeh!AiSN1&ik+E1%)PTRW9p2aT9}HJ0d!Y|8A}b$fufxS99=0c z1hOab#7i4ouLTJh*J?0yC$`U=QGn4)&p~(7VJniT2Z?yP1jXt4=LjqQF!AJ83BDf^ zqL@lvu>rG{`0P6<`hVc|M~-4X9CXr`cSfs(K&g!08}r; z^-`yz{o9yDc+>{oBf5HsKphJl204XT`Jb!?tUpT{5#b|uvtEgL_ubq^4Zd{IA&R)_ z^f%=XtGj&P=$w0d{Pf_DxcQf#hq(s|p1aAi1J92Z+e1sd*q5T1k(1exwq5xx+YFJQ z!{tXWFl=ixtD-G>GbR41dsLNHG5XE@J3dW6`fe0==&02^OUWyv!Lp$KlNr`>f^pzm zgPSW&>BW}&UB;Y{88rU25&K3H*Q0V%z7`UTdGfIZF7SEG_a!J)QOCM{+?P-DHRiqk z=i~yMW(Z$xvbGcKI)vS31NH%2qB*9k%~|zl^qo9=>yV^RUypKVDMdW`^S^!Im5RUy zyE}obnvi?!+k>wMtvX*H_^*+w9)si7c1aJA!IQqUeFp)VV8JpH6$I1r^}xwLc}~b6 zPrx)Fj@4k-K9L!I2~oWsI0z;&1YG%;X(p%EypTBhi4*=v-s2FjUdZo=r9@vpV5iUy%y5{_8c z4_nYamTVx{wz)G(0aW)bBvRhT03XG&Xd}@=9u}BCEU!|I)MIE##do_10y2&vOkV(d zyo5YQaQ4Ivu}8kZw8_;=z5W74vW@~i?-ZFHrW6?)_16Uv7mBnRR4d zbBL-3PayYC0ndJgKG=gs`HoZ0@CNY^4<-<93`0N1d%CyK#||3GTi^V~qT}t+bBRM@ zr5E!LgW(jYa%2Igp)-Wbj67B1-Gb~>Y13{;j!E#)LL$EK6x-L(_d2SdAMIVe;C{SL zQLY-p#x1~g&BVvHaQ^0PK-==^P;ixfkqod4V zg4$XX8ry5S`_zWXw3UFcW)1{1;7RG%qi58te(m9S69s>BfX5#rW{%_%P2tv8&C3{p$W#IoW`Z!5So1HLc*68;Rf!99MC1rE?h2xQ0V>S ztRf?QGtqYiVSoW&myJF?4L3k)1g)iCFEh-|hR5f|696t+cd(uke_h#tr-~fYRi!GVs!X(Fjk6P#g ztGD4Fu)&s5D!)ujr*XTOE|emREG@R{}U}P;aAx783A9( zUb@ohPb}VJg@4RXm;!`P$gMj4_oNe3M>GJiTTWRaEM8 z2+;H<>}P|*Qaq-7Qc^cpYrEb|ja-??Uejhc%81z(zm3axC_zzo4w?8$5{8r0`L;zmwD@>h5BmIm;jv`9qTJ*S;+9}mPQ2S&BjuU^6o%O+k z86Hl?ysIS7Adep4K7!we-zFKW1wn@jRtWlgV-!w6o*n#TVoNb{T;fq8Rg>y|k_0Z* zM(ZKA${LdY-c88r#t!708jB6tuNh12))EjoE>rYBpRh6y2<=o9P0AcUL!PZ(B=nN( znjR_tl~aNRg=#cyS=eVifu*M=d?%zE^>~BG{l3^I1K3M3=d)d(n-S0T0_6CREU3rm z@yXMXKmib!%a=EM*b*DvnH@uB8wDmQr2bB1THjk+^n5Nw0Yp|H9jETegnLlF(;qeX zHP#|yxOarY9RM0v+j7*m|Y@XqU%gSvSG~$!G z4m->E9)38K@j?$ytHIVqndo`eAe`3A93Y} zAHE)y6*QxchW75DGim1Y%aS8Fg!>uHZ)efGJ0nSUAM?IdCJs00cCP3^r3uGUj}Dw! zcEny%bzxHp=~T3rwQe$XYlXvmzHUcKxZ1jAEV*G~TxeJ%Y9@ zp0Fu4KAOcbqPejSI_ZZUONki#AVyWj^iuUjYKIP_kI&9X0+p<~?_^7Mzv3?}LOf*I z>Zn%-_Nfzj{}7y@!sn4*s!s`ij^}H5{*)bVG0h4*oL$_=oNkc)#w(_$CMdIkRB)&MXdNJN>ko2o6g4EIgu4v7*K&Y&ehw=1fe;aU=u0`2iFnC4-?r zoPanf;9q*%so*)&KlV5R#YZgM{TljBVm0#9C4D@8{BcQxKhS(SKYF!FwznKvK4ae9 zP!8N}1UG!Ki)D5zp?4uvLeW+09!T#F67tpZxIAN6cwHW`!ip8FoSx4w6LYIinv0^1 z$-yNu(awt)PU}m41U70gbG&O#|Vp-j}Y8}k{DnKmL$TXbTlNo~+Ys|kV!~K}-P}o~?$q6N&pO}sboOVd+ zyomMRcY+#`VNZN=@ZRuV9>2A`O88yAGDCQ~w?Tc)SoBw?vCCnyX$DLOiPAcg;|!kt z=};@HzMH7~4F3cq9d5*DBUoysG}u4Ir)&IhWu4=7?Wq4=T8zHl^x}{^xcz%HG;d=4 z#n$O}zI?r3!jpzs-<{9fc~lSnFC22_=DzK1`_{%UtB43c*1=%^X5GKM-ul4<{$-6{ zO)(us)rNC;z)vYm&lsKgRr1E<8_74Etd#u>+-i&VEW-WN?q}ZZQ!Zx{e~N@|;WEdY zP4$Y;=^LUjHXplkJ)5S36v(psSR^!T#_o)S`HcvfDCXE=PYnoV$1}izWolsr&nz^~ zm}Nuqna{<8^0fKbtv$e7hC7BuheBTQt@J?*i4~-TpT-y-W#;y~p{Aq_i`CJk;daR2 zbK|U+FC?QUOgAK!O3LX80$GnoLal5t`#_y*S6<@a!x7z$GYeuRUu>La=rm5}3j$k9 zu&yj6Pqj;FOphveUHH|MB+IHL9U+nIJxs^V`Nt`|EL1^VjW#M1BxgnoDSr zH!rz0@s`R&ek+f zHoSp0mMKqZY{l19i=*+63Uk(%m9T9)uL*0xl(+D`EU>Mom`%!9g(`=tHKxde42kd; zY^OFuk5X?S;3$%RenU2nS`J}yf8j>EK~sY(5J`NS%@8rH@nmK$d9z<)uV*{rr6R^7 zdhaNnJsa;kqm2IH92n|_Zps3ckkj|<3D4Zn(==xkNLT9p%yX?p_35c z$pDi{^gbD%u95p!(L$YDlV%YY*#aj8la7YkIZ3yVQGS)EGqBnx0E{pvdND3FS@sDZqoYh1%kfoGvn>>mpB zemMxkPFvyLw~{$*JMK|h4}Wm_Blj{CgheN8?F1V)iOjK5JyW4kxBF{Y&iaY)r!mdr!-@|BIT3N)IkARUDU7`$>@x08z* z(FB^tX9#}Hv9izchrHJ^6044eO3Ibt)VP&cT7$kih_1F8y>=G({Y;kp`-@u$3Fkvt|Eyy_QL}01ZbY&8DPK6Dw(7)pM3`eS|<|>XFpHqM3CB=EN~)zFauq$ z+=@2@cAu;M!JZt4Nqg7Z)RrAqx3FHkp_LGB$GkLKO_HhY++=oH_u-0)k)rORkpl2edP}$Mz5;Q zKU~a_W$`LJ@kj}*wZwmXR4x%V%X5!6avSFD@(cmXAPO`aV)Kz(e8AQ*qFDIl%%^VT zQ+yZ&%^_sf9|5Y0&unFGQf}F|spbeQv-Ml~?l&Y)SDh%Lk>M~H_Yu_S5msF}4U_Q& zLls`7$!6?LPi;cKxN78fVycoX&ENrMrrwk`Dtp5{^KJjKdz;2_U#9C$UDQ!4Zjp(p z%`4`tIVjW_yS992Qfn`<@CYcFz8wj^DWy;3BB-p1gMNZ|Y`Aj#b}?sxYWkH(8+Zxe z{GLHHH038=Af;Qx9oC%3ab7Jr?am(8PF&#w@{<@;M?v7d9rd9xsB*7Rae@}yhCS}* zu22(2I|4mDbD#q}_ur053?TNuVRCTN-Ghk;wc}8FZs zf@p8lSZ@13ZYJ^`H_I_YCL1UOMHDh{PErS8s~&?nqbK9i$withsu36t=XB-TgTlc) z4-Q&YmD8X08@pcoXMwJhT~@0t@`Zrf%Ky6mM80T|Rk}<$STY)`Y}YVj-6X7+@x%QQ zM{l}bHz}CPQkyH%QKOT@QNdKGzIO_t)~%h=&fBKgYMEZ#=vFvua!M zDHokk((cL3-?WbB14~{S0FoLjbL{pZEU$PR_>P1T>9&1=h;$1ci7Q*!q34AZRDJGP zKlmv$Ch^hAp$QwG#X0NyhF_5+8*R3q-a9k%(wJq}S9`koaA3xCRN2VYzklv@4|HmS z+-^{mPhVOon4eYp4y{R1J0#5H>k@s+GCT6$bXDe#SWZmt+JWvWTej84WsE;D%h#Aa z9G7*$NpNE8`ARnFUyb?FrjkU&v{2#-IA2Ai^gSFklKn*$=-e20EDIU(NwtR$%We}v zI<~X~8+5GeF+vF?tD$=>&LDsstU|ETOZSm|9kXBBgAK_m%xX--Fy_nu3{g|=DJ)It z3-+O1K8;)Xh zZkpQ+XROtTgP;1%Y}iCGeQna;3i&uI#7$gx7rGk^M^^=R6WLGs*%-dQ)|Wrr$G4Y%|Z!b~?H1+P!YyYWwEl?Rz`*%cpB_`p3XD z#ofe}zV+6x0J9QUwWMiI|FZSiD#!0XxlS3zF{H5-8;lkU!l^611XY_J?%1>6d4$3$Iv!|0^*9^~cwYwr9EMNq{RQn~KtG0W^L(|oTE`JhSFc;I2fQn$y3 zB7IE>M9OghD+dUSyw^?(&~+024I=timU{lPhhSqLv&&^lp}^E1xUXeID*1FIPD)F* zquJNu@1^>nDiBQ@z1iP4hp`*lWwEX}pDocnY_2qt(tlsDuGJf4kB1;w8rx>TZnKW`j z7tj2JF2e*WR+(;1mJ2wmbv*lIuIhl%HIwH2Ezqpzm<@b=E@DJ^3hOvx#IVVgmzJ#8 zeJTsNK>Amn_FX>rh--s0AxqDT*1fVg3Z_E$v9_kD8xjN zZ+Vb#rZ-Q3UdG=!`M(s;EyS8R7xA_u0;{I>L~pDW=U4xwhM8H;zcWjry1i%W_T7-D zT>u(N;=ebbI=b+)8A~PdnuQ<%p$9=HRT!*=w(^UiBx(;cC9X@aQL`91A@N97gh=>Q z`IWw>W8%n*y3J*`OL$n}D+qrqo6VQCP#feKaIlkeYIOI z?zLn7(izxY`u-kgzOpQ?u5YXR+uN#&WmT4B*0qlI*ejoktHLbYD>i8U`8(gTxwY@7_^a$n3vFP zTUXAfhixOX{EW3p)f)1r%Z*8)Q!pzv1Bs{*w~aI3G-EEJy_*7Pgu*3%3&?y^D#H$CE3HbAA?g=Nt2UeSE)!O584)Hy z7XJ-1RfwERZ{FR?#7g2f7XGs01wr*!{ui7yjTdpB5whxPagcC&W@1c$J;~q|*S85( zkUCr>vHOM25UDcakX%JiB(82Jr9-Z$)~uKGYsl)+ymp{7Hu_wT!Wa|oXGxYmz!qoW z_@=z$1lLlGPRh|OV8hcYru5UD`EQ=`Qb!1E+;-bjt?_HPte5AKFIuG3-= zIZH+@6`)YP#^oOkUM(?b#61W0Whtfec?VBme*$e;xGE5vpJ@UPT5+-u283n3-~^*_ z4Y~3~*xo}ACF`aBVF{d3QiD1?g*|N6!L=bwaaHD8pXi2j5Rw$G=WcY?daB`-g( z2GU zyE?EY%Pv(BE@P<4cAeW+5#LmJCvCNYsP#qO&e+=LPv%xWbO+~~V3=>Apg$N^Zg83E z)KDFc$C1PA4}Slw>s`XE+lM`vZlHs-x1)%)W)f5RENVq-%bCOn@u4Hi4P?6D5_ZLu z+BnbLM@+E?G*$cV7UZ;vDrNI#o;r43ceex3&yo--r{3H8;A|qkw_g8ZT zpfz+9V8Q-8T%Yhpl0+1#m&zW#LW7Cv9f{tvedZY5oq{4o7oc7@63)?SQ^OPAxJ=B2 zd`^U~?w+>t44YqT#z;W|73~SH(Q7;D!LOi;%B-!n5`80TXA6-N`I;kLbAb;&1OoEW-By5U7?cW}~U6^%T@zLtO-R zeH3;}e7h2zFV~q*ex;axE(kSMTIAx$BP(dlE_Vfn)cQD}E7>)+y8=_YmsU(-MDmqQ zryF5E$<9@*Kl9AP5`_-gpi(BCl)nF6m+{L=@c>Dp$^HapS(`d-gPG&RmfA=|#%{3i}nTcq9 z@q%xD#6C6v-jtxYZ2a(^`v*E)k~^<(_H3wfT3 zGrOqq$7I<%Kmb&xF~-+sLvBqCg;>sFo{r?{a#PZ(et=6dd%~DqQz5ZHTe3@dRw+|%6t&(JikOYZly+>=gk2VbW-etYEEA%1)5w&h2 zK|Zi8W+GjBmvqiXz}!2BnCVzmDz3oYgq(WC#v-u&uri1u<7>$r$m)tUxP0(Q7W4)3 zWL|y#)J&&)BGnXQ=5qyWUo>JNV(Ii+NN zdhS}NLVCMwvyXiFs&o@|3wRao1lQ)+WBgKWJ^ZaZUlmvYH2kI}7dS!pu3t&0`9oB& zX7E@FQz^d!YY3ST%&$1X9LGk7Lr-L0c(AOJ-cuBL_xrJ=f0k+VWNW<7Df+K~>-rHU zEZ9Tyd>gY44&`lQDem8Nt8sCh!u}+E`YX0bcM<6?icN^n^@JdyqdsO)Q`<4 zPCfE6dJ<;zL}KqnkIb2A@*36+^0wHtrzNn$M|Ahjt)oKi0mjo6N?(rKmOl<}6$TwO zjhn{%g8LTI0QR$hbAh*F>}vi?#D_rYiW>T}h@)C|K}D;+g0qAzaud`T#( zM|S9gM`OCi1O{R3MiMqy>N4bdrC-4ovoL|3#eF@(B5A})Ef!-Zw*MHgv!bwm3pEk9{4m%Yv3cf;}Ww0Xn68kkGms&ySql z2@PuaM8)&Ri(Lq3UVM!}vCIFW8)Gmq!V#PDe;FgkR-xbJuPXGX?W`M$mNhCNQU81( zL!J!uA0#B=dDQAj%!NX}TZ!5(78T!Af*rtgz$HXQeq9N&yfbWi1-hIv*4J~7KgarP zY6AsWE#oB!jn(V_0c%tn+2pvAZ&=$hiq!=F4JqG=vw`ASW|*`P_k)_C^xA4F2-Smr zC|xCs8?`|yFi8U&W`-W1F_5UA*;=z7+Y%qKPad>F@IcoP_LEKz@fGLKCJFzH$iG(T z$m=wq&PxR7zgQK*v)0m%r!PB3ljeSH(&F9F@}vr2kxqISq!{;Ni+umJjoNdMR!z9y z>B~H^cTrl!hIZX86Cv7pBWaY$VYc4mrheh4S&ZWNYOyRoMDPp%u=wN_pOc4zP99!& z@Wf&K4_Ixr+Q!_<-rUB@%i4C`YWsC-?N(Y@t+TSa@$Pip|MP>eh(pJYocjO&;Ma|s Rc>D+8uPr+^Ki|Yk`ai|T*KYs- literal 0 HcmV?d00001 diff --git a/nvim/.vim/plugged/vim/screenshot.png b/nvim/.vim/plugged/vim/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..3e6a7540eff8b1b85711ac5fdefd0d90916175102675973ace60ba1f593a93a3 GIT binary patch literal 336007 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¨7%cbV$3e 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 literal 0 HcmV?d00001 diff --git a/plasma/.config/gtkrc-2.0 b/plasma/.config/gtkrc-2.0 new file mode 100644 index 0000000..8e65ba5 --- /dev/null +++ b/plasma/.config/gtkrc-2.0 @@ -0,0 +1,5 @@ +# created by KDE Plasma, Tue Jun 18 23:34:43 2024 +# + +gtk-alternative-button-order = 1 + diff --git a/plasma/.config/kded5rc b/plasma/.config/kded5rc new file mode 100644 index 0000000..38e7550 --- /dev/null +++ b/plasma/.config/kded5rc @@ -0,0 +1,2 @@ +[Module-device_automounter] +autoload=false diff --git a/plasma/.config/kdeglobals b/plasma/.config/kdeglobals new file mode 100644 index 0000000..08f00df --- /dev/null +++ b/plasma/.config/kdeglobals @@ -0,0 +1,125 @@ +[ColorEffects:Disabled] +ChangeSelectionColor= +Color=56,56,56 +ColorAmount=0 +ColorEffect=0 +ContrastAmount=0.65 +ContrastEffect=1 +Enable= +IntensityAmount=0.1 +IntensityEffect=2 + +[ColorEffects:Inactive] +ChangeSelectionColor=true +Color=112,111,110 +ColorAmount=0.025000000000000001 +ColorEffect=2 +ContrastAmount=0.10000000000000001 +ContrastEffect=2 +Enable=false +IntensityAmount=0 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=64,69,82 +BackgroundNormal=40,42,54 +DecorationFocus=68,71,90 +DecorationHover=68,71,90 +ForegroundActive=61,174,233 +ForegroundInactive=102,106,115 +ForegroundLink=41,128,185 +ForegroundNegative=255,85,85 +ForegroundNeutral=255,184,108 +ForegroundNormal=248,248,242 +ForegroundPositive=80,250,122 +ForegroundVisited=82,148,226 + +[Colors:Selection] +BackgroundAlternate=29,153,243 +BackgroundNormal=68,71,90 +DecorationFocus=68,71,90 +DecorationHover=68,71,90 +ForegroundActive=252,252,252 +ForegroundInactive=211,218,227 +ForegroundLink=253,188,75 +ForegroundNegative=255,85,85 +ForegroundNeutral=255,184,108 +ForegroundNormal=254,254,254 +ForegroundPositive=80,250,122 +ForegroundVisited=189,195,199 + +[Colors:Tooltip] +BackgroundAlternate=47,52,63 +BackgroundNormal=53,57,69 +DecorationFocus=68,71,90 +DecorationHover=68,71,90 +ForegroundActive=61,174,233 +ForegroundInactive=102,106,115 +ForegroundLink=41,128,185 +ForegroundNegative=255,85,85 +ForegroundNeutral=255,184,108 +ForegroundNormal=211,218,227 +ForegroundPositive=80,250,122 +ForegroundVisited=82,148,226 + +[Colors:View] +BackgroundAlternate=43,45,59 +BackgroundNormal=30,31,41 +DecorationFocus=68,71,90 +DecorationHover=68,71,90 +ForegroundActive=139,233,253 +ForegroundInactive=102,106,115 +ForegroundLink=82,148,226 +ForegroundNegative=255,85,85 +ForegroundNeutral=255,184,108 +ForegroundNormal=248,248,242 +ForegroundPositive=80,250,122 +ForegroundVisited=124,183,255 + +[Colors:Window] +BackgroundAlternate=47,52,63 +BackgroundNormal=40,42,54 +DecorationFocus=68,71,90 +DecorationHover=68,71,90 +ForegroundActive=139,233,253 +ForegroundInactive=102,106,115 +ForegroundLink=41,128,185 +ForegroundNegative=255,85,85 +ForegroundNeutral=255,184,108 +ForegroundNormal=248,248,242 +ForegroundPositive=80,250,122 +ForegroundVisited=68,71,90 + +[General] +ColorSchemeHash=154cb4d8d3e569860cc378f981d35f572c5b9e1d + +[KDE] +LookAndFeelPackage=org.kde.breezedark.desktop + +[KFileDialog Settings] +Allow Expansion=false +Automatically select filename extension=true +Breadcrumb Navigation=true +Decoration position=2 +LocationCombo Completionmode=5 +PathCombo Completionmode=5 +Show Bookmarks=false +Show Full Path=false +Show Inline Previews=true +Show Preview=false +Show Speedbar=true +Show hidden files=false +Sort by=Name +Sort directories first=true +Sort hidden files last=false +Sort reversed=false +Speedbar Width=140 +View Style=DetailTree + +[WM] +activeBackground=47,52,63 +activeBlend=47,52,63 +activeForeground=211,218,227 +inactiveBackground=47,52,63 +inactiveBlend=47,52,63 +inactiveForeground=102,106,115 diff --git a/plasma/.config/kglobalshortcutsrc b/plasma/.config/kglobalshortcutsrc new file mode 100644 index 0000000..fcf8a17 --- /dev/null +++ b/plasma/.config/kglobalshortcutsrc @@ -0,0 +1,259 @@ +[ActivityManager] +_k_friendly_name=Activity Manager +switch-to-activity-586a7ad7-4105-499f-8ad6-442513a5f917=none,none,Switch to activity "Default" +switch-to-activity-78ba6e6d-5dc7-4f18-a39b-c2af6d31bd8a=none,none,Switch to activity "Default" + +[KDE Keyboard Layout Switcher] +Switch to Last-Used Keyboard Layout=Meta+Alt+L,Meta+Alt+L, +Switch to Next Keyboard Layout=Meta+Alt+K,Meta+Alt+K, +_k_friendly_name=Keyboard Layout Switcher + +[kaccess] +Toggle Screen Reader On and Off=Meta+Alt+S,Meta+Alt+S,Toggle Screen Reader On and Off +_k_friendly_name=Accessibility + +[kcm_touchpad] +Disable Touchpad=Touchpad Off,Touchpad Off, +Enable Touchpad=Touchpad On,Touchpad On, +Toggle Touchpad=Touchpad Toggle\tMeta+Ctrl+Zenkaku Hankaku,Touchpad Toggle\tMeta+Ctrl+Zenkaku Hankaku, +_k_friendly_name=Touchpad + +[kmix] +_k_friendly_name=Audio Volume +decrease_microphone_volume=Microphone Volume Down,Microphone Volume Down,Decrease Microphone Volume +decrease_volume=Volume Down,Volume Down,Decrease Volume +decrease_volume_small=Shift+Volume Down,Shift+Volume Down,Decrease Volume by 1% +increase_microphone_volume=Microphone Volume Up,Microphone Volume Up,Increase Microphone Volume +increase_volume=Volume Up,Volume Up,Increase Volume +increase_volume_small=Shift+Volume Up,Shift+Volume Up,Increase Volume by 1% +mic_mute=Microphone Mute\tMeta+Volume Mute,Microphone Mute\tMeta+Volume Mute,Mute Microphone +mute=Volume Mute,Volume Mute,Mute + +[ksmserver] +Halt Without Confirmation=none,,Shut Down Without Confirmation +Lock Session=Meta+L\tScreensaver,Meta+L\tScreensaver,Lock Session +Log Out=Ctrl+Alt+Del,Ctrl+Alt+Del,Log Out +Log Out Without Confirmation=none,,Log Out Without Confirmation +Reboot=none,,Reboot +Reboot Without Confirmation=none,,Reboot Without Confirmation +Shut Down=none,,Shut Down +_k_friendly_name=Session Management + +[kwin] +Activate Window Demanding Attention=Meta+Ctrl+A,Meta+Ctrl+A,Activate Window Demanding Attention +Cycle Overview=none,none,Cycle through Overview and Grid View +Cycle Overview Opposite=none,none,Cycle through Grid View and Overview +Decrease Opacity=none,,Decrease Opacity of Active Window by 5% +Edit Tiles=Meta+T,Meta+T,Toggle Tiles Editor +Expose=Ctrl+F9,Ctrl+F9,Toggle Present Windows (Current desktop) +ExposeAll=Ctrl+F10\tLaunch (C),Ctrl+F10\tLaunch (C),Toggle Present Windows (All desktops) +ExposeClass=Ctrl+F7,Ctrl+F7,Toggle Present Windows (Window class) +ExposeClassCurrentDesktop=none,none,Toggle Present Windows (Window class on current desktop) +Grid View=Meta+G,Meta+G,Toggle Grid View +Increase Opacity=none,,Increase Opacity of Active Window by 5% +Kill Window=Meta+Ctrl+Esc,Meta+Ctrl+Esc,Kill Window +Move Tablet to Next Output=none,none,Move the tablet to the next output +MoveMouseToCenter=Meta+F6,Meta+F6,Move Mouse to Center +MoveMouseToFocus=Meta+F5,Meta+F5,Move Mouse to Focus +MoveZoomDown=none,none,Move Zoomed Area Downwards +MoveZoomLeft=none,none,Move Zoomed Area to Left +MoveZoomRight=none,none,Move Zoomed Area to Right +MoveZoomUp=none,none,Move Zoomed Area Upwards +Overview=Meta+W,Meta+W,Toggle Overview +Setup Window Shortcut=none,,Setup Window Shortcut +Show Desktop=Meta+D,Meta+D,Peek at Desktop +Switch One Desktop Down=Meta+Ctrl+Down,Meta+Ctrl+Down,Switch One Desktop Down +Switch One Desktop Up=Meta+Ctrl+Up,Meta+Ctrl+Up,Switch One Desktop Up +Switch One Desktop to the Left=Meta+Ctrl+Left,Meta+Ctrl+Left,Switch One Desktop to the Left +Switch One Desktop to the Right=Meta+Ctrl+Right,Meta+Ctrl+Right,Switch One Desktop to the Right +Switch Window Down=Meta+Alt+Down,Meta+Alt+Down,Switch to Window Below +Switch Window Left=Meta+Alt+Left,Meta+Alt+Left,Switch to Window to the Left +Switch Window Right=Meta+Alt+Right,Meta+Alt+Right,Switch to Window to the Right +Switch Window Up=Meta+Alt+Up,Meta+Alt+Up,Switch to Window Above +Switch to Desktop 1=Ctrl+F1\tMeta+1,Ctrl+F1,Switch to Desktop 1 +Switch to Desktop 10=none,,Switch to Desktop 10 +Switch to Desktop 11=none,,Switch to Desktop 11 +Switch to Desktop 12=none,,Switch to Desktop 12 +Switch to Desktop 13=none,,Switch to Desktop 13 +Switch to Desktop 14=none,,Switch to Desktop 14 +Switch to Desktop 15=none,,Switch to Desktop 15 +Switch to Desktop 16=none,,Switch to Desktop 16 +Switch to Desktop 17=none,,Switch to Desktop 17 +Switch to Desktop 18=none,,Switch to Desktop 18 +Switch to Desktop 19=none,,Switch to Desktop 19 +Switch to Desktop 2=Ctrl+F2\tMeta+2,Ctrl+F2,Switch to Desktop 2 +Switch to Desktop 20=none,,Switch to Desktop 20 +Switch to Desktop 3=Ctrl+F3\tMeta+3,Ctrl+F3,Switch to Desktop 3 +Switch to Desktop 4=Ctrl+F4\tMeta+4,Ctrl+F4,Switch to Desktop 4 +Switch to Desktop 5=none,,Switch to Desktop 5 +Switch to Desktop 6=none,,Switch to Desktop 6 +Switch to Desktop 7=none,,Switch to Desktop 7 +Switch to Desktop 8=none,,Switch to Desktop 8 +Switch to Desktop 9=none,,Switch to Desktop 9 +Switch to Next Desktop=none,,Switch to Next Desktop +Switch to Next Screen=none,,Switch to Next Screen +Switch to Previous Desktop=none,,Switch to Previous Desktop +Switch to Previous Screen=none,,Switch to Previous Screen +Switch to Screen 0=none,,Switch to Screen 0 +Switch to Screen 1=none,,Switch to Screen 1 +Switch to Screen 2=none,,Switch to Screen 2 +Switch to Screen 3=none,,Switch to Screen 3 +Switch to Screen 4=none,,Switch to Screen 4 +Switch to Screen 5=none,,Switch to Screen 5 +Switch to Screen 6=none,,Switch to Screen 6 +Switch to Screen 7=none,,Switch to Screen 7 +Switch to Screen Above=none,,Switch to Screen Above +Switch to Screen Below=none,,Switch to Screen Below +Switch to Screen to the Left=none,,Switch to Screen to the Left +Switch to Screen to the Right=none,,Switch to Screen to the Right +Toggle Night Color=none,none,Toggle Night Light +Toggle Window Raise/Lower=none,,Toggle Window Raise/Lower +Walk Through Windows=Alt+Tab,Alt+Tab,Walk Through Windows +Walk Through Windows (Reverse)=Alt+Shift+Tab,Alt+Shift+Tab,Walk Through Windows (Reverse) +Walk Through Windows Alternative=none,,Walk Through Windows Alternative +Walk Through Windows Alternative (Reverse)=none,,Walk Through Windows Alternative (Reverse) +Walk Through Windows of Current Application=Alt+`,Alt+`,Walk Through Windows of Current Application +Walk Through Windows of Current Application (Reverse)=Alt+~,Alt+~,Walk Through Windows of Current Application (Reverse) +Walk Through Windows of Current Application Alternative=none,,Walk Through Windows of Current Application Alternative +Walk Through Windows of Current Application Alternative (Reverse)=none,,Walk Through Windows of Current Application Alternative (Reverse) +Window Above Other Windows=none,,Keep Window Above Others +Window Below Other Windows=none,,Keep Window Below Others +Window Close=Meta+Shift+Q\tAlt+F4,Alt+F4,Close Window +Window Fullscreen=none,,Make Window Fullscreen +Window Grow Horizontal=none,,Expand Window Horizontally +Window Grow Vertical=none,,Expand Window Vertically +Window Lower=none,,Lower Window +Window Maximize=Meta+PgUp,Meta+PgUp,Maximize Window +Window Maximize Horizontal=none,,Maximize Window Horizontally +Window Maximize Vertical=none,,Maximize Window Vertically +Window Minimize=Meta+PgDown,Meta+PgDown,Minimize Window +Window Move=none,,Move Window +Window Move Center=none,,Move Window to the Center +Window No Border=none,,Toggle Window Titlebar and Frame +Window On All Desktops=none,,Keep Window on All Desktops +Window One Desktop Down=Meta+Ctrl+Shift+Down,Meta+Ctrl+Shift+Down,Window One Desktop Down +Window One Desktop Up=Meta+Ctrl+Shift+Up,Meta+Ctrl+Shift+Up,Window One Desktop Up +Window One Desktop to the Left=Meta+Ctrl+Shift+Left,Meta+Ctrl+Shift+Left,Window One Desktop to the Left +Window One Desktop to the Right=Meta+Ctrl+Shift+Right,Meta+Ctrl+Shift+Right,Window One Desktop to the Right +Window One Screen Down=none,,Move Window One Screen Down +Window One Screen Up=none,,Move Window One Screen Up +Window One Screen to the Left=none,,Move Window One Screen to the Left +Window One Screen to the Right=none,,Move Window One Screen to the Right +Window Operations Menu=Alt+F3,Alt+F3,Window Operations Menu +Window Pack Down=none,,Move Window Down +Window Pack Left=none,,Move Window Left +Window Pack Right=none,,Move Window Right +Window Pack Up=none,,Move Window Up +Window Quick Tile Bottom=Meta+Down,Meta+Down,Quick Tile Window to the Bottom +Window Quick Tile Bottom Left=none,,Quick Tile Window to the Bottom Left +Window Quick Tile Bottom Right=none,,Quick Tile Window to the Bottom Right +Window Quick Tile Left=Meta+Left,Meta+Left,Quick Tile Window to the Left +Window Quick Tile Right=Meta+Right,Meta+Right,Quick Tile Window to the Right +Window Quick Tile Top=Meta+Up,Meta+Up,Quick Tile Window to the Top +Window Quick Tile Top Left=none,,Quick Tile Window to the Top Left +Window Quick Tile Top Right=none,,Quick Tile Window to the Top Right +Window Raise=none,,Raise Window +Window Resize=none,,Resize Window +Window Shade=none,,Shade Window +Window Shrink Horizontal=none,,Shrink Window Horizontally +Window Shrink Vertical=none,,Shrink Window Vertically +Window to Desktop 1=Meta+!,,Window to Desktop 1 +Window to Desktop 10=none,,Window to Desktop 10 +Window to Desktop 11=none,,Window to Desktop 11 +Window to Desktop 12=none,,Window to Desktop 12 +Window to Desktop 13=none,,Window to Desktop 13 +Window to Desktop 14=none,,Window to Desktop 14 +Window to Desktop 15=none,,Window to Desktop 15 +Window to Desktop 16=none,,Window to Desktop 16 +Window to Desktop 17=none,,Window to Desktop 17 +Window to Desktop 18=none,,Window to Desktop 18 +Window to Desktop 19=none,,Window to Desktop 19 +Window to Desktop 2=Meta+",,Window to Desktop 2 +Window to Desktop 20=none,,Window to Desktop 20 +Window to Desktop 3=Meta+§,,Window to Desktop 3 +Window to Desktop 4=Meta+$,,Window to Desktop 4 +Window to Desktop 5=none,,Window to Desktop 5 +Window to Desktop 6=none,,Window to Desktop 6 +Window to Desktop 7=none,,Window to Desktop 7 +Window to Desktop 8=none,,Window to Desktop 8 +Window to Desktop 9=none,,Window to Desktop 9 +Window to Next Desktop=none,,Window to Next Desktop +Window to Next Screen=Meta+Shift+Right,Meta+Shift+Right,Move Window to Next Screen +Window to Previous Desktop=none,,Window to Previous Desktop +Window to Previous Screen=Meta+Shift+Left,Meta+Shift+Left,Move Window to Previous Screen +Window to Screen 0=none,,Move Window to Screen 0 +Window to Screen 1=none,,Move Window to Screen 1 +Window to Screen 2=none,,Move Window to Screen 2 +Window to Screen 3=none,,Move Window to Screen 3 +Window to Screen 4=none,,Move Window to Screen 4 +Window to Screen 5=none,,Move Window to Screen 5 +Window to Screen 6=none,,Move Window to Screen 6 +Window to Screen 7=none,,Move Window to Screen 7 +_k_friendly_name=KWin +view_actual_size=Meta+0,Meta+0,Zoom to Actual Size +view_zoom_in=Meta++\tMeta+=,Meta++\tMeta+=,Zoom In +view_zoom_out=Meta+-,Meta+-,Zoom Out + +[mediacontrol] +_k_friendly_name=Media Controller +mediavolumedown=none,,Media volume down +mediavolumeup=none,,Media volume up +nextmedia=Media Next,Media Next,Media playback next +pausemedia=Media Pause,Media Pause,Pause media playback +playmedia=none,,Play media playback +playpausemedia=Media Play,Media Play,Play/Pause media playback +previousmedia=Media Previous,Media Previous,Media playback previous +stopmedia=Media Stop,Media Stop,Stop media playback + +[org_kde_powerdevil] +Decrease Keyboard Brightness=Keyboard Brightness Down,Keyboard Brightness Down,Decrease Keyboard Brightness +Decrease Screen Brightness=Monitor Brightness Down,Monitor Brightness Down,Decrease Screen Brightness +Decrease Screen Brightness Small=Shift+Monitor Brightness Down,Shift+Monitor Brightness Down,Decrease Screen Brightness by 1% +Hibernate=Hibernate,Hibernate,Hibernate +Increase Keyboard Brightness=Keyboard Brightness Up,Keyboard Brightness Up,Increase Keyboard Brightness +Increase Screen Brightness=Monitor Brightness Up,Monitor Brightness Up,Increase Screen Brightness +Increase Screen Brightness Small=Shift+Monitor Brightness Up,Shift+Monitor Brightness Up,Increase Screen Brightness by 1% +PowerDown=Power Down,Power Down,Power Down +PowerOff=Power Off,Power Off,Power Off +Sleep=Sleep,Sleep,Suspend +Toggle Keyboard Backlight=Keyboard Light On/Off,Keyboard Light On/Off,Toggle Keyboard Backlight +Turn Off Screen=none,none,Turn Off Screen +_k_friendly_name=KDE Power Management System +powerProfile=Battery\tMeta+B,Battery\tMeta+B,Switch Power Profile + +[plasmashell] +_k_friendly_name=plasmashell +activate task manager entry 1=none,Meta+1,Activate Task Manager Entry 1 +activate task manager entry 10=none,Meta+0,Activate Task Manager Entry 10 +activate task manager entry 2=none,Meta+2,Activate Task Manager Entry 2 +activate task manager entry 3=none,Meta+3,Activate Task Manager Entry 3 +activate task manager entry 4=none,Meta+4,Activate Task Manager Entry 4 +activate task manager entry 5=none,Meta+5,Activate Task Manager Entry 5 +activate task manager entry 6=Meta+6,Meta+6,Activate Task Manager Entry 6 +activate task manager entry 7=Meta+7,Meta+7,Activate Task Manager Entry 7 +activate task manager entry 8=Meta+8,Meta+8,Activate Task Manager Entry 8 +activate task manager entry 9=Meta+9,Meta+9,Activate Task Manager Entry 9 +activate widget 5=Alt+F1,none,Activate Application Launcher Widget +clear-history=none,,Clear Clipboard History +clipboard_action=Meta+Ctrl+X,Meta+Ctrl+X,Automatic Action Popup Menu +cycle-panels=Meta+Alt+P,Meta+Alt+P,Move keyboard focus between panels +cycleNextAction=none,,Next History Item +cyclePrevAction=none,,Previous History Item +manage activities=Meta+Q,Meta+Q,Show Activity Switcher +next activity=Meta+A,none,Walk through activities +previous activity=Meta+Shift+A,none,Walk through activities (Reverse) +repeat_action=none,Meta+Ctrl+R,Manually Invoke Action on Current Clipboard +show dashboard=Ctrl+F12,Ctrl+F12,Show Desktop +show-barcode=none,,Show Barcode… +show-on-mouse-pos=Meta+V,Meta+V,Show Clipboard Items at Mouse Position +stop current activity=Meta+S,Meta+S,Stop Current Activity +switch to next activity=none,,Switch to Next Activity +switch to previous activity=none,,Switch to Previous Activity +toggle do not disturb=none,,Toggle do not disturb + +[services][Alacritty.desktop] +_launch=Meta+Return + +[services][org.kde.spectacle.desktop] +RectangularRegionScreenShot=Meta+Shift+S +_launch=Print diff --git a/plasma/.config/kwinoutputconfig.json b/plasma/.config/kwinoutputconfig.json new file mode 100644 index 0000000..765dd15 --- /dev/null +++ b/plasma/.config/kwinoutputconfig.json @@ -0,0 +1,167 @@ +[ + { + "data": [ + { + "autoRotation": "InTabletMode", + "connectorName": "DP-1", + "edidHash": "ed683a56f1976806cd9ccf23fc680f62", + "edidIdentifier": "MSI 5218 1 45 2017 0", + "highDynamicRange": false, + "iccProfilePath": "", + "mode": { + "height": 1440, + "refreshRate": 143995, + "width": 2560 + }, + "overscan": 0, + "rgbRange": "Automatic", + "scale": 1, + "sdrBrightness": 200, + "sdrGamutWideness": 0, + "transform": "Normal", + "vrrPolicy": "Always", + "wideColorGamut": false + }, + { + "autoRotation": "InTabletMode", + "connectorName": "DP-2", + "edidHash": "3f2aa370203a407bbdbfb476302c6397", + "edidIdentifier": "PHL 49494 1146 46 2021 0", + "highDynamicRange": false, + "iccProfilePath": "", + "mode": { + "height": 1080, + "refreshRate": 74973, + "width": 1920 + }, + "overscan": 0, + "rgbRange": "Automatic", + "scale": 1, + "sdrBrightness": 200, + "sdrGamutWideness": 0, + "transform": "Normal", + "vrrPolicy": "Never", + "wideColorGamut": false + }, + { + "autoRotation": "InTabletMode", + "connectorName": "HDMI-A-2", + "edidHash": "2cacc2503bfb9d8e4b67bed71c722adc", + "edidIdentifier": "PHL 2279 265 16 2018 0", + "highDynamicRange": false, + "iccProfilePath": "", + "mode": { + "height": 1440, + "refreshRate": 59951, + "width": 2560 + }, + "overscan": 0, + "rgbRange": "Automatic", + "scale": 1, + "sdrBrightness": 200, + "sdrGamutWideness": 0, + "transform": "Rotated270", + "vrrPolicy": "Never", + "wideColorGamut": false + } + ], + "name": "outputs" + }, + { + "data": [ + { + "lidClosed": false, + "outputs": [ + { + "enabled": true, + "outputIndex": 0, + "position": { + "x": 1440, + "y": 1120 + }, + "priority": 0 + }, + { + "enabled": true, + "outputIndex": 1, + "position": { + "x": 1440, + "y": 40 + }, + "priority": 1 + }, + { + "enabled": true, + "outputIndex": 2, + "position": { + "x": 0, + "y": 0 + }, + "priority": 2 + } + ] + }, + { + "lidClosed": false, + "outputs": [ + { + "enabled": true, + "outputIndex": 0, + "position": { + "x": 0, + "y": 1080 + }, + "priority": 0 + }, + { + "enabled": true, + "outputIndex": 1, + "position": { + "x": 314, + "y": 0 + }, + "priority": 1 + } + ] + }, + { + "lidClosed": false, + "outputs": [ + { + "enabled": true, + "outputIndex": 1, + "position": { + "x": 0, + "y": 0 + }, + "priority": 0 + } + ] + }, + { + "lidClosed": false, + "outputs": [ + { + "enabled": true, + "outputIndex": 1, + "position": { + "x": 1440, + "y": 0 + }, + "priority": 1 + }, + { + "enabled": true, + "outputIndex": 2, + "position": { + "x": 0, + "y": 0 + }, + "priority": 0 + } + ] + } + ], + "name": "setups" + } +] diff --git a/plasma/.config/kwinrc b/plasma/.config/kwinrc new file mode 100644 index 0000000..ad00eb2 --- /dev/null +++ b/plasma/.config/kwinrc @@ -0,0 +1,26 @@ +[Desktops] +Id_1=8ee0e3b1-c247-47ff-a24c-39723aaf4ee0 +Id_2=344182b2-a47d-498e-a20f-0a9ba22d4dd5 +Id_3=0eca7647-e38c-417e-a527-76f555d7aa3e +Id_4=67e36da5-23c2-44a7-822d-4b09cdf8ac30 +Number=4 +Rows=1 + +[Tiling] +padding=4 + +[Tiling][1a885956-9e56-5f36-a40a-8c7d85ccd296] +tiles={"layoutDirection":"horizontal","tiles":[{"layoutDirection":"vertical","tiles":[{"height":0.5},{"height":0.5}],"width":0.8493055555555543},{"layoutDirection":"vertical","tiles":[{"height":0.5},{"height":0.5}],"width":0.15069444444444569}]} + +[Tiling][28852940-922b-5e48-b156-e62e36e769f5] +tiles={"layoutDirection":"horizontal","tiles":[{"width":0.25},{"width":0.5},{"width":0.25}]} + +[Tiling][7eadfd0f-0ba9-5978-b6fd-527ada28bc81] +tiles={"layoutDirection":"horizontal","tiles":[{"width":0.25},{"width":0.5},{"width":0.25}]} + +[Xwayland] +Scale=1 + +[org.kde.kdecoration2] +library=org.kde.breeze +theme=Breeze diff --git a/plasma/.config/plasma-localerc b/plasma/.config/plasma-localerc new file mode 100644 index 0000000..d1e704c --- /dev/null +++ b/plasma/.config/plasma-localerc @@ -0,0 +1,9 @@ +[Formats] +LANG=en_US.UTF-8 +LC_ADDRESS=de_DE.UTF-8 +LC_MEASUREMENT=de_DE.UTF-8 +LC_NAME=de_DE.UTF-8 +LC_NUMERIC=de_DE.UTF-8 +LC_PAPER=de_DE.UTF-8 +LC_TELEPHONE=de_DE.UTF-8 +LC_TIME=de_DE.UTF-8 diff --git a/plasma/.config/plasma-org.kde.plasma.desktop-appletsrc b/plasma/.config/plasma-org.kde.plasma.desktop-appletsrc new file mode 100644 index 0000000..40742b2 --- /dev/null +++ b/plasma/.config/plasma-org.kde.plasma.desktop-appletsrc @@ -0,0 +1,220 @@ +[ActionPlugins][0] +RightButton;NoModifier=org.kde.contextmenu + +[ActionPlugins][1] +RightButton;NoModifier=org.kde.contextmenu + +[Containments][1] +ItemGeometries-2560x1440= +ItemGeometriesHorizontal= +activityId=78ba6e6d-5dc7-4f18-a39b-c2af6d31bd8a +formfactor=0 +immutability=1 +lastScreen=0 +location=0 +plugin=org.kde.plasma.folder +wallpaperplugin=org.kde.image + +[Containments][10] +activityId= +formfactor=2 +immutability=1 +lastScreen=0 +location=3 +plugin=org.kde.plasma.private.systemtray +popupHeight=432 +popupWidth=432 +wallpaperplugin=org.kde.image + +[Containments][10][Applets][11] +immutability=1 +plugin=org.kde.plasma.cameraindicator + +[Containments][10][Applets][12] +immutability=1 +plugin=org.kde.plasma.clipboard + +[Containments][10][Applets][13] +immutability=1 +plugin=org.kde.plasma.devicenotifier + +[Containments][10][Applets][13][Configuration] +PreloadWeight=100 + +[Containments][10][Applets][14] +immutability=1 +plugin=org.kde.plasma.manage-inputmethod + +[Containments][10][Applets][15] +immutability=1 +plugin=org.kde.plasma.notifications + +[Containments][10][Applets][15][Configuration] +PreloadWeight=55 + +[Containments][10][Applets][16] +immutability=1 +plugin=org.kde.plasma.keyboardlayout + +[Containments][10][Applets][17] +immutability=1 +plugin=org.kde.plasma.volume + +[Containments][10][Applets][17][Configuration] +PreloadWeight=100 + +[Containments][10][Applets][17][Configuration][General] +migrated=true +showVirtualDevices=true + +[Containments][10][Applets][18] +immutability=1 +plugin=org.kde.kscreen + +[Containments][10][Applets][20] +immutability=1 +plugin=org.kde.plasma.networkmanagement + +[Containments][10][Applets][20][Configuration] +PreloadWeight=80 + +[Containments][10][Applets][21] +immutability=1 +plugin=org.kde.plasma.battery + +[Containments][10][Applets][21][Configuration] +PreloadWeight=0 + +[Containments][10][Applets][22] +immutability=1 +plugin=org.kde.plasma.brightness + +[Containments][10][Applets][22][Configuration] +PreloadWeight=0 + +[Containments][10][Applets][23] +immutability=1 +plugin=org.kde.plasma.mediacontroller + +[Containments][10][Applets][23][Configuration] +PreloadWeight=0 + +[Containments][10][ConfigDialog] +DialogHeight=540 +DialogWidth=720 + +[Containments][10][General] +extraItems=org.kde.plasma.battery,org.kde.plasma.brightness,org.kde.plasma.cameraindicator,org.kde.plasma.clipboard,org.kde.plasma.devicenotifier,org.kde.plasma.manage-inputmethod,org.kde.plasma.mediacontroller,org.kde.plasma.keyboardlayout,org.kde.plasma.volume,org.kde.plasma.networkmanagement,org.kde.kscreen,org.kde.plasma.notifications +hiddenItems=org.kde.plasma.mediacontroller,org.kde.plasma.clipboard,org.kde.plasma.brightness +knownItems=org.kde.plasma.battery,org.kde.plasma.brightness,org.kde.plasma.cameraindicator,org.kde.plasma.clipboard,org.kde.plasma.devicenotifier,org.kde.plasma.manage-inputmethod,org.kde.plasma.mediacontroller,org.kde.plasma.notifications,org.kde.plasma.keyboardlayout,org.kde.plasma.volume,org.kde.plasma.networkmanagement,org.kde.kscreen + +[Containments][2] +ItemGeometries-1920x1080= +ItemGeometriesHorizontal= +activityId=78ba6e6d-5dc7-4f18-a39b-c2af6d31bd8a +formfactor=0 +immutability=1 +lastScreen=1 +location=0 +plugin=org.kde.plasma.folder +wallpaperplugin=org.kde.image + +[Containments][3] +ItemGeometries-1440x2560= +ItemGeometriesHorizontal= +ItemGeometriesVertical= +activityId=78ba6e6d-5dc7-4f18-a39b-c2af6d31bd8a +formfactor=0 +immutability=1 +lastScreen=2 +location=0 +plugin=org.kde.plasma.folder +wallpaperplugin=org.kde.image + +[Containments][4] +activityId= +formfactor=2 +immutability=1 +lastScreen=0 +location=3 +plugin=org.kde.panel +wallpaperplugin=org.kde.image + +[Containments][4][Applets][19] +immutability=1 +plugin=org.kde.plasma.showdesktop + +[Containments][4][Applets][27] +immutability=1 +plugin=org.kde.plasma.digitalclock + +[Containments][4][Applets][27][Configuration] +PreloadWeight=85 +popupHeight=450 +popupWidth=560 + +[Containments][4][Applets][27][Configuration][Appearance] +customDateFormat=dd.MM.yy +dateFormat=custom +fontFamily=Noto Sans +fontWeight=400 +use24hFormat=2 + +[Containments][4][Applets][27][Configuration][ConfigDialog] +DialogHeight=540 +DialogWidth=720 + +[Containments][4][Applets][5] +immutability=1 +plugin=org.kde.plasma.kickoff + +[Containments][4][Applets][5][Configuration] +PreloadWeight=100 +popupHeight=510 +popupWidth=647 + +[Containments][4][Applets][5][Configuration][General] +favoritesPortedToKAstats=true + +[Containments][4][Applets][5][Configuration][Shortcuts] +global=Alt+F1 + +[Containments][4][Applets][5][Shortcuts] +global=Alt+F1 + +[Containments][4][Applets][6] +immutability=1 +plugin=org.kde.plasma.pager + +[Containments][4][Applets][6][Configuration][ConfigDialog] +DialogHeight=540 +DialogWidth=720 + +[Containments][4][Applets][6][Configuration][General] +showWindowIcons=true + +[Containments][4][Applets][7] +immutability=1 +plugin=org.kde.plasma.icontasks + +[Containments][4][Applets][7][Configuration][General] +launchers=applications:systemsettings.desktop,preferred://filemanager,applications:mercury-browser.desktop,applications:Alacritty.desktop + +[Containments][4][Applets][8] +immutability=1 +plugin=org.kde.plasma.marginsseparator + +[Containments][4][Applets][9] +immutability=1 +plugin=org.kde.plasma.systemtray + +[Containments][4][Applets][9][Configuration] +PreloadWeight=100 +SystrayContainmentId=10 + +[Containments][4][General] +AppletOrder=5;6;7;8;9;19;27 + +[ScreenMapping] +itemsOnDisabledScreens= +screenMapping=desktop:/Fortnite.desktop,0,78ba6e6d-5dc7-4f18-a39b-c2af6d31bd8a,desktop:/Old Firefox Data,0,78ba6e6d-5dc7-4f18-a39b-c2af6d31bd8a diff --git a/plasma/.config/plasmanotifyrc b/plasma/.config/plasmanotifyrc new file mode 100644 index 0000000..f9b4f7c --- /dev/null +++ b/plasma/.config/plasmanotifyrc @@ -0,0 +1,5 @@ +[Applications][discord] +Seen=true + +[Applications][fr.handbrake.ghb] +Seen=true diff --git a/plasma/.config/plasmaparc b/plasma/.config/plasmaparc new file mode 100644 index 0000000..473a0f4 diff --git a/plasma/.config/plasmashellrc b/plasma/.config/plasmashellrc new file mode 100644 index 0000000..10dc59d --- /dev/null +++ b/plasma/.config/plasmashellrc @@ -0,0 +1,9 @@ +[PlasmaViews][Panel 4] +floating=1 +panelOpacity=2 + +[PlasmaViews][Panel 4][Defaults] +thickness=36 + +[Updates] +performed=/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/containmentactions_middlebutton.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_migrate_font_settings.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_migrate_showseconds_setting.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/digitalclock_rename_timezonedisplay_key.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/folderview_fix_recursive_screenmapping.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/keyboardlayout_migrateiconsetting.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/keyboardlayout_remove_shortcut.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/klipper_clear_config.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/maintain_existing_desktop_icon_sizes.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/mediaframe_migrate_useBackground_setting.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/migrate_font_weights.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/move_desktop_layout_config.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/no_middle_click_paste_on_panels.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/systemloadviewer_systemmonitor.js,/usr/share/plasma/shells/org.kde.plasma.desktop/contents/updates/unlock_widgets.js diff --git a/plasma/.config/spectaclerc b/plasma/.config/spectaclerc new file mode 100644 index 0000000..d2df791 --- /dev/null +++ b/plasma/.config/spectaclerc @@ -0,0 +1,12 @@ +[Annotations] +annotationToolType=2 + +[General] +clipboardGroup=PostScreenshotCopyImage + +[ImageSave] +lastImageSaveLocation=file:///home/philipp/Pictures/Screenshots/Screenshot_20240309_011444.png +translatedScreenshotsFolder=Screenshots + +[VideoSave] +translatedScreencastsFolder=Screencasts diff --git a/zsh/.oh-my-zsh/.editorconfig b/zsh/.oh-my-zsh/.editorconfig new file mode 100644 index 0000000..7f4eda9 --- /dev/null +++ b/zsh/.oh-my-zsh/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_size = 2 +indent_style = space + +[*.py] +indent_size = 4 diff --git a/zsh/.oh-my-zsh/.github/CODEOWNERS b/zsh/.oh-my-zsh/.github/CODEOWNERS new file mode 100644 index 0000000..c9612fa --- /dev/null +++ b/zsh/.oh-my-zsh/.github/CODEOWNERS @@ -0,0 +1,14 @@ +# Plugin owners +plugins/archlinux/ @ratijas +plugins/dbt/ @msempere +plugins/eza/ @pepoluan +plugins/genpass/ @atoponce +plugins/git-lfs/ @hellovietduc +plugins/gitfast/ @felipec +plugins/react-native @esthor +plugins/sdk/ @rgoldberg +plugins/shell-proxy/ @septs +plugins/starship/ @axieax +plugins/universalarchive/ @Konfekt +plugins/wp-cli/ @joshmedeski +plugins/zoxide/ @ajeetdsouza diff --git a/zsh/.oh-my-zsh/.github/FUNDING.yml b/zsh/.oh-my-zsh/.github/FUNDING.yml new file mode 100644 index 0000000..81e2a3b --- /dev/null +++ b/zsh/.oh-my-zsh/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: [ohmyzsh, robbyrussell, mcornella, larson-carter, carlosala] +open_collective: ohmyzsh diff --git a/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/bug_report.yml b/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..2dbc0ef --- /dev/null +++ b/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,68 @@ +name: Report a bug +description: Report a bug that isn't caused by Oh My Zsh. If unsure, use this form +body: + - type: markdown + attributes: + value: | + ## Self Check + - Look for similar errors in existing [GitHub Issues](https://github.com/ohmyzsh/ohmyzsh/issues?q=is%3Aissue) (open or closed). + - Try reaching out on the [Discord server](https://discord.gg/ohmyzsh) for help. + - type: textarea + validations: + required: true + attributes: + label: Describe the bug + description: A clear description of what the bug is. + - type: textarea + validations: + required: true + attributes: + label: Steps to reproduce + description: | + Steps to reproduce the problem. + placeholder: | + For example: + 1. Enable plugin '...' + 2. Run command '...' or try to complete command '...' + 3. See error + - type: textarea + validations: + required: true + attributes: + label: Expected behavior + description: A brief description of what should happen. + - type: textarea + attributes: + label: Screenshots and recordings + description: | + If applicable, add screenshots to help explain your problem. You can also record an asciinema session: https://asciinema.org/ + - type: input + validations: + required: true + attributes: + label: OS / Linux distribution + placeholder: Windows 10, Ubuntu 20.04, Arch Linux, macOS 10.15... + - type: input + validations: + required: true + attributes: + label: Zsh version + description: Run `echo $ZSH_VERSION` to check. + placeholder: "5.6" + - type: input + validations: + required: true + attributes: + label: Terminal emulator + placeholder: iTerm2, GNOME Terminal, Terminal.app... + - type: dropdown + attributes: + label: If using WSL on Windows, which version of WSL + description: Run `wsl -l -v` to check. + options: + - WSL1 + - WSL2 + - type: textarea + attributes: + label: Additional context + description: Add any other context about the problem here. This can be themes, plugins, custom settings... diff --git a/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/bug_report_omz.yml b/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/bug_report_omz.yml new file mode 100644 index 0000000..f62f914 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/bug_report_omz.yml @@ -0,0 +1,77 @@ +name: Report a bug in Oh My Zsh +description: Create a report to help us improve Oh My Zsh +labels: ['Bug'] +body: + - type: markdown + attributes: + value: | + ## Self Check + - **Make sure this bug only happens with Oh My Zsh enabled**. + - Look for similar errors in existing [GitHub Issues](https://github.com/ohmyzsh/ohmyzsh/issues?q=is%3Aissue) (open or closed). + - Try reaching out on the [Discord server](https://discord.gg/ohmyzsh) for help. + - type: textarea + validations: + required: true + attributes: + label: Describe the bug + description: A clear description of what the bug is. + - type: textarea + validations: + required: true + attributes: + label: Steps to reproduce + description: | + Steps to reproduce the problem. + placeholder: | + For example: + 1. Enable plugin '...' + 2. Run command '...' or try to complete command '...' + 3. See error + - type: textarea + validations: + required: true + attributes: + label: Expected behavior + description: A brief description of what should happen. + - type: textarea + attributes: + label: Screenshots and recordings + description: | + If applicable, add screenshots to help explain your problem. You can also record an asciinema session: https://asciinema.org/ + - type: input + validations: + required: true + attributes: + label: OS / Linux distribution + placeholder: Windows 10, Ubuntu 20.04, Arch Linux, macOS 10.15... + - type: input + validations: + required: true + attributes: + label: Zsh version + description: Run `echo $ZSH_VERSION` to check. + placeholder: "5.6" + - type: input + validations: + required: true + attributes: + label: Oh My Zsh version + description: Run `omz version` to check. + placeholder: master (bf303965) + - type: input + validations: + required: true + attributes: + label: Terminal emulator + placeholder: iTerm2, GNOME Terminal, Terminal.app... + - type: dropdown + attributes: + label: If using WSL on Windows, which version of WSL + description: Run `wsl -l -v` to check. + options: + - WSL1 + - WSL2 + - type: textarea + attributes: + label: Additional context + description: Add any other context about the problem here. This can be themes, plugins, custom settings... diff --git a/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/config.yml b/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..a2452a6 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Support + url: https://github.com/ohmyzsh/ohmyzsh/discussions + about: Ask the community for support + - name: Get help on Discord + url: https://discord.gg/ohmyzsh + about: Have a quick question? Join the Discord server and ask on the appropriate channel. diff --git a/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/feature_request.yml b/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..124e3ac --- /dev/null +++ b/zsh/.oh-my-zsh/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,37 @@ +name: Feature request +description: Suggest a feature for Oh My Zsh +labels: ["Feature"] +body: + - type: markdown + attributes: + value: | + ## Self Check + - Look for similar features in existing [GitHub Issues](https://github.com/ohmyzsh/ohmyzsh/issues?q=is%3Aissue) (open or closed). + - type: input + attributes: + label: If the feature request is for a plugin or theme, specify it here. + description: The name of the plugin or theme that you would like us to improve. + placeholder: e.g. Git plugin, Agnoster theme + - type: textarea + attributes: + label: If the feature solves a problem you have, specify it here. + description: A description of what the problem is. + placeholder: Ex. I'm always frustrated when... + - type: textarea + attributes: + label: Describe the proposed feature. + description: A description of what you want to happen. Be as specific as possible. + validations: + required: true + - type: textarea + attributes: + label: Describe alternatives you've considered + description: A description of any alternative solutions or features you've considered. This can also include other plugins or themes. + - type: textarea + attributes: + label: Additional context + description: Add any other context, screenshots or Discord conversations about the feature request here. Also if you have any PRs related to this issue that are already open that you would like us to look at. + - type: textarea + attributes: + label: Related Issues + description: Is there any open or closed issues that is related to this feature request? If so please link them below! diff --git a/zsh/.oh-my-zsh/.github/PULL_REQUEST_TEMPLATE.md b/zsh/.oh-my-zsh/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..cd5f3cb --- /dev/null +++ b/zsh/.oh-my-zsh/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +## Standards checklist: + + + +- [ ] The PR title is descriptive. +- [ ] The PR doesn't replicate another PR which is already open. +- [ ] I have read the contribution guide and followed all the instructions. +- [ ] The code follows the code style guide detailed in the wiki. +- [ ] The code is mine or it's from somewhere with an MIT-compatible license. +- [ ] The code is efficient, to the best of my ability, and does not waste computer resources. +- [ ] The code is stable and I have tested it myself, to the best of my abilities. +- [ ] If the code introduces new aliases, I provide a valid use case for all plugin users down below. + +## Changes: + +- [...] + +## Other comments: + +... diff --git a/zsh/.oh-my-zsh/.github/dependabot.yml b/zsh/.oh-my-zsh/.github/dependabot.yml new file mode 100644 index 0000000..ee98f45 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: "weekly" + day: "sunday" + - package-ecosystem: "pip" + directory: "/.github/workflows/dependencies" + schedule: + interval: "weekly" + day: "sunday" diff --git a/zsh/.oh-my-zsh/.github/dependencies.yml b/zsh/.oh-my-zsh/.github/dependencies.yml new file mode 100644 index 0000000..f385711 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/dependencies.yml @@ -0,0 +1,46 @@ +dependencies: + plugins/gitfast: + repo: felipec/git-completion + branch: master + version: tag:v2.1 + postcopy: | + set -e + rm -rf git-completion.plugin.zsh Makefile README.adoc t tools + test -e git-completion.zsh && mv -f git-completion.zsh _git + plugins/z: + branch: master + repo: agkozak/zsh-z + version: afaf2965b41fdc6ca66066e09382726aa0b6aa04 + precopy: | + set -e + test -e README.md && mv -f README.md MANUAL.md + postcopy: | + set -e + test -e _zshz && mv -f _zshz _z + test -e zsh-z.plugin.zsh && mv -f zsh-z.plugin.zsh z.plugin.zsh + plugins/history-substring-search: + repo: zsh-users/zsh-history-substring-search + branch: master + version: 87ce96b1862928d84b1afe7c173316614b30e301 + precopy: | + set -e + rm -f zsh-history-substring-search.plugin.zsh + test -e zsh-history-substring-search.zsh && mv zsh-history-substring-search.zsh history-substring-search.zsh + postcopy: | + set -e + test -e dependencies/OMZ-README.md && cat dependencies/OMZ-README.md >> README.md + plugins/gradle: + repo: gradle/gradle-completion + branch: master + version: 25da917cf5a88f3e58f05be3868a7b2748c8afe6 + precopy: | + set -e + find . ! -name _gradle ! -name LICENSE -delete + plugins/wd: + repo: mfaerevaag/wd + branch: master + version: tag:v0.7.0 + precopy: | + set -e + rm -r test + rm install.sh tty.gif wd.1 diff --git a/zsh/.oh-my-zsh/.github/workflows/dependencies.yml b/zsh/.oh-my-zsh/.github/workflows/dependencies.yml new file mode 100644 index 0000000..64e7fc7 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/workflows/dependencies.yml @@ -0,0 +1,36 @@ +name: Update dependencies +on: + workflow_dispatch: {} + schedule: + - cron: "0 6 * * 0" + +jobs: + check: + name: Check for updates + runs-on: ubuntu-latest + if: github.repository == 'ohmyzsh/ohmyzsh' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Authenticate as @ohmyzsh + id: generate_token + uses: ohmyzsh/github-app-token@v2 + with: + app_id: ${{ secrets.OHMYZSH_APP_ID }} + private_key: ${{ secrets.OHMYZSH_APP_PRIVATE_KEY }} + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: "pip" + - name: Process dependencies + env: + GH_TOKEN: ${{ steps.generate_token.outputs.token }} + GIT_APP_NAME: ohmyzsh[bot] + GIT_APP_EMAIL: 54982679+ohmyzsh[bot]@users.noreply.github.com + TMP_DIR: ${{ runner.temp }} + run: | + pip install -r .github/workflows/dependencies/requirements.txt + python3 .github/workflows/dependencies/updater.py diff --git a/zsh/.oh-my-zsh/.github/workflows/dependencies/requirements.txt b/zsh/.oh-my-zsh/.github/workflows/dependencies/requirements.txt new file mode 100644 index 0000000..5895e62 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/workflows/dependencies/requirements.txt @@ -0,0 +1,7 @@ +certifi==2024.2.2 +charset-normalizer==3.3.2 +idna==3.7 +PyYAML==6.0.1 +requests==2.31.0 +semver==3.0.2 +urllib3==2.2.1 diff --git a/zsh/.oh-my-zsh/.github/workflows/dependencies/updater.py b/zsh/.oh-my-zsh/.github/workflows/dependencies/updater.py new file mode 100644 index 0000000..6faf8e3 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/workflows/dependencies/updater.py @@ -0,0 +1,598 @@ +import json +import os +import re +import shutil +import subprocess +import sys +import timeit +from copy import deepcopy +from typing import Literal, NotRequired, Optional, TypedDict + +import requests +import yaml +from semver import Version + +# Get TMP_DIR variable from environment +TMP_DIR = os.path.join(os.environ.get("TMP_DIR", "/tmp"), "ohmyzsh") +# Relative path to dependencies.yml file +DEPS_YAML_FILE = ".github/dependencies.yml" +# Dry run flag +DRY_RUN = os.environ.get("DRY_RUN", "0") == "1" + +# utils for tag comparison +BASEVERSION = re.compile( + r"""[vV]? + (?P(0|[1-9])\d*) + (\. + (?P(0|[1-9])\d*) + (\. + (?P(0|[1-9])\d*) + )? + )? + """, + re.VERBOSE, +) + + +def coerce(version: str) -> Optional[Version]: + match = BASEVERSION.search(version) + if not match: + return None + + # BASEVERSION looks for `MAJOR.minor.patch` in the string given + # it fills with None if any of them is missing (for example `2.1`) + ver = { + key: 0 if value is None else value for key, value in match.groupdict().items() + } + # Version takes `major`, `minor`, `patch` arguments + ver = Version(**ver) # pyright: ignore[reportArgumentType] + return ver + + +class CodeTimer: + def __init__(self, name=None): + self.name = " '" + name + "'" if name else "" + + def __enter__(self): + self.start = timeit.default_timer() + + def __exit__(self, exc_type, exc_value, traceback): + self.took = (timeit.default_timer() - self.start) * 1000.0 + print("Code block" + self.name + " took: " + str(self.took) + " ms") + + +### YAML representation +def str_presenter(dumper, data): + """ + Configures yaml for dumping multiline strings + Ref: https://stackoverflow.com/a/33300001 + """ + if len(data.splitlines()) > 1: # check for multiline string + return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|") + return dumper.represent_scalar("tag:yaml.org,2002:str", data) + + +yaml.add_representer(str, str_presenter) +yaml.representer.SafeRepresenter.add_representer(str, str_presenter) + + +# Types +class DependencyDict(TypedDict): + repo: str + branch: str + version: str + precopy: NotRequired[str] + postcopy: NotRequired[str] + + +class DependencyYAML(TypedDict): + dependencies: dict[str, DependencyDict] + + +class UpdateStatusFalse(TypedDict): + has_updates: Literal[False] + + +class UpdateStatusTrue(TypedDict): + has_updates: Literal[True] + version: str + compare_url: str + head_ref: str + head_url: str + + +class CommandRunner: + class Exception(Exception): + def __init__(self, message, returncode, stage, stdout, stderr): + super().__init__(message) + self.returncode = returncode + self.stage = stage + self.stdout = stdout + self.stderr = stderr + + @staticmethod + def run_or_fail(command: list[str], stage: str, *args, **kwargs): + if DRY_RUN and command[0] == "gh": + command.insert(0, "echo") + + result = subprocess.run(command, *args, capture_output=True, **kwargs) + + if result.returncode != 0: + raise CommandRunner.Exception( + f"{stage} command failed with exit code {result.returncode}", + returncode=result.returncode, + stage=stage, + stdout=result.stdout.decode("utf-8"), + stderr=result.stderr.decode("utf-8"), + ) + + return result + + +class DependencyStore: + store: DependencyYAML = {"dependencies": {}} + + @staticmethod + def set(data: DependencyYAML): + DependencyStore.store = data + + @staticmethod + def update_dependency_version(path: str, version: str) -> DependencyYAML: + with CodeTimer(f"store deepcopy: {path}"): + store_copy = deepcopy(DependencyStore.store) + + dependency = store_copy["dependencies"].get(path) + if dependency is None: + raise ValueError(f"Dependency {path} {version} not found") + dependency["version"] = version + store_copy["dependencies"][path] = dependency + + return store_copy + + @staticmethod + def write_store(file: str, data: DependencyYAML): + with open(file, "w") as yaml_file: + yaml.safe_dump(data, yaml_file, sort_keys=False) + + +class Dependency: + def __init__(self, path: str, values: DependencyDict): + self.path = path + self.values = values + + self.name: str = "" + self.desc: str = "" + self.kind: str = "" + + match path.split("/"): + case ["plugins", name]: + self.name = name + self.kind = "plugin" + self.desc = f"{name} plugin" + case ["themes", name]: + self.name = name.replace(".zsh-theme", "") + self.kind = "theme" + self.desc = f"{self.name} theme" + case _: + self.name = self.desc = path + + def __str__(self): + output: str = "" + for key in DependencyDict.__dict__["__annotations__"].keys(): + if key not in self.values: + output += f"{key}: None\n" + continue + + value = self.values[key] + if "\n" not in value: + output += f"{key}: {value}\n" + else: + output += f"{key}:\n " + output += value.replace("\n", "\n ", value.count("\n") - 1) + return output + + def update_or_notify(self): + # Print dependency settings + print(f"Processing {self.desc}...", file=sys.stderr) + print(self, file=sys.stderr) + + # Check for updates + repo = self.values["repo"] + remote_branch = self.values["branch"] + version = self.values["version"] + is_tag = version.startswith("tag:") + + try: + with CodeTimer(f"update check: {repo}"): + if is_tag: + status = GitHub.check_newer_tag(repo, version.replace("tag:", "")) + else: + status = GitHub.check_updates(repo, remote_branch, version) + + if status["has_updates"] is True: + short_sha = status["head_ref"][:8] + new_version = status["version"] if is_tag else short_sha + + try: + branch_name = f"update/{self.path}/{new_version}" + + # Create new branch + branch = Git.checkout_or_create_branch(branch_name) + + # Update dependencies.yml file + self.__update_yaml( + f"tag:{new_version}" if is_tag else status["version"] + ) + + # Update dependency files + self.__apply_upstream_changes() + + # Add all changes and commit + has_new_commit = Git.add_and_commit(self.name, short_sha) + + if has_new_commit: + # Push changes to remote + Git.push(branch) + + # Create GitHub PR + GitHub.create_pr( + branch, + f"feat({self.name}): update to version {new_version}", + f"""## Description + +Update for **{self.desc}**: update to version [{new_version}]({status['head_url']}). +Check out the [list of changes]({status['compare_url']}). +""", + ) + + # Clean up repository + Git.clean_repo() + except (CommandRunner.Exception, shutil.Error) as e: + # Handle exception on automatic update + match type(e): + case CommandRunner.Exception: + # Print error message + print( + f"Error running {e.stage} command: {e.returncode}", # pyright: ignore[reportAttributeAccessIssue] + file=sys.stderr, + ) + print(e.stderr, file=sys.stderr) # pyright: ignore[reportAttributeAccessIssue] + case shutil.Error: + print(f"Error copying files: {e}", file=sys.stderr) + + try: + Git.clean_repo() + except CommandRunner.Exception as e: + print( + f"Error reverting repository to clean state: {e}", + file=sys.stderr, + ) + sys.exit(1) + + # Create a GitHub issue to notify maintainer + title = f"{self.path}: update to {new_version}" + body = f"""## Description + +There is a new version of `{self.name}` {self.kind} available. + +New version: [{new_version}]({status['head_url']}) +Check out the [list of changes]({status['compare_url']}). +""" + + print("Creating GitHub issue", file=sys.stderr) + print(f"{title}\n\n{body}", file=sys.stderr) + GitHub.create_issue(title, body) + except Exception as e: + print(e, file=sys.stderr) + + def __update_yaml(self, new_version: str) -> None: + dep_yaml = DependencyStore.update_dependency_version(self.path, new_version) + DependencyStore.write_store(DEPS_YAML_FILE, dep_yaml) + + def __apply_upstream_changes(self) -> None: + # Patterns to ignore in copying files from upstream repo + GLOBAL_IGNORE = [".git", ".github", ".gitignore"] + + path = os.path.abspath(self.path) + precopy = self.values.get("precopy") + postcopy = self.values.get("postcopy") + + repo = self.values["repo"] + branch = self.values["branch"] + remote_url = f"https://github.com/{repo}.git" + repo_dir = os.path.join(TMP_DIR, repo) + + # Clone repository + Git.clone(remote_url, branch, repo_dir, reclone=True) + + # Run precopy on tmp repo + if precopy is not None: + print("Running precopy script:", end="\n ", file=sys.stderr) + print( + precopy.replace("\n", "\n ", precopy.count("\n") - 1), file=sys.stderr + ) + CommandRunner.run_or_fail( + ["bash", "-c", precopy], cwd=repo_dir, stage="Precopy" + ) + + # Copy files from upstream repo + print(f"Copying files from {repo_dir} to {path}", file=sys.stderr) + shutil.copytree( + repo_dir, + path, + dirs_exist_ok=True, + ignore=shutil.ignore_patterns(*GLOBAL_IGNORE), + ) + + # Run postcopy on our repository + if postcopy is not None: + print("Running postcopy script:", end="\n ", file=sys.stderr) + print( + postcopy.replace("\n", "\n ", postcopy.count("\n") - 1), + file=sys.stderr, + ) + CommandRunner.run_or_fail( + ["bash", "-c", postcopy], cwd=path, stage="Postcopy" + ) + + +class Git: + default_branch = "master" + + @staticmethod + def clone(remote_url: str, branch: str, repo_dir: str, reclone=False): + # If repo needs to be fresh + if reclone and os.path.exists(repo_dir): + shutil.rmtree(repo_dir) + + # Clone repo in tmp directory and checkout branch + if not os.path.exists(repo_dir): + print( + f"Cloning {remote_url} to {repo_dir} and checking out {branch}", + file=sys.stderr, + ) + CommandRunner.run_or_fail( + ["git", "clone", "--depth=1", "-b", branch, remote_url, repo_dir], + stage="Clone", + ) + + @staticmethod + def checkout_or_create_branch(branch_name: str): + # Get current branch name + result = CommandRunner.run_or_fail( + ["git", "rev-parse", "--abbrev-ref", "HEAD"], stage="GetDefaultBranch" + ) + Git.default_branch = result.stdout.decode("utf-8").strip() + + # Create new branch and return created branch name + try: + # try to checkout already existing branch + CommandRunner.run_or_fail( + ["git", "checkout", branch_name], stage="CreateBranch" + ) + except CommandRunner.Exception: + # otherwise create new branch + CommandRunner.run_or_fail( + ["git", "checkout", "-b", branch_name], stage="CreateBranch" + ) + return branch_name + + @staticmethod + def add_and_commit(scope: str, version: str) -> bool: + """ + Returns `True` if there were changes and were indeed commited. + Returns `False` if the repo was clean and no changes were commited. + """ + # check if repo is clean (clean => no error, no commit) + try: + CommandRunner.run_or_fail( + ["git", "diff", "--exit-code"], stage="CheckRepoClean" + ) + return False + except CommandRunner.Exception: + # if it's other kind of error just throw! + pass + + user_name = os.environ.get("GIT_APP_NAME") + user_email = os.environ.get("GIT_APP_EMAIL") + + # Add all files to git staging + CommandRunner.run_or_fail(["git", "add", "-A", "-v"], stage="AddFiles") + + # Reset environment and git config + clean_env = os.environ.copy() + clean_env["LANG"] = "C.UTF-8" + clean_env["GIT_CONFIG_GLOBAL"] = "/dev/null" + clean_env["GIT_CONFIG_NOSYSTEM"] = "1" + + # Commit with settings above + CommandRunner.run_or_fail( + [ + "git", + "-c", + f"user.name={user_name}", + "-c", + f"user.email={user_email}", + "commit", + "-m", + f"feat({scope}): update to {version}", + ], + stage="CreateCommit", + env=clean_env, + ) + return True + + @staticmethod + def push(branch: str): + CommandRunner.run_or_fail( + ["git", "push", "-u", "origin", branch], stage="PushBranch" + ) + + @staticmethod + def clean_repo(): + CommandRunner.run_or_fail( + ["git", "reset", "--hard", "HEAD"], stage="ResetRepository" + ) + CommandRunner.run_or_fail( + ["git", "checkout", Git.default_branch], stage="CheckoutDefaultBranch" + ) + + +class GitHub: + @staticmethod + def check_newer_tag(repo, current_tag) -> UpdateStatusFalse | UpdateStatusTrue: + # GET /repos/:owner/:repo/git/refs/tags + url = f"https://api.github.com/repos/{repo}/git/refs/tags" + + # Send a GET request to the GitHub API + response = requests.get(url) + current_version = coerce(current_tag) + if current_version is None: + raise ValueError( + f"Stored {current_version} from {repo} does not follow semver" + ) + + # If the request was successful + if response.status_code == 200: + # Parse the JSON response + data = response.json() + + if len(data) == 0: + return { + "has_updates": False, + } + + latest_ref = None + latest_version: Optional[Version] = None + for ref in data: + # we find the tag since GitHub returns it as plain git ref + tag_version = coerce(ref["ref"].replace("refs/tags/", "")) + if tag_version is None: + # we skip every tag that is not semver-complaint + continue + if latest_version is None or tag_version.compare(latest_version) > 0: + # if we have a "greater" semver version, set it as latest + latest_version = tag_version + latest_ref = ref + + # raise if no valid semver tag is found + if latest_ref is None or latest_version is None: + raise ValueError(f"No tags following semver found in {repo}") + + # we get the tag since GitHub returns it as plain git ref + latest_tag = latest_ref["ref"].replace("refs/tags/", "") + + if latest_version.compare(current_version) <= 0: + return { + "has_updates": False, + } + + return { + "has_updates": True, + "version": latest_tag, + "compare_url": f"https://github.com/{repo}/compare/{current_tag}...{latest_tag}", + "head_ref": latest_ref["object"]["sha"], + "head_url": f"https://github.com/{repo}/releases/tag/{latest_tag}", + } + else: + # If the request was not successful, raise an exception + raise Exception( + f"GitHub API request failed with status code {response.status_code}: {response.json()}" + ) + + @staticmethod + def check_updates(repo, branch, version) -> UpdateStatusFalse | UpdateStatusTrue: + url = f"https://api.github.com/repos/{repo}/compare/{version}...{branch}" + + # Send a GET request to the GitHub API + response = requests.get(url) + + # If the request was successful + if response.status_code == 200: + # Parse the JSON response + data = response.json() + + # If the base is behind the head, there is a newer version + has_updates = data["status"] != "identical" + + if not has_updates: + return { + "has_updates": False, + } + + return { + "has_updates": data["status"] != "identical", + "version": data["commits"][-1]["sha"], + "compare_url": data["permalink_url"], + "head_ref": data["commits"][-1]["sha"], + "head_url": data["commits"][-1]["html_url"], + } + else: + # If the request was not successful, raise an exception + raise Exception( + f"GitHub API request failed with status code {response.status_code}: {response.json()}" + ) + + @staticmethod + def create_issue(title: str, body: str) -> None: + cmd = ["gh", "issue", "create", "-t", title, "-b", body] + CommandRunner.run_or_fail(cmd, stage="CreateIssue") + + @staticmethod + def create_pr(branch: str, title: str, body: str) -> None: + # first of all let's check if PR is already open + check_cmd = [ + "gh", + "pr", + "list", + "--state", + "open", + "--head", + branch, + "--json", + "title", + ] + # returncode is 0 also if no PRs are found + output = json.loads( + CommandRunner.run_or_fail(check_cmd, stage="CheckPullRequestOpen") + .stdout.decode("utf-8") + .strip() + ) + # we have PR in this case! + if len(output) > 0: + return + cmd = [ + "gh", + "pr", + "create", + "-B", + Git.default_branch, + "-H", + branch, + "-t", + title, + "-b", + body, + ] + CommandRunner.run_or_fail(cmd, stage="CreatePullRequest") + + +def main(): + # Load the YAML file + with open(DEPS_YAML_FILE, "r") as yaml_file: + data: DependencyYAML = yaml.safe_load(yaml_file) + + if "dependencies" not in data: + raise Exception("dependencies.yml not properly formatted") + + # Cache YAML version + DependencyStore.set(data) + + dependencies = data["dependencies"] + for path in dependencies: + dependency = Dependency(path, dependencies[path]) + dependency.update_or_notify() + + +if __name__ == "__main__": + main() diff --git a/zsh/.oh-my-zsh/.github/workflows/installer.yml b/zsh/.oh-my-zsh/.github/workflows/installer.yml new file mode 100644 index 0000000..7b59f9e --- /dev/null +++ b/zsh/.oh-my-zsh/.github/workflows/installer.yml @@ -0,0 +1,56 @@ +name: Test and Deploy installer +on: + workflow_dispatch: {} + push: + paths: + - 'tools/install.sh' + - '.github/workflows/installer/**' + - '.github/workflows/installer.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: false + +permissions: + contents: read # to checkout + +jobs: + test: + name: Test installer + if: github.repository == 'ohmyzsh/ohmyzsh' + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - ubuntu-latest + - macos-latest + steps: + - name: Set up git repository + uses: actions/checkout@v4 + - name: Install zsh + if: runner.os == 'Linux' + run: sudo apt-get update; sudo apt-get install zsh + - name: Test installer + run: sh ./tools/install.sh + + deploy: + name: Deploy installer in install.ohmyz.sh + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + environment: vercel + needs: + - test + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Vercel CLI + run: npm install -g vercel + - name: Setup project and deploy + env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + run: | + cp tools/install.sh .github/workflows/installer/install.sh + cd .github/workflows/installer + vc deploy --prod -t "$VERCEL_TOKEN" diff --git a/zsh/.oh-my-zsh/.github/workflows/installer/.gitignore b/zsh/.oh-my-zsh/.github/workflows/installer/.gitignore new file mode 100644 index 0000000..8039240 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/workflows/installer/.gitignore @@ -0,0 +1 @@ +install.sh diff --git a/zsh/.oh-my-zsh/.github/workflows/installer/.vercelignore b/zsh/.oh-my-zsh/.github/workflows/installer/.vercelignore new file mode 100644 index 0000000..8d2bff1 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/workflows/installer/.vercelignore @@ -0,0 +1,2 @@ +/* +!/install.sh diff --git a/zsh/.oh-my-zsh/.github/workflows/installer/vercel.json b/zsh/.oh-my-zsh/.github/workflows/installer/vercel.json new file mode 100644 index 0000000..45eb8aa --- /dev/null +++ b/zsh/.oh-my-zsh/.github/workflows/installer/vercel.json @@ -0,0 +1,23 @@ +{ + "headers": [ + { + "source": "/((?!favicon.ico).*)", + "headers": [ + { + "key": "Content-Type", + "value": "text/plain" + }, + { + "key": "Content-Disposition", + "value": "inline; filename=\"install.sh\"" + } + ] + } + ], + "rewrites": [ + { + "source": "/((?!favicon.ico|install.sh).*)", + "destination": "/install.sh" + } + ] +} diff --git a/zsh/.oh-my-zsh/.github/workflows/main.yml b/zsh/.oh-my-zsh/.github/workflows/main.yml new file mode 100644 index 0000000..19cd12d --- /dev/null +++ b/zsh/.oh-my-zsh/.github/workflows/main.yml @@ -0,0 +1,38 @@ +name: CI +on: + pull_request: + types: + - opened + - synchronize + branches: + - master + push: + branches: + - master + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + tests: + name: Run tests + runs-on: ubuntu-latest + if: github.repository == 'ohmyzsh/ohmyzsh' + steps: + - name: Set up git repository + uses: actions/checkout@v4 + - name: Install zsh + run: sudo apt-get update; sudo apt-get install zsh + - name: Check syntax + run: | + for file in ./oh-my-zsh.sh \ + ./lib/*.zsh \ + ./plugins/*/*.plugin.zsh \ + ./plugins/*/_* \ + ./themes/*.zsh-theme; do + zsh -n "$file" || return 1 + done diff --git a/zsh/.oh-my-zsh/.github/workflows/project.yml b/zsh/.oh-my-zsh/.github/workflows/project.yml new file mode 100644 index 0000000..bff4b75 --- /dev/null +++ b/zsh/.oh-my-zsh/.github/workflows/project.yml @@ -0,0 +1,146 @@ +name: Project tracking +on: + issues: + types: [opened, reopened] + pull_request_target: + types: [opened, reopened, synchronize] + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: {} +jobs: + add-to-project: + name: Add to project + runs-on: ubuntu-latest + if: github.repository == 'ohmyzsh/ohmyzsh' + steps: + - name: Authenticate as @ohmyzsh + id: generate_token + uses: ohmyzsh/github-app-token@v2 + with: + app_id: ${{ secrets.OHMYZSH_APP_ID }} + private_key: ${{ secrets.OHMYZSH_APP_PRIVATE_KEY }} + - name: Store app token + run: echo "GH_TOKEN=${{ steps.generate_token.outputs.token }}" >> "$GITHUB_ENV" + - name: Read project data + env: + ORGANIZATION: ohmyzsh + PROJECT_NUMBER: "1" + run: | + # Get Project data + gh api graphql -f query=' + query($org: String!, $number: Int!) { + organization(login: $org){ + projectV2(number: $number) { + id + fields(first:20) { + nodes { + ... on ProjectV2Field { + id + name + } + } + } + } + } + }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json + + # Parse project data + cat >> $GITHUB_ENV <> $GITHUB_ENV + + - name: Classify Pull Request + if: github.event_name == 'pull_request_target' + run: | + touch plugins.list themes.list + + gh pr view ${{ github.event.pull_request.number }} \ + --repo ${{ github.repository }} \ + --json files --jq '.files.[].path' | awk -F/ ' + /^plugins\// { + plugins[$2] = 1 + } + /^themes\// { + gsub(/\.zsh-theme$/, "", $2) + themes[$2] = 1 + } + END { + for (plugin in plugins) { + print plugin >> "plugins.list" + } + for (theme in themes) { + print theme >> "themes.list" + } + } + ' + # If only one plugin is modified, add it to the plugin field + if [[ $(wc -l < plugins.list) = 1 ]]; then + echo "PLUGIN=$(cat plugins.list)" >> $GITHUB_ENV + fi + # If only one theme is modified, add it to the theme field + if [[ $(wc -l < themes.list) = 1 ]]; then + echo "THEME=$(cat themes.list)" >> $GITHUB_ENV + fi + + - name: Fill Pull Request fields in project + if: github.event_name == 'pull_request_target' + run: | + gh api graphql -f query=' + mutation ( + $project: ID! + $item: ID! + $plugin_field: ID! + $plugin_value: String! + $theme_field: ID! + $theme_value: String! + ) { + set_plugin: updateProjectV2ItemFieldValue(input: { + projectId: $project + itemId: $item + fieldId: $plugin_field + value: { + text: $plugin_value + } + }) { + projectV2Item { + id + } + } + set_theme: updateProjectV2ItemFieldValue(input: { + projectId: $project + itemId: $item + fieldId: $theme_field + value: { + text: $theme_value + } + }) { + projectV2Item { + id + } + } + } + ' -f project=$PROJECT_ID -f item=$ITEM_ID \ + -f plugin_field=$PLUGIN_FIELD_ID -f plugin_value=$PLUGIN \ + -f theme_field=$THEME_FIELD_ID -f theme_value=$THEME \ + --silent diff --git a/zsh/.oh-my-zsh/.gitignore b/zsh/.oh-my-zsh/.gitignore new file mode 100644 index 0000000..0a19820 --- /dev/null +++ b/zsh/.oh-my-zsh/.gitignore @@ -0,0 +1,12 @@ +# custom files +custom/ + +# temp files directories +cache/ +log/ +*.swp +.DS_Store + +# editor configs +.vscode +.idea diff --git a/zsh/.oh-my-zsh/.gitpod.Dockerfile b/zsh/.oh-my-zsh/.gitpod.Dockerfile new file mode 100644 index 0000000..9b1f862 --- /dev/null +++ b/zsh/.oh-my-zsh/.gitpod.Dockerfile @@ -0,0 +1,5 @@ +FROM gitpod/workspace-full + +RUN sudo apt-get update && \ + sudo apt-get install -y zsh && \ + sudo rm -rf /var/lib/apt/lists/* diff --git a/zsh/.oh-my-zsh/.gitpod.yml b/zsh/.oh-my-zsh/.gitpod.yml new file mode 100644 index 0000000..f760fbf --- /dev/null +++ b/zsh/.oh-my-zsh/.gitpod.yml @@ -0,0 +1,9 @@ +image: + file: .gitpod.Dockerfile + +tasks: + - init: | + export EDITOR="command gp open -w" VISUAL="command gp open -w" + cp -f /workspace/ohmyzsh/templates/zshrc.zsh-template ~/.zshrc + ln -sf /workspace/ohmyzsh ~/.oh-my-zsh + command: exec zsh diff --git a/zsh/.oh-my-zsh/.prettierrc b/zsh/.oh-my-zsh/.prettierrc new file mode 100644 index 0000000..159a1b7 --- /dev/null +++ b/zsh/.oh-my-zsh/.prettierrc @@ -0,0 +1,4 @@ +{ + "printWidth": 110, + "proseWrap": "always" +} diff --git a/zsh/.oh-my-zsh/CODE_OF_CONDUCT.md b/zsh/.oh-my-zsh/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..d5db11f --- /dev/null +++ b/zsh/.oh-my-zsh/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at ohmyzsh@planetargon.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/zsh/.oh-my-zsh/CONTRIBUTING.md b/zsh/.oh-my-zsh/CONTRIBUTING.md new file mode 100644 index 0000000..10f620e --- /dev/null +++ b/zsh/.oh-my-zsh/CONTRIBUTING.md @@ -0,0 +1,245 @@ +# CONTRIBUTING GUIDELINES + +Oh-My-Zsh is a community-driven project. Contribution is welcome, encouraged, and appreciated. +It is also essential for the development of the project. + +First, please take a moment to review our [code of conduct](CODE_OF_CONDUCT.md). + +These guidelines are an attempt at better addressing the huge amount of pending +issues and pull requests. Please read them closely. + +Foremost, be so kind as to [search](#use-the-search-luke). This ensures any contribution +you would make is not already covered. + + + +- [Reporting Issues](#reporting-issues) + - [You have a problem](#you-have-a-problem) + - [You have a suggestion](#you-have-a-suggestion) +- [Submitting Pull Requests](#submitting-pull-requests) + - [Getting started](#getting-started) + - [You have a solution](#you-have-a-solution) + - [You have an addition](#you-have-an-addition) +- [Use the Search, Luke](#use-the-search-luke) +- [Commit Guidelines](#commit-guidelines) + - [Format](#format) + - [Style](#style) +- [Volunteer](#volunteer) + + + +## Reporting Issues + +### You have a problem + +Please be so kind as to [search](#use-the-search-luke) for any open issue already covering +your problem. + +If you find one, comment on it, so we know more people are experiencing it. + +If not, look at the [Troubleshooting](https://github.com/ohmyzsh/ohmyzsh/wiki/Troubleshooting) +page for instructions on how to gather data to better debug your problem. + +Then, you can go ahead and create an issue with as much detail as you can provide. +It should include the data gathered as indicated above, along with the following: + +1. How to reproduce the problem +2. What the correct behavior should be +3. What the actual behavior is + +Please copy to anyone relevant (e.g. plugin maintainers) by mentioning their GitHub handle +(starting with `@`) in your message. + +We will do our very best to help you. + +### You have a suggestion + +Please be so kind as to [search](#use-the-search-luke) for any open issue already covering +your suggestion. + +If you find one, comment on it, so we know more people are supporting it. + +If not, you can go ahead and create an issue. Please copy to anyone relevant (e.g. plugin +maintainers) by mentioning their GitHub handle (starting with `@`) in your message. + +## Submitting Pull Requests + +### Getting started + +You should be familiar with the basics of +[contributing on GitHub](https://help.github.com/articles/using-pull-requests) and have a fork +[properly set up](https://github.com/ohmyzsh/ohmyzsh/wiki/Contribution-Technical-Practices). + +You MUST always create PRs with _a dedicated branch_ based on the latest upstream tree. + +If you create your own PR, please make sure you do it right. Also be so kind as to reference +any issue that would be solved in the PR description body, +[for instance](https://help.github.com/articles/closing-issues-via-commit-messages/) +_"Fixes #XXXX"_ for issue number XXXX. + +### You have a solution + +Please be so kind as to [search](#use-the-search-luke) for any open issue already covering +your [problem](#you-have-a-problem), and any pending/merged/rejected PR covering your solution. + +If the solution is already reported, try it out and +1 the pull request if the +solution works ok. On the other hand, if you think your solution is better, post +it with reference to the other one so we can have both solutions to compare. + +If not, then go ahead and submit a PR. Please copy to anyone relevant (e.g. plugin +maintainers) by mentioning their GitHub handle (starting with `@`) in your message. + +### You have an addition + +Please [do not](https://github.com/ohmyzsh/ohmyzsh/wiki/Themes#dont-send-us-your-theme-for-now) +send themes for now. + +Please be so kind as to [search](#use-the-search-luke) for any pending, merged or rejected Pull Requests +covering or related to what you want to add. + +If you find one, try it out and work with the author on a common solution. + +If not, then go ahead and submit a PR. Please copy to anyone relevant (e.g. plugin +maintainers) by mentioning their GitHub handle (starting with `@`) in your message. + +For any extensive change, such as a new plugin, you will have to find testers to +1 your PR. + +### New plugin aliases + +We acknowledge that aliases are a core part of Oh My Zsh. There are plugins that have +100 aliases! + +This has become an issue for two opposing reasons: + +- Some users want to have their personal aliases in Oh My Zsh. +- Some users don't want any aliases at all and feel that there are too many. + +Because of this, from now on, we require that new aliases follow these conditions: + +1. They will be used by many people, not just a few. +2. The aliases will be used many times and for common tasks. +3. Prefer one generic alias over many specific ones. +4. When justifying the need for an alias, talk about workflows where you'll use it, + preferably in combination with other aliases. +5. If a command with the same name exists, look for a different alias name. + +This list is not exhaustive! Please remember that your alias will be in the machines of many people, +so it should be justified why they should have it. + +---- + +## Use the Search, Luke + +_May the Force (of past experiences) be with you_ + +GitHub offers [many search features](https://help.github.com/articles/searching-github/) +to help you check whether a similar contribution to yours already exists. Please search +before making any contribution, it avoids duplicates and eases maintenance. Trust me, +that works 90% of the time. + +You can also take a look at the [FAQ](https://github.com/ohmyzsh/ohmyzsh/wiki/FAQ) +to be sure your contribution has not already come up. + +If all fails, your thing has probably not been reported yet, so you can go ahead +and [create an issue](#reporting-issues) or [submit a PR](#submitting-pull-requests). + +---- + +## Commit Guidelines + +Oh My Zsh uses the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) +specification. The automatic changelog tool uses these to automatically generate +a changelog based on the commit messages. Here's a guide to writing a commit message +to allow this: + +### Format + +``` +type(scope)!: subject +``` + +- `type`: the type of the commit is one of the following: + + - `feat`: new features. + - `fix`: bug fixes. + - `docs`: documentation changes. + - `refactor`: refactor of a particular code section without introducing + new features or bug fixes. + - `style`: code style improvements. + - `perf`: performance improvements. + - `test`: changes to the test suite. + - `ci`: changes to the CI system. + - `build`: changes to the build system (we don't yet have one so this shouldn't apply). + - `chore`: for other changes that don't match previous types. This doesn't appear + in the changelog. + +- `scope`: section of the codebase that the commit makes changes to. If it makes changes to + many sections, or if no section in particular is modified, leave blank without the parentheses. + Examples: + + - Commit that changes the `git` plugin: + ``` + feat(git): add alias for `git commit` + ``` + + - Commit that changes many plugins: + ``` + style: fix inline declaration of arrays + ``` + + For changes to plugins or themes, the scope should be the plugin or theme name: + + - ✅ `fix(agnoster): commit subject` + - ❌ `fix(theme/agnoster): commit subject` + +- `!`: this goes after the `scope` (or the `type` if scope is empty), to indicate that the commit + introduces breaking changes. + + Optionally, you can specify a message that the changelog tool will display to the user to indicate + what's changed and what they can do to deal with it. You can use multiple lines to type this message; + the changelog parser will keep reading until the end of the commit message or until it finds an empty + line. + + Example (made up): + + ``` + style(agnoster)!: change dirty git repo glyph + + BREAKING CHANGE: the glyph to indicate when a git repository is dirty has + changed from a Powerline character to a standard UTF-8 emoji. You can + change it back by setting `ZSH_THEME_DIRTY_GLYPH`. + + Fixes #420 + + Co-authored-by: Username + ``` + +- `subject`: a brief description of the changes. This will be displayed in the changelog. If you need + to specify other details, you can use the commit body, but it won't be visible. + + Formatting tricks: the commit subject may contain: + + - Links to related issues or PRs by writing `#issue`. This will be highlighted by the changelog tool: + ``` + feat(archlinux): add support for aura AUR helper (#9467) + ``` + + - Formatted inline code by using backticks: the text between backticks will also be highlighted by + the changelog tool: + ``` + feat(shell-proxy): enable unexported `DEFAULT_PROXY` setting (#9774) + ``` + +### Style + +Try to keep the first commit line short. It's harder to do using this commit style but try to be +concise, and if you need more space, you can use the commit body. Try to make sure that the commit +subject is clear and precise enough that users will know what changed by just looking at the changelog. + +---- + +## Volunteer + +Very nice!! :) + +Please have a look at the [Volunteer](https://github.com/ohmyzsh/ohmyzsh/wiki/Volunteers) +page for instructions on where to start and more. diff --git a/zsh/.oh-my-zsh/LICENSE.txt b/zsh/.oh-my-zsh/LICENSE.txt new file mode 100644 index 0000000..6ced2dc --- /dev/null +++ b/zsh/.oh-my-zsh/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2009-2022 Robby Russell and contributors (https://github.com/ohmyzsh/ohmyzsh/contributors) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/zsh/.oh-my-zsh/README.md b/zsh/.oh-my-zsh/README.md new file mode 100644 index 0000000..53481fa --- /dev/null +++ b/zsh/.oh-my-zsh/README.md @@ -0,0 +1,489 @@ +