diff --git a/config/neovim/config.lua b/config/neovim/config.lua
index 89a173f5..0c4e04bf 100644
--- a/config/neovim/config.lua
+++ b/config/neovim/config.lua
@@ -60,397 +60,24 @@ do
end
-- }}}
-vim.loader.disable()
+vim.loader.enable()
vim.cmd([[
]])
require("lazy").setup({
dev = {
- path = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins",
+ path = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins",
patterns = { "." },
fallback = false,
},
spec = {
- {
- "catppuccin",
- ["config"] = function(_, opts)
- require("catppuccin").setup(opts)
-
- vim.cmd([[
- let $BAT_THEME = "catppuccin"
- colorscheme catppuccin
- ]])
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/catppuccin-nvim",
- ["lazy"] = false,
- ["name"] = "catppuccin",
- ["opts"] = { ["background"] = { ["dark"] = "mocha", ["light"] = "latte" }, ["flavour"] = "latte" },
- ["priority"] = 1000,
- },
- {
- "lspconfig",
- ["config"] = function(_, opts)
- local __lspOnAttach = function(client, bufnr) end
-
- local __lspCapabilities = function()
- capabilities = vim.lsp.protocol.make_client_capabilities()
- capabilities =
- vim.tbl_deep_extend("force", capabilities, require("cmp_nvim_lsp").default_capabilities())
- return capabilities
- end
-
- local __setup = {
- on_attach = __lspOnAttach,
- capabilities = __lspCapabilities(),
- }
-
- for i, server in ipairs({
- { ["name"] = "cmake" },
- { ["name"] = "clojure_lsp" },
- { ["name"] = "clangd" },
- { ["name"] = "texlab" },
- { ["name"] = "rust_analyzer" },
- { ["name"] = "pyright" },
- { ["name"] = "nil_ls" },
- { ["cmd"] = { "haskell-language-server-wrapper", "--lsp" }, ["name"] = "hls" },
- }) do
- if type(server) == "string" then
- require("lspconfig")[server].setup(__setup)
- else
- local options = server.extraOptions
-
- if options == nil then
- options = __setup
- else
- options = vim.tbl_extend("keep", options, __setup)
- end
-
- require("lspconfig")[server.name].setup(options)
- end
- end
- end,
- ["dependencies"] = {
- {
- "cmp",
- ["config"] = function(_, opts)
- require("cmp").setup(opts)
- end,
- ["dependencies"] = {
- {
- "cmp-async-path",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/cmp-async-path",
- ["name"] = "cmp-async-path",
- },
- {
- "cmp-buffer",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/cmp-buffer",
- ["enabled"] = false,
- ["name"] = "cmp-buffer",
- },
- {
- "cmp-cmdline",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/cmp-cmdline",
- ["enabled"] = false,
- ["name"] = "cmp-cmdline",
- },
- {
- "cmp-emoji",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/cmp-emoji",
- ["name"] = "cmp-emoji",
- },
- {
- "cmp-nvim-lsp",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/cmp-nvim-lsp",
- ["name"] = "cmp-nvim-lsp",
- },
- {
- "cmp-nvim-lsp-signature-help",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/cmp-nvim-lsp-signature-help",
- ["name"] = "cmp-nvim-lsp-signature-help",
- },
- {
- "cmp-luasnip",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/cmp_luasnip",
- ["name"] = "cmp-luasnip",
- },
- },
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-cmp",
- ["lazy"] = false,
- ["name"] = "cmp",
- ["opts"] = function()
- local cmp = require("cmp")
- local luasnip = require("luasnip")
-
- local has_words_before = function()
- unpack = unpack or table.unpack
- local line, col = unpack(vim.api.nvim_win_get_cursor(0))
- return col ~= 0
- and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s")
- == nil
- end
-
- return {
- sources = cmp.config.sources({
- { ["name"] = "async_path" },
- { ["name"] = "emoji" },
- { ["name"] = "nvim_lsp" },
- { ["name"] = "nvim_lsp_signature_help" },
- { ["name"] = "luasnip" },
- }),
-
- snippet = {
- expand = function(args)
- require("luasnip").lsp_expand(args.body)
- end,
- },
-
- window = {
- completion = cmp.config.window.bordered(),
- documentation = cmp.config.window.bordered(),
- -- completion.border = "rounded",
- -- documentation.border = "rounded",
- },
-
- mapping = cmp.mapping.preset.insert({
- [""] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
- [""] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
- [""] = cmp.mapping.abort(),
- [""] = cmp.mapping.abort(),
- [""] = cmp.mapping.scroll_docs(-4),
- [""] = cmp.mapping.scroll_docs(4),
- [""] = cmp.mapping.complete({}),
-
- [""] = cmp.mapping.confirm({ select = true }),
-
- [""] = cmp.mapping(function(fallback)
- if cmp.visible() then
- cmp.select_next_item()
- elseif require("luasnip").expand_or_jumpable() then
- require("luasnip").expand_or_jump()
- elseif has_words_before() then
- cmp.complete()
- else
- fallback()
- end
- end, { "i", "s" }),
-
- [""] = cmp.mapping(function(fallback)
- if cmp.visible() then
- cmp.select_prev_item()
- elseif luasnip.jumpable(-1) then
- luasnip.jump(-1)
- else
- fallback()
- end
- end, { "i", "s" }),
- }),
- }
- end,
- },
- {
- "illuminate",
- ["config"] = function(_, opts)
- require("illuminate").configure(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/vim-illuminate",
- ["lazy"] = false,
- ["name"] = "illuminate",
- ["opts"] = {
- ["filetypesDenylist"] = {
- "DressingSelect",
- "Outline",
- "TelescopePrompt",
- "alpha",
- "harpoon",
- "toggleterm",
- "neo-tree",
- "Spectre",
- "reason",
- },
- },
- },
- },
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-lspconfig",
- ["lazy"] = false,
- ["name"] = "lspconfig",
- },
- {
- "web-devicons",
- ["config"] = function(_, opts)
- require("nvim-web-devicons").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-web-devicons",
- ["lazy"] = false,
- ["name"] = "web-devicons",
- },
- {
- "better-escape",
- ["config"] = function(_, opts)
- require("better_escape").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/better-escape.nvim",
- ["lazy"] = false,
- ["name"] = "better-escape",
- ["opts"] = { ["mapping"] = { "jk" }, ["timeout"] = 200 },
- },
- {
- "chadtree",
- ["config"] = function(_, opts)
- vim.api.nvim_set_var("chadtree_settings", opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/chadtree",
- ["name"] = "chadtree",
- ["opts"] = { ["theme"] = { ["text_colour_set"] = "nerdtree_syntax_dark" }, ["xdg"] = true },
- },
- {
- "comment",
- ["config"] = function(_, opts)
- require("Comment").setup(opts)
- end,
- ["dependencies"] = {
- {
- "ts-context-commentstring",
- ["config"] = function(_, opts)
- vim.g.skip_ts_context_commentstring_module = true -- Skip compatibility checks
-
- require("ts_context_commentstring").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-ts-context-commentstring",
- ["lazy"] = false,
- ["name"] = "ts-context-commentstring",
- },
- },
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/comment.nvim",
- ["name"] = "comment",
- ["opts"] = {
- ["mappings"] = { ["basic"] = true, ["extra"] = false },
- ["opleader"] = { ["block"] = "", ["line"] = "" },
- ["pre_hook"] = function()
- require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook()
- end,
- ["toggler"] = { ["block"] = "", ["line"] = "" },
- },
- },
- {
- "conform",
- ["config"] = function(_, opts)
- require("conform").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/conform.nvim",
- ["name"] = "conform",
- ["opts"] = {
- ["formatters_by_ft"] = {
- ["c"] = { "clang-format" },
- ["cpp"] = { "clang-format" },
- ["css"] = { { "prettierd", "prettier" } },
- ["h"] = { "clang-format" },
- ["hpp"] = { "clang-format" },
- ["html"] = { { "prettierd", "prettier" } },
- ["java"] = { "google-java-format" },
- ["javascript"] = { { "prettierd", "prettier" } },
- ["markdown"] = { { "prettierd", "prettier" } },
- ["nix"] = { "alejandra" },
- ["python"] = { "black" },
- ["rust"] = { "rustfmt" },
- },
- },
- },
- {
- "flash",
- ["config"] = function(_, opts)
- require("flash").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/flash.nvim",
- ["name"] = "flash",
- },
- {
- "gitmessenger",
- ["config"] = function(_, opts)
- for k, v in pairs(opts) do
- vim.g[k] = v
- end
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/git-messenger.vim",
- ["name"] = "gitmessenger",
- ["opts"] = {
- ["git_messenger_floating_win_opts"] = { ["border"] = "rounded" },
- ["git_messenger_no_default_mappings"] = true,
- },
- },
- {
- "gitsigns",
- ["config"] = function(_, opts)
- require("gitsigns").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/gitsigns.nvim",
- ["lazy"] = false,
- ["name"] = "gitsigns",
- ["opts"] = { ["current_line_blame"] = false },
- },
- {
- "headlines",
- ["config"] = function(_, opts)
- require("headlines").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/headlines.nvim",
- ["name"] = "headlines",
- },
- {
- "intellitab",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/intellitab.nvim",
- ["lazy"] = false,
- ["name"] = "intellitab",
- },
- {
- "lastplace",
- ["config"] = function(_, opts)
- require("nvim-lastplace").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-lastplace",
- ["lazy"] = false,
- ["name"] = "lastplace",
- },
- {
- "lazygit",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/lazygit.nvim",
- ["name"] = "lazygit",
- },
- {
- "lint",
- ["config"] = function(_, opts)
- local lint = require("lint")
-
- for k, v in pairs(opts) do
- lint[k] = v
- end
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-lint",
- ["lazy"] = false,
- ["name"] = "lint",
- ["opts"] = {
- ["linters_by_ft"] = {
- ["c"] = { "clang-tidy" },
- ["clojure"] = { "clj-kondo" },
- ["cpp"] = { "clang-tidy" },
- ["h"] = { "clang-tidy" },
- ["hpp"] = { "clang-tidy" },
- ["java"] = { "checkstyle" },
- ["javascript"] = { "eslint_d" },
- ["markdown"] = { "vale" },
- ["nix"] = { "statix" },
- ["python"] = { "flake8" },
- ["rust"] = { "clippy" },
- ["text"] = { "vale" },
- },
- },
- },
{
"lualine",
["config"] = function(_, opts)
require("lualine").setup(opts)
end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/lualine.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/lualine.nvim",
["lazy"] = false,
["name"] = "lualine",
["opts"] = {
@@ -473,33 +100,6 @@ require("lazy").setup({
["tabline"] = { ["lualine_a"] = { "buffers" }, ["lualine_z"] = { "tabs" } },
},
},
- {
- "luasnip",
- ["config"] = function(_, opts)
- require("luasnip").config.set_config(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/luasnip",
- ["name"] = "luasnip",
- },
- {
- "navbuddy",
- ["config"] = function(_, opts)
- local actions = require("nvim-navbuddy.actions") -- ?
- require("nvim-navbuddy").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-navbuddy",
- ["name"] = "navbuddy",
- ["opts"] = { ["lsp"] = { ["auto_attach"] = true }, ["window"] = { ["border"] = "rounded" } },
- },
- {
- "navic",
- ["config"] = function(_, opts)
- require("nvim-navic").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-navic",
- ["name"] = "navic",
- ["opts"] = { ["click"] = true, ["highlight"] = true, ["lsp"] = { ["auto_attach"] = true } },
- },
{
"noice",
["config"] = function(_, opts)
@@ -508,12 +108,12 @@ require("lazy").setup({
["dependencies"] = {
{
"nui",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nui.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nui.nvim",
["lazy"] = false,
["name"] = "nui",
},
},
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/noice.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/noice.nvim",
["lazy"] = false,
["name"] = "noice",
["opts"] = {
@@ -555,61 +155,10 @@ require("lazy").setup({
vim.notify = require("notify")
require("notify").setup(opts)
end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-notify",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-notify",
["lazy"] = false,
["name"] = "notify",
},
- {
- "autopairs",
- ["config"] = function(_, opts)
- require("nvim-autopairs").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-autopairs",
- ["lazy"] = false,
- ["name"] = "autopairs",
- },
- {
- "colorizer",
- ["config"] = function(_, opts)
- require("colorizer").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-colorizer.lua",
- ["lazy"] = false,
- ["name"] = "colorizer",
- },
- {
- "ufo",
- ["config"] = function(_, opts)
- require("ufo").setup(opts)
- end,
- ["dependencies"] = {
- {
- "promise",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/promise-async",
- ["name"] = "promise",
- },
- },
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-ufo",
- ["name"] = "ufo",
- },
- {
- "rainbow-delimiters",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/rainbow-delimiters.nvim",
- ["lazy"] = false,
- ["name"] = "rainbow-delimiters",
- },
- {
- "sandwich",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/vim-sandwich",
- ["lazy"] = false,
- ["name"] = "sandwich",
- },
- {
- "sleuth",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/vim-sleuth",
- ["lazy"] = false,
- ["name"] = "sleuth",
- },
{
"telescope",
["config"] = function(_, opts)
@@ -623,26 +172,26 @@ require("lazy").setup({
["dependencies"] = {
{
"plenary",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/plenary.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/plenary.nvim",
["name"] = "plenary",
},
{
"telescope-undo",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/telescope-undo.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/telescope-undo.nvim",
["name"] = "telescope-undo",
},
{
"telescope-ui-select",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/telescope-ui-select.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/telescope-ui-select.nvim",
["name"] = "telescope-ui-select",
},
{
"telescope-fzf-native",
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/telescope-fzf-native.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/telescope-fzf-native.nvim",
["name"] = "telescope-fzf-native",
},
},
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/telescope.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/telescope.nvim",
["lazy"] = false,
["name"] = "telescope",
["opts"] = {
@@ -658,37 +207,159 @@ require("lazy").setup({
},
},
{
- "toggleterm",
+ "which-key",
["config"] = function(_, opts)
- require("toggleterm").setup(opts)
+ require("which-key").setup(opts)
end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/toggleterm.nvim",
- ["name"] = "toggleterm",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/which-key.nvim",
+ ["lazy"] = false,
+ ["name"] = "which-key",
+ ["priority"] = 100,
+ },
+ {
+ "clangd-extensions",
+ ["config"] = function(_, opts)
+ require("clangd_extensions").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/clangd_extensions.nvim",
+ ["name"] = "clangd-extensions",
+ },
+ {
+ "conform",
+ ["config"] = function(_, opts)
+ require("conform").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/conform.nvim",
+ ["name"] = "conform",
["opts"] = {
- ["auto_scroll"] = true,
- ["close_on_exit"] = true,
- ["direction"] = "horizontal",
- ["float_opts"] = { ["border"] = "curved", ["height"] = 20, ["width"] = 80, ["winblend"] = 0 },
- ["hide_numbers"] = true,
- ["insert_mappings"] = true,
- ["open_mapping"] = "[[]]",
- ["persist_mode"] = true,
- ["shade_terminals"] = true,
- ["shell"] = "fish",
- ["start_in_insert"] = true,
- ["terminal_mappings"] = true,
+ ["formatters_by_ft"] = {
+ ["c"] = { "clang-format" },
+ ["cpp"] = { "clang-format" },
+ ["css"] = { { "prettierd", "prettier" } },
+ ["h"] = { "clang-format" },
+ ["hpp"] = { "clang-format" },
+ ["html"] = { { "prettierd", "prettier" } },
+ ["java"] = { "google-java-format" },
+ ["javascript"] = { { "prettierd", "prettier" } },
+ ["lua"] = { "stylua" },
+ ["markdown"] = { { "prettierd", "prettier" } },
+ ["nix"] = { "alejandra" },
+ ["python"] = { "black" },
+ ["rust"] = { "rustfmt" },
+ },
},
},
+ {
+ "haskell-tools",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/haskell-tools.nvim",
+ ["name"] = "haskell-tools",
+ },
+ {
+ "lint",
+ ["config"] = function(_, opts)
+ local lint = require("lint")
+
+ for k, v in pairs(opts) do
+ lint[k] = v
+ end
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-lint",
+ ["lazy"] = false,
+ ["name"] = "lint",
+ ["opts"] = {
+ ["linters_by_ft"] = {
+ ["c"] = { "clang-tidy" },
+ ["clojure"] = { "clj-kondo" },
+ ["cpp"] = { "clang-tidy" },
+ ["h"] = { "clang-tidy" },
+ ["hpp"] = { "clang-tidy" },
+ ["java"] = { "checkstyle" },
+ ["javascript"] = { "eslint_d" },
+ ["lua"] = { "luacheck" },
+ ["markdown"] = { "vale" },
+ ["nix"] = { "statix" },
+ ["python"] = { "flake8" },
+ ["rust"] = { "clippy" },
+ ["text"] = { "vale" },
+ },
+ },
+ },
+ {
+ "lspconfig",
+ ["config"] = function(_, opts)
+ local __lspOnAttach = function(client, bufnr) end
+
+ local __lspCapabilities = function()
+ capabilities = vim.lsp.protocol.make_client_capabilities()
+ capabilities =
+ vim.tbl_deep_extend("force", capabilities, require("cmp_nvim_lsp").default_capabilities())
+ return capabilities
+ end
+
+ local __setup = {
+ on_attach = __lspOnAttach,
+ capabilities = __lspCapabilities(),
+ }
+
+ for i, server in ipairs({
+ { ["name"] = "clangd" },
+ { ["name"] = "clojure_lsp" },
+ { ["name"] = "cmake" },
+ { ["name"] = "lua_ls" },
+ { ["name"] = "nil_ls" },
+ { ["name"] = "pyright" },
+ { ["name"] = "texlab" },
+ }) do
+ if type(server) == "string" then
+ require("lspconfig")[server].setup(__setup)
+ else
+ local options = server.extraOptions
+
+ if options == nil then
+ options = __setup
+ else
+ options = vim.tbl_extend("keep", options, __setup)
+ end
+
+ require("lspconfig")[server.name].setup(options)
+ end
+ end
+ end,
+ ["dependencies"] = {
+ {
+ "neodev",
+ ["config"] = function(_, opts)
+ require("neodev").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/neodev.nvim",
+ ["name"] = "neodev",
+ },
+ },
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-lspconfig",
+ ["lazy"] = false,
+ ["name"] = "lspconfig",
+ },
+ {
+ "rustaceanvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/rustaceanvim",
+ ["name"] = "rustaceanvim",
+ },
{
"treesitter",
["config"] = function(_, opts)
+ vim.opt.runtimepath:append(
+ "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/nvim-treesitter"
+ )
+ vim.opt.runtimepath:append("/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/treesitter-parsers")
+
require("nvim-treesitter.configs").setup(opts)
end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/nvim-treesitter",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-treesitter",
["lazy"] = false,
["name"] = "treesitter",
["opts"] = {
- ["highlight"] = { ["enable"] = true },
+ ["auto_install"] = false,
+ ["highlight"] = { ["additional_vim_regex_highlighting"] = false, ["enable"] = true },
["incremental_selection"] = {
["enable"] = true,
["keymaps"] = {
@@ -699,6 +370,371 @@ require("lazy").setup({
},
},
["indent"] = { ["enable"] = true },
+ ["parser_install_dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/treesitter-parsers",
+ },
+ },
+ {
+ "catppuccin",
+ ["config"] = function(_, opts)
+ require("catppuccin").setup(opts)
+
+ vim.cmd([[
+ let $BAT_THEME = "catppuccin"
+ colorscheme catppuccin
+ ]])
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/catppuccin-nvim",
+ ["lazy"] = false,
+ ["name"] = "catppuccin",
+ ["opts"] = { ["background"] = { ["dark"] = "mocha", ["light"] = "latte" }, ["flavour"] = "mocha" },
+ ["priority"] = 1000,
+ },
+ {
+ "web-devicons",
+ ["config"] = function(_, opts)
+ require("nvim-web-devicons").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-web-devicons",
+ ["lazy"] = false,
+ ["name"] = "web-devicons",
+ },
+ {
+ "better-escape",
+ ["config"] = function(_, opts)
+ require("better_escape").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/better-escape.nvim",
+ ["lazy"] = false,
+ ["name"] = "better-escape",
+ ["opts"] = { ["mapping"] = { "jk" }, ["timeout"] = 200 },
+ },
+ {
+ "chadtree",
+ ["config"] = function(_, opts)
+ vim.api.nvim_set_var("chadtree_settings", opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/chadtree",
+ ["name"] = "chadtree",
+ ["opts"] = { ["theme"] = { ["text_colour_set"] = "nerdtree_syntax_dark" }, ["xdg"] = true },
+ },
+ {
+ "cmp",
+ ["config"] = function(_, opts)
+ require("cmp").setup(opts)
+ end,
+ ["dependencies"] = {
+ {
+ "cmp-async-path",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-async-path",
+ ["name"] = "cmp-async-path",
+ },
+ {
+ "cmp-buffer",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-buffer",
+ ["enabled"] = false,
+ ["name"] = "cmp-buffer",
+ },
+ {
+ "cmp-cmdline",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-cmdline",
+ ["enabled"] = false,
+ ["name"] = "cmp-cmdline",
+ },
+ {
+ "cmp-emoji",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-emoji",
+ ["name"] = "cmp-emoji",
+ },
+ {
+ "cmp-nvim-lsp",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-nvim-lsp",
+ ["name"] = "cmp-nvim-lsp",
+ },
+ {
+ "cmp-nvim-lsp-signature-help",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help",
+ ["name"] = "cmp-nvim-lsp-signature-help",
+ },
+ {
+ "cmp-luasnip",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp_luasnip",
+ ["name"] = "cmp-luasnip",
+ },
+ },
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-cmp",
+ ["lazy"] = false,
+ ["name"] = "cmp",
+ ["opts"] = function()
+ local cmp = require("cmp")
+ local luasnip = require("luasnip")
+
+ local has_words_before = function()
+ unpack = unpack or table.unpack
+ local line, col = unpack(vim.api.nvim_win_get_cursor(0))
+ return col ~= 0
+ and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
+ end
+
+ return {
+ sources = cmp.config.sources({
+ { ["name"] = "async_path" },
+ { ["name"] = "emoji" },
+ { ["name"] = "nvim_lsp" },
+ { ["name"] = "nvim_lsp_signature_help" },
+ { ["name"] = "luasnip" },
+ }),
+
+ snippet = {
+ expand = function(args)
+ require("luasnip").lsp_expand(args.body)
+ end,
+ },
+
+ window = {
+ completion = cmp.config.window.bordered(),
+ documentation = cmp.config.window.bordered(),
+ -- completion.border = "rounded",
+ -- documentation.border = "rounded",
+ },
+
+ mapping = cmp.mapping.preset.insert({
+ [""] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
+ [""] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
+ [""] = cmp.mapping.abort(),
+ [""] = cmp.mapping.abort(),
+ [""] = cmp.mapping.scroll_docs(-4),
+ [""] = cmp.mapping.scroll_docs(4),
+ [""] = cmp.mapping.complete({}),
+
+ [""] = cmp.mapping.confirm({ select = true }),
+
+ [""] = cmp.mapping(function(fallback)
+ if cmp.visible() then
+ cmp.select_next_item()
+ elseif require("luasnip").expand_or_jumpable() then
+ require("luasnip").expand_or_jump()
+ elseif has_words_before() then
+ cmp.complete()
+ else
+ fallback()
+ end
+ end, { "i", "s" }),
+
+ [""] = cmp.mapping(function(fallback)
+ if cmp.visible() then
+ cmp.select_prev_item()
+ elseif luasnip.jumpable(-1) then
+ luasnip.jump(-1)
+ else
+ fallback()
+ end
+ end, { "i", "s" }),
+ }),
+ }
+ end,
+ },
+ {
+ "comment",
+ ["config"] = function(_, opts)
+ require("Comment").setup(opts)
+ end,
+ ["dependencies"] = {
+ {
+ "ts-context-commentstring",
+ ["config"] = function(_, opts)
+ vim.g.skip_ts_context_commentstring_module = true -- Skip compatibility checks
+
+ require("ts_context_commentstring").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-ts-context-commentstring",
+ ["lazy"] = false,
+ ["name"] = "ts-context-commentstring",
+ },
+ },
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/comment.nvim",
+ ["name"] = "comment",
+ ["opts"] = {
+ ["mappings"] = { ["basic"] = true, ["extra"] = false },
+ ["opleader"] = { ["block"] = "", ["line"] = "" },
+ ["pre_hook"] = function()
+ require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook()
+ end,
+ ["toggler"] = { ["block"] = "", ["line"] = "" },
+ },
+ },
+ {
+ "flash",
+ ["config"] = function(_, opts)
+ require("flash").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/flash.nvim",
+ ["name"] = "flash",
+ },
+ {
+ "gitmessenger",
+ ["config"] = function(_, opts)
+ for k, v in pairs(opts) do
+ vim.g[k] = v
+ end
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/git-messenger.vim",
+ ["name"] = "gitmessenger",
+ ["opts"] = {
+ ["git_messenger_floating_win_opts"] = { ["border"] = "rounded" },
+ ["git_messenger_no_default_mappings"] = true,
+ },
+ },
+ {
+ "gitsigns",
+ ["config"] = function(_, opts)
+ require("gitsigns").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/gitsigns.nvim",
+ ["lazy"] = false,
+ ["name"] = "gitsigns",
+ ["opts"] = { ["current_line_blame"] = false },
+ },
+ {
+ "illuminate",
+ ["config"] = function(_, opts)
+ require("illuminate").configure(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/vim-illuminate",
+ ["lazy"] = false,
+ ["name"] = "illuminate",
+ ["opts"] = {
+ ["filetypesDenylist"] = {
+ "DressingSelect",
+ "Outline",
+ "TelescopePrompt",
+ "alpha",
+ "harpoon",
+ "toggleterm",
+ "neo-tree",
+ "Spectre",
+ "reason",
+ },
+ },
+ },
+ {
+ "intellitab",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/intellitab.nvim",
+ ["lazy"] = false,
+ ["name"] = "intellitab",
+ },
+ {
+ "lastplace",
+ ["config"] = function(_, opts)
+ require("nvim-lastplace").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-lastplace",
+ ["lazy"] = false,
+ ["name"] = "lastplace",
+ },
+ {
+ "lazygit",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/lazygit.nvim",
+ ["name"] = "lazygit",
+ },
+ {
+ "luasnip",
+ ["config"] = function(_, opts)
+ require("luasnip").config.set_config(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/luasnip",
+ ["name"] = "luasnip",
+ },
+ {
+ "navbuddy",
+ ["config"] = function(_, opts)
+ local actions = require("nvim-navbuddy.actions") -- ?
+ require("nvim-navbuddy").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-navbuddy",
+ ["name"] = "navbuddy",
+ ["opts"] = { ["lsp"] = { ["auto_attach"] = true }, ["window"] = { ["border"] = "rounded" } },
+ },
+ {
+ "navic",
+ ["config"] = function(_, opts)
+ require("nvim-navic").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-navic",
+ ["name"] = "navic",
+ ["opts"] = { ["click"] = true, ["highlight"] = true, ["lsp"] = { ["auto_attach"] = true } },
+ },
+ {
+ "autopairs",
+ ["config"] = function(_, opts)
+ require("nvim-autopairs").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-autopairs",
+ ["lazy"] = false,
+ ["name"] = "autopairs",
+ },
+ {
+ "colorizer",
+ ["config"] = function(_, opts)
+ require("colorizer").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-colorizer.lua",
+ ["lazy"] = false,
+ ["name"] = "colorizer",
+ },
+ {
+ "ufo",
+ ["config"] = function(_, opts)
+ require("ufo").setup(opts)
+ end,
+ ["dependencies"] = {
+ {
+ "promise",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/promise-async",
+ ["name"] = "promise",
+ },
+ },
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-ufo",
+ ["name"] = "ufo",
+ },
+ {
+ "rainbow-delimiters",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/rainbow-delimiters.nvim",
+ ["lazy"] = false,
+ ["name"] = "rainbow-delimiters",
+ },
+ {
+ "sandwich",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/vim-sandwich",
+ ["lazy"] = false,
+ ["name"] = "sandwich",
+ },
+ {
+ "sleuth",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/vim-sleuth",
+ ["lazy"] = false,
+ ["name"] = "sleuth",
+ },
+ {
+ "toggleterm",
+ ["config"] = function(_, opts)
+ require("toggleterm").setup(opts)
+ end,
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/toggleterm.nvim",
+ ["lazy"] = false,
+ ["name"] = "toggleterm",
+ ["opts"] = {
+ ["auto_scroll"] = true,
+ ["close_on_exit"] = true,
+ ["direction"] = "horizontal",
+ ["float_opts"] = { ["border"] = "curved", ["height"] = 20, ["width"] = 80, ["winblend"] = 0 },
+ ["hide_numbers"] = true,
+ ["insert_mappings"] = true,
+ ["open_mapping"] = [[]],
+ ["persist_mode"] = true,
+ ["shade_terminals"] = true,
+ ["shell"] = "fish",
+ ["start_in_insert"] = true,
+ ["terminal_mappings"] = true,
},
},
{
@@ -706,7 +742,7 @@ require("lazy").setup({
["config"] = function(_, opts)
require("trim").setup(opts)
end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/trim.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/trim.nvim",
["lazy"] = false,
["name"] = "trim",
},
@@ -715,26 +751,16 @@ require("lazy").setup({
["config"] = function(_, opts)
require("trouble").setup(opts)
end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/trouble.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/trouble.nvim",
["name"] = "trouble",
},
- { "bbye", ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/vim-bbye", ["name"] = "bbye" },
- {
- "which-key",
- ["config"] = function(_, opts)
- require("which-key").setup(opts)
- end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/which-key.nvim",
- ["lazy"] = false,
- ["name"] = "which-key",
- ["priority"] = 100,
- },
+ { "bbye", ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/vim-bbye", ["name"] = "bbye" },
{
"yanky",
["config"] = function(_, opts)
require("yanky").setup(opts)
end,
- ["dir"] = "/nix/store/q4kqqb39sgasra0y3v6ci25605wqx6id-lazy-plugins/yanky.nvim",
+ ["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/yanky.nvim",
["lazy"] = false,
["name"] = "yanky",
},
@@ -886,6 +912,7 @@ do
["mode"] = "n",
["options"] = { ["desc"] = "Show help tags" },
},
+ { ["action"] = "+quit", ["key"] = "q", ["mode"] = "n" },
{ ["action"] = "+buffers", ["key"] = "b", ["mode"] = "n" },
{
["action"] = "Telescope buffers",
@@ -1090,13 +1117,20 @@ end
-- Set up autocommands {{
do
- local __nixvim_autocommands =
- { {
+ local __nixvim_autocommands = {
+ {
["callback"] = function()
require("lint").try_lint()
end,
["event"] = { "BufWritePost" },
- } }
+ },
+ {
+ ["callback"] = function()
+ require("conform").format()
+ end,
+ ["event"] = { "BufWritePre" },
+ },
+ }
for _, autocmd in ipairs(__nixvim_autocommands) do
vim.api.nvim_create_autocmd(autocmd.event, {
@@ -1119,21 +1153,21 @@ local o = vim.o
-- Neovide
if g.neovide then
- require("notify").notify("Running in NeoVide")
+ -- require("notify").notify("Running in NeoVide")
g.neovide_cursor_animate_command_line = true
g.neovide_cursor_animate_in_insert_mode = true
- g.neovide_fullscreen = false
- g.neovide_hide_mouse_when_typing = false
+ -- g.neovide_fullscreen = false
+ g.neovide_hide_mouse_when_typing = true
g.neovide_padding_top = 0
g.neovide_padding_bottom = 0
g.neovide_padding_right = 0
g.neovide_padding_left = 0
g.neovide_refresh_rate = 144
- g.neovide_theme = "light"
+ -- g.neovide_theme = "light"
-- Neovide Fonts
o.guifont = "JetBrainsMono Nerd Font:h13:Medium"
else
- require("notify").notify("Not running in NeoVide")
+ -- require("notify").notify("Not running in NeoVide")
end
diff --git a/config/neovim/refresh_config.sh b/config/neovim/refresh_config.sh
index bf1cbe86..71a84f66 100755
--- a/config/neovim/refresh_config.sh
+++ b/config/neovim/refresh_config.sh
@@ -1,3 +1,51 @@
#!/usr/bin/env bash
-cp -f $(readlink -f ~/.config/nvim/init.lua) ./config.lua
+INIT_PATH="$(readlink -f ~/.config/nvim/init.lua)"
+cp -f "$INIT_PATH" ./config.lua
+echo "Copied $INIT_PATH to ./config.lua"
+
+chmod +w ./config.lua
+echo "Fixed permission for ./config.lua"
+echo ""
+
+rm -rf ./store/*
+echo "Cleared ./store/"
+
+STORE_PATHS=$(rg -oN "\"/nix/store/.*?(lazy-plugins|vimplugin-nvim-treesitter-.*?|treesitter-parsers)\"" config.lua | uniq | sd "\"" "")
+for STORE_PATH in $STORE_PATHS
+do
+ cp -Lr "$STORE_PATH" ./store/
+ echo "Copied $STORE_PATH to ./store/"
+done
+
+chmod -R +w ./store/*
+echo "Fixed permissions for ./store"
+echo ""
+
+for IDENTIFIER in "treesitter-parsers" "lazy-plugins" "nvim-treesitter"
+do
+ CURRENT_PATH=$(eza -1 ./store | grep $IDENTIFIER)
+ mv "./store/$CURRENT_PATH" "./store/$IDENTIFIER"
+ echo "Moved ./store/$CURRENT_PATH to ./store/$IDENTIFIER"
+done
+echo ""
+
+BASE_PATH="/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store"
+for IDENTIFIER in "treesitter-parsers" "lazy-plugins" "nvim-treesitter"
+do
+ REPLACE_STRINGS=$(rg -oN "\"/nix/store/.*?$IDENTIFIER.*?\"" ./config.lua | uniq | sd "\"" "")
+ for REPLACE_STRING in $REPLACE_STRINGS
+ do
+ if [[ $REPLACE_STRING =~ .*$IDENTIFIER/.* ]];
+ then
+ # Trailing / means not the entire string can be replaced
+ REPLACE_STRING=$(dirname "$REPLACE_STRING")
+ sd "$REPLACE_STRING" "$BASE_PATH/$IDENTIFIER" ./config.lua
+ echo "Substituted $REPLACE_STRING with $BASE_PATH/$IDENTIFIER"
+ else
+ # No trailing / means the entire string can be replaced
+ sd "$REPLACE_STRING" "$BASE_PATH/$IDENTIFIER" ./config.lua
+ echo "Substituted $REPLACE_STRING with $BASE_PATH/$IDENTIFIER"
+ fi
+ done
+done
diff --git a/config/neovim/store/lazy-plugins/better-escape.nvim/.github/FUNDING.yml b/config/neovim/store/lazy-plugins/better-escape.nvim/.github/FUNDING.yml
new file mode 100644
index 00000000..3a51704d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/better-escape.nvim/.github/FUNDING.yml
@@ -0,0 +1,2 @@
+github: 'max397574'
+custom: [ 'https://buymeacoffee.com/max397574' ]
diff --git a/config/neovim/store/lazy-plugins/better-escape.nvim/.gitignore b/config/neovim/store/lazy-plugins/better-escape.nvim/.gitignore
new file mode 100644
index 00000000..e43b0f98
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/better-escape.nvim/.gitignore
@@ -0,0 +1 @@
+.DS_Store
diff --git a/config/neovim/store/lazy-plugins/better-escape.nvim/LICENSE b/config/neovim/store/lazy-plugins/better-escape.nvim/LICENSE
new file mode 100644
index 00000000..f288702d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/better-escape.nvim/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/config/neovim/store/lazy-plugins/better-escape.nvim/lua/better_escape.lua b/config/neovim/store/lazy-plugins/better-escape.nvim/lua/better_escape.lua
new file mode 100644
index 00000000..fe576ea6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/better-escape.nvim/lua/better_escape.lua
@@ -0,0 +1,175 @@
+local M = {}
+
+local api = vim.api
+
+local settings = {
+ timeout = vim.o.timeoutlen,
+ mapping = { "jk", "jj" },
+ clear_empty_lines = false,
+ ---@type string|function
+ keys = "",
+}
+
+local first_chars = {}
+local second_chars = {}
+
+---@class State
+---@field char string
+---@field modified boolean
+
+local timer
+local waiting = false
+---@type State[]
+local input_states = {}
+
+---@param tbl table table to search through
+---@param element any element to search in tbl
+---@return table indices
+--- Search for indices in tbl where element occurs
+local function get_indices(tbl, element)
+ local indices = {}
+ for idx, value in ipairs(tbl) do
+ if element == value then
+ table.insert(indices, idx)
+ end
+ end
+ return indices
+end
+
+---@param keys string keys to feed
+--- Replace keys with termcodes and feed them
+local function feed(keys, mode)
+ api.nvim_feedkeys(
+ api.nvim_replace_termcodes(keys, true, true, true),
+ mode or "n",
+ false
+ )
+end
+
+local function start_timer()
+ waiting = true
+
+ if timer then
+ timer:stop()
+ end
+
+ timer = vim.defer_fn(function()
+ waiting = false
+ end, settings.timeout)
+end
+
+local function get_keys()
+ -- if keys is string use it, else use it as a function
+ return type(settings.keys) == "string" and settings.keys or settings.keys()
+end
+
+local function check_timeout()
+ if waiting then
+ local current_line = api.nvim_get_current_line()
+ if settings.clear_empty_lines and current_line:match("^%s+j$") then
+ vim.schedule(function()
+ api.nvim_set_current_line("")
+ feed(get_keys(), "in")
+ end)
+ else
+ feed("" .. get_keys(), "in") -- delete the characters from the mapping
+ end
+
+ waiting = false -- more timely
+ return true
+ end
+ return false
+end
+
+function M.check_charaters()
+ local char = vim.v.char
+ table.insert(input_states, { char = char, modified = vim.bo.modified })
+
+ local matched = false
+ if #input_states >= 2 then
+ ---@type State
+ local prev_state = input_states[#input_states - 1]
+ local indices = get_indices(second_chars, char)
+ -- if char == second_chars[idx] and prev_char == first_chars[idx] as well
+ -- then matched = true
+ for _, idx in ipairs(indices) do
+ if first_chars[idx] == prev_state.char then
+ matched = check_timeout()
+ break
+ end
+ end
+
+ if matched then
+ input_states = {}
+ vim.schedule(function()
+ vim.bo.modified = prev_state.modified
+ end)
+ end
+ end
+
+ -- if can't find a match, and the typed char is first in a mapping, start the timeout
+ if not matched and vim.tbl_contains(first_chars, char) then
+ start_timer()
+ end
+end
+
+local function char_at(str, pos)
+ return vim.fn.nr2char(vim.fn.strgetchar(str, pos))
+end
+
+local function validate_settings()
+ assert(type(settings.mapping) == "table", "Mapping must be a table.")
+
+ for _, mapping in ipairs(settings.mapping) do
+ -- replace all multibyte chars to `A` char
+ local length = #vim.fn.substitute(mapping, ".", "A", "g")
+ assert(length == 2, "Mapping must be 2 keys.")
+ end
+
+ if settings.timeout then
+ assert(type(settings.timeout) == "number", "Timeout must be a number.")
+ assert(
+ settings.timeout >= 100,
+ "Timeout must be greater than or equal to 100."
+ )
+ end
+
+ assert(
+ vim.tbl_contains({ "string", "function" }, type(settings.keys)),
+ "Keys must be a function or string."
+ )
+end
+
+function M.setup(update)
+ settings = vim.tbl_deep_extend("force", settings, update or {})
+ -- if mapping is a string (single mapping) make it a table
+ if type(settings.mapping) == "string" then
+ settings.mapping = { settings.mapping }
+ end
+ local ok, msg = pcall(validate_settings)
+ if ok then
+ -- create tables with the first and seconds chars of the mappings
+ for _, shortcut in ipairs(settings.mapping) do
+ vim.cmd("silent! iunmap " .. shortcut)
+ table.insert(first_chars, char_at(shortcut, 0))
+ table.insert(second_chars, char_at(shortcut, 1))
+ end
+
+ vim.cmd([[
+ augroup better_escape
+ autocmd!
+ autocmd InsertCharPre * lua require"better_escape".check_charaters()
+ augroup END
+ ]])
+ else
+ vim.notify("Error(better-escape.nvim): " .. msg, vim.log.levels.ERROR)
+ end
+end
+
+return setmetatable(M, {
+ __index = function(_, k)
+ if k == "waiting" then
+ return waiting
+ end
+ end,
+})
diff --git a/config/neovim/store/lazy-plugins/better-escape.nvim/readme.md b/config/neovim/store/lazy-plugins/better-escape.nvim/readme.md
new file mode 100644
index 00000000..e8562569
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/better-escape.nvim/readme.md
@@ -0,0 +1,95 @@
+# 🚪better-escape.nvim
+
+This plugin is the lua version of [better_escape.vim](https://github.com/jdhao/better-escape.vim),
+with some additional features and optimizations
+
+A lot of people have mappings like `jk` or `jj` to escape insert mode.
+The problem with this mappings is that whenever you type a `j`, neovim wait about 100-500ms (depending on your timeoutlen) to see, if you type a `j` or a `k` because these are mapped.
+Only after that time the `j` will be inserted.
+Then you always get a delay when typing a `j`.
+
+This looks like this (see below for a gif):
+
+
+
+## ✨Features
+
+- Escape without getting delay when typing in insert mode
+- Customizable mapping and timeout
+- Use multiple mappings
+- Really small and fast
+
+## 📦Installation
+
+Use your favourite package manager and call the setup function.
+
+```lua
+-- lua with packer.nvim
+use {
+ "max397574/better-escape.nvim",
+ config = function()
+ require("better_escape").setup()
+ end,
+}
+```
+
+## ⚙️Customization
+
+Call the setup function with your options as arguments.
+
+```lua
+-- lua, default settings
+require("better_escape").setup {
+ mapping = {"jk", "jj"}, -- a table with mappings to use
+ timeout = vim.o.timeoutlen, -- the time in which the keys must be hit in ms. Use option timeoutlen by default
+ clear_empty_lines = false, -- clear line after escaping if there is only whitespace
+ keys = "", -- keys used for escaping, if it is a function will use the result everytime
+ -- example(recommended)
+ -- keys = function()
+ -- return vim.api.nvim_win_get_cursor(0)[2] > 1 and 'l' or ''
+ -- end,
+}
+```
+
+## API
+
+`require("better_escape").waiting` is a boolean indicating that it's waiting for
+a mapped sequence to complete.
+
+
+statusline example
+
+```lua
+function escape_status()
+ local ok, m = pcall(require, 'better_escape')
+ return ok and m.waiting and '✺' or ""
+end
+```
+
+
+
+## 👀Demo
+
+
+
+
+
+## 🎓How it works
+
+With the mappings there are two tables created.
+One contains all first characters and one all second characters.
+Whenever you type a character the plugin checks if it's in any of the two tables
+If it is in the first one, the plugin starts a timer.
+If it is in the second, the plugin checks whether the character you typed before is in the table with the first characters.
+
+If this is the case the plugin gets all the indices where the characters are in the tables, then is searches for matches.
+If there is a match, that means that there is a mapping which has the typed character as second and the previous typed character as first character.
+The plugin then checks if the time passed since the first character was types is smaller than `timoutlen`.
+If this is the case the two characters get deleted and `keys` get feed or executed.
+
+Like this it is possible that the characters really get inserted and therefore you have no delay after typing one of the characters of your mapping.
+With the `timeoutlen` it's still possible to type the characters of your mappings.
+
+## ❤️ Support
+If you like the projects I do and they can help you in your life you can support my work with [github sponsors](https://github.com/sponsors/max397574).
+Every support motivates me to continue working on my open source projects.
diff --git a/config/neovim/store/lazy-plugins/better-escape.nvim/stylua.toml b/config/neovim/store/lazy-plugins/better-escape.nvim/stylua.toml
new file mode 100644
index 00000000..ddca0551
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/better-escape.nvim/stylua.toml
@@ -0,0 +1,5 @@
+column_width = 80
+indent_type = "Spaces"
+indent_width = 4
+quote_style = "AutoPreferDouble"
+no_call_parentheses = false
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.editorconfig b/config/neovim/store/lazy-plugins/catppuccin-nvim/.editorconfig
new file mode 100644
index 00000000..fe7a099f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.editorconfig
@@ -0,0 +1,18 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# EditorConfig is awesome: https://EditorConfig.org
+
+root = true
+
+[*]
+end_of_line = lf
+charset = utf-8
+insert_final_newline = true
+
+[*.lua]
+indent_style = tab
+
+[*.{diff,md}]
+trim_trailing_whitespace = false
+indent_style = space
+indent_size = 4
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/ISSUE_TEMPLATE/bug_report.yml b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 00000000..58434501
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,93 @@
+name: Bug report
+description: Report a problem with Catppuccin
+labels: [bug]
+body:
+ - type: textarea
+ attributes:
+ label: "Description"
+ description: "A short description of the problem you are reporting."
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: "Neovim version"
+ description: "Output of `nvim --version` (Catppuccin requires neovim >= 0.8)"
+ render: markdown
+ placeholder: |
+ NVIM v0.9.0
+ Build type: Release
+ LuaJIT 2.1.0-beta3
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: "Terminal and multiplexer"
+ placeholder: "kitty 0.29.2 with tmux 3.3a"
+ validations:
+ required: true
+ - type: markdown
+ attributes:
+ value: |
+ # FOR TMUX USERS
+ FOLLOW THESE GIST BEFORE OPENING THE ISSUE
+ - [Enable true color support](https://gist.github.com/andersevenrud/015e61af2fd264371032763d4ed965b6) to fix the [abnormal colors](https://github.com/catppuccin/nvim/issues/415)
+ - [Enable italic font support](https://gist.github.com/gyribeiro/4192af1aced7a1b555df06bd3781a722) to fix the [incorrect if, then, else, end highlights](https://github.com/catppuccin/nvim/issues/428)
+ - type: input
+ attributes:
+ label: "Catppuccin version / branch / rev"
+ placeholder: "catppuccin v1.4.0"
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: "Steps to reproduce"
+ description: "Steps to reproduce using the minimal config provided below."
+ placeholder: |
+ 1. `nvim -u repro.lua`
+ 2. ...
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: "Expected behavior"
+ description: "A description of the behavior you expected:"
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: "Actual behavior"
+ description: "Observed behavior (may optionally include logs, images, or videos)."
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Repro
+ description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
+ value: |
+ -- DO NOT change the paths and don't remove the colorscheme
+ local root = vim.fn.fnamemodify("./.repro", ":p")
+
+ -- set stdpaths to use .repro
+ for _, name in ipairs({ "config", "data", "state", "cache" }) do
+ vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
+ end
+
+ -- bootstrap lazy
+ local lazypath = root .. "/plugins/lazy.nvim"
+ if not vim.loop.fs_stat(lazypath) then
+ vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath })
+ end
+ vim.opt.runtimepath:prepend(lazypath)
+
+ -- install plugins
+ local plugins = {
+ "catppuccin/nvim",
+ -- add any other plugins here
+ }
+ require("lazy").setup(plugins, {
+ root = root .. "/plugins",
+ })
+
+ vim.cmd.colorscheme("catppuccin")
+ -- add anything else here
+ render: Lua
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/ISSUE_TEMPLATE/config.yml b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 00000000..133a9bb2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Question
+ url: https://discord.com/servers/catppuccin-907385605422448742
+ about: Join our discord server for real-time answers and more!
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/ISSUE_TEMPLATE/feature_request.md b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 00000000..8341b4ad
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: "Suggest an idea for the project"
+title: ""
+labels: enhancement
+assignees: ""
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is.
+Ex. I'm always frustrated when [...]. My workflow is like this [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
\ No newline at end of file
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/PULL_REQUEST_TEMPLATE.md b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 00000000..fe96cc9e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,16 @@
+🎉 First off, thanks for taking the time to contribute! 🎉
+
+Here are some guidelines:
+- Format code using [stylua](https://github.com/johnnymorganz/stylua).
+- New plugin integration should be added in alphabetical order:
+ - to the [README](https://github.com/catppuccin/nvim#integrations) (vimdoc is auto-generated).
+ - to [types.lua](https://github.com/catppuccin/nvim/blob/main/lua/catppuccin/types.lua)
+- Create a topic branch on your fork for your specific PR.
+- Use [conventionalcommits.org's](https://www.conventionalcommits.org/en/v1.0.0/)
+ rules for explicit and meaningful commit messages.
+- If it's your first time contributing to a project, then read
+ [About pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests)
+ on Github's docs.
+
+Here are some tips:
+- Use `vim.g.catppuccin_debug = true` to get live config re-loading
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/scripts/update-palette.py b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/scripts/update-palette.py
new file mode 100644
index 00000000..dbf773fa
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/scripts/update-palette.py
@@ -0,0 +1,14 @@
+import json
+import urllib.request
+
+url = "https://github.com/catppuccin/palette/raw/main/palette.json"
+
+with urllib.request.urlopen(url) as response:
+ flavors = json.loads(response.read().decode())
+
+for flavor in flavors:
+ with open(f"lua/catppuccin/palettes/{flavor}.lua", "w") as f:
+ f.write("return {\n")
+ for color in flavors[flavor]["colors"]:
+ f.write(f'\t{color} = "{flavors[flavor]["colors"][color]["hex"]}",\n')
+ f.write("}\n")
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/formatting.yml b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/formatting.yml
new file mode 100644
index 00000000..fba8cdf4
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/formatting.yml
@@ -0,0 +1,20 @@
+name: StyLua
+on:
+ pull_request:
+ push:
+ paths-ignore:
+ - "*.md"
+ branches:
+ - main
+
+jobs:
+ stylua:
+ name: StyLua
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: JohnnyMorganz/stylua-action@v2
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ version: latest
+ args: --check --config-path=stylua.toml .
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/neovim.yml b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/neovim.yml
new file mode 100644
index 00000000..53ddbc59
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/neovim.yml
@@ -0,0 +1,55 @@
+---
+name: Neovim
+on:
+ pull_request:
+ push:
+ paths-ignore:
+ - "*.md"
+ branches:
+ - main
+
+jobs:
+ ubuntu:
+ name: Ubuntu
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install Neovim
+ uses: MunifTanjim/setup-neovim-action@v1
+ with:
+ tag: nightly
+ - name: Run neovim
+ run: |
+ nvim --version
+ nvim --headless -u tests/init.lua +q
+ macos:
+ name: Macos
+ runs-on: macos-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install Neovim
+ run: |
+ wget -q https://github.com/neovim/neovim/releases/download/nightly/nvim-macos-x86_64.tar.gz
+ xattr -c ./nvim-macos-x86_64.tar.gz
+ tar xzvf nvim-macos-x86_64.tar.gz &> /dev/null
+ ln -s $(pwd)/nvim-macos-x86_64/bin/nvim /usr/local/bin/nvim
+ - name: Run neovim
+ run: |
+ nvim --version
+ nvim --headless -u tests/init.lua +q
+ windows:
+ name: Windows
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install Neovim
+ run: |
+ C:\msys64\usr\bin\wget.exe -q https://github.com/neovim/neovim/releases/download/nightly/nvim-win64.zip
+ 7z x nvim-win64.zip
+ Add-Content $env:GITHUB_PATH ".\nvim-win64\bin\"
+ - name: Run neovim
+ run: |
+ nvim --version
+ nvim --headless -u tests/init.lua +q
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/palette.yml b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/palette.yml
new file mode 100644
index 00000000..31aa5cb3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/palette.yml
@@ -0,0 +1,30 @@
+name: Palette
+
+on:
+ push:
+ workflow_dispatch:
+ schedule:
+ - cron: '0 0 * * *' # Run every day at midnight UTC
+
+jobs:
+ createPullRequest:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Make changes to pull request
+ run: python3 ./.github/scripts/update-palette.py
+
+ - name: Create Pull Request
+ id: cpr
+ uses: peter-evans/create-pull-request@v5
+ with:
+ commit-message: 'feat: auto-sync upstream palettes'
+ committer: GitHub
+ author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
+ signoff: false
+ branch: new-palettes
+ delete-branch: true
+ title: 'feat: auto-sync upstream palettes'
+ body: |
+ Auto-update `lua/catppuccin/palettes/` based on https://github.com/catppuccin/palette/blob/main/palette.json
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/pandocvim.yml b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/pandocvim.yml
new file mode 100644
index 00000000..789a326b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/pandocvim.yml
@@ -0,0 +1,26 @@
+name: panvimdoc
+
+on:
+ push:
+ paths:
+ - '**.md'
+
+jobs:
+ docs:
+ runs-on: ubuntu-latest
+ name: pandoc to vimdoc
+ steps:
+ - uses: actions/checkout@v4
+ - name: panvimdoc
+ uses: kdheepak/panvimdoc@main
+ with:
+ vimdoc: catppuccin
+ description: "Soothing pastel theme for NeoVim"
+ pandoc: "README.md"
+ toc: true
+ version: "nvim >= 0.8.0"
+ treesitter: true
+ - uses: stefanzweifel/git-auto-commit-action@v4
+ with:
+ commit_message: "docs: auto generate vimdoc"
+ branch: ${{ github.head_ref }}
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/release.yml b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/release.yml
new file mode 100644
index 00000000..f7ed8fa3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/release.yml
@@ -0,0 +1,29 @@
+name: release
+
+on:
+ push:
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+ release:
+ name: release
+ if: ${{ github.ref == 'refs/heads/main' }}
+ runs-on: ubuntu-latest
+ steps:
+ - uses: google-github-actions/release-please-action@v3
+ id: release
+ with:
+ release-type: simple
+ package-name: catppuccin
+ - uses: actions/checkout@v4
+ - name: tag stable versions
+ if: ${{ steps.release.outputs.release_created }}
+ run: |
+ git config user.name github-actions[bot]
+ git config user.email github-actions[bot]@users.noreply.github.com
+ git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/google-github-actions/release-please-action.git"
+ git tag -d stable || true
+ git push origin :stable || true
+ git tag -a stable -m "Last Stable Release"
+ git push origin stable
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/tests.yml b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/tests.yml
new file mode 100644
index 00000000..f87e5c05
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/tests.yml
@@ -0,0 +1,42 @@
+---
+name: Tests
+on:
+ pull_request:
+ push:
+ paths-ignore:
+ - "*.md"
+ branches:
+ - main
+ workflow_dispatch:
+ schedule:
+ - cron: '0 0 * * *' # Run every day at midnight UTC
+
+jobs:
+ ubuntu:
+ name: Plenary
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ path: nvim
+ - uses: actions/checkout@v4
+ with:
+ ref: user-configs
+ path: user-configs
+ - run: |
+ mv user-configs/tests/* nvim/tests/
+ - name: Install Neovim
+ uses: MunifTanjim/setup-neovim-action@v1
+ with:
+ tag: nightly
+ - name: Fetch dependencies
+ run: |
+ git clone --depth 1 https://github.com/nvim-lua/plenary.nvim ~/.local/share/nvim/site/pack/vendor/start/plenary.nvim
+ ln -s $(pwd) ~/.local/share/nvim/site/pack/vendor/start
+ - name: Run tests
+ working-directory: ./nvim
+ run: |
+ nvim --version
+ [ ! -d tests ] && exit 0
+ nvim --headless -u tests/minimal_init.vim -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/minimal_init.vim', sequential = true}"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/vim.yml b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/vim.yml
new file mode 100644
index 00000000..469a6fea
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.github/workflows/vim.yml
@@ -0,0 +1,58 @@
+---
+name: Vim
+on:
+ pull_request:
+ push:
+ paths-ignore:
+ - "*.md"
+ branches:
+ - main
+
+jobs:
+ ubuntu:
+ name: Ubuntu
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install Vim
+ shell: bash
+ run: |
+ sudo apt-get update
+ sudo apt-get install vim-gtk lua5.4
+ curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
+ - name: Run vim
+ run: |
+ vim --version
+ vim -u tests/init.vim
+ macos:
+ name: Macos
+ runs-on: macos-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install Vim
+ run: |
+ brew install vim
+ curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
+ - name: Run vim
+ run: |
+ vim --version
+ vim -u tests/init.vim
+ windows:
+ name: Windows
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install Vim
+ run: |
+ choco install vim
+ C:\msys64\usr\bin\wget.exe -q https://downloads.sourceforge.net/project/luabinaries/5.4.2/Tools%20Executables/lua-5.4.2_Win64_bin.zip
+ 7z x lua-5.4.2_Win64_bin.zip
+ move lua54.dll C:\Windows\System32\
+ iwr -useb https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim |`
+ ni $HOME/vimfiles/autoload/plug.vim -Force
+ - name: Run vim
+ run: |
+ vim --version
+ gvim -u tests/init.vim
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/.gitignore b/config/neovim/store/lazy-plugins/catppuccin-nvim/.gitignore
new file mode 100644
index 00000000..4ebdfaa8
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/.gitignore
@@ -0,0 +1,4 @@
+doc/tags
+.vscode/
+.DS_Store
+.repro
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/CHANGELOG.md b/config/neovim/store/lazy-plugins/catppuccin-nvim/CHANGELOG.md
new file mode 100644
index 00000000..b717dca3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/CHANGELOG.md
@@ -0,0 +1,166 @@
+# Changelog
+
+## [1.7.0](https://github.com/catppuccin/nvim/compare/v1.6.0...v1.7.0) (2024-04-13)
+
+
+### Features
+
+* add ability to toggle default integrations ([#687](https://github.com/catppuccin/nvim/issues/687)) ([e60e400](https://github.com/catppuccin/nvim/commit/e60e400c411519f29e203185ddda121d4ec8ef57))
+* add support for `outline.nvim` plugin ([#647](https://github.com/catppuccin/nvim/issues/647)) ([048c18f](https://github.com/catppuccin/nvim/commit/048c18fc531703815f5e10765ea46ce9b2c75ae4))
+* **defaults:** enable neotree ([c536623](https://github.com/catppuccin/nvim/commit/c536623eac60f8443c93ae4ca0e03b51574b5f50))
+* **defaults:** enable treesitter context ([dc392c0](https://github.com/catppuccin/nvim/commit/dc392c067739326c3cff380a8c52b0f31319e6dd)), closes [#683](https://github.com/catppuccin/nvim/issues/683)
+* **feline:** fix feline integration ([#685](https://github.com/catppuccin/nvim/issues/685)) ([07679af](https://github.com/catppuccin/nvim/commit/07679af1af4f446655682ee2557b5840ac551504))
+* **feline:** improve feline lsp display ([#688](https://github.com/catppuccin/nvim/issues/688)) ([f66654d](https://github.com/catppuccin/nvim/commit/f66654d5d5190865333e8e46474c1593302c558e))
+* **integration:** add reactive.nvim integration ([#654](https://github.com/catppuccin/nvim/issues/654)) ([151e478](https://github.com/catppuccin/nvim/commit/151e478edf8108cfd451a3cbd44d0a20503e7b42))
+* **lsp:** add highlight for `LspCodeLensSeparator` ([#693](https://github.com/catppuccin/nvim/issues/693)) ([02bdd74](https://github.com/catppuccin/nvim/commit/02bdd749931a5d739063562e57531c118e081882))
+* set `[@comment](https://github.com/comment).warning` that does not affect readability in gitcommit ([#675](https://github.com/catppuccin/nvim/issues/675)) ([045e349](https://github.com/catppuccin/nvim/commit/045e3499d9ec8d84635fb08877ae44fd33f6a38d))
+* **treesitter:** add styles.miscs to disable hardcoded italics ([#659](https://github.com/catppuccin/nvim/issues/659)) ([c0de3b4](https://github.com/catppuccin/nvim/commit/c0de3b46811fe1ce3912e2245a9dfbea6b41c300))
+* **treesitter:** follow upstream captures ([#630](https://github.com/catppuccin/nvim/issues/630)) ([f288876](https://github.com/catppuccin/nvim/commit/f288876c6d05d3bb91b0e72b8031fe9e26ef05b8))
+* **treesitter:** follow upstream captures ([#694](https://github.com/catppuccin/nvim/issues/694)) ([08c6417](https://github.com/catppuccin/nvim/commit/08c6417bdc3b29e5f8c53e2cfe4067f288d49a54))
+* use a more distinguishable color for todos ([#645](https://github.com/catppuccin/nvim/issues/645)) ([657cc4f](https://github.com/catppuccin/nvim/commit/657cc4f35cf193cadac7e5471eb802c97e7a1b59))
+
+
+### Bug Fixes
+
+* **compile:** string.dump isn't deterministic ([836de8b](https://github.com/catppuccin/nvim/commit/836de8bc1898250b69332e66cbe993058870f849)), closes [#664](https://github.com/catppuccin/nvim/issues/664)
+* **dropbar:** correct keyword highlight link ([#652](https://github.com/catppuccin/nvim/issues/652)) ([afab7ec](https://github.com/catppuccin/nvim/commit/afab7ec2a79c7127627dede79c0018b6e45663d0))
+* ensure consistency between JSX and HTML markup ([#660](https://github.com/catppuccin/nvim/issues/660)) ([9703f22](https://github.com/catppuccin/nvim/commit/9703f227bfab20d04bcee62d2f08f1795723b4ae))
+* **flavour:** g:catppuccin_flavour backwards compatibility ([fc98570](https://github.com/catppuccin/nvim/commit/fc98570d85ae772e56dc42cf8d7d6a497a909bdb))
+* **flavour:** respect terminal's background ([#696](https://github.com/catppuccin/nvim/issues/696)) ([d5760c5](https://github.com/catppuccin/nvim/commit/d5760c53ae3b48f0f539298ec4165adc5c0afb19))
+* **illuminate:** update type ([#690](https://github.com/catppuccin/nvim/issues/690)) ([30930f9](https://github.com/catppuccin/nvim/commit/30930f9656cffd068bcf52ced70cdfffd1e83a44))
+* **integrations:** respect default options ([c2e6f8e](https://github.com/catppuccin/nvim/commit/c2e6f8e7eb8d0ebf55700c89bdf842809aeecf09))
+* **neotree:** add `NeoTreeModified` ([#642](https://github.com/catppuccin/nvim/issues/642)) ([6853cc8](https://github.com/catppuccin/nvim/commit/6853cc8e6efc76e85e10ec153d05fc2520653508))
+* **neotree:** blend sidebar with win separator ([56fb982](https://github.com/catppuccin/nvim/commit/56fb98218d22d5c326387bf9e4076227e7372e6b)), closes [#670](https://github.com/catppuccin/nvim/issues/670)
+* repair treesitter underlined text (`Underline` -> `Underlined`) ([#663](https://github.com/catppuccin/nvim/issues/663)) ([42b687c](https://github.com/catppuccin/nvim/commit/42b687c42a35633366ed45e562bf921fb914048b))
+* respect background variable on startup ([6b7a4df](https://github.com/catppuccin/nvim/commit/6b7a4dfdf241c8be0af6ec691b302e85cce03cab))
+* **semantic_tokens:** namespace -> module ([196f301](https://github.com/catppuccin/nvim/commit/196f301de06090c40d7f98297675ac38ae7d6675))
+* **treesitter:** some captures missing leading `@` ([#650](https://github.com/catppuccin/nvim/issues/650)) ([bc1f215](https://github.com/catppuccin/nvim/commit/bc1f2151f23227ba02ac203c2c59ad693352a741))
+* use external index for lsp counting ([c3572a9](https://github.com/catppuccin/nvim/commit/c3572a968a79b64bd0ef16f2c3e93014f112e66d))
+* wrong color shown when using color_overrides ([#658](https://github.com/catppuccin/nvim/issues/658)) ([b76ada8](https://github.com/catppuccin/nvim/commit/b76ada82bf2019d5e343018b4104cc9266900c16)), closes [#657](https://github.com/catppuccin/nvim/issues/657)
+
+## [1.6.0](https://github.com/catppuccin/nvim/compare/v1.5.0...v1.6.0) (2023-12-28)
+
+
+### Features
+
+* add `WinSeparator` highlight group ([#623](https://github.com/catppuccin/nvim/issues/623)) ([988c0b2](https://github.com/catppuccin/nvim/commit/988c0b2dde4140572ed37c6b8b5d5deac0219f9f))
+* **bufferline:** support `no_underline` option ([#601](https://github.com/catppuccin/nvim/issues/601)) ([f7638a1](https://github.com/catppuccin/nvim/commit/f7638a1a65cbffdd01a9ddac0018a20ec4be29e2))
+* **dashboard:** add highlight groups for `doom` theme ([#593](https://github.com/catppuccin/nvim/issues/593)) ([3bdd5e8](https://github.com/catppuccin/nvim/commit/3bdd5e8296971f8c7ba5e499dac8247c3d621508))
+* **integrations:** enable dap & dap_ui by default ([64dc309](https://github.com/catppuccin/nvim/commit/64dc309bc157779691be38bbfc5123584e0a4a85))
+* **lualine:** darken lualine `b` section for better readability ([#606](https://github.com/catppuccin/nvim/issues/606)) ([32ee05d](https://github.com/catppuccin/nvim/commit/32ee05d014a4611555c7f56a73283efb4718d9c5))
+* **mini.indentscope:** add scope color ([#592](https://github.com/catppuccin/nvim/issues/592)) ([795f639](https://github.com/catppuccin/nvim/commit/795f639ac50d6b8400c1d5868fca54844d579f37))
+* **neogit:** support new highlight groups ([#610](https://github.com/catppuccin/nvim/issues/610)) ([f90c7c0](https://github.com/catppuccin/nvim/commit/f90c7c0c467722dc7acacbae3c3904720e09efb6))
+* **notify:** add `NotifyBackground` hl group ([#637](https://github.com/catppuccin/nvim/issues/637)) ([c7cf3af](https://github.com/catppuccin/nvim/commit/c7cf3afe2eb6d9058eec4abb3ace2c1da006478a))
+
+
+### Bug Fixes
+
+* **airline:** missing refresh function ([dcef0a0](https://github.com/catppuccin/nvim/commit/dcef0a062de380885193fb0f919217d58b979753)), closes [#594](https://github.com/catppuccin/nvim/issues/594)
+* **dashboard:** `orange` -> `peach` ([54002a1](https://github.com/catppuccin/nvim/commit/54002a1adfd543f54352b3ec79d4e62c4163e9ee))
+* **flash:** link `FlashPrompt` to `NormalFloat` ([#605](https://github.com/catppuccin/nvim/issues/605)) ([40dc9f0](https://github.com/catppuccin/nvim/commit/40dc9f0621c55bd40da4ad0731fac44d15bb393a))
+* **lualine:** match lualine mode colors for insert and terminal ([#597](https://github.com/catppuccin/nvim/issues/597)) ([ea52fe8](https://github.com/catppuccin/nvim/commit/ea52fe8a0b1e4a820df0d0cf9a6a5a0e18c3eaa0))
+* **neogit:** remove `NeogitCursorLine` from integration ([#613](https://github.com/catppuccin/nvim/issues/613)) ([5e4be43](https://github.com/catppuccin/nvim/commit/5e4be43e1a6acb044d5c55cd10f22461c40656ed))
+* **neogit:** remove diff context highlight fg ([1b40f07](https://github.com/catppuccin/nvim/commit/1b40f072305be71b73c730ff5c7d881e638fd040)), closes [#627](https://github.com/catppuccin/nvim/issues/627)
+* **neogit:** tweak diff context highlighting ([#614](https://github.com/catppuccin/nvim/issues/614)) ([cc717ac](https://github.com/catppuccin/nvim/commit/cc717acba29259d578548973c41448b092453c52))
+* **neotree:** change color of untracked files ([#608](https://github.com/catppuccin/nvim/issues/608)) ([d7521f6](https://github.com/catppuccin/nvim/commit/d7521f6050b94cb0e23067f63829d86886f870fe))
+* **neotree:** make popup titlebar text visible ([#618](https://github.com/catppuccin/nvim/issues/618)) ([919d1f7](https://github.com/catppuccin/nvim/commit/919d1f786338ebeced798afbf28cd085cd54542a))
+* **noice:** respect transparency ([#632](https://github.com/catppuccin/nvim/issues/632)) ([4fbab1f](https://github.com/catppuccin/nvim/commit/4fbab1f01488718c3d54034a473d0346346b90e3))
+* **selene:** allow mixed tables ([#611](https://github.com/catppuccin/nvim/issues/611)) ([9f3c13b](https://github.com/catppuccin/nvim/commit/9f3c13bbcf16fcaec3a429c03743a13e5923f3e3))
+* sync focused and unfocused winbars ([#628](https://github.com/catppuccin/nvim/issues/628)) ([079500a](https://github.com/catppuccin/nvim/commit/079500a625f3ae5aa6efb758f1a17fe4c7a57e52))
+* **vim:** resolve deprecation of nested [[ ([7a4bcda](https://github.com/catppuccin/nvim/commit/7a4bcdadafc59a5bedbd866c643fa486d8cca4a1))
+
+## [1.5.0](https://github.com/catppuccin/nvim/compare/v1.4.0...v1.5.0) (2023-09-29)
+
+
+### Features
+
+* add kitty detection ([d3da439](https://github.com/catppuccin/nvim/commit/d3da43907d1896ba3e68a62f18820d1d12574317))
+* add ufo integration ([1f53686](https://github.com/catppuccin/nvim/commit/1f536869b1a2ca1710fc892db84d7e8bbc6ad8d9))
+* add workaround for kitty transparent issue ([#579](https://github.com/catppuccin/nvim/issues/579)) ([f36fa5c](https://github.com/catppuccin/nvim/commit/f36fa5cdce162450df88298a16631eeed16b68a3))
+* **compile:** use indexed cmd ([85e9360](https://github.com/catppuccin/nvim/commit/85e93601e0f0b48aa2c6bbfae4d0e9d7a1898280))
+* **illuminate:** enabled by default and optional lsp option ([5b44baa](https://github.com/catppuccin/nvim/commit/5b44baa4aff0ff45c042620ee960d283a79807a1)), closes [#571](https://github.com/catppuccin/nvim/issues/571)
+* **indent-blankline:** update to v3, add scope color ([#585](https://github.com/catppuccin/nvim/issues/585)) ([f04336b](https://github.com/catppuccin/nvim/commit/f04336ba4a2400ee2c5250068b39541652c0962f))
+* **integrations:** add NormalNvim ([0e3c128](https://github.com/catppuccin/nvim/commit/0e3c128eea8a7de692778d52b8429817df5c9040)), closes [#580](https://github.com/catppuccin/nvim/issues/580)
+* **integrations:** add notifier.nvim ([d029098](https://github.com/catppuccin/nvim/commit/d029098e124f6201a07298c0c1c499ed8d5aef76)), closes [#574](https://github.com/catppuccin/nvim/issues/574)
+* **lib:** soft deprecate highlighter ([8202348](https://github.com/catppuccin/nvim/commit/82023485fec1703d6f700a4b2a92fd431d4882f4))
+* **syntax:** respect style guide part 3 ([#576](https://github.com/catppuccin/nvim/issues/576)) ([81096ca](https://github.com/catppuccin/nvim/commit/81096cabe67f360acb06d64c0f7db8dd840afeba))
+
+
+### Bug Fixes
+
+* **coc:** improve inlay hints ([#582](https://github.com/catppuccin/nvim/issues/582)) ([3d9a5ed](https://github.com/catppuccin/nvim/commit/3d9a5ed556e289bce6c1fb0af89ec838360641b2))
+* **editor:** invisible fold with transparent ([1c15c5e](https://github.com/catppuccin/nvim/commit/1c15c5e51a998c9198d63c6d2b75e9d1e4a84541)), closes [#577](https://github.com/catppuccin/nvim/issues/577)
+* **template:** broken tmux italic gist link ([128e0d2](https://github.com/catppuccin/nvim/commit/128e0d27946491da979e2e04f5a4acf330ccdefd))
+* **treesitter:** invalid string in type builtin ([135f9b0](https://github.com/catppuccin/nvim/commit/135f9b01386fa18da6d75c16ceb83e1aa3669430))
+* **ufo:** use folded ellipsis ([846388d](https://github.com/catppuccin/nvim/commit/846388d137590e653390ce2f84fea5351a7516ac))
+* **vim:** add vim.env index ([1786287](https://github.com/catppuccin/nvim/commit/17862877792db104d48c3260aec0ace92d55f863))
+
+
+### Performance Improvements
+
+* **compile:** reduce else statement ([a937d54](https://github.com/catppuccin/nvim/commit/a937d546f4783a1ff67f84043d2d7871ad4ecd83))
+
+## [1.4.0](https://github.com/catppuccin/nvim/compare/v1.3.0...v1.4.0) (2023-08-21)
+
+
+### Features
+
+* add ability to enable/disable all integrations by default ([#552](https://github.com/catppuccin/nvim/issues/552)) ([737f60a](https://github.com/catppuccin/nvim/commit/737f60a3a25c79d9bb9574092f6c6c958a3d747a))
+* add flash.nvim integration ([#550](https://github.com/catppuccin/nvim/issues/550)) ([381eddd](https://github.com/catppuccin/nvim/commit/381edddc4ad12126cfa7276818bca07c3d5606ed))
+* enable neogit by default ([91f9f6f](https://github.com/catppuccin/nvim/commit/91f9f6fb413caff2bd06e326ec174deee1c1b7a9)), closes [#568](https://github.com/catppuccin/nvim/issues/568)
+* **flash:** enable by default ([#551](https://github.com/catppuccin/nvim/issues/551)) ([a84ee18](https://github.com/catppuccin/nvim/commit/a84ee1848bfac4601771805396552bdbaa0a0e91))
+* **gitsigns:** Support GitSignsCurrentLineBlame highlights ([#567](https://github.com/catppuccin/nvim/issues/567)) ([3fdd394](https://github.com/catppuccin/nvim/commit/3fdd3942567503d23b65ccc21e7d7757334defd5))
+* **lspsaga:** support v0.3 ([#543](https://github.com/catppuccin/nvim/issues/543)) ([3ffd2f5](https://github.com/catppuccin/nvim/commit/3ffd2f511f3dc6c01258923d7170ccaf1445634b))
+* **lspsaga:** upstream new hl groups ([#544](https://github.com/catppuccin/nvim/issues/544)) ([e0dd3f9](https://github.com/catppuccin/nvim/commit/e0dd3f9bb1513c98ab4ef9404ea26e18babf858a))
+* **neogit:** update highlights ([#545](https://github.com/catppuccin/nvim/issues/545)) ([#549](https://github.com/catppuccin/nvim/issues/549)) ([371430f](https://github.com/catppuccin/nvim/commit/371430f32f2637d2dd5796399b3982d4cada61d8))
+* **telescope:** make nvchad style great again ([#538](https://github.com/catppuccin/nvim/issues/538)) ([51961da](https://github.com/catppuccin/nvim/commit/51961da41e8189ca6f9ed73f37dfa83087b4e65c))
+* **treesitter-context:** add color for normal background ([#564](https://github.com/catppuccin/nvim/issues/564)) ([b1caff9](https://github.com/catppuccin/nvim/commit/b1caff988fb395c0aae585cecff58b1ffa0a21c6))
+
+
+### Bug Fixes
+
+* don't highlight fg of `PmenuSel` ([#554](https://github.com/catppuccin/nvim/issues/554)) ([6425df1](https://github.com/catppuccin/nvim/commit/6425df128d46f2db2cccf9aa7a66ca2823c1d153))
+* highlight NonText characters ([#547](https://github.com/catppuccin/nvim/issues/547)) ([bfe91df](https://github.com/catppuccin/nvim/commit/bfe91dfb3a19ffd4445e43611fcde68acbb3fed4))
+* **integration_default:** hotfix for [#559](https://github.com/catppuccin/nvim/issues/559) ([4913a8b](https://github.com/catppuccin/nvim/commit/4913a8b47554a89a71ed44da39fc1f6e5c2841c3))
+* **integration_default:** override `enabled` key only if integration has one ([#559](https://github.com/catppuccin/nvim/issues/559)) ([9709f82](https://github.com/catppuccin/nvim/commit/9709f8251a40e874238d6f9436cf4fba654b60e1))
+* **noice:** set background blend to 0 for mini popups ([#556](https://github.com/catppuccin/nvim/issues/556)) ([2d50a4e](https://github.com/catppuccin/nvim/commit/2d50a4e3aecffea4144801bb3c0a3cf7b88fdd6b))
+* **nvim-window-picker:** missing table keys ([#569](https://github.com/catppuccin/nvim/issues/569)) ([b9e4dae](https://github.com/catppuccin/nvim/commit/b9e4dae160bf9bc28d4ceb6d29a7e0134b107724))
+* **options:** disable deprecated ts_rainbow and ts_rainbow2 by default ([096385d](https://github.com/catppuccin/nvim/commit/096385dd024ecd1332659916fd7f09d7d18d7374))
+* **telescope:** keep consistency between the two styles ([#540](https://github.com/catppuccin/nvim/issues/540)) ([dfbc8e2](https://github.com/catppuccin/nvim/commit/dfbc8e2b478a65104d34556698067f2d40f1c227))
+* **telescope:** respect transparency ([#542](https://github.com/catppuccin/nvim/issues/542)) ([f36af06](https://github.com/catppuccin/nvim/commit/f36af062e3242f333b12fe9b730053fdda36e000))
+* **treesitter:** avoid possible nil ([17ae783](https://github.com/catppuccin/nvim/commit/17ae783b88bb7ae73dc004370473138d9d43ee46))
+* **types:** make all options besides nested `enabled` optional ([#565](https://github.com/catppuccin/nvim/issues/565)) ([490078b](https://github.com/catppuccin/nvim/commit/490078b1593c6609e6a50ad5001e7902ea601824))
+
+## [1.3.0](https://github.com/catppuccin/nvim/compare/v1.2.0...v1.3.0) (2023-07-10)
+
+
+### Features
+
+* auto-sync upstream palettes ([#507](https://github.com/catppuccin/nvim/issues/507)) ([8426d3b](https://github.com/catppuccin/nvim/commit/8426d3bfd55f4dc68ae451a82927d2ff88e47e95))
+* **debug:** add auto compile on save ([c9cc5a9](https://github.com/catppuccin/nvim/commit/c9cc5a997f1dae3f35b4bdd62f35958fee363ab4))
+* **dropbar:** add new highlight groups ([4f22a1e](https://github.com/catppuccin/nvim/commit/4f22a1e78460ae06e78a1085a8e0e6cc8027aef2)), closes [#503](https://github.com/catppuccin/nvim/issues/503)
+* **integration:** add dropbar.nvim ([#499](https://github.com/catppuccin/nvim/issues/499)) ([e86aeb8](https://github.com/catppuccin/nvim/commit/e86aeb8ca0f03e97192074fba9dc6c836f953a83))
+* **integrations:** accept both boolean and table config ([#534](https://github.com/catppuccin/nvim/issues/534)) ([f0b947a](https://github.com/catppuccin/nvim/commit/f0b947ab8cfdb9ca7ba6230b30bbc1ed48dd30a1))
+* **integrations:** add rainbow_delimiters.nvim support ([#530](https://github.com/catppuccin/nvim/issues/530)) ([cc8d3ab](https://github.com/catppuccin/nvim/commit/cc8d3abc944d78cb6bf2a4cc88871ab383c4da62))
+* **markdown:** add rainbow headlines ([#493](https://github.com/catppuccin/nvim/issues/493)) ([cc517bd](https://github.com/catppuccin/nvim/commit/cc517bdcb66a0f8dee90bab10ccdd651fa967bbe))
+* **native_lsp:** add ability to disable background for inlay hints ([#518](https://github.com/catppuccin/nvim/issues/518)) ([b032ced](https://github.com/catppuccin/nvim/commit/b032cedb90c42a7bfbfbe2f91479505330f4a396))
+* **native_lsp:** support inlay hints ([#516](https://github.com/catppuccin/nvim/issues/516)) ([d32b0bb](https://github.com/catppuccin/nvim/commit/d32b0bb5b1033920de5026e326869838aba856ee))
+* **navic:** change text color ([278bfeb](https://github.com/catppuccin/nvim/commit/278bfeb61bd627dc2a8885180a0441a1ebe65a41))
+* **semantic_tokens:** add some lsp semantic tokens ([#512](https://github.com/catppuccin/nvim/issues/512)) ([506a4aa](https://github.com/catppuccin/nvim/commit/506a4aa13443e0104ea49b99947cc09488d0791d))
+* **telescope:** telescope flat style support ([#521](https://github.com/catppuccin/nvim/issues/521)) ([fc73faa](https://github.com/catppuccin/nvim/commit/fc73faa37bda393e3c4f846fb3e810a6ac8aae16))
+* **types:** add type annotations ([#495](https://github.com/catppuccin/nvim/issues/495)) ([1d3eda1](https://github.com/catppuccin/nvim/commit/1d3eda15703ba70f57e94e6451db55914ff7017f))
+* **workflows:** auto-sync upstream palettes ([e9fbeec](https://github.com/catppuccin/nvim/commit/e9fbeec106562475e82bae79304b6a421eee73f3))
+
+
+### Bug Fixes
+
+* calling palette before setup ([841d8ab](https://github.com/catppuccin/nvim/commit/841d8abf3be39de833d95a592a1fbbb1b9851296))
+* **feline:** disable lsp status on nightly ([#510](https://github.com/catppuccin/nvim/issues/510)) ([9aaf5b4](https://github.com/catppuccin/nvim/commit/9aaf5b4ce5cd256695d8bbddb65869d19919abde))
+* **feline:** use new `vim.lsp.status()` method ([#509](https://github.com/catppuccin/nvim/issues/509)) ([57ee09d](https://github.com/catppuccin/nvim/commit/57ee09dd532bd442b53d65c2b2f35550960981ed))
+* **lsp:** do not link `LspInlayHint` to `Comment` directly ([#517](https://github.com/catppuccin/nvim/issues/517)) ([5dc566c](https://github.com/catppuccin/nvim/commit/5dc566c4206f383657d67500253559d3be82c421))
+* **mapper:** remove unnecessary globals ([#529](https://github.com/catppuccin/nvim/issues/529)) ([c75562c](https://github.com/catppuccin/nvim/commit/c75562cbc954136f279ced91661251543b6f2a20))
+* **native_lsp:** boolean logic ([#526](https://github.com/catppuccin/nvim/issues/526)) ([8d02781](https://github.com/catppuccin/nvim/commit/8d02781a638123394f9bc160aad47a9560a113f9))
+* **tests:** shadowing variable ([15043d3](https://github.com/catppuccin/nvim/commit/15043d363729f1ef20e615c41bbd8b7e92c1453e))
+* **treesitter_context:** underline content if `transparent_background` is true ([#519](https://github.com/catppuccin/nvim/issues/519)) ([6ecc158](https://github.com/catppuccin/nvim/commit/6ecc158dbf365d2cd290b58993296c42b3111965))
+* **which-key:** wrong separator highlight group ([d438c01](https://github.com/catppuccin/nvim/commit/d438c0141609338140b18363a9a1e8eb8bb17130))
+* **workflows:** stylua format ([2df7036](https://github.com/catppuccin/nvim/commit/2df7036c5c303c9184869936e40ca18935e4afcb))
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/LICENSE.md b/config/neovim/store/lazy-plugins/catppuccin-nvim/LICENSE.md
new file mode 100644
index 00000000..006383b8
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/LICENSE.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Catppuccin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/README.md b/config/neovim/store/lazy-plugins/catppuccin-nvim/README.md
new file mode 100644
index 00000000..afe32b39
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/README.md
@@ -0,0 +1,1551 @@
+
+
+
+ 
+
+ Catppuccin for (Neo)vim
+
+
+
+
+
+
+
+
+
+
+This port of Catppuccin is special because it was the first one and the one that originated the project itself. Given this, it's important to acknowledge that it all didn't come to be what it is now out of nowhere. So, if you are interested in knowing more about the initial stages of the theme, you can find it under the v0.1 tag
+
+
+
+
+
+
+# Flavours
+
+
+Latte
+
+
+
+Frappe
+
+
+
+Macchiato
+
+
+
+Mocha
+
+
+
+**[Bake your own flavour!](https://github.com/catppuccin/nvim/#overwriting-colors)** Here are some **[config from our community](https://github.com/catppuccin/nvim/discussions/323)**: (background source)
+
+
+
+
+
+
+
+# Features
+
+- Supports both vim and neovim (Requires [neovim](https://github.com/neovim/neovim/) >= 0.8 or [vim](https://github.com/vim/vim) >= 9 compiled with [lua](https://github.com/lua/lua) >= 5.1)
+- Highly configurable with 4 different flavours and [ability to create your own!](https://github.com/catppuccin/nvim/discussions/323)
+- [Compile](https://github.com/catppuccin/nvim#Compile) user config for [fastest startuptime](https://www.reddit.com/r/neovim/comments/xxfpt3/catppuccinnvim_now_startup_in_1ms/)
+- Integrations with lsp, treesitter and [a bunch of plugins](https://github.com/catppuccin/nvim#integrations)
+- Supports for [many other applications](https://github.com/catppuccin/catppuccin)
+
+# Installation
+
+[lazy.nvim](https://github.com/folke/lazy.nvim)
+```lua
+{ "catppuccin/nvim", name = "catppuccin", priority = 1000 }
+```
+
+[packer.nvim](https://github.com/wbthomason/packer.nvim)
+```lua
+use { "catppuccin/nvim", as = "catppuccin" }
+```
+
+[vim-plug](https://github.com/junegunn/vim-plug)
+```vim
+Plug 'catppuccin/nvim', { 'as': 'catppuccin' }
+```
+
+# Usage
+
+```vim
+colorscheme catppuccin " catppuccin-latte, catppuccin-frappe, catppuccin-macchiato, catppuccin-mocha
+```
+
+```lua
+vim.cmd.colorscheme "catppuccin"
+```
+
+# Configuration
+
+There is no need to call `setup` if you don't want to change the default options and settings.
+
+```lua
+require("catppuccin").setup({
+ flavour = "auto", -- latte, frappe, macchiato, mocha
+ background = { -- :h background
+ light = "latte",
+ dark = "mocha",
+ },
+ transparent_background = false, -- disables setting the background color.
+ show_end_of_buffer = false, -- shows the '~' characters after the end of buffers
+ term_colors = false, -- sets terminal colors (e.g. `g:terminal_color_0`)
+ dim_inactive = {
+ enabled = false, -- dims the background color of inactive window
+ shade = "dark",
+ percentage = 0.15, -- percentage of the shade to apply to the inactive window
+ },
+ no_italic = false, -- Force no italic
+ no_bold = false, -- Force no bold
+ no_underline = false, -- Force no underline
+ styles = { -- Handles the styles of general hi groups (see `:h highlight-args`):
+ comments = { "italic" }, -- Change the style of comments
+ conditionals = { "italic" },
+ loops = {},
+ functions = {},
+ keywords = {},
+ strings = {},
+ variables = {},
+ numbers = {},
+ booleans = {},
+ properties = {},
+ types = {},
+ operators = {},
+ -- miscs = {}, -- Uncomment to turn off hard-coded styles
+ },
+ color_overrides = {},
+ custom_highlights = {},
+ default_integrations = true,
+ integrations = {
+ cmp = true,
+ gitsigns = true,
+ nvimtree = true,
+ treesitter = true,
+ notify = false,
+ mini = {
+ enabled = true,
+ indentscope_color = "",
+ },
+ -- For more plugins integrations please scroll down (https://github.com/catppuccin/nvim#integrations)
+ },
+})
+
+-- setup must be called before loading
+vim.cmd.colorscheme "catppuccin"
+```
+
+# Customize highlights
+
+## Get catppuccin colors
+
+```lua
+local latte = require("catppuccin.palettes").get_palette "latte"
+local frappe = require("catppuccin.palettes").get_palette "frappe"
+local macchiato = require("catppuccin.palettes").get_palette "macchiato"
+local mocha = require("catppuccin.palettes").get_palette "mocha"
+```
+
+Returns a table where the key is the name of the color and the value is its hex value corresponding to each flavour.
+
+## Overwriting colors
+
+Colors can be overwritten using `color_overrides` in the setting, checkout https://github.com/catppuccin/nvim/discussions/323 for inspirations:
+
+```lua
+require("catppuccin").setup {
+ color_overrides = {
+ all = {
+ text = "#ffffff",
+ },
+ latte = {
+ base = "#ff0000",
+ mantle = "#242424",
+ crust = "#474747",
+ },
+ frappe = {},
+ macchiato = {},
+ mocha = {},
+ }
+}
+```
+
+> [!Note]
+> For more information check out our [style-guide](https://github.com/catppuccin/catppuccin/blob/main/docs/style-guide.md)
+
+## Overwriting highlight groups
+
+Global highlight groups can be overwritten in the setting, for example:
+
+```lua
+require("catppuccin").setup {
+ custom_highlights = function(colors)
+ return {
+ Comment = { fg = colors.flamingo },
+ TabLineSel = { bg = colors.pink },
+ CmpBorder = { fg = colors.surface2 },
+ Pmenu = { bg = colors.none },
+ }
+ end
+}
+```
+
+Per flavour highlight groups can also be overwritten in the setting, for example:
+
+```lua
+require("catppuccin").setup {
+ highlight_overrides = {
+ all = function(colors)
+ return {
+ NvimTreeNormal = { fg = colors.none },
+ CmpBorder = { fg = "#3e4145" },
+ }
+ end,
+ latte = function(latte)
+ return {
+ Normal = { fg = latte.base },
+ }
+ end,
+ frappe = function(frappe)
+ return {
+ ["@comment"] = { fg = frappe.surface2, style = { "italic" } },
+ }
+ end,
+ macchiato = function(macchiato)
+ return {
+ LineNr = { fg = macchiato.overlay1 },
+ }
+ end,
+ mocha = function(mocha)
+ return {
+ Comment = { fg = mocha.flamingo },
+ }
+ end,
+ },
+}
+```
+
+# Integrations
+
+Catppuccin provides theme support for other plugins in the Neovim ecosystem and extended Neovim functionality through _integrations_.
+
+To enable/disable an integration you just need to set it to true/false, for example:
+
+```lua
+require("catppuccin").setup({
+ integrations = {
+ cmp = true,
+ gitsigns = true,
+ nvimtree = true,
+ treesitter = true,
+ notify = false,
+ mini = {
+ enabled = true,
+ indentscope_color = "",
+ },
+ }
+})
+```
+
+Some integrations are enabled by default, you can control this behaviour with `default_integrations` option.
+
+```lua
+require("catppuccin").setup({
+ default_integrations = false,
+})
+```
+
+Below is a list of supported plugins and their corresponding integration module.
+
+> [!Important]
+> If you'd like to know which highlight groups are being affected by catppuccin, check out this directory: [`lua/catppuccin/groups/integrations/`](https://github.com/catppuccin/nvim/tree/main/lua/catppuccin/groups/integrations).
+
+
+
+| Plugin | Default |
+
+
+
+
+
+| aerial.nvim |
+
+
+```lua
+aerial = false
+```
+
+ |
+
+
+
+
+
+
+| alpha-nvim |
+
+
+```lua
+alpha = true
+```
+
+ |
+
+
+
+
+
+
+| barbar.nvim |
+
+
+```lua
+barbar = false
+```
+
+ |
+
+
+
+
+
+
+| barbecue.nvim |
+
+
+```lua
+barbecue = {
+ dim_dirname = true, -- directory name is dimmed by default
+ bold_basename = true,
+ dim_context = false,
+ alt_background = false,
+},
+```
+
+ Special
+
+Use this to set it up:
+
+```lua
+require("barbecue").setup {
+ theme = "catppuccin", -- catppuccin-latte, catppuccin-frappe, catppuccin-macchiato, catppuccin-mocha
+}
+```
+
+
+ |
+
+
+
+
+
+
+| beacon.nvim |
+
+
+```lua
+beacon = false
+```
+
+ |
+
+
+
+
+
+
+| bufferline.nvim |
+
+
+ Special
+
+Update your bufferline config to use the Catppuccin components:
+
+> [!NOTE]
+> bufferline needs to be loaded after setting up catppuccin or it will highlight incorrectly
+
+```lua
+use "akinsho/bufferline.nvim" {
+ after = "catppuccin",
+ config = function()
+ require("bufferline").setup {
+ highlights = require("catppuccin.groups.integrations.bufferline").get()
+ }
+ end
+}
+```
+
+Configurations are self-explanatory, see `:h bufferline-highlights` for detailed explanations:
+
+```lua
+local mocha = require("catppuccin.palettes").get_palette "mocha"
+bufferline.setup {
+ highlights = require("catppuccin.groups.integrations.bufferline").get {
+ styles = { "italic", "bold" },
+ custom = {
+ all = {
+ fill = { bg = "#000000" },
+ },
+ mocha = {
+ background = { fg = mocha.text },
+ },
+ latte = {
+ background = { fg = "#000000" },
+ },
+ },
+ },
+}
+```
+
+
+
+ |
+
+
+
+
+
+
+| coc.nvim |
+
+
+```lua
+coc_nvim = false
+```
+
+ Special
+
+Setting `enabled` to `true` enables this integration.
+
+```lua
+coc_nvim = true,
+```
+> [!Note]
+> coc.nvim by default link to native lsp highlight groups so config from `native_lsp` will also apply to coc
+
+In the inners tables you can set the style for the diagnostics, both `virtual_text` (what you see on the side) and `underlines` (what points directly at the thing (e.g. an error)).
+
+```lua
+native_lsp = {
+ enabled = true,
+ virtual_text = {
+ errors = { "italic" },
+ hints = { "italic" },
+ warnings = { "italic" },
+ information = { "italic" },
+ },
+ underlines = {
+ errors = { "underline" },
+ hints = { "underline" },
+ warnings = { "underline" },
+ information = { "underline" },
+ },
+ inlay_hints = {
+ background = true,
+ },
+},
+```
+
+
+
+ |
+
+
+
+
+
+
+| colorful-winsep.nvim
+ |
+
+
+```lua
+colorful_winsep = {
+ enabled = false,
+ color = "red",
+}
+```
+ |
+
+
+
+
+
+
+| dashboard-nvim |
+
+
+```lua
+dashboard = true
+```
+
+ |
+
+
+
+
+
+
+| diffview.nvim |
+
+
+```lua
+diffview = false
+```
+
+ |
+
+
+
+
+
+
+| dropbar.nvim |
+
+
+```lua
+dropbar = {
+ enabled = false,
+ color_mode = false, -- enable color for kind's texts, not just kind's icons
+},
+```
+
+ |
+
+
+
+
+
+
+| feline.nvim |
+
+
+
+
+ Special
+
+Update your Feline config to use the Catppuccin components:
+
+```lua
+local ctp_feline = require('catppuccin.groups.integrations.feline')
+
+ctp_feline.setup()
+
+require("feline").setup({
+ components = ctp_feline.get(),
+})
+```
+
+Notice that calling `setup()` is optional. You may pass a lua table in order to change assets, settings and the colors per vim mode.
+
+Here are the defaults:
+
+```lua
+local clrs = require("catppuccin.palettes").get_palette()
+local ctp_feline = require('catppuccin.groups.integrations.feline')
+local U = require "catppuccin.utils.colors"
+
+ctp_feline.setup({
+ assets = {
+ left_separator = "",
+ right_separator = "",
+ mode_icon = "",
+ dir = "",
+ file = "",
+ lsp = {
+ server = "",
+ error = "",
+ warning = "",
+ info = "",
+ hint = "",
+ },
+ git = {
+ branch = "",
+ added = "",
+ changed = "",
+ removed = "",
+ },
+ },
+ sett = {
+ text = U.vary_color({ latte = latte.base }, clrs.surface0),
+ bkg = U.vary_color({ latte = latte.crust }, clrs.surface0),
+ diffs = clrs.mauve,
+ extras = clrs.overlay1,
+ curr_file = clrs.maroon,
+ curr_dir = clrs.flamingo,
+ show_modified = true -- show if the file has been modified
+ },
+ mode_colors = {
+ ["n"] = { "NORMAL", clrs.lavender },
+ ["no"] = { "N-PENDING", clrs.lavender },
+ ["i"] = { "INSERT", clrs.green },
+ ["ic"] = { "INSERT", clrs.green },
+ ["t"] = { "TERMINAL", clrs.green },
+ ["v"] = { "VISUAL", clrs.flamingo },
+ ["V"] = { "V-LINE", clrs.flamingo },
+ [""] = { "V-BLOCK", clrs.flamingo },
+ ["R"] = { "REPLACE", clrs.maroon },
+ ["Rv"] = { "V-REPLACE", clrs.maroon },
+ ["s"] = { "SELECT", clrs.maroon },
+ ["S"] = { "S-LINE", clrs.maroon },
+ [""] = { "S-BLOCK", clrs.maroon },
+ ["c"] = { "COMMAND", clrs.peach },
+ ["cv"] = { "COMMAND", clrs.peach },
+ ["ce"] = { "COMMAND", clrs.peach },
+ ["r"] = { "PROMPT", clrs.teal },
+ ["rm"] = { "MORE", clrs.teal },
+ ["r?"] = { "CONFIRM", clrs.mauve },
+ ["!"] = { "SHELL", clrs.green },
+ },
+ view = {
+ lsp = {
+ progress = true, -- if true the status bar will display an lsp progress indicator
+ name = false, -- if true the status bar will display the lsp servers name, otherwise it will display the text "Lsp"
+ exclude_lsp_names = {}, -- lsp server names that should not be displayed when name is set to true
+ separator = "|", -- the separator used when there are multiple lsp servers
+ },
+ }
+})
+```
+
+> [!Warning]
+> Currently feline [doesn't officially support custom themes](https://github.com/feline-nvim/feline.nvim/issues/302). In order for `:colorscheme catppuccin-` to work you could add this autocmd as a workaround:
+
+```lua
+vim.api.nvim_create_autocmd("ColorScheme", {
+ pattern = "*",
+ callback = function()
+ package.loaded["feline"] = nil
+ package.loaded["catppuccin.groups.integrations.feline"] = nil
+ require("feline").setup {
+ components = require("catppuccin.groups.integrations.feline").get(),
+ }
+ end,
+})
+```
+
+
+
+ |
+
+
+
+
+
+
+| fern.vim |
+
+
+```lua
+fern = false
+```
+
+ |
+
+
+
+
+
+
+| fidget.nvim |
+
+
+```lua
+fidget = false
+```
+
+ Special
+Set `notification.window.winblend` to `0`:
+
+```lua
+require("fidget").setup {
+ notification = {
+ window = {
+ winblend = 0,
+ },
+ }
+ -- ... the rest of your fidget config
+}
+```
+
+
+
+ |
+
+
+
+
+
+
+| flash.nvim |
+
+
+```lua
+flash = true
+```
+
+
+
+ |
+
+| gitsigns.nvim |
+
+
+```lua
+gitsigns = true
+```
+
+
+
+ |
+
+| harpoon |
+
+
+```lua
+harpoon = false
+```
+
+
+
+ |
+
+| headlines.nvim |
+
+
+```lua
+headlines = false
+```
+
+
+
+ |
+
+| hop.nvim |
+
+
+```lua
+hop = false
+```
+
+
+
+ |
+
+| indent-blankline.nvim |
+
+
+```lua
+indent_blankline = {
+ enabled = true,
+ scope_color = "", -- catppuccin color (eg. `lavender`) Default: text
+ colored_indent_levels = false,
+},
+
+```
+
+ Special
+
+`colored_indent_levels` enables char highlights per indent level. Follow the instructions [here](https://github.com/lukas-reineke/indent-blankline.nvim#multiple-indent-colors) to set the latter up.
+
+
+
+
+
+
+ |
+
+| leap.nvim |
+
+
+```lua
+leap = false
+```
+
+
+
+ |
+
+| lightline.vim |
+
+
+ Special
+
+```vim
+let g:lightline = {'colorscheme': 'catppuccin'}
+```
+
+
+
+
+
+ |
+
+| lightspeed.nvim |
+
+
+```lua
+lightspeed = false
+```
+
+
+
+ |
+
+| lspsaga.nvim |
+
+
+```lua
+lsp_saga = false
+```
+
+ Special
+
+For custom Lsp Kind Icon and Color
+
+```lua
+require("lspsaga").setup {
+ ui = {
+ kind = require("catppuccin.groups.integrations.lsp_saga").custom_kind(),
+ },
+}
+```
+
+
+ |
+
+
+
+
+| lualine.nvim |
+
+
+ Special
+
+```lua
+require('lualine').setup {
+ options = {
+ theme = "catppuccin"
+ -- ... the rest of your lualine config
+ }
+}
+```
+
+
+
+
+
+
+ |
+
+| markdown |
+
+
+```lua
+markdown = true
+```
+
+ |
+
+
+
+
+
+
+| mason.nvim |
+
+
+```lua
+mason = false
+```
+
+ |
+
+
+
+
+
+
+| mini.nvim |
+
+
+```lua
+mini = {
+ enabled = true,
+ indentscope_color = "", -- catppuccin color (eg. `lavender`) Default: text
+},
+```
+
+ |
+
+
+
+
+
+
+| neo-tree.nvim |
+
+
+```lua
+neotree = false
+```
+
+ |
+
+
+
+
+
+
+| neogit |
+
+
+```lua
+neogit = true
+```
+
+ |
+
+
+
+
+
+
+| neotest |
+
+
+```lua
+neotest = false
+```
+
+ |
+
+
+
+
+
+
+| noice.nvim |
+
+
+```lua
+noice = false
+```
+
+ |
+
+
+
+
+
+
+| NormalNvim |
+
+
+```lua
+NormalNvim = false
+```
+
+ |
+
+
+
+
+
+
+| notifier.nvim |
+
+
+```lua
+notifier = false
+```
+
+ |
+
+
+
+
+
+
+| nvim-cmp |
+
+
+```lua
+cmp = true
+```
+
+ |
+
+
+
+
+
+
+| nvim-dap |
+
+
+```lua
+dap = true
+```
+
+ Special
+
+```lua
+local sign = vim.fn.sign_define
+
+sign("DapBreakpoint", { text = "●", texthl = "DapBreakpoint", linehl = "", numhl = ""})
+sign("DapBreakpointCondition", { text = "●", texthl = "DapBreakpointCondition", linehl = "", numhl = ""})
+sign("DapLogPoint", { text = "◆", texthl = "DapLogPoint", linehl = "", numhl = ""})
+```
+
+
+
+ |
+
+
+
+
+
+
+| nvim-dap-ui |
+
+
+```lua
+dap_ui = true
+```
+
+ |
+
+
+
+
+
+
+| nvim-lspconfig |
+
+
+```lua
+native_lsp = {
+ enabled = true,
+ virtual_text = {
+ errors = { "italic" },
+ hints = { "italic" },
+ warnings = { "italic" },
+ information = { "italic" },
+ },
+ underlines = {
+ errors = { "underline" },
+ hints = { "underline" },
+ warnings = { "underline" },
+ information = { "underline" },
+ },
+ inlay_hints = {
+ background = true,
+ },
+},
+```
+
+ Special
+
+In the inners tables you can set the style for the diagnostics, both `virtual_text` (what you see on the side) and `underlines` (what points directly at the thing (e.g. an error)).
+
+
+
+ |
+
+
+
+
+
+
+| navic |
+
+
+```lua
+navic = {
+ enabled = false,
+ custom_bg = "NONE", -- "lualine" will set background to mantle
+},
+
+```
+ Special
+
+```lua
+-- You NEED to enable highlight in nvim-navic setting or it won't work
+require("nvim-navic").setup {
+ highlight = true
+}
+```
+
+
+
+ |
+
+
+
+
+
+
+| nvim-notify |
+
+
+```lua
+notify = false
+```
+
+ |
+
+
+
+
+
+
+| nvim-semantic-tokens |
+
+
+```lua
+semantic_tokens = true
+```
+
+ |
+
+
+
+
+
+
+| nvim-tree.lua |
+
+
+```lua
+nvimtree = true
+```
+
+ |
+
+
+
+
+
+
+| nvim-treesitter-context |
+
+
+```lua
+treesitter_context = true
+```
+
+ |
+
+
+
+
+
+
+| nvim-treesitter |
+
+
+```lua
+treesitter = true
+```
+
+ |
+
+
+
+
+
+
+| nvim-ts-rainbow2 |
+
+
+```lua
+ts_rainbow2 = false
+```
+
+ |
+
+
+
+
+
+
+| nvim-ts-rainbow |
+
+
+```lua
+ts_rainbow = false
+```
+
+ |
+
+
+
+
+
+
+| nvim-ufo |
+
+
+```lua
+ufo = true
+```
+
+ |
+
+
+
+
+
+
+| nvim-window-picker |
+
+
+```lua
+window_picker = false
+```
+
+
+
+ |
+
+| octo.nvim |
+
+
+```lua
+octo = false
+```
+
+ |
+
+
+
+
+
+
+| overseer.nvim |
+
+
+```lua
+overseer = false
+```
+
+ |
+
+
+
+
+
+
+| pounce.nvim |
+
+
+```lua
+pounce = false
+```
+
+ |
+
+
+
+
+
+
+| rainbow-delimiters.nvim |
+
+
+```lua
+rainbow_delimiters = true
+```
+
+ |
+
+
+
+
+
+
+| reactive.nvim |
+
+
+ Special
+
+There're 2 available presets (`cursor` and `cursorline`) for every flavour.
+
+Here is how you can use them.
+
+```lua
+require('reactive').setup {
+ load = { 'catppuccin-mocha-cursor', 'catppuccin-mocha-cursorline' }
+}
+```
+
+To use another flavour just replace `mocha` with the one you want to use.
+
+
+
+ |
+
+
+
+
+
+
+| symbols-outline.nvim |
+
+
+> [!NOTE]
+> This plugin has been archived by the author, consider using [outline.nvim](https://github.com/hedyhli/outline.nvim)
+
+```lua
+symbols_outline = false
+```
+
+ |
+
+
+
+
+
+
+| telekasten.nvim |
+
+
+```lua
+telekasten = false
+```
+
+ |
+
+
+
+
+
+
+| telescope.nvim |
+
+
+```lua
+telescope = {
+ enabled = true,
+ -- style = "nvchad"
+}
+```
+
+ |
+
+
+
+
+
+
+| trouble.nvim |
+
+
+```lua
+lsp_trouble = false
+```
+
+ |
+
+
+
+
+
+
+| vim-airline |
+
+
+ Special
+
+```vim
+let g:airline_theme = 'catppuccin'
+```
+
+
+
+ |
+
+
+
+
+
+
+| vim-clap |
+
+
+ Special
+
+Use this to set it up:
+
+```vim
+let g:clap_theme = 'catppuccin'
+```
+
+
+
+ |
+
+
+
+
+
+
+| vim-gitgutter |
+
+
+```lua
+gitgutter = false
+```
+
+ |
+
+
+
+
+
+
+| vim-illuminate |
+
+
+```lua
+illuminate = {
+ enabled = true,
+ lsp = false
+}
+```
+
+ |
+
+
+
+
+
+
+| vim-sandwich |
+
+
+```lua
+sandwich = false
+```
+
+ |
+
+
+
+
+
+
+| vim-sneak |
+
+
+```lua
+vim_sneak = false
+```
+
+ |
+
+
+
+
+
+
+| vimwiki |
+
+
+```lua
+vimwiki = false
+```
+
+ |
+
+
+
+
+
+
+| which-key.nvim |
+
+
+```lua
+which_key = false
+```
+
+ |
+
+
+
+
+
+# Compile
+
+> **Important**
+> As of 7/10/2022, catppuccin should be able to automatically recompile when the setup table changed.
+
+Catppuccin is a highly customizable and configurable colorscheme. This does however come at the cost of complexity and execution time. Catppuccin can pre compute the results of your configuration and store the results in a compiled lua file. We use these precached values to set it's highlights.
+
+By default catppuccin writes the compiled results into the system's cache directory. You can change the cache dir using:
+
+```lua
+require("catppuccin").setup({ -- Note: On windows we replace `/` with `\` by default
+ compile_path = vim.fn.stdpath "cache" .. "/catppuccin"
+})
+```
+
+# FAQ
+
+## Wrong treesitter highlights
+
+Please disable `additional_vim_regex_highlighting`
+
+```lua
+require("nvim-treesitter.configs").setup {
+ highlight = {
+ enable = true,
+ additional_vim_regex_highlighting = false
+ },
+}
+```
+
+## Colors doesn't match preview screenshots
+
+Catppuccin requires true color support AKA terminals support the full range of 16 million colors
+
+- Supported: iterm2 (macOS), kitty, wezterm, alacritty, tmux, ...
+
+Full list of support terminals can be found here:
+
+- Unsupported terminal: Terminal.app (macOS), Terminus, Terminology, ...
+
+Full list of Unsupported terminals can be found here:
+
+### For tmux users
+
+- [Enable true color support](https://gist.github.com/andersevenrud/015e61af2fd264371032763d4ed965b6) to fix the following [abnormal colors](https://github.com/catppuccin/nvim/issues/415):
+
+
+
+- [Enable italic font support](https://gist.github.com/gyribeiro/4192af1aced7a1b555df06bd3781a722) to fix the following [incorrect if, then, else, end highlights](https://github.com/catppuccin/nvim/issues/428):
+
+
+
+# Thanks to
+
+- [Pocco81](https://github.com/Pocco81)
+- [nullchilly](https://github.com/nullchilly)
+
+
+
+
+
+
+Copyright © 2021-present Catppuccin Org
+

+
+
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/after/queries/css/highlights.scm b/config/neovim/store/lazy-plugins/catppuccin-nvim/after/queries/css/highlights.scm
new file mode 100644
index 00000000..7dc8b31f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/after/queries/css/highlights.scm
@@ -0,0 +1,16 @@
+;; extends
+[
+(class_name)
+] @property.class
+
+[
+ (id_name)
+ ] @property.id
+
+[
+ (declaration
+ (plain_value) @string.plain)
+ ]
+[
+ (tag_name)
+ ] @type.tag
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/after/queries/javascript/highlights.scm b/config/neovim/store/lazy-plugins/catppuccin-nvim/after/queries/javascript/highlights.scm
new file mode 100644
index 00000000..1ce3d330
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/after/queries/javascript/highlights.scm
@@ -0,0 +1,4 @@
+;; extends
+[
+"export"
+] @keyword.export
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/after/queries/typescript/highlights.scm b/config/neovim/store/lazy-plugins/catppuccin-nvim/after/queries/typescript/highlights.scm
new file mode 100644
index 00000000..1ce3d330
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/after/queries/typescript/highlights.scm
@@ -0,0 +1,4 @@
+;; extends
+[
+"export"
+] @keyword.export
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/autoload/airline/themes/catppuccin.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/autoload/airline/themes/catppuccin.vim
new file mode 100644
index 00000000..542c8e67
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/autoload/airline/themes/catppuccin.vim
@@ -0,0 +1,72 @@
+let g:airline#themes#catppuccin#palette = {}
+
+function! airline#themes#catppuccin#refresh()
+ let s:c = has("nvim") == 1 ? luaeval('require("catppuccin.palettes").get_palette()') : luaeval('vim.dict(require("catppuccin.palettes").get_palette())')
+
+ " Normal mode
+ " (Dark)
+ let s:N1 = [ s:c.mantle, s:c.blue, 59, 149 ] " guifg guibg ctermfg ctermbg
+ let s:N2 = [ s:c.blue, s:c.surface0, 149, 59 ] " guifg guibg ctermfg ctermbg
+ let s:N3 = [ s:c.text, s:c.mantle, 145, 16 ] " guifg guibg ctermfg ctermbg
+
+ " Insert mode
+ let s:I1 = [ s:c.mantle, s:c.teal, 59, 74 ] " guifg guibg ctermfg ctermbg
+ let s:I2 = [ s:c.teal, s:c.surface0, 74, 59 ] " guifg guibg ctermfg ctermbg
+ let s:I3 = [ s:c.text, s:c.mantle, 145, 16 ] " guifg guibg ctermfg ctermbg
+
+ " Visual mode
+ let s:V1 = [ s:c.mantle, s:c.mauve, 59, 209 ] " guifg guibg ctermfg ctermbg
+ let s:V2 = [ s:c.mauve, s:c.surface0, 209, 59 ] " guifg guibg ctermfg ctermbg
+ let s:V3 = [ s:c.text, s:c.mantle, 145, 16 ] " guifg guibg ctermfg ctermbg
+
+ " Replace mode
+ let s:R1 = [ s:c.mantle, s:c.red, 59, 203 ] " guifg guibg ctermfg ctermbg
+ let s:R2 = [ s:c.red, s:c.surface0, 203, 59 ] " guifg guibg ctermfg ctermbg
+
+ " Command mode
+ let s:C1 = [ s:c.base, s:c.peach, 59, 166 ] " guifg guibg ctermfg ctermbg
+ let s:C2 = [ s:c.peach, s:c.surface0, 166, 59 ] " guifg guibg ctermfg ctermbg
+
+ " Warning section
+ let s:WR = [s:c.mantle, s:c.peach, 232, 166 ]
+
+ " Error section
+ let s:ER = [s:c.mantle, s:c.red, 232, 166 ]
+
+
+ let g:airline#themes#catppuccin#palette.normal = airline#themes#generate_color_map(s:N1, s:N2, s:N3)
+
+ let g:airline#themes#catppuccin#palette.insert = airline#themes#generate_color_map(s:I1, s:I2, s:I3)
+
+ let g:airline#themes#catppuccin#palette.visual = airline#themes#generate_color_map(s:V1, s:V2, s:V3)
+
+ let s:IA = [ s:N1[1], s:N3[1], s:N1[3], s:N3[3], '' ]
+ let g:airline#themes#catppuccin#palette.inactive = airline#themes#generate_color_map(s:IA, s:IA, s:IA)
+
+ let g:airline#themes#catppuccin#palette.normal.airline_warning = s:WR
+ let g:airline#themes#catppuccin#palette.insert.airline_warning = s:WR
+ let g:airline#themes#catppuccin#palette.visual.airline_warning = s:WR
+
+ let g:airline#themes#catppuccin#palette.normal.airline_warning_to_airline_error = s:WR
+ let g:airline#themes#catppuccin#palette.insert.airline_warning_to_airline_error = s:WR
+ let g:airline#themes#catppuccin#palette.visual.airline_warning_to_airline_error = s:WR
+
+ let g:airline#themes#catppuccin#palette.normal.airline_error = s:ER
+ let g:airline#themes#catppuccin#palette.insert.airline_error = s:ER
+ let g:airline#themes#catppuccin#palette.visual.airline_error = s:ER
+
+ " Fork replace mode from insert mode
+ let g:airline#themes#catppuccin#palette.replace = copy(g:airline#themes#catppuccin#palette.insert)
+ let g:airline#themes#catppuccin#palette.replace.airline_a = [ s:R1[0], s:R1[1], s:R1[2], s:R1[3], '' ]
+ let g:airline#themes#catppuccin#palette.replace.airline_b = [ s:R2[0], s:R2[1], s:R2[2], s:R2[3], '' ]
+
+ " Terminal mode is same as insert mode
+ let g:airline#themes#catppuccin#palette.terminal = copy(g:airline#themes#catppuccin#palette.insert)
+
+ " Fork command mode from normal mode
+ let g:airline#themes#catppuccin#palette.commandline = copy(g:airline#themes#catppuccin#palette.normal)
+ let g:airline#themes#catppuccin#palette.commandline.airline_a = [ s:C1[0], s:C1[1], s:C1[2], s:C1[3], '' ]
+ let g:airline#themes#catppuccin#palette.commandline.airline_b = [ s:C2[0], s:C2[1], s:C2[2], s:C2[3], '' ]
+endfunction
+
+call airline#themes#catppuccin#refresh()
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/autoload/clap/themes/catppuccin.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/autoload/clap/themes/catppuccin.vim
new file mode 100644
index 00000000..16efd509
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/autoload/clap/themes/catppuccin.vim
@@ -0,0 +1,20 @@
+let s:c = has("nvim") == 1 ? luaeval('require("catppuccin.palettes").get_palette()') : luaeval('vim.dict(require("catppuccin.palettes").get_palette())')
+
+let s:p = {}
+
+let s:p.display = { 'guibg': s:c.mantle }
+
+let s:p.input = s:p.display
+let s:p.indicator = { 'guifg': s:c.subtext1, 'guibg': s:c.mantle }
+let s:p.spinner = { 'guifg': s:c.yellow, 'guibg': s:c.mantle, 'gui': "bold" }
+let s:p.search_text = { 'guifg': s:c.text, 'guibg': s:c.mantle, 'gui': "bold" }
+
+let s:p.preview = { 'guibg': s:c.base }
+
+let s:p.selected = { 'guifg': s:c.sapphire, 'gui': "bold,underline" }
+let s:p.current_selection = { 'guibg': s:c.surface0, 'gui': "bold" }
+
+let s:p.selected_sign = { 'guifg': s:c.red }
+let s:p.current_selection_sign = copy(s:p.selected_sign)
+
+let g:clap#themes#catppuccin#palette = s:p
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/autoload/lightline/colorscheme/catppuccin.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/autoload/lightline/colorscheme/catppuccin.vim
new file mode 100644
index 00000000..aeb778eb
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/autoload/lightline/colorscheme/catppuccin.vim
@@ -0,0 +1,22 @@
+let s:c = has("nvim") == 1 ? luaeval('require("catppuccin.palettes").get_palette()') : luaeval('vim.dict(require("catppuccin.palettes").get_palette())')
+
+let s:p = {'normal': {}, 'inactive': {}, 'insert': {}, 'replace': {}, 'visual': {}, 'tabline': {}}
+let s:p.normal.left = [ [ s:c.mantle, s:c.blue ], [ s:c.blue, s:c.base ] ]
+let s:p.normal.middle = [ [ s:c.blue, s:c.mantle ] ]
+let s:p.normal.right = [ [ s:c.overlay0, s:c.base ], [ s:c.blue, s:c.surface0 ] ]
+let s:p.insert.left = [ [ s:c.mantle, s:c.teal ], [ s:c.blue, s:c.base ] ]
+let s:p.visual.left = [ [ s:c.mantle, s:c.mauve ], [ s:c.blue, s:c.base ] ]
+let s:p.replace.left = [ [ s:c.mantle, s:c.red ], [ s:c.blue, s:c.base ] ]
+
+let s:p.inactive.left = [ [ s:c.blue, s:c.base ], [ s:c.overlay0, s:c.base ] ]
+let s:p.inactive.middle = [ [ s:c.surface1, s:c.base ] ]
+let s:p.inactive.right = [ [ s:c.surface1, s:c.base ], [ s:c.overlay0, s:c.base ] ]
+
+let s:p.tabline.left = [ [ s:c.overlay0, s:c.base ], [ s:c.overlay0, s:c.base ] ]
+let s:p.tabline.tabsel = [ [ s:c.blue, s:c.surface1 ], [ s:c.overlay0, s:c.base] ]
+let s:p.tabline.middle = [ [ s:c.surface1, s:c.base ] ]
+let s:p.tabline.right = copy(s:p.inactive.right)
+let s:p.normal.error = [ [ s:c.mantle, s:c.red ] ]
+let s:p.normal.warning = [ [ s:c.mantle, s:c.yellow ] ]
+
+let g:lightline#colorscheme#catppuccin#palette = lightline#colorscheme#fill(s:p)
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-frappe.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-frappe.vim
new file mode 100644
index 00000000..c9fd8d5c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-frappe.vim
@@ -0,0 +1 @@
+lua require("catppuccin").load "frappe"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-latte.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-latte.vim
new file mode 100644
index 00000000..6d877828
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-latte.vim
@@ -0,0 +1 @@
+lua require("catppuccin").load "latte"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-macchiato.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-macchiato.vim
new file mode 100644
index 00000000..cc4f0056
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-macchiato.vim
@@ -0,0 +1 @@
+lua require("catppuccin").load "macchiato"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-mocha.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-mocha.vim
new file mode 100644
index 00000000..4e6a3006
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin-mocha.vim
@@ -0,0 +1 @@
+lua require("catppuccin").load "mocha"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin.vim
new file mode 100644
index 00000000..916847b5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/colors/catppuccin.vim
@@ -0,0 +1 @@
+lua require("catppuccin").load()
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/doc/catppuccin.txt b/config/neovim/store/lazy-plugins/catppuccin-nvim/doc/catppuccin.txt
new file mode 100644
index 00000000..14d2276d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/doc/catppuccin.txt
@@ -0,0 +1,918 @@
+*catppuccin.txt* Soothing pastel theme for NeoVim
+
+==============================================================================
+Table of Contents *catppuccin-table-of-contents*
+
+1. Features |catppuccin-features|
+2. Installation |catppuccin-installation|
+3. Usage |catppuccin-usage|
+4. Configuration |catppuccin-configuration|
+5. Customize highlights |catppuccin-customize-highlights|
+ - Get catppuccin colors|catppuccin-customize-highlights-get-catppuccin-colors|
+ - Overwriting colors |catppuccin-customize-highlights-overwriting-colors|
+ - Overwriting highlight groups|catppuccin-customize-highlights-overwriting-highlight-groups|
+6. Integrations |catppuccin-integrations|
+7. Compile |catppuccin-compile|
+8. FAQ |catppuccin-faq|
+ - Wrong treesitter highlights |catppuccin-faq-wrong-treesitter-highlights|
+ - Colors doesn’t match preview screenshots|catppuccin-faq-colors-doesn’t-match-preview-screenshots|
+9. Thanks to |catppuccin-thanks-to|
+10. Links |catppuccin-links|
+
+==============================================================================
+1. Features *catppuccin-features*
+
+- Supports both vim and neovim (Requires neovim >= 0.8 or vim >= 9 compiled with lua >= 5.1)
+- Highly configurable with 4 different flavours and ability to create your own!
+- Compile user config for fastest startuptime
+- Integrations with lsp, treesitter and a bunch of plugins
+- Supports for many other applications
+
+
+==============================================================================
+2. Installation *catppuccin-installation*
+
+lazy.nvim
+
+>lua
+ { "catppuccin/nvim", name = "catppuccin", priority = 1000 }
+<
+
+packer.nvim
+
+>lua
+ use { "catppuccin/nvim", as = "catppuccin" }
+<
+
+vim-plug
+
+>vim
+ Plug 'catppuccin/nvim', { 'as': 'catppuccin' }
+<
+
+
+==============================================================================
+3. Usage *catppuccin-usage*
+
+>vim
+ colorscheme catppuccin " catppuccin-latte, catppuccin-frappe, catppuccin-macchiato, catppuccin-mocha
+<
+
+>lua
+ vim.cmd.colorscheme "catppuccin"
+<
+
+
+==============================================================================
+4. Configuration *catppuccin-configuration*
+
+There is no need to call `setup` if you don’t want to change the default
+options and settings.
+
+>lua
+ require("catppuccin").setup({
+ flavour = "auto", -- latte, frappe, macchiato, mocha
+ background = { -- :h background
+ light = "latte",
+ dark = "mocha",
+ },
+ transparent_background = false, -- disables setting the background color.
+ show_end_of_buffer = false, -- shows the '~' characters after the end of buffers
+ term_colors = false, -- sets terminal colors (e.g. `g:terminal_color_0`)
+ dim_inactive = {
+ enabled = false, -- dims the background color of inactive window
+ shade = "dark",
+ percentage = 0.15, -- percentage of the shade to apply to the inactive window
+ },
+ no_italic = false, -- Force no italic
+ no_bold = false, -- Force no bold
+ no_underline = false, -- Force no underline
+ styles = { -- Handles the styles of general hi groups (see `:h highlight-args`):
+ comments = { "italic" }, -- Change the style of comments
+ conditionals = { "italic" },
+ loops = {},
+ functions = {},
+ keywords = {},
+ strings = {},
+ variables = {},
+ numbers = {},
+ booleans = {},
+ properties = {},
+ types = {},
+ operators = {},
+ -- miscs = {}, -- Uncomment to turn off hard-coded styles
+ },
+ color_overrides = {},
+ custom_highlights = {},
+ default_integrations = true,
+ integrations = {
+ cmp = true,
+ gitsigns = true,
+ nvimtree = true,
+ treesitter = true,
+ notify = false,
+ mini = {
+ enabled = true,
+ indentscope_color = "",
+ },
+ -- For more plugins integrations please scroll down (https://github.com/catppuccin/nvim#integrations)
+ },
+ })
+
+ -- setup must be called before loading
+ vim.cmd.colorscheme "catppuccin"
+<
+
+
+==============================================================================
+5. Customize highlights *catppuccin-customize-highlights*
+
+
+GET CATPPUCCIN COLORS *catppuccin-customize-highlights-get-catppuccin-colors*
+
+>lua
+ local latte = require("catppuccin.palettes").get_palette "latte"
+ local frappe = require("catppuccin.palettes").get_palette "frappe"
+ local macchiato = require("catppuccin.palettes").get_palette "macchiato"
+ local mocha = require("catppuccin.palettes").get_palette "mocha"
+<
+
+Returns a table where the key is the name of the color and the value is its hex
+value corresponding to each flavour.
+
+
+OVERWRITING COLORS *catppuccin-customize-highlights-overwriting-colors*
+
+Colors can be overwritten using `color_overrides` in the setting, checkout
+https://github.com/catppuccin/nvim/discussions/323 for inspirations:
+
+>lua
+ require("catppuccin").setup {
+ color_overrides = {
+ all = {
+ text = "#ffffff",
+ },
+ latte = {
+ base = "#ff0000",
+ mantle = "#242424",
+ crust = "#474747",
+ },
+ frappe = {},
+ macchiato = {},
+ mocha = {},
+ }
+ }
+<
+
+
+ [!Note] For more information check out our style-guide
+
+
+OVERWRITING HIGHLIGHT GROUPS*catppuccin-customize-highlights-overwriting-highlight-groups*
+
+Global highlight groups can be overwritten in the setting, for example:
+
+>lua
+ require("catppuccin").setup {
+ custom_highlights = function(colors)
+ return {
+ Comment = { fg = colors.flamingo },
+ TabLineSel = { bg = colors.pink },
+ CmpBorder = { fg = colors.surface2 },
+ Pmenu = { bg = colors.none },
+ }
+ end
+ }
+<
+
+Per flavour highlight groups can also be overwritten in the setting, for
+example:
+
+>lua
+ require("catppuccin").setup {
+ highlight_overrides = {
+ all = function(colors)
+ return {
+ NvimTreeNormal = { fg = colors.none },
+ CmpBorder = { fg = "#3e4145" },
+ }
+ end,
+ latte = function(latte)
+ return {
+ Normal = { fg = latte.base },
+ }
+ end,
+ frappe = function(frappe)
+ return {
+ ["@comment"] = { fg = frappe.surface2, style = { "italic" } },
+ }
+ end,
+ macchiato = function(macchiato)
+ return {
+ LineNr = { fg = macchiato.overlay1 },
+ }
+ end,
+ mocha = function(mocha)
+ return {
+ Comment = { fg = mocha.flamingo },
+ }
+ end,
+ },
+ }
+<
+
+
+==============================================================================
+6. Integrations *catppuccin-integrations*
+
+Catppuccin provides theme support for other plugins in the Neovim ecosystem and
+extended Neovim functionality through _integrations_.
+
+To enable/disable an integration you just need to set it to true/false, for
+example:
+
+>lua
+ require("catppuccin").setup({
+ integrations = {
+ cmp = true,
+ gitsigns = true,
+ nvimtree = true,
+ treesitter = true,
+ notify = false,
+ mini = {
+ enabled = true,
+ indentscope_color = "",
+ },
+ }
+ })
+<
+
+Some integrations are enabled by default, you can control this behaviour with
+`default_integrations` option.
+
+>lua
+ require("catppuccin").setup({
+ default_integrations = false,
+ })
+<
+
+Below is a list of supported plugins and their corresponding integration
+module.
+
+
+ [!Important] If you’d like to know which highlight groups are being affected
+ by catppuccin, check out this directory: `lua/catppuccin/groups/integrations/`
+ .
+PluginDefaultaerial.nvim>lua
+ aerial = false
+<
+
+alpha-nvim>lua
+ alpha = true
+<
+
+barbar.nvim>lua
+ barbar = false
+<
+
+barbecue.nvim>lua
+ barbecue = {
+ dim_dirname = true, -- directory name is dimmed by default
+ bold_basename = true,
+ dim_context = false,
+ alt_background = false,
+ },
+<
+
+Special ~
+
+Use this to set it up:
+
+>lua
+ require("barbecue").setup {
+ theme = "catppuccin", -- catppuccin-latte, catppuccin-frappe, catppuccin-macchiato, catppuccin-mocha
+ }
+<
+
+beacon.nvim>lua
+ beacon = false
+<
+
+bufferline.nvimSpecial ~
+
+Update your bufferline config to use the Catppuccin components:
+
+
+ [!NOTE] bufferline needs to be loaded after setting up catppuccin or it will
+ highlight incorrectly
+>lua
+ use "akinsho/bufferline.nvim" {
+ after = "catppuccin",
+ config = function()
+ require("bufferline").setup {
+ highlights = require("catppuccin.groups.integrations.bufferline").get()
+ }
+ end
+ }
+<
+
+Configurations are self-explanatory, see |bufferline-highlights| for detailed
+explanations:
+
+>lua
+ local mocha = require("catppuccin.palettes").get_palette "mocha"
+ bufferline.setup {
+ highlights = require("catppuccin.groups.integrations.bufferline").get {
+ styles = { "italic", "bold" },
+ custom = {
+ all = {
+ fill = { bg = "#000000" },
+ },
+ mocha = {
+ background = { fg = mocha.text },
+ },
+ latte = {
+ background = { fg = "#000000" },
+ },
+ },
+ },
+ }
+<
+
+coc.nvim>lua
+ coc_nvim = false
+<
+
+Special ~
+
+Setting `enabled` to `true` enables this integration.
+
+>lua
+ coc_nvim = true,
+<
+
+
+ [!Note] coc.nvim by default link to native lsp highlight groups so config from
+ `native_lsp` will also apply to coc
+In the inners tables you can set the style for the diagnostics, both
+`virtual_text` (what you see on the side) and `underlines` (what points
+directly at the thing (e.g. an error)).
+
+>lua
+ native_lsp = {
+ enabled = true,
+ virtual_text = {
+ errors = { "italic" },
+ hints = { "italic" },
+ warnings = { "italic" },
+ information = { "italic" },
+ },
+ underlines = {
+ errors = { "underline" },
+ hints = { "underline" },
+ warnings = { "underline" },
+ information = { "underline" },
+ },
+ inlay_hints = {
+ background = true,
+ },
+ },
+<
+
+colorful-winsep.nvim>lua
+ colorful_winsep = {
+ enabled = false,
+ color = "red",
+ }
+<
+
+dashboard-nvim>lua
+ dashboard = true
+<
+
+diffview.nvim>lua
+ diffview = false
+<
+
+dropbar.nvim>lua
+ dropbar = {
+ enabled = false,
+ color_mode = false, -- enable color for kind's texts, not just kind's icons
+ },
+<
+
+feline.nvimSpecial ~
+
+Update your Feline config to use the Catppuccin components:
+
+>lua
+ local ctp_feline = require('catppuccin.groups.integrations.feline')
+
+ ctp_feline.setup()
+
+ require("feline").setup({
+ components = ctp_feline.get(),
+ })
+<
+
+Notice that calling `setup()` is optional. You may pass a lua table in order to
+change assets, settings and the colors per vim mode.
+
+Here are the defaults:
+
+>lua
+ local clrs = require("catppuccin.palettes").get_palette()
+ local ctp_feline = require('catppuccin.groups.integrations.feline')
+ local U = require "catppuccin.utils.colors"
+
+ ctp_feline.setup({
+ assets = {
+ left_separator = "",
+ right_separator = "",
+ mode_icon = "",
+ dir = "",
+ file = "",
+ lsp = {
+ server = "",
+ error = "",
+ warning = "",
+ info = "",
+ hint = "",
+ },
+ git = {
+ branch = "",
+ added = "",
+ changed = "",
+ removed = "",
+ },
+ },
+ sett = {
+ text = U.vary_color({ latte = latte.base }, clrs.surface0),
+ bkg = U.vary_color({ latte = latte.crust }, clrs.surface0),
+ diffs = clrs.mauve,
+ extras = clrs.overlay1,
+ curr_file = clrs.maroon,
+ curr_dir = clrs.flamingo,
+ show_modified = true -- show if the file has been modified
+ },
+ mode_colors = {
+ ["n"] = { "NORMAL", clrs.lavender },
+ ["no"] = { "N-PENDING", clrs.lavender },
+ ["i"] = { "INSERT", clrs.green },
+ ["ic"] = { "INSERT", clrs.green },
+ ["t"] = { "TERMINAL", clrs.green },
+ ["v"] = { "VISUAL", clrs.flamingo },
+ ["V"] = { "V-LINE", clrs.flamingo },
+ [""] = { "V-BLOCK", clrs.flamingo },
+ ["R"] = { "REPLACE", clrs.maroon },
+ ["Rv"] = { "V-REPLACE", clrs.maroon },
+ ["s"] = { "SELECT", clrs.maroon },
+ ["S"] = { "S-LINE", clrs.maroon },
+ [""] = { "S-BLOCK", clrs.maroon },
+ ["c"] = { "COMMAND", clrs.peach },
+ ["cv"] = { "COMMAND", clrs.peach },
+ ["ce"] = { "COMMAND", clrs.peach },
+ ["r"] = { "PROMPT", clrs.teal },
+ ["rm"] = { "MORE", clrs.teal },
+ ["r?"] = { "CONFIRM", clrs.mauve },
+ ["!"] = { "SHELL", clrs.green },
+ },
+ view = {
+ lsp = {
+ progress = true, -- if true the status bar will display an lsp progress indicator
+ name = false, -- if true the status bar will display the lsp servers name, otherwise it will display the text "Lsp"
+ exclude_lsp_names = {}, -- lsp server names that should not be displayed when name is set to true
+ separator = "|", -- the separator used when there are multiple lsp servers
+ },
+ }
+ })
+<
+
+
+ [!Warning] Currently feline doesn’t officially support custom themes
+ . In order for
+ `:colorscheme catppuccin-` to work you could add this autocmd as a
+ workaround:
+>lua
+ vim.api.nvim_create_autocmd("ColorScheme", {
+ pattern = "*",
+ callback = function()
+ package.loaded["feline"] = nil
+ package.loaded["catppuccin.groups.integrations.feline"] = nil
+ require("feline").setup {
+ components = require("catppuccin.groups.integrations.feline").get(),
+ }
+ end,
+ })
+<
+
+fern.vim>lua
+ fern = false
+<
+
+fidget.nvim>lua
+ fidget = false
+<
+
+Special ~
+
+Set `notification.window.winblend` to `0`:
+
+>lua
+ require("fidget").setup {
+ notification = {
+ window = {
+ winblend = 0,
+ },
+ }
+ -- ... the rest of your fidget config
+ }
+<
+
+flash.nvim>lua
+ flash = true
+<
+
+gitsigns.nvim>lua
+ gitsigns = true
+<
+
+harpoon>lua
+ harpoon = false
+<
+
+headlines.nvim>lua
+ headlines = false
+<
+
+hop.nvim>lua
+ hop = false
+<
+
+indent-blankline.nvim>lua
+ indent_blankline = {
+ enabled = true,
+ scope_color = "", -- catppuccin color (eg. `lavender`) Default: text
+ colored_indent_levels = false,
+ },
+<
+
+Special ~
+
+`colored_indent_levels` enables char highlights per indent level. Follow the
+instructions here
+
+to set the latter up.
+
+leap.nvim>lua
+ leap = false
+<
+
+lightline.vimSpecial ~
+
+>vim
+ let g:lightline = {'colorscheme': 'catppuccin'}
+<
+
+lightspeed.nvim>lua
+ lightspeed = false
+<
+
+lspsaga.nvim>lua
+ lsp_saga = false
+<
+
+Special ~
+
+For custom Lsp Kind Icon and Color
+
+>lua
+ require("lspsaga").setup {
+ ui = {
+ kind = require("catppuccin.groups.integrations.lsp_saga").custom_kind(),
+ },
+ }
+<
+
+lualine.nvimSpecial ~
+
+>lua
+ require('lualine').setup {
+ options = {
+ theme = "catppuccin"
+ -- ... the rest of your lualine config
+ }
+ }
+<
+
+markdown>lua
+ markdown = true
+<
+
+mason.nvim>lua
+ mason = false
+<
+
+mini.nvim>lua
+ mini = {
+ enabled = true,
+ indentscope_color = "", -- catppuccin color (eg. `lavender`) Default: text
+ },
+<
+
+neo-tree.nvim>lua
+ neotree = false
+<
+
+neogit>lua
+ neogit = true
+<
+
+neotest>lua
+ neotest = false
+<
+
+noice.nvim>lua
+ noice = false
+<
+
+NormalNvim>lua
+ NormalNvim = false
+<
+
+notifier.nvim>lua
+ notifier = false
+<
+
+nvim-cmp>lua
+ cmp = true
+<
+
+nvim-dap>lua
+ dap = true
+<
+
+Special ~
+
+>lua
+ local sign = vim.fn.sign_define
+
+ sign("DapBreakpoint", { text = "●", texthl = "DapBreakpoint", linehl = "", numhl = ""})
+ sign("DapBreakpointCondition", { text = "●", texthl = "DapBreakpointCondition", linehl = "", numhl = ""})
+ sign("DapLogPoint", { text = "◆", texthl = "DapLogPoint", linehl = "", numhl = ""})
+<
+
+nvim-dap-ui>lua
+ dap_ui = true
+<
+
+nvim-lspconfig>lua
+ native_lsp = {
+ enabled = true,
+ virtual_text = {
+ errors = { "italic" },
+ hints = { "italic" },
+ warnings = { "italic" },
+ information = { "italic" },
+ },
+ underlines = {
+ errors = { "underline" },
+ hints = { "underline" },
+ warnings = { "underline" },
+ information = { "underline" },
+ },
+ inlay_hints = {
+ background = true,
+ },
+ },
+<
+
+Special ~
+
+In the inners tables you can set the style for the diagnostics, both
+`virtual_text` (what you see on the side) and `underlines` (what points
+directly at the thing (e.g. an error)).
+
+navic>lua
+ navic = {
+ enabled = false,
+ custom_bg = "NONE", -- "lualine" will set background to mantle
+ },
+<
+
+Special ~
+
+>lua
+ -- You NEED to enable highlight in nvim-navic setting or it won't work
+ require("nvim-navic").setup {
+ highlight = true
+ }
+<
+
+nvim-notify>lua
+ notify = false
+<
+
+nvim-semantic-tokens>lua
+ semantic_tokens = true
+<
+
+nvim-tree.lua>lua
+ nvimtree = true
+<
+
+nvim-treesitter-context>lua
+ treesitter_context = true
+<
+
+nvim-treesitter>lua
+ treesitter = true
+<
+
+nvim-ts-rainbow2>lua
+ ts_rainbow2 = false
+<
+
+nvim-ts-rainbow>lua
+ ts_rainbow = false
+<
+
+nvim-ufo>lua
+ ufo = true
+<
+
+nvim-window-picker>lua
+ window_picker = false
+<
+
+octo.nvim>lua
+ octo = false
+<
+
+overseer.nvim>lua
+ overseer = false
+<
+
+pounce.nvim>lua
+ pounce = false
+<
+
+rainbow-delimiters.nvim>lua
+ rainbow_delimiters = true
+<
+
+reactive.nvimSpecial ~
+
+There’re 2 available presets (`cursor` and `cursorline`) for every flavour.
+
+Here is how you can use them.
+
+>lua
+ require('reactive').setup {
+ load = { 'catppuccin-mocha-cursor', 'catppuccin-mocha-cursorline' }
+ }
+<
+
+To use another flavour just replace `mocha` with the one you want to use.
+
+symbols-outline.nvim
+ [!NOTE] This plugin has been archived by the author, consider using
+ outline.nvim
+>lua
+ symbols_outline = false
+<
+
+telekasten.nvim>lua
+ telekasten = false
+<
+
+telescope.nvim>lua
+ telescope = {
+ enabled = true,
+ -- style = "nvchad"
+ }
+<
+
+trouble.nvim>lua
+ lsp_trouble = false
+<
+
+vim-airlineSpecial ~
+
+>vim
+ let g:airline_theme = 'catppuccin'
+<
+
+vim-clapSpecial ~
+
+Use this to set it up:
+
+>vim
+ let g:clap_theme = 'catppuccin'
+<
+
+vim-gitgutter>lua
+ gitgutter = false
+<
+
+vim-illuminate>lua
+ illuminate = {
+ enabled = true,
+ lsp = false
+ }
+<
+
+vim-sandwich>lua
+ sandwich = false
+<
+
+vim-sneak>lua
+ vim_sneak = false
+<
+
+vimwiki>lua
+ vimwiki = false
+<
+
+which-key.nvim>lua
+ which_key = false
+<
+
+
+==============================================================================
+7. Compile *catppuccin-compile*
+
+
+ **Important** As of 7/10/2022, catppuccin should be able to automatically
+ recompile when the setup table changed.
+Catppuccin is a highly customizable and configurable colorscheme. This does
+however come at the cost of complexity and execution time. Catppuccin can pre
+compute the results of your configuration and store the results in a compiled
+lua file. We use these precached values to set it’s highlights.
+
+By default catppuccin writes the compiled results into the system’s cache
+directory. You can change the cache dir using:
+
+>lua
+ require("catppuccin").setup({ -- Note: On windows we replace `/` with `\` by default
+ compile_path = vim.fn.stdpath "cache" .. "/catppuccin"
+ })
+<
+
+
+==============================================================================
+8. FAQ *catppuccin-faq*
+
+
+WRONG TREESITTER HIGHLIGHTS *catppuccin-faq-wrong-treesitter-highlights*
+
+Please disable `additional_vim_regex_highlighting`
+
+>lua
+ require("nvim-treesitter.configs").setup {
+ highlight = {
+ enable = true,
+ additional_vim_regex_highlighting = false
+ },
+ }
+<
+
+
+COLORS DOESN’T MATCH PREVIEW SCREENSHOTS*catppuccin-faq-colors-doesn’t-match-preview-screenshots*
+
+Catppuccin requires true color support AKA terminals support the full range of
+16 million colors
+
+- Supported: iterm2 (macOS), kitty, wezterm, alacritty, tmux, …
+
+Full list of support terminals can be found here:
+
+
+- Unsupported terminal: Terminal.app (macOS), Terminus, Terminology, …
+
+Full list of Unsupported terminals can be found here:
+
+
+
+FOR TMUX USERS ~
+
+- Enable true color support to fix the following abnormal colors :
+
+- Enable italic font support to fix the following incorrect if, then, else, end highlights :
+
+
+==============================================================================
+9. Thanks to *catppuccin-thanks-to*
+
+- Pocco81
+- nullchilly
+
+==============================================================================
+10. Links *catppuccin-links*
+
+1. *image*: https://user-images.githubusercontent.com/1941785/220280749-c3ab52fb-9b8a-4f04-ab98-f8c1bb41f84b.png
+2. *image*: https://user-images.githubusercontent.com/13246770/224011118-dcf0f567-650a-4eb2-8be6-0af5cf435501.png
+
+Generated by panvimdoc
+
+vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-frappe.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-frappe.lua
new file mode 100644
index 00000000..ecebd5ec
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-frappe.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.barbecue" "frappe"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-latte.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-latte.lua
new file mode 100644
index 00000000..e52461d8
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-latte.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.barbecue" "latte"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-macchiato.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-macchiato.lua
new file mode 100644
index 00000000..5778cea3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-macchiato.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.barbecue" "macchiato"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-mocha.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-mocha.lua
new file mode 100644
index 00000000..044f8716
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin-mocha.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.barbecue" "mocha"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin.lua
new file mode 100644
index 00000000..b5848cf7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/barbecue/theme/catppuccin.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.barbecue"()
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/editor.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/editor.lua
new file mode 100644
index 00000000..6a12ef66
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/editor.lua
@@ -0,0 +1,77 @@
+local M = {}
+
+function M.get()
+ return {
+ ColorColumn = { bg = C.surface0 }, -- used for the columns set with 'colorcolumn'
+ Conceal = { fg = C.overlay1 }, -- placeholder characters substituted for concealed text (see 'conceallevel')
+ Cursor = { fg = C.base, bg = C.text }, -- character under the cursor
+ lCursor = { fg = C.base, bg = C.text }, -- the character under the cursor when |language-mapping| is used (see 'guicursor')
+ CursorIM = { fg = C.base, bg = C.text }, -- like Cursor, but used when in IME mode |CursorIM|
+ CursorColumn = { bg = C.mantle }, -- Screen-column at the cursor, when 'cursorcolumn' is set.
+ CursorLine = {
+ bg = U.vary_color({ latte = U.lighten(C.mantle, 0.70, C.base) }, U.darken(C.surface0, 0.64, C.base)),
+ }, -- Screen-line at the cursor, when 'cursorline' is set. Low-priority if forecrust (ctermfg OR guifg) is not set.
+ Directory = { fg = C.blue }, -- directory names (and other special names in listings)
+ EndOfBuffer = { fg = O.show_end_of_buffer and C.surface1 or C.base }, -- filler lines (~) after the end of the buffer. By default, this is highlighted like |hl-NonText|.
+ ErrorMsg = { fg = C.red, style = { "bold", "italic" } }, -- error messages on the command line
+ VertSplit = { fg = O.transparent_background and C.surface1 or C.crust }, -- the column separating vertically split windows
+ Folded = { fg = C.blue, bg = O.transparent_background and C.none or C.surface1 }, -- line used for closed folds
+ FoldColumn = { fg = C.overlay0 }, -- 'foldcolumn'
+ SignColumn = { fg = C.surface1 }, -- column where |signs| are displayed
+ SignColumnSB = { bg = C.crust, fg = C.surface1 }, -- column where |signs| are displayed
+ Substitute = { bg = C.surface1, fg = U.vary_color({ latte = C.red }, C.pink) }, -- |:substitute| replacement text highlighting
+ LineNr = { fg = C.surface1 }, -- Line number for ":number" and ":#" commands, and when 'number' or 'relativenumber' option is set.
+ CursorLineNr = { fg = C.lavender }, -- Like LineNr when 'cursorline' or 'relativenumber' is set for the cursor line. highlights the number in numberline.
+ MatchParen = { fg = C.peach, bg = C.surface1, style = { "bold" } }, -- The character under the cursor or just before it, if it is a paired bracket, and its match. |pi_paren.txt|
+ ModeMsg = { fg = C.text, style = { "bold" } }, -- 'showmode' message (e.g., "-- INSERT -- ")
+ -- MsgArea = { fg = C.text }, -- Area for messages and cmdline, don't set this highlight because of https://github.com/neovim/neovim/issues/17832
+ MsgSeparator = {}, -- Separator for scrolled messages, `msgsep` flag of 'display'
+ MoreMsg = { fg = C.blue }, -- |more-prompt|
+ NonText = { fg = C.overlay0 }, -- '@' at the end of the window, characters from 'showbreak' and other characters that do not really exist in the text (e.g., ">" displayed when a double-wide character doesn't fit at the end of the line). See also |hl-EndOfBuffer|.
+ Normal = { fg = C.text, bg = O.transparent_background and C.none or C.base }, -- normal text
+ NormalNC = {
+ fg = C.text,
+ bg = (O.transparent_background and O.dim_inactive.enabled and C.dim)
+ or (O.dim_inactive.enabled and C.dim)
+ or (O.transparent_background and C.none)
+ or C.base,
+ }, -- normal text in non-current windows
+ NormalSB = { fg = C.text, bg = C.crust }, -- normal text in non-current windows
+ NormalFloat = { fg = C.text, bg = (O.transparent_background and vim.o.winblend == 0) and C.none or C.mantle }, -- Normal text in floating windows.
+ FloatBorder = { fg = C.blue },
+ FloatTitle = { fg = C.subtext0 }, -- Title of floating windows
+ Pmenu = {
+ bg = (O.transparent_background and vim.o.pumblend == 0) and C.none or U.darken(C.surface0, 0.8, C.crust),
+ fg = C.overlay2,
+ }, -- Popup menu: normal item.
+ PmenuSel = { bg = C.surface1, style = { "bold" } }, -- Popup menu: selected item.
+ PmenuSbar = { bg = C.surface1 }, -- Popup menu: scrollbar.
+ PmenuThumb = { bg = C.overlay0 }, -- Popup menu: Thumb of the scrollbar.
+ Question = { fg = C.blue }, -- |hit-enter| prompt and yes/no questions
+ QuickFixLine = { bg = C.surface1, style = { "bold" } }, -- Current |quickfix| item in the quickfix window. Combined with |hl-CursorLine| when the cursor is there.
+ Search = { bg = U.darken(C.sky, 0.30, C.base), fg = C.text }, -- Last search pattern highlighting (see 'hlsearch'). Also used for similar items that need to stand out.
+ IncSearch = { bg = U.darken(C.sky, 0.90, C.base), fg = C.mantle }, -- 'incsearch' highlighting; also used for the text replaced with ":s///c"
+ CurSearch = { bg = C.red, fg = C.mantle }, -- 'cursearch' highlighting: highlights the current search you're on differently
+ SpecialKey = { link = "NonText" }, -- Unprintable characters: text displayed differently from what it really is. But not 'listchars' textspace. |hl-Whitespace|
+ SpellBad = { sp = C.red, style = { "undercurl" } }, -- Word that is not recognized by the spellchecker. |spell| Combined with the highlighting used otherwise.
+ SpellCap = { sp = C.yellow, style = { "undercurl" } }, -- Word that should start with a capital. |spell| Combined with the highlighting used otherwise.
+ SpellLocal = { sp = C.blue, style = { "undercurl" } }, -- Word that is recognized by the spellchecker as one that is used in another region. |spell| Combined with the highlighting used otherwise.
+ SpellRare = { sp = C.green, style = { "undercurl" } }, -- Word that is recognized by the spellchecker as one that is hardly ever used. |spell| Combined with the highlighting used otherwise.
+ StatusLine = { fg = C.text, bg = O.transparent_background and C.none or C.mantle }, -- status line of current window
+ StatusLineNC = { fg = C.surface1, bg = O.transparent_background and C.none or C.mantle }, -- status lines of not-current windows Note: if this is equal to "StatusLine" Vim will use "^^^" in the status line of the current window.
+ TabLine = { bg = C.mantle, fg = C.surface1 }, -- tab pages line, not active tab page label
+ TabLineFill = {}, -- tab pages line, where there are no labels
+ TabLineSel = { fg = C.green, bg = C.surface1 }, -- tab pages line, active tab page label
+ Title = { fg = C.blue, style = { "bold" } }, -- titles for output from ":set all", ":autocmd" etc.
+ Visual = { bg = C.surface1, style = { "bold" } }, -- Visual mode selection
+ VisualNOS = { bg = C.surface1, style = { "bold" } }, -- Visual mode selection when vim is "Not Owning the Selection".
+ WarningMsg = { fg = C.yellow }, -- warning messages
+ Whitespace = { fg = C.surface1 }, -- "nbsp", "space", "tab" and "trail" in 'listchars'
+ WildMenu = { bg = C.overlay0 }, -- current match in 'wildmenu' completion
+ WinBar = { fg = C.rosewater },
+ WinBarNC = { link = "WinBar" },
+ WinSeparator = { fg = O.transparent_background and C.surface1 or C.crust },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/NormalNvim.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/NormalNvim.lua
new file mode 100644
index 00000000..7e711efd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/NormalNvim.lua
@@ -0,0 +1,15 @@
+local M = {}
+
+function M.get()
+ return {
+ MarkdownTask = { fg = C.teal, style = { "bold" } },
+ MarkdownTodo = { fg = C.flamingo, style = { "bold" } },
+ MarkdownNote = { fg = C.red, style = { "bold" } },
+ MarkdownSee = { fg = C.blue, style = { "bold" } },
+ MarkdownCheck = { fg = C.green, style = { "bold" } },
+ MarkdownURL = { fg = C.lavender, style = { "bold" } },
+ MarkdownExample = { fg = C.mauve, style = { "bold" } },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/aerial.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/aerial.lua
new file mode 100644
index 00000000..a0f5b0cd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/aerial.lua
@@ -0,0 +1,36 @@
+local M = {}
+
+function M.get()
+ return {
+ AerialLine = { fg = C.yellow, bg = C.none },
+ AerialGuide = { fg = C.overlay2 },
+ AerialBooleanIcon = { link = "@boolean" },
+ AerialClassIcon = { link = "@type" },
+ AerialConstantIcon = { link = "@constant" },
+ AerialConstructorIcon = { link = "@constructor" },
+ AerialFieldIcon = { link = "@field" },
+ AerialFunctionIcon = { link = "@function" },
+ AerialMethodIcon = { link = "@method" },
+ AerialNamespaceIcon = { link = "@namespace" },
+ AerialNumberIcon = { link = "@number" },
+ AerialOperatorIcon = { link = "@operator" },
+ AerialTypeParameterIcon = { link = "@type" },
+ AerialPropertyIcon = { link = "@property" },
+ AerialStringIcon = { link = "@string" },
+ AerialVariableIcon = { link = "@constant" },
+ AerialEnumMemberIcon = { link = "@field" },
+ AerialEnumIcon = { link = "@type" },
+ AerialFileIcon = { link = "@text.uri" },
+ AerialModuleIcon = { link = "@namespace" },
+ AerialPackageIcon = { link = "@namespace" },
+ AerialInterfaceIcon = { link = "@type" },
+ AerialStructIcon = { link = "@type" },
+ AerialEventIcon = { link = "@type" },
+ AerialArrayIcon = { link = "@constant" },
+ AerialObjectIcon = { link = "@type" },
+ AerialKeyIcon = { link = "@type" },
+ AerialNullIcon = { link = "@type" },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/alpha.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/alpha.lua
new file mode 100644
index 00000000..8839b11f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/alpha.lua
@@ -0,0 +1,13 @@
+local M = {}
+
+function M.get()
+ return {
+ AlphaShortcut = { fg = C.green },
+ AlphaHeader = { fg = C.blue },
+ AlphaHeaderLabel = { fg = C.peach },
+ AlphaButtons = { fg = C.lavender },
+ AlphaFooter = { fg = C.yellow, style = { "italic" } },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/barbar.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/barbar.lua
new file mode 100644
index 00000000..6926ccf8
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/barbar.lua
@@ -0,0 +1,25 @@
+local M = {}
+
+function M.get()
+ return {
+ BufferCurrent = { bg = C.surface1, fg = C.text },
+ BufferCurrentIndex = { bg = C.surface1, fg = C.blue },
+ BufferCurrentMod = { bg = C.surface1, fg = C.yellow },
+ BufferCurrentSign = { bg = C.surface1, fg = C.blue },
+ BufferCurrentTarget = { bg = C.surface1, fg = C.red },
+ BufferVisible = { bg = C.mantle, fg = C.text },
+ BufferVisibleIndex = { bg = C.mantle, fg = C.blue },
+ BufferVisibleMod = { bg = C.mantle, fg = C.yellow },
+ BufferVisibleSign = { bg = C.mantle, fg = C.blue },
+ BufferVisibleTarget = { bg = C.mantle, fg = C.red },
+ BufferInactive = { bg = C.mantle, fg = C.overlay0 },
+ BufferInactiveIndex = { bg = C.mantle, fg = C.overlay0 },
+ BufferInactiveMod = { bg = C.mantle, fg = C.yellow },
+ BufferInactiveSign = { bg = C.mantle, fg = C.blue },
+ BufferInactiveTarget = { bg = C.mantle, fg = C.red },
+ BufferTabpages = { bg = C.mantle, fg = C.none },
+ BufferTabpage = { bg = C.mantle, fg = C.blue },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/beacon.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/beacon.lua
new file mode 100644
index 00000000..5f8280c7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/beacon.lua
@@ -0,0 +1,9 @@
+local M = {}
+
+function M.get()
+ return {
+ Beacon = { bg = C.blue },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/bufferline.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/bufferline.lua
new file mode 100644
index 00000000..454fe0d2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/bufferline.lua
@@ -0,0 +1,117 @@
+local M = {}
+local ctp = require "catppuccin"
+local O = ctp.options
+
+function M.get(user_config)
+ user_config = user_config or {}
+ -- Backward compatibility
+ if O.integrations.bufferline then return {} end
+ return function()
+ local C = require("catppuccin.palettes").get_palette()
+ local transparent_background = O.transparent_background
+ local bg_highlight = (transparent_background and O.dim_inactive.enabled and C.dim)
+ or (transparent_background and "NONE")
+ or (O.dim_inactive.enabled and C.dim)
+ or C.crust
+
+ local active_bg = transparent_background and "NONE" or C.base
+ local inactive_bg = transparent_background and "NONE" or C.mantle
+
+ local separator_fg = O.transparent_background and C.surface1 or C.crust
+
+ local styles = user_config.styles or { "bold", "italic" }
+
+ local highlights = {
+ -- buffers
+ background = { bg = inactive_bg },
+ buffer_visible = { fg = C.surface1, bg = inactive_bg },
+ buffer_selected = { fg = C.text, bg = active_bg, style = styles }, -- current
+ -- Duplicate
+ duplicate_selected = { fg = C.text, bg = active_bg, style = styles },
+ duplicate_visible = { fg = C.surface1, bg = inactive_bg, style = styles },
+ duplicate = { fg = C.surface1, bg = inactive_bg, style = styles },
+ -- tabs
+ tab = { fg = C.surface1, bg = inactive_bg },
+ tab_selected = { fg = C.sky, bg = active_bg, bold = true },
+ tab_separator = { fg = separator_fg, bg = inactive_bg },
+ tab_separator_selected = { fg = separator_fg, bg = active_bg },
+
+ tab_close = { fg = C.red, bg = inactive_bg },
+ indicator_selected = { fg = C.peach, bg = active_bg, style = styles },
+ -- separators
+ separator = { fg = separator_fg, bg = inactive_bg },
+ separator_visible = { fg = separator_fg, bg = inactive_bg },
+ separator_selected = { fg = separator_fg, bg = active_bg },
+ offset_separator = { fg = separator_fg, bg = active_bg },
+ -- close buttons
+ close_button = { fg = C.surface1, bg = inactive_bg },
+ close_button_visible = { fg = C.surface1, bg = inactive_bg },
+ close_button_selected = { fg = C.red, bg = active_bg },
+ -- Empty fill
+ fill = { bg = bg_highlight },
+ -- Numbers
+ numbers = { fg = C.subtext0, bg = inactive_bg },
+ numbers_visible = { fg = C.subtext0, bg = inactive_bg },
+ numbers_selected = { fg = C.subtext0, bg = active_bg, style = styles },
+ -- Errors
+ error = { fg = C.red, bg = inactive_bg },
+ error_visible = { fg = C.red, bg = inactive_bg },
+ error_selected = { fg = C.red, bg = active_bg, style = styles },
+ error_diagnostic = { fg = C.red, bg = inactive_bg },
+ error_diagnostic_visible = { fg = C.red, bg = inactive_bg },
+ error_diagnostic_selected = { fg = C.red, bg = active_bg },
+ -- Warnings
+ warning = { fg = C.yellow, bg = inactive_bg },
+ warning_visible = { fg = C.yellow, bg = inactive_bg },
+ warning_selected = { fg = C.yellow, bg = active_bg, style = styles },
+ warning_diagnostic = { fg = C.yellow, bg = inactive_bg },
+ warning_diagnostic_visible = { fg = C.yellow, bg = inactive_bg },
+ warning_diagnostic_selected = { fg = C.yellow, bg = active_bg },
+ -- Infos
+ info = { fg = C.sky, bg = inactive_bg },
+ info_visible = { fg = C.sky, bg = inactive_bg },
+ info_selected = { fg = C.sky, bg = active_bg, style = styles },
+ info_diagnostic = { fg = C.sky, bg = inactive_bg },
+ info_diagnostic_visible = { fg = C.sky, bg = inactive_bg },
+ info_diagnostic_selected = { fg = C.sky, bg = active_bg },
+ -- Hint
+ hint = { fg = C.teal, bg = inactive_bg },
+ hint_visible = { fg = C.teal, bg = inactive_bg },
+ hint_selected = { fg = C.teal, bg = active_bg, style = styles },
+ hint_diagnostic = { fg = C.teal, bg = inactive_bg },
+ hint_diagnostic_visible = { fg = C.teal, bg = inactive_bg },
+ hint_diagnostic_selected = { fg = C.teal, bg = active_bg },
+ -- Diagnostics
+ diagnostic = { fg = C.subtext0, bg = inactive_bg },
+ diagnostic_visible = { fg = C.subtext0, bg = inactive_bg },
+ diagnostic_selected = { fg = C.subtext0, bg = active_bg, style = styles },
+ -- Modified
+ modified = { fg = C.peach, bg = inactive_bg },
+ modified_selected = { fg = C.peach, bg = active_bg },
+ }
+
+ local user_highlights = user_config.custom or {}
+ highlights =
+ vim.tbl_deep_extend("keep", user_highlights[ctp.flavour] or {}, user_highlights.all or {}, highlights)
+
+ for _, color in pairs(highlights) do
+ -- Because default is gui=bold,italic
+ color.italic = false
+ color.bold = false
+
+ if color.style then
+ for _, style in pairs(color.style) do
+ color[style] = true
+ if O.no_italic and style == "italic" then color[style] = false end
+ if O.no_bold and style == "bold" then color[style] = false end
+ if O.no_underline and style == "underline" then color[style] = false end
+ end
+ end
+ color.style = nil
+ end
+
+ return highlights
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/cmp.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/cmp.lua
new file mode 100644
index 00000000..677a90f1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/cmp.lua
@@ -0,0 +1,42 @@
+local M = {}
+
+function M.get()
+ return {
+ CmpItemAbbr = { fg = C.overlay2 },
+ CmpItemAbbrDeprecated = { fg = C.overlay0, style = { "strikethrough" } },
+ CmpItemKind = { fg = C.blue },
+ CmpItemMenu = { fg = C.text },
+ CmpItemAbbrMatch = { fg = C.text, style = { "bold" } },
+ CmpItemAbbrMatchFuzzy = { fg = C.text, style = { "bold" } },
+
+ -- kind support
+ CmpItemKindSnippet = { fg = C.mauve },
+ CmpItemKindKeyword = { fg = C.red },
+ CmpItemKindText = { fg = C.teal },
+ CmpItemKindMethod = { fg = C.blue },
+ CmpItemKindConstructor = { fg = C.blue },
+ CmpItemKindFunction = { fg = C.blue },
+ CmpItemKindFolder = { fg = C.blue },
+ CmpItemKindModule = { fg = C.blue },
+ CmpItemKindConstant = { fg = C.peach },
+ CmpItemKindField = { fg = C.green },
+ CmpItemKindProperty = { fg = C.green },
+ CmpItemKindEnum = { fg = C.green },
+ CmpItemKindUnit = { fg = C.green },
+ CmpItemKindClass = { fg = C.yellow },
+ CmpItemKindVariable = { fg = C.flamingo },
+ CmpItemKindFile = { fg = C.blue },
+ CmpItemKindInterface = { fg = C.yellow },
+ CmpItemKindColor = { fg = C.red },
+ CmpItemKindReference = { fg = C.red },
+ CmpItemKindEnumMember = { fg = C.red },
+ CmpItemKindStruct = { fg = C.blue },
+ CmpItemKindValue = { fg = C.peach },
+ CmpItemKindEvent = { fg = C.blue },
+ CmpItemKindOperator = { fg = C.blue },
+ CmpItemKindTypeParameter = { fg = C.blue },
+ CmpItemKindCopilot = { fg = C.teal },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/coc_nvim.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/coc_nvim.lua
new file mode 100644
index 00000000..d9d8c3a4
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/coc_nvim.lua
@@ -0,0 +1,19 @@
+local M = {}
+
+function M.get()
+ return {
+ -- These groups are for the coc.nvim, see ":h coc-highlights"
+ -- Custom popup menu since coc v0.0.82
+ CocMenuSel = { link = "PmenuSel" },
+ CocPumSearch = { fg = C.sky, style = { "bold" } },
+
+ -- Inlay hints
+ CocInlayHint = {
+ -- fg of `Comment`
+ fg = C.overlay0,
+ style = { "italic" },
+ },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/colorful_winsep.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/colorful_winsep.lua
new file mode 100644
index 00000000..d4d5f885
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/colorful_winsep.lua
@@ -0,0 +1,9 @@
+local M = {}
+
+function M.get()
+ return {
+ NvimSeparator = { bg = C.base, fg = C[O.integrations.colorful_winsep.color] },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dap.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dap.lua
new file mode 100644
index 00000000..94c5f297
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dap.lua
@@ -0,0 +1,13 @@
+local M = {}
+
+function M.get()
+ return {
+ DapBreakpoint = { fg = C.red },
+ DapBreakpointCondition = { fg = C.yellow },
+ DapBreakpointRejected = { fg = C.mauve },
+ DapLogPoint = { fg = C.sky },
+ DapStopped = { fg = C.maroon },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dap_ui.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dap_ui.lua
new file mode 100644
index 00000000..88643e96
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dap_ui.lua
@@ -0,0 +1,39 @@
+local M = {}
+
+function M.get()
+ return {
+ DapUIScope = { fg = C.sky },
+ DapUIType = { fg = C.mauve },
+ DapUIValue = { fg = C.sky },
+ DapUIVariable = { fg = C.text },
+ DapUIModifiedValue = { fg = C.peach },
+ DapUIDecoration = { fg = C.sky },
+ DapUIThread = { fg = C.green },
+ DapUIStoppedThread = { fg = C.sky },
+ DapUISource = { fg = C.lavender },
+ DapUILineNumber = { fg = C.sky },
+ DapUIFloatBorder = { fg = C.sky },
+
+ DapUIWatchesEmpty = { fg = C.maroon },
+ DapUIWatchesValue = { fg = C.green },
+ DapUIWatchesError = { fg = C.maroon },
+
+ DapUIBreakpointsPath = { fg = C.sky },
+ DapUIBreakpointsInfo = { fg = C.green },
+ DapUIBreakpointsCurrentLine = { fg = C.green, style = { "bold" } },
+ DapUIBreakpointsDisabledLine = { fg = C.surface2 },
+
+ DapUIStepOver = { fg = C.blue },
+ DapUIStepInto = { fg = C.blue },
+ DapUIStepBack = { fg = C.blue },
+ DapUIStepOut = { fg = C.blue },
+ DapUIStop = { fg = C.red },
+ DapUIPlayPause = { fg = C.green },
+ DapUIRestart = { fg = C.green },
+ DapUIUnavailable = { fg = C.surface1 },
+
+ DapUIWinSelect = { fg = C.peach },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dashboard.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dashboard.lua
new file mode 100644
index 00000000..52953db4
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dashboard.lua
@@ -0,0 +1,18 @@
+local M = {}
+
+function M.get()
+ return {
+ DashboardShortCut = { fg = C.pink },
+ DashboardHeader = { fg = C.blue },
+ DashboardCenter = { fg = C.green },
+ DashboardFooter = { fg = C.yellow, style = { "italic" } },
+ DashboardMruTitle = { fg = C.sky },
+ DashboardProjectTitle = { fg = C.sky },
+ DashboardFiles = { fg = C.lavender },
+ DashboardKey = { fg = C.peach },
+ DashboardDesc = { fg = C.blue },
+ DashboardIcon = { fg = C.pink, bold = true },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/diffview.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/diffview.lua
new file mode 100644
index 00000000..b14b482d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/diffview.lua
@@ -0,0 +1,41 @@
+local M = {}
+
+function M.get()
+ return {
+ DiffviewDim1 = { link = "Comment" },
+ DiffviewPrimary = { fg = C.blue },
+ DiffviewSecondary = { fg = C.green },
+ DiffviewNormal = { fg = C.text, bg = O.transparent_background and C.none or C.mantle },
+ DiffviewWinSeparator = {
+ fg = O.transparent_background and C.surface1 or C.base,
+ bg = O.transparent_background and C.none or C.base,
+ },
+ DiffviewFilePanelTitle = { fg = C.blue, style = { "bold" } },
+ DiffviewFilePanelCounter = { fg = C.text },
+ DiffviewFilePanelRootPath = { fg = C.lavender, style = { "bold" } },
+ DiffviewFilePanelFileName = { fg = C.text },
+ DiffviewFilePanelSelected = { fg = C.yellow },
+ DiffviewFilePanelPath = { link = "Comment" },
+ DiffviewFilePanelInsertions = { fg = C.green },
+ DiffviewFilePanelDeletions = { fg = C.red },
+ DiffviewFilePanelConflicts = { fg = C.yellow },
+ DiffviewFolderName = { fg = C.blue, style = { "bold" } },
+ DiffviewFolderSign = { fg = C.blue },
+ DiffviewHash = { fg = C.flamingo },
+ DiffviewReference = { fg = C.blue, style = { "bold" } },
+ DiffviewReflogSelector = { fg = C.pink },
+ DiffviewStatusAdded = { fg = C.green },
+ DiffviewStatusUntracked = { fg = C.green },
+ DiffviewStatusModified = { fg = C.yellow },
+ DiffviewStatusRenamed = { fg = C.yellow },
+ DiffviewStatusCopied = { fg = C.yellow },
+ DiffviewStatusTypeChange = { fg = C.yellow },
+ DiffviewStatusUnmerged = { fg = C.yellow },
+ DiffviewStatusUnknown = { fg = C.red },
+ DiffviewStatusDeleted = { fg = C.red },
+ DiffviewStatusBroken = { fg = C.red },
+ DiffviewStatusIgnored = { fg = C.overlay0 },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dropbar.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dropbar.lua
new file mode 100644
index 00000000..712a9148
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/dropbar.lua
@@ -0,0 +1,69 @@
+local M = {}
+
+function M.get()
+ local color = O.integrations.dropbar.color_mode
+ return {
+ DropBarMenuHoverEntry = { link = "Visual" },
+ DropBarMenuHoverIcon = { reverse = true },
+ DropBarMenuHoverSymbol = { bold = true },
+ DropBarIconUISeparator = { fg = C.overlay1 },
+ DropBarKindArray = color and { link = "DropBarIconKindArray" } or { fg = C.text },
+ DropBarKindBoolean = color and { link = "DropBarIconKindBoolean" } or { fg = C.text },
+ DropBarKindBreakStatement = color and { link = "DropBarIconKindBreakStatement" } or { fg = C.text },
+ DropBarKindCall = color and { link = "DropBarIconKindCall" } or { fg = C.text },
+ DropBarKindCaseStatement = color and { link = "DropBarIconKindCaseStatement" } or { fg = C.text },
+ DropBarKindClass = color and { link = "DropBarIconKindClass" } or { fg = C.text },
+ DropBarKindConstant = color and { link = "DropBarIconKindConstant" } or { fg = C.text },
+ DropBarKindConstructor = color and { link = "DropBarIconKindConstructor" } or { fg = C.text },
+ DropBarKindContinueStatement = color and { link = "DropBarIconKindContinueStatement" } or { fg = C.text },
+ DropBarKindDeclaration = color and { link = "DropBarIconKindDeclaration" } or { fg = C.text },
+ DropBarKindDelete = color and { link = "DropBarIconKindDelete" } or { fg = C.text },
+ DropBarKindDoStatement = color and { link = "DropBarIconKindDoStatement" } or { fg = C.text },
+ DropBarKindElseStatement = color and { link = "DropBarIconKindElseStatement" } or { fg = C.text },
+ DropBarKindEnum = color and { link = "DropBarIconKindEnum" } or { fg = C.text },
+ DropBarKindEnumMember = color and { link = "DropBarIconKindEnumMember" } or { fg = C.text },
+ DropBarKindEvent = color and { link = "DropBarIconKindEvent" } or { fg = C.text },
+ DropBarKindField = color and { link = "DropBarIconKindField" } or { fg = C.text },
+ DropBarKindFile = color and { link = "DropBarIconKindFile" } or { fg = C.text },
+ DropBarKindFolder = color and { link = "DropBarIconKindFolder" } or { fg = C.text },
+ DropBarKindForStatement = color and { link = "DropBarIconKindForStatement" } or { fg = C.text },
+ DropBarKindFunction = color and { link = "DropBarIconKindFunction" } or { fg = C.text },
+ DropBarKindIdentifier = color and { link = "DropBarIconKindIdentifier" } or { fg = C.text },
+ DropBarKindIfStatement = color and { link = "DropBarIconKindIfStatement" } or { fg = C.text },
+ DropBarKindInterface = color and { link = "DropBarIconKindInterface" } or { fg = C.text },
+ DropBarKindKeyword = color and { link = "DropBarIconKindKeyword" } or { fg = C.text },
+ DropBarKindList = color and { link = "DropBarIconKindList" } or { fg = C.text },
+ DropBarKindMacro = color and { link = "DropBarIconKindMacro" } or { fg = C.text },
+ DropBarKindMarkdownH1 = color and { link = "DropBarIconKindMarkdownH1" } or { fg = C.text },
+ DropBarKindMarkdownH2 = color and { link = "DropBarIconKindMarkdownH2" } or { fg = C.text },
+ DropBarKindMarkdownH3 = color and { link = "DropBarIconKindMarkdownH3" } or { fg = C.text },
+ DropBarKindMarkdownH4 = color and { link = "DropBarIconKindMarkdownH4" } or { fg = C.text },
+ DropBarKindMarkdownH5 = color and { link = "DropBarIconKindMarkdownH5" } or { fg = C.text },
+ DropBarKindMarkdownH6 = color and { link = "DropBarIconKindMarkdownH6" } or { fg = C.text },
+ DropBarKindMethod = color and { link = "DropBarIconKindMethod" } or { fg = C.text },
+ DropBarKindModule = color and { link = "DropBarIconKindModule" } or { fg = C.text },
+ DropBarKindNamespace = color and { link = "DropBarIconKindNamespace" } or { fg = C.text },
+ DropBarKindNull = color and { link = "DropBarIconKindNull" } or { fg = C.text },
+ DropBarKindNumber = color and { link = "DropBarIconKindNumber" } or { fg = C.text },
+ DropBarKindObject = color and { link = "DropBarIconKindObject" } or { fg = C.text },
+ DropBarKindOperator = color and { link = "DropBarIconKindOperator" } or { fg = C.text },
+ DropBarKindPackage = color and { link = "DropBarIconKindPackage" } or { fg = C.text },
+ DropBarKindProperty = color and { link = "DropBarIconKindProperty" } or { fg = C.text },
+ DropBarKindReference = color and { link = "DropBarIconKindReference" } or { fg = C.text },
+ DropBarKindRepeat = color and { link = "DropBarIconKindRepeat" } or { fg = C.text },
+ DropBarKindScope = color and { link = "DropBarIconKindScope" } or { fg = C.text },
+ DropBarKindSpecifier = color and { link = "DropBarIconKindSpecifier" } or { fg = C.text },
+ DropBarKindStatement = color and { link = "DropBarIconKindStatement" } or { fg = C.text },
+ DropBarKindString = color and { link = "DropBarIconKindString" } or { fg = C.text },
+ DropBarKindStruct = color and { link = "DropBarIconKindStruct" } or { fg = C.text },
+ DropBarKindSwitchStatement = color and { link = "DropBarIconKindSwitchStatement" } or { fg = C.text },
+ DropBarKindType = color and { link = "DropBarIconKindType" } or { fg = C.text },
+ DropBarKindTypeParameter = color and { link = "DropBarIconKindTypeParameter" } or { fg = C.text },
+ DropBarKindUnit = color and { link = "DropBarIconKindUnit" } or { fg = C.text },
+ DropBarKindValue = color and { link = "DropBarIconKindValue" } or { fg = C.text },
+ DropBarKindVariable = color and { link = "DropBarIconKindVariable" } or { fg = C.text },
+ DropBarKindWhileStatement = color and { link = "DropBarIconKindWhileStatement" } or { fg = C.text },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/feline.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/feline.lua
new file mode 100644
index 00000000..f0d9c024
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/feline.lua
@@ -0,0 +1,501 @@
+local M = {}
+
+local C = require("catppuccin.palettes").get_palette()
+local lsp = require "feline.providers.lsp"
+
+local assets = {
+ left_separator = "",
+ right_separator = "",
+ mode_icon = "",
+ dir = "",
+ file = "",
+ lsp = {
+ server = "",
+ error = "",
+ warning = "",
+ info = "",
+ hint = "",
+ },
+ git = {
+ branch = "",
+ added = "",
+ changed = "",
+ removed = "",
+ },
+}
+
+local sett = {
+ text = C.mantle,
+ bkg = C.crust,
+ diffs = C.mauve,
+ extras = C.overlay1,
+ curr_file = C.maroon,
+ curr_dir = C.flamingo,
+ show_modified = false,
+}
+
+if require("catppuccin").flavour == "latte" then
+ local latte = require("catppuccin.palettes").get_palette "latte"
+ sett.text = latte.base
+ sett.bkg = latte.crust
+end
+
+if require("catppuccin").options.transparent_background then sett.bkg = "NONE" end
+
+local mode_colors = {
+ ["n"] = { "NORMAL", C.lavender },
+ ["no"] = { "N-PENDING", C.lavender },
+ ["i"] = { "INSERT", C.green },
+ ["ic"] = { "INSERT", C.green },
+ ["t"] = { "TERMINAL", C.green },
+ ["v"] = { "VISUAL", C.flamingo },
+ ["V"] = { "V-LINE", C.flamingo },
+ [""] = { "V-BLOCK", C.flamingo },
+ ["R"] = { "REPLACE", C.maroon },
+ ["Rv"] = { "V-REPLACE", C.maroon },
+ ["s"] = { "SELECT", C.maroon },
+ ["S"] = { "S-LINE", C.maroon },
+ [""] = { "S-BLOCK", C.maroon },
+ ["c"] = { "COMMAND", C.peach },
+ ["cv"] = { "COMMAND", C.peach },
+ ["ce"] = { "COMMAND", C.peach },
+ ["r"] = { "PROMPT", C.teal },
+ ["rm"] = { "MORE", C.teal },
+ ["r?"] = { "CONFIRM", C.mauve },
+ ["!"] = { "SHELL", C.green },
+}
+
+local view = {
+ lsp = {
+ progress = true,
+ name = false,
+ exclude_lsp_names = {},
+ separator = "|",
+ },
+}
+
+local is_lsp_in_excluded_list = function(lsp_name)
+ for _, excluded_lsp in ipairs(view.lsp.exclude_lsp_names) do
+ if lsp_name == excluded_lsp then return true end
+ end
+ return false
+end
+
+function M.setup(opts)
+ if opts then
+ opts.assets = opts.assets or {}
+ opts.sett = opts.sett or {}
+ opts.mode_colors = opts.mode_colors or {}
+ opts.view = opts.view or {}
+ else
+ opts = {
+ assets = {},
+ sett = {},
+ mode_colors = {},
+ view = {},
+ }
+ end
+ assets = vim.tbl_deep_extend("force", assets, opts.assets)
+ sett = vim.tbl_deep_extend("force", sett, opts.sett)
+ mode_colors = vim.tbl_deep_extend("force", mode_colors, opts.mode_colors)
+ view = vim.tbl_deep_extend("force", view, opts.view)
+end
+
+function M.get()
+ local shortline = false
+
+ local components = {
+ active = { {}, {}, {} }, -- left, center, right
+ inactive = { {} },
+ }
+
+ local function is_enabled(min_width)
+ if shortline then return true end
+
+ return vim.api.nvim_win_get_width(0) > min_width
+ end
+
+ -- global components
+ local invi_sep = {
+ str = " ",
+ hl = {
+ fg = sett.bkg,
+ bg = sett.bkg,
+ },
+ }
+
+ -- helpers
+ local function any_git_changes()
+ local gst = vim.b.gitsigns_status_dict -- git stats
+ if gst then
+ if
+ gst["added"] and gst["added"] > 0
+ or gst["removed"] and gst["removed"] > 0
+ or gst["changed"] and gst["changed"] > 0
+ then
+ return true
+ end
+ end
+ return false
+ end
+
+ -- #################### STATUSLINE ->
+
+ -- ######## Left
+
+ -- Current vi mode ------>
+ local vi_mode_hl = function()
+ return {
+ fg = sett.text,
+ bg = mode_colors[vim.fn.mode()][2],
+ style = "bold",
+ }
+ end
+
+ components.active[1][1] = {
+ provider = " " .. assets.mode_icon .. " ",
+ hl = function()
+ return {
+ fg = sett.text,
+ bg = mode_colors[vim.fn.mode()][2],
+ }
+ end,
+ }
+
+ components.active[1][2] = {
+ provider = function() return mode_colors[vim.fn.mode()][1] .. " " end,
+ hl = vi_mode_hl,
+ }
+
+ -- there is a dilemma: we need to hide Diffs if there is no git info. We can do that, but this will
+ -- leave the right_separator colored with purple, and since we can't change the color conditonally
+ -- then the solution is to create two right_separators: one with a mauve sett.bkg and the other one normal
+ -- sett.bkg; both have the same fg (vi mode). The mauve one appears if there is git info, else the one with
+ -- the normal sett.bkg appears. Fixed :)
+
+ -- enable if git diffs are not available
+ components.active[1][3] = {
+ provider = assets.right_separator,
+ hl = function()
+ return {
+ fg = mode_colors[vim.fn.mode()][2],
+ bg = sett.bkg,
+ }
+ end,
+ enabled = function() return not any_git_changes() end,
+ }
+
+ -- enable if git diffs are available
+ components.active[1][4] = {
+ provider = assets.right_separator,
+ hl = function()
+ return {
+ fg = mode_colors[vim.fn.mode()][2],
+ bg = sett.diffs,
+ }
+ end,
+ enabled = function() return any_git_changes() end,
+ }
+ -- Current vi mode ------>
+
+ -- Diffs ------>
+ components.active[1][5] = {
+ provider = "git_diff_added",
+ hl = {
+ fg = sett.text,
+ bg = sett.diffs,
+ },
+ icon = " " .. assets.git.added .. " ",
+ }
+
+ components.active[1][6] = {
+ provider = "git_diff_changed",
+ hl = {
+ fg = sett.text,
+ bg = sett.diffs,
+ },
+ icon = " " .. assets.git.changed .. " ",
+ }
+
+ components.active[1][7] = {
+ provider = "git_diff_removed",
+ hl = {
+ fg = sett.text,
+ bg = sett.diffs,
+ },
+ icon = " " .. assets.git.removed .. " ",
+ }
+
+ components.active[1][8] = {
+ provider = " ",
+ hl = {
+ fg = sett.bkg,
+ bg = sett.diffs,
+ },
+ enabled = function() return any_git_changes() end,
+ }
+
+ components.active[1][9] = {
+ provider = assets.right_separator,
+ hl = {
+ fg = sett.diffs,
+ bg = sett.bkg,
+ },
+ enabled = function() return any_git_changes() end,
+ }
+ -- Diffs ------>
+
+ -- Extras ------>
+
+ -- file progress
+ components.active[1][10] = {
+ provider = function()
+ local current_line = vim.fn.line "."
+ local total_line = vim.fn.line "$"
+
+ if current_line == 1 then
+ return "Top"
+ elseif current_line == vim.fn.line "$" then
+ return "Bot"
+ end
+ local result, _ = math.modf((current_line / total_line) * 100)
+ return result .. "%%"
+ end,
+ -- enabled = shortline or function(winid)
+ -- return vim.api.nvim_win_get_width(winid) > 90
+ -- end,
+ hl = {
+ fg = sett.extras,
+ bg = sett.bkg,
+ },
+ left_sep = invi_sep,
+ }
+
+ -- position
+ components.active[1][11] = {
+ provider = "position",
+ -- enabled = shortline or function(winid)
+ -- return vim.api.nvim_win_get_width(winid) > 90
+ -- end,
+ hl = {
+ fg = sett.extras,
+ bg = sett.bkg,
+ },
+ left_sep = invi_sep,
+ }
+
+ -- macro
+ components.active[1][12] = {
+ provider = "macro",
+ enabled = function() return vim.api.nvim_get_option "cmdheight" == 0 end,
+ hl = {
+ fg = sett.extras,
+ bg = sett.bkg,
+ },
+ left_sep = invi_sep,
+ }
+
+ -- search count
+ components.active[1][13] = {
+ provider = "search_count",
+ enabled = function() return vim.api.nvim_get_option "cmdheight" == 0 end,
+ hl = {
+ fg = sett.extras,
+ bg = sett.bkg,
+ },
+ left_sep = invi_sep,
+ }
+ -- Extras ------>
+
+ -- ######## Left
+
+ -- ######## Center
+
+ -- Diagnostics ------>
+ -- workspace loader
+ components.active[2][1] = {
+ provider = function()
+ if vim.lsp.status then return "" end
+ local Lsp = vim.lsp.util.get_progress_messages()[1]
+
+ if Lsp then
+ local msg = Lsp.message or ""
+ local percentage = Lsp.percentage
+ if not percentage then return "" end
+ local title = Lsp.title or ""
+ local spinners = {
+ "",
+ "",
+ "",
+ }
+ local success_icon = {
+ "",
+ "",
+ "",
+ }
+ local ms = vim.loop.hrtime() / 1000000
+ local frame = math.floor(ms / 120) % #spinners
+
+ if percentage >= 70 then
+ return string.format(" %%<%s %s %s (%s%%%%) ", success_icon[frame + 1], title, msg, percentage)
+ end
+
+ return string.format(" %%<%s %s %s (%s%%%%) ", spinners[frame + 1], title, msg, percentage)
+ end
+
+ return ""
+ end,
+ enabled = is_enabled(80) and view.lsp.progress == true,
+ hl = {
+ fg = C.rosewater,
+ bg = sett.bkg,
+ },
+ }
+
+ -- general diagnostics (errors, warnings. info and hints)
+ components.active[2][2] = {
+ provider = "diagnostic_errors",
+ enabled = function() return lsp.diagnostics_exist(vim.diagnostic.severity.ERROR) end,
+
+ hl = {
+ fg = C.red,
+ bg = sett.bkg,
+ },
+ icon = " " .. assets.lsp.error .. " ",
+ }
+
+ components.active[2][3] = {
+ provider = "diagnostic_warnings",
+ enabled = function() return lsp.diagnostics_exist(vim.diagnostic.severity.WARN) end,
+ hl = {
+ fg = C.yellow,
+ bg = sett.bkg,
+ },
+ icon = " " .. assets.lsp.warning .. " ",
+ }
+
+ components.active[2][4] = {
+ provider = "diagnostic_info",
+ enabled = function() return lsp.diagnostics_exist(vim.diagnostic.severity.INFO) end,
+ hl = {
+ fg = C.sky,
+ bg = sett.bkg,
+ },
+ icon = " " .. assets.lsp.info .. " ",
+ }
+
+ components.active[2][5] = {
+ provider = "diagnostic_hints",
+ enabled = function() return lsp.diagnostics_exist(vim.diagnostic.severity.HINT) end,
+ hl = {
+ fg = C.rosewater,
+ bg = sett.bkg,
+ },
+ icon = " " .. assets.lsp.hint .. " ",
+ }
+ -- Diagnostics ------>
+
+ -- ######## Center
+
+ -- ######## Right
+
+ components.active[3][1] = {
+ provider = "git_branch",
+ enabled = is_enabled(70),
+ hl = {
+ fg = sett.extras,
+ bg = sett.bkg,
+ },
+ icon = assets.git.branch .. " ",
+ right_sep = invi_sep,
+ }
+
+ components.active[3][2] = {
+ provider = function()
+ local active_clients = vim.lsp.get_active_clients { bufnr = 0 }
+
+ -- show an indicator that we have running lsps
+ if view.lsp.name == false and next(active_clients) ~= nil then return assets.lsp.server .. " " .. "Lsp" end
+
+ -- show the actual name of the runing lsps
+ local index = 0
+ local lsp_names = ""
+ for _, lsp_config in ipairs(active_clients) do
+ if is_lsp_in_excluded_list(lsp_config.name) then goto continue end
+
+ index = index + 1
+ if index == 1 then
+ lsp_names = assets.lsp.server .. " " .. lsp_config.name
+ else
+ lsp_names = lsp_names .. view.lsp.separator .. lsp_config.name
+ end
+
+ ::continue::
+ end
+
+ return lsp_names
+ end,
+
+ hl = {
+ fg = sett.extras,
+ bg = sett.bkg,
+ },
+
+ right_sep = invi_sep,
+ }
+
+ components.active[3][3] = {
+ provider = function()
+ local filename = vim.fn.expand "%:t"
+ local extension = vim.fn.expand "%:e"
+ local present, icons = pcall(require, "nvim-web-devicons")
+ local icon = present and icons.get_icon(filename, extension) or assets.file
+ return (sett.show_modified and "%m" or "") .. " " .. icon .. " " .. filename .. " "
+ end,
+ enabled = is_enabled(70),
+ hl = {
+ fg = sett.text,
+ bg = sett.curr_file,
+ },
+ left_sep = {
+ str = assets.left_separator,
+ hl = {
+ fg = sett.curr_file,
+ bg = sett.bkg,
+ },
+ },
+ }
+
+ components.active[3][4] = {
+ provider = function()
+ local dir_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":t")
+ return " " .. assets.dir .. " " .. dir_name .. " "
+ end,
+ enabled = is_enabled(80),
+ hl = {
+ fg = sett.text,
+ bg = sett.curr_dir,
+ },
+ left_sep = {
+ str = assets.left_separator,
+ hl = {
+ fg = sett.curr_dir,
+ bg = sett.curr_file,
+ },
+ },
+ }
+ -- ######## Right
+
+ -- Inanctive components
+ components.inactive[1][1] = {
+ provider = function() return " " .. string.upper(vim.bo.ft) .. " " end,
+ hl = {
+ fg = C.overlay2,
+ bg = C.mantle,
+ },
+ }
+
+ return components
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/fern.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/fern.lua
new file mode 100644
index 00000000..4e951d9d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/fern.lua
@@ -0,0 +1,9 @@
+local M = {}
+
+function M.get()
+ return {
+ FernBranchText = { fg = C.blue },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/fidget.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/fidget.lua
new file mode 100644
index 00000000..90882323
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/fidget.lua
@@ -0,0 +1,13 @@
+local M = {}
+
+function M.get()
+ return {
+ FidgetTask = {
+ bg = O.transparent_background and C.none or C.mantle,
+ fg = C.text,
+ },
+ FidgetTitle = { fg = C.blue },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/flash.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/flash.lua
new file mode 100644
index 00000000..1a746b6b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/flash.lua
@@ -0,0 +1,14 @@
+local M = {}
+
+function M.get()
+ local bg = O.transparent_background and C.none or C.base
+ return {
+ FlashBackdrop = { fg = C.overlay0 },
+ FlashLabel = { fg = C.green, bg = bg, style = { "bold" } },
+ FlashMatch = { fg = C.lavender, bg = bg },
+ FlashCurrent = { fg = C.peach, bg = bg },
+ FlashPrompt = { link = "NormalFloat" },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/gitgutter.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/gitgutter.lua
new file mode 100644
index 00000000..6a8c4fc8
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/gitgutter.lua
@@ -0,0 +1,11 @@
+local M = {}
+
+function M.get()
+ return {
+ GitGutterAdd = { fg = C.green },
+ GitGutterChange = { fg = C.yellow },
+ GitGutterDelete = { fg = C.red },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/gitsigns.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/gitsigns.lua
new file mode 100644
index 00000000..6bc89403
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/gitsigns.lua
@@ -0,0 +1,53 @@
+local M = {}
+
+function M.get()
+ if type(O.integrations.gitsigns) == "boolean" then
+ O.integrations.gitsigns = { enabled = true, transparent = false }
+ end
+
+ if O.transparent_background then
+ return {
+ GitSignsAdd = { fg = C.green }, -- diff mode: Added line |diff.txt|
+ GitSignsChange = { fg = C.yellow }, -- diff mode: Changed line |diff.txt|
+ GitSignsDelete = { fg = C.red }, -- diff mode: Deleted line |diff.txt|
+
+ GitSignsCurrentLineBlame = { fg = C.surface1 },
+
+ GitSignsAddPreview = O.transparent_background and { fg = U.darken(C.green, 0.72, C.base), bg = C.none }
+ or { link = "DiffAdd" },
+ GitSignsDeletePreview = O.transparent_background and { fg = U.darken(C.red, 0.72, C.base), bg = C.none }
+ or { link = "DiffDelete" },
+ -- for word diff in previews
+ GitSignsAddInline = O.transparent_background and {
+ fg = C.green,
+ bg = C.none,
+ style = { "bold" },
+ } or { link = "DiffAdd" },
+ GitSignsDeleteInline = O.transparent_background and {
+ fg = C.red,
+ bg = C.none,
+ style = { "bold" },
+ } or { link = "DiffDelete" },
+ GitSignsChangeInline = O.transparent_background and {
+ fg = C.yellow,
+ bg = C.none,
+ style = { "bold" },
+ } or { link = "DiffChange" },
+
+ GitSignsDeleteVirtLn = O.transparent_background and { bg = C.none, fg = C.red } or { link = "DiffDelete" },
+ }
+ else
+ return {
+ GitSignsAdd = { fg = C.green }, -- diff mode: Added line |diff.txt|
+ GitSignsChange = { fg = C.yellow }, -- diff mode: Changed line |diff.txt|
+ GitSignsDelete = { fg = C.red }, -- diff mode: Deleted line |diff.txt|
+
+ GitSignsCurrentLineBlame = { fg = C.surface1 },
+
+ GitSignsAddPreview = O.transparent_background and { fg = C.green, bg = C.none } or { link = "DiffAdd" },
+ GitSignsDeletePreview = O.transparent_background and { fg = C.red, bg = C.none } or { link = "DiffDelete" },
+ }
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/harpoon.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/harpoon.lua
new file mode 100644
index 00000000..29bc2078
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/harpoon.lua
@@ -0,0 +1,10 @@
+local M = {}
+
+function M.get()
+ return {
+ HarpoonWindow = { fg = C.text, bg = O.transparent_background and C.none or C.base },
+ HarpoonBorder = { fg = C.blue },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/headlines.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/headlines.lua
new file mode 100644
index 00000000..2b4f49c7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/headlines.lua
@@ -0,0 +1,18 @@
+local M = {}
+
+function M.get()
+ return {
+ Dash = { fg = C.overlay2, style = { "bold" } },
+ Quote = { link = "@markup.strong" },
+ CodeBlock = { bg = C.mantle },
+ Headline = { link = "Headline1" },
+ Headline1 = { bg = C.surface0, fg = C.red },
+ Headline2 = { bg = C.surface0, fg = C.peach },
+ Headline3 = { bg = C.surface0, fg = C.yellow },
+ Headline4 = { bg = C.surface0, fg = C.green },
+ Headline5 = { bg = C.surface0, fg = C.sapphire },
+ Headline6 = { bg = C.surface0, fg = C.lavender },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/hop.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/hop.lua
new file mode 100644
index 00000000..1f989837
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/hop.lua
@@ -0,0 +1,13 @@
+local M = {}
+
+function M.get()
+ local bg = O.transparent_background and C.none or C.base
+ return {
+ HopNextKey = { bg = bg, fg = C.peach, style = { "bold", "underline" } },
+ HopNextKey1 = { bg = bg, fg = C.blue, style = { "bold" } },
+ HopNextKey2 = { bg = bg, fg = C.teal, style = { "bold", "italic" } },
+ HopUnmatched = { bg = bg, fg = C.overlay0 },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/illuminate.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/illuminate.lua
new file mode 100644
index 00000000..f214affe
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/illuminate.lua
@@ -0,0 +1,14 @@
+local M = {}
+
+function M.get()
+ return {
+ IlluminatedWordText = { bg = U.darken(C.surface1, 0.7, C.base) },
+ IlluminatedWordRead = { bg = U.darken(C.surface1, 0.7, C.base) },
+ IlluminatedWordWrite = {
+ bg = U.darken(C.surface1, 0.7, C.base),
+ style = O.integrations.illuminate.lsp and { "standout" } or {},
+ },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/indent_blankline.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/indent_blankline.lua
new file mode 100644
index 00000000..15b94e69
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/indent_blankline.lua
@@ -0,0 +1,24 @@
+local M = {}
+
+function M.get()
+ local scope_color = O.integrations.indent_blankline.scope_color
+
+ local hi = {
+ IblIndent = { fg = C.surface0 },
+ IblScope = { fg = C[scope_color] or C.text },
+ }
+
+ if O.integrations.indent_blankline.colored_indent_levels then
+ hi["RainbowRed"] = { blend = 0, fg = C.red }
+ hi["RainbowYellow"] = { blend = 0, fg = C.yellow }
+ hi["RainbowBlue"] = { blend = 0, fg = C.blue }
+ hi["RainbowOrange"] = { blend = 0, fg = C.peach }
+ hi["RainbowGreen"] = { blend = 0, fg = C.green }
+ hi["RainbowViolet"] = { blend = 0, fg = C.mauve }
+ hi["RainbowCyan"] = { blend = 0, fg = C.teal }
+ end
+
+ return hi
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/leap.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/leap.lua
new file mode 100644
index 00000000..b9bb2943
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/leap.lua
@@ -0,0 +1,24 @@
+local M = {}
+
+function M.get()
+ return {
+ LeapMatch = {
+ fg = O.transparent_background and C.pink or U.vary_color({ latte = "#222222" }, U.brighten(C.green, 0.3)),
+ style = { "underline", "nocombine", O.transparent_background and "bold" or nil },
+ },
+ LeapLabelPrimary = {
+ fg = O.transparent_background and C.green or U.vary_color({ latte = "#222222" }, C.base),
+ bg = O.transparent_background and C.none
+ or U.vary_color({ latte = U.brighten(C.red, 0.4) }, U.brighten(C.green, 0.3)),
+ style = { "nocombine", O.transparent_background and "bold" or nil },
+ },
+ LeapLabelSecondary = {
+ fg = O.transparent_background and C.blue or U.vary_color({ latte = "#222222" }, C.base),
+ bg = O.transparent_background and C.none or U.vary_color({ latte = U.brighten(C.sky, 0.3) }, C.sky),
+ style = { "nocombine", O.transparent_background and "bold" or nil },
+ },
+ LeapBackdrop = { fg = O.transparent_background and C.overlay0 or C.none },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/lightspeed.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/lightspeed.lua
new file mode 100644
index 00000000..c7039ee1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/lightspeed.lua
@@ -0,0 +1,27 @@
+local M = {}
+
+function M.get()
+ return {
+ LightspeedLabel = { fg = C.red, style = { "bold", "underline" } },
+ LightspeedLabelDistant = {
+ fg = U.vary_color({ latte = C.blue }, C.sky),
+ style = { "bold", "underline" },
+ },
+ LightspeedShortcut = {
+ fg = "#ffffff",
+ bg = U.increase_saturation(C.red, 0.7),
+ style = { "bold" },
+ },
+ LightspeedMaskedChar = {
+ fg = U.vary_color({ latte = U.lighten(C.pink, 0.7, C.text) }, U.darken(C.pink, 0.7, C.base)),
+ },
+ LightspeedUnlabeledMatch = { fg = C.text, style = { "bold" } },
+ LightspeedGreyWash = { link = "Comment" },
+ LightspeedUniqueChar = { link = "LightspeedUnlabeledMatch" },
+ LightspeedOneCharMatch = { link = "LightspeedShortcut" },
+ LightspeedPendingOpArea = { link = "IncSearch" },
+ LightspeedCursor = { link = "Cursor" },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/lsp_saga.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/lsp_saga.lua
new file mode 100644
index 00000000..28d71212
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/lsp_saga.lua
@@ -0,0 +1,132 @@
+local M = {}
+
+function M.get()
+ return {
+ SagaTitle = { fg = C.teal, style = { "bold" } },
+ SagaBorder = { fg = C.blue, bg = C.none },
+ SagaNormal = { bg = O.transparent_background and C.none or C.base },
+ SagaToggle = { fg = C.green },
+ SagaCount = { fg = C.overlay1 },
+ SagaBeacon = { bg = U.darken(C.surface0, 0.8, C.crust) },
+ SagaVirtLine = { fg = C.surface2 },
+ SagaSpinner = { fg = C.mauve, style = { "bold" } },
+ SagaSpinnerTitle = { fg = C.mauve, style = { "bold" } },
+ SagaText = { fg = C.text },
+ SagaSelect = { fg = C.blue, style = { "bold" } },
+ SagaSearch = { link = "Search" },
+ SagaFinderFname = { fg = C.subtext0, style = { "bold" } },
+ ActionFix = { fg = C.pink },
+ ActionPreviewTitle = { fg = C.mauve, bg = O.transparent_background and C.none or C.base },
+ CodeActionText = { fg = C.green },
+ CodeActionNumber = { fg = C.pink },
+ SagaImpIcon = { fg = C.pink },
+ SagaLightBulb = { link = "DiagnosticSignHint" },
+ RenameNormal = { fg = C.text },
+ RenameMatch = { link = "Search" },
+ DiagnosticText = { fg = C.text },
+ SagaWinbarSep = { fg = C.flamingo },
+ SagaDetail = { link = "Comment" },
+ SagaFileName = { fg = C.overlay2, style = { "bold" } },
+ SagaFolderName = { fg = C.overlay2, style = { "bold" } },
+ SagaInCurrent = { fg = C.peach },
+
+ -- Lspkind icons support
+ LspKindClass = { fg = C.yellow },
+ LspKindConstant = { fg = C.peach },
+ LspKindConstructor = { fg = C.sapphire },
+ LspKindEnum = { fg = C.yellow },
+ LspKindEnumMember = { fg = C.teal },
+ LspKindEvent = { fg = C.yellow },
+ LspKindField = { fg = C.teal },
+ LspKindFile = { fg = C.rosewater },
+ LspKindFunction = { fg = C.blue },
+ LspKindInterface = { fg = C.yellow },
+ LspKindKey = { fg = C.red },
+ LspKindMethod = { fg = C.blue },
+ LspKindModule = { fg = C.blue },
+ LspKindNamespace = { fg = C.blue },
+ LspKindNumber = { fg = C.peach },
+ LspKindOperator = { fg = C.sky },
+ LspKindPackage = { fg = C.blue },
+ LspKindProperty = { fg = C.teal },
+ LspKindStruct = { fg = C.yellow },
+ LspKindTypeParameter = { fg = C.blue },
+ LspKindVariable = { fg = C.peach },
+ LspKindArray = { fg = C.peach },
+ LspKindBoolean = { fg = C.peach },
+ LspKindNull = { fg = C.yellow },
+ LspKindObject = { fg = C.yellow },
+ LspKindString = { fg = C.green },
+ -- ccls-specific icons.
+ LspKindTypeAlias = { fg = C.green },
+ LspKindParameter = { fg = C.blue },
+ LspKindStaticMethod = { fg = C.peach },
+ -- Microsoft-specific icons.
+ LspKindText = { fg = C.green },
+ LspKindSnippet = { fg = C.mauve },
+ LspKindFolder = { fg = C.blue },
+ LspKindUnit = { fg = C.green },
+ LspKindValue = { fg = C.peach },
+ }
+end
+
+function M.custom_kind()
+ return {
+ File = { " ", "LspKindFile" },
+ Module = { " ", "LspKindModule" },
+ Namespace = { " ", "LspKindNamespace" },
+ Package = { " ", "LspKindPackage" },
+ Class = { " ", "LspKindClass" },
+ Method = { " ", "LspKindMethod" },
+ Property = { " ", "LspKindProperty" },
+ Field = { " ", "LspKindField" },
+ Constructor = { " ", "LspKindConstructor" },
+ Enum = { "", "LspKindEnum" },
+ Interface = { " ", "LspKindInterface" },
+ Function = { " ", "LspKindFunction" },
+ Variable = { " ", "LspKindVariable" },
+ Constant = { " ", "LspKindConstant" },
+ String = { " ", "LspKindString" },
+ Number = { " ", "LspKindNumber" },
+ Boolean = { " ", "LspKindBoolean" },
+ Array = { " ", "LspKindArray" },
+ Object = { " ", "LspKindObject" },
+ Key = { " ", "LspKindKey" },
+ Null = { " ", "LspKindNull" },
+ EnumMember = { " ", "LspKindEnumMember" },
+ Struct = { " ", "LspKindStruct" },
+ Event = { " ", "LspKindEvent" },
+ Operator = { " ", "LspKindOperator" },
+ TypeParameter = { " ", "LspKindTypeParameter" },
+ TypeAlias = { " ", "LspKindTypeAlias" },
+ Parameter = { " ", "LspKindParameter" },
+ StaticMethod = { " ", "LspKindStaticMethod" },
+ Macro = { " ", "LspKindMacro" },
+ Text = { " ", "LspKindText" },
+ Snippet = { " ", "LspKindSnippet" },
+ Folder = { " ", "LspKindFolder" },
+ Unit = { " ", "LspKindUnit" },
+ Value = { " ", "LspKindValue" },
+ }
+end
+
+-- Backwards compatibility
+function M.custom_colors()
+ local C = require("catppuccin.palettes").get_palette()
+ return {
+ normal_bg = C.base,
+ title_bg = C.green,
+ red = C.red,
+ magenta = C.maroon,
+ orange = C.peach,
+ yellow = C.yellow,
+ green = C.green,
+ cyan = C.sky,
+ blue = C.blue,
+ purple = C.mauve,
+ white = C.text,
+ black = C.crust,
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/lsp_trouble.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/lsp_trouble.lua
new file mode 100644
index 00000000..4a5005ab
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/lsp_trouble.lua
@@ -0,0 +1,11 @@
+local M = {}
+
+function M.get()
+ return {
+ TroubleText = { fg = C.green },
+ TroubleCount = { fg = C.pink, bg = O.transparent_background and C.none or C.surface1 },
+ TroubleNormal = { fg = C.text, bg = O.transparent_background and C.none or C.crust },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/markdown.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/markdown.lua
new file mode 100644
index 00000000..a852f709
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/markdown.lua
@@ -0,0 +1,18 @@
+local M = {}
+
+function M.get()
+ return {
+ markdownHeadingDelimiter = { fg = C.peach, style = { "bold" } },
+ markdownCode = { fg = C.flamingo },
+ markdownCodeBlock = { fg = C.flamingo },
+ markdownLinkText = { fg = C.blue, style = { "underline" } },
+ markdownH1 = { link = "rainbow1" },
+ markdownH2 = { link = "rainbow2" },
+ markdownH3 = { link = "rainbow3" },
+ markdownH4 = { link = "rainbow4" },
+ markdownH5 = { link = "rainbow5" },
+ markdownH6 = { link = "rainbow6" },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/mason.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/mason.lua
new file mode 100644
index 00000000..ea510773
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/mason.lua
@@ -0,0 +1,38 @@
+local M = {}
+
+function M.get()
+ local bg = O.transparent_background and C.none or C.lavender
+ local fg = O.transparent_background and C.lavender or C.base
+
+ local secondary_bg = O.transparent_background and C.none or C.blue
+ local secondary_fg = O.transparent_background and C.blue or C.base
+
+ local muted_bg = O.transparent_background and C.none or C.overlay0
+ local muted_fg = O.transparent_background and C.overlay0 or C.base
+
+ return {
+ MasonHeader = { fg = fg, bg = bg, style = { "bold" } },
+ MasonHeaderSecondary = { fg = secondary_fg, bg = secondary_bg, style = { "bold" } },
+
+ MasonHighlight = { fg = C.green },
+ MasonHighlightBlock = {
+ bg = O.transparent_background and C.none or C.green,
+ fg = O.transparent_background and C.green or C.base,
+ },
+ MasonHighlightBlockBold = { bg = secondary_bg, fg = secondary_fg, bold = true },
+
+ MasonHighlightSecondary = { fg = C.mauve },
+ MasonHighlightBlockSecondary = { fg = secondary_fg, bg = secondary_bg },
+ MasonHighlightBlockBoldSecondary = { fg = fg, bg = bg, bold = true },
+
+ MasonMuted = { fg = C.overlay0 },
+ MasonMutedBlock = { bg = muted_bg, fg = muted_fg },
+ MasonMutedBlockBold = { bg = C.yellow, fg = C.base, bold = true },
+
+ MasonError = { fg = C.red },
+
+ MasonHeading = { fg = C.lavender, bold = true },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/mini.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/mini.lua
new file mode 100644
index 00000000..07596da0
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/mini.lua
@@ -0,0 +1,63 @@
+local M = {}
+
+function M.get()
+ local transparent_background = require("catppuccin").options.transparent_background
+ local bg_highlight = transparent_background and "NONE" or C.base
+
+ local inactive_bg = transparent_background and "NONE" or C.mantle
+
+ local indentscope_color = O.integrations.mini.indentscope_color
+ return {
+ MiniCompletionActiveParameter = { style = { "underline" } },
+
+ MiniCursorword = { style = { "underline" } },
+ MiniCursorwordCurrent = { style = { "underline" } },
+
+ MiniIndentscopeSymbol = { fg = C[indentscope_color] or C.text },
+ MiniIndentscopePrefix = { style = { "nocombine" } }, -- Make it invisible
+
+ MiniJump = { fg = C.overlay2, bg = C.pink },
+
+ MiniJump2dSpot = { bg = C.base, fg = C.peach, style = { "bold", "underline" } },
+
+ MiniStarterCurrent = {},
+ MiniStarterFooter = { fg = C.yellow, style = { "italic" } },
+ MiniStarterHeader = { fg = C.blue },
+ MiniStarterInactive = { fg = C.surface2, style = O.styles.comments },
+ MiniStarterItem = { fg = C.text },
+ MiniStarterItemBullet = { fg = C.blue },
+ MiniStarterItemPrefix = { fg = C.pink },
+ MiniStarterSection = { fg = C.flamingo },
+ MiniStarterQuery = { fg = C.green },
+
+ MiniStatuslineDevinfo = { fg = C.subtext1, bg = C.surface1 },
+ MiniStatuslineFileinfo = { fg = C.subtext1, bg = C.surface1 },
+ MiniStatuslineFilename = { fg = C.text, bg = C.mantle },
+ MiniStatuslineInactive = { fg = C.blue, bg = C.mantle },
+ MiniStatuslineModeCommand = { fg = C.base, bg = C.peach, style = { "bold" } },
+ MiniStatuslineModeInsert = { fg = C.base, bg = C.green, style = { "bold" } },
+ MiniStatuslineModeNormal = { fg = C.mantle, bg = C.blue, style = { "bold" } },
+ MiniStatuslineModeOther = { fg = C.base, bg = C.teal, style = { "bold" } },
+ MiniStatuslineModeReplace = { fg = C.base, bg = C.red, style = { "bold" } },
+ MiniStatuslineModeVisual = { fg = C.base, bg = C.mauve, style = { "bold" } },
+
+ MiniSurround = { bg = C.pink, fg = C.surface1 },
+
+ MiniTablineCurrent = { fg = C.text, bg = C.base, sp = C.red, style = { "bold", "italic", "underline" } },
+ MiniTablineFill = { bg = bg_highlight },
+ MiniTablineHidden = { fg = C.text, bg = inactive_bg },
+ MiniTablineModifiedCurrent = { fg = C.red, bg = C.none, style = { "bold", "italic" } },
+ MiniTablineModifiedHidden = { fg = C.red, bg = C.none },
+ MiniTablineModifiedVisible = { fg = C.red, bg = C.none },
+ MiniTablineTabpagesection = { fg = C.surface1, bg = C.base },
+ MiniTablineVisible = { bg = C.none },
+
+ MiniTestEmphasis = { style = { "bold" } },
+ MiniTestFail = { fg = C.red, style = { "bold" } },
+ MiniTestPass = { fg = C.green, style = { "bold" } },
+
+ MiniTrailspace = { bg = C.red },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/native_lsp.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/native_lsp.lua
new file mode 100644
index 00000000..e4ae10a7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/native_lsp.lua
@@ -0,0 +1,100 @@
+local M = {}
+
+function M.get()
+ local virtual_text = O.integrations.native_lsp.virtual_text
+ local underlines = O.integrations.native_lsp.underlines
+ local inlay_hints = O.integrations.native_lsp.inlay_hints
+
+ local error = C.red
+ local warning = C.yellow
+ local info = C.sky
+ local hint = C.teal
+ local darkening_percentage = 0.095
+
+ return {
+ -- These groups are for the native LSP client. Some other LSP clients may
+ -- use these groups, or use their own. Consult your LSP client's
+ -- documentation.
+ LspReferenceText = { bg = C.surface1 }, -- used for highlighting "text" references
+ LspReferenceRead = { bg = C.surface1 }, -- used for highlighting "read" references
+ LspReferenceWrite = { bg = C.surface1 }, -- used for highlighting "write" references
+ -- highlight diagnostics in numberline
+
+ DiagnosticVirtualTextError = {
+ bg = O.transparent_background and C.none or U.darken(error, darkening_percentage, C.base),
+ fg = error,
+ style = virtual_text.errors,
+ }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
+ DiagnosticVirtualTextWarn = {
+ bg = O.transparent_background and C.none or U.darken(warning, darkening_percentage, C.base),
+ fg = warning,
+ style = virtual_text.warnings,
+ }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
+ DiagnosticVirtualTextInfo = {
+ bg = O.transparent_background and C.none or U.darken(info, darkening_percentage, C.base),
+ fg = info,
+ style = virtual_text.information,
+ }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
+ DiagnosticVirtualTextHint = {
+ bg = O.transparent_background and C.none or U.darken(hint, darkening_percentage, C.base),
+ fg = hint,
+ style = virtual_text.hints,
+ }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
+
+ DiagnosticError = { bg = C.none, fg = error, style = virtual_text.errors }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
+ DiagnosticWarn = { bg = C.none, fg = warning, style = virtual_text.warnings }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
+ DiagnosticInfo = { bg = C.none, fg = info, style = virtual_text.information }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
+ DiagnosticHint = { bg = C.none, fg = hint, style = virtual_text.hints }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
+
+ -- for nvim nightly
+ DiagnosticUnderlineError = { style = underlines.errors, sp = error }, -- Used to underline "Error" diagnostics
+ DiagnosticUnderlineWarn = { style = underlines.warnings, sp = warning }, -- Used to underline "Warn" diagnostics
+ DiagnosticUnderlineInfo = { style = underlines.information, sp = info }, -- Used to underline "Info" diagnostics
+ DiagnosticUnderlineHint = { style = underlines.hints, sp = hint }, -- Used to underline "Hint" diagnostics
+
+ DiagnosticFloatingError = { fg = error }, -- Used to color "Error" diagnostic messages in diagnostics float
+ DiagnosticFloatingWarn = { fg = warning }, -- Used to color "Warn" diagnostic messages in diagnostics float
+ DiagnosticFloatingInfo = { fg = info }, -- Used to color "Info" diagnostic messages in diagnostics float
+ DiagnosticFloatingHint = { fg = hint }, -- Used to color "Hint" diagnostic messages in diagnostics float
+
+ DiagnosticSignError = { fg = error }, -- Used for "Error" signs in sign column
+ DiagnosticSignWarn = { fg = warning }, -- Used for "Warn" signs in sign column
+ DiagnosticSignInfo = { fg = info }, -- Used for "Info" signs in sign column
+ DiagnosticSignHint = { fg = hint }, -- Used for "Hint" signs in sign column
+
+ LspDiagnosticsDefaultError = { fg = error }, -- Used as the mantle highlight group. Other LspDiagnostic highlights link to this by default (except Underline)
+ LspDiagnosticsDefaultWarning = { fg = warning }, -- Used as the mantle highlight group. Other LspDiagnostic highlights link to this by default (except Underline)
+ LspDiagnosticsDefaultInformation = { fg = info }, -- Used as the mantle highlight group. Other LspDiagnostic highlights link to this by default (except Underline)
+ LspDiagnosticsDefaultHint = { fg = hint }, -- Used as the mantle highlight group. Other LspDiagnostic highlights link to this by default (except Underline)
+ LspSignatureActiveParameter = { fg = C.peach },
+ -- LspDiagnosticsFloatingError = { }, -- Used to color "Error" diagnostic messages in diagnostics float
+ -- LspDiagnosticsFloatingWarning = { }, -- Used to color "Warning" diagnostic messages in diagnostics float
+ -- LspDiagnosticsFloatingInformation = { }, -- Used to color "Information" diagnostic messages in diagnostics float
+ -- LspDiagnosticsFloatingHint = { }, -- Used to color "Hint" diagnostic messages in diagnostics float
+
+ LspDiagnosticsError = { fg = error },
+ LspDiagnosticsWarning = { fg = warning },
+ LspDiagnosticsInformation = { fg = info },
+ LspDiagnosticsHint = { fg = hint },
+ LspDiagnosticsVirtualTextError = { fg = error, style = virtual_text.errors }, -- Used for "Error" diagnostic virtual text
+ LspDiagnosticsVirtualTextWarning = { fg = warning, style = virtual_text.warnings }, -- Used for "Warning" diagnostic virtual text
+ LspDiagnosticsVirtualTextInformation = { fg = info, style = virtual_text.warnings }, -- Used for "Information" diagnostic virtual text
+ LspDiagnosticsVirtualTextHint = { fg = hint, style = virtual_text.hints }, -- Used for "Hint" diagnostic virtual text
+ LspDiagnosticsUnderlineError = { style = underlines.errors, sp = error }, -- Used to underline "Error" diagnostics
+ LspDiagnosticsUnderlineWarning = { style = underlines.warnings, sp = warning }, -- Used to underline "Warning" diagnostics
+ LspDiagnosticsUnderlineInformation = { style = underlines.information, sp = info }, -- Used to underline "Information" diagnostics
+ LspDiagnosticsUnderlineHint = { style = underlines.hints, sp = hint }, -- Used to underline "Hint" diagnostics
+ LspCodeLens = { fg = C.overlay0 }, -- virtual text of the codelens
+ LspCodeLensSeparator = { link = "LspCodeLens" }, -- virtual text of the codelens separators
+ LspInlayHint = {
+ -- fg of `Comment`
+ fg = C.overlay0,
+ -- bg of `CursorLine`
+ bg = (O.transparent_background or not inlay_hints.background) and C.none
+ or U.vary_color({ latte = U.lighten(C.mantle, 0.70, C.base) }, U.darken(C.surface0, 0.64, C.base)),
+ }, -- virtual text of the inlay hints
+ LspInfoBorder = { link = "FloatBorder" }, -- LspInfo border
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/navic.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/navic.lua
new file mode 100644
index 00000000..da6bcbcf
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/navic.lua
@@ -0,0 +1,39 @@
+local M = {}
+
+function M.get()
+ local background = O.integrations.navic.custom_bg and O.integrations.navic.custom_bg or C.none
+ if O.integrations.navic.custom_bg == "lualine" then background = C.mantle end
+
+ return {
+ NavicIconsFile = { fg = C.blue, bg = background },
+ NavicIconsModule = { fg = C.blue, bg = background },
+ NavicIconsNamespace = { fg = C.blue, bg = background },
+ NavicIconsPackage = { fg = C.blue, bg = background },
+ NavicIconsClass = { fg = C.yellow, bg = background },
+ NavicIconsMethod = { fg = C.blue, bg = background },
+ NavicIconsProperty = { fg = C.green, bg = background },
+ NavicIconsField = { fg = C.green, bg = background },
+ NavicIconsConstructor = { fg = C.blue, bg = background },
+ NavicIconsEnum = { fg = C.green, bg = background },
+ NavicIconsInterface = { fg = C.yellow, bg = background },
+ NavicIconsFunction = { fg = C.blue, bg = background },
+ NavicIconsVariable = { fg = C.flamingo, bg = background },
+ NavicIconsConstant = { fg = C.peach, bg = background },
+ NavicIconsString = { fg = C.green, style = O.styles.strings, bg = background },
+ NavicIconsNumber = { fg = C.peach, bg = background },
+ NavicIconsBoolean = { fg = C.peach, bg = background },
+ NavicIconsArray = { fg = C.peach, bg = background },
+ NavicIconsObject = { fg = C.peach, bg = background },
+ NavicIconsKey = { fg = C.pink, style = O.styles.keywords, bg = background },
+ NavicIconsNull = { fg = C.peach, bg = background },
+ NavicIconsEnumMember = { fg = C.red, bg = background },
+ NavicIconsStruct = { fg = C.blue, bg = background },
+ NavicIconsEvent = { fg = C.blue, bg = background },
+ NavicIconsOperator = { fg = C.sky, bg = background },
+ NavicIconsTypeParameter = { fg = C.blue, bg = background },
+ NavicText = { fg = C.sapphire, bg = background },
+ NavicSeparator = { fg = C.text, bg = background },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/neogit.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/neogit.lua
new file mode 100644
index 00000000..b0499d60
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/neogit.lua
@@ -0,0 +1,244 @@
+local M = {}
+
+function M.get()
+ return {
+ NeogitBranch = {
+ fg = C.peach,
+ style = { "bold" },
+ },
+ NeogitRemote = {
+ fg = C.green,
+ style = { "bold" },
+ },
+ NeogitUnmergedInto = {
+ link = "Function",
+ },
+ NeogitUnpulledFrom = {
+ link = "Function",
+ },
+ NeogitObjectId = {
+ link = "Comment",
+ },
+ NeogitStash = {
+ link = "Comment",
+ },
+ NeogitRebaseDone = {
+ link = "Comment",
+ },
+ NeogitHunkHeader = {
+ bg = U.darken(C.blue, 0.095, C.base),
+ fg = U.darken(C.blue, 0.5, C.base),
+ },
+ NeogitHunkHeaderHighlight = {
+ bg = U.darken(C.blue, 0.215, C.base),
+ fg = C.blue,
+ },
+ NeogitDiffContextHighlight = {
+ bg = C.surface0,
+ },
+ NeogitDiffDeleteHighlight = {
+ bg = U.darken(C.red, 0.345, C.base),
+ fg = U.lighten(C.red, 0.850, C.text),
+ },
+ NeogitDiffAddHighlight = {
+ bg = U.darken(C.green, 0.345, C.base),
+ fg = U.lighten(C.green, 0.850, C.text),
+ },
+ NeogitDiffDelete = {
+ bg = U.darken(C.red, 0.095, C.base),
+ fg = U.darken(C.red, 0.800, C.base),
+ },
+ NeogitDiffAdd = {
+ bg = U.darken(C.green, 0.095, C.base),
+ fg = U.darken(C.green, 0.800, C.base),
+ },
+ NeogitCommitViewHeader = {
+ bg = U.darken(C.blue, 0.300, C.base),
+ fg = U.lighten(C.blue, 0.800, C.text),
+ },
+ NeogitChangeModified = {
+ fg = C.blue,
+ style = { "bold" },
+ },
+ NeogitChangeDeleted = {
+ fg = C.red,
+ style = { "bold" },
+ },
+ NeogitChangeAdded = {
+ fg = C.green,
+ style = { "bold" },
+ },
+ NeogitChangeRenamed = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitChangeUpdated = {
+ fg = C.peach,
+ style = { "bold" },
+ },
+ NeogitChangeCopied = {
+ fg = C.pink,
+ style = { "bold" },
+ },
+ NeogitChangeBothModified = {
+ fg = C.yellow,
+ style = { "bold" },
+ },
+ NeogitChangeNewFile = {
+ fg = C.green,
+ style = { "bold" },
+ },
+ NeogitUntrackedfiles = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitUnstagedchanges = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitUnmergedchanges = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitUnpulledchanges = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitRecentcommits = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitStagedchanges = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitStashes = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitRebasing = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitNotificationInfo = {
+ fg = C.blue,
+ },
+ NeogitNotificationWarning = {
+ fg = C.yellow,
+ },
+ NeogitNotificationError = {
+ fg = C.red,
+ },
+ NeogitGraphRed = {
+ fg = C.red,
+ },
+ NeogitGraphWhite = {
+ fg = C.base,
+ },
+ NeogitGraphYellow = {
+ fg = C.yellow,
+ },
+ NeogitGraphGreen = {
+ fg = C.green,
+ },
+ NeogitGraphCyan = {
+ fg = C.blue,
+ },
+ NeogitGraphBlue = {
+ fg = C.blue,
+ },
+ NeogitGraphPurple = {
+ fg = C.lavender,
+ },
+ NeogitGraphGray = {
+ fg = C.subtext1,
+ },
+ NeogitGraphOrange = {
+ fg = C.peach,
+ },
+ NeogitGraphBoldRed = {
+ fg = C.red,
+ style = { "bold" },
+ },
+ NeogitGraphBoldWhite = {
+ fg = C.white,
+ style = { "bold" },
+ },
+ NeogitGraphBoldYellow = {
+ fg = C.yellow,
+ style = { "bold" },
+ },
+ NeogitGraphBoldGreen = {
+ fg = C.green,
+ style = { "bold" },
+ },
+ NeogitGraphBoldCyan = {
+ fg = C.blue,
+ style = { "bold" },
+ },
+ NeogitGraphBoldBlue = {
+ fg = C.blue,
+ style = { "bold" },
+ },
+ NeogitGraphBoldPurple = {
+ fg = C.lavender,
+ style = { "bold" },
+ },
+ NeogitGraphBoldGray = {
+ fg = C.subtext1,
+ style = { "bold" },
+ },
+ NeogitDiffContext = {
+ bg = C.base,
+ },
+ NeogitPopupBold = {
+ style = { "bold" },
+ },
+ NeogitPopupSwitchKey = {
+ fg = C.lavender,
+ },
+ NeogitPopupOptionKey = {
+ fg = C.lavender,
+ },
+ NeogitPopupConfigKey = {
+ fg = C.lavender,
+ },
+ NeogitPopupActionKey = {
+ fg = C.lavender,
+ },
+ NeogitFilePath = {
+ fg = C.blue,
+ style = { "italic" },
+ },
+ NeogitDiffHeader = {
+ bg = C.base,
+ fg = C.blue,
+ style = { "bold" },
+ },
+ NeogitDiffHeaderHighlight = {
+ bg = C.base,
+ fg = C.peach,
+ style = { "bold" },
+ },
+ NeogitUnpushedTo = {
+ fg = C.lavender,
+ style = { "bold" },
+ },
+ NeogitFold = {
+ fg = C.none,
+ bg = C.none,
+ },
+ NeogitSectionHeader = {
+ fg = C.mauve,
+ style = { "bold" },
+ },
+ NeogitTagName = {
+ fg = C.yellow,
+ },
+ NeogitTagDistance = {
+ fg = C.blue,
+ },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/neotest.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/neotest.lua
new file mode 100644
index 00000000..5385cc09
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/neotest.lua
@@ -0,0 +1,24 @@
+local M = {}
+
+function M.get()
+ return {
+ NeotestPassed = { fg = C.green },
+ NeotestFailed = { fg = C.red },
+ NeotestRunning = { fg = C.yellow },
+ NeotestSkipped = { fg = C.blue },
+ NeotestTest = { fg = C.text },
+ NeotestNamespace = { fg = C.mauve },
+ NeotestFocused = { style = { "bold", "underline" } },
+ NeotestFile = { fg = C.blue },
+ NeotestDir = { fg = C.blue },
+ NeotestIndent = { fg = C.overlay1 },
+ NeotestExpandMarker = { fg = C.overlay1 },
+ NeotestAdapterName = { fg = C.maroon },
+ NeotestWinSelect = { fg = C.blue, style = { "bold" } },
+ NeotestMarked = { fg = C.peach, style = { "bold" } },
+ NeotestTarget = { fg = C.red },
+ NeotestUnknown = { fg = C.text },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/neotree.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/neotree.lua
new file mode 100644
index 00000000..c5e7f0fc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/neotree.lua
@@ -0,0 +1,46 @@
+local M = {}
+
+function M.get()
+ local active_bg = O.transparent_background and C.none or C.mantle
+ local inactive_bg = O.transparent_background and C.none or C.base
+ return {
+ NeoTreeDirectoryName = { fg = C.blue },
+ NeoTreeDirectoryIcon = { fg = C.blue },
+ NeoTreeNormal = { fg = C.text, bg = active_bg },
+ NeoTreeNormalNC = { fg = C.text, bg = active_bg },
+ NeoTreeExpander = { fg = C.overlay0 },
+ NeoTreeIndentMarker = { fg = C.overlay0 },
+ NeoTreeRootName = { fg = C.blue, style = { "bold" } },
+ NeoTreeSymbolicLinkTarget = { fg = C.pink },
+ NeoTreeModified = { fg = C.peach },
+
+ NeoTreeGitAdded = { fg = C.green },
+ NeoTreeGitConflict = { fg = C.red },
+ NeoTreeGitDeleted = { fg = C.red },
+ NeoTreeGitIgnored = { fg = C.overlay0 },
+ NeoTreeGitModified = { fg = C.yellow },
+ NeoTreeGitUnstaged = { fg = C.red },
+ NeoTreeGitUntracked = { fg = C.mauve },
+ NeoTreeGitStaged = { fg = C.green },
+
+ NeoTreeFloatBorder = { link = "FloatBorder" },
+ NeoTreeFloatTitle = { link = "FloatTitle" },
+ NeoTreeTitleBar = { fg = C.mantle, bg = C.blue },
+
+ NeoTreeFileNameOpened = { fg = C.pink },
+ NeoTreeDimText = { fg = C.overlay1 },
+ NeoTreeFilterTerm = { fg = C.green, style = { "bold" } },
+ NeoTreeTabActive = { bg = active_bg, fg = C.lavender, style = { "bold" } },
+ NeoTreeTabInactive = { bg = inactive_bg, fg = C.overlay0 },
+ NeoTreeTabSeparatorActive = { fg = active_bg, bg = active_bg },
+ NeoTreeTabSeparatorInactive = { fg = inactive_bg, bg = inactive_bg },
+ NeoTreeVertSplit = { fg = C.base, bg = inactive_bg },
+ NeoTreeWinSeparator = {
+ fg = O.transparent_background and C.surface1 or C.base,
+ bg = O.transparent_background and C.none or C.base,
+ },
+ NeoTreeStatusLineNC = { fg = C.mantle, bg = C.mantle },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/noice.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/noice.lua
new file mode 100644
index 00000000..45bf6b55
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/noice.lua
@@ -0,0 +1,26 @@
+local M = {}
+
+local virtual_text = O.integrations.native_lsp.virtual_text
+
+function M.get()
+ return { -- Personally the default integration is already pretty good
+ NoiceCmdline = { fg = C.text },
+ NoiceCmdlineIcon = { fg = C.sky, style = virtual_text.information },
+ NoiceCmdlineIconSearch = { fg = C.yellow },
+ NoiceCmdlinePopupBorder = { fg = C.lavender },
+ NoiceCmdlinePopupBorderSearch = { fg = C.yellow },
+ NoiceConfirmBorder = { fg = C.blue },
+ NoiceMini = { fg = C.subtext0, blend = 0 },
+ NoiceFormatProgressDone = {
+ bg = O.transparent_background and C.none or U.darken(C.sky, 0.30, C.base),
+ fg = C.subtext0,
+ },
+ NoiceFormatProgressTodo = {
+ bg = O.transparent_background and C.none
+ or U.vary_color({ latte = U.lighten(C.mantle, 0.70, C.base) }, U.darken(C.surface0, 0.64, C.base)),
+ fg = C.subtext0,
+ },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/notifier.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/notifier.lua
new file mode 100644
index 00000000..12ecfe40
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/notifier.lua
@@ -0,0 +1,11 @@
+local M = {}
+
+function M.get()
+ return {
+ NotifierIcon = { fg = C.mauve },
+ NotifierContent = { fg = C.overlay2, blend = 0, style = { "italic" } },
+ NotifierContentDim = { fg = C.overlay1, blend = 0, style = { "italic" } },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/notify.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/notify.lua
new file mode 100644
index 00000000..fcd5002c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/notify.lua
@@ -0,0 +1,25 @@
+local M = {}
+
+function M.get()
+ return {
+ NotifyBackground = { bg = (O.transparent_background and vim.o.winblend == 0) and "#000000" or C.mantle },
+
+ NotifyERRORBorder = { fg = C.red },
+ NotifyERRORIcon = { fg = C.red },
+ NotifyERRORTitle = { fg = C.red, style = { "italic" } },
+ NotifyWARNBorder = { fg = C.yellow },
+ NotifyWARNIcon = { fg = C.yellow },
+ NotifyWARNTitle = { fg = C.yellow, style = { "italic" } },
+ NotifyINFOBorder = { fg = C.blue },
+ NotifyINFOIcon = { fg = C.blue },
+ NotifyINFOTitle = { fg = C.blue, style = { "italic" } },
+ NotifyDEBUGBorder = { fg = C.peach },
+ NotifyDEBUGIcon = { fg = C.peach },
+ NotifyDEBUGTitle = { fg = C.peach, style = { "italic" } },
+ NotifyTRACEBorder = { fg = C.rosewater },
+ NotifyTRACEIcon = { fg = C.rosewater },
+ NotifyTRACETitle = { fg = C.rosewater, style = { "italic" } },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/nvimtree.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/nvimtree.lua
new file mode 100644
index 00000000..725196ed
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/nvimtree.lua
@@ -0,0 +1,27 @@
+local M = {}
+
+function M.get()
+ return {
+ NvimTreeFolderName = { fg = C.blue },
+ NvimTreeFolderIcon = { fg = C.blue },
+ NvimTreeNormal = { fg = C.text, bg = O.transparent_background and C.none or C.mantle },
+ NvimTreeOpenedFolderName = { fg = C.blue },
+ NvimTreeEmptyFolderName = { fg = C.blue },
+ NvimTreeIndentMarker = { fg = C.overlay0 },
+ NvimTreeWinSeparator = {
+ fg = O.transparent_background and C.surface1 or C.base,
+ bg = O.transparent_background and C.none or C.base,
+ },
+ NvimTreeRootFolder = { fg = C.lavender, style = { "bold" } },
+ NvimTreeSymlink = { fg = C.pink },
+ NvimTreeStatuslineNc = { fg = C.mantle, bg = C.mantle },
+ NvimTreeGitDirty = { fg = C.yellow },
+ NvimTreeGitNew = { fg = C.blue },
+ NvimTreeGitDeleted = { fg = C.red },
+ NvimTreeSpecialFile = { fg = C.flamingo },
+ NvimTreeImageFile = { fg = C.text },
+ NvimTreeOpenedFile = { fg = C.pink },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/octo.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/octo.lua
new file mode 100644
index 00000000..cd1fd64f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/octo.lua
@@ -0,0 +1,78 @@
+local M = {}
+
+function M.get()
+ return {
+ -- colors
+ OctoGrey = { fg = C.base },
+ OctoBlue = { fg = C.blue },
+ OctoGreen = { fg = C.green },
+ OctoRed = { fg = C.red },
+ OctoPurple = { fg = C.mauve },
+ OctoYellow = { fg = C.yellow },
+ -- highlight groups
+ OctoDirty = { link = "ErrorMsg" },
+ OctoIssueTitle = { link = "PreProc" },
+ OctoIssueId = { link = "Question" },
+ OctoEmpty = { link = "Comment" },
+ OctoFloat = { link = "NormalNC" },
+ OctoDate = { link = "Comment" },
+ OctoSymbol = { link = "Comment" },
+ OctoTimelineItemHeading = { link = "Comment" },
+ OctoDetailsLabel = { link = "Title" },
+ OctoMissingDetails = { link = "Comment" },
+ OctoDetailsValue = { link = "Identifier" },
+ OctoDiffHunkPosition = { link = "NormalFloat" },
+ OctoCommentLine = { link = "TabLineSel" },
+ OctoViewer = { fg = C.base, bg = C.blue },
+ OctoBubble = { fg = C.text, bg = C.mantle },
+ OctoBubbleGrey = { fg = C.text, bg = C.mantle },
+ OctoBubbleDelimiterGrey = { fg = C.mantle },
+ OctoBubbleGreen = { fg = C.base, bg = C.green },
+ OctoBubbleDelimiterGreen = { fg = C.green },
+ OctoBubbleBlue = { fg = C.base, bg = C.sky },
+ OctoBubbleDelimiterBlue = { fg = C.sky },
+ OctoBubbleYellow = { fg = C.base, bg = C.yellow },
+ OctoBubbleDelimiterYellow = { fg = C.yellow },
+ OctoBubbleRed = { fg = C.base, bg = C.red },
+ OctoBubbleDelimiterRed = { fg = C.red },
+ OctoBubblePurple = { fg = C.base, bg = C.mauve },
+ OctoBubbleDelimiterPurple = { fg = C.mauve },
+ OctoUser = { link = "OctoBubble" },
+ OctoUserViewer = { link = "OctoViewer" },
+ OctoReaction = { link = "OctoBubble" },
+ OctoReactionViewer = { link = "OctoViewer" },
+ OctoPassingTest = { link = "OctoGreen" },
+ OctoFailingTest = { link = "OctoRed" },
+ OctoPullAdditions = { link = "OctoGreen" },
+ OctoPullDeletions = { link = "OctoRed" },
+ OctoPullModifications = { fg = C.peach },
+ OctoStateOpen = { fg = C.green, bg = C.mantle },
+ OctoStateOpenFloat = { fg = C.green, bg = C.mantle },
+ OctoStateClosed = { fg = C.red, bg = C.mantle },
+ OctoStateClosedFloat = { fg = C.red, bg = C.mantle },
+ OctoStateMerged = { fg = C.mauve, bg = C.mantle },
+ OctoStateMergedFloat = { fg = C.mauve, bg = C.mantle },
+ OctoStatePending = { fg = C.peach, bg = C.mantle },
+ OctoStatePendingFloat = { fg = C.peach, bg = C.mantle },
+ OctoStateApproved = { link = "OctoStateOpen" },
+ OctoStateApprovedFloat = { link = "OctoStateOpen" },
+ OctoStateChangesRequested = { fg = C.maroon, bg = C.mantle },
+ OctoStateChangesRequestedFloat = { fg = C.maroon, bg = C.mantle },
+ OctoStateCommented = { link = "Normal" },
+ OctoStateCommentedFloat = { link = "Normal" },
+ OctoStateDismissed = { link = "OctoStateClosed" },
+ OctoStateDismissedFloat = { link = "OctoStateClosed" },
+ OctoStateSubmittedBubble = { link = "OctoBubbleGreen" },
+ OctoFilePanelCounter = { fg = C.blue, style = { "bold" } },
+ OctoFilePanelTitle = { fg = C.blue, style = { "bold" } },
+ OctoNormalFront = { fg = C.text },
+ OctoYellowFloat = { fg = C.yellow, bg = C.mantle },
+ OctoPurpleFloat = { fg = C.mauve, bg = C.mantle },
+ OctoRedFloat = { fg = C.red, bg = C.mantle },
+ OctoGreenFloat = { fg = C.green, bg = C.mantle },
+ OctoGreyFloat = { fg = C.text, bg = C.mantle },
+ OctoBlueFloat = { fg = C.blue, bg = C.mantle },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/overseer.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/overseer.lua
new file mode 100644
index 00000000..20f47b7b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/overseer.lua
@@ -0,0 +1,18 @@
+local M = {}
+
+function M.get()
+ return {
+ OverseerPENDING = { fg = C.grey },
+ OverseerRUNNING = { fg = C.yellow },
+ OverseerSUCCESS = { fg = C.green },
+ OverseerCANCELED = { fg = C.overlay2 },
+ OverseerFAILURE = { fg = C.red },
+ OverseerTask = { fg = C.blue },
+ OverseerTaskBorder = { fg = C.sky },
+ OverseerOutput = { fg = C.text },
+ OverseerComponent = { fg = C.yellow },
+ OverseerField = { fg = C.green },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/pounce.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/pounce.lua
new file mode 100644
index 00000000..608c99f6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/pounce.lua
@@ -0,0 +1,12 @@
+local M = {}
+
+function M.get()
+ return {
+ PounceMatch = { bg = U.lighten(C.green, 0.7), fg = C.base, style = { "bold" } },
+ PounceGap = { bg = U.darken(C.green, 0.7), fg = C.base, style = { "bold" } },
+ PounceAccept = { bg = C.peach, fg = C.base, style = { "bold" } },
+ PounceAcceptBest = { bg = C.teal, fg = C.base, style = { "bold" } },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/rainbow_delimiters.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/rainbow_delimiters.lua
new file mode 100644
index 00000000..bfaeecf7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/rainbow_delimiters.lua
@@ -0,0 +1,15 @@
+local M = {}
+
+function M.get()
+ return {
+ RainbowDelimiterRed = { fg = C.red },
+ RainbowDelimiterYellow = { fg = C.yellow },
+ RainbowDelimiterBlue = { fg = C.blue },
+ RainbowDelimiterOrange = { fg = C.peach },
+ RainbowDelimiterGreen = { fg = C.green },
+ RainbowDelimiterViolet = { fg = C.mauve },
+ RainbowDelimiterCyan = { fg = C.teal },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/sandwich.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/sandwich.lua
new file mode 100644
index 00000000..e366c845
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/sandwich.lua
@@ -0,0 +1,12 @@
+local M = {}
+
+function M.get()
+ return {
+ OperatorSandwichAdd = { bg = C.blue, fg = C.base },
+ OperatorSandwichBuns = { bg = C.blue, fg = C.base },
+ OperatorSandwichChange = { bg = C.blue, fg = C.base },
+ OperatorSandwichDelete = { bg = C.blue, fg = C.base },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/semantic_tokens.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/semantic_tokens.lua
new file mode 100644
index 00000000..6d9094b6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/semantic_tokens.lua
@@ -0,0 +1,48 @@
+local M = {}
+
+function M.get()
+ if vim.treesitter.highlighter.hl_map then
+ vim.notify_once(
+ [[Catppuccin (info):
+semantic_tokens integration requires neovim 0.8
+If you want to stay on nvim 0.7, disable the integration.
+]],
+ vim.log.levels.INFO
+ )
+ return {}
+ end
+ return {
+ ["@lsp.type.boolean"] = { link = "@boolean" },
+ ["@lsp.type.builtinType"] = { link = "@type.builtin" },
+ ["@lsp.type.comment"] = { link = "@comment" },
+ ["@lsp.type.enum"] = { link = "@type" },
+ ["@lsp.type.enumMember"] = { link = "@constant" },
+ ["@lsp.type.escapeSequence"] = { link = "@string.escape" },
+ ["@lsp.type.formatSpecifier"] = { link = "@punctuation.special" },
+ ["@lsp.type.interface"] = { fg = C.flamingo },
+ ["@lsp.type.keyword"] = { link = "@keyword" },
+ ["@lsp.type.namespace"] = { link = "@module" },
+ ["@lsp.type.number"] = { link = "@number" },
+ ["@lsp.type.operator"] = { link = "@operator" },
+ ["@lsp.type.parameter"] = { link = "@parameter" },
+ ["@lsp.type.property"] = { link = "@property" },
+ ["@lsp.type.selfKeyword"] = { link = "@variable.builtin" },
+ ["@lsp.type.typeAlias"] = { link = "@type.definition" },
+ ["@lsp.type.unresolvedReference"] = { link = "@error" },
+ ["@lsp.type.variable"] = {}, -- use treesitter styles for regular variables
+ ["@lsp.typemod.class.defaultLibrary"] = { link = "@type.builtin" },
+ ["@lsp.typemod.enum.defaultLibrary"] = { link = "@type.builtin" },
+ ["@lsp.typemod.enumMember.defaultLibrary"] = { link = "@constant.builtin" },
+ ["@lsp.typemod.function.defaultLibrary"] = { link = "@function.builtin" },
+ ["@lsp.typemod.keyword.async"] = { link = "@keyword.coroutine" },
+ ["@lsp.typemod.macro.defaultLibrary"] = { link = "@function.builtin" },
+ ["@lsp.typemod.method.defaultLibrary"] = { link = "@function.builtin" },
+ ["@lsp.typemod.operator.injected"] = { link = "@operator" },
+ ["@lsp.typemod.string.injected"] = { link = "@string" },
+ ["@lsp.typemod.type.defaultLibrary"] = { link = "@type.builtin" },
+ ["@lsp.typemod.variable.defaultLibrary"] = { link = "@variable.builtin" },
+ ["@lsp.typemod.variable.injected"] = { link = "@variable" },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/symbols_outline.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/symbols_outline.lua
new file mode 100644
index 00000000..f16b6c28
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/symbols_outline.lua
@@ -0,0 +1,13 @@
+local M = {}
+
+function M.get()
+ return {
+ -- https://github.com/simrat39/symbols-outline.nvim
+ FocusedSymbol = { fg = C.yellow, bg = C.none },
+
+ -- https://github.com/hedyhli/outline.nvim
+ OutlineCurrent = { link = "FocusedSymbol" },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/telekasten.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/telekasten.lua
new file mode 100644
index 00000000..9af7a855
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/telekasten.lua
@@ -0,0 +1,11 @@
+local M = {}
+
+function M.get()
+ return {
+ tkLink = { fg = C.blue },
+ tkBrackets = { fg = C.pink },
+ tkTag = { fg = C.sky },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/telescope.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/telescope.lua
new file mode 100644
index 00000000..58401704
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/telescope.lua
@@ -0,0 +1,60 @@
+local M = {}
+
+function M.get()
+ if O.integrations.telescope.style == "nvchad" then
+ return {
+ TelescopeBorder = {
+ fg = O.transparent_background and C.blue or C.mantle,
+ bg = O.transparent_background and C.none or C.mantle,
+ },
+ TelescopeMatching = { fg = C.blue },
+ TelescopeNormal = {
+ bg = O.transparent_background and C.none or C.mantle,
+ },
+ TelescopePromptBorder = {
+ fg = O.transparent_background and C.blue or C.surface0,
+ bg = O.transparent_background and C.none or C.surface0,
+ },
+ TelescopePromptNormal = {
+ fg = C.text,
+ bg = O.transparent_background and C.none or C.surface0,
+ },
+ TelescopePromptPrefix = {
+ fg = C.flamingo,
+ bg = O.transparent_background and C.none or C.surface0,
+ },
+ TelescopePreviewTitle = {
+ fg = O.transparent_background and C.green or C.base,
+ bg = O.transparent_background and C.none or C.green,
+ },
+ TelescopePromptTitle = {
+ fg = O.transparent_background and C.red or C.base,
+ bg = O.transparent_background and C.none or C.red,
+ },
+ TelescopeResultsTitle = {
+ fg = O.transparent_background and C.lavender or C.mantle,
+ bg = O.transparent_background and C.none or C.lavender,
+ },
+ TelescopeSelection = {
+ fg = O.transparent_background and C.flamingo or C.text,
+ bg = O.transparent_background and C.none or C.surface0,
+ style = { "bold" },
+ },
+ TelescopeSelectionCaret = { fg = C.flamingo },
+ }
+ end
+
+ return {
+ -- TelescopeNormal = { link = "NormalFloat" }, -- Respect telescope's default float bg
+ TelescopeBorder = { link = "FloatBorder" },
+ TelescopeSelectionCaret = { fg = C.flamingo },
+ TelescopeSelection = {
+ fg = O.transparent_background and C.flamingo or C.text,
+ bg = O.transparent_background and C.none or C.surface0,
+ style = { "bold" },
+ },
+ TelescopeMatching = { fg = C.blue },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/treesitter.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/treesitter.lua
new file mode 100644
index 00000000..cd4981ec
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/treesitter.lua
@@ -0,0 +1,274 @@
+local M = {}
+
+function M.get()
+ if vim.treesitter.highlighter.hl_map then
+ vim.notify_once(
+ [[Catppuccin (info):
+nvim-treesitter integration requires neovim 0.8
+If you want to stay on nvim 0.7, either disable the integration or pin catppuccin tag to v0.2.4 and nvim-treesitter commit to 4cccb6f494eb255b32a290d37c35ca12584c74d0.
+]],
+ vim.log.levels.INFO
+ )
+ return {}
+ end
+
+ local colors = { -- Reference: https://github.com/nvim-treesitter/nvim-treesitter/blob/master/CONTRIBUTING.md
+ -- Identifiers
+ ["@variable"] = { fg = C.text, style = O.styles.variables or {} }, -- Any variable name that does not have another highlight.
+ ["@variable.builtin"] = { fg = C.red, style = O.styles.properties or {} }, -- Variable names that are defined by the languages, like this or self.
+ ["@variable.parameter"] = { fg = C.maroon, style = O.styles.variables or {} }, -- For parameters of a function.
+ ["@variable.member"] = { fg = C.lavender }, -- For fields.
+
+ ["@constant"] = { link = "Constant" }, -- For constants
+ ["@constant.builtin"] = { fg = C.peach, style = O.styles.keywords or {} }, -- For constant that are built in the language: nil in Lua.
+ ["@constant.macro"] = { link = "Macro" }, -- For constants that are defined by macros: NULL in C.
+
+ ["@module"] = { fg = C.lavender, style = O.styles.miscs or { "italic" } }, -- For identifiers referring to modules and namespaces.
+ ["@label"] = { link = "Label" }, -- For labels: label: in C and :label: in Lua.
+
+ -- Literals
+ ["@string"] = { link = "String" }, -- For strings.
+ ["@string.documentation"] = { fg = C.teal, style = O.styles.strings or {} }, -- For strings documenting code (e.g. Python docstrings).
+ ["@string.regexp"] = { fg = C.peach, style = O.styles.strings or {} }, -- For regexes.
+ ["@string.escape"] = { fg = C.pink, style = O.styles.strings or {} }, -- For escape characters within a string.
+ ["@string.special"] = { link = "Special" }, -- other special strings (e.g. dates)
+ ["@string.special.path"] = { link = "Special" }, -- filenames
+ ["@string.special.symbol"] = { fg = C.flamingo }, -- symbols or atoms
+ ["@string.special.url"] = { fg = C.rosewater, style = { "italic", "underline" } }, -- urls, links and emails
+
+ ["@character"] = { link = "Character" }, -- character literals
+ ["@character.special"] = { link = "SpecialChar" }, -- special characters (e.g. wildcards)
+
+ ["@boolean"] = { link = "Boolean" }, -- For booleans.
+ ["@number"] = { link = "Number" }, -- For all numbers
+ ["@number.float"] = { link = "Float" }, -- For floats.
+
+ -- Types
+ ["@type"] = { link = "Type" }, -- For types.
+ ["@type.builtin"] = { fg = C.yellow, style = O.styles.properties or { "italic" } }, -- For builtin types.
+ ["@type.definition"] = { link = "Type" }, -- type definitions (e.g. `typedef` in C)
+
+ ["@attribute"] = { link = "Constant" }, -- attribute annotations (e.g. Python decorators)
+ ["@property"] = { fg = C.lavender, style = O.styles.properties or {} }, -- Same as TSField.
+
+ -- Functions
+ ["@function"] = { link = "Function" }, -- For function (calls and definitions).
+ ["@function.builtin"] = { fg = C.peach, style = O.styles.functions or {} }, -- For builtin functions: table.insert in Lua.
+ ["@function.call"] = { link = "Function" }, -- function calls
+ ["@function.macro"] = { fg = C.teal, style = O.styles.functions or {} }, -- For macro defined functions (calls and definitions): each macro_rules in Rust.
+
+ ["@function.method"] = { link = "Function" }, -- For method definitions.
+ ["@function.method.call"] = { link = "Function" }, -- For method calls.
+
+ ["@constructor"] = { fg = C.sapphire }, -- For constructor calls and definitions: = { } in Lua, and Java constructors.
+ ["@operator"] = { link = "Operator" }, -- For any operator: +, but also -> and * in C.
+
+ -- Keywords
+ ["@keyword"] = { link = "Keyword" }, -- For keywords that don't fall in previous categories.
+ ["@keyword.modifier"] = { link = "Keyword" }, -- For keywords modifying other constructs (e.g. `const`, `static`, `public`)
+ ["@keyword.type"] = { link = "Keyword" }, -- For keywords describing composite types (e.g. `struct`, `enum`)
+ ["@keyword.coroutine"] = { link = "Keyword" }, -- For keywords related to coroutines (e.g. `go` in Go, `async/await` in Python)
+ ["@keyword.function"] = { fg = C.mauve, style = O.styles.keywords or {} }, -- For keywords used to define a function.
+ ["@keyword.operator"] = { link = "Operator" }, -- For new keyword operator
+ ["@keyword.import"] = { link = "Include" }, -- For includes: #include in C, use or extern crate in Rust, or require in Lua.
+ ["@keyword.repeat"] = { link = "Repeat" }, -- For keywords related to loops.
+ ["@keyword.return"] = { fg = C.mauve, style = O.styles.keywords or {} },
+ ["@keyword.debug"] = { link = "Exception" }, -- For keywords related to debugging
+ ["@keyword.exception"] = { link = "Exception" }, -- For exception related keywords.
+
+ ["@keyword.conditional"] = { link = "Conditional" }, -- For keywords related to conditionnals.
+ ["@keyword.conditional.ternary"] = { link = "Operator" }, -- For ternary operators (e.g. `?` / `:`)
+
+ ["@keyword.directive"] = { link = "PreProc" }, -- various preprocessor directives & shebangs
+ ["@keyword.directive.define"] = { link = "Define" }, -- preprocessor definition directives
+ -- JS & derivative
+ ["@keyword.export"] = { fg = C.sky, style = O.styles.keywords },
+
+ -- Punctuation
+ ["@punctuation.delimiter"] = { link = "Delimiter" }, -- For delimiters (e.g. `;` / `.` / `,`).
+ ["@punctuation.bracket"] = { fg = C.overlay2 }, -- For brackets and parenthesis.
+ ["@punctuation.special"] = { link = "Special" }, -- For special punctuation that does not fall in the categories before (e.g. `{}` in string interpolation).
+
+ -- Comment
+ ["@comment"] = { link = "Comment" },
+ ["@comment.documentation"] = { link = "Comment" }, -- For comments documenting code
+
+ ["@comment.error"] = { fg = C.base, bg = C.red },
+ ["@comment.warning"] = { fg = C.base, bg = C.yellow },
+ ["@comment.hint"] = { fg = C.base, bg = C.blue },
+ ["@comment.todo"] = { fg = C.base, bg = C.flamingo },
+ ["@comment.note"] = { fg = C.base, bg = C.rosewater },
+
+ -- Markup
+ ["@markup"] = { fg = C.text }, -- For strings considerated text in a markup language.
+ ["@markup.strong"] = { fg = C.maroon, style = { "bold" } }, -- bold
+ ["@markup.italic"] = { fg = C.maroon, style = { "italic" } }, -- italic
+ ["@markup.strikethrough"] = { fg = C.text, style = { "strikethrough" } }, -- strikethrough text
+ ["@markup.underline"] = { link = "Underlined" }, -- underlined text
+
+ ["@markup.heading"] = { fg = C.blue, style = { "bold" } }, -- titles like: # Example
+
+ ["@markup.math"] = { fg = C.blue }, -- math environments (e.g. `$ ... $` in LaTeX)
+ ["@markup.quote"] = { fg = C.maroon, style = { "bold" } }, -- block quotes
+ ["@markup.environment"] = { fg = C.pink }, -- text environments of markup languages
+ ["@markup.environment.name"] = { fg = C.blue }, -- text indicating the type of an environment
+
+ ["@markup.link"] = { link = "Tag" }, -- text references, footnotes, citations, etc.
+ ["@markup.link.label"] = { link = "Label" }, -- link, reference descriptions
+ ["@markup.link.url"] = { fg = C.rosewater, style = { "italic", "underline" } }, -- urls, links and emails
+
+ ["@markup.raw"] = { fg = C.teal }, -- used for inline code in markdown and for doc in python (""")
+
+ ["@markup.list"] = { link = "Special" },
+ ["@markup.list.checked"] = { fg = C.green }, -- todo notes
+ ["@markup.list.unchecked"] = { fg = C.overlay1 }, -- todo notes
+
+ -- Diff
+ ["@diff.plus"] = { link = "diffAdded" }, -- added text (for diff files)
+ ["@diff.minus"] = { link = "diffRemoved" }, -- deleted text (for diff files)
+ ["@diff.delta"] = { link = "diffChanged" }, -- deleted text (for diff files)
+
+ -- Tags
+ ["@tag"] = { fg = C.mauve }, -- Tags like html tag names.
+ ["@tag.attribute"] = { fg = C.teal, style = O.styles.miscs or { "italic" } }, -- Tags like html tag names.
+ ["@tag.delimiter"] = { fg = C.sky }, -- Tag delimiter like < > /
+
+ -- Misc
+ ["@error"] = { link = "Error" },
+
+ -- Language specific:
+ -- bash
+ ["@function.builtin.bash"] = { fg = C.red, style = O.styles.miscs or { "italic" } },
+
+ -- markdown
+ ["@markup.heading.1.markdown"] = { link = "rainbow1" },
+ ["@markup.heading.2.markdown"] = { link = "rainbow2" },
+ ["@markup.heading.3.markdown"] = { link = "rainbow3" },
+ ["@markup.heading.4.markdown"] = { link = "rainbow4" },
+ ["@markup.heading.5.markdown"] = { link = "rainbow5" },
+ ["@markup.heading.6.markdown"] = { link = "rainbow6" },
+
+ -- java
+ ["@constant.java"] = { fg = C.teal },
+
+ -- css
+ ["@property.css"] = { fg = C.lavender },
+ ["@property.id.css"] = { fg = C.blue },
+ ["@property.class.css"] = { fg = C.yellow },
+ ["@type.css"] = { fg = C.lavender },
+ ["@type.tag.css"] = { fg = C.mauve },
+ ["@string.plain.css"] = { fg = C.peach },
+ ["@number.css"] = { fg = C.peach },
+
+ -- toml
+ ["@property.toml"] = { fg = C.blue }, -- Differentiates between string and properties
+
+ -- json
+ ["@label.json"] = { fg = C.blue }, -- For labels: label: in C and :label: in Lua.
+
+ -- lua
+ ["@constructor.lua"] = { fg = C.flamingo }, -- For constructor calls and definitions: = { } in Lua.
+
+ -- typescript
+ ["@property.typescript"] = { fg = C.lavender, style = O.styles.properties or {} },
+ ["@constructor.typescript"] = { fg = C.lavender },
+
+ -- TSX (Typescript React)
+ ["@constructor.tsx"] = { fg = C.lavender },
+ ["@tag.attribute.tsx"] = { fg = C.teal, style = O.styles.miscs or { "italic" } },
+
+ -- yaml
+ ["@variable.member.yaml"] = { fg = C.blue }, -- For fields.
+
+ -- Ruby
+ ["@string.special.symbol.ruby"] = { fg = C.flamingo },
+
+ -- PHP
+ ["@function.method.php"] = { link = "Function" },
+ ["@function.method.call.php"] = { link = "Function" },
+
+ -- C/CPP
+ ["@type.builtin.c"] = { fg = C.yellow, style = {} },
+ ["@property.cpp"] = { fg = C.text },
+ ["@type.builtin.cpp"] = { fg = C.yellow, style = {} },
+
+ -- gitcommit
+ ["@comment.warning.gitcommit"] = { fg = C.yellow },
+
+ -- Misc
+ gitcommitSummary = { fg = C.rosewater, style = O.styles.miscs or { "italic" } },
+ zshKSHFunction = { link = "Function" },
+ }
+
+ -- Legacy highlights
+ colors["@parameter"] = colors["@variable.parameter"]
+ colors["@field"] = colors["@variable.member"]
+ colors["@namespace"] = colors["@module"]
+ colors["@float"] = colors["@number.float"]
+ colors["@symbol"] = colors["@string.special.symbol"]
+ colors["@string.regex"] = colors["@string.regexp"]
+
+ colors["@text"] = colors["@markup"]
+ colors["@text.strong"] = colors["@markup.strong"]
+ colors["@text.emphasis"] = colors["@markup.italic"]
+ colors["@text.underline"] = colors["@markup.underline"]
+ colors["@text.strike"] = colors["@markup.strikethrough"]
+ colors["@text.uri"] = colors["@markup.link.url"]
+ colors["@text.math"] = colors["@markup.math"]
+ colors["@text.environment"] = colors["@markup.environment"]
+ colors["@text.environment.name"] = colors["@markup.environment.name"]
+
+ colors["@text.title"] = colors["@markup.heading"]
+ colors["@text.literal"] = colors["@markup.raw"]
+ colors["@text.reference"] = colors["@markup.link"]
+
+ colors["@text.todo.checked"] = colors["@markup.list.checked"]
+ colors["@text.todo.unchecked"] = colors["@markup.list.unchecked"]
+
+ colors["@comment.note"] = colors["@comment.hint"]
+
+ -- @text.todo is now for todo comments, not todo notes like in markdown
+ colors["@text.todo"] = colors["@comment.todo"]
+ colors["@text.warning"] = colors["@comment.warning"]
+ colors["@text.note"] = colors["@comment.note"]
+ colors["@text.danger"] = colors["@comment.error"]
+
+ -- @text.uri is now
+ -- > @markup.link.url in markup links
+ -- > @string.special.url outside of markup
+ colors["@text.uri"] = colors["@markup.link.uri"]
+
+ colors["@method"] = colors["@function.method"]
+ colors["@method.call"] = colors["@function.method.call"]
+
+ colors["@text.diff.add"] = colors["@diff.plus"]
+ colors["@text.diff.delete"] = colors["@diff.minus"]
+
+ colors["@type.qualifier"] = colors["@keyword.modifier"]
+ colors["@keyword.storage"] = colors["@keyword.modifier"]
+ colors["@define"] = colors["@keyword.directive.define"]
+ colors["@preproc"] = colors["@keyword.directive"]
+ colors["@storageclass"] = colors["@keyword.storage"]
+ colors["@conditional"] = colors["@keyword.conditional"]
+ colors["@exception"] = colors["@keyword.exception"]
+ colors["@include"] = colors["@keyword.import"]
+ colors["@repeat"] = colors["@keyword.repeat"]
+
+ colors["@symbol.ruby"] = colors["@string.special.symbol.ruby"]
+
+ colors["@variable.member.yaml"] = colors["@field.yaml"]
+
+ colors["@text.title.1.markdown"] = colors["@markup.heading.1.markdown"]
+ colors["@text.title.2.markdown"] = colors["@markup.heading.2.markdown"]
+ colors["@text.title.3.markdown"] = colors["@markup.heading.3.markdown"]
+ colors["@text.title.4.markdown"] = colors["@markup.heading.4.markdown"]
+ colors["@text.title.5.markdown"] = colors["@markup.heading.5.markdown"]
+ colors["@text.title.6.markdown"] = colors["@markup.heading.6.markdown"]
+
+ colors["@method.php"] = colors["@function.method.php"]
+ colors["@method.call.php"] = colors["@function.method.call.php"]
+
+ return colors
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/treesitter_context.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/treesitter_context.lua
new file mode 100644
index 00000000..a21518ec
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/treesitter_context.lua
@@ -0,0 +1,18 @@
+local M = {}
+
+function M.get()
+ return O.transparent_background and {
+ TreesitterContextBottom = { sp = C.dim, style = { "underline" } },
+ } or {
+ TreesitterContextBottom = {
+ sp = C.surface0,
+ style = { "underline" },
+ },
+ TreesitterContextLineNumber = {
+ fg = C.surface1,
+ bg = C.mantle,
+ },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/ts_rainbow.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/ts_rainbow.lua
new file mode 100644
index 00000000..c2827dd2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/ts_rainbow.lua
@@ -0,0 +1,15 @@
+local M = {}
+
+function M.get()
+ return {
+ rainbowcol1 = { fg = C.red },
+ rainbowcol2 = { fg = C.teal },
+ rainbowcol3 = { fg = C.yellow },
+ rainbowcol4 = { fg = C.blue },
+ rainbowcol5 = { fg = C.pink },
+ rainbowcol6 = { fg = C.flamingo },
+ rainbowcol7 = { fg = C.green },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/ts_rainbow2.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/ts_rainbow2.lua
new file mode 100644
index 00000000..651ea848
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/ts_rainbow2.lua
@@ -0,0 +1,15 @@
+local M = {}
+
+function M.get()
+ return {
+ TSRainbowRed = { fg = C.red },
+ TSRainbowYellow = { fg = C.yellow },
+ TSRainbowBlue = { fg = C.blue },
+ TSRainbowOrange = { fg = C.peach },
+ TSRainbowGreen = { fg = C.green },
+ TSRainbowViolet = { fg = C.mauve },
+ TSRainbowCyan = { fg = C.teal },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/ufo.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/ufo.lua
new file mode 100644
index 00000000..9e823a6d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/ufo.lua
@@ -0,0 +1,10 @@
+local M = {}
+
+M.get = function()
+ return {
+ UfoFoldedFg = { fg = C.lavender },
+ UfoFoldedEllipsis = { fg = C.crust, bg = C.blue },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/vim_sneak.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/vim_sneak.lua
new file mode 100644
index 00000000..fa09bca2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/vim_sneak.lua
@@ -0,0 +1,10 @@
+local M = {}
+
+function M.get()
+ return {
+ Sneak = { fg = C.overlay2, bg = C.pink },
+ SneakScope = { bg = C.text },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/vimwiki.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/vimwiki.lua
new file mode 100644
index 00000000..b7009716
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/vimwiki.lua
@@ -0,0 +1,20 @@
+local M = {}
+
+function M.get()
+ return {
+ VimwikiLink = { fg = C.sky, bg = C.none },
+ VimwikiHeaderChar = { fg = C.grey, bg = C.none },
+ VimwikiHR = { fg = C.yellow, bg = C.none },
+ VimwikiList = { fg = C.peach, bg = C.none },
+ VimwikiTag = { fg = C.peach, bg = C.none },
+ VimwikiMarkers = { fg = C.subtext0, bg = C.none },
+ VimwikiHeader1 = { fg = C.peach, bg = C.none, style = { "bold" } },
+ VimwikiHeader2 = { fg = C.green, bg = C.none, style = { "bold" } },
+ VimwikiHeader3 = { fg = C.blue, bg = C.none, style = { "bold" } },
+ VimwikiHeader4 = { fg = C.sky, bg = C.none, style = { "bold" } },
+ VimwikiHeader5 = { fg = C.yellow, bg = C.none, style = { "bold" } },
+ VimwikiHeader6 = { fg = C.mauve, bg = C.none, style = { "bold" } },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/which_key.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/which_key.lua
new file mode 100644
index 00000000..3983d449
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/which_key.lua
@@ -0,0 +1,15 @@
+local M = {}
+
+function M.get()
+ return {
+ WhichKey = { link = "NormalFloat" },
+ WhichKeyBorder = { link = "FloatBorder" },
+
+ WhichKeyGroup = { fg = C.blue },
+ WhichKeySeparator = { fg = C.overlay0 },
+ WhichKeyDesc = { fg = C.pink },
+ WhichKeyValue = { fg = C.overlay0 },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/window_picker.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/window_picker.lua
new file mode 100644
index 00000000..06af3e56
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/integrations/window_picker.lua
@@ -0,0 +1,12 @@
+local M = {}
+
+function M.get()
+ return {
+ WindowPickerStatusLine = { fg = C.red, style = { "bold" } },
+ WindowPickerStatusLineNC = { fg = C.red, style = { "bold" } },
+ WindowPickerWinBar = { fg = C.red, style = { "bold" } },
+ WindowPickerWinBarNC = { fg = C.red, style = { "bold" } },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/syntax.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/syntax.lua
new file mode 100644
index 00000000..055ddfe1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/syntax.lua
@@ -0,0 +1,102 @@
+local M = {}
+
+function M.get()
+ return {
+ Comment = { fg = C.overlay0, style = O.styles.comments }, -- just comments
+ SpecialComment = { link = "Special" }, -- special things inside a comment
+ Constant = { fg = C.peach }, -- (preferred) any constant
+ String = { fg = C.green, style = O.styles.strings or {} }, -- a string constant: "this is a string"
+ Character = { fg = C.teal }, -- a character constant: 'c', '\n'
+ Number = { fg = C.peach, style = O.styles.numbers or {} }, -- a number constant: 234, 0xff
+ Float = { link = "Number" }, -- a floating point constant: 2.3e10
+ Boolean = { fg = C.peach, style = O.styles.booleans or {} }, -- a boolean constant: TRUE, false
+ Identifier = { fg = C.flamingo, style = O.styles.variables or {} }, -- (preferred) any variable name
+ Function = { fg = C.blue, style = O.styles.functions or {} }, -- function name (also: methods for classes)
+ Statement = { fg = C.mauve }, -- (preferred) any statement
+ Conditional = { fg = C.mauve, style = O.styles.conditionals or {} }, -- if, then, else, endif, switch, etc.
+ Repeat = { fg = C.mauve, style = O.styles.loops or {} }, -- for, do, while, etc.
+ Label = { fg = C.sapphire }, -- case, default, etc.
+ Operator = { fg = C.sky, style = O.styles.operators or {} }, -- "sizeof", "+", "*", etc.
+ Keyword = { fg = C.mauve, style = O.styles.keywords or {} }, -- any other keyword
+ Exception = { fg = C.mauve, style = O.styles.keywords or {} }, -- try, catch, throw
+
+ PreProc = { fg = C.pink }, -- (preferred) generic Preprocessor
+ Include = { fg = C.mauve, style = O.styles.keywords or {} }, -- preprocessor #include
+ Define = { link = "PreProc" }, -- preprocessor #define
+ Macro = { fg = C.mauve }, -- same as Define
+ PreCondit = { link = "PreProc" }, -- preprocessor #if, #else, #endif, etc.
+
+ StorageClass = { fg = C.yellow }, -- static, register, volatile, etc.
+ Structure = { fg = C.yellow }, -- struct, union, enum, etc.
+ Special = { fg = C.pink }, -- (preferred) any special symbol
+ Type = { fg = C.yellow, style = O.styles.types or {} }, -- (preferred) int, long, char, etc.
+ Typedef = { link = "Type" }, -- A typedef
+ SpecialChar = { link = "Special" }, -- special character in a constant
+ Tag = { fg = C.lavender, style = { "bold" } }, -- you can use CTRL-] on this
+ Delimiter = { fg = C.overlay2 }, -- character that needs attention
+ Debug = { link = "Special" }, -- debugging statements
+
+ Underlined = { style = { "underline" } }, -- (preferred) text that stands out, HTML links
+ Bold = { style = { "bold" } },
+ Italic = { style = { "italic" } },
+ -- ("Ignore", below, may be invisible...)
+ -- Ignore = { }, -- (preferred) left blank, hidden |hl-Ignore|
+
+ Error = { fg = C.red }, -- (preferred) any erroneous construct
+ Todo = { bg = C.flamingo, fg = C.base, style = { "bold" } }, -- (preferred) anything that needs extra attention; mostly the keywords TODO FIXME and XXX
+ qfLineNr = { fg = C.yellow },
+ qfFileName = { fg = C.blue },
+ htmlH1 = { fg = C.pink, style = { "bold" } },
+ htmlH2 = { fg = C.blue, style = { "bold" } },
+ -- mkdHeading = { fg = C.peach, style = { "bold" } },
+ -- mkdCode = { bg = C.terminal_black, fg = C.text },
+ mkdCodeDelimiter = { bg = C.base, fg = C.text },
+ mkdCodeStart = { fg = C.flamingo, style = { "bold" } },
+ mkdCodeEnd = { fg = C.flamingo, style = { "bold" } },
+ -- mkdLink = { fg = C.blue, style = { "underline" } },
+
+ -- debugging
+ debugPC = { bg = O.transparent_background and C.none or C.crust }, -- used for highlighting the current line in terminal-debug
+ debugBreakpoint = { bg = C.base, fg = C.overlay0 }, -- used for breakpoint colors in terminal-debug
+ -- illuminate
+ illuminatedWord = { bg = C.surface1 },
+ illuminatedCurWord = { bg = C.surface1 },
+ -- diff
+ diffAdded = { fg = C.green },
+ diffRemoved = { fg = C.red },
+ diffChanged = { fg = C.blue },
+ diffOldFile = { fg = C.yellow },
+ diffNewFile = { fg = C.peach },
+ diffFile = { fg = C.blue },
+ diffLine = { fg = C.overlay0 },
+ diffIndexLine = { fg = C.teal },
+ DiffAdd = { bg = U.darken(C.green, 0.18, C.base) }, -- diff mode: Added line |diff.txt|
+ DiffChange = { bg = U.darken(C.blue, 0.07, C.base) }, -- diff mode: Changed line |diff.txt|
+ DiffDelete = { bg = U.darken(C.red, 0.18, C.base) }, -- diff mode: Deleted line |diff.txt|
+ DiffText = { bg = U.darken(C.blue, 0.30, C.base) }, -- diff mode: Changed text within a changed line |diff.txt|
+ -- NeoVim
+ healthError = { fg = C.red },
+ healthSuccess = { fg = C.teal },
+ healthWarning = { fg = C.yellow },
+ -- misc
+
+ -- glyphs
+ GlyphPalette1 = { fg = C.red },
+ GlyphPalette2 = { fg = C.teal },
+ GlyphPalette3 = { fg = C.yellow },
+ GlyphPalette4 = { fg = C.blue },
+ GlyphPalette6 = { fg = C.teal },
+ GlyphPalette7 = { fg = C.text },
+ GlyphPalette9 = { fg = C.red },
+
+ -- rainbow
+ rainbow1 = { fg = C.red },
+ rainbow2 = { fg = C.peach },
+ rainbow3 = { fg = C.yellow },
+ rainbow4 = { fg = C.green },
+ rainbow5 = { fg = C.sapphire },
+ rainbow6 = { fg = C.lavender },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/terminal.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/terminal.lua
new file mode 100644
index 00000000..26f4fd30
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/groups/terminal.lua
@@ -0,0 +1,31 @@
+local M = {}
+
+function M.get()
+ return {
+ terminal_color_0 = C.overlay0,
+ terminal_color_8 = C.overlay1,
+
+ terminal_color_1 = C.red,
+ terminal_color_9 = C.red,
+
+ terminal_color_2 = C.green,
+ terminal_color_10 = C.green,
+
+ terminal_color_3 = C.yellow,
+ terminal_color_11 = C.yellow,
+
+ terminal_color_4 = C.blue,
+ terminal_color_12 = C.blue,
+
+ terminal_color_5 = C.pink,
+ terminal_color_13 = C.pink,
+
+ terminal_color_6 = C.sky,
+ terminal_color_14 = C.sky,
+
+ terminal_color_7 = C.text,
+ terminal_color_15 = C.text,
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/init.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/init.lua
new file mode 100644
index 00000000..ad205f95
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/init.lua
@@ -0,0 +1,231 @@
+local is_vim = vim.fn.has "nvim" ~= 1
+if is_vim then require "catppuccin.lib.vim" end
+
+---@type Catppuccin
+local M = {
+ default_options = {
+ flavour = "auto",
+ background = {
+ light = "latte",
+ dark = "mocha",
+ },
+ compile_path = vim.fn.stdpath "cache" .. "/catppuccin",
+ transparent_background = false,
+ show_end_of_buffer = false,
+ term_colors = false,
+ kitty = vim.env.KITTY_WINDOW_ID and true or false,
+ dim_inactive = {
+ enabled = false,
+ shade = "dark",
+ percentage = 0.15,
+ },
+ no_italic = false,
+ no_bold = false,
+ no_underline = false,
+ styles = {
+ comments = { "italic" },
+ conditionals = { "italic" },
+ loops = {},
+ functions = {},
+ keywords = {},
+ strings = {},
+ variables = {},
+ numbers = {},
+ booleans = {},
+ properties = {},
+ types = {},
+ operators = {},
+ },
+ default_integrations = true,
+ integrations = {
+ alpha = true,
+ cmp = true,
+ dap = true,
+ dap_ui = true,
+ dashboard = true,
+ diffview = false,
+ flash = true,
+ gitsigns = true,
+ markdown = true,
+ neogit = true,
+ neotree = true,
+ nvimtree = true,
+ ufo = true,
+ rainbow_delimiters = true,
+ semantic_tokens = not is_vim,
+ telescope = { enabled = true },
+ treesitter = not is_vim,
+ treesitter_context = true,
+ barbecue = {
+ dim_dirname = true,
+ bold_basename = true,
+ dim_context = false,
+ alt_background = false,
+ },
+ illuminate = {
+ enabled = true,
+ lsp = false,
+ },
+ indent_blankline = {
+ enabled = true,
+ scope_color = "",
+ colored_indent_levels = false,
+ },
+ native_lsp = {
+ enabled = true,
+ virtual_text = {
+ errors = { "italic" },
+ hints = { "italic" },
+ warnings = { "italic" },
+ information = { "italic" },
+ },
+ underlines = {
+ errors = { "underline" },
+ hints = { "underline" },
+ warnings = { "underline" },
+ information = { "underline" },
+ },
+ inlay_hints = {
+ background = true,
+ },
+ },
+ navic = {
+ enabled = false,
+ custom_bg = "NONE",
+ },
+ dropbar = {
+ enabled = true,
+ color_mode = false,
+ },
+ colorful_winsep = {
+ enabled = false,
+ color = "red",
+ },
+ },
+ color_overrides = {},
+ highlight_overrides = {},
+ },
+ flavours = { latte = 1, frappe = 2, macchiato = 3, mocha = 4 },
+ path_sep = jit and (jit.os == "Windows" and "\\" or "/") or package.config:sub(1, 1),
+}
+
+M.options = M.default_options
+
+function M.compile()
+ local user_flavour = M.flavour
+ for flavour, _ in pairs(M.flavours) do
+ M.flavour = flavour
+ require("catppuccin.lib." .. (is_vim and "vim." or "") .. "compiler").compile(flavour)
+ end
+ M.flavour = user_flavour -- Restore user flavour after compile
+end
+
+local function get_flavour(default)
+ local flavour
+ if default and default == M.flavour and vim.o.background ~= (M.flavour == "latte" and "light" or "dark") then
+ flavour = M.options.background[vim.o.background]
+ else
+ flavour = default
+ end
+
+ if flavour and not M.flavours[flavour] then
+ vim.notify(
+ string.format(
+ "Catppuccin (error): Invalid flavour '%s', flavour must be 'latte', 'frappe', 'macchiato', 'mocha' or 'auto'",
+ flavour
+ ),
+ vim.log.levels.ERROR
+ )
+ flavour = nil
+ end
+ return flavour or M.options.flavour or vim.g.catppuccin_flavour or M.options.background[vim.o.background]
+end
+
+local did_setup = false
+
+function M.load(flavour)
+ if M.options.flavour == "auto" then -- set colorscheme based on o:background
+ M.options.flavour = nil -- ensure that this will only run once on startup
+ end
+ if not did_setup then M.setup() end
+ M.flavour = get_flavour(flavour)
+ local compiled_path = M.options.compile_path .. M.path_sep .. M.flavour
+ local f = loadfile(compiled_path)
+ if not f then
+ M.compile()
+ f = assert(loadfile(compiled_path), "could not load cache")
+ end
+ f(flavour or M.options.flavour or vim.g.catppuccin_flavour)
+end
+
+---@type fun(user_conf: CatppuccinOptions?)
+function M.setup(user_conf)
+ did_setup = true
+ -- Parsing user config
+ user_conf = user_conf or {}
+
+ if user_conf.default_integrations == false then M.default_options.integrations = {} end
+
+ M.options = vim.tbl_deep_extend("keep", user_conf, M.default_options)
+ M.options.highlight_overrides.all = user_conf.custom_highlights or M.options.highlight_overrides.all
+
+ -- Get cached hash
+ local cached_path = M.options.compile_path .. M.path_sep .. "cached"
+ local file = io.open(cached_path)
+ local cached = nil
+ if file then
+ cached = file:read()
+ file:close()
+ end
+
+ -- Get current hash
+ local git_path = debug.getinfo(1).source:sub(2, -24) .. ".git"
+ local git = vim.fn.getftime(git_path) -- 2x faster vim.loop.fs_stat
+ local hash = require("catppuccin.lib.hashing").hash(user_conf)
+ .. (git == -1 and git_path or git) -- no .git in /nix/store -> cache path
+ .. (vim.o.winblend == 0 and 1 or 0) -- :h winblend
+ .. (vim.o.pumblend == 0 and 1 or 0) -- :h pumblend
+
+ -- Recompile if hash changed
+ if cached ~= hash then
+ M.compile()
+ file = io.open(cached_path, "wb")
+ if file then
+ file:write(hash)
+ file:close()
+ end
+ end
+end
+
+if is_vim then return M end
+
+vim.api.nvim_create_user_command(
+ "Catppuccin",
+ function(inp) vim.api.nvim_command("colorscheme catppuccin-" .. get_flavour(inp.args)) end,
+ {
+ nargs = 1,
+ complete = function(line)
+ return vim.tbl_filter(function(val) return vim.startswith(val, line) end, vim.tbl_keys(M.flavours))
+ end,
+ }
+)
+
+vim.api.nvim_create_user_command("CatppuccinCompile", function()
+ for name, _ in pairs(package.loaded) do
+ if name:match "^catppuccin." then package.loaded[name] = nil end
+ end
+ M.compile()
+ vim.notify("Catppuccin (info): compiled cache!", vim.log.levels.INFO)
+ vim.cmd.colorscheme "catppuccin"
+end, {})
+
+if vim.g.catppuccin_debug then
+ vim.api.nvim_create_autocmd("BufWritePost", {
+ pattern = "*/catppuccin/*",
+ callback = function()
+ vim.schedule(function() vim.cmd "CatppuccinCompile" end)
+ end,
+ })
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/compiler.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/compiler.lua
new file mode 100644
index 00000000..5c844567
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/compiler.lua
@@ -0,0 +1,104 @@
+local path_sep = require("catppuccin").path_sep
+local O = require("catppuccin").options
+local M = {}
+
+-- Credit: https://github.com/EdenEast/nightfox.nvim
+local fmt = string.format
+
+local function inspect(t)
+ local list = {}
+ for k, v in pairs(t) do
+ local tv = type(v)
+ if tv == "string" then
+ table.insert(list, fmt([[%s = "%s"]], k, v))
+ elseif tv == "table" then
+ table.insert(list, fmt([[%s = %s]], k, inspect(v)))
+ else
+ table.insert(list, fmt([[%s = %s]], k, tostring(v)))
+ end
+ end
+ return fmt([[{ %s }]], table.concat(list, ", "))
+end
+
+function M.compile(flavour)
+ local theme = require("catppuccin.lib.mapper").apply(flavour)
+ local lines = {
+ string.format(
+ [[
+return string.dump(function(flavour)
+vim.o.termguicolors = true
+if vim.g.colors_name then vim.cmd("hi clear") end
+if flavour then vim.o.background = "%s" end
+vim.g.colors_name = "catppuccin-%s"
+local h = vim.api.nvim_set_hl]],
+ flavour == "latte" and "light" or "dark",
+ flavour
+ ),
+ }
+ if path_sep == "\\" then O.compile_path = O.compile_path:gsub("/", "\\") end
+
+ local tbl = vim.tbl_deep_extend("keep", theme.custom_highlights, theme.integrations, theme.syntax, theme.editor)
+
+ if O.term_colors == true then
+ for k, v in pairs(theme.terminal) do
+ table.insert(lines, fmt('vim.g.%s = "%s"', k, v))
+ end
+ end
+
+ for group, color in pairs(tbl) do
+ if color.style then
+ for _, style in pairs(color.style) do
+ color[style] = true
+ if O.no_italic and style == "italic" then color[style] = false end
+ if O.no_bold and style == "bold" then color[style] = false end
+ if O.no_underline and style == "underline" then color[style] = false end
+ end
+ end
+ color.style = nil
+ if color.link and (theme.custom_highlights[group] and not theme.custom_highlights[group].link) then
+ color.link = nil
+ end
+ table.insert(lines, fmt([[h(0, "%s", %s)]], group, inspect(color)))
+ end
+ table.insert(lines, "end, true)")
+ if vim.fn.isdirectory(O.compile_path) == 0 then vim.fn.mkdir(O.compile_path, "p") end
+
+ if vim.g.catppuccin_debug then -- Debugging purpose
+ local deb = io.open(O.compile_path .. path_sep .. flavour .. ".lua", "wb")
+ if deb then
+ deb:write(table.concat(lines, "\n"))
+ deb:close()
+ end
+ end
+
+ local f = loadstring(table.concat(lines, "\n"))
+ if not f then
+ local err_path = (path_sep == "/" and "/tmp" or os.getenv "TMP") .. "/catppuccin_error.lua"
+ print(string.format(
+ [[Catppuccin (error): Most likely some mistake made in your catppuccin config
+You can open %s for debugging
+
+If you think this is a bug, kindly open an issue and attach %s file
+Below is the error message that we captured:
+]],
+ err_path,
+ err_path
+ ))
+ local err = io.open(err_path, "wb")
+ if err then
+ err:write(table.concat(lines, "\n"))
+ err:close()
+ end
+ dofile(err_path)
+ return
+ end
+
+ local file = assert(
+ io.open(O.compile_path .. path_sep .. flavour, "wb"),
+ "Permission denied while writing compiled file to " .. O.compile_path .. path_sep .. flavour
+ )
+ file:write(f())
+ file:close()
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/hashing.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/hashing.lua
new file mode 100644
index 00000000..d2272f15
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/hashing.lua
@@ -0,0 +1,26 @@
+local M = {}
+local B = bit or bit32 or require "catppuccin.lib.vim.bit"
+
+local hash_str = function(str) -- djb2, https://theartincode.stanis.me/008-djb2/
+ local hash = 5381
+ for i = 1, #str do
+ hash = B.lshift(hash, 5) + hash + string.byte(str, i)
+ end
+ return hash
+end
+
+function M.hash(v) -- Xor hashing: https://codeforces.com/blog/entry/85900
+ local t = type(v)
+ if t == "table" then
+ local hash = 0
+ for p, u in next, v do
+ hash = B.bxor(hash, hash_str(p .. M.hash(u)))
+ end
+ return hash
+ elseif t == "function" then
+ return M.hash(v(require("catppuccin.palettes").get_palette()))
+ end
+ return tostring(v)
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/highlighter.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/highlighter.lua
new file mode 100644
index 00000000..d6887437
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/highlighter.lua
@@ -0,0 +1,20 @@
+-- DEPRECATED MODULE
+local M = {}
+
+function M.highlight(group, color)
+ if color.style then
+ for _, style in ipairs(color.style) do
+ color[style] = true
+ end
+ end
+ color.style = nil
+ vim.api.nvim_set_hl(0, group, color)
+end
+
+function M.syntax(tbl)
+ for group, colors in pairs(tbl) do
+ M.highlight(group, colors)
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/hsluv.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/hsluv.lua
new file mode 100644
index 00000000..36354164
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/hsluv.lua
@@ -0,0 +1,290 @@
+--[[
+Lua implementation of HSLuv and HPLuv color spaces
+Homepage: http://www.hsluv.org/
+
+Copyright (C) 2019 Alexei Boronine
+
+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.
+]]
+local hsluv = {}
+
+hsluv.hexChars = "0123456789abcdef"
+
+local distance_line_from_origin = function(line) return math.abs(line.intercept) / math.sqrt((line.slope ^ 2) + 1) end
+
+local length_of_ray_until_intersect = function(theta, line)
+ return line.intercept / (math.sin(theta) - line.slope * math.cos(theta))
+end
+
+hsluv.get_bounds = function(l)
+ local result = {}
+ local sub2
+ local sub1 = ((l + 16) ^ 3) / 1560896
+ if sub1 > hsluv.epsilon then
+ sub2 = sub1
+ else
+ sub2 = l / hsluv.kappa
+ end
+
+ for i = 1, 3 do
+ local m1 = hsluv.m[i][1]
+ local m2 = hsluv.m[i][2]
+ local m3 = hsluv.m[i][3]
+
+ for t = 0, 1 do
+ local top1 = (284517 * m1 - 94839 * m3) * sub2
+ local top2 = (838422 * m3 + 769860 * m2 + 731718 * m1) * l * sub2 - 769860 * t * l
+ local bottom = (632260 * m3 - 126452 * m2) * sub2 + 126452 * t
+ table.insert(result, { slope = top1 / bottom, intercept = top2 / bottom })
+ end
+ end
+ return result
+end
+
+hsluv.max_safe_chroma_for_l = function(l)
+ local bounds = hsluv.get_bounds(l)
+ local min = 1.7976931348623157e+308
+
+ for i = 1, 6 do
+ local length = distance_line_from_origin(bounds[i])
+ if length >= 0 then min = math.min(min, length) end
+ end
+ return min
+end
+
+hsluv.max_safe_chroma_for_lh = function(l, h)
+ local hrad = h / 360 * math.pi * 2
+ local bounds = hsluv.get_bounds(l)
+ local min = 1.7976931348623157e+308
+
+ for i = 1, 6 do
+ local bound = bounds[i]
+ local length = length_of_ray_until_intersect(hrad, bound)
+ if length >= 0 then min = math.min(min, length) end
+ end
+ return min
+end
+
+hsluv.dot_product = function(a, b)
+ local sum = 0
+ for i = 1, 3 do
+ sum = sum + a[i] * b[i]
+ end
+ return sum
+end
+
+hsluv.from_linear = function(c)
+ if c <= 0.0031308 then
+ return 12.92 * c
+ else
+ return 1.055 * (c ^ 0.416666666666666685) - 0.055
+ end
+end
+
+hsluv.to_linear = function(c)
+ if c > 0.04045 then
+ return ((c + 0.055) / 1.055) ^ 2.4
+ else
+ return c / 12.92
+ end
+end
+
+hsluv.xyz_to_rgb = function(tuple)
+ return {
+ hsluv.from_linear(hsluv.dot_product(hsluv.m[1], tuple)),
+ hsluv.from_linear(hsluv.dot_product(hsluv.m[2], tuple)),
+ hsluv.from_linear(hsluv.dot_product(hsluv.m[3], tuple)),
+ }
+end
+
+hsluv.rgb_to_xyz = function(tuple)
+ local rgbl = { hsluv.to_linear(tuple[1]), hsluv.to_linear(tuple[2]), hsluv.to_linear(tuple[3]) }
+ return {
+ hsluv.dot_product(hsluv.minv[1], rgbl),
+ hsluv.dot_product(hsluv.minv[2], rgbl),
+ hsluv.dot_product(hsluv.minv[3], rgbl),
+ }
+end
+
+hsluv.y_to_l = function(Y)
+ if Y <= hsluv.epsilon then
+ return Y / hsluv.refY * hsluv.kappa
+ else
+ return 116 * ((Y / hsluv.refY) ^ 0.333333333333333315) - 16
+ end
+end
+
+hsluv.l_to_y = function(L)
+ if L <= 8 then
+ return hsluv.refY * L / hsluv.kappa
+ else
+ return hsluv.refY * (((L + 16) / 116) ^ 3)
+ end
+end
+
+hsluv.xyz_to_luv = function(tuple)
+ local X = tuple[1]
+ local Y = tuple[2]
+ local divider = X + 15 * Y + 3 * tuple[3]
+ local varU = 4 * X
+ local varV = 9 * Y
+ if divider ~= 0 then
+ varU = varU / divider
+ varV = varV / divider
+ else
+ varU = 0
+ varV = 0
+ end
+ local L = hsluv.y_to_l(Y)
+ if L == 0 then return { 0, 0, 0 } end
+ return { L, 13 * L * (varU - hsluv.refU), 13 * L * (varV - hsluv.refV) }
+end
+
+hsluv.luv_to_xyz = function(tuple)
+ local L = tuple[1]
+ local U = tuple[2]
+ local V = tuple[3]
+ if L == 0 then return { 0, 0, 0 } end
+ local varU = U / (13 * L) + hsluv.refU
+ local varV = V / (13 * L) + hsluv.refV
+ local Y = hsluv.l_to_y(L)
+ local X = 0 - (9 * Y * varU) / (((varU - 4) * varV) - varU * varV)
+ return { X, Y, (9 * Y - 15 * varV * Y - varV * X) / (3 * varV) }
+end
+
+hsluv.luv_to_lch = function(tuple)
+ local L = tuple[1]
+ local U = tuple[2]
+ local V = tuple[3]
+ local C = math.sqrt(U * U + V * V)
+ local H
+ if C < 0.00000001 then
+ H = 0
+ else
+ H = math.atan2(V, U) * 180.0 / 3.1415926535897932
+ if H < 0 then H = 360 + H end
+ end
+ return { L, C, H }
+end
+
+hsluv.lch_to_luv = function(tuple)
+ local L = tuple[1]
+ local C = tuple[2]
+ local Hrad = tuple[3] / 360.0 * 2 * math.pi
+ return { L, math.cos(Hrad) * C, math.sin(Hrad) * C }
+end
+
+hsluv.hsluv_to_lch = function(tuple)
+ local H = tuple[1]
+ local S = tuple[2]
+ local L = tuple[3]
+ if L > 99.9999999 then return { 100, 0, H } end
+ if L < 0.00000001 then return { 0, 0, H } end
+ return { L, hsluv.max_safe_chroma_for_lh(L, H) / 100 * S, H }
+end
+
+hsluv.lch_to_hsluv = function(tuple)
+ local L = tuple[1]
+ local C = tuple[2]
+ local H = tuple[3]
+ local max_chroma = hsluv.max_safe_chroma_for_lh(L, H)
+ if L > 99.9999999 then return { H, 0, 100 } end
+ if L < 0.00000001 then return { H, 0, 0 } end
+
+ return { H, C / max_chroma * 100, L }
+end
+
+hsluv.hpluv_to_lch = function(tuple)
+ local H = tuple[1]
+ local S = tuple[2]
+ local L = tuple[3]
+ if L > 99.9999999 then return { 100, 0, H } end
+ if L < 0.00000001 then return { 0, 0, H } end
+ return { L, hsluv.max_safe_chroma_for_l(L) / 100 * S, H }
+end
+
+hsluv.lch_to_hpluv = function(tuple)
+ local L = tuple[1]
+ local C = tuple[2]
+ local H = tuple[3]
+ if L > 99.9999999 then return { H, 0, 100 } end
+ if L < 0.00000001 then return { H, 0, 0 } end
+ return { H, C / hsluv.max_safe_chroma_for_l(L) * 100, L }
+end
+
+hsluv.rgb_to_hex = function(tuple)
+ local h = "#"
+ for i = 1, 3 do
+ local c = math.floor(tuple[i] * 255 + 0.5)
+ local digit2 = math.fmod(c, 16)
+ local x = (c - digit2) / 16
+ local digit1 = math.floor(x)
+ h = h .. string.sub(hsluv.hexChars, digit1 + 1, digit1 + 1)
+ h = h .. string.sub(hsluv.hexChars, digit2 + 1, digit2 + 1)
+ end
+ return h
+end
+
+hsluv.hex_to_rgb = function(hex)
+ hex = string.lower(hex)
+ local ret = {}
+ for i = 0, 2 do
+ local char1 = string.sub(hex, i * 2 + 2, i * 2 + 2)
+ local char2 = string.sub(hex, i * 2 + 3, i * 2 + 3)
+ local digit1 = string.find(hsluv.hexChars, char1) - 1
+ local digit2 = string.find(hsluv.hexChars, char2) - 1
+ ret[i + 1] = (digit1 * 16 + digit2) / 255.0
+ end
+ return ret
+end
+
+hsluv.lch_to_rgb = function(tuple) return hsluv.xyz_to_rgb(hsluv.luv_to_xyz(hsluv.lch_to_luv(tuple))) end
+
+hsluv.rgb_to_lch = function(tuple) return hsluv.luv_to_lch(hsluv.xyz_to_luv(hsluv.rgb_to_xyz(tuple))) end
+
+hsluv.hsluv_to_rgb = function(tuple) return hsluv.lch_to_rgb(hsluv.hsluv_to_lch(tuple)) end
+
+hsluv.rgb_to_hsluv = function(tuple) return hsluv.lch_to_hsluv(hsluv.rgb_to_lch(tuple)) end
+
+hsluv.hpluv_to_rgb = function(tuple) return hsluv.lch_to_rgb(hsluv.hpluv_to_lch(tuple)) end
+
+hsluv.rgb_to_hpluv = function(tuple) return hsluv.lch_to_hpluv(hsluv.rgb_to_lch(tuple)) end
+
+hsluv.hsluv_to_hex = function(tuple) return hsluv.rgb_to_hex(hsluv.hsluv_to_rgb(tuple)) end
+
+hsluv.hpluv_to_hex = function(tuple) return hsluv.rgb_to_hex(hsluv.hpluv_to_rgb(tuple)) end
+
+hsluv.hex_to_hsluv = function(s) return hsluv.rgb_to_hsluv(hsluv.hex_to_rgb(s)) end
+
+hsluv.hex_to_hpluv = function(s) return hsluv.rgb_to_hpluv(hsluv.hex_to_rgb(s)) end
+
+hsluv.m = {
+ { 3.240969941904521, -1.537383177570093, -0.498610760293 },
+ { -0.96924363628087, 1.87596750150772, 0.041555057407175 },
+ { 0.055630079696993, -0.20397695888897, 1.056971514242878 },
+}
+hsluv.minv = {
+ { 0.41239079926595, 0.35758433938387, 0.18048078840183 },
+ { 0.21263900587151, 0.71516867876775, 0.072192315360733 },
+ { 0.019330818715591, 0.11919477979462, 0.95053215224966 },
+}
+hsluv.refY = 1.0
+hsluv.refU = 0.19783000664283
+hsluv.refV = 0.46831999493879
+hsluv.kappa = 903.2962962
+hsluv.epsilon = 0.0088564516
+
+return hsluv
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/mapper.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/mapper.lua
new file mode 100644
index 00000000..2f60323d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/mapper.lua
@@ -0,0 +1,72 @@
+local M = {}
+
+function M.apply(flavour)
+ flavour = flavour or require("catppuccin").flavour
+
+ local _O, _C, _U = O, C, U -- Borrowing global var (setfenv doesn't work with require)
+ O = require("catppuccin").options
+ C = require("catppuccin.palettes").get_palette(flavour)
+ U = require "catppuccin.utils.colors"
+
+ C.none = "NONE"
+
+ local dim_percentage = O.dim_inactive.percentage
+ C.dim = O.dim_inactive.shade == "dark"
+ and U.vary_color(
+ { latte = U.darken(C.base, dim_percentage, C.mantle) },
+ U.darken(C.base, dim_percentage, C.mantle)
+ )
+ or U.vary_color(
+ { latte = U.lighten("#FBFCFD", dim_percentage, C.base) },
+ U.lighten(C.surface0, dim_percentage, C.base)
+ )
+
+ local theme = {}
+ theme.syntax = require("catppuccin.groups.syntax").get()
+ theme.editor = require("catppuccin.groups.editor").get()
+ local final_integrations = {}
+
+ -- https://github.com/catppuccin/nvim/pull/624
+ if type(O.integrations.dap) == "table" and O.integrations.dap.enable_ui ~= nil then
+ O.integrations.dap_ui = O.integrations.dap.enable_ui
+ O.integrations.dap.enable_ui = nil
+ end
+
+ for integration in pairs(O.integrations) do
+ local cot = false
+ if type(O.integrations[integration]) == "table" then
+ if O.integrations[integration].enabled == true then cot = true end
+ else
+ if O.integrations[integration] == true then
+ local default = require("catppuccin").default_options.integrations[integration]
+ O.integrations[integration] = type(default) == "table" and default or {}
+ O.integrations[integration].enabled = true
+ cot = true
+ end
+ end
+
+ if cot then
+ final_integrations = vim.tbl_deep_extend(
+ "force",
+ final_integrations,
+ require("catppuccin.groups.integrations." .. integration).get()
+ )
+ end
+ end
+
+ theme.integrations = final_integrations -- plugins
+ theme.terminal = require("catppuccin.groups.terminal").get() -- terminal colors
+ local user_highlights = O.highlight_overrides
+ if type(user_highlights[flavour]) == "function" then user_highlights[flavour] = user_highlights[flavour](C) end
+ theme.custom_highlights = vim.tbl_deep_extend(
+ "keep",
+ user_highlights[flavour] or {},
+ type(user_highlights.all) == "function" and user_highlights.all(C) or user_highlights.all or {}
+ )
+
+ O, C, U = _O, _C, _U -- Returning global var
+
+ return theme
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/vim/bit.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/vim/bit.lua
new file mode 100644
index 00000000..ea565fe5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/vim/bit.lua
@@ -0,0 +1,79 @@
+-- Reference(stripped down): https://github.com/davidm/lua-bit-numberlua/blob/master/lmod/bit/numberlua.lua
+local M = {}
+
+local floor = math.floor
+
+local MOD = 2 ^ 32
+
+local function memoize(f)
+ local mt = {}
+ local t = setmetatable({}, mt)
+ function mt:__index(k)
+ local v = f(k)
+ t[k] = v
+ return v
+ end
+
+ return t
+end
+
+local function make_bitop_uncached(t, m)
+ local function bitop(a, b)
+ local res, p = 0, 1
+ while a ~= 0 and b ~= 0 do
+ local am, bm = a % m, b % m
+ res = res + t[am][bm] * p
+ a = (a - am) / m
+ b = (b - bm) / m
+ p = p * m
+ end
+ res = res + (a + b) * p
+ return res
+ end
+
+ return bitop
+end
+
+local function make_bitop(t)
+ local op1 = make_bitop_uncached(t, 2 ^ 1)
+ local op2 = memoize(function(a)
+ return memoize(function(b) return op1(a, b) end)
+ end)
+ return make_bitop_uncached(op2, 2 ^ (t.n or 1))
+end
+
+M.bxor = make_bitop { [0] = { [0] = 0, [1] = 1 }, [1] = { [0] = 1, [1] = 0 }, n = 4 }
+local bxor = M.bxor
+
+local lshift, rshift
+
+lshift = function(a, disp) -- Lua5.2 inspired
+ if disp < 0 then return rshift(a, -disp) end
+ return (a * 2 ^ disp) % 2 ^ 32
+end
+
+rshift = function(a, disp) -- Lua5.2 inspired
+ if disp < 0 then return lshift(a, -disp) end
+ return floor(a % 2 ^ 32 / 2 ^ disp)
+end
+
+local function bit_tobit(x)
+ x = x % MOD
+ if x >= 0x80000000 then x = x - MOD end
+ return x
+end
+
+local function bit_bxor(a, b, c, ...)
+ if c then
+ return bit_bxor(bit_bxor(a, b), c, ...)
+ elseif b then
+ return bit_tobit(bxor(a % MOD, b % MOD))
+ else
+ return bit_tobit(a)
+ end
+end
+
+return {
+ bxor = bit_bxor,
+ lshift = function(x, n) return bit_tobit(lshift(x % MOD, n % 32)) end,
+}
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/vim/compiler.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/vim/compiler.lua
new file mode 100644
index 00000000..cf2bbdd2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/vim/compiler.lua
@@ -0,0 +1,107 @@
+local path_sep = require("catppuccin").path_sep
+local O = require("catppuccin").options
+local M = {}
+
+-- Reference: https://github.com/EdenEast/nightfox.nvim
+local fmt = string.format
+
+function M.compile(flavour)
+ local theme = require("catppuccin.lib.mapper").apply(flavour)
+ local lines = {
+ string.format(
+ [=[
+return string.dump(function()
+vim.command[[
+if exists("colors_name")
+ hi clear
+endif
+set termguicolors
+set background=%s
+let g:colors_name = "catppuccin-%s"]=],
+ (flavour == "latte" and "light" or "dark"),
+ flavour
+ ),
+ }
+
+ local tbl = vim.tbl_deep_extend("keep", theme.custom_highlights, theme.integrations, theme.syntax, theme.editor)
+
+ if O.term_colors == true then
+ for k, v in pairs(theme.terminal) do
+ table.insert(lines, fmt("let g:%s = '%s'", k, v))
+ end
+ end
+
+ for group, color in pairs(tbl) do
+ if color.link and (theme.custom_highlights[group] and not theme.custom_highlights[group].link) then
+ color.link = nil
+ end
+ if color.link then
+ table.insert(lines, fmt([[highlight! link %s %s]], group, color.link))
+ else
+ if color.style then
+ local rstyle = {}
+ for _, style in pairs(color.style) do
+ if O.no_italic and style == "italic" then style = nil end
+ if O.no_bold and style == "bold" then style = nil end
+ if O.no_underline and style == "underline" then style = nil end
+ if style then rstyle[#rstyle + 1] = style end
+ end
+ color.style = table.concat(rstyle, ",")
+ end
+ if color.style == "" then color.style = nil end
+ table.insert(
+ lines,
+ fmt(
+ [[highlight %s guifg=%s guibg=%s gui=%s guisp=%s]],
+ group,
+ color.fg or "NONE",
+ color.bg or "NONE",
+ color.style or "NONE",
+ color.sp or "NONE"
+ )
+ )
+ end
+ end
+ table.insert(lines, "]]end, true)")
+ if vim.fn.isdirectory(O.compile_path) == 0 then vim.fn.mkdir(O.compile_path, "p") end
+ local ls = loadstring or load
+
+ if vim.g.catppuccin_debug then -- Debugging purpose
+ local deb = io.open(O.compile_path .. path_sep .. flavour .. ".lua", "wb")
+ if deb then
+ deb:write(table.concat(lines, "\n"))
+ deb:close()
+ end
+ end
+
+ local f = ls(table.concat(lines, "\n"))
+ if not f then
+ local err_path = (path_sep == "/" and "/tmp" or os.getenv "TMP") .. "/catppuccin_error.lua"
+ print(string.format(
+ [[Catppuccin (error): Most likely some mistake made in your catppuccin config
+You can open %s for debugging
+
+If you think this is a bug, kindly open an issue and attach %s file
+Below is the error message that we captured:
+]],
+ err_path,
+ err_path
+ ))
+ local err = io.open(err_path, "wb")
+ if err then
+ err:write(table.concat(lines, "\n"))
+ err:close()
+ end
+ dofile(err_path)
+ return
+ end
+
+ local file = assert(
+ io.open(O.compile_path .. path_sep .. flavour, "wb"),
+ "Permission denied while writing compiled file to " .. O.compile_path .. path_sep .. flavour
+ )
+ file:write(f())
+ file:close()
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/vim/init.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/vim/init.lua
new file mode 100644
index 00000000..3ea1a1b7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/lib/vim/init.lua
@@ -0,0 +1,83 @@
+-- TODO: private _G.vim
+vim.command [[command! CatppuccinCompile lua require('catppuccin').compile() print("Catppuccin (info): compiled cache!")]]
+
+vim.o = setmetatable({}, {
+ __index = function(_, k)
+ if k == "background" then return vim.eval "&background" end
+ end,
+})
+
+vim.fn.stdpath = function(what)
+ if what ~= "cache" then return end
+ if package.config:sub(1, 1) == "\\" then
+ return vim.fn.expand "%localappdata%" .. [[Temp\vim]]
+ else
+ return (os.getenv "XDG_CACHE_HOME" or vim.fn.expand "$HOME/.cache") .. "/vim"
+ end
+end
+
+vim.env = setmetatable({}, {
+ __index = function(_, k) return os.getenv(k) end,
+})
+
+-- Reference: https://github.com/neovim/neovim/blob/master/runtime/lua/vim/shared.lua
+local function tbl_isempty(t)
+ assert(type(t) == "table", string.format("Expected table, got %s", type(t)))
+ return next(t) == nil
+end
+
+local function tbl_islist(t)
+ if type(t) ~= "table" then return false end
+
+ local count = 0
+
+ for k, _ in pairs(t) do
+ if type(k) == "number" then
+ count = count + 1
+ else
+ return false
+ end
+ end
+
+ if count > 0 then
+ return true
+ else
+ -- TODO(bfredl): in the future, we will always be inside nvim
+ -- then this check can be deleted.
+ if vim._empty_dict_mt == nil then return false end
+ return getmetatable(t) ~= vim._empty_dict_mt
+ end
+end
+
+local function can_merge(v) return type(v) == "table" and (tbl_isempty(v) or not tbl_islist(v)) end
+
+local function tbl_extend(behavior, deep_extend, ...)
+ if behavior ~= "error" and behavior ~= "keep" and behavior ~= "force" then
+ error('invalid "behavior": ' .. tostring(behavior))
+ end
+
+ if select("#", ...) < 2 then
+ error("wrong number of arguments (given " .. tostring(1 + select("#", ...)) .. ", expected at least 3)")
+ end
+
+ local ret = {}
+ if vim._empty_dict_mt ~= nil and getmetatable(select(1, ...)) == vim._empty_dict_mt then ret = vim.empty_dict() end
+
+ for i = 1, select("#", ...) do
+ local tbl = select(i, ...)
+ if tbl then
+ for k, v in pairs(tbl) do
+ if deep_extend and can_merge(v) and can_merge(ret[k]) then
+ ret[k] = tbl_extend(behavior, true, ret[k], v)
+ elseif behavior ~= "force" and ret[k] ~= nil then
+ if behavior == "error" then error("key found in more than one map: " .. k) end -- Else behavior is "keep".
+ else
+ ret[k] = v
+ end
+ end
+ end
+ end
+ return ret
+end
+
+function vim.tbl_deep_extend(behavior, ...) return tbl_extend(behavior, true, ...) end
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/frappe.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/frappe.lua
new file mode 100644
index 00000000..911d0af4
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/frappe.lua
@@ -0,0 +1,28 @@
+return {
+ rosewater = "#f2d5cf",
+ flamingo = "#eebebe",
+ pink = "#f4b8e4",
+ mauve = "#ca9ee6",
+ red = "#e78284",
+ maroon = "#ea999c",
+ peach = "#ef9f76",
+ yellow = "#e5c890",
+ green = "#a6d189",
+ teal = "#81c8be",
+ sky = "#99d1db",
+ sapphire = "#85c1dc",
+ blue = "#8caaee",
+ lavender = "#babbf1",
+ text = "#c6d0f5",
+ subtext1 = "#b5bfe2",
+ subtext0 = "#a5adce",
+ overlay2 = "#949cbb",
+ overlay1 = "#838ba7",
+ overlay0 = "#737994",
+ surface2 = "#626880",
+ surface1 = "#51576d",
+ surface0 = "#414559",
+ base = "#303446",
+ mantle = "#292c3c",
+ crust = "#232634",
+}
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/init.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/init.lua
new file mode 100644
index 00000000..68030c45
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/init.lua
@@ -0,0 +1,21 @@
+local M = {}
+
+function M.get_palette(flavour)
+ local flvr = flavour or require("catppuccin").flavour or vim.g.catppuccin_flavour or "mocha"
+ local _, palette = pcall(require, "catppuccin.palettes." .. flvr)
+ local O = require("catppuccin").options
+ local ans = vim.tbl_deep_extend("keep", O.color_overrides.all or {}, O.color_overrides[flvr] or {}, palette or {})
+ if O.kitty then -- https://github.com/kovidgoyal/kitty/issues/2917
+ for accent, hex in pairs(ans) do
+ local red_green_string = hex:sub(1, 5)
+ local blue_value = tonumber(hex:sub(6, 7), 16)
+
+ -- Slightly increase or decrease brightness of the blue channel
+ blue_value = blue_value == 255 and blue_value - 1 or blue_value + 1
+ ans[accent] = string.format("%s%.2x", red_green_string, blue_value)
+ end
+ end
+ return ans
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/latte.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/latte.lua
new file mode 100644
index 00000000..d03f661e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/latte.lua
@@ -0,0 +1,28 @@
+return {
+ rosewater = "#dc8a78",
+ flamingo = "#dd7878",
+ pink = "#ea76cb",
+ mauve = "#8839ef",
+ red = "#d20f39",
+ maroon = "#e64553",
+ peach = "#fe640b",
+ yellow = "#df8e1d",
+ green = "#40a02b",
+ teal = "#179299",
+ sky = "#04a5e5",
+ sapphire = "#209fb5",
+ blue = "#1e66f5",
+ lavender = "#7287fd",
+ text = "#4c4f69",
+ subtext1 = "#5c5f77",
+ subtext0 = "#6c6f85",
+ overlay2 = "#7c7f93",
+ overlay1 = "#8c8fa1",
+ overlay0 = "#9ca0b0",
+ surface2 = "#acb0be",
+ surface1 = "#bcc0cc",
+ surface0 = "#ccd0da",
+ base = "#eff1f5",
+ mantle = "#e6e9ef",
+ crust = "#dce0e8",
+}
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/macchiato.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/macchiato.lua
new file mode 100644
index 00000000..f5d95c02
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/macchiato.lua
@@ -0,0 +1,28 @@
+return {
+ rosewater = "#f4dbd6",
+ flamingo = "#f0c6c6",
+ pink = "#f5bde6",
+ mauve = "#c6a0f6",
+ red = "#ed8796",
+ maroon = "#ee99a0",
+ peach = "#f5a97f",
+ yellow = "#eed49f",
+ green = "#a6da95",
+ teal = "#8bd5ca",
+ sky = "#91d7e3",
+ sapphire = "#7dc4e4",
+ blue = "#8aadf4",
+ lavender = "#b7bdf8",
+ text = "#cad3f5",
+ subtext1 = "#b8c0e0",
+ subtext0 = "#a5adcb",
+ overlay2 = "#939ab7",
+ overlay1 = "#8087a2",
+ overlay0 = "#6e738d",
+ surface2 = "#5b6078",
+ surface1 = "#494d64",
+ surface0 = "#363a4f",
+ base = "#24273a",
+ mantle = "#1e2030",
+ crust = "#181926",
+}
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/mocha.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/mocha.lua
new file mode 100644
index 00000000..296c0008
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/palettes/mocha.lua
@@ -0,0 +1,28 @@
+return {
+ rosewater = "#f5e0dc",
+ flamingo = "#f2cdcd",
+ pink = "#f5c2e7",
+ mauve = "#cba6f7",
+ red = "#f38ba8",
+ maroon = "#eba0ac",
+ peach = "#fab387",
+ yellow = "#f9e2af",
+ green = "#a6e3a1",
+ teal = "#94e2d5",
+ sky = "#89dceb",
+ sapphire = "#74c7ec",
+ blue = "#89b4fa",
+ lavender = "#b4befe",
+ text = "#cdd6f4",
+ subtext1 = "#bac2de",
+ subtext0 = "#a6adc8",
+ overlay2 = "#9399b2",
+ overlay1 = "#7f849c",
+ overlay0 = "#6c7086",
+ surface2 = "#585b70",
+ surface1 = "#45475a",
+ surface0 = "#313244",
+ base = "#1e1e2e",
+ mantle = "#181825",
+ crust = "#11111b",
+}
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/types.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/types.lua
new file mode 100644
index 00000000..8b98a293
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/types.lua
@@ -0,0 +1,278 @@
+---@class Catppuccin
+---@field options CatppuccinOptions
+---@field setup fun(opts: CatppuccinOptions?)
+
+---@alias CtpFlavor "mocha" | "macchiato" | "frappe" | "latte" | "auto"
+---@alias CtpColor "rosewater" | "flamingo" | "pink" | "mauve" | "red" | "maroon" | "peach" | "yellow" | "green" | "teal" | "sky" | "sapphire" | "blue" | "lavender" | "text" | "subtext1" | "subtext0" | "overlay2" | "overlay1" | "overlay0" | "surface2" | "surface1" | "surface0" | "base" | "mantle" | "crust"
+---@class CtpFlavors: {all: T, mocha: T, macchiato: T, frappe: T, latte: T }
+---@class CtpColors: {rosewater: T, flamingo: T, pink: T, mauve: T, red: T, maroon: T, peach: T, yellow: T, green: T, teal: T, sky: T, sapphire: T, blue: T, lavender: T, text: T, subtext1: T, subtext0: T, overlay2: T, overlay1: T, overlay0: T, surface2: T, surface1: T, surface0: T, base: T, mantle: T, crust: T, none: T }
+
+---@class CatppuccinOptions
+-- Changes the flavor based on the background. See `:h background` for more info.
+---@field background CtpBackground?
+-- By default catppuccin writes the compiled results into the system's cache directory.
+-- You can change the cache dir by changing this value.
+---@field compile_path string?
+-- Whether to enable transparency.
+---@field transparent_background boolean?
+-- Toggle the `~` characters after the end of buffers.
+---@field show_end_of_buffer boolean?
+-- If true, sets terminal colors (e.g. `g:terminal_color_0`).
+---@field term_colors boolean?
+-- Workaround for kitty transparency issue: https://github.com/kovidgoyal/kitty/issues/2917
+---@field kitty boolean?
+-- Settings for dimming of inactive windows.
+---@field dim_inactive CtpDimInactive?
+-- Disables all italic styles.
+---@field no_italic boolean?
+-- Disables all bold styles.
+---@field no_bold boolean?
+-- Disables all underline styles.
+---@field no_underline boolean?
+-- Handles the style of general hl groups (see `:h highlight-groups`).
+---@field styles CtpStyles?
+-- Should default integrations be used.
+---@field default_integrations boolean?
+-- Toggle integrations. Integrations allow Catppuccin to set the theme of various plugins.
+---@field integrations CtpIntegrations?
+-- Catppuccin colors can be overwritten here.
+---@field color_overrides CtpColors | CtpFlavors> | nil
+-- Catppuccin highlights can be overwritten here.
+---@field highlight_overrides CtpHighlightOverrides?
+-- Global highlight overrides.
+---@field custom_highlights CtpHighlightOverrideFn | {[string]: CtpHighlight} | nil
+-- The default flavor to use on startup.
+---@field flavour CtpFlavor?
+
+---@class CtpBackground
+-- Catppuccin flavor to use when `:set background=dark` is set.
+---@field dark CtpFlavor?
+-- Catppuccin flavor to use when `:set background=light` is set.
+---@field light CtpFlavor?
+
+---@class CtpDimInactive
+-- Whether to dim inactive windows.
+---@field enabled boolean
+-- Whether to darken or lighten inactive windows.
+---@field shade "dark" | "light" | nil
+-- Percentage of the shade to apply to the inactive window
+---@field percentage number?
+
+---@class CtpStyles
+-- Change the style of comments.
+---@field comments CtpHighlightArgs[]?
+-- Change the style of conditionals.
+---@field conditionals CtpHighlightArgs[]?
+-- Change the style of loops.
+---@field loops CtpHighlightArgs[]?
+-- Change the style of functions.
+---@field functions CtpHighlightArgs[]?
+-- Change the style of keywords.
+---@field keywords CtpHighlightArgs[]?
+-- Change the style of strings.
+---@field strings CtpHighlightArgs[]?
+-- Change the style of variables.
+---@field variables CtpHighlightArgs[]?
+-- Change the style of numbers.
+---@field numbers CtpHighlightArgs[]?
+-- Change the style of booleans.
+---@field booleans CtpHighlightArgs[]?
+-- Change the style of properties.
+---@field properties CtpHighlightArgs[]?
+-- Change the style of types.
+---@field types CtpHighlightArgs[]?
+-- Change the style of operators.
+---@field operators CtpHighlightArgs[]?
+-- Change the style of miscs.
+---@field miscs CtpHighlightArgs[]?
+
+---@class CtpNativeLspStyles
+-- Change the style of LSP errors.
+---@field errors CtpHighlightArgs[]?
+-- Change the style of LSP hints.
+---@field hints CtpHighlightArgs[]?
+-- Change the style of LSP warnings.
+---@field warnings CtpHighlightArgs[]?
+-- Change the style of LSP information.
+---@field information CtpHighlightArgs[]?
+
+---@class CtpNativeLspInlayHints
+-- Toggle the background of inlay hints.
+---@field background boolean?
+
+---@class CtpIntegrations
+---@field aerial boolean?
+---@field alpha boolean?
+---@field barbar boolean?
+-- Use this to set it up:
+--
+-- ```lua
+-- require("barbecue").setup {
+-- -- valid options:
+-- -- "catppuccin-latte"
+-- -- "catppuccin-frappe"
+-- -- "catppuccin-macchiato"
+-- -- "catppuccin-mocha"
+-- theme = "catppuccin",
+-- }
+---```
+---@field barbecue CtpIntegrationBarbecue | boolean?
+---@field beacon boolean?
+---@field colorful_winsep CtpIntegrationColorfulWinsep | boolean?
+---@field cmp boolean?
+-- `coc.nvim` links to `native_lsp` highlight groups, so you can use
+-- `native_lsp.virtual_text` and `native_lsp.underlines` to style diagnostics.
+---@field coc_nvim boolean?
+-- ```lua
+-- local sign = vim.fn.sign_define
+--
+-- sign("DapBreakpoint", { text = "●", texthl = "DapBreakpoint", linehl = "", numhl = ""})
+-- sign("DapBreakpointCondition", { text = "●", texthl = "DapBreakpointCondition", linehl = "", numhl = ""})
+-- sign("DapLogPoint", { text = "◆", texthl = "DapLogPoint", linehl = "", numhl = ""})
+-- ```
+---@field dap boolean?
+---@field dap_ui boolean?
+---@field dashboard boolean?
+---@field diffview boolean?
+---@field dropbar CtpIntegrationDropbar | boolean?
+---@field fern boolean?
+-- Set `notification.window.winblend` to `0` in your `fidget` config:
+--
+-- ```lua
+-- require("fidget").setup {
+-- notification = {
+-- window = { winblend = 0 },
+-- }
+-- }
+-- ```
+---@field fidget boolean?
+---@field flash boolean?
+---@field gitgutter boolean?
+---@field gitsigns boolean?
+---@field harpoon boolean?
+---@field headlines boolean?
+---@field hop boolean?
+---@field illuminate CtpIntegrationIlluminate | boolean?
+---@field indent_blankline CtpIntegrationIndentBlankline | boolean?
+---@field leap boolean?
+---@field lightspeed boolean?
+-- For custom Lsp kind icon and colors, adjust your `lspsaga` config:
+--
+-- ```lua
+-- require("lspsaga").setup {
+-- ui = {
+-- kind = require("catppuccin.groups.integrations.lsp_saga").custom_kind(),
+-- },
+-- }
+-- ```
+---@field lsp_saga boolean?
+---@field lsp_trouble boolean?
+---@field markdown boolean?
+---@field mason boolean?
+---@field native_lsp CtpIntegrationNativeLsp | boolean?
+-- You **NEED** to enable highlight in your `nvim-navic` config or it won't work:
+--
+-- ```lua
+-- require("nvim-navic").setup {
+-- highlight = true
+-- }
+-- ```
+---@field navic CtpIntegrationNavic | boolean?
+---@field neogit boolean?
+---@field neotest boolean?
+---@field neotree boolean?
+---@field noice boolean?
+---@field notify boolean?
+---@field nvimtree boolean?
+---@field octo boolean?
+---@field overseer boolean?
+---@field pounce boolean?
+---@field rainbow_delimiters boolean?
+---@field sandwich boolean?
+---@field semantic_tokens boolean?
+---@field symbols_outline boolean?
+---@field telekasten boolean?
+---@field telescope CtpIntegrationTelescope | boolean?
+---@field treesitter boolean?
+---@field treesitter_context boolean?
+---@field ts_rainbow boolean?
+---@field ts_rainbow2 boolean?
+---@field vim_sneak boolean?
+---@field vimwiki boolean?
+---@field which_key boolean?
+---@field window_picker boolean?
+
+---@class CtpIntegrationBarbecue
+-- Whether to use the alternative background.
+---@field alt_background boolean?
+-- Whether the basename should be bold.
+---@field bold_basename boolean?
+-- Whether the context should be dimmed.
+---@field dim_context boolean?
+-- Whether the directory name should be dimmed.
+---@field dim_dirname boolean?
+
+---@class CtpIntegrationColorfulWinsep
+-- Whether to enable the colorful-winsep integration.
+---@field enabled boolean
+-- Set to a Catppuccin color name to use for the split separator.
+---@field color CtpColor?
+
+---@class CtpIntegrationDropbar
+-- Whether to enable the dropbar integration.
+---@field enabled boolean
+-- Set to true to apply color to the text in dropbar, false to only apply it to the icons.
+---@field color_mode boolean?
+
+---@class CtpIntegrationIndentBlankline
+-- Whether to enable the integration.
+---@field enabled boolean
+-- Sets the color of the scope line
+---@field scope_color CtpColor?
+-- Enables char highlights per indent level.
+-- Follow the instructions on the plugins GitHub repo to set it up.
+---@field colored_indent_levels boolean?
+
+---@class CtpIntegrationMini
+-- Whether to enable the integration.
+---@field enabled boolean
+-- Sets the color of the scope line
+---@field indentscope_color CtpColor?
+
+---@class CtpIntegrationNativeLsp
+-- Whether to enable the Native LSP integration.
+---@field enabled boolean
+-- Styles to apply to virtual text.
+---@field virtual_text CtpNativeLspStyles?
+-- Styles to apply to underlines.
+---@field underlines CtpNativeLspStyles?
+-- Inlay hints options.
+---@field inlay_hints CtpNativeLspInlayHints?
+
+---@class CtpIntegrationNavic
+-- Whether to enable the navic integration.
+---@field enabled boolean
+-- Override the background color for navic.
+---@field custom_bg CtpColor | "NONE" | "lualine" | nil
+
+---@class CtpIntegrationTelescope
+-- Whether to enable the telescope integration
+---@field enabled boolean?
+-- The style of Telescope
+---@field style "classic" | "nvchad" | nil
+
+---@class CtpIntegrationIlluminate
+-- Whether to enable the vim-illuminate integration
+---@field enabled boolean?
+-- Whether to standout IlluminatedWordWrite hl group
+---@field lsp boolean?
+
+---@alias CtpHighlightArgs "bold" | "underline" | "undercurl" | "underdouble" | "underdotted" | "underdashed" | "strikethrough" | "reverse" | "inverse" | "italic" | "standout" | "altfont" | "nocombine" | "NONE"
+---@alias CtpHighlightOverrideFn fun(colors: CtpColors): { [string]: CtpHighlight}
+---@alias CtpHighlightOverrides CtpFlavors
+
+---@class CtpHighlight
+---@field fg string?
+---@field bg string?
+---@field style CtpHighlightArgs[]?
+---@field link string?
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/barbecue.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/barbecue.lua
new file mode 100644
index 00000000..cfef00b9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/barbecue.lua
@@ -0,0 +1,53 @@
+return function(flavour)
+ local C = require("catppuccin.palettes").get_palette(flavour)
+ local O = require("catppuccin").options
+
+ local transparent_bg = O.transparent_background and C.none or C.mantle
+
+ local dirname_color = O.integrations.barbecue.dim_dirname and C.overlay1 or C.text
+ local basename_bold = O.integrations.barbecue.bold_basename
+ local context_color = O.integrations.barbecue.dim_context and C.overlay1 or C.text
+ local background_color = O.integrations.barbecue.alt_background and transparent_bg or C.none
+
+ local M = {
+ normal = { fg = C.text, bg = background_color },
+
+ ellipsis = { fg = C.overlay1 },
+ separator = { fg = C.overlay1 },
+ modified = { fg = C.peach },
+
+ dirname = { fg = dirname_color },
+ basename = { fg = C.text, bold = basename_bold },
+ context = { fg = context_color },
+
+ -- Same keys as navic
+ context_file = { fg = C.blue },
+ context_module = { fg = C.blue },
+ context_namespace = { fg = C.blue },
+ context_package = { fg = C.blue },
+ context_class = { fg = C.yellow },
+ context_method = { fg = C.blue },
+ context_property = { fg = C.green },
+ context_field = { fg = C.green },
+ context_constructor = { fg = C.blue },
+ context_enum = { fg = C.green },
+ context_interface = { fg = C.yellow },
+ context_function = { fg = C.blue },
+ context_variable = { fg = C.flamingo },
+ context_constant = { fg = C.peach },
+ context_string = { fg = C.green },
+ context_number = { fg = C.peach },
+ context_boolean = { fg = C.peach },
+ context_array = { fg = C.blue },
+ context_object = { fg = C.blue },
+ context_key = { fg = C.flamingo },
+ context_null = { fg = C.peach },
+ context_enum_member = { fg = C.red },
+ context_struct = { fg = C.blue },
+ context_event = { fg = C.blue },
+ context_operator = { fg = C.blue },
+ context_type_parameter = { fg = C.blue },
+ }
+
+ return M
+end
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/colors.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/colors.lua
new file mode 100644
index 00000000..ddf0ff17
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/colors.lua
@@ -0,0 +1,170 @@
+local M = {}
+
+local hsluv = require "catppuccin.lib.hsluv"
+
+M.bg = "#000000"
+M.fg = "#ffffff"
+M.day_brightness = 0.3
+
+---@param hex_str string hexadecimal value of a color
+local hex_to_rgb = function(hex_str)
+ local hex = "[abcdef0-9][abcdef0-9]"
+ local pat = "^#(" .. hex .. ")(" .. hex .. ")(" .. hex .. ")$"
+ hex_str = string.lower(hex_str)
+
+ assert(string.find(hex_str, pat) ~= nil, "hex_to_rgb: invalid hex_str: " .. tostring(hex_str))
+
+ local red, green, blue = string.match(hex_str, pat)
+ return { tonumber(red, 16), tonumber(green, 16), tonumber(blue, 16) }
+end
+
+---@param fg string forecrust color
+---@param bg string background color
+---@param alpha number number between 0 and 1. 0 results in bg, 1 results in fg
+function M.blend(fg, bg, alpha)
+ bg = hex_to_rgb(bg)
+ fg = hex_to_rgb(fg)
+
+ local blendChannel = function(i)
+ local ret = (alpha * fg[i] + ((1 - alpha) * bg[i]))
+ return math.floor(math.min(math.max(0, ret), 255) + 0.5)
+ end
+
+ return string.format("#%02X%02X%02X", blendChannel(1), blendChannel(2), blendChannel(3))
+end
+
+function M.darken(hex, amount, bg) return M.blend(hex, bg or M.bg, math.abs(amount)) end
+
+function M.lighten(hex, amount, fg) return M.blend(hex, fg or M.fg, math.abs(amount)) end
+
+function M.brighten(color, percentage)
+ local hsl = hsluv.hex_to_hsluv(color)
+ local larpSpace = 100 - hsl[3]
+ if percentage < 0 then larpSpace = hsl[3] end
+ hsl[3] = hsl[3] + larpSpace * percentage
+ return hsluv.hsluv_to_hex(hsl)
+end
+
+function M.invertColor(color)
+ if color ~= "NONE" then
+ local hsl = hsluv.hex_to_hsluv(color)
+ hsl[3] = 100 - hsl[3]
+ if hsl[3] < 40 then hsl[3] = hsl[3] + (100 - hsl[3]) * M.day_brightness end
+ return hsluv.hsluv_to_hex(hsl)
+ end
+ return color
+end
+
+function M.string_to_color(colors, value, default)
+ if not value or value == "" then return default end
+
+ -- If the value is a hex color code then return it
+ local hex = "[abcdef0-9][abcdef0-9]"
+ local pat = "^#" .. hex .. hex .. hex .. "$"
+ if string.match(value, pat) then return value end
+
+ local acceptable_colors = { "black", "red", "green", "blue", "magenta", "cyan", "text", "orange", "pink" }
+ for _, ac in ipairs(acceptable_colors) do
+ if string.match(value, ac) then return colors[value] end
+ end
+
+ -- Did not match anything to return default
+ return default
+end
+
+function M.color_is_bright(r, g, b)
+ -- Counting the perceptive luminance - human eye favors green color
+ local luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
+ if luminance > 0.5 then
+ return true -- Bright colors, black font
+ else
+ return false -- Dark colors, text font
+ end
+end
+
+function M.hex2rgb(hex)
+ return tonumber("0x" .. hex:sub(1, 2)), tonumber("0x" .. hex:sub(3, 4)), tonumber("0x" .. hex:sub(5, 6))
+end
+
+function M.assert_brightness(color)
+ local hex = color:gsub("#", "")
+ local r = M.hex2rgb(string.sub(hex, 1, 2))
+ local g = M.hex2rgb(string.sub(hex, 3, 4))
+ local b = M.hex2rgb(string.sub(hex, 5, 6))
+
+ if M.color_is_bright(tonumber(r), tonumber(g), tonumber(b)) == true then
+ return true -- bright
+ end
+
+ return false -- dull
+end
+
+function M.vary_color(palettes, default)
+ local flvr = require("catppuccin").flavour
+
+ if palettes[flvr] ~= nil then return palettes[flvr] end
+ return default
+end
+
+local function rgb2Hex(rgb)
+ local hexadecimal = "#"
+
+ for _, value in pairs(rgb) do
+ local hex = ""
+
+ while value > 0 do
+ local index = math.fmod(value, 16) + 1
+ value = math.floor(value / 16)
+ hex = string.sub(hsluv.hexChars, index, index) .. hex
+ end
+
+ if string.len(hex) == 0 then
+ hex = "00"
+ elseif string.len(hex) == 1 then
+ hex = "0" .. hex
+ end
+
+ hexadecimal = hexadecimal .. hex
+ end
+
+ return hexadecimal
+end
+
+function M.increase_saturation(hex, percentage)
+ local rgb = hex_to_rgb(hex)
+
+ local saturation_float = percentage
+
+ table.sort(rgb)
+ local rgb_intensity = {
+ min = rgb[1] / 255,
+ mid = rgb[2] / 255,
+ max = rgb[3] / 255,
+ }
+
+ if rgb_intensity.max == rgb_intensity.min then
+ -- all colors have same intensity, which means
+ -- the original color is gray, so we can't change saturation.
+ return hex
+ end
+
+ local new_intensities = {}
+ new_intensities.max = rgb_intensity.max
+ new_intensities.min = rgb_intensity.max * (1 - saturation_float)
+
+ if rgb_intensity.mid == rgb_intensity.min then
+ new_intensities.mid = new_intensities.min
+ else
+ local intensity_proportion = (rgb_intensity.max - rgb_intensity.mid) / (rgb_intensity.mid - rgb_intensity.min)
+ new_intensities.mid = (intensity_proportion * new_intensities.min + rgb_intensity.max)
+ / (intensity_proportion + 1)
+ end
+
+ for i, v in pairs(new_intensities) do
+ new_intensities[i] = math.floor(v * 255)
+ end
+ table.sort(new_intensities)
+ return (rgb2Hex { new_intensities.max, new_intensities.min, new_intensities.mid })
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/lualine.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/lualine.lua
new file mode 100644
index 00000000..8f0b1f0b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/lualine.lua
@@ -0,0 +1,46 @@
+return function(flavour)
+ local C = require("catppuccin.palettes").get_palette(flavour)
+ local O = require("catppuccin").options
+ local catppuccin = {}
+
+ local transparent_bg = O.transparent_background and "NONE" or C.mantle
+
+ catppuccin.normal = {
+ a = { bg = C.blue, fg = C.mantle, gui = "bold" },
+ b = { bg = C.surface0, fg = C.blue },
+ c = { bg = transparent_bg, fg = C.text },
+ }
+
+ catppuccin.insert = {
+ a = { bg = C.green, fg = C.base, gui = "bold" },
+ b = { bg = C.surface0, fg = C.green },
+ }
+
+ catppuccin.terminal = {
+ a = { bg = C.green, fg = C.base, gui = "bold" },
+ b = { bg = C.surface0, fg = C.green },
+ }
+
+ catppuccin.command = {
+ a = { bg = C.peach, fg = C.base, gui = "bold" },
+ b = { bg = C.surface0, fg = C.peach },
+ }
+
+ catppuccin.visual = {
+ a = { bg = C.mauve, fg = C.base, gui = "bold" },
+ b = { bg = C.surface0, fg = C.mauve },
+ }
+
+ catppuccin.replace = {
+ a = { bg = C.red, fg = C.base, gui = "bold" },
+ b = { bg = C.surface0, fg = C.red },
+ }
+
+ catppuccin.inactive = {
+ a = { bg = transparent_bg, fg = C.blue },
+ b = { bg = transparent_bg, fg = C.surface1, gui = "bold" },
+ c = { bg = transparent_bg, fg = C.overlay0 },
+ }
+
+ return catppuccin
+end
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/reactive.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/reactive.lua
new file mode 100644
index 00000000..ca8bfc26
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/catppuccin/utils/reactive.lua
@@ -0,0 +1,135 @@
+local M = {}
+
+function M.cursor(name, palette)
+ return {
+ name = name,
+ init = function() vim.opt.guicursor:append "a:ReactiveCursor" end,
+ modes = {
+ i = {
+ hl = {
+ ReactiveCursor = { bg = palette.teal },
+ },
+ },
+ no = {
+ operators = {
+ d = {
+ hl = {
+ ReactiveCursor = { bg = palette.red },
+ },
+ },
+ y = {
+ hl = {
+ ReactiveCursor = { bg = palette.peach },
+ },
+ },
+ c = {
+ hl = {
+ ReactiveCursor = { bg = palette.blue },
+ },
+ },
+ },
+ },
+ R = {
+ hl = {
+ ReactiveCursor = { bg = palette.sapphire },
+ },
+ },
+ -- visual
+ [{ "v", "V", "\x16" }] = {
+ hl = {
+ ReactiveCursor = { bg = palette.mauve },
+ },
+ },
+ -- select
+ [{ "s", "S", "\x13" }] = {
+ hl = {
+ ReactiveCursor = { bg = palette.pink },
+ },
+ },
+ },
+ }
+end
+
+function M.cursorline(name, palette)
+ local darken = require("catppuccin.utils.colors").darken
+
+ return {
+ name = name,
+ static = {
+ winhl = {
+ inactive = {
+ CursorLine = { bg = darken(palette.surface0, 0.75) },
+ CursorLineNr = { bg = darken(palette.surface0, 0.75) },
+ },
+ },
+ },
+ modes = {
+ -- insert mode
+ i = {
+ winhl = {
+ CursorLine = { bg = darken(palette.sky, 0.3) },
+ CursorLineNr = { bg = darken(palette.sky, 0.3) },
+ },
+ },
+ -- normal mode
+ n = {
+ winhl = {
+ CursorLine = { bg = palette.surface0 },
+ CursorLineNr = { bg = palette.surface0 },
+ },
+ },
+ -- operator-pending mode
+ no = {
+ operators = {
+ [{ "gu", "gU", "g~", "~" }] = {
+ winhl = {
+ CursorLine = { bg = palette.surface2 },
+ CursorLineNr = { bg = palette.surface2 },
+ },
+ },
+ -- delete operator
+ d = {
+ winhl = {
+ CursorLine = { bg = darken(palette.red, 0.4) },
+ CursorLineNr = { bg = darken(palette.red, 0.4) },
+ },
+ },
+ -- yank operator
+ y = {
+ winhl = {
+ CursorLine = { bg = darken(palette.peach, 0.3) },
+ CursorLineNr = { bg = darken(palette.peach, 0.3) },
+ },
+ },
+ -- change operator
+ c = {
+ winhl = {
+ CursorLine = { bg = darken(palette.blue, 0.4) },
+ CursorLineNr = { bg = darken(palette.blue, 0.4) },
+ },
+ },
+ },
+ },
+ R = {
+ winhl = {
+ CursorLine = { bg = darken(palette.sapphire, 0.4) },
+ CursorLineNr = { bg = darken(palette.sapphire, 0.4) },
+ },
+ },
+ -- visual mode
+ [{ "v", "V", "\x16" }] = {
+ winhl = {
+ Visual = { bg = darken(palette.mauve, 0.4) },
+ },
+ },
+ -- select mode
+ [{ "s", "S", "\x13" }] = {
+ winhl = {
+ Visual = { bg = darken(palette.pink, 0.4) },
+ },
+ },
+ },
+ }
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-frappe.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-frappe.lua
new file mode 100644
index 00000000..aafd00c3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-frappe.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.lualine" "frappe"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-latte.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-latte.lua
new file mode 100644
index 00000000..2b11e17f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-latte.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.lualine" "latte"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-macchiato.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-macchiato.lua
new file mode 100644
index 00000000..c8102ca3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-macchiato.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.lualine" "macchiato"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-mocha.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-mocha.lua
new file mode 100644
index 00000000..d5b190cf
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin-mocha.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.lualine" "mocha"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin.lua
new file mode 100644
index 00000000..4e18b44c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/lualine/themes/catppuccin.lua
@@ -0,0 +1 @@
+return require "catppuccin.utils.lualine"()
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-frappe-cursor.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-frappe-cursor.lua
new file mode 100644
index 00000000..3cbc8c67
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-frappe-cursor.lua
@@ -0,0 +1,4 @@
+local palette = require("catppuccin.palettes").get_palette "frappe"
+local presets = require "catppuccin.utils.reactive"
+
+return presets.cursor("catppuccin-frappe-cursor", palette)
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-frappe-cursorline.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-frappe-cursorline.lua
new file mode 100644
index 00000000..4e8a1b44
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-frappe-cursorline.lua
@@ -0,0 +1,78 @@
+local darken = require("catppuccin.utils.colors").darken
+local palette = require("catppuccin.palettes").get_palette "frappe"
+
+return {
+ name = "catppuccin-frappe-cursorline",
+ static = {
+ winhl = {
+ inactive = {
+ CursorLine = { bg = darken(palette.surface0, 0.85) },
+ CursorLineNr = { bg = darken(palette.surface0, 0.85) },
+ },
+ },
+ },
+ modes = {
+ i = {
+ winhl = {
+ CursorLine = { bg = darken(palette.sky, 0.4) },
+ CursorLineNr = { bg = darken(palette.sky, 0.4) },
+ },
+ },
+ n = {
+ winhl = {
+ CursorLine = { bg = palette.surface0 },
+ CursorLineNr = { bg = palette.surface0 },
+ },
+ },
+ no = {
+ operators = {
+ [{ "gu", "gU", "g~", "~" }] = {
+ winhl = {
+ CursorLine = { bg = palette.surface2 },
+ CursorLineNr = { bg = palette.surface2 },
+ },
+ },
+ -- delete operator
+ d = {
+ winhl = {
+ CursorLine = { bg = darken(palette.red, 0.4) },
+ CursorLineNr = { bg = darken(palette.red, 0.4) },
+ },
+ },
+ -- yank operator
+ y = {
+ winhl = {
+ CursorLine = { bg = darken(palette.peach, 0.4) },
+ CursorLineNr = { bg = darken(palette.peach, 0.4) },
+ },
+ },
+ -- change operator
+ c = {
+ winhl = {
+ CursorLine = { bg = darken(palette.blue, 0.5) },
+ CursorLineNr = { bg = darken(palette.blue, 0.5) },
+ },
+ },
+ },
+ },
+ -- replace mode
+ R = {
+ winhl = {
+ CursorLine = { bg = darken(palette.sapphire, 0.5) },
+ CursorLineNr = { bg = darken(palette.sapphire, 0.5) },
+ },
+ },
+ -- visual mode
+ [{ "v", "V", "\x16" }] = {
+ winhl = {
+ Visual = { bg = darken(palette.mauve, 0.4) },
+ },
+ },
+ -- select mode
+ [{ "s", "S", "\x13" }] = {
+ winhl = {
+ Visual = { bg = darken(palette.pink, 0.4) },
+ },
+ },
+ },
+}
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-latte-cursor.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-latte-cursor.lua
new file mode 100644
index 00000000..3c9a660e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-latte-cursor.lua
@@ -0,0 +1,8 @@
+local palette = require("catppuccin.palettes").get_palette "latte"
+local presets = require "catppuccin.utils.reactive"
+
+local preset = presets.cursor("catppuccin-latte-cursor", palette)
+
+preset.modes.R.hl.ReactiveCursor = { bg = palette.flamingo }
+
+return preset
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-latte-cursorline.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-latte-cursorline.lua
new file mode 100644
index 00000000..77e647bf
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-latte-cursorline.lua
@@ -0,0 +1,77 @@
+local lighten = require("catppuccin.utils.colors").lighten
+local palette = require("catppuccin.palettes").get_palette "latte"
+
+return {
+ name = "catppuccin-latte-cursorline",
+ static = {
+ winhl = {
+ inactive = {
+ CursorLine = { bg = lighten(palette.surface0, 0.5) },
+ CursorLineNr = { bg = lighten(palette.surface0, 0.5) },
+ },
+ },
+ },
+ modes = {
+ i = {
+ winhl = {
+ CursorLine = { bg = lighten(palette.teal, 0.4) },
+ CursorLineNr = { bg = lighten(palette.teal, 0.4) },
+ },
+ },
+ n = {
+ winhl = {
+ CursorLine = { bg = palette.surface0 },
+ CursorLineNr = { bg = palette.surface0 },
+ },
+ },
+ no = {
+ operators = {
+ [{ "gu", "gU", "g~", "~" }] = {
+ winhl = {
+ CursorLine = { bg = palette.surface2 },
+ CursorLineNr = { bg = palette.surface2 },
+ },
+ },
+ -- delete operator
+ d = {
+ winhl = {
+ CursorLine = { bg = lighten(palette.red, 0.3) },
+ CursorLineNr = { bg = lighten(palette.red, 0.3) },
+ },
+ },
+ -- yank operator
+ y = {
+ winhl = {
+ CursorLine = { bg = lighten(palette.peach, 0.3) },
+ CursorLineNr = { bg = lighten(palette.peach, 0.3) },
+ },
+ },
+ -- change operator
+ c = {
+ winhl = {
+ CursorLine = { bg = lighten(palette.blue, 0.3) },
+ CursorLineNr = { bg = lighten(palette.blue, 0.3) },
+ },
+ },
+ },
+ },
+ -- visual
+ [{ "v", "V", "\x16" }] = {
+ winhl = {
+ Visual = { bg = lighten(palette.mauve, 0.3) },
+ },
+ },
+ -- select
+ [{ "s", "S", "\x13" }] = {
+ winhl = {
+ Visual = { bg = lighten(palette.pink, 0.3) },
+ },
+ },
+ R = {
+ winhl = {
+ CursorLine = { bg = lighten(palette.flamingo, 0.2) },
+ CursorLineNr = { bg = lighten(palette.flamingo, 0.2) },
+ },
+ },
+ },
+}
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-macchiato-cursor.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-macchiato-cursor.lua
new file mode 100644
index 00000000..73d3b3a1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-macchiato-cursor.lua
@@ -0,0 +1,4 @@
+local palette = require("catppuccin.palettes").get_palette "macchiato"
+local presets = require "catppuccin.utils.reactive"
+
+return presets.cursor("catppuccin-macchiato-cursor", palette)
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-macchiato-cursorline.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-macchiato-cursorline.lua
new file mode 100644
index 00000000..a38c3fd1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-macchiato-cursorline.lua
@@ -0,0 +1,10 @@
+local palette = require("catppuccin.palettes").get_palette "macchiato"
+local presets = require "catppuccin.utils.reactive"
+local darken = require("catppuccin.utils.colors").darken
+
+local preset = presets.cursorline("catppuccin-macchiato-cursorline", palette)
+
+preset.static.winhl.inactive.CursorLine = { bg = darken(palette.surface0, 0.8) }
+preset.static.winhl.inactive.CursorLineNr = { bg = darken(palette.surface0, 0.8) }
+
+return preset
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-mocha-cursor.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-mocha-cursor.lua
new file mode 100644
index 00000000..c4e47939
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-mocha-cursor.lua
@@ -0,0 +1,4 @@
+local palette = require("catppuccin.palettes").get_palette "mocha"
+local presets = require "catppuccin.utils.reactive"
+
+return presets.cursor("catppuccin-mocha-cursor", palette)
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-mocha-cursorline.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-mocha-cursorline.lua
new file mode 100644
index 00000000..d511dc9f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/lua/reactive/presets/catppuccin-mocha-cursorline.lua
@@ -0,0 +1,4 @@
+local palette = require("catppuccin.palettes").get_palette "mocha"
+local presets = require "catppuccin.utils.reactive"
+
+return presets.cursorline("catppuccin-mocha-cursorline", palette)
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/stylua.toml b/config/neovim/store/lazy-plugins/catppuccin-nvim/stylua.toml
new file mode 100644
index 00000000..7a77a3f5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/stylua.toml
@@ -0,0 +1,7 @@
+column_width = 120
+line_endings = "Unix"
+indent_type = "Tabs"
+indent_width = 4
+quote_style = "AutoPreferDouble"
+collapse_simple_statement = "Always"
+call_parentheses = "None"
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/flavour_spec.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/flavour_spec.lua
new file mode 100644
index 00000000..2d069775
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/flavour_spec.lua
@@ -0,0 +1,104 @@
+local function reload()
+ for name, _ in pairs(package.loaded) do
+ if name:match "^catppuccin" then package.loaded[name] = nil end
+ end
+ vim.g.catppuccin_flavour = nil
+ vim.cmd [[highlight clear]]
+end
+
+describe("set background to", function()
+ before_each(function()
+ reload()
+ vim.cmd.colorscheme "catppuccin"
+ end)
+ it("light", function()
+ vim.o.background = "light"
+ assert.equals("catppuccin-latte", vim.g.colors_name)
+ end)
+ it("dark", function()
+ vim.o.background = "dark"
+ assert.equals("catppuccin-mocha", vim.g.colors_name)
+ end)
+end)
+
+describe("respect vim.o.background =", function()
+ before_each(function() reload() end)
+ it("light", function()
+ vim.o.background = "light"
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-latte", vim.g.colors_name)
+ end)
+ it("dark", function()
+ vim.o.background = "dark"
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-mocha", vim.g.colors_name)
+ end)
+end)
+
+describe("change flavour to", function()
+ before_each(function() reload() end)
+ it("latte", function()
+ vim.cmd.colorscheme "catppuccin-latte"
+ assert.equals("catppuccin-latte", vim.g.colors_name)
+ end)
+ it("frappe", function()
+ vim.cmd.colorscheme "catppuccin-frappe"
+ assert.equals("catppuccin-frappe", vim.g.colors_name)
+ end)
+ it("macchiato", function()
+ vim.cmd.colorscheme "catppuccin-macchiato"
+ assert.equals("catppuccin-macchiato", vim.g.colors_name)
+ end)
+ it("mocha", function()
+ vim.cmd.colorscheme "catppuccin-mocha"
+ assert.equals("catppuccin-mocha", vim.g.colors_name)
+ end)
+end)
+
+describe("respect setup flavour =", function()
+ before_each(function() reload() end)
+ it("latte", function()
+ require("catppuccin").setup { flavour = "latte" }
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-latte", vim.g.colors_name)
+ end)
+ it("frappe", function()
+ require("catppuccin").setup { flavour = "frappe" }
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-frappe", vim.g.colors_name)
+ end)
+ it("macchiato", function()
+ require("catppuccin").setup { flavour = "macchiato" }
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-macchiato", vim.g.colors_name)
+ end)
+ it("mocha", function()
+ require("catppuccin").setup { flavour = "mocha" }
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-mocha", vim.g.colors_name)
+ end)
+end)
+
+describe("(deprecated) respect vim.g.catppuccin_flavour =", function()
+ before_each(function() reload() end)
+ it("latte", function()
+ vim.g.catppuccin_flavour = "latte"
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-latte", vim.g.colors_name)
+ end)
+ it("frappe", function()
+ vim.g.catppuccin_flavour = "frappe"
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-frappe", vim.g.colors_name)
+ end)
+ it("macchiato", function()
+ vim.g.catppuccin_flavour = "macchiato"
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-macchiato", vim.g.colors_name)
+ end)
+ it("mocha", function()
+ vim.g.catppuccin_flavour = "mocha"
+ vim.cmd.colorscheme "catppuccin"
+ assert.equals("catppuccin-mocha", vim.g.colors_name)
+ end)
+end)
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/hash_spec.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/hash_spec.lua
new file mode 100644
index 00000000..dc475098
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/hash_spec.lua
@@ -0,0 +1,41 @@
+describe("hash", function()
+ local hash = require("catppuccin.lib.hashing").hash
+ it("typo", function() assert.are_not.equals(hash { custom_highlight = {} }, hash { ustom_highlight = {} }) end)
+ it(
+ "when table order is shuffled",
+ function()
+ assert.equals(
+ hash {
+ custom_highlight = {
+ Search = { fg = "#F5C2E7", bg = "#45475A", style = { "bold" } },
+ IncSearch = { fg = "#45475A", bg = "#F5C2E7" },
+ },
+ },
+ hash {
+ custom_highlight = {
+ Search = { style = { "bold" }, bg = "#45475A", fg = "#F5C2E7" },
+ IncSearch = { bg = "#F5C2E7", fg = "#45475A" },
+ },
+ }
+ )
+ end
+ )
+ it(
+ "when toggle true/false",
+ function()
+ assert.are_not.equals({
+ integrations = {
+ navic = true,
+ noice = true,
+ fidget = true,
+ },
+ }, {
+ integrations = {
+ navic = true,
+ noice = false,
+ fidget = false,
+ },
+ })
+ end
+ )
+end)
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/init.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/init.lua
new file mode 100644
index 00000000..6db3de31
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/init.lua
@@ -0,0 +1,27 @@
+local status, error = pcall(function()
+ local root = vim.fn.fnamemodify(".repro", ":p")
+ for _, name in ipairs { "config", "data", "state", "cache" } do
+ vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
+ end
+
+ local lazypath = root .. "/plugins/lazy.nvim"
+ if not vim.loop.fs_stat(lazypath) then
+ vim.fn.system { "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath }
+ end
+ vim.opt.runtimepath:prepend(lazypath)
+
+ require("lazy").setup({
+ { "catppuccin/nvim", dev = true },
+ }, {
+ root = root .. "/plugins",
+ dev = {
+ path = debug.getinfo(1).source:sub(2, -21),
+ },
+ })
+
+ require("catppuccin").setup()
+ vim.cmd.colorscheme "catppuccin"
+end)
+
+if error then print(error) end
+vim.cmd(status and "0cq" or "1cq")
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/init.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/init.vim
new file mode 100644
index 00000000..e0b4e9c2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/init.vim
@@ -0,0 +1,13 @@
+try
+ call plug#begin()
+ Plug expand('')[0:-16]
+ call plug#end()
+
+ lua require("catppuccin").setup {}
+ colorscheme catppuccin
+catch
+ echo v:exception
+ 1cq
+finally
+ 0cq
+endtry
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/minimal_init.vim b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/minimal_init.vim
new file mode 100644
index 00000000..a22651af
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/minimal_init.vim
@@ -0,0 +1,3 @@
+set rtp+=.
+
+runtime! plugin/plenary.vim
diff --git a/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/palette_spec.lua b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/palette_spec.lua
new file mode 100644
index 00000000..a411cbf0
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/catppuccin-nvim/tests/palette_spec.lua
@@ -0,0 +1,19 @@
+local function reload()
+ for name, _ in pairs(package.loaded) do
+ if name:match "^catppuccin" then package.loaded[name] = nil end
+ end
+ vim.g.catppuccin_flavour = nil
+ vim.cmd [[highlight clear]]
+end
+
+-- TODO: Move this to setup_spec
+describe("get palette", function()
+ before_each(function() reload() end)
+ it("before setup", function()
+ assert.equals(pcall(function() require("catppuccin.palettes").get_palette() end), true)
+ end)
+ it("after setup", function()
+ require("catppuccin").setup()
+ assert.equals(pcall(function() require("catppuccin.palettes").get_palette() end), true)
+ end)
+end)
diff --git a/config/neovim/store/lazy-plugins/chadtree/.dockerignore b/config/neovim/store/lazy-plugins/chadtree/.dockerignore
new file mode 100644
index 00000000..706a2a11
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/.dockerignore
@@ -0,0 +1,7 @@
+/.git/
+/.venv/
+__pycache__/
+.mypy_cache/
+/.vars/
+/temp/
+/.vscode/
diff --git a/config/neovim/store/lazy-plugins/chadtree/.github/workflows/artifacts.yml b/config/neovim/store/lazy-plugins/chadtree/.github/workflows/artifacts.yml
new file mode 100644
index 00000000..97a657fe
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/.github/workflows/artifacts.yml
@@ -0,0 +1,25 @@
+---
+name: Artifacts
+
+on:
+ push:
+ branches:
+ - chad
+ schedule:
+ - cron: "0 0 * * *" # daily
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Setup Python
+ uses: actions/setup-python@v3
+
+ - env:
+ CI_TOKEN: ${{ secrets.CI_TOKEN }}
+ run: |-
+ make build
diff --git a/config/neovim/store/lazy-plugins/chadtree/.github/workflows/ci.yml b/config/neovim/store/lazy-plugins/chadtree/.github/workflows/ci.yml
new file mode 100644
index 00000000..8051a9b2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/.github/workflows/ci.yml
@@ -0,0 +1,33 @@
+---
+name: CI
+
+on:
+ push:
+ schedule:
+ - cron: "0 0 * * *" # daily
+
+jobs:
+ mypy:
+ strategy:
+ matrix:
+ python_ver:
+ - "3.8"
+ - "3.9"
+ - "3.10"
+ - "3.11"
+ - "3.12"
+ - "3"
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Setup Python
+ uses: actions/setup-python@v3
+ with:
+ python-version: ${{ matrix.python_ver }}
+
+ - run: |-
+ make lint
diff --git a/config/neovim/store/lazy-plugins/chadtree/.github/workflows/codeql-analysis.yml b/config/neovim/store/lazy-plugins/chadtree/.github/workflows/codeql-analysis.yml
new file mode 100644
index 00000000..85042a63
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,57 @@
+---
+name: "CodeQL"
+
+on:
+ push:
+ schedule:
+ - cron: "0 0 * * *" # daily
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'python' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
+ # Learn more:
+ # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v1
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v1
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 https://git.io/JvXDl
+
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
+
+ #- run: |
+ # make bootstrap
+ # make release
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v1
diff --git a/config/neovim/store/lazy-plugins/chadtree/.gitignore b/config/neovim/store/lazy-plugins/chadtree/.gitignore
new file mode 100644
index 00000000..706a2a11
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/.gitignore
@@ -0,0 +1,7 @@
+/.git/
+/.venv/
+__pycache__/
+.mypy_cache/
+/.vars/
+/temp/
+/.vscode/
diff --git a/config/neovim/store/lazy-plugins/chadtree/.hadolint.yaml b/config/neovim/store/lazy-plugins/chadtree/.hadolint.yaml
new file mode 100644
index 00000000..eb3743d0
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/.hadolint.yaml
@@ -0,0 +1,6 @@
+---
+ignored:
+ # Allow Latest Dockerfile
+ - DL3007
+ # Allow Unpinned Apt Packages
+ - DL3008
diff --git a/config/neovim/store/lazy-plugins/chadtree/Dockerfile b/config/neovim/store/lazy-plugins/chadtree/Dockerfile
new file mode 100644
index 00000000..5489d0d7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/Dockerfile
@@ -0,0 +1,13 @@
+FROM ubuntu:focal
+
+ENV TERM=xterm-256color
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends -- python3-venv neovim git ca-certificates && \
+ rm -rf -- /var/lib/apt/lists/*
+
+
+COPY ./docker /
+WORKDIR /root/.config/nvim/pack/modules/start/chadtree
+COPY . .
+
+RUN python3 -m chadtree deps --xdg ~/.local/share/nvim
diff --git a/config/neovim/store/lazy-plugins/chadtree/Makefile b/config/neovim/store/lazy-plugins/chadtree/Makefile
new file mode 100644
index 00000000..be5d2b6d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/Makefile
@@ -0,0 +1,60 @@
+MAKEFLAGS += --check-symlink-times
+MAKEFLAGS += --jobs
+MAKEFLAGS += --no-builtin-rules
+MAKEFLAGS += --no-builtin-variables
+MAKEFLAGS += --shuffle
+MAKEFLAGS += --warn-undefined-variables
+SHELL := bash
+.DELETE_ON_ERROR:
+.ONESHELL:
+.SHELLFLAGS := --norc --noprofile -Eeuo pipefail -O dotglob -O nullglob -O extglob -O failglob -O globstar -c
+
+.DEFAULT_GOAL := help
+
+.PHONY: clean clobber build lint fmt
+
+clean:
+ rm -v -rf -- .mypy_cache/ .venv/
+
+clobber: clean
+ rm -v -rf -- .vars/
+
+.venv/bin/python3:
+ python3 -m venv -- .venv
+
+define PYDEPS
+from itertools import chain
+from os import execl
+from sys import executable
+
+from tomli import load
+
+toml = load(open("pyproject.toml", "rb"))
+
+project = toml["project"]
+execl(
+ executable,
+ executable,
+ "-m",
+ "pip",
+ "install",
+ "--upgrade",
+ "--",
+ *project.get("dependencies", ()),
+ *chain.from_iterable(project["optional-dependencies"].values()),
+)
+endef
+
+.venv/bin/mypy: .venv/bin/python3
+ '$<' -m pip install --requirement requirements.txt -- tomli
+ '$<' <<< '$(PYDEPS)'
+
+lint: .venv/bin/mypy
+ '$<' -- .
+
+build: .venv/bin/mypy
+ .venv/bin/python3 -- ci/prepare.py
+
+fmt: .venv/bin/mypy
+ .venv/bin/isort --profile=black --gitignore -- .
+ .venv/bin/black -- .
diff --git a/config/neovim/store/lazy-plugins/chadtree/README.md b/config/neovim/store/lazy-plugins/chadtree/README.md
new file mode 100644
index 00000000..54338f09
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/README.md
@@ -0,0 +1,157 @@
+# [CHADTree](https://ms-jpq.github.io/chadtree)
+
+File Manager for Neovim, Better than NERDTree.
+
+## Features Illustrated
+
+**See full list of screen captures [here](https://github.com/ms-jpq/chadtree/tree/chad/docs/FEATURES.md)**
+
+### I like speed
+
+- **Parallel** Filesystem Scan
+
+- **[React Like](https://reactjs.org/docs/reconciliation.html)** Reconciling Difference Minimizing Rendering engine
+
+- **Never** blocks
+
+_You can read more about my [performance optimization](https://github.com/ms-jpq/chadtree/tree/chad/docs/ARCHITECTURE.md) here._
+
+### I like power
+
+- Visual mode selections
+
+- Create, Copy, Paste, Delete, Rename, gotta do them all
+
+- Quickfix integration
+
+- [Bookmarks](https://raw.githubusercontent.com/ms-jpq/chadtree/chad/docs/img/bookmarks.png)
+
+
+
+### I like 21st century
+
+- Filtering by glob
+
+- Follow mode
+
+- Session support (save open folders to disk, pick up where you left off)
+
+- Trash support (requires [`trash`](https://formulae.brew.sh/formula/trash) or [`trash-cli`](https://github.com/andreafrancia/trash-cli))
+
+- `ls -l` statistics
+
+- Correct! handling of symlinks
+
+
+
+### I like version control
+
+- Asynchronous parse git status (untracked, modified, staged)
+
+- Full support for git submodules
+
+
+
+### I like colours
+
+- Full `$LS_COLOR` support! (shows same colours as unix `ls` & `tree` commands)
+
+- [Github coloured](https://github.com/github/linguist) icons (over 600 colours!)
+
+- Three different sets of icons out of the box
+
+- Four built-in themes - nord, solarized, trapdoor, vim-syntax
+
+
+
+
+
+### I like refinement
+
+- Maintain cursor position on relevant files even when during movements.
+
+- Maintain selection when copying, moving files
+
+- Mimetype warning (so you don't accidentally open an image)
+
+- Validating config parser **(notice, I added an extra `"dog"` param)**
+
+
+
+
+
+### I like documentation
+
+- Built-in help command in a floating window!
+
+- Over 1000 lines of meticulous docs covering every option / function!
+
+**Use `:CHADhelp` to view [documentation](https://github.com/ms-jpq/chadtree/tree/chad/docs)**
+
+**Use `:CHADhelp --web` to open documentation in your browser!** (If you have one installed)
+
+## Install
+
+**Minimum version**: `python`: 3.8.2, `nvim`: `0.4.3`, make sure to have `virtualenv` installed (e.g.: `sudo apt install --yes -- python3-venv`)
+
+Install the usual way, ie. [VimPlug](https://github.com/junegunn/vim-plug), [Vundle](https://github.com/VundleVim/Vundle.vim), etc
+
+```vim
+Plug 'ms-jpq/chadtree', {'branch': 'chad', 'do': 'python3 -m chadtree deps'}
+```
+
+You will have to run `:CHADdeps` when installing / updating. This will install CHADTree's dependencies locally inside `chadtree/.vars/runtime`.
+
+doing `rm -rf chadtree/` will cleanly remove everything CHADTree uses on your computer.
+
+## Usage
+
+To toggle CHADTree run command `:CHADopen`. Set it to a hotkey for convenience.
+
+```vimL
+nnoremap v CHADopen
+```
+
+To see a list of hot keys:
+
+Either use `:CHADhelp keybind` or open in browser using [`:CHADhelp keybind --web`](https://github.com/ms-jpq/chadtree/tree/chad/docs/KEYBIND.md)
+
+### FAQ
+
+Q: Sometimes Windows will get stuck with CHADTree decorations when I do not want them to be, how do I resolve this?
+
+A: Run `:CHADrestore`
+
+### Recommendations
+
+Add a hotkey to clear quickfix list:
+
+```vimL
+nnoremap l call setqflist([])
+```
+
+## If you like this...
+
+Also check out
+
+- [`sad`](https://github.com/ms-jpq/sad), its a modern `sed` that does previews with syntax highlighting, and lets you pick and choose which chunks to edit.
+
+- [`coq.nvim`](https://github.com/ms-jpq/coq_nvim), it's a FAST AS FUCK completion client with shit tons of features.
+
+- [isomorphic-copy](https://github.com/ms-jpq/isomorphic-copy), it's a cross platform clipboard that is daemonless, and does not require third party support.
+
+## Special Thanks
+
+CHADTree does not define it's own colours beyond some minimal defaults, all themes are imported from other open source projects.
+
+> The base icons are imported from the [vim-devicon](https://github.com/ryanoasis/vim-devicons)
+
+> All emoji icons are imported from the [vim-emoji-icon-theme](https://github.com/adelarsq/vim-emoji-icon-theme)
+
+> Some themes are imported from [dircolors-solarized](https://github.com/seebi/dircolors-solarized)
+
+> Some themes are imported from [nord-dircolors](https://github.com/arcticicestudio/nord-dircolors)
+
+> Some themes are imported from [LS_COLORS](https://github.com/trapd00r/LS_COLORS)
+
+> Some themes are imported from [vim-nerdtree-syntax-highlight](https://github.com/tiagofumo/vim-nerdtree-syntax-highlight)
diff --git a/config/neovim/store/lazy-plugins/chadtree/_config.yml b/config/neovim/store/lazy-plugins/chadtree/_config.yml
new file mode 100644
index 00000000..6a42506f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/_config.yml
@@ -0,0 +1,7 @@
+---
+title: CHADTree
+
+showcase: True
+
+images:
+ - https://raw.githubusercontent.com/ms-jpq/chadtree/chad/docs/img/visual_select.gif
diff --git a/config/neovim/store/lazy-plugins/chadtree/artifacts/README.md b/config/neovim/store/lazy-plugins/chadtree/artifacts/README.md
new file mode 100644
index 00000000..56e33c08
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/artifacts/README.md
@@ -0,0 +1,3 @@
+# DO NOT EDIT
+
+These are code generated jsons.
diff --git a/config/neovim/store/lazy-plugins/chadtree/artifacts/artifact.json b/config/neovim/store/lazy-plugins/chadtree/artifacts/artifact.json
new file mode 100644
index 00000000..8cf4d557
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/artifacts/artifact.json
@@ -0,0 +1,2310 @@
+{
+ "icon_colours": {
+ "github": {
+ ".1": "#ecdebe",
+ ".1in": "#ecdebe",
+ ".1m": "#ecdebe",
+ ".1x": "#ecdebe",
+ ".2": "#ecdebe",
+ ".2da": "#38761D",
+ ".3": "#ecdebe",
+ ".3in": "#ecdebe",
+ ".3m": "#ecdebe",
+ ".3p": "#ecdebe",
+ ".3pm": "#ecdebe",
+ ".3qt": "#ecdebe",
+ ".3x": "#ecdebe",
+ ".4": "#ecdebe",
+ ".4DForm": "#292929",
+ ".4DProject": "#292929",
+ ".4dm": "#004289",
+ ".4gl": "#63408e",
+ ".4th": "#341708",
+ ".5": "#ecdebe",
+ ".6": "#ecdebe",
+ ".6pl": "#0000fb",
+ ".6pm": "#0000fb",
+ ".7": "#ecdebe",
+ ".8": "#ecdebe",
+ ".8xk": "#A0AA87",
+ ".8xk.txt": "#A0AA87",
+ ".8xp": "#A0AA87",
+ ".8xp.txt": "#A0AA87",
+ ".9": "#ecdebe",
+ ".Dsr": "#2c6353",
+ ".JSON-tmLanguage": "#292929",
+ ".OutJob": "#A89663",
+ ".PcbDoc": "#A89663",
+ ".PrjPCB": "#A89663",
+ ".SchDoc": "#A89663",
+ "._coffee": "#244776",
+ "._js": "#f1e05a",
+ "._ls": "#499886",
+ ".a51": "#6E4C13",
+ ".abap": "#E8274B",
+ ".ada": "#02f88c",
+ ".adb": "#02f88c",
+ ".adml": "#0060ac",
+ ".admx": "#0060ac",
+ ".ado": "#1a5f91",
+ ".adoc": "#73a0c5",
+ ".adp": "#e4cc98",
+ ".ads": "#02f88c",
+ ".afm": "#fa0f00",
+ ".agc": "#0B3D91",
+ ".agda": "#315665",
+ ".ahk": "#6594b9",
+ ".ahkl": "#6594b9",
+ ".aidl": "#34EB6B",
+ ".aj": "#a957b0",
+ ".al": "#0298c3",
+ ".als": "#64C800",
+ ".ampl": "#E6EFBB",
+ ".angelscript": "#C7D7DC",
+ ".anim": "#222c37",
+ ".ant": "#0060ac",
+ ".antlers.html": "#ff269e",
+ ".antlers.php": "#ff269e",
+ ".antlers.xml": "#ff269e",
+ ".apacheconf": "#d12127",
+ ".apib": "#2ACCA8",
+ ".apl": "#5A8164",
+ ".app": "#B83998",
+ ".app.src": "#B83998",
+ ".applescript": "#101F1F",
+ ".arc": "#aa2afe",
+ ".arr": "#ee1e10",
+ ".as": "#C7D7DC",
+ ".asax": "#9400ff",
+ ".asc": "#73a0c5",
+ ".asciidoc": "#73a0c5",
+ ".ascx": "#9400ff",
+ ".asd": "#3fb68b",
+ ".asddls": "#555e25",
+ ".ash": "#B9D9FF",
+ ".ashx": "#9400ff",
+ ".asm": "#005daa",
+ ".asmx": "#9400ff",
+ ".asp": "#6a40fd",
+ ".aspx": "#9400ff",
+ ".asset": "#222c37",
+ ".astro": "#ff5a03",
+ ".asy": "#ff0000",
+ ".au3": "#1C3552",
+ ".aug": "#9CC134",
+ ".auk": "#c30e9b",
+ ".aux": "#3D6117",
+ ".avdl": "#0040FF",
+ ".avsc": "#292929",
+ ".aw": "#4F5D95",
+ ".awk": "#c30e9b",
+ ".axaml": "#0060ac",
+ ".axd": "#9400ff",
+ ".axi": "#0aa0ff",
+ ".axi.erb": "#747faa",
+ ".axml": "#0060ac",
+ ".axs": "#0aa0ff",
+ ".axs.erb": "#747faa",
+ ".b": "#2F2530",
+ ".bal": "#FF5000",
+ ".bas": "#2c6353",
+ ".bash": "#89e051",
+ ".bat": "#C1F12E",
+ ".bats": "#89e051",
+ ".bb": "#db5855",
+ ".bbx": "#3D6117",
+ ".bdy": "#dad8d8",
+ ".be": "#15A13C",
+ ".bf": "#2F2530",
+ ".bi": "#141AC9",
+ ".bib": "#778899",
+ ".bibtex": "#778899",
+ ".bicep": "#519aba",
+ ".bison": "#6A463F",
+ ".blade": "#f7523f",
+ ".blade.php": "#f7523f",
+ ".bmx": "#cd6400",
+ ".bones": "#f1e05a",
+ ".boo": "#d4bec1",
+ ".boot": "#db5855",
+ ".bpl": "#c80fa0",
+ ".brd": "#2f4aab",
+ ".brs": "#662D91",
+ ".bs": "#66AABB",
+ ".bsl": "#814CCC",
+ ".bsv": "#12223c",
+ ".builder": "#701516",
+ ".builds": "#0060ac",
+ ".bzl": "#76d275",
+ ".c": "#555555",
+ ".c++": "#f34b7d",
+ ".cabal": "#483465",
+ ".cairo": "#ff4a48",
+ ".cake": "#244776",
+ ".capnp": "#c42727",
+ ".cats": "#555555",
+ ".cbx": "#3D6117",
+ ".cc": "#f34b7d",
+ ".ccproj": "#0060ac",
+ ".ccxml": "#0060ac",
+ ".cdc": "#00ef8b",
+ ".cdf": "#dd1100",
+ ".cds": "#0092d1",
+ ".ceylon": "#dfa535",
+ ".cfc": "#ed2cd6",
+ ".cfg": "#d1dbe0",
+ ".cfm": "#ed2cd6",
+ ".cfml": "#ed2cd6",
+ ".cgi": "#89e051",
+ ".cginc": "#aace60",
+ ".ch": "#403a40",
+ ".chpl": "#8dc63f",
+ ".circom": "#707575",
+ ".cirru": "#ccccff",
+ ".cjs": "#f1e05a",
+ ".cjsx": "#244776",
+ ".ck": "#3f8000",
+ ".cl": "#ed2e2d",
+ ".cl2": "#db5855",
+ ".clar": "#5546ff",
+ ".click": "#E4E6F3",
+ ".clixml": "#0060ac",
+ ".clj": "#db5855",
+ ".cljc": "#db5855",
+ ".cljs": "#db5855",
+ ".cljs.hl": "#db5855",
+ ".cljscm": "#db5855",
+ ".cljx": "#db5855",
+ ".clp": "#00A300",
+ ".cls": "#2c6353",
+ ".clw": "#db901e",
+ ".cmake": "#DA3434",
+ ".cmake.in": "#DA3434",
+ ".cmd": "#C1F12E",
+ ".cmp": "#d20b00",
+ ".cnc": "#D08CF2",
+ ".cnf": "#d1dbe0",
+ ".cocci": "#c94949",
+ ".code-snippets": "#292929",
+ ".code-workspace": "#292929",
+ ".coffee": "#244776",
+ ".coffee.md": "#244776",
+ ".command": "#89e051",
+ ".coq": "#d0b68c",
+ ".cp": "#B0CE4E",
+ ".cpp": "#f34b7d",
+ ".cppm": "#f34b7d",
+ ".cproject": "#0060ac",
+ ".cps": "#B0CE4E",
+ ".cql": "#e38c00",
+ ".cr": "#000100",
+ ".cs": "#596706",
+ ".csc": "#FF6800",
+ ".cscfg": "#0060ac",
+ ".csd": "#1a1a1a",
+ ".csdef": "#0060ac",
+ ".cshtml": "#512be4",
+ ".csl": "#0060ac",
+ ".cson": "#244776",
+ ".csproj": "#0060ac",
+ ".css": "#563d7c",
+ ".csv": "#237346",
+ ".csx": "#178600",
+ ".ct": "#0060ac",
+ ".ctl": "#2c6353",
+ ".ctp": "#4F5D95",
+ ".cts": "#3178c6",
+ ".cu": "#3A4E3A",
+ ".cue": "#5886E1",
+ ".cuh": "#3A4E3A",
+ ".curry": "#531242",
+ ".cwl": "#B5314C",
+ ".cxx": "#f34b7d",
+ ".cyp": "#34c0eb",
+ ".cypher": "#34c0eb",
+ ".d": "#427819",
+ ".d2": "#526ee8",
+ ".dae": "#F1A42B",
+ ".darcspatch": "#8eff23",
+ ".dart": "#00B4AB",
+ ".dats": "#1ac620",
+ ".db2": "#e38c00",
+ ".dcl": "#3F85AF",
+ ".ddl": "#e38c00",
+ ".decls": "#00FFAE",
+ ".depproj": "#0060ac",
+ ".dfm": "#E3F171",
+ ".dfy": "#FFEC25",
+ ".dhall": "#dfafff",
+ ".di": "#ba595e",
+ ".dita": "#0060ac",
+ ".ditamap": "#0060ac",
+ ".ditaval": "#0060ac",
+ ".djs": "#cca760",
+ ".dll.config": "#0060ac",
+ ".dlm": "#a3522f",
+ ".dm": "#447265",
+ ".do": "#1a5f91",
+ ".dockerfile": "#384d54",
+ ".dof": "#d1dbe0",
+ ".doh": "#1a5f91",
+ ".dot": "#2596be",
+ ".dotsettings": "#0060ac",
+ ".dpatch": "#8eff23",
+ ".dpr": "#E3F171",
+ ".druby": "#c7a938",
+ ".dsc": "#FBEE96",
+ ".dsp": "#c37240",
+ ".dtx": "#3D6117",
+ ".duby": "#c7a938",
+ ".dwl": "#003a52",
+ ".dyalog": "#5A8164",
+ ".dyl": "#6c616e",
+ ".dylan": "#6c616e",
+ ".e": "#FF790B",
+ ".eb": "#069406",
+ ".ebuild": "#9400ff",
+ ".ec": "#913960",
+ ".ecl": "#001d9d",
+ ".eclass": "#9400ff",
+ ".eclxml": "#8a1267",
+ ".ecr": "#2e1052",
+ ".ect": "#a91e50",
+ ".edgeql": "#31A7FF",
+ ".editorconfig": "#fff1f2",
+ ".eex": "#6e4a7e",
+ ".eh": "#913960",
+ ".ejs": "#a91e50",
+ ".ejs.t": "#a91e50",
+ ".el": "#c065db",
+ ".eliom": "#ef7a08",
+ ".eliomi": "#ef7a08",
+ ".elm": "#60B5CC",
+ ".elv": "#55BB55",
+ ".em": "#FFF4F3",
+ ".emacs": "#c065db",
+ ".emacs.desktop": "#c065db",
+ ".emberscript": "#FFF4F3",
+ ".env": "#e5d559",
+ ".epj": "#913960",
+ ".eps": "#da291c",
+ ".epsi": "#da291c",
+ ".eq": "#a78649",
+ ".erb": "#701516",
+ ".erb.deface": "#701516",
+ ".erl": "#B83998",
+ ".es": "#f1e05a",
+ ".es6": "#f1e05a",
+ ".escript": "#B83998",
+ ".esdl": "#31A7FF",
+ ".ex": "#FF790B",
+ ".exs": "#6e4a7e",
+ ".eye": "#701516",
+ ".f": "#4d41b1",
+ ".f03": "#4d41b1",
+ ".f08": "#4d41b1",
+ ".f77": "#4d41b1",
+ ".f90": "#4d41b1",
+ ".f95": "#4d41b1",
+ ".factor": "#636746",
+ ".fan": "#14253c",
+ ".fancypack": "#7b9db4",
+ ".fcgi": "#89e051",
+ ".feature": "#5B2063",
+ ".filters": "#0060ac",
+ ".fish": "#4aae47",
+ ".flex": "#DBCA00",
+ ".flf": "#FFDDBB",
+ ".flux": "#88ccff",
+ ".fnc": "#dad8d8",
+ ".fnl": "#fff3d7",
+ ".for": "#4d41b1",
+ ".forth": "#341708",
+ ".fp": "#5686a5",
+ ".fpp": "#4d41b1",
+ ".fr": "#00cafe",
+ ".frag": "#f1e05a",
+ ".frg": "#5686a5",
+ ".frm": "#2c6353",
+ ".frt": "#341708",
+ ".fs": "#5686a5",
+ ".fsh": "#5686a5",
+ ".fshader": "#5686a5",
+ ".fsi": "#b845fc",
+ ".fsproj": "#0060ac",
+ ".fst": "#572e30",
+ ".fsti": "#572e30",
+ ".fsx": "#b845fc",
+ ".fth": "#341708",
+ ".ftl": "#0050b2",
+ ".fun": "#dc566d",
+ ".fut": "#5f021f",
+ ".fx": "#aace60",
+ ".fxh": "#aace60",
+ ".fxml": "#0060ac",
+ ".fy": "#7b9db4",
+ ".g": "#0000cc",
+ ".g4": "#9DC3FF",
+ ".gaml": "#FFC766",
+ ".gap": "#0000cc",
+ ".gawk": "#c30e9b",
+ ".gbl": "#d20b00",
+ ".gbo": "#d20b00",
+ ".gbp": "#d20b00",
+ ".gbr": "#d20b00",
+ ".gbs": "#d20b00",
+ ".gco": "#D08CF2",
+ ".gcode": "#D08CF2",
+ ".gd": "#355570",
+ ".gdnlib": "#355570",
+ ".gdns": "#355570",
+ ".ged": "#003058",
+ ".gemspec": "#701516",
+ ".geo": "#5686a5",
+ ".geojson": "#292929",
+ ".geom": "#5686a5",
+ ".gf": "#ff0000",
+ ".gi": "#0000cc",
+ ".gitconfig": "#F44D27",
+ ".gitignore": "#000000",
+ ".gjs": "#F5835F",
+ ".gko": "#d20b00",
+ ".glade": "#0060ac",
+ ".gleam": "#ffaff3",
+ ".glf": "#c1ac7f",
+ ".glsl": "#5686a5",
+ ".glslf": "#5686a5",
+ ".glslv": "#5686a5",
+ ".gltf": "#292929",
+ ".gmi": "#ff6900",
+ ".gml": "#0060ac",
+ ".gms": "#f49a22",
+ ".gmx": "#0060ac",
+ ".gnu": "#f0a9f0",
+ ".gnuplot": "#f0a9f0",
+ ".go": "#00ADD8",
+ ".god": "#701516",
+ ".golo": "#88562A",
+ ".gp": "#f0a9f0",
+ ".gpb": "#d20b00",
+ ".gpt": "#d20b00",
+ ".gql": "#e10098",
+ ".grace": "#615f8b",
+ ".gradle": "#02303a",
+ ".gradle.kts": "#02303a",
+ ".graphql": "#e10098",
+ ".graphqls": "#e10098",
+ ".groovy": "#4298b8",
+ ".grt": "#4298b8",
+ ".grxml": "#0060ac",
+ ".gs": "#f1e05a",
+ ".gsc": "#FF6800",
+ ".gsh": "#FF6800",
+ ".gshader": "#5686a5",
+ ".gsp": "#4298b8",
+ ".gst": "#0060ac",
+ ".gsx": "#82937f",
+ ".gtl": "#d20b00",
+ ".gto": "#d20b00",
+ ".gtp": "#d20b00",
+ ".gtpl": "#4298b8",
+ ".gts": "#d20b00",
+ ".gv": "#2596be",
+ ".gvy": "#4298b8",
+ ".gyp": "#3572A5",
+ ".gypi": "#3572A5",
+ ".h": "#438eff",
+ ".h++": "#f34b7d",
+ ".hack": "#878787",
+ ".haml": "#ece2a9",
+ ".haml.deface": "#ece2a9",
+ ".handlebars": "#f7931e",
+ ".har": "#292929",
+ ".hats": "#1ac620",
+ ".hb": "#0e60e3",
+ ".hbs": "#f7931e",
+ ".hc": "#ffefaf",
+ ".hcl": "#844FBA",
+ ".hh": "#878787",
+ ".hhi": "#878787",
+ ".hic": "#db5855",
+ ".hlsl": "#aace60",
+ ".hlsli": "#aace60",
+ ".hocon": "#9ff8ee",
+ ".hoon": "#00b171",
+ ".hpp": "#f34b7d",
+ ".hqf": "#3F3F3F",
+ ".hql": "#dce200",
+ ".hrl": "#B83998",
+ ".hs": "#5e5086",
+ ".hs-boot": "#5e5086",
+ ".hsc": "#5e5086",
+ ".hta": "#e34c26",
+ ".htm": "#e34c26",
+ ".html": "#e34c26",
+ ".html.heex": "#6e4a7e",
+ ".html.hl": "#e34c26",
+ ".html.leex": "#6e4a7e",
+ ".http": "#005C9C",
+ ".hx": "#df7900",
+ ".hxml": "#f68712",
+ ".hxsl": "#df7900",
+ ".hxx": "#f34b7d",
+ ".hy": "#7790B2",
+ ".hzp": "#0060ac",
+ ".i": "#005daa",
+ ".i3": "#223388",
+ ".ice": "#003fa2",
+ ".iced": "#244776",
+ ".icl": "#3F85AF",
+ ".idc": "#555555",
+ ".idr": "#b30000",
+ ".ig": "#223388",
+ ".ihlp": "#1a5f91",
+ ".ijm": "#99AAFF",
+ ".ijs": "#9EEDFF",
+ ".ik": "#078193",
+ ".ily": "#9ccc7c",
+ ".imba": "#16cec6",
+ ".iml": "#0060ac",
+ ".inc": "#f69e1d",
+ ".ini": "#d1dbe0",
+ ".inl": "#f34b7d",
+ ".ino": "#f34b7d",
+ ".ins": "#3D6117",
+ ".intr": "#6c616e",
+ ".io": "#a9188d",
+ ".iol": "#843179",
+ ".ipf": "#0000cc",
+ ".ipp": "#f34b7d",
+ ".ipynb": "#DA5B0B",
+ ".isl": "#264b99",
+ ".iss": "#264b99",
+ ".iuml": "#fbbd16",
+ ".ivy": "#0060ac",
+ ".ixx": "#f34b7d",
+ ".j": "#ff0c5a",
+ ".j2": "#a52a22",
+ ".jade": "#a86454",
+ ".jake": "#f1e05a",
+ ".janet": "#0886a5",
+ ".jav": "#b07219",
+ ".java": "#b07219",
+ ".javascript": "#f1e05a",
+ ".jbuilder": "#701516",
+ ".jcl": "#d90e09",
+ ".jelly": "#0060ac",
+ ".jflex": "#DBCA00",
+ ".jinja": "#a52a22",
+ ".jinja2": "#a52a22",
+ ".jison": "#56b3cb",
+ ".jisonlex": "#56b3cb",
+ ".jl": "#a270ba",
+ ".jq": "#c7254e",
+ ".js": "#f1e05a",
+ ".js.erb": "#f1e05a",
+ ".jsb": "#f1e05a",
+ ".jscad": "#f1e05a",
+ ".jsfl": "#f1e05a",
+ ".jsh": "#b07219",
+ ".jslib": "#f1e05a",
+ ".jsm": "#f1e05a",
+ ".json": "#85ea2d",
+ ".json5": "#267CB9",
+ ".jsonc": "#292929",
+ ".jsonl": "#292929",
+ ".jsonld": "#0c479c",
+ ".jsonnet": "#0064bd",
+ ".jsp": "#2A6277",
+ ".jspre": "#f1e05a",
+ ".jsproj": "#0060ac",
+ ".jss": "#f1e05a",
+ ".jst": "#a91e50",
+ ".jsx": "#f1e05a",
+ ".kak": "#6f8042",
+ ".kicad_mod": "#2f4aab",
+ ".kicad_pcb": "#2f4aab",
+ ".kicad_sch": "#2f4aab",
+ ".kicad_wks": "#2f4aab",
+ ".kid": "#951531",
+ ".kml": "#0060ac",
+ ".kojo": "#c22d40",
+ ".krl": "#28430A",
+ ".ks": "#41adf0",
+ ".ksh": "#89e051",
+ ".ksy": "#773b37",
+ ".kt": "#A97BFF",
+ ".ktm": "#A97BFF",
+ ".kts": "#A97BFF",
+ ".kv": "#1da6e0",
+ ".l": "#ecdebe",
+ ".lagda": "#315665",
+ ".lark": "#2980B9",
+ ".las": "#999999",
+ ".lasso": "#999999",
+ ".lasso8": "#999999",
+ ".lasso9": "#999999",
+ ".latte": "#f2a542",
+ ".launch": "#0060ac",
+ ".lbx": "#3D6117",
+ ".lektorproject": "#d1dbe0",
+ ".less": "#1d365d",
+ ".lex": "#DBCA00",
+ ".lfe": "#4C3023",
+ ".lgt": "#295b9a",
+ ".lhs": "#5e5086",
+ ".libsonnet": "#0064bd",
+ ".lid": "#6c616e",
+ ".lidr": "#b30000",
+ ".ligo": "#0e74ff",
+ ".linq": "#178600",
+ ".liquid": "#67b8de",
+ ".lisp": "#87AED7",
+ ".litcoffee": "#244776",
+ ".livemd": "#083fa1",
+ ".lkml": "#652B81",
+ ".ll": "#185619",
+ ".lmi": "#3572A5",
+ ".logtalk": "#295b9a",
+ ".lol": "#cc9900",
+ ".lookml": "#652B81",
+ ".lpr": "#E3F171",
+ ".ls": "#499886",
+ ".lsl": "#3d9970",
+ ".lslp": "#3d9970",
+ ".lsp": "#87AED7",
+ ".ltx": "#3D6117",
+ ".lua": "#000080",
+ ".lvclass": "#fede06",
+ ".lvlib": "#fede06",
+ ".lvproj": "#fede06",
+ ".ly": "#9ccc7c",
+ ".m": "#438eff",
+ ".m2": "#d8ffff",
+ ".m3": "#223388",
+ ".ma": "#dd1100",
+ ".mak": "#427819",
+ ".make": "#427819",
+ ".makefile": "#427819",
+ ".mako": "#7e858d",
+ ".man": "#ecdebe",
+ ".mao": "#7e858d",
+ ".markdown": "#083fa1",
+ ".marko": "#42bff2",
+ ".mask": "#222c37",
+ ".mat": "#222c37",
+ ".mata": "#1a5f91",
+ ".matah": "#1a5f91",
+ ".mathematica": "#dd1100",
+ ".matlab": "#e16737",
+ ".mawk": "#c30e9b",
+ ".maxhelp": "#c4a79c",
+ ".maxpat": "#c4a79c",
+ ".maxproj": "#c4a79c",
+ ".mc": "#8D6747",
+ ".mcfunction": "#E22837",
+ ".mcmeta": "#292929",
+ ".mcr": "#00a6a6",
+ ".md": "#083fa1",
+ ".mdoc": "#ecdebe",
+ ".mdown": "#083fa1",
+ ".mdpolicy": "#0060ac",
+ ".mdwn": "#083fa1",
+ ".mdx": "#fcb32c",
+ ".me": "#ecdebe",
+ ".mediawiki": "#fc5757",
+ ".mermaid": "#ff3670",
+ ".meta": "#222c37",
+ ".metal": "#8f14e9",
+ ".mg": "#223388",
+ ".mint": "#02b046",
+ ".mir": "#cb171e",
+ ".mirah": "#c7a938",
+ ".mjml": "#0060ac",
+ ".mjs": "#f1e05a",
+ ".mk": "#427819",
+ ".mkd": "#083fa1",
+ ".mkdn": "#083fa1",
+ ".mkdown": "#083fa1",
+ ".mkfile": "#427819",
+ ".mkii": "#3D6117",
+ ".mkiv": "#3D6117",
+ ".mkvi": "#3D6117",
+ ".ml": "#dc566d",
+ ".ml4": "#ef7a08",
+ ".mli": "#ef7a08",
+ ".mligo": "#3be133",
+ ".mlir": "#5EC8DB",
+ ".mll": "#ef7a08",
+ ".mly": "#ef7a08",
+ ".mm": "#0060ac",
+ ".mmd": "#ff3670",
+ ".mo": "#fbb03b",
+ ".mod": "#0060ac",
+ ".moo": "#ff2b2b",
+ ".moon": "#ff4585",
+ ".move": "#4a137a",
+ ".mpl": "#21D789",
+ ".mps": "#21D789",
+ ".mq4": "#62A8D6",
+ ".mq5": "#4A76B8",
+ ".mqh": "#4A76B8",
+ ".mrc": "#3d57c3",
+ ".ms": "#ecdebe",
+ ".msd": "#21D789",
+ ".mspec": "#701516",
+ ".mt": "#dd1100",
+ ".mtml": "#b7e1f4",
+ ".mts": "#3178c6",
+ ".mu": "#244963",
+ ".mud": "#dc75e5",
+ ".mustache": "#724b3b",
+ ".mxml": "#0060ac",
+ ".mxt": "#c4a79c",
+ ".mysql": "#e38c00",
+ ".n": "#ecdebe",
+ ".nanorc": "#2d004d",
+ ".nas": "#1d2c4e",
+ ".nasm": "#6E4C13",
+ ".natvis": "#0060ac",
+ ".nawk": "#c30e9b",
+ ".nb": "#dd1100",
+ ".nbp": "#dd1100",
+ ".nc": "#94B0C7",
+ ".ncl": "#0060ac",
+ ".ndproj": "#0060ac",
+ ".ne": "#990000",
+ ".nearley": "#990000",
+ ".nf": "#3ac486",
+ ".nginx": "#009639",
+ ".nginxconf": "#009639",
+ ".nim": "#ffc200",
+ ".nim.cfg": "#ffc200",
+ ".nimble": "#ffc200",
+ ".nimrod": "#ffc200",
+ ".nims": "#ffc200",
+ ".nit": "#009917",
+ ".nix": "#7e7eff",
+ ".njk": "#3d8137",
+ ".njs": "#f1e05a",
+ ".nl": "#87AED7",
+ ".nlogo": "#ff6375",
+ ".nomad": "#844FBA",
+ ".nproj": "#0060ac",
+ ".nqp": "#0000fb",
+ ".nr": "#ecdebe",
+ ".nse": "#000080",
+ ".nss": "#111522",
+ ".nu": "#4E9906",
+ ".numpy": "#9C8AF9",
+ ".numpyw": "#9C8AF9",
+ ".numsc": "#9C8AF9",
+ ".nuspec": "#0060ac",
+ ".nut": "#800000",
+ ".ny": "#3fb68b",
+ ".odd": "#0060ac",
+ ".odin": "#60AFFE",
+ ".ol": "#843179",
+ ".omgrofl": "#cabbff",
+ ".ooc": "#b0b77e",
+ ".opal": "#f7ede0",
+ ".opencl": "#ed2e2d",
+ ".orc": "#1a1a1a",
+ ".org": "#77aa99",
+ ".os": "#814CCC",
+ ".osm": "#0060ac",
+ ".owl": "#5b70bd",
+ ".oxygene": "#cdd0e3",
+ ".oz": "#fab738",
+ ".p": "#5ce600",
+ ".p4": "#7055b5",
+ ".p6": "#0000fb",
+ ".p6l": "#0000fb",
+ ".p6m": "#0000fb",
+ ".p8": "#000080",
+ ".pac": "#f1e05a",
+ ".pact": "#F7A8B8",
+ ".pan": "#cc0000",
+ ".parrot": "#f3ca0a",
+ ".pas": "#E3F171",
+ ".pascal": "#E3F171",
+ ".pat": "#c4a79c",
+ ".pb": "#5a6986",
+ ".pbi": "#5a6986",
+ ".pbt": "#8f0f8d",
+ ".pck": "#dad8d8",
+ ".pcss": "#dc3a0c",
+ ".pd_lua": "#000080",
+ ".pddl": "#0d00ff",
+ ".pde": "#0096D8",
+ ".pegjs": "#234d6b",
+ ".pep": "#C76F5B",
+ ".per": "#d8df39",
+ ".perl": "#0298c3",
+ ".pfa": "#da291c",
+ ".pgsql": "#336790",
+ ".ph": "#0298c3",
+ ".php": "#4F5D95",
+ ".php3": "#4F5D95",
+ ".php4": "#4F5D95",
+ ".php5": "#4F5D95",
+ ".phps": "#4F5D95",
+ ".phpt": "#4F5D95",
+ ".phtml": "#4f5d95",
+ ".pig": "#fcd7de",
+ ".pike": "#005390",
+ ".pkb": "#dad8d8",
+ ".pkgproj": "#0060ac",
+ ".pks": "#dad8d8",
+ ".pl": "#0000fb",
+ ".pl6": "#0000fb",
+ ".plantuml": "#fbbd16",
+ ".plb": "#dad8d8",
+ ".plist": "#0060ac",
+ ".plot": "#f0a9f0",
+ ".pls": "#dad8d8",
+ ".plsql": "#dad8d8",
+ ".plt": "#74283c",
+ ".pluginspec": "#0060ac",
+ ".plx": "#0298c3",
+ ".pm": "#0000fb",
+ ".pm6": "#0000fb",
+ ".pml": "#de0000",
+ ".pmod": "#005390",
+ ".podsl": "#3fb68b",
+ ".podspec": "#701516",
+ ".pogo": "#d80074",
+ ".polar": "#ae81ff",
+ ".por": "#f8bd00",
+ ".postcss": "#dc3a0c",
+ ".pov": "#6bac65",
+ ".pp": "#302B6D",
+ ".pprx": "#d90e09",
+ ".praat": "#c8506d",
+ ".prawn": "#701516",
+ ".prc": "#e38c00",
+ ".prefab": "#222c37",
+ ".prefs": "#d1dbe0",
+ ".prg": "#403a40",
+ ".prisma": "#0c344b",
+ ".pro": "#74283c",
+ ".proj": "#0060ac",
+ ".prolog": "#74283c",
+ ".properties": "#2A6277",
+ ".props": "#0060ac",
+ ".prw": "#403a40",
+ ".ps": "#da291c",
+ ".ps1": "#012456",
+ ".ps1xml": "#0060ac",
+ ".psc": "#6600cc",
+ ".psc1": "#0060ac",
+ ".psd1": "#012456",
+ ".psgi": "#0298c3",
+ ".psm1": "#012456",
+ ".pt": "#0060ac",
+ ".pug": "#a86454",
+ ".puml": "#fbbd16",
+ ".purs": "#1D222D",
+ ".pwn": "#dbb284",
+ ".pxd": "#fedf5b",
+ ".pxi": "#fedf5b",
+ ".py": "#3572A5",
+ ".py3": "#3572A5",
+ ".pyde": "#3572A5",
+ ".pyi": "#3572A5",
+ ".pyp": "#3572A5",
+ ".pyt": "#3572A5",
+ ".pytb": "#3572A5",
+ ".pyw": "#3572A5",
+ ".pyx": "#fedf5b",
+ ".q": "#0040cd",
+ ".qasm": "#AA70FF",
+ ".qbs": "#44a51c",
+ ".qhelp": "#0060ac",
+ ".ql": "#140f46",
+ ".qll": "#140f46",
+ ".qmd": "#198ce7",
+ ".qml": "#44a51c",
+ ".qs": "#00b841",
+ ".r": "#FFDAB3",
+ ".r2": "#358a5b",
+ ".r3": "#358a5b",
+ ".rabl": "#701516",
+ ".rake": "#701516",
+ ".raku": "#0000fb",
+ ".rakumod": "#0000fb",
+ ".raml": "#77d9fb",
+ ".razor": "#512be4",
+ ".rb": "#701516",
+ ".rbi": "#701516",
+ ".rbs": "#701516",
+ ".rbuild": "#701516",
+ ".rbw": "#701516",
+ ".rbx": "#701516",
+ ".rbxs": "#000080",
+ ".rchit": "#5686a5",
+ ".rd": "#198CE7",
+ ".rdf": "#0060ac",
+ ".rdoc": "#701516",
+ ".re": "#ff5847",
+ ".reb": "#358a5b",
+ ".rebol": "#358a5b",
+ ".red": "#f50000",
+ ".reds": "#f50000",
+ ".reek": "#cb171e",
+ ".reg": "#52d5ff",
+ ".regex": "#009a00",
+ ".regexp": "#009a00",
+ ".rego": "#7d9199",
+ ".rei": "#ff5847",
+ ".religo": "#ff5847",
+ ".res": "#0060ac",
+ ".rest": "#141414",
+ ".rest.txt": "#141414",
+ ".resx": "#0060ac",
+ ".rex": "#d90e09",
+ ".rexx": "#d90e09",
+ ".rg": "#cc0088",
+ ".rhtml": "#701516",
+ ".ring": "#2D54CB",
+ ".riot": "#A71E49",
+ ".rkt": "#3c5caa",
+ ".rktd": "#3c5caa",
+ ".rktl": "#3c5caa",
+ ".rl": "#9d5200",
+ ".rmd": "#198ce7",
+ ".rmiss": "#5686a5",
+ ".rnh": "#665a4e",
+ ".rno": "#ecdebe",
+ ".rnw": "#198ce7",
+ ".robot": "#00c0b5",
+ ".rockspec": "#000080",
+ ".roff": "#ecdebe",
+ ".ronn": "#083fa1",
+ ".rpgle": "#2BDE21",
+ ".rpy": "#ff7f7f",
+ ".rq": "#0C4597",
+ ".rs": "#0060ac",
+ ".rs.in": "#dea584",
+ ".rsc": "#DE3941",
+ ".rss": "#0060ac",
+ ".rst": "#141414",
+ ".rst.txt": "#141414",
+ ".rsx": "#198CE7",
+ ".ru": "#701516",
+ ".ruby": "#701516",
+ ".rviz": "#cb171e",
+ ".s": "#005daa",
+ ".sas": "#B34936",
+ ".sass": "#a53b70",
+ ".sats": "#1ac620",
+ ".sbt": "#c22d40",
+ ".sc": "#46390b",
+ ".scad": "#e5cd45",
+ ".scala": "#c22d40",
+ ".scaml": "#bd181a",
+ ".scd": "#46390b",
+ ".sce": "#ca0f21",
+ ".scenic": "#fdc700",
+ ".sch": "#0060ac",
+ ".sci": "#ca0f21",
+ ".scm": "#1e4aec",
+ ".sco": "#1a1a1a",
+ ".scpt": "#101F1F",
+ ".scrbl": "#3c5caa",
+ ".scss": "#c6538c",
+ ".scxml": "#0060ac",
+ ".sdc": "#e4cc98",
+ ".sed": "#64b970",
+ ".self": "#0579aa",
+ ".sexp": "#3fb68b",
+ ".sfproj": "#0060ac",
+ ".sfv": "#C9BFED",
+ ".sh": "#89e051",
+ ".sh.in": "#89e051",
+ ".shader": "#222c37",
+ ".shen": "#120F14",
+ ".shproj": "#0060ac",
+ ".sig": "#dc566d",
+ ".sj": "#ff0c5a",
+ ".sjs": "#f1e05a",
+ ".sl": "#007eff",
+ ".sld": "#1e4aec",
+ ".slim": "#2b2b2b",
+ ".sls": "#1e4aec",
+ ".sma": "#dbb284",
+ ".smithy": "#c44536",
+ ".smk": "#419179",
+ ".sml": "#dc566d",
+ ".snakefile": "#419179",
+ ".snap": "#15c213",
+ ".snip": "#199f4b",
+ ".snippet": "#199f4b",
+ ".snippets": "#199f4b",
+ ".sol": "#AA6746",
+ ".soy": "#0d948f",
+ ".sp": "#f69e1d",
+ ".sparql": "#0C4597",
+ ".spc": "#dad8d8",
+ ".spec": "#701516",
+ ".spin": "#7fa2a7",
+ ".sps": "#1e4aec",
+ ".sqf": "#3F3F3F",
+ ".sql": "#e38c00",
+ ".sqlrpgle": "#2BDE21",
+ ".sra": "#8f0f8d",
+ ".srdf": "#0060ac",
+ ".srt": "#9e0101",
+ ".sru": "#8f0f8d",
+ ".srw": "#8f0f8d",
+ ".ss": "#1e4aec",
+ ".ssjs": "#f1e05a",
+ ".sss": "#2fcc9f",
+ ".st": "#3fb34f",
+ ".stTheme": "#0060ac",
+ ".stan": "#b2011d",
+ ".star": "#76d275",
+ ".sthlp": "#1a5f91",
+ ".stl": "#373b5e",
+ ".story": "#5B2063",
+ ".storyboard": "#0060ac",
+ ".sty": "#3D6117",
+ ".styl": "#ff6347",
+ ".sublime-build": "#292929",
+ ".sublime-commands": "#292929",
+ ".sublime-completions": "#292929",
+ ".sublime-keymap": "#292929",
+ ".sublime-macro": "#292929",
+ ".sublime-menu": "#292929",
+ ".sublime-mousemap": "#292929",
+ ".sublime-project": "#292929",
+ ".sublime-settings": "#292929",
+ ".sublime-snippet": "#0060ac",
+ ".sublime-syntax": "#cb171e",
+ ".sublime-theme": "#292929",
+ ".sublime-workspace": "#292929",
+ ".sublime_metrics": "#292929",
+ ".sublime_session": "#292929",
+ ".sv": "#DAE1C2",
+ ".svelte": "#ff3e00",
+ ".svg": "#ff9900",
+ ".svh": "#DAE1C2",
+ ".sw": "#0060ac",
+ ".swift": "#F05138",
+ ".syntax": "#cb171e",
+ ".t": "#cf142b",
+ ".tab": "#e38c00",
+ ".tac": "#3572A5",
+ ".tag": "#2A6277",
+ ".talon": "#333333",
+ ".targets": "#0060ac",
+ ".tcc": "#f34b7d",
+ ".tcl": "#e4cc98",
+ ".tcl.in": "#e4cc98",
+ ".tesc": "#5686a5",
+ ".tese": "#5686a5",
+ ".tex": "#3D6117",
+ ".textile": "#ffe7ac",
+ ".tf": "#844FBA",
+ ".tfstate": "#292929",
+ ".tfstate.backup": "#292929",
+ ".tftpl": "#7b42bb",
+ ".tfvars": "#844FBA",
+ ".thor": "#701516",
+ ".thrift": "#D12127",
+ ".thy": "#FEFE00",
+ ".tla": "#4b0079",
+ ".tlv": "#C40023",
+ ".tm": "#e4cc98",
+ ".tmCommand": "#0060ac",
+ ".tmLanguage": "#0060ac",
+ ".tmPreferences": "#0060ac",
+ ".tmSnippet": "#0060ac",
+ ".tmTheme": "#0060ac",
+ ".tmac": "#ecdebe",
+ ".tml": "#0060ac",
+ ".tmux": "#89e051",
+ ".toc": "#f7e43f",
+ ".toit": "#c2c9fb",
+ ".toml": "#9c4221",
+ ".tool": "#89e051",
+ ".topojson": "#292929",
+ ".tpb": "#dad8d8",
+ ".tpl": "#f0c040",
+ ".tpp": "#f34b7d",
+ ".tps": "#dad8d8",
+ ".tres": "#355570",
+ ".trg": "#dad8d8",
+ ".trigger": "#89e051",
+ ".ts": "#0060ac",
+ ".tscn": "#355570",
+ ".tst": "#ca0f21",
+ ".tsv": "#237346",
+ ".tsx": "#0060ac",
+ ".tu": "#cf142b",
+ ".twig": "#c1d026",
+ ".txl": "#0178b8",
+ ".txt": "#199f4b",
+ ".txx": "#f34b7d",
+ ".typ": "#0060ac",
+ ".uc": "#a54c4d",
+ ".udf": "#e38c00",
+ ".udo": "#1a1a1a",
+ ".ui": "#0060ac",
+ ".unity": "#222c37",
+ ".uno": "#9933cc",
+ ".upc": "#4e3617",
+ ".ur": "#ccccee",
+ ".urdf": "#0060ac",
+ ".url": "#d1dbe0",
+ ".urs": "#ccccee",
+ ".ux": "#0060ac",
+ ".v": "#b2b7f8",
+ ".vala": "#a56de2",
+ ".vapi": "#a56de2",
+ ".vark": "#82937f",
+ ".vb": "#945db7",
+ ".vba": "#199f4b",
+ ".vbhtml": "#945db7",
+ ".vbproj": "#0060ac",
+ ".vbs": "#15dcdc",
+ ".vcl": "#148AA8",
+ ".vcxproj": "#0060ac",
+ ".vdf": "#f26025",
+ ".veo": "#b2b7f8",
+ ".vert": "#5686a5",
+ ".vh": "#DAE1C2",
+ ".vhd": "#adb2cb",
+ ".vhdl": "#adb2cb",
+ ".vhf": "#adb2cb",
+ ".vhi": "#adb2cb",
+ ".vho": "#adb2cb",
+ ".vhost": "#009639",
+ ".vhs": "#adb2cb",
+ ".vht": "#adb2cb",
+ ".vhw": "#adb2cb",
+ ".vim": "#199f4b",
+ ".vimrc": "#199f4b",
+ ".viw": "#e38c00",
+ ".vmb": "#199f4b",
+ ".volt": "#1F1F1F",
+ ".vrx": "#5686a5",
+ ".vs": "#5686a5",
+ ".vsh": "#5686a5",
+ ".vshader": "#5686a5",
+ ".vsixmanifest": "#0060ac",
+ ".vssettings": "#0060ac",
+ ".vstemplate": "#0060ac",
+ ".vtl": "#507cff",
+ ".vue": "#41b883",
+ ".vw": "#dad8d8",
+ ".vxml": "#0060ac",
+ ".vy": "#2980b9",
+ ".w": "#5ce600",
+ ".wast": "#04133b",
+ ".wat": "#04133b",
+ ".watchr": "#701516",
+ ".wdl": "#42f1f4",
+ ".webapp": "#292929",
+ ".webmanifest": "#292929",
+ ".wgsl": "#1a5e9a",
+ ".whiley": "#d5c397",
+ ".wiki": "#fc5757",
+ ".wikitext": "#fc5757",
+ ".wisp": "#7582D1",
+ ".wit": "#6250e7",
+ ".wixproj": "#0060ac",
+ ".wl": "#dd1100",
+ ".wlk": "#a23738",
+ ".wlt": "#dd1100",
+ ".wlua": "#000080",
+ ".workbook": "#083fa1",
+ ".workflow": "#0060ac",
+ ".wren": "#383838",
+ ".ws": "#ff0000",
+ ".wsdl": "#0060ac",
+ ".wsf": "#0060ac",
+ ".wsgi": "#3572A5",
+ ".wxi": "#0060ac",
+ ".wxl": "#0060ac",
+ ".wxs": "#0060ac",
+ ".x": "#aace60",
+ ".x10": "#4B6BEF",
+ ".x3d": "#0060ac",
+ ".x68": "#005daa",
+ ".xacro": "#0060ac",
+ ".xaml": "#0060ac",
+ ".xc": "#99DA07",
+ ".xdc": "#e4cc98",
+ ".xht": "#e34c26",
+ ".xhtml": "#e34c26",
+ ".xib": "#0060ac",
+ ".xlf": "#0060ac",
+ ".xliff": "#0060ac",
+ ".xmi": "#0060ac",
+ ".xml": "#0060ac",
+ ".xml.dist": "#0060ac",
+ ".xmp": "#0060ac",
+ ".xojo_code": "#81bd41",
+ ".xojo_menu": "#81bd41",
+ ".xojo_report": "#81bd41",
+ ".xojo_script": "#81bd41",
+ ".xojo_toolbar": "#81bd41",
+ ".xojo_window": "#81bd41",
+ ".xproj": "#0060ac",
+ ".xpy": "#3572A5",
+ ".xq": "#5232e7",
+ ".xql": "#5232e7",
+ ".xqm": "#5232e7",
+ ".xquery": "#5232e7",
+ ".xqy": "#5232e7",
+ ".xrl": "#B83998",
+ ".xsd": "#0060ac",
+ ".xsh": "#285EEF",
+ ".xsjs": "#f1e05a",
+ ".xsjslib": "#f1e05a",
+ ".xsl": "#EB8CEB",
+ ".xslt": "#EB8CEB",
+ ".xspec": "#0060ac",
+ ".xtend": "#24255d",
+ ".xul": "#0060ac",
+ ".xzap": "#0d665e",
+ ".y": "#4B6C4B",
+ ".yacc": "#4B6C4B",
+ ".yaml": "#cb171e",
+ ".yaml-tmlanguage": "#cb171e",
+ ".yaml.sed": "#cb171e",
+ ".yap": "#74283c",
+ ".yar": "#220000",
+ ".yara": "#220000",
+ ".yasnippet": "#32AB90",
+ ".yml": "#cb171e",
+ ".yml.mysql": "#cb171e",
+ ".yrl": "#B83998",
+ ".yul": "#794932",
+ ".yy": "#4B6C4B",
+ ".yyp": "#292929",
+ ".zap": "#0d665e",
+ ".zcml": "#0060ac",
+ ".zep": "#118f9e",
+ ".zig": "#ec915c",
+ ".zil": "#dc75e5",
+ ".zimpl": "#d67711",
+ ".zmpl": "#d67711",
+ ".zpl": "#d67711",
+ ".zs": "#00BCD1",
+ ".zsh": "#89e051",
+ ".zsh-theme": "#89e051"
+ }
+ },
+ "icons": {
+ "ascii": {
+ "default_icon": "●",
+ "ext_exact": {},
+ "folder": {
+ "closed": "▶",
+ "open": "▼"
+ },
+ "link": {
+ "broken": "-/->",
+ "normal": "->"
+ },
+ "name_exact": {},
+ "name_glob": {},
+ "status": {
+ "active": ">",
+ "inactive": " ",
+ "not_selected": " ",
+ "selected": "*"
+ }
+ },
+ "ascii_hollow": {
+ "default_icon": "○",
+ "ext_exact": {},
+ "folder": {
+ "closed": "▷",
+ "open": "▽"
+ },
+ "link": {
+ "broken": "-/->",
+ "normal": "->"
+ },
+ "name_exact": {},
+ "name_glob": {},
+ "status": {
+ "active": ">",
+ "inactive": " ",
+ "not_selected": " ",
+ "selected": "*"
+ }
+ },
+ "devicons": {
+ "default_icon": "",
+ "ext_exact": {
+ ".ai": "",
+ ".awk": "",
+ ".bash": "",
+ ".bat": "",
+ ".bmp": "",
+ ".c": "",
+ ".c++": "",
+ ".cc": "",
+ ".clj": "",
+ ".cljc": "",
+ ".cljs": "",
+ ".coffee": "",
+ ".conf": "",
+ ".cp": "",
+ ".cpp": "",
+ ".cs": "",
+ ".csh": "",
+ ".css": "",
+ ".cxx": "",
+ ".d": "",
+ ".dart": "",
+ ".db": "",
+ ".diff": "",
+ ".dump": "",
+ ".edn": "",
+ ".eex": "",
+ ".ejs": "",
+ ".elm": "",
+ ".erl": "",
+ ".ex": "",
+ ".exs": "",
+ ".f#": "",
+ ".fish": "",
+ ".fs": "",
+ ".fsi": "",
+ ".fsscript": "",
+ ".fsx": "",
+ ".gemspec": "",
+ ".gif": "",
+ ".go": "",
+ ".h": "",
+ ".haml": "",
+ ".hbs": "",
+ ".heex": "",
+ ".hh": "",
+ ".hpp": "",
+ ".hrl": "",
+ ".hs": "",
+ ".htm": "",
+ ".html": "",
+ ".hxx": "",
+ ".ico": "",
+ ".ini": "",
+ ".java": "",
+ ".jl": "",
+ ".jpeg": "",
+ ".jpg": "",
+ ".js": "",
+ ".json": "",
+ ".jsx": "",
+ ".ksh": "",
+ ".leex": "",
+ ".less": "",
+ ".lhs": "",
+ ".lua": "",
+ ".markdown": "",
+ ".md": "",
+ ".mdx": "",
+ ".mjs": "",
+ ".mk": "",
+ ".ml": "λ",
+ ".mli": "λ",
+ ".mustache": "",
+ ".nix": "",
+ ".pem": "",
+ ".php": "",
+ ".pl": "",
+ ".pm": "",
+ ".png": "",
+ ".pp": "",
+ ".ps1": "",
+ ".psb": "",
+ ".psd": "",
+ ".py": "",
+ ".pyc": "",
+ ".pyd": "",
+ ".pyo": "",
+ ".r": "ﳒ",
+ ".rake": "",
+ ".rb": "",
+ ".rlib": "",
+ ".rmd": "",
+ ".rproj": "鉶",
+ ".rs": "",
+ ".rss": "",
+ ".sass": "",
+ ".scala": "",
+ ".scss": "",
+ ".sh": "",
+ ".slim": "",
+ ".sln": "",
+ ".sol": "ﲹ",
+ ".sql": "",
+ ".styl": "",
+ ".suo": "",
+ ".swift": "",
+ ".t": "",
+ ".tex": "ﭨ",
+ ".toml": "",
+ ".ts": "",
+ ".tsx": "",
+ ".twig": "",
+ ".vim": "",
+ ".vue": "﵂",
+ ".webmanifest": "",
+ ".webp": "",
+ ".xcplayground": "",
+ ".xul": "",
+ ".yaml": "",
+ ".yml": "",
+ ".zsh": ""
+ },
+ "folder": {
+ "closed": "",
+ "open": ""
+ },
+ "link": {
+ "broken": "",
+ "normal": ""
+ },
+ "name_exact": {
+ ".bashprofile": "",
+ ".bashrc": "",
+ ".ds_store": "",
+ ".gitattributes": "",
+ ".gitconfig": "",
+ ".gitignore": "",
+ ".gitlab-ci.yml": "",
+ ".gvimrc": "",
+ ".vimrc": "",
+ ".zprofile": "",
+ ".zshenv": "",
+ ".zshrc": "",
+ "_gvimrc": "",
+ "_vimrc": "",
+ "cmakelists.txt": "",
+ "config.ru": "",
+ "docker-compose.yml": "",
+ "dockerfile": "",
+ "dropbox": "",
+ "exact-match-case-sensitive-1.txt": "1",
+ "exact-match-case-sensitive-2": "2",
+ "favicon.ico": "",
+ "gemfile": "",
+ "gruntfile.coffee": "",
+ "gruntfile.js": "",
+ "gruntfile.ls": "",
+ "gulpfile.coffee": "",
+ "gulpfile.js": "",
+ "gulpfile.ls": "",
+ "license": "",
+ "makefile": "",
+ "mix.lock": "",
+ "node_modules": "",
+ "procfile": "",
+ "rakefile": "",
+ "react.jsx": "",
+ "robots.txt": "ﮧ"
+ },
+ "name_glob": {
+ ".*angular.*.js": "",
+ ".*backbone.*.js": "",
+ ".*jquery.*.js": "",
+ ".*materialize.*.css": "",
+ ".*materialize.*.js": "",
+ ".*mootools.*.js": "",
+ ".*require.*.js": "",
+ ".*vimrc.*": "",
+ "Vagrantfile": ""
+ },
+ "status": {
+ "active": "▶",
+ "inactive": " ",
+ "not_selected": " ",
+ "selected": "✸"
+ }
+ },
+ "emoji": {
+ "default_icon": "📄",
+ "ext_exact": {
+ ".3ds": "🦖",
+ ".5vw": "🔬",
+ ".60": "🦋",
+ ".7z": "📦",
+ ".a80": "🧩",
+ ".aar": "📦",
+ ".acp": "🔬",
+ ".ahk": "🔨",
+ ".ai": "🎨",
+ ".alda": "🎶",
+ ".ani": "🦖",
+ ".apc": "🔬",
+ ".apk": "📦",
+ ".arb": "🔶",
+ ".as": "👼🏻",
+ ".asm": "🧩",
+ ".asta": "🔀",
+ ".astro": "🔶",
+ ".atc": "🔬",
+ ".atom": "💢",
+ ".avi": "🎞 ",
+ ".axml": "💢",
+ ".bat": "🦇",
+ ".bb": "🐚",
+ ".beam": "🔟",
+ ".bf": "🥩",
+ ".bfr": "🔬",
+ ".bib": "📜",
+ ".bin": "🔟",
+ ".blend": "🦖",
+ ".blob": "🔟",
+ ".bmp": "🎨",
+ ".bpg": "🎨",
+ ".bsdl": "🅱️ ",
+ ".bsl": "🐲",
+ ".c": "🐮",
+ ".cap": "🔬",
+ ".carbon": "🐮",
+ ".carp": "🎏",
+ ".cbl": "⚙️ ",
+ ".cer": "🔑",
+ ".cff": "📜",
+ ".cfg": "🔨",
+ ".chs": "🦥",
+ ".cjs": "🔶",
+ ".class": "🔟",
+ ".clj": "🦚",
+ ".cmd": "🦇",
+ ".cmi": "🔟",
+ ".coffee": "☕️",
+ ".conf": "🔨",
+ ".config": "🔨",
+ ".cpp": "🐮",
+ ".cql": "🎲",
+ ".cr": "💎",
+ ".crt": "🔑",
+ ".cs": "☪️ ",
+ ".cshtml": "☪️ ",
+ ".csproj": "🔨",
+ ".css": "🌸",
+ ".csv": "📊",
+ ".csx": "☪️ ",
+ ".cu": "🦖",
+ ".cuh": "🦖",
+ ".d": "🆔",
+ ".dae": "🦖",
+ ".dart": "🎯",
+ ".dat": "🔟",
+ ".data": "🔟",
+ ".db": "🎲",
+ ".dds": "🎨",
+ ".deb": "📦",
+ ".dib": "📝",
+ ".diff": "💊",
+ ".dll": "🔟",
+ ".dmg": "📦",
+ ".doc": "📘",
+ ".docx": "📘",
+ ".dpk": "🥏",
+ ".dproj": "🥏",
+ ".drc": "🎞 ",
+ ".drcs": "🎞 ",
+ ".dtd": "💢",
+ ".duel": "⚔️ ",
+ ".dump": "💣",
+ ".dxf": "🦖",
+ ".dylib": "🔟",
+ ".ear": "📦",
+ ".ebnf": "🐲",
+ ".eex": "💧",
+ ".elm": "🔰",
+ ".elmi": "🔟",
+ ".elmo": "🔟",
+ ".enc": "🔬",
+ ".eot": "🀄️",
+ ".epp": "👻",
+ ".epub": "📙",
+ ".erb": "🔻",
+ ".erf": "🔬",
+ ".erl": "📡",
+ ".erm": "💢",
+ ".erwin": "🎲",
+ ".etlua": "🌏",
+ ".ex": "💧",
+ ".exe": "🚀",
+ ".exs": "💧",
+ ".ez": "📦",
+ ".fbx": "🦖",
+ ".fdc": "🔬",
+ ".fish": "🐚",
+ ".flr": "🎆",
+ ".fnl": "🌱",
+ ".frxml": "💢",
+ ".fs": "🔷",
+ ".fsi": "🔷",
+ ".fsl": "🔷",
+ ".fsproj": "🔨",
+ ".fsx": "🔷",
+ ".fsy": "🔷",
+ ".functions": "🐚",
+ ".fxml": "💢",
+ ".gdb": "🐞",
+ ".gif": "🎨",
+ ".gift": "📝",
+ ".git": "🐙",
+ ".glb": "🦖",
+ ".gleam": "✨",
+ ".glsl": "🦖",
+ ".gltf": "🦖",
+ ".go": "🌰",
+ ".gql": "🏀",
+ ".gr": "🌾",
+ ".gradle": "🐘",
+ ".graphql": "🏀",
+ ".graphqls": "🏀",
+ ".gravity": "🔵",
+ ".groovy": "🌟",
+ ".gvdesign": "🔀",
+ ".gz": "📦",
+ ".gzip": "📦",
+ ".h": "🧩",
+ ".hbs": "🈴",
+ ".hdr": "🎨",
+ ".heex": "🌏",
+ ".hive": "🔟",
+ ".hs": "🦥",
+ ".hs-boot": "🦥",
+ ".hsc": "🦥",
+ ".hsig": "🦥",
+ ".hss": "🌸",
+ ".htm": "🌏",
+ ".html": "🌏",
+ ".http": "🌐",
+ ".hvm": "🦥",
+ ".hx": "🏀",
+ ".icns": "🎨",
+ ".ico": "🎨",
+ ".ics": "⏳",
+ ".idl": "🧩",
+ ".imba": "🔶",
+ ".iml": "🔨",
+ ".inc": "🧩",
+ ".info": "📜",
+ ".ini": "🔨",
+ ".ino": "📟",
+ ".ipa": "📦",
+ ".ipfix": "🔬",
+ ".ipynb": "📝",
+ ".iso": "💿",
+ ".jade": "🈴",
+ ".jar": "📦",
+ ".jasper": "💹",
+ ".java": "☕️",
+ ".jenkinsfile": "🎩",
+ ".jks": "🔑",
+ ".jl": "🍡",
+ ".jmx": "💢",
+ ".jnlp": "💢",
+ ".jpeg": "🎨",
+ ".jpg": "🎨",
+ ".jrxml": "💢",
+ ".js": "🔶",
+ ".json": "🔶",
+ ".jsx": "🐟",
+ ".jws": "🔨",
+ ".jxl": "🎨",
+ ".key": "🔑",
+ ".kind": "🔶",
+ ".kind2": "🔶",
+ ".kt": "🗼",
+ ".kts": "🗼",
+ ".latex": "📜",
+ ".lc": "🦥",
+ ".lcap": "🔬",
+ ".leex": "💧",
+ ".less": "🌸",
+ ".lhs": "🦥",
+ ".lis": "🧩",
+ ".list": "🧩",
+ ".lock": "🔐",
+ ".log": "🦎",
+ ".lua": "🌕",
+ ".lz4": "📦",
+ ".m": "🐄",
+ ".mak": "🐃",
+ ".map": "🌐",
+ ".markdown": "⬇️ ",
+ ".marko": "⬇️ ",
+ ".md": "⬇️ ",
+ ".mdj": "🔀",
+ ".mdl": "🦖",
+ ".mint": "🍃",
+ ".mjs": "🔶",
+ ".mk": "🐃",
+ ".mkd": "⬇️ ",
+ ".mkv": "🎞 ",
+ ".ml": "🐫",
+ ".mli": "🧩",
+ ".mlt": "🎞 ",
+ ".mm": "🐄",
+ ".mo": "🗽",
+ ".mod": "🔨",
+ ".moon": "🌕",
+ ".mov": "🎞 ",
+ ".mp3": "🎶",
+ ".mp4": "🎞 ",
+ ".mpeg": "🎞 ",
+ ".mpg": "🎞 ",
+ ".mplog": "🔬",
+ ".mq4": "💰",
+ ".mq5": "💰",
+ ".mqlh": "🧩",
+ ".nelua": "🌕",
+ ".nib": "🧩",
+ ".nim": "👑",
+ ".norg": "🦄",
+ ".nupkg": "📦",
+ ".nuspec": "💢",
+ ".obj": "🦖",
+ ".odin": "🔵",
+ ".odp": "🎭",
+ ".ods": "📊",
+ ".odt": "📘",
+ ".ogg": "🎶",
+ ".org": "🦄",
+ ".os": "🐲",
+ ".out": "🔬",
+ ".ovpn": "🔑",
+ ".pages": "📘",
+ ".parquet": "🟫",
+ ".pas": "🌡 ",
+ ".pcap": "🔬",
+ ".pcapng": "🔬",
+ ".pdb": "🔟",
+ ".pde": "📟",
+ ".pdf": "🅿️ ",
+ ".pem": "🔑",
+ ".pepk": "🔑",
+ ".pfx": "🔑",
+ ".pgsql": "🎲",
+ ".php": "🐘",
+ ".pid": "🔟",
+ ".pkg": "📦",
+ ".pkl": "🔨",
+ ".pklg": "🔬",
+ ".pkt": "🔬",
+ ".pl": "🍐",
+ ".plist": "💢",
+ ".png": "🎨",
+ ".po": "🗽",
+ ".pony": "🐴",
+ ".pot": "🗽",
+ ".pp": "👻",
+ ".ppk": "🔑",
+ ".ppt": "🎭",
+ ".pptx": "🎭",
+ ".prefs": "🔨",
+ ".prisma": "🔷",
+ ".pro": "🔨",
+ ".profile": "👤",
+ ".properties": "🔨",
+ ".props": "💢",
+ ".proto": "⚛️ ",
+ ".ps1": "🐚",
+ ".psb": "🎨",
+ ".psd": "🎨",
+ ".psl": "🖌 ",
+ ".pug": "🐶",
+ ".puml": "🔀",
+ ".py": "🐍",
+ ".pyc": "🐍",
+ ".pyd": "🐍",
+ ".pyo": "🐍",
+ ".python": "🐍",
+ ".r": "🧮",
+ ".rar": "📦",
+ ".razor": "🟣",
+ ".rb": "🔻",
+ ".rc": "🥏",
+ ".re": "🐫",
+ ".reality": "🦖",
+ ".reg": "🔐",
+ ".rei": "🧩",
+ ".res": "🐫",
+ ".resi": "🧩",
+ ".rest": "🌐",
+ ".resx": "💢",
+ ".rf5": "🔬",
+ ".rh": "🐚",
+ ".rlib": "🔟",
+ ".rmd": "🎭",
+ ".rock": "🌕",
+ ".rockspec": "🌕",
+ ".rpm": "📦",
+ ".rproj": "🔨",
+ ".rs": "🦀",
+ ".rss": "💢",
+ ".rst": "🍇",
+ ".ru": "🔻",
+ ".s": "🧩",
+ ".sar": "📦",
+ ".sass": "👓",
+ ".sbt": "🔨",
+ ".sc": "💈",
+ ".scala": "💈",
+ ".scd": "🎶",
+ ".scm": "🌻",
+ ".scss": "🌸",
+ ".sfb": "🦖",
+ ".sfz": "🎶",
+ ".sh": "🐚",
+ ".slime": "🍨",
+ ".sln": "🔨",
+ ".snap": "📦",
+ ".snoop": "🔬",
+ ".so": "🔟",
+ ".socket": "🌐",
+ ".sol": "🐲",
+ ".spi": "🌀",
+ ".spiproj": "🌀",
+ ".spir": "🌀",
+ ".sql": "🎲",
+ ".sqlite": "🎲",
+ ".storyboard": "💢",
+ ".strings": "💢",
+ ".styl": "🌸",
+ ".suo": "☪️ ",
+ ".svelte": "💃🏻",
+ ".svg": "🎨",
+ ".swift": "🐦",
+ ".swo": "⏳",
+ ".swp": "⏳",
+ ".syc": "🔬",
+ ".t": "🌷",
+ ".tar": "📦",
+ ".tera": "🌏",
+ ".tflite": "🤖",
+ ".tga": "🎨",
+ ".tgz": "📦",
+ ".tif": "🎨",
+ ".tiff": "🀄️",
+ ".tlb": "🧩",
+ ".toml": "🔨",
+ ".tpc": "🔬",
+ ".tpl": "🈴",
+ ".tr1": "🔬",
+ ".trace": "🔬",
+ ".trc": "🔬",
+ ".ts": "🔷",
+ ".tsx": "🔷",
+ ".ttf": "🀄️",
+ ".tup": "🐃",
+ ".txt": "📝",
+ ".uml": "🔀",
+ ".usd": "🦖",
+ ".usda": "🦖",
+ ".usdc": "🦖",
+ ".usdz": "🦖",
+ ".userprefs": "🔨",
+ ".v": "✅",
+ ".val": "✔️",
+ ".vbs": "🌀",
+ ".vcxproj": "💢",
+ ".vdf": "🔨",
+ ".vgb": "🔨",
+ ".vh": "🧩",
+ ".vim": "🍃",
+ ".vimrc": "🍃",
+ ".vimspec": "🍃",
+ ".vmb": "📦",
+ ".vpp": "🔀",
+ ".vrx": "🦖",
+ ".vsh": "✅",
+ ".vue": "🌲",
+ ".vv": "✅",
+ ".vwr": "🔬",
+ ".wad": "🔟",
+ ".war": "📦",
+ ".wasm": "🔟",
+ ".wast": "🔟",
+ ".wat": "🔟",
+ ".wav": "🎶",
+ ".wbmp": "🎨",
+ ".webp": "🎨",
+ ".woff": "🀄️",
+ ".wpc": "🔬",
+ ".wpz": "🔬",
+ ".wscene": "🎞 ",
+ ".wsdl": "💢",
+ ".xaml": "💢",
+ ".xcf": "🎨",
+ ".xdata": "💢",
+ ".xhtml": "🌏",
+ ".xib": "💢",
+ ".xjb": "💢",
+ ".xlf": "💢",
+ ".xls": "📊",
+ ".xlsx": "📊",
+ ".xml": "💢",
+ ".xsd": "💢",
+ ".xsl": "💢",
+ ".xz": "📦",
+ ".yaml": "🎴",
+ ".yml": "🎴",
+ ".z80": "🧩",
+ ".zig": "⚡️",
+ ".zip": "📦",
+ ".zsh": "🐚",
+ ".zst": "📦"
+ },
+ "folder": {
+ "closed": "📁",
+ "open": "📂"
+ },
+ "link": {
+ "broken": "",
+ "normal": ""
+ },
+ "name_exact": {
+ ".bashprofile": "🐚",
+ ".bashrc": "🐚",
+ ".cabal": "🔨",
+ ".dart_tool": "🔨",
+ ".dockerignore": "🐳",
+ ".ds_store": "📌",
+ ".editorconfig": "🐭",
+ ".env": "🏕 ",
+ ".envrc": "🔨",
+ ".git": "🐙",
+ ".gitattributes": "🐙",
+ ".gitconfig": "🐙",
+ ".gitignore": "🐙",
+ ".gitlab-ci.yml": "🎴",
+ ".gqlconfig": "🔨",
+ ".hackernews": "📰",
+ ".idea": "🔨",
+ ".merlin": "🧙",
+ ".svn": "🐢",
+ ".tool-versions": "🔨",
+ ".vimspector.json": "🐞",
+ ".vscode": "🆚",
+ ".zprofile": "🔨",
+ ".zshenv": "🔨",
+ ".zshrc": "🐚",
+ "MANIFEST.MF": "🔨",
+ "android": "🤖",
+ "cabal.config": "🔨",
+ "cabal.project": "🔨",
+ "changelog.md": "🍁",
+ "config": "🔨",
+ "deps": "🚼",
+ "docker-compose-single-broker.yml": "🐳",
+ "docker-compose-swarm.yml": "🐳",
+ "docker-compose.yml": "🐳",
+ "dockerfile": "🐳",
+ "dropbox": "📪",
+ "elm-package.json": "🔰",
+ "elm.json": "🔰",
+ "favicon.ico": "🎨",
+ "gemfile": "🔨",
+ "gemfile.lock": "🔐",
+ "gradlew": "🐚",
+ "gruntfile.coffee": "🔨",
+ "gruntfile.js": "🔶",
+ "gruntfile.ls": "🔶",
+ "guardfile": "💂",
+ "gulpfile.coffee": "🔨",
+ "gulpfile.js": "🔶",
+ "gulpfile.ls": "🔶",
+ "ios": "📱",
+ "jenkinsfile": "🎩",
+ "justfile": "🔨",
+ "lib": "📚",
+ "license": "📜",
+ "license.txt": "📜",
+ "makefile": "🐃",
+ "mix.lock": "🔐",
+ "node_modules": "🔶",
+ "paket.dependencies": "🔨",
+ "paket.references": "🔨",
+ "podfile": "🔨",
+ "pom.xml": "🔨",
+ "procfile": "🔨",
+ "rakefile": "🔨",
+ "react.jsx": "💢",
+ "routes": "🔨",
+ "spec.ts": "🔷",
+ "tags": "📌",
+ "test": "🧪",
+ "tests": "🧪",
+ "todo": "🚧",
+ "todo.md": "🚧",
+ "yarn.lock": "🐈"
+ },
+ "name_glob": {
+ ".*.UnitDoc": "🥏",
+ ".*.config.js": "🔨",
+ ".*.config.ts": "🔨",
+ ".*.csproj.user": "💢",
+ ".*.css.map": "🌸",
+ ".*.db-journal": "🎲",
+ ".*.dockerfile": "🐳",
+ ".*.gr.wasm": "🌾",
+ ".*.js.map": "🔶",
+ ".*.mobileprovision": "📱",
+ ".*.podspec": "🔨",
+ ".*.xaml": "🔨",
+ ".*.xaml.cs": "🔨",
+ ".*LICENSE.*": "📜",
+ ".*angular.*.js": "🔶",
+ ".*backbone.*.js": "🔶",
+ ".*jquery.*.js": "🔶",
+ ".*materialize.*.css": "🔶",
+ ".*materialize.*.js": "🔶",
+ ".*mootools.*.js": "🔶",
+ ".*require.*.js": "🔶",
+ ".*vcxproj.filters": "💢",
+ ".*vimrc.*": "🍃",
+ ".dropbox": "📪",
+ ".gitconfig": "🐙",
+ ".npmrc": "🔨",
+ "commit_editmsg": "🐙",
+ "dockerfile..*": "🐳"
+ },
+ "status": {
+ "active": "▶",
+ "inactive": " ",
+ "not_selected": " ",
+ "selected": "✸"
+ }
+ }
+ },
+ "ls_colours": {
+ "nord": "no=00:rs=0:fi=00:di=01;34:ln=36:mh=04;36:pi=04;01;36:so=04;33:do=04;01;36:bd=01;33:cd=33:or=31:mi=01;37;41:ex=01;36:su=01;04;37:sg=01;04;37:ca=01;37:tw=01;37;44:ow=01;04;34:st=04;37;44:*.7z=01;32:*.ace=01;32:*.alz=01;32:*.arc=01;32:*.arj=01;32:*.bz=01;32:*.bz2=01;32:*.cab=01;32:*.cpio=01;32:*.deb=01;32:*.dz=01;32:*.ear=01;32:*.gz=01;32:*.jar=01;32:*.lha=01;32:*.lrz=01;32:*.lz=01;32:*.lz4=01;32:*.lzh=01;32:*.lzma=01;32:*.lzo=01;32:*.rar=01;32:*.rpm=01;32:*.rz=01;32:*.sar=01;32:*.t7z=01;32:*.tar=01;32:*.taz=01;32:*.tbz=01;32:*.tbz2=01;32:*.tgz=01;32:*.tlz=01;32:*.txz=01;32:*.tz=01;32:*.tzo=01;32:*.tzst=01;32:*.war=01;32:*.xz=01;32:*.z=01;32:*.Z=01;32:*.zip=01;32:*.zoo=01;32:*.zst=01;32:*.aac=32:*.au=32:*.flac=32:*.m4a=32:*.mid=32:*.midi=32:*.mka=32:*.mp3=32:*.mpa=32:*.mpeg=32:*.mpg=32:*.ogg=32:*.opus=32:*.ra=32:*.wav=32:*.3des=01;35:*.aes=01;35:*.gpg=01;35:*.pgp=01;35:*.doc=32:*.docx=32:*.dot=32:*.odg=32:*.odp=32:*.ods=32:*.odt=32:*.otg=32:*.otp=32:*.ots=32:*.ott=32:*.pdf=32:*.ppt=32:*.pptx=32:*.xls=32:*.xlsx=32:*.app=01;36:*.bat=01;36:*.btm=01;36:*.cmd=01;36:*.com=01;36:*.exe=01;36:*.reg=01;36:*~=02;37:*.bak=02;37:*.BAK=02;37:*.log=02;37:*.log=02;37:*.old=02;37:*.OLD=02;37:*.orig=02;37:*.ORIG=02;37:*.swo=02;37:*.swp=02;37:*.bmp=32:*.cgm=32:*.dl=32:*.dvi=32:*.emf=32:*.eps=32:*.gif=32:*.jpeg=32:*.jpg=32:*.JPG=32:*.mng=32:*.pbm=32:*.pcx=32:*.pgm=32:*.png=32:*.PNG=32:*.ppm=32:*.pps=32:*.ppsx=32:*.ps=32:*.svg=32:*.svgz=32:*.tga=32:*.tif=32:*.tiff=32:*.xbm=32:*.xcf=32:*.xpm=32:*.xwd=32:*.xwd=32:*.yuv=32:*.anx=32:*.asf=32:*.avi=32:*.axv=32:*.flc=32:*.fli=32:*.flv=32:*.gl=32:*.m2v=32:*.m4v=32:*.mkv=32:*.mov=32:*.MOV=32:*.mp4=32:*.mpeg=32:*.mpg=32:*.nuv=32:*.ogm=32:*.ogv=32:*.ogx=32:*.qt=32:*.rm=32:*.rmvb=32:*.swf=32:*.vob=32:*.webm=32:*.wmv=32:",
+ "solarized_dark": "no=00:fi=00:di=34:ow=34;40:ln=35:pi=30;44:so=35;44:do=35;44:bd=33;44:cd=37;44:or=05;37;41:mi=05;37;41:ex=01;31:*.cmd=01;31:*.exe=01;31:*.com=01;31:*.bat=01;31:*.reg=01;31:*.app=01;31:*.txt=32:*.org=32:*.md=32:*.mkd=32:*.h=32:*.hpp=32:*.c=32:*.C=32:*.cc=32:*.cpp=32:*.cxx=32:*.objc=32:*.cl=32:*.sh=32:*.bash=32:*.csh=32:*.zsh=32:*.el=32:*.vim=32:*.java=32:*.pl=32:*.pm=32:*.py=32:*.rb=32:*.hs=32:*.php=32:*.htm=32:*.html=32:*.shtml=32:*.erb=32:*.haml=32:*.xml=32:*.rdf=32:*.css=32:*.sass=32:*.scss=32:*.less=32:*.js=32:*.coffee=32:*.man=32:*.0=32:*.1=32:*.2=32:*.3=32:*.4=32:*.5=32:*.6=32:*.7=32:*.8=32:*.9=32:*.l=32:*.n=32:*.p=32:*.pod=32:*.tex=32:*.go=32:*.sql=32:*.csv=32:*.sv=32:*.svh=32:*.v=32:*.vh=32:*.vhd=32:*.bmp=33:*.cgm=33:*.dl=33:*.dvi=33:*.emf=33:*.eps=33:*.gif=33:*.jpeg=33:*.jpg=33:*.JPG=33:*.mng=33:*.pbm=33:*.pcx=33:*.pgm=33:*.png=33:*.PNG=33:*.ppm=33:*.pps=33:*.ppsx=33:*.ps=33:*.svg=33:*.svgz=33:*.tga=33:*.tif=33:*.tiff=33:*.xbm=33:*.xcf=33:*.xpm=33:*.xwd=33:*.xwd=33:*.yuv=33:*.nef=33:*.NEF=33:*.webp=33:*.heic=33:*.HEIC=33:*.avif=33:*.aac=33:*.au=33:*.flac=33:*.m4a=33:*.mid=33:*.midi=33:*.mka=33:*.mp3=33:*.mpa=33:*.mpeg=33:*.mpg=33:*.ogg=33:*.opus=33:*.ra=33:*.wav=33:*.anx=33:*.asf=33:*.avi=33:*.axv=33:*.flc=33:*.fli=33:*.flv=33:*.gl=33:*.m2v=33:*.m4v=33:*.mkv=33:*.mov=33:*.MOV=33:*.mp4=33:*.mp4v=33:*.mpeg=33:*.mpg=33:*.nuv=33:*.ogm=33:*.ogv=33:*.ogx=33:*.qt=33:*.rm=33:*.rmvb=33:*.swf=33:*.vob=33:*.webm=33:*.wmv=33:*.doc=31:*.docx=31:*.rtf=31:*.odt=31:*.dot=31:*.dotx=31:*.ott=31:*.xls=31:*.xlsx=31:*.ods=31:*.ots=31:*.ppt=31:*.pptx=31:*.odp=31:*.otp=31:*.fla=31:*.psd=31:*.pdf=31:*.7z=1;35:*.apk=1;35:*.arj=1;35:*.bin=1;35:*.bz=1;35:*.bz2=1;35:*.cab=1;35:*.deb=1;35:*.dmg=1;35:*.gem=1;35:*.gz=1;35:*.iso=1;35:*.jar=1;35:*.msi=1;35:*.rar=1;35:*.rpm=1;35:*.tar=1;35:*.tbz=1;35:*.tbz2=1;35:*.tgz=1;35:*.tx=1;35:*.war=1;35:*.xpi=1;35:*.xz=1;35:*.z=1;35:*.Z=1;35:*.zip=1;35:*.zst=1;35:*.ANSI-30-black=30:*.ANSI-01;30-brblack=01;30:*.ANSI-31-red=31:*.ANSI-01;31-brred=01;31:*.ANSI-32-green=32:*.ANSI-01;32-brgreen=01;32:*.ANSI-33-yellow=33:*.ANSI-01;33-bryellow=01;33:*.ANSI-34-blue=34:*.ANSI-01;34-brblue=01;34:*.ANSI-35-magenta=35:*.ANSI-01;35-brmagenta=01;35:*.ANSI-36-cyan=36:*.ANSI-01;36-brcyan=01;36:*.ANSI-37-white=37:*.ANSI-01;37-brwhite=01;37:*.log=01;32:*~=01;32:*#=01;32:*.bak=01;33:*.BAK=01;33:*.old=01;33:*.OLD=01;33:*.org_archive=01;33:*.off=01;33:*.OFF=01;33:*.dist=01;33:*.DIST=01;33:*.orig=01;33:*.ORIG=01;33:*.swp=01;33:*.swo=01;33:*.v=01;33:*.gpg=34:*.pgp=34:*.asc=34:*.3des=34:*.aes=34:*.enc=34:*.sqlite=34:",
+ "solarized_dark_256": "no=00;38;5;244:rs=0:di=00;38;5;33:ln=01;38;5;37:mh=00:pi=48;5;230;38;5;136;01:so=48;5;230;38;5;136;01:do=48;5;230;38;5;136;01:bd=48;5;230;38;5;244;01:cd=48;5;230;38;5;244;01:or=48;5;235;38;5;160:su=48;5;160;38;5;230:sg=48;5;136;38;5;230:ca=30;41:tw=48;5;64;38;5;230:ow=48;5;235;38;5;33:st=48;5;33;38;5;230:ex=01;38;5;64:*.tar=00;38;5;61:*.tgz=01;38;5;61:*.arj=01;38;5;61:*.taz=01;38;5;61:*.lzh=01;38;5;61:*.lzma=01;38;5;61:*.tlz=01;38;5;61:*.txz=01;38;5;61:*.zip=01;38;5;61:*.zst=01;38;5;61:*.z=01;38;5;61:*.Z=01;38;5;61:*.dz=01;38;5;61:*.gz=01;38;5;61:*.lz=01;38;5;61:*.xz=01;38;5;61:*.bz2=01;38;5;61:*.bz=01;38;5;61:*.tbz=01;38;5;61:*.tbz2=01;38;5;61:*.tz=01;38;5;61:*.deb=01;38;5;61:*.rpm=01;38;5;61:*.jar=01;38;5;61:*.rar=01;38;5;61:*.ace=01;38;5;61:*.zoo=01;38;5;61:*.cpio=01;38;5;61:*.7z=01;38;5;61:*.rz=01;38;5;61:*.apk=01;38;5;61:*.gem=01;38;5;61:*.jpg=00;38;5;136:*.JPG=00;38;5;136:*.jpeg=00;38;5;136:*.gif=00;38;5;136:*.bmp=00;38;5;136:*.pbm=00;38;5;136:*.pgm=00;38;5;136:*.ppm=00;38;5;136:*.tga=00;38;5;136:*.xbm=00;38;5;136:*.xpm=00;38;5;136:*.tif=00;38;5;136:*.tiff=00;38;5;136:*.png=00;38;5;136:*.PNG=00;38;5;136:*.svg=00;38;5;136:*.svgz=00;38;5;136:*.mng=00;38;5;136:*.pcx=00;38;5;136:*.dl=00;38;5;136:*.xcf=00;38;5;136:*.xwd=00;38;5;136:*.yuv=00;38;5;136:*.cgm=00;38;5;136:*.emf=00;38;5;136:*.eps=00;38;5;136:*.CR2=00;38;5;136:*.ico=00;38;5;136:*.nef=00;38;5;136:*.NEF=00;38;5;136:*.webp=00;38;5;136:*.heic=00;38;5;136:*.HEIC=00;38;5;136:*.avif=00;38;5;136:*.tex=01;38;5;245:*.rdf=01;38;5;245:*.owl=01;38;5;245:*.n3=01;38;5;245:*.ttl=01;38;5;245:*.nt=01;38;5;245:*.torrent=01;38;5;245:*.xml=01;38;5;245:*Makefile=01;38;5;245:*Rakefile=01;38;5;245:*Dockerfile=01;38;5;245:*build.xml=01;38;5;245:*rc=01;38;5;245:*1=01;38;5;245:*.nfo=01;38;5;245:*README=01;38;5;245:*README.txt=01;38;5;245:*readme.txt=01;38;5;245:*.md=01;38;5;245:*README.markdown=01;38;5;245:*.ini=01;38;5;245:*.yml=01;38;5;245:*.cfg=01;38;5;245:*.conf=01;38;5;245:*.h=01;38;5;245:*.hpp=01;38;5;245:*.c=01;38;5;245:*.cpp=01;38;5;245:*.cxx=01;38;5;245:*.cc=01;38;5;245:*.objc=01;38;5;245:*.sqlite=01;38;5;245:*.go=01;38;5;245:*.sql=01;38;5;245:*.csv=01;38;5;245:*.log=00;38;5;240:*.bak=00;38;5;240:*.aux=00;38;5;240:*.lof=00;38;5;240:*.lol=00;38;5;240:*.lot=00;38;5;240:*.out=00;38;5;240:*.toc=00;38;5;240:*.bbl=00;38;5;240:*.blg=00;38;5;240:*~=00;38;5;240:*#=00;38;5;240:*.part=00;38;5;240:*.incomplete=00;38;5;240:*.swp=00;38;5;240:*.tmp=00;38;5;240:*.temp=00;38;5;240:*.o=00;38;5;240:*.pyc=00;38;5;240:*.class=00;38;5;240:*.cache=00;38;5;240:*.aac=00;38;5;166:*.au=00;38;5;166:*.flac=00;38;5;166:*.mid=00;38;5;166:*.midi=00;38;5;166:*.mka=00;38;5;166:*.mp3=00;38;5;166:*.mpc=00;38;5;166:*.ogg=00;38;5;166:*.opus=00;38;5;166:*.ra=00;38;5;166:*.wav=00;38;5;166:*.m4a=00;38;5;166:*.axa=00;38;5;166:*.oga=00;38;5;166:*.spx=00;38;5;166:*.xspf=00;38;5;166:*.mov=01;38;5;166:*.MOV=01;38;5;166:*.mpg=01;38;5;166:*.mpeg=01;38;5;166:*.m2v=01;38;5;166:*.mkv=01;38;5;166:*.ogm=01;38;5;166:*.mp4=01;38;5;166:*.m4v=01;38;5;166:*.mp4v=01;38;5;166:*.vob=01;38;5;166:*.qt=01;38;5;166:*.nuv=01;38;5;166:*.wmv=01;38;5;166:*.asf=01;38;5;166:*.rm=01;38;5;166:*.rmvb=01;38;5;166:*.flc=01;38;5;166:*.avi=01;38;5;166:*.fli=01;38;5;166:*.flv=01;38;5;166:*.gl=01;38;5;166:*.m2ts=01;38;5;166:*.divx=01;38;5;166:*.webm=01;38;5;166:*.axv=01;38;5;166:*.anx=01;38;5;166:*.ogv=01;38;5;166:*.ogx=01;38;5;166:",
+ "solarized_light": "no=00:fi=00:di=36:ow=34;47:ln=35:pi=30;44:so=35;44:do=35;44:bd=33;44:cd=37;44:or=05;37;41:mi=05;37;41:ex=01;31:*.cmd=01;31:*.exe=01;31:*.com=01;31:*.bat=01;31:*.reg=01;31:*.app=01;31:*.txt=32:*.org=32:*.md=32:*.mkd=32:*.h=32:*.hpp=32:*.c=32:*.C=32:*.cc=32:*.cpp=32:*.cxx=32:*.objc=32:*.cl=32:*.sh=32:*.bash=32:*.csh=32:*.zsh=32:*.el=32:*.vim=32:*.java=32:*.pl=32:*.pm=32:*.py=32:*.rb=32:*.hs=32:*.php=32:*.htm=32:*.html=32:*.shtml=32:*.erb=32:*.haml=32:*.xml=32:*.rdf=32:*.css=32:*.sass=32:*.scss=32:*.less=32:*.js=32:*.coffee=32:*.man=32:*.0=32:*.1=32:*.2=32:*.3=32:*.4=32:*.5=32:*.6=32:*.7=32:*.8=32:*.9=32:*.l=32:*.n=32:*.p=32:*.pod=32:*.tex=32:*.go=32:*.sql=32:*.csv=32:*.sv=32:*.svh=32:*.v=32:*.vh=32:*.vhd=32:*.bmp=33:*.cgm=33:*.dl=33:*.dvi=33:*.emf=33:*.eps=33:*.gif=33:*.jpeg=33:*.jpg=33:*.JPG=33:*.mng=33:*.pbm=33:*.pcx=33:*.pgm=33:*.png=33:*.PNG=33:*.ppm=33:*.pps=33:*.ppsx=33:*.ps=33:*.svg=33:*.svgz=33:*.tga=33:*.tif=33:*.tiff=33:*.xbm=33:*.xcf=33:*.xpm=33:*.xwd=33:*.xwd=33:*.yuv=33:*.nef=33:*.NEF=33:*.webp=33:*.heic=33:*.HEIC=33:*.avif=33:*.aac=33:*.au=33:*.flac=33:*.m4a=33:*.mid=33:*.midi=33:*.mka=33:*.mp3=33:*.mpa=33:*.mpeg=33:*.mpg=33:*.ogg=33:*.opus=33:*.ra=33:*.wav=33:*.anx=33:*.asf=33:*.avi=33:*.axv=33:*.flc=33:*.fli=33:*.flv=33:*.gl=33:*.m2v=33:*.m4v=33:*.mkv=33:*.mov=33:*.MOV=33:*.mp4=33:*.mp4v=33:*.mpeg=33:*.mpg=33:*.nuv=33:*.ogm=33:*.ogv=33:*.ogx=33:*.qt=33:*.rm=33:*.rmvb=33:*.swf=33:*.vob=33:*.webm=33:*.wmv=33:*.doc=31:*.docx=31:*.rtf=31:*.odt=31:*.dot=31:*.dotx=31:*.ott=31:*.xls=31:*.xlsx=31:*.ods=31:*.ots=31:*.ppt=31:*.pptx=31:*.odp=31:*.otp=31:*.fla=31:*.psd=31:*.pdf=31:*.7z=1;35:*.apk=1;35:*.arj=1;35:*.bin=1;35:*.bz=1;35:*.bz2=1;35:*.cab=1;35:*.deb=1;35:*.dmg=1;35:*.gem=1;35:*.gz=1;35:*.iso=1;35:*.jar=1;35:*.msi=1;35:*.rar=1;35:*.rpm=1;35:*.tar=1;35:*.tbz=1;35:*.tbz2=1;35:*.tgz=1;35:*.tx=1;35:*.war=1;35:*.xpi=1;35:*.xz=1;35:*.z=1;35:*.Z=1;35:*.zip=1;35:*.zst=1;35:*.ANSI-30-black=30:*.ANSI-01;30-brblack=01;30:*.ANSI-31-red=31:*.ANSI-01;31-brred=01;31:*.ANSI-32-green=32:*.ANSI-01;32-brgreen=01;32:*.ANSI-33-yellow=33:*.ANSI-01;33-bryellow=01;33:*.ANSI-34-blue=34:*.ANSI-01;34-brblue=01;34:*.ANSI-35-magenta=35:*.ANSI-01;35-brmagenta=01;35:*.ANSI-36-cyan=36:*.ANSI-01;36-brcyan=01;36:*.ANSI-37-white=37:*.ANSI-01;37-brwhite=01;37:*.log=01;34:*~=01;34:*#=01;34:*.bak=01;36:*.BAK=01;36:*.old=01;36:*.OLD=01;36:*.org_archive=01;36:*.off=01;36:*.OFF=01;36:*.dist=01;36:*.DIST=01;36:*.orig=01;36:*.ORIG=01;36:*.swp=01;36:*.swo=01;36:*.v=01;36:*.gpg=34:*.pgp=34:*.asc=34:*.3des=34:*.aes=34:*.enc=34:*.sqlite=34:",
+ "solarized_universal": "no=00:fi=00:di=36:ln=35:pi=30;44:so=35;44:do=35;44:bd=33;44:cd=37;44:or=05;37;41:mi=05;37;41:ex=01;31:*.cmd=01;31:*.exe=01;31:*.com=01;31:*.bat=01;31:*.reg=01;31:*.app=01;31:*.txt=32:*.org=32:*.md=32:*.mkd=32:*.bib=32:*.h=32:*.hpp=32:*.c=32:*.C=32:*.cc=32:*.cpp=32:*.cxx=32:*.objc=32:*.cl=32:*.sh=32:*.bash=32:*.csh=32:*.zsh=32:*.el=32:*.vim=32:*.java=32:*.pl=32:*.pm=32:*.py=32:*.rb=32:*.hs=32:*.php=32:*.htm=32:*.html=32:*.shtml=32:*.erb=32:*.haml=32:*.xml=32:*.rdf=32:*.css=32:*.sass=32:*.scss=32:*.less=32:*.js=32:*.coffee=32:*.man=32:*.0=32:*.1=32:*.2=32:*.3=32:*.4=32:*.5=32:*.6=32:*.7=32:*.8=32:*.9=32:*.l=32:*.n=32:*.p=32:*.pod=32:*.tex=32:*.go=32:*.sql=32:*.csv=32:*.sv=32:*.svh=32:*.v=32:*.vh=32:*.vhd=32:*.bmp=33:*.cgm=33:*.dl=33:*.dvi=33:*.emf=33:*.eps=33:*.gif=33:*.jpeg=33:*.jpg=33:*.JPG=33:*.mng=33:*.pbm=33:*.pcx=33:*.pgm=33:*.png=33:*.PNG=33:*.ppm=33:*.pps=33:*.ppsx=33:*.ps=33:*.svg=33:*.svgz=33:*.tga=33:*.tif=33:*.tiff=33:*.xbm=33:*.xcf=33:*.xpm=33:*.xwd=33:*.xwd=33:*.yuv=33:*.NEF=33:*.nef=33:*.webp=33:*.heic=33:*.HEIC=33:*.avif=33:*.aac=33:*.au=33:*.flac=33:*.m4a=33:*.mid=33:*.midi=33:*.mka=33:*.mp3=33:*.mpa=33:*.mpeg=33:*.mpg=33:*.ogg=33:*.opus=33:*.ra=33:*.wav=33:*.anx=33:*.asf=33:*.avi=33:*.axv=33:*.flc=33:*.fli=33:*.flv=33:*.gl=33:*.m2v=33:*.m4v=33:*.mkv=33:*.mov=33:*.MOV=33:*.mp4=33:*.mp4v=33:*.mpeg=33:*.mpg=33:*.nuv=33:*.ogm=33:*.ogv=33:*.ogx=33:*.qt=33:*.rm=33:*.rmvb=33:*.swf=33:*.vob=33:*.webm=33:*.wmv=33:*.doc=31:*.docx=31:*.rtf=31:*.odt=31:*.dot=31:*.dotx=31:*.ott=31:*.xls=31:*.xlsx=31:*.ods=31:*.ots=31:*.ppt=31:*.pptx=31:*.odp=31:*.otp=31:*.fla=31:*.psd=31:*.pdf=31:*.7z=1;35:*.apk=1;35:*.arj=1;35:*.bin=1;35:*.bz=1;35:*.bz2=1;35:*.cab=1;35:*.deb=1;35:*.dmg=1;35:*.gem=1;35:*.gz=1;35:*.iso=1;35:*.jar=1;35:*.msi=1;35:*.rar=1;35:*.rpm=1;35:*.tar=1;35:*.tbz=1;35:*.tbz2=1;35:*.tgz=1;35:*.tx=1;35:*.war=1;35:*.xpi=1;35:*.xz=1;35:*.z=1;35:*.Z=1;35:*.zip=1;35:*.zst=1;35:*.ANSI-30-black=30:*.ANSI-01;30-brblack=01;30:*.ANSI-31-red=31:*.ANSI-01;31-brred=01;31:*.ANSI-32-green=32:*.ANSI-01;32-brgreen=01;32:*.ANSI-33-yellow=33:*.ANSI-01;33-bryellow=01;33:*.ANSI-34-blue=34:*.ANSI-01;34-brblue=01;34:*.ANSI-35-magenta=35:*.ANSI-01;35-brmagenta=01;35:*.ANSI-36-cyan=36:*.ANSI-01;36-brcyan=01;36:*.ANSI-37-white=37:*.ANSI-01;37-brwhite=01;37:*.log=01;32:*~=01;32:*#=01;32:*.bak=01;36:*.BAK=01;36:*.old=01;36:*.OLD=01;36:*.org_archive=01;36:*.off=01;36:*.OFF=01;36:*.dist=01;36:*.DIST=01;36:*.orig=01;36:*.ORIG=01;36:*.swp=01;36:*.swo=01;36:*.v=01;36:*.gpg=34:*.pgp=34:*.asc=34:*.3des=34:*.aes=34:*.enc=34:*.sqlite=34:*.db=34:",
+ "trapdoor": "bd=38;5;68:ca=38;5;17:cd=38;5;113;1:di=38;5;30:do=38;5;127:ex=38;5;208;1:pi=38;5;126:fi=0:ln=target:mh=38;5;222;1:no=0:or=48;5;196;38;5;232;1:ow=38;5;220;1:sg=48;5;3;38;5;0:su=38;5;220;1;3;100;1:so=38;5;197:st=38;5;86;48;5;234:tw=48;5;235;38;5;139;3:*LS_COLORS=48;5;89;38;5;197;1;3;4;7:*.txt=38;5;253:*README=38;5;220;1:*README.rst=38;5;220;1:*README.md=38;5;220;1:*LICENSE=38;5;220;1:*LICENSE.md=38;5;220;1:*COPYING=38;5;220;1:*INSTALL=38;5;220;1:*COPYRIGHT=38;5;220;1:*AUTHORS=38;5;220;1:*HISTORY=38;5;220;1:*CONTRIBUTORS=38;5;220;1:*CONTRIBUTING=38;5;220;1:*CONTRIBUTING.md=38;5;220;1:*CHANGELOG=38;5;220;1:*CHANGELOG.md=38;5;220;1:*CODEOWNERS=38;5;220;1:*PATENTS=38;5;220;1:*VERSION=38;5;220;1:*NOTICE=38;5;220;1:*CHANGES=38;5;220;1:*.log=38;5;190:*.adoc=38;5;184:*.asciidoc=38;5;184:*.etx=38;5;184:*.info=38;5;184:*.markdown=38;5;184:*.md=38;5;184:*.mkd=38;5;184:*.mdx=38;5;184:*.nfo=38;5;184:*.org=38;5;184:*.norg=38;5;184:*.pod=38;5;184:*.rst=38;5;184:*.tex=38;5;184:*.textile=38;5;184:*.bib=38;5;178:*.json=38;5;178:*.jsonc=38;5;178:*.json5=38;5;178:*.hjson=38;5;178:*.jsonl=38;5;178:*.jsonnet=38;5;178:*.libsonnet=38;5;142:*.ndjson=38;5;178:*.msg=38;5;178:*.pgn=38;5;178:*.rss=38;5;178:*.xml=38;5;178:*.fxml=38;5;178:*.toml=38;5;178:*.yaml=38;5;178:*.yml=38;5;178:*.RData=38;5;178:*.rdata=38;5;178:*.xsd=38;5;178:*.dtd=38;5;178:*.sgml=38;5;178:*.rng=38;5;178:*.rnc=38;5;178:*.accdb=38;5;60:*.accde=38;5;60:*.accdr=38;5;60:*.accdt=38;5;60:*.db=38;5;60:*.fmp12=38;5;60:*.fp7=38;5;60:*.localstorage=38;5;60:*.mdb=38;5;60:*.mde=38;5;60:*.sqlite=38;5;60:*.typelib=38;5;60:*.nc=38;5;60:*.cbr=38;5;141:*.cbz=38;5;141:*.chm=38;5;141:*.djvu=38;5;141:*.pdf=38;5;141:*.PDF=38;5;141:*.mobi=38;5;141:*.epub=38;5;141:*.docm=38;5;111;4:*.doc=38;5;111:*.docx=38;5;111:*.odb=38;5;111:*.odt=38;5;111:*.rtf=38;5;111:*.pages=38;5;111:*.odp=38;5;166:*.pps=38;5;166:*.ppt=38;5;166:*.pptx=38;5;166:*.ppts=38;5;166:*.pptxm=38;5;166;4:*.pptsm=38;5;166;4:*.prisma=38;5;222:*.csv=38;5;78:*.tsv=38;5;78:*.numbers=38;5;112:*.ods=38;5;112:*.xla=38;5;76:*.xls=38;5;112:*.xlsx=38;5;112:*.xlsxm=38;5;112;4:*.xltm=38;5;73;4:*.xltx=38;5;73:*.key=38;5;166:*config=1:*cfg=1:*conf=1:*rc=1:*authorized_keys=1:*known_hosts=1:*.ini=1:*.plist=1:*.profile=1:*.bash_profile=1:*.bash_login=1:*.bash_logout=1:*.zshenv=1:*.zprofile=1:*.zlogin=1:*.zlogout=1:*.viminfo=1:*.pcf=1:*.psf=1:*.hidden-color-scheme=1:*.hidden-tmTheme=1:*.last-run=1:*.merged-ca-bundle=1:*.sublime-build=1:*.sublime-commands=1:*.sublime-keymap=1:*.sublime-settings=1:*.sublime-snippet=1:*.sublime-project=1:*.sublime-workspace=1:*.tmTheme=1:*.user-ca-bundle=1:*.rstheme=1:*.epf=1:*.git=38;5;197:*.github=38;5;197:*.gitignore=38;5;240:*.gitattributes=38;5;240:*.gitmodules=38;5;240:*.awk=38;5;172:*.bash=38;5;172:*.bat=38;5;172:*.BAT=38;5;172:*.sed=38;5;172:*.sh=38;5;172:*.zsh=38;5;172:*.fish=38;5;172:*.vim=38;5;172:*.kak=38;5;172:*.ahk=38;5;41:*.py=38;5;41:*.ipynb=38;5;41:*.xsh=38;5;41:*.rb=38;5;41:*.gemspec=38;5;41:*.pl=38;5;208:*.PL=38;5;160:*.pm=38;5;203:*.t=38;5;114:*.msql=38;5;222:*.mysql=38;5;222:*.prql=38;5;222:*.pgsql=38;5;222:*.sql=38;5;222:*.tcl=38;5;64;1:*.r=38;5;49:*.R=38;5;49:*.gs=38;5;81:*.clj=38;5;41:*.cljs=38;5;41:*.cljc=38;5;41:*.cljw=38;5;41:*.scala=38;5;41:*.sc=38;5;41:*.dart=38;5;51:*.asm=38;5;81:*.cl=38;5;81:*.ml=38;5;81:*.lisp=38;5;81:*.rkt=38;5;81:*.el=38;5;81:*.elc=38;5;241:*.eln=38;5;241:*.lua=38;5;81:*.moon=38;5;81:*.c=38;5;81:*.C=38;5;81:*.h=38;5;110:*.H=38;5;110:*.tcc=38;5;110:*.c++=38;5;81:*.h++=38;5;110:*.hpp=38;5;110:*.hxx=38;5;110:*.ii=38;5;110:*.M=38;5;110:*.m=38;5;110:*.cc=38;5;81:*.cs=38;5;81:*.cp=38;5;81:*.cpp=38;5;81:*.cxx=38;5;81:*.cr=38;5;81:*.go=38;5;81:*.f=38;5;81:*.F=38;5;81:*.for=38;5;81:*.ftn=38;5;81:*.f90=38;5;81:*.F90=38;5;81:*.f95=38;5;81:*.F95=38;5;81:*.f03=38;5;81:*.F03=38;5;81:*.f08=38;5;81:*.F08=38;5;81:*.nim=38;5;81:*.nimble=38;5;81:*.s=38;5;110:*.S=38;5;110:*.rs=38;5;81:*.scpt=38;5;219:*.swift=38;5;219:*.sx=38;5;81:*.vala=38;5;81:*.vapi=38;5;81:*.hi=38;5;110:*.hs=38;5;81:*.lhs=38;5;81:*.agda=38;5;81:*.lagda=38;5;81:*.lagda.tex=38;5;81:*.lagda.rst=38;5;81:*.lagda.md=38;5;81:*.agdai=38;5;110:*.zig=38;5;81:*.v=38;5;81:*.pyc=38;5;240:*.tf=38;5;168:*.tfstate=38;5;168:*.tfvars=38;5;168:*.http=38;5;90;1:*.eml=38;5;90;1:*.css=38;5;105;1:*.less=38;5;105;1:*.sass=38;5;105;1:*.scss=38;5;105;1:*.htm=38;5;125;1:*.html=38;5;125;1:*.jhtm=38;5;125;1:*.mht=38;5;125;1:*.mustache=38;5;135;1:*.ejs=38;5;135;1:*.pug=38;5;135;1:*.svelte=38;5;135;1:*.vue=38;5;135;1:*.astro=38;5;135;1:*.js=38;5;074;1:*.jsx=38;5;074;1:*.ts=38;5;074;1:*.tsx=38;5;074;1:*.mjs=38;5;074;1:*.cjs=38;5;074;1:*.coffee=38;5;079;1:*.java=38;5;079;1:*.jsm=38;5;079;1:*.jsp=38;5;079;1:*.php=38;5;81:*.ctp=38;5;81:*.twig=38;5;81:*.vb=38;5;81:*.vba=38;5;81:*.vbs=38;5;81:*Containerfile=38;5;155:*.containerignore=38;5;240:*Dockerfile=38;5;155:*.dockerignore=38;5;240:*Makefile=38;5;155:*MANIFEST=38;5;243:*pm_to_blib=38;5;240:*.nix=38;5;155:*.dhall=38;5;178:*.rake=38;5;155:*.am=38;5;242:*.in=38;5;242:*.hin=38;5;242:*.scan=38;5;242:*.m4=38;5;242:*.old=38;5;242:*.out=38;5;242:*.SKIP=38;5;244:*.diff=48;5;197;38;5;232:*.patch=48;5;197;38;5;232;1:*.bmp=38;5;97:*.dicom=38;5;97:*.tiff=38;5;97:*.tif=38;5;97:*.TIFF=38;5;97:*.cdr=38;5;97:*.flif=38;5;97:*.gif=38;5;97:*.icns=38;5;97:*.ico=38;5;97:*.jpeg=38;5;97:*.JPG=38;5;97:*.jpg=38;5;97:*.jxl=38;5;97:*.nth=38;5;97:*.png=38;5;97:*.psd=38;5;97:*.pxd=38;5;97:*.pxm=38;5;97:*.xpm=38;5;97:*.webp=38;5;97:*.ai=38;5;99:*.eps=38;5;99:*.epsf=38;5;99:*.drw=38;5;99:*.ps=38;5;99:*.svg=38;5;99:*.avi=38;5;114:*.divx=38;5;114:*.IFO=38;5;114:*.m2v=38;5;114:*.m4v=38;5;114:*.mkv=38;5;114:*.MOV=38;5;114:*.mov=38;5;114:*.mp4=38;5;114:*.mpeg=38;5;114:*.mpg=38;5;114:*.ogm=38;5;114:*.rmvb=38;5;114:*.sample=38;5;114:*.wmv=38;5;114:*.3g2=38;5;115:*.3gp=38;5;115:*.gp3=38;5;115:*.webm=38;5;115:*.gp4=38;5;115:*.asf=38;5;115:*.flv=38;5;115:*.ogv=38;5;115:*.f4v=38;5;115:*.VOB=38;5;115;1:*.vob=38;5;115;1:*.ass=38;5;117:*.srt=38;5;117:*.ssa=38;5;117:*.sub=38;5;117:*.sup=38;5;117:*.vtt=38;5;117:*.3ga=38;5;137;1:*.S3M=38;5;137;1:*.aac=38;5;137;1:*.amr=38;5;137;1:*.au=38;5;137;1:*.caf=38;5;137;1:*.dat=38;5;137;1:*.dts=38;5;137;1:*.fcm=38;5;137;1:*.m4a=38;5;137;1:*.mod=38;5;137;1:*.mp3=38;5;137;1:*.mp4a=38;5;137;1:*.oga=38;5;137;1:*.ogg=38;5;137;1:*.opus=38;5;137;1:*.s3m=38;5;137;1:*.sid=38;5;137;1:*.wma=38;5;137;1:*.ape=38;5;136;1:*.aiff=38;5;136;1:*.cda=38;5;136;1:*.flac=38;5;136;1:*.alac=38;5;136;1:*.mid=38;5;136;1:*.midi=38;5;136;1:*.pcm=38;5;136;1:*.wav=38;5;136;1:*.wv=38;5;136;1:*.wvc=38;5;136;1:*.afm=38;5;66:*.fon=38;5;66:*.fnt=38;5;66:*.pfb=38;5;66:*.pfm=38;5;66:*.ttf=38;5;66:*.otf=38;5;66:*.woff=38;5;66:*.woff2=38;5;66:*.PFA=38;5;66:*.pfa=38;5;66:*.7z=38;5;40:*.a=38;5;40:*.arj=38;5;40:*.br=38;5;40:*.bz2=38;5;40:*.cpio=38;5;40:*.gz=38;5;40:*.lrz=38;5;40:*.lz=38;5;40:*.lzma=38;5;40:*.lzo=38;5;40:*.rar=38;5;40:*.s7z=38;5;40:*.sz=38;5;40:*.tar=38;5;40:*.tbz=38;5;40:*.tgz=38;5;40:*.warc=38;5;40:*.WARC=38;5;40:*.xz=38;5;40:*.z=38;5;40:*.zip=38;5;40:*.zipx=38;5;40:*.zoo=38;5;40:*.zpaq=38;5;40:*.zst=38;5;40:*.zstd=38;5;40:*.zz=38;5;40:*.apk=38;5;215:*.ipa=38;5;215:*.deb=38;5;215:*.rpm=38;5;215:*.jad=38;5;215:*.jar=38;5;215:*.ear=38;5;215:*.war=38;5;215:*.cab=38;5;215:*.pak=38;5;215:*.pk3=38;5;215:*.vdf=38;5;215:*.vpk=38;5;215:*.bsp=38;5;215:*.dmg=38;5;215:*.crx=38;5;215:*.xpi=38;5;215:*.iso=38;5;124:*.img=38;5;124:*.bin=38;5;124:*.nrg=38;5;124:*.qcow=38;5;124:*.fvd=38;5;124:*.sparseimage=38;5;124:*.toast=38;5;124:*.vcd=38;5;124:*.vdi=38;5;124:*.vhd=38;5;124:*.vhdx=38;5;124:*.vfd=38;5;124:*.vmdk=38;5;124:*.swp=38;5;244:*.swo=38;5;244:*.tmp=38;5;244:*.sassc=38;5;244:*.pacnew=38;5;33:*.un~=38;5;241:*.orig=38;5;241:*.BUP=38;5;241:*.bak=38;5;241:*.o=38;5;241:*core=38;5;241:*.mdump=38;5;241:*.rlib=38;5;241:*.dll=38;5;241:*.aria2=38;5;241:*.dump=38;5;241:*.stackdump=38;5;241:*.zcompdump=38;5;241:*.zwc=38;5;241:*.part=38;5;239:*.r[0-9]{0,2}=38;5;239:*.zx[0-9]{0,2}=38;5;239:*.z[0-9]{0,2}=38;5;239:*.pid=38;5;248:*.state=38;5;248:*lockfile=38;5;248:*lock=38;5;248:*.err=38;5;160;1:*.error=38;5;160;1:*.stderr=38;5;160;1:*.pcap=38;5;29:*.cap=38;5;29:*.dmp=38;5;29:*.allow=38;5;112:*.deny=38;5;196:*.service=38;5;45:*@.service=38;5;45:*.socket=38;5;45:*.swap=38;5;45:*.device=38;5;45:*.mount=38;5;45:*.automount=38;5;45:*.target=38;5;45:*.path=38;5;45:*.timer=38;5;45:*.snapshot=38;5;45:*.lnk=38;5;39:*.application=38;5;116:*.cue=38;5;116:*.description=38;5;116:*.directory=38;5;116:*.m3u=38;5;116:*.m3u8=38;5;116:*.md5=38;5;116:*.properties=38;5;116:*.sfv=38;5;116:*.theme=38;5;116:*.torrent=38;5;116:*.urlview=38;5;116:*.webloc=38;5;116:*.asc=38;5;192;3:*.bfe=38;5;192;3:*.enc=38;5;192;3:*.gpg=38;5;192;3:*.signature=38;5;192;3:*.sig=38;5;192;3:*.p12=38;5;192;3:*.pem=38;5;192;3:*.pgp=38;5;192;3:*.p7s=38;5;192;3:*id_dsa=38;5;192;3:*id_rsa=38;5;192;3:*id_ecdsa=38;5;192;3:*id_ed25519=38;5;192;3:*.32x=38;5;213:*.cdi=38;5;213:*.fm2=38;5;213:*.rom=38;5;213:*.sav=38;5;213:*.st=38;5;213:*.a00=38;5;213:*.a52=38;5;213:*.A64=38;5;213:*.a64=38;5;213:*.a78=38;5;213:*.adf=38;5;213:*.atr=38;5;213:*.gb=38;5;213:*.gba=38;5;213:*.gbc=38;5;213:*.gel=38;5;213:*.gg=38;5;213:*.ggl=38;5;213:*.ipk=38;5;213:*.j64=38;5;213:*.nds=38;5;213:*.nes=38;5;213:*.sms=38;5;213:*.8xp=38;5;121:*.8eu=38;5;121:*.82p=38;5;121:*.83p=38;5;121:*.8xe=38;5;121:*.stl=38;5;216:*.dwg=38;5;216:*.ply=38;5;216:*.wrl=38;5;216:*.vert=38;5;136:*.comp=38;5;136:*.frag=38;5;136:*.spv=38;5;217:*.wgsl=38;5;97:*.xib=38;5;208:*.iml=38;5;166:*.DS_Store=38;5;239:*.localized=38;5;239:*.CFUserTextEncoding=38;5;239:*CodeResources=38;5;239:*PkgInfo=38;5;239:*.nib=38;5;57:*.car=38;5;57:*.dylib=38;5;241:*.entitlements=1:*.pbxproj=1:*.strings=1:*.storyboard=38;5;196:*.xcconfig=1:*.xcsettings=1:*.xcuserstate=1:*.xcworkspacedata=1:*.pot=38;5;7:*.pcb=38;5;7:*.mm=38;5;7:*.gbr=38;5;7:*.scm=38;5;7:*.xcf=38;5;7:*.spl=38;5;7:*.Rproj=38;5;11:*.sis=38;5;7:*.1p=38;5;7:*.3p=38;5;7:*.cnc=38;5;7:*.def=38;5;7:*.ex=38;5;7:*.example=38;5;7:*.feature=38;5;7:*.ger=38;5;7:*.ics=38;5;7:*.map=38;5;7:*.mf=38;5;7:*.mfasl=38;5;7:*.mi=38;5;7:*.mtx=38;5;7:*.pc=38;5;7:*.pi=38;5;7:*.plt=38;5;7:*.rdf=38;5;7:*.ru=38;5;7:*.sch=38;5;7:*.sty=38;5;7:*.sug=38;5;7:*.tdy=38;5;7:*.tfm=38;5;7:*.tfnt=38;5;7:*.tg=38;5;7:*.vcard=38;5;7:*.vcf=38;5;7:*.xln=38;5;7:"
+ },
+ "text_colours": {
+ "nerdtree_syntax_dark": {
+ "ext_exact": {
+ ".ai": "#F16529",
+ ".awk": "#FFFFFF",
+ ".bash": "#834F79",
+ ".bat": "#FFFFFF",
+ ".bmp": "#3AFFDB",
+ ".c": "#689FB6",
+ ".c++": "#689FB6",
+ ".cc": "#689FB6",
+ ".clj": "#8FAA54",
+ ".cljc": "#8FAA54",
+ ".cljs": "#8FAA54",
+ ".coffee": "#905532",
+ ".conf": "#FFFFFF",
+ ".cp": "#689FB6",
+ ".cpp": "#689FB6",
+ ".cs": "#689FB6",
+ ".csh": "#FFFFFF",
+ ".css": "#689FB6",
+ ".cxx": "#689FB6",
+ ".d": "#AE403F",
+ ".dart": "#689FB6",
+ ".db": "#689FB6",
+ ".diff": "#FFFFFF",
+ ".dump": "#689FB6",
+ ".edn": "#8FAA54",
+ ".eex": "#834F79",
+ ".ejs": "#F09F17",
+ ".elm": "#FFFFFF",
+ ".erb": "#AE403F",
+ ".erl": "#834F79",
+ ".ex": "#834F79",
+ ".exs": "#834F79",
+ ".f#": "#44788E",
+ ".fish": "#8FAA54",
+ ".fs": "#689FB6",
+ ".fsi": "#689FB6",
+ ".fsscript": "#689FB6",
+ ".fsx": "#689FB6",
+ ".gif": "#3AFFDB",
+ ".go": "#F5C06F",
+ ".h": "#689FB6",
+ ".hbs": "#D4843E",
+ ".hh": "#689FB6",
+ ".hpp": "#689FB6",
+ ".hrl": "#CB6F6F",
+ ".hs": "#F5C06F",
+ ".htm": "#F16529",
+ ".html": "#F16529",
+ ".hxx": "#689FB6",
+ ".ico": "#3AFFDB",
+ ".ini": "#FFFFFF",
+ ".java": "#834F79",
+ ".jl": "#9558B2",
+ ".jpeg": "#3AFFDB",
+ ".jpg": "#3AFFDB",
+ ".js": "#F5C06F",
+ ".json": "#F5C06F",
+ ".jsx": "#689FB6",
+ ".ksh": "#FFFFFF",
+ ".leex": "#FFFFFF",
+ ".less": "#44788E",
+ ".lhs": "#F5C06F",
+ ".lua": "#834F79",
+ ".markdown": "#F09F17",
+ ".md": "#F09F17",
+ ".mdx": "#F09F17",
+ ".mjs": "#F5C06F",
+ ".ml": "#F09F17",
+ ".mli": "#F09F17",
+ ".mustache": "#D4843E",
+ ".php": "#834F79",
+ ".pl": "#689FB6",
+ ".pm": "#689FB6",
+ ".png": "#3AFFDB",
+ ".pp": "#FFFFFF",
+ ".ps1": "#689FB6",
+ ".psb": "#44788E",
+ ".psd": "#44788E",
+ ".py": "#F09F17",
+ ".pyc": "#F09F17",
+ ".pyd": "#F09F17",
+ ".pyo": "#F09F17",
+ ".rb": "#AE403F",
+ ".rlib": "#F16529",
+ ".rmd": "#F09F17",
+ ".rs": "#F16529",
+ ".rss": "#F16529",
+ ".sass": "#CB6F6F",
+ ".scala": "#AE403F",
+ ".scss": "#CB6F6F",
+ ".sh": "#834F79",
+ ".slim": "#D4843E",
+ ".sln": "#834F79",
+ ".sql": "#44788E",
+ ".styl": "#8FAA54",
+ ".suo": "#834F79",
+ ".swift": "#D4843E",
+ ".t": "#689FB6",
+ ".toml": "#FFFFFF",
+ ".ts": "#689FB6",
+ ".tsx": "#689FB6",
+ ".twig": "#8FAA54",
+ ".vim": "#8FAA54",
+ ".vue": "#42B883",
+ ".webp": "#3AFFDB",
+ ".xcplayground": "#D4843E",
+ ".xul": "#F16529",
+ ".yaml": "#FFFFFF",
+ ".yml": "#FFFFFF",
+ ".zsh": "#FFFFFF"
+ },
+ "name_exact": {
+ ".bashprofile": "#FFFFFF",
+ ".bashrc": "#FFFFFF",
+ ".ds_store": "#FFFFFF",
+ ".gitconfig": "#FFFFFF",
+ ".gitignore": "#FFFFFF",
+ ".gitlab-ci.yml": "#D4843E",
+ ".gvimrc": "#8FAA54",
+ ".vimrc": "#8FAA54",
+ ".zshrc": "#FFFFFF",
+ "_gvimrc": "#8FAA54",
+ "_vimrc": "#8FAA54",
+ "cmakelists.txt": "#FFFFFF",
+ "docker-compose.yml": "#689FB6",
+ "dockerfile": "#689FB6",
+ "dropbox": "#689FB6",
+ "favicon.ico": "#F09F17",
+ "gruntfile.coffee": "#F09F17",
+ "gruntfile.js": "#F09F17",
+ "gruntfile.ls": "#F09F17",
+ "gulpfile.coffee": "#CB6F6F",
+ "gulpfile.js": "#CB6F6F",
+ "gulpfile.ls": "#CB6F6F",
+ "license": "#FFFFFF",
+ "makefile": "#FFFFFF",
+ "mix.lock": "#FFFFFF",
+ "node_modules": "#8FAA54",
+ "procfile": "#834F79",
+ "react.jsx": "#689FB6",
+ "typescript.jsx": "#689FB6",
+ "typescript.tsx": "#689FB6"
+ },
+ "name_glob": {
+ ".*angular.*.js": "#AE403F",
+ ".*backbone.*.js": "#44788E",
+ ".*jquery.*.js": "#689FB6",
+ ".*materialize.*.css": "#EE6E73",
+ ".*materialize.*.js": "#EE6E73",
+ ".*mootools.*.js": "#FFFFFF",
+ ".*require.*.js": "#689FB6",
+ ".*vimrc.*": "#8FAA54",
+ "Vagrantfile": "#689FB6"
+ }
+ },
+ "nerdtree_syntax_light": {
+ "ext_exact": {
+ ".ai": "#0e9ad6",
+ ".awk": "#000000",
+ ".bash": "#7cb086",
+ ".bat": "#000000",
+ ".bmp": "#c50024",
+ ".c": "#976049",
+ ".c++": "#976049",
+ ".cc": "#976049",
+ ".clj": "#7055ab",
+ ".cljc": "#7055ab",
+ ".cljs": "#7055ab",
+ ".coffee": "#6faacd",
+ ".conf": "#000000",
+ ".cp": "#976049",
+ ".cpp": "#976049",
+ ".cs": "#976049",
+ ".csh": "#000000",
+ ".css": "#976049",
+ ".cxx": "#976049",
+ ".d": "#51bfc0",
+ ".dart": "#976049",
+ ".db": "#976049",
+ ".diff": "#000000",
+ ".dump": "#976049",
+ ".edn": "#7055ab",
+ ".eex": "#7cb086",
+ ".ejs": "#0f60e8",
+ ".elm": "#000000",
+ ".erb": "#51bfc0",
+ ".erl": "#7cb086",
+ ".ex": "#7cb086",
+ ".exs": "#7cb086",
+ ".f#": "#bb8771",
+ ".fish": "#7055ab",
+ ".fs": "#976049",
+ ".fsi": "#976049",
+ ".fsscript": "#976049",
+ ".fsx": "#976049",
+ ".gif": "#c50024",
+ ".go": "#0a3f90",
+ ".h": "#976049",
+ ".hbs": "#2b7bc1",
+ ".hh": "#976049",
+ ".hpp": "#976049",
+ ".hrl": "#349090",
+ ".hs": "#0a3f90",
+ ".htm": "#0e9ad6",
+ ".html": "#0e9ad6",
+ ".hxx": "#976049",
+ ".ico": "#c50024",
+ ".ini": "#000000",
+ ".java": "#7cb086",
+ ".jl": "#6aa74d",
+ ".jpeg": "#c50024",
+ ".jpg": "#c50024",
+ ".js": "#0a3f90",
+ ".json": "#0a3f90",
+ ".jsx": "#976049",
+ ".ksh": "#000000",
+ ".leex": "#000000",
+ ".less": "#bb8771",
+ ".lhs": "#0a3f90",
+ ".lua": "#7cb086",
+ ".markdown": "#0f60e8",
+ ".md": "#0f60e8",
+ ".mdx": "#0f60e8",
+ ".mjs": "#0a3f90",
+ ".ml": "#0f60e8",
+ ".mli": "#0f60e8",
+ ".mustache": "#2b7bc1",
+ ".php": "#7cb086",
+ ".pl": "#976049",
+ ".pm": "#976049",
+ ".png": "#c50024",
+ ".pp": "#000000",
+ ".ps1": "#976049",
+ ".psb": "#bb8771",
+ ".psd": "#bb8771",
+ ".py": "#0f60e8",
+ ".pyc": "#0f60e8",
+ ".pyd": "#0f60e8",
+ ".pyo": "#0f60e8",
+ ".rb": "#51bfc0",
+ ".rlib": "#0e9ad6",
+ ".rmd": "#0f60e8",
+ ".rs": "#0e9ad6",
+ ".rss": "#0e9ad6",
+ ".sass": "#349090",
+ ".scala": "#51bfc0",
+ ".scss": "#349090",
+ ".sh": "#7cb086",
+ ".slim": "#2b7bc1",
+ ".sln": "#7cb086",
+ ".sql": "#bb8771",
+ ".styl": "#7055ab",
+ ".suo": "#7cb086",
+ ".swift": "#2b7bc1",
+ ".t": "#976049",
+ ".toml": "#000000",
+ ".ts": "#976049",
+ ".tsx": "#976049",
+ ".twig": "#7055ab",
+ ".vim": "#7055ab",
+ ".vue": "#bd477c",
+ ".webp": "#c50024",
+ ".xcplayground": "#2b7bc1",
+ ".xul": "#0e9ad6",
+ ".yaml": "#000000",
+ ".yml": "#000000",
+ ".zsh": "#000000"
+ },
+ "name_exact": {
+ ".bashprofile": "#000000",
+ ".bashrc": "#000000",
+ ".ds_store": "#000000",
+ ".gitconfig": "#000000",
+ ".gitignore": "#000000",
+ ".gitlab-ci.yml": "#2b7bc1",
+ ".gvimrc": "#7055ab",
+ ".vimrc": "#7055ab",
+ ".zshrc": "#000000",
+ "_gvimrc": "#7055ab",
+ "_vimrc": "#7055ab",
+ "cmakelists.txt": "#000000",
+ "docker-compose.yml": "#976049",
+ "dockerfile": "#976049",
+ "dropbox": "#976049",
+ "favicon.ico": "#0f60e8",
+ "gruntfile.coffee": "#0f60e8",
+ "gruntfile.js": "#0f60e8",
+ "gruntfile.ls": "#0f60e8",
+ "gulpfile.coffee": "#349090",
+ "gulpfile.js": "#349090",
+ "gulpfile.ls": "#349090",
+ "license": "#000000",
+ "makefile": "#000000",
+ "mix.lock": "#000000",
+ "node_modules": "#7055ab",
+ "procfile": "#7cb086",
+ "react.jsx": "#976049",
+ "typescript.jsx": "#976049",
+ "typescript.tsx": "#976049"
+ },
+ "name_glob": {
+ ".*angular.*.js": "#51bfc0",
+ ".*backbone.*.js": "#bb8771",
+ ".*jquery.*.js": "#976049",
+ ".*materialize.*.css": "#11918c",
+ ".*materialize.*.js": "#11918c",
+ ".*mootools.*.js": "#000000",
+ ".*require.*.js": "#976049",
+ ".*vimrc.*": "#7055ab",
+ "Vagrantfile": "#976049"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/config/neovim/store/lazy-plugins/chadtree/assets/README.md b/config/neovim/store/lazy-plugins/chadtree/assets/README.md
new file mode 100644
index 00000000..044d273c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/assets/README.md
@@ -0,0 +1 @@
+# Used to Generate Artifacts
\ No newline at end of file
diff --git a/config/neovim/store/lazy-plugins/chadtree/assets/aliases.yml b/config/neovim/store/lazy-plugins/chadtree/assets/aliases.yml
new file mode 100644
index 00000000..c6105699
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/assets/aliases.yml
@@ -0,0 +1,6 @@
+---
+icon_colours: {}
+text_colours:
+ ext_exact: {}
+ name_exact: {}
+ name_glob: {}
diff --git a/config/neovim/store/lazy-plugins/chadtree/assets/icon_base.yml b/config/neovim/store/lazy-plugins/chadtree/assets/icon_base.yml
new file mode 100644
index 00000000..e90c764f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/assets/icon_base.yml
@@ -0,0 +1,36 @@
+---
+ascii: &ascii
+ default_icon: ●
+ ext_exact: {}
+ folder:
+ closed: ▶
+ open: ▼
+ link:
+ broken: -/->
+ normal: ->
+ name_exact: {}
+ name_glob: {}
+ status:
+ active: ">"
+ inactive: " "
+ not_selected: " "
+ selected: "*"
+
+ascii_hollow:
+ <<: *ascii
+ default_icon: ○
+ folder:
+ closed: ▷
+ open: ▽
+
+devicons: &devicons
+ link:
+ broken:
+ normal:
+ status:
+ active: ▶
+ inactive: " "
+ not_selected: " "
+ selected: ✸
+
+emoji: *devicons
diff --git a/config/neovim/store/lazy-plugins/chadtree/chad_types.py b/config/neovim/store/lazy-plugins/chadtree/chad_types.py
new file mode 100644
index 00000000..9113fb20
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chad_types.py
@@ -0,0 +1,146 @@
+from dataclasses import dataclass
+from enum import Enum, auto
+from pathlib import Path
+from typing import Mapping
+
+TOP_LEVEL = Path(__file__).resolve(strict=True).parent
+ASSETS = TOP_LEVEL / "assets"
+ARTIFACT = TOP_LEVEL / "artifacts" / "artifact.json"
+
+
+"""
+Icons
+"""
+
+
+Icon = str
+
+
+@dataclass(frozen=True)
+class _FolderIcons:
+ open: Icon
+ closed: Icon
+
+
+@dataclass(frozen=True)
+class _LinkIcons:
+ normal: Icon
+ broken: Icon
+
+
+@dataclass(frozen=True)
+class _StatusIcons:
+ active: Icon
+ inactive: Icon
+ selected: Icon
+ not_selected: Icon
+
+
+@dataclass(frozen=True)
+class IconGlyphs:
+ default_icon: Icon
+ folder: _FolderIcons
+ link: _LinkIcons
+ status: _StatusIcons
+
+ ext_exact: Mapping[str, Icon]
+ name_exact: Mapping[str, Icon]
+ name_glob: Mapping[str, Icon]
+
+
+@dataclass(frozen=True)
+class IconGlyphSet:
+ ascii_hollow: IconGlyphs
+ ascii: IconGlyphs
+ devicons: IconGlyphs
+ emoji: IconGlyphs
+
+
+class IconGlyphSetEnum(Enum):
+ ascii_hollow = auto()
+ ascii = auto()
+ devicons = auto()
+ emoji = auto()
+
+
+"""
+Icon Colours
+"""
+
+
+Hex = str
+IconColours = Mapping[str, Hex]
+
+
+@dataclass(frozen=True)
+class IconColourSet:
+ github: IconColours
+
+
+class IconColourSetEnum(Enum):
+ github = auto()
+ none = auto()
+
+
+"""
+LS Colours
+"""
+
+
+LS_COLOR = str
+
+
+@dataclass(frozen=True)
+class LSColourSet:
+ solarized_dark_256: LS_COLOR
+ solarized_dark: LS_COLOR
+ solarized_light: LS_COLOR
+ solarized_universal: LS_COLOR
+ nord: LS_COLOR
+ trapdoor: LS_COLOR
+
+
+class LSColoursEnum(Enum):
+ env = auto()
+ solarized_dark_256 = auto()
+ solarized_dark = auto()
+ solarized_light = auto()
+ solarized_universal = auto()
+ nord = auto()
+ trapdoor = auto()
+
+
+"""
+Text Colours
+"""
+
+
+@dataclass(frozen=True)
+class TextColours:
+ ext_exact: Mapping[str, Hex]
+ name_exact: Mapping[str, Hex]
+ name_glob: Mapping[str, Hex]
+
+
+@dataclass(frozen=True)
+class TextColourSet:
+ nerdtree_syntax_light: TextColours
+ nerdtree_syntax_dark: TextColours
+
+
+class TextColourSetEnum(Enum):
+ nerdtree_syntax_light = auto()
+ nerdtree_syntax_dark = auto()
+
+
+"""
+Artifact
+"""
+
+
+@dataclass(frozen=True)
+class Artifact:
+ icons: IconGlyphSet
+ ls_colours: LSColourSet
+ icon_colours: IconColourSet
+ text_colours: TextColourSet
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/__main__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/__main__.py
new file mode 100644
index 00000000..5c2399b1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/__main__.py
@@ -0,0 +1,158 @@
+from argparse import ArgumentParser, Namespace
+from asyncio import run as arun
+from concurrent.futures import ThreadPoolExecutor
+from contextlib import nullcontext, redirect_stderr, redirect_stdout
+from io import StringIO
+from pathlib import Path, PurePath
+from subprocess import DEVNULL, STDOUT, CalledProcessError, run
+from sys import (
+ executable,
+ exit,
+ getswitchinterval,
+ setswitchinterval,
+ stderr,
+ version_info,
+)
+from textwrap import dedent
+from typing import Any, Union
+from webbrowser import open as open_w
+
+from .consts import GIL_SWITCH, IS_WIN, MIGRATION_URI, REQUIREMENTS, RT_DIR, RT_PY
+
+setswitchinterval(min(getswitchinterval(), GIL_SWITCH))
+
+try:
+ from typing import Literal
+
+ if version_info < (3, 8, 2):
+ raise ImportError()
+except ImportError:
+ msg = "For python < 3.8.2 please install using the branch -- legacy"
+ print(msg, file=stderr)
+ open_w(MIGRATION_URI)
+ exit(1)
+
+
+def _socket(arg: str) -> Any:
+ if arg.startswith("localhost:"):
+ host, _, port = arg.rpartition(":")
+ return host, int(port)
+ else:
+ return PurePath(arg)
+
+
+def parse_args() -> Namespace:
+ parser = ArgumentParser()
+
+ sub_parsers = parser.add_subparsers(dest="command", required=True)
+
+ with nullcontext(sub_parsers.add_parser("run")) as p:
+ p.add_argument("--ppid", type=int)
+ p.add_argument("--socket", required=True, type=_socket)
+ p.add_argument("--xdg")
+
+ with nullcontext(sub_parsers.add_parser("deps")) as p:
+ p.add_argument("--nvim", action="store_true")
+ p.add_argument("--xdg", nargs="?")
+
+ return parser.parse_args()
+
+
+args = parse_args()
+command: Union[Literal["deps"], Literal["run"]] = args.command
+
+_XDG = Path(args.xdg) if args.xdg is not None else None
+
+_RT_DIR = _XDG / "chadrt" if _XDG else RT_DIR
+_RT_PY = (
+ (_RT_DIR / "Scripts" / "python.exe" if IS_WIN else _RT_DIR / "bin" / "python3")
+ if _XDG
+ else RT_PY
+)
+_LOCK_FILE = _RT_DIR / "requirements.lock"
+_EXEC_PATH = Path(executable)
+_EXEC_PATH = _EXEC_PATH.parent.resolve(strict=True) / _EXEC_PATH.name
+_REQ = REQUIREMENTS.read_text()
+
+_IN_VENV = True
+
+
+if command == "deps":
+ assert not _IN_VENV
+
+ io_out = StringIO()
+ try:
+ from venv import EnvBuilder
+
+ print("...", flush=True)
+ with redirect_stdout(io_out), redirect_stderr(io_out):
+ EnvBuilder(
+ system_site_packages=False,
+ with_pip=True,
+ upgrade=True,
+ symlinks=not IS_WIN,
+ clear=True,
+ ).create(_RT_DIR)
+ except (ImportError, CalledProcessError):
+ msg = "Please install python3-venv separately. (apt, yum, apk, etc)"
+ print(msg, io_out.getvalue(), file=stderr)
+ exit(1)
+ else:
+ proc = run(
+ (
+ _RT_PY,
+ "-m",
+ "pip",
+ "install",
+ "--upgrade",
+ "--requirement",
+ REQUIREMENTS,
+ ),
+ stdin=DEVNULL,
+ stderr=STDOUT,
+ )
+ if proc.returncode:
+ print("Installation failed, check :message", file=stderr)
+ exit(proc.returncode)
+ else:
+ _LOCK_FILE.write_text(_REQ)
+ msg = """
+ ---
+ You can now use :CHADopen
+ """
+ print(dedent(msg), file=stderr)
+
+elif command == "run":
+ try:
+ lock = _LOCK_FILE.read_text()
+ except Exception:
+ lock = ""
+ try:
+ if not _IN_VENV:
+ raise ImportError()
+ elif False:
+ raise ImportError()
+ else:
+ import pynvim_pp
+ import yaml
+
+ from .client import init
+ except ImportError as e:
+ print(e)
+ msg = """
+ Please update dependencies using :CHADdeps
+ -
+ -
+ Dependencies will be installed privately inside `chadtree/.vars`
+ `rm -rf chadtree/` will cleanly remove everything
+ """
+ msg = dedent(msg)
+ print(msg, end="", file=stderr)
+ exit(1)
+ else:
+ with ThreadPoolExecutor() as th:
+ arun(init(args.socket, ppid=args.ppid, th=th))
+
+
+else:
+ assert False
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/__main__.py.orig b/config/neovim/store/lazy-plugins/chadtree/chadtree/__main__.py.orig
new file mode 100644
index 00000000..aede27b6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/__main__.py.orig
@@ -0,0 +1,158 @@
+from argparse import ArgumentParser, Namespace
+from asyncio import run as arun
+from concurrent.futures import ThreadPoolExecutor
+from contextlib import nullcontext, redirect_stderr, redirect_stdout
+from io import StringIO
+from pathlib import Path, PurePath
+from subprocess import DEVNULL, STDOUT, CalledProcessError, run
+from sys import (
+ executable,
+ exit,
+ getswitchinterval,
+ setswitchinterval,
+ stderr,
+ version_info,
+)
+from textwrap import dedent
+from typing import Any, Union
+from webbrowser import open as open_w
+
+from .consts import GIL_SWITCH, IS_WIN, MIGRATION_URI, REQUIREMENTS, RT_DIR, RT_PY
+
+setswitchinterval(min(getswitchinterval(), GIL_SWITCH))
+
+try:
+ from typing import Literal
+
+ if version_info < (3, 8, 2):
+ raise ImportError()
+except ImportError:
+ msg = "For python < 3.8.2 please install using the branch -- legacy"
+ print(msg, file=stderr)
+ open_w(MIGRATION_URI)
+ exit(1)
+
+
+def _socket(arg: str) -> Any:
+ if arg.startswith("localhost:"):
+ host, _, port = arg.rpartition(":")
+ return host, int(port)
+ else:
+ return PurePath(arg)
+
+
+def parse_args() -> Namespace:
+ parser = ArgumentParser()
+
+ sub_parsers = parser.add_subparsers(dest="command", required=True)
+
+ with nullcontext(sub_parsers.add_parser("run")) as p:
+ p.add_argument("--ppid", type=int)
+ p.add_argument("--socket", required=True, type=_socket)
+ p.add_argument("--xdg")
+
+ with nullcontext(sub_parsers.add_parser("deps")) as p:
+ p.add_argument("--nvim", action="store_true")
+ p.add_argument("--xdg", nargs="?")
+
+ return parser.parse_args()
+
+
+args = parse_args()
+command: Union[Literal["deps"], Literal["run"]] = args.command
+
+_XDG = Path(args.xdg) if args.xdg is not None else None
+
+_RT_DIR = _XDG / "chadrt" if _XDG else RT_DIR
+_RT_PY = (
+ (_RT_DIR / "Scripts" / "python.exe" if IS_WIN else _RT_DIR / "bin" / "python3")
+ if _XDG
+ else RT_PY
+)
+_LOCK_FILE = _RT_DIR / "requirements.lock"
+_EXEC_PATH = Path(executable)
+_EXEC_PATH = _EXEC_PATH.parent.resolve(strict=True) / _EXEC_PATH.name
+_REQ = REQUIREMENTS.read_text()
+
+_IN_VENV = _RT_PY == _EXEC_PATH
+
+
+if command == "deps":
+ assert not _IN_VENV
+
+ io_out = StringIO()
+ try:
+ from venv import EnvBuilder
+
+ print("...", flush=True)
+ with redirect_stdout(io_out), redirect_stderr(io_out):
+ EnvBuilder(
+ system_site_packages=False,
+ with_pip=True,
+ upgrade=True,
+ symlinks=not IS_WIN,
+ clear=True,
+ ).create(_RT_DIR)
+ except (ImportError, CalledProcessError):
+ msg = "Please install python3-venv separately. (apt, yum, apk, etc)"
+ print(msg, io_out.getvalue(), file=stderr)
+ exit(1)
+ else:
+ proc = run(
+ (
+ _RT_PY,
+ "-m",
+ "pip",
+ "install",
+ "--upgrade",
+ "--requirement",
+ REQUIREMENTS,
+ ),
+ stdin=DEVNULL,
+ stderr=STDOUT,
+ )
+ if proc.returncode:
+ print("Installation failed, check :message", file=stderr)
+ exit(proc.returncode)
+ else:
+ _LOCK_FILE.write_text(_REQ)
+ msg = """
+ ---
+ You can now use :CHADopen
+ """
+ print(dedent(msg), file=stderr)
+
+elif command == "run":
+ try:
+ lock = _LOCK_FILE.read_text()
+ except Exception:
+ lock = ""
+ try:
+ if not _IN_VENV:
+ raise ImportError()
+ elif lock != _REQ:
+ raise ImportError()
+ else:
+ import pynvim_pp
+ import yaml
+
+ from .client import init
+ except ImportError as e:
+ print(e)
+ msg = """
+ Please update dependencies using :CHADdeps
+ -
+ -
+ Dependencies will be installed privately inside `chadtree/.vars`
+ `rm -rf chadtree/` will cleanly remove everything
+ """
+ msg = dedent(msg)
+ print(msg, end="", file=stderr)
+ exit(1)
+ else:
+ with ThreadPoolExecutor() as th:
+ arun(init(args.socket, ppid=args.ppid, th=th))
+
+
+else:
+ assert False
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/_registry.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/_registry.py
new file mode 100644
index 00000000..2d1f4873
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/_registry.py
@@ -0,0 +1,54 @@
+from .transitions import (
+ autocmds,
+ click,
+ collapse,
+ copy_name,
+ cut_copy,
+ delete,
+ filter,
+ focus,
+ help,
+ link,
+ marks,
+ new,
+ noop,
+ open_system,
+ quit,
+ refresh,
+ rename,
+ resize,
+ schedule_update,
+ selection,
+ stat,
+ toggle_exec,
+ toggle_open,
+ toggles,
+)
+
+assert autocmds
+assert click
+assert collapse
+assert copy_name
+assert cut_copy
+assert delete
+assert filter
+assert focus
+assert help
+assert link
+assert marks
+assert new
+assert noop
+assert open_system
+assert quit
+assert refresh
+assert refresh
+assert rename
+assert resize
+assert schedule_update
+assert selection
+assert stat
+assert toggle_exec
+assert toggle_open
+assert toggles
+
+____ = None
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/client.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/client.py
new file mode 100644
index 00000000..b5086908
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/client.py
@@ -0,0 +1,217 @@
+from asyncio import (
+ FIRST_COMPLETED,
+ AbstractEventLoop,
+ Event,
+ Lock,
+ Task,
+ create_task,
+ gather,
+ get_running_loop,
+ wait,
+ wrap_future,
+)
+from concurrent.futures import Future, ThreadPoolExecutor
+from contextlib import AbstractAsyncContextManager, suppress
+from functools import wraps
+from logging import DEBUG as DEBUG_LVL
+from logging import INFO
+from multiprocessing import cpu_count
+from pathlib import Path
+from platform import uname
+from string import Template
+from sys import executable, exit
+from textwrap import dedent
+from time import monotonic
+from typing import Any, Optional, Sequence, cast
+
+from pynvim_pp.highlight import highlight
+from pynvim_pp.logging import log, suppress_and_log
+from pynvim_pp.nvim import Nvim, conn
+from pynvim_pp.rpc_types import (
+ Method,
+ MsgType,
+ NvimError,
+ RPCallable,
+ RPClient,
+ ServerAddr,
+)
+from pynvim_pp.types import NoneType
+from std2.asyncio import cancel
+from std2.cell import RefCell
+from std2.contextlib import nullacontext
+from std2.pickle.types import DecodeError
+from std2.platform import OS, os
+from std2.sched import aticker
+from std2.sys import autodie
+
+from ._registry import ____
+from .consts import DEBUG, RENDER_RETRIES
+from .registry import autocmd, dequeue_event, enqueue_event, rpc
+from .settings.load import initial as initial_settings
+from .settings.localization import init as init_locale
+from .state.load import initial as initial_state
+from .state.types import State
+from .timeit import timeit
+from .transitions.autocmds import setup
+from .transitions.redraw import redraw
+from .transitions.schedule_update import scheduled_update
+from .transitions.types import Stage
+
+assert ____ or True
+
+_CB = RPCallable[Optional[Stage]]
+
+
+def _autodie(ppid: int) -> AbstractAsyncContextManager:
+ if os is OS.windows:
+ return nullacontext(None)
+ else:
+ return autodie(ppid)
+
+
+async def _profile(t1: float) -> None:
+ t2 = monotonic()
+ info = uname()
+ msg = f"""
+ First msg {int((t2 - t1) * 1000)}ms
+ Arch {info.machine}
+ Processor {info.processor}
+ Cores {cpu_count()}
+ System {info.system}
+ Version {info.version}
+ Python {Path(executable).resolve(strict=True)}
+ """
+ await Nvim.write(dedent(msg))
+
+
+async def _sched(ref: RefCell[State]) -> None:
+ await enqueue_event(False, method=scheduled_update.method, params=(True,))
+
+ async for _ in aticker(ref.val.settings.polling_rate, immediately=False):
+ if ref.val.vim_focus:
+ await enqueue_event(False, method=scheduled_update.method)
+
+
+def _trans(handler: _CB) -> _CB:
+ @wraps(handler)
+ async def f(*params: Any) -> None:
+ await enqueue_event(True, method=handler.method, params=params)
+
+ return cast(_CB, f)
+
+
+async def _default(_: MsgType, method: Method, params: Sequence[Any]) -> None:
+ await enqueue_event(True, method=method, params=params)
+
+
+async def _go(loop: AbstractEventLoop, client: RPClient) -> None:
+ th = ThreadPoolExecutor()
+ atomic, handlers = rpc.drain()
+ try:
+ settings = await initial_settings(handlers.values())
+ except DecodeError as e:
+ tpl = """
+ Some options may have changed.
+ See help doc on Github under [docs/CONFIGURATION.md]
+
+
+ ${e}
+ """
+ ms = Template(dedent(tpl)).substitute(e=e)
+ await Nvim.write(ms, error=True)
+ exit(1)
+ else:
+ hl = highlight(*settings.view.hl_context.groups)
+ await (atomic + autocmd.drain() + hl).commit(NoneType)
+ state = RefCell(await initial_state(settings, th=th))
+
+ init_locale(settings.lang)
+ with suppress_and_log():
+ await setup(settings)
+
+ for f in handlers.values():
+ ff = _trans(f)
+ client.register(ff)
+
+ staged = RefCell[Optional[Stage]](None)
+ event = Event()
+ lock = Lock()
+
+ async def step(method: Method, params: Sequence[Any]) -> None:
+ if handler := cast(Optional[_CB], handlers.get(method)):
+ with suppress_and_log():
+ async with lock:
+ if stage := await handler(state.val, *params):
+ state.val = stage.state
+ staged.val = stage
+ event.set()
+ else:
+ assert False, (method, params)
+
+ async def c1() -> None:
+ transcient: Optional[Task] = None
+ get: Optional[Task] = None
+ try:
+ while True:
+ with suppress_and_log():
+ get = create_task(dequeue_event())
+ if transcient:
+ await wait((transcient, get), return_when=FIRST_COMPLETED)
+ if not transcient.done():
+ with timeit("transcient"):
+ await cancel(transcient)
+ transcient = None
+
+ sync, method, params = await get
+ task = step(method, params=params)
+ if sync:
+ with timeit(method):
+ await task
+ else:
+ transcient = create_task(task)
+ finally:
+ await cancel(
+ *(get or loop.create_future(), transcient or loop.create_future())
+ )
+
+ async def c2() -> None:
+ t1, has_drawn = monotonic(), False
+
+ while True:
+ await event.wait()
+ with suppress_and_log():
+ try:
+ if stage := staged.val:
+ state = stage.state
+
+ for _ in range(RENDER_RETRIES - 1):
+ with suppress(NvimError):
+ await redraw(state, focus=stage.focus)
+ break
+ else:
+ try:
+ await redraw(state, focus=stage.focus)
+ except NvimError as e:
+ log.warn("%s", e)
+
+ if settings.profiling and not has_drawn:
+ has_drawn = True
+ await _profile(t1=t1)
+ finally:
+ event.clear()
+
+ await gather(c1(), c2(), _sched(state))
+
+
+async def init(socket: ServerAddr, ppid: int, th: ThreadPoolExecutor) -> None:
+ loop = get_running_loop()
+ loop.set_default_executor(th)
+ log.setLevel(DEBUG_LVL if DEBUG else INFO)
+
+ die: Future = Future()
+
+ async def cont() -> None:
+ async with conn(die, socket=socket, default=_default) as client:
+ await _go(loop, client=client)
+
+ await gather(wrap_future(die), cont())
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/consts.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/consts.py
new file mode 100644
index 00000000..1fff3629
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/consts.py
@@ -0,0 +1,65 @@
+from os import environ, name
+from pathlib import Path
+
+from chad_types import TOP_LEVEL
+
+GIL_SWITCH = 1 / 1000
+IS_WIN = name == "nt"
+REQUIREMENTS = TOP_LEVEL / "requirements.txt"
+
+DEBUG = "CHADTREE_DEBUG" in environ
+
+BATCH_FACTOR = 88
+RENDER_RETRIES = 3
+
+FM_FILETYPE = "CHADTree"
+FM_HL_PREFIX = "chadtree"
+URI_SCHEME = FM_FILETYPE.casefold()
+
+DEFAULT_LANG = "en"
+LANG_ROOT = TOP_LEVEL / "locale"
+CONFIG_YML = TOP_LEVEL / "config" / "defaults.yml"
+SETTINGS_VAR = "chadtree_settings"
+
+"""
+STORAGE
+"""
+
+_VARS = Path.home() / ".cache/chadtree/vars"
+RT_DIR = _VARS / "runtime"
+RT_PY = RT_DIR / "Scripts" / "python.exe" if IS_WIN else RT_DIR / "bin" / "python3"
+SESSION_DIR = _VARS / "sessions"
+
+
+"""
+Docs
+"""
+
+
+_DOCS_URI_BASE = "https://github.com/ms-jpq/chadtree/blob/chad/docs"
+_DOCS_DIR = TOP_LEVEL / "docs"
+
+
+_README_md = "README.md"
+README_MD = _DOCS_DIR / _README_md
+README_URI = f"{_DOCS_URI_BASE}"
+
+_FEATURES_md = "FEATURES.md"
+FEATURES_MD = _DOCS_DIR / _FEATURES_md
+FEATURES_URI = f"{_DOCS_URI_BASE}/{_FEATURES_md}"
+
+_KEYBIND_md = "KEYBIND.md"
+KEYBIND_MD = _DOCS_DIR / _KEYBIND_md
+KEYBIND_URI = f"{_DOCS_URI_BASE}/{_KEYBIND_md}"
+
+_CONFIGURATION_md = "CONFIGURATION.md"
+CONFIGURATION_MD = _DOCS_DIR / _CONFIGURATION_md
+CONFIGURATION_URI = f"{_DOCS_URI_BASE}/{_CONFIGURATION_md}"
+
+_THEME_md = "THEME.md"
+THEME_MD = _DOCS_DIR / _THEME_md
+THEME_URI = f"{_DOCS_URI_BASE}/{_THEME_md}"
+
+_MIGRATION_md = "MIGRATION.md"
+MIGRATION_MD = _DOCS_DIR / _MIGRATION_md
+MIGRATION_URI = f"{_DOCS_URI_BASE}/{_MIGRATION_md}"
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/cartographer.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/cartographer.py
new file mode 100644
index 00000000..06734879
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/cartographer.py
@@ -0,0 +1,230 @@
+from asyncio import sleep
+from concurrent.futures import ThreadPoolExecutor
+from contextlib import suppress
+from fnmatch import fnmatch
+from os import DirEntry, scandir, stat, stat_result
+from os.path import normcase
+from pathlib import Path, PurePath
+from stat import (
+ S_IFDOOR,
+ S_ISBLK,
+ S_ISCHR,
+ S_ISDIR,
+ S_ISFIFO,
+ S_ISGID,
+ S_ISLNK,
+ S_ISREG,
+ S_ISSOCK,
+ S_ISUID,
+ S_ISVTX,
+ S_IWOTH,
+ S_IXUSR,
+)
+from typing import (
+ AbstractSet,
+ Iterator,
+ Mapping,
+ MutableMapping,
+ Optional,
+ Tuple,
+ Union,
+ cast,
+)
+
+from std2.itertools import batched
+from std2.pathlib import is_relative_to
+
+from ..consts import BATCH_FACTOR
+from ..state.executor import AsyncExecutor
+from ..state.types import Index
+from ..timeit import timeit
+from .nt import is_junction
+from .types import Ignored, Mode, Node
+
+_FILE_MODES: Mapping[int, Mode] = {
+ S_IXUSR: Mode.executable,
+ S_IFDOOR: Mode.door,
+ S_ISGID: Mode.set_gid,
+ S_ISUID: Mode.set_uid,
+ S_ISVTX: Mode.sticky,
+ S_IWOTH: Mode.other_writable,
+ S_IWOTH | S_ISVTX: Mode.sticky_other_writable,
+}
+
+
+def _iter(
+ dirent: Union[PurePath, DirEntry[str]], follow: bool, index: Index, lv: int = 0
+) -> Iterator[PurePath]:
+ if not lv:
+ yield PurePath(dirent)
+ with suppress(NotADirectoryError, FileNotFoundError, PermissionError):
+ with scandir(dirent) as dirents:
+ for child in dirents:
+ yield (path := PurePath(child))
+ if child.is_dir(follow_symlinks=follow) and path in index:
+ yield from _iter(child, follow=follow, index=index, lv=lv + 1)
+
+
+def _fs_modes(stat: stat_result) -> Iterator[Mode]:
+ st_mode = stat.st_mode
+ if S_ISDIR(st_mode):
+ yield Mode.folder
+ if S_ISREG(st_mode):
+ yield Mode.file
+ if S_ISFIFO(st_mode):
+ yield Mode.pipe
+ if S_ISSOCK(st_mode):
+ yield Mode.socket
+ if S_ISCHR(st_mode):
+ yield Mode.char_device
+ if S_ISBLK(st_mode):
+ yield Mode.block_device
+ if stat.st_nlink > 1:
+ yield Mode.multi_hardlink
+ for bit, mode in _FILE_MODES.items():
+ if bit and st_mode & bit == bit:
+ yield mode
+
+
+def _fs_stat(path: PurePath) -> Tuple[AbstractSet[Mode], Optional[PurePath]]:
+ try:
+ info = stat(path, follow_symlinks=False)
+ except (FileNotFoundError, PermissionError):
+ return {Mode.orphan_link}, None
+ else:
+ if S_ISLNK(info.st_mode) or is_junction(info):
+ try:
+ pointed = Path(path).resolve(strict=True)
+ link_info = stat(pointed, follow_symlinks=False)
+ except (FileNotFoundError, NotADirectoryError, RuntimeError):
+ return {Mode.orphan_link}, None
+ else:
+ mode = {*_fs_modes(link_info)}
+ return mode | {Mode.link}, pointed
+ else:
+ mode = {*_fs_modes(info)}
+ return mode, None
+
+
+def _fs_node(path: PurePath) -> Node:
+ mode, pointed = _fs_stat(path)
+ node = Node(
+ path=path,
+ mode=mode,
+ pointed=pointed,
+ children={},
+ )
+ return node
+
+
+def _iter_single_nodes(
+ th: ThreadPoolExecutor, root: PurePath, follow: bool, index: Index
+) -> Iterator[Node]:
+ with timeit("fs->_iter"):
+ dir_stream = batched(_iter(root, index=index, follow=follow), n=BATCH_FACTOR)
+ for seq in th.map(lambda x: tuple(map(_fs_node, x)), dir_stream):
+ yield from seq
+
+
+async def _new(
+ th: ThreadPoolExecutor, root: PurePath, follow_links: bool, index: Index
+) -> Node:
+ nodes: MutableMapping[PurePath, Node] = {}
+
+ for idx, node in enumerate(
+ _iter_single_nodes(th, root=root, follow=follow_links, index=index), start=1
+ ):
+ if idx % BATCH_FACTOR == 0:
+ await sleep(0)
+ nodes[node.path] = node
+ if parent := nodes.get(node.path.parent):
+ if parent == node:
+ continue
+ cast(MutableMapping[PurePath, Node], parent.children)[node.path] = node
+
+ return nodes[root]
+
+
+def _cross_over(root: PurePath, invalid: PurePath) -> bool:
+ return is_relative_to(root, invalid) or is_relative_to(invalid, root)
+
+
+async def _update(
+ th: ThreadPoolExecutor,
+ root: Node,
+ follow_links: bool,
+ index: Index,
+ invalidate_dirs: AbstractSet[PurePath],
+) -> Node:
+ if any((_cross_over(root.path, invalid=invalid) for invalid in invalidate_dirs)):
+ return await _new(th, root=root.path, follow_links=follow_links, index=index)
+ else:
+ children: MutableMapping[PurePath, Node] = {}
+ for path, node in root.children.items():
+ new_node = await _update(
+ th,
+ root=node,
+ follow_links=follow_links,
+ index=index,
+ invalidate_dirs=invalidate_dirs,
+ )
+ children[path] = new_node
+ return Node(
+ path=root.path,
+ mode=root.mode,
+ pointed=root.pointed,
+ children=children,
+ )
+
+
+async def new(
+ exec: AsyncExecutor, root: PurePath, follow_links: bool, index: Index
+) -> Node:
+ with timeit("fs->new"):
+ return await exec.submit(
+ _new(exec.threadpool, root=root, follow_links=follow_links, index=index)
+ )
+
+
+async def update(
+ exec: AsyncExecutor,
+ root: Node,
+ *,
+ follow_links: bool,
+ index: Index,
+ invalidate_dirs: AbstractSet[PurePath],
+) -> Node:
+ with timeit("fs->_update"):
+ try:
+ return await exec.submit(
+ _update(
+ exec.threadpool,
+ root=root,
+ follow_links=follow_links,
+ index=index,
+ invalidate_dirs=invalidate_dirs,
+ )
+ )
+ except FileNotFoundError:
+ return await new(
+ exec, follow_links=follow_links, root=root.path, index=index
+ )
+
+
+def user_ignored(node: Node, ignores: Ignored) -> bool:
+ return (
+ node.path.name in ignores.name_exact
+ or any(fnmatch(node.path.name, pattern) for pattern in ignores.name_glob)
+ or any(fnmatch(normcase(node.path), pattern) for pattern in ignores.path_glob)
+ )
+
+
+def is_dir(node: Node) -> bool:
+ return Mode.folder in node.mode
+
+
+def act_like_dir(node: Node, follow_links: bool) -> bool:
+ if node.pointed and not follow_links:
+ return False
+ else:
+ return is_dir(node)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/nt.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/nt.py
new file mode 100644
index 00000000..a5d687c6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/nt.py
@@ -0,0 +1,13 @@
+import sys
+from os import stat_result
+from stat import S_ISDIR
+
+if sys.platform == "win32":
+
+ def is_junction(st: stat_result) -> bool:
+ return bool(S_ISDIR(st.st_mode) and st.st_reparse_tag)
+
+else:
+
+ def is_junction(st: stat_result) -> bool:
+ return False
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/ops.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/ops.py
new file mode 100644
index 00000000..551b41d2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/ops.py
@@ -0,0 +1,242 @@
+from asyncio import Lock, gather
+from dataclasses import dataclass
+from datetime import datetime
+from functools import lru_cache
+from itertools import chain
+from os import makedirs, readlink
+from os import remove as rm
+from os import stat, symlink
+from os.path import isdir, isfile, normpath
+from pathlib import Path, PurePath
+from shutil import copy2, copytree
+from shutil import move as mv
+from shutil import rmtree
+from shutil import which as _which
+from stat import S_ISDIR, S_ISLNK, filemode
+from typing import AbstractSet, Iterable, Mapping, Optional
+
+from std2.asyncio import to_thread
+from std2.stat import RW_R__R__, RWXR_XR_X
+
+from .nt import is_junction
+
+_FOLDER_MODE = RWXR_XR_X
+_FILE_MODE = RW_R__R__
+
+
+def ancestors(*paths: PurePath) -> AbstractSet[PurePath]:
+ return {*chain.from_iterable(path.parents for path in paths)}
+
+
+def unify_ancestors(paths: AbstractSet[PurePath]) -> AbstractSet[PurePath]:
+ return {p for p in paths if ancestors(p).isdisjoint(paths)}
+
+
+@dataclass(frozen=True)
+class FSstat:
+ permissions: str
+ user: str
+ group: str
+ date_mod: datetime
+ size: int
+ link: Optional[PurePath]
+
+
+@lru_cache(maxsize=None)
+def lock() -> Lock:
+ return Lock()
+
+
+try:
+ from grp import getgrgid
+ from pwd import getpwuid
+
+ def _get_username(uid: int) -> str:
+ try:
+ return getpwuid(uid).pw_name
+ except KeyError:
+ return str(uid)
+
+ def _get_groupname(gid: int) -> str:
+ try:
+ return getgrgid(gid).gr_name
+ except KeyError:
+ return str(gid)
+
+except ImportError:
+
+ def _get_username(uid: int) -> str:
+ return str(uid)
+
+ def _get_groupname(gid: int) -> str:
+ return str(gid)
+
+
+@lru_cache(maxsize=None)
+def which(path: PurePath) -> Optional[PurePath]:
+ if bin := _which(path):
+ return PurePath(bin)
+ else:
+ return None
+
+
+async def fs_stat(path: PurePath) -> FSstat:
+ def cont() -> FSstat:
+ stats = stat(path, follow_symlinks=False)
+ permissions = filemode(stats.st_mode)
+ user = _get_username(stats.st_uid)
+ group = _get_groupname(stats.st_gid)
+ date_mod = datetime.fromtimestamp(stats.st_mtime)
+ size = stats.st_size
+ try:
+ link = (
+ readlink(path) if S_ISLNK(stats.st_mode) or is_junction(stats) else None
+ )
+ except OSError:
+ plink = None
+ else:
+ plink = PurePath(link) if link else None
+ fs_stat = FSstat(
+ permissions=permissions,
+ user=user,
+ group=group,
+ date_mod=date_mod,
+ size=size,
+ link=plink,
+ )
+ return fs_stat
+
+ return await to_thread(cont)
+
+
+async def resolve(path: PurePath, strict: bool) -> Path:
+ def cont() -> Path:
+ return Path(path).resolve(strict=strict)
+
+ return await to_thread(cont)
+
+
+async def exists(path: PurePath, follow: bool) -> bool:
+ def cont() -> bool:
+ try:
+ stat(path, follow_symlinks=follow)
+ except (OSError, ValueError):
+ return False
+ else:
+ return True
+
+ return await to_thread(cont)
+
+
+async def exists_many(
+ paths: Iterable[PurePath], follow: bool
+) -> Mapping[PurePath, bool]:
+ existence = await gather(*(exists(path, follow=follow) for path in paths))
+ return {path: exi for path, exi in zip(paths, existence)}
+
+
+async def is_dir(path: PurePath) -> bool:
+ return await to_thread(lambda: isdir(path))
+
+
+async def is_file(path: PurePath) -> bool:
+ return await to_thread(lambda: isfile(path))
+
+
+def _mkdir_p(path: PurePath) -> None:
+ makedirs(path, mode=_FOLDER_MODE, exist_ok=True)
+
+
+async def _mkdir(path: PurePath) -> None:
+ def cont() -> None:
+ _mkdir_p(path)
+
+ await to_thread(cont)
+
+
+async def mkdir(paths: Iterable[PurePath]) -> None:
+ await gather(*map(_mkdir, paths))
+
+
+async def _new(path: PurePath) -> None:
+ def cont() -> None:
+ makedirs(path.parent, mode=_FOLDER_MODE, exist_ok=True)
+ Path(path).touch(mode=_FILE_MODE, exist_ok=True)
+
+ await to_thread(cont)
+
+
+async def new(paths: Iterable[PurePath]) -> None:
+ async with lock():
+ await gather(*map(_new, paths))
+
+
+async def _rename(src: PurePath, dst: PurePath) -> None:
+ def cont() -> None:
+ makedirs(dst.parent, mode=_FOLDER_MODE, exist_ok=True)
+ mv(normpath(src), normpath(dst))
+
+ await to_thread(cont)
+
+
+async def rename(operations: Mapping[PurePath, PurePath]) -> None:
+ async with lock():
+ await gather(*(_rename(src, dst) for src, dst in operations.items()))
+
+
+async def _remove(path: PurePath) -> None:
+ def cont() -> None:
+ stats = stat(path, follow_symlinks=False)
+ if S_ISDIR(stats.st_mode):
+ rmtree(path)
+ else:
+ rm(path)
+
+ await to_thread(cont)
+
+
+async def remove(paths: Iterable[PurePath]) -> None:
+ async with lock():
+ await gather(*map(_remove, paths))
+
+
+async def _cut(src: PurePath, dst: PurePath) -> None:
+ def cont() -> None:
+ mv(normpath(src), normpath(dst))
+
+ await to_thread(cont)
+
+
+async def cut(operations: Mapping[PurePath, PurePath]) -> None:
+ async with lock():
+ await gather(*(_cut(src, dst) for src, dst in operations.items()))
+
+
+async def _copy(src: PurePath, dst: PurePath) -> None:
+ def cont() -> None:
+ stats = stat(src, follow_symlinks=False)
+ if S_ISDIR(stats.st_mode):
+ copytree(src, dst, symlinks=True, dirs_exist_ok=True)
+ else:
+ copy2(src, dst, follow_symlinks=False)
+
+ await to_thread(cont)
+
+
+async def copy(operations: Mapping[PurePath, PurePath]) -> None:
+ async with lock():
+ await gather(*(_copy(src, dst) for src, dst in operations.items()))
+
+
+async def _link(src: PurePath, dst: PurePath) -> None:
+ def cont() -> None:
+ target_is_directory = isdir(src)
+ _mkdir_p(dst.parent)
+ symlink(normpath(src), normpath(dst), target_is_directory=target_is_directory)
+
+ await to_thread(cont)
+
+
+async def link(operations: Mapping[PurePath, PurePath]) -> None:
+ async with lock():
+ await gather(*(_link(src, dst) for dst, src in operations.items()))
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/types.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/types.py
new file mode 100644
index 00000000..808513c1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/fs/types.py
@@ -0,0 +1,52 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+from enum import IntEnum, auto, unique
+from pathlib import PurePath
+from typing import AbstractSet, Any, Mapping, Optional, Sequence
+
+
+# https://github.com/coreutils/coreutils/blob/master/src/ls.c
+@unique
+class Mode(IntEnum):
+ orphan_link = auto()
+ link = auto()
+
+ pipe = auto()
+ socket = auto()
+ block_device = auto()
+ char_device = auto()
+ door = auto()
+
+ sticky_other_writable = auto()
+ other_writable = auto()
+ sticky = auto()
+ folder = auto()
+
+ set_uid = auto()
+ set_gid = auto()
+ file_w_capacity = auto()
+ executable = auto()
+ multi_hardlink = auto()
+ file = auto()
+
+
+@dataclass
+class _RenderCache:
+ sort_by: Optional[Sequence[Any]] = None
+
+
+@dataclass(frozen=True)
+class Node:
+ mode: AbstractSet[Mode]
+ path: PurePath
+ pointed: Optional[PurePath]
+ children: Mapping[PurePath, Node]
+ cache: _RenderCache = field(default_factory=_RenderCache)
+
+
+@dataclass(frozen=True)
+class Ignored:
+ name_exact: AbstractSet[str]
+ name_glob: Sequence[str]
+ path_glob: Sequence[str]
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/diagnostics.lua b/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/diagnostics.lua
new file mode 100644
index 00000000..ea70dabd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/diagnostics.lua
@@ -0,0 +1,30 @@
+(function(_)
+ if vim.diagnostic then
+ local diagnostics = vim.diagnostic.get(nil, nil)
+ vim.validate({diagnostics = {diagnostics, "table"}})
+ local acc = {}
+ for _, row in pairs(diagnostics) do
+ local buf = row.bufnr
+ local severity = tostring(row.severity)
+ vim.validate(
+ {
+ buf = {buf, "number"},
+ row_severity = {row.severity, "number"}
+ }
+ )
+ if not acc[buf] then
+ acc[buf] = {}
+ end
+ if not acc[buf][severity] then
+ acc[buf][severity] = 0
+ end
+ acc[buf][severity] = acc[buf][severity] + 1
+ end
+ local acc2 = {}
+ for buf, warnings in pairs(acc) do
+ local path = vim.api.nvim_buf_get_name(buf)
+ acc2[path] = warnings
+ end
+ return acc2
+ end
+end)(...)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/diagnostics.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/diagnostics.py
new file mode 100644
index 00000000..979d6874
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/diagnostics.py
@@ -0,0 +1,44 @@
+import sys
+from collections import Counter
+from pathlib import Path, PurePath
+from typing import Mapping, MutableMapping, cast
+
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.types import NoneType
+
+from ..fs.ops import ancestors
+from ..state.types import Diagnostics
+
+_LUA = (
+ Path(__file__).resolve(strict=True).with_name("diagnostics.lua").read_text("UTF-8")
+)
+
+if sys.version_info < (3, 9):
+ _C = Counter
+else:
+ _C = Counter[int]
+
+
+async def poll(min_severity: int) -> Diagnostics:
+ diagnostics: Mapping[str, Mapping[str, int]] = cast(
+ Mapping[str, Mapping[str, int]], await Nvim.fn.luaeval(NoneType, _LUA, ())
+ )
+
+ raw = {
+ PurePath(path): Counter(
+ {
+ s: count
+ for severity, count in (counts or {}).items()
+ if (s := int(severity)) <= min_severity
+ }
+ )
+ for path, counts in (diagnostics or {}).items()
+ }
+
+ acc: MutableMapping[PurePath, _C] = {}
+ for path, counts in raw.items():
+ for parent in ancestors(path):
+ c = acc.setdefault(parent, Counter())
+ c += counts
+
+ return {**acc, **raw}
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/notify.lua b/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/notify.lua
new file mode 100644
index 00000000..cd53990b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/notify.lua
@@ -0,0 +1,9 @@
+(function(args)
+ local method, params = unpack(args)
+ if vim.lsp then
+ local clients = (vim.lsp.get_clients or vim.lsp.get_active_clients)()
+ for _, client in pairs(clients) do
+ client.notify(method, params)
+ end
+ end
+end)(...)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/notify.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/notify.py
new file mode 100644
index 00000000..9d3025ba
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/lsp/notify.py
@@ -0,0 +1,31 @@
+from pathlib import Path, PurePath
+from typing import Any, Iterable, Mapping
+
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.types import NoneType
+
+_LUA = Path(__file__).resolve(strict=True).with_name("notify.lua").read_text("UTF-8")
+
+
+async def _notify(method: str, params: Any) -> None:
+ await Nvim.fn.luaeval(NoneType, _LUA, (method, params))
+
+
+async def lsp_created(paths: Iterable[PurePath]) -> None:
+ params = {"files": tuple({"uri": path.as_uri()} for path in paths)}
+ await _notify("workspace/didCreateFiles", params=params)
+
+
+async def lsp_removed(paths: Iterable[PurePath]) -> None:
+ params = {"files": tuple({"uri": path.as_uri()} for path in paths)}
+ await _notify("workspace/didDeleteFiles", params=params)
+
+
+async def lsp_moved(paths: Mapping[PurePath, PurePath]) -> None:
+ params = {
+ "files": tuple(
+ {"oldUri": old.as_uri(), "newUri": new.as_uri()}
+ for old, new in paths.items()
+ )
+ }
+ await _notify("workspace/didRenameFiles", params=params)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/nvim/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/nvim/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/nvim/markers.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/nvim/markers.py
new file mode 100644
index 00000000..efb03d72
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/nvim/markers.py
@@ -0,0 +1,48 @@
+from asyncio import gather
+from collections import Counter
+from itertools import chain
+from pathlib import PurePath
+from typing import AbstractSet, Mapping, MutableMapping, MutableSet, Sequence, cast
+
+from pynvim_pp.atomic import Atomic
+from pynvim_pp.buffer import Buffer
+from pynvim_pp.nvim import Marker, Nvim
+from pynvim_pp.types import NoneType
+
+from ..fs.ops import ancestors
+from .types import Markers
+
+
+async def _bookmarks() -> Mapping[PurePath, AbstractSet[Marker]]:
+ acc: MutableMapping[PurePath, MutableSet[Marker]] = {}
+ bookmarks = await Nvim.list_bookmarks()
+ for marker, (path, _, _) in bookmarks.items():
+ if path:
+ for marked_path in chain((path,), ancestors(path)):
+ marks = acc.setdefault(marked_path, set())
+ marks.add(marker)
+
+ return acc
+
+
+async def _quickfix() -> Mapping[PurePath, int]:
+ qflist = cast(Sequence[Mapping[str, int]], await Nvim.fn.getqflist(NoneType))
+
+ atomic = Atomic()
+ for q in qflist:
+ bufnr = q["bufnr"]
+ buf = Buffer.from_int(bufnr)
+ atomic.buf_get_name(buf)
+
+ bufnames = cast(Sequence[str], await atomic.commit(NoneType))
+ filenames = tuple(map(PurePath, bufnames))
+ parents = (ancestor for fullname in filenames for ancestor in ancestors(fullname))
+ locations = Counter(chain(filenames, parents))
+
+ return locations
+
+
+async def markers() -> Markers:
+ qf, bm = await gather(_quickfix(), _bookmarks())
+ markers = Markers(quick_fix=qf, bookmarks=bm)
+ return markers
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/nvim/types.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/nvim/types.py
new file mode 100644
index 00000000..5a321540
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/nvim/types.py
@@ -0,0 +1,11 @@
+from dataclasses import dataclass
+from pathlib import PurePath
+from typing import AbstractSet, Mapping
+
+from pynvim_pp.nvim import Marker
+
+
+@dataclass(frozen=True)
+class Markers:
+ quick_fix: Mapping[PurePath, int]
+ bookmarks: Mapping[PurePath, AbstractSet[Marker]]
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/registry.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/registry.py
new file mode 100644
index 00000000..e6e43b61
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/registry.py
@@ -0,0 +1,34 @@
+from asyncio import Queue
+from functools import lru_cache
+from typing import Any, Awaitable, Callable, Sequence, Tuple
+
+from pynvim_pp.autocmd import AutoCMD
+from pynvim_pp.handler import RPC
+from pynvim_pp.rpc_types import Method
+
+_MSG = Tuple[bool, Method, Sequence[Any]]
+
+NAMESPACE = "CHAD"
+
+
+def _name_gen(fn: Callable[..., Awaitable[Any]]) -> str:
+ return fn.__qualname__.lstrip("_").capitalize()
+
+
+@lru_cache(maxsize=None)
+def queue() -> Queue:
+ return Queue()
+
+
+autocmd = AutoCMD()
+rpc = RPC(NAMESPACE, name_gen=_name_gen)
+
+
+async def enqueue_event(sync: bool, method: Method, params: Sequence[Any] = ()) -> None:
+ msg = (sync, method, params)
+ await queue().put(msg)
+
+
+async def dequeue_event() -> _MSG:
+ msg: _MSG = await queue().get()
+ return msg
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/load.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/load.py
new file mode 100644
index 00000000..9b17d889
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/load.py
@@ -0,0 +1,178 @@
+from dataclasses import dataclass
+from enum import Enum, auto
+from locale import strxfrm
+from typing import (
+ AbstractSet,
+ Any,
+ Iterable,
+ Mapping,
+ Optional,
+ Sequence,
+ SupportsFloat,
+ Union,
+ cast,
+)
+
+from pynvim_pp.atomic import Atomic
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.rpc_types import RPCallable
+from pynvim_pp.types import NoneType
+from pynvim_pp.window import Window
+from std2.configparser import hydrate
+from std2.graphlib import merge
+from std2.pickle.decoder import new_decoder
+from std2.pickle.types import DecodeError
+from yaml import safe_load
+
+from chad_types import (
+ ARTIFACT,
+ Artifact,
+ IconColourSetEnum,
+ IconGlyphSetEnum,
+ LSColoursEnum,
+ TextColourSetEnum,
+)
+
+from ..consts import CONFIG_YML, SETTINGS_VAR
+from ..fs.types import Ignored
+from ..registry import NAMESPACE
+from ..view.load import load_theme
+from ..view.types import HLGroups, Sortby, ViewOptions
+from .types import MimetypeOptions, Settings, VersionCtlOpts
+
+
+class _OpenDirection(Enum):
+ left = auto()
+ right = auto()
+
+
+@dataclass(frozen=True)
+class _UserOptions:
+ close_on_open: bool
+ follow: bool
+ follow_links: bool
+ follow_ignore: bool
+ lang: Optional[str]
+ mimetypes: MimetypeOptions
+ page_increment: int
+ polling_rate: SupportsFloat
+ session: bool
+ show_hidden: bool
+ min_diagnostics_severity: int
+ version_control: VersionCtlOpts
+
+
+@dataclass(frozen=True)
+class _UserTheme:
+ highlights: HLGroups
+ icon_glyph_set: IconGlyphSetEnum
+ icon_colour_set: IconColourSetEnum
+ text_colour_set: Union[LSColoursEnum, TextColourSetEnum]
+ discrete_colour_map: Mapping[str, str]
+
+
+@dataclass(frozen=True)
+class _UserView:
+ open_direction: _OpenDirection
+ width: int
+ sort_by: Sequence[Sortby]
+ time_format: str
+ window_options: Mapping[str, Union[bool, str]]
+
+
+@dataclass(frozen=True)
+class _UserConfig:
+ keymap: Mapping[str, AbstractSet[str]]
+ options: _UserOptions
+ idle_timeout: SupportsFloat
+ ignore: Ignored
+ view: _UserView
+ theme: _UserTheme
+ xdg: bool
+ profiling: bool
+
+
+async def initial(specs: Iterable[RPCallable]) -> Settings:
+ a_decode = new_decoder[Artifact](Artifact)
+ c_decode = new_decoder[_UserConfig](_UserConfig)
+
+ win = await Window.get_current()
+ artifacts = a_decode(safe_load(ARTIFACT.read_text("UTF-8")))
+
+ user_config = cast(
+ Mapping[str, Any], await Nvim.vars.get(NoneType, SETTINGS_VAR) or {}
+ )
+ config = c_decode(
+ merge(
+ safe_load(CONFIG_YML.read_text("UTF-8")), hydrate(user_config), replace=True
+ )
+ )
+ options, view, theme = config.options, config.view, config.theme
+
+ atomic = Atomic()
+ for opt in view.window_options:
+ atomic.win_get_option(win, opt)
+ win_opts = cast(Sequence[Union[bool, str]], await atomic.commit(NoneType))
+ win_actual_opts = {k: v for k, v in zip(view.window_options, win_opts)}
+
+ icons, hl_context = load_theme(
+ artifact=artifacts,
+ particular_mappings=theme.highlights,
+ discrete_colours=theme.discrete_colour_map,
+ icon_set=theme.icon_glyph_set,
+ icon_colour_set=theme.icon_colour_set,
+ text_colour_set=theme.text_colour_set,
+ )
+
+ use_icons = theme.icon_glyph_set not in {
+ IconGlyphSetEnum.ascii,
+ IconGlyphSetEnum.ascii_hollow,
+ }
+
+ view_opts = ViewOptions(
+ hl_context=hl_context,
+ icons=icons,
+ sort_by=tuple(view.sort_by),
+ use_icons=use_icons,
+ time_fmt=view.time_format,
+ )
+
+ keymap = {f"{NAMESPACE}.{k.capitalize()}": v for k, v in config.keymap.items()}
+ legal_keys = {f"{NAMESPACE}.{spec.method.capitalize()}" for spec in specs}
+ extra_keys = keymap.keys() - legal_keys
+
+ if extra_keys:
+ raise DecodeError(
+ path=(_UserOptions, sorted(legal_keys, key=strxfrm)),
+ actual=None,
+ missing_keys=(),
+ extra_keys=sorted(extra_keys, key=strxfrm),
+ )
+
+ else:
+ settings = Settings(
+ close_on_open=options.close_on_open,
+ follow=options.follow,
+ follow_links=options.follow_links,
+ follow_ignore=options.follow_ignore,
+ ignores=config.ignore,
+ idle_timeout=float(config.idle_timeout),
+ keymap=keymap,
+ lang=options.lang,
+ mime=options.mimetypes,
+ min_diagnostics_severity=options.min_diagnostics_severity,
+ open_left=view.open_direction is _OpenDirection.left,
+ page_increment=options.page_increment,
+ polling_rate=float(options.polling_rate),
+ session=options.session,
+ show_hidden=options.show_hidden,
+ version_ctl=options.version_control,
+ view=view_opts,
+ width=view.width,
+ win_actual_opts=win_actual_opts,
+ win_local_opts=view.window_options,
+ xdg=config.xdg,
+ profiling=config.profiling,
+ )
+
+ return settings
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/localization.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/localization.py
new file mode 100644
index 00000000..dc8b058f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/localization.py
@@ -0,0 +1,46 @@
+from locale import getlocale
+from string import Template
+from typing import Mapping, MutableMapping, Optional, Union
+
+from std2.pickle.decoder import new_decoder
+from yaml import safe_load
+
+from ..consts import DEFAULT_LANG, LANG_ROOT
+
+
+def _get_lang(code: Optional[str], fallback: str) -> str:
+ if code:
+ return code.casefold()
+ else:
+ tag, _ = getlocale()
+ tag = (tag or fallback).casefold()
+ primary, _, _ = tag.partition("-")
+ lang, _, _ = primary.partition("_")
+ return lang
+
+
+class _Lang:
+ def __init__(self, specs: MutableMapping[str, str]) -> None:
+ self._specs = specs
+
+ def __call__(self, key: str, **kwds: Union[int, float, str]) -> str:
+ spec = self._specs[key]
+ return Template(spec).substitute(kwds)
+
+
+LANG = _Lang({})
+
+
+def init(code: Optional[str]) -> None:
+ decode = new_decoder[Mapping[str, str]](Mapping[str, str])
+
+ lang = _get_lang(code, fallback=DEFAULT_LANG)
+ lang_path = (LANG_ROOT / lang).with_suffix(".yml")
+ yml_path = (
+ lang_path
+ if lang_path.exists()
+ else (LANG_ROOT / DEFAULT_LANG).with_suffix(".yml")
+ )
+
+ specs = decode(safe_load(yml_path.read_text("UTF-8")))
+ LANG._specs.update(specs)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/types.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/types.py
new file mode 100644
index 00000000..c2ba04b5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/settings/types.py
@@ -0,0 +1,42 @@
+from dataclasses import dataclass
+from typing import AbstractSet, Mapping, Optional, Union
+
+from ..fs.types import Ignored
+from ..view.types import ViewOptions
+
+
+@dataclass(frozen=True)
+class VersionCtlOpts:
+ enable: bool
+
+
+@dataclass(frozen=True)
+class MimetypeOptions:
+ warn: AbstractSet[str]
+ allow_exts: AbstractSet[str]
+
+
+@dataclass(frozen=True)
+class Settings:
+ close_on_open: bool
+ follow: bool
+ follow_links: bool
+ follow_ignore: bool
+ ignores: Ignored
+ keymap: Mapping[str, AbstractSet[str]]
+ lang: Optional[str]
+ mime: MimetypeOptions
+ open_left: bool
+ page_increment: int
+ polling_rate: float
+ idle_timeout: float
+ profiling: bool
+ session: bool
+ show_hidden: bool
+ version_ctl: VersionCtlOpts
+ view: ViewOptions
+ width: int
+ win_actual_opts: Mapping[str, Union[bool, str]]
+ win_local_opts: Mapping[str, Union[bool, str]]
+ min_diagnostics_severity: int
+ xdg: bool
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/state/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/state/cache.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/cache.py
new file mode 100644
index 00000000..c89f0650
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/cache.py
@@ -0,0 +1,25 @@
+from functools import cached_property
+
+from ..timeit import timeit
+from ..view.render import render
+from ..view.types import Derived
+from .types import State
+
+
+class DeepState(State):
+ @cached_property
+ def derived(self) -> Derived:
+ with timeit("render"):
+ return render(
+ self.root,
+ settings=self.settings,
+ index=self.index,
+ selection=self.selection,
+ filter_pattern=self.filter_pattern,
+ markers=self.markers,
+ diagnostics=self.diagnostics,
+ vc=self.vc,
+ follow_links=self.follow_links,
+ show_hidden=self.show_hidden,
+ current=self.current,
+ )
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/state/executor.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/executor.py
new file mode 100644
index 00000000..b299d61c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/executor.py
@@ -0,0 +1,56 @@
+from asyncio import (
+ AbstractEventLoop,
+ get_running_loop,
+ run,
+ run_coroutine_threadsafe,
+ wrap_future,
+)
+from concurrent.futures import Future, InvalidStateError, ThreadPoolExecutor
+from contextlib import suppress
+from threading import Thread
+from typing import Any, Awaitable, Callable, Coroutine, TypeVar
+
+_T = TypeVar("_T")
+
+
+class AsyncExecutor:
+ def __init__(self, threadpool: ThreadPoolExecutor) -> None:
+ f: Future = Future()
+ self._fut: Future = Future()
+
+ async def cont() -> None:
+ loop = get_running_loop()
+ if threadpool:
+ loop.set_default_executor(threadpool)
+ f.set_result(loop)
+ main: Coroutine = await wrap_future(self._fut)
+ await main
+
+ self._th = Thread(daemon=True, target=lambda: run(cont()))
+ self._th.start()
+ self.threadpool = threadpool
+ self.loop: AbstractEventLoop = f.result()
+
+ def run(self, main: Awaitable[Any]) -> None:
+ self._fut.set_result(main)
+
+ def fsubmit(self, f: Callable[..., Any], *args: Any, **kwargs: Any) -> Future:
+ fut: Future = Future()
+
+ def cont() -> None:
+ if fut.set_running_or_notify_cancel():
+ try:
+ ret = f(*args, **kwargs)
+ except BaseException as e:
+ with suppress(InvalidStateError):
+ fut.set_exception(e)
+ else:
+ with suppress(InvalidStateError):
+ fut.set_result(ret)
+
+ self.loop.call_soon_threadsafe(cont)
+ return fut
+
+ def submit(self, co: Awaitable[_T]) -> Awaitable[_T]:
+ f = run_coroutine_threadsafe(co, loop=self.loop)
+ return wrap_future(f)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/state/load.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/load.py
new file mode 100644
index 00000000..996520c3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/load.py
@@ -0,0 +1,72 @@
+from asyncio import gather
+from concurrent.futures import ThreadPoolExecutor
+from pathlib import Path
+
+from pynvim_pp.nvim import Nvim
+
+from ..consts import SESSION_DIR
+from ..fs.cartographer import new
+from ..nvim.markers import markers
+from ..settings.types import Settings
+from ..version_ctl.types import VCStatus
+from .cache import DeepState
+from .executor import AsyncExecutor
+from .ops import load_session
+from .types import Selection, Session, State
+
+
+async def initial(settings: Settings, th: ThreadPoolExecutor) -> State:
+ executor = AsyncExecutor(threadpool=th)
+ cwd, marks = await gather(Nvim.getcwd(), markers())
+ storage = (
+ Path(await Nvim.fn.stdpath(str, "cache")) / "chad_sessions"
+ if settings.xdg
+ else SESSION_DIR
+ )
+
+ session = Session(workdir=cwd, storage=storage)
+ stored = await load_session(session) if settings.session else None
+ index = {cwd} | (stored.index if stored else frozenset())
+
+ show_hidden = (
+ stored.show_hidden
+ if stored and stored.show_hidden is not None
+ else settings.show_hidden
+ )
+ enable_vc = (
+ stored.enable_vc
+ if stored and stored.enable_vc is not None
+ else settings.version_ctl.enable
+ )
+
+ selection: Selection = frozenset()
+ node = await new(
+ executor, follow_links=settings.follow_links, root=cwd, index=index
+ )
+ vc = VCStatus()
+
+ current = None
+ filter_pattern = None
+
+ state = DeepState(
+ executor=executor,
+ settings=settings,
+ session=session,
+ vim_focus=True,
+ index=index,
+ selection=selection,
+ filter_pattern=filter_pattern,
+ show_hidden=show_hidden,
+ follow=settings.follow,
+ follow_links=settings.follow_links,
+ follow_ignore=settings.follow_ignore,
+ enable_vc=enable_vc,
+ width=settings.width,
+ root=node,
+ markers=marks,
+ diagnostics={},
+ vc=vc,
+ current=current,
+ window_order={},
+ )
+ return state
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/state/next.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/next.py
new file mode 100644
index 00000000..61f9ff68
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/next.py
@@ -0,0 +1,85 @@
+from pathlib import PurePath
+from typing import AbstractSet, Mapping, Optional, Union, cast
+
+from pynvim_pp.rpc_types import ExtData
+from std2.types import Void, VoidType, or_else
+
+from ..fs.cartographer import update
+from ..fs.types import Node
+from ..nvim.types import Markers
+from ..version_ctl.types import VCStatus
+from .cache import DeepState
+from .types import Diagnostics, FilterPattern, Index, Selection, Session, State
+
+
+async def forward(
+ state: State,
+ *,
+ root: Union[Node, VoidType] = Void,
+ index: Union[Index, VoidType] = Void,
+ selection: Union[Selection, VoidType] = Void,
+ filter_pattern: Union[Optional[FilterPattern], VoidType] = Void,
+ show_hidden: Union[bool, VoidType] = Void,
+ follow: Union[bool, VoidType] = Void,
+ follow_links: Union[bool, VoidType] = Void,
+ follow_ignore: Union[bool, VoidType] = Void,
+ enable_vc: Union[bool, VoidType] = Void,
+ width: Union[int, VoidType] = Void,
+ markers: Union[Markers, VoidType] = Void,
+ diagnostics: Union[Diagnostics, VoidType] = Void,
+ vc: Union[VCStatus, VoidType] = Void,
+ current: Union[PurePath, VoidType] = Void,
+ invalidate_dirs: Union[AbstractSet[PurePath], VoidType] = Void,
+ window_order: Union[Mapping[ExtData, None], VoidType] = Void,
+ session: Union[Session, VoidType] = Void,
+ vim_focus: Union[bool, VoidType] = Void,
+ trace: bool = True,
+) -> State:
+ new_index = or_else(index, state.index)
+ new_selection = or_else(selection, state.selection)
+ new_filter_pattern = or_else(filter_pattern, state.filter_pattern)
+ new_current = or_else(current, state.current)
+ new_follow_links = or_else(follow_links, state.follow_links)
+ new_root = cast(
+ Node,
+ root
+ or (
+ await update(
+ state.executor,
+ root=state.root,
+ follow_links=new_follow_links,
+ index=new_index,
+ invalidate_dirs=invalidate_dirs,
+ )
+ if not isinstance(invalidate_dirs, VoidType)
+ else state.root
+ ),
+ )
+ new_markers = or_else(markers, state.markers)
+ new_vc = or_else(vc, state.vc)
+ new_hidden = or_else(show_hidden, state.show_hidden)
+ new_vim_focus = or_else(vim_focus, state.vim_focus)
+
+ new_state = DeepState(
+ executor=state.executor,
+ settings=state.settings,
+ session=or_else(session, state.session),
+ vim_focus=new_vim_focus,
+ index=new_index,
+ selection=new_selection,
+ filter_pattern=new_filter_pattern,
+ show_hidden=new_hidden,
+ follow=or_else(follow, state.follow),
+ follow_links=new_follow_links,
+ follow_ignore=or_else(follow_ignore, state.follow_ignore),
+ enable_vc=or_else(enable_vc, state.enable_vc),
+ width=or_else(width, state.width),
+ root=new_root,
+ markers=new_markers,
+ diagnostics=or_else(diagnostics, state.diagnostics),
+ vc=new_vc,
+ current=new_current,
+ window_order=or_else(window_order, state.window_order),
+ )
+
+ return new_state
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/state/ops.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/ops.py
new file mode 100644
index 00000000..c860e9c9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/ops.py
@@ -0,0 +1,69 @@
+from hashlib import sha1
+from json import dumps, loads
+from os.path import normcase
+from pathlib import Path, PurePath
+from tempfile import NamedTemporaryFile
+from typing import Any, MutableMapping, Optional
+
+from pynvim_pp.lib import decode, encode
+from std2.asyncio import to_thread
+from std2.pickle.decoder import new_decoder
+from std2.pickle.encoder import new_encoder
+
+from .types import Session, State, StoredSession
+
+_DECODER = new_decoder[StoredSession](StoredSession)
+_ENCODER = new_encoder[StoredSession](StoredSession)
+
+
+def _session_path(cwd: PurePath, storage: Path) -> Path:
+ hashed = sha1(normcase(cwd).encode()).hexdigest()
+ part = storage / hashed
+ return part.with_suffix(".json")
+
+
+async def _load_json(path: Path) -> Optional[Any]:
+ def cont() -> Optional[Any]:
+ try:
+ json = decode(path.read_bytes())
+ except FileNotFoundError:
+ return None
+ else:
+ return loads(json)
+
+ return await to_thread(cont)
+
+
+async def load_session(session: Session) -> StoredSession:
+ load_path = _session_path(session.workdir, storage=session.storage)
+ try:
+ json = await _load_json(load_path)
+ if isinstance(json, MutableMapping):
+ json.pop("bookmarks", None)
+ sessions = _DECODER(json)
+ except Exception:
+ return StoredSession(index=frozenset(), show_hidden=None, enable_vc=None)
+ else:
+ return sessions
+
+
+async def dump_session(state: State) -> None:
+ stored = StoredSession(
+ index=state.index,
+ show_hidden=state.show_hidden,
+ enable_vc=state.enable_vc,
+ )
+
+ json = _ENCODER(stored)
+ path = _session_path(state.session.workdir, storage=state.session.storage)
+ parent = path.parent
+ dumped = encode(dumps(json, ensure_ascii=False, check_circular=False, indent=2))
+
+ def cont() -> None:
+ parent.mkdir(parents=True, exist_ok=True)
+ with NamedTemporaryFile(dir=parent, delete=False) as f:
+ f.write(dumped)
+
+ Path(f.name).replace(path)
+
+ await to_thread(cont)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/state/types.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/types.py
new file mode 100644
index 00000000..09980a87
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/state/types.py
@@ -0,0 +1,63 @@
+from dataclasses import dataclass
+from pathlib import Path, PurePath
+from typing import AbstractSet, Mapping, Optional
+
+from pynvim_pp.rpc_types import ExtData
+
+from ..fs.types import Node
+from ..nvim.types import Markers
+from ..settings.types import Settings
+from ..version_ctl.types import VCStatus
+from ..view.types import Derived
+from .executor import AsyncExecutor
+
+Index = AbstractSet[PurePath]
+Selection = Index
+Diagnostics = Mapping[PurePath, Mapping[int, int]]
+
+
+@dataclass(frozen=True)
+class FilterPattern:
+ pattern: str
+
+
+@dataclass(frozen=True)
+class Session:
+ workdir: PurePath
+ storage: Path
+
+
+@dataclass(frozen=True)
+class State:
+ executor: AsyncExecutor
+ settings: Settings
+ session: Session
+ follow_links: bool
+ follow_ignore: bool
+ vim_focus: bool
+ current: Optional[PurePath]
+ enable_vc: bool
+ filter_pattern: Optional[FilterPattern]
+ follow: bool
+ index: Index
+ markers: Markers
+ root: Node
+ selection: Selection
+ show_hidden: bool
+ vc: VCStatus
+ width: int
+ diagnostics: Diagnostics
+ window_order: Mapping[ExtData, None]
+
+ @property
+ def derived(self) -> Derived:
+ raise NotImplementedError()
+
+
+@dataclass(frozen=True)
+class StoredSession:
+ # TODO: sync across sessions
+ # pid: int
+ index: Index
+ show_hidden: Optional[bool]
+ enable_vc: Optional[bool]
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/timeit.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/timeit.py
new file mode 100644
index 00000000..c1112de2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/timeit.py
@@ -0,0 +1,35 @@
+from contextlib import contextmanager
+from typing import Any, Iterator, MutableMapping, Optional, Tuple
+
+from pynvim_pp.logging import log
+from std2.locale import si_prefixed_smol
+from std2.timeit import timeit as _timeit
+
+from .consts import DEBUG
+
+_RECORDS: MutableMapping[str, Tuple[int, float]] = {}
+
+
+@contextmanager
+def timeit(
+ name: str, *args: Any, force: bool = False, warn: Optional[float] = None
+) -> Iterator[None]:
+ if DEBUG or force or warn is not None:
+ with _timeit() as t:
+ yield None
+ delta = t().total_seconds()
+ if DEBUG or force or delta >= (warn or 0):
+ times, cum = _RECORDS.get(name, (0, 0))
+ tt, c = times + 1, cum + delta
+ _RECORDS[name] = tt, c
+
+ label = name.ljust(50)
+ time = f"{si_prefixed_smol(delta, precision=0)}s".ljust(8)
+ ttime = f"{si_prefixed_smol(c / tt, precision=0)}s".ljust(8)
+ msg = f"TIME -- {label} :: {time} @ {ttime} {' '.join(map(str, args))}"
+ if force:
+ log.info("%s", msg)
+ else:
+ log.debug("%s", msg)
+ else:
+ yield None
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/autocmds.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/autocmds.py
new file mode 100644
index 00000000..95e78554
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/autocmds.py
@@ -0,0 +1,199 @@
+from asyncio import Task, create_task, sleep
+from collections.abc import Sequence
+from itertools import chain
+from typing import Optional
+
+from pynvim_pp.buffer import Buffer
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.rpc_types import NvimError
+from pynvim_pp.window import Window
+from std2.asyncio import cancel
+from std2.cell import RefCell
+
+from ..consts import FM_FILETYPE, URI_SCHEME
+from ..fs.ops import ancestors, is_file
+from ..lsp.diagnostics import poll
+from ..nvim.markers import markers
+from ..registry import NAMESPACE, autocmd, rpc
+from ..settings.types import Settings
+from ..state.next import forward
+from ..state.ops import dump_session
+from ..state.types import State
+from .shared.current import new_current_file, new_root
+from .shared.wm import (
+ find_current_buffer_path,
+ find_fm_buffers,
+ is_fm_buf_name,
+ is_fm_buffer,
+ restore_non_fm_win,
+ setup_fm_buf,
+)
+from .types import Stage
+
+_CELL = RefCell[Optional[Task]](None)
+
+
+async def _setup_fm_win(settings: Settings, win: Window) -> None:
+ for key, val in settings.win_local_opts.items():
+ await win.opts.set(key, val=val)
+
+
+async def setup(settings: Settings) -> None:
+ async for buf in find_fm_buffers():
+ await setup_fm_buf(settings, buf=buf)
+ for win in await Window.list():
+ buf = await win.get_buf()
+ if await is_fm_buffer(buf):
+ await _setup_fm_win(settings, win=win)
+
+
+@rpc(blocking=False)
+async def _when_idle(state: State) -> None:
+ if task := _CELL.val:
+ _CELL.val = None
+ await cancel(task)
+
+ async def cont() -> None:
+ await sleep(state.settings.idle_timeout)
+ diagnostics = await poll(state.settings.min_diagnostics_severity)
+ await forward(state, diagnostics=diagnostics)
+
+ _CELL.val = create_task(cont())
+
+
+_ = autocmd("CursorHold", "CursorHoldI") << f"lua {NAMESPACE}.{_when_idle.method}()"
+
+
+@rpc(blocking=False)
+async def save_session(state: State) -> None:
+ """
+ Save CHADTree state
+ """
+
+ await dump_session(state)
+
+
+_ = autocmd("ExitPre") << f"lua {NAMESPACE}.{save_session.method}()"
+_ = (
+ autocmd("User", modifiers=("CHADSave",))
+ << f"lua {NAMESPACE}.{save_session.method}()"
+)
+
+
+@rpc(blocking=False)
+async def focus_lost(state: State) -> Stage:
+ """
+ Save CHADTree state
+ """
+
+ await dump_session(state)
+ new_state = await forward(state, vim_focus=False)
+ return Stage(new_state)
+
+
+_ = autocmd("FocusLost") << f"lua {NAMESPACE}.{focus_lost.method}()"
+
+
+@rpc(blocking=False)
+async def _focus_gained(state: State) -> Stage:
+ """ """
+
+ new_state = await forward(state, vim_focus=True)
+ return Stage(new_state)
+
+
+_ = autocmd("FocusGained") << f"lua {NAMESPACE}.{_focus_gained.method}()"
+
+
+@rpc(blocking=False)
+async def _record_win_pos(state: State) -> Stage:
+ """
+ Record last windows
+ """
+
+ win = await Window.get_current()
+ win_id = win.data
+
+ window_order = {
+ wid: None
+ for wid in chain(
+ (wid for wid in state.window_order if wid != win_id), (win_id,)
+ )
+ }
+ new_state = await forward(state, window_order=window_order)
+ return Stage(new_state)
+
+
+_ = autocmd("WinEnter") << f"lua {NAMESPACE}.{_record_win_pos.method}()"
+
+
+@rpc(blocking=False)
+async def _changedir(state: State) -> Stage:
+ """
+ Follow cwd update
+ """
+
+ cwd = await Nvim.getcwd()
+ new_state = await new_root(state, new_cwd=cwd, indices=frozenset())
+ return Stage(new_state)
+
+
+_ = autocmd("DirChanged") << f"lua {NAMESPACE}.{_changedir.method}()"
+
+
+@rpc(blocking=False)
+async def _restore(state: State, args: Sequence[str]) -> None:
+ win = await Window.get_current()
+ await restore_non_fm_win(state.settings.win_actual_opts, win=win)
+
+
+@rpc(blocking=False)
+async def _update_follow(state: State) -> Optional[Stage]:
+ """
+ Follow buffer
+ """
+
+ win = await Window.get_current()
+ buf = await Buffer.get_current()
+ name = await buf.get_name()
+ is_fm_win = await win.vars.get(bool, URI_SCHEME)
+ is_fm_buf = await buf.filetype() == FM_FILETYPE
+ is_fm_uri = name and is_fm_buf_name(name)
+
+ if is_fm_win and not is_fm_buf:
+ await restore_non_fm_win(state.settings.win_actual_opts, win=win)
+
+ if is_fm_uri or is_fm_buf and not is_fm_win:
+ await _setup_fm_win(state.settings, win=win)
+
+ if is_fm_uri and not is_fm_buf:
+ await setup_fm_buf(state.settings, buf=buf)
+
+ try:
+ if (current := await find_current_buffer_path(name)) and await is_file(current):
+ if state.vc.ignored & {current, *ancestors(current)}:
+ return None
+ else:
+ stage = await new_current_file(state, current=current)
+ return stage
+ else:
+ return None
+ except NvimError:
+ return None
+
+
+_ = autocmd("BufEnter") << f"lua {NAMESPACE}.{_update_follow.method}()"
+
+
+@rpc(blocking=False)
+async def _update_markers(state: State) -> Stage:
+ """
+ Update markers
+ """
+
+ mks = await markers()
+ new_state = await forward(state, markers=mks)
+ return Stage(new_state)
+
+
+_ = autocmd("QuickfixCmdPost") << f"lua {NAMESPACE}.{_update_markers.method}()"
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/click.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/click.py
new file mode 100644
index 00000000..5d585854
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/click.py
@@ -0,0 +1,108 @@
+from typing import Optional
+
+from pynvim_pp.nvim import Nvim
+from std2 import anext
+
+from ..fs.cartographer import is_dir
+from ..fs.types import Mode
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.next import forward
+from ..state.types import State
+from .shared.index import indices
+from .shared.open_file import open_file
+from .shared.wm import find_fm_windows
+from .types import ClickType, Stage
+
+
+async def _click(
+ state: State, is_visual: bool, click_type: ClickType
+) -> Optional[Stage]:
+ node = await anext(indices(state, is_visual=is_visual), None)
+
+ if not node:
+ return None
+ else:
+ if Mode.orphan_link in node.mode:
+ await Nvim.write(LANG("dead_link", name=node.path.name), error=True)
+ return None
+ else:
+ if is_dir(node):
+ if node.path == state.root.path:
+ return None
+ elif node.pointed and not state.follow_links:
+ return None
+ elif state.filter_pattern:
+ await Nvim.write(LANG("filter_click"))
+ return None
+ else:
+ index = state.index ^ {node.path}
+ invalidate_dirs = {node.path}
+ new_state = await forward(
+ state,
+ index=index,
+ invalidate_dirs=invalidate_dirs,
+ )
+ return Stage(new_state)
+ else:
+ nxt = await open_file(
+ state,
+ path=node.path,
+ click_type=click_type,
+ )
+
+ if state.settings.close_on_open and click_type != ClickType.secondary:
+ async for win, _ in find_fm_windows():
+ await win.close()
+
+ return nxt
+
+
+@rpc(blocking=False)
+async def _primary(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Folders -> toggle
+ File -> open
+ """
+
+ return await _click(state, is_visual=is_visual, click_type=ClickType.primary)
+
+
+@rpc(blocking=False)
+async def _secondary(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Folders -> toggle
+ File -> preview
+ """
+
+ return await _click(state, is_visual=is_visual, click_type=ClickType.secondary)
+
+
+@rpc(blocking=False)
+async def _tertiary(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Folders -> toggle
+ File -> open in new tab
+ """
+
+ return await _click(state, is_visual=is_visual, click_type=ClickType.tertiary)
+
+
+@rpc(blocking=False)
+async def _v_split(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Folders -> toggle
+ File -> open in vertical split
+ """
+
+ return await _click(state, is_visual=is_visual, click_type=ClickType.v_split)
+
+
+@rpc(blocking=False)
+async def _h_split(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Folders -> toggle
+ File -> open in horizontal split
+ """
+
+ return await _click(state, is_visual=is_visual, click_type=ClickType.h_split)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/collapse.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/collapse.py
new file mode 100644
index 00000000..4d21342b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/collapse.py
@@ -0,0 +1,38 @@
+from typing import Optional
+
+from std2 import anext
+
+from ..fs.cartographer import act_like_dir
+from ..fs.ops import ancestors
+from ..registry import rpc
+from ..state.next import forward
+from ..state.types import State
+from .shared.index import indices
+from .types import Stage
+
+
+@rpc(blocking=False)
+async def _collapse(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Collapse folder
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ if act_like_dir(node, follow_links=state.follow_links):
+ path = node.path if node.path in state.index else node.path.parent
+ else:
+ path = node.path.parent
+
+ paths = {
+ indexed
+ for indexed in state.index
+ if path in (ancestors(indexed) | {indexed})
+ }
+
+ index = (state.index - paths) | {state.root.path}
+ invalidate_dirs = {path}
+ new_state = await forward(state, index=index, invalidate_dirs=invalidate_dirs)
+ return Stage(new_state, focus=path)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/copy_name.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/copy_name.py
new file mode 100644
index 00000000..fcf5abee
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/copy_name.py
@@ -0,0 +1,75 @@
+from locale import strxfrm
+from os import linesep
+from os.path import normpath, sep
+from pathlib import PurePath
+from typing import AsyncIterator, Callable
+
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.types import NoneType
+
+from ..fs.cartographer import is_dir
+from ..fs.ops import is_dir as iis_dir
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.types import State
+from .shared.index import indices
+
+
+async def _cn(state: State, is_visual: bool, proc: Callable[[PurePath], str]) -> None:
+ async def gen_paths() -> AsyncIterator[str]:
+ if selection := state.selection:
+ for path in selection:
+ suffix = sep if await iis_dir(path) else ""
+ yield proc(path) + suffix
+ else:
+ nodes = indices(state, is_visual=is_visual)
+ async for node in nodes:
+ suffix = sep if is_dir(node) else ""
+ yield proc(node.path) + suffix
+
+ paths = sorted([path async for path in gen_paths()], key=strxfrm)
+ clip = linesep.join(paths)
+ copied_paths = ", ".join(paths)
+
+ await Nvim.fn.setreg(NoneType, "+", clip)
+ await Nvim.fn.setreg(NoneType, "*", clip)
+ await Nvim.write(LANG("copy_paths", copied_paths=copied_paths))
+
+
+@rpc(blocking=False)
+async def _copy_name(state: State, is_visual: bool) -> None:
+ """
+ Copy dirname / filename
+ """
+
+ await _cn(
+ state,
+ is_visual=is_visual,
+ proc=lambda p: normpath(p.name),
+ )
+
+
+@rpc(blocking=False)
+async def _copy_basename(state: State, is_visual: bool) -> None:
+ """
+ Copy basename of dirname / filename
+ """
+
+ await _cn(
+ state,
+ is_visual=is_visual,
+ proc=normpath,
+ )
+
+
+@rpc(blocking=False)
+async def _copy_relname(state: State, is_visual: bool) -> None:
+ """
+ Copy relname of dirname / filename
+ """
+
+ await _cn(
+ state,
+ is_visual=is_visual,
+ proc=lambda p: normpath(p.relative_to(state.root.path)),
+ )
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/cut_copy.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/cut_copy.py
new file mode 100644
index 00000000..eee7de95
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/cut_copy.py
@@ -0,0 +1,171 @@
+from itertools import chain
+from os import linesep
+from pathlib import PurePath
+from typing import AbstractSet, Awaitable, Callable, Mapping, MutableMapping, Optional
+
+from pynvim_pp.nvim import Nvim
+from std2 import anext
+from std2.locale import pathsort_key
+
+from ..fs.cartographer import act_like_dir
+from ..fs.ops import ancestors, copy, cut, exists, unify_ancestors
+from ..fs.types import Node
+from ..lsp.notify import lsp_created, lsp_moved
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.next import forward
+from ..state.types import State
+from ..view.ops import display_path
+from .shared.index import indices
+from .shared.refresh import refresh
+from .shared.wm import kill_buffers
+from .types import Stage
+
+
+def _find_dest(src: PurePath, node: Node, follow_links: bool) -> PurePath:
+ parent = (
+ node.path if act_like_dir(node, follow_links=follow_links) else node.path.parent
+ )
+ dst = parent / src.name
+ return dst
+
+
+async def _operation(
+ *,
+ state: State,
+ is_visual: bool,
+ nono: AbstractSet[PurePath],
+ op_name: str,
+ is_move: bool,
+ action: Callable[[Mapping[PurePath, PurePath]], Awaitable[None]],
+) -> Optional[Stage]:
+ node = await anext(indices(state, is_visual=is_visual), None)
+ selection = state.selection
+ unified = unify_ancestors(selection)
+
+ if not unified or not node:
+ await Nvim.write(LANG("nothing_select"), error=True)
+ return None
+ elif not unified.isdisjoint(nono):
+ await Nvim.write(LANG("operation not permitted on root"), error=True)
+ return None
+ else:
+ pre_operations = {
+ src: _find_dest(src, node=node, follow_links=state.follow_links)
+ for src in unified
+ }
+ pre_existing = {
+ s: d for s, d in pre_operations.items() if await exists(d, follow=False)
+ }
+
+ new_operations: MutableMapping[PurePath, PurePath] = {}
+ while pre_existing:
+ source, dest = pre_existing.popitem()
+ resp = await Nvim.input(question=LANG("path_exists_err"), default=dest.name)
+ new_dest = dest.parent / resp if resp else None
+
+ if not new_dest:
+ pre_existing[source] = dest
+ break
+ elif await exists(new_dest, follow=False):
+ pre_existing[source] = new_dest
+ else:
+ new_operations[source] = new_dest
+
+ if pre_existing:
+ msg = linesep.join(
+ f"{display_path(s, state=state)} -> {display_path(d, state=state)}"
+ for s, d in sorted(
+ pre_existing.items(), key=lambda t: pathsort_key(t[0])
+ )
+ )
+ await Nvim.write(
+ LANG("paths already exist", operation=op_name, paths=msg),
+ error=True,
+ )
+ return None
+
+ else:
+ operations = {**pre_operations, **new_operations}
+ msg = linesep.join(
+ f"{display_path(s, state=state)} -> {display_path(d, state=state)}"
+ for s, d in sorted(operations.items(), key=lambda t: pathsort_key(t[0]))
+ )
+
+ question = LANG("confirm op", operation=op_name, paths=msg)
+ ans = await Nvim.confirm(
+ question=question,
+ answers=LANG("ask_yesno"),
+ answer_key={1: True, 2: False},
+ )
+
+ if not ans:
+ return None
+ else:
+ try:
+ await action(operations)
+ except Exception as e:
+ await Nvim.write(e, error=True)
+ return await refresh(state)
+ else:
+ parents = {
+ p.parent for p in chain(operations.keys(), operations.values())
+ }
+ invalidate_dirs = parents
+ index = state.index | parents
+ new_selection = {*operations.values()}
+ new_state = await forward(
+ state,
+ index=index,
+ selection=new_selection if is_move else selection,
+ invalidate_dirs=invalidate_dirs,
+ )
+ focus = next(
+ iter(sorted(new_selection, key=pathsort_key)),
+ None,
+ )
+
+ if is_move:
+ await kill_buffers(
+ last_used=new_state.window_order,
+ paths=selection,
+ reopen={},
+ )
+ await lsp_moved(operations)
+ else:
+ await lsp_created(new_selection)
+ return Stage(new_state, focus=focus)
+
+
+@rpc(blocking=False)
+async def _cut(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Cut selected
+ """
+
+ cwd, root = await Nvim.getcwd(), state.root.path
+ nono = {cwd, root} | ancestors(cwd, root)
+ return await _operation(
+ state=state,
+ is_visual=is_visual,
+ nono=nono,
+ op_name=LANG("cut"),
+ action=cut,
+ is_move=True,
+ )
+
+
+@rpc(blocking=False)
+async def _copy(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Copy selected
+ """
+
+ return await _operation(
+ state=state,
+ is_visual=is_visual,
+ nono=frozenset(),
+ op_name=LANG("copy"),
+ action=copy,
+ is_move=False,
+ )
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/delete.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/delete.py
new file mode 100644
index 00000000..ff71d75b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/delete.py
@@ -0,0 +1,102 @@
+from locale import strxfrm
+from os import linesep
+from pathlib import PurePath
+from subprocess import CalledProcessError
+from typing import Awaitable, Callable, Iterable, Optional
+
+from pynvim_pp.nvim import Nvim
+from std2.asyncio.subprocess import call
+
+from ..fs.ops import ancestors, remove, unify_ancestors, which
+from ..lsp.notify import lsp_removed
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.next import forward
+from ..state.types import State
+from ..view.ops import display_path
+from .shared.index import indices
+from .shared.refresh import refresh
+from .shared.wm import kill_buffers
+from .types import Stage
+
+
+async def _remove(
+ state: State,
+ is_visual: bool,
+ yeet: Callable[[Iterable[PurePath]], Awaitable[None]],
+) -> Optional[Stage]:
+ cwd, root = await Nvim.getcwd(), state.root.path
+ nono = {cwd, root} | ancestors(cwd, root)
+
+ selection = state.selection or {
+ node.path async for node in indices(state, is_visual=is_visual)
+ }
+ unified = unify_ancestors(selection)
+
+ if not unified:
+ return None
+ elif not unified.isdisjoint(nono):
+ await Nvim.write(LANG("operation not permitted on root"), error=True)
+ return None
+ else:
+ display_paths = linesep.join(
+ sorted((display_path(path, state=state) for path in unified), key=strxfrm)
+ )
+
+ question = LANG("ask_trash", display_paths=display_paths)
+ ans = await Nvim.confirm(
+ question=question,
+ answers=LANG("ask_yesno"),
+ answer_key={1: True, 2: False},
+ )
+
+ if not ans:
+ return None
+ else:
+ try:
+ await yeet(unified)
+ except Exception as e:
+ await Nvim.write(e, error=True)
+ return await refresh(state)
+ else:
+ invalidate_dirs = {path.parent for path in unified}
+ new_state = await forward(
+ state, selection=frozenset(), invalidate_dirs=invalidate_dirs
+ )
+
+ await kill_buffers(
+ last_used=new_state.window_order, paths=selection, reopen={}
+ )
+ await lsp_removed(unified)
+ return Stage(new_state)
+
+
+@rpc(blocking=False)
+async def _delete(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Delete selected
+ """
+
+ return await _remove(state, is_visual=is_visual, yeet=remove)
+
+
+async def _sys_trash(paths: Iterable[PurePath]) -> None:
+ cwd = await Nvim.getcwd()
+
+ if arg0 := which("trash"):
+ try:
+ await call(arg0, "--", *map(str, paths), cwd=cwd)
+ except CalledProcessError as e:
+ await Nvim.write(e, e.stderr, e.stdout, error=True)
+
+ else:
+ await Nvim.write(LANG("sys_trash_err"), error=True)
+
+
+@rpc(blocking=False)
+async def _trash(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Delete selected
+ """
+
+ return await _remove(state, is_visual=is_visual, yeet=_sys_trash)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/filter.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/filter.py
new file mode 100644
index 00000000..a74fde4e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/filter.py
@@ -0,0 +1,48 @@
+from typing import Optional
+
+from pynvim_pp.nvim import Nvim
+from std2 import anext
+
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.next import forward
+from ..state.types import FilterPattern, Selection, State
+from .shared.index import indices
+from .types import Stage
+
+
+@rpc(blocking=False)
+async def _clear_filter(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Clear filter
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ focus = node.path
+ new_state = await forward(state, filter_pattern=None)
+ return Stage(new_state, focus=focus)
+
+
+@rpc(blocking=False)
+async def _filter(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Update filter
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ focus = node.path
+ old_p = state.filter_pattern.pattern if state.filter_pattern else ""
+ pattern = await Nvim.input(question=LANG("new_filter"), default=old_p)
+
+ filter_pattern = FilterPattern(pattern=pattern) if pattern else None
+ selection: Selection = state.selection if filter_pattern else frozenset()
+ new_state = await forward(
+ state, selection=selection, filter_pattern=filter_pattern
+ )
+ return Stage(new_state, focus=focus)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/focus.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/focus.py
new file mode 100644
index 00000000..307def10
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/focus.py
@@ -0,0 +1,105 @@
+from os.path import normcase, normpath
+from pathlib import PurePath
+from typing import Optional
+
+from pynvim_pp.nvim import Nvim
+from std2 import anext
+
+from ..fs.cartographer import act_like_dir
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.types import State
+from .shared.current import maybe_path_above, new_current_file, new_root
+from .shared.index import indices
+from .types import Stage
+
+
+async def _jump(state: State, path: PurePath) -> Optional[Stage]:
+ if new_state := await maybe_path_above(state, paths={path}):
+ return Stage(new_state, focus=path)
+ elif stage := await new_current_file(state, current=path):
+ return Stage(stage.state, focus=path)
+ else:
+ return None
+
+
+@rpc(blocking=False)
+async def _jump_to_current(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Jump to active file
+ """
+
+ if not (curr := state.current):
+ return None
+ else:
+ return await _jump(state, path=curr)
+
+
+@rpc(blocking=False)
+async def _refocus(state: State, is_visual: bool) -> Stage:
+ """
+ Follow cwd update
+ """
+
+ cwd = await Nvim.getcwd()
+ new_state = await new_root(state, new_cwd=cwd, indices=frozenset())
+ focus = new_state.root.path
+ return Stage(new_state, focus=focus)
+
+
+@rpc(blocking=False)
+async def _change_dir(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Change root directory
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ cwd = (
+ node.path
+ if act_like_dir(node, follow_links=state.follow_links)
+ else node.path.parent
+ )
+ new_state = await new_root(state, new_cwd=cwd, indices=frozenset())
+ escaped = await Nvim.fn.fnameescape(str, normcase(new_state.root.path))
+ await Nvim.exec(f"chdir {escaped}")
+ await Nvim.write(LANG("new cwd", cwd=normpath(new_state.root.path)))
+ return Stage(new_state, focus=new_state.root.path)
+
+
+@rpc(blocking=False)
+async def _change_focus(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Refocus root directory
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ new_base = (
+ node.path
+ if act_like_dir(node, follow_links=state.follow_links)
+ else node.path.parent
+ )
+ new_state = await new_root(state, new_cwd=new_base, indices=frozenset())
+ focus = node.path
+ return Stage(new_state, focus=focus)
+
+
+@rpc(blocking=False)
+async def _change_focus_up(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Refocus root directory up
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ new_state = await new_root(
+ state, new_cwd=state.root.path.parent, indices=frozenset()
+ )
+ return Stage(new_state, focus=node.path)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/help.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/help.py
new file mode 100644
index 00000000..00347dae
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/help.py
@@ -0,0 +1,95 @@
+from enum import Enum, auto
+from pathlib import Path
+from typing import Sequence, Tuple
+from uuid import uuid4
+from webbrowser import open as open_w
+
+from pynvim_pp.buffer import Buffer
+from pynvim_pp.float_win import list_floatwins, open_float_win
+from pynvim_pp.nvim import Nvim
+from std2.argparse import ArgparseError, ArgParser
+from std2.types import never
+
+from ..consts import (
+ CONFIGURATION_MD,
+ CONFIGURATION_URI,
+ FEATURES_MD,
+ FEATURES_URI,
+ KEYBIND_MD,
+ KEYBIND_URI,
+ MIGRATION_MD,
+ MIGRATION_URI,
+ README_MD,
+ README_URI,
+ THEME_MD,
+ THEME_URI,
+)
+from ..registry import rpc
+from ..state.types import State
+
+_NS = uuid4()
+
+
+class _Topics(Enum):
+ index = auto()
+ features = auto()
+ keybind = auto()
+ config = auto()
+ theme = auto()
+ migration = auto()
+
+
+def _directory(topic: _Topics) -> Tuple[Path, str]:
+ if topic is _Topics.index:
+ return README_MD, README_URI
+ elif topic is _Topics.features:
+ return FEATURES_MD, FEATURES_URI
+ elif topic is _Topics.keybind:
+ return KEYBIND_MD, KEYBIND_URI
+ elif topic is _Topics.config:
+ return CONFIGURATION_MD, CONFIGURATION_URI
+ elif topic is _Topics.theme:
+ return THEME_MD, THEME_URI
+ elif topic is _Topics.migration:
+ return MIGRATION_MD, MIGRATION_URI
+ else:
+ never(topic)
+
+
+def _parse_args(args: Sequence[str]) -> Tuple[_Topics, bool]:
+ parser = ArgParser()
+ parser.add_argument(
+ "topic",
+ nargs="?",
+ choices=tuple(topic.name for topic in _Topics),
+ default=_Topics.index.name,
+ )
+ parser.add_argument("-w", "--web", action="store_true", default=False)
+ ns = parser.parse_args(args)
+ return _Topics[ns.topic], ns.web
+
+
+@rpc(blocking=False)
+async def _help(state: State, args: Sequence[str]) -> None:
+ """
+ Open help doc
+ """
+
+ try:
+ topic, use_web = _parse_args(args)
+ except ArgparseError as e:
+ await Nvim.write(e, error=True)
+ else:
+ md, uri = _directory(topic)
+ web_d = open_w(uri) if use_web else False
+ if not web_d:
+ async for win in list_floatwins(_NS):
+ await win.close()
+ lines = md.read_text("UTF-8").splitlines()
+ buf = await Buffer.create(
+ listed=False, scratch=True, wipe=True, nofile=True, noswap=True
+ )
+ await buf.set_lines(lines=lines)
+ await buf.opts.set("modifiable", val=False)
+ await buf.opts.set("syntax", val="markdown")
+ await open_float_win(_NS, margin=0, relsize=0.95, buf=buf, border="rounded")
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/link.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/link.py
new file mode 100644
index 00000000..5c9d4ca6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/link.py
@@ -0,0 +1,79 @@
+from os.path import normpath, relpath
+from pathlib import PurePath
+from typing import MutableMapping, Optional
+
+from pynvim_pp.nvim import Nvim
+from std2 import anext
+from std2.locale import pathsort_key
+
+from ..fs.cartographer import act_like_dir
+from ..fs.ops import ancestors, exists, link, resolve
+from ..lsp.notify import lsp_created
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.next import forward
+from ..state.types import State
+from ..view.ops import display_path
+from .shared.current import maybe_path_above
+from .shared.index import indices
+from .shared.refresh import refresh
+from .types import Stage
+
+
+@rpc(blocking=False)
+async def _link(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Symlink selected
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if node is None:
+ return None
+ else:
+ parent = (
+ node.path
+ if act_like_dir(node, follow_links=state.follow_links)
+ else node.path.parent
+ )
+ selection = state.selection or {node.path}
+ operations: MutableMapping[PurePath, PurePath] = {}
+ for selected in selection:
+ display = display_path(selected, state=state)
+ if child := await Nvim.input(
+ question=LANG("link", src=display), default=""
+ ):
+ try:
+ dst = await resolve(parent / child, strict=False)
+ except Exception as e:
+ await Nvim.write(e, error=True)
+ return None
+ else:
+ if dst in operations or await exists(dst, follow=False):
+ await Nvim.write(
+ LANG("already_exists", name=normpath(dst)), error=True
+ )
+ return None
+ else:
+ src = PurePath(relpath(selected, start=dst.parent))
+ operations[dst] = src
+ else:
+ return None
+
+ try:
+ await link(operations)
+ except Exception as e:
+ await Nvim.write(e, error=True)
+ return await refresh(state)
+ else:
+ paths = operations.keys()
+ new_state = await maybe_path_above(state, paths=paths) or state
+ await lsp_created(paths)
+ focus, *_ = sorted(paths, key=pathsort_key)
+ invalidate_dirs = {path.parent for path in paths}
+ index = state.index | ancestors(*paths)
+ next_state = await forward(
+ new_state,
+ index=index,
+ invalidate_dirs=invalidate_dirs,
+ )
+ return Stage(next_state, focus=focus)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/marks.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/marks.py
new file mode 100644
index 00000000..a299e89d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/marks.py
@@ -0,0 +1,57 @@
+from locale import strxfrm
+from pathlib import PurePath
+from typing import Any, Iterator, MutableMapping, MutableSet, Optional, Tuple
+
+from pynvim_pp.nvim import Nvim
+from std2.locale import pathsort_key
+from std2.pathlib import is_relative_to
+
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.types import State
+from ..view.ops import display_path
+from .focus import _jump
+from .types import Stage
+
+
+def _order(root: PurePath, marks: str, path: PurePath) -> Tuple[bool, str, Any]:
+ return not is_relative_to(path, root), "", pathsort_key(path)
+
+
+def _display_path(state: State, marks: str, path: PurePath, idx: int) -> str:
+ display = display_path(path, state=state)
+ return f"{idx}. [{marks}] {display}"
+
+
+@rpc(blocking=False)
+async def _bookmark_goto(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Goto bookmark
+ """
+
+ def cont() -> Iterator[Tuple[str, PurePath]]:
+ root = state.root.path
+ markers: MutableMapping[str, PurePath] = {}
+ for path, marks in state.markers.bookmarks.items():
+ for mark in marks:
+ if m := markers.get(mark):
+ markers[mark] = max(m, path)
+ else:
+ markers[mark] = path
+
+ seen: MutableSet[PurePath] = set()
+ for _, path in sorted(markers.items(), key=lambda kv: _order(root, *kv)):
+ if path not in seen:
+ ms = sorted(state.markers.bookmarks.get(path, ()), key=strxfrm)
+ yield "".join(ms), path
+
+ opts = {
+ _display_path(state, marks=marks, path=path, idx=idx): path
+ for idx, (marks, path) in enumerate(cont(), start=1)
+ }
+
+ if mark := await Nvim.input_list(opts):
+ return await _jump(state, path=mark)
+ else:
+ await Nvim.write(LANG("no_bookmarks"), error=True)
+ return None
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/new.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/new.py
new file mode 100644
index 00000000..9c183cd2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/new.py
@@ -0,0 +1,68 @@
+from os import sep
+from os.path import abspath, normpath
+from pathlib import PurePath
+from typing import Optional
+
+from pynvim_pp.nvim import Nvim
+from std2 import anext
+
+from ..fs.cartographer import act_like_dir
+from ..fs.ops import ancestors, exists, mkdir, new
+from ..lsp.notify import lsp_created
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.next import forward
+from ..state.types import State
+from .shared.current import maybe_path_above
+from .shared.index import indices
+from .shared.refresh import refresh
+from .types import Stage
+
+
+@rpc(blocking=False)
+async def _new(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ new file / folder
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ parent = (
+ node.path
+ if act_like_dir(node, follow_links=state.follow_links)
+ else node.path.parent
+ )
+
+ child = await Nvim.input(question=LANG("pencil"), default="")
+
+ if not child:
+ return None
+ else:
+ path = PurePath(abspath(parent / child))
+ if await exists(path, follow=False):
+ await Nvim.write(
+ LANG("already_exists", name=normpath(path)), error=True
+ )
+ return None
+ else:
+ try:
+ if child.endswith(sep):
+ await mkdir((path,))
+ else:
+ await new((path,))
+ except Exception as e:
+ await Nvim.write(e, error=True)
+ return await refresh(state=state)
+ else:
+ new_state = await maybe_path_above(state, paths={path}) or state
+ invalidate_dirs = {path.parent}
+ index = state.index | ancestors(path)
+ next_state = await forward(
+ new_state,
+ index=index,
+ invalidate_dirs=invalidate_dirs,
+ )
+ await lsp_created((path,))
+ return Stage(next_state, focus=path)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/noop.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/noop.py
new file mode 100644
index 00000000..707de3fc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/noop.py
@@ -0,0 +1,11 @@
+from typing import Any
+
+from ..registry import rpc
+from ..state.types import State
+
+
+@rpc(blocking=False)
+async def _noop(state: State, *_: Any) -> None:
+ """
+ NOOP
+ """
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/open_system.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/open_system.py
new file mode 100644
index 00000000..50418fe4
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/open_system.py
@@ -0,0 +1,52 @@
+import sys
+from asyncio import create_task
+from pathlib import PurePath
+from subprocess import CalledProcessError
+
+from pynvim_pp.logging import suppress_and_log
+from pynvim_pp.nvim import Nvim
+from std2 import anext
+from std2.asyncio.subprocess import call
+from std2.pathlib import AnyPath
+from std2.platform import OS, os
+
+from ..fs.ops import which
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.types import State
+from .shared.index import indices
+
+
+async def _call(cwd: PurePath, arg0: AnyPath, *args: AnyPath) -> None:
+ try:
+ await call(arg0, *args, cwd=cwd)
+ except CalledProcessError as e:
+ await Nvim.write(e, e.stderr, e.stdout, error=True)
+
+
+async def _open_gui(path: PurePath, cwd: PurePath) -> None:
+ with suppress_and_log():
+ if sys.platform == "win32":
+ from os import startfile
+
+ startfile(path, cwd=cwd)
+ elif os is OS.macos and (arg0 := which("open")):
+ await _call(cwd, arg0, "--", path)
+ elif os is OS.linux and (arg0 := which("xdg-open")):
+ await _call(cwd, arg0, path)
+ else:
+ await Nvim.write(LANG("sys_open_err"))
+
+
+@rpc(blocking=False)
+async def _open_sys(state: State, is_visual: bool) -> None:
+ """
+ Open using finder / dolphin, etc
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ cwd = await Nvim.getcwd()
+ create_task(_open_gui(node.path, cwd=cwd))
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/quit.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/quit.py
new file mode 100644
index 00000000..5c82b3bc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/quit.py
@@ -0,0 +1,20 @@
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.window import Window
+
+from ..registry import rpc
+from ..state.types import State
+from .shared.wm import find_fm_windows_in_tab
+
+
+@rpc(blocking=False)
+async def _quit(state: State, is_visual: bool) -> None:
+ """
+ Close sidebar
+ """
+
+ wins = await Window.list()
+ if len(wins) <= 1:
+ await Nvim.exec("quit")
+ else:
+ async for win in find_fm_windows_in_tab(state.window_order):
+ await win.close()
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/redraw.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/redraw.py
new file mode 100644
index 00000000..b555a3d2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/redraw.py
@@ -0,0 +1,145 @@
+from pathlib import Path, PurePath
+from posixpath import sep
+from typing import Optional, Sequence
+from uuid import uuid4
+
+from pynvim_pp.atomic import Atomic
+from pynvim_pp.buffer import Buffer
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.operators import operator_marks
+from pynvim_pp.rpc_types import NvimError
+from pynvim_pp.types import NoneType
+from std2.difflib import trans_inplace
+from std2.pickle.decoder import new_decoder
+from std2.pickle.types import DecodeError
+
+from ..consts import URI_SCHEME
+from ..state.types import State
+from ..view.types import Derived
+from .shared.wm import find_fm_windows
+
+
+class UnrecoverableError(Exception):
+ ...
+
+
+_NS = uuid4()
+
+
+_DECODER = new_decoder[Sequence[str]](Sequence[str])
+_HOME = Path.home()
+
+
+def _buf_name(root: PurePath) -> str:
+ try:
+ rel = root.relative_to(_HOME)
+ except ValueError:
+ name = root.as_posix()
+ else:
+ name = f"~{sep}{rel.as_posix()}"
+
+ return name
+
+
+def _update(
+ use_extmarks: bool,
+ buf: Buffer,
+ ns: int,
+ derived: Derived,
+ hashed_lines: Sequence[str],
+) -> Atomic:
+ atomic = Atomic()
+ for (i1, i2), (j1, j2) in trans_inplace(
+ src=hashed_lines, dest=derived.hashed, unifying=10
+ ):
+ atomic.buf_clear_namespace(buf, ns, i1, i2)
+ atomic.buf_set_lines(buf, i1, i2, True, derived.lines[j1:j2])
+
+ for idx, highlights in enumerate(derived.highlights[j1:j2], start=i1):
+ for hl in highlights:
+ atomic.buf_add_highlight(buf, ns, hl.group, idx, hl.begin, hl.end)
+
+ for idx, badges in enumerate(derived.badges[j1:j2], start=i1):
+ vtxt = tuple((bdg.text, bdg.group) for bdg in badges)
+ if use_extmarks:
+ atomic.buf_set_extmark(
+ buf, ns, idx, -1, {"virt_text": vtxt, "hl_mode": "combine"}
+ )
+ else:
+ atomic.buf_set_virtual_text(buf, ns, idx, vtxt, {})
+
+ atomic.buf_set_var(buf, str(_NS), derived.hashed)
+ return atomic
+
+
+async def redraw(state: State, focus: Optional[PurePath]) -> None:
+ focus_row = state.derived.path_row_lookup.get(focus) if focus else None
+ buf_name = _buf_name(state.root.path)
+
+ ns = await Nvim.create_namespace(_NS)
+ use_extmarks = await Nvim.api.has("nvim-0.6")
+
+ async for win, buf in find_fm_windows():
+ is_fm_win = await win.vars.get(bool, URI_SCHEME)
+ p_count = await buf.line_count()
+ n_count = len(state.derived.lines)
+ row, col = await win.get_cursor()
+ (r1, c1), (r2, c2) = await operator_marks(buf, visual_type=None)
+ buf_var = await buf.vars.get(NoneType, str(_NS))
+
+ try:
+ hashed_lines = _DECODER(buf_var)
+ except DecodeError:
+ hashed_lines = ("",)
+
+ if focus_row is not None:
+ new_row: Optional[int] = focus_row + 1
+ elif row >= n_count:
+ new_row = n_count
+ elif p_count != n_count:
+ new_row = row + 1
+ else:
+ new_row = None
+
+ a1 = Atomic()
+ a1.buf_set_option(buf, "modifiable", True)
+
+ a2 = _update(
+ use_extmarks,
+ buf=buf,
+ ns=ns,
+ derived=state.derived,
+ hashed_lines=hashed_lines,
+ )
+
+ a3 = Atomic()
+ a3.buf_set_option(buf, "modifiable", False)
+ a3.call_function("setpos", ("'<", (buf.number, r1 + 1, c1 + 1, 0)))
+ a3.call_function("setpos", ("'>", (buf.number, r2 + 1, c2, 0)))
+ if new_row is not None:
+ win_height = await win.get_height()
+ win_lo = await Nvim.fn.line(int, "w0", win)
+ win_hi = await Nvim.fn.line(int, "w$", win)
+ lo = max(1, new_row - win_height // 2)
+ hi = min(n_count, new_row + win_height // 2)
+
+ if new_row < win_lo or new_row > win_hi:
+ a3.win_set_cursor(win, (lo, 0))
+ a3.win_set_cursor(win, (hi, 0))
+ a3.win_set_cursor(win, (lo, 0))
+ a3.win_set_cursor(win, (hi, 0))
+
+ a3.win_set_cursor(win, (new_row, col))
+
+ a3.buf_set_name(buf, f"{URI_SCHEME}://{buf_name}")
+ a3.win_set_var(win, URI_SCHEME, True)
+
+ if not is_fm_win:
+ for key, val in state.settings.win_local_opts.items():
+ a3.win_set_option(win, key, val)
+
+ a4 = a1 + a2 + a3
+ try:
+ await a4.commit(NoneType)
+ except NvimError as e:
+ raise UnrecoverableError(e)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/refresh.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/refresh.py
new file mode 100644
index 00000000..e90a610c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/refresh.py
@@ -0,0 +1,23 @@
+from contextlib import asynccontextmanager
+from typing import AsyncIterator
+
+from pynvim_pp.nvim import Nvim
+
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.types import State
+from .shared.refresh import refresh as _refresh
+from .types import Stage
+
+
+@asynccontextmanager
+async def with_manual() -> AsyncIterator[None]:
+ await Nvim.write(LANG("hourglass"))
+ yield None
+ await Nvim.write(LANG("ok_sym"))
+
+
+@rpc(blocking=False)
+async def refresh(state: State, is_visual: bool) -> Stage:
+ async with with_manual():
+ return await _refresh(state)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/rename.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/rename.py
new file mode 100644
index 00000000..533f7442
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/rename.py
@@ -0,0 +1,75 @@
+from os.path import abspath, normpath
+from pathlib import PurePath
+from typing import Optional
+
+from pynvim_pp.hold import hold_win
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.window import Window
+from std2 import anext
+
+from ..fs.ops import ancestors, exists, rename
+from ..lsp.notify import lsp_moved
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.next import forward
+from ..state.types import State
+from .shared.current import maybe_path_above
+from .shared.index import indices
+from .shared.refresh import refresh
+from .shared.wm import kill_buffers
+from .types import Stage
+
+
+@rpc(blocking=False)
+async def _rename(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ rename file / folder
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ old_path = node.path
+ child = await Nvim.input(question=LANG("pencil"), default=old_path.name)
+ if not child:
+ return None
+ else:
+ new_path = PurePath(abspath(old_path.parent / child))
+ operations = {old_path: new_path}
+ if await exists(new_path, follow=False):
+ await Nvim.write(
+ LANG("already_exists", name=normpath(new_path)), error=True
+ )
+ return None
+ else:
+ killed = await kill_buffers(
+ last_used=state.window_order,
+ paths={old_path},
+ reopen={old_path: new_path},
+ )
+ try:
+ await rename(operations)
+ except Exception as e:
+ await Nvim.write(e, error=True)
+ return await refresh(state=state)
+ else:
+ async with hold_win(win=None):
+ for win, new_path in killed.items():
+ await Window.set_current(win)
+ escaped = await Nvim.fn.fnameescape(str, normpath(new_path))
+ await Nvim.exec(f"edit! {escaped}")
+
+ new_state = await maybe_path_above(state, paths={new_path}) or state
+ parents = ancestors(new_path)
+ invalidate_dirs = {old_path.parent, new_path.parent}
+ index = state.index | parents
+ new_selection = {new_path} if state.selection else frozenset()
+ next_state = await forward(
+ new_state,
+ index=index,
+ invalidate_dirs=invalidate_dirs,
+ selection=new_selection,
+ )
+ await lsp_moved(operations)
+ return Stage(next_state, focus=new_path)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/resize.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/resize.py
new file mode 100644
index 00000000..15f94afc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/resize.py
@@ -0,0 +1,42 @@
+from operator import add, sub
+from typing import Callable, Optional
+
+from pynvim_pp.window import Window
+
+from ..registry import rpc
+from ..state.next import forward
+from ..state.types import State
+from .shared.wm import is_fm_window, resize_fm_windows
+from .types import Stage
+
+
+async def _resize(
+ state: State, direction: Callable[[int, int], int]
+) -> Optional[Stage]:
+ win = await Window.get_current()
+ if not await is_fm_window(win):
+ return None
+ else:
+ old_width = await win.get_width()
+ new_width = max(direction(old_width, 10), 1)
+ new_state = await forward(state, width=new_width)
+ await resize_fm_windows(new_state.window_order, width=new_state.width)
+ return Stage(new_state)
+
+
+@rpc(blocking=False)
+async def _bigger(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Bigger sidebar
+ """
+
+ return await _resize(state, direction=add)
+
+
+@rpc(blocking=False)
+async def _smaller(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Smaller sidebar
+ """
+
+ return await _resize(state, direction=sub)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/schedule_update.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/schedule_update.py
new file mode 100644
index 00000000..7abe265e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/schedule_update.py
@@ -0,0 +1,37 @@
+from asyncio import gather
+from typing import Optional
+
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.rpc_types import NvimError
+from std2.asyncio import pure
+
+from ..lsp.diagnostics import poll
+from ..registry import rpc
+from ..state.next import forward
+from ..state.ops import dump_session
+from ..state.types import State
+from ..version_ctl.git import status
+from ..version_ctl.types import VCStatus
+from .shared.refresh import refresh
+from .types import Stage
+
+
+@rpc(blocking=False)
+async def scheduled_update(state: State, init: bool = False) -> Optional[Stage]:
+ cwd = await Nvim.getcwd()
+ store = dump_session(state) if state.vim_focus else pure(None)
+
+ try:
+ stage, diagnostics, vc, _ = await gather(
+ refresh(state=state),
+ poll(state.settings.min_diagnostics_severity),
+ status(cwd, prev=state.vc)
+ if not init and state.enable_vc
+ else pure(VCStatus()),
+ store,
+ )
+ except NvimError:
+ return None
+ else:
+ new_state = await forward(stage.state, diagnostics=diagnostics, vc=vc)
+ return Stage(new_state, focus=stage.focus)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/selection.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/selection.py
new file mode 100644
index 00000000..12e6f051
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/selection.py
@@ -0,0 +1,27 @@
+from ..registry import rpc
+from ..state.next import forward
+from ..state.types import State
+from .shared.index import indices
+from .types import Stage
+
+
+@rpc(blocking=False)
+async def _clear_selection(state: State, is_visual: bool) -> Stage:
+ """
+ Clear selected
+ """
+
+ new_state = await forward(state, selection=frozenset())
+ return Stage(new_state)
+
+
+@rpc(blocking=False)
+async def _select(state: State, is_visual: bool) -> Stage:
+ """
+ Folder / File -> select
+ """
+
+ nodes = indices(state, is_visual=is_visual)
+ selection = state.selection ^ {node.path async for node in nodes}
+ new_state = await forward(state, selection=selection)
+ return Stage(new_state)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/current.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/current.py
new file mode 100644
index 00000000..d48f325d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/current.py
@@ -0,0 +1,65 @@
+from pathlib import PurePath
+from typing import AbstractSet, Iterator, Optional
+
+from std2.locale import pathsort_key
+from std2.pathlib import is_relative_to, longest_common_path
+
+from ...fs.cartographer import new
+from ...fs.ops import ancestors
+from ...state.next import forward
+from ...state.types import State
+from ..types import Stage
+
+
+async def new_current_file(state: State, current: PurePath) -> Stage:
+ """
+ New file focused in buf
+ """
+
+ parents = ancestors(current)
+ if state.root.path in parents:
+ invalidate_dirs = {current.parent}
+ index = state.index | parents
+ new_state = await forward(
+ state,
+ index=index,
+ invalidate_dirs=invalidate_dirs,
+ current=current,
+ )
+ else:
+ new_state = await forward(state, current=current)
+
+ focus = current if state.follow else None
+ return Stage(new_state, focus=focus)
+
+
+async def new_root(
+ state: State,
+ new_cwd: PurePath,
+ indices: AbstractSet[PurePath],
+) -> State:
+ index = state.index | ancestors(new_cwd) | {new_cwd} | indices
+ root = await new(
+ state.executor, follow_links=state.follow_links, root=new_cwd, index=index
+ )
+ selection = {path for path in state.selection if root.path in ancestors(path)}
+ return await forward(state, root=root, selection=selection, index=index)
+
+
+async def maybe_path_above(
+ state: State, paths: AbstractSet[PurePath]
+) -> Optional[State]:
+ root = state.root.path
+ if all(is_relative_to(path, root) for path in paths):
+ return None
+ else:
+
+ def cont() -> Iterator[PurePath]:
+ for path in paths:
+ lcp = longest_common_path(path, root)
+ yield lcp if lcp else path.parent
+
+ ordered = sorted(cont(), key=pathsort_key)
+ indices = ancestors(*ordered)
+ new_cwd, *_ = ordered
+ return await new_root(state=state, new_cwd=new_cwd, indices=indices)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/index.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/index.py
new file mode 100644
index 00000000..bb19675b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/index.py
@@ -0,0 +1,35 @@
+from typing import AsyncIterator, Optional
+
+from pynvim_pp.operators import operator_marks
+from pynvim_pp.window import Window
+
+from ...fs.types import Node
+from ...state.types import State
+from .wm import is_fm_buffer
+
+
+def _row_index(state: State, row: int) -> Optional[Node]:
+ if (row >= 0) and (row < len(state.derived.node_row_lookup)):
+ return state.derived.node_row_lookup[row]
+ else:
+ return None
+
+
+async def indices(state: State, is_visual: bool) -> AsyncIterator[Node]:
+ win = await Window.get_current()
+ buf = await win.get_buf()
+
+ if not await is_fm_buffer(buf):
+ return
+ else:
+ row, _ = await win.get_cursor()
+ if node := _row_index(state, row):
+ yield node
+
+ if is_visual:
+ (row1, _), (row2, _) = await operator_marks(buf, visual_type=None)
+
+ for r in range(row1, row2 + 1):
+ if r != row:
+ if node := _row_index(state, r):
+ yield node
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/open_file.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/open_file.py
new file mode 100644
index 00000000..819e6ee1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/open_file.py
@@ -0,0 +1,117 @@
+from contextlib import suppress
+from mimetypes import guess_type
+from os.path import getsize, normpath
+from pathlib import PurePath
+from posixpath import sep
+from typing import AsyncContextManager, Optional, cast
+
+from pynvim_pp.buffer import Buffer
+from pynvim_pp.hold import hold_win
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.window import Window
+from std2 import anext
+from std2.aitertools import achain, to_async
+from std2.contextlib import nullacontext
+
+from ...settings.localization import LANG
+from ...state.next import forward
+from ...state.types import State
+from ..types import ClickType, Stage
+from .wm import (
+ find_buffers_with_file,
+ find_non_fm_windows_in_tab,
+ find_window_with_file_in_tab,
+ new_window,
+ resize_fm_windows,
+)
+
+
+async def _show_file(*, state: State, click_type: ClickType) -> None:
+ if click_type is ClickType.tertiary:
+ await Nvim.exec("tabnew")
+ win = await Window.get_current()
+ for key, val in state.settings.win_actual_opts.items():
+ await win.opts.set(key, val=val)
+
+ if path := state.current:
+ mgr = (
+ cast(AsyncContextManager[None], hold_win(win=None))
+ if click_type is ClickType.secondary
+ else nullacontext(None)
+ )
+ async with mgr:
+ non_fm_windows = [
+ win
+ async for win in find_non_fm_windows_in_tab(
+ last_used=state.window_order
+ )
+ ]
+ buf = await anext(find_buffers_with_file(file=path), None)
+ win = await anext(
+ achain(
+ find_window_with_file_in_tab(
+ last_used=state.window_order, file=path
+ ),
+ to_async(non_fm_windows),
+ ),
+ cast(Window, None),
+ ) or await new_window(
+ last_used=state.window_order,
+ win_local=state.settings.win_actual_opts,
+ open_left=not state.settings.open_left,
+ width=None
+ if len(non_fm_windows)
+ else await Nvim.opts.get(int, "columns") - state.width - 1,
+ )
+
+ await Window.set_current(win)
+ non_fm_count = len(non_fm_windows)
+
+ if click_type is ClickType.v_split and non_fm_count:
+ await Nvim.exec("vnew")
+ temp_buf = await Buffer.get_current()
+ await temp_buf.opts.set("bufhidden", val="wipe")
+ elif click_type is ClickType.h_split and non_fm_count:
+ await Nvim.exec("new")
+ temp_buf = await Buffer.get_current()
+ await temp_buf.opts.set("bufhidden", val="wipe")
+
+ win = await Window.get_current()
+
+ if buf:
+ await win.set_buf(buf)
+ else:
+ escaped = await Nvim.fn.fnameescape(str, normpath(path))
+ await Nvim.exec(f"edit! {escaped}")
+
+ await resize_fm_windows(last_used=state.window_order, width=state.width)
+
+
+async def open_file(
+ state: State, path: PurePath, click_type: ClickType
+) -> Optional[Stage]:
+ mime, _ = guess_type(path.name, strict=False)
+ m_type, _, _ = (mime or "").partition(sep)
+
+ with suppress(OSError):
+ size = getsize(path)
+
+ question = LANG("mime_warn", name=path.name, mime=str(mime))
+
+ go = (
+ await Nvim.confirm(
+ question=question,
+ answers=LANG("ask_yesno"),
+ answer_key={1: True, 2: False},
+ )
+ if m_type in state.settings.mime.warn
+ and path.suffix not in state.settings.mime.allow_exts
+ else True
+ )
+
+ if go:
+ new_state = await forward(state, current=path)
+ await _show_file(state=new_state, click_type=click_type)
+ return Stage(new_state, focus=path)
+ else:
+ return None
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/refresh.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/refresh.py
new file mode 100644
index 00000000..51202266
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/refresh.py
@@ -0,0 +1,78 @@
+from asyncio import gather
+from pathlib import PurePath
+from typing import AbstractSet, Mapping
+
+from pynvim_pp.rpc_types import ExtData
+from pynvim_pp.window import Window
+from std2.types import Void
+
+from ...fs.ops import ancestors, exists_many
+from ...nvim.markers import markers
+from ...state.next import forward
+from ...state.types import State
+from ..shared.wm import find_current_buffer_path
+from ..types import Stage
+
+
+async def _index(state: State, paths: AbstractSet[PurePath]) -> AbstractSet[PurePath]:
+ index = {
+ path
+ for path, exists in (await exists_many(state.index, follow=True)).items()
+ if exists
+ } | paths
+
+ return index
+
+
+async def _selection(state: State) -> AbstractSet[PurePath]:
+ selection = {
+ selected
+ for selected, exists in (
+ await exists_many(state.selection, follow=False)
+ ).items()
+ if exists
+ }
+
+ return selection
+
+
+async def _window_order(state: State) -> Mapping[ExtData, None]:
+ window_ids = {w.data for w in await Window.list()}
+ window_order = {
+ win_id: None for win_id in state.window_order if win_id in window_ids
+ }
+ return window_order
+
+
+async def refresh(state: State) -> Stage:
+ cwd = state.root.path
+ invalidate_dirs = {cwd}
+
+ current, index, selection, window_order, mks = await gather(
+ find_current_buffer_path(),
+ _index(state, paths=invalidate_dirs),
+ _selection(state),
+ _window_order(state),
+ markers(),
+ )
+ current_ancestors = ancestors(current) if current else frozenset()
+ new_current = current if cwd in current_ancestors else None
+
+ parent_paths: AbstractSet[PurePath] = (
+ current_ancestors if state.follow else frozenset()
+ )
+ new_index = index if new_current else index | parent_paths
+ focus = current if state.follow else None
+
+ new_state = await forward(
+ state,
+ index=new_index,
+ selection=selection,
+ markers=mks,
+ invalidate_dirs=invalidate_dirs,
+ current=new_current or Void,
+ window_order=window_order,
+ trace=False,
+ )
+
+ return Stage(new_state, focus=focus)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/wm.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/wm.py
new file mode 100644
index 00000000..db509e93
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/shared/wm.py
@@ -0,0 +1,254 @@
+from contextlib import suppress
+from math import inf
+from pathlib import PurePath
+from typing import (
+ AbstractSet,
+ AsyncIterator,
+ Mapping,
+ Optional,
+ Sequence,
+ Tuple,
+ Union,
+ cast,
+)
+from urllib.parse import urlsplit
+
+from pynvim_pp.atomic import Atomic
+from pynvim_pp.buffer import Buffer
+from pynvim_pp.keymap import Keymap
+from pynvim_pp.lib import resolve_path
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.rpc_types import ExtData
+from pynvim_pp.tabpage import Tabpage
+from pynvim_pp.types import NoneType
+from pynvim_pp.window import Window
+
+from ...consts import FM_FILETYPE, URI_SCHEME
+from ...fs.ops import ancestors
+from ...settings.types import Settings
+
+
+def is_fm_buf_name(name: str) -> bool:
+ with suppress(ValueError):
+ uri = urlsplit(name)
+ return uri.scheme == URI_SCHEME
+ return False
+
+
+async def is_fm_buffer(buf: Buffer) -> bool:
+ ft = await buf.filetype()
+ if ft == FM_FILETYPE:
+ return True
+ elif name := await buf.get_name():
+ return is_fm_buf_name(name)
+
+ return False
+
+
+async def is_fm_window(win: Window) -> bool:
+ buf = await win.get_buf()
+ return await is_fm_buffer(buf)
+
+
+async def find_windows_in_tab(
+ last_used: Mapping[ExtData, None], no_secondary: bool
+) -> AsyncIterator[Window]:
+ ordering = {win_id: idx for idx, win_id in enumerate(reversed(last_used.keys()))}
+ tab = await Tabpage.get_current()
+ wins = await tab.list_wins()
+
+ atomic = Atomic()
+ for win in wins:
+ atomic.win_get_position(win)
+ pos = cast(Sequence[Tuple[int, int]], await atomic.commit(NoneType))
+ positions = {win.data: rc for win, rc in zip(wins, pos)}
+
+ def key_by(win: Window) -> Tuple[float, float, float]:
+ """
+ -> sort by last_used, then row, then col
+ """
+
+ order = ordering.get(win.data, inf)
+ row, col = positions.get(win.data, (inf, inf))
+ return order, col, row
+
+ ordered = sorted(wins, key=key_by)
+
+ for win in ordered:
+ is_preview = await win.opts.get(bool, "previewwindow")
+ buf = await win.get_buf()
+ ft = await buf.filetype()
+ is_secondary = is_preview or ft == "qf"
+ if not is_secondary or not no_secondary:
+ yield win
+
+
+async def find_fm_windows() -> AsyncIterator[Tuple[Window, Buffer]]:
+ for win in await Window.list():
+ buf = await win.get_buf()
+ if await is_fm_buffer(buf):
+ yield win, buf
+
+
+async def find_fm_windows_in_tab(
+ last_used: Mapping[ExtData, None]
+) -> AsyncIterator[Window]:
+ async for win in find_windows_in_tab(last_used, no_secondary=True):
+ buf = await win.get_buf()
+ if await is_fm_buffer(buf):
+ yield win
+
+
+async def find_non_fm_windows_in_tab(
+ last_used: Mapping[ExtData, None]
+) -> AsyncIterator[Window]:
+ async for win in find_windows_in_tab(last_used, no_secondary=True):
+ buf = await win.get_buf()
+ if not await is_fm_buffer(buf):
+ yield win
+
+
+async def find_window_with_file_in_tab(
+ last_used: Mapping[ExtData, None], file: PurePath
+) -> AsyncIterator[Window]:
+ async for win in find_windows_in_tab(last_used, no_secondary=True):
+ buf = await win.get_buf()
+ if name := await buf.get_name():
+ if PurePath(name) == file:
+ yield win
+
+
+async def find_fm_buffers() -> AsyncIterator[Buffer]:
+ for buf in await Buffer.list(listed=True):
+ if await is_fm_buffer(buf):
+ yield buf
+
+
+async def find_buffers_with_file(file: PurePath) -> AsyncIterator[Buffer]:
+ for buf in await Buffer.list(listed=True):
+ if name := await buf.get_name():
+ if PurePath(name) == file:
+ yield buf
+
+
+async def find_current_buffer_path(
+ buf_name: Optional[str] = None,
+) -> Optional[PurePath]:
+ if buf_name is None:
+ buf = await Buffer.get_current()
+ buf_name = await buf.get_name()
+
+ if buf_name and not is_fm_buf_name(buf_name):
+ return await resolve_path(None, path=buf_name)
+
+ return None
+
+
+async def setup_fm_buf(settings: Settings, buf: Buffer) -> None:
+ await buf.opts.set("modifiable", val=False)
+ await buf.opts.set("filetype", val=FM_FILETYPE)
+ await buf.opts.set("undolevels", val=-1)
+
+ km = Keymap()
+ _ = km.n("{") << f"{settings.page_increment}g"
+ _ = km.n("}") << f"{settings.page_increment}g"
+ for function, mappings in settings.keymap.items():
+ for mapping in mappings:
+ _ = (
+ km.n(mapping, noremap=True, silent=True, nowait=True)
+ << f"lua {function}(false)"
+ )
+ _ = (
+ km.v(mapping, noremap=True, silent=True, nowait=True)
+ << rf"lua {function}(true)"
+ )
+
+ await km.drain(buf=buf).commit(NoneType)
+
+
+async def new_fm_buffer(settings: Settings) -> Buffer:
+ buf = await Buffer.create(
+ listed=False, scratch=True, wipe=False, nofile=True, noswap=True
+ )
+ await setup_fm_buf(settings, buf=buf)
+ return buf
+
+
+async def restore_non_fm_win(
+ win_local: Mapping[str, Union[bool, str]], win: Window
+) -> None:
+ await win.vars.set(URI_SCHEME, False)
+ for key, val in win_local.items():
+ await win.opts.set(key, val=val)
+
+
+async def new_window(
+ *,
+ last_used: Mapping[ExtData, None],
+ win_local: Mapping[str, Union[bool, str]],
+ open_left: bool,
+ width: Optional[int],
+) -> Window:
+ split_r = await Nvim.opts.get(bool, "splitright")
+
+ wins = [win async for win in find_windows_in_tab(last_used, no_secondary=False)]
+ focus_win = wins[0] if open_left else wins[-1]
+ direction = False if open_left else True
+
+ await Nvim.opts.set("splitright", val=direction)
+ await Window.set_current(focus_win)
+ await Nvim.exec(f"{width}vnew" if width else "vnew")
+ await Nvim.opts.set("splitright", val=split_r)
+
+ win = await Window.get_current()
+ buf = await win.get_buf()
+ await restore_non_fm_win(win_local, win=win)
+ await buf.opts.set("bufhidden", val="wipe")
+ return win
+
+
+async def resize_fm_windows(last_used: Mapping[ExtData, None], width: int) -> None:
+ async for win in find_fm_windows_in_tab(last_used):
+ await win.set_width(width)
+
+
+async def kill_buffers(
+ last_used: Mapping[ExtData, None],
+ paths: AbstractSet[PurePath],
+ reopen: Mapping[PurePath, PurePath],
+) -> Mapping[Window, PurePath]:
+ active = (
+ {
+ await win.get_buf(): win
+ async for win in find_non_fm_windows_in_tab(
+ last_used,
+ )
+ }
+ if reopen
+ else {}
+ )
+
+ async def cont() -> AsyncIterator[Tuple[Window, PurePath]]:
+ for buf in await Buffer.list(listed=True):
+ if bufname := await buf.get_name():
+ name = PurePath(bufname)
+ buf_paths = ancestors(name) | {name}
+
+ if not buf_paths.isdisjoint(paths):
+ if (
+ reopen
+ and (win := active.get(buf))
+ and (new_path := reopen.get(name))
+ ):
+ tmp = await Buffer.create(
+ listed=False,
+ scratch=True,
+ wipe=True,
+ nofile=True,
+ noswap=True,
+ )
+ await win.set_buf(tmp)
+ yield win, new_path
+ await buf.delete()
+
+ return {win: path async for win, path in cont()}
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/stat.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/stat.py
new file mode 100644
index 00000000..30c5c124
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/stat.py
@@ -0,0 +1,35 @@
+from pynvim_pp.nvim import Nvim
+from std2 import anext
+from std2.locale import si_prefixed
+
+from ..fs.ops import fs_stat
+from ..registry import rpc
+from ..state.types import State
+from ..view.ops import display_path
+from .shared.index import indices
+
+
+@rpc(blocking=False)
+async def _stat(state: State, is_visual: bool) -> None:
+ """
+ Print file stat to cmdline
+ """
+
+ node = await anext(indices(state, is_visual=is_visual), None)
+ if not node:
+ return None
+ else:
+ try:
+ stat = await fs_stat(node.path)
+ except Exception as e:
+ await Nvim.write(e, error=True)
+ else:
+ permissions = stat.permissions
+ size = si_prefixed(stat.size, precision=2)
+ user = stat.user
+ group = stat.group
+ mtime = stat.date_mod.strftime(state.settings.view.time_fmt)
+ name = display_path(node.path, state=state)
+ full_name = f"{name} -> {stat.link}" if stat.link else name
+ mode_line = f"{permissions} {size}b {user} {group} {mtime} {full_name}"
+ await Nvim.write(mode_line)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/toggle_exec.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/toggle_exec.py
new file mode 100644
index 00000000..be3f64d7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/toggle_exec.py
@@ -0,0 +1,43 @@
+from os import chmod, stat, stat_result
+from pathlib import PurePath
+from stat import S_ISDIR, S_IXGRP, S_IXOTH, S_IXUSR
+from typing import Iterator, Tuple
+
+from ..fs.cartographer import act_like_dir
+from ..registry import rpc
+from ..state.next import forward
+from ..state.types import State
+from .shared.index import indices
+from .types import Stage
+
+
+@rpc(blocking=False)
+async def _toggle_exec(state: State, is_visual: bool) -> Stage:
+ """
+ Toggle chmod +-x
+ """
+
+ selected = state.selection or {
+ node.path
+ async for node in indices(state, is_visual=is_visual)
+ if not act_like_dir(node, follow_links=state.follow_links)
+ }
+
+ def cont() -> Iterator[Tuple[PurePath, stat_result]]:
+ for path in selected:
+ try:
+ st = stat(path)
+ except FileNotFoundError:
+ pass
+ else:
+ if not S_ISDIR(st.st_mode):
+ yield path, st
+
+ stats = {path: st for path, st in cont()}
+
+ for path, st in stats.items():
+ chmod(path, st.st_mode ^ S_IXUSR ^ S_IXGRP ^ S_IXOTH)
+
+ invalidate_dirs = {path.parent for path in stats.keys()}
+ new_state = await forward(state, invalidate_dirs=invalidate_dirs)
+ return Stage(state=new_state)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/toggle_open.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/toggle_open.py
new file mode 100644
index 00000000..2e1b46fc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/toggle_open.py
@@ -0,0 +1,184 @@
+from dataclasses import dataclass
+from pathlib import PurePath
+from subprocess import CalledProcessError
+from typing import Mapping, Optional, Sequence
+
+from pynvim_pp.nvim import Nvim
+from pynvim_pp.rpc_types import ExtData
+from pynvim_pp.window import Window
+from std2 import anext
+from std2.argparse import ArgparseError, ArgParser
+
+from ..fs.ops import exists, new, which
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..settings.types import Settings
+from ..state.types import State
+from ..version_ctl.git import root as version_ctl_toplv
+from .shared.current import maybe_path_above, new_current_file, new_root
+from .shared.open_file import open_file
+from .shared.wm import (
+ find_current_buffer_path,
+ find_fm_buffers,
+ find_fm_windows_in_tab,
+ find_windows_in_tab,
+ new_fm_buffer,
+ new_window,
+ resize_fm_windows,
+)
+from .types import ClickType, Stage
+
+
+@dataclass(frozen=True)
+class _Args:
+ path: Optional[PurePath]
+ version_ctl: bool
+ toggle: bool
+ focus: bool
+
+
+def _parse_args(args: Sequence[str]) -> _Args:
+ parser = ArgParser()
+ parser.add_argument("path", nargs="?", type=PurePath)
+ parser.add_argument("--version-ctl", action="store_true")
+
+ focus_group = parser.add_mutually_exclusive_group()
+ focus_group.add_argument(
+ "--always-focus", dest="toggle", action="store_false", default=True
+ )
+ focus_group.add_argument(
+ "--nofocus", dest="focus", action="store_false", default=True
+ )
+
+ ns = parser.parse_args(args=args)
+ opts = _Args(
+ path=ns.path,
+ version_ctl=ns.version_ctl,
+ toggle=False if ns.version_ctl or ns.path else ns.toggle,
+ focus=ns.focus,
+ )
+ return opts
+
+
+async def _ensure_side_window(
+ *,
+ settings: Settings,
+ window_order: Mapping[ExtData, None],
+ width: int,
+ window: Window,
+) -> None:
+ open_left = settings.open_left
+ windows = [
+ win
+ async for win in find_windows_in_tab(last_used=window_order, no_secondary=False)
+ ]
+ target = windows[0] if open_left else windows[-1]
+ if window.data != target.data:
+ if open_left:
+ await Nvim.exec("wincmd H")
+ else:
+ await Nvim.exec("wincmd L")
+ await resize_fm_windows(last_used=window_order, width=width)
+
+
+async def _open_fm_window(
+ settings: Settings,
+ window_order: Mapping[ExtData, None],
+ opts: _Args,
+ width: int,
+) -> None:
+ cwin = await Window.get_current()
+ win = await anext(find_fm_windows_in_tab(last_used=window_order), None)
+ if win:
+ if opts.toggle:
+ wins = await Window.list()
+ if len(wins) > 1:
+ await win.close()
+ else:
+ await Window.set_current(win)
+ else:
+ buf = await anext(find_fm_buffers(), None)
+ if not buf:
+ buf = await new_fm_buffer(settings=settings)
+
+ win = await new_window(
+ last_used=window_order,
+ win_local=settings.win_actual_opts,
+ open_left=settings.open_left,
+ width=width,
+ )
+
+ await win.set_buf(buf)
+
+ await _ensure_side_window(
+ window=win, settings=settings, window_order=window_order, width=width
+ )
+ if not opts.focus:
+ await Window.set_current(cwin)
+
+
+@rpc(blocking=False)
+async def _open(state: State, args: Sequence[str]) -> Optional[Stage]:
+ """
+ Toggle sidebar
+ """
+
+ try:
+ opts = _parse_args(args)
+ except ArgparseError as e:
+ await Nvim.write(e, error=True)
+ return None
+ else:
+ if opts.version_ctl:
+ if git := which("git"):
+ try:
+ cwd = await version_ctl_toplv(git, cwd=state.root.path)
+ new_state = await new_root(
+ state=state, new_cwd=cwd, indices=frozenset()
+ )
+ except CalledProcessError:
+ await Nvim.write(LANG("cannot find version ctl root"), error=True)
+ return None
+ else:
+ await Nvim.write(LANG("cannot find version ctl root"), error=True)
+ return None
+ else:
+ new_state = state
+
+ if opts.path:
+ path = (
+ opts.path
+ if opts.path.is_absolute()
+ else await Nvim.getcwd() / opts.path
+ )
+ if not await exists(path, follow=True):
+ await new((path,))
+ next_state = await maybe_path_above(new_state, paths={path}) or new_state
+ await _open_fm_window(
+ state.settings,
+ opts=opts,
+ window_order=new_state.window_order,
+ width=next_state.width,
+ )
+ await open_file(
+ state=state,
+ path=path,
+ click_type=ClickType.primary,
+ )
+ return Stage(next_state, focus=path)
+ else:
+ curr = await find_current_buffer_path()
+ stage = (
+ await new_current_file(state=new_state, current=curr) if curr else None
+ )
+ await _open_fm_window(
+ state.settings,
+ opts=opts,
+ window_order=new_state.window_order,
+ width=new_state.width,
+ )
+ return (
+ Stage(stage.state, focus=curr)
+ if stage
+ else Stage(new_state, focus=curr)
+ )
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/toggles.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/toggles.py
new file mode 100644
index 00000000..13478416
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/toggles.py
@@ -0,0 +1,78 @@
+from typing import Optional, Union
+
+from pynvim_pp.nvim import Nvim
+from std2 import anext
+from std2.types import Void, VoidType
+
+from ..registry import rpc
+from ..settings.localization import LANG
+from ..state.next import forward
+from ..state.types import Selection, State
+from ..version_ctl.types import VCStatus
+from .shared.index import indices
+from .types import Stage
+
+
+@rpc(blocking=False)
+async def _toggle_hidden(state: State, is_visual: bool) -> Optional[Stage]:
+ """
+ Toggle hidden
+ """
+
+ node = await anext(indices(state, is_visual=is_visual))
+ if not node:
+ return None
+ else:
+ focus = node.path
+ show_hidden = not state.show_hidden
+ selection: Selection = state.selection if show_hidden else frozenset()
+ new_state = await forward(state, show_hidden=show_hidden, selection=selection)
+ return Stage(new_state, focus=focus)
+
+
+@rpc(blocking=False)
+async def _toggle_follow(state: State, is_visual: bool) -> Stage:
+ """
+ Toggle follow
+ """
+
+ new_state = await forward(state, follow=not state.follow)
+ await Nvim.write(LANG("follow_mode_indi", follow=str(new_state.follow)))
+ return Stage(new_state)
+
+
+@rpc(blocking=False)
+async def _toggle_follow_links(state: State, is_visual: bool) -> Stage:
+ """
+ Toggle --follow
+ """
+
+ follow_links = not state.follow_links
+ new_state = await forward(state, follow_links=follow_links)
+ await Nvim.write(LANG("follow_links_indi", follow=str(new_state.follow_links)))
+ return Stage(new_state)
+
+
+@rpc(blocking=False)
+async def _toggle_follow_ignore(state: State, is_visual: bool) -> Stage:
+ """
+ Toggle --follow
+ """
+
+ follow_links = not state.follow_links
+ new_state = await forward(state, follow_links=follow_links)
+ await Nvim.write(LANG("follow_ignore_indi", follow=str(new_state.follow_links)))
+ return Stage(new_state)
+
+
+@rpc(blocking=False)
+async def _toggle_version_control(state: State, is_visual: bool) -> Stage:
+ """
+ Toggle version control
+ """
+
+ enable_vc = not state.enable_vc
+ vc: Union[VoidType, VCStatus] = Void if enable_vc else VCStatus()
+ new_state = await forward(state, enable_vc=enable_vc, vc=vc)
+ await Nvim.write(LANG("version_control_indi", enable_vc=str(new_state.enable_vc)))
+ return Stage(new_state)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/types.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/types.py
new file mode 100644
index 00000000..abc8e376
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/transitions/types.py
@@ -0,0 +1,20 @@
+from dataclasses import dataclass
+from enum import Enum, auto
+from pathlib import PurePath
+from typing import Optional
+
+from ..state.types import State
+
+
+class ClickType(Enum):
+ primary = auto()
+ secondary = auto()
+ tertiary = auto()
+ v_split = auto()
+ h_split = auto()
+
+
+@dataclass(frozen=True)
+class Stage:
+ state: State
+ focus: Optional[PurePath] = None
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/git.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/git.py
new file mode 100644
index 00000000..ca2c9540
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/git.py
@@ -0,0 +1,189 @@
+from asyncio import gather
+from functools import lru_cache
+from itertools import chain
+from locale import strxfrm
+from os import linesep
+from os.path import normpath
+from pathlib import PurePath
+from string import whitespace
+from subprocess import CalledProcessError
+from typing import (
+ Iterable,
+ Iterator,
+ MutableMapping,
+ MutableSequence,
+ MutableSet,
+ Sequence,
+ Tuple,
+)
+
+from std2.asyncio import to_thread
+from std2.pathlib import ROOT
+from std2.string import removeprefix, removesuffix
+
+from ..fs.ops import ancestors, which
+from .nice import nice_call
+from .types import VCStatus
+
+_Stats = Iterable[Tuple[str, PurePath]]
+
+_WHITE_SPACES = {*whitespace}
+_GIT_LIST_CMD = (
+ "--no-optional-locks",
+ "status",
+ "--ignored",
+ "--renames",
+ "--porcelain",
+ "-z",
+)
+
+
+_GIT_SUBMODULE_MARKER = "Entering "
+_SUBMODULE_MARKER = "S"
+_IGNORED_MARKER = "I"
+_UNTRACKED_MARKER = "?"
+
+
+async def root(git: PurePath, cwd: PurePath) -> PurePath:
+ stdout = await nice_call(
+ (
+ git,
+ "--no-optional-locks",
+ "rev-parse",
+ "--path-format=relative",
+ "--show-toplevel",
+ ),
+ cwd=cwd,
+ )
+ return PurePath(normpath(cwd / stdout.rstrip()))
+
+
+@lru_cache(maxsize=1)
+def _parse_stats_main(stdout: str) -> Sequence[Tuple[str, PurePath]]:
+ def cont() -> Iterator[Tuple[str, PurePath]]:
+ it = iter(stdout.split("\0"))
+ for line in it:
+ prefix, file = line[:2], line[3:]
+ yield prefix, PurePath(file)
+
+ if "R" in prefix:
+ next(it, None)
+
+ return tuple(cont())
+
+
+async def _stat_main(git: PurePath, cwd: PurePath) -> str:
+ stdout = await nice_call((git, *_GIT_LIST_CMD), cwd=cwd)
+ return stdout
+
+
+@lru_cache(maxsize=1)
+def _parse_sub_modules(stdout: str) -> Sequence[Tuple[str, PurePath]]:
+ def cont() -> Iterator[Tuple[str, PurePath]]:
+ it = iter(stdout)
+ sub_module = ROOT
+ acc: MutableSequence[str] = []
+
+ for char in it:
+ if char == linesep:
+ line = "".join(acc)
+ acc.clear()
+
+ if not line.startswith(_GIT_SUBMODULE_MARKER):
+ raise ValueError(stdout)
+ else:
+ quoted = removeprefix(line, prefix=_GIT_SUBMODULE_MARKER)
+ if not (quoted.startswith("'") and quoted.endswith("'")):
+ raise ValueError(stdout)
+ else:
+ sub_module = PurePath(
+ removesuffix(removeprefix(quoted, prefix="'"), suffix="'")
+ )
+ yield _SUBMODULE_MARKER, sub_module
+
+ elif char == "\0":
+ line = "".join(acc)
+ acc.clear()
+
+ if not sub_module:
+ raise ValueError(stdout)
+ else:
+ prefix, file = line[:2], line[3:]
+ yield prefix, sub_module / file
+
+ if "R" in prefix:
+ next(it, None)
+ else:
+ acc.append(char)
+
+ return tuple(cont())
+
+
+async def _stat_sub_modules(git: PurePath, cwd: PurePath) -> str:
+ stdout = await nice_call(
+ (
+ git,
+ "--no-optional-locks",
+ "submodule",
+ "foreach",
+ "--recursive",
+ git,
+ *_GIT_LIST_CMD,
+ ),
+ cwd=cwd,
+ )
+ return stdout
+
+
+def _stat_name(stat: str) -> str:
+ markers = {
+ "!!": _IGNORED_MARKER,
+ "??": _UNTRACKED_MARKER,
+ }
+ return markers.get(stat, stat)
+
+
+def _parse(root: PurePath, stats: _Stats) -> VCStatus:
+ above = ancestors(root)
+ ignored: MutableSet[PurePath] = set()
+ status: MutableMapping[PurePath, str] = {}
+ directories: MutableMapping[PurePath, MutableSet[str]] = {}
+
+ for stat, name in stats:
+ path = root / name
+ status[path] = _stat_name(stat)
+ if "!" in stat:
+ ignored.add(path)
+ else:
+ for ancestor in ancestors(path):
+ parents = directories.setdefault(ancestor, set())
+ if stat != _SUBMODULE_MARKER:
+ for sym in stat:
+ parents.add(sym)
+
+ for directory, syms in directories.items():
+ pre_existing = {*status.get(directory, "")}
+ symbols = pre_existing | syms - _WHITE_SPACES
+ consoildated = sorted(symbols, key=strxfrm)
+ status[directory] = "".join(consoildated)
+
+ trimmed = {path: stat for path, stat in status.items() if path not in above}
+ return VCStatus(ignored=ignored, status=trimmed)
+
+
+async def status(cwd: PurePath, prev: VCStatus) -> VCStatus:
+ if git := which("git"):
+ bin = PurePath(git)
+ try:
+ raw_root, main, submodules = await gather(
+ root(bin, cwd=cwd),
+ _stat_main(bin, cwd=cwd),
+ _stat_sub_modules(bin, cwd=cwd),
+ )
+ stats = chain((_parse_stats_main(main)), _parse_sub_modules(submodules))
+ except CalledProcessError:
+ return VCStatus()
+ else:
+ return await to_thread(lambda: _parse(raw_root, stats=stats))
+ else:
+ return VCStatus()
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/nice.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/nice.py
new file mode 100644
index 00000000..de1c3472
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/nice.py
@@ -0,0 +1,42 @@
+import sys
+from contextlib import suppress
+from os import environ
+from pathlib import PurePath
+from typing import Optional, Sequence
+
+from pynvim_pp.lib import decode
+from std2.asyncio.subprocess import call
+from std2.pathlib import AnyPath
+
+if sys.platform == "win32":
+ from subprocess import BELOW_NORMAL_PRIORITY_CLASS
+
+ nice = lambda _: None
+else:
+ from os import nice
+
+ BELOW_NORMAL_PRIORITY_CLASS = 0
+
+
+_ENV = {**environ, "LC_ALL": "C"}
+
+
+def _nice() -> None:
+ with suppress(PermissionError):
+ nice(19)
+
+
+async def nice_call(
+ argv: Sequence[AnyPath],
+ stdin: Optional[bytes] = None,
+ cwd: Optional[PurePath] = None,
+) -> str:
+ proc = await call(
+ *argv,
+ cwd=cwd,
+ stdin=stdin,
+ env=_ENV,
+ preexec_fn=_nice,
+ creationflags=BELOW_NORMAL_PRIORITY_CLASS,
+ )
+ return decode(proc.stdout)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/types.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/types.py
new file mode 100644
index 00000000..aa9378d3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/version_ctl/types.py
@@ -0,0 +1,12 @@
+from dataclasses import dataclass, field
+from pathlib import PurePath
+from typing import AbstractSet, Mapping, MutableMapping
+
+
+@dataclass(frozen=True)
+class VCStatus:
+ main: str = ""
+ submodules: str = ""
+ ignored: AbstractSet[PurePath] = frozenset()
+ status: Mapping[PurePath, str] = field(default_factory=dict)
+ ignore_cache: MutableMapping[PurePath, bool] = field(default_factory=dict)
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/view/__init__.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/view/highlight.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/highlight.py
new file mode 100644
index 00000000..301e5f47
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/highlight.py
@@ -0,0 +1,27 @@
+from typing import Iterator, Mapping, Tuple
+from uuid import uuid4
+
+from pynvim_pp.highlight import HLgroup
+
+from ..consts import FM_HL_PREFIX
+
+LEGAL_CTERM = {
+ "bold",
+ "underline",
+ "undercurl",
+ "strikethrough",
+ "reverse",
+ "italic",
+ "standout",
+}
+
+LEGAL_CTERM_COLOURS = range(8)
+
+
+def gen_hl(name_prefix: str, mapping: Mapping[str, str]) -> Mapping[str, HLgroup]:
+ def cont() -> Iterator[Tuple[str, HLgroup]]:
+ for key, val in mapping.items():
+ name = f"{FM_HL_PREFIX}_{name_prefix}_{uuid4().hex}"
+ yield key, HLgroup(name=name, guifg=val)
+
+ return {k: v for k, v in cont()}
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/view/load.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/load.py
new file mode 100644
index 00000000..ae7b8032
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/load.py
@@ -0,0 +1,118 @@
+from itertools import chain
+from os import environ
+from typing import Mapping, Tuple, TypeVar, Union
+
+from pynvim_pp.highlight import HLgroup
+from std2.types import never
+
+from chad_types import (
+ Artifact,
+ IconColourSetEnum,
+ IconGlyphs,
+ IconGlyphSetEnum,
+ LSColoursEnum,
+ TextColourSetEnum,
+)
+
+from ..consts import FM_HL_PREFIX
+from .highlight import gen_hl
+from .ls_colours import parse_lsc
+from .types import HLcontext, HLGroups
+
+T = TypeVar("T")
+
+
+def _trans(mapping: Mapping[T, HLgroup]) -> Mapping[T, str]:
+ return {k: v.name for k, v in mapping.items()}
+
+
+def load_theme(
+ artifact: Artifact,
+ particular_mappings: HLGroups,
+ discrete_colours: Mapping[str, str],
+ icon_set: IconGlyphSetEnum,
+ icon_colour_set: IconColourSetEnum,
+ text_colour_set: Union[LSColoursEnum, TextColourSetEnum],
+) -> Tuple[IconGlyphs, HLcontext]:
+ if icon_set is IconGlyphSetEnum.ascii:
+ icons = artifact.icons.ascii
+ elif icon_set is IconGlyphSetEnum.ascii_hollow:
+ icons = artifact.icons.ascii_hollow
+ elif icon_set is IconGlyphSetEnum.devicons:
+ icons = artifact.icons.devicons
+ elif icon_set is IconGlyphSetEnum.emoji:
+ icons = artifact.icons.emoji
+ else:
+ never(icon_set)
+
+ if text_colour_set is LSColoursEnum.env and "LS_COLORS" not in environ:
+ text_colour_set = LSColoursEnum.solarized_dark_256
+
+ if isinstance(text_colour_set, LSColoursEnum):
+ if text_colour_set is LSColoursEnum.env:
+ _lsc = environ.get("LS_COLORS", "")
+ elif text_colour_set is LSColoursEnum.solarized_dark_256:
+ _lsc = artifact.ls_colours.solarized_dark_256
+ elif text_colour_set is LSColoursEnum.solarized_light:
+ _lsc = artifact.ls_colours.solarized_light
+ elif text_colour_set is LSColoursEnum.solarized_dark:
+ _lsc = artifact.ls_colours.solarized_dark
+ elif text_colour_set is LSColoursEnum.solarized_universal:
+ _lsc = artifact.ls_colours.solarized_universal
+ elif text_colour_set is LSColoursEnum.nord:
+ _lsc = artifact.ls_colours.nord
+ elif text_colour_set is LSColoursEnum.trapdoor:
+ _lsc = artifact.ls_colours.trapdoor
+ else:
+ never(text_colour_set)
+
+ lsc = parse_lsc(_lsc, discrete_colours=discrete_colours)
+ mode_pre = lsc.mode_pre
+ mode_post = lsc.mode_post
+ ext_exact = lsc.exts
+ name_exact: Mapping[str, HLgroup] = {}
+ name_glob = lsc.name_glob
+ else:
+ if text_colour_set is TextColourSetEnum.nerdtree_syntax_light:
+ text_colour = artifact.text_colours.nerdtree_syntax_light
+ elif text_colour_set is TextColourSetEnum.nerdtree_syntax_dark:
+ text_colour = artifact.text_colours.nerdtree_syntax_dark
+ else:
+ never(text_colour_set)
+
+ mode_pre = {}
+ mode_post = {}
+ ext_exact = gen_hl(FM_HL_PREFIX, mapping=text_colour.ext_exact)
+ name_exact = gen_hl(FM_HL_PREFIX, mapping=text_colour.name_exact)
+ name_glob = gen_hl(FM_HL_PREFIX, mapping=text_colour.name_glob)
+
+ if icon_colour_set is IconColourSetEnum.github:
+ icon_exts = gen_hl(FM_HL_PREFIX, mapping=artifact.icon_colours.github)
+ elif icon_colour_set is IconColourSetEnum.none:
+ icon_exts = gen_hl(FM_HL_PREFIX, mapping={})
+ else:
+ never(icon_colour_set)
+
+ groups = tuple(
+ chain(
+ icon_exts.values(),
+ mode_pre.values(),
+ mode_post.values(),
+ ext_exact.values(),
+ name_exact.values(),
+ name_glob.values(),
+ ),
+ )
+
+ context = HLcontext(
+ groups=groups,
+ icon_exts=_trans(icon_exts),
+ mode_pre=_trans(mode_pre),
+ mode_post=_trans(mode_post),
+ ext_exact=_trans(ext_exact),
+ name_exact=_trans(name_exact),
+ name_glob=_trans(name_glob),
+ particular_mappings=particular_mappings,
+ )
+
+ return icons, context
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/view/ls_colours.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/ls_colours.py
new file mode 100644
index 00000000..815b6f8f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/ls_colours.py
@@ -0,0 +1,303 @@
+from dataclasses import dataclass
+from enum import Enum, IntEnum, auto
+from itertools import chain, repeat
+from typing import (
+ AbstractSet,
+ Callable,
+ Iterator,
+ Mapping,
+ MutableMapping,
+ MutableSet,
+ Optional,
+ Tuple,
+ Union,
+)
+from uuid import uuid4
+
+from pynvim_pp.highlight import HLgroup
+from std2.coloursys import rgb_to_hex
+
+from ..consts import FM_HL_PREFIX
+from ..fs.types import Mode
+
+
+class _Style(IntEnum):
+ bold = auto()
+ dimmed = auto()
+ italic = auto()
+ underline = auto()
+ blink = auto()
+ blink_fast = auto()
+ reverse = auto()
+ hidden = auto()
+ strikethrough = auto()
+
+
+class _Ground(Enum):
+ fore = auto()
+ back = auto()
+
+
+class _AnsiColour(IntEnum):
+ black = auto()
+ red = auto()
+ green = auto()
+ yellow = auto()
+ blue = auto()
+ magenta = auto()
+ cyan = auto()
+ white = auto()
+
+ bright_black = auto()
+ bright_red = auto()
+ bright_green = auto()
+ bright_yellow = auto()
+ bright_blue = auto()
+ bright_magenta = auto()
+ bright_cyan = auto()
+ bright_white = auto()
+
+
+@dataclass(frozen=True)
+class _Colour:
+ r: int
+ g: int
+ b: int
+
+
+@dataclass(frozen=True)
+class _Styling:
+ styles: AbstractSet[_Style]
+ foreground: Union[_AnsiColour, _Colour, None]
+ background: Union[_AnsiColour, _Colour, None]
+
+
+@dataclass(frozen=True)
+class LSC:
+ mode_pre: Mapping[Mode, HLgroup]
+ mode_post: Mapping[Optional[Mode], HLgroup]
+ exts: Mapping[str, HLgroup]
+ name_glob: Mapping[str, HLgroup]
+
+
+_ANSI_RANGE = range(256)
+_RGB_RANGE = range(256)
+
+_STYLE_TABLE: Mapping[str, _Style] = {str(code + 0): code for code in _Style}
+
+_GROUND_TABLE: Mapping[str, _Ground] = {
+ str(code): ground
+ for code, ground in chain(
+ zip(chain(range(30, 39), range(90, 98)), repeat(_Ground.fore)),
+ zip(chain(range(40, 49), range(100, 108)), repeat(_Ground.back)),
+ )
+}
+
+_COLOUR_TABLE: Mapping[str, _AnsiColour] = {
+ str(code): colour
+ for code, colour in chain(
+ ((c + 29 if c <= 8 else c + 31, c) for c in _AnsiColour),
+ ((c + 89 if c <= 8 else c + 91, c) for c in _AnsiColour),
+ )
+}
+
+_RGB_TABLE: AbstractSet[str] = {"38", "48"}
+
+_E_BASIC_TABLE: Mapping[int, _AnsiColour] = {i: c for i, c in enumerate(_AnsiColour)}
+
+_E_GREY_TABLE: Mapping[int, _Colour] = {
+ i: _Colour(r=s, g=s, b=s)
+ for i, s in enumerate((round(step / 23 * 255) for step in range(24)), 232)
+}
+
+
+def _parse_8(codes: Iterator[str]) -> Union[_AnsiColour, _Colour, None]:
+ try:
+ ansi_code = int(next(codes, ""))
+ except ValueError:
+ return None
+ else:
+ if ansi_code in _ANSI_RANGE:
+ basic = _E_BASIC_TABLE.get(ansi_code)
+ if basic:
+ return basic
+ grey = _E_GREY_TABLE.get(ansi_code)
+ if grey:
+ return grey
+ ratio = 255 / 5
+ code = ansi_code - 16
+ r = code // 36
+ g = code % 36 // 6
+ b = code % 36 % 6
+ return _Colour(r=round(r * ratio), g=round(g * ratio), b=round(b * ratio))
+ else:
+ return None
+
+
+def _parse_24(codes: Iterator[str]) -> Optional[_Colour]:
+ try:
+ r, g, b = int(next(codes, "")), int(next(codes, "")), int(next(codes, ""))
+ except ValueError:
+ return None
+ else:
+ if r in _RGB_RANGE and g in _RGB_RANGE and b in _RGB_RANGE:
+ return _Colour(r=r, g=g, b=b)
+ else:
+ return None
+
+
+_PARSE_TABLE: Mapping[
+ str, Callable[[Iterator[str]], Union[_AnsiColour, _Colour, None]]
+] = {
+ "5": _parse_8,
+ "2": _parse_24,
+}
+
+
+_SPECIAL_PRE_TABLE: Mapping[str, Mode] = {
+ "bd": Mode.block_device,
+ "ca": Mode.file_w_capacity,
+ "cd": Mode.char_device,
+ "di": Mode.folder,
+ "do": Mode.door,
+ "ex": Mode.executable,
+ "ln": Mode.link,
+ "mh": Mode.multi_hardlink,
+ "or": Mode.orphan_link,
+ "ow": Mode.other_writable,
+ "pi": Mode.pipe,
+ "sg": Mode.set_gid,
+ "so": Mode.socket,
+ "st": Mode.sticky,
+ "su": Mode.set_uid,
+ "tw": Mode.sticky_other_writable,
+}
+
+
+_SPECIAL_POST_TABLE: Mapping[str, Optional[Mode]] = {
+ "fi": Mode.file,
+ "no": None,
+}
+
+_UNUSED = {
+ "mi": "colour of missing symlink pointee",
+ "cl": "ANSI clear",
+ "ec": "ANSI end_code",
+ "lc": "ANSI left_code",
+ "rc": "ANSI right_code",
+ "rs": "ANSI reset",
+}
+
+assert _UNUSED
+
+
+_HL_STYLE_TABLE: Mapping[_Style, Optional[str]] = {
+ _Style.bold: "bold",
+ _Style.dimmed: None,
+ _Style.italic: "italic",
+ _Style.underline: "underline",
+ _Style.blink: None,
+ _Style.blink_fast: None,
+ _Style.reverse: "reverse",
+ _Style.hidden: None,
+ _Style.strikethrough: "strikethrough",
+}
+
+
+def _parse_codes(
+ codes: str,
+) -> Iterator[Union[_Style, Tuple[_Ground, Union[_AnsiColour, _Colour]]]]:
+ it = (code.lstrip("0") for code in codes.split(";"))
+ for code in it:
+ style = _STYLE_TABLE.get(code)
+ if style:
+ yield style
+ continue
+ ground = _GROUND_TABLE.get(code)
+ ansi_colour = _COLOUR_TABLE.get(code)
+ if ground and ansi_colour:
+ yield ground, ansi_colour
+ elif ground and code in _RGB_TABLE:
+ code = next(it, "")
+ parse = _PARSE_TABLE.get(code)
+ if parse:
+ colour = parse(it)
+ if colour:
+ yield ground, colour
+
+
+def _parse_styling(codes: str) -> _Styling:
+ styles: MutableSet[_Style] = set()
+ colours: MutableMapping[_Ground, Union[_AnsiColour, _Colour]] = {}
+ for ret in _parse_codes(codes):
+ if isinstance(ret, _Style):
+ styles.add(ret)
+ elif isinstance(ret, tuple):
+ ground, colour = ret
+ colours[ground] = colour
+
+ styling = _Styling(
+ styles=styles,
+ foreground=colours.get(_Ground.fore),
+ background=colours.get(_Ground.back),
+ )
+ return styling
+
+
+def _parseHLGroup(styling: _Styling, discrete_colours: Mapping[str, str]) -> HLgroup:
+ fg, bg = styling.foreground, styling.background
+ name = f"{FM_HL_PREFIX}_ls_{uuid4().hex}"
+ cterm = {
+ style
+ for style in (_HL_STYLE_TABLE.get(style) for style in styling.styles)
+ if style
+ }
+ ctermfg = fg.value - 1 if isinstance(fg, _AnsiColour) else None
+ ctermbg = bg.value - 1 if isinstance(bg, _AnsiColour) else None
+ guifg = (
+ rgb_to_hex(fg.r, fg.g, fg.b)
+ if isinstance(fg, _Colour)
+ else (discrete_colours.get(fg.name) if isinstance(fg, _AnsiColour) else None)
+ )
+ guibg = (
+ rgb_to_hex(bg.r, bg.g, bg.b)
+ if isinstance(bg, _Colour)
+ else (discrete_colours.get(bg.name) if isinstance(bg, _AnsiColour) else None)
+ )
+ group = HLgroup(
+ name=name,
+ cterm=cterm,
+ ctermfg=ctermfg,
+ ctermbg=ctermbg,
+ guifg=guifg,
+ guibg=guibg,
+ )
+ return group
+
+
+def parse_lsc(ls_colours: str, discrete_colours: Mapping[str, str]) -> LSC:
+ hl_lookup = {
+ key: _parseHLGroup(_parse_styling(val), discrete_colours=discrete_colours)
+ for key, _, val in (
+ segment.partition("=") for segment in ls_colours.strip(":").split(":")
+ )
+ }
+
+ mode_pre = {
+ mode: hl
+ for indicator, mode in _SPECIAL_PRE_TABLE.items()
+ if (hl := hl_lookup.pop(indicator, None))
+ }
+ mode_post = {
+ mode: hl
+ for indicator, mode in _SPECIAL_POST_TABLE.items()
+ if (hl := hl_lookup.pop(indicator, None))
+ }
+
+ _ext_keys = tuple(
+ key for key in hl_lookup if key.startswith("*.") and key.count(".") == 1
+ )
+ exts = {key[1:]: hl_lookup.pop(key) for key in _ext_keys}
+
+ lsc = LSC(exts=exts, mode_pre=mode_pre, mode_post=mode_post, name_glob=hl_lookup)
+ return lsc
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/view/ops.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/ops.py
new file mode 100644
index 00000000..73f78dd9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/ops.py
@@ -0,0 +1,25 @@
+from os import sep
+from os.path import relpath
+from pathlib import Path, PurePath
+from string import whitespace
+
+from ..state.types import State
+
+_WS = {*whitespace} - {"\t"}
+
+
+def encode_for_display(text: str) -> str:
+ encoded = "".join(
+ char.encode("unicode_escape").decode("utf-8") if char in _WS else char
+ for char in text
+ )
+ return encoded
+
+
+def display_path(path: PurePath, state: State) -> str:
+ raw = relpath(path, start=state.root.path)
+ name = encode_for_display(raw)
+ if Path(path).is_dir():
+ return f"{name}{sep}"
+ else:
+ return name
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/view/render.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/render.py
new file mode 100644
index 00000000..093d4496
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/render.py
@@ -0,0 +1,345 @@
+from collections import UserString
+from enum import IntEnum, auto
+from fnmatch import fnmatch
+from functools import lru_cache
+from locale import strxfrm
+from os.path import extsep, sep
+from pathlib import PurePath
+from typing import Any, Callable, Iterator, Optional, Sequence, Tuple, Union, cast
+
+from pynvim_pp.lib import encode
+from std2.platform import OS, os
+from std2.types import never
+
+from ..fs.cartographer import is_dir, user_ignored
+from ..fs.types import Mode, Node
+from ..nvim.types import Markers
+from ..settings.types import Settings
+from ..state.types import Diagnostics, FilterPattern, Index, Selection
+from ..version_ctl.types import VCStatus
+from .ops import encode_for_display
+from .types import Badge, Derived, Highlight, Sortby
+
+
+class _CompVals(IntEnum):
+ FOLDER = auto()
+ FILE = auto()
+
+
+_Str = Union[str, UserString]
+_Render = Tuple[str, Sequence[Highlight], Sequence[Badge]]
+_NRender = Tuple[Node, str, Sequence[Highlight], Sequence[Badge]]
+
+
+class _str(UserString):
+ def __lt__(self, _: _Str) -> bool:
+ return False
+
+ def __gt__(self, _: _Str) -> bool:
+ return True
+
+
+_EMPTY = _str("")
+
+
+def _suffixx(path: PurePath) -> _Str:
+ if path.suffix:
+ return strxfrm(path.suffix)
+ elif path.stem.startswith(extsep):
+ return strxfrm(path.stem)
+ else:
+ return _EMPTY
+
+
+def _lax_suffix(path: PurePath) -> str:
+ return path.suffix or path.name
+
+
+@lru_cache(maxsize=None)
+def _gen_comp(sortby: Sequence[Sortby]) -> Callable[[Node], Any]:
+ def comp(node: Node) -> Sequence[Any]:
+ if node.cache.sort_by is None:
+
+ def cont() -> Iterator[Any]:
+ for sb in sortby:
+ if sb is Sortby.is_folder:
+ yield _CompVals.FOLDER if is_dir(node) else _CompVals.FILE
+ elif sb is Sortby.ext:
+ yield "" if is_dir(node) else _suffixx(node.path)
+ elif sb is Sortby.file_name_lower:
+ yield strxfrm(node.path.name.casefold())
+ elif sb is Sortby.file_name:
+ yield strxfrm(node.path.name)
+ else:
+ never(sb)
+
+ node.cache.sort_by = tuple(cont())
+ return node.cache.sort_by
+
+ return comp
+
+
+def _vc_ignored(node: Node, vc: VCStatus) -> bool:
+ path = node.path
+ if (ignored := vc.ignore_cache.get(path, None)) is not None:
+ return ignored
+ else:
+ ignored = not vc.ignored.isdisjoint({path} | {*map(PurePath, path.parents)})
+ vc.ignore_cache[path] = ignored
+ return ignored
+
+
+def _gen_spacer(depth: int) -> str:
+ return (depth * 2 - 1) * " "
+
+
+def _paint(
+ settings: Settings,
+ index: Index,
+ selection: Selection,
+ markers: Markers,
+ diagnostics: Diagnostics,
+ vc: VCStatus,
+ follow_links: bool,
+ show_hidden: bool,
+ current: Optional[PurePath],
+) -> Callable[[Node, int], Optional[_Render]]:
+ icons = settings.view.icons
+ context = settings.view.hl_context
+
+ def search_icon_hl(node: Node, ignored: bool) -> Optional[str]:
+ if ignored:
+ return context.particular_mappings.ignored
+ else:
+ return context.icon_exts.get(_lax_suffix(node.path))
+
+ def search_text_hl(node: Node, ignored: bool) -> Optional[str]:
+ if ignored:
+ return context.particular_mappings.ignored
+
+ s_modes = sorted(node.mode)
+ for mode in s_modes:
+ if os is OS.windows and mode is Mode.other_writable:
+ pass
+ elif hl := context.mode_pre.get(mode):
+ return hl
+
+ if hl := context.name_exact.get(node.path.name):
+ return hl
+
+ for pattern, hl in context.name_glob.items():
+ if fnmatch(node.path.name, pattern):
+ return hl
+
+ if hl := context.ext_exact.get(_lax_suffix(node.path)):
+ return hl
+
+ for mode in s_modes:
+ if hl := context.mode_post.get(mode):
+ return hl
+ else:
+ return context.mode_post.get(None)
+
+ def gen_status(path: PurePath) -> str:
+ selected = (
+ icons.status.selected if path in selection else icons.status.not_selected
+ )
+ active = icons.status.active if path == current else icons.status.inactive
+ return f"{selected}{active}"
+
+ def gen_decor_pre(node: Node, depth: int) -> Iterator[str]:
+ yield _gen_spacer(depth)
+ yield gen_status(node.path)
+
+ def gen_icon(node: Node) -> Iterator[str]:
+ yield " "
+ if is_dir(node):
+ if node.pointed and not follow_links:
+ yield icons.link.normal
+ elif node.path in index:
+ yield icons.folder.open
+ else:
+ yield icons.folder.closed
+ else:
+ yield (
+ (
+ icons.name_exact.get(node.path.name, "")
+ or icons.ext_exact.get(_lax_suffix(node.path), "")
+ or next(
+ (
+ v
+ for k, v in icons.name_glob.items()
+ if fnmatch(node.path.name, k)
+ ),
+ icons.default_icon,
+ )
+ )
+ if settings.view.use_icons
+ else icons.default_icon
+ )
+ yield " "
+
+ def gen_name(node: Node) -> Iterator[str]:
+ yield encode_for_display(node.path.name)
+ if not settings.view.use_icons and is_dir(node):
+ yield sep
+
+ def gen_decor_post(node: Node) -> Iterator[str]:
+ mode = node.mode
+ if Mode.orphan_link in mode:
+ yield " "
+ yield icons.link.broken
+ elif Mode.link in mode:
+ yield " "
+ if is_dir(node) and not follow_links:
+ if node.path in index:
+ yield icons.folder.open
+ else:
+ yield icons.folder.closed
+ else:
+ yield icons.link.normal
+
+ def gen_badges(path: PurePath) -> Iterator[Badge]:
+ l = ""
+ if diagnostic := diagnostics.get(path, {}):
+ l = " "
+ dl = len(diagnostic)
+ for idx, (severity, count) in enumerate(sorted(diagnostic.items())):
+ group = context.particular_mappings.diagnostics.get(
+ severity, context.particular_mappings.diagnostic_unknown
+ )
+ lhs, rhs = not idx, idx + 1 == dl
+ r = " " if dl > 1 and not rhs else ""
+ if lhs:
+ yield Badge(
+ text="{", group=context.particular_mappings.diagnostic_context
+ )
+ yield Badge(text=f"{count}{r}", group=group)
+ if rhs:
+ yield Badge(
+ text="}", group=context.particular_mappings.diagnostic_context
+ )
+
+ if marks := markers.bookmarks.get(path):
+ ordered = "".join(sorted(marks))
+ yield Badge(
+ text=f"{l}<{ordered}>",
+ group=context.particular_mappings.bookmarks,
+ )
+
+ if qf_count := markers.quick_fix.get(path):
+ yield Badge(
+ text=f"{l}({qf_count})",
+ group=context.particular_mappings.quickfix,
+ )
+
+ if stat := vc.status.get(path):
+ yield Badge(
+ text=f"{l}[{stat}]",
+ group=context.particular_mappings.version_control,
+ )
+
+ def gen_highlights(
+ node: Node, pre: str, icon: str, name: str, ignored: bool
+ ) -> Iterator[Highlight]:
+ icon_begin = len(encode(pre))
+ icon_end = icon_begin + len(encode(icon))
+ text_begin = icon_end
+ text_end = len(encode(name)) + text_begin
+
+ if icon_group := search_icon_hl(node, ignored=ignored):
+ hl = Highlight(group=icon_group, begin=icon_begin, end=icon_end)
+ yield hl
+
+ if text_group := search_text_hl(node, ignored=ignored):
+ hl = Highlight(group=text_group, begin=text_begin, end=text_end)
+ yield hl
+
+ def show(node: Node, depth: int) -> Optional[_Render]:
+ _user_ignored = user_ignored(node, ignores=settings.ignores)
+ vc_ignored = _vc_ignored(node, vc=vc)
+ ignored = vc_ignored or _user_ignored
+
+ if depth and _user_ignored and not show_hidden:
+ return None
+ else:
+ pre = "".join(gen_decor_pre(node, depth=depth))
+ icon = "".join(gen_icon(node))
+ name = "".join(gen_name(node))
+ post = "".join(gen_decor_post(node))
+
+ line = f"{pre}{icon}{name}{post}"
+ badges = tuple(gen_badges(node.path))
+ highlights = tuple(
+ gen_highlights(node, pre=pre, icon=icon, name=name, ignored=ignored)
+ )
+ return line, highlights, badges
+
+ return show
+
+
+def render(
+ node: Node,
+ *,
+ settings: Settings,
+ index: Index,
+ selection: Selection,
+ filter_pattern: Optional[FilterPattern],
+ markers: Markers,
+ diagnostics: Diagnostics,
+ vc: VCStatus,
+ follow_links: bool,
+ show_hidden: bool,
+ current: Optional[PurePath],
+) -> Derived:
+ show = _paint(
+ settings,
+ index=index,
+ selection=selection,
+ markers=markers,
+ diagnostics=diagnostics,
+ vc=vc,
+ follow_links=follow_links,
+ show_hidden=show_hidden,
+ current=current,
+ )
+ comp = _gen_comp(settings.view.sort_by)
+ keep_open = {node.path}
+
+ def render(node: Node, *, depth: int, cleared: bool) -> Iterator[_NRender]:
+ clear = (
+ cleared
+ or not filter_pattern
+ or fnmatch(node.path.name, filter_pattern.pattern)
+ )
+
+ if rend := show(node, depth):
+
+ def gen_children() -> Iterator[_NRender]:
+ for child in sorted(node.children.values(), key=comp):
+ yield from render(child, depth=depth + 1, cleared=clear)
+
+ children = tuple(gen_children())
+ if clear or children or node.path in keep_open:
+ yield (node, *rend)
+ yield from iter(children)
+
+ rendered = render(node, depth=0, cleared=False)
+ _nodes, _lines, _highlights, _badges = zip(*rendered)
+ nodes, lines, highlights, badges = (
+ cast(Sequence[Node], _nodes),
+ cast(Sequence[str], _lines),
+ cast(Sequence[Sequence[Highlight]], _highlights),
+ cast(Sequence[Sequence[Badge]], _badges),
+ )
+ hashed = tuple(str(hash(zipped)) for zipped in zip(lines, highlights, badges))
+ path_row_lookup = {node.path: idx for idx, node in enumerate(nodes)}
+ derived = Derived(
+ lines=lines,
+ highlights=highlights,
+ badges=badges,
+ hashed=hashed,
+ node_row_lookup=nodes,
+ path_row_lookup=path_row_lookup,
+ )
+ return derived
diff --git a/config/neovim/store/lazy-plugins/chadtree/chadtree/view/types.py b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/types.py
new file mode 100644
index 00000000..1c11037a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/chadtree/view/types.py
@@ -0,0 +1,74 @@
+from dataclasses import dataclass
+from enum import Enum, auto
+from pathlib import PurePath
+from typing import Mapping, Optional, Sequence
+
+from pynvim_pp.highlight import HLgroup
+
+from chad_types import IconGlyphs
+
+from ..fs.types import Mode, Node
+
+
+@dataclass(frozen=True)
+class HLGroups:
+ bookmarks: str
+ ignored: str
+ marks: str
+ quickfix: str
+ diagnostics: Mapping[int, str]
+ diagnostic_unknown: str
+ diagnostic_context: str
+ version_control: str
+
+
+@dataclass(frozen=True)
+class HLcontext:
+ groups: Sequence[HLgroup]
+ icon_exts: Mapping[str, str]
+ mode_pre: Mapping[Mode, str]
+ mode_post: Mapping[Optional[Mode], str]
+ name_exact: Mapping[str, str]
+ name_glob: Mapping[str, str]
+ ext_exact: Mapping[str, str]
+ particular_mappings: HLGroups
+
+
+class Sortby(Enum):
+ is_folder = auto()
+ ext = auto()
+ file_name_lower = auto()
+ file_name = auto()
+
+
+@dataclass(frozen=True)
+class ViewOptions:
+ hl_context: HLcontext
+ icons: IconGlyphs
+ sort_by: Sequence[Sortby]
+ time_fmt: str
+ use_icons: bool
+
+
+@dataclass(frozen=True)
+class Badge:
+ text: str
+ group: str
+
+
+@dataclass(frozen=True)
+class Highlight:
+ begin: int
+ end: int
+ group: str
+
+
+@dataclass(frozen=True)
+class Derived:
+ lines: Sequence[str]
+ highlights: Sequence[Sequence[Highlight]]
+ badges: Sequence[Sequence[Badge]]
+
+ hashed: Sequence[str]
+ node_row_lookup: Sequence[Node]
+ path_row_lookup: Mapping[PurePath, int]
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/__init__.py b/config/neovim/store/lazy-plugins/chadtree/ci/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/__main__.py b/config/neovim/store/lazy-plugins/chadtree/ci/__main__.py
new file mode 100644
index 00000000..eef3012a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/__main__.py
@@ -0,0 +1,31 @@
+from json import dump
+
+from std2.graphlib import recur_sort
+from std2.pickle.encoder import new_encoder
+
+from chad_types import ARTIFACT, Artifact
+
+from .icon_colours import load_icon_colours
+from .ls_colours import load_ls_colours
+from .text_decorations import load_text_decors
+
+
+def main() -> None:
+ encode = new_encoder[Artifact](Artifact)
+ ls_colours = load_ls_colours()
+ icon_colours = load_icon_colours()
+ icons, text_colours = load_text_decors()
+
+ artifact = Artifact(
+ icons=icons,
+ ls_colours=ls_colours,
+ icon_colours=icon_colours,
+ text_colours=text_colours,
+ )
+
+ json = recur_sort(encode(artifact))
+ with ARTIFACT.open("w") as fd:
+ dump(json, fd, ensure_ascii=False, check_circular=False, indent=2)
+
+
+main()
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/icon_colours/__init__.py b/config/neovim/store/lazy-plugins/chadtree/ci/icon_colours/__init__.py
new file mode 100644
index 00000000..b516da4d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/icon_colours/__init__.py
@@ -0,0 +1,47 @@
+from dataclasses import dataclass
+from typing import Mapping, Optional, Sequence
+
+from std2.pickle.decoder import new_decoder
+from std2.urllib import urlopen
+from yaml import safe_load
+
+from chad_types import Hex, IconColours, IconColourSet
+
+_LINGUIST = """
+https://raw.githubusercontent.com/github/linguist/master/lib/linguist/languages.yml
+"""
+
+
+@dataclass(frozen=True)
+class _GithubColours:
+ extensions: Sequence[str] = ()
+ color: Optional[Hex] = None
+
+
+_GithubSpec = Mapping[str, _GithubColours]
+
+
+def _fetch(uri: str) -> str:
+ with urlopen(uri) as resp:
+ code = resp.getcode()
+ body = resp.read()
+ if code != 200:
+ raise Exception(resp.headers, body)
+ else:
+ return body.decode()
+
+
+def load_icon_colours() -> IconColourSet:
+ decode = new_decoder[_GithubSpec](_GithubSpec, strict=False)
+
+ rawGH = _fetch(_LINGUIST)
+ yamlGH = decode(safe_load(rawGH))
+
+ github: IconColours = {
+ ext: spec.color
+ for spec in yamlGH.values()
+ for ext in spec.extensions
+ if spec.color
+ }
+ colours = IconColourSet(github=github)
+ return colours
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/Dockerfile b/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/Dockerfile
new file mode 100644
index 00000000..a6aa4fe8
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/Dockerfile
@@ -0,0 +1,19 @@
+FROM ubuntu:latest
+
+
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends -- python3 git ca-certificates && \
+ rm -rf -- /var/lib/apt/lists/* && \
+ update-ca-certificates
+
+
+WORKDIR /root
+
+
+RUN git clone --depth=1 https://github.com/seebi/dircolors-solarized.git && \
+ git clone --depth=1 https://github.com/arcticicestudio/nord-dircolors.git && \
+ git clone --depth=1 https://github.com/trapd00r/LS_COLORS
+COPY . /
+
+
+ENTRYPOINT ["./lsc.py"]
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/__init__.py b/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/__init__.py
new file mode 100644
index 00000000..044afb39
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/__init__.py
@@ -0,0 +1,18 @@
+from json import loads
+from pathlib import Path
+
+from std2.pickle.decoder import new_decoder
+
+from chad_types import LSColourSet
+
+from ..run import docker_run
+
+_DOCKERFILE = Path(__file__).resolve(strict=True).with_name("Dockerfile")
+
+
+def load_ls_colours() -> LSColourSet:
+ decode = new_decoder[LSColourSet](LSColourSet)
+
+ json = loads(docker_run(_DOCKERFILE))
+ lsc = decode(json)
+ return lsc
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/root/lsc.py b/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/root/lsc.py
new file mode 100755
index 00000000..a030131b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/root/lsc.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+
+from json import dump
+from os.path import normcase
+from pathlib import Path
+from subprocess import check_output
+from sys import stdout
+
+_LSC_SH = Path(__file__).resolve(strict=True).with_name("lsc.sh")
+
+_SOLARIZED = Path("dircolors-solarized").resolve(strict=True)
+_NORD = Path("nord-dircolors").resolve(strict=True)
+_TRAP_DOOR = Path("LS_COLORS").resolve(strict=True)
+
+_PARSING = {
+ _SOLARIZED / "dircolors.256dark": "solarized_dark_256",
+ _SOLARIZED / "dircolors.ansi-dark": "solarized_dark",
+ _SOLARIZED / "dircolors.ansi-light": "solarized_light",
+ _SOLARIZED / "dircolors.ansi-universal": "solarized_universal",
+ _NORD / "src" / "dir_colors": "nord",
+ _TRAP_DOOR / "LS_COLORS": "trapdoor",
+}
+
+
+def main() -> None:
+ lsc = {
+ dest: check_output((str(_LSC_SH), normcase(file_name)), text=True)
+ for file_name, dest in _PARSING.items()
+ }
+ dump(lsc, stdout, ensure_ascii=False, check_circular=False)
+
+
+main()
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/root/lsc.sh b/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/root/lsc.sh
new file mode 100755
index 00000000..ce0ce121
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/ls_colours/root/lsc.sh
@@ -0,0 +1,9 @@
+#!/nix/store/306znyj77fv49kwnkpxmb0j2znqpa8bj-bash-5.2p26/bin/bash
+
+set -eu
+set -o pipefail
+
+FILE="$1"
+export TERM=xterm-256color
+eval "$(dircolors -b "$FILE")"
+printf '%s' "$LS_COLORS"
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/prepare.py b/config/neovim/store/lazy-plugins/chadtree/ci/prepare.py
new file mode 100755
index 00000000..3669d087
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/prepare.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+
+from datetime import datetime, timezone
+from os import environ, sep
+from pathlib import Path
+from subprocess import check_call, check_output, run
+from sys import executable
+from typing import Iterator
+
+_TOP_LV = Path(__file__).resolve(strict=True).parent.parent
+
+
+def _git_identity() -> None:
+ email = "ci@ci.ci"
+ username = "ci-bot"
+ check_call(("git", "config", "--global", "user.email", email))
+ check_call(("git", "config", "--global", "user.name", username))
+
+
+def _get_branch() -> str:
+ if ref := environ.get("GITHUB_REF"):
+ return ref.replace("refs/heads/", "")
+ else:
+ br = check_output(("git", "branch", "--show-current"), text=True, cwd=_TOP_LV)
+ return br.strip()
+
+
+def _git_clone(path: Path) -> None:
+ if not path.is_dir():
+ if token := environ.get("CI_TOKEN"):
+ uri = f"https://ms-jpq:{token}@github.com/ms-jpq/chadtree.git"
+ else:
+ uri = "git@github.com:ms-jpq/chadtree.git"
+
+ branch = _get_branch()
+ check_call(("git", "clone", "--branch", branch, uri, path))
+
+
+def _build() -> None:
+ check_call((executable, "-m", "ci"), cwd=_TOP_LV)
+
+
+def _git_alert(cwd: Path) -> None:
+ prefix = "ci"
+ remote_brs = check_output(("git", "branch", "--remotes"), text=True, cwd=cwd)
+
+ def cont() -> Iterator[str]:
+ for br in remote_brs.splitlines():
+ b = br.strip()
+ if b and "->" not in b:
+ _, _, name = b.partition(sep)
+ if name.startswith(prefix):
+ yield name
+
+ refs = tuple(cont())
+
+ if refs:
+ check_call(("git", "push", "--delete", "origin", *refs), cwd=cwd)
+
+ proc = run(("git", "diff", "--exit-code"), cwd=cwd)
+ print(proc)
+ if proc.returncode:
+ time = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d")
+ brname = f"{prefix}--{time}"
+ check_call(("git", "checkout", "-b", brname), cwd=cwd)
+ check_call(("git", "add", "."), cwd=cwd)
+ check_call(("git", "commit", "-m", f"update_icons: {time}"), cwd=cwd)
+ check_call(
+ ("git", "push", "--force", "--set-upstream", "origin", brname), cwd=cwd
+ )
+
+
+def main() -> None:
+ cwd = Path() / "temp"
+ if "CI" in environ:
+ _git_identity()
+ _git_clone(cwd)
+ _build()
+ _git_alert(_TOP_LV)
+
+
+main()
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/run.py b/config/neovim/store/lazy-plugins/chadtree/ci/run.py
new file mode 100644
index 00000000..6ae694e5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/run.py
@@ -0,0 +1,25 @@
+from pathlib import Path
+from subprocess import check_call, check_output
+
+
+def docker_run(dockerfile: Path) -> str:
+ parent = dockerfile.parent
+ name = f"chad_{parent.name}"
+ check_call(
+ (
+ "docker",
+ "buildx",
+ "build",
+ "--progress",
+ "plain",
+ "--tag",
+ name,
+ "--file",
+ dockerfile,
+ "--",
+ ".",
+ ),
+ cwd=parent,
+ )
+ output = check_output(("docker", "run", "--rm", name), text=True)
+ return output
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/Dockerfile b/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/Dockerfile
new file mode 100644
index 00000000..1aafae84
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/Dockerfile
@@ -0,0 +1,21 @@
+FROM ubuntu:latest
+
+
+RUN apt-get update && \
+ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends -- neovim git ca-certificates && \
+ rm -rf -- /var/lib/apt/lists/*
+
+
+WORKDIR /root
+
+
+RUN git clone --depth=1 https://github.com/ryanoasis/vim-devicons.git && \
+ git clone --depth=1 https://github.com/adelarsq/vim-emoji-icon-theme.git && \
+ git clone --depth=1 https://github.com/tiagofumo/vim-nerdtree-syntax-highlight.git
+
+
+COPY . /
+
+
+RUN nvim --headless
+ENTRYPOINT ["cat", "exports.json"]
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/__init__.py b/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/__init__.py
new file mode 100644
index 00000000..8d82ae6e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/__init__.py
@@ -0,0 +1,104 @@
+from dataclasses import dataclass
+from json import loads
+from pathlib import Path
+from typing import Mapping, Tuple
+
+from std2.coloursys import hex_inverse
+from std2.graphlib import merge
+from std2.pickle.decoder import new_decoder
+from yaml import safe_load
+
+from chad_types import ASSETS, Hex, IconGlyphs, IconGlyphSet, TextColours, TextColourSet
+
+from ..run import docker_run
+
+
+@dataclass(frozen=True)
+class _TCAliases:
+ ext_exact: Mapping[str, str]
+ name_exact: Mapping[str, str]
+ name_glob: Mapping[str, str]
+
+
+@dataclass(frozen=True)
+class _Aliases:
+ icon_colours: Mapping[str, str]
+ text_colours: _TCAliases
+
+
+_DOCKERFILE = Path(__file__).resolve(strict=True).with_name("Dockerfile")
+_ICON_BASE = ASSETS / "icon_base.yml"
+_ALIASES = ASSETS / "aliases.yml"
+
+
+def _process_exts(exts: Mapping[str, str]) -> Mapping[str, str]:
+ return {f".{k}": v for k, v in exts.items()}
+
+
+def _process_glob(glob: Mapping[str, str]) -> Mapping[str, str]:
+ return {k.rstrip("$").replace(r"\.", "."): v for k, v in glob.items()}
+
+
+def _process_hexcode(colours: Mapping[str, str]) -> Mapping[str, Hex]:
+ return {k: f"#{v}" for k, v in colours.items()}
+
+
+def _process_inverse(colours: Mapping[str, str]) -> Mapping[str, str]:
+ return {k: hex_inverse(v) for k, v in colours.items()}
+
+
+def _process_icons(icons: IconGlyphs) -> IconGlyphs:
+ return IconGlyphs(
+ default_icon=icons.default_icon,
+ folder=icons.folder,
+ link=icons.link,
+ status=icons.status,
+ ext_exact=_process_exts(icons.ext_exact),
+ name_exact=icons.name_exact,
+ name_glob=_process_glob(icons.name_glob),
+ )
+
+
+def _process_colours(colours: TextColours) -> TextColours:
+ return TextColours(
+ ext_exact=_process_hexcode(_process_exts(colours.ext_exact)),
+ name_exact=_process_hexcode(colours.name_exact),
+ name_glob=_process_hexcode(_process_glob(colours.name_glob)),
+ )
+
+
+def _make_lightmode(colours: TextColours) -> TextColours:
+ return TextColours(
+ ext_exact=_process_inverse(colours.ext_exact),
+ name_exact=_process_inverse(colours.name_exact),
+ name_glob=_process_inverse(colours.name_glob),
+ )
+
+
+def load_text_decors() -> Tuple[IconGlyphSet, TextColourSet]:
+ i_decode = new_decoder[IconGlyphSet](IconGlyphSet, strict=False)
+ c_decode = new_decoder[TextColourSet](TextColourSet, strict=False)
+ a_decode = new_decoder[_Aliases](_Aliases)
+
+ icon_base = safe_load(_ICON_BASE.read_text("UTF-8"))
+ aliases = safe_load(_ALIASES.read_text("UTF-8"))
+
+ json = loads(docker_run(_DOCKERFILE))
+ data = merge(json, icon_base)
+ icon_spec = i_decode(data)
+ ali = a_decode(aliases)
+
+ icon_set = IconGlyphSet(
+ ascii=_process_icons(icon_spec.ascii),
+ ascii_hollow=_process_icons(icon_spec.ascii_hollow),
+ devicons=_process_icons(icon_spec.devicons),
+ emoji=_process_icons(icon_spec.emoji),
+ )
+ colour_spec = c_decode(data)
+ colour_set = TextColourSet(
+ nerdtree_syntax_light=_make_lightmode(
+ _process_colours(colour_spec.nerdtree_syntax_light)
+ ),
+ nerdtree_syntax_dark=_process_colours(colour_spec.nerdtree_syntax_dark),
+ )
+ return icon_set, colour_set
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/root/.config/nvim/init.vim b/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/root/.config/nvim/init.vim
new file mode 100644
index 00000000..8c161e57
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/root/.config/nvim/init.vim
@@ -0,0 +1 @@
+lua require 'chad'
diff --git a/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/root/.config/nvim/lua/chad.lua b/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/root/.config/nvim/lua/chad.lua
new file mode 100644
index 00000000..a490321c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/ci/text_decorations/root/.config/nvim/lua/chad.lua
@@ -0,0 +1,49 @@
+local export_icons = function()
+ return {
+ ext_exact = vim.g.WebDevIconsUnicodeDecorateFileNodesExtensionSymbols,
+ name_exact = vim.g.WebDevIconsUnicodeDecorateFileNodesExactSymbols,
+ name_glob = vim.g.WebDevIconsUnicodeDecorateFileNodesPatternSymbols,
+ default_icon = vim.g.WebDevIconsUnicodeDecorateFileNodesDefaultSymbol,
+ folder = {
+ open = vim.g.DevIconsDefaultFolderOpenSymbol,
+ closed = vim.g.WebDevIconsUnicodeDecorateFolderNodesDefaultSymbol
+ }
+ }
+end
+
+local export_colours = function()
+ return {
+ ext_exact = vim.g.NERDTreeExtensionHighlightColor,
+ name_exact = vim.g.NERDTreeExactMatchHighlightColor,
+ name_glob = vim.g.NERDTreePatternMatchHighlightColor
+ }
+end
+
+local load_rtp = function(src)
+ vim.o.runtimepath = vim.o.runtimepath .. "," .. "/root/" .. src
+end
+
+local load_viml = function(src)
+ vim.cmd("source " .. "/root/" .. src)
+end
+
+load_viml "vim-devicons/plugin/webdevicons.vim"
+local devicons = export_icons()
+
+load_viml "vim-emoji-icon-theme/plugin/vim-emoji-icon-theme.vim"
+local emoji = export_icons()
+
+load_viml "vim-nerdtree-syntax-highlight/after/syntax/nerdtree.vim"
+local nerdtree_syntax = export_colours()
+
+local exports = {
+ devicons = devicons,
+ emoji = emoji,
+ nerdtree_syntax_light = nerdtree_syntax,
+ nerdtree_syntax_dark = nerdtree_syntax
+}
+local json = vim.fn.json_encode(exports)
+
+vim.fn.writefile({json}, "exports.json")
+
+os.exit(0)
diff --git a/config/neovim/store/lazy-plugins/chadtree/config/defaults.yml b/config/neovim/store/lazy-plugins/chadtree/config/defaults.yml
new file mode 100644
index 00000000..8ddb9096
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/config/defaults.yml
@@ -0,0 +1,171 @@
+---
+idle_timeout: 1.0
+ignore:
+ name_exact:
+ - .DS_Store
+ - .directory
+ - .git
+ - .localized
+ - thumbs.db
+ name_glob: []
+ path_glob: []
+keymap:
+ bigger:
+ - +
+ - "="
+ bookmark_goto:
+ - m
+ change_dir:
+ - b
+ change_focus:
+ - c
+ change_focus_up:
+ - C
+ clear_filter:
+ - F
+ clear_selection:
+ - S
+ collapse:
+ -
+ - "`"
+ copy:
+ - p
+ copy_basename:
+ - Y
+ copy_name:
+ - y
+ copy_relname:
+ -
+ cut:
+ - x
+ delete:
+ - d
+ filter:
+ - f
+ h_split:
+ - W
+ jump_to_current:
+ - J
+ link:
+ - A
+ new:
+ - a
+ open_sys:
+ - o
+ primary:
+ -
+ quit:
+ - q
+ refocus:
+ - "~"
+ refresh:
+ -
+ rename:
+ - r
+ secondary:
+ -
+ - <2-leftmouse>
+ select:
+ - s
+ smaller:
+ - "-"
+ - _
+ stat:
+ - K
+ tertiary:
+ -
+ -
+ toggle_exec:
+ - X
+ toggle_follow:
+ - u
+ toggle_follow_links:
+ - U
+ toggle_follow_ignore:
+ - T
+ toggle_hidden:
+ - .
+ toggle_version_control:
+ - i
+ trash:
+ - t
+ v_split:
+ - w
+options:
+ close_on_open: false
+ follow: true
+ follow_links: true
+ follow_ignore: false
+ lang: null
+ mimetypes:
+ allow_exts:
+ - .svg
+ - .ts
+ warn:
+ - audio
+ - font
+ - image
+ - video
+ min_diagnostics_severity: 2
+ page_increment: 5
+ polling_rate: 2.0
+ session: true
+ show_hidden: false
+ version_control:
+ enable: true
+profiling: false
+theme:
+ discrete_colour_map:
+ black: "#202020"
+ blue: "#4eb5e0"
+ bright_black: "#000000"
+ bright_blue: "#58c7ff"
+ bright_cyan: "#5ac8a9"
+ bright_green: "#8dc437"
+ bright_magenta: "#ffa3cc"
+ bright_red: "#ff8883"
+ bright_white: "#feffff"
+ bright_yellow: "#ffa84f"
+ cyan: "#52bcaf"
+ green: "#96bc00"
+ magenta: "#f587c5"
+ red: "#ff4c41"
+ white: "#feffff"
+ yellow: "#f6a311"
+ highlights:
+ bookmarks: Title
+ ignored: Comment
+ marks: Keyword
+ quickfix: Label
+ version_control: Comment
+ diagnostics:
+ 1: DiagnosticError
+ 2: DiagnosticWarn
+ 3: DiagnosticInfo
+ 4: DiagnosticHint
+ 5: DiagnosticOk
+ diagnostic_unknown: DiagnosticOk
+ diagnostic_context: Menu
+
+ icon_colour_set: github
+ icon_glyph_set: devicons
+ text_colour_set: env
+
+view:
+ open_direction: left
+ sort_by:
+ - is_folder
+ - ext
+ - file_name_lower
+ - file_name
+ time_format: "%Y-%m-%d %H:%M"
+ width: 40
+ window_options:
+ cursorline: true
+ foldenable: false
+ number: false
+ relativenumber: false
+ signcolumn: "no"
+ winfixwidth: true
+ wrap: false
+xdg: false
diff --git a/config/neovim/store/lazy-plugins/chadtree/docker-compose.yml b/config/neovim/store/lazy-plugins/chadtree/docker-compose.yml
new file mode 100644
index 00000000..ae67fb03
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/docker-compose.yml
@@ -0,0 +1,9 @@
+version: "3.7"
+
+services:
+ chadtree:
+ restart: always
+ build: .
+ environment:
+ - TZ
+
diff --git a/config/neovim/store/lazy-plugins/chadtree/docker/root/.config/nvim/init.vim b/config/neovim/store/lazy-plugins/chadtree/docker/root/.config/nvim/init.vim
new file mode 100644
index 00000000..066355e7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/docker/root/.config/nvim/init.vim
@@ -0,0 +1,17 @@
+nnoremap Q
+nnoremap QQ quitall!
+vnoremap Q
+vnoremap QQ quitall!
+
+filetype on
+set nomodeline
+set secure
+set termguicolors
+set shortmess+=I
+
+let g:python3_host_prog = '/usr/bin/python3'
+let g:chadtree_settings = {'profiling': v:true, 'xdg': v:true}
+let mapleader=' '
+nnoremap v CHADopen
+
+packloadall
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/ARCHITECTURE.md b/config/neovim/store/lazy-plugins/chadtree/docs/ARCHITECTURE.md
new file mode 100644
index 00000000..39712218
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/docs/ARCHITECTURE.md
@@ -0,0 +1,41 @@
+# Architecture
+
+## Asynchronous Event Loop
+
+CHADTree uses it's own event loop aside from the `asyncio` one defined by the [`pynvim` client](https://github.com/neovim/pynvim).
+
+In fact, `pynvim` doesn't even run in the main thread.
+
+All RPC notifications from the `nvim` server are sent to a global message queue, which is then processed in order of arrival after initialization code.
+
+No further messages can be processed until the previous ones have.
+
+`nvim` never blocks on the notifications. The CHADTree client has no blocking API.
+
+## Parallelism
+
+CHADTree uses a traditional threadpool for parallelizable operations, this includes querying for `git` status and file system walking, as well as other minor ones such as `mv` or `cp`.
+
+The fs walk is done using a native parallel BFS strategy with a chunking step to avoid flooding the thread pool. This is not optimal since a [Fork Join](https://en.wikipedia.org/wiki/Fork%E2%80%93join_model) model should be more efficient.
+
+However, as benchmarked, the performance bottleneck is in fact not the filesystem, but text & decorations rendering.
+
+## Virtual Rendering
+
+It turns out, if you have thousands lines of text with decorations such as colour or virtual text, `nvim` struggles to update buffers, even if you batch the render in a single call.
+
+The answer is to have a virtual render target, and to compute the minimal necessary render instructions.
+
+Previously I had written [Noact](https://github.com/ms-jpq/noact), a 70 line React like virtual dom engine. CHADTree works similarly, except with a more sophisticated diff algorithm, since the native approach does not cope with flat lists. (A flat list is a degenerate tree)
+
+Instead of Virtual DOM nodes, a hash is used for each desired line of the render target.
+
+## Memorylessness
+
+CHADTree is designed with [Memorylessness](https://en.wikipedia.org/wiki/Memorylessness) in mind. For the most part the state transitions in CHADTree follow the Markov Property in that each successive state is independent from history.
+
+## Pipelining
+
+Broadly speaking, CHADTree has a two stage pipeline. The first stage processes messages, and generates render and cursor placement instructions for the second stage.
+
+Ideally the first stage should be referentially transparent, with zero side effects, while the second stage executes all of the side effects. However, this is too tedious, a memoryless approach is taken for the two stages instead.
\ No newline at end of file
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/CONFIGURATION.md b/config/neovim/store/lazy-plugins/chadtree/docs/CONFIGURATION.md
new file mode 100644
index 00000000..6c584998
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/docs/CONFIGURATION.md
@@ -0,0 +1,326 @@
+# Configurations
+
+All configurations are under the global variable **`chadtree_settings`**.
+
+VimL:
+
+```vim
+let g:chadtree_settings = { ... }
+```
+
+Lua:
+
+```lua
+local chadtree_settings = { ... }
+vim.api.nvim_set_var("chadtree_settings", chadtree_settings)
+```
+
+---
+
+## Shorthand
+
+Dictionary keys will be automatically expanded with the `.` notation. This works recursively.
+
+ie. The following are equivalent
+
+```json
+{ "dog.puppy": 2 }
+```
+
+```json
+{ "dog": { "puppy": 2 } }
+```
+
+Note in lua, you will need to quote your keys like so:
+
+```lua
+{ ["dog.puppy"] = 2 }
+```
+
+Note in VimL, to specify `True` and `False`, you need to use the following:
+
+```vim
+v:true
+v:false
+```
+
+---
+
+## Validation
+
+Variables will be validated against a schema.
+
+ie.
+
+```vim
+let g:chadtree_settings = { 'ignore.dog': 'scratch, stratch' }
+```
+
+Will give you the following error message:
+
+
+
+**Notice it says `Extra keys: {dog}`**
+
+---
+
+## Specifics
+
+The default configuration can be found under an [`yaml` file](https://github.com/ms-jpq/chadtree/tree/chad/config/defaults.yml)
+
+---
+
+### chadtree_settings.xdg
+
+Use `XDG` specifications for storing the CHADTree runtime and session files.
+
+If set to false, will store everything under repo location.
+
+**default:**
+
+```json
+false
+```
+
+---
+
+### chadtree_settings.keymap
+
+See help docs on [keybind](https://github.com/ms-jpq/chadtree/tree/chad/docs/KEYBIND.md)
+
+---
+
+### chadtree_settings.options
+
+#### `chadtree_settings.options.follow`
+
+CHADTree will highlight currently open file, and open all its parents.
+
+**default:**
+
+```json
+true
+```
+
+#### `chadtree_settings.options.follow_links`
+
+CHADTree will follow symlinks
+
+**default:**
+
+```json
+true
+```
+
+#### `chadtree_settings.options.lang`
+
+CHADTree will guess your locale from [unix environmental variables](https://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html).
+
+Set to `c` to disable emojis.
+
+**default:**
+
+```json
+null
+```
+
+**note:**
+
+I only wrote localization for `en`. `zh` will be coming, and maybe `fr` if I can get my girlfriend to help.
+
+#### `chadtree_settings.options.mimetypes`
+
+CHADTree will attempt to warn you when you try to open say an image. This is done via the [Internet Assigned Numbers Authority](https://www.iana.org/assignments/media-types/media-types.xhtml)'s mimetype database.
+
+##### `chadtree_settings.options.mimetypes.warn`
+
+Show a warning before opening these datatypes
+
+**default:**
+
+```json
+["audio", "font", "image", "video"]
+```
+
+##### `chadtree_settings.options.mimetypes.allow_exts`
+
+Skip warning for these extensions
+
+**default:**
+
+```json
+[".ts"]
+```
+
+#### `chadtree_settings.options.page_increment`
+
+Change how many lines `{` and `}` scroll
+
+**default:**
+
+```json
+5
+```
+
+#### `chadtree_settings.options.min_diagnostics_severity`
+
+Lower is more severe.
+
+**default:**
+
+```json
+2
+```
+
+#### `chadtree_settings.options.polling_rate`
+
+CHADTree's background refresh rate
+
+**default:**
+
+```json
+2.0
+```
+
+#### `chadtree_settings.options.session`
+
+Save & restore currently open folders
+
+**default:**
+
+```json
+true
+```
+
+#### `chadtree_settings.options.show_hidden`
+
+Hide some files and folders by default. By default this can be toggled using the `.` key.
+
+see `chadtree_settings.ignore` for more details
+
+**default:**
+
+```json
+false
+```
+
+#### `chadtree_settings.options.version_control`
+
+##### `chadtree_settings.options.version_control.enable`
+
+Enable version control. This can also be toggled. But unlike `show_hidden`, does not have a default keybind.
+
+**default:**
+
+```json
+true
+```
+
+---
+
+### chadtree_settings.ignore
+
+CHADTree can ignore showing some files. This is toggable by default using the `.` key.
+
+#### `chadtree_settings.ignore.name_exact`
+
+Files whose name match these exactly will be ignored.
+
+**default:**
+
+```json
+[".DS_Store", ".directory", "thumbs.db", ".git"]
+```
+
+#### `chadtree_settings.ignore.name_glob`
+
+Files whose name match these [glob patterns](https://en.wikipedia.org/wiki/Glob_%28programming%29) will be ignored.
+
+ie. `*.py` will match all python files
+
+**default:**
+
+```json
+[]
+```
+
+#### `chadtree_settings.ignore.path_glob`
+
+Files whose full path match these [glob patterns](https://en.wikipedia.org/wiki/Glob_%28programming%29) will be ignored.
+
+**default:**
+
+```json
+[]
+```
+
+---
+
+### chadtree_settings.view
+
+Some options to change CHADTree's appearance
+
+#### `chadtree_settings.view.open_direction`
+
+Which way does CHADTree open?
+
+**legal keys: one of**
+
+```json
+["left", "right"]
+```
+
+**default:**
+
+```json
+"left"
+```
+
+#### `chadtree_settings.view.sort_by`
+
+CHADTree can sort by the following criterion. Reorder them if you want a different sorting order.
+
+**legal keys: some of**
+
+```json
+["is_folder", "ext", "file_name_lower", "file_name"]
+```
+
+**default:**
+
+```json
+["is_folder", "ext", "file_name_lower", "file_name"]
+```
+
+#### `chadtree_settings.view.width`
+
+How big is CHADTree when initially opened?
+
+**default:**
+
+```json
+40
+```
+
+#### `chadtree_settings.view.window_options`
+
+Set of window local options to for CHADTree windows
+
+**default:**
+
+```json
+{
+ "cursorline": true,
+ "number": false,
+ "relativenumber": false,
+ "signcolumn": "no",
+ "winfixwidth": true,
+ "wrap": false
+}
+```
+
+---
+
+### chadtree_settings.theme
+
+See help docs on [themes](https://github.com/ms-jpq/chadtree/tree/chad/docs/THEME.md)
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/FEATURES.md b/config/neovim/store/lazy-plugins/chadtree/docs/FEATURES.md
new file mode 100644
index 00000000..da7a8cb9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/docs/FEATURES.md
@@ -0,0 +1,41 @@
+# Features
+
+## Filtering
+
+
+
+## Follow Mode
+
+
+
+## Git Integrations
+
+
+
+## Quickfix
+
+
+
+## Sessions
+
+
+
+## Visual Select
+
+
+
+## Github Colours
+
+
+
+## LS_COLORS
+
+
+
+## LS -l statistics
+
+
+
+## MimeType warning
+
+
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/KEYBIND.md b/config/neovim/store/lazy-plugins/chadtree/docs/KEYBIND.md
new file mode 100644
index 00000000..6633dd46
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/docs/KEYBIND.md
@@ -0,0 +1,433 @@
+# Keybinds
+
+Keybinds can be customized under `chadtree_settings.keymap.` with a set of keys.
+
+---
+
+## Window management
+
+##### `chadtree_settings.keymap.quit`
+
+Close CHADTree window, quit if it is the last window.
+
+**default:**
+
+```json
+["q"]
+```
+
+##### `chadtree_settings.keymap.bigger`
+
+Resize CHADTree window bigger.
+
+**default:**
+
+```json
+["+", "="]
+```
+
+##### `chadtree_settings.keymap.smaller`
+
+Resize CHADTree window smaller.
+
+**default:**
+
+```json
+["-", "_"]
+```
+
+##### `chadtree_settings.keymap.refresh`
+
+Refresh CHADTree.
+
+**default:**
+
+```json
+[""]
+```
+
+---
+
+## Rerooting CHADTree
+
+##### `chadtree_settings.keymap.change_dir`
+
+Change vim's working directory.
+
+**default:**
+
+```json
+["b"]
+```
+
+##### `chadtree_settings.keymap.change_focus`
+
+Set CHADTree's root to folder at cursor. Does not change working directory.
+
+**default:**
+
+```json
+["c"]
+```
+
+##### `chadtree_settings.keymap.change_focus_up`
+
+Set CHADTree's root one level up.
+
+**default:**
+
+```json
+["C"]
+```
+
+---
+
+## Open file / folder
+
+Any of the keys that open files will double as a open / close toggle on folders.
+
+##### `chadtree_settings.keymap.primary`
+
+Open file at cursor.
+
+**default:**
+
+```json
+[""]
+```
+
+##### `chadtree_settings.keymap.secondary`
+
+Open file at cursor, keep cursor in CHADTree's window.
+
+**default:**
+
+```json
+["", "<2-leftmouse>"]
+```
+
+##### `chadtree_settings.keymap.tertiary`
+
+Open file at cursor in a new tab.
+
+**default:**
+
+```json
+["", ""]
+```
+
+##### `chadtree_settings.keymap.v_split`
+
+Open file at cursor in vertical split.
+
+**default:**
+
+```json
+["w"]
+```
+
+##### `chadtree_settings.keymap.h_split`
+
+Open file at cursor in horizontal split.
+
+**default:**
+
+```json
+["W"]
+```
+
+##### `chadtree_settings.keymap.open_sys`
+
+Open file with GUI tools using `open` or `xdg open`. This will open third party tools such as `Finder` or `KDE Dolphin` or `GNOME nautilus`, etc. Depends on platform and user setup.
+
+**default:**
+
+```json
+["o"]
+```
+
+##### `chadtree_settings.keymap.collapse`
+
+Collapse all subdirectories for directory at cursor.
+
+**default:**
+
+```json
+["", "`"]
+```
+
+---
+
+## Doing things with cursor
+
+##### `chadtree_settings.keymap.refocus`
+
+Put cursor at the root of CHADTree
+
+**default:**
+
+```json
+["~"]
+```
+
+##### `chadtree_settings.keymap.jump_to_current`
+
+Position cursor in CHADTree at currently open buffer, if the buffer points to a location visible under CHADTree.
+
+**default:**
+
+```json
+["J"]
+```
+
+##### `chadtree_settings.keymap.stat`
+
+Print `ls --long` stat for file under cursor.
+
+**default:**
+
+```json
+["K"]
+```
+
+##### `chadtree_settings.keymap.copy_name`
+
+Copy paths of files under cursor or visual block.
+
+**default:**
+
+```json
+["Y"]
+```
+
+##### `chadtree_settings.keymap.copy_basename`
+
+Copy names of files under cursor or visual block.
+
+**default:**
+
+```json
+["y"]
+```
+
+##### `chadtree_settings.keymap.copy_relname`
+
+Copy relative paths of files under cursor or visual block.
+
+**default:**
+
+```json
+[""]
+```
+
+---
+
+## Filtering
+
+##### `chadtree_settings.keymap.filter`
+
+Set a glob pattern to narrow down visible files.
+
+**default:**
+
+```json
+["f"]
+```
+
+##### `chadtree_settings.keymap.clear_filter`
+
+Clear filter.
+
+**default:**
+
+```json
+["F"]
+```
+
+---
+
+## Bookmarks
+
+##### `chadtree_settings.keymap.bookmark_goto`
+
+Goto bookmark `A-Z`.
+
+**default:**
+
+```json
+["m"]
+```
+
+---
+
+## Selecting
+
+##### `chadtree_settings.keymap.select`
+
+Select files under cursor or visual block.
+
+**default:**
+
+```json
+["s"]
+```
+
+##### `chadtree_settings.keymap.clear_selection`
+
+Clear selection.
+
+**default:**
+
+```json
+["S"]
+```
+
+---
+
+## File operations
+
+##### `chadtree_settings.keymap.new`
+
+Create new file at location under cursor. Files ending with platform specific path separator will be folders.
+
+Intermediary folders are created automatically.
+
+ie. `uwu/owo/` under `unix` will create `uwu/` then `owo/` under it. Both are folders.
+
+**default:**
+
+```json
+["a"]
+```
+
+##### `chadtree_settings.keymap.link`
+
+Create links at location under cursor from selection.
+
+Links are always relative.
+
+Intermediary folders are created automatically.
+
+**default:**
+
+```json
+["A"]
+```
+
+##### `chadtree_settings.keymap.rename`
+
+Rename file under cursor.
+
+**default:**
+
+```json
+["r"]
+```
+
+##### `chadtree_settings.keymap.toggle_exec`
+
+Toggle all the `+x` bits of the selected / highlighted files.
+
+Except for directories, where `-x` will prevent reading.
+
+**default:**
+
+```json
+["X"]
+```
+
+##### `chadtree_settings.keymap.copy`
+
+Copy the selected files to location under cursor.
+
+**default:**
+
+```json
+["p"]
+```
+
+##### `chadtree_settings.keymap.cut`
+
+Move the selected files to location under cursor.
+
+**default:**
+
+```json
+["x"]
+```
+
+##### `chadtree_settings.keymap.delete`
+
+Delete the selected files. Items deleted cannot be recovered.
+
+**default:**
+
+```json
+["d"]
+```
+
+##### `chadtree_settings.keymap.trash`
+
+Trash the selected files using platform specific `trash` command, if they are available. Items trashed may be recovered.
+
+You need [`brew install trash`](https://formulae.brew.sh/formula/trash) for MacOS and [`pip3 install trash-cli`](https://github.com/andreafrancia/trash-cli) on Linux.
+
+**default:**
+
+```json
+["t"]
+```
+
+---
+
+## Toggle settings on / off
+
+##### `chadtree_settings.keymap.toggle_hidden`
+
+Toggle `show_hidden` on and off. See `chadtree_settings.options.show_hidden` for details.
+
+**default:**
+
+```json
+["."]
+```
+
+##### `chadtree_settings.keymap.toggle_follow`
+
+Toggle `follow` on and off. See `chadtree_settings.options.follow` for details.
+
+**default:**
+
+```json
+["u"]
+```
+
+##### `chadtree_settings.keymap.toggle_follow_links`
+
+Toggle `follow_links` on and off. See `chadtree_settings.options.follow_links` for details.
+
+**default:**
+
+```json
+["U"]
+```
+
+##### `chadtree_settings.keymap.toggle_follow_ignore`
+
+Toggle `follow_ignore` on and off. See `chadtree_settings.options.follow_ignore` for details.
+
+**default:**
+
+```json
+["T"]
+```
+
+##### `chadtree_settings.keymap.toggle_version_control`
+
+Toggle version control integration on and off
+
+**default:**
+
+```json
+["i"]
+```
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/MIGRATION.md b/config/neovim/store/lazy-plugins/chadtree/docs/MIGRATION.md
new file mode 100644
index 00000000..02d2dadf
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/docs/MIGRATION.md
@@ -0,0 +1,116 @@
+# Migration
+
+Hello everybody, I am dropping support for `python_version < 3.8.2` for the main branch.
+
+Please use the `legacy` branch if you cannot use newer versions of `python`.
+
+I am very sorry about this, but I am doing this in order to support more awesome features.
+
+## What you need to do:
+
+Run the following once after updating your git repo to latest
+
+```vim
+:UpdateRemotePlugins
+```
+
+Change your extension manager to use the following:
+
+```vim
+Plug 'ms-jpq/chadtree', {'branch': 'chad', 'do': 'python3 -m chadtree deps'}
+
+```
+
+Run `:CHADdeps` the first time before you use `:CHADopen`
+
+**Check out [`new configuration`](https://github.com/ms-jpq/chadtree/blob/chad/docs/CONFIGURATION.md)**. It is incompatible with the old one, BUT comes with a new parser and vaildator so the migration will be mostly just renaming one or two keys.
+
+If you make a typo, CHADTree will tell you so!
+
+## Why?
+
+Several reasons:
+
+Python `3.8.2` is the version of `python` on the latest Ubuntu LTS.
+
+There are some features I wanted to add that strictly cannot be supported below `python 3.8`. For example, I wanted to include a spec validator, but `python 3.7` lacks support for `Literal` in the `typing` module, and therefore could introduce ambiguities in the parser.
+
+The old CHADTree ran by `nvim`'s default extension implementation, which had major short comings:
+
+1. Everything ran in the same process.
+
+2. The user needs to call `:UpdateRemotePlugins` each time I add a new RPC end point, or else they will get a random confusing error.
+
+3. [`pynvim`](https://github.com/neovim/pynvim) needed to be installed, For most users who aren't familiar with how `pip` and python modules work. This will either mess up their usage of `virtualenv`, or require a global or user level `pip` package just to use CHADTree.
+
+In order to fix these issues, I will have to make breaking changes anyways, why not now?
+
+## Solutions
+
+At the cost of one time migration, which means users need to update their configs and perhaps python version. I will deilver enough features to warrant the upgrade.
+
+## New Features
+
+### Independent package management
+
+CHADTree now will use all local dependencies. Which means `pynvim` can be installed under a subdirectory to `chadtree`. Doing a `rm -rf` on CHADTree will cleanly remove everything it brings in.
+
+Nothing will pollute the global namespace for python.
+
+### Isolated Process
+
+CHADTree now runs inside an isolated process! Not only will it start faster, it will also be isolated from your other python plugins. In case of errors or crashes, they will not affect each other nearly as much!
+
+### New Vaildating Config Parser
+
+CHADTree will now validate your typos and misunderstandings on how to configure it! No more silent failures. If you make a typo in the config, it will tell you loud and clear!
+
+New `property.sub_property` syntax also supported on a recursive level.
+
+### Faster startup
+
+CHADTree started up kinda of slowly before. I have made it perceptibly faster through various marginal improvements.
+
+### Bigly Improved Documentation
+
+CHADTree now comes with it's own help command!
+
+Use `:CHADhelp {topic}` to open up built-in help docs in a floating window.
+
+Use `:CHADhelp {topic} --web` to open up the same help docs in a browser.
+
+### Parallel File System Operations
+
+Previously CHADTree was fast because it was async.
+
+Now CHADTree can be even faster because it does things in parallel.
+
+See [design document here](https://github.com/ms-jpq/chadtree/tree/chad/docs/ARCHITECTURE.md) for details.
+
+### Vastly Improved Rendering Speed
+
+You know how React is famous because it only renders what needs to be changed?
+
+CHADTree now uses a React-like virtual rendering target. It only re-renders the minimal amount of lines. CHADTree can now handle thousands of visible files and still be reasonably performant!
+
+_This is only visible when you have 1000+ files visible. The old ways was fast enough for most tasks._
+
+### Theming
+
+Yub, this is yuge. The #1 request was for more themes. They have came!
+
+Go see `:CHADhelp theme` for [details](https://github.com/ms-jpq/chadtree/tree/chad/docs/THEME.md).
+
+### Even more Polish
+
+- Maintain cursor position in many circumstances, ie. move root up / down, filtering for files, renaming, creating files, etc
+
+- Selection of hidden / invisible files no longer possible.
+
+- Retain selection when copying or moving files.
+
+- Now shows `git submodules`
+
+### Even Higher Quality Code
+
+Yes the quality of code is a feature. The better the code, the easier it is for me and other people to add in future improvements.
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/README.md b/config/neovim/store/lazy-plugins/chadtree/docs/README.md
new file mode 100644
index 00000000..96472235
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/docs/README.md
@@ -0,0 +1,43 @@
+# Docs
+
+Use `:CHADhelp` to open up a list of help pages!
+
+Help docs are written in `markdown` because a picture is worth a thousand words.
+
+Use `:CHADhelp -w` or `:CHADhelp --web` to open help pages in a browser window if possible.
+
+Use `:CHADhelp {topic}` or `:CHADhelp {topic} --web` to visit a particular topic for more information
+
+- [:CHADhelp features](https://github.com/ms-jpq/chadtree/tree/chad/docs/FEATURES.md)
+
+- [:CHADhelp keybind](https://github.com/ms-jpq/chadtree/tree/chad/docs/KEYBIND.md)
+
+- [:CHADhelp config](https://github.com/ms-jpq/chadtree/tree/chad/docs/CONFIGURATION.md)
+
+- [:CHADhelp theme](https://github.com/ms-jpq/chadtree/tree/chad/docs/THEME.md)
+
+- [:CHADhelp migration](https://github.com/ms-jpq/chadtree/tree/chad/docs/MIGRATION.md)
+
+---
+
+## Commands
+
+### `CHADopen`
+
+`:CHADopen` will toggle CHADTree open / close
+
+`:CHADopen ` will open at ``
+
+`:CHADopen --always-focus` will disable toggle if already opened
+
+`:CHADopen --nofocus` will open CHADTree without giving the sidebar focus
+
+`:CHADopen --version-ctl` will open CHADTree at version control top level.
+
+### `CHADdeps`
+
+`:CHADdeps` will install all of CHADTree's dependencies locally.
+
+Dependencies will be privately installed inside CHADTree's git root under `.vars/runtime`.
+
+Running `rm -rf` on `chadtree/` will cleanly remove everything CHADTree installs to your local system.
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/THEME.md b/config/neovim/store/lazy-plugins/chadtree/docs/THEME.md
new file mode 100644
index 00000000..e9f42b0c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/docs/THEME.md
@@ -0,0 +1,154 @@
+# Theme
+
+CHADTree does not define it's own theme, outside of some minimal defaults.
+
+All themes are imported from other open source projects.
+
+You can customize themes using the `chadtree_settings.theme` settings.
+
+---
+
+### `chadtree_settings.theme.highlights`
+
+Vim comes with some built-in highlight groups, these are used to colour things which I cannot find good imports for.
+
+see `:help highlight-groups`
+
+#### `chadtree_settings.theme.highlights.ignored`
+
+These are used for files that are ignored by user supplied pattern in `chadtree_settings.ignore` and by version control.
+
+**default:**
+
+```json
+"Comment"
+```
+
+#### `chadtree_settings.theme.highlights.bookmarks`
+
+These are used to show bookmarks.
+
+**default:**
+
+```json
+"Title"
+```
+
+#### `chadtree_settings.theme.highlights.quickfix`
+
+These are used to notify the number of times a file / folder appears in the `quickfix` list.
+
+**default:**
+
+```json
+"Label"
+```
+
+#### `chadtree_settings.theme.highlights.version_control`
+
+These are used to put a version control status beside each file.
+
+**default:**
+
+```json
+"Comment"
+```
+
+---
+
+### `chadtree_settings.theme.icon_glyph_set`
+
+To use **devicons**, you will need [supported fonts](https://github.com/ryanoasis/nerd-fonts#font-installation)
+
+**devicons:**
+
+Imported from [vim-devicons](https://github.com/ryanoasis/vim-devicons)
+
+
+
+**emoji:**
+
+Imported from [vim-emoji-icon-theme](https://github.com/adelarsq/vim-emoji-icon-theme)
+
+
+
+**ascii:**
+
+
+
+**ascii_hollow:**
+
+
+
+
+**default:**
+
+```json
+"devicons"
+```
+
+---
+
+### `chadtree_settings.theme.text_colour_set`
+
+On `unix`, the command `ls` can produce coloured results based on the `LS_COLORS` environmental variable.
+
+CHADTree can pretend it's `ls` by setting `chadtree_settings.theme.text_colour_set` to `env`.
+
+If you are not happy with that, you can choose one of the many others:
+
+- [dircolors-solarized](https://github.com/seebi/dircolors-solarized)
+
+- [nord-dircolors](https://github.com/arcticicestudio/nord-dircolors)
+
+- [trapd00r](https://github.com/trapd00r/LS_COLORS)
+
+- [vim-nerdtree-syntax-highlight](https://github.com/tiagofumo/vim-nerdtree-syntax-highlight)
+
+**legal keys: one of**
+
+```json
+[
+ "env",
+ "solarized_dark_256",
+ "solarized_dark",
+ "solarized_light",
+ "solarized_universal",
+ "nord",
+ "trapdoor",
+ "nerdtree_syntax_light",
+ "nerdtree_syntax_dark"
+]
+```
+
+**default:**
+
+```json
+"env"
+```
+
+---
+
+### `chadtree_settings.theme.icon_colour_set`
+
+Right now you all the file icons are coloured according to [Github colours](https://github.com/github/linguist).
+
+You may also disable colouring if you wish.
+
+**github:**
+
+
+
+**legal keys: one of**
+
+```json
+["github", "none"]
+```
+
+**default:**
+
+```json
+"github"
+```
+
+---
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/bookmarks.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/bookmarks.png
new file mode 100644
index 00000000..8c126f0d
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/bookmarks.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/filtering.gif b/config/neovim/store/lazy-plugins/chadtree/docs/img/filtering.gif
new file mode 100644
index 00000000..c6dbf0af
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/filtering.gif differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/follow.gif b/config/neovim/store/lazy-plugins/chadtree/docs/img/follow.gif
new file mode 100644
index 00000000..b7c46fd7
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/follow.gif differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/git_showcase.gif b/config/neovim/store/lazy-plugins/chadtree/docs/img/git_showcase.gif
new file mode 100644
index 00000000..dd88c987
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/git_showcase.gif differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/github_colours.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/github_colours.png
new file mode 100644
index 00000000..6cb955c0
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/github_colours.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_ascii.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_ascii.png
new file mode 100644
index 00000000..3d4ecc91
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_ascii.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_ascii_hollow.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_ascii_hollow.png
new file mode 100644
index 00000000..434768f7
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_ascii_hollow.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_devicons.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_devicons.png
new file mode 100644
index 00000000..67a20905
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_devicons.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_emoji.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_emoji.png
new file mode 100644
index 00000000..bb18846d
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/icons_emoji.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/ls_colours.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/ls_colours.png
new file mode 100644
index 00000000..c363118f
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/ls_colours.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/ls_l.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/ls_l.png
new file mode 100644
index 00000000..4ca323b3
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/ls_l.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/mimetype.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/mimetype.png
new file mode 100644
index 00000000..14d1b7a0
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/mimetype.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/quickfix.gif b/config/neovim/store/lazy-plugins/chadtree/docs/img/quickfix.gif
new file mode 100644
index 00000000..f13b9df8
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/quickfix.gif differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/schema_error.png b/config/neovim/store/lazy-plugins/chadtree/docs/img/schema_error.png
new file mode 100644
index 00000000..eb424039
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/schema_error.png differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/session.gif b/config/neovim/store/lazy-plugins/chadtree/docs/img/session.gif
new file mode 100644
index 00000000..25e46daa
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/session.gif differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/docs/img/visual_select.gif b/config/neovim/store/lazy-plugins/chadtree/docs/img/visual_select.gif
new file mode 100644
index 00000000..62684e2d
Binary files /dev/null and b/config/neovim/store/lazy-plugins/chadtree/docs/img/visual_select.gif differ
diff --git a/config/neovim/store/lazy-plugins/chadtree/locale/c.yml b/config/neovim/store/lazy-plugins/chadtree/locale/c.yml
new file mode 100644
index 00000000..20713ce3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/locale/c.yml
@@ -0,0 +1,97 @@
+---
+"already_exists": |-
+ !! Exists: ${name}
+
+"paths already exist": |-
+ !! -- ${operation}: path(s) already exist! ::
+ ${paths}
+
+"new cwd": |-
+ $$PWD=${cwd}
+
+"ask_trash": |-
+ Trash?
+ ${display_paths}
+
+"ask_yesno": |-
+ &Yes
+ &No
+
+"cannot find version ctl root": |-
+ !! Cannot find version control top level
+
+"operation not permitted on root": |-
+ Operation not permitted on root or parent(s) of root
+
+"render time warning": |-
+ !! Warning: Render time is slow @${duration}s, consider closing some folders
+
+"copy": |-
+ Copy
+
+"copy_paths": |-
+ Copied ${copied_paths}
+
+"cut": |-
+ Cut
+
+"confirm op": |-
+ ${operation} ?
+ ${paths}
+
+"dead_link": |-
+ !! cannot open dead link: ${name}
+
+"filter_click": |-
+ !! cannot click on folders while filtering
+
+"follow_mode_indi": |-
+ !! follow mode: ${follow}
+
+"follow_links_indi": |-
+ !! follow links: ${follow}
+
+"follow_ignore_indi": |-
+ !! follow ignore: ${follow}
+
+"hourglass": |-
+ Wait...
+
+"link": |-
+ Link ${src} ->:
+
+"mime_warn": |-
+ ${name} have possible mimetype ${mime}, continue?
+
+"new_filter": |-
+ New Filter:
+
+"new_search": |-
+ New Search:
+
+"nothing_select": |-
+ !! -- nothing selected!
+
+"ok_sym": |-
+ Ok
+
+"path_exists_err": |-
+ !! Path exist - Rename:
+
+"pencil": |-
+ Input:
+
+"clear_bookmarks": |-
+ ${idx}. Clear!
+
+"no_bookmarks": |-
+ !! Error - no bookmarks found
+
+"sys_open_err": |-
+ !! Error -- cannot find system opener
+
+"sys_trash_err": |-
+ !! Error -- cannot find trash program
+
+"version_control_indi": |-
+ 🐶 enable version control: ${enable_vc}
diff --git a/config/neovim/store/lazy-plugins/chadtree/locale/en.yml b/config/neovim/store/lazy-plugins/chadtree/locale/en.yml
new file mode 100644
index 00000000..e45eb637
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/locale/en.yml
@@ -0,0 +1,97 @@
+---
+"already_exists": |-
+ ⚠️ Exists: ${name}
+
+"paths already exist": |-
+ ⚠️ -- ${operation} : path(s) already exist! ::
+ ${paths}
+
+"new cwd": |-
+ 🏠 =${cwd}
+
+"ask_trash": |-
+ 🗑 ?
+ ${display_paths}
+
+"ask_yesno": |-
+ &Yes
+ &No
+
+"cannot find version ctl root": |-
+ ⚠️ Cannot find version control top level
+
+"operation not permitted on root": |-
+ ⚠️ Operation not permitted on root or parent(s) of root
+
+"render time warning": |-
+ ⚠️ Warning: Render time is slow @${duration}s, consider closing some folders
+
+"copy": |-
+ 🖇
+
+"copy_paths": |-
+ 📎 ${copied_paths}
+
+"cut": |-
+ ✂️
+
+"confirm op": |-
+ ${operation} ?
+ ${paths}
+
+"dead_link": |-
+ ⚠️ cannot open dead link: ${name}
+
+"filter_click": |-
+ ⚠️ cannot click on folders while filtering
+
+"follow_mode_indi": |-
+ 🐶 follow mode: ${follow}
+
+"follow_links_indi": |-
+ 🔗 follow mode: ${follow}
+
+"follow_ignore_indi": |-
+ 🌫️ follow mode: ${follow}
+
+"hourglass": |-
+ ⏳...⌛️
+
+"link": |-
+ 🔗 ${src} 👉 :
+
+"mime_warn": |-
+ ${name} have possible mimetype ${mime}, continue?
+
+"new_filter": |-
+ New Filter:
+
+"new_search": |-
+ 🔍:
+
+"nothing_select": |-
+ ⚠️ -- nothing selected!
+
+"ok_sym": |-
+ ✅
+
+"path_exists_err": |-
+ ⚠️ Path exist!!! Rename:
+
+"pencil": |-
+ ✏️ :
+
+"clear_bookmarks": |-
+ ${idx}. 🔖 Clear!
+
+"no_bookmarks": |-
+ ⚠️ Error - no bookmarks found
+
+"sys_open_err": |-
+ ⚠️ Error -- cannot find system opener
+
+"sys_trash_err": |-
+ ⚠️ Error -- cannot find trash program
+
+"version_control_indi": |-
+ 🐶 enable version control: ${enable_vc}
diff --git a/config/neovim/store/lazy-plugins/chadtree/locale/zh.yml b/config/neovim/store/lazy-plugins/chadtree/locale/zh.yml
new file mode 100644
index 00000000..6c5bc50b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/locale/zh.yml
@@ -0,0 +1,97 @@
+---
+"already_exists": |-
+ ⚠️ 已存在: ${name}
+
+"paths already exist": |-
+ ⚠️ -- ${operation} : 路径已存在! ::
+ ${paths}
+
+"new cwd": |-
+ 🏠 =${cwd}
+
+"ask_trash": |-
+ 🗑 ?
+ ${display_paths}
+
+"ask_yesno": |-
+ &Y (确定)
+ &N (取消)
+
+"cannot find version ctl root": |-
+ ⚠️ 文件系统顶层找不到版本控制
+
+"operation not permitted on root": |-
+ ⚠️ 此操作不可文件系统顶层(以上)
+
+"render time warning": |-
+ ⚠️ 警告: 渲染时间有点慢 @${duration}s, 考虑关闭一些文件夹
+
+"copy": |-
+ 🖇
+
+"copy_paths": |-
+ 📎 ${copied_paths}
+
+"cut": |-
+ ✂️
+
+"confirm op": |-
+ ${operation} ?
+ ${paths}
+
+"dead_link": |-
+ ⚠️ 打不开死链接: ${name}
+
+"filter_click": |-
+ ⚠️ 不可在过滤时点击文件夹
+
+"follow_mode_indi": |-
+ 🐶 跟随模式: ${follow}
+
+"follow_links_indi": |-
+ 🔗 跟随模式: ${follow}
+
+"follow_ignore_indi": |-
+ 🌫️ 跟随模式: ${follow}
+
+"hourglass": |-
+ ⏳...⌛️
+
+"link": |-
+ 🔗 ${src} 👉 :
+
+"mime_warn": |-
+ ${name} 文件猜到 mimetype ${mime}, 继续?
+
+"new_filter": |-
+ 新过滤:
+
+"new_search": |-
+ 🔍:
+
+"nothing_select": |-
+ ⚠️ -- 选择是空的!
+
+"ok_sym": |-
+ ✅
+
+"path_exists_err": |-
+ ⚠️ 路径已存在!!! 重新命名:
+
+"pencil": |-
+ ✏️ :
+
+"clear_bookmarks": |-
+ ${idx}. 🔖 清除
+
+"no_bookmarks": |-
+ ⚠️ 错误 -- 找不到书签
+
+"sys_open_err": |-
+ ⚠️ 错误 -- 找不到系统开启程序
+
+"sys_trash_err": |-
+ ⚠️ 错误 -- 找不到垃圾(trash)程序
+
+"version_control_indi": |-
+ 🐶 版本控制: ${enable_vc}
diff --git a/config/neovim/store/lazy-plugins/chadtree/lua/chadtree.lua b/config/neovim/store/lazy-plugins/chadtree/lua/chadtree.lua
new file mode 100644
index 00000000..82562bc4
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/lua/chadtree.lua
@@ -0,0 +1,212 @@
+CHAD = CHAD or {}
+chad = chad or {}
+
+local linesep = "\n"
+local POLLING_RATE = 10
+local is_win = vim.api.nvim_call_function("has", {"win32"}) == 1
+
+local cwd = (function()
+ local source = debug.getinfo(2, "S").source
+ local file = string.match(source, "^@(.*)")
+ return vim.api.nvim_call_function("fnamemodify", {file, ":p:h:h"})
+end)()
+
+local function defer(timeout, callback)
+ local timer = vim.loop.new_timer()
+ timer:start(
+ timeout,
+ 0,
+ function()
+ timer:stop()
+ timer:close()
+ vim.schedule(callback)
+ end
+ )
+ return timer
+end
+
+local settings = function()
+ local go, _settings = pcall(vim.api.nvim_get_var, "chadtree_settings")
+ local settings = go and _settings or {}
+ return settings
+end
+
+local job_id = nil
+local err_exit = false
+
+chad.on_exit = function(args)
+ local code = unpack(args)
+ if not (code == 0 or code == 143) then
+ err_exit = true
+ vim.api.nvim_err_writeln("CHADTree EXITED - " .. code)
+ else
+ err_exit = false
+ end
+ job_id = nil
+end
+
+chad.on_stdout = function(args)
+ local msg = unpack(args)
+ vim.api.nvim_out_write(table.concat(msg, linesep))
+end
+
+chad.on_stderr = function(args)
+ local msg = unpack(args)
+ if vim.api.nvim_call_function("has", {"nvim-0.5"}) == 1 then
+ vim.api.nvim_echo({{table.concat(msg, linesep), "ErrorMsg"}}, true, {})
+ else
+ vim.api.nvim_err_write(table.concat(msg, linesep))
+ end
+end
+
+local go, _py3 = pcall(vim.api.nvim_get_var, "python3_host_prog")
+local py3 = go and _py3 or (is_win and "python.exe" or "python3")
+local xdg_dir = vim.api.nvim_call_function("stdpath", {"data"})
+
+local main = function(is_xdg)
+ local v_py =
+ cwd ..
+ (is_win and [[/.vars/runtime/Scripts/python.exe]] or
+ "/.vars/runtime/bin/python3")
+
+ if is_win then
+ local v_py_xdg = xdg_dir .. "/chadrt/Scripts/python"
+ local v_py = is_xdg and v_py_xdg or v_py
+ if vim.api.nvim_call_function("filereadable", {v_py}) == 1 then
+ return {v_py}
+ else
+ -- local win_proxy = cwd .. [[/win.cmd]]
+ return {py3}
+ end
+ else
+ local v_py_xdg = xdg_dir .. "/chadrt/bin/python3"
+ local v_py = is_xdg and v_py_xdg or v_py
+ if vim.api.nvim_call_function("filereadable", {v_py}) == 1 then
+ return {v_py}
+ else
+ return {py3}
+ end
+ end
+end
+
+local start = function(deps, ...)
+ local is_xdg = settings().xdg
+ local args =
+ vim.tbl_flatten {
+ deps and py3 or main(is_xdg),
+ {"-s", "-u", "-m", "chadtree"},
+ {...},
+ (is_xdg and {"--xdg", xdg_dir} or {})
+ }
+ local params = {
+ cwd = cwd,
+ env = {PYTHONSAFEPATH = "1", PYTHONPATH = cwd},
+ on_exit = "CHADon_exit",
+ on_stdout = (function()
+ if deps then
+ return nil
+ else
+ return "CHADon_stdout"
+ end
+ end)(),
+ on_stderr = (function()
+ if deps then
+ return nil
+ else
+ return "CHADon_stderr"
+ end
+ end)()
+ }
+ if deps then
+ vim.api.nvim_command [[new]]
+ vim.api.nvim_call_function("termopen", {args, params})
+ else
+ job_id = vim.api.nvim_call_function("jobstart", {args, params})
+ return job_id
+ end
+end
+
+chad.Deps = function()
+ start(true, "deps")
+end
+
+vim.api.nvim_command [[command! -nargs=0 CHADdeps lua chad.Deps()]]
+
+local set_chad_call = function(cmd)
+ local t1 = 0
+ chad[cmd] = function(...)
+ local args = {...}
+ if t1 == 0 then
+ t1 = vim.loop.now()
+ end
+
+ if not job_id then
+ local srv = is_win and {"localhost:0"} or {}
+ local server = vim.api.nvim_call_function("serverstart", srv)
+ job_id =
+ start(
+ false,
+ "run",
+ "--ppid",
+ vim.api.nvim_call_function("getpid", {}),
+ "--socket",
+ server
+ )
+ end
+
+ if not err_exit and CHAD[cmd] then
+ CHAD[cmd](args)
+ local t2 = vim.loop.now()
+ if settings().profiling and t1 >= 0 then
+ print("Init " .. (t2 - t1) .. "ms")
+ end
+ t1 = -1
+ else
+ defer(
+ POLLING_RATE,
+ function()
+ if err_exit then
+ return
+ else
+ chad[cmd](unpack(args))
+ end
+ end
+ )
+ end
+ end
+end
+
+set_chad_call("Noop")
+
+set_chad_call("Open")
+vim.api.nvim_command [[command! -nargs=* CHADopen lua chad.Open()]]
+
+set_chad_call("Help")
+vim.api.nvim_command [[command! -nargs=* CHADhelp lua chad.Help()]]
+
+set_chad_call("Restore")
+vim.api.nvim_command [[command! -nargs=0 CHADrestore lua chad.Restore()]]
+
+chad.lsp_ensure_capabilities = function(cfg)
+ local spec1 = {
+ capabilities = vim.lsp.protocol.make_client_capabilities()
+ }
+ local spec2 = {
+ capabilities = {
+ workspace = {
+ fileOperations = {
+ didCreate = true,
+ didRename = true,
+ didDelete = true
+ }
+ }
+ }
+ }
+ local maps = cfg.capabilities and {spec2} or {spec1, spec2}
+ local new =
+ vim.tbl_deep_extend("force", cfg or vim.empty_dict(), unpack(maps))
+ return new
+end
+
+chad.Noop()
+return chad
diff --git a/config/neovim/store/lazy-plugins/chadtree/mypy.ini b/config/neovim/store/lazy-plugins/chadtree/mypy.ini
new file mode 100644
index 00000000..db81273c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/mypy.ini
@@ -0,0 +1,26 @@
+[mypy]
+cache_dir = .vars/mypy
+check_untyped_defs = true
+disallow_any_generics = false
+disallow_any_unimported = true
+disallow_incomplete_defs = true
+disallow_subclassing_any = true
+disallow_untyped_calls = true
+disallow_untyped_decorators = true
+disallow_untyped_defs = true
+error_summary = true
+extra_checks = true
+implicit_reexport = false
+no_implicit_optional = true
+pretty = true
+show_column_numbers = true
+show_error_codes = true
+show_error_context = true
+strict = true
+strict_equality = true
+warn_incomplete_stub = true
+warn_redundant_casts = true
+warn_return_any = true
+warn_unreachable = true
+warn_unused_configs = true
+warn_unused_ignores = true
diff --git a/config/neovim/store/lazy-plugins/chadtree/plugin/chadtree.vim b/config/neovim/store/lazy-plugins/chadtree/plugin/chadtree.vim
new file mode 100644
index 00000000..3cd3300b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/plugin/chadtree.vim
@@ -0,0 +1,20 @@
+autocmd VimEnter * silent! autocmd! FileExplorer
+silent! autocmd! FileExplorer
+
+augroup CHADTree
+ autocmd!
+ autocmd FileType CHADTree autocmd BufEnter,WinEnter stopinsert
+augroup end
+
+function CHADon_exit(_, code, __)
+ call luaeval('chad.on_exit(...)', [a:code])
+endfunction
+function CHADon_stdout(_, msg, __)
+ call luaeval('chad.on_stdout(...)', [a:msg])
+endfunction
+function CHADon_stderr(_, msg, __)
+ call luaeval('chad.on_stderr(...)', [a:msg])
+endfunction
+
+
+call luaeval('require("chadtree") and 0')
diff --git a/config/neovim/store/lazy-plugins/chadtree/pyproject.toml b/config/neovim/store/lazy-plugins/chadtree/pyproject.toml
new file mode 100644
index 00000000..57bd13e1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/pyproject.toml
@@ -0,0 +1,7 @@
+[project]
+name = "chadtree"
+requires-python = ">=3.8.0"
+version = "0"
+
+[project.optional-dependencies]
+dev = ["mypy", "types-PyYAML", "black", "isort"]
diff --git a/config/neovim/store/lazy-plugins/chadtree/requirements.txt b/config/neovim/store/lazy-plugins/chadtree/requirements.txt
new file mode 100644
index 00000000..9537cd0e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/chadtree/requirements.txt
@@ -0,0 +1,3 @@
+std2@https://github.com/ms-jpq/std2/archive/d8ac12686cdf0d640aed7cee6a981b1835d1724e.tar.gz
+pynvim_pp@https://github.com/ms-jpq/pynvim_pp/archive/34e3a027c595981886d7efd1c91071f3eaa4715d.tar.gz
+PyYAML
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/LICENSE b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/LICENSE
new file mode 100644
index 00000000..14c4587e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022-2023 Chinmay Dalal
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/README.md b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/README.md
new file mode 100644
index 00000000..dd0cee97
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/README.md
@@ -0,0 +1,202 @@
+
+
+Requires Neovim 0.7+
+
+## Installation
+Install this plugin using any plugin/package manager or see [`:h packages`](https://neovim.io/doc/user/repeat.html#packages)
+
+## Configuration:
+Set up clangd via lspconfig/vim.lsp.start, as usual.
+You don't need to call `require("clangd_extensions").setup` if you like the defaults:
+```lua
+require("clangd_extensions").setup({
+ inlay_hints = {
+ inline = vim.fn.has("nvim-0.10") == 1,
+ -- Options other than `highlight' and `priority' only work
+ -- if `inline' is disabled
+ -- Only show inlay hints for the current line
+ only_current_line = false,
+ -- Event which triggers a refresh of the inlay hints.
+ -- You can make this { "CursorMoved" } or { "CursorMoved,CursorMovedI" } but
+ -- note that this may cause higher CPU usage.
+ -- This option is only respected when only_current_line is true.
+ only_current_line_autocmd = { "CursorHold" },
+ -- whether to show parameter hints with the inlay hints or not
+ show_parameter_hints = true,
+ -- prefix for parameter hints
+ parameter_hints_prefix = "<- ",
+ -- prefix for all the other hints (type, chaining)
+ other_hints_prefix = "=> ",
+ -- whether to align to the length of the longest line in the file
+ max_len_align = false,
+ -- padding from the left if max_len_align is true
+ max_len_align_padding = 1,
+ -- whether to align to the extreme right or not
+ right_align = false,
+ -- padding from the right if right_align is true
+ right_align_padding = 7,
+ -- The color of the hints
+ highlight = "Comment",
+ -- The highlight group priority for extmark
+ priority = 100,
+ },
+ ast = {
+ -- These are unicode, should be available in any font
+ role_icons = {
+ type = "🄣",
+ declaration = "🄓",
+ expression = "🄔",
+ statement = ";",
+ specifier = "🄢",
+ ["template argument"] = "🆃",
+ },
+ kind_icons = {
+ Compound = "🄲",
+ Recovery = "🅁",
+ TranslationUnit = "🅄",
+ PackExpansion = "🄿",
+ TemplateTypeParm = "🅃",
+ TemplateTemplateParm = "🅃",
+ TemplateParamObject = "🅃",
+ },
+ --[[ These require codicons (https://github.com/microsoft/vscode-codicons)
+ role_icons = {
+ type = "",
+ declaration = "",
+ expression = "",
+ specifier = "",
+ statement = "",
+ ["template argument"] = "",
+ },
+
+ kind_icons = {
+ Compound = "",
+ Recovery = "",
+ TranslationUnit = "",
+ PackExpansion = "",
+ TemplateTypeParm = "",
+ TemplateTemplateParm = "",
+ TemplateParamObject = "",
+ }, ]]
+
+ highlights = {
+ detail = "Comment",
+ },
+ },
+ memory_usage = {
+ border = "none",
+ },
+ symbol_info = {
+ border = "none",
+ },
+})
+```
+## Features:
+### [Switch between source/header](https://clangd.llvm.org/extensions#switch-between-sourceheader)
+### Usage
+`:ClangdSwitchSourceHeader`
+### [Inlay hints](https://clangd.llvm.org/extensions#inlay-hints)
+
+#### Usage
+Add this to your nvim-lspconfig / `vim.lsp.start()`'s `on_attach`:
+```lua
+require("clangd_extensions.inlay_hints").setup_autocmd()
+require("clangd_extensions.inlay_hints").set_inlay_hints()
+```
+
+You can also enable, disable or toggle the hints with `ClangdSetInlayHints`, `ClangdDisableInlayHints` and `ClangdToggleInlayHints`.
+Toggling returns the current state of the hints, this is useful if you want to hook a callback when toggling inlay hints:
+```lua
+if require("clangd_extensions.inlay_hints").toggle_inlay_hints() then
+ -- Inlay hints are enabled
+else
+ -- Inlay hints are disabled
+end
+```
+For example if you have autocommands related to Clangd inlay hints you might want to disable/enable them when toggling inlay hints:
+```lua
+on_attach = function(_, buf)
+ local group = vim.api.nvim_create_augroup("clangd_no_inlay_hints_in_insert", { clear = true })
+
+ vim.keymap.set("n", "lh", function()
+ if require("clangd_extensions.inlay_hints").toggle_inlay_hints() then
+ vim.api.nvim_create_autocmd("InsertEnter", { group = group, buffer = buf,
+ callback = require("clangd_extensions.inlay_hints").disable_inlay_hints
+ })
+ vim.api.nvim_create_autocmd({ "TextChanged", "InsertLeave" }, { group = group, buffer = buf,
+ callback = require("clangd_extensions.inlay_hints").set_inlay_hints
+ })
+ else
+ vim.api.nvim_clear_autocmds({ group = group, buffer = buf })
+ end
+ end, { buffer = buf, desc = "[l]sp [h]ints toggle" })
+end,
+}
+```
+
+### [View AST](https://clangd.llvm.org/extensions#ast)
+
+You can fold nodes using `zc` and friends - the AST window has `shiftwidth=2` and `foldmethod=indent`.
+
+#### Usage
+`:ClangdAST` to view the ast with the current line as the range, `:'<,'>ClangdAST` with a visual selection to view the ast with the selected lines as range.
+See how ranges are handled at https://clangd.llvm.org/extensions#ast
+### [Completion scores](https://clangd.llvm.org/extensions#code-completion-scores)
+Usage: For nvim-cmp
+```lua
+local cmp = require "cmp"
+cmp.setup {
+ -- ... rest of your cmp setup ...
+
+ sorting = {
+ comparators = {
+ cmp.config.compare.offset,
+ cmp.config.compare.exact,
+ cmp.config.compare.recently_used,
+ require("clangd_extensions.cmp_scores"),
+ cmp.config.compare.kind,
+ cmp.config.compare.sort_text,
+ cmp.config.compare.length,
+ cmp.config.compare.order,
+ },
+ },
+}
+```
+### [Symbol info](https://clangd.llvm.org/extensions#symbol-info-request)
+
+#### Usage
+`:ClangdSymbolInfo` with the cursor at the desired symbol.
+### [Type hierarchy](https://clangd.llvm.org/extensions#type-hierarchy)
+
+
+#### Usage
+`:ClangdTypeHierarchy` with the cursor over the desired type or a symbol of that type.
+`gd` with the cursor over a type in a window to go to its definition.
+### [Memory usage](https://clangd.llvm.org/extensions#memory-usage)
+You can fold items using `zc` and friends - the memory usage window has `shiftwidth=2` and `foldmethod=indent`.
+
+#### Usage
+`:ClangdMemoryUsage`. Preamble can be large so it is collapsed by default, to expand it use `:ClangdMemoryUsage expand_preamble`
+
+## Implementation status of [extensions](https://clangd.llvm.org/extensions)
+ ☑️ Memory usage
+
+ ☑️ AST
+
+ ☑️ Symbol info request
+
+ ☑️ Type hierarchy
+
+ ☑️ Inlay hints
+
+ ☑️ Switch between source/header
+
+ ☑️ File status (see lsp-status.nvim)
+
+ ☑️ Compilation commands (can be specified in `vim.lsp.start()`/lspconfig `init_options` and `settings`)
+
+ ☑️ Code completion scores
+
+ ⬜ Force diagnostics generation (not sure)
+## Credits
+[simrat39](https://github.com/simrat39) - the code for inlay hints was taken from [rust-tools.nvim](https://github.com/simrat39/rust-tools.nvim) with very minor changes.
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/ast.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/ast.lua
new file mode 100644
index 00000000..3083ec20
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/ast.lua
@@ -0,0 +1,183 @@
+local fmt = string.format
+local api = vim.api
+local conf = require("clangd_extensions.config").options.ast
+
+local M = {}
+--- node_pos[source_buf][ast_buf][linenum] = { start = start, end = end }
+--- position of node in `source_buf` corresponding to line no. `linenum` in `ast_buf`
+M.node_pos = {}
+--- detail_pos[ast_buf][linenum] = { start = start, end = end }
+--- position of `detail` in line no. `linenum` of `ast_buf`
+M.detail_pos = {}
+M.nsid = vim.api.nvim_create_namespace("clangd_extensions")
+
+local function setup_hl_autocmd(source_buf, ast_buf)
+ local group = api.nvim_create_augroup("ClangdExtensions", {})
+ api.nvim_create_autocmd("CursorMoved", {
+ group = group,
+ buffer = ast_buf,
+ callback = function() M.update_highlight(source_buf, ast_buf) end,
+ })
+ api.nvim_create_autocmd("BufLeave", {
+ group = group,
+ buffer = ast_buf,
+ callback = function() M.clear_highlight(source_buf) end,
+ })
+end
+
+local function icon_prefix(role, kind)
+ if conf.kind_icons[kind] then
+ return conf.kind_icons[kind] .. " "
+ elseif conf.role_icons[role] then
+ return conf.role_icons[role] .. " "
+ else
+ return " "
+ end
+end
+
+local function describe(role, kind, detail)
+ local str = ""
+ local icon = icon_prefix(role, kind)
+ local detailpos = nil
+ str = str .. kind
+ if
+ not (
+ role == "expression"
+ or role == "statement"
+ or role == "declaration"
+ or role == "template name"
+ )
+ then
+ str = str .. " " .. role
+ end
+ if detail then
+ detailpos = {
+ start = string.len(str) + vim.fn.strlen(icon) + 1,
+ ["end"] = string.len(str) + vim.fn.strlen(icon) + string.len(
+ detail
+ ) + 1,
+ }
+ str = str .. " " .. detail
+ end
+ return (icon .. str), detailpos
+end
+
+local function walk_tree(node, visited, result, padding, hl_bufs)
+ visited[node] = true
+ local str, detpos = describe(node.role, node.kind, node.detail)
+ table.insert(result, padding .. str)
+
+ if node.detail and detpos then
+ M.detail_pos[hl_bufs.ast_buf][#result] = {
+ start = string.len(padding) + detpos.start,
+ ["end"] = string.len(padding) + detpos["end"],
+ }
+ end
+
+ if node.range then
+ M.node_pos[hl_bufs.source_buf][hl_bufs.ast_buf][#result] = {
+ start = { node.range.start.line, node.range.start.character },
+ ["end"] = { node.range["end"].line, node.range["end"].character },
+ }
+ end
+
+ if node.children then
+ for _, child in pairs(node.children) do
+ if not visited[child] then
+ walk_tree(child, visited, result, padding .. " ", hl_bufs)
+ end
+ end
+ end
+
+ return result
+end
+
+local function highlight_detail(ast_buf)
+ for linenum, range in pairs(M.detail_pos[ast_buf]) do
+ vim.highlight.range(
+ ast_buf,
+ M.nsid,
+ conf.highlights.detail,
+ { linenum - 1, range.start },
+ { linenum - 1, range["end"] },
+ "v",
+ false,
+ 110
+ )
+ end
+end
+
+local function handler(err, ASTNode)
+ if err or not ASTNode then
+ return
+ else
+ local source_buf = api.nvim_get_current_buf()
+ vim.cmd.vsplit(fmt("%s: AST", ASTNode.detail))
+ local ast_buf = api.nvim_get_current_buf()
+ api.nvim_set_option_value("filetype", "ClangdAST", { buf = ast_buf })
+ if not M.node_pos[source_buf] then M.node_pos[source_buf] = {} end
+ M.node_pos[source_buf][ast_buf] = {}
+ M.detail_pos[ast_buf] = {}
+
+ local lines = walk_tree(
+ ASTNode,
+ {},
+ {},
+ "",
+ { source_buf = source_buf, ast_buf = ast_buf }
+ )
+ api.nvim_buf_set_lines(ast_buf, 0, -1, true, lines)
+ vim.bo.buftype = "nofile"
+ vim.bo.bufhidden = "wipe"
+ vim.bo.modifiable = false
+ vim.bo.shiftwidth = 2
+ vim.wo.foldmethod = "indent"
+ api.nvim_set_option_value("number", false, { scope = "local" })
+ api.nvim_set_option_value("relativenumber", false, { scope = "local" })
+ api.nvim_set_option_value("spell", false, { scope = "local" })
+ api.nvim_set_option_value("cursorline", false, { scope = "local" })
+ setup_hl_autocmd(source_buf, ast_buf)
+ highlight_detail(ast_buf)
+ end
+end
+
+function M.clear_highlight(source_buf)
+ api.nvim_buf_clear_namespace(source_buf, M.nsid, 0, -1)
+end
+
+function M.update_highlight(source_buf, ast_buf)
+ M.clear_highlight(source_buf)
+ if api.nvim_get_current_buf() ~= ast_buf then return end
+ local curline = vim.fn.getcurpos()[2]
+ local curline_ranges = M.node_pos[source_buf][ast_buf][curline]
+ if curline_ranges then
+ vim.highlight.range(
+ source_buf,
+ M.nsid,
+ "Search",
+ curline_ranges.start,
+ curline_ranges["end"],
+ "v",
+ false,
+ 110
+ )
+ end
+end
+
+function M.display_ast(line1, line2)
+ vim.lsp.buf_request(0, "textDocument/ast", {
+ textDocument = { uri = vim.uri_from_bufnr(0) },
+ range = {
+ start = {
+ line = line1 - 1,
+ character = 0,
+ },
+ ["end"] = {
+ line = line2,
+ character = 0,
+ },
+ },
+ }, handler)
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/cmp_scores.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/cmp_scores.lua
new file mode 100644
index 00000000..66885c60
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/cmp_scores.lua
@@ -0,0 +1,10 @@
+return function(entry1, entry2)
+ local diff
+ if entry1.completion_item.score and entry2.completion_item.score then
+ diff = (entry2.completion_item.score * entry2.score)
+ - (entry1.completion_item.score * entry1.score)
+ else
+ diff = entry2.score - entry1.score
+ end
+ return (diff < 0)
+end
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/config.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/config.lua
new file mode 100644
index 00000000..3c28c1f9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/config.lua
@@ -0,0 +1,57 @@
+local M = {}
+
+M.options = {
+ inlay_hints = {
+ inline = vim.fn.has("nvim-0.10") == 1,
+ only_current_line = false,
+ only_current_line_autocmd = { "CursorHold" },
+ show_parameter_hints = true,
+ parameter_hints_prefix = "<- ",
+ other_hints_prefix = "=> ",
+ max_len_align = false,
+ max_len_align_padding = 1,
+ right_align = false,
+ right_align_padding = 7,
+ highlight = "Comment",
+ priority = 100,
+ },
+
+ ast = {
+ role_icons = {
+ type = "🄣",
+ declaration = "🄓",
+ expression = "🄔",
+ statement = ";",
+ specifier = "🄢",
+ ["template argument"] = "🆃",
+ },
+
+ kind_icons = {
+ Compound = "🄲",
+ Recovery = "🅁",
+ TranslationUnit = "🅄",
+ PackExpansion = "🄿",
+ TemplateTypeParm = "🅃",
+ TemplateTemplateParm = "🅃",
+ TemplateParamObject = "🅃",
+ },
+
+ highlights = {
+ detail = "Comment",
+ },
+ },
+
+ memory_usage = {
+ border = "none",
+ },
+
+ symbol_info = {
+ border = "none",
+ },
+}
+
+function M.setup(options)
+ M.options = vim.tbl_deep_extend("force", {}, M.options, options or {})
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/init.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/init.lua
new file mode 100644
index 00000000..b2cc377d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/init.lua
@@ -0,0 +1,5 @@
+return {
+ setup = function(options)
+ require("clangd_extensions.config").setup(options)
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/inlay_hints.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/inlay_hints.lua
new file mode 100644
index 00000000..e0ee08aa
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/inlay_hints.lua
@@ -0,0 +1,311 @@
+-- MIT License
+--
+-- Copyright (c) 2020 simrat39
+--
+-- 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.
+
+local M = {}
+local config = require("clangd_extensions.config")
+local api = vim.api
+
+-- Update inlay hints when opening a new buffer and when writing a buffer to a
+-- file
+-- opts is a string representation of the table of options
+function M.setup_autocmd()
+ local events = { "BufEnter", "BufWinEnter", "TabEnter", "BufWritePost" }
+ if config.options.inlay_hints.only_current_line then
+ vim.list_extend(
+ events,
+ config.options.inlay_hints.only_current_line_autocmd
+ )
+ end
+
+ local augroup = vim.api.nvim_create_augroup("ClangdInlayHints", {})
+ local buffer = api.nvim_get_current_buf()
+ api.nvim_clear_autocmds({
+ buffer = buffer,
+ group = augroup,
+ })
+ api.nvim_create_autocmd(events, {
+ buffer = buffer,
+ group = augroup,
+ callback = M.set_inlay_hints,
+ })
+end
+
+local function get_inline_params()
+ return {
+ textDocument = vim.lsp.util.make_text_document_params(),
+ range = {
+ start = {
+ line = 0,
+ character = 0,
+ },
+ ["end"] = {
+ line = vim.api.nvim_buf_line_count(0),
+ character = 0,
+ },
+ },
+ }
+end
+
+local namespace = vim.api.nvim_create_namespace("clangd/inlayHints")
+-- whether the hints are enabled or not
+local enabled = nil
+
+-- parses the result into a easily parsable format
+-- example:
+-- {
+-- ["12"] = { {
+-- kind = "TypeHint",
+-- label = "String"
+-- } },
+-- ["13"] = { {
+-- kind = "TypeHint",
+-- label = "usize"
+-- } },
+-- ["15"] = { {
+-- kind = "ParameterHint",
+-- label = "styles"
+-- }, {
+-- kind = "ParameterHint",
+-- label = "len"
+-- } },
+-- ["7"] = { {
+-- kind = "ChainingHint",
+-- label = "Result"
+-- }, {
+-- kind = "ParameterHint",
+-- label = "key"
+-- } },
+-- ["8"] = { {
+-- kind = "ParameterHint",
+-- label = "op"
+-- } }
+-- }
+--
+local function parseHints(result)
+ local map = {}
+ local only_current_line = config.options.inlay_hints.only_current_line
+
+ if type(result) ~= "table" then return {} end
+ for _, value in pairs(result) do
+ local line = tostring(value.range["end"].line)
+ local label = value.label
+ local kind = value.kind
+ local current_line = vim.api.nvim_win_get_cursor(0)[1]
+
+ local function add_line()
+ if map[line] ~= nil then
+ table.insert(map[line], { label = label, kind = kind })
+ else
+ map[line] = { { label = label, kind = kind } }
+ end
+ end
+
+ if only_current_line then
+ if line == tostring(current_line - 1) then add_line() end
+ else
+ add_line()
+ end
+ end
+ return map
+end
+
+local function handler(err, result, ctx)
+ if err then return end
+ local opts = config.options.inlay_hints
+ local bufnr = ctx.bufnr
+
+ if vim.api.nvim_get_current_buf() ~= bufnr then return end
+
+ -- clean it up at first
+ M.disable_inlay_hints()
+
+ local ret = parseHints(result)
+ local max_len = -1
+
+ for key, _ in pairs(ret) do
+ local line = tonumber(key)
+ local current_line =
+ vim.api.nvim_buf_get_lines(bufnr, line, line + 1, false)[1]
+ if current_line then
+ local current_line_len = string.len(current_line)
+ max_len = math.max(max_len, current_line_len)
+ end
+ end
+
+ for key, value in pairs(ret) do
+ local virt_text = ""
+ local line = tonumber(key)
+
+ local current_line =
+ vim.api.nvim_buf_get_lines(bufnr, line, line + 1, false)[1]
+
+ if current_line then
+ local current_line_len = string.len(current_line)
+
+ local param_hints = {}
+ local other_hints = {}
+
+ -- segregate paramter hints and other hints
+ for _, value_inner in ipairs(value) do
+ if value_inner.kind == "parameter" then
+ table.insert(param_hints, value_inner.label:sub(1, -3))
+ else
+ local hint_text = value_inner.label
+ if hint_text:sub(1, 2) == ": " then
+ hint_text = hint_text:sub(3)
+ end
+ table.insert(other_hints, hint_text)
+ end
+ end
+
+ -- show parameter hints inside brackets with commas and a thin arrow
+ if
+ not vim.tbl_isempty(param_hints) and opts.show_parameter_hints
+ then
+ virt_text = virt_text .. opts.parameter_hints_prefix .. "("
+ for i, value_inner_inner in ipairs(param_hints) do
+ virt_text = virt_text .. value_inner_inner
+ if i ~= #param_hints then virt_text = virt_text .. ", " end
+ end
+ virt_text = virt_text .. ") "
+ end
+
+ -- show other hints with commas and a thicc arrow
+ if not vim.tbl_isempty(other_hints) then
+ virt_text = virt_text .. opts.other_hints_prefix
+ for i, value_inner_inner in ipairs(other_hints) do
+ virt_text = virt_text .. value_inner_inner
+ if i ~= #other_hints then virt_text = virt_text .. ", " end
+ end
+ end
+
+ if config.options.inlay_hints.right_align then
+ virt_text = virt_text
+ .. string.rep(
+ " ",
+ config.options.inlay_hints.right_align_padding
+ )
+ end
+
+ if config.options.inlay_hints.max_len_align then
+ virt_text = string.rep(
+ " ",
+ max_len
+ - current_line_len
+ + config.options.inlay_hints.max_len_align_padding
+ ) .. virt_text
+ end
+
+ -- set the virtual text
+ vim.api.nvim_buf_set_extmark(bufnr, namespace, line, 0, {
+ virt_text_pos = config.options.inlay_hints.right_align
+ and "right_align"
+ or "eol",
+ virt_text = {
+ { virt_text, config.options.inlay_hints.highlight },
+ },
+ hl_mode = "combine",
+ priority = config.options.inlay_hints.priority,
+ })
+
+ -- update state
+ enabled = true
+ end
+ end
+end
+
+local function inline_handler(err, result, ctx)
+ if err then return end
+ local bufnr = ctx.bufnr
+
+ if vim.api.nvim_get_current_buf() ~= bufnr then return end
+ local current_line = vim.api.nvim_win_get_cursor(0)[1]
+
+ -- clean it up first
+ M.disable_inlay_hints()
+
+ for _, hint in pairs(result) do
+ local text = hint.label
+ if hint.paddingLeft then text = " " .. text end
+ if hint.paddingRight then text = text .. " " end
+ local line = hint.position.line
+ if
+ line == current_line - 1
+ or not config.options.inlay_hints.only_current_line
+ then
+ local col = hint.position.character
+ vim.api.nvim_buf_set_extmark(bufnr, namespace, line, col, {
+ virt_text_pos = "inline",
+ virt_text = {
+ { text, config.options.inlay_hints.highlight },
+ },
+ hl_mode = "combine",
+ priority = config.options.inlay_hints.priority,
+ })
+ end
+ end
+end
+
+function M.toggle_inlay_hints()
+ if enabled then
+ M.disable_inlay_hints()
+ else
+ M.set_inlay_hints()
+ end
+ enabled = not enabled
+ return enabled
+end
+
+function M.disable_inlay_hints()
+ -- clear namespace which clears the virtual text as well
+ vim.api.nvim_buf_clear_namespace(0, namespace, 0, -1)
+end
+
+-- Sends the request to clangd to get the inlay hints and handle them
+function M.set_inlay_hints()
+ local buf = vim.api.nvim_get_current_buf()
+ local clients = vim.lsp.get_clients and vim.lsp.get_clients({ bufnr = buf })
+ or vim.lsp.buf_get_clients(buf)
+ -- ensure clangd is running and request doesn't cause error
+ for _, c in pairs(clients) do
+ if c.name == "clangd" then
+ if config.options.inlay_hints.inline then
+ vim.lsp.buf_request(
+ 0,
+ "textDocument/inlayHint",
+ get_inline_params(),
+ inline_handler
+ )
+ else
+ vim.lsp.buf_request(
+ 0,
+ "clangd/inlayHints",
+ { textDocument = vim.lsp.util.make_text_document_params() },
+ handler
+ )
+ end
+ break
+ end
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/memory_usage.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/memory_usage.lua
new file mode 100644
index 00000000..1efd52d8
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/memory_usage.lua
@@ -0,0 +1,112 @@
+local api = vim.api
+local fmt = string.format
+
+local function display(lines)
+ for k, line in pairs(lines) do -- Pad lines
+ if k ~= 1 then lines[k] = " " .. line .. " " end
+ end
+ local vim_width = api.nvim_get_option("columns")
+ local vim_height = api.nvim_get_option("lines")
+ local height = math.ceil(vim_height * 0.7 - 4)
+ local width = math.ceil(vim_width * 0.7)
+ local row = math.ceil((vim_height - height) / 2 - 1)
+ local col = math.ceil((vim_width - width) / 2)
+ local buf = api.nvim_create_buf(false, true)
+ api.nvim_open_win(buf, true, {
+ style = "minimal",
+ relative = "editor",
+ width = width,
+ height = height,
+ row = row,
+ col = col,
+ border = require("clangd_extensions.config").options.memory_usage.border,
+ })
+ vim.bo.shiftwidth = 2
+ vim.wo.foldmethod = "indent"
+ api.nvim_buf_set_lines(buf, 0, -1, true, lines)
+ api.nvim_set_option_value("bufhidden", "wipe", { buf = buf })
+ api.nvim_set_option_value("modifiable", false, { buf = buf })
+ api.nvim_set_option_value("buftype", "nofile", { buf = buf })
+ api.nvim_buf_set_keymap(buf, "n", "q", ":bd", {
+ noremap = true,
+ silent = true,
+ })
+ api.nvim_buf_set_keymap(buf, "n", "", ":bd", {
+ noremap = true,
+ silent = true,
+ })
+end
+
+local function format_name(name)
+ if name:sub(1, 7) == "file://" then name = vim.uri_to_fname(name) end
+ local cwd = vim.fn.getcwd()
+ if name:sub(1, string.len(cwd)) == cwd then
+ name = name:sub(string.len(cwd) + 2, -1)
+ end
+ return name
+end
+
+local function format_tree(
+ node,
+ visited,
+ result,
+ padding,
+ prefix,
+ expand_preamble
+)
+ if padding == "" then
+ table.insert(
+ result,
+ fmt("Total: self = %s, total = %s", node._self, node._total)
+ )
+ end
+ visited[prefix] = true
+ for child_name, child_node in pairs(node) do
+ if
+ child_name ~= "_self"
+ and child_name ~= "_total"
+ and not visited[prefix .. child_name]
+ then
+ child_name = format_name(child_name)
+ table.insert(
+ result,
+ padding
+ .. fmt(
+ "%s: self = %s, total = %s",
+ child_name,
+ child_node._self,
+ child_node._total
+ )
+ )
+ if child_name ~= "preamble" or expand_preamble then
+ format_tree(
+ child_node,
+ visited,
+ result,
+ padding .. " ",
+ prefix .. child_name,
+ expand_preamble
+ )
+ end
+ end
+ end
+ return result
+end
+
+local function handler(err, result, expand_preamble)
+ if err then return end
+ display(format_tree(result, {}, { "" }, "", "", expand_preamble))
+end
+
+local M = {}
+
+function M.show_memory_usage(expand_preamble)
+ vim.lsp.buf_request(
+ 0,
+ "$/memoryUsage",
+ nil,
+ function(err, result) handler(err, result, expand_preamble) end
+ )
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/switch_source_header.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/switch_source_header.lua
new file mode 100644
index 00000000..d19ae9c9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/switch_source_header.lua
@@ -0,0 +1,19 @@
+local function handler(_err, uri)
+ if not uri or uri == "" then
+ vim.api.nvim_echo({ { "Corresponding file cannot be determined" } }, false, {})
+ return
+ end
+ local file_name = vim.uri_to_fname(uri)
+ vim.api.nvim_cmd({
+ cmd = "edit",
+ args = { file_name },
+ }, {})
+end
+
+return {
+ switch_source_header = function()
+ vim.lsp.buf_request(0, "textDocument/switchSourceHeader", {
+ uri = vim.uri_from_bufnr(0),
+ }, handler)
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/symbol_info.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/symbol_info.lua
new file mode 100644
index 00000000..ad757fe2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/symbol_info.lua
@@ -0,0 +1,29 @@
+local function handler(err, result)
+ if err or (#result == 0) then return end
+ local name_str = string.format("name: %s", result[1].name)
+ local container_str =
+ string.format("container: %s", result[1].containerName)
+ vim.lsp.util.open_floating_preview({ name_str, container_str }, "", {
+ height = 2,
+ width = math.max(string.len(name_str), string.len(container_str)),
+ focusable = false,
+ focus = false,
+ border = require("clangd_extensions.config").options.symbol_info.border,
+ })
+end
+
+local M = {}
+
+function M.show_symbol_info()
+ vim.lsp.buf_request(0, "textDocument/symbolInfo", {
+ textDocument = {
+ uri = vim.uri_from_bufnr(0),
+ },
+ position = {
+ line = vim.fn.getcurpos()[2] - 1,
+ character = vim.fn.getcurpos()[3] - 1,
+ },
+ }, handler)
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/symbol_kind.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/symbol_kind.lua
new file mode 100644
index 00000000..74df28cf
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/symbol_kind.lua
@@ -0,0 +1,28 @@
+return {
+ "File",
+ "Module",
+ "Namespace",
+ "Package",
+ "Class",
+ "Method",
+ "Property",
+ "Field",
+ "Constructor",
+ "Enum",
+ "Interface",
+ "Function",
+ "Variable",
+ "Constant",
+ "String",
+ "Number",
+ "Boolean",
+ "Array",
+ "Object",
+ "Key",
+ "Null",
+ "EnumMember",
+ "Struct",
+ "Event",
+ "Operator",
+ "TypeParameter",
+}
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/type_hierarchy.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/type_hierarchy.lua
new file mode 100644
index 00000000..3650d728
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/lua/clangd_extensions/type_hierarchy.lua
@@ -0,0 +1,144 @@
+local symbol_kind = require("clangd_extensions.symbol_kind")
+local fmt = string.format
+local api = vim.api
+local type_hierarchy_augroup =
+ api.nvim_create_augroup("ClangdTypeHierarchy", {})
+
+local M = {}
+M.type_to_location = {}
+M.offset_encoding = {}
+
+local function format_tree(node, visited, result, padding, type_to_location)
+ visited[node.data] = true
+ table.insert(
+ result,
+ padding .. fmt(" • %s: %s", node.name, symbol_kind[node.kind])
+ )
+
+ type_to_location[node.name] = { uri = node.uri, range = node.range }
+
+ if node.parents then
+ if #node.parents > 0 then
+ table.insert(result, padding .. " Parents:")
+ for _, parent in pairs(node.parents) do
+ if not visited[parent.data] then
+ format_tree(
+ parent,
+ visited,
+ result,
+ padding .. " ",
+ type_to_location
+ )
+ end
+ end
+ end
+ end
+
+ if node.children then
+ if #node.children > 0 then
+ table.insert(result, padding .. " Children:")
+ for _, child in pairs(node.children) do
+ if not visited[child.data] then
+ format_tree(
+ child,
+ visited,
+ result,
+ padding .. " ",
+ type_to_location
+ )
+ end
+ end
+ end
+ end
+
+ return result
+end
+
+local function handler(err, TypeHierarchyItem, ctx)
+ if err or not TypeHierarchyItem then
+ return
+ else
+ -- Save old state
+ local source_win = api.nvim_get_current_win()
+
+ -- Init
+ M.offset_encoding[ctx.client_id] =
+ vim.lsp.get_client_by_id(ctx.client_id).offset_encoding
+ vim.cmd.split(fmt("%s: type hierarchy", TypeHierarchyItem.name))
+ local bufnr = vim.api.nvim_get_current_buf()
+ M.type_to_location[bufnr] = {}
+
+ -- Set content
+ local lines = format_tree(
+ TypeHierarchyItem,
+ {},
+ {},
+ "",
+ M.type_to_location[bufnr]
+ )
+ api.nvim_buf_set_lines(bufnr, 0, -1, true, lines)
+
+ -- Set options
+ vim.bo.modifiable = false
+ vim.bo.filetype = "ClangdTypeHierarchy"
+ vim.bo.buftype = "nofile"
+ vim.bo.bufhidden = "wipe"
+ vim.bo.buflisted = true
+ api.nvim_set_option_value("number", false, { scope = "local" })
+ api.nvim_set_option_value("relativenumber", false, { scope = "local" })
+ api.nvim_set_option_value("spell", false, { scope = "local" })
+ api.nvim_set_option_value("cursorline", false, { scope = "local" })
+ local winbar = api.nvim_get_option_value("winbar", {})
+ local numlines = winbar == "" and #lines or #lines + 1
+ local winheight = math.min(numlines, 15)
+ api.nvim_win_set_height(0, winheight)
+
+ -- Set highlights
+ vim.cmd([[
+ syntax clear
+ syntax match ClangdTypeName "\( \{2,\}• \)\@<=\w\+\(:\)\@="
+ ]])
+ vim.api.nvim_set_hl(0, "ClangdTypeName", { link = "Underlined" })
+
+ -- Set keymap
+ vim.keymap.set("n", "gd", function()
+ local word = vim.fn.expand("")
+ word = string.gsub(word, ":$", "")
+ local location = M.type_to_location[bufnr][word]
+ if location ~= nil then
+ api.nvim_set_current_win(source_win)
+ vim.lsp.util.jump_to_location(
+ location,
+ M.offset_encoding[ctx.client_id]
+ )
+ end
+ end, {
+ buffer = bufnr,
+ desc = "go to definition of type under cursor",
+ })
+
+ -- Clear `type_to_location` for this buffer when it is wiped out
+ api.nvim_create_autocmd("BufWipeOut", {
+ buffer = bufnr,
+ group = type_hierarchy_augroup,
+ callback = function() M.type_to_location[bufnr] = nil end,
+ })
+ end
+end
+
+function M.show_hierarchy()
+ vim.lsp.buf_request(0, "textDocument/typeHierarchy", {
+ textDocument = {
+ uri = vim.uri_from_bufnr(0),
+ },
+ position = {
+ line = vim.fn.getcurpos()[2] - 1,
+ character = vim.fn.getcurpos()[3] - 1,
+ },
+ -- TODO make these configurable (config + command args)
+ resolve = 3,
+ direction = 2,
+ }, handler)
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/nvim.yaml b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/nvim.yaml
new file mode 100644
index 00000000..b6c8743d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/nvim.yaml
@@ -0,0 +1,5 @@
+---
+base: lua51
+globals:
+ vim:
+ any: true
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/plugin/clangd_extensions.lua b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/plugin/clangd_extensions.lua
new file mode 100644
index 00000000..ca4a8fdc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/plugin/clangd_extensions.lua
@@ -0,0 +1,42 @@
+local create_command = vim.api.nvim_create_user_command
+
+create_command('ClangdSetInlayHints', function()
+ require("clangd_extensions.inlay_hints").set_inlay_hints()
+end, {})
+
+create_command('ClangdDisableInlayHints', function()
+ require("clangd_extensions.inlay_hints").disable_inlay_hints()
+end, {})
+
+create_command('ClangdToggleInlayHints', function()
+ require("clangd_extensions.inlay_hints").toggle_inlay_hints()
+end, {})
+
+create_command('ClangdAST', function(opts)
+ require("clangd_extensions.ast").display_ast(opts.line1, opts.line2)
+end, { range = true })
+
+create_command('ClangdTypeHierarchy', function()
+ require("clangd_extensions.type_hierarchy").show_hierarchy()
+end, {})
+
+create_command('ClangdSymbolInfo', function()
+ require("clangd_extensions.symbol_info").show_symbol_info()
+end, {})
+
+create_command(
+ 'ClangdMemoryUsage',
+ function(opts)
+ require("clangd_extensions.memory_usage").show_memory_usage(opts.args == 'expand_preamble')
+ end,
+ {
+ nargs = '?',
+ complete = function(_, _, _)
+ return { 'expand_preamble' }
+ end
+ }
+)
+
+create_command('ClangdSwitchSourceHeader', function()
+ require("clangd_extensions.switch_source_header").switch_source_header()
+end, {})
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/selene.toml b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/selene.toml
new file mode 100644
index 00000000..98b6ac72
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/selene.toml
@@ -0,0 +1 @@
+std = "nvim"
diff --git a/config/neovim/store/lazy-plugins/clangd_extensions.nvim/stylua.toml b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/stylua.toml
new file mode 100644
index 00000000..083b1c8a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/clangd_extensions.nvim/stylua.toml
@@ -0,0 +1,4 @@
+indent_width = 4
+column_width = 80
+indent_type = "Spaces"
+collapse_simple_statement = "Always"
diff --git a/config/neovim/store/lazy-plugins/cmp-async-path/LICENSE b/config/neovim/store/lazy-plugins/cmp-async-path/LICENSE
new file mode 100644
index 00000000..ae725ef1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-async-path/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 hrsh7th
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/neovim/store/lazy-plugins/cmp-async-path/README.md b/config/neovim/store/lazy-plugins/cmp-async-path/README.md
new file mode 100644
index 00000000..36f0406e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-async-path/README.md
@@ -0,0 +1,54 @@
+https://codeberg.org/FelipeLema/cmp-async-path
+
+# cmp-async-path
+
+nvim-cmp source for filesystem paths with async processing (neovim won't block while reading from disk).
+
+forked from https://github.com/hrsh7th/cmp-path/
+
+# Setup
+
+```lua
+require'cmp'.setup {
+ sources = {
+ { name = 'async_path' }
+ }
+}
+```
+
+
+## Configuration
+
+The below source configuration options are available. To set any of these options, do:
+
+```lua
+cmp.setup({
+ sources = {
+ {
+ name = 'async_path',
+ option = {
+ -- Options go into this table
+ },
+ },
+ },
+})
+```
+
+
+### trailing_slash (type: boolean)
+
+_Default:_ `false`
+
+Specify if completed directory names should include a trailing slash. Enabling this option makes this source behave like Vim's built-in path completion.
+
+### label_trailing_slash (type: boolean)
+
+_Default:_ `true`
+
+Specify if directory names in the completion menu should include a trailing slash.
+
+### get_cwd (type: function)
+
+_Default:_ returns the current working directory of the current buffer
+
+Specifies the base directory for relative paths.
diff --git a/config/neovim/store/lazy-plugins/cmp-async-path/after/plugin/cmp_async_path.lua b/config/neovim/store/lazy-plugins/cmp-async-path/after/plugin/cmp_async_path.lua
new file mode 100644
index 00000000..ed3ec264
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-async-path/after/plugin/cmp_async_path.lua
@@ -0,0 +1 @@
+require('cmp').register_source('async_path', require('cmp_async_path').new())
diff --git a/config/neovim/store/lazy-plugins/cmp-async-path/lua/cmp_async_path/init.lua b/config/neovim/store/lazy-plugins/cmp-async-path/lua/cmp_async_path/init.lua
new file mode 100644
index 00000000..6c80b1b1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-async-path/lua/cmp_async_path/init.lua
@@ -0,0 +1,249 @@
+local cmp = require 'cmp'
+local NAME_REGEX = '\\%([^/\\\\:\\*?<>\'"`\\|]\\)'
+local PATH_REGEX = assert(vim.regex(
+ ([[\%(\%(/PAT*[^/\\\\:\\*?<>\'"`\\| .~]\)\|\%(/\.\.\)\)*/\zePAT*$]]):gsub(
+ 'PAT', NAME_REGEX)))
+
+local source = {}
+
+local constants = {max_lines = 20}
+
+---@class cmp_path.Option
+---@field public trailing_slash boolean
+---@field public label_trailing_slash boolean
+---@field public get_cwd fun(table): string
+
+---@type cmp_path.Option
+local defaults = {
+ trailing_slash = false,
+ label_trailing_slash = true,
+ get_cwd = function(params)
+ return vim.fn.expand(('#%d:p:h'):format(params.context.bufnr))
+ end,
+}
+
+source.new = function() return setmetatable({}, {__index = source}) end
+
+source.get_trigger_characters = function() return {'/', '.'} end
+
+source.get_keyword_pattern = function(_, _) return NAME_REGEX .. '*' end
+
+source.complete = function(self, params, callback)
+ local option = self:_validate_option(params)
+
+ local dirname = self:_dirname(params, option)
+ if not dirname then
+ return callback()
+ end
+
+ local include_hidden = string.sub(params.context.cursor_before_line,
+ params.offset, params.offset) == '.'
+ self:_candidates(dirname, include_hidden, option, function(err, candidates)
+ if err then
+ return callback()
+ end
+ callback(candidates)
+ end)
+end
+
+source.resolve = function(self, completion_item, callback)
+ local data = completion_item.data
+ if data.stat and data.stat.type == 'file' then
+ local ok, documentation = pcall(function()
+ return self:_get_documentation(data.path, constants.max_lines)
+ end)
+ if ok then
+ completion_item.documentation = documentation
+ end
+ end
+ callback(completion_item)
+end
+
+source._dirname = function(self, params, option)
+ local s = PATH_REGEX:match_str(params.context.cursor_before_line)
+ if not s then
+ return nil
+ end
+
+ local dirname = string.gsub(string.sub(params.context.cursor_before_line,
+ s + 2), '%a*$', '') -- exclude '/'
+ local prefix = string.sub(params.context.cursor_before_line, 1, s + 1) -- include '/'
+
+ local buf_dirname = option.get_cwd(params)
+ if vim.api.nvim_get_mode().mode == 'c' then
+ buf_dirname = vim.fn.getcwd()
+ end
+ if prefix:match('%.%./$') then
+ return vim.fn.resolve(buf_dirname .. '/../' .. dirname)
+ end
+ if (prefix:match('%./$') or prefix:match('"$') or prefix:match('\'$')) then
+ return vim.fn.resolve(buf_dirname .. '/' .. dirname)
+ end
+ if prefix:match('~/$') then
+ return vim.fn.resolve(vim.fn.expand('~') .. '/' .. dirname)
+ end
+ local env_var_name = prefix:match('%$([%a_]+)/$')
+ if env_var_name then
+ local env_var_value = vim.fn.getenv(env_var_name)
+ if env_var_value ~= vim.NIL then
+ return vim.fn.resolve(env_var_value .. '/' .. dirname)
+ end
+ end
+ if prefix:match('/$') then
+ local accept = true
+ -- Ignore URL components
+ accept = accept and not prefix:match('%a/$')
+ -- Ignore URL scheme
+ accept = accept and not prefix:match('%a+:/$') and
+ not prefix:match('%a+://$')
+ -- Ignore HTML closing tags
+ accept = accept and not prefix:match('$')
+ -- Ignore math calculation
+ accept = accept and not prefix:match('[%d%)]%s*/$')
+ -- Ignore / comment
+ accept = accept and
+ (not prefix:match('^[%s/]*$') or not self:_is_slash_comment())
+ if accept then
+ return vim.fn.resolve('/' .. dirname)
+ end
+ end
+ return nil
+end
+
+source._candidates = function(_, dirname, include_hidden, option, callback)
+ local entries, err = vim.loop.fs_scandir(dirname)
+ if err then
+ return callback(err, nil)
+ end
+
+ local work
+ work = assert(vim.loop.new_work(function(_entries, _dirname,
+ label_trailing_slash, trailing_slash,
+ file_kind, folder_kind)
+ local items = {}
+
+ local function create_item(name, fs_type)
+ if not (include_hidden or string.sub(name, 1, 1) ~= '.') then
+ return
+ end
+
+ local path = _dirname .. '/' .. name
+ local stat = assert(vim.loop.fs_stat)(path)
+ local lstat = nil
+ if stat then
+ fs_type = stat.type
+ elseif fs_type == 'link' then
+ -- Broken symlink
+ lstat = assert(vim.loop.fs_lstat)(_dirname)
+ if not lstat then
+ return
+ end
+ else
+ return
+ end
+
+ local item = {
+ label = name,
+ filterText = name,
+ insertText = name,
+ kind = file_kind,
+ data = {path = path, type = fs_type, stat = stat, lstat = lstat},
+ }
+ if fs_type == 'directory' then
+ item.kind = folder_kind
+ if label_trailing_slash then
+ item.label = name .. '/'
+ else
+ item.label = name
+ end
+ item.insertText = name .. '/'
+ if not trailing_slash then
+ item.word = name
+ end
+ end
+
+ table.insert(items, item)
+ end
+
+ while true do
+ local name, fs_type, e = assert(vim.loop.fs_scandir_next)(_entries)
+ if e then
+ return fs_type, ""
+ end
+ if not name then
+ break
+ end
+ create_item(name, fs_type)
+ end
+
+ return nil, vim.json.encode(items)
+ end, function(worker_error, serialized_items)
+ if worker_error then
+ callback(err, nil)
+ return
+ end
+ local read_ok, items = pcall(vim.json.decode, serialized_items, { luanil = { object = true, array = true } })
+ if not read_ok then
+ callback("Problem de-serializing file entries", nil)
+ end
+ callback(nil, items)
+ end))
+
+ work:queue(entries, dirname, option.label_trailing_slash,
+ option.trailing_slash, cmp.lsp.CompletionItemKind.File,
+ cmp.lsp.CompletionItemKind.Folder)
+
+end
+
+source._is_slash_comment = function(_)
+ local commentstring = vim.bo.commentstring or ''
+ local no_filetype = vim.bo.filetype == ''
+ local is_slash_comment = false
+ is_slash_comment = is_slash_comment or commentstring:match('/%*')
+ is_slash_comment = is_slash_comment or commentstring:match('//')
+ return is_slash_comment and not no_filetype
+end
+
+---@return cmp_path.Option
+source._validate_option = function(_, params)
+ local option = vim.tbl_deep_extend('keep', params.option, defaults)
+ vim.validate({
+ trailing_slash = {option.trailing_slash, 'boolean'},
+ label_trailing_slash = {option.label_trailing_slash, 'boolean'},
+ get_cwd = {option.get_cwd, 'function'},
+ })
+ return option
+end
+
+source._get_documentation = function(_, filename, count)
+ local binary = assert(io.open(filename, 'rb'))
+ local first_kb = binary:read(1024)
+ if first_kb:find('\0') then
+ return {kind = cmp.lsp.MarkupKind.PlainText, value = 'binary file'}
+ end
+
+ local contents = {}
+ for content in first_kb:gmatch("[^\r\n]+") do
+ table.insert(contents, content)
+ if count ~= nil and #contents >= count then
+ break
+ end
+ end
+
+ local filetype = vim.filetype.match({filename = filename})
+ if not filetype then
+ return {
+ kind = cmp.lsp.MarkupKind.PlainText,
+ value = table.concat(contents, '\n'),
+ }
+ end
+
+ table.insert(contents, 1, '```' .. filetype)
+ table.insert(contents, '```')
+ return {
+ kind = cmp.lsp.MarkupKind.Markdown,
+ value = table.concat(contents, '\n'),
+ }
+end
+
+return source
diff --git a/config/neovim/store/lazy-plugins/cmp-buffer/LICENSE b/config/neovim/store/lazy-plugins/cmp-buffer/LICENSE
new file mode 100644
index 00000000..ae725ef1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-buffer/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 hrsh7th
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/neovim/store/lazy-plugins/cmp-buffer/README.md b/config/neovim/store/lazy-plugins/cmp-buffer/README.md
new file mode 100644
index 00000000..4d0f5611
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-buffer/README.md
@@ -0,0 +1,226 @@
+# cmp-buffer
+
+nvim-cmp source for buffer words.
+
+## Setup
+
+```lua
+require('cmp').setup({
+ sources = {
+ { name = 'buffer' },
+ },
+})
+```
+
+## Configuration
+
+The below source configuration are available. To set any of these options, do:
+
+```lua
+cmp.setup({
+ sources = {
+ {
+ name = 'buffer',
+ option = {
+ -- Options go into this table
+ },
+ },
+ },
+})
+```
+
+
+### keyword_length (type: number)
+
+_Default:_ `3`
+
+The number of characters that need to be typed to trigger auto-completion.
+
+
+### keyword_pattern (type: string)
+
+_Default:_ `[[\%(-\?\d\+\%(\.\d\+\)\?\|\h\w*\%([\-.]\w*\)*\)]]`
+
+A vim's regular expression for creating a word list from buffer content.
+
+You can set this to `[[\k\+]]` if you want to use the `iskeyword` option for recognizing words.
+Lua's `[[ ]]` string literals are particularly useful here to avoid escaping all of the backslash
+(`\`) characters used for writing regular expressions.
+
+**NOTE:** Be careful with where you set this option! You must do this:
+
+```lua
+cmp.setup({
+ sources = {
+ {
+ name = 'buffer',
+ -- Correct:
+ option = {
+ keyword_pattern = [[\k\+]],
+ }
+ },
+ },
+})
+```
+
+Instead of this:
+
+```lua
+cmp.setup({
+ sources = {
+ {
+ name = 'buffer',
+ -- Wrong:
+ keyword_pattern = [[\k\+]],
+ },
+ },
+})
+```
+
+The second notation is allowed by nvim-cmp (documented [here](https://github.com/hrsh7th/nvim-cmp#sourcesnumberkeyword_pattern-type-string)), but it is meant for a different purpose and will not be detected by this plugin as the pattern for searching words.
+
+
+### get_bufnrs (type: fun(): number[])
+
+_Default:_ `function() return { vim.api.nvim_get_current_buf() } end`
+
+A function that specifies the buffer numbers to complete.
+
+You can use the following pre-defined recipes.
+
+##### All buffers
+
+```lua
+cmp.setup {
+ sources = {
+ {
+ name = 'buffer',
+ option = {
+ get_bufnrs = function()
+ return vim.api.nvim_list_bufs()
+ end
+ }
+ }
+ }
+}
+```
+
+##### Visible buffers
+
+```lua
+cmp.setup {
+ sources = {
+ {
+ name = 'buffer',
+ option = {
+ get_bufnrs = function()
+ local bufs = {}
+ for _, win in ipairs(vim.api.nvim_list_wins()) do
+ bufs[vim.api.nvim_win_get_buf(win)] = true
+ end
+ return vim.tbl_keys(bufs)
+ end
+ }
+ }
+ }
+}
+
+```
+
+
+### indexing_interval (type: number)
+
+_Default:_ `100`
+
+Optimization option. See the section [Indexing](#indexing-and-how-to-optimize-it).
+
+
+### indexing_batch_size (type: number)
+
+_Default:_ `1000`
+
+Optimization option. See the section [Indexing](#indexing-and-how-to-optimize-it).
+
+
+### max_indexed_line_length (type: number)
+
+_Default:_ `1024 * 40` (40 Kilobytes)
+
+Optimization option. See the section [Indexing](#indexing-and-how-to-optimize-it).
+
+
+## Locality bonus comparator (distance-based sorting)
+
+This source also provides a comparator function which uses information from the word indexer
+to sort completion results based on the distance of the word from the cursor line. It will also
+sort completion results coming from other sources, such as Language Servers, which might improve
+accuracy of their suggestions too. The usage is as follows:
+
+```lua
+local cmp = require('cmp')
+local cmp_buffer = require('cmp_buffer')
+
+cmp.setup({
+ sources = {
+ { name = 'buffer' },
+ -- The rest of your sources...
+ },
+ sorting = {
+ comparators = {
+ function(...) return cmp_buffer:compare_locality(...) end,
+ -- The rest of your comparators...
+ }
+ }
+})
+```
+
+
+## Indexing and how to optimize it
+
+When a buffer is opened, this source first has to scan all lines in the buffer, match all words
+and store all of their occurrences. This process is called _indexing_. When actually editing the
+text in the buffer, the index of words is kept up-to-date with changes to the buffer's contents,
+this is called _watching_. It is done by re-running the indexer on just the changed lines.
+Indexing happens completely asynchronously in background, unlike watching, which must be performed
+synchronously to ensure that the index of words is kept perfectly in-sync with the lines in the
+buffer. However, most of the time this will not be a problem since many typical text edit
+operations affect only one or two lines, unless you are pasting a 1000-line snippet.
+
+_Note that you can freely edit the buffer while it is being indexed_, the underlying algorithm is
+written in such a way that your changes will not break the index or cause errors. If a crash does
+happen - it is a bug, so please report it.
+
+The speed of indexing is configurable with two options: `indexing_interval` and
+`indexing_batch_size`. Essentially, when indexing, a timer is started, which pulls a batch of
+`indexing_batch_size` lines from the buffer, scans them for words, and repeats after
+`indexing_interval` milliseconds. Decreasing interval and/or increasing the batch size will make
+the indexer faster, but at the expense of higher CPU usage and more lag when editing the file
+while indexing is still in progress. Setting `indexing_batch_size` to a negative value will switch
+the indexer to the "synchronous" mode: this will process all lines in one go, take less time in
+total (since no other code will be running on the Lua thread), but with the obvious downside that
+the editor UI will be blocked.
+
+The option `max_indexed_line_length` controls plugin's behavior in files with very long lines.
+This is known to slow this source down significantly (see issue [#13](https://github.com/hrsh7th/cmp-buffer/issues/13)),
+so by default it will take only the first few kilobytes of the line it is currently on. In other
+words, very long lines are not ignored, but only a part of them is indexed.
+
+### Performance on large text files
+
+This source has been tested on code files of a few megabytes in size (5-10) and contains
+optimizations for them, however, the indexed words can still take up tens of megabytes of RAM if
+the file is large. So, if you wish to avoid accidentally running this source on big files, you
+can tweak `get_bufnrs`, for example like this:
+
+```lua
+get_bufnrs = function()
+ local buf = vim.api.nvim_get_current_buf()
+ local byte_size = vim.api.nvim_buf_get_offset(buf, vim.api.nvim_buf_line_count(buf))
+ if byte_size > 1024 * 1024 then -- 1 Megabyte max
+ return {}
+ end
+ return { buf }
+end
+```
+
+Of course, this snippet can be combined with any other recipes for `get_bufnrs`.
diff --git a/config/neovim/store/lazy-plugins/cmp-buffer/after/plugin/cmp_buffer.lua b/config/neovim/store/lazy-plugins/cmp-buffer/after/plugin/cmp_buffer.lua
new file mode 100644
index 00000000..a66afbd8
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-buffer/after/plugin/cmp_buffer.lua
@@ -0,0 +1 @@
+require('cmp').register_source('buffer', require('cmp_buffer'))
diff --git a/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/buffer.lua b/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/buffer.lua
new file mode 100644
index 00000000..d0ed2858
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/buffer.lua
@@ -0,0 +1,380 @@
+local timer = require('cmp_buffer.timer')
+
+local function clear_table(tbl)
+ for k in pairs(tbl) do
+ tbl[k] = nil
+ end
+end
+
+---@class cmp_buffer.Buffer
+---@field public bufnr number
+---@field public opts cmp_buffer.Options
+---@field public regex any
+---@field public timer cmp_buffer.Timer
+---@field public lines_count number
+---@field public timer_current_line number
+---@field public lines_words table
+---@field public unique_words_curr_line table
+---@field public unique_words_other_lines table
+---@field public unique_words_curr_line_dirty boolean
+---@field public unique_words_other_lines_dirty boolean
+---@field public last_edit_first_line number
+---@field public last_edit_last_line number
+---@field public closed boolean
+---@field public on_close_cb fun()|nil
+---@field public words_distances table
+---@field public words_distances_last_cursor_row number
+---@field public words_distances_dirty boolean
+local buffer = {}
+
+-- For some reason requesting this much lines multiple times in chunks leads to
+-- much better memory usage than fetching the entire file in one go.
+buffer.GET_LINES_CHUNK_SIZE = 1000
+
+---Create new buffer object
+---@param bufnr number
+---@param opts cmp_buffer.Options
+---@return cmp_buffer.Buffer
+function buffer.new(bufnr, opts)
+ local self = setmetatable({}, { __index = buffer })
+
+ self.bufnr = bufnr
+ self.timer = timer.new()
+ self.closed = false
+ self.on_close_cb = nil
+
+ self.opts = opts
+ self.regex = vim.regex(self.opts.keyword_pattern)
+
+ self.lines_count = 0
+ self.timer_current_line = -1
+ self.lines_words = {}
+
+ self.unique_words_curr_line = {}
+ self.unique_words_other_lines = {}
+ self.unique_words_curr_line_dirty = true
+ self.unique_words_other_lines_dirty = true
+ self.last_edit_first_line = 0
+ self.last_edit_last_line = 0
+
+ self.words_distances = {}
+ self.words_distances_dirty = true
+ self.words_distances_last_cursor_row = 0
+
+ return self
+end
+
+---Close buffer
+function buffer.close(self)
+ self.closed = true
+ self:stop_indexing_timer()
+ self.timer:close()
+ self.timer = nil
+
+ self.lines_count = 0
+ self.timer_current_line = -1
+ self.lines_words = {}
+
+ self.unique_words_curr_line = {}
+ self.unique_words_other_lines = {}
+ self.unique_words_curr_line_dirty = false
+ self.unique_words_other_lines_dirty = false
+ self.last_edit_first_line = 0
+ self.last_edit_last_line = 0
+
+ self.words_distances = {}
+ self.words_distances_dirty = false
+ self.words_distances_last_cursor_row = 0
+
+ if self.on_close_cb then
+ self.on_close_cb()
+ end
+end
+
+function buffer.stop_indexing_timer(self)
+ self.timer:stop()
+ self.timer_current_line = -1
+end
+
+function buffer.mark_all_lines_dirty(self)
+ self.unique_words_curr_line_dirty = true
+ self.unique_words_other_lines_dirty = true
+ self.last_edit_first_line = 0
+ self.last_edit_last_line = 0
+ self.words_distances_dirty = true
+end
+
+--- Workaround for https://github.com/neovim/neovim/issues/16729
+function buffer.safe_buf_call(self, callback)
+ if vim.api.nvim_get_current_buf() == self.bufnr then
+ callback()
+ else
+ vim.api.nvim_buf_call(self.bufnr, callback)
+ end
+end
+
+function buffer.index_range(self, range_start, range_end, skip_already_indexed)
+ self:safe_buf_call(function()
+ local chunk_size = self.GET_LINES_CHUNK_SIZE
+ local chunk_start = range_start
+ while chunk_start < range_end do
+ local chunk_end = math.min(chunk_start + chunk_size, range_end)
+ local chunk_lines = vim.api.nvim_buf_get_lines(self.bufnr, chunk_start, chunk_end, true)
+ for i, line in ipairs(chunk_lines) do
+ if not skip_already_indexed or not self.lines_words[chunk_start + i] then
+ self:index_line(chunk_start + i, line)
+ end
+ end
+ chunk_start = chunk_end
+ end
+ end)
+end
+
+function buffer.start_indexing_timer(self)
+ self.lines_count = vim.api.nvim_buf_line_count(self.bufnr)
+ self.timer_current_line = 0
+
+ -- Negative values result in an integer overflow in luv (vim.loop), and zero
+ -- disables timer repeat, so only intervals larger than 1 are valid.
+ local interval = math.max(1, self.opts.indexing_interval)
+ self.timer:start(0, interval, function()
+ if self.closed then
+ self:stop_indexing_timer()
+ return
+ end
+
+ -- Note that the async indexer is designed to not break even if the user is
+ -- editing the file while it is in the process of being indexed. Because
+ -- the indexing in watcher must use the synchronous algorithm, we assume
+ -- that the data already present in self.lines_words to be correct and
+ -- doesn't need refreshing here because even if we do receive text from
+ -- nvim_buf_get_lines different from what the watcher has seen so far, it
+ -- (the watcher) will catch up on the next on_lines event.
+
+ -- Skip over the already indexed lines
+ while self.lines_words[self.timer_current_line + 1] do
+ self.timer_current_line = self.timer_current_line + 1
+ end
+
+ local batch_start = self.timer_current_line
+ local batch_size = self.opts.indexing_batch_size
+ -- NOTE: self.lines_count may be modified by the indexer.
+ local batch_end = batch_size >= 1 and math.min(batch_start + batch_size, self.lines_count) or self.lines_count
+ if batch_end >= self.lines_count then
+ self:stop_indexing_timer()
+ end
+ self.timer_current_line = batch_end
+ self:mark_all_lines_dirty()
+
+ self:index_range(batch_start, batch_end, true)
+ end)
+end
+
+--- watch
+function buffer.watch(self)
+ self.lines_count = vim.api.nvim_buf_line_count(self.bufnr)
+
+ -- NOTE: As far as I know, indexing in watching can't be done asynchronously
+ -- because even built-in commands generate multiple consequent `on_lines`
+ -- events, and I'm not even mentioning plugins here. To get accurate results
+ -- we would have to either re-index the entire file on throttled events (slow
+ -- and looses the benefit of on_lines watching), or put the events in a
+ -- queue, which would complicate the plugin a lot. Plus, most changes which
+ -- trigger this event will be from regular editing, and so 99% of the time
+ -- they will affect only 1-2 lines.
+ vim.api.nvim_buf_attach(self.bufnr, false, {
+ -- NOTE: line indexes are 0-based and the last line is not inclusive.
+ on_lines = function(_, _, _, first_line, old_last_line, new_last_line, _, _, _)
+ if self.closed then
+ return true
+ end
+
+ if old_last_line == new_last_line and first_line == new_last_line then
+ -- This condition is really intended as a workaround for
+ -- https://github.com/hrsh7th/cmp-buffer/issues/28, but it will also
+ -- protect us from completely empty text edits.
+ return
+ end
+
+ local delta = new_last_line - old_last_line
+ local old_lines_count = self.lines_count
+ local new_lines_count = old_lines_count + delta
+ if new_lines_count == 0 then -- clear
+ -- This branch protects against bugs after full-file deletion. If you
+ -- do, for example, gdGG, the new_last_line of the event will be zero.
+ -- Which is not true, a buffer always contains at least one empty line,
+ -- only unloaded buffers contain zero lines.
+ new_lines_count = 1
+ for i = old_lines_count, 2, -1 do
+ self.lines_words[i] = nil
+ end
+ self.lines_words[1] = {}
+ elseif delta > 0 then -- append
+ -- Explicitly reserve more slots in the array part of the lines table,
+ -- all of them will be filled in the next loop, but in reverse order
+ -- (which is why I am concerned about preallocation). Why is there no
+ -- built-in function to do this in Lua???
+ for i = old_lines_count + 1, new_lines_count do
+ self.lines_words[i] = false
+ end
+ -- Move forwards the unchanged elements in the tail part.
+ for i = old_lines_count, old_last_line + 1, -1 do
+ self.lines_words[i + delta] = self.lines_words[i]
+ end
+ -- Fill in new tables for the added lines.
+ for i = old_last_line + 1, new_last_line do
+ self.lines_words[i] = {}
+ end
+ elseif delta < 0 then -- remove
+ -- Move backwards the unchanged elements in the tail part.
+ for i = old_last_line + 1, old_lines_count do
+ self.lines_words[i + delta] = self.lines_words[i]
+ end
+ -- Remove (already copied) tables from the end, in reverse order, so
+ -- that we don't make holes in the lines table.
+ for i = old_lines_count, new_lines_count + 1, -1 do
+ self.lines_words[i] = nil
+ end
+ end
+ self.lines_count = new_lines_count
+
+ -- This branch is support code for handling cases when the user is
+ -- editing the buffer while the async indexer is running. It solves the
+ -- problem that if new lines are inserted or old lines are deleted, the
+ -- indexes of each subsequent line will change, and so the indexer
+ -- current position must be adjusted to not accidentally skip any lines.
+ if self.timer:is_active() then
+ if first_line <= self.timer_current_line and self.timer_current_line < old_last_line then
+ -- The indexer was in the area of the current text edit. We will
+ -- synchronously index this area it in a moment, so the indexer
+ -- should resume from right after the edit range.
+ self.timer_current_line = new_last_line
+ elseif self.timer_current_line >= old_last_line then
+ -- The indexer was somewhere past the current text edit. This means
+ -- that the line numbers could have changed, and the indexing
+ -- position must be adjusted accordingly.
+ self.timer_current_line = self.timer_current_line + delta
+ end
+ end
+
+ if first_line == self.last_edit_first_line and old_last_line == self.last_edit_last_line and new_last_line == self.last_edit_last_line then
+ self.unique_words_curr_line_dirty = true
+ else
+ self.unique_words_curr_line_dirty = true
+ self.unique_words_other_lines_dirty = true
+ end
+ self.last_edit_first_line = first_line
+ self.last_edit_last_line = new_last_line
+
+ self.words_distances_dirty = true
+
+ -- replace lines
+ self:index_range(first_line, new_last_line)
+ end,
+
+ on_reload = function(_, _)
+ if self.closed then
+ return true
+ end
+
+ clear_table(self.lines_words)
+
+ self:stop_indexing_timer()
+ self:start_indexing_timer()
+ end,
+
+ on_detach = function(_, _)
+ if self.closed then
+ return true
+ end
+ self:close()
+ end,
+ })
+end
+
+---@param linenr number
+---@param line string
+function buffer.index_line(self, linenr, line)
+ local words = self.lines_words[linenr]
+ if not words then
+ words = {}
+ self.lines_words[linenr] = words
+ else
+ clear_table(words)
+ end
+ local word_i = 1
+
+ local remaining = line
+ -- The if statement checks the number of bytes in the line string, but slices
+ -- it on the number of characters. This is not a problem because the number
+ -- of characters is always equal to (if only ASCII characters are used) or
+ -- smaller than (if multibyte Unicode characters are used) the number of bytes.
+ -- In other words, if the line contains more characters than the max limit,
+ -- then it will always contain more bytes than the same limit.
+ -- This check is here because calling a Vimscript function is relatively slow.
+ if #remaining > self.opts.max_indexed_line_length then
+ remaining = vim.fn.strcharpart(line, 0, self.opts.max_indexed_line_length)
+ end
+ while #remaining > 0 do
+ -- NOTE: Both start and end indexes here are 0-based (unlike Lua strings),
+ -- and the end index is not inclusive.
+ local match_start, match_end = self.regex:match_str(remaining)
+ if match_start and match_end then
+ local word = remaining:sub(match_start + 1, match_end)
+ if #word >= self.opts.keyword_length then
+ words[word_i] = word
+ word_i = word_i + 1
+ end
+ remaining = remaining:sub(match_end + 1)
+ else
+ break
+ end
+ end
+end
+
+function buffer.get_words(self)
+ -- NOTE: unique_words are rebuilt on-demand because it is common for the
+ -- watcher callback to be fired VERY frequently, and a rebuild needs to go
+ -- over ALL lines, not just the changed ones.
+ if self.unique_words_other_lines_dirty then
+ clear_table(self.unique_words_other_lines)
+ self:rebuild_unique_words(self.unique_words_other_lines, 0, self.last_edit_first_line)
+ self:rebuild_unique_words(self.unique_words_other_lines, self.last_edit_last_line, self.lines_count)
+ self.unique_words_other_lines_dirty = false
+ end
+ if self.unique_words_curr_line_dirty then
+ clear_table(self.unique_words_curr_line)
+ self:rebuild_unique_words(self.unique_words_curr_line, self.last_edit_first_line, self.last_edit_last_line)
+ self.unique_words_curr_line_dirty = false
+ end
+ return { self.unique_words_other_lines, self.unique_words_curr_line }
+end
+
+--- rebuild_unique_words
+function buffer.rebuild_unique_words(self, words_table, range_start, range_end)
+ for i = range_start + 1, range_end do
+ for _, w in ipairs(self.lines_words[i] or {}) do
+ words_table[w] = true
+ end
+ end
+end
+
+---@param cursor_row number
+---@return table
+function buffer.get_words_distances(self, cursor_row)
+ if self.words_distances_dirty or cursor_row ~= self.words_distances_last_cursor_row then
+ local distances = self.words_distances
+ clear_table(distances)
+ for i = 1, self.lines_count do
+ for _, w in ipairs(self.lines_words[i] or {}) do
+ local dist = math.abs(cursor_row - i)
+ distances[w] = distances[w] and math.min(distances[w], dist) or dist
+ end
+ end
+ self.words_distances_last_cursor_row = cursor_row
+ self.words_distances_dirty = false
+ end
+ return self.words_distances
+end
+
+return buffer
diff --git a/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/init.lua b/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/init.lua
new file mode 100644
index 00000000..1f10b87e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/init.lua
@@ -0,0 +1 @@
+return require('cmp_buffer.source').new()
diff --git a/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/source.lua b/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/source.lua
new file mode 100644
index 00000000..9be673cf
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/source.lua
@@ -0,0 +1,125 @@
+local buffer = require('cmp_buffer.buffer')
+
+---@class cmp_buffer.Options
+---@field public keyword_length number
+---@field public keyword_pattern string
+---@field public get_bufnrs fun(): number[]
+---@field public indexing_batch_size number
+---@field public indexing_interval number
+---@field public max_indexed_line_length number
+
+---@type cmp_buffer.Options
+local defaults = {
+ keyword_length = 3,
+ keyword_pattern = [[\%(-\?\d\+\%(\.\d\+\)\?\|\h\%(\w\|á\|Á\|é\|É\|í\|Í\|ó\|Ó\|ú\|Ú\)*\%(-\%(\w\|á\|Á\|é\|É\|í\|Í\|ó\|Ó\|ú\|Ú\)*\)*\)]],
+ get_bufnrs = function()
+ return { vim.api.nvim_get_current_buf() }
+ end,
+ indexing_batch_size = 1000,
+ indexing_interval = 100,
+ max_indexed_line_length = 1024 * 40,
+}
+
+local source = {}
+
+source.new = function()
+ local self = setmetatable({}, { __index = source })
+ self.buffers = {}
+ return self
+end
+
+---@return cmp_buffer.Options
+source._validate_options = function(_, params)
+ local opts = vim.tbl_deep_extend('keep', params.option, defaults)
+ vim.validate({
+ keyword_length = { opts.keyword_length, 'number' },
+ keyword_pattern = { opts.keyword_pattern, 'string' },
+ get_bufnrs = { opts.get_bufnrs, 'function' },
+ indexing_batch_size = { opts.indexing_batch_size, 'number' },
+ indexing_interval = { opts.indexing_interval, 'number' },
+ })
+ return opts
+end
+
+source.get_keyword_pattern = function(self, params)
+ local opts = self:_validate_options(params)
+ return opts.keyword_pattern
+end
+
+source.complete = function(self, params, callback)
+ local opts = self:_validate_options(params)
+
+ local processing = false
+ local bufs = self:_get_buffers(opts)
+ for _, buf in ipairs(bufs) do
+ if buf.timer:is_active() then
+ processing = true
+ break
+ end
+ end
+
+ vim.defer_fn(function()
+ local input = string.sub(params.context.cursor_before_line, params.offset)
+ local items = {}
+ local words = {}
+ for _, buf in ipairs(bufs) do
+ for _, word_list in ipairs(buf:get_words()) do
+ for word, _ in pairs(word_list) do
+ if not words[word] and input ~= word then
+ words[word] = true
+ table.insert(items, {
+ label = word,
+ dup = 0,
+ })
+ end
+ end
+ end
+ end
+
+ callback({
+ items = items,
+ isIncomplete = processing,
+ })
+ end, processing and 100 or 0)
+end
+
+---@param opts cmp_buffer.Options
+---@return cmp_buffer.Buffer[]
+source._get_buffers = function(self, opts)
+ local buffers = {}
+ for _, bufnr in ipairs(opts.get_bufnrs()) do
+ if not self.buffers[bufnr] then
+ local new_buf = buffer.new(bufnr, opts)
+ new_buf.on_close_cb = function()
+ self.buffers[bufnr] = nil
+ end
+ new_buf:start_indexing_timer()
+ new_buf:watch()
+ self.buffers[bufnr] = new_buf
+ end
+ table.insert(buffers, self.buffers[bufnr])
+ end
+
+ return buffers
+end
+
+source._get_distance_from_entry = function(self, entry)
+ local buf = self.buffers[entry.context.bufnr]
+ if buf then
+ local distances = buf:get_words_distances(entry.context.cursor.line + 1)
+ return distances[entry.completion_item.filterText] or distances[entry.completion_item.label]
+ end
+end
+
+source.compare_locality = function(self, entry1, entry2)
+ if entry1.context ~= entry2.context then
+ return
+ end
+ local dist1 = self:_get_distance_from_entry(entry1) or math.huge
+ local dist2 = self:_get_distance_from_entry(entry2) or math.huge
+ if dist1 ~= dist2 then
+ return dist1 < dist2
+ end
+end
+
+return source
diff --git a/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/timer.lua b/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/timer.lua
new file mode 100644
index 00000000..3ed83c79
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-buffer/lua/cmp_buffer/timer.lua
@@ -0,0 +1,68 @@
+---This timer matches the semantics of setInterval and clearInterval of
+---Javascript. It provides a more reliable alternative to vim.loop.timer_start
+---with a callback wrapped into a vim.schedule call by addressing two problems:
+---1. Scheduled callbacks are invoked less frequently than a libuv timer with a
+--- small interval (1-5ms). This causes those callbacks to fill up the queue
+--- in the event loop, and so the callback function may get invoked multiple
+--- times on one event loop tick. In contrast, Javascript's setInterval
+--- guarantees that the callback is not invoked more frequently than the
+--- interval.
+---2. When a libuv timer is stopped with vim.loop.timer_stop, it doesn't affect
+--- the callbacks that have already been scheduled. So timer_stop will not
+--- immediately stop the timer, the actual callback function will run one
+--- more time until it is finally stopped. This implementation ensures that
+--- timer_stop prevents any subsequent invocations of the callback.
+---
+---@class cmp_buffer.Timer
+---@field public handle any
+---@field private callback_wrapper_instance fun()|nil
+local timer = {}
+
+function timer.new()
+ local self = setmetatable({}, { __index = timer })
+ self.handle = vim.loop.new_timer()
+ self.callback_wrapper_instance = nil
+ return self
+end
+
+---@param timeout_ms number
+---@param repeat_ms number
+---@param callback fun()
+function timer:start(timeout_ms, repeat_ms, callback)
+ -- This is the flag that fixes problem 1.
+ local scheduled = false
+ -- Creating a function on every call to timer_start ensures that we can always
+ -- detect when a different callback is set by calling timer_start and prevent
+ -- the old one from being invoked.
+ local function callback_wrapper()
+ if scheduled then
+ return
+ end
+ scheduled = true
+ vim.schedule(function()
+ scheduled = false
+ -- Either a different callback was set, or the timer has been stopped.
+ if self.callback_wrapper_instance ~= callback_wrapper then
+ return
+ end
+ callback()
+ end)
+ end
+ self.handle:start(timeout_ms, repeat_ms, callback_wrapper)
+ self.callback_wrapper_instance = callback_wrapper
+end
+
+function timer:stop()
+ self.handle:stop()
+ self.callback_wrapper_instance = nil
+end
+
+function timer:is_active()
+ return self.handle:is_active()
+end
+
+function timer:close()
+ self.handle:close()
+end
+
+return timer
diff --git a/config/neovim/store/lazy-plugins/cmp-cmdline/LICENSE b/config/neovim/store/lazy-plugins/cmp-cmdline/LICENSE
new file mode 100644
index 00000000..3a4ecf60
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-cmdline/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 hrsh7th
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/neovim/store/lazy-plugins/cmp-cmdline/README.md b/config/neovim/store/lazy-plugins/cmp-cmdline/README.md
new file mode 100644
index 00000000..9107a98e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-cmdline/README.md
@@ -0,0 +1,52 @@
+# cmp-cmdline
+
+nvim-cmp source for vim's cmdline.
+
+# Setup
+
+Completions for `/` search based on current buffer:
+```lua
+ -- `/` cmdline setup.
+ cmp.setup.cmdline('/', {
+ mapping = cmp.mapping.preset.cmdline(),
+ sources = {
+ { name = 'buffer' }
+ }
+ })
+```
+
+Completions for command mode:
+```lua
+ -- `:` cmdline setup.
+ cmp.setup.cmdline(':', {
+ mapping = cmp.mapping.preset.cmdline(),
+ sources = cmp.config.sources({
+ { name = 'path' }
+ }, {
+ {
+ name = 'cmdline',
+ option = {
+ ignore_cmds = { 'Man', '!' }
+ }
+ }
+ })
+ })
+```
+
+For the buffer source to work, [cmp-buffer](https://github.com/hrsh7th/cmp-buffer) is needed.
+
+
+# Option
+
+### ignore_cmds: string[]
+Default: `{ "Man", "!" }`
+
+You can specify ignore command name.
+
+### treat_trailing_slash: boolean
+Default: `true`
+
+`vim.fn.getcompletion` can return path items.
+unfortunately, that items has trailing slash so we don't narrowing with next directory with pressing `/`.
+
+if you turnd on this option, `cmp-cmdline` removes trailing slash automatically.
diff --git a/config/neovim/store/lazy-plugins/cmp-cmdline/after/plugin/cmp_cmdline.lua b/config/neovim/store/lazy-plugins/cmp-cmdline/after/plugin/cmp_cmdline.lua
new file mode 100644
index 00000000..936e662f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-cmdline/after/plugin/cmp_cmdline.lua
@@ -0,0 +1 @@
+require('cmp').register_source('cmdline', require('cmp_cmdline').new())
diff --git a/config/neovim/store/lazy-plugins/cmp-cmdline/lua/cmp_cmdline/init.lua b/config/neovim/store/lazy-plugins/cmp-cmdline/lua/cmp_cmdline/init.lua
new file mode 100644
index 00000000..53e75935
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-cmdline/lua/cmp_cmdline/init.lua
@@ -0,0 +1,248 @@
+local cmp = require('cmp')
+
+---@param patterns string[]
+---@param head boolean
+---@return table #regex object
+local function create_regex(patterns, head)
+ local pattern = [[\%(]] .. table.concat(patterns, [[\|]]) .. [[\)]]
+ if head then
+ pattern = '^' .. pattern
+ end
+ return vim.regex(pattern)
+end
+
+---@class cmp-cmdline.Option
+---@field treat_trailing_slash boolean
+---@field ignore_cmds string[]
+local DEFAULT_OPTION = {
+ treat_trailing_slash = true,
+ ignore_cmds = { 'Man', '!' }
+}
+
+local MODIFIER_REGEX = create_regex({
+ [=[\s*abo\%[veleft]\s*]=],
+ [=[\s*bel\%[owright]\s*]=],
+ [=[\s*bo\%[tright]\s*]=],
+ [=[\s*bro\%[wse]\s*]=],
+ [=[\s*conf\%[irm]\s*]=],
+ [=[\s*hid\%[e]\s*]=],
+ [=[\s*keepal\s*t]=],
+ [=[\s*keeppa\%[tterns]\s*]=],
+ [=[\s*lefta\%[bove]\s*]=],
+ [=[\s*loc\%[kmarks]\s*]=],
+ [=[\s*nos\%[wapfile]\s*]=],
+ [=[\s*rightb\%[elow]\s*]=],
+ [=[\s*sil\%[ent]\s*]=],
+ [=[\s*tab\s*]=],
+ [=[\s*to\%[pleft]\s*]=],
+ [=[\s*verb\%[ose]\s*]=],
+ [=[\s*vert\%[ical]\s*]=],
+}, true)
+
+local COUNT_RANGE_REGEX = create_regex({
+ [=[\s*\%(\d\+\|\$\)\%[,\%(\d\+\|\$\)]\s*]=],
+ [=[\s*'\%[<,'>]\s*]=],
+ [=[\s*\%(\d\+\|\$\)\s*]=],
+}, true)
+
+local ONLY_RANGE_REGEX = create_regex({
+ [=[^\s*\%(\d\+\|\$\)\%[,\%(\d\+\|\$\)]\s*$]=],
+ [=[^\s*'\%[<,'>]\s*$]=],
+ [=[^\s*\%(\d\+\|\$\)\s*$]=],
+}, true)
+
+local OPTION_NAME_COMPLETION_REGEX = create_regex({
+ [=[se\%[tlocal][^=]*$]=],
+}, true)
+
+---@param word string
+---@return boolean?
+local function is_boolean_option(word)
+ local ok, opt = pcall(function()
+ return vim.opt[word]:get()
+ end)
+ if ok then
+ return type(opt) == 'boolean'
+ end
+end
+
+---@class cmp.Cmdline.Definition
+---@field ctype string
+---@field regex string
+---@field kind lsp.CompletionItemKind
+---@field isIncomplete boolean
+---@field exec fun(option: table, arglead: string, cmdline: string, force: boolean): lsp.CompletionItem[]
+---@field fallback boolean?
+
+---@type cmp.Cmdline.Definition[]
+local definitions = {
+ {
+ ctype = 'cmdline',
+ regex = [=[[^[:blank:]]*$]=],
+ kind = cmp.lsp.CompletionItemKind.Variable,
+ isIncomplete = true,
+ ---@param option cmp-cmdline.Option
+ exec = function(option, arglead, cmdline, force)
+ -- Ignore range only cmdline. (e.g.: 4, '<,'>)
+ if not force and ONLY_RANGE_REGEX:match_str(cmdline) then
+ return {}
+ end
+
+ local _, parsed = pcall(function()
+ local target = cmdline
+ local s, e = COUNT_RANGE_REGEX:match_str(target)
+ if s and e then
+ target = target:sub(e + 1)
+ end
+ -- nvim_parse_cmd throw error when the cmdline contains range specifier.
+ return vim.api.nvim_parse_cmd(target, {}) or {}
+ end)
+ parsed = parsed or {}
+
+ -- Check ignore cmd.
+ if vim.tbl_contains(option.ignore_cmds, parsed.cmd) then
+ return {}
+ end
+
+ -- Cleanup modifiers.
+ -- We can just remove modifiers because modifiers is always separated by space.
+ if arglead ~= cmdline then
+ while true do
+ local s, e = MODIFIER_REGEX:match_str(cmdline)
+ if s == nil then
+ break
+ end
+ cmdline = string.sub(cmdline, e + 1)
+ end
+ end
+
+ -- Support `lua vim.treesitter._get|` or `'<,'>del|` completion.
+ -- In this case, the `vim.fn.getcompletion` will return only `get_query` for `vim.treesitter.get_|`.
+ -- We should detect `vim.treesitter.` and `get_query` separately.
+ -- TODO: The `\h\w*` was choosed by huristic. We should consider more suitable detection.
+ local fixed_input
+ do
+ local suffix_pos = vim.regex([[\h\w*$]]):match_str(arglead)
+ fixed_input = string.sub(arglead, 1, suffix_pos or #arglead)
+ end
+
+ -- The `vim.fn.getcompletion` does not return `*no*cursorline` option.
+ -- cmp-cmdline corrects `no` prefix for option name.
+ local is_option_name_completion = OPTION_NAME_COMPLETION_REGEX:match_str(cmdline) ~= nil
+
+ --- create items.
+ local items = {}
+ local escaped = cmdline:gsub([[\\]], [[\\\\]]);
+ for _, word_or_item in ipairs(vim.fn.getcompletion(escaped, 'cmdline')) do
+ local word = type(word_or_item) == 'string' and word_or_item or word_or_item.word
+ local item = { label = word }
+ table.insert(items, item)
+ if is_option_name_completion and is_boolean_option(word) then
+ table.insert(items, vim.tbl_deep_extend('force', {}, item, {
+ label = 'no' .. word,
+ filterText = word,
+ }))
+ end
+ end
+
+ -- fix label with `fixed_input`
+ for _, item in ipairs(items) do
+ if not string.find(item.label, fixed_input, 1, true) then
+ item.label = fixed_input .. item.label
+ end
+ end
+
+ -- fix trailing slash for path like item
+ if option.treat_trailing_slash then
+ for _, item in ipairs(items) do
+ local is_target = string.match(item.label, [[/$]])
+ is_target = is_target and not (string.match(item.label, [[~/$]]))
+ is_target = is_target and not (string.match(item.label, [[%./$]]))
+ is_target = is_target and not (string.match(item.label, [[%.%./$]]))
+ if is_target then
+ item.label = item.label:sub(1, -2)
+ end
+ end
+ end
+ return items
+ end
+ },
+}
+
+local source = {}
+
+source.new = function()
+ return setmetatable({
+ before_line = '',
+ offset = -1,
+ ctype = '',
+ items = {},
+ }, { __index = source })
+end
+
+source.get_keyword_pattern = function()
+ return [=[[^[:blank:]]*]=]
+end
+
+source.get_trigger_characters = function()
+ return { ' ', '.', '#', '-' }
+end
+
+source.complete = function(self, params, callback)
+ local offset = 0
+ local ctype = ''
+ local items = {}
+ local kind
+ local isIncomplete = false
+ for _, def in ipairs(definitions) do
+ local s, e = vim.regex(def.regex):match_str(params.context.cursor_before_line)
+ if s and e then
+ offset = s
+ ctype = def.ctype
+ items = def.exec(
+ vim.tbl_deep_extend('keep', params.option or {}, DEFAULT_OPTION),
+ string.sub(params.context.cursor_before_line, s + 1),
+ params.context.cursor_before_line,
+ params.context:get_reason() == cmp.ContextReason.Manual
+ )
+ kind = def.kind
+ isIncomplete = def.isIncomplete
+ if not (#items == 0 and def.fallback) then
+ break
+ end
+ end
+ end
+
+ local labels = {}
+ for _, item in ipairs(items) do
+ item.kind = kind
+ labels[item.label] = true
+ end
+
+ -- `vim.fn.getcompletion` does not handle fuzzy matches. So, we must return all items, including items that were matched in the previous input.
+ local should_merge_previous_items = false
+ if #params.context.cursor_before_line > #self.before_line then
+ should_merge_previous_items = string.find(params.context.cursor_before_line, self.before_line, 1, true) == 1
+ elseif #params.context.cursor_before_line < #self.before_line then
+ should_merge_previous_items = string.find(self.before_line, params.context.cursor_before_line, 1, true) == 1
+ end
+
+ if should_merge_previous_items and self.offset == offset and self.ctype == ctype then
+ for _, item in ipairs(self.items) do
+ if not labels[item.label] then
+ table.insert(items, item)
+ end
+ end
+ end
+ self.before_line = params.context.cursor_before_line
+ self.offset = offset
+ self.ctype = ctype
+ self.items = items
+
+ callback({
+ isIncomplete = isIncomplete,
+ items = items,
+ })
+end
+
+return source
diff --git a/config/neovim/store/lazy-plugins/cmp-emoji/README.md b/config/neovim/store/lazy-plugins/cmp-emoji/README.md
new file mode 100644
index 00000000..853f0370
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-emoji/README.md
@@ -0,0 +1,22 @@
+# cmp-emoji
+
+nvim-cmp source for emojis.
+
+# Setup
+
+```lua
+require'cmp'.setup {
+ sources = {
+ { name = 'emoji' }
+ }
+}
+```
+
+# Option
+
+#### insert (type: boolean)
+
+Speficy emoji should be insert or not.
+
+Default: `false`
+
diff --git a/config/neovim/store/lazy-plugins/cmp-emoji/after/plugin/cmp_emoji.lua b/config/neovim/store/lazy-plugins/cmp-emoji/after/plugin/cmp_emoji.lua
new file mode 100644
index 00000000..ca2fa187
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-emoji/after/plugin/cmp_emoji.lua
@@ -0,0 +1,2 @@
+require'cmp'.register_source('emoji', require'cmp_emoji'.new())
+
diff --git a/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/emoji.json b/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/emoji.json
new file mode 100755
index 00000000..cab15c80
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/emoji.json
@@ -0,0 +1 @@
+[{"name":"HASH KEY","unified":"0023-FE0F-20E3","non_qualified":"0023-20E3","docomo":"E6E0","au":"EB84","softbank":"E210","google":"FE82C","image":"0023-fe0f-20e3.png","sheet_x":0,"sheet_y":0,"short_name":"hash","short_names":["hash"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1549,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP: *","unified":"002A-FE0F-20E3","non_qualified":"002A-20E3","docomo":null,"au":null,"softbank":null,"google":null,"image":"002a-fe0f-20e3.png","sheet_x":0,"sheet_y":1,"short_name":"keycap_star","short_names":["keycap_star"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1550,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 0","unified":"0030-FE0F-20E3","non_qualified":"0030-20E3","docomo":"E6EB","au":"E5AC","softbank":"E225","google":"FE837","image":"0030-fe0f-20e3.png","sheet_x":0,"sheet_y":2,"short_name":"zero","short_names":["zero"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1551,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 1","unified":"0031-FE0F-20E3","non_qualified":"0031-20E3","docomo":"E6E2","au":"E522","softbank":"E21C","google":"FE82E","image":"0031-fe0f-20e3.png","sheet_x":0,"sheet_y":3,"short_name":"one","short_names":["one"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1552,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 2","unified":"0032-FE0F-20E3","non_qualified":"0032-20E3","docomo":"E6E3","au":"E523","softbank":"E21D","google":"FE82F","image":"0032-fe0f-20e3.png","sheet_x":0,"sheet_y":4,"short_name":"two","short_names":["two"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1553,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 3","unified":"0033-FE0F-20E3","non_qualified":"0033-20E3","docomo":"E6E4","au":"E524","softbank":"E21E","google":"FE830","image":"0033-fe0f-20e3.png","sheet_x":0,"sheet_y":5,"short_name":"three","short_names":["three"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1554,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 4","unified":"0034-FE0F-20E3","non_qualified":"0034-20E3","docomo":"E6E5","au":"E525","softbank":"E21F","google":"FE831","image":"0034-fe0f-20e3.png","sheet_x":0,"sheet_y":6,"short_name":"four","short_names":["four"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1555,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 5","unified":"0035-FE0F-20E3","non_qualified":"0035-20E3","docomo":"E6E6","au":"E526","softbank":"E220","google":"FE832","image":"0035-fe0f-20e3.png","sheet_x":0,"sheet_y":7,"short_name":"five","short_names":["five"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1556,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 6","unified":"0036-FE0F-20E3","non_qualified":"0036-20E3","docomo":"E6E7","au":"E527","softbank":"E221","google":"FE833","image":"0036-fe0f-20e3.png","sheet_x":0,"sheet_y":8,"short_name":"six","short_names":["six"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1557,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 7","unified":"0037-FE0F-20E3","non_qualified":"0037-20E3","docomo":"E6E8","au":"E528","softbank":"E222","google":"FE834","image":"0037-fe0f-20e3.png","sheet_x":0,"sheet_y":9,"short_name":"seven","short_names":["seven"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1558,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 8","unified":"0038-FE0F-20E3","non_qualified":"0038-20E3","docomo":"E6E9","au":"E529","softbank":"E223","google":"FE835","image":"0038-fe0f-20e3.png","sheet_x":0,"sheet_y":10,"short_name":"eight","short_names":["eight"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1559,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"KEYCAP 9","unified":"0039-FE0F-20E3","non_qualified":"0039-20E3","docomo":"E6EA","au":"E52A","softbank":"E224","google":"FE836","image":"0039-fe0f-20e3.png","sheet_x":0,"sheet_y":11,"short_name":"nine","short_names":["nine"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1560,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"COPYRIGHT SIGN","unified":"00A9-FE0F","non_qualified":"00A9","docomo":"E731","au":"E558","softbank":"E24E","google":"FEB29","image":"00a9-fe0f.png","sheet_x":0,"sheet_y":12,"short_name":"copyright","short_names":["copyright"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1546,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"REGISTERED SIGN","unified":"00AE-FE0F","non_qualified":"00AE","docomo":"E736","au":"E559","softbank":"E24F","google":"FEB2D","image":"00ae-fe0f.png","sheet_x":0,"sheet_y":13,"short_name":"registered","short_names":["registered"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1547,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"MAHJONG TILE RED DRAGON","unified":"1F004","non_qualified":null,"docomo":null,"au":"E5D1","softbank":"E12D","google":"FE80B","image":"1f004.png","sheet_x":0,"sheet_y":14,"short_name":"mahjong","short_names":["mahjong"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1141,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PLAYING CARD BLACK JOKER","unified":"1F0CF","non_qualified":null,"docomo":null,"au":"EB6F","softbank":null,"google":"FE812","image":"1f0cf.png","sheet_x":0,"sheet_y":15,"short_name":"black_joker","short_names":["black_joker"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1140,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEGATIVE SQUARED LATIN CAPITAL LETTER A","unified":"1F170-FE0F","non_qualified":"1F170","docomo":null,"au":"EB26","softbank":"E532","google":"FE50B","image":"1f170-fe0f.png","sheet_x":0,"sheet_y":16,"short_name":"a","short_names":["a"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1567,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEGATIVE SQUARED LATIN CAPITAL LETTER B","unified":"1F171-FE0F","non_qualified":"1F171","docomo":null,"au":"EB27","softbank":"E533","google":"FE50C","image":"1f171-fe0f.png","sheet_x":0,"sheet_y":17,"short_name":"b","short_names":["b"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1569,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEGATIVE SQUARED LATIN CAPITAL LETTER O","unified":"1F17E-FE0F","non_qualified":"1F17E","docomo":null,"au":"EB28","softbank":"E535","google":"FE50E","image":"1f17e-fe0f.png","sheet_x":0,"sheet_y":18,"short_name":"o2","short_names":["o2"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1578,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEGATIVE SQUARED LATIN CAPITAL LETTER P","unified":"1F17F-FE0F","non_qualified":"1F17F","docomo":"E66C","au":"E4A6","softbank":"E14F","google":"FE7F6","image":"1f17f-fe0f.png","sheet_x":0,"sheet_y":19,"short_name":"parking","short_names":["parking"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1580,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEGATIVE SQUARED AB","unified":"1F18E","non_qualified":null,"docomo":null,"au":"EB29","softbank":"E534","google":"FE50D","image":"1f18e.png","sheet_x":0,"sheet_y":20,"short_name":"ab","short_names":["ab"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1568,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CL","unified":"1F191","non_qualified":null,"docomo":"E6DB","au":"E5AB","softbank":null,"google":"FEB84","image":"1f191.png","sheet_x":0,"sheet_y":21,"short_name":"cl","short_names":["cl"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1570,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED COOL","unified":"1F192","non_qualified":null,"docomo":null,"au":"EA85","softbank":"E214","google":"FEB38","image":"1f192.png","sheet_x":0,"sheet_y":22,"short_name":"cool","short_names":["cool"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1571,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED FREE","unified":"1F193","non_qualified":null,"docomo":"E6D7","au":"E578","softbank":null,"google":"FEB21","image":"1f193.png","sheet_x":0,"sheet_y":23,"short_name":"free","short_names":["free"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1572,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED ID","unified":"1F194","non_qualified":null,"docomo":"E6D8","au":"EA88","softbank":"E229","google":"FEB81","image":"1f194.png","sheet_x":0,"sheet_y":24,"short_name":"id","short_names":["id"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1574,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED NEW","unified":"1F195","non_qualified":null,"docomo":"E6DD","au":"E5B5","softbank":"E212","google":"FEB36","image":"1f195.png","sheet_x":0,"sheet_y":25,"short_name":"new","short_names":["new"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1576,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED NG","unified":"1F196","non_qualified":null,"docomo":"E72F","au":null,"softbank":null,"google":"FEB28","image":"1f196.png","sheet_x":0,"sheet_y":26,"short_name":"ng","short_names":["ng"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1577,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED OK","unified":"1F197","non_qualified":null,"docomo":"E70B","au":"E5AD","softbank":"E24D","google":"FEB27","image":"1f197.png","sheet_x":0,"sheet_y":27,"short_name":"ok","short_names":["ok"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1579,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED SOS","unified":"1F198","non_qualified":null,"docomo":null,"au":"E4E8","softbank":null,"google":"FEB4F","image":"1f198.png","sheet_x":0,"sheet_y":28,"short_name":"sos","short_names":["sos"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1581,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED UP WITH EXCLAMATION MARK","unified":"1F199","non_qualified":null,"docomo":null,"au":"E50F","softbank":"E213","google":"FEB37","image":"1f199.png","sheet_x":0,"sheet_y":29,"short_name":"up","short_names":["up"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1582,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED VS","unified":"1F19A","non_qualified":null,"docomo":null,"au":"E5D2","softbank":"E12E","google":"FEB32","image":"1f19a.png","sheet_x":0,"sheet_y":30,"short_name":"vs","short_names":["vs"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1583,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Ascension Island Flag","unified":"1F1E6-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1e8.png","sheet_x":0,"sheet_y":31,"short_name":"flag-ac","short_names":["flag-ac"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1643,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Andorra Flag","unified":"1F1E6-1F1E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1e9.png","sheet_x":0,"sheet_y":32,"short_name":"flag-ad","short_names":["flag-ad"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1644,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"United Arab Emirates Flag","unified":"1F1E6-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1ea.png","sheet_x":0,"sheet_y":33,"short_name":"flag-ae","short_names":["flag-ae"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1645,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Afghanistan Flag","unified":"1F1E6-1F1EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1eb.png","sheet_x":0,"sheet_y":34,"short_name":"flag-af","short_names":["flag-af"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1646,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Antigua & Barbuda Flag","unified":"1F1E6-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1ec.png","sheet_x":0,"sheet_y":35,"short_name":"flag-ag","short_names":["flag-ag"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1647,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Anguilla Flag","unified":"1F1E6-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1ee.png","sheet_x":0,"sheet_y":36,"short_name":"flag-ai","short_names":["flag-ai"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1648,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Albania Flag","unified":"1F1E6-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1f1.png","sheet_x":0,"sheet_y":37,"short_name":"flag-al","short_names":["flag-al"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1649,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Armenia Flag","unified":"1F1E6-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1f2.png","sheet_x":0,"sheet_y":38,"short_name":"flag-am","short_names":["flag-am"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1650,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Angola Flag","unified":"1F1E6-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1f4.png","sheet_x":0,"sheet_y":39,"short_name":"flag-ao","short_names":["flag-ao"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1651,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Antarctica Flag","unified":"1F1E6-1F1F6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1f6.png","sheet_x":0,"sheet_y":40,"short_name":"flag-aq","short_names":["flag-aq"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1652,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Argentina Flag","unified":"1F1E6-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1f7.png","sheet_x":0,"sheet_y":41,"short_name":"flag-ar","short_names":["flag-ar"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1653,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"American Samoa Flag","unified":"1F1E6-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1f8.png","sheet_x":0,"sheet_y":42,"short_name":"flag-as","short_names":["flag-as"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1654,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Austria Flag","unified":"1F1E6-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1f9.png","sheet_x":0,"sheet_y":43,"short_name":"flag-at","short_names":["flag-at"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1655,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Australia Flag","unified":"1F1E6-1F1FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1fa.png","sheet_x":0,"sheet_y":44,"short_name":"flag-au","short_names":["flag-au"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1656,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Aruba Flag","unified":"1F1E6-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1fc.png","sheet_x":0,"sheet_y":45,"short_name":"flag-aw","short_names":["flag-aw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1657,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"\u00c5land Islands Flag","unified":"1F1E6-1F1FD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1fd.png","sheet_x":0,"sheet_y":46,"short_name":"flag-ax","short_names":["flag-ax"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1658,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Azerbaijan Flag","unified":"1F1E6-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e6-1f1ff.png","sheet_x":0,"sheet_y":47,"short_name":"flag-az","short_names":["flag-az"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1659,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Bosnia & Herzegovina Flag","unified":"1F1E7-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1e6.png","sheet_x":0,"sheet_y":48,"short_name":"flag-ba","short_names":["flag-ba"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1660,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Barbados Flag","unified":"1F1E7-1F1E7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1e7.png","sheet_x":0,"sheet_y":49,"short_name":"flag-bb","short_names":["flag-bb"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1661,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Bangladesh Flag","unified":"1F1E7-1F1E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1e9.png","sheet_x":0,"sheet_y":50,"short_name":"flag-bd","short_names":["flag-bd"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1662,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Belgium Flag","unified":"1F1E7-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1ea.png","sheet_x":0,"sheet_y":51,"short_name":"flag-be","short_names":["flag-be"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1663,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Burkina Faso Flag","unified":"1F1E7-1F1EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1eb.png","sheet_x":0,"sheet_y":52,"short_name":"flag-bf","short_names":["flag-bf"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1664,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Bulgaria Flag","unified":"1F1E7-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1ec.png","sheet_x":0,"sheet_y":53,"short_name":"flag-bg","short_names":["flag-bg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1665,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Bahrain Flag","unified":"1F1E7-1F1ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1ed.png","sheet_x":0,"sheet_y":54,"short_name":"flag-bh","short_names":["flag-bh"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1666,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Burundi Flag","unified":"1F1E7-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1ee.png","sheet_x":0,"sheet_y":55,"short_name":"flag-bi","short_names":["flag-bi"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1667,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Benin Flag","unified":"1F1E7-1F1EF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1ef.png","sheet_x":0,"sheet_y":56,"short_name":"flag-bj","short_names":["flag-bj"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1668,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"St. Barth\u00e9lemy Flag","unified":"1F1E7-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1f1.png","sheet_x":0,"sheet_y":57,"short_name":"flag-bl","short_names":["flag-bl"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1669,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Bermuda Flag","unified":"1F1E7-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1f2.png","sheet_x":0,"sheet_y":58,"short_name":"flag-bm","short_names":["flag-bm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1670,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Brunei Flag","unified":"1F1E7-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1f3.png","sheet_x":0,"sheet_y":59,"short_name":"flag-bn","short_names":["flag-bn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1671,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Bolivia Flag","unified":"1F1E7-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1f4.png","sheet_x":0,"sheet_y":60,"short_name":"flag-bo","short_names":["flag-bo"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1672,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Caribbean Netherlands Flag","unified":"1F1E7-1F1F6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1f6.png","sheet_x":0,"sheet_y":61,"short_name":"flag-bq","short_names":["flag-bq"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1673,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Brazil Flag","unified":"1F1E7-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1f7.png","sheet_x":1,"sheet_y":0,"short_name":"flag-br","short_names":["flag-br"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1674,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Bahamas Flag","unified":"1F1E7-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1f8.png","sheet_x":1,"sheet_y":1,"short_name":"flag-bs","short_names":["flag-bs"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1675,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Bhutan Flag","unified":"1F1E7-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1f9.png","sheet_x":1,"sheet_y":2,"short_name":"flag-bt","short_names":["flag-bt"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1676,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Bouvet Island Flag","unified":"1F1E7-1F1FB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1fb.png","sheet_x":1,"sheet_y":3,"short_name":"flag-bv","short_names":["flag-bv"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1677,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Botswana Flag","unified":"1F1E7-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1fc.png","sheet_x":1,"sheet_y":4,"short_name":"flag-bw","short_names":["flag-bw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1678,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Belarus Flag","unified":"1F1E7-1F1FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1fe.png","sheet_x":1,"sheet_y":5,"short_name":"flag-by","short_names":["flag-by"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1679,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Belize Flag","unified":"1F1E7-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e7-1f1ff.png","sheet_x":1,"sheet_y":6,"short_name":"flag-bz","short_names":["flag-bz"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1680,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Canada Flag","unified":"1F1E8-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1e6.png","sheet_x":1,"sheet_y":7,"short_name":"flag-ca","short_names":["flag-ca"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1681,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Cocos (Keeling) Islands Flag","unified":"1F1E8-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1e8.png","sheet_x":1,"sheet_y":8,"short_name":"flag-cc","short_names":["flag-cc"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1682,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Congo - Kinshasa Flag","unified":"1F1E8-1F1E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1e9.png","sheet_x":1,"sheet_y":9,"short_name":"flag-cd","short_names":["flag-cd"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1683,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Central African Republic Flag","unified":"1F1E8-1F1EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1eb.png","sheet_x":1,"sheet_y":10,"short_name":"flag-cf","short_names":["flag-cf"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1684,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Congo - Brazzaville Flag","unified":"1F1E8-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1ec.png","sheet_x":1,"sheet_y":11,"short_name":"flag-cg","short_names":["flag-cg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1685,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Switzerland Flag","unified":"1F1E8-1F1ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1ed.png","sheet_x":1,"sheet_y":12,"short_name":"flag-ch","short_names":["flag-ch"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1686,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"C\u00f4te d\u2019Ivoire Flag","unified":"1F1E8-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1ee.png","sheet_x":1,"sheet_y":13,"short_name":"flag-ci","short_names":["flag-ci"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1687,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Cook Islands Flag","unified":"1F1E8-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1f0.png","sheet_x":1,"sheet_y":14,"short_name":"flag-ck","short_names":["flag-ck"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1688,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Chile Flag","unified":"1F1E8-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1f1.png","sheet_x":1,"sheet_y":15,"short_name":"flag-cl","short_names":["flag-cl"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1689,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Cameroon Flag","unified":"1F1E8-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1f2.png","sheet_x":1,"sheet_y":16,"short_name":"flag-cm","short_names":["flag-cm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1690,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"China Flag","unified":"1F1E8-1F1F3","non_qualified":null,"docomo":null,"au":"EB11","softbank":"E513","google":"FE4ED","image":"1f1e8-1f1f3.png","sheet_x":1,"sheet_y":17,"short_name":"cn","short_names":["cn","flag-cn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1691,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Colombia Flag","unified":"1F1E8-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1f4.png","sheet_x":1,"sheet_y":18,"short_name":"flag-co","short_names":["flag-co"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1692,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Clipperton Island Flag","unified":"1F1E8-1F1F5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1f5.png","sheet_x":1,"sheet_y":19,"short_name":"flag-cp","short_names":["flag-cp"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1693,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Costa Rica Flag","unified":"1F1E8-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1f7.png","sheet_x":1,"sheet_y":20,"short_name":"flag-cr","short_names":["flag-cr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1694,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Cuba Flag","unified":"1F1E8-1F1FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1fa.png","sheet_x":1,"sheet_y":21,"short_name":"flag-cu","short_names":["flag-cu"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1695,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Cape Verde Flag","unified":"1F1E8-1F1FB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1fb.png","sheet_x":1,"sheet_y":22,"short_name":"flag-cv","short_names":["flag-cv"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1696,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Cura\u00e7ao Flag","unified":"1F1E8-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1fc.png","sheet_x":1,"sheet_y":23,"short_name":"flag-cw","short_names":["flag-cw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1697,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Christmas Island Flag","unified":"1F1E8-1F1FD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1fd.png","sheet_x":1,"sheet_y":24,"short_name":"flag-cx","short_names":["flag-cx"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1698,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Cyprus Flag","unified":"1F1E8-1F1FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1fe.png","sheet_x":1,"sheet_y":25,"short_name":"flag-cy","short_names":["flag-cy"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1699,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Czechia Flag","unified":"1F1E8-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e8-1f1ff.png","sheet_x":1,"sheet_y":26,"short_name":"flag-cz","short_names":["flag-cz"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1700,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Germany Flag","unified":"1F1E9-1F1EA","non_qualified":null,"docomo":null,"au":"EB0E","softbank":"E50E","google":"FE4E8","image":"1f1e9-1f1ea.png","sheet_x":1,"sheet_y":27,"short_name":"de","short_names":["de","flag-de"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1701,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Diego Garcia Flag","unified":"1F1E9-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e9-1f1ec.png","sheet_x":1,"sheet_y":28,"short_name":"flag-dg","short_names":["flag-dg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1702,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Djibouti Flag","unified":"1F1E9-1F1EF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e9-1f1ef.png","sheet_x":1,"sheet_y":29,"short_name":"flag-dj","short_names":["flag-dj"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1703,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Denmark Flag","unified":"1F1E9-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e9-1f1f0.png","sheet_x":1,"sheet_y":30,"short_name":"flag-dk","short_names":["flag-dk"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1704,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Dominica Flag","unified":"1F1E9-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e9-1f1f2.png","sheet_x":1,"sheet_y":31,"short_name":"flag-dm","short_names":["flag-dm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1705,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Dominican Republic Flag","unified":"1F1E9-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e9-1f1f4.png","sheet_x":1,"sheet_y":32,"short_name":"flag-do","short_names":["flag-do"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1706,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Algeria Flag","unified":"1F1E9-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1e9-1f1ff.png","sheet_x":1,"sheet_y":33,"short_name":"flag-dz","short_names":["flag-dz"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1707,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Ceuta & Melilla Flag","unified":"1F1EA-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ea-1f1e6.png","sheet_x":1,"sheet_y":34,"short_name":"flag-ea","short_names":["flag-ea"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1708,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Ecuador Flag","unified":"1F1EA-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ea-1f1e8.png","sheet_x":1,"sheet_y":35,"short_name":"flag-ec","short_names":["flag-ec"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1709,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Estonia Flag","unified":"1F1EA-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ea-1f1ea.png","sheet_x":1,"sheet_y":36,"short_name":"flag-ee","short_names":["flag-ee"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1710,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Egypt Flag","unified":"1F1EA-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ea-1f1ec.png","sheet_x":1,"sheet_y":37,"short_name":"flag-eg","short_names":["flag-eg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1711,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Western Sahara Flag","unified":"1F1EA-1F1ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ea-1f1ed.png","sheet_x":1,"sheet_y":38,"short_name":"flag-eh","short_names":["flag-eh"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1712,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Eritrea Flag","unified":"1F1EA-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ea-1f1f7.png","sheet_x":1,"sheet_y":39,"short_name":"flag-er","short_names":["flag-er"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1713,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Spain Flag","unified":"1F1EA-1F1F8","non_qualified":null,"docomo":null,"au":"E5D5","softbank":"E511","google":"FE4EB","image":"1f1ea-1f1f8.png","sheet_x":1,"sheet_y":40,"short_name":"es","short_names":["es","flag-es"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1714,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Ethiopia Flag","unified":"1F1EA-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ea-1f1f9.png","sheet_x":1,"sheet_y":41,"short_name":"flag-et","short_names":["flag-et"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1715,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"European Union Flag","unified":"1F1EA-1F1FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ea-1f1fa.png","sheet_x":1,"sheet_y":42,"short_name":"flag-eu","short_names":["flag-eu"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1716,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Finland Flag","unified":"1F1EB-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1eb-1f1ee.png","sheet_x":1,"sheet_y":43,"short_name":"flag-fi","short_names":["flag-fi"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1717,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Fiji Flag","unified":"1F1EB-1F1EF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1eb-1f1ef.png","sheet_x":1,"sheet_y":44,"short_name":"flag-fj","short_names":["flag-fj"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1718,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Falkland Islands Flag","unified":"1F1EB-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1eb-1f1f0.png","sheet_x":1,"sheet_y":45,"short_name":"flag-fk","short_names":["flag-fk"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1719,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Micronesia Flag","unified":"1F1EB-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1eb-1f1f2.png","sheet_x":1,"sheet_y":46,"short_name":"flag-fm","short_names":["flag-fm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1720,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Faroe Islands Flag","unified":"1F1EB-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1eb-1f1f4.png","sheet_x":1,"sheet_y":47,"short_name":"flag-fo","short_names":["flag-fo"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1721,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"France Flag","unified":"1F1EB-1F1F7","non_qualified":null,"docomo":null,"au":"EAFA","softbank":"E50D","google":"FE4E7","image":"1f1eb-1f1f7.png","sheet_x":1,"sheet_y":48,"short_name":"fr","short_names":["fr","flag-fr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1722,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Gabon Flag","unified":"1F1EC-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1e6.png","sheet_x":1,"sheet_y":49,"short_name":"flag-ga","short_names":["flag-ga"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1723,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"United Kingdom Flag","unified":"1F1EC-1F1E7","non_qualified":null,"docomo":null,"au":"EB10","softbank":"E510","google":"FE4EA","image":"1f1ec-1f1e7.png","sheet_x":1,"sheet_y":50,"short_name":"gb","short_names":["gb","uk","flag-gb"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1724,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Grenada Flag","unified":"1F1EC-1F1E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1e9.png","sheet_x":1,"sheet_y":51,"short_name":"flag-gd","short_names":["flag-gd"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1725,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Georgia Flag","unified":"1F1EC-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1ea.png","sheet_x":1,"sheet_y":52,"short_name":"flag-ge","short_names":["flag-ge"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1726,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"French Guiana Flag","unified":"1F1EC-1F1EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1eb.png","sheet_x":1,"sheet_y":53,"short_name":"flag-gf","short_names":["flag-gf"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1727,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Guernsey Flag","unified":"1F1EC-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1ec.png","sheet_x":1,"sheet_y":54,"short_name":"flag-gg","short_names":["flag-gg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1728,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Ghana Flag","unified":"1F1EC-1F1ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1ed.png","sheet_x":1,"sheet_y":55,"short_name":"flag-gh","short_names":["flag-gh"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1729,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Gibraltar Flag","unified":"1F1EC-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1ee.png","sheet_x":1,"sheet_y":56,"short_name":"flag-gi","short_names":["flag-gi"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1730,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Greenland Flag","unified":"1F1EC-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1f1.png","sheet_x":1,"sheet_y":57,"short_name":"flag-gl","short_names":["flag-gl"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1731,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Gambia Flag","unified":"1F1EC-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1f2.png","sheet_x":1,"sheet_y":58,"short_name":"flag-gm","short_names":["flag-gm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1732,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Guinea Flag","unified":"1F1EC-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1f3.png","sheet_x":1,"sheet_y":59,"short_name":"flag-gn","short_names":["flag-gn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1733,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Guadeloupe Flag","unified":"1F1EC-1F1F5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1f5.png","sheet_x":1,"sheet_y":60,"short_name":"flag-gp","short_names":["flag-gp"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1734,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Equatorial Guinea Flag","unified":"1F1EC-1F1F6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1f6.png","sheet_x":1,"sheet_y":61,"short_name":"flag-gq","short_names":["flag-gq"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1735,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Greece Flag","unified":"1F1EC-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1f7.png","sheet_x":2,"sheet_y":0,"short_name":"flag-gr","short_names":["flag-gr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1736,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"South Georgia & South Sandwich Islands Flag","unified":"1F1EC-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1f8.png","sheet_x":2,"sheet_y":1,"short_name":"flag-gs","short_names":["flag-gs"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1737,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Guatemala Flag","unified":"1F1EC-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1f9.png","sheet_x":2,"sheet_y":2,"short_name":"flag-gt","short_names":["flag-gt"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1738,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Guam Flag","unified":"1F1EC-1F1FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1fa.png","sheet_x":2,"sheet_y":3,"short_name":"flag-gu","short_names":["flag-gu"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1739,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Guinea-Bissau Flag","unified":"1F1EC-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1fc.png","sheet_x":2,"sheet_y":4,"short_name":"flag-gw","short_names":["flag-gw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1740,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Guyana Flag","unified":"1F1EC-1F1FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ec-1f1fe.png","sheet_x":2,"sheet_y":5,"short_name":"flag-gy","short_names":["flag-gy"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1741,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Hong Kong SAR China Flag","unified":"1F1ED-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ed-1f1f0.png","sheet_x":2,"sheet_y":6,"short_name":"flag-hk","short_names":["flag-hk"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1742,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Heard & McDonald Islands Flag","unified":"1F1ED-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ed-1f1f2.png","sheet_x":2,"sheet_y":7,"short_name":"flag-hm","short_names":["flag-hm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1743,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Honduras Flag","unified":"1F1ED-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ed-1f1f3.png","sheet_x":2,"sheet_y":8,"short_name":"flag-hn","short_names":["flag-hn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1744,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Croatia Flag","unified":"1F1ED-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ed-1f1f7.png","sheet_x":2,"sheet_y":9,"short_name":"flag-hr","short_names":["flag-hr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1745,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Haiti Flag","unified":"1F1ED-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ed-1f1f9.png","sheet_x":2,"sheet_y":10,"short_name":"flag-ht","short_names":["flag-ht"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1746,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Hungary Flag","unified":"1F1ED-1F1FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ed-1f1fa.png","sheet_x":2,"sheet_y":11,"short_name":"flag-hu","short_names":["flag-hu"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1747,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Canary Islands Flag","unified":"1F1EE-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1e8.png","sheet_x":2,"sheet_y":12,"short_name":"flag-ic","short_names":["flag-ic"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1748,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Indonesia Flag","unified":"1F1EE-1F1E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1e9.png","sheet_x":2,"sheet_y":13,"short_name":"flag-id","short_names":["flag-id"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1749,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Ireland Flag","unified":"1F1EE-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1ea.png","sheet_x":2,"sheet_y":14,"short_name":"flag-ie","short_names":["flag-ie"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1750,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Israel Flag","unified":"1F1EE-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1f1.png","sheet_x":2,"sheet_y":15,"short_name":"flag-il","short_names":["flag-il"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1751,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Isle of Man Flag","unified":"1F1EE-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1f2.png","sheet_x":2,"sheet_y":16,"short_name":"flag-im","short_names":["flag-im"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1752,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"India Flag","unified":"1F1EE-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1f3.png","sheet_x":2,"sheet_y":17,"short_name":"flag-in","short_names":["flag-in"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1753,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"British Indian Ocean Territory Flag","unified":"1F1EE-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1f4.png","sheet_x":2,"sheet_y":18,"short_name":"flag-io","short_names":["flag-io"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1754,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Iraq Flag","unified":"1F1EE-1F1F6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1f6.png","sheet_x":2,"sheet_y":19,"short_name":"flag-iq","short_names":["flag-iq"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1755,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Iran Flag","unified":"1F1EE-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1f7.png","sheet_x":2,"sheet_y":20,"short_name":"flag-ir","short_names":["flag-ir"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1756,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Iceland Flag","unified":"1F1EE-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ee-1f1f8.png","sheet_x":2,"sheet_y":21,"short_name":"flag-is","short_names":["flag-is"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1757,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Italy Flag","unified":"1F1EE-1F1F9","non_qualified":null,"docomo":null,"au":"EB0F","softbank":"E50F","google":"FE4E9","image":"1f1ee-1f1f9.png","sheet_x":2,"sheet_y":22,"short_name":"it","short_names":["it","flag-it"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1758,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Jersey Flag","unified":"1F1EF-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ef-1f1ea.png","sheet_x":2,"sheet_y":23,"short_name":"flag-je","short_names":["flag-je"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1759,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Jamaica Flag","unified":"1F1EF-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ef-1f1f2.png","sheet_x":2,"sheet_y":24,"short_name":"flag-jm","short_names":["flag-jm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1760,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Jordan Flag","unified":"1F1EF-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ef-1f1f4.png","sheet_x":2,"sheet_y":25,"short_name":"flag-jo","short_names":["flag-jo"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1761,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Japan Flag","unified":"1F1EF-1F1F5","non_qualified":null,"docomo":null,"au":"E4CC","softbank":"E50B","google":"FE4E5","image":"1f1ef-1f1f5.png","sheet_x":2,"sheet_y":26,"short_name":"jp","short_names":["jp","flag-jp"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1762,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Kenya Flag","unified":"1F1F0-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1ea.png","sheet_x":2,"sheet_y":27,"short_name":"flag-ke","short_names":["flag-ke"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1763,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Kyrgyzstan Flag","unified":"1F1F0-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1ec.png","sheet_x":2,"sheet_y":28,"short_name":"flag-kg","short_names":["flag-kg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1764,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Cambodia Flag","unified":"1F1F0-1F1ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1ed.png","sheet_x":2,"sheet_y":29,"short_name":"flag-kh","short_names":["flag-kh"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1765,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Kiribati Flag","unified":"1F1F0-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1ee.png","sheet_x":2,"sheet_y":30,"short_name":"flag-ki","short_names":["flag-ki"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1766,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Comoros Flag","unified":"1F1F0-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1f2.png","sheet_x":2,"sheet_y":31,"short_name":"flag-km","short_names":["flag-km"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1767,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"St. Kitts & Nevis Flag","unified":"1F1F0-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1f3.png","sheet_x":2,"sheet_y":32,"short_name":"flag-kn","short_names":["flag-kn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1768,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"North Korea Flag","unified":"1F1F0-1F1F5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1f5.png","sheet_x":2,"sheet_y":33,"short_name":"flag-kp","short_names":["flag-kp"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1769,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"South Korea Flag","unified":"1F1F0-1F1F7","non_qualified":null,"docomo":null,"au":"EB12","softbank":"E514","google":"FE4EE","image":"1f1f0-1f1f7.png","sheet_x":2,"sheet_y":34,"short_name":"kr","short_names":["kr","flag-kr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1770,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Kuwait Flag","unified":"1F1F0-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1fc.png","sheet_x":2,"sheet_y":35,"short_name":"flag-kw","short_names":["flag-kw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1771,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Cayman Islands Flag","unified":"1F1F0-1F1FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1fe.png","sheet_x":2,"sheet_y":36,"short_name":"flag-ky","short_names":["flag-ky"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1772,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Kazakhstan Flag","unified":"1F1F0-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f0-1f1ff.png","sheet_x":2,"sheet_y":37,"short_name":"flag-kz","short_names":["flag-kz"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1773,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Laos Flag","unified":"1F1F1-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1e6.png","sheet_x":2,"sheet_y":38,"short_name":"flag-la","short_names":["flag-la"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1774,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Lebanon Flag","unified":"1F1F1-1F1E7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1e7.png","sheet_x":2,"sheet_y":39,"short_name":"flag-lb","short_names":["flag-lb"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1775,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"St. Lucia Flag","unified":"1F1F1-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1e8.png","sheet_x":2,"sheet_y":40,"short_name":"flag-lc","short_names":["flag-lc"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1776,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Liechtenstein Flag","unified":"1F1F1-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1ee.png","sheet_x":2,"sheet_y":41,"short_name":"flag-li","short_names":["flag-li"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1777,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Sri Lanka Flag","unified":"1F1F1-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1f0.png","sheet_x":2,"sheet_y":42,"short_name":"flag-lk","short_names":["flag-lk"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1778,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Liberia Flag","unified":"1F1F1-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1f7.png","sheet_x":2,"sheet_y":43,"short_name":"flag-lr","short_names":["flag-lr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1779,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Lesotho Flag","unified":"1F1F1-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1f8.png","sheet_x":2,"sheet_y":44,"short_name":"flag-ls","short_names":["flag-ls"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1780,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Lithuania Flag","unified":"1F1F1-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1f9.png","sheet_x":2,"sheet_y":45,"short_name":"flag-lt","short_names":["flag-lt"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1781,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Luxembourg Flag","unified":"1F1F1-1F1FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1fa.png","sheet_x":2,"sheet_y":46,"short_name":"flag-lu","short_names":["flag-lu"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1782,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Latvia Flag","unified":"1F1F1-1F1FB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1fb.png","sheet_x":2,"sheet_y":47,"short_name":"flag-lv","short_names":["flag-lv"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1783,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Libya Flag","unified":"1F1F1-1F1FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f1-1f1fe.png","sheet_x":2,"sheet_y":48,"short_name":"flag-ly","short_names":["flag-ly"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1784,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Morocco Flag","unified":"1F1F2-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1e6.png","sheet_x":2,"sheet_y":49,"short_name":"flag-ma","short_names":["flag-ma"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1785,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Monaco Flag","unified":"1F1F2-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1e8.png","sheet_x":2,"sheet_y":50,"short_name":"flag-mc","short_names":["flag-mc"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1786,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Moldova Flag","unified":"1F1F2-1F1E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1e9.png","sheet_x":2,"sheet_y":51,"short_name":"flag-md","short_names":["flag-md"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1787,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Montenegro Flag","unified":"1F1F2-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1ea.png","sheet_x":2,"sheet_y":52,"short_name":"flag-me","short_names":["flag-me"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1788,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"St. Martin Flag","unified":"1F1F2-1F1EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1eb.png","sheet_x":2,"sheet_y":53,"short_name":"flag-mf","short_names":["flag-mf"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1789,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Madagascar Flag","unified":"1F1F2-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1ec.png","sheet_x":2,"sheet_y":54,"short_name":"flag-mg","short_names":["flag-mg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1790,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Marshall Islands Flag","unified":"1F1F2-1F1ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1ed.png","sheet_x":2,"sheet_y":55,"short_name":"flag-mh","short_names":["flag-mh"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1791,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"North Macedonia Flag","unified":"1F1F2-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f0.png","sheet_x":2,"sheet_y":56,"short_name":"flag-mk","short_names":["flag-mk"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1792,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Mali Flag","unified":"1F1F2-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f1.png","sheet_x":2,"sheet_y":57,"short_name":"flag-ml","short_names":["flag-ml"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1793,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Myanmar (Burma) Flag","unified":"1F1F2-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f2.png","sheet_x":2,"sheet_y":58,"short_name":"flag-mm","short_names":["flag-mm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1794,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Mongolia Flag","unified":"1F1F2-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f3.png","sheet_x":2,"sheet_y":59,"short_name":"flag-mn","short_names":["flag-mn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1795,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Macao SAR China Flag","unified":"1F1F2-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f4.png","sheet_x":2,"sheet_y":60,"short_name":"flag-mo","short_names":["flag-mo"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1796,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Northern Mariana Islands Flag","unified":"1F1F2-1F1F5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f5.png","sheet_x":2,"sheet_y":61,"short_name":"flag-mp","short_names":["flag-mp"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1797,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Martinique Flag","unified":"1F1F2-1F1F6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f6.png","sheet_x":3,"sheet_y":0,"short_name":"flag-mq","short_names":["flag-mq"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1798,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Mauritania Flag","unified":"1F1F2-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f7.png","sheet_x":3,"sheet_y":1,"short_name":"flag-mr","short_names":["flag-mr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1799,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Montserrat Flag","unified":"1F1F2-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f8.png","sheet_x":3,"sheet_y":2,"short_name":"flag-ms","short_names":["flag-ms"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1800,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Malta Flag","unified":"1F1F2-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1f9.png","sheet_x":3,"sheet_y":3,"short_name":"flag-mt","short_names":["flag-mt"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1801,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Mauritius Flag","unified":"1F1F2-1F1FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1fa.png","sheet_x":3,"sheet_y":4,"short_name":"flag-mu","short_names":["flag-mu"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1802,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Maldives Flag","unified":"1F1F2-1F1FB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1fb.png","sheet_x":3,"sheet_y":5,"short_name":"flag-mv","short_names":["flag-mv"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1803,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Malawi Flag","unified":"1F1F2-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1fc.png","sheet_x":3,"sheet_y":6,"short_name":"flag-mw","short_names":["flag-mw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1804,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Mexico Flag","unified":"1F1F2-1F1FD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1fd.png","sheet_x":3,"sheet_y":7,"short_name":"flag-mx","short_names":["flag-mx"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1805,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Malaysia Flag","unified":"1F1F2-1F1FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1fe.png","sheet_x":3,"sheet_y":8,"short_name":"flag-my","short_names":["flag-my"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1806,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Mozambique Flag","unified":"1F1F2-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f2-1f1ff.png","sheet_x":3,"sheet_y":9,"short_name":"flag-mz","short_names":["flag-mz"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1807,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Namibia Flag","unified":"1F1F3-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1e6.png","sheet_x":3,"sheet_y":10,"short_name":"flag-na","short_names":["flag-na"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1808,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"New Caledonia Flag","unified":"1F1F3-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1e8.png","sheet_x":3,"sheet_y":11,"short_name":"flag-nc","short_names":["flag-nc"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1809,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Niger Flag","unified":"1F1F3-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1ea.png","sheet_x":3,"sheet_y":12,"short_name":"flag-ne","short_names":["flag-ne"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1810,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Norfolk Island Flag","unified":"1F1F3-1F1EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1eb.png","sheet_x":3,"sheet_y":13,"short_name":"flag-nf","short_names":["flag-nf"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1811,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Nigeria Flag","unified":"1F1F3-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1ec.png","sheet_x":3,"sheet_y":14,"short_name":"flag-ng","short_names":["flag-ng"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1812,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Nicaragua Flag","unified":"1F1F3-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1ee.png","sheet_x":3,"sheet_y":15,"short_name":"flag-ni","short_names":["flag-ni"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1813,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Netherlands Flag","unified":"1F1F3-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1f1.png","sheet_x":3,"sheet_y":16,"short_name":"flag-nl","short_names":["flag-nl"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1814,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Norway Flag","unified":"1F1F3-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1f4.png","sheet_x":3,"sheet_y":17,"short_name":"flag-no","short_names":["flag-no"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1815,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Nepal Flag","unified":"1F1F3-1F1F5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1f5.png","sheet_x":3,"sheet_y":18,"short_name":"flag-np","short_names":["flag-np"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1816,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Nauru Flag","unified":"1F1F3-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1f7.png","sheet_x":3,"sheet_y":19,"short_name":"flag-nr","short_names":["flag-nr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1817,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Niue Flag","unified":"1F1F3-1F1FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1fa.png","sheet_x":3,"sheet_y":20,"short_name":"flag-nu","short_names":["flag-nu"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1818,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"New Zealand Flag","unified":"1F1F3-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f3-1f1ff.png","sheet_x":3,"sheet_y":21,"short_name":"flag-nz","short_names":["flag-nz"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1819,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Oman Flag","unified":"1F1F4-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f4-1f1f2.png","sheet_x":3,"sheet_y":22,"short_name":"flag-om","short_names":["flag-om"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1820,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Panama Flag","unified":"1F1F5-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1e6.png","sheet_x":3,"sheet_y":23,"short_name":"flag-pa","short_names":["flag-pa"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1821,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Peru Flag","unified":"1F1F5-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1ea.png","sheet_x":3,"sheet_y":24,"short_name":"flag-pe","short_names":["flag-pe"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1822,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"French Polynesia Flag","unified":"1F1F5-1F1EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1eb.png","sheet_x":3,"sheet_y":25,"short_name":"flag-pf","short_names":["flag-pf"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1823,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Papua New Guinea Flag","unified":"1F1F5-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1ec.png","sheet_x":3,"sheet_y":26,"short_name":"flag-pg","short_names":["flag-pg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1824,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Philippines Flag","unified":"1F1F5-1F1ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1ed.png","sheet_x":3,"sheet_y":27,"short_name":"flag-ph","short_names":["flag-ph"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1825,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Pakistan Flag","unified":"1F1F5-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1f0.png","sheet_x":3,"sheet_y":28,"short_name":"flag-pk","short_names":["flag-pk"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1826,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Poland Flag","unified":"1F1F5-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1f1.png","sheet_x":3,"sheet_y":29,"short_name":"flag-pl","short_names":["flag-pl"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1827,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"St. Pierre & Miquelon Flag","unified":"1F1F5-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1f2.png","sheet_x":3,"sheet_y":30,"short_name":"flag-pm","short_names":["flag-pm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1828,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Pitcairn Islands Flag","unified":"1F1F5-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1f3.png","sheet_x":3,"sheet_y":31,"short_name":"flag-pn","short_names":["flag-pn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1829,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Puerto Rico Flag","unified":"1F1F5-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1f7.png","sheet_x":3,"sheet_y":32,"short_name":"flag-pr","short_names":["flag-pr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1830,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Palestinian Territories Flag","unified":"1F1F5-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1f8.png","sheet_x":3,"sheet_y":33,"short_name":"flag-ps","short_names":["flag-ps"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1831,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Portugal Flag","unified":"1F1F5-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1f9.png","sheet_x":3,"sheet_y":34,"short_name":"flag-pt","short_names":["flag-pt"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1832,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Palau Flag","unified":"1F1F5-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1fc.png","sheet_x":3,"sheet_y":35,"short_name":"flag-pw","short_names":["flag-pw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1833,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Paraguay Flag","unified":"1F1F5-1F1FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f5-1f1fe.png","sheet_x":3,"sheet_y":36,"short_name":"flag-py","short_names":["flag-py"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1834,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Qatar Flag","unified":"1F1F6-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f6-1f1e6.png","sheet_x":3,"sheet_y":37,"short_name":"flag-qa","short_names":["flag-qa"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1835,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"R\u00e9union Flag","unified":"1F1F7-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f7-1f1ea.png","sheet_x":3,"sheet_y":38,"short_name":"flag-re","short_names":["flag-re"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1836,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Romania Flag","unified":"1F1F7-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f7-1f1f4.png","sheet_x":3,"sheet_y":39,"short_name":"flag-ro","short_names":["flag-ro"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1837,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Serbia Flag","unified":"1F1F7-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f7-1f1f8.png","sheet_x":3,"sheet_y":40,"short_name":"flag-rs","short_names":["flag-rs"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1838,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Russia Flag","unified":"1F1F7-1F1FA","non_qualified":null,"docomo":null,"au":"E5D6","softbank":"E512","google":"FE4EC","image":"1f1f7-1f1fa.png","sheet_x":3,"sheet_y":41,"short_name":"ru","short_names":["ru","flag-ru"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1839,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Rwanda Flag","unified":"1F1F7-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f7-1f1fc.png","sheet_x":3,"sheet_y":42,"short_name":"flag-rw","short_names":["flag-rw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1840,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Saudi Arabia Flag","unified":"1F1F8-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1e6.png","sheet_x":3,"sheet_y":43,"short_name":"flag-sa","short_names":["flag-sa"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1841,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Solomon Islands Flag","unified":"1F1F8-1F1E7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1e7.png","sheet_x":3,"sheet_y":44,"short_name":"flag-sb","short_names":["flag-sb"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1842,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Seychelles Flag","unified":"1F1F8-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1e8.png","sheet_x":3,"sheet_y":45,"short_name":"flag-sc","short_names":["flag-sc"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1843,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Sudan Flag","unified":"1F1F8-1F1E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1e9.png","sheet_x":3,"sheet_y":46,"short_name":"flag-sd","short_names":["flag-sd"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1844,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Sweden Flag","unified":"1F1F8-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1ea.png","sheet_x":3,"sheet_y":47,"short_name":"flag-se","short_names":["flag-se"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1845,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Singapore Flag","unified":"1F1F8-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1ec.png","sheet_x":3,"sheet_y":48,"short_name":"flag-sg","short_names":["flag-sg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1846,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"St. Helena Flag","unified":"1F1F8-1F1ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1ed.png","sheet_x":3,"sheet_y":49,"short_name":"flag-sh","short_names":["flag-sh"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1847,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Slovenia Flag","unified":"1F1F8-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1ee.png","sheet_x":3,"sheet_y":50,"short_name":"flag-si","short_names":["flag-si"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1848,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Svalbard & Jan Mayen Flag","unified":"1F1F8-1F1EF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1ef.png","sheet_x":3,"sheet_y":51,"short_name":"flag-sj","short_names":["flag-sj"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1849,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Slovakia Flag","unified":"1F1F8-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1f0.png","sheet_x":3,"sheet_y":52,"short_name":"flag-sk","short_names":["flag-sk"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1850,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Sierra Leone Flag","unified":"1F1F8-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1f1.png","sheet_x":3,"sheet_y":53,"short_name":"flag-sl","short_names":["flag-sl"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1851,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"San Marino Flag","unified":"1F1F8-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1f2.png","sheet_x":3,"sheet_y":54,"short_name":"flag-sm","short_names":["flag-sm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1852,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Senegal Flag","unified":"1F1F8-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1f3.png","sheet_x":3,"sheet_y":55,"short_name":"flag-sn","short_names":["flag-sn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1853,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Somalia Flag","unified":"1F1F8-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1f4.png","sheet_x":3,"sheet_y":56,"short_name":"flag-so","short_names":["flag-so"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1854,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Suriname Flag","unified":"1F1F8-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1f7.png","sheet_x":3,"sheet_y":57,"short_name":"flag-sr","short_names":["flag-sr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1855,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"South Sudan Flag","unified":"1F1F8-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1f8.png","sheet_x":3,"sheet_y":58,"short_name":"flag-ss","short_names":["flag-ss"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1856,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"S\u00e3o Tom\u00e9 & Pr\u00edncipe Flag","unified":"1F1F8-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1f9.png","sheet_x":3,"sheet_y":59,"short_name":"flag-st","short_names":["flag-st"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1857,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"El Salvador Flag","unified":"1F1F8-1F1FB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1fb.png","sheet_x":3,"sheet_y":60,"short_name":"flag-sv","short_names":["flag-sv"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1858,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Sint Maarten Flag","unified":"1F1F8-1F1FD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1fd.png","sheet_x":3,"sheet_y":61,"short_name":"flag-sx","short_names":["flag-sx"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1859,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Syria Flag","unified":"1F1F8-1F1FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1fe.png","sheet_x":4,"sheet_y":0,"short_name":"flag-sy","short_names":["flag-sy"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1860,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Eswatini Flag","unified":"1F1F8-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f8-1f1ff.png","sheet_x":4,"sheet_y":1,"short_name":"flag-sz","short_names":["flag-sz"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1861,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Tristan da Cunha Flag","unified":"1F1F9-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1e6.png","sheet_x":4,"sheet_y":2,"short_name":"flag-ta","short_names":["flag-ta"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1862,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Turks & Caicos Islands Flag","unified":"1F1F9-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1e8.png","sheet_x":4,"sheet_y":3,"short_name":"flag-tc","short_names":["flag-tc"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1863,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Chad Flag","unified":"1F1F9-1F1E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1e9.png","sheet_x":4,"sheet_y":4,"short_name":"flag-td","short_names":["flag-td"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1864,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"French Southern Territories Flag","unified":"1F1F9-1F1EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1eb.png","sheet_x":4,"sheet_y":5,"short_name":"flag-tf","short_names":["flag-tf"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1865,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Togo Flag","unified":"1F1F9-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1ec.png","sheet_x":4,"sheet_y":6,"short_name":"flag-tg","short_names":["flag-tg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1866,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Thailand Flag","unified":"1F1F9-1F1ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1ed.png","sheet_x":4,"sheet_y":7,"short_name":"flag-th","short_names":["flag-th"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1867,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Tajikistan Flag","unified":"1F1F9-1F1EF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1ef.png","sheet_x":4,"sheet_y":8,"short_name":"flag-tj","short_names":["flag-tj"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1868,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Tokelau Flag","unified":"1F1F9-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1f0.png","sheet_x":4,"sheet_y":9,"short_name":"flag-tk","short_names":["flag-tk"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1869,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Timor-Leste Flag","unified":"1F1F9-1F1F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1f1.png","sheet_x":4,"sheet_y":10,"short_name":"flag-tl","short_names":["flag-tl"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1870,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Turkmenistan Flag","unified":"1F1F9-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1f2.png","sheet_x":4,"sheet_y":11,"short_name":"flag-tm","short_names":["flag-tm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1871,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Tunisia Flag","unified":"1F1F9-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1f3.png","sheet_x":4,"sheet_y":12,"short_name":"flag-tn","short_names":["flag-tn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1872,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Tonga Flag","unified":"1F1F9-1F1F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1f4.png","sheet_x":4,"sheet_y":13,"short_name":"flag-to","short_names":["flag-to"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1873,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"T\u00fcrkiye Flag","unified":"1F1F9-1F1F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1f7.png","sheet_x":4,"sheet_y":14,"short_name":"flag-tr","short_names":["flag-tr"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1874,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Trinidad & Tobago Flag","unified":"1F1F9-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1f9.png","sheet_x":4,"sheet_y":15,"short_name":"flag-tt","short_names":["flag-tt"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1875,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Tuvalu Flag","unified":"1F1F9-1F1FB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1fb.png","sheet_x":4,"sheet_y":16,"short_name":"flag-tv","short_names":["flag-tv"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1876,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Taiwan Flag","unified":"1F1F9-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1fc.png","sheet_x":4,"sheet_y":17,"short_name":"flag-tw","short_names":["flag-tw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1877,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Tanzania Flag","unified":"1F1F9-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1f9-1f1ff.png","sheet_x":4,"sheet_y":18,"short_name":"flag-tz","short_names":["flag-tz"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1878,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Ukraine Flag","unified":"1F1FA-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fa-1f1e6.png","sheet_x":4,"sheet_y":19,"short_name":"flag-ua","short_names":["flag-ua"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1879,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Uganda Flag","unified":"1F1FA-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fa-1f1ec.png","sheet_x":4,"sheet_y":20,"short_name":"flag-ug","short_names":["flag-ug"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1880,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"U.S. Outlying Islands Flag","unified":"1F1FA-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fa-1f1f2.png","sheet_x":4,"sheet_y":21,"short_name":"flag-um","short_names":["flag-um"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1881,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"United Nations Flag","unified":"1F1FA-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fa-1f1f3.png","sheet_x":4,"sheet_y":22,"short_name":"flag-un","short_names":["flag-un"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1882,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"United States Flag","unified":"1F1FA-1F1F8","non_qualified":null,"docomo":null,"au":"E573","softbank":"E50C","google":"FE4E6","image":"1f1fa-1f1f8.png","sheet_x":4,"sheet_y":23,"short_name":"us","short_names":["us","flag-us"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1883,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Uruguay Flag","unified":"1F1FA-1F1FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fa-1f1fe.png","sheet_x":4,"sheet_y":24,"short_name":"flag-uy","short_names":["flag-uy"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1884,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Uzbekistan Flag","unified":"1F1FA-1F1FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fa-1f1ff.png","sheet_x":4,"sheet_y":25,"short_name":"flag-uz","short_names":["flag-uz"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1885,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Vatican City Flag","unified":"1F1FB-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fb-1f1e6.png","sheet_x":4,"sheet_y":26,"short_name":"flag-va","short_names":["flag-va"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1886,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"St. Vincent & Grenadines Flag","unified":"1F1FB-1F1E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fb-1f1e8.png","sheet_x":4,"sheet_y":27,"short_name":"flag-vc","short_names":["flag-vc"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1887,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Venezuela Flag","unified":"1F1FB-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fb-1f1ea.png","sheet_x":4,"sheet_y":28,"short_name":"flag-ve","short_names":["flag-ve"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1888,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"British Virgin Islands Flag","unified":"1F1FB-1F1EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fb-1f1ec.png","sheet_x":4,"sheet_y":29,"short_name":"flag-vg","short_names":["flag-vg"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1889,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"U.S. Virgin Islands Flag","unified":"1F1FB-1F1EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fb-1f1ee.png","sheet_x":4,"sheet_y":30,"short_name":"flag-vi","short_names":["flag-vi"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1890,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Vietnam Flag","unified":"1F1FB-1F1F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fb-1f1f3.png","sheet_x":4,"sheet_y":31,"short_name":"flag-vn","short_names":["flag-vn"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1891,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Vanuatu Flag","unified":"1F1FB-1F1FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fb-1f1fa.png","sheet_x":4,"sheet_y":32,"short_name":"flag-vu","short_names":["flag-vu"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1892,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Wallis & Futuna Flag","unified":"1F1FC-1F1EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fc-1f1eb.png","sheet_x":4,"sheet_y":33,"short_name":"flag-wf","short_names":["flag-wf"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1893,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Samoa Flag","unified":"1F1FC-1F1F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fc-1f1f8.png","sheet_x":4,"sheet_y":34,"short_name":"flag-ws","short_names":["flag-ws"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1894,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Kosovo Flag","unified":"1F1FD-1F1F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fd-1f1f0.png","sheet_x":4,"sheet_y":35,"short_name":"flag-xk","short_names":["flag-xk"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1895,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Yemen Flag","unified":"1F1FE-1F1EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fe-1f1ea.png","sheet_x":4,"sheet_y":36,"short_name":"flag-ye","short_names":["flag-ye"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1896,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Mayotte Flag","unified":"1F1FE-1F1F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1fe-1f1f9.png","sheet_x":4,"sheet_y":37,"short_name":"flag-yt","short_names":["flag-yt"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1897,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"South Africa Flag","unified":"1F1FF-1F1E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ff-1f1e6.png","sheet_x":4,"sheet_y":38,"short_name":"flag-za","short_names":["flag-za"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1898,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Zambia Flag","unified":"1F1FF-1F1F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ff-1f1f2.png","sheet_x":4,"sheet_y":39,"short_name":"flag-zm","short_names":["flag-zm"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1899,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Zimbabwe Flag","unified":"1F1FF-1F1FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f1ff-1f1fc.png","sheet_x":4,"sheet_y":40,"short_name":"flag-zw","short_names":["flag-zw"],"text":null,"texts":null,"category":"Flags","subcategory":"country-flag","sort_order":1900,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED KATAKANA KOKO","unified":"1F201","non_qualified":null,"docomo":null,"au":null,"softbank":"E203","google":"FEB24","image":"1f201.png","sheet_x":4,"sheet_y":41,"short_name":"koko","short_names":["koko"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1584,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED KATAKANA SA","unified":"1F202-FE0F","non_qualified":"1F202","docomo":null,"au":"EA87","softbank":"E228","google":"FEB3F","image":"1f202-fe0f.png","sheet_x":4,"sheet_y":42,"short_name":"sa","short_names":["sa"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1585,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-7121","unified":"1F21A","non_qualified":null,"docomo":null,"au":null,"softbank":"E216","google":"FEB3A","image":"1f21a.png","sheet_x":4,"sheet_y":43,"short_name":"u7121","short_names":["u7121"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1591,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-6307","unified":"1F22F","non_qualified":null,"docomo":null,"au":"EA8B","softbank":"E22C","google":"FEB40","image":"1f22f.png","sheet_x":4,"sheet_y":44,"short_name":"u6307","short_names":["u6307"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1588,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-7981","unified":"1F232","non_qualified":null,"docomo":"E738","au":null,"softbank":null,"google":"FEB2E","image":"1f232.png","sheet_x":4,"sheet_y":45,"short_name":"u7981","short_names":["u7981"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1592,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-7A7A","unified":"1F233","non_qualified":null,"docomo":"E739","au":"EA8A","softbank":"E22B","google":"FEB2F","image":"1f233.png","sheet_x":4,"sheet_y":46,"short_name":"u7a7a","short_names":["u7a7a"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1596,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-5408","unified":"1F234","non_qualified":null,"docomo":"E73A","au":null,"softbank":null,"google":"FEB30","image":"1f234.png","sheet_x":4,"sheet_y":47,"short_name":"u5408","short_names":["u5408"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1595,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-6E80","unified":"1F235","non_qualified":null,"docomo":"E73B","au":"EA89","softbank":"E22A","google":"FEB31","image":"1f235.png","sheet_x":4,"sheet_y":48,"short_name":"u6e80","short_names":["u6e80"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1600,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-6709","unified":"1F236","non_qualified":null,"docomo":null,"au":null,"softbank":"E215","google":"FEB39","image":"1f236.png","sheet_x":4,"sheet_y":49,"short_name":"u6709","short_names":["u6709"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1587,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-6708","unified":"1F237-FE0F","non_qualified":"1F237","docomo":null,"au":null,"softbank":"E217","google":"FEB3B","image":"1f237-fe0f.png","sheet_x":4,"sheet_y":50,"short_name":"u6708","short_names":["u6708"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1586,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-7533","unified":"1F238","non_qualified":null,"docomo":null,"au":null,"softbank":"E218","google":"FEB3C","image":"1f238.png","sheet_x":4,"sheet_y":51,"short_name":"u7533","short_names":["u7533"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1594,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-5272","unified":"1F239","non_qualified":null,"docomo":null,"au":"EA86","softbank":"E227","google":"FEB3E","image":"1f239.png","sheet_x":4,"sheet_y":52,"short_name":"u5272","short_names":["u5272"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1590,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUARED CJK UNIFIED IDEOGRAPH-55B6","unified":"1F23A","non_qualified":null,"docomo":null,"au":"EA8C","softbank":"E22D","google":"FEB41","image":"1f23a.png","sheet_x":4,"sheet_y":53,"short_name":"u55b6","short_names":["u55b6"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1599,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CIRCLED IDEOGRAPH ADVANTAGE","unified":"1F250","non_qualified":null,"docomo":null,"au":"E4F7","softbank":"E226","google":"FEB3D","image":"1f250.png","sheet_x":4,"sheet_y":54,"short_name":"ideograph_advantage","short_names":["ideograph_advantage"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1589,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CIRCLED IDEOGRAPH ACCEPT","unified":"1F251","non_qualified":null,"docomo":null,"au":"EB01","softbank":null,"google":"FEB50","image":"1f251.png","sheet_x":4,"sheet_y":55,"short_name":"accept","short_names":["accept"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1593,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CYCLONE","unified":"1F300","non_qualified":null,"docomo":"E643","au":"E469","softbank":"E443","google":"FE005","image":"1f300.png","sheet_x":4,"sheet_y":56,"short_name":"cyclone","short_names":["cyclone"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1051,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FOGGY","unified":"1F301","non_qualified":null,"docomo":"E644","au":"E598","softbank":null,"google":"FE006","image":"1f301.png","sheet_x":4,"sheet_y":57,"short_name":"foggy","short_names":["foggy"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":898,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOSED UMBRELLA","unified":"1F302","non_qualified":null,"docomo":"E645","au":"EAE8","softbank":"E43C","google":"FE007","image":"1f302.png","sheet_x":4,"sheet_y":58,"short_name":"closed_umbrella","short_names":["closed_umbrella"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1053,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NIGHT WITH STARS","unified":"1F303","non_qualified":null,"docomo":"E6B3","au":"EAF1","softbank":"E44B","google":"FE008","image":"1f303.png","sheet_x":4,"sheet_y":59,"short_name":"night_with_stars","short_names":["night_with_stars"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":899,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUNRISE OVER MOUNTAINS","unified":"1F304","non_qualified":null,"docomo":"E63E","au":"EAF4","softbank":"E04D","google":"FE009","image":"1f304.png","sheet_x":4,"sheet_y":60,"short_name":"sunrise_over_mountains","short_names":["sunrise_over_mountains"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":901,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUNRISE","unified":"1F305","non_qualified":null,"docomo":"E63E","au":"EAF4","softbank":"E449","google":"FE00A","image":"1f305.png","sheet_x":4,"sheet_y":61,"short_name":"sunrise","short_names":["sunrise"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":902,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CITYSCAPE AT DUSK","unified":"1F306","non_qualified":null,"docomo":null,"au":"E5DA","softbank":"E146","google":"FE00B","image":"1f306.png","sheet_x":5,"sheet_y":0,"short_name":"city_sunset","short_names":["city_sunset"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":903,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUNSET OVER BUILDINGS","unified":"1F307","non_qualified":null,"docomo":"E63E","au":"E5DA","softbank":"E44A","google":"FE00C","image":"1f307.png","sheet_x":5,"sheet_y":1,"short_name":"city_sunrise","short_names":["city_sunrise"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":904,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RAINBOW","unified":"1F308","non_qualified":null,"docomo":null,"au":"EAF2","softbank":"E44C","google":"FE00D","image":"1f308.png","sheet_x":5,"sheet_y":2,"short_name":"rainbow","short_names":["rainbow"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1052,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BRIDGE AT NIGHT","unified":"1F309","non_qualified":null,"docomo":"E6B3","au":"E4BF","softbank":null,"google":"FE010","image":"1f309.png","sheet_x":5,"sheet_y":3,"short_name":"bridge_at_night","short_names":["bridge_at_night"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":905,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WATER WAVE","unified":"1F30A","non_qualified":null,"docomo":"E73F","au":"EB7C","softbank":"E43E","google":"FE038","image":"1f30a.png","sheet_x":5,"sheet_y":4,"short_name":"ocean","short_names":["ocean"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1064,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"VOLCANO","unified":"1F30B","non_qualified":null,"docomo":null,"au":"EB53","softbank":null,"google":"FE03A","image":"1f30b.png","sheet_x":5,"sheet_y":5,"short_name":"volcano","short_names":["volcano"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-geographic","sort_order":856,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MILKY WAY","unified":"1F30C","non_qualified":null,"docomo":"E6B3","au":"EB5F","softbank":null,"google":"FE03B","image":"1f30c.png","sheet_x":5,"sheet_y":6,"short_name":"milky_way","short_names":["milky_way"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1038,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EARTH GLOBE EUROPE-AFRICA","unified":"1F30D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f30d.png","sheet_x":5,"sheet_y":7,"short_name":"earth_africa","short_names":["earth_africa"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-map","sort_order":847,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EARTH GLOBE AMERICAS","unified":"1F30E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f30e.png","sheet_x":5,"sheet_y":8,"short_name":"earth_americas","short_names":["earth_americas"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-map","sort_order":848,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EARTH GLOBE ASIA-AUSTRALIA","unified":"1F30F","non_qualified":null,"docomo":null,"au":"E5B3","softbank":null,"google":"FE039","image":"1f30f.png","sheet_x":5,"sheet_y":9,"short_name":"earth_asia","short_names":["earth_asia"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-map","sort_order":849,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GLOBE WITH MERIDIANS","unified":"1F310","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f310.png","sheet_x":5,"sheet_y":10,"short_name":"globe_with_meridians","short_names":["globe_with_meridians"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-map","sort_order":850,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEW MOON SYMBOL","unified":"1F311","non_qualified":null,"docomo":"E69C","au":"E5A8","softbank":null,"google":"FE011","image":"1f311.png","sheet_x":5,"sheet_y":11,"short_name":"new_moon","short_names":["new_moon"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1018,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WAXING CRESCENT MOON SYMBOL","unified":"1F312","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f312.png","sheet_x":5,"sheet_y":12,"short_name":"waxing_crescent_moon","short_names":["waxing_crescent_moon"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1019,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FIRST QUARTER MOON SYMBOL","unified":"1F313","non_qualified":null,"docomo":"E69E","au":"E5AA","softbank":null,"google":"FE013","image":"1f313.png","sheet_x":5,"sheet_y":13,"short_name":"first_quarter_moon","short_names":["first_quarter_moon"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1020,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WAXING GIBBOUS MOON SYMBOL","unified":"1F314","non_qualified":null,"docomo":"E69D","au":"E5A9","softbank":null,"google":"FE012","image":"1f314.png","sheet_x":5,"sheet_y":14,"short_name":"moon","short_names":["moon","waxing_gibbous_moon"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1021,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FULL MOON SYMBOL","unified":"1F315","non_qualified":null,"docomo":"E6A0","au":null,"softbank":null,"google":"FE015","image":"1f315.png","sheet_x":5,"sheet_y":15,"short_name":"full_moon","short_names":["full_moon"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1022,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WANING GIBBOUS MOON SYMBOL","unified":"1F316","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f316.png","sheet_x":5,"sheet_y":16,"short_name":"waning_gibbous_moon","short_names":["waning_gibbous_moon"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1023,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LAST QUARTER MOON SYMBOL","unified":"1F317","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f317.png","sheet_x":5,"sheet_y":17,"short_name":"last_quarter_moon","short_names":["last_quarter_moon"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1024,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WANING CRESCENT MOON SYMBOL","unified":"1F318","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f318.png","sheet_x":5,"sheet_y":18,"short_name":"waning_crescent_moon","short_names":["waning_crescent_moon"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1025,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CRESCENT MOON","unified":"1F319","non_qualified":null,"docomo":"E69F","au":"E486","softbank":"E04C","google":"FE014","image":"1f319.png","sheet_x":5,"sheet_y":19,"short_name":"crescent_moon","short_names":["crescent_moon"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1026,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEW MOON WITH FACE","unified":"1F31A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f31a.png","sheet_x":5,"sheet_y":20,"short_name":"new_moon_with_face","short_names":["new_moon_with_face"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1027,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FIRST QUARTER MOON WITH FACE","unified":"1F31B","non_qualified":null,"docomo":"E69E","au":"E489","softbank":null,"google":"FE016","image":"1f31b.png","sheet_x":5,"sheet_y":21,"short_name":"first_quarter_moon_with_face","short_names":["first_quarter_moon_with_face"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1028,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LAST QUARTER MOON WITH FACE","unified":"1F31C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f31c.png","sheet_x":5,"sheet_y":22,"short_name":"last_quarter_moon_with_face","short_names":["last_quarter_moon_with_face"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1029,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FULL MOON WITH FACE","unified":"1F31D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f31d.png","sheet_x":5,"sheet_y":23,"short_name":"full_moon_with_face","short_names":["full_moon_with_face"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1032,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUN WITH FACE","unified":"1F31E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f31e.png","sheet_x":5,"sheet_y":24,"short_name":"sun_with_face","short_names":["sun_with_face"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1033,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GLOWING STAR","unified":"1F31F","non_qualified":null,"docomo":null,"au":"E48B","softbank":"E335","google":"FEB69","image":"1f31f.png","sheet_x":5,"sheet_y":25,"short_name":"star2","short_names":["star2"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1036,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHOOTING STAR","unified":"1F320","non_qualified":null,"docomo":null,"au":"E468","softbank":null,"google":"FEB6A","image":"1f320.png","sheet_x":5,"sheet_y":26,"short_name":"stars","short_names":["stars"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1037,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"THERMOMETER","unified":"1F321-FE0F","non_qualified":"1F321","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f321-fe0f.png","sheet_x":5,"sheet_y":27,"short_name":"thermometer","short_names":["thermometer"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1030,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUN BEHIND SMALL CLOUD","unified":"1F324-FE0F","non_qualified":"1F324","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f324-fe0f.png","sheet_x":5,"sheet_y":28,"short_name":"mostly_sunny","short_names":["mostly_sunny","sun_small_cloud"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1042,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUN BEHIND LARGE CLOUD","unified":"1F325-FE0F","non_qualified":"1F325","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f325-fe0f.png","sheet_x":5,"sheet_y":29,"short_name":"barely_sunny","short_names":["barely_sunny","sun_behind_cloud"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1043,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUN BEHIND RAIN CLOUD","unified":"1F326-FE0F","non_qualified":"1F326","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f326-fe0f.png","sheet_x":5,"sheet_y":30,"short_name":"partly_sunny_rain","short_names":["partly_sunny_rain","sun_behind_rain_cloud"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1044,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOUD WITH RAIN","unified":"1F327-FE0F","non_qualified":"1F327","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f327-fe0f.png","sheet_x":5,"sheet_y":31,"short_name":"rain_cloud","short_names":["rain_cloud"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1045,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOUD WITH SNOW","unified":"1F328-FE0F","non_qualified":"1F328","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f328-fe0f.png","sheet_x":5,"sheet_y":32,"short_name":"snow_cloud","short_names":["snow_cloud"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1046,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOUD WITH LIGHTNING","unified":"1F329-FE0F","non_qualified":"1F329","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f329-fe0f.png","sheet_x":5,"sheet_y":33,"short_name":"lightning","short_names":["lightning","lightning_cloud"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1047,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TORNADO","unified":"1F32A-FE0F","non_qualified":"1F32A","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f32a-fe0f.png","sheet_x":5,"sheet_y":34,"short_name":"tornado","short_names":["tornado","tornado_cloud"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1048,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FOG","unified":"1F32B-FE0F","non_qualified":"1F32B","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f32b-fe0f.png","sheet_x":5,"sheet_y":35,"short_name":"fog","short_names":["fog"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1049,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WIND FACE","unified":"1F32C-FE0F","non_qualified":"1F32C","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f32c-fe0f.png","sheet_x":5,"sheet_y":36,"short_name":"wind_blowing_face","short_names":["wind_blowing_face"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1050,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOT DOG","unified":"1F32D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f32d.png","sheet_x":5,"sheet_y":37,"short_name":"hotdog","short_names":["hotdog"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":766,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TACO","unified":"1F32E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f32e.png","sheet_x":5,"sheet_y":38,"short_name":"taco","short_names":["taco"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":768,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BURRITO","unified":"1F32F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f32f.png","sheet_x":5,"sheet_y":39,"short_name":"burrito","short_names":["burrito"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":769,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHESTNUT","unified":"1F330","non_qualified":null,"docomo":null,"au":"EB38","softbank":null,"google":"FE04C","image":"1f330.png","sheet_x":5,"sheet_y":40,"short_name":"chestnut","short_names":["chestnut"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":746,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SEEDLING","unified":"1F331","non_qualified":null,"docomo":"E746","au":"EB7D","softbank":null,"google":"FE03E","image":"1f331.png","sheet_x":5,"sheet_y":41,"short_name":"seedling","short_names":["seedling"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":696,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EVERGREEN TREE","unified":"1F332","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f332.png","sheet_x":5,"sheet_y":42,"short_name":"evergreen_tree","short_names":["evergreen_tree"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":698,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DECIDUOUS TREE","unified":"1F333","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f333.png","sheet_x":5,"sheet_y":43,"short_name":"deciduous_tree","short_names":["deciduous_tree"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":699,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PALM TREE","unified":"1F334","non_qualified":null,"docomo":null,"au":"E4E2","softbank":"E307","google":"FE047","image":"1f334.png","sheet_x":5,"sheet_y":44,"short_name":"palm_tree","short_names":["palm_tree"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":700,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CACTUS","unified":"1F335","non_qualified":null,"docomo":null,"au":"EA96","softbank":"E308","google":"FE048","image":"1f335.png","sheet_x":5,"sheet_y":45,"short_name":"cactus","short_names":["cactus"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":701,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOT PEPPER","unified":"1F336-FE0F","non_qualified":"1F336","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f336-fe0f.png","sheet_x":5,"sheet_y":46,"short_name":"hot_pepper","short_names":["hot_pepper"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":737,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TULIP","unified":"1F337","non_qualified":null,"docomo":"E743","au":"E4E4","softbank":"E304","google":"FE03D","image":"1f337.png","sheet_x":5,"sheet_y":47,"short_name":"tulip","short_names":["tulip"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":694,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHERRY BLOSSOM","unified":"1F338","non_qualified":null,"docomo":"E748","au":"E4CA","softbank":"E030","google":"FE040","image":"1f338.png","sheet_x":5,"sheet_y":48,"short_name":"cherry_blossom","short_names":["cherry_blossom"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":685,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROSE","unified":"1F339","non_qualified":null,"docomo":null,"au":"E5BA","softbank":"E032","google":"FE041","image":"1f339.png","sheet_x":5,"sheet_y":49,"short_name":"rose","short_names":["rose"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":689,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HIBISCUS","unified":"1F33A","non_qualified":null,"docomo":null,"au":"EA94","softbank":"E303","google":"FE045","image":"1f33a.png","sheet_x":5,"sheet_y":50,"short_name":"hibiscus","short_names":["hibiscus"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":691,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUNFLOWER","unified":"1F33B","non_qualified":null,"docomo":null,"au":"E4E3","softbank":"E305","google":"FE046","image":"1f33b.png","sheet_x":5,"sheet_y":51,"short_name":"sunflower","short_names":["sunflower"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":692,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLOSSOM","unified":"1F33C","non_qualified":null,"docomo":null,"au":"EB49","softbank":null,"google":"FE04D","image":"1f33c.png","sheet_x":5,"sheet_y":52,"short_name":"blossom","short_names":["blossom"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":693,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EAR OF MAIZE","unified":"1F33D","non_qualified":null,"docomo":null,"au":"EB36","softbank":null,"google":"FE04A","image":"1f33d.png","sheet_x":5,"sheet_y":53,"short_name":"corn","short_names":["corn"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":736,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EAR OF RICE","unified":"1F33E","non_qualified":null,"docomo":null,"au":null,"softbank":"E444","google":"FE049","image":"1f33e.png","sheet_x":5,"sheet_y":54,"short_name":"ear_of_rice","short_names":["ear_of_rice"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":702,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HERB","unified":"1F33F","non_qualified":null,"docomo":"E741","au":"EB82","softbank":null,"google":"FE04E","image":"1f33f.png","sheet_x":5,"sheet_y":55,"short_name":"herb","short_names":["herb"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":703,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FOUR LEAF CLOVER","unified":"1F340","non_qualified":null,"docomo":"E741","au":"E513","softbank":"E110","google":"FE03C","image":"1f340.png","sheet_x":5,"sheet_y":56,"short_name":"four_leaf_clover","short_names":["four_leaf_clover"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":705,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MAPLE LEAF","unified":"1F341","non_qualified":null,"docomo":"E747","au":"E4CE","softbank":"E118","google":"FE03F","image":"1f341.png","sheet_x":5,"sheet_y":57,"short_name":"maple_leaf","short_names":["maple_leaf"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":706,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FALLEN LEAF","unified":"1F342","non_qualified":null,"docomo":"E747","au":"E5CD","softbank":"E119","google":"FE042","image":"1f342.png","sheet_x":5,"sheet_y":58,"short_name":"fallen_leaf","short_names":["fallen_leaf"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":707,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEAF FLUTTERING IN WIND","unified":"1F343","non_qualified":null,"docomo":null,"au":"E5CD","softbank":"E447","google":"FE043","image":"1f343.png","sheet_x":5,"sheet_y":59,"short_name":"leaves","short_names":["leaves"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":708,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BROWN MUSHROOM","unified":"1F344-200D-1F7EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f344-200d-1f7eb.png","sheet_x":5,"sheet_y":60,"short_name":"brown_mushroom","short_names":["brown_mushroom"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":749,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"MUSHROOM","unified":"1F344","non_qualified":null,"docomo":null,"au":"EB37","softbank":null,"google":"FE04B","image":"1f344.png","sheet_x":5,"sheet_y":61,"short_name":"mushroom","short_names":["mushroom"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":711,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TOMATO","unified":"1F345","non_qualified":null,"docomo":null,"au":"EABB","softbank":"E349","google":"FE055","image":"1f345.png","sheet_x":6,"sheet_y":0,"short_name":"tomato","short_names":["tomato"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":729,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AUBERGINE","unified":"1F346","non_qualified":null,"docomo":null,"au":"EABC","softbank":"E34A","google":"FE056","image":"1f346.png","sheet_x":6,"sheet_y":1,"short_name":"eggplant","short_names":["eggplant"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":733,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GRAPES","unified":"1F347","non_qualified":null,"docomo":null,"au":"EB34","softbank":null,"google":"FE059","image":"1f347.png","sheet_x":6,"sheet_y":2,"short_name":"grapes","short_names":["grapes"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":712,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MELON","unified":"1F348","non_qualified":null,"docomo":null,"au":"EB32","softbank":null,"google":"FE057","image":"1f348.png","sheet_x":6,"sheet_y":3,"short_name":"melon","short_names":["melon"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":713,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WATERMELON","unified":"1F349","non_qualified":null,"docomo":null,"au":"E4CD","softbank":"E348","google":"FE054","image":"1f349.png","sheet_x":6,"sheet_y":4,"short_name":"watermelon","short_names":["watermelon"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":714,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TANGERINE","unified":"1F34A","non_qualified":null,"docomo":null,"au":"EABA","softbank":"E346","google":"FE052","image":"1f34a.png","sheet_x":6,"sheet_y":5,"short_name":"tangerine","short_names":["tangerine"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":715,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LIME","unified":"1F34B-200D-1F7E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f34b-200d-1f7e9.png","sheet_x":6,"sheet_y":6,"short_name":"lime","short_names":["lime"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":717,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"LEMON","unified":"1F34B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f34b.png","sheet_x":6,"sheet_y":7,"short_name":"lemon","short_names":["lemon"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":716,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BANANA","unified":"1F34C","non_qualified":null,"docomo":"E744","au":"EB35","softbank":null,"google":"FE050","image":"1f34c.png","sheet_x":6,"sheet_y":8,"short_name":"banana","short_names":["banana"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":718,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PINEAPPLE","unified":"1F34D","non_qualified":null,"docomo":null,"au":"EB33","softbank":null,"google":"FE058","image":"1f34d.png","sheet_x":6,"sheet_y":9,"short_name":"pineapple","short_names":["pineapple"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":719,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RED APPLE","unified":"1F34E","non_qualified":null,"docomo":"E745","au":"EAB9","softbank":"E345","google":"FE051","image":"1f34e.png","sheet_x":6,"sheet_y":10,"short_name":"apple","short_names":["apple"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":721,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GREEN APPLE","unified":"1F34F","non_qualified":null,"docomo":"E745","au":"EB5A","softbank":null,"google":"FE05B","image":"1f34f.png","sheet_x":6,"sheet_y":11,"short_name":"green_apple","short_names":["green_apple"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":722,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PEAR","unified":"1F350","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f350.png","sheet_x":6,"sheet_y":12,"short_name":"pear","short_names":["pear"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":723,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PEACH","unified":"1F351","non_qualified":null,"docomo":null,"au":"EB39","softbank":null,"google":"FE05A","image":"1f351.png","sheet_x":6,"sheet_y":13,"short_name":"peach","short_names":["peach"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":724,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHERRIES","unified":"1F352","non_qualified":null,"docomo":"E742","au":"E4D2","softbank":null,"google":"FE04F","image":"1f352.png","sheet_x":6,"sheet_y":14,"short_name":"cherries","short_names":["cherries"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":725,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STRAWBERRY","unified":"1F353","non_qualified":null,"docomo":null,"au":"E4D4","softbank":"E347","google":"FE053","image":"1f353.png","sheet_x":6,"sheet_y":15,"short_name":"strawberry","short_names":["strawberry"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":726,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HAMBURGER","unified":"1F354","non_qualified":null,"docomo":"E673","au":"E4D6","softbank":"E120","google":"FE960","image":"1f354.png","sheet_x":6,"sheet_y":16,"short_name":"hamburger","short_names":["hamburger"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":763,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SLICE OF PIZZA","unified":"1F355","non_qualified":null,"docomo":null,"au":"EB3B","softbank":null,"google":"FE975","image":"1f355.png","sheet_x":6,"sheet_y":17,"short_name":"pizza","short_names":["pizza"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":765,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MEAT ON BONE","unified":"1F356","non_qualified":null,"docomo":null,"au":"E4C4","softbank":null,"google":"FE972","image":"1f356.png","sheet_x":6,"sheet_y":18,"short_name":"meat_on_bone","short_names":["meat_on_bone"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":759,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POULTRY LEG","unified":"1F357","non_qualified":null,"docomo":null,"au":"EB3C","softbank":null,"google":"FE976","image":"1f357.png","sheet_x":6,"sheet_y":19,"short_name":"poultry_leg","short_names":["poultry_leg"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":760,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RICE CRACKER","unified":"1F358","non_qualified":null,"docomo":null,"au":"EAB3","softbank":"E33D","google":"FE969","image":"1f358.png","sheet_x":6,"sheet_y":20,"short_name":"rice_cracker","short_names":["rice_cracker"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":785,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RICE BALL","unified":"1F359","non_qualified":null,"docomo":"E749","au":"E4D5","softbank":"E342","google":"FE961","image":"1f359.png","sheet_x":6,"sheet_y":21,"short_name":"rice_ball","short_names":["rice_ball"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":786,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COOKED RICE","unified":"1F35A","non_qualified":null,"docomo":"E74C","au":"EAB4","softbank":"E33E","google":"FE96A","image":"1f35a.png","sheet_x":6,"sheet_y":22,"short_name":"rice","short_names":["rice"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":787,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CURRY AND RICE","unified":"1F35B","non_qualified":null,"docomo":null,"au":"EAB6","softbank":"E341","google":"FE96C","image":"1f35b.png","sheet_x":6,"sheet_y":23,"short_name":"curry","short_names":["curry"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":788,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STEAMING BOWL","unified":"1F35C","non_qualified":null,"docomo":"E74C","au":"E5B4","softbank":"E340","google":"FE963","image":"1f35c.png","sheet_x":6,"sheet_y":24,"short_name":"ramen","short_names":["ramen"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":789,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPAGHETTI","unified":"1F35D","non_qualified":null,"docomo":null,"au":"EAB5","softbank":"E33F","google":"FE96B","image":"1f35d.png","sheet_x":6,"sheet_y":25,"short_name":"spaghetti","short_names":["spaghetti"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":790,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BREAD","unified":"1F35E","non_qualified":null,"docomo":"E74D","au":"EAAF","softbank":"E339","google":"FE964","image":"1f35e.png","sheet_x":6,"sheet_y":26,"short_name":"bread","short_names":["bread"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":750,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FRENCH FRIES","unified":"1F35F","non_qualified":null,"docomo":null,"au":"EAB1","softbank":"E33B","google":"FE967","image":"1f35f.png","sheet_x":6,"sheet_y":27,"short_name":"fries","short_names":["fries"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":764,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROASTED SWEET POTATO","unified":"1F360","non_qualified":null,"docomo":null,"au":"EB3A","softbank":null,"google":"FE974","image":"1f360.png","sheet_x":6,"sheet_y":28,"short_name":"sweet_potato","short_names":["sweet_potato"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":791,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DANGO","unified":"1F361","non_qualified":null,"docomo":null,"au":"EAB2","softbank":"E33C","google":"FE968","image":"1f361.png","sheet_x":6,"sheet_y":29,"short_name":"dango","short_names":["dango"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":797,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ODEN","unified":"1F362","non_qualified":null,"docomo":null,"au":"EAB7","softbank":"E343","google":"FE96D","image":"1f362.png","sheet_x":6,"sheet_y":30,"short_name":"oden","short_names":["oden"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":792,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUSHI","unified":"1F363","non_qualified":null,"docomo":null,"au":"EAB8","softbank":"E344","google":"FE96E","image":"1f363.png","sheet_x":6,"sheet_y":31,"short_name":"sushi","short_names":["sushi"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":793,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FRIED SHRIMP","unified":"1F364","non_qualified":null,"docomo":null,"au":"EB70","softbank":null,"google":"FE97F","image":"1f364.png","sheet_x":6,"sheet_y":32,"short_name":"fried_shrimp","short_names":["fried_shrimp"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":794,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FISH CAKE WITH SWIRL DESIGN","unified":"1F365","non_qualified":null,"docomo":"E643","au":"E4ED","softbank":null,"google":"FE973","image":"1f365.png","sheet_x":6,"sheet_y":33,"short_name":"fish_cake","short_names":["fish_cake"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":795,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SOFT ICE CREAM","unified":"1F366","non_qualified":null,"docomo":null,"au":"EAB0","softbank":"E33A","google":"FE966","image":"1f366.png","sheet_x":6,"sheet_y":34,"short_name":"icecream","short_names":["icecream"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":806,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHAVED ICE","unified":"1F367","non_qualified":null,"docomo":null,"au":"EAEA","softbank":"E43F","google":"FE971","image":"1f367.png","sheet_x":6,"sheet_y":35,"short_name":"shaved_ice","short_names":["shaved_ice"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":807,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ICE CREAM","unified":"1F368","non_qualified":null,"docomo":null,"au":"EB4A","softbank":null,"google":"FE977","image":"1f368.png","sheet_x":6,"sheet_y":36,"short_name":"ice_cream","short_names":["ice_cream"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":808,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOUGHNUT","unified":"1F369","non_qualified":null,"docomo":null,"au":"EB4B","softbank":null,"google":"FE978","image":"1f369.png","sheet_x":6,"sheet_y":37,"short_name":"doughnut","short_names":["doughnut"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":809,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COOKIE","unified":"1F36A","non_qualified":null,"docomo":null,"au":"EB4C","softbank":null,"google":"FE979","image":"1f36a.png","sheet_x":6,"sheet_y":38,"short_name":"cookie","short_names":["cookie"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":810,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHOCOLATE BAR","unified":"1F36B","non_qualified":null,"docomo":null,"au":"EB4D","softbank":null,"google":"FE97A","image":"1f36b.png","sheet_x":6,"sheet_y":39,"short_name":"chocolate_bar","short_names":["chocolate_bar"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":815,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CANDY","unified":"1F36C","non_qualified":null,"docomo":null,"au":"EB4E","softbank":null,"google":"FE97B","image":"1f36c.png","sheet_x":6,"sheet_y":40,"short_name":"candy","short_names":["candy"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":816,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOLLIPOP","unified":"1F36D","non_qualified":null,"docomo":null,"au":"EB4F","softbank":null,"google":"FE97C","image":"1f36d.png","sheet_x":6,"sheet_y":41,"short_name":"lollipop","short_names":["lollipop"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":817,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CUSTARD","unified":"1F36E","non_qualified":null,"docomo":null,"au":"EB56","softbank":null,"google":"FE97D","image":"1f36e.png","sheet_x":6,"sheet_y":42,"short_name":"custard","short_names":["custard"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":818,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HONEY POT","unified":"1F36F","non_qualified":null,"docomo":null,"au":"EB59","softbank":null,"google":"FE97E","image":"1f36f.png","sheet_x":6,"sheet_y":43,"short_name":"honey_pot","short_names":["honey_pot"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":819,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHORTCAKE","unified":"1F370","non_qualified":null,"docomo":"E74A","au":"E4D0","softbank":"E046","google":"FE962","image":"1f370.png","sheet_x":6,"sheet_y":44,"short_name":"cake","short_names":["cake"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":812,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BENTO BOX","unified":"1F371","non_qualified":null,"docomo":null,"au":"EABD","softbank":"E34C","google":"FE96F","image":"1f371.png","sheet_x":6,"sheet_y":45,"short_name":"bento","short_names":["bento"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":784,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POT OF FOOD","unified":"1F372","non_qualified":null,"docomo":null,"au":"EABE","softbank":"E34D","google":"FE970","image":"1f372.png","sheet_x":6,"sheet_y":46,"short_name":"stew","short_names":["stew"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":776,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COOKING","unified":"1F373","non_qualified":null,"docomo":null,"au":"E4D1","softbank":"E147","google":"FE965","image":"1f373.png","sheet_x":6,"sheet_y":47,"short_name":"fried_egg","short_names":["fried_egg","cooking"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":774,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FORK AND KNIFE","unified":"1F374","non_qualified":null,"docomo":"E66F","au":"E4AC","softbank":"E043","google":"FE980","image":"1f374.png","sheet_x":6,"sheet_y":48,"short_name":"fork_and_knife","short_names":["fork_and_knife"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"dishware","sort_order":842,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TEACUP WITHOUT HANDLE","unified":"1F375","non_qualified":null,"docomo":"E71E","au":"EAAE","softbank":"E338","google":"FE984","image":"1f375.png","sheet_x":6,"sheet_y":49,"short_name":"tea","short_names":["tea"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":824,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SAKE BOTTLE AND CUP","unified":"1F376","non_qualified":null,"docomo":"E74B","au":"EA97","softbank":"E30B","google":"FE985","image":"1f376.png","sheet_x":6,"sheet_y":50,"short_name":"sake","short_names":["sake"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":825,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WINE GLASS","unified":"1F377","non_qualified":null,"docomo":"E756","au":"E4C1","softbank":null,"google":"FE986","image":"1f377.png","sheet_x":6,"sheet_y":51,"short_name":"wine_glass","short_names":["wine_glass"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":827,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COCKTAIL GLASS","unified":"1F378","non_qualified":null,"docomo":"E671","au":"E4C2","softbank":"E044","google":"FE982","image":"1f378.png","sheet_x":6,"sheet_y":52,"short_name":"cocktail","short_names":["cocktail"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":828,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TROPICAL DRINK","unified":"1F379","non_qualified":null,"docomo":"E671","au":"EB3E","softbank":null,"google":"FE988","image":"1f379.png","sheet_x":6,"sheet_y":53,"short_name":"tropical_drink","short_names":["tropical_drink"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":829,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BEER MUG","unified":"1F37A","non_qualified":null,"docomo":"E672","au":"E4C3","softbank":"E047","google":"FE983","image":"1f37a.png","sheet_x":6,"sheet_y":54,"short_name":"beer","short_names":["beer"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":830,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLINKING BEER MUGS","unified":"1F37B","non_qualified":null,"docomo":"E672","au":"EA98","softbank":"E30C","google":"FE987","image":"1f37b.png","sheet_x":6,"sheet_y":55,"short_name":"beers","short_names":["beers"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":831,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BABY BOTTLE","unified":"1F37C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f37c.png","sheet_x":6,"sheet_y":56,"short_name":"baby_bottle","short_names":["baby_bottle"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":820,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FORK AND KNIFE WITH PLATE","unified":"1F37D-FE0F","non_qualified":"1F37D","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f37d-fe0f.png","sheet_x":6,"sheet_y":57,"short_name":"knife_fork_plate","short_names":["knife_fork_plate"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"dishware","sort_order":841,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOTTLE WITH POPPING CORK","unified":"1F37E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f37e.png","sheet_x":6,"sheet_y":58,"short_name":"champagne","short_names":["champagne"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":826,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POPCORN","unified":"1F37F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f37f.png","sheet_x":6,"sheet_y":59,"short_name":"popcorn","short_names":["popcorn"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":780,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RIBBON","unified":"1F380","non_qualified":null,"docomo":"E684","au":"E59F","softbank":"E314","google":"FE50F","image":"1f380.png","sheet_x":6,"sheet_y":60,"short_name":"ribbon","short_names":["ribbon"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1081,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WRAPPED PRESENT","unified":"1F381","non_qualified":null,"docomo":"E685","au":"E4CF","softbank":"E112","google":"FE510","image":"1f381.png","sheet_x":6,"sheet_y":61,"short_name":"gift","short_names":["gift"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1082,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BIRTHDAY CAKE","unified":"1F382","non_qualified":null,"docomo":"E686","au":"E5A0","softbank":"E34B","google":"FE511","image":"1f382.png","sheet_x":7,"sheet_y":0,"short_name":"birthday","short_names":["birthday"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":811,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JACK-O-LANTERN","unified":"1F383","non_qualified":null,"docomo":null,"au":"EAEE","softbank":"E445","google":"FE51F","image":"1f383.png","sheet_x":7,"sheet_y":1,"short_name":"jack_o_lantern","short_names":["jack_o_lantern"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1065,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHRISTMAS TREE","unified":"1F384","non_qualified":null,"docomo":"E6A4","au":"E4C9","softbank":"E033","google":"FE512","image":"1f384.png","sheet_x":7,"sheet_y":2,"short_name":"christmas_tree","short_names":["christmas_tree"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1066,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FATHER CHRISTMAS","unified":"1F385","non_qualified":null,"docomo":null,"au":"EAF0","softbank":"E448","google":"FE513","image":"1f385.png","sheet_x":7,"sheet_y":3,"short_name":"santa","short_names":["santa"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":371,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F385-1F3FB","non_qualified":null,"image":"1f385-1f3fb.png","sheet_x":7,"sheet_y":4,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F385-1F3FC","non_qualified":null,"image":"1f385-1f3fc.png","sheet_x":7,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F385-1F3FD","non_qualified":null,"image":"1f385-1f3fd.png","sheet_x":7,"sheet_y":6,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F385-1F3FE","non_qualified":null,"image":"1f385-1f3fe.png","sheet_x":7,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F385-1F3FF","non_qualified":null,"image":"1f385-1f3ff.png","sheet_x":7,"sheet_y":8,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FIREWORKS","unified":"1F386","non_qualified":null,"docomo":null,"au":"E5CC","softbank":"E117","google":"FE515","image":"1f386.png","sheet_x":7,"sheet_y":9,"short_name":"fireworks","short_names":["fireworks"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1067,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FIREWORK SPARKLER","unified":"1F387","non_qualified":null,"docomo":null,"au":"EAEB","softbank":"E440","google":"FE51D","image":"1f387.png","sheet_x":7,"sheet_y":10,"short_name":"sparkler","short_names":["sparkler"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1068,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BALLOON","unified":"1F388","non_qualified":null,"docomo":null,"au":"EA9B","softbank":"E310","google":"FE516","image":"1f388.png","sheet_x":7,"sheet_y":11,"short_name":"balloon","short_names":["balloon"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1071,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PARTY POPPER","unified":"1F389","non_qualified":null,"docomo":null,"au":"EA9C","softbank":"E312","google":"FE517","image":"1f389.png","sheet_x":7,"sheet_y":12,"short_name":"tada","short_names":["tada"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1072,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CONFETTI BALL","unified":"1F38A","non_qualified":null,"docomo":null,"au":"E46F","softbank":null,"google":"FE520","image":"1f38a.png","sheet_x":7,"sheet_y":13,"short_name":"confetti_ball","short_names":["confetti_ball"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1073,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TANABATA TREE","unified":"1F38B","non_qualified":null,"docomo":null,"au":"EB3D","softbank":null,"google":"FE521","image":"1f38b.png","sheet_x":7,"sheet_y":14,"short_name":"tanabata_tree","short_names":["tanabata_tree"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1074,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CROSSED FLAGS","unified":"1F38C","non_qualified":null,"docomo":null,"au":"E5D9","softbank":"E143","google":"FE514","image":"1f38c.png","sheet_x":7,"sheet_y":15,"short_name":"crossed_flags","short_names":["crossed_flags"],"text":null,"texts":null,"category":"Flags","subcategory":"flag","sort_order":1637,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PINE DECORATION","unified":"1F38D","non_qualified":null,"docomo":null,"au":"EAE3","softbank":"E436","google":"FE518","image":"1f38d.png","sheet_x":7,"sheet_y":16,"short_name":"bamboo","short_names":["bamboo"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1075,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JAPANESE DOLLS","unified":"1F38E","non_qualified":null,"docomo":null,"au":"EAE4","softbank":"E438","google":"FE519","image":"1f38e.png","sheet_x":7,"sheet_y":17,"short_name":"dolls","short_names":["dolls"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1076,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CARP STREAMER","unified":"1F38F","non_qualified":null,"docomo":null,"au":"EAE7","softbank":"E43B","google":"FE51C","image":"1f38f.png","sheet_x":7,"sheet_y":18,"short_name":"flags","short_names":["flags"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1077,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WIND CHIME","unified":"1F390","non_qualified":null,"docomo":null,"au":"EAED","softbank":"E442","google":"FE51E","image":"1f390.png","sheet_x":7,"sheet_y":19,"short_name":"wind_chime","short_names":["wind_chime"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1078,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOON VIEWING CEREMONY","unified":"1F391","non_qualified":null,"docomo":null,"au":"EAEF","softbank":"E446","google":"FE017","image":"1f391.png","sheet_x":7,"sheet_y":20,"short_name":"rice_scene","short_names":["rice_scene"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1079,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SCHOOL SATCHEL","unified":"1F392","non_qualified":null,"docomo":null,"au":"EAE6","softbank":"E43A","google":"FE51B","image":"1f392.png","sheet_x":7,"sheet_y":21,"short_name":"school_satchel","short_names":["school_satchel"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1175,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GRADUATION CAP","unified":"1F393","non_qualified":null,"docomo":null,"au":"EAE5","softbank":"E439","google":"FE51A","image":"1f393.png","sheet_x":7,"sheet_y":22,"short_name":"mortar_board","short_names":["mortar_board"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1189,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MILITARY MEDAL","unified":"1F396-FE0F","non_qualified":"1F396","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f396-fe0f.png","sheet_x":7,"sheet_y":23,"short_name":"medal","short_names":["medal"],"text":null,"texts":null,"category":"Activities","subcategory":"award-medal","sort_order":1086,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"REMINDER RIBBON","unified":"1F397-FE0F","non_qualified":"1F397","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f397-fe0f.png","sheet_x":7,"sheet_y":24,"short_name":"reminder_ribbon","short_names":["reminder_ribbon"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1083,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STUDIO MICROPHONE","unified":"1F399-FE0F","non_qualified":"1F399","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f399-fe0f.png","sheet_x":7,"sheet_y":25,"short_name":"studio_microphone","short_names":["studio_microphone"],"text":null,"texts":null,"category":"Objects","subcategory":"music","sort_order":1209,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEVEL SLIDER","unified":"1F39A-FE0F","non_qualified":"1F39A","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f39a-fe0f.png","sheet_x":7,"sheet_y":26,"short_name":"level_slider","short_names":["level_slider"],"text":null,"texts":null,"category":"Objects","subcategory":"music","sort_order":1210,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CONTROL KNOBS","unified":"1F39B-FE0F","non_qualified":"1F39B","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f39b-fe0f.png","sheet_x":7,"sheet_y":27,"short_name":"control_knobs","short_names":["control_knobs"],"text":null,"texts":null,"category":"Objects","subcategory":"music","sort_order":1211,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FILM FRAMES","unified":"1F39E-FE0F","non_qualified":"1F39E","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f39e-fe0f.png","sheet_x":7,"sheet_y":28,"short_name":"film_frames","short_names":["film_frames"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1247,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ADMISSION TICKETS","unified":"1F39F-FE0F","non_qualified":"1F39F","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f39f-fe0f.png","sheet_x":7,"sheet_y":29,"short_name":"admission_tickets","short_names":["admission_tickets"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1084,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CAROUSEL HORSE","unified":"1F3A0","non_qualified":null,"docomo":"E679","au":null,"softbank":null,"google":"FE7FC","image":"1f3a0.png","sheet_x":7,"sheet_y":30,"short_name":"carousel_horse","short_names":["carousel_horse"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":907,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FERRIS WHEEL","unified":"1F3A1","non_qualified":null,"docomo":null,"au":"E46D","softbank":"E124","google":"FE7FD","image":"1f3a1.png","sheet_x":7,"sheet_y":31,"short_name":"ferris_wheel","short_names":["ferris_wheel"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":909,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROLLER COASTER","unified":"1F3A2","non_qualified":null,"docomo":null,"au":"EAE2","softbank":"E433","google":"FE7FE","image":"1f3a2.png","sheet_x":7,"sheet_y":32,"short_name":"roller_coaster","short_names":["roller_coaster"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":910,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FISHING POLE AND FISH","unified":"1F3A3","non_qualified":null,"docomo":"E751","au":"EB42","softbank":null,"google":"FE7FF","image":"1f3a3.png","sheet_x":7,"sheet_y":33,"short_name":"fishing_pole_and_fish","short_names":["fishing_pole_and_fish"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1113,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MICROPHONE","unified":"1F3A4","non_qualified":null,"docomo":"E676","au":"E503","softbank":"E03C","google":"FE800","image":"1f3a4.png","sheet_x":7,"sheet_y":34,"short_name":"microphone","short_names":["microphone"],"text":null,"texts":null,"category":"Objects","subcategory":"music","sort_order":1212,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOVIE CAMERA","unified":"1F3A5","non_qualified":null,"docomo":"E677","au":"E517","softbank":"E03D","google":"FE801","image":"1f3a5.png","sheet_x":7,"sheet_y":35,"short_name":"movie_camera","short_names":["movie_camera"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1246,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CINEMA","unified":"1F3A6","non_qualified":null,"docomo":"E677","au":"E517","softbank":"E507","google":"FE802","image":"1f3a6.png","sheet_x":7,"sheet_y":36,"short_name":"cinema","short_names":["cinema"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1503,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEADPHONE","unified":"1F3A7","non_qualified":null,"docomo":"E67A","au":"E508","softbank":"E30A","google":"FE803","image":"1f3a7.png","sheet_x":7,"sheet_y":37,"short_name":"headphones","short_names":["headphones"],"text":null,"texts":null,"category":"Objects","subcategory":"music","sort_order":1213,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ARTIST PALETTE","unified":"1F3A8","non_qualified":null,"docomo":"E67B","au":"E59C","softbank":"E502","google":"FE804","image":"1f3a8.png","sheet_x":7,"sheet_y":38,"short_name":"art","short_names":["art"],"text":null,"texts":null,"category":"Activities","subcategory":"arts & crafts","sort_order":1145,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TOP HAT","unified":"1F3A9","non_qualified":null,"docomo":"E67C","au":"EAF5","softbank":"E503","google":"FE805","image":"1f3a9.png","sheet_x":7,"sheet_y":39,"short_name":"tophat","short_names":["tophat"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1188,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CIRCUS TENT","unified":"1F3AA","non_qualified":null,"docomo":"E67D","au":"E59E","softbank":null,"google":"FE806","image":"1f3aa.png","sheet_x":7,"sheet_y":40,"short_name":"circus_tent","short_names":["circus_tent"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":912,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TICKET","unified":"1F3AB","non_qualified":null,"docomo":"E67E","au":"E49E","softbank":"E125","google":"FE807","image":"1f3ab.png","sheet_x":7,"sheet_y":41,"short_name":"ticket","short_names":["ticket"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1085,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLAPPER BOARD","unified":"1F3AC","non_qualified":null,"docomo":"E6AC","au":"E4BE","softbank":"E324","google":"FE808","image":"1f3ac.png","sheet_x":7,"sheet_y":42,"short_name":"clapper","short_names":["clapper"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1249,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PERFORMING ARTS","unified":"1F3AD","non_qualified":null,"docomo":null,"au":"E59D","softbank":null,"google":"FE809","image":"1f3ad.png","sheet_x":7,"sheet_y":43,"short_name":"performing_arts","short_names":["performing_arts"],"text":null,"texts":null,"category":"Activities","subcategory":"arts & crafts","sort_order":1143,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"VIDEO GAME","unified":"1F3AE","non_qualified":null,"docomo":"E68B","au":"E4C6","softbank":null,"google":"FE80A","image":"1f3ae.png","sheet_x":7,"sheet_y":44,"short_name":"video_game","short_names":["video_game"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1126,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DIRECT HIT","unified":"1F3AF","non_qualified":null,"docomo":null,"au":"E4C5","softbank":"E130","google":"FE80C","image":"1f3af.png","sheet_x":7,"sheet_y":45,"short_name":"dart","short_names":["dart"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1119,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SLOT MACHINE","unified":"1F3B0","non_qualified":null,"docomo":null,"au":"E46E","softbank":"E133","google":"FE80D","image":"1f3b0.png","sheet_x":7,"sheet_y":46,"short_name":"slot_machine","short_names":["slot_machine"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1128,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BILLIARDS","unified":"1F3B1","non_qualified":null,"docomo":null,"au":"EADD","softbank":"E42C","google":"FE80E","image":"1f3b1.png","sheet_x":7,"sheet_y":47,"short_name":"8ball","short_names":["8ball"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1123,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GAME DIE","unified":"1F3B2","non_qualified":null,"docomo":null,"au":"E4C8","softbank":null,"google":"FE80F","image":"1f3b2.png","sheet_x":7,"sheet_y":48,"short_name":"game_die","short_names":["game_die"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1129,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOWLING","unified":"1F3B3","non_qualified":null,"docomo":null,"au":"EB43","softbank":null,"google":"FE810","image":"1f3b3.png","sheet_x":7,"sheet_y":49,"short_name":"bowling","short_names":["bowling"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1101,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLOWER PLAYING CARDS","unified":"1F3B4","non_qualified":null,"docomo":null,"au":"EB6E","softbank":null,"google":"FE811","image":"1f3b4.png","sheet_x":7,"sheet_y":50,"short_name":"flower_playing_cards","short_names":["flower_playing_cards"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1142,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MUSICAL NOTE","unified":"1F3B5","non_qualified":null,"docomo":"E6F6","au":"E5BE","softbank":"E03E","google":"FE813","image":"1f3b5.png","sheet_x":7,"sheet_y":51,"short_name":"musical_note","short_names":["musical_note"],"text":null,"texts":null,"category":"Objects","subcategory":"music","sort_order":1207,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MULTIPLE MUSICAL NOTES","unified":"1F3B6","non_qualified":null,"docomo":"E6FF","au":"E505","softbank":"E326","google":"FE814","image":"1f3b6.png","sheet_x":7,"sheet_y":52,"short_name":"notes","short_names":["notes"],"text":null,"texts":null,"category":"Objects","subcategory":"music","sort_order":1208,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SAXOPHONE","unified":"1F3B7","non_qualified":null,"docomo":null,"au":null,"softbank":"E040","google":"FE815","image":"1f3b7.png","sheet_x":7,"sheet_y":53,"short_name":"saxophone","short_names":["saxophone"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1215,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GUITAR","unified":"1F3B8","non_qualified":null,"docomo":null,"au":"E506","softbank":"E041","google":"FE816","image":"1f3b8.png","sheet_x":7,"sheet_y":54,"short_name":"guitar","short_names":["guitar"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1217,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MUSICAL KEYBOARD","unified":"1F3B9","non_qualified":null,"docomo":null,"au":"EB40","softbank":null,"google":"FE817","image":"1f3b9.png","sheet_x":7,"sheet_y":55,"short_name":"musical_keyboard","short_names":["musical_keyboard"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1218,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRUMPET","unified":"1F3BA","non_qualified":null,"docomo":null,"au":"EADC","softbank":"E042","google":"FE818","image":"1f3ba.png","sheet_x":7,"sheet_y":56,"short_name":"trumpet","short_names":["trumpet"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1219,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"VIOLIN","unified":"1F3BB","non_qualified":null,"docomo":null,"au":"E507","softbank":null,"google":"FE819","image":"1f3bb.png","sheet_x":7,"sheet_y":57,"short_name":"violin","short_names":["violin"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1220,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MUSICAL SCORE","unified":"1F3BC","non_qualified":null,"docomo":"E6FF","au":"EACC","softbank":null,"google":"FE81A","image":"1f3bc.png","sheet_x":7,"sheet_y":58,"short_name":"musical_score","short_names":["musical_score"],"text":null,"texts":null,"category":"Objects","subcategory":"music","sort_order":1206,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RUNNING SHIRT WITH SASH","unified":"1F3BD","non_qualified":null,"docomo":"E652","au":null,"softbank":null,"google":"FE7D0","image":"1f3bd.png","sheet_x":7,"sheet_y":59,"short_name":"running_shirt_with_sash","short_names":["running_shirt_with_sash"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1115,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TENNIS RACQUET AND BALL","unified":"1F3BE","non_qualified":null,"docomo":"E655","au":"E4B7","softbank":"E015","google":"FE7D3","image":"1f3be.png","sheet_x":7,"sheet_y":60,"short_name":"tennis","short_names":["tennis"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1099,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SKI AND SKI BOOT","unified":"1F3BF","non_qualified":null,"docomo":"E657","au":"EAAC","softbank":"E013","google":"FE7D5","image":"1f3bf.png","sheet_x":7,"sheet_y":61,"short_name":"ski","short_names":["ski"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1116,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BASKETBALL AND HOOP","unified":"1F3C0","non_qualified":null,"docomo":"E658","au":"E59A","softbank":"E42A","google":"FE7D6","image":"1f3c0.png","sheet_x":8,"sheet_y":0,"short_name":"basketball","short_names":["basketball"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1095,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHEQUERED FLAG","unified":"1F3C1","non_qualified":null,"docomo":"E659","au":"E4B9","softbank":"E132","google":"FE7D7","image":"1f3c1.png","sheet_x":8,"sheet_y":1,"short_name":"checkered_flag","short_names":["checkered_flag"],"text":null,"texts":null,"category":"Flags","subcategory":"flag","sort_order":1635,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SNOWBOARDER","unified":"1F3C2","non_qualified":null,"docomo":"E712","au":"E4B8","softbank":null,"google":"FE7D8","image":"1f3c2.png","sheet_x":8,"sheet_y":2,"short_name":"snowboarder","short_names":["snowboarder"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":462,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3C2-1F3FB","non_qualified":null,"image":"1f3c2-1f3fb.png","sheet_x":8,"sheet_y":3,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3C2-1F3FC","non_qualified":null,"image":"1f3c2-1f3fc.png","sheet_x":8,"sheet_y":4,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3C2-1F3FD","non_qualified":null,"image":"1f3c2-1f3fd.png","sheet_x":8,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3C2-1F3FE","non_qualified":null,"image":"1f3c2-1f3fe.png","sheet_x":8,"sheet_y":6,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3C2-1F3FF","non_qualified":null,"image":"1f3c2-1f3ff.png","sheet_x":8,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN RUNNING","unified":"1F3C3-200D-2640-FE0F","non_qualified":"1F3C3-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c3-200d-2640-fe0f.png","sheet_x":8,"sheet_y":8,"short_name":"woman-running","short_names":["woman-running"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":443,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3C3-1F3FB-200D-2640-FE0F","non_qualified":"1F3C3-1F3FB-200D-2640","image":"1f3c3-1f3fb-200d-2640-fe0f.png","sheet_x":8,"sheet_y":9,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3C3-1F3FC-200D-2640-FE0F","non_qualified":"1F3C3-1F3FC-200D-2640","image":"1f3c3-1f3fc-200d-2640-fe0f.png","sheet_x":8,"sheet_y":10,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3C3-1F3FD-200D-2640-FE0F","non_qualified":"1F3C3-1F3FD-200D-2640","image":"1f3c3-1f3fd-200d-2640-fe0f.png","sheet_x":8,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3C3-1F3FE-200D-2640-FE0F","non_qualified":"1F3C3-1F3FE-200D-2640","image":"1f3c3-1f3fe-200d-2640-fe0f.png","sheet_x":8,"sheet_y":12,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3C3-1F3FF-200D-2640-FE0F","non_qualified":"1F3C3-1F3FF-200D-2640","image":"1f3c3-1f3ff-200d-2640-fe0f.png","sheet_x":8,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN RUNNING FACING RIGHT","unified":"1F3C3-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-200D-2640-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c3-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":14,"short_name":"woman_running_facing_right","short_names":["woman_running_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":445,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F3C3-1F3FB-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FB-200D-2640-200D-27A1","image":"1f3c3-1f3fb-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":15,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F3C3-1F3FC-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FC-200D-2640-200D-27A1","image":"1f3c3-1f3fc-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":16,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F3C3-1F3FD-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FD-200D-2640-200D-27A1","image":"1f3c3-1f3fd-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":17,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F3C3-1F3FE-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FE-200D-2640-200D-27A1","image":"1f3c3-1f3fe-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":18,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F3C3-1F3FF-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FF-200D-2640-200D-27A1","image":"1f3c3-1f3ff-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":19,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"MAN RUNNING","unified":"1F3C3-200D-2642-FE0F","non_qualified":"1F3C3-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c3-200d-2642-fe0f.png","sheet_x":8,"sheet_y":20,"short_name":"man-running","short_names":["man-running"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":442,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3C3-1F3FB-200D-2642-FE0F","non_qualified":"1F3C3-1F3FB-200D-2642","image":"1f3c3-1f3fb-200d-2642-fe0f.png","sheet_x":8,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3C3-1F3FC-200D-2642-FE0F","non_qualified":"1F3C3-1F3FC-200D-2642","image":"1f3c3-1f3fc-200d-2642-fe0f.png","sheet_x":8,"sheet_y":22,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3C3-1F3FD-200D-2642-FE0F","non_qualified":"1F3C3-1F3FD-200D-2642","image":"1f3c3-1f3fd-200d-2642-fe0f.png","sheet_x":8,"sheet_y":23,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3C3-1F3FE-200D-2642-FE0F","non_qualified":"1F3C3-1F3FE-200D-2642","image":"1f3c3-1f3fe-200d-2642-fe0f.png","sheet_x":8,"sheet_y":24,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3C3-1F3FF-200D-2642-FE0F","non_qualified":"1F3C3-1F3FF-200D-2642","image":"1f3c3-1f3ff-200d-2642-fe0f.png","sheet_x":8,"sheet_y":25,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F3C3"},{"name":"MAN RUNNING FACING RIGHT","unified":"1F3C3-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-200D-2642-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c3-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":26,"short_name":"man_running_facing_right","short_names":["man_running_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":446,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F3C3-1F3FB-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FB-200D-2642-200D-27A1","image":"1f3c3-1f3fb-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":27,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F3C3-1F3FC-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FC-200D-2642-200D-27A1","image":"1f3c3-1f3fc-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":28,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F3C3-1F3FD-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FD-200D-2642-200D-27A1","image":"1f3c3-1f3fd-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":29,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F3C3-1F3FE-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FE-200D-2642-200D-27A1","image":"1f3c3-1f3fe-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":30,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F3C3-1F3FF-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FF-200D-2642-200D-27A1","image":"1f3c3-1f3ff-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":31,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"PERSON RUNNING FACING RIGHT","unified":"1F3C3-200D-27A1-FE0F","non_qualified":"1F3C3-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c3-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":32,"short_name":"person_running_facing_right","short_names":["person_running_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":444,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F3C3-1F3FB-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FB-200D-27A1","image":"1f3c3-1f3fb-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":33,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F3C3-1F3FC-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FC-200D-27A1","image":"1f3c3-1f3fc-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":34,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F3C3-1F3FD-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FD-200D-27A1","image":"1f3c3-1f3fd-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":35,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F3C3-1F3FE-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FE-200D-27A1","image":"1f3c3-1f3fe-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":36,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F3C3-1F3FF-200D-27A1-FE0F","non_qualified":"1F3C3-1F3FF-200D-27A1","image":"1f3c3-1f3ff-200d-27a1-fe0f.png","sheet_x":8,"sheet_y":37,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"RUNNER","unified":"1F3C3","non_qualified":null,"docomo":"E733","au":"E46B","softbank":"E115","google":"FE7D9","image":"1f3c3.png","sheet_x":8,"sheet_y":38,"short_name":"runner","short_names":["runner","running"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":441,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3C3-1F3FB","non_qualified":null,"image":"1f3c3-1f3fb.png","sheet_x":8,"sheet_y":39,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3C3-1F3FC","non_qualified":null,"image":"1f3c3-1f3fc.png","sheet_x":8,"sheet_y":40,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3C3-1F3FD","non_qualified":null,"image":"1f3c3-1f3fd.png","sheet_x":8,"sheet_y":41,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3C3-1F3FE","non_qualified":null,"image":"1f3c3-1f3fe.png","sheet_x":8,"sheet_y":42,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3C3-1F3FF","non_qualified":null,"image":"1f3c3-1f3ff.png","sheet_x":8,"sheet_y":43,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F3C3-200D-2642-FE0F"},{"name":"WOMAN SURFING","unified":"1F3C4-200D-2640-FE0F","non_qualified":"1F3C4-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c4-200d-2640-fe0f.png","sheet_x":8,"sheet_y":44,"short_name":"woman-surfing","short_names":["woman-surfing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":468,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3C4-1F3FB-200D-2640-FE0F","non_qualified":"1F3C4-1F3FB-200D-2640","image":"1f3c4-1f3fb-200d-2640-fe0f.png","sheet_x":8,"sheet_y":45,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3C4-1F3FC-200D-2640-FE0F","non_qualified":"1F3C4-1F3FC-200D-2640","image":"1f3c4-1f3fc-200d-2640-fe0f.png","sheet_x":8,"sheet_y":46,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3C4-1F3FD-200D-2640-FE0F","non_qualified":"1F3C4-1F3FD-200D-2640","image":"1f3c4-1f3fd-200d-2640-fe0f.png","sheet_x":8,"sheet_y":47,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3C4-1F3FE-200D-2640-FE0F","non_qualified":"1F3C4-1F3FE-200D-2640","image":"1f3c4-1f3fe-200d-2640-fe0f.png","sheet_x":8,"sheet_y":48,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3C4-1F3FF-200D-2640-FE0F","non_qualified":"1F3C4-1F3FF-200D-2640","image":"1f3c4-1f3ff-200d-2640-fe0f.png","sheet_x":8,"sheet_y":49,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN SURFING","unified":"1F3C4-200D-2642-FE0F","non_qualified":"1F3C4-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c4-200d-2642-fe0f.png","sheet_x":8,"sheet_y":50,"short_name":"man-surfing","short_names":["man-surfing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":467,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3C4-1F3FB-200D-2642-FE0F","non_qualified":"1F3C4-1F3FB-200D-2642","image":"1f3c4-1f3fb-200d-2642-fe0f.png","sheet_x":8,"sheet_y":51,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3C4-1F3FC-200D-2642-FE0F","non_qualified":"1F3C4-1F3FC-200D-2642","image":"1f3c4-1f3fc-200d-2642-fe0f.png","sheet_x":8,"sheet_y":52,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3C4-1F3FD-200D-2642-FE0F","non_qualified":"1F3C4-1F3FD-200D-2642","image":"1f3c4-1f3fd-200d-2642-fe0f.png","sheet_x":8,"sheet_y":53,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3C4-1F3FE-200D-2642-FE0F","non_qualified":"1F3C4-1F3FE-200D-2642","image":"1f3c4-1f3fe-200d-2642-fe0f.png","sheet_x":8,"sheet_y":54,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3C4-1F3FF-200D-2642-FE0F","non_qualified":"1F3C4-1F3FF-200D-2642","image":"1f3c4-1f3ff-200d-2642-fe0f.png","sheet_x":8,"sheet_y":55,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F3C4"},{"name":"SURFER","unified":"1F3C4","non_qualified":null,"docomo":"E712","au":"EB41","softbank":"E017","google":"FE7DA","image":"1f3c4.png","sheet_x":8,"sheet_y":56,"short_name":"surfer","short_names":["surfer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":466,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3C4-1F3FB","non_qualified":null,"image":"1f3c4-1f3fb.png","sheet_x":8,"sheet_y":57,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3C4-1F3FC","non_qualified":null,"image":"1f3c4-1f3fc.png","sheet_x":8,"sheet_y":58,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3C4-1F3FD","non_qualified":null,"image":"1f3c4-1f3fd.png","sheet_x":8,"sheet_y":59,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3C4-1F3FE","non_qualified":null,"image":"1f3c4-1f3fe.png","sheet_x":8,"sheet_y":60,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3C4-1F3FF","non_qualified":null,"image":"1f3c4-1f3ff.png","sheet_x":8,"sheet_y":61,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F3C4-200D-2642-FE0F"},{"name":"SPORTS MEDAL","unified":"1F3C5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c5.png","sheet_x":9,"sheet_y":0,"short_name":"sports_medal","short_names":["sports_medal"],"text":null,"texts":null,"category":"Activities","subcategory":"award-medal","sort_order":1088,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TROPHY","unified":"1F3C6","non_qualified":null,"docomo":null,"au":"E5D3","softbank":"E131","google":"FE7DB","image":"1f3c6.png","sheet_x":9,"sheet_y":1,"short_name":"trophy","short_names":["trophy"],"text":null,"texts":null,"category":"Activities","subcategory":"award-medal","sort_order":1087,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HORSE RACING","unified":"1F3C7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c7.png","sheet_x":9,"sheet_y":2,"short_name":"horse_racing","short_names":["horse_racing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":460,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3C7-1F3FB","non_qualified":null,"image":"1f3c7-1f3fb.png","sheet_x":9,"sheet_y":3,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3C7-1F3FC","non_qualified":null,"image":"1f3c7-1f3fc.png","sheet_x":9,"sheet_y":4,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3C7-1F3FD","non_qualified":null,"image":"1f3c7-1f3fd.png","sheet_x":9,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3C7-1F3FE","non_qualified":null,"image":"1f3c7-1f3fe.png","sheet_x":9,"sheet_y":6,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3C7-1F3FF","non_qualified":null,"image":"1f3c7-1f3ff.png","sheet_x":9,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"AMERICAN FOOTBALL","unified":"1F3C8","non_qualified":null,"docomo":null,"au":"E4BB","softbank":"E42B","google":"FE7DD","image":"1f3c8.png","sheet_x":9,"sheet_y":8,"short_name":"football","short_names":["football"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1097,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RUGBY FOOTBALL","unified":"1F3C9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3c9.png","sheet_x":9,"sheet_y":9,"short_name":"rugby_football","short_names":["rugby_football"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1098,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN SWIMMING","unified":"1F3CA-200D-2640-FE0F","non_qualified":"1F3CA-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3ca-200d-2640-fe0f.png","sheet_x":9,"sheet_y":10,"short_name":"woman-swimming","short_names":["woman-swimming"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":474,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3CA-1F3FB-200D-2640-FE0F","non_qualified":"1F3CA-1F3FB-200D-2640","image":"1f3ca-1f3fb-200d-2640-fe0f.png","sheet_x":9,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3CA-1F3FC-200D-2640-FE0F","non_qualified":"1F3CA-1F3FC-200D-2640","image":"1f3ca-1f3fc-200d-2640-fe0f.png","sheet_x":9,"sheet_y":12,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3CA-1F3FD-200D-2640-FE0F","non_qualified":"1F3CA-1F3FD-200D-2640","image":"1f3ca-1f3fd-200d-2640-fe0f.png","sheet_x":9,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3CA-1F3FE-200D-2640-FE0F","non_qualified":"1F3CA-1F3FE-200D-2640","image":"1f3ca-1f3fe-200d-2640-fe0f.png","sheet_x":9,"sheet_y":14,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3CA-1F3FF-200D-2640-FE0F","non_qualified":"1F3CA-1F3FF-200D-2640","image":"1f3ca-1f3ff-200d-2640-fe0f.png","sheet_x":9,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN SWIMMING","unified":"1F3CA-200D-2642-FE0F","non_qualified":"1F3CA-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3ca-200d-2642-fe0f.png","sheet_x":9,"sheet_y":16,"short_name":"man-swimming","short_names":["man-swimming"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":473,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3CA-1F3FB-200D-2642-FE0F","non_qualified":"1F3CA-1F3FB-200D-2642","image":"1f3ca-1f3fb-200d-2642-fe0f.png","sheet_x":9,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3CA-1F3FC-200D-2642-FE0F","non_qualified":"1F3CA-1F3FC-200D-2642","image":"1f3ca-1f3fc-200d-2642-fe0f.png","sheet_x":9,"sheet_y":18,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3CA-1F3FD-200D-2642-FE0F","non_qualified":"1F3CA-1F3FD-200D-2642","image":"1f3ca-1f3fd-200d-2642-fe0f.png","sheet_x":9,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3CA-1F3FE-200D-2642-FE0F","non_qualified":"1F3CA-1F3FE-200D-2642","image":"1f3ca-1f3fe-200d-2642-fe0f.png","sheet_x":9,"sheet_y":20,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3CA-1F3FF-200D-2642-FE0F","non_qualified":"1F3CA-1F3FF-200D-2642","image":"1f3ca-1f3ff-200d-2642-fe0f.png","sheet_x":9,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F3CA"},{"name":"SWIMMER","unified":"1F3CA","non_qualified":null,"docomo":null,"au":"EADE","softbank":"E42D","google":"FE7DE","image":"1f3ca.png","sheet_x":9,"sheet_y":22,"short_name":"swimmer","short_names":["swimmer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":472,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3CA-1F3FB","non_qualified":null,"image":"1f3ca-1f3fb.png","sheet_x":9,"sheet_y":23,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3CA-1F3FC","non_qualified":null,"image":"1f3ca-1f3fc.png","sheet_x":9,"sheet_y":24,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3CA-1F3FD","non_qualified":null,"image":"1f3ca-1f3fd.png","sheet_x":9,"sheet_y":25,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3CA-1F3FE","non_qualified":null,"image":"1f3ca-1f3fe.png","sheet_x":9,"sheet_y":26,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3CA-1F3FF","non_qualified":null,"image":"1f3ca-1f3ff.png","sheet_x":9,"sheet_y":27,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F3CA-200D-2642-FE0F"},{"name":"WOMAN LIFTING WEIGHTS","unified":"1F3CB-FE0F-200D-2640-FE0F","non_qualified":"1F3CB-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3cb-fe0f-200d-2640-fe0f.png","sheet_x":9,"sheet_y":28,"short_name":"woman-lifting-weights","short_names":["woman-lifting-weights"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":480,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F3CB-1F3FB-200D-2640-FE0F","non_qualified":"1F3CB-1F3FB-200D-2640","image":"1f3cb-1f3fb-200d-2640-fe0f.png","sheet_x":9,"sheet_y":29,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3CB-1F3FC-200D-2640-FE0F","non_qualified":"1F3CB-1F3FC-200D-2640","image":"1f3cb-1f3fc-200d-2640-fe0f.png","sheet_x":9,"sheet_y":30,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3CB-1F3FD-200D-2640-FE0F","non_qualified":"1F3CB-1F3FD-200D-2640","image":"1f3cb-1f3fd-200d-2640-fe0f.png","sheet_x":9,"sheet_y":31,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3CB-1F3FE-200D-2640-FE0F","non_qualified":"1F3CB-1F3FE-200D-2640","image":"1f3cb-1f3fe-200d-2640-fe0f.png","sheet_x":9,"sheet_y":32,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3CB-1F3FF-200D-2640-FE0F","non_qualified":"1F3CB-1F3FF-200D-2640","image":"1f3cb-1f3ff-200d-2640-fe0f.png","sheet_x":9,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN LIFTING WEIGHTS","unified":"1F3CB-FE0F-200D-2642-FE0F","non_qualified":"1F3CB-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3cb-fe0f-200d-2642-fe0f.png","sheet_x":9,"sheet_y":34,"short_name":"man-lifting-weights","short_names":["man-lifting-weights"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":479,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F3CB-1F3FB-200D-2642-FE0F","non_qualified":"1F3CB-1F3FB-200D-2642","image":"1f3cb-1f3fb-200d-2642-fe0f.png","sheet_x":9,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3CB-1F3FC-200D-2642-FE0F","non_qualified":"1F3CB-1F3FC-200D-2642","image":"1f3cb-1f3fc-200d-2642-fe0f.png","sheet_x":9,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3CB-1F3FD-200D-2642-FE0F","non_qualified":"1F3CB-1F3FD-200D-2642","image":"1f3cb-1f3fd-200d-2642-fe0f.png","sheet_x":9,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3CB-1F3FE-200D-2642-FE0F","non_qualified":"1F3CB-1F3FE-200D-2642","image":"1f3cb-1f3fe-200d-2642-fe0f.png","sheet_x":9,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3CB-1F3FF-200D-2642-FE0F","non_qualified":"1F3CB-1F3FF-200D-2642","image":"1f3cb-1f3ff-200d-2642-fe0f.png","sheet_x":9,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F3CB-FE0F"},{"name":"PERSON LIFTING WEIGHTS","unified":"1F3CB-FE0F","non_qualified":"1F3CB","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3cb-fe0f.png","sheet_x":9,"sheet_y":40,"short_name":"weight_lifter","short_names":["weight_lifter"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":478,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3CB-1F3FB","non_qualified":null,"image":"1f3cb-1f3fb.png","sheet_x":9,"sheet_y":41,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3CB-1F3FC","non_qualified":null,"image":"1f3cb-1f3fc.png","sheet_x":9,"sheet_y":42,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3CB-1F3FD","non_qualified":null,"image":"1f3cb-1f3fd.png","sheet_x":9,"sheet_y":43,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3CB-1F3FE","non_qualified":null,"image":"1f3cb-1f3fe.png","sheet_x":9,"sheet_y":44,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3CB-1F3FF","non_qualified":null,"image":"1f3cb-1f3ff.png","sheet_x":9,"sheet_y":45,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F3CB-FE0F-200D-2642-FE0F"},{"name":"WOMAN GOLFING","unified":"1F3CC-FE0F-200D-2640-FE0F","non_qualified":"1F3CC-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3cc-fe0f-200d-2640-fe0f.png","sheet_x":9,"sheet_y":46,"short_name":"woman-golfing","short_names":["woman-golfing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":465,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F3CC-1F3FB-200D-2640-FE0F","non_qualified":"1F3CC-1F3FB-200D-2640","image":"1f3cc-1f3fb-200d-2640-fe0f.png","sheet_x":9,"sheet_y":47,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3CC-1F3FC-200D-2640-FE0F","non_qualified":"1F3CC-1F3FC-200D-2640","image":"1f3cc-1f3fc-200d-2640-fe0f.png","sheet_x":9,"sheet_y":48,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3CC-1F3FD-200D-2640-FE0F","non_qualified":"1F3CC-1F3FD-200D-2640","image":"1f3cc-1f3fd-200d-2640-fe0f.png","sheet_x":9,"sheet_y":49,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3CC-1F3FE-200D-2640-FE0F","non_qualified":"1F3CC-1F3FE-200D-2640","image":"1f3cc-1f3fe-200d-2640-fe0f.png","sheet_x":9,"sheet_y":50,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3CC-1F3FF-200D-2640-FE0F","non_qualified":"1F3CC-1F3FF-200D-2640","image":"1f3cc-1f3ff-200d-2640-fe0f.png","sheet_x":9,"sheet_y":51,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN GOLFING","unified":"1F3CC-FE0F-200D-2642-FE0F","non_qualified":"1F3CC-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3cc-fe0f-200d-2642-fe0f.png","sheet_x":9,"sheet_y":52,"short_name":"man-golfing","short_names":["man-golfing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":464,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F3CC-1F3FB-200D-2642-FE0F","non_qualified":"1F3CC-1F3FB-200D-2642","image":"1f3cc-1f3fb-200d-2642-fe0f.png","sheet_x":9,"sheet_y":53,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3CC-1F3FC-200D-2642-FE0F","non_qualified":"1F3CC-1F3FC-200D-2642","image":"1f3cc-1f3fc-200d-2642-fe0f.png","sheet_x":9,"sheet_y":54,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3CC-1F3FD-200D-2642-FE0F","non_qualified":"1F3CC-1F3FD-200D-2642","image":"1f3cc-1f3fd-200d-2642-fe0f.png","sheet_x":9,"sheet_y":55,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3CC-1F3FE-200D-2642-FE0F","non_qualified":"1F3CC-1F3FE-200D-2642","image":"1f3cc-1f3fe-200d-2642-fe0f.png","sheet_x":9,"sheet_y":56,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3CC-1F3FF-200D-2642-FE0F","non_qualified":"1F3CC-1F3FF-200D-2642","image":"1f3cc-1f3ff-200d-2642-fe0f.png","sheet_x":9,"sheet_y":57,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F3CC-FE0F"},{"name":"PERSON GOLFING","unified":"1F3CC-FE0F","non_qualified":"1F3CC","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3cc-fe0f.png","sheet_x":9,"sheet_y":58,"short_name":"golfer","short_names":["golfer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":463,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F3CC-1F3FB","non_qualified":null,"image":"1f3cc-1f3fb.png","sheet_x":9,"sheet_y":59,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F3CC-1F3FC","non_qualified":null,"image":"1f3cc-1f3fc.png","sheet_x":9,"sheet_y":60,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F3CC-1F3FD","non_qualified":null,"image":"1f3cc-1f3fd.png","sheet_x":9,"sheet_y":61,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F3CC-1F3FE","non_qualified":null,"image":"1f3cc-1f3fe.png","sheet_x":10,"sheet_y":0,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F3CC-1F3FF","non_qualified":null,"image":"1f3cc-1f3ff.png","sheet_x":10,"sheet_y":1,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F3CC-FE0F-200D-2642-FE0F"},{"name":"MOTORCYCLE","unified":"1F3CD-FE0F","non_qualified":"1F3CD","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3cd-fe0f.png","sheet_x":10,"sheet_y":2,"short_name":"racing_motorcycle","short_names":["racing_motorcycle"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":943,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RACING CAR","unified":"1F3CE-FE0F","non_qualified":"1F3CE","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3ce-fe0f.png","sheet_x":10,"sheet_y":3,"short_name":"racing_car","short_names":["racing_car"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":942,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CRICKET BAT AND BALL","unified":"1F3CF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3cf.png","sheet_x":10,"sheet_y":4,"short_name":"cricket_bat_and_ball","short_names":["cricket_bat_and_ball"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1102,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"VOLLEYBALL","unified":"1F3D0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d0.png","sheet_x":10,"sheet_y":5,"short_name":"volleyball","short_names":["volleyball"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1096,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FIELD HOCKEY STICK AND BALL","unified":"1F3D1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d1.png","sheet_x":10,"sheet_y":6,"short_name":"field_hockey_stick_and_ball","short_names":["field_hockey_stick_and_ball"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1103,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ICE HOCKEY STICK AND PUCK","unified":"1F3D2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d2.png","sheet_x":10,"sheet_y":7,"short_name":"ice_hockey_stick_and_puck","short_names":["ice_hockey_stick_and_puck"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1104,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TABLE TENNIS PADDLE AND BALL","unified":"1F3D3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d3.png","sheet_x":10,"sheet_y":8,"short_name":"table_tennis_paddle_and_ball","short_names":["table_tennis_paddle_and_ball"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1106,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SNOW-CAPPED MOUNTAIN","unified":"1F3D4-FE0F","non_qualified":"1F3D4","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d4-fe0f.png","sheet_x":10,"sheet_y":9,"short_name":"snow_capped_mountain","short_names":["snow_capped_mountain"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-geographic","sort_order":854,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CAMPING","unified":"1F3D5-FE0F","non_qualified":"1F3D5","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d5-fe0f.png","sheet_x":10,"sheet_y":10,"short_name":"camping","short_names":["camping"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-geographic","sort_order":858,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BEACH WITH UMBRELLA","unified":"1F3D6-FE0F","non_qualified":"1F3D6","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d6-fe0f.png","sheet_x":10,"sheet_y":11,"short_name":"beach_with_umbrella","short_names":["beach_with_umbrella"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-geographic","sort_order":859,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUILDING CONSTRUCTION","unified":"1F3D7-FE0F","non_qualified":"1F3D7","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d7-fe0f.png","sheet_x":10,"sheet_y":12,"short_name":"building_construction","short_names":["building_construction"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":865,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOUSES","unified":"1F3D8-FE0F","non_qualified":"1F3D8","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d8-fe0f.png","sheet_x":10,"sheet_y":13,"short_name":"house_buildings","short_names":["house_buildings"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":870,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CITYSCAPE","unified":"1F3D9-FE0F","non_qualified":"1F3D9","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3d9-fe0f.png","sheet_x":10,"sheet_y":14,"short_name":"cityscape","short_names":["cityscape"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":900,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DERELICT HOUSE","unified":"1F3DA-FE0F","non_qualified":"1F3DA","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3da-fe0f.png","sheet_x":10,"sheet_y":15,"short_name":"derelict_house_building","short_names":["derelict_house_building"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":871,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLASSICAL BUILDING","unified":"1F3DB-FE0F","non_qualified":"1F3DB","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3db-fe0f.png","sheet_x":10,"sheet_y":16,"short_name":"classical_building","short_names":["classical_building"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":864,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DESERT","unified":"1F3DC-FE0F","non_qualified":"1F3DC","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3dc-fe0f.png","sheet_x":10,"sheet_y":17,"short_name":"desert","short_names":["desert"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-geographic","sort_order":860,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DESERT ISLAND","unified":"1F3DD-FE0F","non_qualified":"1F3DD","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3dd-fe0f.png","sheet_x":10,"sheet_y":18,"short_name":"desert_island","short_names":["desert_island"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-geographic","sort_order":861,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NATIONAL PARK","unified":"1F3DE-FE0F","non_qualified":"1F3DE","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3de-fe0f.png","sheet_x":10,"sheet_y":19,"short_name":"national_park","short_names":["national_park"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-geographic","sort_order":862,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STADIUM","unified":"1F3DF-FE0F","non_qualified":"1F3DF","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3df-fe0f.png","sheet_x":10,"sheet_y":20,"short_name":"stadium","short_names":["stadium"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":863,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOUSE BUILDING","unified":"1F3E0","non_qualified":null,"docomo":"E663","au":"E4AB","softbank":"E036","google":"FE4B0","image":"1f3e0.png","sheet_x":10,"sheet_y":21,"short_name":"house","short_names":["house"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":872,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOUSE WITH GARDEN","unified":"1F3E1","non_qualified":null,"docomo":"E663","au":"EB09","softbank":null,"google":"FE4B1","image":"1f3e1.png","sheet_x":10,"sheet_y":22,"short_name":"house_with_garden","short_names":["house_with_garden"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":873,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OFFICE BUILDING","unified":"1F3E2","non_qualified":null,"docomo":"E664","au":"E4AD","softbank":"E038","google":"FE4B2","image":"1f3e2.png","sheet_x":10,"sheet_y":23,"short_name":"office","short_names":["office"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":874,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JAPANESE POST OFFICE","unified":"1F3E3","non_qualified":null,"docomo":"E665","au":"E5DE","softbank":"E153","google":"FE4B3","image":"1f3e3.png","sheet_x":10,"sheet_y":24,"short_name":"post_office","short_names":["post_office"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":875,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EUROPEAN POST OFFICE","unified":"1F3E4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3e4.png","sheet_x":10,"sheet_y":25,"short_name":"european_post_office","short_names":["european_post_office"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":876,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOSPITAL","unified":"1F3E5","non_qualified":null,"docomo":"E666","au":"E5DF","softbank":"E155","google":"FE4B4","image":"1f3e5.png","sheet_x":10,"sheet_y":26,"short_name":"hospital","short_names":["hospital"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":877,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BANK","unified":"1F3E6","non_qualified":null,"docomo":"E667","au":"E4AA","softbank":"E14D","google":"FE4B5","image":"1f3e6.png","sheet_x":10,"sheet_y":27,"short_name":"bank","short_names":["bank"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":878,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AUTOMATED TELLER MACHINE","unified":"1F3E7","non_qualified":null,"docomo":"E668","au":"E4A3","softbank":"E154","google":"FE4B6","image":"1f3e7.png","sheet_x":10,"sheet_y":28,"short_name":"atm","short_names":["atm"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1412,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOTEL","unified":"1F3E8","non_qualified":null,"docomo":"E669","au":"EA81","softbank":"E158","google":"FE4B7","image":"1f3e8.png","sheet_x":10,"sheet_y":29,"short_name":"hotel","short_names":["hotel"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":879,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOVE HOTEL","unified":"1F3E9","non_qualified":null,"docomo":"E669-E6EF","au":"EAF3","softbank":"E501","google":"FE4B8","image":"1f3e9.png","sheet_x":10,"sheet_y":30,"short_name":"love_hotel","short_names":["love_hotel"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":880,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CONVENIENCE STORE","unified":"1F3EA","non_qualified":null,"docomo":"E66A","au":"E4A4","softbank":"E156","google":"FE4B9","image":"1f3ea.png","sheet_x":10,"sheet_y":31,"short_name":"convenience_store","short_names":["convenience_store"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":881,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SCHOOL","unified":"1F3EB","non_qualified":null,"docomo":"E73E","au":"EA80","softbank":"E157","google":"FE4BA","image":"1f3eb.png","sheet_x":10,"sheet_y":32,"short_name":"school","short_names":["school"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":882,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DEPARTMENT STORE","unified":"1F3EC","non_qualified":null,"docomo":null,"au":"EAF6","softbank":"E504","google":"FE4BD","image":"1f3ec.png","sheet_x":10,"sheet_y":33,"short_name":"department_store","short_names":["department_store"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":883,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACTORY","unified":"1F3ED","non_qualified":null,"docomo":null,"au":"EAF9","softbank":"E508","google":"FE4C0","image":"1f3ed.png","sheet_x":10,"sheet_y":34,"short_name":"factory","short_names":["factory"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":884,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"IZAKAYA LANTERN","unified":"1F3EE","non_qualified":null,"docomo":"E74B","au":"E4BD","softbank":null,"google":"FE4C2","image":"1f3ee.png","sheet_x":10,"sheet_y":35,"short_name":"izakaya_lantern","short_names":["izakaya_lantern","lantern"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1260,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JAPANESE CASTLE","unified":"1F3EF","non_qualified":null,"docomo":null,"au":"EAF7","softbank":"E505","google":"FE4BE","image":"1f3ef.png","sheet_x":10,"sheet_y":36,"short_name":"japanese_castle","short_names":["japanese_castle"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":885,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EUROPEAN CASTLE","unified":"1F3F0","non_qualified":null,"docomo":null,"au":"EAF8","softbank":"E506","google":"FE4BF","image":"1f3f0.png","sheet_x":10,"sheet_y":37,"short_name":"european_castle","short_names":["european_castle"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":886,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RAINBOW FLAG","unified":"1F3F3-FE0F-200D-1F308","non_qualified":"1F3F3-200D-1F308","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f3-fe0f-200d-1f308.png","sheet_x":10,"sheet_y":38,"short_name":"rainbow-flag","short_names":["rainbow-flag"],"text":null,"texts":null,"category":"Flags","subcategory":"flag","sort_order":1640,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRANSGENDER FLAG","unified":"1F3F3-FE0F-200D-26A7-FE0F","non_qualified":"1F3F3-200D-26A7","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f3-fe0f-200d-26a7-fe0f.png","sheet_x":10,"sheet_y":39,"short_name":"transgender_flag","short_names":["transgender_flag"],"text":null,"texts":null,"category":"Flags","subcategory":"flag","sort_order":1641,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"WHITE FLAG","unified":"1F3F3-FE0F","non_qualified":"1F3F3","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f3-fe0f.png","sheet_x":10,"sheet_y":40,"short_name":"waving_white_flag","short_names":["waving_white_flag"],"text":null,"texts":null,"category":"Flags","subcategory":"flag","sort_order":1639,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PIRATE FLAG","unified":"1F3F4-200D-2620-FE0F","non_qualified":"1F3F4-200D-2620","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f4-200d-2620-fe0f.png","sheet_x":10,"sheet_y":41,"short_name":"pirate_flag","short_names":["pirate_flag"],"text":null,"texts":null,"category":"Flags","subcategory":"flag","sort_order":1642,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"England Flag","unified":"1F3F4-E0067-E0062-E0065-E006E-E0067-E007F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f.png","sheet_x":10,"sheet_y":42,"short_name":"flag-england","short_names":["flag-england"],"text":null,"texts":null,"category":"Flags","subcategory":"subdivision-flag","sort_order":1901,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Scotland Flag","unified":"1F3F4-E0067-E0062-E0073-E0063-E0074-E007F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f.png","sheet_x":10,"sheet_y":43,"short_name":"flag-scotland","short_names":["flag-scotland"],"text":null,"texts":null,"category":"Flags","subcategory":"subdivision-flag","sort_order":1902,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"Wales Flag","unified":"1F3F4-E0067-E0062-E0077-E006C-E0073-E007F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f.png","sheet_x":10,"sheet_y":44,"short_name":"flag-wales","short_names":["flag-wales"],"text":null,"texts":null,"category":"Flags","subcategory":"subdivision-flag","sort_order":1903,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WAVING BLACK FLAG","unified":"1F3F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f4.png","sheet_x":10,"sheet_y":45,"short_name":"waving_black_flag","short_names":["waving_black_flag"],"text":null,"texts":null,"category":"Flags","subcategory":"flag","sort_order":1638,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROSETTE","unified":"1F3F5-FE0F","non_qualified":"1F3F5","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f5-fe0f.png","sheet_x":10,"sheet_y":46,"short_name":"rosette","short_names":["rosette"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":688,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LABEL","unified":"1F3F7-FE0F","non_qualified":"1F3F7","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f7-fe0f.png","sheet_x":10,"sheet_y":47,"short_name":"label","short_names":["label"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1278,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BADMINTON RACQUET AND SHUTTLECOCK","unified":"1F3F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f8.png","sheet_x":10,"sheet_y":48,"short_name":"badminton_racquet_and_shuttlecock","short_names":["badminton_racquet_and_shuttlecock"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1107,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOW AND ARROW","unified":"1F3F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3f9.png","sheet_x":10,"sheet_y":49,"short_name":"bow_and_arrow","short_names":["bow_and_arrow"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1347,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AMPHORA","unified":"1F3FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3fa.png","sheet_x":10,"sheet_y":50,"short_name":"amphora","short_names":["amphora"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"dishware","sort_order":846,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EMOJI MODIFIER FITZPATRICK TYPE-1-2","unified":"1F3FB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3fb.png","sheet_x":10,"sheet_y":51,"short_name":"skin-tone-2","short_names":["skin-tone-2"],"text":null,"texts":null,"category":"Component","subcategory":"skin-tone","sort_order":554,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EMOJI MODIFIER FITZPATRICK TYPE-3","unified":"1F3FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3fc.png","sheet_x":10,"sheet_y":52,"short_name":"skin-tone-3","short_names":["skin-tone-3"],"text":null,"texts":null,"category":"Component","subcategory":"skin-tone","sort_order":555,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EMOJI MODIFIER FITZPATRICK TYPE-4","unified":"1F3FD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3fd.png","sheet_x":10,"sheet_y":53,"short_name":"skin-tone-4","short_names":["skin-tone-4"],"text":null,"texts":null,"category":"Component","subcategory":"skin-tone","sort_order":556,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EMOJI MODIFIER FITZPATRICK TYPE-5","unified":"1F3FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3fe.png","sheet_x":10,"sheet_y":54,"short_name":"skin-tone-5","short_names":["skin-tone-5"],"text":null,"texts":null,"category":"Component","subcategory":"skin-tone","sort_order":557,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EMOJI MODIFIER FITZPATRICK TYPE-6","unified":"1F3FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f3ff.png","sheet_x":10,"sheet_y":55,"short_name":"skin-tone-6","short_names":["skin-tone-6"],"text":null,"texts":null,"category":"Component","subcategory":"skin-tone","sort_order":558,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RAT","unified":"1F400","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f400.png","sheet_x":10,"sheet_y":56,"short_name":"rat","short_names":["rat"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":607,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOUSE","unified":"1F401","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f401.png","sheet_x":10,"sheet_y":57,"short_name":"mouse2","short_names":["mouse2"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":606,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OX","unified":"1F402","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f402.png","sheet_x":10,"sheet_y":58,"short_name":"ox","short_names":["ox"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":587,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WATER BUFFALO","unified":"1F403","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f403.png","sheet_x":10,"sheet_y":59,"short_name":"water_buffalo","short_names":["water_buffalo"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":588,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COW","unified":"1F404","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f404.png","sheet_x":10,"sheet_y":60,"short_name":"cow2","short_names":["cow2"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":589,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TIGER","unified":"1F405","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f405.png","sheet_x":10,"sheet_y":61,"short_name":"tiger2","short_names":["tiger2"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":576,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEOPARD","unified":"1F406","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f406.png","sheet_x":11,"sheet_y":0,"short_name":"leopard","short_names":["leopard"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":577,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RABBIT","unified":"1F407","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f407.png","sheet_x":11,"sheet_y":1,"short_name":"rabbit2","short_names":["rabbit2"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":610,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK CAT","unified":"1F408-200D-2B1B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f408-200d-2b1b.png","sheet_x":11,"sheet_y":2,"short_name":"black_cat","short_names":["black_cat"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":573,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CAT","unified":"1F408","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f408.png","sheet_x":11,"sheet_y":3,"short_name":"cat2","short_names":["cat2"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":572,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DRAGON","unified":"1F409","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f409.png","sheet_x":11,"sheet_y":4,"short_name":"dragon","short_names":["dragon"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-reptile","sort_order":653,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CROCODILE","unified":"1F40A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f40a.png","sheet_x":11,"sheet_y":5,"short_name":"crocodile","short_names":["crocodile"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-reptile","sort_order":648,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHALE","unified":"1F40B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f40b.png","sheet_x":11,"sheet_y":6,"short_name":"whale2","short_names":["whale2"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":657,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SNAIL","unified":"1F40C","non_qualified":null,"docomo":"E74E","au":"EB7E","softbank":null,"google":"FE1B9","image":"1f40c.png","sheet_x":11,"sheet_y":7,"short_name":"snail","short_names":["snail"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":668,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SNAKE","unified":"1F40D","non_qualified":null,"docomo":null,"au":"EB22","softbank":"E52D","google":"FE1D3","image":"1f40d.png","sheet_x":11,"sheet_y":8,"short_name":"snake","short_names":["snake"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-reptile","sort_order":651,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HORSE","unified":"1F40E","non_qualified":null,"docomo":"E754","au":"E4D8","softbank":"E134","google":"FE7DC","image":"1f40e.png","sheet_x":11,"sheet_y":9,"short_name":"racehorse","short_names":["racehorse"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":581,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RAM","unified":"1F40F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f40f.png","sheet_x":11,"sheet_y":10,"short_name":"ram","short_names":["ram"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":594,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GOAT","unified":"1F410","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f410.png","sheet_x":11,"sheet_y":11,"short_name":"goat","short_names":["goat"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":596,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHEEP","unified":"1F411","non_qualified":null,"docomo":null,"au":"E48F","softbank":"E529","google":"FE1CF","image":"1f411.png","sheet_x":11,"sheet_y":12,"short_name":"sheep","short_names":["sheep"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":595,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MONKEY","unified":"1F412","non_qualified":null,"docomo":null,"au":"E4D9","softbank":"E528","google":"FE1CE","image":"1f412.png","sheet_x":11,"sheet_y":13,"short_name":"monkey","short_names":["monkey"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":560,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROOSTER","unified":"1F413","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f413.png","sheet_x":11,"sheet_y":14,"short_name":"rooster","short_names":["rooster"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":627,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHICKEN","unified":"1F414","non_qualified":null,"docomo":null,"au":"EB23","softbank":"E52E","google":"FE1D4","image":"1f414.png","sheet_x":11,"sheet_y":15,"short_name":"chicken","short_names":["chicken"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":626,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SERVICE DOG","unified":"1F415-200D-1F9BA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f415-200d-1f9ba.png","sheet_x":11,"sheet_y":16,"short_name":"service_dog","short_names":["service_dog"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":566,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOG","unified":"1F415","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f415.png","sheet_x":11,"sheet_y":17,"short_name":"dog2","short_names":["dog2"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":564,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PIG","unified":"1F416","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f416.png","sheet_x":11,"sheet_y":18,"short_name":"pig2","short_names":["pig2"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":591,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOAR","unified":"1F417","non_qualified":null,"docomo":null,"au":"EB24","softbank":"E52F","google":"FE1D5","image":"1f417.png","sheet_x":11,"sheet_y":19,"short_name":"boar","short_names":["boar"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":592,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ELEPHANT","unified":"1F418","non_qualified":null,"docomo":null,"au":"EB1F","softbank":"E526","google":"FE1CC","image":"1f418.png","sheet_x":11,"sheet_y":20,"short_name":"elephant","short_names":["elephant"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":601,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OCTOPUS","unified":"1F419","non_qualified":null,"docomo":null,"au":"E5C7","softbank":"E10A","google":"FE1C5","image":"1f419.png","sheet_x":11,"sheet_y":21,"short_name":"octopus","short_names":["octopus"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":664,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPIRAL SHELL","unified":"1F41A","non_qualified":null,"docomo":null,"au":"EAEC","softbank":"E441","google":"FE1C6","image":"1f41a.png","sheet_x":11,"sheet_y":22,"short_name":"shell","short_names":["shell"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":665,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUG","unified":"1F41B","non_qualified":null,"docomo":null,"au":"EB1E","softbank":"E525","google":"FE1CB","image":"1f41b.png","sheet_x":11,"sheet_y":23,"short_name":"bug","short_names":["bug"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":670,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ANT","unified":"1F41C","non_qualified":null,"docomo":null,"au":"E4DD","softbank":null,"google":"FE1DA","image":"1f41c.png","sheet_x":11,"sheet_y":24,"short_name":"ant","short_names":["ant"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":671,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HONEYBEE","unified":"1F41D","non_qualified":null,"docomo":null,"au":"EB57","softbank":null,"google":"FE1E1","image":"1f41d.png","sheet_x":11,"sheet_y":25,"short_name":"bee","short_names":["bee","honeybee"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":672,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LADY BEETLE","unified":"1F41E","non_qualified":null,"docomo":null,"au":"EB58","softbank":null,"google":"FE1E2","image":"1f41e.png","sheet_x":11,"sheet_y":26,"short_name":"ladybug","short_names":["ladybug","lady_beetle"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":674,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FISH","unified":"1F41F","non_qualified":null,"docomo":"E751","au":"E49A","softbank":"E019","google":"FE1BD","image":"1f41f.png","sheet_x":11,"sheet_y":27,"short_name":"fish","short_names":["fish"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":660,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TROPICAL FISH","unified":"1F420","non_qualified":null,"docomo":"E751","au":"EB1D","softbank":"E522","google":"FE1C9","image":"1f420.png","sheet_x":11,"sheet_y":28,"short_name":"tropical_fish","short_names":["tropical_fish"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":661,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLOWFISH","unified":"1F421","non_qualified":null,"docomo":"E751","au":"E4D3","softbank":null,"google":"FE1D9","image":"1f421.png","sheet_x":11,"sheet_y":29,"short_name":"blowfish","short_names":["blowfish"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":662,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TURTLE","unified":"1F422","non_qualified":null,"docomo":null,"au":"E5D4","softbank":null,"google":"FE1DC","image":"1f422.png","sheet_x":11,"sheet_y":30,"short_name":"turtle","short_names":["turtle"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-reptile","sort_order":649,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HATCHING CHICK","unified":"1F423","non_qualified":null,"docomo":"E74F","au":"E5DB","softbank":null,"google":"FE1DD","image":"1f423.png","sheet_x":11,"sheet_y":31,"short_name":"hatching_chick","short_names":["hatching_chick"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":628,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BABY CHICK","unified":"1F424","non_qualified":null,"docomo":"E74F","au":"E4E0","softbank":"E523","google":"FE1BA","image":"1f424.png","sheet_x":11,"sheet_y":32,"short_name":"baby_chick","short_names":["baby_chick"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":629,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FRONT-FACING BABY CHICK","unified":"1F425","non_qualified":null,"docomo":"E74F","au":"EB76","softbank":null,"google":"FE1BB","image":"1f425.png","sheet_x":11,"sheet_y":33,"short_name":"hatched_chick","short_names":["hatched_chick"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":630,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PHOENIX","unified":"1F426-200D-1F525","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f426-200d-1f525.png","sheet_x":11,"sheet_y":34,"short_name":"phoenix","short_names":["phoenix"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":646,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"BLACK BIRD","unified":"1F426-200D-2B1B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f426-200d-2b1b.png","sheet_x":11,"sheet_y":35,"short_name":"black_bird","short_names":["black_bird"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":644,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BIRD","unified":"1F426","non_qualified":null,"docomo":"E74F","au":"E4E0","softbank":"E521","google":"FE1C8","image":"1f426.png","sheet_x":11,"sheet_y":36,"short_name":"bird","short_names":["bird"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":631,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PENGUIN","unified":"1F427","non_qualified":null,"docomo":"E750","au":"E4DC","softbank":"E055","google":"FE1BC","image":"1f427.png","sheet_x":11,"sheet_y":37,"short_name":"penguin","short_names":["penguin"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":632,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KOALA","unified":"1F428","non_qualified":null,"docomo":null,"au":"EB20","softbank":"E527","google":"FE1CD","image":"1f428.png","sheet_x":11,"sheet_y":38,"short_name":"koala","short_names":["koala"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":617,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POODLE","unified":"1F429","non_qualified":null,"docomo":"E6A1","au":"E4DF","softbank":null,"google":"FE1D8","image":"1f429.png","sheet_x":11,"sheet_y":39,"short_name":"poodle","short_names":["poodle"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":567,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DROMEDARY CAMEL","unified":"1F42A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f42a.png","sheet_x":11,"sheet_y":40,"short_name":"dromedary_camel","short_names":["dromedary_camel"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":597,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BACTRIAN CAMEL","unified":"1F42B","non_qualified":null,"docomo":null,"au":"EB25","softbank":"E530","google":"FE1D6","image":"1f42b.png","sheet_x":11,"sheet_y":41,"short_name":"camel","short_names":["camel"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":598,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOLPHIN","unified":"1F42C","non_qualified":null,"docomo":null,"au":"EB1B","softbank":"E520","google":"FE1C7","image":"1f42c.png","sheet_x":11,"sheet_y":42,"short_name":"dolphin","short_names":["dolphin","flipper"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":658,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOUSE FACE","unified":"1F42D","non_qualified":null,"docomo":null,"au":"E5C2","softbank":"E053","google":"FE1C2","image":"1f42d.png","sheet_x":11,"sheet_y":43,"short_name":"mouse","short_names":["mouse"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":605,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COW FACE","unified":"1F42E","non_qualified":null,"docomo":null,"au":"EB21","softbank":"E52B","google":"FE1D1","image":"1f42e.png","sheet_x":11,"sheet_y":44,"short_name":"cow","short_names":["cow"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":586,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TIGER FACE","unified":"1F42F","non_qualified":null,"docomo":null,"au":"E5C0","softbank":"E050","google":"FE1C0","image":"1f42f.png","sheet_x":11,"sheet_y":45,"short_name":"tiger","short_names":["tiger"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":575,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RABBIT FACE","unified":"1F430","non_qualified":null,"docomo":null,"au":"E4D7","softbank":"E52C","google":"FE1D2","image":"1f430.png","sheet_x":11,"sheet_y":46,"short_name":"rabbit","short_names":["rabbit"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":609,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CAT FACE","unified":"1F431","non_qualified":null,"docomo":"E6A2","au":"E4DB","softbank":"E04F","google":"FE1B8","image":"1f431.png","sheet_x":11,"sheet_y":47,"short_name":"cat","short_names":["cat"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":571,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DRAGON FACE","unified":"1F432","non_qualified":null,"docomo":null,"au":"EB3F","softbank":null,"google":"FE1DE","image":"1f432.png","sheet_x":11,"sheet_y":48,"short_name":"dragon_face","short_names":["dragon_face"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-reptile","sort_order":652,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPOUTING WHALE","unified":"1F433","non_qualified":null,"docomo":null,"au":"E470","softbank":"E054","google":"FE1C3","image":"1f433.png","sheet_x":11,"sheet_y":49,"short_name":"whale","short_names":["whale"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":656,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HORSE FACE","unified":"1F434","non_qualified":null,"docomo":"E754","au":"E4D8","softbank":"E01A","google":"FE1BE","image":"1f434.png","sheet_x":11,"sheet_y":50,"short_name":"horse","short_names":["horse"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":578,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MONKEY FACE","unified":"1F435","non_qualified":null,"docomo":null,"au":"E4D9","softbank":"E109","google":"FE1C4","image":"1f435.png","sheet_x":11,"sheet_y":51,"short_name":"monkey_face","short_names":["monkey_face"],"text":null,"texts":[":o)"],"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":559,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOG FACE","unified":"1F436","non_qualified":null,"docomo":"E6A1","au":"E4E1","softbank":"E052","google":"FE1B7","image":"1f436.png","sheet_x":11,"sheet_y":52,"short_name":"dog","short_names":["dog"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":563,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PIG FACE","unified":"1F437","non_qualified":null,"docomo":"E755","au":"E4DE","softbank":"E10B","google":"FE1BF","image":"1f437.png","sheet_x":11,"sheet_y":53,"short_name":"pig","short_names":["pig"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":590,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FROG FACE","unified":"1F438","non_qualified":null,"docomo":null,"au":"E4DA","softbank":"E531","google":"FE1D7","image":"1f438.png","sheet_x":11,"sheet_y":54,"short_name":"frog","short_names":["frog"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-amphibian","sort_order":647,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HAMSTER FACE","unified":"1F439","non_qualified":null,"docomo":null,"au":null,"softbank":"E524","google":"FE1CA","image":"1f439.png","sheet_x":11,"sheet_y":55,"short_name":"hamster","short_names":["hamster"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":608,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOLF FACE","unified":"1F43A","non_qualified":null,"docomo":"E6A1","au":"E4E1","softbank":"E52A","google":"FE1D0","image":"1f43a.png","sheet_x":11,"sheet_y":56,"short_name":"wolf","short_names":["wolf"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":568,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POLAR BEAR","unified":"1F43B-200D-2744-FE0F","non_qualified":"1F43B-200D-2744","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f43b-200d-2744-fe0f.png","sheet_x":11,"sheet_y":57,"short_name":"polar_bear","short_names":["polar_bear"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":616,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BEAR FACE","unified":"1F43B","non_qualified":null,"docomo":null,"au":"E5C1","softbank":"E051","google":"FE1C1","image":"1f43b.png","sheet_x":11,"sheet_y":58,"short_name":"bear","short_names":["bear"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":615,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PANDA FACE","unified":"1F43C","non_qualified":null,"docomo":null,"au":"EB46","softbank":null,"google":"FE1DF","image":"1f43c.png","sheet_x":11,"sheet_y":59,"short_name":"panda_face","short_names":["panda_face"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":618,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PIG NOSE","unified":"1F43D","non_qualified":null,"docomo":"E755","au":"EB48","softbank":null,"google":"FE1E0","image":"1f43d.png","sheet_x":11,"sheet_y":60,"short_name":"pig_nose","short_names":["pig_nose"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":593,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PAW PRINTS","unified":"1F43E","non_qualified":null,"docomo":"E698","au":"E4EE","softbank":null,"google":"FE1DB","image":"1f43e.png","sheet_x":11,"sheet_y":61,"short_name":"feet","short_names":["feet","paw_prints"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":624,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHIPMUNK","unified":"1F43F-FE0F","non_qualified":"1F43F","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f43f-fe0f.png","sheet_x":12,"sheet_y":0,"short_name":"chipmunk","short_names":["chipmunk"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":611,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EYES","unified":"1F440","non_qualified":null,"docomo":"E691","au":"E5A4","softbank":"E419","google":"FE190","image":"1f440.png","sheet_x":12,"sheet_y":1,"short_name":"eyes","short_names":["eyes"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":225,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EYE IN SPEECH BUBBLE","unified":"1F441-FE0F-200D-1F5E8-FE0F","non_qualified":"1F441-200D-1F5E8","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f441-fe0f-200d-1f5e8-fe0f.png","sheet_x":12,"sheet_y":2,"short_name":"eye-in-speech-bubble","short_names":["eye-in-speech-bubble"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":164,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false},{"name":"EYE","unified":"1F441-FE0F","non_qualified":"1F441","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f441-fe0f.png","sheet_x":12,"sheet_y":3,"short_name":"eye","short_names":["eye"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":226,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EAR","unified":"1F442","non_qualified":null,"docomo":"E692","au":"E5A5","softbank":"E41B","google":"FE191","image":"1f442.png","sheet_x":12,"sheet_y":4,"short_name":"ear","short_names":["ear"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":217,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F442-1F3FB","non_qualified":null,"image":"1f442-1f3fb.png","sheet_x":12,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F442-1F3FC","non_qualified":null,"image":"1f442-1f3fc.png","sheet_x":12,"sheet_y":6,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F442-1F3FD","non_qualified":null,"image":"1f442-1f3fd.png","sheet_x":12,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F442-1F3FE","non_qualified":null,"image":"1f442-1f3fe.png","sheet_x":12,"sheet_y":8,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F442-1F3FF","non_qualified":null,"image":"1f442-1f3ff.png","sheet_x":12,"sheet_y":9,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"NOSE","unified":"1F443","non_qualified":null,"docomo":null,"au":"EAD0","softbank":"E41A","google":"FE192","image":"1f443.png","sheet_x":12,"sheet_y":10,"short_name":"nose","short_names":["nose"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":219,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F443-1F3FB","non_qualified":null,"image":"1f443-1f3fb.png","sheet_x":12,"sheet_y":11,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F443-1F3FC","non_qualified":null,"image":"1f443-1f3fc.png","sheet_x":12,"sheet_y":12,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F443-1F3FD","non_qualified":null,"image":"1f443-1f3fd.png","sheet_x":12,"sheet_y":13,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F443-1F3FE","non_qualified":null,"image":"1f443-1f3fe.png","sheet_x":12,"sheet_y":14,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F443-1F3FF","non_qualified":null,"image":"1f443-1f3ff.png","sheet_x":12,"sheet_y":15,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MOUTH","unified":"1F444","non_qualified":null,"docomo":"E6F9","au":"EAD1","softbank":"E41C","google":"FE193","image":"1f444.png","sheet_x":12,"sheet_y":16,"short_name":"lips","short_names":["lips"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":228,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TONGUE","unified":"1F445","non_qualified":null,"docomo":"E728","au":"EB47","softbank":null,"google":"FE194","image":"1f445.png","sheet_x":12,"sheet_y":17,"short_name":"tongue","short_names":["tongue"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":227,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE UP POINTING BACKHAND INDEX","unified":"1F446","non_qualified":null,"docomo":null,"au":"EA8D","softbank":"E22E","google":"FEB99","image":"1f446.png","sheet_x":12,"sheet_y":18,"short_name":"point_up_2","short_names":["point_up_2"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-single-finger","sort_order":191,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F446-1F3FB","non_qualified":null,"image":"1f446-1f3fb.png","sheet_x":12,"sheet_y":19,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F446-1F3FC","non_qualified":null,"image":"1f446-1f3fc.png","sheet_x":12,"sheet_y":20,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F446-1F3FD","non_qualified":null,"image":"1f446-1f3fd.png","sheet_x":12,"sheet_y":21,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F446-1F3FE","non_qualified":null,"image":"1f446-1f3fe.png","sheet_x":12,"sheet_y":22,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F446-1F3FF","non_qualified":null,"image":"1f446-1f3ff.png","sheet_x":12,"sheet_y":23,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WHITE DOWN POINTING BACKHAND INDEX","unified":"1F447","non_qualified":null,"docomo":null,"au":"EA8E","softbank":"E22F","google":"FEB9A","image":"1f447.png","sheet_x":12,"sheet_y":24,"short_name":"point_down","short_names":["point_down"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-single-finger","sort_order":193,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F447-1F3FB","non_qualified":null,"image":"1f447-1f3fb.png","sheet_x":12,"sheet_y":25,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F447-1F3FC","non_qualified":null,"image":"1f447-1f3fc.png","sheet_x":12,"sheet_y":26,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F447-1F3FD","non_qualified":null,"image":"1f447-1f3fd.png","sheet_x":12,"sheet_y":27,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F447-1F3FE","non_qualified":null,"image":"1f447-1f3fe.png","sheet_x":12,"sheet_y":28,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F447-1F3FF","non_qualified":null,"image":"1f447-1f3ff.png","sheet_x":12,"sheet_y":29,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WHITE LEFT POINTING BACKHAND INDEX","unified":"1F448","non_qualified":null,"docomo":null,"au":"E4FF","softbank":"E230","google":"FEB9B","image":"1f448.png","sheet_x":12,"sheet_y":30,"short_name":"point_left","short_names":["point_left"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-single-finger","sort_order":189,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F448-1F3FB","non_qualified":null,"image":"1f448-1f3fb.png","sheet_x":12,"sheet_y":31,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F448-1F3FC","non_qualified":null,"image":"1f448-1f3fc.png","sheet_x":12,"sheet_y":32,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F448-1F3FD","non_qualified":null,"image":"1f448-1f3fd.png","sheet_x":12,"sheet_y":33,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F448-1F3FE","non_qualified":null,"image":"1f448-1f3fe.png","sheet_x":12,"sheet_y":34,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F448-1F3FF","non_qualified":null,"image":"1f448-1f3ff.png","sheet_x":12,"sheet_y":35,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WHITE RIGHT POINTING BACKHAND INDEX","unified":"1F449","non_qualified":null,"docomo":null,"au":"E500","softbank":"E231","google":"FEB9C","image":"1f449.png","sheet_x":12,"sheet_y":36,"short_name":"point_right","short_names":["point_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-single-finger","sort_order":190,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F449-1F3FB","non_qualified":null,"image":"1f449-1f3fb.png","sheet_x":12,"sheet_y":37,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F449-1F3FC","non_qualified":null,"image":"1f449-1f3fc.png","sheet_x":12,"sheet_y":38,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F449-1F3FD","non_qualified":null,"image":"1f449-1f3fd.png","sheet_x":12,"sheet_y":39,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F449-1F3FE","non_qualified":null,"image":"1f449-1f3fe.png","sheet_x":12,"sheet_y":40,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F449-1F3FF","non_qualified":null,"image":"1f449-1f3ff.png","sheet_x":12,"sheet_y":41,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FISTED HAND SIGN","unified":"1F44A","non_qualified":null,"docomo":"E6FD","au":"E4F3","softbank":"E00D","google":"FEB96","image":"1f44a.png","sheet_x":12,"sheet_y":42,"short_name":"facepunch","short_names":["facepunch","punch"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-closed","sort_order":199,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F44A-1F3FB","non_qualified":null,"image":"1f44a-1f3fb.png","sheet_x":12,"sheet_y":43,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F44A-1F3FC","non_qualified":null,"image":"1f44a-1f3fc.png","sheet_x":12,"sheet_y":44,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F44A-1F3FD","non_qualified":null,"image":"1f44a-1f3fd.png","sheet_x":12,"sheet_y":45,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F44A-1F3FE","non_qualified":null,"image":"1f44a-1f3fe.png","sheet_x":12,"sheet_y":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F44A-1F3FF","non_qualified":null,"image":"1f44a-1f3ff.png","sheet_x":12,"sheet_y":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WAVING HAND SIGN","unified":"1F44B","non_qualified":null,"docomo":"E695","au":"EAD6","softbank":"E41E","google":"FEB9D","image":"1f44b.png","sheet_x":12,"sheet_y":48,"short_name":"wave","short_names":["wave"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":169,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F44B-1F3FB","non_qualified":null,"image":"1f44b-1f3fb.png","sheet_x":12,"sheet_y":49,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F44B-1F3FC","non_qualified":null,"image":"1f44b-1f3fc.png","sheet_x":12,"sheet_y":50,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F44B-1F3FD","non_qualified":null,"image":"1f44b-1f3fd.png","sheet_x":12,"sheet_y":51,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F44B-1F3FE","non_qualified":null,"image":"1f44b-1f3fe.png","sheet_x":12,"sheet_y":52,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F44B-1F3FF","non_qualified":null,"image":"1f44b-1f3ff.png","sheet_x":12,"sheet_y":53,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"OK HAND SIGN","unified":"1F44C","non_qualified":null,"docomo":"E70B","au":"EAD4","softbank":"E420","google":"FEB9F","image":"1f44c.png","sheet_x":12,"sheet_y":54,"short_name":"ok_hand","short_names":["ok_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-partial","sort_order":180,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F44C-1F3FB","non_qualified":null,"image":"1f44c-1f3fb.png","sheet_x":12,"sheet_y":55,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F44C-1F3FC","non_qualified":null,"image":"1f44c-1f3fc.png","sheet_x":12,"sheet_y":56,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F44C-1F3FD","non_qualified":null,"image":"1f44c-1f3fd.png","sheet_x":12,"sheet_y":57,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F44C-1F3FE","non_qualified":null,"image":"1f44c-1f3fe.png","sheet_x":12,"sheet_y":58,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F44C-1F3FF","non_qualified":null,"image":"1f44c-1f3ff.png","sheet_x":12,"sheet_y":59,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"THUMBS UP SIGN","unified":"1F44D","non_qualified":null,"docomo":"E727","au":"E4F9","softbank":"E00E","google":"FEB97","image":"1f44d.png","sheet_x":12,"sheet_y":60,"short_name":"+1","short_names":["+1","thumbsup"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-closed","sort_order":196,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F44D-1F3FB","non_qualified":null,"image":"1f44d-1f3fb.png","sheet_x":12,"sheet_y":61,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F44D-1F3FC","non_qualified":null,"image":"1f44d-1f3fc.png","sheet_x":13,"sheet_y":0,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F44D-1F3FD","non_qualified":null,"image":"1f44d-1f3fd.png","sheet_x":13,"sheet_y":1,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F44D-1F3FE","non_qualified":null,"image":"1f44d-1f3fe.png","sheet_x":13,"sheet_y":2,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F44D-1F3FF","non_qualified":null,"image":"1f44d-1f3ff.png","sheet_x":13,"sheet_y":3,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"THUMBS DOWN SIGN","unified":"1F44E","non_qualified":null,"docomo":"E700","au":"EAD5","softbank":"E421","google":"FEBA0","image":"1f44e.png","sheet_x":13,"sheet_y":4,"short_name":"-1","short_names":["-1","thumbsdown"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-closed","sort_order":197,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F44E-1F3FB","non_qualified":null,"image":"1f44e-1f3fb.png","sheet_x":13,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F44E-1F3FC","non_qualified":null,"image":"1f44e-1f3fc.png","sheet_x":13,"sheet_y":6,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F44E-1F3FD","non_qualified":null,"image":"1f44e-1f3fd.png","sheet_x":13,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F44E-1F3FE","non_qualified":null,"image":"1f44e-1f3fe.png","sheet_x":13,"sheet_y":8,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F44E-1F3FF","non_qualified":null,"image":"1f44e-1f3ff.png","sheet_x":13,"sheet_y":9,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"CLAPPING HANDS SIGN","unified":"1F44F","non_qualified":null,"docomo":null,"au":"EAD3","softbank":"E41F","google":"FEB9E","image":"1f44f.png","sheet_x":13,"sheet_y":10,"short_name":"clap","short_names":["clap"],"text":null,"texts":null,"category":"People & Body","subcategory":"hands","sort_order":202,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F44F-1F3FB","non_qualified":null,"image":"1f44f-1f3fb.png","sheet_x":13,"sheet_y":11,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F44F-1F3FC","non_qualified":null,"image":"1f44f-1f3fc.png","sheet_x":13,"sheet_y":12,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F44F-1F3FD","non_qualified":null,"image":"1f44f-1f3fd.png","sheet_x":13,"sheet_y":13,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F44F-1F3FE","non_qualified":null,"image":"1f44f-1f3fe.png","sheet_x":13,"sheet_y":14,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F44F-1F3FF","non_qualified":null,"image":"1f44f-1f3ff.png","sheet_x":13,"sheet_y":15,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"OPEN HANDS SIGN","unified":"1F450","non_qualified":null,"docomo":"E695","au":"EAD6","softbank":"E422","google":"FEBA1","image":"1f450.png","sheet_x":13,"sheet_y":16,"short_name":"open_hands","short_names":["open_hands"],"text":null,"texts":null,"category":"People & Body","subcategory":"hands","sort_order":205,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F450-1F3FB","non_qualified":null,"image":"1f450-1f3fb.png","sheet_x":13,"sheet_y":17,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F450-1F3FC","non_qualified":null,"image":"1f450-1f3fc.png","sheet_x":13,"sheet_y":18,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F450-1F3FD","non_qualified":null,"image":"1f450-1f3fd.png","sheet_x":13,"sheet_y":19,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F450-1F3FE","non_qualified":null,"image":"1f450-1f3fe.png","sheet_x":13,"sheet_y":20,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F450-1F3FF","non_qualified":null,"image":"1f450-1f3ff.png","sheet_x":13,"sheet_y":21,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"CROWN","unified":"1F451","non_qualified":null,"docomo":"E71A","au":"E5C9","softbank":"E10E","google":"FE4D1","image":"1f451.png","sheet_x":13,"sheet_y":22,"short_name":"crown","short_names":["crown"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1186,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMANS HAT","unified":"1F452","non_qualified":null,"docomo":null,"au":"EA9E","softbank":"E318","google":"FE4D4","image":"1f452.png","sheet_x":13,"sheet_y":23,"short_name":"womans_hat","short_names":["womans_hat"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1187,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EYEGLASSES","unified":"1F453","non_qualified":null,"docomo":"E69A","au":"E4FE","softbank":null,"google":"FE4CE","image":"1f453.png","sheet_x":13,"sheet_y":24,"short_name":"eyeglasses","short_names":["eyeglasses"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1150,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NECKTIE","unified":"1F454","non_qualified":null,"docomo":null,"au":"EA93","softbank":"E302","google":"FE4D3","image":"1f454.png","sheet_x":13,"sheet_y":25,"short_name":"necktie","short_names":["necktie"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1155,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"T-SHIRT","unified":"1F455","non_qualified":null,"docomo":"E70E","au":"E5B6","softbank":"E006","google":"FE4CF","image":"1f455.png","sheet_x":13,"sheet_y":26,"short_name":"shirt","short_names":["shirt","tshirt"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1156,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JEANS","unified":"1F456","non_qualified":null,"docomo":"E711","au":"EB77","softbank":null,"google":"FE4D0","image":"1f456.png","sheet_x":13,"sheet_y":27,"short_name":"jeans","short_names":["jeans"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1157,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DRESS","unified":"1F457","non_qualified":null,"docomo":null,"au":"EB6B","softbank":"E319","google":"FE4D5","image":"1f457.png","sheet_x":13,"sheet_y":28,"short_name":"dress","short_names":["dress"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1162,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KIMONO","unified":"1F458","non_qualified":null,"docomo":null,"au":"EAA3","softbank":"E321","google":"FE4D9","image":"1f458.png","sheet_x":13,"sheet_y":29,"short_name":"kimono","short_names":["kimono"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1163,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BIKINI","unified":"1F459","non_qualified":null,"docomo":null,"au":"EAA4","softbank":"E322","google":"FE4DA","image":"1f459.png","sheet_x":13,"sheet_y":30,"short_name":"bikini","short_names":["bikini"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1168,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMANS CLOTHES","unified":"1F45A","non_qualified":null,"docomo":"E70E","au":"E50D","softbank":null,"google":"FE4DB","image":"1f45a.png","sheet_x":13,"sheet_y":31,"short_name":"womans_clothes","short_names":["womans_clothes"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1169,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PURSE","unified":"1F45B","non_qualified":null,"docomo":"E70F","au":"E504","softbank":null,"google":"FE4DC","image":"1f45b.png","sheet_x":13,"sheet_y":32,"short_name":"purse","short_names":["purse"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1171,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HANDBAG","unified":"1F45C","non_qualified":null,"docomo":"E682","au":"E49C","softbank":"E323","google":"FE4F0","image":"1f45c.png","sheet_x":13,"sheet_y":33,"short_name":"handbag","short_names":["handbag"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1172,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POUCH","unified":"1F45D","non_qualified":null,"docomo":"E6AD","au":null,"softbank":null,"google":"FE4F1","image":"1f45d.png","sheet_x":13,"sheet_y":34,"short_name":"pouch","short_names":["pouch"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1173,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MANS SHOE","unified":"1F45E","non_qualified":null,"docomo":"E699","au":"E5B7","softbank":null,"google":"FE4CC","image":"1f45e.png","sheet_x":13,"sheet_y":35,"short_name":"mans_shoe","short_names":["mans_shoe","shoe"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1177,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ATHLETIC SHOE","unified":"1F45F","non_qualified":null,"docomo":"E699","au":"EB2B","softbank":"E007","google":"FE4CD","image":"1f45f.png","sheet_x":13,"sheet_y":36,"short_name":"athletic_shoe","short_names":["athletic_shoe"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1178,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HIGH-HEELED SHOE","unified":"1F460","non_qualified":null,"docomo":"E674","au":"E51A","softbank":"E13E","google":"FE4D6","image":"1f460.png","sheet_x":13,"sheet_y":37,"short_name":"high_heel","short_names":["high_heel"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1181,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMANS SANDAL","unified":"1F461","non_qualified":null,"docomo":"E674","au":"E51A","softbank":"E31A","google":"FE4D7","image":"1f461.png","sheet_x":13,"sheet_y":38,"short_name":"sandal","short_names":["sandal"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1182,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMANS BOOTS","unified":"1F462","non_qualified":null,"docomo":null,"au":"EA9F","softbank":"E31B","google":"FE4D8","image":"1f462.png","sheet_x":13,"sheet_y":39,"short_name":"boot","short_names":["boot"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1184,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FOOTPRINTS","unified":"1F463","non_qualified":null,"docomo":"E698","au":"EB2A","softbank":"E536","google":"FE553","image":"1f463.png","sheet_x":13,"sheet_y":40,"short_name":"footprints","short_names":["footprints"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":553,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUST IN SILHOUETTE","unified":"1F464","non_qualified":null,"docomo":"E6B1","au":null,"softbank":null,"google":"FE19A","image":"1f464.png","sheet_x":13,"sheet_y":41,"short_name":"bust_in_silhouette","short_names":["bust_in_silhouette"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":545,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUSTS IN SILHOUETTE","unified":"1F465","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f465.png","sheet_x":13,"sheet_y":42,"short_name":"busts_in_silhouette","short_names":["busts_in_silhouette"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":546,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOY","unified":"1F466","non_qualified":null,"docomo":"E6F0","au":"E4FC","softbank":"E001","google":"FE19B","image":"1f466.png","sheet_x":13,"sheet_y":43,"short_name":"boy","short_names":["boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":232,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F466-1F3FB","non_qualified":null,"image":"1f466-1f3fb.png","sheet_x":13,"sheet_y":44,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F466-1F3FC","non_qualified":null,"image":"1f466-1f3fc.png","sheet_x":13,"sheet_y":45,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F466-1F3FD","non_qualified":null,"image":"1f466-1f3fd.png","sheet_x":13,"sheet_y":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F466-1F3FE","non_qualified":null,"image":"1f466-1f3fe.png","sheet_x":13,"sheet_y":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F466-1F3FF","non_qualified":null,"image":"1f466-1f3ff.png","sheet_x":13,"sheet_y":48,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"GIRL","unified":"1F467","non_qualified":null,"docomo":"E6F0","au":"E4FA","softbank":"E002","google":"FE19C","image":"1f467.png","sheet_x":13,"sheet_y":49,"short_name":"girl","short_names":["girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":233,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F467-1F3FB","non_qualified":null,"image":"1f467-1f3fb.png","sheet_x":13,"sheet_y":50,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F467-1F3FC","non_qualified":null,"image":"1f467-1f3fc.png","sheet_x":13,"sheet_y":51,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F467-1F3FD","non_qualified":null,"image":"1f467-1f3fd.png","sheet_x":13,"sheet_y":52,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F467-1F3FE","non_qualified":null,"image":"1f467-1f3fe.png","sheet_x":13,"sheet_y":53,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F467-1F3FF","non_qualified":null,"image":"1f467-1f3ff.png","sheet_x":13,"sheet_y":54,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN FARMER","unified":"1F468-200D-1F33E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f33e.png","sheet_x":13,"sheet_y":55,"short_name":"male-farmer","short_names":["male-farmer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":301,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F33E","non_qualified":null,"image":"1f468-1f3fb-200d-1f33e.png","sheet_x":13,"sheet_y":56,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F33E","non_qualified":null,"image":"1f468-1f3fc-200d-1f33e.png","sheet_x":13,"sheet_y":57,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F33E","non_qualified":null,"image":"1f468-1f3fd-200d-1f33e.png","sheet_x":13,"sheet_y":58,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F33E","non_qualified":null,"image":"1f468-1f3fe-200d-1f33e.png","sheet_x":13,"sheet_y":59,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F33E","non_qualified":null,"image":"1f468-1f3ff-200d-1f33e.png","sheet_x":13,"sheet_y":60,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN COOK","unified":"1F468-200D-1F373","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f373.png","sheet_x":13,"sheet_y":61,"short_name":"male-cook","short_names":["male-cook"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":304,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F373","non_qualified":null,"image":"1f468-1f3fb-200d-1f373.png","sheet_x":14,"sheet_y":0,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F373","non_qualified":null,"image":"1f468-1f3fc-200d-1f373.png","sheet_x":14,"sheet_y":1,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F373","non_qualified":null,"image":"1f468-1f3fd-200d-1f373.png","sheet_x":14,"sheet_y":2,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F373","non_qualified":null,"image":"1f468-1f3fe-200d-1f373.png","sheet_x":14,"sheet_y":3,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F373","non_qualified":null,"image":"1f468-1f3ff-200d-1f373.png","sheet_x":14,"sheet_y":4,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN FEEDING BABY","unified":"1F468-200D-1F37C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f37c.png","sheet_x":14,"sheet_y":5,"short_name":"man_feeding_baby","short_names":["man_feeding_baby"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":368,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F37C","non_qualified":null,"image":"1f468-1f3fb-200d-1f37c.png","sheet_x":14,"sheet_y":6,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F37C","non_qualified":null,"image":"1f468-1f3fc-200d-1f37c.png","sheet_x":14,"sheet_y":7,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F37C","non_qualified":null,"image":"1f468-1f3fd-200d-1f37c.png","sheet_x":14,"sheet_y":8,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F37C","non_qualified":null,"image":"1f468-1f3fe-200d-1f37c.png","sheet_x":14,"sheet_y":9,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F37C","non_qualified":null,"image":"1f468-1f3ff-200d-1f37c.png","sheet_x":14,"sheet_y":10,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN STUDENT","unified":"1F468-200D-1F393","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f393.png","sheet_x":14,"sheet_y":11,"short_name":"male-student","short_names":["male-student"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":292,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F393","non_qualified":null,"image":"1f468-1f3fb-200d-1f393.png","sheet_x":14,"sheet_y":12,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F393","non_qualified":null,"image":"1f468-1f3fc-200d-1f393.png","sheet_x":14,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F393","non_qualified":null,"image":"1f468-1f3fd-200d-1f393.png","sheet_x":14,"sheet_y":14,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F393","non_qualified":null,"image":"1f468-1f3fe-200d-1f393.png","sheet_x":14,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F393","non_qualified":null,"image":"1f468-1f3ff-200d-1f393.png","sheet_x":14,"sheet_y":16,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN SINGER","unified":"1F468-200D-1F3A4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f3a4.png","sheet_x":14,"sheet_y":17,"short_name":"male-singer","short_names":["male-singer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":322,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F3A4","non_qualified":null,"image":"1f468-1f3fb-200d-1f3a4.png","sheet_x":14,"sheet_y":18,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F3A4","non_qualified":null,"image":"1f468-1f3fc-200d-1f3a4.png","sheet_x":14,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F3A4","non_qualified":null,"image":"1f468-1f3fd-200d-1f3a4.png","sheet_x":14,"sheet_y":20,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F3A4","non_qualified":null,"image":"1f468-1f3fe-200d-1f3a4.png","sheet_x":14,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F3A4","non_qualified":null,"image":"1f468-1f3ff-200d-1f3a4.png","sheet_x":14,"sheet_y":22,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN ARTIST","unified":"1F468-200D-1F3A8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f3a8.png","sheet_x":14,"sheet_y":23,"short_name":"male-artist","short_names":["male-artist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":325,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F3A8","non_qualified":null,"image":"1f468-1f3fb-200d-1f3a8.png","sheet_x":14,"sheet_y":24,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F3A8","non_qualified":null,"image":"1f468-1f3fc-200d-1f3a8.png","sheet_x":14,"sheet_y":25,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F3A8","non_qualified":null,"image":"1f468-1f3fd-200d-1f3a8.png","sheet_x":14,"sheet_y":26,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F3A8","non_qualified":null,"image":"1f468-1f3fe-200d-1f3a8.png","sheet_x":14,"sheet_y":27,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F3A8","non_qualified":null,"image":"1f468-1f3ff-200d-1f3a8.png","sheet_x":14,"sheet_y":28,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN TEACHER","unified":"1F468-200D-1F3EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f3eb.png","sheet_x":14,"sheet_y":29,"short_name":"male-teacher","short_names":["male-teacher"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":295,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F3EB","non_qualified":null,"image":"1f468-1f3fb-200d-1f3eb.png","sheet_x":14,"sheet_y":30,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F3EB","non_qualified":null,"image":"1f468-1f3fc-200d-1f3eb.png","sheet_x":14,"sheet_y":31,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F3EB","non_qualified":null,"image":"1f468-1f3fd-200d-1f3eb.png","sheet_x":14,"sheet_y":32,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F3EB","non_qualified":null,"image":"1f468-1f3fe-200d-1f3eb.png","sheet_x":14,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F3EB","non_qualified":null,"image":"1f468-1f3ff-200d-1f3eb.png","sheet_x":14,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN FACTORY WORKER","unified":"1F468-200D-1F3ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f3ed.png","sheet_x":14,"sheet_y":35,"short_name":"male-factory-worker","short_names":["male-factory-worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":310,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F3ED","non_qualified":null,"image":"1f468-1f3fb-200d-1f3ed.png","sheet_x":14,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F3ED","non_qualified":null,"image":"1f468-1f3fc-200d-1f3ed.png","sheet_x":14,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F3ED","non_qualified":null,"image":"1f468-1f3fd-200d-1f3ed.png","sheet_x":14,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F3ED","non_qualified":null,"image":"1f468-1f3fe-200d-1f3ed.png","sheet_x":14,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F3ED","non_qualified":null,"image":"1f468-1f3ff-200d-1f3ed.png","sheet_x":14,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FAMILY: MAN, BOY, BOY","unified":"1F468-200D-1F466-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f466-200d-1f466.png","sheet_x":14,"sheet_y":41,"short_name":"man-boy-boy","short_names":["man-boy-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":535,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, BOY","unified":"1F468-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f466.png","sheet_x":14,"sheet_y":42,"short_name":"man-boy","short_names":["man-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":534,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, GIRL, BOY","unified":"1F468-200D-1F467-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f467-200d-1f466.png","sheet_x":14,"sheet_y":43,"short_name":"man-girl-boy","short_names":["man-girl-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":537,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, GIRL, GIRL","unified":"1F468-200D-1F467-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f467-200d-1f467.png","sheet_x":14,"sheet_y":44,"short_name":"man-girl-girl","short_names":["man-girl-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":538,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, GIRL","unified":"1F468-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f467.png","sheet_x":14,"sheet_y":45,"short_name":"man-girl","short_names":["man-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":536,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, MAN, BOY","unified":"1F468-200D-1F468-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f468-200d-1f466.png","sheet_x":14,"sheet_y":46,"short_name":"man-man-boy","short_names":["man-man-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":524,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, MAN, BOY, BOY","unified":"1F468-200D-1F468-200D-1F466-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f468-200d-1f466-200d-1f466.png","sheet_x":14,"sheet_y":47,"short_name":"man-man-boy-boy","short_names":["man-man-boy-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":527,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, MAN, GIRL","unified":"1F468-200D-1F468-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f468-200d-1f467.png","sheet_x":14,"sheet_y":48,"short_name":"man-man-girl","short_names":["man-man-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":525,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, MAN, GIRL, BOY","unified":"1F468-200D-1F468-200D-1F467-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f468-200d-1f467-200d-1f466.png","sheet_x":14,"sheet_y":49,"short_name":"man-man-girl-boy","short_names":["man-man-girl-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":526,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, MAN, GIRL, GIRL","unified":"1F468-200D-1F468-200D-1F467-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f468-200d-1f467-200d-1f467.png","sheet_x":14,"sheet_y":50,"short_name":"man-man-girl-girl","short_names":["man-man-girl-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":528,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, WOMAN, BOY","unified":"1F468-200D-1F469-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f469-200d-1f466.png","sheet_x":14,"sheet_y":51,"short_name":"man-woman-boy","short_names":["man-woman-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":519,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F46A"},{"name":"FAMILY: MAN, WOMAN, BOY, BOY","unified":"1F468-200D-1F469-200D-1F466-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f469-200d-1f466-200d-1f466.png","sheet_x":14,"sheet_y":52,"short_name":"man-woman-boy-boy","short_names":["man-woman-boy-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":522,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, WOMAN, GIRL","unified":"1F468-200D-1F469-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f469-200d-1f467.png","sheet_x":14,"sheet_y":53,"short_name":"man-woman-girl","short_names":["man-woman-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":520,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, WOMAN, GIRL, BOY","unified":"1F468-200D-1F469-200D-1F467-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f469-200d-1f467-200d-1f466.png","sheet_x":14,"sheet_y":54,"short_name":"man-woman-girl-boy","short_names":["man-woman-girl-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":521,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: MAN, WOMAN, GIRL, GIRL","unified":"1F468-200D-1F469-200D-1F467-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f469-200d-1f467-200d-1f467.png","sheet_x":14,"sheet_y":55,"short_name":"man-woman-girl-girl","short_names":["man-woman-girl-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":523,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MAN TECHNOLOGIST","unified":"1F468-200D-1F4BB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f4bb.png","sheet_x":14,"sheet_y":56,"short_name":"male-technologist","short_names":["male-technologist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":319,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F4BB","non_qualified":null,"image":"1f468-1f3fb-200d-1f4bb.png","sheet_x":14,"sheet_y":57,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F4BB","non_qualified":null,"image":"1f468-1f3fc-200d-1f4bb.png","sheet_x":14,"sheet_y":58,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F4BB","non_qualified":null,"image":"1f468-1f3fd-200d-1f4bb.png","sheet_x":14,"sheet_y":59,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F4BB","non_qualified":null,"image":"1f468-1f3fe-200d-1f4bb.png","sheet_x":14,"sheet_y":60,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F4BB","non_qualified":null,"image":"1f468-1f3ff-200d-1f4bb.png","sheet_x":14,"sheet_y":61,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN OFFICE WORKER","unified":"1F468-200D-1F4BC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f4bc.png","sheet_x":15,"sheet_y":0,"short_name":"male-office-worker","short_names":["male-office-worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":313,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F4BC","non_qualified":null,"image":"1f468-1f3fb-200d-1f4bc.png","sheet_x":15,"sheet_y":1,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F4BC","non_qualified":null,"image":"1f468-1f3fc-200d-1f4bc.png","sheet_x":15,"sheet_y":2,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F4BC","non_qualified":null,"image":"1f468-1f3fd-200d-1f4bc.png","sheet_x":15,"sheet_y":3,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F4BC","non_qualified":null,"image":"1f468-1f3fe-200d-1f4bc.png","sheet_x":15,"sheet_y":4,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F4BC","non_qualified":null,"image":"1f468-1f3ff-200d-1f4bc.png","sheet_x":15,"sheet_y":5,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN MECHANIC","unified":"1F468-200D-1F527","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f527.png","sheet_x":15,"sheet_y":6,"short_name":"male-mechanic","short_names":["male-mechanic"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":307,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F527","non_qualified":null,"image":"1f468-1f3fb-200d-1f527.png","sheet_x":15,"sheet_y":7,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F527","non_qualified":null,"image":"1f468-1f3fc-200d-1f527.png","sheet_x":15,"sheet_y":8,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F527","non_qualified":null,"image":"1f468-1f3fd-200d-1f527.png","sheet_x":15,"sheet_y":9,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F527","non_qualified":null,"image":"1f468-1f3fe-200d-1f527.png","sheet_x":15,"sheet_y":10,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F527","non_qualified":null,"image":"1f468-1f3ff-200d-1f527.png","sheet_x":15,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN SCIENTIST","unified":"1F468-200D-1F52C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f52c.png","sheet_x":15,"sheet_y":12,"short_name":"male-scientist","short_names":["male-scientist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":316,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F52C","non_qualified":null,"image":"1f468-1f3fb-200d-1f52c.png","sheet_x":15,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F52C","non_qualified":null,"image":"1f468-1f3fc-200d-1f52c.png","sheet_x":15,"sheet_y":14,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F52C","non_qualified":null,"image":"1f468-1f3fd-200d-1f52c.png","sheet_x":15,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F52C","non_qualified":null,"image":"1f468-1f3fe-200d-1f52c.png","sheet_x":15,"sheet_y":16,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F52C","non_qualified":null,"image":"1f468-1f3ff-200d-1f52c.png","sheet_x":15,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN ASTRONAUT","unified":"1F468-200D-1F680","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f680.png","sheet_x":15,"sheet_y":18,"short_name":"male-astronaut","short_names":["male-astronaut"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":331,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F680","non_qualified":null,"image":"1f468-1f3fb-200d-1f680.png","sheet_x":15,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F680","non_qualified":null,"image":"1f468-1f3fc-200d-1f680.png","sheet_x":15,"sheet_y":20,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F680","non_qualified":null,"image":"1f468-1f3fd-200d-1f680.png","sheet_x":15,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F680","non_qualified":null,"image":"1f468-1f3fe-200d-1f680.png","sheet_x":15,"sheet_y":22,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F680","non_qualified":null,"image":"1f468-1f3ff-200d-1f680.png","sheet_x":15,"sheet_y":23,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN FIREFIGHTER","unified":"1F468-200D-1F692","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f692.png","sheet_x":15,"sheet_y":24,"short_name":"male-firefighter","short_names":["male-firefighter"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":334,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F692","non_qualified":null,"image":"1f468-1f3fb-200d-1f692.png","sheet_x":15,"sheet_y":25,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F692","non_qualified":null,"image":"1f468-1f3fc-200d-1f692.png","sheet_x":15,"sheet_y":26,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F692","non_qualified":null,"image":"1f468-1f3fd-200d-1f692.png","sheet_x":15,"sheet_y":27,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F692","non_qualified":null,"image":"1f468-1f3fe-200d-1f692.png","sheet_x":15,"sheet_y":28,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F692","non_qualified":null,"image":"1f468-1f3ff-200d-1f692.png","sheet_x":15,"sheet_y":29,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN WITH WHITE CANE FACING RIGHT","unified":"1F468-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F468-200D-1F9AF-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9af-200d-27a1-fe0f.png","sheet_x":15,"sheet_y":30,"short_name":"man_with_white_cane_facing_right","short_names":["man_with_white_cane_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":426,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F468-1F3FB-200D-1F9AF-200D-27A1","image":"1f468-1f3fb-200d-1f9af-200d-27a1-fe0f.png","sheet_x":15,"sheet_y":31,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F468-1F3FC-200D-1F9AF-200D-27A1","image":"1f468-1f3fc-200d-1f9af-200d-27a1-fe0f.png","sheet_x":15,"sheet_y":32,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F468-1F3FD-200D-1F9AF-200D-27A1","image":"1f468-1f3fd-200d-1f9af-200d-27a1-fe0f.png","sheet_x":15,"sheet_y":33,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F468-1F3FE-200D-1F9AF-200D-27A1","image":"1f468-1f3fe-200d-1f9af-200d-27a1-fe0f.png","sheet_x":15,"sheet_y":34,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F468-1F3FF-200D-1F9AF-200D-27A1","image":"1f468-1f3ff-200d-1f9af-200d-27a1-fe0f.png","sheet_x":15,"sheet_y":35,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"MAN WITH WHITE CANE","unified":"1F468-200D-1F9AF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9af.png","sheet_x":15,"sheet_y":36,"short_name":"man_with_probing_cane","short_names":["man_with_probing_cane"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":425,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9AF","non_qualified":null,"image":"1f468-1f3fb-200d-1f9af.png","sheet_x":15,"sheet_y":37,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9AF","non_qualified":null,"image":"1f468-1f3fc-200d-1f9af.png","sheet_x":15,"sheet_y":38,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9AF","non_qualified":null,"image":"1f468-1f3fd-200d-1f9af.png","sheet_x":15,"sheet_y":39,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9AF","non_qualified":null,"image":"1f468-1f3fe-200d-1f9af.png","sheet_x":15,"sheet_y":40,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9AF","non_qualified":null,"image":"1f468-1f3ff-200d-1f9af.png","sheet_x":15,"sheet_y":41,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN: RED HAIR","unified":"1F468-200D-1F9B0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9b0.png","sheet_x":15,"sheet_y":42,"short_name":"red_haired_man","short_names":["red_haired_man"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":240,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9B0","non_qualified":null,"image":"1f468-1f3fb-200d-1f9b0.png","sheet_x":15,"sheet_y":43,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9B0","non_qualified":null,"image":"1f468-1f3fc-200d-1f9b0.png","sheet_x":15,"sheet_y":44,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9B0","non_qualified":null,"image":"1f468-1f3fd-200d-1f9b0.png","sheet_x":15,"sheet_y":45,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9B0","non_qualified":null,"image":"1f468-1f3fe-200d-1f9b0.png","sheet_x":15,"sheet_y":46,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9B0","non_qualified":null,"image":"1f468-1f3ff-200d-1f9b0.png","sheet_x":15,"sheet_y":47,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN: CURLY HAIR","unified":"1F468-200D-1F9B1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9b1.png","sheet_x":15,"sheet_y":48,"short_name":"curly_haired_man","short_names":["curly_haired_man"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":241,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9B1","non_qualified":null,"image":"1f468-1f3fb-200d-1f9b1.png","sheet_x":15,"sheet_y":49,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9B1","non_qualified":null,"image":"1f468-1f3fc-200d-1f9b1.png","sheet_x":15,"sheet_y":50,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9B1","non_qualified":null,"image":"1f468-1f3fd-200d-1f9b1.png","sheet_x":15,"sheet_y":51,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9B1","non_qualified":null,"image":"1f468-1f3fe-200d-1f9b1.png","sheet_x":15,"sheet_y":52,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9B1","non_qualified":null,"image":"1f468-1f3ff-200d-1f9b1.png","sheet_x":15,"sheet_y":53,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN: BALD","unified":"1F468-200D-1F9B2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9b2.png","sheet_x":15,"sheet_y":54,"short_name":"bald_man","short_names":["bald_man"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":243,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9B2","non_qualified":null,"image":"1f468-1f3fb-200d-1f9b2.png","sheet_x":15,"sheet_y":55,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9B2","non_qualified":null,"image":"1f468-1f3fc-200d-1f9b2.png","sheet_x":15,"sheet_y":56,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9B2","non_qualified":null,"image":"1f468-1f3fd-200d-1f9b2.png","sheet_x":15,"sheet_y":57,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9B2","non_qualified":null,"image":"1f468-1f3fe-200d-1f9b2.png","sheet_x":15,"sheet_y":58,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9B2","non_qualified":null,"image":"1f468-1f3ff-200d-1f9b2.png","sheet_x":15,"sheet_y":59,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN: WHITE HAIR","unified":"1F468-200D-1F9B3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9b3.png","sheet_x":15,"sheet_y":60,"short_name":"white_haired_man","short_names":["white_haired_man"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":242,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9B3","non_qualified":null,"image":"1f468-1f3fb-200d-1f9b3.png","sheet_x":15,"sheet_y":61,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9B3","non_qualified":null,"image":"1f468-1f3fc-200d-1f9b3.png","sheet_x":16,"sheet_y":0,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9B3","non_qualified":null,"image":"1f468-1f3fd-200d-1f9b3.png","sheet_x":16,"sheet_y":1,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9B3","non_qualified":null,"image":"1f468-1f3fe-200d-1f9b3.png","sheet_x":16,"sheet_y":2,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9B3","non_qualified":null,"image":"1f468-1f3ff-200d-1f9b3.png","sheet_x":16,"sheet_y":3,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN IN MOTORIZED WHEELCHAIR FACING RIGHT","unified":"1F468-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F468-200D-1F9BC-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":4,"short_name":"man_in_motorized_wheelchair_facing_right","short_names":["man_in_motorized_wheelchair_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":432,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F468-1F3FB-200D-1F9BC-200D-27A1","image":"1f468-1f3fb-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":5,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F468-1F3FC-200D-1F9BC-200D-27A1","image":"1f468-1f3fc-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":6,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F468-1F3FD-200D-1F9BC-200D-27A1","image":"1f468-1f3fd-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":7,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F468-1F3FE-200D-1F9BC-200D-27A1","image":"1f468-1f3fe-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":8,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F468-1F3FF-200D-1F9BC-200D-27A1","image":"1f468-1f3ff-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":9,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"MAN IN MOTORIZED WHEELCHAIR","unified":"1F468-200D-1F9BC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9bc.png","sheet_x":16,"sheet_y":10,"short_name":"man_in_motorized_wheelchair","short_names":["man_in_motorized_wheelchair"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":431,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9BC","non_qualified":null,"image":"1f468-1f3fb-200d-1f9bc.png","sheet_x":16,"sheet_y":11,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9BC","non_qualified":null,"image":"1f468-1f3fc-200d-1f9bc.png","sheet_x":16,"sheet_y":12,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9BC","non_qualified":null,"image":"1f468-1f3fd-200d-1f9bc.png","sheet_x":16,"sheet_y":13,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9BC","non_qualified":null,"image":"1f468-1f3fe-200d-1f9bc.png","sheet_x":16,"sheet_y":14,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9BC","non_qualified":null,"image":"1f468-1f3ff-200d-1f9bc.png","sheet_x":16,"sheet_y":15,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN IN MANUAL WHEELCHAIR FACING RIGHT","unified":"1F468-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F468-200D-1F9BD-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":16,"short_name":"man_in_manual_wheelchair_facing_right","short_names":["man_in_manual_wheelchair_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":438,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F468-1F3FB-200D-1F9BD-200D-27A1","image":"1f468-1f3fb-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":17,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F468-1F3FC-200D-1F9BD-200D-27A1","image":"1f468-1f3fc-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":18,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F468-1F3FD-200D-1F9BD-200D-27A1","image":"1f468-1f3fd-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":19,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F468-1F3FE-200D-1F9BD-200D-27A1","image":"1f468-1f3fe-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":20,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F468-1F3FF-200D-1F9BD-200D-27A1","image":"1f468-1f3ff-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":16,"sheet_y":21,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"MAN IN MANUAL WHEELCHAIR","unified":"1F468-200D-1F9BD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-1f9bd.png","sheet_x":16,"sheet_y":22,"short_name":"man_in_manual_wheelchair","short_names":["man_in_manual_wheelchair"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":437,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-1F9BD","non_qualified":null,"image":"1f468-1f3fb-200d-1f9bd.png","sheet_x":16,"sheet_y":23,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-1F9BD","non_qualified":null,"image":"1f468-1f3fc-200d-1f9bd.png","sheet_x":16,"sheet_y":24,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-1F9BD","non_qualified":null,"image":"1f468-1f3fd-200d-1f9bd.png","sheet_x":16,"sheet_y":25,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-1F9BD","non_qualified":null,"image":"1f468-1f3fe-200d-1f9bd.png","sheet_x":16,"sheet_y":26,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-1F9BD","non_qualified":null,"image":"1f468-1f3ff-200d-1f9bd.png","sheet_x":16,"sheet_y":27,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN HEALTH WORKER","unified":"1F468-200D-2695-FE0F","non_qualified":"1F468-200D-2695","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-2695-fe0f.png","sheet_x":16,"sheet_y":28,"short_name":"male-doctor","short_names":["male-doctor"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":289,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-2695-FE0F","non_qualified":"1F468-1F3FB-200D-2695","image":"1f468-1f3fb-200d-2695-fe0f.png","sheet_x":16,"sheet_y":29,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-2695-FE0F","non_qualified":"1F468-1F3FC-200D-2695","image":"1f468-1f3fc-200d-2695-fe0f.png","sheet_x":16,"sheet_y":30,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-2695-FE0F","non_qualified":"1F468-1F3FD-200D-2695","image":"1f468-1f3fd-200d-2695-fe0f.png","sheet_x":16,"sheet_y":31,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-2695-FE0F","non_qualified":"1F468-1F3FE-200D-2695","image":"1f468-1f3fe-200d-2695-fe0f.png","sheet_x":16,"sheet_y":32,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-2695-FE0F","non_qualified":"1F468-1F3FF-200D-2695","image":"1f468-1f3ff-200d-2695-fe0f.png","sheet_x":16,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN JUDGE","unified":"1F468-200D-2696-FE0F","non_qualified":"1F468-200D-2696","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-2696-fe0f.png","sheet_x":16,"sheet_y":34,"short_name":"male-judge","short_names":["male-judge"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":298,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-2696-FE0F","non_qualified":"1F468-1F3FB-200D-2696","image":"1f468-1f3fb-200d-2696-fe0f.png","sheet_x":16,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-2696-FE0F","non_qualified":"1F468-1F3FC-200D-2696","image":"1f468-1f3fc-200d-2696-fe0f.png","sheet_x":16,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-2696-FE0F","non_qualified":"1F468-1F3FD-200D-2696","image":"1f468-1f3fd-200d-2696-fe0f.png","sheet_x":16,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-2696-FE0F","non_qualified":"1F468-1F3FE-200D-2696","image":"1f468-1f3fe-200d-2696-fe0f.png","sheet_x":16,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-2696-FE0F","non_qualified":"1F468-1F3FF-200D-2696","image":"1f468-1f3ff-200d-2696-fe0f.png","sheet_x":16,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN PILOT","unified":"1F468-200D-2708-FE0F","non_qualified":"1F468-200D-2708","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-2708-fe0f.png","sheet_x":16,"sheet_y":40,"short_name":"male-pilot","short_names":["male-pilot"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":328,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB-200D-2708-FE0F","non_qualified":"1F468-1F3FB-200D-2708","image":"1f468-1f3fb-200d-2708-fe0f.png","sheet_x":16,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC-200D-2708-FE0F","non_qualified":"1F468-1F3FC-200D-2708","image":"1f468-1f3fc-200d-2708-fe0f.png","sheet_x":16,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD-200D-2708-FE0F","non_qualified":"1F468-1F3FD-200D-2708","image":"1f468-1f3fd-200d-2708-fe0f.png","sheet_x":16,"sheet_y":43,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE-200D-2708-FE0F","non_qualified":"1F468-1F3FE-200D-2708","image":"1f468-1f3fe-200d-2708-fe0f.png","sheet_x":16,"sheet_y":44,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF-200D-2708-FE0F","non_qualified":"1F468-1F3FF-200D-2708","image":"1f468-1f3ff-200d-2708-fe0f.png","sheet_x":16,"sheet_y":45,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"COUPLE WITH HEART: MAN, MAN","unified":"1F468-200D-2764-FE0F-200D-1F468","non_qualified":"1F468-200D-2764-200D-1F468","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-2764-fe0f-200d-1f468.png","sheet_x":16,"sheet_y":46,"short_name":"man-heart-man","short_names":["man-heart-man"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":517,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB-1F3FB":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F468-1F3FB-200D-2764-200D-1F468-1F3FB","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":16,"sheet_y":47,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F468-1F3FB-200D-2764-200D-1F468-1F3FC","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":16,"sheet_y":48,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F468-1F3FB-200D-2764-200D-1F468-1F3FD","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":16,"sheet_y":49,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F468-1F3FB-200D-2764-200D-1F468-1F3FE","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":16,"sheet_y":50,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F468-1F3FB-200D-2764-200D-1F468-1F3FF","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":16,"sheet_y":51,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F468-1F3FC-200D-2764-200D-1F468-1F3FB","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":16,"sheet_y":52,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FC":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F468-1F3FC-200D-2764-200D-1F468-1F3FC","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":16,"sheet_y":53,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F468-1F3FC-200D-2764-200D-1F468-1F3FD","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":16,"sheet_y":54,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F468-1F3FC-200D-2764-200D-1F468-1F3FE","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":16,"sheet_y":55,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F468-1F3FC-200D-2764-200D-1F468-1F3FF","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":16,"sheet_y":56,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F468-1F3FD-200D-2764-200D-1F468-1F3FB","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":16,"sheet_y":57,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F468-1F3FD-200D-2764-200D-1F468-1F3FC","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":16,"sheet_y":58,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FD":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F468-1F3FD-200D-2764-200D-1F468-1F3FD","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":16,"sheet_y":59,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F468-1F3FD-200D-2764-200D-1F468-1F3FE","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":16,"sheet_y":60,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F468-1F3FD-200D-2764-200D-1F468-1F3FF","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":16,"sheet_y":61,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F468-1F3FE-200D-2764-200D-1F468-1F3FB","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":17,"sheet_y":0,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F468-1F3FE-200D-2764-200D-1F468-1F3FC","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":17,"sheet_y":1,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F468-1F3FE-200D-2764-200D-1F468-1F3FD","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":17,"sheet_y":2,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FE":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F468-1F3FE-200D-2764-200D-1F468-1F3FE","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":17,"sheet_y":3,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F468-1F3FE-200D-2764-200D-1F468-1F3FF","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":17,"sheet_y":4,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F468-1F3FF-200D-2764-200D-1F468-1F3FB","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":17,"sheet_y":5,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F468-1F3FF-200D-2764-200D-1F468-1F3FC","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":17,"sheet_y":6,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F468-1F3FF-200D-2764-200D-1F468-1F3FD","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":17,"sheet_y":7,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F468-1F3FF-200D-2764-200D-1F468-1F3FE","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":17,"sheet_y":8,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FF":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F468-1F3FF-200D-2764-200D-1F468-1F3FF","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":17,"sheet_y":9,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"KISS: MAN, MAN","unified":"1F468-200D-2764-FE0F-200D-1F48B-200D-1F468","non_qualified":"1F468-200D-2764-200D-1F48B-200D-1F468","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f468-200d-2764-fe0f-200d-1f48b-200d-1f468.png","sheet_x":17,"sheet_y":10,"short_name":"man-kiss-man","short_names":["man-kiss-man"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":513,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB-1F3FB":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F468-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":17,"sheet_y":11,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F468-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":17,"sheet_y":12,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F468-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":17,"sheet_y":13,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F468-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":17,"sheet_y":14,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F468-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F468-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f468-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":17,"sheet_y":15,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F468-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":17,"sheet_y":16,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FC":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F468-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":17,"sheet_y":17,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F468-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":17,"sheet_y":18,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F468-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":17,"sheet_y":19,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F468-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F468-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f468-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":17,"sheet_y":20,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F468-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":17,"sheet_y":21,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F468-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":17,"sheet_y":22,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FD":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F468-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":17,"sheet_y":23,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F468-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":17,"sheet_y":24,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F468-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F468-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f468-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":17,"sheet_y":25,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F468-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":17,"sheet_y":26,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F468-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":17,"sheet_y":27,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F468-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":17,"sheet_y":28,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FE":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F468-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":17,"sheet_y":29,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F468-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F468-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f468-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":17,"sheet_y":30,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F468-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":17,"sheet_y":31,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F468-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":17,"sheet_y":32,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F468-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":17,"sheet_y":33,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F468-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":17,"sheet_y":34,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FF":{"unified":"1F468-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F468-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f468-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":17,"sheet_y":35,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN","unified":"1F468","non_qualified":null,"docomo":"E6F0","au":"E4FC","softbank":"E004","google":"FE19D","image":"1f468.png","sheet_x":17,"sheet_y":36,"short_name":"man","short_names":["man"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":236,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F468-1F3FB","non_qualified":null,"image":"1f468-1f3fb.png","sheet_x":17,"sheet_y":37,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F468-1F3FC","non_qualified":null,"image":"1f468-1f3fc.png","sheet_x":17,"sheet_y":38,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F468-1F3FD","non_qualified":null,"image":"1f468-1f3fd.png","sheet_x":17,"sheet_y":39,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F468-1F3FE","non_qualified":null,"image":"1f468-1f3fe.png","sheet_x":17,"sheet_y":40,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F468-1F3FF","non_qualified":null,"image":"1f468-1f3ff.png","sheet_x":17,"sheet_y":41,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN FARMER","unified":"1F469-200D-1F33E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f33e.png","sheet_x":17,"sheet_y":42,"short_name":"female-farmer","short_names":["female-farmer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":302,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F33E","non_qualified":null,"image":"1f469-1f3fb-200d-1f33e.png","sheet_x":17,"sheet_y":43,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F33E","non_qualified":null,"image":"1f469-1f3fc-200d-1f33e.png","sheet_x":17,"sheet_y":44,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F33E","non_qualified":null,"image":"1f469-1f3fd-200d-1f33e.png","sheet_x":17,"sheet_y":45,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F33E","non_qualified":null,"image":"1f469-1f3fe-200d-1f33e.png","sheet_x":17,"sheet_y":46,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F33E","non_qualified":null,"image":"1f469-1f3ff-200d-1f33e.png","sheet_x":17,"sheet_y":47,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN COOK","unified":"1F469-200D-1F373","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f373.png","sheet_x":17,"sheet_y":48,"short_name":"female-cook","short_names":["female-cook"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":305,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F373","non_qualified":null,"image":"1f469-1f3fb-200d-1f373.png","sheet_x":17,"sheet_y":49,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F373","non_qualified":null,"image":"1f469-1f3fc-200d-1f373.png","sheet_x":17,"sheet_y":50,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F373","non_qualified":null,"image":"1f469-1f3fd-200d-1f373.png","sheet_x":17,"sheet_y":51,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F373","non_qualified":null,"image":"1f469-1f3fe-200d-1f373.png","sheet_x":17,"sheet_y":52,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F373","non_qualified":null,"image":"1f469-1f3ff-200d-1f373.png","sheet_x":17,"sheet_y":53,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN FEEDING BABY","unified":"1F469-200D-1F37C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f37c.png","sheet_x":17,"sheet_y":54,"short_name":"woman_feeding_baby","short_names":["woman_feeding_baby"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":367,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F37C","non_qualified":null,"image":"1f469-1f3fb-200d-1f37c.png","sheet_x":17,"sheet_y":55,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F37C","non_qualified":null,"image":"1f469-1f3fc-200d-1f37c.png","sheet_x":17,"sheet_y":56,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F37C","non_qualified":null,"image":"1f469-1f3fd-200d-1f37c.png","sheet_x":17,"sheet_y":57,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F37C","non_qualified":null,"image":"1f469-1f3fe-200d-1f37c.png","sheet_x":17,"sheet_y":58,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F37C","non_qualified":null,"image":"1f469-1f3ff-200d-1f37c.png","sheet_x":17,"sheet_y":59,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN STUDENT","unified":"1F469-200D-1F393","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f393.png","sheet_x":17,"sheet_y":60,"short_name":"female-student","short_names":["female-student"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":293,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F393","non_qualified":null,"image":"1f469-1f3fb-200d-1f393.png","sheet_x":17,"sheet_y":61,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F393","non_qualified":null,"image":"1f469-1f3fc-200d-1f393.png","sheet_x":18,"sheet_y":0,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F393","non_qualified":null,"image":"1f469-1f3fd-200d-1f393.png","sheet_x":18,"sheet_y":1,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F393","non_qualified":null,"image":"1f469-1f3fe-200d-1f393.png","sheet_x":18,"sheet_y":2,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F393","non_qualified":null,"image":"1f469-1f3ff-200d-1f393.png","sheet_x":18,"sheet_y":3,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN SINGER","unified":"1F469-200D-1F3A4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f3a4.png","sheet_x":18,"sheet_y":4,"short_name":"female-singer","short_names":["female-singer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":323,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F3A4","non_qualified":null,"image":"1f469-1f3fb-200d-1f3a4.png","sheet_x":18,"sheet_y":5,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F3A4","non_qualified":null,"image":"1f469-1f3fc-200d-1f3a4.png","sheet_x":18,"sheet_y":6,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F3A4","non_qualified":null,"image":"1f469-1f3fd-200d-1f3a4.png","sheet_x":18,"sheet_y":7,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F3A4","non_qualified":null,"image":"1f469-1f3fe-200d-1f3a4.png","sheet_x":18,"sheet_y":8,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F3A4","non_qualified":null,"image":"1f469-1f3ff-200d-1f3a4.png","sheet_x":18,"sheet_y":9,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN ARTIST","unified":"1F469-200D-1F3A8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f3a8.png","sheet_x":18,"sheet_y":10,"short_name":"female-artist","short_names":["female-artist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":326,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F3A8","non_qualified":null,"image":"1f469-1f3fb-200d-1f3a8.png","sheet_x":18,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F3A8","non_qualified":null,"image":"1f469-1f3fc-200d-1f3a8.png","sheet_x":18,"sheet_y":12,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F3A8","non_qualified":null,"image":"1f469-1f3fd-200d-1f3a8.png","sheet_x":18,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F3A8","non_qualified":null,"image":"1f469-1f3fe-200d-1f3a8.png","sheet_x":18,"sheet_y":14,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F3A8","non_qualified":null,"image":"1f469-1f3ff-200d-1f3a8.png","sheet_x":18,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN TEACHER","unified":"1F469-200D-1F3EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f3eb.png","sheet_x":18,"sheet_y":16,"short_name":"female-teacher","short_names":["female-teacher"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":296,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F3EB","non_qualified":null,"image":"1f469-1f3fb-200d-1f3eb.png","sheet_x":18,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F3EB","non_qualified":null,"image":"1f469-1f3fc-200d-1f3eb.png","sheet_x":18,"sheet_y":18,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F3EB","non_qualified":null,"image":"1f469-1f3fd-200d-1f3eb.png","sheet_x":18,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F3EB","non_qualified":null,"image":"1f469-1f3fe-200d-1f3eb.png","sheet_x":18,"sheet_y":20,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F3EB","non_qualified":null,"image":"1f469-1f3ff-200d-1f3eb.png","sheet_x":18,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN FACTORY WORKER","unified":"1F469-200D-1F3ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f3ed.png","sheet_x":18,"sheet_y":22,"short_name":"female-factory-worker","short_names":["female-factory-worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":311,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F3ED","non_qualified":null,"image":"1f469-1f3fb-200d-1f3ed.png","sheet_x":18,"sheet_y":23,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F3ED","non_qualified":null,"image":"1f469-1f3fc-200d-1f3ed.png","sheet_x":18,"sheet_y":24,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F3ED","non_qualified":null,"image":"1f469-1f3fd-200d-1f3ed.png","sheet_x":18,"sheet_y":25,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F3ED","non_qualified":null,"image":"1f469-1f3fe-200d-1f3ed.png","sheet_x":18,"sheet_y":26,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F3ED","non_qualified":null,"image":"1f469-1f3ff-200d-1f3ed.png","sheet_x":18,"sheet_y":27,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FAMILY: WOMAN, BOY, BOY","unified":"1F469-200D-1F466-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f466-200d-1f466.png","sheet_x":18,"sheet_y":28,"short_name":"woman-boy-boy","short_names":["woman-boy-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":540,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: WOMAN, BOY","unified":"1F469-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f466.png","sheet_x":18,"sheet_y":29,"short_name":"woman-boy","short_names":["woman-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":539,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: WOMAN, GIRL, BOY","unified":"1F469-200D-1F467-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f467-200d-1f466.png","sheet_x":18,"sheet_y":30,"short_name":"woman-girl-boy","short_names":["woman-girl-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":542,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: WOMAN, GIRL, GIRL","unified":"1F469-200D-1F467-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f467-200d-1f467.png","sheet_x":18,"sheet_y":31,"short_name":"woman-girl-girl","short_names":["woman-girl-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":543,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: WOMAN, GIRL","unified":"1F469-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f467.png","sheet_x":18,"sheet_y":32,"short_name":"woman-girl","short_names":["woman-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":541,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: WOMAN, WOMAN, BOY","unified":"1F469-200D-1F469-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f469-200d-1f466.png","sheet_x":18,"sheet_y":33,"short_name":"woman-woman-boy","short_names":["woman-woman-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":529,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: WOMAN, WOMAN, BOY, BOY","unified":"1F469-200D-1F469-200D-1F466-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f469-200d-1f466-200d-1f466.png","sheet_x":18,"sheet_y":34,"short_name":"woman-woman-boy-boy","short_names":["woman-woman-boy-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":532,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: WOMAN, WOMAN, GIRL","unified":"1F469-200D-1F469-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f469-200d-1f467.png","sheet_x":18,"sheet_y":35,"short_name":"woman-woman-girl","short_names":["woman-woman-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":530,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: WOMAN, WOMAN, GIRL, BOY","unified":"1F469-200D-1F469-200D-1F467-200D-1F466","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f469-200d-1f467-200d-1f466.png","sheet_x":18,"sheet_y":36,"short_name":"woman-woman-girl-boy","short_names":["woman-woman-girl-boy"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":531,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAMILY: WOMAN, WOMAN, GIRL, GIRL","unified":"1F469-200D-1F469-200D-1F467-200D-1F467","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f469-200d-1f467-200d-1f467.png","sheet_x":18,"sheet_y":37,"short_name":"woman-woman-girl-girl","short_names":["woman-woman-girl-girl"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":533,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN TECHNOLOGIST","unified":"1F469-200D-1F4BB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f4bb.png","sheet_x":18,"sheet_y":38,"short_name":"female-technologist","short_names":["female-technologist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":320,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F4BB","non_qualified":null,"image":"1f469-1f3fb-200d-1f4bb.png","sheet_x":18,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F4BB","non_qualified":null,"image":"1f469-1f3fc-200d-1f4bb.png","sheet_x":18,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F4BB","non_qualified":null,"image":"1f469-1f3fd-200d-1f4bb.png","sheet_x":18,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F4BB","non_qualified":null,"image":"1f469-1f3fe-200d-1f4bb.png","sheet_x":18,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F4BB","non_qualified":null,"image":"1f469-1f3ff-200d-1f4bb.png","sheet_x":18,"sheet_y":43,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN OFFICE WORKER","unified":"1F469-200D-1F4BC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f4bc.png","sheet_x":18,"sheet_y":44,"short_name":"female-office-worker","short_names":["female-office-worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":314,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F4BC","non_qualified":null,"image":"1f469-1f3fb-200d-1f4bc.png","sheet_x":18,"sheet_y":45,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F4BC","non_qualified":null,"image":"1f469-1f3fc-200d-1f4bc.png","sheet_x":18,"sheet_y":46,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F4BC","non_qualified":null,"image":"1f469-1f3fd-200d-1f4bc.png","sheet_x":18,"sheet_y":47,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F4BC","non_qualified":null,"image":"1f469-1f3fe-200d-1f4bc.png","sheet_x":18,"sheet_y":48,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F4BC","non_qualified":null,"image":"1f469-1f3ff-200d-1f4bc.png","sheet_x":18,"sheet_y":49,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN MECHANIC","unified":"1F469-200D-1F527","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f527.png","sheet_x":18,"sheet_y":50,"short_name":"female-mechanic","short_names":["female-mechanic"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":308,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F527","non_qualified":null,"image":"1f469-1f3fb-200d-1f527.png","sheet_x":18,"sheet_y":51,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F527","non_qualified":null,"image":"1f469-1f3fc-200d-1f527.png","sheet_x":18,"sheet_y":52,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F527","non_qualified":null,"image":"1f469-1f3fd-200d-1f527.png","sheet_x":18,"sheet_y":53,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F527","non_qualified":null,"image":"1f469-1f3fe-200d-1f527.png","sheet_x":18,"sheet_y":54,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F527","non_qualified":null,"image":"1f469-1f3ff-200d-1f527.png","sheet_x":18,"sheet_y":55,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN SCIENTIST","unified":"1F469-200D-1F52C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f52c.png","sheet_x":18,"sheet_y":56,"short_name":"female-scientist","short_names":["female-scientist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":317,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F52C","non_qualified":null,"image":"1f469-1f3fb-200d-1f52c.png","sheet_x":18,"sheet_y":57,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F52C","non_qualified":null,"image":"1f469-1f3fc-200d-1f52c.png","sheet_x":18,"sheet_y":58,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F52C","non_qualified":null,"image":"1f469-1f3fd-200d-1f52c.png","sheet_x":18,"sheet_y":59,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F52C","non_qualified":null,"image":"1f469-1f3fe-200d-1f52c.png","sheet_x":18,"sheet_y":60,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F52C","non_qualified":null,"image":"1f469-1f3ff-200d-1f52c.png","sheet_x":18,"sheet_y":61,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN ASTRONAUT","unified":"1F469-200D-1F680","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f680.png","sheet_x":19,"sheet_y":0,"short_name":"female-astronaut","short_names":["female-astronaut"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":332,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F680","non_qualified":null,"image":"1f469-1f3fb-200d-1f680.png","sheet_x":19,"sheet_y":1,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F680","non_qualified":null,"image":"1f469-1f3fc-200d-1f680.png","sheet_x":19,"sheet_y":2,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F680","non_qualified":null,"image":"1f469-1f3fd-200d-1f680.png","sheet_x":19,"sheet_y":3,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F680","non_qualified":null,"image":"1f469-1f3fe-200d-1f680.png","sheet_x":19,"sheet_y":4,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F680","non_qualified":null,"image":"1f469-1f3ff-200d-1f680.png","sheet_x":19,"sheet_y":5,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN FIREFIGHTER","unified":"1F469-200D-1F692","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f692.png","sheet_x":19,"sheet_y":6,"short_name":"female-firefighter","short_names":["female-firefighter"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":335,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F692","non_qualified":null,"image":"1f469-1f3fb-200d-1f692.png","sheet_x":19,"sheet_y":7,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F692","non_qualified":null,"image":"1f469-1f3fc-200d-1f692.png","sheet_x":19,"sheet_y":8,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F692","non_qualified":null,"image":"1f469-1f3fd-200d-1f692.png","sheet_x":19,"sheet_y":9,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F692","non_qualified":null,"image":"1f469-1f3fe-200d-1f692.png","sheet_x":19,"sheet_y":10,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F692","non_qualified":null,"image":"1f469-1f3ff-200d-1f692.png","sheet_x":19,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN WITH WHITE CANE FACING RIGHT","unified":"1F469-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F469-200D-1F9AF-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9af-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":12,"short_name":"woman_with_white_cane_facing_right","short_names":["woman_with_white_cane_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":428,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F469-1F3FB-200D-1F9AF-200D-27A1","image":"1f469-1f3fb-200d-1f9af-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":13,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F469-1F3FC-200D-1F9AF-200D-27A1","image":"1f469-1f3fc-200d-1f9af-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":14,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F469-1F3FD-200D-1F9AF-200D-27A1","image":"1f469-1f3fd-200d-1f9af-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":15,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F469-1F3FE-200D-1F9AF-200D-27A1","image":"1f469-1f3fe-200d-1f9af-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":16,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F469-1F3FF-200D-1F9AF-200D-27A1","image":"1f469-1f3ff-200d-1f9af-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":17,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"WOMAN WITH WHITE CANE","unified":"1F469-200D-1F9AF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9af.png","sheet_x":19,"sheet_y":18,"short_name":"woman_with_probing_cane","short_names":["woman_with_probing_cane"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":427,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9AF","non_qualified":null,"image":"1f469-1f3fb-200d-1f9af.png","sheet_x":19,"sheet_y":19,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9AF","non_qualified":null,"image":"1f469-1f3fc-200d-1f9af.png","sheet_x":19,"sheet_y":20,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9AF","non_qualified":null,"image":"1f469-1f3fd-200d-1f9af.png","sheet_x":19,"sheet_y":21,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9AF","non_qualified":null,"image":"1f469-1f3fe-200d-1f9af.png","sheet_x":19,"sheet_y":22,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9AF","non_qualified":null,"image":"1f469-1f3ff-200d-1f9af.png","sheet_x":19,"sheet_y":23,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN: RED HAIR","unified":"1F469-200D-1F9B0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9b0.png","sheet_x":19,"sheet_y":24,"short_name":"red_haired_woman","short_names":["red_haired_woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":245,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9B0","non_qualified":null,"image":"1f469-1f3fb-200d-1f9b0.png","sheet_x":19,"sheet_y":25,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9B0","non_qualified":null,"image":"1f469-1f3fc-200d-1f9b0.png","sheet_x":19,"sheet_y":26,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9B0","non_qualified":null,"image":"1f469-1f3fd-200d-1f9b0.png","sheet_x":19,"sheet_y":27,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9B0","non_qualified":null,"image":"1f469-1f3fe-200d-1f9b0.png","sheet_x":19,"sheet_y":28,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9B0","non_qualified":null,"image":"1f469-1f3ff-200d-1f9b0.png","sheet_x":19,"sheet_y":29,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN: CURLY HAIR","unified":"1F469-200D-1F9B1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9b1.png","sheet_x":19,"sheet_y":30,"short_name":"curly_haired_woman","short_names":["curly_haired_woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":247,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9B1","non_qualified":null,"image":"1f469-1f3fb-200d-1f9b1.png","sheet_x":19,"sheet_y":31,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9B1","non_qualified":null,"image":"1f469-1f3fc-200d-1f9b1.png","sheet_x":19,"sheet_y":32,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9B1","non_qualified":null,"image":"1f469-1f3fd-200d-1f9b1.png","sheet_x":19,"sheet_y":33,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9B1","non_qualified":null,"image":"1f469-1f3fe-200d-1f9b1.png","sheet_x":19,"sheet_y":34,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9B1","non_qualified":null,"image":"1f469-1f3ff-200d-1f9b1.png","sheet_x":19,"sheet_y":35,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN: BALD","unified":"1F469-200D-1F9B2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9b2.png","sheet_x":19,"sheet_y":36,"short_name":"bald_woman","short_names":["bald_woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":251,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9B2","non_qualified":null,"image":"1f469-1f3fb-200d-1f9b2.png","sheet_x":19,"sheet_y":37,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9B2","non_qualified":null,"image":"1f469-1f3fc-200d-1f9b2.png","sheet_x":19,"sheet_y":38,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9B2","non_qualified":null,"image":"1f469-1f3fd-200d-1f9b2.png","sheet_x":19,"sheet_y":39,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9B2","non_qualified":null,"image":"1f469-1f3fe-200d-1f9b2.png","sheet_x":19,"sheet_y":40,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9B2","non_qualified":null,"image":"1f469-1f3ff-200d-1f9b2.png","sheet_x":19,"sheet_y":41,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN: WHITE HAIR","unified":"1F469-200D-1F9B3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9b3.png","sheet_x":19,"sheet_y":42,"short_name":"white_haired_woman","short_names":["white_haired_woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":249,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9B3","non_qualified":null,"image":"1f469-1f3fb-200d-1f9b3.png","sheet_x":19,"sheet_y":43,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9B3","non_qualified":null,"image":"1f469-1f3fc-200d-1f9b3.png","sheet_x":19,"sheet_y":44,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9B3","non_qualified":null,"image":"1f469-1f3fd-200d-1f9b3.png","sheet_x":19,"sheet_y":45,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9B3","non_qualified":null,"image":"1f469-1f3fe-200d-1f9b3.png","sheet_x":19,"sheet_y":46,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9B3","non_qualified":null,"image":"1f469-1f3ff-200d-1f9b3.png","sheet_x":19,"sheet_y":47,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN IN MOTORIZED WHEELCHAIR FACING RIGHT","unified":"1F469-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F469-200D-1F9BC-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":48,"short_name":"woman_in_motorized_wheelchair_facing_right","short_names":["woman_in_motorized_wheelchair_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":434,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F469-1F3FB-200D-1F9BC-200D-27A1","image":"1f469-1f3fb-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":49,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F469-1F3FC-200D-1F9BC-200D-27A1","image":"1f469-1f3fc-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":50,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F469-1F3FD-200D-1F9BC-200D-27A1","image":"1f469-1f3fd-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":51,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F469-1F3FE-200D-1F9BC-200D-27A1","image":"1f469-1f3fe-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":52,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F469-1F3FF-200D-1F9BC-200D-27A1","image":"1f469-1f3ff-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":53,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"WOMAN IN MOTORIZED WHEELCHAIR","unified":"1F469-200D-1F9BC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9bc.png","sheet_x":19,"sheet_y":54,"short_name":"woman_in_motorized_wheelchair","short_names":["woman_in_motorized_wheelchair"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":433,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9BC","non_qualified":null,"image":"1f469-1f3fb-200d-1f9bc.png","sheet_x":19,"sheet_y":55,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9BC","non_qualified":null,"image":"1f469-1f3fc-200d-1f9bc.png","sheet_x":19,"sheet_y":56,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9BC","non_qualified":null,"image":"1f469-1f3fd-200d-1f9bc.png","sheet_x":19,"sheet_y":57,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9BC","non_qualified":null,"image":"1f469-1f3fe-200d-1f9bc.png","sheet_x":19,"sheet_y":58,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9BC","non_qualified":null,"image":"1f469-1f3ff-200d-1f9bc.png","sheet_x":19,"sheet_y":59,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN IN MANUAL WHEELCHAIR FACING RIGHT","unified":"1F469-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F469-200D-1F9BD-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":60,"short_name":"woman_in_manual_wheelchair_facing_right","short_names":["woman_in_manual_wheelchair_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":440,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F469-1F3FB-200D-1F9BD-200D-27A1","image":"1f469-1f3fb-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":19,"sheet_y":61,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F469-1F3FC-200D-1F9BD-200D-27A1","image":"1f469-1f3fc-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":20,"sheet_y":0,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F469-1F3FD-200D-1F9BD-200D-27A1","image":"1f469-1f3fd-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":20,"sheet_y":1,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F469-1F3FE-200D-1F9BD-200D-27A1","image":"1f469-1f3fe-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":20,"sheet_y":2,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F469-1F3FF-200D-1F9BD-200D-27A1","image":"1f469-1f3ff-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":20,"sheet_y":3,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"WOMAN IN MANUAL WHEELCHAIR","unified":"1F469-200D-1F9BD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-1f9bd.png","sheet_x":20,"sheet_y":4,"short_name":"woman_in_manual_wheelchair","short_names":["woman_in_manual_wheelchair"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":439,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-1F9BD","non_qualified":null,"image":"1f469-1f3fb-200d-1f9bd.png","sheet_x":20,"sheet_y":5,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-1F9BD","non_qualified":null,"image":"1f469-1f3fc-200d-1f9bd.png","sheet_x":20,"sheet_y":6,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-1F9BD","non_qualified":null,"image":"1f469-1f3fd-200d-1f9bd.png","sheet_x":20,"sheet_y":7,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-1F9BD","non_qualified":null,"image":"1f469-1f3fe-200d-1f9bd.png","sheet_x":20,"sheet_y":8,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-1F9BD","non_qualified":null,"image":"1f469-1f3ff-200d-1f9bd.png","sheet_x":20,"sheet_y":9,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN HEALTH WORKER","unified":"1F469-200D-2695-FE0F","non_qualified":"1F469-200D-2695","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-2695-fe0f.png","sheet_x":20,"sheet_y":10,"short_name":"female-doctor","short_names":["female-doctor"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":290,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-2695-FE0F","non_qualified":"1F469-1F3FB-200D-2695","image":"1f469-1f3fb-200d-2695-fe0f.png","sheet_x":20,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-2695-FE0F","non_qualified":"1F469-1F3FC-200D-2695","image":"1f469-1f3fc-200d-2695-fe0f.png","sheet_x":20,"sheet_y":12,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-2695-FE0F","non_qualified":"1F469-1F3FD-200D-2695","image":"1f469-1f3fd-200d-2695-fe0f.png","sheet_x":20,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-2695-FE0F","non_qualified":"1F469-1F3FE-200D-2695","image":"1f469-1f3fe-200d-2695-fe0f.png","sheet_x":20,"sheet_y":14,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-2695-FE0F","non_qualified":"1F469-1F3FF-200D-2695","image":"1f469-1f3ff-200d-2695-fe0f.png","sheet_x":20,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN JUDGE","unified":"1F469-200D-2696-FE0F","non_qualified":"1F469-200D-2696","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-2696-fe0f.png","sheet_x":20,"sheet_y":16,"short_name":"female-judge","short_names":["female-judge"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":299,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-2696-FE0F","non_qualified":"1F469-1F3FB-200D-2696","image":"1f469-1f3fb-200d-2696-fe0f.png","sheet_x":20,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-2696-FE0F","non_qualified":"1F469-1F3FC-200D-2696","image":"1f469-1f3fc-200d-2696-fe0f.png","sheet_x":20,"sheet_y":18,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-2696-FE0F","non_qualified":"1F469-1F3FD-200D-2696","image":"1f469-1f3fd-200d-2696-fe0f.png","sheet_x":20,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-2696-FE0F","non_qualified":"1F469-1F3FE-200D-2696","image":"1f469-1f3fe-200d-2696-fe0f.png","sheet_x":20,"sheet_y":20,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-2696-FE0F","non_qualified":"1F469-1F3FF-200D-2696","image":"1f469-1f3ff-200d-2696-fe0f.png","sheet_x":20,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN PILOT","unified":"1F469-200D-2708-FE0F","non_qualified":"1F469-200D-2708","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-2708-fe0f.png","sheet_x":20,"sheet_y":22,"short_name":"female-pilot","short_names":["female-pilot"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":329,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB-200D-2708-FE0F","non_qualified":"1F469-1F3FB-200D-2708","image":"1f469-1f3fb-200d-2708-fe0f.png","sheet_x":20,"sheet_y":23,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC-200D-2708-FE0F","non_qualified":"1F469-1F3FC-200D-2708","image":"1f469-1f3fc-200d-2708-fe0f.png","sheet_x":20,"sheet_y":24,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD-200D-2708-FE0F","non_qualified":"1F469-1F3FD-200D-2708","image":"1f469-1f3fd-200d-2708-fe0f.png","sheet_x":20,"sheet_y":25,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE-200D-2708-FE0F","non_qualified":"1F469-1F3FE-200D-2708","image":"1f469-1f3fe-200d-2708-fe0f.png","sheet_x":20,"sheet_y":26,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF-200D-2708-FE0F","non_qualified":"1F469-1F3FF-200D-2708","image":"1f469-1f3ff-200d-2708-fe0f.png","sheet_x":20,"sheet_y":27,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"COUPLE WITH HEART: WOMAN, MAN","unified":"1F469-200D-2764-FE0F-200D-1F468","non_qualified":"1F469-200D-2764-200D-1F468","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-2764-fe0f-200d-1f468.png","sheet_x":20,"sheet_y":28,"short_name":"woman-heart-man","short_names":["woman-heart-man"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":516,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB-1F3FB":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F469-1F3FB-200D-2764-200D-1F468-1F3FB","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":20,"sheet_y":29,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F469-1F3FB-200D-2764-200D-1F468-1F3FC","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":20,"sheet_y":30,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F469-1F3FB-200D-2764-200D-1F468-1F3FD","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":20,"sheet_y":31,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F469-1F3FB-200D-2764-200D-1F468-1F3FE","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":20,"sheet_y":32,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F469-1F3FB-200D-2764-200D-1F468-1F3FF","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":20,"sheet_y":33,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F469-1F3FC-200D-2764-200D-1F468-1F3FB","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":20,"sheet_y":34,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FC":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F469-1F3FC-200D-2764-200D-1F468-1F3FC","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":20,"sheet_y":35,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F469-1F3FC-200D-2764-200D-1F468-1F3FD","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":20,"sheet_y":36,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F469-1F3FC-200D-2764-200D-1F468-1F3FE","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":20,"sheet_y":37,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F469-1F3FC-200D-2764-200D-1F468-1F3FF","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":20,"sheet_y":38,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F469-1F3FD-200D-2764-200D-1F468-1F3FB","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":20,"sheet_y":39,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F469-1F3FD-200D-2764-200D-1F468-1F3FC","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":20,"sheet_y":40,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FD":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F469-1F3FD-200D-2764-200D-1F468-1F3FD","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":20,"sheet_y":41,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F469-1F3FD-200D-2764-200D-1F468-1F3FE","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":20,"sheet_y":42,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F469-1F3FD-200D-2764-200D-1F468-1F3FF","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":20,"sheet_y":43,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F469-1F3FE-200D-2764-200D-1F468-1F3FB","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":20,"sheet_y":44,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F469-1F3FE-200D-2764-200D-1F468-1F3FC","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":20,"sheet_y":45,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F469-1F3FE-200D-2764-200D-1F468-1F3FD","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":20,"sheet_y":46,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FE":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F469-1F3FE-200D-2764-200D-1F468-1F3FE","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":20,"sheet_y":47,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F469-1F3FE-200D-2764-200D-1F468-1F3FF","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":20,"sheet_y":48,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F468-1F3FB","non_qualified":"1F469-1F3FF-200D-2764-200D-1F468-1F3FB","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f468-1f3fb.png","sheet_x":20,"sheet_y":49,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F468-1F3FC","non_qualified":"1F469-1F3FF-200D-2764-200D-1F468-1F3FC","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f468-1f3fc.png","sheet_x":20,"sheet_y":50,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F468-1F3FD","non_qualified":"1F469-1F3FF-200D-2764-200D-1F468-1F3FD","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f468-1f3fd.png","sheet_x":20,"sheet_y":51,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F468-1F3FE","non_qualified":"1F469-1F3FF-200D-2764-200D-1F468-1F3FE","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f468-1f3fe.png","sheet_x":20,"sheet_y":52,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FF":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F468-1F3FF","non_qualified":"1F469-1F3FF-200D-2764-200D-1F468-1F3FF","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f468-1f3ff.png","sheet_x":20,"sheet_y":53,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"COUPLE WITH HEART: WOMAN, WOMAN","unified":"1F469-200D-2764-FE0F-200D-1F469","non_qualified":"1F469-200D-2764-200D-1F469","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-2764-fe0f-200d-1f469.png","sheet_x":20,"sheet_y":54,"short_name":"woman-heart-woman","short_names":["woman-heart-woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":518,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB-1F3FB":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F469-1F3FB","non_qualified":"1F469-1F3FB-200D-2764-200D-1F469-1F3FB","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f469-1f3fb.png","sheet_x":20,"sheet_y":55,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F469-1F3FC","non_qualified":"1F469-1F3FB-200D-2764-200D-1F469-1F3FC","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f469-1f3fc.png","sheet_x":20,"sheet_y":56,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F469-1F3FD","non_qualified":"1F469-1F3FB-200D-2764-200D-1F469-1F3FD","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f469-1f3fd.png","sheet_x":20,"sheet_y":57,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F469-1F3FE","non_qualified":"1F469-1F3FB-200D-2764-200D-1F469-1F3FE","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f469-1f3fe.png","sheet_x":20,"sheet_y":58,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F469-1F3FF","non_qualified":"1F469-1F3FB-200D-2764-200D-1F469-1F3FF","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f469-1f3ff.png","sheet_x":20,"sheet_y":59,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F469-1F3FB","non_qualified":"1F469-1F3FC-200D-2764-200D-1F469-1F3FB","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f469-1f3fb.png","sheet_x":20,"sheet_y":60,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FC":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F469-1F3FC","non_qualified":"1F469-1F3FC-200D-2764-200D-1F469-1F3FC","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f469-1f3fc.png","sheet_x":20,"sheet_y":61,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F469-1F3FD","non_qualified":"1F469-1F3FC-200D-2764-200D-1F469-1F3FD","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f469-1f3fd.png","sheet_x":21,"sheet_y":0,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F469-1F3FE","non_qualified":"1F469-1F3FC-200D-2764-200D-1F469-1F3FE","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f469-1f3fe.png","sheet_x":21,"sheet_y":1,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F469-1F3FF","non_qualified":"1F469-1F3FC-200D-2764-200D-1F469-1F3FF","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f469-1f3ff.png","sheet_x":21,"sheet_y":2,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F469-1F3FB","non_qualified":"1F469-1F3FD-200D-2764-200D-1F469-1F3FB","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f469-1f3fb.png","sheet_x":21,"sheet_y":3,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F469-1F3FC","non_qualified":"1F469-1F3FD-200D-2764-200D-1F469-1F3FC","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f469-1f3fc.png","sheet_x":21,"sheet_y":4,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FD":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F469-1F3FD","non_qualified":"1F469-1F3FD-200D-2764-200D-1F469-1F3FD","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f469-1f3fd.png","sheet_x":21,"sheet_y":5,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F469-1F3FE","non_qualified":"1F469-1F3FD-200D-2764-200D-1F469-1F3FE","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f469-1f3fe.png","sheet_x":21,"sheet_y":6,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F469-1F3FF","non_qualified":"1F469-1F3FD-200D-2764-200D-1F469-1F3FF","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f469-1f3ff.png","sheet_x":21,"sheet_y":7,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F469-1F3FB","non_qualified":"1F469-1F3FE-200D-2764-200D-1F469-1F3FB","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f469-1f3fb.png","sheet_x":21,"sheet_y":8,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F469-1F3FC","non_qualified":"1F469-1F3FE-200D-2764-200D-1F469-1F3FC","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f469-1f3fc.png","sheet_x":21,"sheet_y":9,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F469-1F3FD","non_qualified":"1F469-1F3FE-200D-2764-200D-1F469-1F3FD","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f469-1f3fd.png","sheet_x":21,"sheet_y":10,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FE":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F469-1F3FE","non_qualified":"1F469-1F3FE-200D-2764-200D-1F469-1F3FE","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f469-1f3fe.png","sheet_x":21,"sheet_y":11,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F469-1F3FF","non_qualified":"1F469-1F3FE-200D-2764-200D-1F469-1F3FF","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f469-1f3ff.png","sheet_x":21,"sheet_y":12,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F469-1F3FB","non_qualified":"1F469-1F3FF-200D-2764-200D-1F469-1F3FB","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f469-1f3fb.png","sheet_x":21,"sheet_y":13,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F469-1F3FC","non_qualified":"1F469-1F3FF-200D-2764-200D-1F469-1F3FC","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f469-1f3fc.png","sheet_x":21,"sheet_y":14,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F469-1F3FD","non_qualified":"1F469-1F3FF-200D-2764-200D-1F469-1F3FD","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f469-1f3fd.png","sheet_x":21,"sheet_y":15,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F469-1F3FE","non_qualified":"1F469-1F3FF-200D-2764-200D-1F469-1F3FE","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f469-1f3fe.png","sheet_x":21,"sheet_y":16,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FF":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F469-1F3FF","non_qualified":"1F469-1F3FF-200D-2764-200D-1F469-1F3FF","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f469-1f3ff.png","sheet_x":21,"sheet_y":17,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"KISS: WOMAN, MAN","unified":"1F469-200D-2764-FE0F-200D-1F48B-200D-1F468","non_qualified":"1F469-200D-2764-200D-1F48B-200D-1F468","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-2764-fe0f-200d-1f48b-200d-1f468.png","sheet_x":21,"sheet_y":18,"short_name":"woman-kiss-man","short_names":["woman-kiss-man"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":512,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB-1F3FB":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":21,"sheet_y":19,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":21,"sheet_y":20,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":21,"sheet_y":21,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":21,"sheet_y":22,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":21,"sheet_y":23,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":21,"sheet_y":24,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FC":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":21,"sheet_y":25,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":21,"sheet_y":26,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":21,"sheet_y":27,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":21,"sheet_y":28,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":21,"sheet_y":29,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":21,"sheet_y":30,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FD":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":21,"sheet_y":31,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":21,"sheet_y":32,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":21,"sheet_y":33,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":21,"sheet_y":34,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":21,"sheet_y":35,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":21,"sheet_y":36,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FE":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":21,"sheet_y":37,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":21,"sheet_y":38,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FB","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb.png","sheet_x":21,"sheet_y":39,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FC","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FC","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc.png","sheet_x":21,"sheet_y":40,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FD","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FD","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd.png","sheet_x":21,"sheet_y":41,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FE","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FE","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe.png","sheet_x":21,"sheet_y":42,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FF":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FF","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F468-1F3FF","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff.png","sheet_x":21,"sheet_y":43,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"KISS: WOMAN, WOMAN","unified":"1F469-200D-2764-FE0F-200D-1F48B-200D-1F469","non_qualified":"1F469-200D-2764-200D-1F48B-200D-1F469","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f469-200d-2764-fe0f-200d-1f48b-200d-1f469.png","sheet_x":21,"sheet_y":44,"short_name":"woman-kiss-woman","short_names":["woman-kiss-woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":514,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB-1F3FB":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FB","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F469-1F3FB","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fb.png","sheet_x":21,"sheet_y":45,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FC","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F469-1F3FC","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fc.png","sheet_x":21,"sheet_y":46,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FD","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F469-1F3FD","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fd.png","sheet_x":21,"sheet_y":47,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FE","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F469-1F3FE","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fe.png","sheet_x":21,"sheet_y":48,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F469-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FF","non_qualified":"1F469-1F3FB-200D-2764-200D-1F48B-200D-1F469-1F3FF","image":"1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3ff.png","sheet_x":21,"sheet_y":49,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FB","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F469-1F3FB","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fb.png","sheet_x":21,"sheet_y":50,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FC":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FC","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F469-1F3FC","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fc.png","sheet_x":21,"sheet_y":51,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FD","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F469-1F3FD","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fd.png","sheet_x":21,"sheet_y":52,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FE","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F469-1F3FE","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fe.png","sheet_x":21,"sheet_y":53,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F469-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FF","non_qualified":"1F469-1F3FC-200D-2764-200D-1F48B-200D-1F469-1F3FF","image":"1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3ff.png","sheet_x":21,"sheet_y":54,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FB","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F469-1F3FB","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fb.png","sheet_x":21,"sheet_y":55,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FC","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F469-1F3FC","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fc.png","sheet_x":21,"sheet_y":56,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FD":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FD","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F469-1F3FD","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fd.png","sheet_x":21,"sheet_y":57,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FE","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F469-1F3FE","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fe.png","sheet_x":21,"sheet_y":58,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F469-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FF","non_qualified":"1F469-1F3FD-200D-2764-200D-1F48B-200D-1F469-1F3FF","image":"1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3ff.png","sheet_x":21,"sheet_y":59,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FB","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F469-1F3FB","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fb.png","sheet_x":21,"sheet_y":60,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FC","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F469-1F3FC","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fc.png","sheet_x":21,"sheet_y":61,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FD","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F469-1F3FD","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fd.png","sheet_x":22,"sheet_y":0,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FE":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FE","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F469-1F3FE","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fe.png","sheet_x":22,"sheet_y":1,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F469-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FF","non_qualified":"1F469-1F3FE-200D-2764-200D-1F48B-200D-1F469-1F3FF","image":"1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3ff.png","sheet_x":22,"sheet_y":2,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FB","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F469-1F3FB","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fb.png","sheet_x":22,"sheet_y":3,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FC","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F469-1F3FC","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fc.png","sheet_x":22,"sheet_y":4,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FD","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F469-1F3FD","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fd.png","sheet_x":22,"sheet_y":5,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FE","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F469-1F3FE","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fe.png","sheet_x":22,"sheet_y":6,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FF":{"unified":"1F469-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F469-1F3FF","non_qualified":"1F469-1F3FF-200D-2764-200D-1F48B-200D-1F469-1F3FF","image":"1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3ff.png","sheet_x":22,"sheet_y":7,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN","unified":"1F469","non_qualified":null,"docomo":"E6F0","au":"E4FA","softbank":"E005","google":"FE19E","image":"1f469.png","sheet_x":22,"sheet_y":8,"short_name":"woman","short_names":["woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":244,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F469-1F3FB","non_qualified":null,"image":"1f469-1f3fb.png","sheet_x":22,"sheet_y":9,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F469-1F3FC","non_qualified":null,"image":"1f469-1f3fc.png","sheet_x":22,"sheet_y":10,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F469-1F3FD","non_qualified":null,"image":"1f469-1f3fd.png","sheet_x":22,"sheet_y":11,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F469-1F3FE","non_qualified":null,"image":"1f469-1f3fe.png","sheet_x":22,"sheet_y":12,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F469-1F3FF","non_qualified":null,"image":"1f469-1f3ff.png","sheet_x":22,"sheet_y":13,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FAMILY","unified":"1F46A","non_qualified":null,"docomo":null,"au":"E501","softbank":null,"google":"FE19F","image":"1f46a.png","sheet_x":22,"sheet_y":14,"short_name":"family","short_names":["family"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":548,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F468-200D-1F469-200D-1F466"},{"name":"MAN AND WOMAN HOLDING HANDS","unified":"1F46B","non_qualified":null,"docomo":null,"au":null,"softbank":"E428","google":"FE1A0","image":"1f46b.png","sheet_x":22,"sheet_y":15,"short_name":"man_and_woman_holding_hands","short_names":["man_and_woman_holding_hands","woman_and_man_holding_hands","couple"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":509,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F46B-1F3FB","non_qualified":null,"image":"1f46b-1f3fb.png","sheet_x":22,"sheet_y":16,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F46B-1F3FC","non_qualified":null,"image":"1f46b-1f3fc.png","sheet_x":22,"sheet_y":17,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F46B-1F3FD","non_qualified":null,"image":"1f46b-1f3fd.png","sheet_x":22,"sheet_y":18,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F46B-1F3FE","non_qualified":null,"image":"1f46b-1f3fe.png","sheet_x":22,"sheet_y":19,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F46B-1F3FF","non_qualified":null,"image":"1f46b-1f3ff.png","sheet_x":22,"sheet_y":20,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F469-1F3FB-200D-1F91D-200D-1F468-1F3FC","non_qualified":null,"image":"1f469-1f3fb-200d-1f91d-200d-1f468-1f3fc.png","sheet_x":22,"sheet_y":21,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F469-1F3FB-200D-1F91D-200D-1F468-1F3FD","non_qualified":null,"image":"1f469-1f3fb-200d-1f91d-200d-1f468-1f3fd.png","sheet_x":22,"sheet_y":22,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F469-1F3FB-200D-1F91D-200D-1F468-1F3FE","non_qualified":null,"image":"1f469-1f3fb-200d-1f91d-200d-1f468-1f3fe.png","sheet_x":22,"sheet_y":23,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F469-1F3FB-200D-1F91D-200D-1F468-1F3FF","non_qualified":null,"image":"1f469-1f3fb-200d-1f91d-200d-1f468-1f3ff.png","sheet_x":22,"sheet_y":24,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F469-1F3FC-200D-1F91D-200D-1F468-1F3FB","non_qualified":null,"image":"1f469-1f3fc-200d-1f91d-200d-1f468-1f3fb.png","sheet_x":22,"sheet_y":25,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F469-1F3FC-200D-1F91D-200D-1F468-1F3FD","non_qualified":null,"image":"1f469-1f3fc-200d-1f91d-200d-1f468-1f3fd.png","sheet_x":22,"sheet_y":26,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F469-1F3FC-200D-1F91D-200D-1F468-1F3FE","non_qualified":null,"image":"1f469-1f3fc-200d-1f91d-200d-1f468-1f3fe.png","sheet_x":22,"sheet_y":27,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F469-1F3FC-200D-1F91D-200D-1F468-1F3FF","non_qualified":null,"image":"1f469-1f3fc-200d-1f91d-200d-1f468-1f3ff.png","sheet_x":22,"sheet_y":28,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F469-1F3FD-200D-1F91D-200D-1F468-1F3FB","non_qualified":null,"image":"1f469-1f3fd-200d-1f91d-200d-1f468-1f3fb.png","sheet_x":22,"sheet_y":29,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F469-1F3FD-200D-1F91D-200D-1F468-1F3FC","non_qualified":null,"image":"1f469-1f3fd-200d-1f91d-200d-1f468-1f3fc.png","sheet_x":22,"sheet_y":30,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F469-1F3FD-200D-1F91D-200D-1F468-1F3FE","non_qualified":null,"image":"1f469-1f3fd-200d-1f91d-200d-1f468-1f3fe.png","sheet_x":22,"sheet_y":31,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F469-1F3FD-200D-1F91D-200D-1F468-1F3FF","non_qualified":null,"image":"1f469-1f3fd-200d-1f91d-200d-1f468-1f3ff.png","sheet_x":22,"sheet_y":32,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F469-1F3FE-200D-1F91D-200D-1F468-1F3FB","non_qualified":null,"image":"1f469-1f3fe-200d-1f91d-200d-1f468-1f3fb.png","sheet_x":22,"sheet_y":33,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F469-1F3FE-200D-1F91D-200D-1F468-1F3FC","non_qualified":null,"image":"1f469-1f3fe-200d-1f91d-200d-1f468-1f3fc.png","sheet_x":22,"sheet_y":34,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F469-1F3FE-200D-1F91D-200D-1F468-1F3FD","non_qualified":null,"image":"1f469-1f3fe-200d-1f91d-200d-1f468-1f3fd.png","sheet_x":22,"sheet_y":35,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F469-1F3FE-200D-1F91D-200D-1F468-1F3FF","non_qualified":null,"image":"1f469-1f3fe-200d-1f91d-200d-1f468-1f3ff.png","sheet_x":22,"sheet_y":36,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F469-1F3FF-200D-1F91D-200D-1F468-1F3FB","non_qualified":null,"image":"1f469-1f3ff-200d-1f91d-200d-1f468-1f3fb.png","sheet_x":22,"sheet_y":37,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F469-1F3FF-200D-1F91D-200D-1F468-1F3FC","non_qualified":null,"image":"1f469-1f3ff-200d-1f91d-200d-1f468-1f3fc.png","sheet_x":22,"sheet_y":38,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F469-1F3FF-200D-1F91D-200D-1F468-1F3FD","non_qualified":null,"image":"1f469-1f3ff-200d-1f91d-200d-1f468-1f3fd.png","sheet_x":22,"sheet_y":39,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F469-1F3FF-200D-1F91D-200D-1F468-1F3FE","non_qualified":null,"image":"1f469-1f3ff-200d-1f91d-200d-1f468-1f3fe.png","sheet_x":22,"sheet_y":40,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"TWO MEN HOLDING HANDS","unified":"1F46C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f46c.png","sheet_x":22,"sheet_y":41,"short_name":"two_men_holding_hands","short_names":["two_men_holding_hands","men_holding_hands"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":510,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F46C-1F3FB","non_qualified":null,"image":"1f46c-1f3fb.png","sheet_x":22,"sheet_y":42,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F46C-1F3FC","non_qualified":null,"image":"1f46c-1f3fc.png","sheet_x":22,"sheet_y":43,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F46C-1F3FD","non_qualified":null,"image":"1f46c-1f3fd.png","sheet_x":22,"sheet_y":44,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F46C-1F3FE","non_qualified":null,"image":"1f46c-1f3fe.png","sheet_x":22,"sheet_y":45,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F46C-1F3FF","non_qualified":null,"image":"1f46c-1f3ff.png","sheet_x":22,"sheet_y":46,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F468-1F3FB-200D-1F91D-200D-1F468-1F3FC","non_qualified":null,"image":"1f468-1f3fb-200d-1f91d-200d-1f468-1f3fc.png","sheet_x":22,"sheet_y":47,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F468-1F3FB-200D-1F91D-200D-1F468-1F3FD","non_qualified":null,"image":"1f468-1f3fb-200d-1f91d-200d-1f468-1f3fd.png","sheet_x":22,"sheet_y":48,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F468-1F3FB-200D-1F91D-200D-1F468-1F3FE","non_qualified":null,"image":"1f468-1f3fb-200d-1f91d-200d-1f468-1f3fe.png","sheet_x":22,"sheet_y":49,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F468-1F3FB-200D-1F91D-200D-1F468-1F3FF","non_qualified":null,"image":"1f468-1f3fb-200d-1f91d-200d-1f468-1f3ff.png","sheet_x":22,"sheet_y":50,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F468-1F3FC-200D-1F91D-200D-1F468-1F3FB","non_qualified":null,"image":"1f468-1f3fc-200d-1f91d-200d-1f468-1f3fb.png","sheet_x":22,"sheet_y":51,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F468-1F3FC-200D-1F91D-200D-1F468-1F3FD","non_qualified":null,"image":"1f468-1f3fc-200d-1f91d-200d-1f468-1f3fd.png","sheet_x":22,"sheet_y":52,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F468-1F3FC-200D-1F91D-200D-1F468-1F3FE","non_qualified":null,"image":"1f468-1f3fc-200d-1f91d-200d-1f468-1f3fe.png","sheet_x":22,"sheet_y":53,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F468-1F3FC-200D-1F91D-200D-1F468-1F3FF","non_qualified":null,"image":"1f468-1f3fc-200d-1f91d-200d-1f468-1f3ff.png","sheet_x":22,"sheet_y":54,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F468-1F3FD-200D-1F91D-200D-1F468-1F3FB","non_qualified":null,"image":"1f468-1f3fd-200d-1f91d-200d-1f468-1f3fb.png","sheet_x":22,"sheet_y":55,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F468-1F3FD-200D-1F91D-200D-1F468-1F3FC","non_qualified":null,"image":"1f468-1f3fd-200d-1f91d-200d-1f468-1f3fc.png","sheet_x":22,"sheet_y":56,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F468-1F3FD-200D-1F91D-200D-1F468-1F3FE","non_qualified":null,"image":"1f468-1f3fd-200d-1f91d-200d-1f468-1f3fe.png","sheet_x":22,"sheet_y":57,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F468-1F3FD-200D-1F91D-200D-1F468-1F3FF","non_qualified":null,"image":"1f468-1f3fd-200d-1f91d-200d-1f468-1f3ff.png","sheet_x":22,"sheet_y":58,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F468-1F3FE-200D-1F91D-200D-1F468-1F3FB","non_qualified":null,"image":"1f468-1f3fe-200d-1f91d-200d-1f468-1f3fb.png","sheet_x":22,"sheet_y":59,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F468-1F3FE-200D-1F91D-200D-1F468-1F3FC","non_qualified":null,"image":"1f468-1f3fe-200d-1f91d-200d-1f468-1f3fc.png","sheet_x":22,"sheet_y":60,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F468-1F3FE-200D-1F91D-200D-1F468-1F3FD","non_qualified":null,"image":"1f468-1f3fe-200d-1f91d-200d-1f468-1f3fd.png","sheet_x":22,"sheet_y":61,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F468-1F3FE-200D-1F91D-200D-1F468-1F3FF","non_qualified":null,"image":"1f468-1f3fe-200d-1f91d-200d-1f468-1f3ff.png","sheet_x":23,"sheet_y":0,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F468-1F3FF-200D-1F91D-200D-1F468-1F3FB","non_qualified":null,"image":"1f468-1f3ff-200d-1f91d-200d-1f468-1f3fb.png","sheet_x":23,"sheet_y":1,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F468-1F3FF-200D-1F91D-200D-1F468-1F3FC","non_qualified":null,"image":"1f468-1f3ff-200d-1f91d-200d-1f468-1f3fc.png","sheet_x":23,"sheet_y":2,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F468-1F3FF-200D-1F91D-200D-1F468-1F3FD","non_qualified":null,"image":"1f468-1f3ff-200d-1f91d-200d-1f468-1f3fd.png","sheet_x":23,"sheet_y":3,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F468-1F3FF-200D-1F91D-200D-1F468-1F3FE","non_qualified":null,"image":"1f468-1f3ff-200d-1f91d-200d-1f468-1f3fe.png","sheet_x":23,"sheet_y":4,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"TWO WOMEN HOLDING HANDS","unified":"1F46D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f46d.png","sheet_x":23,"sheet_y":5,"short_name":"two_women_holding_hands","short_names":["two_women_holding_hands","women_holding_hands"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":508,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F46D-1F3FB","non_qualified":null,"image":"1f46d-1f3fb.png","sheet_x":23,"sheet_y":6,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F46D-1F3FC","non_qualified":null,"image":"1f46d-1f3fc.png","sheet_x":23,"sheet_y":7,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F46D-1F3FD","non_qualified":null,"image":"1f46d-1f3fd.png","sheet_x":23,"sheet_y":8,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F46D-1F3FE","non_qualified":null,"image":"1f46d-1f3fe.png","sheet_x":23,"sheet_y":9,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F46D-1F3FF","non_qualified":null,"image":"1f46d-1f3ff.png","sheet_x":23,"sheet_y":10,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F469-1F3FB-200D-1F91D-200D-1F469-1F3FC","non_qualified":null,"image":"1f469-1f3fb-200d-1f91d-200d-1f469-1f3fc.png","sheet_x":23,"sheet_y":11,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F469-1F3FB-200D-1F91D-200D-1F469-1F3FD","non_qualified":null,"image":"1f469-1f3fb-200d-1f91d-200d-1f469-1f3fd.png","sheet_x":23,"sheet_y":12,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F469-1F3FB-200D-1F91D-200D-1F469-1F3FE","non_qualified":null,"image":"1f469-1f3fb-200d-1f91d-200d-1f469-1f3fe.png","sheet_x":23,"sheet_y":13,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F469-1F3FB-200D-1F91D-200D-1F469-1F3FF","non_qualified":null,"image":"1f469-1f3fb-200d-1f91d-200d-1f469-1f3ff.png","sheet_x":23,"sheet_y":14,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F469-1F3FC-200D-1F91D-200D-1F469-1F3FB","non_qualified":null,"image":"1f469-1f3fc-200d-1f91d-200d-1f469-1f3fb.png","sheet_x":23,"sheet_y":15,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F469-1F3FC-200D-1F91D-200D-1F469-1F3FD","non_qualified":null,"image":"1f469-1f3fc-200d-1f91d-200d-1f469-1f3fd.png","sheet_x":23,"sheet_y":16,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F469-1F3FC-200D-1F91D-200D-1F469-1F3FE","non_qualified":null,"image":"1f469-1f3fc-200d-1f91d-200d-1f469-1f3fe.png","sheet_x":23,"sheet_y":17,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F469-1F3FC-200D-1F91D-200D-1F469-1F3FF","non_qualified":null,"image":"1f469-1f3fc-200d-1f91d-200d-1f469-1f3ff.png","sheet_x":23,"sheet_y":18,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F469-1F3FD-200D-1F91D-200D-1F469-1F3FB","non_qualified":null,"image":"1f469-1f3fd-200d-1f91d-200d-1f469-1f3fb.png","sheet_x":23,"sheet_y":19,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F469-1F3FD-200D-1F91D-200D-1F469-1F3FC","non_qualified":null,"image":"1f469-1f3fd-200d-1f91d-200d-1f469-1f3fc.png","sheet_x":23,"sheet_y":20,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F469-1F3FD-200D-1F91D-200D-1F469-1F3FE","non_qualified":null,"image":"1f469-1f3fd-200d-1f91d-200d-1f469-1f3fe.png","sheet_x":23,"sheet_y":21,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F469-1F3FD-200D-1F91D-200D-1F469-1F3FF","non_qualified":null,"image":"1f469-1f3fd-200d-1f91d-200d-1f469-1f3ff.png","sheet_x":23,"sheet_y":22,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F469-1F3FE-200D-1F91D-200D-1F469-1F3FB","non_qualified":null,"image":"1f469-1f3fe-200d-1f91d-200d-1f469-1f3fb.png","sheet_x":23,"sheet_y":23,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F469-1F3FE-200D-1F91D-200D-1F469-1F3FC","non_qualified":null,"image":"1f469-1f3fe-200d-1f91d-200d-1f469-1f3fc.png","sheet_x":23,"sheet_y":24,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F469-1F3FE-200D-1F91D-200D-1F469-1F3FD","non_qualified":null,"image":"1f469-1f3fe-200d-1f91d-200d-1f469-1f3fd.png","sheet_x":23,"sheet_y":25,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F469-1F3FE-200D-1F91D-200D-1F469-1F3FF","non_qualified":null,"image":"1f469-1f3fe-200d-1f91d-200d-1f469-1f3ff.png","sheet_x":23,"sheet_y":26,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F469-1F3FF-200D-1F91D-200D-1F469-1F3FB","non_qualified":null,"image":"1f469-1f3ff-200d-1f91d-200d-1f469-1f3fb.png","sheet_x":23,"sheet_y":27,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F469-1F3FF-200D-1F91D-200D-1F469-1F3FC","non_qualified":null,"image":"1f469-1f3ff-200d-1f91d-200d-1f469-1f3fc.png","sheet_x":23,"sheet_y":28,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F469-1F3FF-200D-1F91D-200D-1F469-1F3FD","non_qualified":null,"image":"1f469-1f3ff-200d-1f91d-200d-1f469-1f3fd.png","sheet_x":23,"sheet_y":29,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F469-1F3FF-200D-1F91D-200D-1F469-1F3FE","non_qualified":null,"image":"1f469-1f3ff-200d-1f91d-200d-1f469-1f3fe.png","sheet_x":23,"sheet_y":30,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN POLICE OFFICER","unified":"1F46E-200D-2640-FE0F","non_qualified":"1F46E-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f46e-200d-2640-fe0f.png","sheet_x":23,"sheet_y":31,"short_name":"female-police-officer","short_names":["female-police-officer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":338,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F46E-1F3FB-200D-2640-FE0F","non_qualified":"1F46E-1F3FB-200D-2640","image":"1f46e-1f3fb-200d-2640-fe0f.png","sheet_x":23,"sheet_y":32,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F46E-1F3FC-200D-2640-FE0F","non_qualified":"1F46E-1F3FC-200D-2640","image":"1f46e-1f3fc-200d-2640-fe0f.png","sheet_x":23,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F46E-1F3FD-200D-2640-FE0F","non_qualified":"1F46E-1F3FD-200D-2640","image":"1f46e-1f3fd-200d-2640-fe0f.png","sheet_x":23,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F46E-1F3FE-200D-2640-FE0F","non_qualified":"1F46E-1F3FE-200D-2640","image":"1f46e-1f3fe-200d-2640-fe0f.png","sheet_x":23,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F46E-1F3FF-200D-2640-FE0F","non_qualified":"1F46E-1F3FF-200D-2640","image":"1f46e-1f3ff-200d-2640-fe0f.png","sheet_x":23,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN POLICE OFFICER","unified":"1F46E-200D-2642-FE0F","non_qualified":"1F46E-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f46e-200d-2642-fe0f.png","sheet_x":23,"sheet_y":37,"short_name":"male-police-officer","short_names":["male-police-officer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":337,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F46E-1F3FB-200D-2642-FE0F","non_qualified":"1F46E-1F3FB-200D-2642","image":"1f46e-1f3fb-200d-2642-fe0f.png","sheet_x":23,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F46E-1F3FC-200D-2642-FE0F","non_qualified":"1F46E-1F3FC-200D-2642","image":"1f46e-1f3fc-200d-2642-fe0f.png","sheet_x":23,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F46E-1F3FD-200D-2642-FE0F","non_qualified":"1F46E-1F3FD-200D-2642","image":"1f46e-1f3fd-200d-2642-fe0f.png","sheet_x":23,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F46E-1F3FE-200D-2642-FE0F","non_qualified":"1F46E-1F3FE-200D-2642","image":"1f46e-1f3fe-200d-2642-fe0f.png","sheet_x":23,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F46E-1F3FF-200D-2642-FE0F","non_qualified":"1F46E-1F3FF-200D-2642","image":"1f46e-1f3ff-200d-2642-fe0f.png","sheet_x":23,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F46E"},{"name":"POLICE OFFICER","unified":"1F46E","non_qualified":null,"docomo":null,"au":"E5DD","softbank":"E152","google":"FE1A1","image":"1f46e.png","sheet_x":23,"sheet_y":43,"short_name":"cop","short_names":["cop"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":336,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F46E-1F3FB","non_qualified":null,"image":"1f46e-1f3fb.png","sheet_x":23,"sheet_y":44,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F46E-1F3FC","non_qualified":null,"image":"1f46e-1f3fc.png","sheet_x":23,"sheet_y":45,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F46E-1F3FD","non_qualified":null,"image":"1f46e-1f3fd.png","sheet_x":23,"sheet_y":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F46E-1F3FE","non_qualified":null,"image":"1f46e-1f3fe.png","sheet_x":23,"sheet_y":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F46E-1F3FF","non_qualified":null,"image":"1f46e-1f3ff.png","sheet_x":23,"sheet_y":48,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F46E-200D-2642-FE0F"},{"name":"WOMEN WITH BUNNY EARS","unified":"1F46F-200D-2640-FE0F","non_qualified":"1F46F-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f46f-200d-2640-fe0f.png","sheet_x":23,"sheet_y":49,"short_name":"women-with-bunny-ears-partying","short_names":["women-with-bunny-ears-partying","woman-with-bunny-ears-partying"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":452,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F46F"},{"name":"MEN WITH BUNNY EARS","unified":"1F46F-200D-2642-FE0F","non_qualified":"1F46F-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f46f-200d-2642-fe0f.png","sheet_x":23,"sheet_y":50,"short_name":"men-with-bunny-ears-partying","short_names":["men-with-bunny-ears-partying","man-with-bunny-ears-partying"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":451,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN WITH BUNNY EARS","unified":"1F46F","non_qualified":null,"docomo":null,"au":"EADB","softbank":"E429","google":"FE1A2","image":"1f46f.png","sheet_x":23,"sheet_y":51,"short_name":"dancers","short_names":["dancers"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":450,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F46F-200D-2640-FE0F"},{"name":"WOMAN WITH VEIL","unified":"1F470-200D-2640-FE0F","non_qualified":"1F470-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f470-200d-2640-fe0f.png","sheet_x":23,"sheet_y":52,"short_name":"woman_with_veil","short_names":["woman_with_veil"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":362,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F470-1F3FB-200D-2640-FE0F","non_qualified":"1F470-1F3FB-200D-2640","image":"1f470-1f3fb-200d-2640-fe0f.png","sheet_x":23,"sheet_y":53,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F470-1F3FC-200D-2640-FE0F","non_qualified":"1F470-1F3FC-200D-2640","image":"1f470-1f3fc-200d-2640-fe0f.png","sheet_x":23,"sheet_y":54,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F470-1F3FD-200D-2640-FE0F","non_qualified":"1F470-1F3FD-200D-2640","image":"1f470-1f3fd-200d-2640-fe0f.png","sheet_x":23,"sheet_y":55,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F470-1F3FE-200D-2640-FE0F","non_qualified":"1F470-1F3FE-200D-2640","image":"1f470-1f3fe-200d-2640-fe0f.png","sheet_x":23,"sheet_y":56,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F470-1F3FF-200D-2640-FE0F","non_qualified":"1F470-1F3FF-200D-2640","image":"1f470-1f3ff-200d-2640-fe0f.png","sheet_x":23,"sheet_y":57,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN WITH VEIL","unified":"1F470-200D-2642-FE0F","non_qualified":"1F470-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f470-200d-2642-fe0f.png","sheet_x":23,"sheet_y":58,"short_name":"man_with_veil","short_names":["man_with_veil"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":361,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F470-1F3FB-200D-2642-FE0F","non_qualified":"1F470-1F3FB-200D-2642","image":"1f470-1f3fb-200d-2642-fe0f.png","sheet_x":23,"sheet_y":59,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F470-1F3FC-200D-2642-FE0F","non_qualified":"1F470-1F3FC-200D-2642","image":"1f470-1f3fc-200d-2642-fe0f.png","sheet_x":23,"sheet_y":60,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F470-1F3FD-200D-2642-FE0F","non_qualified":"1F470-1F3FD-200D-2642","image":"1f470-1f3fd-200d-2642-fe0f.png","sheet_x":23,"sheet_y":61,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F470-1F3FE-200D-2642-FE0F","non_qualified":"1F470-1F3FE-200D-2642","image":"1f470-1f3fe-200d-2642-fe0f.png","sheet_x":24,"sheet_y":0,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F470-1F3FF-200D-2642-FE0F","non_qualified":"1F470-1F3FF-200D-2642","image":"1f470-1f3ff-200d-2642-fe0f.png","sheet_x":24,"sheet_y":1,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"BRIDE WITH VEIL","unified":"1F470","non_qualified":null,"docomo":null,"au":"EAE9","softbank":null,"google":"FE1A3","image":"1f470.png","sheet_x":24,"sheet_y":2,"short_name":"bride_with_veil","short_names":["bride_with_veil"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":360,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F470-1F3FB","non_qualified":null,"image":"1f470-1f3fb.png","sheet_x":24,"sheet_y":3,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F470-1F3FC","non_qualified":null,"image":"1f470-1f3fc.png","sheet_x":24,"sheet_y":4,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F470-1F3FD","non_qualified":null,"image":"1f470-1f3fd.png","sheet_x":24,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F470-1F3FE","non_qualified":null,"image":"1f470-1f3fe.png","sheet_x":24,"sheet_y":6,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F470-1F3FF","non_qualified":null,"image":"1f470-1f3ff.png","sheet_x":24,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN: BLOND HAIR","unified":"1F471-200D-2640-FE0F","non_qualified":"1F471-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f471-200d-2640-fe0f.png","sheet_x":24,"sheet_y":8,"short_name":"blond-haired-woman","short_names":["blond-haired-woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":253,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F471-1F3FB-200D-2640-FE0F","non_qualified":"1F471-1F3FB-200D-2640","image":"1f471-1f3fb-200d-2640-fe0f.png","sheet_x":24,"sheet_y":9,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F471-1F3FC-200D-2640-FE0F","non_qualified":"1F471-1F3FC-200D-2640","image":"1f471-1f3fc-200d-2640-fe0f.png","sheet_x":24,"sheet_y":10,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F471-1F3FD-200D-2640-FE0F","non_qualified":"1F471-1F3FD-200D-2640","image":"1f471-1f3fd-200d-2640-fe0f.png","sheet_x":24,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F471-1F3FE-200D-2640-FE0F","non_qualified":"1F471-1F3FE-200D-2640","image":"1f471-1f3fe-200d-2640-fe0f.png","sheet_x":24,"sheet_y":12,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F471-1F3FF-200D-2640-FE0F","non_qualified":"1F471-1F3FF-200D-2640","image":"1f471-1f3ff-200d-2640-fe0f.png","sheet_x":24,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN: BLOND HAIR","unified":"1F471-200D-2642-FE0F","non_qualified":"1F471-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f471-200d-2642-fe0f.png","sheet_x":24,"sheet_y":14,"short_name":"blond-haired-man","short_names":["blond-haired-man"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":254,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F471-1F3FB-200D-2642-FE0F","non_qualified":"1F471-1F3FB-200D-2642","image":"1f471-1f3fb-200d-2642-fe0f.png","sheet_x":24,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F471-1F3FC-200D-2642-FE0F","non_qualified":"1F471-1F3FC-200D-2642","image":"1f471-1f3fc-200d-2642-fe0f.png","sheet_x":24,"sheet_y":16,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F471-1F3FD-200D-2642-FE0F","non_qualified":"1F471-1F3FD-200D-2642","image":"1f471-1f3fd-200d-2642-fe0f.png","sheet_x":24,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F471-1F3FE-200D-2642-FE0F","non_qualified":"1F471-1F3FE-200D-2642","image":"1f471-1f3fe-200d-2642-fe0f.png","sheet_x":24,"sheet_y":18,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F471-1F3FF-200D-2642-FE0F","non_qualified":"1F471-1F3FF-200D-2642","image":"1f471-1f3ff-200d-2642-fe0f.png","sheet_x":24,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F471"},{"name":"PERSON WITH BLOND HAIR","unified":"1F471","non_qualified":null,"docomo":null,"au":"EB13","softbank":"E515","google":"FE1A4","image":"1f471.png","sheet_x":24,"sheet_y":20,"short_name":"person_with_blond_hair","short_names":["person_with_blond_hair"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":235,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F471-1F3FB","non_qualified":null,"image":"1f471-1f3fb.png","sheet_x":24,"sheet_y":21,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F471-1F3FC","non_qualified":null,"image":"1f471-1f3fc.png","sheet_x":24,"sheet_y":22,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F471-1F3FD","non_qualified":null,"image":"1f471-1f3fd.png","sheet_x":24,"sheet_y":23,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F471-1F3FE","non_qualified":null,"image":"1f471-1f3fe.png","sheet_x":24,"sheet_y":24,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F471-1F3FF","non_qualified":null,"image":"1f471-1f3ff.png","sheet_x":24,"sheet_y":25,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F471-200D-2642-FE0F"},{"name":"MAN WITH GUA PI MAO","unified":"1F472","non_qualified":null,"docomo":null,"au":"EB14","softbank":"E516","google":"FE1A5","image":"1f472.png","sheet_x":24,"sheet_y":26,"short_name":"man_with_gua_pi_mao","short_names":["man_with_gua_pi_mao"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":355,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F472-1F3FB","non_qualified":null,"image":"1f472-1f3fb.png","sheet_x":24,"sheet_y":27,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F472-1F3FC","non_qualified":null,"image":"1f472-1f3fc.png","sheet_x":24,"sheet_y":28,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F472-1F3FD","non_qualified":null,"image":"1f472-1f3fd.png","sheet_x":24,"sheet_y":29,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F472-1F3FE","non_qualified":null,"image":"1f472-1f3fe.png","sheet_x":24,"sheet_y":30,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F472-1F3FF","non_qualified":null,"image":"1f472-1f3ff.png","sheet_x":24,"sheet_y":31,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN WEARING TURBAN","unified":"1F473-200D-2640-FE0F","non_qualified":"1F473-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f473-200d-2640-fe0f.png","sheet_x":24,"sheet_y":32,"short_name":"woman-wearing-turban","short_names":["woman-wearing-turban"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":354,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F473-1F3FB-200D-2640-FE0F","non_qualified":"1F473-1F3FB-200D-2640","image":"1f473-1f3fb-200d-2640-fe0f.png","sheet_x":24,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F473-1F3FC-200D-2640-FE0F","non_qualified":"1F473-1F3FC-200D-2640","image":"1f473-1f3fc-200d-2640-fe0f.png","sheet_x":24,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F473-1F3FD-200D-2640-FE0F","non_qualified":"1F473-1F3FD-200D-2640","image":"1f473-1f3fd-200d-2640-fe0f.png","sheet_x":24,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F473-1F3FE-200D-2640-FE0F","non_qualified":"1F473-1F3FE-200D-2640","image":"1f473-1f3fe-200d-2640-fe0f.png","sheet_x":24,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F473-1F3FF-200D-2640-FE0F","non_qualified":"1F473-1F3FF-200D-2640","image":"1f473-1f3ff-200d-2640-fe0f.png","sheet_x":24,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN WEARING TURBAN","unified":"1F473-200D-2642-FE0F","non_qualified":"1F473-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f473-200d-2642-fe0f.png","sheet_x":24,"sheet_y":38,"short_name":"man-wearing-turban","short_names":["man-wearing-turban"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":353,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F473-1F3FB-200D-2642-FE0F","non_qualified":"1F473-1F3FB-200D-2642","image":"1f473-1f3fb-200d-2642-fe0f.png","sheet_x":24,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F473-1F3FC-200D-2642-FE0F","non_qualified":"1F473-1F3FC-200D-2642","image":"1f473-1f3fc-200d-2642-fe0f.png","sheet_x":24,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F473-1F3FD-200D-2642-FE0F","non_qualified":"1F473-1F3FD-200D-2642","image":"1f473-1f3fd-200d-2642-fe0f.png","sheet_x":24,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F473-1F3FE-200D-2642-FE0F","non_qualified":"1F473-1F3FE-200D-2642","image":"1f473-1f3fe-200d-2642-fe0f.png","sheet_x":24,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F473-1F3FF-200D-2642-FE0F","non_qualified":"1F473-1F3FF-200D-2642","image":"1f473-1f3ff-200d-2642-fe0f.png","sheet_x":24,"sheet_y":43,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F473"},{"name":"MAN WITH TURBAN","unified":"1F473","non_qualified":null,"docomo":null,"au":"EB15","softbank":"E517","google":"FE1A6","image":"1f473.png","sheet_x":24,"sheet_y":44,"short_name":"man_with_turban","short_names":["man_with_turban"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":352,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F473-1F3FB","non_qualified":null,"image":"1f473-1f3fb.png","sheet_x":24,"sheet_y":45,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F473-1F3FC","non_qualified":null,"image":"1f473-1f3fc.png","sheet_x":24,"sheet_y":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F473-1F3FD","non_qualified":null,"image":"1f473-1f3fd.png","sheet_x":24,"sheet_y":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F473-1F3FE","non_qualified":null,"image":"1f473-1f3fe.png","sheet_x":24,"sheet_y":48,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F473-1F3FF","non_qualified":null,"image":"1f473-1f3ff.png","sheet_x":24,"sheet_y":49,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F473-200D-2642-FE0F"},{"name":"OLDER MAN","unified":"1F474","non_qualified":null,"docomo":null,"au":"EB16","softbank":"E518","google":"FE1A7","image":"1f474.png","sheet_x":24,"sheet_y":50,"short_name":"older_man","short_names":["older_man"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":256,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F474-1F3FB","non_qualified":null,"image":"1f474-1f3fb.png","sheet_x":24,"sheet_y":51,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F474-1F3FC","non_qualified":null,"image":"1f474-1f3fc.png","sheet_x":24,"sheet_y":52,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F474-1F3FD","non_qualified":null,"image":"1f474-1f3fd.png","sheet_x":24,"sheet_y":53,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F474-1F3FE","non_qualified":null,"image":"1f474-1f3fe.png","sheet_x":24,"sheet_y":54,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F474-1F3FF","non_qualified":null,"image":"1f474-1f3ff.png","sheet_x":24,"sheet_y":55,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"OLDER WOMAN","unified":"1F475","non_qualified":null,"docomo":null,"au":"EB17","softbank":"E519","google":"FE1A8","image":"1f475.png","sheet_x":24,"sheet_y":56,"short_name":"older_woman","short_names":["older_woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":257,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F475-1F3FB","non_qualified":null,"image":"1f475-1f3fb.png","sheet_x":24,"sheet_y":57,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F475-1F3FC","non_qualified":null,"image":"1f475-1f3fc.png","sheet_x":24,"sheet_y":58,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F475-1F3FD","non_qualified":null,"image":"1f475-1f3fd.png","sheet_x":24,"sheet_y":59,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F475-1F3FE","non_qualified":null,"image":"1f475-1f3fe.png","sheet_x":24,"sheet_y":60,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F475-1F3FF","non_qualified":null,"image":"1f475-1f3ff.png","sheet_x":24,"sheet_y":61,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"BABY","unified":"1F476","non_qualified":null,"docomo":null,"au":"EB18","softbank":"E51A","google":"FE1A9","image":"1f476.png","sheet_x":25,"sheet_y":0,"short_name":"baby","short_names":["baby"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":230,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F476-1F3FB","non_qualified":null,"image":"1f476-1f3fb.png","sheet_x":25,"sheet_y":1,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F476-1F3FC","non_qualified":null,"image":"1f476-1f3fc.png","sheet_x":25,"sheet_y":2,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F476-1F3FD","non_qualified":null,"image":"1f476-1f3fd.png","sheet_x":25,"sheet_y":3,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F476-1F3FE","non_qualified":null,"image":"1f476-1f3fe.png","sheet_x":25,"sheet_y":4,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F476-1F3FF","non_qualified":null,"image":"1f476-1f3ff.png","sheet_x":25,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN CONSTRUCTION WORKER","unified":"1F477-200D-2640-FE0F","non_qualified":"1F477-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f477-200d-2640-fe0f.png","sheet_x":25,"sheet_y":6,"short_name":"female-construction-worker","short_names":["female-construction-worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":348,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F477-1F3FB-200D-2640-FE0F","non_qualified":"1F477-1F3FB-200D-2640","image":"1f477-1f3fb-200d-2640-fe0f.png","sheet_x":25,"sheet_y":7,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F477-1F3FC-200D-2640-FE0F","non_qualified":"1F477-1F3FC-200D-2640","image":"1f477-1f3fc-200d-2640-fe0f.png","sheet_x":25,"sheet_y":8,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F477-1F3FD-200D-2640-FE0F","non_qualified":"1F477-1F3FD-200D-2640","image":"1f477-1f3fd-200d-2640-fe0f.png","sheet_x":25,"sheet_y":9,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F477-1F3FE-200D-2640-FE0F","non_qualified":"1F477-1F3FE-200D-2640","image":"1f477-1f3fe-200d-2640-fe0f.png","sheet_x":25,"sheet_y":10,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F477-1F3FF-200D-2640-FE0F","non_qualified":"1F477-1F3FF-200D-2640","image":"1f477-1f3ff-200d-2640-fe0f.png","sheet_x":25,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN CONSTRUCTION WORKER","unified":"1F477-200D-2642-FE0F","non_qualified":"1F477-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f477-200d-2642-fe0f.png","sheet_x":25,"sheet_y":12,"short_name":"male-construction-worker","short_names":["male-construction-worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":347,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F477-1F3FB-200D-2642-FE0F","non_qualified":"1F477-1F3FB-200D-2642","image":"1f477-1f3fb-200d-2642-fe0f.png","sheet_x":25,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F477-1F3FC-200D-2642-FE0F","non_qualified":"1F477-1F3FC-200D-2642","image":"1f477-1f3fc-200d-2642-fe0f.png","sheet_x":25,"sheet_y":14,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F477-1F3FD-200D-2642-FE0F","non_qualified":"1F477-1F3FD-200D-2642","image":"1f477-1f3fd-200d-2642-fe0f.png","sheet_x":25,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F477-1F3FE-200D-2642-FE0F","non_qualified":"1F477-1F3FE-200D-2642","image":"1f477-1f3fe-200d-2642-fe0f.png","sheet_x":25,"sheet_y":16,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F477-1F3FF-200D-2642-FE0F","non_qualified":"1F477-1F3FF-200D-2642","image":"1f477-1f3ff-200d-2642-fe0f.png","sheet_x":25,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F477"},{"name":"CONSTRUCTION WORKER","unified":"1F477","non_qualified":null,"docomo":null,"au":"EB19","softbank":"E51B","google":"FE1AA","image":"1f477.png","sheet_x":25,"sheet_y":18,"short_name":"construction_worker","short_names":["construction_worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":346,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F477-1F3FB","non_qualified":null,"image":"1f477-1f3fb.png","sheet_x":25,"sheet_y":19,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F477-1F3FC","non_qualified":null,"image":"1f477-1f3fc.png","sheet_x":25,"sheet_y":20,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F477-1F3FD","non_qualified":null,"image":"1f477-1f3fd.png","sheet_x":25,"sheet_y":21,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F477-1F3FE","non_qualified":null,"image":"1f477-1f3fe.png","sheet_x":25,"sheet_y":22,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F477-1F3FF","non_qualified":null,"image":"1f477-1f3ff.png","sheet_x":25,"sheet_y":23,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F477-200D-2642-FE0F"},{"name":"PRINCESS","unified":"1F478","non_qualified":null,"docomo":null,"au":"EB1A","softbank":"E51C","google":"FE1AB","image":"1f478.png","sheet_x":25,"sheet_y":24,"short_name":"princess","short_names":["princess"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":351,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F478-1F3FB","non_qualified":null,"image":"1f478-1f3fb.png","sheet_x":25,"sheet_y":25,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F478-1F3FC","non_qualified":null,"image":"1f478-1f3fc.png","sheet_x":25,"sheet_y":26,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F478-1F3FD","non_qualified":null,"image":"1f478-1f3fd.png","sheet_x":25,"sheet_y":27,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F478-1F3FE","non_qualified":null,"image":"1f478-1f3fe.png","sheet_x":25,"sheet_y":28,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F478-1F3FF","non_qualified":null,"image":"1f478-1f3ff.png","sheet_x":25,"sheet_y":29,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"JAPANESE OGRE","unified":"1F479","non_qualified":null,"docomo":null,"au":"EB44","softbank":null,"google":"FE1AC","image":"1f479.png","sheet_x":25,"sheet_y":30,"short_name":"japanese_ogre","short_names":["japanese_ogre"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-costume","sort_order":112,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JAPANESE GOBLIN","unified":"1F47A","non_qualified":null,"docomo":null,"au":"EB45","softbank":null,"google":"FE1AD","image":"1f47a.png","sheet_x":25,"sheet_y":31,"short_name":"japanese_goblin","short_names":["japanese_goblin"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-costume","sort_order":113,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GHOST","unified":"1F47B","non_qualified":null,"docomo":null,"au":"E4CB","softbank":"E11B","google":"FE1AE","image":"1f47b.png","sheet_x":25,"sheet_y":32,"short_name":"ghost","short_names":["ghost"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-costume","sort_order":114,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BABY ANGEL","unified":"1F47C","non_qualified":null,"docomo":null,"au":"E5BF","softbank":"E04E","google":"FE1AF","image":"1f47c.png","sheet_x":25,"sheet_y":33,"short_name":"angel","short_names":["angel"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":370,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F47C-1F3FB","non_qualified":null,"image":"1f47c-1f3fb.png","sheet_x":25,"sheet_y":34,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F47C-1F3FC","non_qualified":null,"image":"1f47c-1f3fc.png","sheet_x":25,"sheet_y":35,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F47C-1F3FD","non_qualified":null,"image":"1f47c-1f3fd.png","sheet_x":25,"sheet_y":36,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F47C-1F3FE","non_qualified":null,"image":"1f47c-1f3fe.png","sheet_x":25,"sheet_y":37,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F47C-1F3FF","non_qualified":null,"image":"1f47c-1f3ff.png","sheet_x":25,"sheet_y":38,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"EXTRATERRESTRIAL ALIEN","unified":"1F47D","non_qualified":null,"docomo":null,"au":"E50E","softbank":"E10C","google":"FE1B0","image":"1f47d.png","sheet_x":25,"sheet_y":39,"short_name":"alien","short_names":["alien"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-costume","sort_order":115,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ALIEN MONSTER","unified":"1F47E","non_qualified":null,"docomo":null,"au":"E4EC","softbank":"E12B","google":"FE1B1","image":"1f47e.png","sheet_x":25,"sheet_y":40,"short_name":"space_invader","short_names":["space_invader"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-costume","sort_order":116,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"IMP","unified":"1F47F","non_qualified":null,"docomo":null,"au":"E4EF","softbank":"E11A","google":"FE1B2","image":"1f47f.png","sheet_x":25,"sheet_y":41,"short_name":"imp","short_names":["imp"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-negative","sort_order":107,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SKULL","unified":"1F480","non_qualified":null,"docomo":null,"au":"E4F8","softbank":"E11C","google":"FE1B3","image":"1f480.png","sheet_x":25,"sheet_y":42,"short_name":"skull","short_names":["skull"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-negative","sort_order":108,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN TIPPING HAND","unified":"1F481-200D-2640-FE0F","non_qualified":"1F481-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f481-200d-2640-fe0f.png","sheet_x":25,"sheet_y":43,"short_name":"woman-tipping-hand","short_names":["woman-tipping-hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":272,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F481-1F3FB-200D-2640-FE0F","non_qualified":"1F481-1F3FB-200D-2640","image":"1f481-1f3fb-200d-2640-fe0f.png","sheet_x":25,"sheet_y":44,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F481-1F3FC-200D-2640-FE0F","non_qualified":"1F481-1F3FC-200D-2640","image":"1f481-1f3fc-200d-2640-fe0f.png","sheet_x":25,"sheet_y":45,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F481-1F3FD-200D-2640-FE0F","non_qualified":"1F481-1F3FD-200D-2640","image":"1f481-1f3fd-200d-2640-fe0f.png","sheet_x":25,"sheet_y":46,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F481-1F3FE-200D-2640-FE0F","non_qualified":"1F481-1F3FE-200D-2640","image":"1f481-1f3fe-200d-2640-fe0f.png","sheet_x":25,"sheet_y":47,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F481-1F3FF-200D-2640-FE0F","non_qualified":"1F481-1F3FF-200D-2640","image":"1f481-1f3ff-200d-2640-fe0f.png","sheet_x":25,"sheet_y":48,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F481"},{"name":"MAN TIPPING HAND","unified":"1F481-200D-2642-FE0F","non_qualified":"1F481-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f481-200d-2642-fe0f.png","sheet_x":25,"sheet_y":49,"short_name":"man-tipping-hand","short_names":["man-tipping-hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":271,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F481-1F3FB-200D-2642-FE0F","non_qualified":"1F481-1F3FB-200D-2642","image":"1f481-1f3fb-200d-2642-fe0f.png","sheet_x":25,"sheet_y":50,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F481-1F3FC-200D-2642-FE0F","non_qualified":"1F481-1F3FC-200D-2642","image":"1f481-1f3fc-200d-2642-fe0f.png","sheet_x":25,"sheet_y":51,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F481-1F3FD-200D-2642-FE0F","non_qualified":"1F481-1F3FD-200D-2642","image":"1f481-1f3fd-200d-2642-fe0f.png","sheet_x":25,"sheet_y":52,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F481-1F3FE-200D-2642-FE0F","non_qualified":"1F481-1F3FE-200D-2642","image":"1f481-1f3fe-200d-2642-fe0f.png","sheet_x":25,"sheet_y":53,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F481-1F3FF-200D-2642-FE0F","non_qualified":"1F481-1F3FF-200D-2642","image":"1f481-1f3ff-200d-2642-fe0f.png","sheet_x":25,"sheet_y":54,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"INFORMATION DESK PERSON","unified":"1F481","non_qualified":null,"docomo":null,"au":null,"softbank":"E253","google":"FE1B4","image":"1f481.png","sheet_x":25,"sheet_y":55,"short_name":"information_desk_person","short_names":["information_desk_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":270,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F481-1F3FB","non_qualified":null,"image":"1f481-1f3fb.png","sheet_x":25,"sheet_y":56,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F481-1F3FC","non_qualified":null,"image":"1f481-1f3fc.png","sheet_x":25,"sheet_y":57,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F481-1F3FD","non_qualified":null,"image":"1f481-1f3fd.png","sheet_x":25,"sheet_y":58,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F481-1F3FE","non_qualified":null,"image":"1f481-1f3fe.png","sheet_x":25,"sheet_y":59,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F481-1F3FF","non_qualified":null,"image":"1f481-1f3ff.png","sheet_x":25,"sheet_y":60,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F481-200D-2640-FE0F"},{"name":"WOMAN GUARD","unified":"1F482-200D-2640-FE0F","non_qualified":"1F482-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f482-200d-2640-fe0f.png","sheet_x":25,"sheet_y":61,"short_name":"female-guard","short_names":["female-guard"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":344,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F482-1F3FB-200D-2640-FE0F","non_qualified":"1F482-1F3FB-200D-2640","image":"1f482-1f3fb-200d-2640-fe0f.png","sheet_x":26,"sheet_y":0,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F482-1F3FC-200D-2640-FE0F","non_qualified":"1F482-1F3FC-200D-2640","image":"1f482-1f3fc-200d-2640-fe0f.png","sheet_x":26,"sheet_y":1,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F482-1F3FD-200D-2640-FE0F","non_qualified":"1F482-1F3FD-200D-2640","image":"1f482-1f3fd-200d-2640-fe0f.png","sheet_x":26,"sheet_y":2,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F482-1F3FE-200D-2640-FE0F","non_qualified":"1F482-1F3FE-200D-2640","image":"1f482-1f3fe-200d-2640-fe0f.png","sheet_x":26,"sheet_y":3,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F482-1F3FF-200D-2640-FE0F","non_qualified":"1F482-1F3FF-200D-2640","image":"1f482-1f3ff-200d-2640-fe0f.png","sheet_x":26,"sheet_y":4,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN GUARD","unified":"1F482-200D-2642-FE0F","non_qualified":"1F482-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f482-200d-2642-fe0f.png","sheet_x":26,"sheet_y":5,"short_name":"male-guard","short_names":["male-guard"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":343,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F482-1F3FB-200D-2642-FE0F","non_qualified":"1F482-1F3FB-200D-2642","image":"1f482-1f3fb-200d-2642-fe0f.png","sheet_x":26,"sheet_y":6,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F482-1F3FC-200D-2642-FE0F","non_qualified":"1F482-1F3FC-200D-2642","image":"1f482-1f3fc-200d-2642-fe0f.png","sheet_x":26,"sheet_y":7,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F482-1F3FD-200D-2642-FE0F","non_qualified":"1F482-1F3FD-200D-2642","image":"1f482-1f3fd-200d-2642-fe0f.png","sheet_x":26,"sheet_y":8,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F482-1F3FE-200D-2642-FE0F","non_qualified":"1F482-1F3FE-200D-2642","image":"1f482-1f3fe-200d-2642-fe0f.png","sheet_x":26,"sheet_y":9,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F482-1F3FF-200D-2642-FE0F","non_qualified":"1F482-1F3FF-200D-2642","image":"1f482-1f3ff-200d-2642-fe0f.png","sheet_x":26,"sheet_y":10,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F482"},{"name":"GUARDSMAN","unified":"1F482","non_qualified":null,"docomo":null,"au":null,"softbank":"E51E","google":"FE1B5","image":"1f482.png","sheet_x":26,"sheet_y":11,"short_name":"guardsman","short_names":["guardsman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":342,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F482-1F3FB","non_qualified":null,"image":"1f482-1f3fb.png","sheet_x":26,"sheet_y":12,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F482-1F3FC","non_qualified":null,"image":"1f482-1f3fc.png","sheet_x":26,"sheet_y":13,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F482-1F3FD","non_qualified":null,"image":"1f482-1f3fd.png","sheet_x":26,"sheet_y":14,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F482-1F3FE","non_qualified":null,"image":"1f482-1f3fe.png","sheet_x":26,"sheet_y":15,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F482-1F3FF","non_qualified":null,"image":"1f482-1f3ff.png","sheet_x":26,"sheet_y":16,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F482-200D-2642-FE0F"},{"name":"DANCER","unified":"1F483","non_qualified":null,"docomo":null,"au":"EB1C","softbank":"E51F","google":"FE1B6","image":"1f483.png","sheet_x":26,"sheet_y":17,"short_name":"dancer","short_names":["dancer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":447,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F483-1F3FB","non_qualified":null,"image":"1f483-1f3fb.png","sheet_x":26,"sheet_y":18,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F483-1F3FC","non_qualified":null,"image":"1f483-1f3fc.png","sheet_x":26,"sheet_y":19,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F483-1F3FD","non_qualified":null,"image":"1f483-1f3fd.png","sheet_x":26,"sheet_y":20,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F483-1F3FE","non_qualified":null,"image":"1f483-1f3fe.png","sheet_x":26,"sheet_y":21,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F483-1F3FF","non_qualified":null,"image":"1f483-1f3ff.png","sheet_x":26,"sheet_y":22,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"LIPSTICK","unified":"1F484","non_qualified":null,"docomo":"E710","au":"E509","softbank":"E31C","google":"FE195","image":"1f484.png","sheet_x":26,"sheet_y":23,"short_name":"lipstick","short_names":["lipstick"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1194,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NAIL POLISH","unified":"1F485","non_qualified":null,"docomo":null,"au":"EAA0","softbank":"E31D","google":"FE196","image":"1f485.png","sheet_x":26,"sheet_y":24,"short_name":"nail_care","short_names":["nail_care"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-prop","sort_order":210,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F485-1F3FB","non_qualified":null,"image":"1f485-1f3fb.png","sheet_x":26,"sheet_y":25,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F485-1F3FC","non_qualified":null,"image":"1f485-1f3fc.png","sheet_x":26,"sheet_y":26,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F485-1F3FD","non_qualified":null,"image":"1f485-1f3fd.png","sheet_x":26,"sheet_y":27,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F485-1F3FE","non_qualified":null,"image":"1f485-1f3fe.png","sheet_x":26,"sheet_y":28,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F485-1F3FF","non_qualified":null,"image":"1f485-1f3ff.png","sheet_x":26,"sheet_y":29,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN GETTING MASSAGE","unified":"1F486-200D-2640-FE0F","non_qualified":"1F486-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f486-200d-2640-fe0f.png","sheet_x":26,"sheet_y":30,"short_name":"woman-getting-massage","short_names":["woman-getting-massage"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":404,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F486-1F3FB-200D-2640-FE0F","non_qualified":"1F486-1F3FB-200D-2640","image":"1f486-1f3fb-200d-2640-fe0f.png","sheet_x":26,"sheet_y":31,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F486-1F3FC-200D-2640-FE0F","non_qualified":"1F486-1F3FC-200D-2640","image":"1f486-1f3fc-200d-2640-fe0f.png","sheet_x":26,"sheet_y":32,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F486-1F3FD-200D-2640-FE0F","non_qualified":"1F486-1F3FD-200D-2640","image":"1f486-1f3fd-200d-2640-fe0f.png","sheet_x":26,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F486-1F3FE-200D-2640-FE0F","non_qualified":"1F486-1F3FE-200D-2640","image":"1f486-1f3fe-200d-2640-fe0f.png","sheet_x":26,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F486-1F3FF-200D-2640-FE0F","non_qualified":"1F486-1F3FF-200D-2640","image":"1f486-1f3ff-200d-2640-fe0f.png","sheet_x":26,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F486"},{"name":"MAN GETTING MASSAGE","unified":"1F486-200D-2642-FE0F","non_qualified":"1F486-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f486-200d-2642-fe0f.png","sheet_x":26,"sheet_y":36,"short_name":"man-getting-massage","short_names":["man-getting-massage"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":403,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F486-1F3FB-200D-2642-FE0F","non_qualified":"1F486-1F3FB-200D-2642","image":"1f486-1f3fb-200d-2642-fe0f.png","sheet_x":26,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F486-1F3FC-200D-2642-FE0F","non_qualified":"1F486-1F3FC-200D-2642","image":"1f486-1f3fc-200d-2642-fe0f.png","sheet_x":26,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F486-1F3FD-200D-2642-FE0F","non_qualified":"1F486-1F3FD-200D-2642","image":"1f486-1f3fd-200d-2642-fe0f.png","sheet_x":26,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F486-1F3FE-200D-2642-FE0F","non_qualified":"1F486-1F3FE-200D-2642","image":"1f486-1f3fe-200d-2642-fe0f.png","sheet_x":26,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F486-1F3FF-200D-2642-FE0F","non_qualified":"1F486-1F3FF-200D-2642","image":"1f486-1f3ff-200d-2642-fe0f.png","sheet_x":26,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FACE MASSAGE","unified":"1F486","non_qualified":null,"docomo":null,"au":"E50B","softbank":"E31E","google":"FE197","image":"1f486.png","sheet_x":26,"sheet_y":42,"short_name":"massage","short_names":["massage"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":402,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F486-1F3FB","non_qualified":null,"image":"1f486-1f3fb.png","sheet_x":26,"sheet_y":43,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F486-1F3FC","non_qualified":null,"image":"1f486-1f3fc.png","sheet_x":26,"sheet_y":44,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F486-1F3FD","non_qualified":null,"image":"1f486-1f3fd.png","sheet_x":26,"sheet_y":45,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F486-1F3FE","non_qualified":null,"image":"1f486-1f3fe.png","sheet_x":26,"sheet_y":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F486-1F3FF","non_qualified":null,"image":"1f486-1f3ff.png","sheet_x":26,"sheet_y":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F486-200D-2640-FE0F"},{"name":"WOMAN GETTING HAIRCUT","unified":"1F487-200D-2640-FE0F","non_qualified":"1F487-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f487-200d-2640-fe0f.png","sheet_x":26,"sheet_y":48,"short_name":"woman-getting-haircut","short_names":["woman-getting-haircut"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":407,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F487-1F3FB-200D-2640-FE0F","non_qualified":"1F487-1F3FB-200D-2640","image":"1f487-1f3fb-200d-2640-fe0f.png","sheet_x":26,"sheet_y":49,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F487-1F3FC-200D-2640-FE0F","non_qualified":"1F487-1F3FC-200D-2640","image":"1f487-1f3fc-200d-2640-fe0f.png","sheet_x":26,"sheet_y":50,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F487-1F3FD-200D-2640-FE0F","non_qualified":"1F487-1F3FD-200D-2640","image":"1f487-1f3fd-200d-2640-fe0f.png","sheet_x":26,"sheet_y":51,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F487-1F3FE-200D-2640-FE0F","non_qualified":"1F487-1F3FE-200D-2640","image":"1f487-1f3fe-200d-2640-fe0f.png","sheet_x":26,"sheet_y":52,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F487-1F3FF-200D-2640-FE0F","non_qualified":"1F487-1F3FF-200D-2640","image":"1f487-1f3ff-200d-2640-fe0f.png","sheet_x":26,"sheet_y":53,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F487"},{"name":"MAN GETTING HAIRCUT","unified":"1F487-200D-2642-FE0F","non_qualified":"1F487-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f487-200d-2642-fe0f.png","sheet_x":26,"sheet_y":54,"short_name":"man-getting-haircut","short_names":["man-getting-haircut"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":406,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F487-1F3FB-200D-2642-FE0F","non_qualified":"1F487-1F3FB-200D-2642","image":"1f487-1f3fb-200d-2642-fe0f.png","sheet_x":26,"sheet_y":55,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F487-1F3FC-200D-2642-FE0F","non_qualified":"1F487-1F3FC-200D-2642","image":"1f487-1f3fc-200d-2642-fe0f.png","sheet_x":26,"sheet_y":56,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F487-1F3FD-200D-2642-FE0F","non_qualified":"1F487-1F3FD-200D-2642","image":"1f487-1f3fd-200d-2642-fe0f.png","sheet_x":26,"sheet_y":57,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F487-1F3FE-200D-2642-FE0F","non_qualified":"1F487-1F3FE-200D-2642","image":"1f487-1f3fe-200d-2642-fe0f.png","sheet_x":26,"sheet_y":58,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F487-1F3FF-200D-2642-FE0F","non_qualified":"1F487-1F3FF-200D-2642","image":"1f487-1f3ff-200d-2642-fe0f.png","sheet_x":26,"sheet_y":59,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"HAIRCUT","unified":"1F487","non_qualified":null,"docomo":"E675","au":"EAA1","softbank":"E31F","google":"FE198","image":"1f487.png","sheet_x":26,"sheet_y":60,"short_name":"haircut","short_names":["haircut"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":405,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F487-1F3FB","non_qualified":null,"image":"1f487-1f3fb.png","sheet_x":26,"sheet_y":61,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F487-1F3FC","non_qualified":null,"image":"1f487-1f3fc.png","sheet_x":27,"sheet_y":0,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F487-1F3FD","non_qualified":null,"image":"1f487-1f3fd.png","sheet_x":27,"sheet_y":1,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F487-1F3FE","non_qualified":null,"image":"1f487-1f3fe.png","sheet_x":27,"sheet_y":2,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F487-1F3FF","non_qualified":null,"image":"1f487-1f3ff.png","sheet_x":27,"sheet_y":3,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F487-200D-2640-FE0F"},{"name":"BARBER POLE","unified":"1F488","non_qualified":null,"docomo":null,"au":"EAA2","softbank":"E320","google":"FE199","image":"1f488.png","sheet_x":27,"sheet_y":4,"short_name":"barber","short_names":["barber"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":911,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SYRINGE","unified":"1F489","non_qualified":null,"docomo":null,"au":"E510","softbank":"E13B","google":"FE509","image":"1f489.png","sheet_x":27,"sheet_y":5,"short_name":"syringe","short_names":["syringe"],"text":null,"texts":null,"category":"Objects","subcategory":"medical","sort_order":1371,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PILL","unified":"1F48A","non_qualified":null,"docomo":null,"au":"EA9A","softbank":"E30F","google":"FE50A","image":"1f48a.png","sheet_x":27,"sheet_y":6,"short_name":"pill","short_names":["pill"],"text":null,"texts":null,"category":"Objects","subcategory":"medical","sort_order":1373,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KISS MARK","unified":"1F48B","non_qualified":null,"docomo":"E6F9","au":"E4EB","softbank":"E003","google":"FE823","image":"1f48b.png","sheet_x":27,"sheet_y":7,"short_name":"kiss","short_names":["kiss"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":155,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOVE LETTER","unified":"1F48C","non_qualified":null,"docomo":"E717","au":"EB78","softbank":null,"google":"FE824","image":"1f48c.png","sheet_x":27,"sheet_y":8,"short_name":"love_letter","short_names":["love_letter"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":130,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RING","unified":"1F48D","non_qualified":null,"docomo":"E71B","au":"E514","softbank":"E034","google":"FE825","image":"1f48d.png","sheet_x":27,"sheet_y":9,"short_name":"ring","short_names":["ring"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1195,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GEM STONE","unified":"1F48E","non_qualified":null,"docomo":"E71B","au":"E514","softbank":"E035","google":"FE826","image":"1f48e.png","sheet_x":27,"sheet_y":10,"short_name":"gem","short_names":["gem"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1196,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KISS","unified":"1F48F","non_qualified":null,"docomo":"E6F9","au":"E5CA","softbank":"E111","google":"FE827","image":"1f48f.png","sheet_x":27,"sheet_y":11,"short_name":"couplekiss","short_names":["couplekiss"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":511,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F48F-1F3FB","non_qualified":null,"image":"1f48f-1f3fb.png","sheet_x":27,"sheet_y":12,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F48F-1F3FC","non_qualified":null,"image":"1f48f-1f3fc.png","sheet_x":27,"sheet_y":13,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F48F-1F3FD","non_qualified":null,"image":"1f48f-1f3fd.png","sheet_x":27,"sheet_y":14,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F48F-1F3FE","non_qualified":null,"image":"1f48f-1f3fe.png","sheet_x":27,"sheet_y":15,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F48F-1F3FF","non_qualified":null,"image":"1f48f-1f3ff.png","sheet_x":27,"sheet_y":16,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F9D1-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FC","non_qualified":"1F9D1-1F3FB-200D-2764-200D-1F48B-200D-1F9D1-1F3FC","image":"1f9d1-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fc.png","sheet_x":27,"sheet_y":17,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F9D1-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FD","non_qualified":"1F9D1-1F3FB-200D-2764-200D-1F48B-200D-1F9D1-1F3FD","image":"1f9d1-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fd.png","sheet_x":27,"sheet_y":18,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F9D1-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FE","non_qualified":"1F9D1-1F3FB-200D-2764-200D-1F48B-200D-1F9D1-1F3FE","image":"1f9d1-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fe.png","sheet_x":27,"sheet_y":19,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F9D1-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FF","non_qualified":"1F9D1-1F3FB-200D-2764-200D-1F48B-200D-1F9D1-1F3FF","image":"1f9d1-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3ff.png","sheet_x":27,"sheet_y":20,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F9D1-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FB","non_qualified":"1F9D1-1F3FC-200D-2764-200D-1F48B-200D-1F9D1-1F3FB","image":"1f9d1-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fb.png","sheet_x":27,"sheet_y":21,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F9D1-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FD","non_qualified":"1F9D1-1F3FC-200D-2764-200D-1F48B-200D-1F9D1-1F3FD","image":"1f9d1-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fd.png","sheet_x":27,"sheet_y":22,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F9D1-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FE","non_qualified":"1F9D1-1F3FC-200D-2764-200D-1F48B-200D-1F9D1-1F3FE","image":"1f9d1-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fe.png","sheet_x":27,"sheet_y":23,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F9D1-1F3FC-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FF","non_qualified":"1F9D1-1F3FC-200D-2764-200D-1F48B-200D-1F9D1-1F3FF","image":"1f9d1-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3ff.png","sheet_x":27,"sheet_y":24,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F9D1-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FB","non_qualified":"1F9D1-1F3FD-200D-2764-200D-1F48B-200D-1F9D1-1F3FB","image":"1f9d1-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fb.png","sheet_x":27,"sheet_y":25,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F9D1-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FC","non_qualified":"1F9D1-1F3FD-200D-2764-200D-1F48B-200D-1F9D1-1F3FC","image":"1f9d1-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fc.png","sheet_x":27,"sheet_y":26,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F9D1-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FE","non_qualified":"1F9D1-1F3FD-200D-2764-200D-1F48B-200D-1F9D1-1F3FE","image":"1f9d1-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fe.png","sheet_x":27,"sheet_y":27,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F9D1-1F3FD-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FF","non_qualified":"1F9D1-1F3FD-200D-2764-200D-1F48B-200D-1F9D1-1F3FF","image":"1f9d1-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3ff.png","sheet_x":27,"sheet_y":28,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F9D1-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FB","non_qualified":"1F9D1-1F3FE-200D-2764-200D-1F48B-200D-1F9D1-1F3FB","image":"1f9d1-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fb.png","sheet_x":27,"sheet_y":29,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F9D1-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FC","non_qualified":"1F9D1-1F3FE-200D-2764-200D-1F48B-200D-1F9D1-1F3FC","image":"1f9d1-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fc.png","sheet_x":27,"sheet_y":30,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F9D1-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FD","non_qualified":"1F9D1-1F3FE-200D-2764-200D-1F48B-200D-1F9D1-1F3FD","image":"1f9d1-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fd.png","sheet_x":27,"sheet_y":31,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F9D1-1F3FE-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FF","non_qualified":"1F9D1-1F3FE-200D-2764-200D-1F48B-200D-1F9D1-1F3FF","image":"1f9d1-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3ff.png","sheet_x":27,"sheet_y":32,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F9D1-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FB","non_qualified":"1F9D1-1F3FF-200D-2764-200D-1F48B-200D-1F9D1-1F3FB","image":"1f9d1-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fb.png","sheet_x":27,"sheet_y":33,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F9D1-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FC","non_qualified":"1F9D1-1F3FF-200D-2764-200D-1F48B-200D-1F9D1-1F3FC","image":"1f9d1-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fc.png","sheet_x":27,"sheet_y":34,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F9D1-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FD","non_qualified":"1F9D1-1F3FF-200D-2764-200D-1F48B-200D-1F9D1-1F3FD","image":"1f9d1-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fd.png","sheet_x":27,"sheet_y":35,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F9D1-1F3FF-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FE","non_qualified":"1F9D1-1F3FF-200D-2764-200D-1F48B-200D-1F9D1-1F3FE","image":"1f9d1-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f9d1-1f3fe.png","sheet_x":27,"sheet_y":36,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"BOUQUET","unified":"1F490","non_qualified":null,"docomo":null,"au":"EA95","softbank":"E306","google":"FE828","image":"1f490.png","sheet_x":27,"sheet_y":37,"short_name":"bouquet","short_names":["bouquet"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":684,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COUPLE WITH HEART","unified":"1F491","non_qualified":null,"docomo":"E6ED","au":"EADA","softbank":"E425","google":"FE829","image":"1f491.png","sheet_x":27,"sheet_y":38,"short_name":"couple_with_heart","short_names":["couple_with_heart"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":515,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F491-1F3FB","non_qualified":null,"image":"1f491-1f3fb.png","sheet_x":27,"sheet_y":39,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F491-1F3FC","non_qualified":null,"image":"1f491-1f3fc.png","sheet_x":27,"sheet_y":40,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F491-1F3FD","non_qualified":null,"image":"1f491-1f3fd.png","sheet_x":27,"sheet_y":41,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F491-1F3FE","non_qualified":null,"image":"1f491-1f3fe.png","sheet_x":27,"sheet_y":42,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F491-1F3FF","non_qualified":null,"image":"1f491-1f3ff.png","sheet_x":27,"sheet_y":43,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F9D1-1F3FB-200D-2764-FE0F-200D-1F9D1-1F3FC","non_qualified":"1F9D1-1F3FB-200D-2764-200D-1F9D1-1F3FC","image":"1f9d1-1f3fb-200d-2764-fe0f-200d-1f9d1-1f3fc.png","sheet_x":27,"sheet_y":44,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F9D1-1F3FB-200D-2764-FE0F-200D-1F9D1-1F3FD","non_qualified":"1F9D1-1F3FB-200D-2764-200D-1F9D1-1F3FD","image":"1f9d1-1f3fb-200d-2764-fe0f-200d-1f9d1-1f3fd.png","sheet_x":27,"sheet_y":45,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F9D1-1F3FB-200D-2764-FE0F-200D-1F9D1-1F3FE","non_qualified":"1F9D1-1F3FB-200D-2764-200D-1F9D1-1F3FE","image":"1f9d1-1f3fb-200d-2764-fe0f-200d-1f9d1-1f3fe.png","sheet_x":27,"sheet_y":46,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F9D1-1F3FB-200D-2764-FE0F-200D-1F9D1-1F3FF","non_qualified":"1F9D1-1F3FB-200D-2764-200D-1F9D1-1F3FF","image":"1f9d1-1f3fb-200d-2764-fe0f-200d-1f9d1-1f3ff.png","sheet_x":27,"sheet_y":47,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F9D1-1F3FC-200D-2764-FE0F-200D-1F9D1-1F3FB","non_qualified":"1F9D1-1F3FC-200D-2764-200D-1F9D1-1F3FB","image":"1f9d1-1f3fc-200d-2764-fe0f-200d-1f9d1-1f3fb.png","sheet_x":27,"sheet_y":48,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F9D1-1F3FC-200D-2764-FE0F-200D-1F9D1-1F3FD","non_qualified":"1F9D1-1F3FC-200D-2764-200D-1F9D1-1F3FD","image":"1f9d1-1f3fc-200d-2764-fe0f-200d-1f9d1-1f3fd.png","sheet_x":27,"sheet_y":49,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F9D1-1F3FC-200D-2764-FE0F-200D-1F9D1-1F3FE","non_qualified":"1F9D1-1F3FC-200D-2764-200D-1F9D1-1F3FE","image":"1f9d1-1f3fc-200d-2764-fe0f-200d-1f9d1-1f3fe.png","sheet_x":27,"sheet_y":50,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F9D1-1F3FC-200D-2764-FE0F-200D-1F9D1-1F3FF","non_qualified":"1F9D1-1F3FC-200D-2764-200D-1F9D1-1F3FF","image":"1f9d1-1f3fc-200d-2764-fe0f-200d-1f9d1-1f3ff.png","sheet_x":27,"sheet_y":51,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F9D1-1F3FD-200D-2764-FE0F-200D-1F9D1-1F3FB","non_qualified":"1F9D1-1F3FD-200D-2764-200D-1F9D1-1F3FB","image":"1f9d1-1f3fd-200d-2764-fe0f-200d-1f9d1-1f3fb.png","sheet_x":27,"sheet_y":52,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F9D1-1F3FD-200D-2764-FE0F-200D-1F9D1-1F3FC","non_qualified":"1F9D1-1F3FD-200D-2764-200D-1F9D1-1F3FC","image":"1f9d1-1f3fd-200d-2764-fe0f-200d-1f9d1-1f3fc.png","sheet_x":27,"sheet_y":53,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F9D1-1F3FD-200D-2764-FE0F-200D-1F9D1-1F3FE","non_qualified":"1F9D1-1F3FD-200D-2764-200D-1F9D1-1F3FE","image":"1f9d1-1f3fd-200d-2764-fe0f-200d-1f9d1-1f3fe.png","sheet_x":27,"sheet_y":54,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F9D1-1F3FD-200D-2764-FE0F-200D-1F9D1-1F3FF","non_qualified":"1F9D1-1F3FD-200D-2764-200D-1F9D1-1F3FF","image":"1f9d1-1f3fd-200d-2764-fe0f-200d-1f9d1-1f3ff.png","sheet_x":27,"sheet_y":55,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F9D1-1F3FE-200D-2764-FE0F-200D-1F9D1-1F3FB","non_qualified":"1F9D1-1F3FE-200D-2764-200D-1F9D1-1F3FB","image":"1f9d1-1f3fe-200d-2764-fe0f-200d-1f9d1-1f3fb.png","sheet_x":27,"sheet_y":56,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F9D1-1F3FE-200D-2764-FE0F-200D-1F9D1-1F3FC","non_qualified":"1F9D1-1F3FE-200D-2764-200D-1F9D1-1F3FC","image":"1f9d1-1f3fe-200d-2764-fe0f-200d-1f9d1-1f3fc.png","sheet_x":27,"sheet_y":57,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F9D1-1F3FE-200D-2764-FE0F-200D-1F9D1-1F3FD","non_qualified":"1F9D1-1F3FE-200D-2764-200D-1F9D1-1F3FD","image":"1f9d1-1f3fe-200d-2764-fe0f-200d-1f9d1-1f3fd.png","sheet_x":27,"sheet_y":58,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F9D1-1F3FE-200D-2764-FE0F-200D-1F9D1-1F3FF","non_qualified":"1F9D1-1F3FE-200D-2764-200D-1F9D1-1F3FF","image":"1f9d1-1f3fe-200d-2764-fe0f-200d-1f9d1-1f3ff.png","sheet_x":27,"sheet_y":59,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F9D1-1F3FF-200D-2764-FE0F-200D-1F9D1-1F3FB","non_qualified":"1F9D1-1F3FF-200D-2764-200D-1F9D1-1F3FB","image":"1f9d1-1f3ff-200d-2764-fe0f-200d-1f9d1-1f3fb.png","sheet_x":27,"sheet_y":60,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F9D1-1F3FF-200D-2764-FE0F-200D-1F9D1-1F3FC","non_qualified":"1F9D1-1F3FF-200D-2764-200D-1F9D1-1F3FC","image":"1f9d1-1f3ff-200d-2764-fe0f-200d-1f9d1-1f3fc.png","sheet_x":27,"sheet_y":61,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F9D1-1F3FF-200D-2764-FE0F-200D-1F9D1-1F3FD","non_qualified":"1F9D1-1F3FF-200D-2764-200D-1F9D1-1F3FD","image":"1f9d1-1f3ff-200d-2764-fe0f-200d-1f9d1-1f3fd.png","sheet_x":28,"sheet_y":0,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F9D1-1F3FF-200D-2764-FE0F-200D-1F9D1-1F3FE","non_qualified":"1F9D1-1F3FF-200D-2764-200D-1F9D1-1F3FE","image":"1f9d1-1f3ff-200d-2764-fe0f-200d-1f9d1-1f3fe.png","sheet_x":28,"sheet_y":1,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WEDDING","unified":"1F492","non_qualified":null,"docomo":null,"au":"E5BB","softbank":"E43D","google":"FE82A","image":"1f492.png","sheet_x":28,"sheet_y":2,"short_name":"wedding","short_names":["wedding"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":887,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BEATING HEART","unified":"1F493","non_qualified":null,"docomo":"E6ED","au":"EB75","softbank":"E327","google":"FEB0D","image":"1f493.png","sheet_x":28,"sheet_y":3,"short_name":"heartbeat","short_names":["heartbeat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":135,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BROKEN HEART","unified":"1F494","non_qualified":null,"docomo":"E6EE","au":"E477","softbank":"E023","google":"FEB0E","image":"1f494.png","sheet_x":28,"sheet_y":4,"short_name":"broken_heart","short_names":["broken_heart"],"text":"<\/3","texts":["<\/3"],"category":"Smileys & Emotion","subcategory":"heart","sort_order":140,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TWO HEARTS","unified":"1F495","non_qualified":null,"docomo":"E6EF","au":"E478","softbank":null,"google":"FEB0F","image":"1f495.png","sheet_x":28,"sheet_y":5,"short_name":"two_hearts","short_names":["two_hearts"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":137,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPARKLING HEART","unified":"1F496","non_qualified":null,"docomo":"E6EC","au":"EAA6","softbank":null,"google":"FEB10","image":"1f496.png","sheet_x":28,"sheet_y":6,"short_name":"sparkling_heart","short_names":["sparkling_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":133,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GROWING HEART","unified":"1F497","non_qualified":null,"docomo":"E6ED","au":"EB75","softbank":"E328","google":"FEB11","image":"1f497.png","sheet_x":28,"sheet_y":7,"short_name":"heartpulse","short_names":["heartpulse"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":134,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEART WITH ARROW","unified":"1F498","non_qualified":null,"docomo":"E6EC","au":"E4EA","softbank":"E329","google":"FEB12","image":"1f498.png","sheet_x":28,"sheet_y":8,"short_name":"cupid","short_names":["cupid"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":131,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLUE HEART","unified":"1F499","non_qualified":null,"docomo":"E6EC","au":"EAA7","softbank":"E32A","google":"FEB13","image":"1f499.png","sheet_x":28,"sheet_y":9,"short_name":"blue_heart","short_names":["blue_heart"],"text":"<3","texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":148,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GREEN HEART","unified":"1F49A","non_qualified":null,"docomo":"E6EC","au":"EAA8","softbank":"E32B","google":"FEB14","image":"1f49a.png","sheet_x":28,"sheet_y":10,"short_name":"green_heart","short_names":["green_heart"],"text":"<3","texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":147,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"YELLOW HEART","unified":"1F49B","non_qualified":null,"docomo":"E6EC","au":"EAA9","softbank":"E32C","google":"FEB15","image":"1f49b.png","sheet_x":28,"sheet_y":11,"short_name":"yellow_heart","short_names":["yellow_heart"],"text":"<3","texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":146,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PURPLE HEART","unified":"1F49C","non_qualified":null,"docomo":"E6EC","au":"EAAA","softbank":"E32D","google":"FEB16","image":"1f49c.png","sheet_x":28,"sheet_y":12,"short_name":"purple_heart","short_names":["purple_heart"],"text":"<3","texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":150,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEART WITH RIBBON","unified":"1F49D","non_qualified":null,"docomo":"E6EC","au":"EB54","softbank":"E437","google":"FEB17","image":"1f49d.png","sheet_x":28,"sheet_y":13,"short_name":"gift_heart","short_names":["gift_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":132,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"REVOLVING HEARTS","unified":"1F49E","non_qualified":null,"docomo":"E6ED","au":"E5AF","softbank":null,"google":"FEB18","image":"1f49e.png","sheet_x":28,"sheet_y":14,"short_name":"revolving_hearts","short_names":["revolving_hearts"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":136,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEART DECORATION","unified":"1F49F","non_qualified":null,"docomo":"E6F8","au":"E595","softbank":"E204","google":"FEB19","image":"1f49f.png","sheet_x":28,"sheet_y":15,"short_name":"heart_decoration","short_names":["heart_decoration"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":138,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DIAMOND SHAPE WITH A DOT INSIDE","unified":"1F4A0","non_qualified":null,"docomo":"E6F8","au":null,"softbank":null,"google":"FEB55","image":"1f4a0.png","sheet_x":28,"sheet_y":16,"short_name":"diamond_shape_with_a_dot_inside","short_names":["diamond_shape_with_a_dot_inside"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1631,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ELECTRIC LIGHT BULB","unified":"1F4A1","non_qualified":null,"docomo":"E6FB","au":"E476","softbank":"E10F","google":"FEB56","image":"1f4a1.png","sheet_x":28,"sheet_y":17,"short_name":"bulb","short_names":["bulb"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1258,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ANGER SYMBOL","unified":"1F4A2","non_qualified":null,"docomo":"E6FC","au":"E4E5","softbank":"E334","google":"FEB57","image":"1f4a2.png","sheet_x":28,"sheet_y":18,"short_name":"anger","short_names":["anger"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":157,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOMB","unified":"1F4A3","non_qualified":null,"docomo":"E6FE","au":"E47A","softbank":"E311","google":"FEB58","image":"1f4a3.png","sheet_x":28,"sheet_y":19,"short_name":"bomb","short_names":["bomb"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1345,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SLEEPING SYMBOL","unified":"1F4A4","non_qualified":null,"docomo":"E701","au":"E475","softbank":"E13C","google":"FEB59","image":"1f4a4.png","sheet_x":28,"sheet_y":20,"short_name":"zzz","short_names":["zzz"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":168,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COLLISION SYMBOL","unified":"1F4A5","non_qualified":null,"docomo":"E705","au":"E5B0","softbank":null,"google":"FEB5A","image":"1f4a5.png","sheet_x":28,"sheet_y":21,"short_name":"boom","short_names":["boom","collision"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":158,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPLASHING SWEAT SYMBOL","unified":"1F4A6","non_qualified":null,"docomo":"E706","au":"E5B1","softbank":"E331","google":"FEB5B","image":"1f4a6.png","sheet_x":28,"sheet_y":22,"short_name":"sweat_drops","short_names":["sweat_drops"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":160,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DROPLET","unified":"1F4A7","non_qualified":null,"docomo":"E707","au":"E4E6","softbank":null,"google":"FEB5C","image":"1f4a7.png","sheet_x":28,"sheet_y":23,"short_name":"droplet","short_names":["droplet"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1063,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DASH SYMBOL","unified":"1F4A8","non_qualified":null,"docomo":"E708","au":"E4F4","softbank":"E330","google":"FEB5D","image":"1f4a8.png","sheet_x":28,"sheet_y":24,"short_name":"dash","short_names":["dash"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":161,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PILE OF POO","unified":"1F4A9","non_qualified":null,"docomo":null,"au":"E4F5","softbank":"E05A","google":"FE4F4","image":"1f4a9.png","sheet_x":28,"sheet_y":25,"short_name":"hankey","short_names":["hankey","poop","shit"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-costume","sort_order":110,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLEXED BICEPS","unified":"1F4AA","non_qualified":null,"docomo":null,"au":"E4E9","softbank":"E14C","google":"FEB5E","image":"1f4aa.png","sheet_x":28,"sheet_y":26,"short_name":"muscle","short_names":["muscle"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":212,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F4AA-1F3FB","non_qualified":null,"image":"1f4aa-1f3fb.png","sheet_x":28,"sheet_y":27,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F4AA-1F3FC","non_qualified":null,"image":"1f4aa-1f3fc.png","sheet_x":28,"sheet_y":28,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F4AA-1F3FD","non_qualified":null,"image":"1f4aa-1f3fd.png","sheet_x":28,"sheet_y":29,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F4AA-1F3FE","non_qualified":null,"image":"1f4aa-1f3fe.png","sheet_x":28,"sheet_y":30,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F4AA-1F3FF","non_qualified":null,"image":"1f4aa-1f3ff.png","sheet_x":28,"sheet_y":31,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"DIZZY SYMBOL","unified":"1F4AB","non_qualified":null,"docomo":null,"au":"EB5C","softbank":null,"google":"FEB5F","image":"1f4ab.png","sheet_x":28,"sheet_y":32,"short_name":"dizzy","short_names":["dizzy"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":159,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPEECH BALLOON","unified":"1F4AC","non_qualified":null,"docomo":null,"au":"E4FD","softbank":null,"google":"FE532","image":"1f4ac.png","sheet_x":28,"sheet_y":33,"short_name":"speech_balloon","short_names":["speech_balloon"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":163,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"THOUGHT BALLOON","unified":"1F4AD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4ad.png","sheet_x":28,"sheet_y":34,"short_name":"thought_balloon","short_names":["thought_balloon"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":167,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE FLOWER","unified":"1F4AE","non_qualified":null,"docomo":null,"au":"E4F0","softbank":null,"google":"FEB7A","image":"1f4ae.png","sheet_x":28,"sheet_y":35,"short_name":"white_flower","short_names":["white_flower"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":686,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HUNDRED POINTS SYMBOL","unified":"1F4AF","non_qualified":null,"docomo":null,"au":"E4F2","softbank":null,"google":"FEB7B","image":"1f4af.png","sheet_x":28,"sheet_y":36,"short_name":"100","short_names":["100"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":156,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MONEY BAG","unified":"1F4B0","non_qualified":null,"docomo":"E715","au":"E4C7","softbank":"E12F","google":"FE4DD","image":"1f4b0.png","sheet_x":28,"sheet_y":37,"short_name":"moneybag","short_names":["moneybag"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1279,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CURRENCY EXCHANGE","unified":"1F4B1","non_qualified":null,"docomo":null,"au":null,"softbank":"E149","google":"FE4DE","image":"1f4b1.png","sheet_x":28,"sheet_y":38,"short_name":"currency_exchange","short_names":["currency_exchange"],"text":null,"texts":null,"category":"Symbols","subcategory":"currency","sort_order":1526,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY DOLLAR SIGN","unified":"1F4B2","non_qualified":null,"docomo":"E715","au":"E579","softbank":null,"google":"FE4E0","image":"1f4b2.png","sheet_x":28,"sheet_y":39,"short_name":"heavy_dollar_sign","short_names":["heavy_dollar_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"currency","sort_order":1527,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CREDIT CARD","unified":"1F4B3","non_qualified":null,"docomo":null,"au":"E57C","softbank":null,"google":"FE4E1","image":"1f4b3.png","sheet_x":28,"sheet_y":40,"short_name":"credit_card","short_names":["credit_card"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1286,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BANKNOTE WITH YEN SIGN","unified":"1F4B4","non_qualified":null,"docomo":"E6D6","au":"E57D","softbank":null,"google":"FE4E2","image":"1f4b4.png","sheet_x":28,"sheet_y":41,"short_name":"yen","short_names":["yen"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1281,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BANKNOTE WITH DOLLAR SIGN","unified":"1F4B5","non_qualified":null,"docomo":"E715","au":"E585","softbank":null,"google":"FE4E3","image":"1f4b5.png","sheet_x":28,"sheet_y":42,"short_name":"dollar","short_names":["dollar"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1282,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BANKNOTE WITH EURO SIGN","unified":"1F4B6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4b6.png","sheet_x":28,"sheet_y":43,"short_name":"euro","short_names":["euro"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1283,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BANKNOTE WITH POUND SIGN","unified":"1F4B7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4b7.png","sheet_x":28,"sheet_y":44,"short_name":"pound","short_names":["pound"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1284,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MONEY WITH WINGS","unified":"1F4B8","non_qualified":null,"docomo":null,"au":"EB5B","softbank":null,"google":"FE4E4","image":"1f4b8.png","sheet_x":28,"sheet_y":45,"short_name":"money_with_wings","short_names":["money_with_wings"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1285,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHART WITH UPWARDS TREND AND YEN SIGN","unified":"1F4B9","non_qualified":null,"docomo":null,"au":"E5DC","softbank":"E14A","google":"FE4DF","image":"1f4b9.png","sheet_x":28,"sheet_y":46,"short_name":"chart","short_names":["chart"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1288,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SEAT","unified":"1F4BA","non_qualified":null,"docomo":"E6B2","au":null,"softbank":"E11F","google":"FE537","image":"1f4ba.png","sheet_x":28,"sheet_y":47,"short_name":"seat","short_names":["seat"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":977,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PERSONAL COMPUTER","unified":"1F4BB","non_qualified":null,"docomo":"E716","au":"E5B8","softbank":"E00C","google":"FE538","image":"1f4bb.png","sheet_x":28,"sheet_y":48,"short_name":"computer","short_names":["computer"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1235,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BRIEFCASE","unified":"1F4BC","non_qualified":null,"docomo":"E682","au":"E5CE","softbank":"E11E","google":"FE53B","image":"1f4bc.png","sheet_x":28,"sheet_y":49,"short_name":"briefcase","short_names":["briefcase"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1309,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MINIDISC","unified":"1F4BD","non_qualified":null,"docomo":null,"au":"E582","softbank":"E316","google":"FE53C","image":"1f4bd.png","sheet_x":28,"sheet_y":50,"short_name":"minidisc","short_names":["minidisc"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1241,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLOPPY DISK","unified":"1F4BE","non_qualified":null,"docomo":null,"au":"E562","softbank":null,"google":"FE53D","image":"1f4be.png","sheet_x":28,"sheet_y":51,"short_name":"floppy_disk","short_names":["floppy_disk"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1242,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OPTICAL DISC","unified":"1F4BF","non_qualified":null,"docomo":"E68C","au":"E50C","softbank":"E126","google":"FE81D","image":"1f4bf.png","sheet_x":28,"sheet_y":52,"short_name":"cd","short_names":["cd"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1243,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DVD","unified":"1F4C0","non_qualified":null,"docomo":"E68C","au":"E50C","softbank":"E127","google":"FE81E","image":"1f4c0.png","sheet_x":28,"sheet_y":53,"short_name":"dvd","short_names":["dvd"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1244,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FILE FOLDER","unified":"1F4C1","non_qualified":null,"docomo":null,"au":"E58F","softbank":null,"google":"FE543","image":"1f4c1.png","sheet_x":28,"sheet_y":54,"short_name":"file_folder","short_names":["file_folder"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1310,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OPEN FILE FOLDER","unified":"1F4C2","non_qualified":null,"docomo":null,"au":"E590","softbank":null,"google":"FE544","image":"1f4c2.png","sheet_x":28,"sheet_y":55,"short_name":"open_file_folder","short_names":["open_file_folder"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1311,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PAGE WITH CURL","unified":"1F4C3","non_qualified":null,"docomo":"E689","au":"E561","softbank":null,"google":"FE540","image":"1f4c3.png","sheet_x":28,"sheet_y":56,"short_name":"page_with_curl","short_names":["page_with_curl"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1271,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PAGE FACING UP","unified":"1F4C4","non_qualified":null,"docomo":"E689","au":"E569","softbank":null,"google":"FE541","image":"1f4c4.png","sheet_x":28,"sheet_y":57,"short_name":"page_facing_up","short_names":["page_facing_up"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1273,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CALENDAR","unified":"1F4C5","non_qualified":null,"docomo":null,"au":"E563","softbank":null,"google":"FE542","image":"1f4c5.png","sheet_x":28,"sheet_y":58,"short_name":"date","short_names":["date"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1313,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TEAR-OFF CALENDAR","unified":"1F4C6","non_qualified":null,"docomo":null,"au":"E56A","softbank":null,"google":"FE549","image":"1f4c6.png","sheet_x":28,"sheet_y":59,"short_name":"calendar","short_names":["calendar"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1314,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CARD INDEX","unified":"1F4C7","non_qualified":null,"docomo":"E683","au":"E56C","softbank":null,"google":"FE54D","image":"1f4c7.png","sheet_x":28,"sheet_y":60,"short_name":"card_index","short_names":["card_index"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1317,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHART WITH UPWARDS TREND","unified":"1F4C8","non_qualified":null,"docomo":null,"au":"E575","softbank":null,"google":"FE54B","image":"1f4c8.png","sheet_x":28,"sheet_y":61,"short_name":"chart_with_upwards_trend","short_names":["chart_with_upwards_trend"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1318,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHART WITH DOWNWARDS TREND","unified":"1F4C9","non_qualified":null,"docomo":null,"au":"E576","softbank":null,"google":"FE54C","image":"1f4c9.png","sheet_x":29,"sheet_y":0,"short_name":"chart_with_downwards_trend","short_names":["chart_with_downwards_trend"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1319,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BAR CHART","unified":"1F4CA","non_qualified":null,"docomo":null,"au":"E574","softbank":null,"google":"FE54A","image":"1f4ca.png","sheet_x":29,"sheet_y":1,"short_name":"bar_chart","short_names":["bar_chart"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1320,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLIPBOARD","unified":"1F4CB","non_qualified":null,"docomo":"E689","au":"E564","softbank":null,"google":"FE548","image":"1f4cb.png","sheet_x":29,"sheet_y":2,"short_name":"clipboard","short_names":["clipboard"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1321,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PUSHPIN","unified":"1F4CC","non_qualified":null,"docomo":null,"au":"E56D","softbank":null,"google":"FE54E","image":"1f4cc.png","sheet_x":29,"sheet_y":3,"short_name":"pushpin","short_names":["pushpin"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1322,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROUND PUSHPIN","unified":"1F4CD","non_qualified":null,"docomo":null,"au":"E560","softbank":null,"google":"FE53F","image":"1f4cd.png","sheet_x":29,"sheet_y":4,"short_name":"round_pushpin","short_names":["round_pushpin"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1323,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PAPERCLIP","unified":"1F4CE","non_qualified":null,"docomo":"E730","au":"E4A0","softbank":null,"google":"FE53A","image":"1f4ce.png","sheet_x":29,"sheet_y":5,"short_name":"paperclip","short_names":["paperclip"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1324,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STRAIGHT RULER","unified":"1F4CF","non_qualified":null,"docomo":null,"au":"E570","softbank":null,"google":"FE550","image":"1f4cf.png","sheet_x":29,"sheet_y":6,"short_name":"straight_ruler","short_names":["straight_ruler"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1326,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRIANGULAR RULER","unified":"1F4D0","non_qualified":null,"docomo":null,"au":"E4A2","softbank":null,"google":"FE551","image":"1f4d0.png","sheet_x":29,"sheet_y":7,"short_name":"triangular_ruler","short_names":["triangular_ruler"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1327,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOOKMARK TABS","unified":"1F4D1","non_qualified":null,"docomo":"E689","au":"EB0B","softbank":null,"google":"FE552","image":"1f4d1.png","sheet_x":29,"sheet_y":8,"short_name":"bookmark_tabs","short_names":["bookmark_tabs"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1276,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEDGER","unified":"1F4D2","non_qualified":null,"docomo":"E683","au":"E56E","softbank":null,"google":"FE54F","image":"1f4d2.png","sheet_x":29,"sheet_y":9,"short_name":"ledger","short_names":["ledger"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1270,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NOTEBOOK","unified":"1F4D3","non_qualified":null,"docomo":"E683","au":"E56B","softbank":null,"google":"FE545","image":"1f4d3.png","sheet_x":29,"sheet_y":10,"short_name":"notebook","short_names":["notebook"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1269,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NOTEBOOK WITH DECORATIVE COVER","unified":"1F4D4","non_qualified":null,"docomo":"E683","au":"E49D","softbank":null,"google":"FE547","image":"1f4d4.png","sheet_x":29,"sheet_y":11,"short_name":"notebook_with_decorative_cover","short_names":["notebook_with_decorative_cover"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1262,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOSED BOOK","unified":"1F4D5","non_qualified":null,"docomo":"E683","au":"E568","softbank":null,"google":"FE502","image":"1f4d5.png","sheet_x":29,"sheet_y":12,"short_name":"closed_book","short_names":["closed_book"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1263,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OPEN BOOK","unified":"1F4D6","non_qualified":null,"docomo":"E683","au":"E49F","softbank":"E148","google":"FE546","image":"1f4d6.png","sheet_x":29,"sheet_y":13,"short_name":"book","short_names":["book","open_book"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1264,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GREEN BOOK","unified":"1F4D7","non_qualified":null,"docomo":"E683","au":"E565","softbank":null,"google":"FE4FF","image":"1f4d7.png","sheet_x":29,"sheet_y":14,"short_name":"green_book","short_names":["green_book"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1265,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLUE BOOK","unified":"1F4D8","non_qualified":null,"docomo":"E683","au":"E566","softbank":null,"google":"FE500","image":"1f4d8.png","sheet_x":29,"sheet_y":15,"short_name":"blue_book","short_names":["blue_book"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1266,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ORANGE BOOK","unified":"1F4D9","non_qualified":null,"docomo":"E683","au":"E567","softbank":null,"google":"FE501","image":"1f4d9.png","sheet_x":29,"sheet_y":16,"short_name":"orange_book","short_names":["orange_book"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1267,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOOKS","unified":"1F4DA","non_qualified":null,"docomo":"E683","au":"E56F","softbank":null,"google":"FE503","image":"1f4da.png","sheet_x":29,"sheet_y":17,"short_name":"books","short_names":["books"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1268,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NAME BADGE","unified":"1F4DB","non_qualified":null,"docomo":null,"au":"E51D","softbank":null,"google":"FE504","image":"1f4db.png","sheet_x":29,"sheet_y":18,"short_name":"name_badge","short_names":["name_badge"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1532,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SCROLL","unified":"1F4DC","non_qualified":null,"docomo":"E70A","au":"E55F","softbank":null,"google":"FE4FD","image":"1f4dc.png","sheet_x":29,"sheet_y":19,"short_name":"scroll","short_names":["scroll"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1272,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MEMO","unified":"1F4DD","non_qualified":null,"docomo":"E689","au":"EA92","softbank":"E301","google":"FE527","image":"1f4dd.png","sheet_x":29,"sheet_y":20,"short_name":"memo","short_names":["memo","pencil"],"text":null,"texts":null,"category":"Objects","subcategory":"writing","sort_order":1308,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TELEPHONE RECEIVER","unified":"1F4DE","non_qualified":null,"docomo":"E687","au":"E51E","softbank":null,"google":"FE524","image":"1f4de.png","sheet_x":29,"sheet_y":21,"short_name":"telephone_receiver","short_names":["telephone_receiver"],"text":null,"texts":null,"category":"Objects","subcategory":"phone","sort_order":1229,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PAGER","unified":"1F4DF","non_qualified":null,"docomo":"E65A","au":"E59B","softbank":null,"google":"FE522","image":"1f4df.png","sheet_x":29,"sheet_y":22,"short_name":"pager","short_names":["pager"],"text":null,"texts":null,"category":"Objects","subcategory":"phone","sort_order":1230,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FAX MACHINE","unified":"1F4E0","non_qualified":null,"docomo":"E6D0","au":"E520","softbank":"E00B","google":"FE528","image":"1f4e0.png","sheet_x":29,"sheet_y":23,"short_name":"fax","short_names":["fax"],"text":null,"texts":null,"category":"Objects","subcategory":"phone","sort_order":1231,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SATELLITE ANTENNA","unified":"1F4E1","non_qualified":null,"docomo":null,"au":"E4A8","softbank":"E14B","google":"FE531","image":"1f4e1.png","sheet_x":29,"sheet_y":24,"short_name":"satellite_antenna","short_names":["satellite_antenna"],"text":null,"texts":null,"category":"Objects","subcategory":"science","sort_order":1370,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PUBLIC ADDRESS LOUDSPEAKER","unified":"1F4E2","non_qualified":null,"docomo":null,"au":"E511","softbank":"E142","google":"FE52F","image":"1f4e2.png","sheet_x":29,"sheet_y":25,"short_name":"loudspeaker","short_names":["loudspeaker"],"text":null,"texts":null,"category":"Objects","subcategory":"sound","sort_order":1201,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHEERING MEGAPHONE","unified":"1F4E3","non_qualified":null,"docomo":null,"au":"E511","softbank":"E317","google":"FE530","image":"1f4e3.png","sheet_x":29,"sheet_y":26,"short_name":"mega","short_names":["mega"],"text":null,"texts":null,"category":"Objects","subcategory":"sound","sort_order":1202,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OUTBOX TRAY","unified":"1F4E4","non_qualified":null,"docomo":null,"au":"E592","softbank":null,"google":"FE533","image":"1f4e4.png","sheet_x":29,"sheet_y":27,"short_name":"outbox_tray","short_names":["outbox_tray"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1293,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"INBOX TRAY","unified":"1F4E5","non_qualified":null,"docomo":null,"au":"E593","softbank":null,"google":"FE534","image":"1f4e5.png","sheet_x":29,"sheet_y":28,"short_name":"inbox_tray","short_names":["inbox_tray"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1294,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PACKAGE","unified":"1F4E6","non_qualified":null,"docomo":"E685","au":"E51F","softbank":null,"google":"FE535","image":"1f4e6.png","sheet_x":29,"sheet_y":29,"short_name":"package","short_names":["package"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1295,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"E-MAIL SYMBOL","unified":"1F4E7","non_qualified":null,"docomo":"E6D3","au":"EB71","softbank":null,"google":"FEB92","image":"1f4e7.png","sheet_x":29,"sheet_y":30,"short_name":"e-mail","short_names":["e-mail"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1290,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"INCOMING ENVELOPE","unified":"1F4E8","non_qualified":null,"docomo":"E6CF","au":"E591","softbank":null,"google":"FE52A","image":"1f4e8.png","sheet_x":29,"sheet_y":31,"short_name":"incoming_envelope","short_names":["incoming_envelope"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1291,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ENVELOPE WITH DOWNWARDS ARROW ABOVE","unified":"1F4E9","non_qualified":null,"docomo":"E6CF","au":"EB62","softbank":"E103","google":"FE52B","image":"1f4e9.png","sheet_x":29,"sheet_y":32,"short_name":"envelope_with_arrow","short_names":["envelope_with_arrow"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1292,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOSED MAILBOX WITH LOWERED FLAG","unified":"1F4EA","non_qualified":null,"docomo":"E665","au":"E51B","softbank":null,"google":"FE52C","image":"1f4ea.png","sheet_x":29,"sheet_y":33,"short_name":"mailbox_closed","short_names":["mailbox_closed"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1297,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOSED MAILBOX WITH RAISED FLAG","unified":"1F4EB","non_qualified":null,"docomo":"E665","au":"EB0A","softbank":"E101","google":"FE52D","image":"1f4eb.png","sheet_x":29,"sheet_y":34,"short_name":"mailbox","short_names":["mailbox"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1296,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OPEN MAILBOX WITH RAISED FLAG","unified":"1F4EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4ec.png","sheet_x":29,"sheet_y":35,"short_name":"mailbox_with_mail","short_names":["mailbox_with_mail"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1298,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OPEN MAILBOX WITH LOWERED FLAG","unified":"1F4ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4ed.png","sheet_x":29,"sheet_y":36,"short_name":"mailbox_with_no_mail","short_names":["mailbox_with_no_mail"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1299,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POSTBOX","unified":"1F4EE","non_qualified":null,"docomo":"E665","au":"E51B","softbank":"E102","google":"FE52E","image":"1f4ee.png","sheet_x":29,"sheet_y":37,"short_name":"postbox","short_names":["postbox"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1300,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POSTAL HORN","unified":"1F4EF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4ef.png","sheet_x":29,"sheet_y":38,"short_name":"postal_horn","short_names":["postal_horn"],"text":null,"texts":null,"category":"Objects","subcategory":"sound","sort_order":1203,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEWSPAPER","unified":"1F4F0","non_qualified":null,"docomo":null,"au":"E58B","softbank":null,"google":"FE822","image":"1f4f0.png","sheet_x":29,"sheet_y":39,"short_name":"newspaper","short_names":["newspaper"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1274,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOBILE PHONE","unified":"1F4F1","non_qualified":null,"docomo":"E688","au":"E588","softbank":"E00A","google":"FE525","image":"1f4f1.png","sheet_x":29,"sheet_y":40,"short_name":"iphone","short_names":["iphone"],"text":null,"texts":null,"category":"Objects","subcategory":"phone","sort_order":1226,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT","unified":"1F4F2","non_qualified":null,"docomo":"E6CE","au":"EB08","softbank":"E104","google":"FE526","image":"1f4f2.png","sheet_x":29,"sheet_y":41,"short_name":"calling","short_names":["calling"],"text":null,"texts":null,"category":"Objects","subcategory":"phone","sort_order":1227,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"VIBRATION MODE","unified":"1F4F3","non_qualified":null,"docomo":null,"au":"EA90","softbank":"E250","google":"FE839","image":"1f4f3.png","sheet_x":29,"sheet_y":42,"short_name":"vibration_mode","short_names":["vibration_mode"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1508,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOBILE PHONE OFF","unified":"1F4F4","non_qualified":null,"docomo":null,"au":"EA91","softbank":"E251","google":"FE83A","image":"1f4f4.png","sheet_x":29,"sheet_y":43,"short_name":"mobile_phone_off","short_names":["mobile_phone_off"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1509,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NO MOBILE PHONES","unified":"1F4F5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4f5.png","sheet_x":29,"sheet_y":44,"short_name":"no_mobile_phones","short_names":["no_mobile_phones"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1434,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ANTENNA WITH BARS","unified":"1F4F6","non_qualified":null,"docomo":null,"au":"EA84","softbank":"E20B","google":"FE838","image":"1f4f6.png","sheet_x":29,"sheet_y":45,"short_name":"signal_strength","short_names":["signal_strength"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1506,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CAMERA","unified":"1F4F7","non_qualified":null,"docomo":"E681","au":"E515","softbank":"E008","google":"FE4EF","image":"1f4f7.png","sheet_x":29,"sheet_y":46,"short_name":"camera","short_names":["camera"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1251,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CAMERA WITH FLASH","unified":"1F4F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4f8.png","sheet_x":29,"sheet_y":47,"short_name":"camera_with_flash","short_names":["camera_with_flash"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1252,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"VIDEO CAMERA","unified":"1F4F9","non_qualified":null,"docomo":"E677","au":"E57E","softbank":null,"google":"FE4F9","image":"1f4f9.png","sheet_x":29,"sheet_y":48,"short_name":"video_camera","short_names":["video_camera"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1253,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TELEVISION","unified":"1F4FA","non_qualified":null,"docomo":"E68A","au":"E502","softbank":"E12A","google":"FE81C","image":"1f4fa.png","sheet_x":29,"sheet_y":49,"short_name":"tv","short_names":["tv"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1250,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RADIO","unified":"1F4FB","non_qualified":null,"docomo":null,"au":"E5B9","softbank":"E128","google":"FE81F","image":"1f4fb.png","sheet_x":29,"sheet_y":50,"short_name":"radio","short_names":["radio"],"text":null,"texts":null,"category":"Objects","subcategory":"music","sort_order":1214,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"VIDEOCASSETTE","unified":"1F4FC","non_qualified":null,"docomo":null,"au":"E580","softbank":"E129","google":"FE820","image":"1f4fc.png","sheet_x":29,"sheet_y":51,"short_name":"vhs","short_names":["vhs"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1254,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FILM PROJECTOR","unified":"1F4FD-FE0F","non_qualified":"1F4FD","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4fd-fe0f.png","sheet_x":29,"sheet_y":52,"short_name":"film_projector","short_names":["film_projector"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1248,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PRAYER BEADS","unified":"1F4FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f4ff.png","sheet_x":29,"sheet_y":53,"short_name":"prayer_beads","short_names":["prayer_beads"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1193,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TWISTED RIGHTWARDS ARROWS","unified":"1F500","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f500.png","sheet_x":29,"sheet_y":54,"short_name":"twisted_rightwards_arrows","short_names":["twisted_rightwards_arrows"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1485,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS","unified":"1F501","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f501.png","sheet_x":29,"sheet_y":55,"short_name":"repeat","short_names":["repeat"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1486,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY","unified":"1F502","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f502.png","sheet_x":29,"sheet_y":56,"short_name":"repeat_one","short_names":["repeat_one"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1487,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS","unified":"1F503","non_qualified":null,"docomo":"E735","au":"EB0D","softbank":null,"google":"FEB91","image":"1f503.png","sheet_x":29,"sheet_y":57,"short_name":"arrows_clockwise","short_names":["arrows_clockwise"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1452,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS","unified":"1F504","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f504.png","sheet_x":29,"sheet_y":58,"short_name":"arrows_counterclockwise","short_names":["arrows_counterclockwise"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1453,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOW BRIGHTNESS SYMBOL","unified":"1F505","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f505.png","sheet_x":29,"sheet_y":59,"short_name":"low_brightness","short_names":["low_brightness"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1504,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HIGH BRIGHTNESS SYMBOL","unified":"1F506","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f506.png","sheet_x":29,"sheet_y":60,"short_name":"high_brightness","short_names":["high_brightness"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1505,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPEAKER WITH CANCELLATION STROKE","unified":"1F507","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f507.png","sheet_x":29,"sheet_y":61,"short_name":"mute","short_names":["mute"],"text":null,"texts":null,"category":"Objects","subcategory":"sound","sort_order":1197,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPEAKER","unified":"1F508","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f508.png","sheet_x":30,"sheet_y":0,"short_name":"speaker","short_names":["speaker"],"text":null,"texts":null,"category":"Objects","subcategory":"sound","sort_order":1198,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPEAKER WITH ONE SOUND WAVE","unified":"1F509","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f509.png","sheet_x":30,"sheet_y":1,"short_name":"sound","short_names":["sound"],"text":null,"texts":null,"category":"Objects","subcategory":"sound","sort_order":1199,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPEAKER WITH THREE SOUND WAVES","unified":"1F50A","non_qualified":null,"docomo":null,"au":"E511","softbank":"E141","google":"FE821","image":"1f50a.png","sheet_x":30,"sheet_y":2,"short_name":"loud_sound","short_names":["loud_sound"],"text":null,"texts":null,"category":"Objects","subcategory":"sound","sort_order":1200,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BATTERY","unified":"1F50B","non_qualified":null,"docomo":null,"au":"E584","softbank":null,"google":"FE4FC","image":"1f50b.png","sheet_x":30,"sheet_y":3,"short_name":"battery","short_names":["battery"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1232,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ELECTRIC PLUG","unified":"1F50C","non_qualified":null,"docomo":null,"au":"E589","softbank":null,"google":"FE4FE","image":"1f50c.png","sheet_x":30,"sheet_y":4,"short_name":"electric_plug","short_names":["electric_plug"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1234,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEFT-POINTING MAGNIFYING GLASS","unified":"1F50D","non_qualified":null,"docomo":"E6DC","au":"E518","softbank":"E114","google":"FEB85","image":"1f50d.png","sheet_x":30,"sheet_y":5,"short_name":"mag","short_names":["mag"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1255,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RIGHT-POINTING MAGNIFYING GLASS","unified":"1F50E","non_qualified":null,"docomo":"E6DC","au":"EB05","softbank":null,"google":"FEB8D","image":"1f50e.png","sheet_x":30,"sheet_y":6,"short_name":"mag_right","short_names":["mag_right"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1256,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOCK WITH INK PEN","unified":"1F50F","non_qualified":null,"docomo":"E6D9","au":"EB0C","softbank":null,"google":"FEB90","image":"1f50f.png","sheet_x":30,"sheet_y":7,"short_name":"lock_with_ink_pen","short_names":["lock_with_ink_pen"],"text":null,"texts":null,"category":"Objects","subcategory":"lock","sort_order":1334,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOSED LOCK WITH KEY","unified":"1F510","non_qualified":null,"docomo":"E6D9","au":"EAFC","softbank":null,"google":"FEB8A","image":"1f510.png","sheet_x":30,"sheet_y":8,"short_name":"closed_lock_with_key","short_names":["closed_lock_with_key"],"text":null,"texts":null,"category":"Objects","subcategory":"lock","sort_order":1335,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KEY","unified":"1F511","non_qualified":null,"docomo":"E6D9","au":"E519","softbank":"E03F","google":"FEB82","image":"1f511.png","sheet_x":30,"sheet_y":9,"short_name":"key","short_names":["key"],"text":null,"texts":null,"category":"Objects","subcategory":"lock","sort_order":1336,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOCK","unified":"1F512","non_qualified":null,"docomo":"E6D9","au":"E51C","softbank":"E144","google":"FEB86","image":"1f512.png","sheet_x":30,"sheet_y":10,"short_name":"lock","short_names":["lock"],"text":null,"texts":null,"category":"Objects","subcategory":"lock","sort_order":1332,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OPEN LOCK","unified":"1F513","non_qualified":null,"docomo":"E6D9","au":"E51C","softbank":"E145","google":"FEB87","image":"1f513.png","sheet_x":30,"sheet_y":11,"short_name":"unlock","short_names":["unlock"],"text":null,"texts":null,"category":"Objects","subcategory":"lock","sort_order":1333,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BELL","unified":"1F514","non_qualified":null,"docomo":"E713","au":"E512","softbank":"E325","google":"FE4F2","image":"1f514.png","sheet_x":30,"sheet_y":12,"short_name":"bell","short_names":["bell"],"text":null,"texts":null,"category":"Objects","subcategory":"sound","sort_order":1204,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BELL WITH CANCELLATION STROKE","unified":"1F515","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f515.png","sheet_x":30,"sheet_y":13,"short_name":"no_bell","short_names":["no_bell"],"text":null,"texts":null,"category":"Objects","subcategory":"sound","sort_order":1205,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOOKMARK","unified":"1F516","non_qualified":null,"docomo":null,"au":"EB07","softbank":null,"google":"FEB8F","image":"1f516.png","sheet_x":30,"sheet_y":14,"short_name":"bookmark","short_names":["bookmark"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1277,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LINK SYMBOL","unified":"1F517","non_qualified":null,"docomo":null,"au":"E58A","softbank":null,"google":"FEB4B","image":"1f517.png","sheet_x":30,"sheet_y":15,"short_name":"link","short_names":["link"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1357,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RADIO BUTTON","unified":"1F518","non_qualified":null,"docomo":null,"au":"EB04","softbank":null,"google":"FEB8C","image":"1f518.png","sheet_x":30,"sheet_y":16,"short_name":"radio_button","short_names":["radio_button"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1632,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BACK WITH LEFTWARDS ARROW ABOVE","unified":"1F519","non_qualified":null,"docomo":null,"au":"EB06","softbank":null,"google":"FEB8E","image":"1f519.png","sheet_x":30,"sheet_y":17,"short_name":"back","short_names":["back"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1454,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"END WITH LEFTWARDS ARROW ABOVE","unified":"1F51A","non_qualified":null,"docomo":"E6B9","au":null,"softbank":null,"google":"FE01A","image":"1f51a.png","sheet_x":30,"sheet_y":18,"short_name":"end","short_names":["end"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1455,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE","unified":"1F51B","non_qualified":null,"docomo":"E6B8","au":null,"softbank":null,"google":"FE019","image":"1f51b.png","sheet_x":30,"sheet_y":19,"short_name":"on","short_names":["on"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1456,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SOON WITH RIGHTWARDS ARROW ABOVE","unified":"1F51C","non_qualified":null,"docomo":"E6B7","au":null,"softbank":null,"google":"FE018","image":"1f51c.png","sheet_x":30,"sheet_y":20,"short_name":"soon","short_names":["soon"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1457,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TOP WITH UPWARDS ARROW ABOVE","unified":"1F51D","non_qualified":null,"docomo":null,"au":null,"softbank":"E24C","google":"FEB42","image":"1f51d.png","sheet_x":30,"sheet_y":21,"short_name":"top","short_names":["top"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1458,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NO ONE UNDER EIGHTEEN SYMBOL","unified":"1F51E","non_qualified":null,"docomo":null,"au":"EA83","softbank":"E207","google":"FEB25","image":"1f51e.png","sheet_x":30,"sheet_y":22,"short_name":"underage","short_names":["underage"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1435,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KEYCAP TEN","unified":"1F51F","non_qualified":null,"docomo":null,"au":"E52B","softbank":null,"google":"FE83B","image":"1f51f.png","sheet_x":30,"sheet_y":23,"short_name":"keycap_ten","short_names":["keycap_ten"],"text":null,"texts":null,"category":"Symbols","subcategory":"keycap","sort_order":1561,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"INPUT SYMBOL FOR LATIN CAPITAL LETTERS","unified":"1F520","non_qualified":null,"docomo":null,"au":"EAFD","softbank":null,"google":"FEB7C","image":"1f520.png","sheet_x":30,"sheet_y":24,"short_name":"capital_abcd","short_names":["capital_abcd"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1562,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"INPUT SYMBOL FOR LATIN SMALL LETTERS","unified":"1F521","non_qualified":null,"docomo":null,"au":"EAFE","softbank":null,"google":"FEB7D","image":"1f521.png","sheet_x":30,"sheet_y":25,"short_name":"abcd","short_names":["abcd"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1563,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"INPUT SYMBOL FOR NUMBERS","unified":"1F522","non_qualified":null,"docomo":null,"au":"EAFF","softbank":null,"google":"FEB7E","image":"1f522.png","sheet_x":30,"sheet_y":26,"short_name":"1234","short_names":["1234"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1564,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"INPUT SYMBOL FOR SYMBOLS","unified":"1F523","non_qualified":null,"docomo":null,"au":"EB00","softbank":null,"google":"FEB7F","image":"1f523.png","sheet_x":30,"sheet_y":27,"short_name":"symbols","short_names":["symbols"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1565,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"INPUT SYMBOL FOR LATIN LETTERS","unified":"1F524","non_qualified":null,"docomo":null,"au":"EB55","softbank":null,"google":"FEB80","image":"1f524.png","sheet_x":30,"sheet_y":28,"short_name":"abc","short_names":["abc"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1566,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FIRE","unified":"1F525","non_qualified":null,"docomo":null,"au":"E47B","softbank":"E11D","google":"FE4F6","image":"1f525.png","sheet_x":30,"sheet_y":29,"short_name":"fire","short_names":["fire"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1062,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ELECTRIC TORCH","unified":"1F526","non_qualified":null,"docomo":"E6FB","au":"E583","softbank":null,"google":"FE4FB","image":"1f526.png","sheet_x":30,"sheet_y":30,"short_name":"flashlight","short_names":["flashlight"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1259,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WRENCH","unified":"1F527","non_qualified":null,"docomo":"E718","au":"E587","softbank":null,"google":"FE4C9","image":"1f527.png","sheet_x":30,"sheet_y":31,"short_name":"wrench","short_names":["wrench"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1350,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HAMMER","unified":"1F528","non_qualified":null,"docomo":null,"au":"E5CB","softbank":"E116","google":"FE4CA","image":"1f528.png","sheet_x":30,"sheet_y":32,"short_name":"hammer","short_names":["hammer"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1338,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NUT AND BOLT","unified":"1F529","non_qualified":null,"docomo":null,"au":"E581","softbank":null,"google":"FE4CB","image":"1f529.png","sheet_x":30,"sheet_y":33,"short_name":"nut_and_bolt","short_names":["nut_and_bolt"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1352,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOCHO","unified":"1F52A","non_qualified":null,"docomo":null,"au":"E57F","softbank":null,"google":"FE4FA","image":"1f52a.png","sheet_x":30,"sheet_y":34,"short_name":"hocho","short_names":["hocho","knife"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"dishware","sort_order":844,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PISTOL","unified":"1F52B","non_qualified":null,"docomo":null,"au":"E50A","softbank":"E113","google":"FE4F5","image":"1f52b.png","sheet_x":30,"sheet_y":35,"short_name":"gun","short_names":["gun"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1122,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MICROSCOPE","unified":"1F52C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f52c.png","sheet_x":30,"sheet_y":36,"short_name":"microscope","short_names":["microscope"],"text":null,"texts":null,"category":"Objects","subcategory":"science","sort_order":1368,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TELESCOPE","unified":"1F52D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f52d.png","sheet_x":30,"sheet_y":37,"short_name":"telescope","short_names":["telescope"],"text":null,"texts":null,"category":"Objects","subcategory":"science","sort_order":1369,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CRYSTAL BALL","unified":"1F52E","non_qualified":null,"docomo":null,"au":"EA8F","softbank":null,"google":"FE4F7","image":"1f52e.png","sheet_x":30,"sheet_y":38,"short_name":"crystal_ball","short_names":["crystal_ball"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1124,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SIX POINTED STAR WITH MIDDLE DOT","unified":"1F52F","non_qualified":null,"docomo":null,"au":"EA8F","softbank":"E23E","google":"FE4F8","image":"1f52f.png","sheet_x":30,"sheet_y":39,"short_name":"six_pointed_star","short_names":["six_pointed_star"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1470,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JAPANESE SYMBOL FOR BEGINNER","unified":"1F530","non_qualified":null,"docomo":null,"au":"E480","softbank":"E209","google":"FE044","image":"1f530.png","sheet_x":30,"sheet_y":40,"short_name":"beginner","short_names":["beginner"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1533,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRIDENT EMBLEM","unified":"1F531","non_qualified":null,"docomo":"E71A","au":"E5C9","softbank":"E031","google":"FE4D2","image":"1f531.png","sheet_x":30,"sheet_y":41,"short_name":"trident","short_names":["trident"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1531,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK SQUARE BUTTON","unified":"1F532","non_qualified":null,"docomo":"E69C","au":"E54B","softbank":"E21A","google":"FEB64","image":"1f532.png","sheet_x":30,"sheet_y":42,"short_name":"black_square_button","short_names":["black_square_button"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1634,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE SQUARE BUTTON","unified":"1F533","non_qualified":null,"docomo":"E69C","au":"E54B","softbank":"E21B","google":"FEB67","image":"1f533.png","sheet_x":30,"sheet_y":43,"short_name":"white_square_button","short_names":["white_square_button"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1633,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE RED CIRCLE","unified":"1F534","non_qualified":null,"docomo":"E69C","au":"E54A","softbank":"E219","google":"FEB63","image":"1f534.png","sheet_x":30,"sheet_y":44,"short_name":"red_circle","short_names":["red_circle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1601,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE BLUE CIRCLE","unified":"1F535","non_qualified":null,"docomo":"E69C","au":"E54B","softbank":null,"google":"FEB64","image":"1f535.png","sheet_x":30,"sheet_y":45,"short_name":"large_blue_circle","short_names":["large_blue_circle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1605,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE ORANGE DIAMOND","unified":"1F536","non_qualified":null,"docomo":null,"au":"E546","softbank":null,"google":"FEB73","image":"1f536.png","sheet_x":30,"sheet_y":46,"short_name":"large_orange_diamond","short_names":["large_orange_diamond"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1625,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE BLUE DIAMOND","unified":"1F537","non_qualified":null,"docomo":null,"au":"E547","softbank":null,"google":"FEB74","image":"1f537.png","sheet_x":30,"sheet_y":47,"short_name":"large_blue_diamond","short_names":["large_blue_diamond"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1626,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMALL ORANGE DIAMOND","unified":"1F538","non_qualified":null,"docomo":null,"au":"E536","softbank":null,"google":"FEB75","image":"1f538.png","sheet_x":30,"sheet_y":48,"short_name":"small_orange_diamond","short_names":["small_orange_diamond"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1627,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMALL BLUE DIAMOND","unified":"1F539","non_qualified":null,"docomo":null,"au":"E537","softbank":null,"google":"FEB76","image":"1f539.png","sheet_x":30,"sheet_y":49,"short_name":"small_blue_diamond","short_names":["small_blue_diamond"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1628,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UP-POINTING RED TRIANGLE","unified":"1F53A","non_qualified":null,"docomo":null,"au":"E55A","softbank":null,"google":"FEB78","image":"1f53a.png","sheet_x":30,"sheet_y":50,"short_name":"small_red_triangle","short_names":["small_red_triangle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1629,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOWN-POINTING RED TRIANGLE","unified":"1F53B","non_qualified":null,"docomo":null,"au":"E55B","softbank":null,"google":"FEB79","image":"1f53b.png","sheet_x":30,"sheet_y":51,"short_name":"small_red_triangle_down","short_names":["small_red_triangle_down"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1630,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UP-POINTING SMALL RED TRIANGLE","unified":"1F53C","non_qualified":null,"docomo":null,"au":"E543","softbank":null,"google":"FEB01","image":"1f53c.png","sheet_x":30,"sheet_y":52,"short_name":"arrow_up_small","short_names":["arrow_up_small"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1495,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOWN-POINTING SMALL RED TRIANGLE","unified":"1F53D","non_qualified":null,"docomo":null,"au":"E542","softbank":null,"google":"FEB00","image":"1f53d.png","sheet_x":30,"sheet_y":53,"short_name":"arrow_down_small","short_names":["arrow_down_small"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1497,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OM","unified":"1F549-FE0F","non_qualified":"1F549","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f549-fe0f.png","sheet_x":30,"sheet_y":54,"short_name":"om_symbol","short_names":["om_symbol"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1461,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOVE","unified":"1F54A-FE0F","non_qualified":"1F54A","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f54a-fe0f.png","sheet_x":30,"sheet_y":55,"short_name":"dove_of_peace","short_names":["dove_of_peace"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":633,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KAABA","unified":"1F54B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f54b.png","sheet_x":30,"sheet_y":56,"short_name":"kaaba","short_names":["kaaba"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-religious","sort_order":895,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOSQUE","unified":"1F54C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f54c.png","sheet_x":30,"sheet_y":57,"short_name":"mosque","short_names":["mosque"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-religious","sort_order":891,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SYNAGOGUE","unified":"1F54D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f54d.png","sheet_x":30,"sheet_y":58,"short_name":"synagogue","short_names":["synagogue"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-religious","sort_order":893,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MENORAH WITH NINE BRANCHES","unified":"1F54E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f54e.png","sheet_x":30,"sheet_y":59,"short_name":"menorah_with_nine_branches","short_names":["menorah_with_nine_branches"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1469,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE ONE OCLOCK","unified":"1F550","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E024","google":"FE01E","image":"1f550.png","sheet_x":30,"sheet_y":60,"short_name":"clock1","short_names":["clock1"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":996,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE TWO OCLOCK","unified":"1F551","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E025","google":"FE01F","image":"1f551.png","sheet_x":30,"sheet_y":61,"short_name":"clock2","short_names":["clock2"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":998,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE THREE OCLOCK","unified":"1F552","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E026","google":"FE020","image":"1f552.png","sheet_x":31,"sheet_y":0,"short_name":"clock3","short_names":["clock3"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1000,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE FOUR OCLOCK","unified":"1F553","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E027","google":"FE021","image":"1f553.png","sheet_x":31,"sheet_y":1,"short_name":"clock4","short_names":["clock4"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1002,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE FIVE OCLOCK","unified":"1F554","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E028","google":"FE022","image":"1f554.png","sheet_x":31,"sheet_y":2,"short_name":"clock5","short_names":["clock5"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1004,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE SIX OCLOCK","unified":"1F555","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E029","google":"FE023","image":"1f555.png","sheet_x":31,"sheet_y":3,"short_name":"clock6","short_names":["clock6"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1006,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE SEVEN OCLOCK","unified":"1F556","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E02A","google":"FE024","image":"1f556.png","sheet_x":31,"sheet_y":4,"short_name":"clock7","short_names":["clock7"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1008,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE EIGHT OCLOCK","unified":"1F557","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E02B","google":"FE025","image":"1f557.png","sheet_x":31,"sheet_y":5,"short_name":"clock8","short_names":["clock8"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1010,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE NINE OCLOCK","unified":"1F558","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E02C","google":"FE026","image":"1f558.png","sheet_x":31,"sheet_y":6,"short_name":"clock9","short_names":["clock9"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1012,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE TEN OCLOCK","unified":"1F559","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E02D","google":"FE027","image":"1f559.png","sheet_x":31,"sheet_y":7,"short_name":"clock10","short_names":["clock10"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1014,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE ELEVEN OCLOCK","unified":"1F55A","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E02E","google":"FE028","image":"1f55a.png","sheet_x":31,"sheet_y":8,"short_name":"clock11","short_names":["clock11"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1016,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE TWELVE OCLOCK","unified":"1F55B","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":"E02F","google":"FE029","image":"1f55b.png","sheet_x":31,"sheet_y":9,"short_name":"clock12","short_names":["clock12"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":994,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE ONE-THIRTY","unified":"1F55C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f55c.png","sheet_x":31,"sheet_y":10,"short_name":"clock130","short_names":["clock130"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":997,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE TWO-THIRTY","unified":"1F55D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f55d.png","sheet_x":31,"sheet_y":11,"short_name":"clock230","short_names":["clock230"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":999,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE THREE-THIRTY","unified":"1F55E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f55e.png","sheet_x":31,"sheet_y":12,"short_name":"clock330","short_names":["clock330"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1001,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE FOUR-THIRTY","unified":"1F55F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f55f.png","sheet_x":31,"sheet_y":13,"short_name":"clock430","short_names":["clock430"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1003,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE FIVE-THIRTY","unified":"1F560","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f560.png","sheet_x":31,"sheet_y":14,"short_name":"clock530","short_names":["clock530"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1005,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE SIX-THIRTY","unified":"1F561","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f561.png","sheet_x":31,"sheet_y":15,"short_name":"clock630","short_names":["clock630"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1007,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE SEVEN-THIRTY","unified":"1F562","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f562.png","sheet_x":31,"sheet_y":16,"short_name":"clock730","short_names":["clock730"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1009,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE EIGHT-THIRTY","unified":"1F563","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f563.png","sheet_x":31,"sheet_y":17,"short_name":"clock830","short_names":["clock830"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1011,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE NINE-THIRTY","unified":"1F564","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f564.png","sheet_x":31,"sheet_y":18,"short_name":"clock930","short_names":["clock930"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1013,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE TEN-THIRTY","unified":"1F565","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f565.png","sheet_x":31,"sheet_y":19,"short_name":"clock1030","short_names":["clock1030"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1015,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE ELEVEN-THIRTY","unified":"1F566","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f566.png","sheet_x":31,"sheet_y":20,"short_name":"clock1130","short_names":["clock1130"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":1017,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOCK FACE TWELVE-THIRTY","unified":"1F567","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f567.png","sheet_x":31,"sheet_y":21,"short_name":"clock1230","short_names":["clock1230"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":995,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CANDLE","unified":"1F56F-FE0F","non_qualified":"1F56F","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f56f-fe0f.png","sheet_x":31,"sheet_y":22,"short_name":"candle","short_names":["candle"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1257,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MANTELPIECE CLOCK","unified":"1F570-FE0F","non_qualified":"1F570","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f570-fe0f.png","sheet_x":31,"sheet_y":23,"short_name":"mantelpiece_clock","short_names":["mantelpiece_clock"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":993,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOLE","unified":"1F573-FE0F","non_qualified":"1F573","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f573-fe0f.png","sheet_x":31,"sheet_y":24,"short_name":"hole","short_names":["hole"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":162,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PERSON IN SUIT LEVITATING","unified":"1F574-FE0F","non_qualified":"1F574","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f574-fe0f.png","sheet_x":31,"sheet_y":25,"short_name":"man_in_business_suit_levitating","short_names":["man_in_business_suit_levitating"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":449,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F574-1F3FB","non_qualified":null,"image":"1f574-1f3fb.png","sheet_x":31,"sheet_y":26,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F574-1F3FC","non_qualified":null,"image":"1f574-1f3fc.png","sheet_x":31,"sheet_y":27,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F574-1F3FD","non_qualified":null,"image":"1f574-1f3fd.png","sheet_x":31,"sheet_y":28,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F574-1F3FE","non_qualified":null,"image":"1f574-1f3fe.png","sheet_x":31,"sheet_y":29,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F574-1F3FF","non_qualified":null,"image":"1f574-1f3ff.png","sheet_x":31,"sheet_y":30,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN DETECTIVE","unified":"1F575-FE0F-200D-2640-FE0F","non_qualified":"1F575-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f575-fe0f-200d-2640-fe0f.png","sheet_x":31,"sheet_y":31,"short_name":"female-detective","short_names":["female-detective"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":341,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F575-1F3FB-200D-2640-FE0F","non_qualified":"1F575-1F3FB-200D-2640","image":"1f575-1f3fb-200d-2640-fe0f.png","sheet_x":31,"sheet_y":32,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F575-1F3FC-200D-2640-FE0F","non_qualified":"1F575-1F3FC-200D-2640","image":"1f575-1f3fc-200d-2640-fe0f.png","sheet_x":31,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F575-1F3FD-200D-2640-FE0F","non_qualified":"1F575-1F3FD-200D-2640","image":"1f575-1f3fd-200d-2640-fe0f.png","sheet_x":31,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F575-1F3FE-200D-2640-FE0F","non_qualified":"1F575-1F3FE-200D-2640","image":"1f575-1f3fe-200d-2640-fe0f.png","sheet_x":31,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F575-1F3FF-200D-2640-FE0F","non_qualified":"1F575-1F3FF-200D-2640","image":"1f575-1f3ff-200d-2640-fe0f.png","sheet_x":31,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN DETECTIVE","unified":"1F575-FE0F-200D-2642-FE0F","non_qualified":"1F575-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f575-fe0f-200d-2642-fe0f.png","sheet_x":31,"sheet_y":37,"short_name":"male-detective","short_names":["male-detective"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":340,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F575-1F3FB-200D-2642-FE0F","non_qualified":"1F575-1F3FB-200D-2642","image":"1f575-1f3fb-200d-2642-fe0f.png","sheet_x":31,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F575-1F3FC-200D-2642-FE0F","non_qualified":"1F575-1F3FC-200D-2642","image":"1f575-1f3fc-200d-2642-fe0f.png","sheet_x":31,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F575-1F3FD-200D-2642-FE0F","non_qualified":"1F575-1F3FD-200D-2642","image":"1f575-1f3fd-200d-2642-fe0f.png","sheet_x":31,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F575-1F3FE-200D-2642-FE0F","non_qualified":"1F575-1F3FE-200D-2642","image":"1f575-1f3fe-200d-2642-fe0f.png","sheet_x":31,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F575-1F3FF-200D-2642-FE0F","non_qualified":"1F575-1F3FF-200D-2642","image":"1f575-1f3ff-200d-2642-fe0f.png","sheet_x":31,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F575-FE0F"},{"name":"DETECTIVE","unified":"1F575-FE0F","non_qualified":"1F575","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f575-fe0f.png","sheet_x":31,"sheet_y":43,"short_name":"sleuth_or_spy","short_names":["sleuth_or_spy"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":339,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F575-1F3FB","non_qualified":null,"image":"1f575-1f3fb.png","sheet_x":31,"sheet_y":44,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F575-1F3FC","non_qualified":null,"image":"1f575-1f3fc.png","sheet_x":31,"sheet_y":45,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F575-1F3FD","non_qualified":null,"image":"1f575-1f3fd.png","sheet_x":31,"sheet_y":46,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F575-1F3FE","non_qualified":null,"image":"1f575-1f3fe.png","sheet_x":31,"sheet_y":47,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F575-1F3FF","non_qualified":null,"image":"1f575-1f3ff.png","sheet_x":31,"sheet_y":48,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F575-FE0F-200D-2642-FE0F"},{"name":"SUNGLASSES","unified":"1F576-FE0F","non_qualified":"1F576","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f576-fe0f.png","sheet_x":31,"sheet_y":49,"short_name":"dark_sunglasses","short_names":["dark_sunglasses"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1151,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPIDER","unified":"1F577-FE0F","non_qualified":"1F577","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f577-fe0f.png","sheet_x":31,"sheet_y":50,"short_name":"spider","short_names":["spider"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":677,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPIDER WEB","unified":"1F578-FE0F","non_qualified":"1F578","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f578-fe0f.png","sheet_x":31,"sheet_y":51,"short_name":"spider_web","short_names":["spider_web"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":678,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JOYSTICK","unified":"1F579-FE0F","non_qualified":"1F579","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f579-fe0f.png","sheet_x":31,"sheet_y":52,"short_name":"joystick","short_names":["joystick"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1127,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MAN DANCING","unified":"1F57A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f57a.png","sheet_x":31,"sheet_y":53,"short_name":"man_dancing","short_names":["man_dancing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":448,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F57A-1F3FB","non_qualified":null,"image":"1f57a-1f3fb.png","sheet_x":31,"sheet_y":54,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F57A-1F3FC","non_qualified":null,"image":"1f57a-1f3fc.png","sheet_x":31,"sheet_y":55,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F57A-1F3FD","non_qualified":null,"image":"1f57a-1f3fd.png","sheet_x":31,"sheet_y":56,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F57A-1F3FE","non_qualified":null,"image":"1f57a-1f3fe.png","sheet_x":31,"sheet_y":57,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F57A-1F3FF","non_qualified":null,"image":"1f57a-1f3ff.png","sheet_x":31,"sheet_y":58,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"LINKED PAPERCLIPS","unified":"1F587-FE0F","non_qualified":"1F587","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f587-fe0f.png","sheet_x":31,"sheet_y":59,"short_name":"linked_paperclips","short_names":["linked_paperclips"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1325,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PEN","unified":"1F58A-FE0F","non_qualified":"1F58A","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f58a-fe0f.png","sheet_x":31,"sheet_y":60,"short_name":"lower_left_ballpoint_pen","short_names":["lower_left_ballpoint_pen"],"text":null,"texts":null,"category":"Objects","subcategory":"writing","sort_order":1305,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FOUNTAIN PEN","unified":"1F58B-FE0F","non_qualified":"1F58B","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f58b-fe0f.png","sheet_x":31,"sheet_y":61,"short_name":"lower_left_fountain_pen","short_names":["lower_left_fountain_pen"],"text":null,"texts":null,"category":"Objects","subcategory":"writing","sort_order":1304,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PAINTBRUSH","unified":"1F58C-FE0F","non_qualified":"1F58C","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f58c-fe0f.png","sheet_x":32,"sheet_y":0,"short_name":"lower_left_paintbrush","short_names":["lower_left_paintbrush"],"text":null,"texts":null,"category":"Objects","subcategory":"writing","sort_order":1306,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CRAYON","unified":"1F58D-FE0F","non_qualified":"1F58D","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f58d-fe0f.png","sheet_x":32,"sheet_y":1,"short_name":"lower_left_crayon","short_names":["lower_left_crayon"],"text":null,"texts":null,"category":"Objects","subcategory":"writing","sort_order":1307,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HAND WITH FINGERS SPLAYED","unified":"1F590-FE0F","non_qualified":"1F590","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f590-fe0f.png","sheet_x":32,"sheet_y":2,"short_name":"raised_hand_with_fingers_splayed","short_names":["raised_hand_with_fingers_splayed"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":171,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F590-1F3FB","non_qualified":null,"image":"1f590-1f3fb.png","sheet_x":32,"sheet_y":3,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F590-1F3FC","non_qualified":null,"image":"1f590-1f3fc.png","sheet_x":32,"sheet_y":4,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F590-1F3FD","non_qualified":null,"image":"1f590-1f3fd.png","sheet_x":32,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F590-1F3FE","non_qualified":null,"image":"1f590-1f3fe.png","sheet_x":32,"sheet_y":6,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F590-1F3FF","non_qualified":null,"image":"1f590-1f3ff.png","sheet_x":32,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"REVERSED HAND WITH MIDDLE FINGER EXTENDED","unified":"1F595","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f595.png","sheet_x":32,"sheet_y":8,"short_name":"middle_finger","short_names":["middle_finger","reversed_hand_with_middle_finger_extended"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-single-finger","sort_order":192,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F595-1F3FB","non_qualified":null,"image":"1f595-1f3fb.png","sheet_x":32,"sheet_y":9,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F595-1F3FC","non_qualified":null,"image":"1f595-1f3fc.png","sheet_x":32,"sheet_y":10,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F595-1F3FD","non_qualified":null,"image":"1f595-1f3fd.png","sheet_x":32,"sheet_y":11,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F595-1F3FE","non_qualified":null,"image":"1f595-1f3fe.png","sheet_x":32,"sheet_y":12,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F595-1F3FF","non_qualified":null,"image":"1f595-1f3ff.png","sheet_x":32,"sheet_y":13,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS","unified":"1F596","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f596.png","sheet_x":32,"sheet_y":14,"short_name":"spock-hand","short_names":["spock-hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":173,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F596-1F3FB","non_qualified":null,"image":"1f596-1f3fb.png","sheet_x":32,"sheet_y":15,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F596-1F3FC","non_qualified":null,"image":"1f596-1f3fc.png","sheet_x":32,"sheet_y":16,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F596-1F3FD","non_qualified":null,"image":"1f596-1f3fd.png","sheet_x":32,"sheet_y":17,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F596-1F3FE","non_qualified":null,"image":"1f596-1f3fe.png","sheet_x":32,"sheet_y":18,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F596-1F3FF","non_qualified":null,"image":"1f596-1f3ff.png","sheet_x":32,"sheet_y":19,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"BLACK HEART","unified":"1F5A4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5a4.png","sheet_x":32,"sheet_y":20,"short_name":"black_heart","short_names":["black_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":152,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DESKTOP COMPUTER","unified":"1F5A5-FE0F","non_qualified":"1F5A5","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5a5-fe0f.png","sheet_x":32,"sheet_y":21,"short_name":"desktop_computer","short_names":["desktop_computer"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1236,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PRINTER","unified":"1F5A8-FE0F","non_qualified":"1F5A8","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5a8-fe0f.png","sheet_x":32,"sheet_y":22,"short_name":"printer","short_names":["printer"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1237,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COMPUTER MOUSE","unified":"1F5B1-FE0F","non_qualified":"1F5B1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5b1-fe0f.png","sheet_x":32,"sheet_y":23,"short_name":"three_button_mouse","short_names":["three_button_mouse"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1239,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRACKBALL","unified":"1F5B2-FE0F","non_qualified":"1F5B2","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5b2-fe0f.png","sheet_x":32,"sheet_y":24,"short_name":"trackball","short_names":["trackball"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1240,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FRAMED PICTURE","unified":"1F5BC-FE0F","non_qualified":"1F5BC","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5bc-fe0f.png","sheet_x":32,"sheet_y":25,"short_name":"frame_with_picture","short_names":["frame_with_picture"],"text":null,"texts":null,"category":"Activities","subcategory":"arts & crafts","sort_order":1144,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CARD INDEX DIVIDERS","unified":"1F5C2-FE0F","non_qualified":"1F5C2","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5c2-fe0f.png","sheet_x":32,"sheet_y":26,"short_name":"card_index_dividers","short_names":["card_index_dividers"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1312,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CARD FILE BOX","unified":"1F5C3-FE0F","non_qualified":"1F5C3","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5c3-fe0f.png","sheet_x":32,"sheet_y":27,"short_name":"card_file_box","short_names":["card_file_box"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1329,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FILE CABINET","unified":"1F5C4-FE0F","non_qualified":"1F5C4","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5c4-fe0f.png","sheet_x":32,"sheet_y":28,"short_name":"file_cabinet","short_names":["file_cabinet"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1330,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WASTEBASKET","unified":"1F5D1-FE0F","non_qualified":"1F5D1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5d1-fe0f.png","sheet_x":32,"sheet_y":29,"short_name":"wastebasket","short_names":["wastebasket"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1331,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPIRAL NOTEPAD","unified":"1F5D2-FE0F","non_qualified":"1F5D2","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5d2-fe0f.png","sheet_x":32,"sheet_y":30,"short_name":"spiral_note_pad","short_names":["spiral_note_pad"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1315,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPIRAL CALENDAR","unified":"1F5D3-FE0F","non_qualified":"1F5D3","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5d3-fe0f.png","sheet_x":32,"sheet_y":31,"short_name":"spiral_calendar_pad","short_names":["spiral_calendar_pad"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1316,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLAMP","unified":"1F5DC-FE0F","non_qualified":"1F5DC","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5dc-fe0f.png","sheet_x":32,"sheet_y":32,"short_name":"compression","short_names":["compression"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1354,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OLD KEY","unified":"1F5DD-FE0F","non_qualified":"1F5DD","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5dd-fe0f.png","sheet_x":32,"sheet_y":33,"short_name":"old_key","short_names":["old_key"],"text":null,"texts":null,"category":"Objects","subcategory":"lock","sort_order":1337,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROLLED-UP NEWSPAPER","unified":"1F5DE-FE0F","non_qualified":"1F5DE","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5de-fe0f.png","sheet_x":32,"sheet_y":34,"short_name":"rolled_up_newspaper","short_names":["rolled_up_newspaper"],"text":null,"texts":null,"category":"Objects","subcategory":"book-paper","sort_order":1275,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DAGGER","unified":"1F5E1-FE0F","non_qualified":"1F5E1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5e1-fe0f.png","sheet_x":32,"sheet_y":35,"short_name":"dagger_knife","short_names":["dagger_knife"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1343,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPEAKING HEAD","unified":"1F5E3-FE0F","non_qualified":"1F5E3","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5e3-fe0f.png","sheet_x":32,"sheet_y":36,"short_name":"speaking_head_in_silhouette","short_names":["speaking_head_in_silhouette"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":544,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEFT SPEECH BUBBLE","unified":"1F5E8-FE0F","non_qualified":"1F5E8","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5e8-fe0f.png","sheet_x":32,"sheet_y":37,"short_name":"left_speech_bubble","short_names":["left_speech_bubble"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":165,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RIGHT ANGER BUBBLE","unified":"1F5EF-FE0F","non_qualified":"1F5EF","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5ef-fe0f.png","sheet_x":32,"sheet_y":38,"short_name":"right_anger_bubble","short_names":["right_anger_bubble"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"emotion","sort_order":166,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BALLOT BOX WITH BALLOT","unified":"1F5F3-FE0F","non_qualified":"1F5F3","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5f3-fe0f.png","sheet_x":32,"sheet_y":39,"short_name":"ballot_box_with_ballot","short_names":["ballot_box_with_ballot"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1301,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WORLD MAP","unified":"1F5FA-FE0F","non_qualified":"1F5FA","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f5fa-fe0f.png","sheet_x":32,"sheet_y":40,"short_name":"world_map","short_names":["world_map"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-map","sort_order":851,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOUNT FUJI","unified":"1F5FB","non_qualified":null,"docomo":"E740","au":"E5BD","softbank":"E03B","google":"FE4C3","image":"1f5fb.png","sheet_x":32,"sheet_y":41,"short_name":"mount_fuji","short_names":["mount_fuji"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-geographic","sort_order":857,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TOKYO TOWER","unified":"1F5FC","non_qualified":null,"docomo":null,"au":"E4C0","softbank":"E509","google":"FE4C4","image":"1f5fc.png","sheet_x":32,"sheet_y":42,"short_name":"tokyo_tower","short_names":["tokyo_tower"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":888,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STATUE OF LIBERTY","unified":"1F5FD","non_qualified":null,"docomo":null,"au":null,"softbank":"E51D","google":"FE4C6","image":"1f5fd.png","sheet_x":32,"sheet_y":43,"short_name":"statue_of_liberty","short_names":["statue_of_liberty"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":889,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SILHOUETTE OF JAPAN","unified":"1F5FE","non_qualified":null,"docomo":null,"au":"E572","softbank":null,"google":"FE4C7","image":"1f5fe.png","sheet_x":32,"sheet_y":44,"short_name":"japan","short_names":["japan"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-map","sort_order":852,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOYAI","unified":"1F5FF","non_qualified":null,"docomo":null,"au":"EB6C","softbank":null,"google":"FE4C8","image":"1f5ff.png","sheet_x":32,"sheet_y":45,"short_name":"moyai","short_names":["moyai"],"text":null,"texts":null,"category":"Objects","subcategory":"other-object","sort_order":1409,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GRINNING FACE","unified":"1F600","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f600.png","sheet_x":32,"sheet_y":46,"short_name":"grinning","short_names":["grinning"],"text":":D","texts":null,"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":1,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GRINNING FACE WITH SMILING EYES","unified":"1F601","non_qualified":null,"docomo":"E753","au":"EB80","softbank":"E404","google":"FE333","image":"1f601.png","sheet_x":32,"sheet_y":47,"short_name":"grin","short_names":["grin"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":4,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH TEARS OF JOY","unified":"1F602","non_qualified":null,"docomo":"E72A","au":"EB64","softbank":"E412","google":"FE334","image":"1f602.png","sheet_x":32,"sheet_y":48,"short_name":"joy","short_names":["joy"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":8,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH OPEN MOUTH","unified":"1F603","non_qualified":null,"docomo":"E6F0","au":"E471","softbank":"E057","google":"FE330","image":"1f603.png","sheet_x":32,"sheet_y":49,"short_name":"smiley","short_names":["smiley"],"text":":)","texts":["=)","=-)"],"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":2,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH OPEN MOUTH AND SMILING EYES","unified":"1F604","non_qualified":null,"docomo":"E6F0","au":"E471","softbank":"E415","google":"FE338","image":"1f604.png","sheet_x":32,"sheet_y":50,"short_name":"smile","short_names":["smile"],"text":":)","texts":["C:","c:",":D",":-D"],"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":3,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH OPEN MOUTH AND COLD SWEAT","unified":"1F605","non_qualified":null,"docomo":"E722","au":"E471-E5B1","softbank":null,"google":"FE331","image":"1f605.png","sheet_x":32,"sheet_y":51,"short_name":"sweat_smile","short_names":["sweat_smile"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":6,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES","unified":"1F606","non_qualified":null,"docomo":"E72A","au":"EAC5","softbank":null,"google":"FE332","image":"1f606.png","sheet_x":32,"sheet_y":52,"short_name":"laughing","short_names":["laughing","satisfied"],"text":null,"texts":[":>",":->"],"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":5,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH HALO","unified":"1F607","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f607.png","sheet_x":32,"sheet_y":53,"short_name":"innocent","short_names":["innocent"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":14,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH HORNS","unified":"1F608","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f608.png","sheet_x":32,"sheet_y":54,"short_name":"smiling_imp","short_names":["smiling_imp"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-negative","sort_order":106,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WINKING FACE","unified":"1F609","non_qualified":null,"docomo":"E729","au":"E5C3","softbank":"E405","google":"FE347","image":"1f609.png","sheet_x":32,"sheet_y":55,"short_name":"wink","short_names":["wink"],"text":";)","texts":[";)",";-)"],"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":12,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH SMILING EYES","unified":"1F60A","non_qualified":null,"docomo":"E6F0","au":"EACD","softbank":"E056","google":"FE335","image":"1f60a.png","sheet_x":32,"sheet_y":56,"short_name":"blush","short_names":["blush"],"text":":)","texts":null,"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":13,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE SAVOURING DELICIOUS FOOD","unified":"1F60B","non_qualified":null,"docomo":"E752","au":"EACD","softbank":null,"google":"FE32B","image":"1f60b.png","sheet_x":32,"sheet_y":57,"short_name":"yum","short_names":["yum"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-tongue","sort_order":24,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RELIEVED FACE","unified":"1F60C","non_qualified":null,"docomo":"E721","au":"EAC5","softbank":"E40A","google":"FE33E","image":"1f60c.png","sheet_x":32,"sheet_y":58,"short_name":"relieved","short_names":["relieved"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-sleepy","sort_order":53,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH HEART-SHAPED EYES","unified":"1F60D","non_qualified":null,"docomo":"E726","au":"E5C4","softbank":"E106","google":"FE327","image":"1f60d.png","sheet_x":32,"sheet_y":59,"short_name":"heart_eyes","short_names":["heart_eyes"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-affection","sort_order":16,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH SUNGLASSES","unified":"1F60E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f60e.png","sheet_x":32,"sheet_y":60,"short_name":"sunglasses","short_names":["sunglasses"],"text":null,"texts":["8)"],"category":"Smileys & Emotion","subcategory":"face-glasses","sort_order":73,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMIRKING FACE","unified":"1F60F","non_qualified":null,"docomo":"E72C","au":"EABF","softbank":"E402","google":"FE343","image":"1f60f.png","sheet_x":32,"sheet_y":61,"short_name":"smirk","short_names":["smirk"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":44,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEUTRAL FACE","unified":"1F610","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f610.png","sheet_x":33,"sheet_y":0,"short_name":"neutral_face","short_names":["neutral_face"],"text":null,"texts":[":|",":-|"],"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":39,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EXPRESSIONLESS FACE","unified":"1F611","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f611.png","sheet_x":33,"sheet_y":1,"short_name":"expressionless","short_names":["expressionless"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":40,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UNAMUSED FACE","unified":"1F612","non_qualified":null,"docomo":"E725","au":"EAC9","softbank":"E40E","google":"FE326","image":"1f612.png","sheet_x":33,"sheet_y":2,"short_name":"unamused","short_names":["unamused"],"text":":(","texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":45,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH COLD SWEAT","unified":"1F613","non_qualified":null,"docomo":"E723","au":"E5C6","softbank":"E108","google":"FE344","image":"1f613.png","sheet_x":33,"sheet_y":3,"short_name":"sweat","short_names":["sweat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":98,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PENSIVE FACE","unified":"1F614","non_qualified":null,"docomo":"E720","au":"EAC0","softbank":"E403","google":"FE340","image":"1f614.png","sheet_x":33,"sheet_y":4,"short_name":"pensive","short_names":["pensive"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-sleepy","sort_order":54,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CONFUSED FACE","unified":"1F615","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f615.png","sheet_x":33,"sheet_y":5,"short_name":"confused","short_names":["confused"],"text":null,"texts":[":\\",":-\\",":\/",":-\/"],"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":76,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CONFOUNDED FACE","unified":"1F616","non_qualified":null,"docomo":"E6F3","au":"EAC3","softbank":"E407","google":"FE33F","image":"1f616.png","sheet_x":33,"sheet_y":6,"short_name":"confounded","short_names":["confounded"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":95,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KISSING FACE","unified":"1F617","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f617.png","sheet_x":33,"sheet_y":7,"short_name":"kissing","short_names":["kissing"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-affection","sort_order":19,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE THROWING A KISS","unified":"1F618","non_qualified":null,"docomo":"E726","au":"EACF","softbank":"E418","google":"FE32C","image":"1f618.png","sheet_x":33,"sheet_y":8,"short_name":"kissing_heart","short_names":["kissing_heart"],"text":null,"texts":[":*",":-*"],"category":"Smileys & Emotion","subcategory":"face-affection","sort_order":18,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KISSING FACE WITH SMILING EYES","unified":"1F619","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f619.png","sheet_x":33,"sheet_y":9,"short_name":"kissing_smiling_eyes","short_names":["kissing_smiling_eyes"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-affection","sort_order":22,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KISSING FACE WITH CLOSED EYES","unified":"1F61A","non_qualified":null,"docomo":"E726","au":"EACE","softbank":"E417","google":"FE32D","image":"1f61a.png","sheet_x":33,"sheet_y":10,"short_name":"kissing_closed_eyes","short_names":["kissing_closed_eyes"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-affection","sort_order":21,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH STUCK-OUT TONGUE","unified":"1F61B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f61b.png","sheet_x":33,"sheet_y":11,"short_name":"stuck_out_tongue","short_names":["stuck_out_tongue"],"text":":p","texts":[":p",":-p",":P",":-P",":b",":-b"],"category":"Smileys & Emotion","subcategory":"face-tongue","sort_order":25,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH STUCK-OUT TONGUE AND WINKING EYE","unified":"1F61C","non_qualified":null,"docomo":"E728","au":"E4E7","softbank":"E105","google":"FE329","image":"1f61c.png","sheet_x":33,"sheet_y":12,"short_name":"stuck_out_tongue_winking_eye","short_names":["stuck_out_tongue_winking_eye"],"text":";p","texts":[";p",";-p",";b",";-b",";P",";-P"],"category":"Smileys & Emotion","subcategory":"face-tongue","sort_order":26,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES","unified":"1F61D","non_qualified":null,"docomo":"E728","au":"E4E7","softbank":"E409","google":"FE32A","image":"1f61d.png","sheet_x":33,"sheet_y":13,"short_name":"stuck_out_tongue_closed_eyes","short_names":["stuck_out_tongue_closed_eyes"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-tongue","sort_order":28,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DISAPPOINTED FACE","unified":"1F61E","non_qualified":null,"docomo":"E6F2","au":"EAC0","softbank":"E058","google":"FE323","image":"1f61e.png","sheet_x":33,"sheet_y":14,"short_name":"disappointed","short_names":["disappointed"],"text":":(","texts":["):",":(",":-("],"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":97,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WORRIED FACE","unified":"1F61F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f61f.png","sheet_x":33,"sheet_y":15,"short_name":"worried","short_names":["worried"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":78,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ANGRY FACE","unified":"1F620","non_qualified":null,"docomo":"E6F1","au":"E472","softbank":"E059","google":"FE320","image":"1f620.png","sheet_x":33,"sheet_y":16,"short_name":"angry","short_names":["angry"],"text":null,"texts":[">:(",">:-("],"category":"Smileys & Emotion","subcategory":"face-negative","sort_order":104,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POUTING FACE","unified":"1F621","non_qualified":null,"docomo":"E724","au":"EB5D","softbank":"E416","google":"FE33D","image":"1f621.png","sheet_x":33,"sheet_y":17,"short_name":"rage","short_names":["rage"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-negative","sort_order":103,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CRYING FACE","unified":"1F622","non_qualified":null,"docomo":"E72E","au":"EB69","softbank":"E413","google":"FE339","image":"1f622.png","sheet_x":33,"sheet_y":18,"short_name":"cry","short_names":["cry"],"text":":'(","texts":[":'("],"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":92,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PERSEVERING FACE","unified":"1F623","non_qualified":null,"docomo":"E72B","au":"EAC2","softbank":"E406","google":"FE33C","image":"1f623.png","sheet_x":33,"sheet_y":19,"short_name":"persevere","short_names":["persevere"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":96,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH LOOK OF TRIUMPH","unified":"1F624","non_qualified":null,"docomo":"E753","au":"EAC1","softbank":null,"google":"FE328","image":"1f624.png","sheet_x":33,"sheet_y":20,"short_name":"triumph","short_names":["triumph"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-negative","sort_order":102,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DISAPPOINTED BUT RELIEVED FACE","unified":"1F625","non_qualified":null,"docomo":"E723","au":"E5C6","softbank":"E401","google":"FE345","image":"1f625.png","sheet_x":33,"sheet_y":21,"short_name":"disappointed_relieved","short_names":["disappointed_relieved"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":91,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FROWNING FACE WITH OPEN MOUTH","unified":"1F626","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f626.png","sheet_x":33,"sheet_y":22,"short_name":"frowning","short_names":["frowning"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":87,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ANGUISHED FACE","unified":"1F627","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f627.png","sheet_x":33,"sheet_y":23,"short_name":"anguished","short_names":["anguished"],"text":null,"texts":["D:"],"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":88,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FEARFUL FACE","unified":"1F628","non_qualified":null,"docomo":"E757","au":"EAC6","softbank":"E40B","google":"FE33B","image":"1f628.png","sheet_x":33,"sheet_y":24,"short_name":"fearful","short_names":["fearful"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":89,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WEARY FACE","unified":"1F629","non_qualified":null,"docomo":"E6F3","au":"EB67","softbank":null,"google":"FE321","image":"1f629.png","sheet_x":33,"sheet_y":25,"short_name":"weary","short_names":["weary"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":99,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SLEEPY FACE","unified":"1F62A","non_qualified":null,"docomo":"E701","au":"EAC4","softbank":"E408","google":"FE342","image":"1f62a.png","sheet_x":33,"sheet_y":26,"short_name":"sleepy","short_names":["sleepy"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-sleepy","sort_order":55,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TIRED FACE","unified":"1F62B","non_qualified":null,"docomo":"E72B","au":"E474","softbank":null,"google":"FE346","image":"1f62b.png","sheet_x":33,"sheet_y":27,"short_name":"tired_face","short_names":["tired_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":100,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GRIMACING FACE","unified":"1F62C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f62c.png","sheet_x":33,"sheet_y":28,"short_name":"grimacing","short_names":["grimacing"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOUDLY CRYING FACE","unified":"1F62D","non_qualified":null,"docomo":"E72D","au":"E473","softbank":"E411","google":"FE33A","image":"1f62d.png","sheet_x":33,"sheet_y":29,"short_name":"sob","short_names":["sob"],"text":":'(","texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":93,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE EXHALING","unified":"1F62E-200D-1F4A8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f62e-200d-1f4a8.png","sheet_x":33,"sheet_y":30,"short_name":"face_exhaling","short_names":["face_exhaling"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":48,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH OPEN MOUTH","unified":"1F62E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f62e.png","sheet_x":33,"sheet_y":31,"short_name":"open_mouth","short_names":["open_mouth"],"text":null,"texts":[":o",":-o",":O",":-O"],"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":81,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HUSHED FACE","unified":"1F62F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f62f.png","sheet_x":33,"sheet_y":32,"short_name":"hushed","short_names":["hushed"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":82,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH OPEN MOUTH AND COLD SWEAT","unified":"1F630","non_qualified":null,"docomo":"E723","au":"EACB","softbank":"E40F","google":"FE325","image":"1f630.png","sheet_x":33,"sheet_y":33,"short_name":"cold_sweat","short_names":["cold_sweat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":90,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE SCREAMING IN FEAR","unified":"1F631","non_qualified":null,"docomo":"E757","au":"E5C5","softbank":"E107","google":"FE341","image":"1f631.png","sheet_x":33,"sheet_y":34,"short_name":"scream","short_names":["scream"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":94,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ASTONISHED FACE","unified":"1F632","non_qualified":null,"docomo":"E6F4","au":"EACA","softbank":"E410","google":"FE322","image":"1f632.png","sheet_x":33,"sheet_y":35,"short_name":"astonished","short_names":["astonished"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":83,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLUSHED FACE","unified":"1F633","non_qualified":null,"docomo":"E72A","au":"EAC8","softbank":"E40D","google":"FE32F","image":"1f633.png","sheet_x":33,"sheet_y":36,"short_name":"flushed","short_names":["flushed"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":84,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SLEEPING FACE","unified":"1F634","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f634.png","sheet_x":33,"sheet_y":37,"short_name":"sleeping","short_names":["sleeping"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-sleepy","sort_order":57,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH SPIRAL EYES","unified":"1F635-200D-1F4AB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f635-200d-1f4ab.png","sheet_x":33,"sheet_y":38,"short_name":"face_with_spiral_eyes","short_names":["face_with_spiral_eyes"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":68,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DIZZY FACE","unified":"1F635","non_qualified":null,"docomo":"E6F4","au":"E5AE","softbank":null,"google":"FE324","image":"1f635.png","sheet_x":33,"sheet_y":39,"short_name":"dizzy_face","short_names":["dizzy_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":67,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE IN CLOUDS","unified":"1F636-200D-1F32B-FE0F","non_qualified":"1F636-200D-1F32B","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f636-200d-1f32b-fe0f.png","sheet_x":33,"sheet_y":40,"short_name":"face_in_clouds","short_names":["face_in_clouds"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":43,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITHOUT MOUTH","unified":"1F636","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f636.png","sheet_x":33,"sheet_y":41,"short_name":"no_mouth","short_names":["no_mouth"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":41,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH MEDICAL MASK","unified":"1F637","non_qualified":null,"docomo":null,"au":"EAC7","softbank":"E40C","google":"FE32E","image":"1f637.png","sheet_x":33,"sheet_y":42,"short_name":"mask","short_names":["mask"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":58,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GRINNING CAT FACE WITH SMILING EYES","unified":"1F638","non_qualified":null,"docomo":"E753","au":"EB7F","softbank":null,"google":"FE349","image":"1f638.png","sheet_x":33,"sheet_y":43,"short_name":"smile_cat","short_names":["smile_cat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"cat-face","sort_order":119,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CAT FACE WITH TEARS OF JOY","unified":"1F639","non_qualified":null,"docomo":"E72A","au":"EB63","softbank":null,"google":"FE34A","image":"1f639.png","sheet_x":33,"sheet_y":44,"short_name":"joy_cat","short_names":["joy_cat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"cat-face","sort_order":120,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING CAT FACE WITH OPEN MOUTH","unified":"1F63A","non_qualified":null,"docomo":"E6F0","au":"EB61","softbank":null,"google":"FE348","image":"1f63a.png","sheet_x":33,"sheet_y":45,"short_name":"smiley_cat","short_names":["smiley_cat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"cat-face","sort_order":118,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING CAT FACE WITH HEART-SHAPED EYES","unified":"1F63B","non_qualified":null,"docomo":"E726","au":"EB65","softbank":null,"google":"FE34C","image":"1f63b.png","sheet_x":33,"sheet_y":46,"short_name":"heart_eyes_cat","short_names":["heart_eyes_cat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"cat-face","sort_order":121,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CAT FACE WITH WRY SMILE","unified":"1F63C","non_qualified":null,"docomo":"E753","au":"EB6A","softbank":null,"google":"FE34F","image":"1f63c.png","sheet_x":33,"sheet_y":47,"short_name":"smirk_cat","short_names":["smirk_cat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"cat-face","sort_order":122,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KISSING CAT FACE WITH CLOSED EYES","unified":"1F63D","non_qualified":null,"docomo":"E726","au":"EB60","softbank":null,"google":"FE34B","image":"1f63d.png","sheet_x":33,"sheet_y":48,"short_name":"kissing_cat","short_names":["kissing_cat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"cat-face","sort_order":123,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POUTING CAT FACE","unified":"1F63E","non_qualified":null,"docomo":"E724","au":"EB5E","softbank":null,"google":"FE34E","image":"1f63e.png","sheet_x":33,"sheet_y":49,"short_name":"pouting_cat","short_names":["pouting_cat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"cat-face","sort_order":126,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CRYING CAT FACE","unified":"1F63F","non_qualified":null,"docomo":"E72E","au":"EB68","softbank":null,"google":"FE34D","image":"1f63f.png","sheet_x":33,"sheet_y":50,"short_name":"crying_cat_face","short_names":["crying_cat_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"cat-face","sort_order":125,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WEARY CAT FACE","unified":"1F640","non_qualified":null,"docomo":"E6F3","au":"EB66","softbank":null,"google":"FE350","image":"1f640.png","sheet_x":33,"sheet_y":51,"short_name":"scream_cat","short_names":["scream_cat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"cat-face","sort_order":124,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SLIGHTLY FROWNING FACE","unified":"1F641","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f641.png","sheet_x":33,"sheet_y":52,"short_name":"slightly_frowning_face","short_names":["slightly_frowning_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":79,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAD SHAKING HORIZONTALLY","unified":"1F642-200D-2194-FE0F","non_qualified":"1F642-200D-2194","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f642-200d-2194-fe0f.png","sheet_x":33,"sheet_y":53,"short_name":"head_shaking_horizontally","short_names":["head_shaking_horizontally"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":51,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"HEAD SHAKING VERTICALLY","unified":"1F642-200D-2195-FE0F","non_qualified":"1F642-200D-2195","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f642-200d-2195-fe0f.png","sheet_x":33,"sheet_y":54,"short_name":"head_shaking_vertically","short_names":["head_shaking_vertically"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":52,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"SLIGHTLY SMILING FACE","unified":"1F642","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f642.png","sheet_x":33,"sheet_y":55,"short_name":"slightly_smiling_face","short_names":["slightly_smiling_face"],"text":null,"texts":[":)","(:",":-)"],"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":9,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UPSIDE-DOWN FACE","unified":"1F643","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f643.png","sheet_x":33,"sheet_y":56,"short_name":"upside_down_face","short_names":["upside_down_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":10,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH ROLLING EYES","unified":"1F644","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f644.png","sheet_x":33,"sheet_y":57,"short_name":"face_with_rolling_eyes","short_names":["face_with_rolling_eyes"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN GESTURING NO","unified":"1F645-200D-2640-FE0F","non_qualified":"1F645-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f645-200d-2640-fe0f.png","sheet_x":33,"sheet_y":58,"short_name":"woman-gesturing-no","short_names":["woman-gesturing-no"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":266,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F645-1F3FB-200D-2640-FE0F","non_qualified":"1F645-1F3FB-200D-2640","image":"1f645-1f3fb-200d-2640-fe0f.png","sheet_x":33,"sheet_y":59,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F645-1F3FC-200D-2640-FE0F","non_qualified":"1F645-1F3FC-200D-2640","image":"1f645-1f3fc-200d-2640-fe0f.png","sheet_x":33,"sheet_y":60,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F645-1F3FD-200D-2640-FE0F","non_qualified":"1F645-1F3FD-200D-2640","image":"1f645-1f3fd-200d-2640-fe0f.png","sheet_x":33,"sheet_y":61,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F645-1F3FE-200D-2640-FE0F","non_qualified":"1F645-1F3FE-200D-2640","image":"1f645-1f3fe-200d-2640-fe0f.png","sheet_x":34,"sheet_y":0,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F645-1F3FF-200D-2640-FE0F","non_qualified":"1F645-1F3FF-200D-2640","image":"1f645-1f3ff-200d-2640-fe0f.png","sheet_x":34,"sheet_y":1,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F645"},{"name":"MAN GESTURING NO","unified":"1F645-200D-2642-FE0F","non_qualified":"1F645-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f645-200d-2642-fe0f.png","sheet_x":34,"sheet_y":2,"short_name":"man-gesturing-no","short_names":["man-gesturing-no"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":265,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F645-1F3FB-200D-2642-FE0F","non_qualified":"1F645-1F3FB-200D-2642","image":"1f645-1f3fb-200d-2642-fe0f.png","sheet_x":34,"sheet_y":3,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F645-1F3FC-200D-2642-FE0F","non_qualified":"1F645-1F3FC-200D-2642","image":"1f645-1f3fc-200d-2642-fe0f.png","sheet_x":34,"sheet_y":4,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F645-1F3FD-200D-2642-FE0F","non_qualified":"1F645-1F3FD-200D-2642","image":"1f645-1f3fd-200d-2642-fe0f.png","sheet_x":34,"sheet_y":5,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F645-1F3FE-200D-2642-FE0F","non_qualified":"1F645-1F3FE-200D-2642","image":"1f645-1f3fe-200d-2642-fe0f.png","sheet_x":34,"sheet_y":6,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F645-1F3FF-200D-2642-FE0F","non_qualified":"1F645-1F3FF-200D-2642","image":"1f645-1f3ff-200d-2642-fe0f.png","sheet_x":34,"sheet_y":7,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FACE WITH NO GOOD GESTURE","unified":"1F645","non_qualified":null,"docomo":"E72F","au":"EAD7","softbank":"E423","google":"FE351","image":"1f645.png","sheet_x":34,"sheet_y":8,"short_name":"no_good","short_names":["no_good"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":264,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F645-1F3FB","non_qualified":null,"image":"1f645-1f3fb.png","sheet_x":34,"sheet_y":9,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F645-1F3FC","non_qualified":null,"image":"1f645-1f3fc.png","sheet_x":34,"sheet_y":10,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F645-1F3FD","non_qualified":null,"image":"1f645-1f3fd.png","sheet_x":34,"sheet_y":11,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F645-1F3FE","non_qualified":null,"image":"1f645-1f3fe.png","sheet_x":34,"sheet_y":12,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F645-1F3FF","non_qualified":null,"image":"1f645-1f3ff.png","sheet_x":34,"sheet_y":13,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F645-200D-2640-FE0F"},{"name":"WOMAN GESTURING OK","unified":"1F646-200D-2640-FE0F","non_qualified":"1F646-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f646-200d-2640-fe0f.png","sheet_x":34,"sheet_y":14,"short_name":"woman-gesturing-ok","short_names":["woman-gesturing-ok"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":269,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F646-1F3FB-200D-2640-FE0F","non_qualified":"1F646-1F3FB-200D-2640","image":"1f646-1f3fb-200d-2640-fe0f.png","sheet_x":34,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F646-1F3FC-200D-2640-FE0F","non_qualified":"1F646-1F3FC-200D-2640","image":"1f646-1f3fc-200d-2640-fe0f.png","sheet_x":34,"sheet_y":16,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F646-1F3FD-200D-2640-FE0F","non_qualified":"1F646-1F3FD-200D-2640","image":"1f646-1f3fd-200d-2640-fe0f.png","sheet_x":34,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F646-1F3FE-200D-2640-FE0F","non_qualified":"1F646-1F3FE-200D-2640","image":"1f646-1f3fe-200d-2640-fe0f.png","sheet_x":34,"sheet_y":18,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F646-1F3FF-200D-2640-FE0F","non_qualified":"1F646-1F3FF-200D-2640","image":"1f646-1f3ff-200d-2640-fe0f.png","sheet_x":34,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F646"},{"name":"MAN GESTURING OK","unified":"1F646-200D-2642-FE0F","non_qualified":"1F646-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f646-200d-2642-fe0f.png","sheet_x":34,"sheet_y":20,"short_name":"man-gesturing-ok","short_names":["man-gesturing-ok"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":268,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F646-1F3FB-200D-2642-FE0F","non_qualified":"1F646-1F3FB-200D-2642","image":"1f646-1f3fb-200d-2642-fe0f.png","sheet_x":34,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F646-1F3FC-200D-2642-FE0F","non_qualified":"1F646-1F3FC-200D-2642","image":"1f646-1f3fc-200d-2642-fe0f.png","sheet_x":34,"sheet_y":22,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F646-1F3FD-200D-2642-FE0F","non_qualified":"1F646-1F3FD-200D-2642","image":"1f646-1f3fd-200d-2642-fe0f.png","sheet_x":34,"sheet_y":23,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F646-1F3FE-200D-2642-FE0F","non_qualified":"1F646-1F3FE-200D-2642","image":"1f646-1f3fe-200d-2642-fe0f.png","sheet_x":34,"sheet_y":24,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F646-1F3FF-200D-2642-FE0F","non_qualified":"1F646-1F3FF-200D-2642","image":"1f646-1f3ff-200d-2642-fe0f.png","sheet_x":34,"sheet_y":25,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FACE WITH OK GESTURE","unified":"1F646","non_qualified":null,"docomo":"E70B","au":"EAD8","softbank":"E424","google":"FE352","image":"1f646.png","sheet_x":34,"sheet_y":26,"short_name":"ok_woman","short_names":["ok_woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":267,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F646-1F3FB","non_qualified":null,"image":"1f646-1f3fb.png","sheet_x":34,"sheet_y":27,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F646-1F3FC","non_qualified":null,"image":"1f646-1f3fc.png","sheet_x":34,"sheet_y":28,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F646-1F3FD","non_qualified":null,"image":"1f646-1f3fd.png","sheet_x":34,"sheet_y":29,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F646-1F3FE","non_qualified":null,"image":"1f646-1f3fe.png","sheet_x":34,"sheet_y":30,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F646-1F3FF","non_qualified":null,"image":"1f646-1f3ff.png","sheet_x":34,"sheet_y":31,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F646-200D-2640-FE0F"},{"name":"WOMAN BOWING","unified":"1F647-200D-2640-FE0F","non_qualified":"1F647-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f647-200d-2640-fe0f.png","sheet_x":34,"sheet_y":32,"short_name":"woman-bowing","short_names":["woman-bowing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":281,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F647-1F3FB-200D-2640-FE0F","non_qualified":"1F647-1F3FB-200D-2640","image":"1f647-1f3fb-200d-2640-fe0f.png","sheet_x":34,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F647-1F3FC-200D-2640-FE0F","non_qualified":"1F647-1F3FC-200D-2640","image":"1f647-1f3fc-200d-2640-fe0f.png","sheet_x":34,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F647-1F3FD-200D-2640-FE0F","non_qualified":"1F647-1F3FD-200D-2640","image":"1f647-1f3fd-200d-2640-fe0f.png","sheet_x":34,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F647-1F3FE-200D-2640-FE0F","non_qualified":"1F647-1F3FE-200D-2640","image":"1f647-1f3fe-200d-2640-fe0f.png","sheet_x":34,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F647-1F3FF-200D-2640-FE0F","non_qualified":"1F647-1F3FF-200D-2640","image":"1f647-1f3ff-200d-2640-fe0f.png","sheet_x":34,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN BOWING","unified":"1F647-200D-2642-FE0F","non_qualified":"1F647-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f647-200d-2642-fe0f.png","sheet_x":34,"sheet_y":38,"short_name":"man-bowing","short_names":["man-bowing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":280,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F647-1F3FB-200D-2642-FE0F","non_qualified":"1F647-1F3FB-200D-2642","image":"1f647-1f3fb-200d-2642-fe0f.png","sheet_x":34,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F647-1F3FC-200D-2642-FE0F","non_qualified":"1F647-1F3FC-200D-2642","image":"1f647-1f3fc-200d-2642-fe0f.png","sheet_x":34,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F647-1F3FD-200D-2642-FE0F","non_qualified":"1F647-1F3FD-200D-2642","image":"1f647-1f3fd-200d-2642-fe0f.png","sheet_x":34,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F647-1F3FE-200D-2642-FE0F","non_qualified":"1F647-1F3FE-200D-2642","image":"1f647-1f3fe-200d-2642-fe0f.png","sheet_x":34,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F647-1F3FF-200D-2642-FE0F","non_qualified":"1F647-1F3FF-200D-2642","image":"1f647-1f3ff-200d-2642-fe0f.png","sheet_x":34,"sheet_y":43,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON BOWING DEEPLY","unified":"1F647","non_qualified":null,"docomo":null,"au":"EAD9","softbank":"E426","google":"FE353","image":"1f647.png","sheet_x":34,"sheet_y":44,"short_name":"bow","short_names":["bow"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":279,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F647-1F3FB","non_qualified":null,"image":"1f647-1f3fb.png","sheet_x":34,"sheet_y":45,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F647-1F3FC","non_qualified":null,"image":"1f647-1f3fc.png","sheet_x":34,"sheet_y":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F647-1F3FD","non_qualified":null,"image":"1f647-1f3fd.png","sheet_x":34,"sheet_y":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F647-1F3FE","non_qualified":null,"image":"1f647-1f3fe.png","sheet_x":34,"sheet_y":48,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F647-1F3FF","non_qualified":null,"image":"1f647-1f3ff.png","sheet_x":34,"sheet_y":49,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SEE-NO-EVIL MONKEY","unified":"1F648","non_qualified":null,"docomo":null,"au":"EB50","softbank":null,"google":"FE354","image":"1f648.png","sheet_x":34,"sheet_y":50,"short_name":"see_no_evil","short_names":["see_no_evil"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"monkey-face","sort_order":127,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAR-NO-EVIL MONKEY","unified":"1F649","non_qualified":null,"docomo":null,"au":"EB52","softbank":null,"google":"FE356","image":"1f649.png","sheet_x":34,"sheet_y":51,"short_name":"hear_no_evil","short_names":["hear_no_evil"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"monkey-face","sort_order":128,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPEAK-NO-EVIL MONKEY","unified":"1F64A","non_qualified":null,"docomo":null,"au":"EB51","softbank":null,"google":"FE355","image":"1f64a.png","sheet_x":34,"sheet_y":52,"short_name":"speak_no_evil","short_names":["speak_no_evil"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"monkey-face","sort_order":129,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN RAISING HAND","unified":"1F64B-200D-2640-FE0F","non_qualified":"1F64B-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f64b-200d-2640-fe0f.png","sheet_x":34,"sheet_y":53,"short_name":"woman-raising-hand","short_names":["woman-raising-hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":275,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64B-1F3FB-200D-2640-FE0F","non_qualified":"1F64B-1F3FB-200D-2640","image":"1f64b-1f3fb-200d-2640-fe0f.png","sheet_x":34,"sheet_y":54,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64B-1F3FC-200D-2640-FE0F","non_qualified":"1F64B-1F3FC-200D-2640","image":"1f64b-1f3fc-200d-2640-fe0f.png","sheet_x":34,"sheet_y":55,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64B-1F3FD-200D-2640-FE0F","non_qualified":"1F64B-1F3FD-200D-2640","image":"1f64b-1f3fd-200d-2640-fe0f.png","sheet_x":34,"sheet_y":56,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64B-1F3FE-200D-2640-FE0F","non_qualified":"1F64B-1F3FE-200D-2640","image":"1f64b-1f3fe-200d-2640-fe0f.png","sheet_x":34,"sheet_y":57,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64B-1F3FF-200D-2640-FE0F","non_qualified":"1F64B-1F3FF-200D-2640","image":"1f64b-1f3ff-200d-2640-fe0f.png","sheet_x":34,"sheet_y":58,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F64B"},{"name":"MAN RAISING HAND","unified":"1F64B-200D-2642-FE0F","non_qualified":"1F64B-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f64b-200d-2642-fe0f.png","sheet_x":34,"sheet_y":59,"short_name":"man-raising-hand","short_names":["man-raising-hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":274,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64B-1F3FB-200D-2642-FE0F","non_qualified":"1F64B-1F3FB-200D-2642","image":"1f64b-1f3fb-200d-2642-fe0f.png","sheet_x":34,"sheet_y":60,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64B-1F3FC-200D-2642-FE0F","non_qualified":"1F64B-1F3FC-200D-2642","image":"1f64b-1f3fc-200d-2642-fe0f.png","sheet_x":34,"sheet_y":61,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64B-1F3FD-200D-2642-FE0F","non_qualified":"1F64B-1F3FD-200D-2642","image":"1f64b-1f3fd-200d-2642-fe0f.png","sheet_x":35,"sheet_y":0,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64B-1F3FE-200D-2642-FE0F","non_qualified":"1F64B-1F3FE-200D-2642","image":"1f64b-1f3fe-200d-2642-fe0f.png","sheet_x":35,"sheet_y":1,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64B-1F3FF-200D-2642-FE0F","non_qualified":"1F64B-1F3FF-200D-2642","image":"1f64b-1f3ff-200d-2642-fe0f.png","sheet_x":35,"sheet_y":2,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"HAPPY PERSON RAISING ONE HAND","unified":"1F64B","non_qualified":null,"docomo":null,"au":"EB85","softbank":null,"google":"FE357","image":"1f64b.png","sheet_x":35,"sheet_y":3,"short_name":"raising_hand","short_names":["raising_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":273,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64B-1F3FB","non_qualified":null,"image":"1f64b-1f3fb.png","sheet_x":35,"sheet_y":4,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64B-1F3FC","non_qualified":null,"image":"1f64b-1f3fc.png","sheet_x":35,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64B-1F3FD","non_qualified":null,"image":"1f64b-1f3fd.png","sheet_x":35,"sheet_y":6,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64B-1F3FE","non_qualified":null,"image":"1f64b-1f3fe.png","sheet_x":35,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64B-1F3FF","non_qualified":null,"image":"1f64b-1f3ff.png","sheet_x":35,"sheet_y":8,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F64B-200D-2640-FE0F"},{"name":"PERSON RAISING BOTH HANDS IN CELEBRATION","unified":"1F64C","non_qualified":null,"docomo":null,"au":"EB86","softbank":"E427","google":"FE358","image":"1f64c.png","sheet_x":35,"sheet_y":9,"short_name":"raised_hands","short_names":["raised_hands"],"text":null,"texts":null,"category":"People & Body","subcategory":"hands","sort_order":203,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64C-1F3FB","non_qualified":null,"image":"1f64c-1f3fb.png","sheet_x":35,"sheet_y":10,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64C-1F3FC","non_qualified":null,"image":"1f64c-1f3fc.png","sheet_x":35,"sheet_y":11,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64C-1F3FD","non_qualified":null,"image":"1f64c-1f3fd.png","sheet_x":35,"sheet_y":12,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64C-1F3FE","non_qualified":null,"image":"1f64c-1f3fe.png","sheet_x":35,"sheet_y":13,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64C-1F3FF","non_qualified":null,"image":"1f64c-1f3ff.png","sheet_x":35,"sheet_y":14,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN FROWNING","unified":"1F64D-200D-2640-FE0F","non_qualified":"1F64D-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f64d-200d-2640-fe0f.png","sheet_x":35,"sheet_y":15,"short_name":"woman-frowning","short_names":["woman-frowning"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":260,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64D-1F3FB-200D-2640-FE0F","non_qualified":"1F64D-1F3FB-200D-2640","image":"1f64d-1f3fb-200d-2640-fe0f.png","sheet_x":35,"sheet_y":16,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64D-1F3FC-200D-2640-FE0F","non_qualified":"1F64D-1F3FC-200D-2640","image":"1f64d-1f3fc-200d-2640-fe0f.png","sheet_x":35,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64D-1F3FD-200D-2640-FE0F","non_qualified":"1F64D-1F3FD-200D-2640","image":"1f64d-1f3fd-200d-2640-fe0f.png","sheet_x":35,"sheet_y":18,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64D-1F3FE-200D-2640-FE0F","non_qualified":"1F64D-1F3FE-200D-2640","image":"1f64d-1f3fe-200d-2640-fe0f.png","sheet_x":35,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64D-1F3FF-200D-2640-FE0F","non_qualified":"1F64D-1F3FF-200D-2640","image":"1f64d-1f3ff-200d-2640-fe0f.png","sheet_x":35,"sheet_y":20,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F64D"},{"name":"MAN FROWNING","unified":"1F64D-200D-2642-FE0F","non_qualified":"1F64D-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f64d-200d-2642-fe0f.png","sheet_x":35,"sheet_y":21,"short_name":"man-frowning","short_names":["man-frowning"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":259,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64D-1F3FB-200D-2642-FE0F","non_qualified":"1F64D-1F3FB-200D-2642","image":"1f64d-1f3fb-200d-2642-fe0f.png","sheet_x":35,"sheet_y":22,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64D-1F3FC-200D-2642-FE0F","non_qualified":"1F64D-1F3FC-200D-2642","image":"1f64d-1f3fc-200d-2642-fe0f.png","sheet_x":35,"sheet_y":23,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64D-1F3FD-200D-2642-FE0F","non_qualified":"1F64D-1F3FD-200D-2642","image":"1f64d-1f3fd-200d-2642-fe0f.png","sheet_x":35,"sheet_y":24,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64D-1F3FE-200D-2642-FE0F","non_qualified":"1F64D-1F3FE-200D-2642","image":"1f64d-1f3fe-200d-2642-fe0f.png","sheet_x":35,"sheet_y":25,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64D-1F3FF-200D-2642-FE0F","non_qualified":"1F64D-1F3FF-200D-2642","image":"1f64d-1f3ff-200d-2642-fe0f.png","sheet_x":35,"sheet_y":26,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON FROWNING","unified":"1F64D","non_qualified":null,"docomo":"E6F3","au":"EB87","softbank":null,"google":"FE359","image":"1f64d.png","sheet_x":35,"sheet_y":27,"short_name":"person_frowning","short_names":["person_frowning"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":258,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64D-1F3FB","non_qualified":null,"image":"1f64d-1f3fb.png","sheet_x":35,"sheet_y":28,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64D-1F3FC","non_qualified":null,"image":"1f64d-1f3fc.png","sheet_x":35,"sheet_y":29,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64D-1F3FD","non_qualified":null,"image":"1f64d-1f3fd.png","sheet_x":35,"sheet_y":30,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64D-1F3FE","non_qualified":null,"image":"1f64d-1f3fe.png","sheet_x":35,"sheet_y":31,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64D-1F3FF","non_qualified":null,"image":"1f64d-1f3ff.png","sheet_x":35,"sheet_y":32,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F64D-200D-2640-FE0F"},{"name":"WOMAN POUTING","unified":"1F64E-200D-2640-FE0F","non_qualified":"1F64E-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f64e-200d-2640-fe0f.png","sheet_x":35,"sheet_y":33,"short_name":"woman-pouting","short_names":["woman-pouting"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":263,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64E-1F3FB-200D-2640-FE0F","non_qualified":"1F64E-1F3FB-200D-2640","image":"1f64e-1f3fb-200d-2640-fe0f.png","sheet_x":35,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64E-1F3FC-200D-2640-FE0F","non_qualified":"1F64E-1F3FC-200D-2640","image":"1f64e-1f3fc-200d-2640-fe0f.png","sheet_x":35,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64E-1F3FD-200D-2640-FE0F","non_qualified":"1F64E-1F3FD-200D-2640","image":"1f64e-1f3fd-200d-2640-fe0f.png","sheet_x":35,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64E-1F3FE-200D-2640-FE0F","non_qualified":"1F64E-1F3FE-200D-2640","image":"1f64e-1f3fe-200d-2640-fe0f.png","sheet_x":35,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64E-1F3FF-200D-2640-FE0F","non_qualified":"1F64E-1F3FF-200D-2640","image":"1f64e-1f3ff-200d-2640-fe0f.png","sheet_x":35,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F64E"},{"name":"MAN POUTING","unified":"1F64E-200D-2642-FE0F","non_qualified":"1F64E-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f64e-200d-2642-fe0f.png","sheet_x":35,"sheet_y":39,"short_name":"man-pouting","short_names":["man-pouting"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":262,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64E-1F3FB-200D-2642-FE0F","non_qualified":"1F64E-1F3FB-200D-2642","image":"1f64e-1f3fb-200d-2642-fe0f.png","sheet_x":35,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64E-1F3FC-200D-2642-FE0F","non_qualified":"1F64E-1F3FC-200D-2642","image":"1f64e-1f3fc-200d-2642-fe0f.png","sheet_x":35,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64E-1F3FD-200D-2642-FE0F","non_qualified":"1F64E-1F3FD-200D-2642","image":"1f64e-1f3fd-200d-2642-fe0f.png","sheet_x":35,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64E-1F3FE-200D-2642-FE0F","non_qualified":"1F64E-1F3FE-200D-2642","image":"1f64e-1f3fe-200d-2642-fe0f.png","sheet_x":35,"sheet_y":43,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64E-1F3FF-200D-2642-FE0F","non_qualified":"1F64E-1F3FF-200D-2642","image":"1f64e-1f3ff-200d-2642-fe0f.png","sheet_x":35,"sheet_y":44,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON WITH POUTING FACE","unified":"1F64E","non_qualified":null,"docomo":"E6F1","au":"EB88","softbank":null,"google":"FE35A","image":"1f64e.png","sheet_x":35,"sheet_y":45,"short_name":"person_with_pouting_face","short_names":["person_with_pouting_face"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":261,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64E-1F3FB","non_qualified":null,"image":"1f64e-1f3fb.png","sheet_x":35,"sheet_y":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64E-1F3FC","non_qualified":null,"image":"1f64e-1f3fc.png","sheet_x":35,"sheet_y":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64E-1F3FD","non_qualified":null,"image":"1f64e-1f3fd.png","sheet_x":35,"sheet_y":48,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64E-1F3FE","non_qualified":null,"image":"1f64e-1f3fe.png","sheet_x":35,"sheet_y":49,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64E-1F3FF","non_qualified":null,"image":"1f64e-1f3ff.png","sheet_x":35,"sheet_y":50,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F64E-200D-2640-FE0F"},{"name":"PERSON WITH FOLDED HANDS","unified":"1F64F","non_qualified":null,"docomo":null,"au":"EAD2","softbank":"E41D","google":"FE35B","image":"1f64f.png","sheet_x":35,"sheet_y":51,"short_name":"pray","short_names":["pray"],"text":null,"texts":null,"category":"People & Body","subcategory":"hands","sort_order":208,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F64F-1F3FB","non_qualified":null,"image":"1f64f-1f3fb.png","sheet_x":35,"sheet_y":52,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F64F-1F3FC","non_qualified":null,"image":"1f64f-1f3fc.png","sheet_x":35,"sheet_y":53,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F64F-1F3FD","non_qualified":null,"image":"1f64f-1f3fd.png","sheet_x":35,"sheet_y":54,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F64F-1F3FE","non_qualified":null,"image":"1f64f-1f3fe.png","sheet_x":35,"sheet_y":55,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F64F-1F3FF","non_qualified":null,"image":"1f64f-1f3ff.png","sheet_x":35,"sheet_y":56,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"ROCKET","unified":"1F680","non_qualified":null,"docomo":null,"au":"E5C8","softbank":"E10D","google":"FE7ED","image":"1f680.png","sheet_x":35,"sheet_y":57,"short_name":"rocket","short_names":["rocket"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":983,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HELICOPTER","unified":"1F681","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f681.png","sheet_x":35,"sheet_y":58,"short_name":"helicopter","short_names":["helicopter"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":978,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STEAM LOCOMOTIVE","unified":"1F682","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f682.png","sheet_x":35,"sheet_y":59,"short_name":"steam_locomotive","short_names":["steam_locomotive"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":913,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RAILWAY CAR","unified":"1F683","non_qualified":null,"docomo":"E65B","au":"E4B5","softbank":"E01E","google":"FE7DF","image":"1f683.png","sheet_x":35,"sheet_y":60,"short_name":"railway_car","short_names":["railway_car"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":914,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HIGH-SPEED TRAIN","unified":"1F684","non_qualified":null,"docomo":"E65D","au":"E4B0","softbank":"E435","google":"FE7E2","image":"1f684.png","sheet_x":35,"sheet_y":61,"short_name":"bullettrain_side","short_names":["bullettrain_side"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":915,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HIGH-SPEED TRAIN WITH BULLET NOSE","unified":"1F685","non_qualified":null,"docomo":"E65D","au":"E4B0","softbank":"E01F","google":"FE7E3","image":"1f685.png","sheet_x":36,"sheet_y":0,"short_name":"bullettrain_front","short_names":["bullettrain_front"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":916,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRAIN","unified":"1F686","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f686.png","sheet_x":36,"sheet_y":1,"short_name":"train2","short_names":["train2"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":917,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"METRO","unified":"1F687","non_qualified":null,"docomo":"E65C","au":"E5BC","softbank":"E434","google":"FE7E0","image":"1f687.png","sheet_x":36,"sheet_y":2,"short_name":"metro","short_names":["metro"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":918,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LIGHT RAIL","unified":"1F688","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f688.png","sheet_x":36,"sheet_y":3,"short_name":"light_rail","short_names":["light_rail"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":919,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STATION","unified":"1F689","non_qualified":null,"docomo":null,"au":"EB6D","softbank":"E039","google":"FE7EC","image":"1f689.png","sheet_x":36,"sheet_y":4,"short_name":"station","short_names":["station"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":920,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRAM","unified":"1F68A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f68a.png","sheet_x":36,"sheet_y":5,"short_name":"tram","short_names":["tram"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":921,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRAM CAR","unified":"1F68B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f68b.png","sheet_x":36,"sheet_y":6,"short_name":"train","short_names":["train"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":924,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUS","unified":"1F68C","non_qualified":null,"docomo":"E660","au":"E4AF","softbank":"E159","google":"FE7E6","image":"1f68c.png","sheet_x":36,"sheet_y":7,"short_name":"bus","short_names":["bus"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":925,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ONCOMING BUS","unified":"1F68D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f68d.png","sheet_x":36,"sheet_y":8,"short_name":"oncoming_bus","short_names":["oncoming_bus"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":926,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TROLLEYBUS","unified":"1F68E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f68e.png","sheet_x":36,"sheet_y":9,"short_name":"trolleybus","short_names":["trolleybus"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":927,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUS STOP","unified":"1F68F","non_qualified":null,"docomo":null,"au":"E4A7","softbank":"E150","google":"FE7E7","image":"1f68f.png","sheet_x":36,"sheet_y":10,"short_name":"busstop","short_names":["busstop"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":952,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MINIBUS","unified":"1F690","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f690.png","sheet_x":36,"sheet_y":11,"short_name":"minibus","short_names":["minibus"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":928,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AMBULANCE","unified":"1F691","non_qualified":null,"docomo":null,"au":"EAE0","softbank":"E431","google":"FE7F3","image":"1f691.png","sheet_x":36,"sheet_y":12,"short_name":"ambulance","short_names":["ambulance"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":929,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FIRE ENGINE","unified":"1F692","non_qualified":null,"docomo":null,"au":"EADF","softbank":"E430","google":"FE7F2","image":"1f692.png","sheet_x":36,"sheet_y":13,"short_name":"fire_engine","short_names":["fire_engine"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":930,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POLICE CAR","unified":"1F693","non_qualified":null,"docomo":null,"au":"EAE1","softbank":"E432","google":"FE7F4","image":"1f693.png","sheet_x":36,"sheet_y":14,"short_name":"police_car","short_names":["police_car"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":931,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ONCOMING POLICE CAR","unified":"1F694","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f694.png","sheet_x":36,"sheet_y":15,"short_name":"oncoming_police_car","short_names":["oncoming_police_car"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":932,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TAXI","unified":"1F695","non_qualified":null,"docomo":"E65E","au":"E4B1","softbank":"E15A","google":"FE7EF","image":"1f695.png","sheet_x":36,"sheet_y":16,"short_name":"taxi","short_names":["taxi"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":933,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ONCOMING TAXI","unified":"1F696","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f696.png","sheet_x":36,"sheet_y":17,"short_name":"oncoming_taxi","short_names":["oncoming_taxi"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":934,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AUTOMOBILE","unified":"1F697","non_qualified":null,"docomo":"E65E","au":"E4B1","softbank":"E01B","google":"FE7E4","image":"1f697.png","sheet_x":36,"sheet_y":18,"short_name":"car","short_names":["car","red_car"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":935,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ONCOMING AUTOMOBILE","unified":"1F698","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f698.png","sheet_x":36,"sheet_y":19,"short_name":"oncoming_automobile","short_names":["oncoming_automobile"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":936,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RECREATIONAL VEHICLE","unified":"1F699","non_qualified":null,"docomo":"E65F","au":"E4B1","softbank":"E42E","google":"FE7E5","image":"1f699.png","sheet_x":36,"sheet_y":20,"short_name":"blue_car","short_names":["blue_car"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":937,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DELIVERY TRUCK","unified":"1F69A","non_qualified":null,"docomo":null,"au":"E4B2","softbank":"E42F","google":"FE7F1","image":"1f69a.png","sheet_x":36,"sheet_y":21,"short_name":"truck","short_names":["truck"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":939,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ARTICULATED LORRY","unified":"1F69B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f69b.png","sheet_x":36,"sheet_y":22,"short_name":"articulated_lorry","short_names":["articulated_lorry"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":940,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRACTOR","unified":"1F69C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f69c.png","sheet_x":36,"sheet_y":23,"short_name":"tractor","short_names":["tractor"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":941,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MONORAIL","unified":"1F69D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f69d.png","sheet_x":36,"sheet_y":24,"short_name":"monorail","short_names":["monorail"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":922,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOUNTAIN RAILWAY","unified":"1F69E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f69e.png","sheet_x":36,"sheet_y":25,"short_name":"mountain_railway","short_names":["mountain_railway"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":923,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUSPENSION RAILWAY","unified":"1F69F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f69f.png","sheet_x":36,"sheet_y":26,"short_name":"suspension_railway","short_names":["suspension_railway"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":979,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOUNTAIN CABLEWAY","unified":"1F6A0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6a0.png","sheet_x":36,"sheet_y":27,"short_name":"mountain_cableway","short_names":["mountain_cableway"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":980,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AERIAL TRAMWAY","unified":"1F6A1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6a1.png","sheet_x":36,"sheet_y":28,"short_name":"aerial_tramway","short_names":["aerial_tramway"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":981,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHIP","unified":"1F6A2","non_qualified":null,"docomo":"E661","au":"EA82","softbank":"E202","google":"FE7E8","image":"1f6a2.png","sheet_x":36,"sheet_y":29,"short_name":"ship","short_names":["ship"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-water","sort_order":971,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN ROWING BOAT","unified":"1F6A3-200D-2640-FE0F","non_qualified":"1F6A3-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6a3-200d-2640-fe0f.png","sheet_x":36,"sheet_y":30,"short_name":"woman-rowing-boat","short_names":["woman-rowing-boat"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":471,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6A3-1F3FB-200D-2640-FE0F","non_qualified":"1F6A3-1F3FB-200D-2640","image":"1f6a3-1f3fb-200d-2640-fe0f.png","sheet_x":36,"sheet_y":31,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6A3-1F3FC-200D-2640-FE0F","non_qualified":"1F6A3-1F3FC-200D-2640","image":"1f6a3-1f3fc-200d-2640-fe0f.png","sheet_x":36,"sheet_y":32,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6A3-1F3FD-200D-2640-FE0F","non_qualified":"1F6A3-1F3FD-200D-2640","image":"1f6a3-1f3fd-200d-2640-fe0f.png","sheet_x":36,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6A3-1F3FE-200D-2640-FE0F","non_qualified":"1F6A3-1F3FE-200D-2640","image":"1f6a3-1f3fe-200d-2640-fe0f.png","sheet_x":36,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6A3-1F3FF-200D-2640-FE0F","non_qualified":"1F6A3-1F3FF-200D-2640","image":"1f6a3-1f3ff-200d-2640-fe0f.png","sheet_x":36,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN ROWING BOAT","unified":"1F6A3-200D-2642-FE0F","non_qualified":"1F6A3-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6a3-200d-2642-fe0f.png","sheet_x":36,"sheet_y":36,"short_name":"man-rowing-boat","short_names":["man-rowing-boat"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":470,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6A3-1F3FB-200D-2642-FE0F","non_qualified":"1F6A3-1F3FB-200D-2642","image":"1f6a3-1f3fb-200d-2642-fe0f.png","sheet_x":36,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6A3-1F3FC-200D-2642-FE0F","non_qualified":"1F6A3-1F3FC-200D-2642","image":"1f6a3-1f3fc-200d-2642-fe0f.png","sheet_x":36,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6A3-1F3FD-200D-2642-FE0F","non_qualified":"1F6A3-1F3FD-200D-2642","image":"1f6a3-1f3fd-200d-2642-fe0f.png","sheet_x":36,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6A3-1F3FE-200D-2642-FE0F","non_qualified":"1F6A3-1F3FE-200D-2642","image":"1f6a3-1f3fe-200d-2642-fe0f.png","sheet_x":36,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6A3-1F3FF-200D-2642-FE0F","non_qualified":"1F6A3-1F3FF-200D-2642","image":"1f6a3-1f3ff-200d-2642-fe0f.png","sheet_x":36,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F6A3"},{"name":"ROWBOAT","unified":"1F6A3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6a3.png","sheet_x":36,"sheet_y":42,"short_name":"rowboat","short_names":["rowboat"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":469,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6A3-1F3FB","non_qualified":null,"image":"1f6a3-1f3fb.png","sheet_x":36,"sheet_y":43,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6A3-1F3FC","non_qualified":null,"image":"1f6a3-1f3fc.png","sheet_x":36,"sheet_y":44,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6A3-1F3FD","non_qualified":null,"image":"1f6a3-1f3fd.png","sheet_x":36,"sheet_y":45,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6A3-1F3FE","non_qualified":null,"image":"1f6a3-1f3fe.png","sheet_x":36,"sheet_y":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6A3-1F3FF","non_qualified":null,"image":"1f6a3-1f3ff.png","sheet_x":36,"sheet_y":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F6A3-200D-2642-FE0F"},{"name":"SPEEDBOAT","unified":"1F6A4","non_qualified":null,"docomo":"E6A3","au":"E4B4","softbank":"E135","google":"FE7EE","image":"1f6a4.png","sheet_x":36,"sheet_y":48,"short_name":"speedboat","short_names":["speedboat"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-water","sort_order":967,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HORIZONTAL TRAFFIC LIGHT","unified":"1F6A5","non_qualified":null,"docomo":"E66D","au":"E46A","softbank":"E14E","google":"FE7F7","image":"1f6a5.png","sheet_x":36,"sheet_y":49,"short_name":"traffic_light","short_names":["traffic_light"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":959,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"VERTICAL TRAFFIC LIGHT","unified":"1F6A6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6a6.png","sheet_x":36,"sheet_y":50,"short_name":"vertical_traffic_light","short_names":["vertical_traffic_light"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":960,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CONSTRUCTION SIGN","unified":"1F6A7","non_qualified":null,"docomo":null,"au":"E5D7","softbank":"E137","google":"FE7F8","image":"1f6a7.png","sheet_x":36,"sheet_y":51,"short_name":"construction","short_names":["construction"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":962,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POLICE CARS REVOLVING LIGHT","unified":"1F6A8","non_qualified":null,"docomo":null,"au":"EB73","softbank":null,"google":"FE7F9","image":"1f6a8.png","sheet_x":36,"sheet_y":52,"short_name":"rotating_light","short_names":["rotating_light"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":958,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRIANGULAR FLAG ON POST","unified":"1F6A9","non_qualified":null,"docomo":"E6DE","au":"EB2C","softbank":null,"google":"FEB22","image":"1f6a9.png","sheet_x":36,"sheet_y":53,"short_name":"triangular_flag_on_post","short_names":["triangular_flag_on_post"],"text":null,"texts":null,"category":"Flags","subcategory":"flag","sort_order":1636,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOOR","unified":"1F6AA","non_qualified":null,"docomo":"E714","au":null,"softbank":null,"google":"FE4F3","image":"1f6aa.png","sheet_x":36,"sheet_y":54,"short_name":"door","short_names":["door"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1378,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NO ENTRY SIGN","unified":"1F6AB","non_qualified":null,"docomo":"E738","au":"E541","softbank":null,"google":"FEB48","image":"1f6ab.png","sheet_x":36,"sheet_y":55,"short_name":"no_entry_sign","short_names":["no_entry_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1428,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMOKING SYMBOL","unified":"1F6AC","non_qualified":null,"docomo":"E67F","au":"E47D","softbank":"E30E","google":"FEB1E","image":"1f6ac.png","sheet_x":36,"sheet_y":56,"short_name":"smoking","short_names":["smoking"],"text":null,"texts":null,"category":"Objects","subcategory":"other-object","sort_order":1403,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NO SMOKING SYMBOL","unified":"1F6AD","non_qualified":null,"docomo":"E680","au":"E47E","softbank":"E208","google":"FEB1F","image":"1f6ad.png","sheet_x":36,"sheet_y":57,"short_name":"no_smoking","short_names":["no_smoking"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1430,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PUT LITTER IN ITS PLACE SYMBOL","unified":"1F6AE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6ae.png","sheet_x":36,"sheet_y":58,"short_name":"put_litter_in_its_place","short_names":["put_litter_in_its_place"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1413,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DO NOT LITTER SYMBOL","unified":"1F6AF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6af.png","sheet_x":36,"sheet_y":59,"short_name":"do_not_litter","short_names":["do_not_litter"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1431,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POTABLE WATER SYMBOL","unified":"1F6B0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b0.png","sheet_x":36,"sheet_y":60,"short_name":"potable_water","short_names":["potable_water"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1414,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NON-POTABLE WATER SYMBOL","unified":"1F6B1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b1.png","sheet_x":36,"sheet_y":61,"short_name":"non-potable_water","short_names":["non-potable_water"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1432,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BICYCLE","unified":"1F6B2","non_qualified":null,"docomo":"E71D","au":"E4AE","softbank":"E136","google":"FE7EB","image":"1f6b2.png","sheet_x":37,"sheet_y":0,"short_name":"bike","short_names":["bike"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":948,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NO BICYCLES","unified":"1F6B3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b3.png","sheet_x":37,"sheet_y":1,"short_name":"no_bicycles","short_names":["no_bicycles"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1429,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN BIKING","unified":"1F6B4-200D-2640-FE0F","non_qualified":"1F6B4-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b4-200d-2640-fe0f.png","sheet_x":37,"sheet_y":2,"short_name":"woman-biking","short_names":["woman-biking"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":483,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6B4-1F3FB-200D-2640-FE0F","non_qualified":"1F6B4-1F3FB-200D-2640","image":"1f6b4-1f3fb-200d-2640-fe0f.png","sheet_x":37,"sheet_y":3,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6B4-1F3FC-200D-2640-FE0F","non_qualified":"1F6B4-1F3FC-200D-2640","image":"1f6b4-1f3fc-200d-2640-fe0f.png","sheet_x":37,"sheet_y":4,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6B4-1F3FD-200D-2640-FE0F","non_qualified":"1F6B4-1F3FD-200D-2640","image":"1f6b4-1f3fd-200d-2640-fe0f.png","sheet_x":37,"sheet_y":5,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6B4-1F3FE-200D-2640-FE0F","non_qualified":"1F6B4-1F3FE-200D-2640","image":"1f6b4-1f3fe-200d-2640-fe0f.png","sheet_x":37,"sheet_y":6,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6B4-1F3FF-200D-2640-FE0F","non_qualified":"1F6B4-1F3FF-200D-2640","image":"1f6b4-1f3ff-200d-2640-fe0f.png","sheet_x":37,"sheet_y":7,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN BIKING","unified":"1F6B4-200D-2642-FE0F","non_qualified":"1F6B4-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b4-200d-2642-fe0f.png","sheet_x":37,"sheet_y":8,"short_name":"man-biking","short_names":["man-biking"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":482,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6B4-1F3FB-200D-2642-FE0F","non_qualified":"1F6B4-1F3FB-200D-2642","image":"1f6b4-1f3fb-200d-2642-fe0f.png","sheet_x":37,"sheet_y":9,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6B4-1F3FC-200D-2642-FE0F","non_qualified":"1F6B4-1F3FC-200D-2642","image":"1f6b4-1f3fc-200d-2642-fe0f.png","sheet_x":37,"sheet_y":10,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6B4-1F3FD-200D-2642-FE0F","non_qualified":"1F6B4-1F3FD-200D-2642","image":"1f6b4-1f3fd-200d-2642-fe0f.png","sheet_x":37,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6B4-1F3FE-200D-2642-FE0F","non_qualified":"1F6B4-1F3FE-200D-2642","image":"1f6b4-1f3fe-200d-2642-fe0f.png","sheet_x":37,"sheet_y":12,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6B4-1F3FF-200D-2642-FE0F","non_qualified":"1F6B4-1F3FF-200D-2642","image":"1f6b4-1f3ff-200d-2642-fe0f.png","sheet_x":37,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F6B4"},{"name":"BICYCLIST","unified":"1F6B4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b4.png","sheet_x":37,"sheet_y":14,"short_name":"bicyclist","short_names":["bicyclist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":481,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6B4-1F3FB","non_qualified":null,"image":"1f6b4-1f3fb.png","sheet_x":37,"sheet_y":15,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6B4-1F3FC","non_qualified":null,"image":"1f6b4-1f3fc.png","sheet_x":37,"sheet_y":16,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6B4-1F3FD","non_qualified":null,"image":"1f6b4-1f3fd.png","sheet_x":37,"sheet_y":17,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6B4-1F3FE","non_qualified":null,"image":"1f6b4-1f3fe.png","sheet_x":37,"sheet_y":18,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6B4-1F3FF","non_qualified":null,"image":"1f6b4-1f3ff.png","sheet_x":37,"sheet_y":19,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F6B4-200D-2642-FE0F"},{"name":"WOMAN MOUNTAIN BIKING","unified":"1F6B5-200D-2640-FE0F","non_qualified":"1F6B5-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b5-200d-2640-fe0f.png","sheet_x":37,"sheet_y":20,"short_name":"woman-mountain-biking","short_names":["woman-mountain-biking"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":486,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6B5-1F3FB-200D-2640-FE0F","non_qualified":"1F6B5-1F3FB-200D-2640","image":"1f6b5-1f3fb-200d-2640-fe0f.png","sheet_x":37,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6B5-1F3FC-200D-2640-FE0F","non_qualified":"1F6B5-1F3FC-200D-2640","image":"1f6b5-1f3fc-200d-2640-fe0f.png","sheet_x":37,"sheet_y":22,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6B5-1F3FD-200D-2640-FE0F","non_qualified":"1F6B5-1F3FD-200D-2640","image":"1f6b5-1f3fd-200d-2640-fe0f.png","sheet_x":37,"sheet_y":23,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6B5-1F3FE-200D-2640-FE0F","non_qualified":"1F6B5-1F3FE-200D-2640","image":"1f6b5-1f3fe-200d-2640-fe0f.png","sheet_x":37,"sheet_y":24,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6B5-1F3FF-200D-2640-FE0F","non_qualified":"1F6B5-1F3FF-200D-2640","image":"1f6b5-1f3ff-200d-2640-fe0f.png","sheet_x":37,"sheet_y":25,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN MOUNTAIN BIKING","unified":"1F6B5-200D-2642-FE0F","non_qualified":"1F6B5-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b5-200d-2642-fe0f.png","sheet_x":37,"sheet_y":26,"short_name":"man-mountain-biking","short_names":["man-mountain-biking"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":485,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6B5-1F3FB-200D-2642-FE0F","non_qualified":"1F6B5-1F3FB-200D-2642","image":"1f6b5-1f3fb-200d-2642-fe0f.png","sheet_x":37,"sheet_y":27,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6B5-1F3FC-200D-2642-FE0F","non_qualified":"1F6B5-1F3FC-200D-2642","image":"1f6b5-1f3fc-200d-2642-fe0f.png","sheet_x":37,"sheet_y":28,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6B5-1F3FD-200D-2642-FE0F","non_qualified":"1F6B5-1F3FD-200D-2642","image":"1f6b5-1f3fd-200d-2642-fe0f.png","sheet_x":37,"sheet_y":29,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6B5-1F3FE-200D-2642-FE0F","non_qualified":"1F6B5-1F3FE-200D-2642","image":"1f6b5-1f3fe-200d-2642-fe0f.png","sheet_x":37,"sheet_y":30,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6B5-1F3FF-200D-2642-FE0F","non_qualified":"1F6B5-1F3FF-200D-2642","image":"1f6b5-1f3ff-200d-2642-fe0f.png","sheet_x":37,"sheet_y":31,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F6B5"},{"name":"MOUNTAIN BICYCLIST","unified":"1F6B5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b5.png","sheet_x":37,"sheet_y":32,"short_name":"mountain_bicyclist","short_names":["mountain_bicyclist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":484,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6B5-1F3FB","non_qualified":null,"image":"1f6b5-1f3fb.png","sheet_x":37,"sheet_y":33,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6B5-1F3FC","non_qualified":null,"image":"1f6b5-1f3fc.png","sheet_x":37,"sheet_y":34,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6B5-1F3FD","non_qualified":null,"image":"1f6b5-1f3fd.png","sheet_x":37,"sheet_y":35,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6B5-1F3FE","non_qualified":null,"image":"1f6b5-1f3fe.png","sheet_x":37,"sheet_y":36,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6B5-1F3FF","non_qualified":null,"image":"1f6b5-1f3ff.png","sheet_x":37,"sheet_y":37,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F6B5-200D-2642-FE0F"},{"name":"WOMAN WALKING","unified":"1F6B6-200D-2640-FE0F","non_qualified":"1F6B6-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b6-200d-2640-fe0f.png","sheet_x":37,"sheet_y":38,"short_name":"woman-walking","short_names":["woman-walking"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":410,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6B6-1F3FB-200D-2640-FE0F","non_qualified":"1F6B6-1F3FB-200D-2640","image":"1f6b6-1f3fb-200d-2640-fe0f.png","sheet_x":37,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6B6-1F3FC-200D-2640-FE0F","non_qualified":"1F6B6-1F3FC-200D-2640","image":"1f6b6-1f3fc-200d-2640-fe0f.png","sheet_x":37,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6B6-1F3FD-200D-2640-FE0F","non_qualified":"1F6B6-1F3FD-200D-2640","image":"1f6b6-1f3fd-200d-2640-fe0f.png","sheet_x":37,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6B6-1F3FE-200D-2640-FE0F","non_qualified":"1F6B6-1F3FE-200D-2640","image":"1f6b6-1f3fe-200d-2640-fe0f.png","sheet_x":37,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6B6-1F3FF-200D-2640-FE0F","non_qualified":"1F6B6-1F3FF-200D-2640","image":"1f6b6-1f3ff-200d-2640-fe0f.png","sheet_x":37,"sheet_y":43,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN WALKING FACING RIGHT","unified":"1F6B6-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-200D-2640-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b6-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":44,"short_name":"woman_walking_facing_right","short_names":["woman_walking_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":412,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F6B6-1F3FB-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FB-200D-2640-200D-27A1","image":"1f6b6-1f3fb-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":45,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F6B6-1F3FC-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FC-200D-2640-200D-27A1","image":"1f6b6-1f3fc-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":46,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F6B6-1F3FD-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FD-200D-2640-200D-27A1","image":"1f6b6-1f3fd-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":47,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F6B6-1F3FE-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FE-200D-2640-200D-27A1","image":"1f6b6-1f3fe-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":48,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F6B6-1F3FF-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FF-200D-2640-200D-27A1","image":"1f6b6-1f3ff-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":49,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"MAN WALKING","unified":"1F6B6-200D-2642-FE0F","non_qualified":"1F6B6-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b6-200d-2642-fe0f.png","sheet_x":37,"sheet_y":50,"short_name":"man-walking","short_names":["man-walking"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":409,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6B6-1F3FB-200D-2642-FE0F","non_qualified":"1F6B6-1F3FB-200D-2642","image":"1f6b6-1f3fb-200d-2642-fe0f.png","sheet_x":37,"sheet_y":51,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6B6-1F3FC-200D-2642-FE0F","non_qualified":"1F6B6-1F3FC-200D-2642","image":"1f6b6-1f3fc-200d-2642-fe0f.png","sheet_x":37,"sheet_y":52,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6B6-1F3FD-200D-2642-FE0F","non_qualified":"1F6B6-1F3FD-200D-2642","image":"1f6b6-1f3fd-200d-2642-fe0f.png","sheet_x":37,"sheet_y":53,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6B6-1F3FE-200D-2642-FE0F","non_qualified":"1F6B6-1F3FE-200D-2642","image":"1f6b6-1f3fe-200d-2642-fe0f.png","sheet_x":37,"sheet_y":54,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6B6-1F3FF-200D-2642-FE0F","non_qualified":"1F6B6-1F3FF-200D-2642","image":"1f6b6-1f3ff-200d-2642-fe0f.png","sheet_x":37,"sheet_y":55,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"1F6B6"},{"name":"MAN WALKING FACING RIGHT","unified":"1F6B6-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-200D-2642-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b6-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":56,"short_name":"man_walking_facing_right","short_names":["man_walking_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":413,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F6B6-1F3FB-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FB-200D-2642-200D-27A1","image":"1f6b6-1f3fb-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":57,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F6B6-1F3FC-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FC-200D-2642-200D-27A1","image":"1f6b6-1f3fc-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":58,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F6B6-1F3FD-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FD-200D-2642-200D-27A1","image":"1f6b6-1f3fd-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":59,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F6B6-1F3FE-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FE-200D-2642-200D-27A1","image":"1f6b6-1f3fe-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":60,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F6B6-1F3FF-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FF-200D-2642-200D-27A1","image":"1f6b6-1f3ff-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":37,"sheet_y":61,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"PERSON WALKING FACING RIGHT","unified":"1F6B6-200D-27A1-FE0F","non_qualified":"1F6B6-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b6-200d-27a1-fe0f.png","sheet_x":38,"sheet_y":0,"short_name":"person_walking_facing_right","short_names":["person_walking_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":411,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F6B6-1F3FB-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FB-200D-27A1","image":"1f6b6-1f3fb-200d-27a1-fe0f.png","sheet_x":38,"sheet_y":1,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F6B6-1F3FC-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FC-200D-27A1","image":"1f6b6-1f3fc-200d-27a1-fe0f.png","sheet_x":38,"sheet_y":2,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F6B6-1F3FD-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FD-200D-27A1","image":"1f6b6-1f3fd-200d-27a1-fe0f.png","sheet_x":38,"sheet_y":3,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F6B6-1F3FE-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FE-200D-27A1","image":"1f6b6-1f3fe-200d-27a1-fe0f.png","sheet_x":38,"sheet_y":4,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F6B6-1F3FF-200D-27A1-FE0F","non_qualified":"1F6B6-1F3FF-200D-27A1","image":"1f6b6-1f3ff-200d-27a1-fe0f.png","sheet_x":38,"sheet_y":5,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"PEDESTRIAN","unified":"1F6B6","non_qualified":null,"docomo":"E733","au":"EB72","softbank":"E201","google":"FE7F0","image":"1f6b6.png","sheet_x":38,"sheet_y":6,"short_name":"walking","short_names":["walking"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":408,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6B6-1F3FB","non_qualified":null,"image":"1f6b6-1f3fb.png","sheet_x":38,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6B6-1F3FC","non_qualified":null,"image":"1f6b6-1f3fc.png","sheet_x":38,"sheet_y":8,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6B6-1F3FD","non_qualified":null,"image":"1f6b6-1f3fd.png","sheet_x":38,"sheet_y":9,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6B6-1F3FE","non_qualified":null,"image":"1f6b6-1f3fe.png","sheet_x":38,"sheet_y":10,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6B6-1F3FF","non_qualified":null,"image":"1f6b6-1f3ff.png","sheet_x":38,"sheet_y":11,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"1F6B6-200D-2642-FE0F"},{"name":"NO PEDESTRIANS","unified":"1F6B7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b7.png","sheet_x":38,"sheet_y":12,"short_name":"no_pedestrians","short_names":["no_pedestrians"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1433,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHILDREN CROSSING","unified":"1F6B8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6b8.png","sheet_x":38,"sheet_y":13,"short_name":"children_crossing","short_names":["children_crossing"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1426,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MENS SYMBOL","unified":"1F6B9","non_qualified":null,"docomo":null,"au":null,"softbank":"E138","google":"FEB33","image":"1f6b9.png","sheet_x":38,"sheet_y":14,"short_name":"mens","short_names":["mens"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1416,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMENS SYMBOL","unified":"1F6BA","non_qualified":null,"docomo":null,"au":null,"softbank":"E139","google":"FEB34","image":"1f6ba.png","sheet_x":38,"sheet_y":15,"short_name":"womens","short_names":["womens"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1417,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RESTROOM","unified":"1F6BB","non_qualified":null,"docomo":"E66E","au":"E4A5","softbank":"E151","google":"FE506","image":"1f6bb.png","sheet_x":38,"sheet_y":16,"short_name":"restroom","short_names":["restroom"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1418,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BABY SYMBOL","unified":"1F6BC","non_qualified":null,"docomo":null,"au":"EB18","softbank":"E13A","google":"FEB35","image":"1f6bc.png","sheet_x":38,"sheet_y":17,"short_name":"baby_symbol","short_names":["baby_symbol"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1419,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TOILET","unified":"1F6BD","non_qualified":null,"docomo":"E66E","au":"E4A5","softbank":"E140","google":"FE507","image":"1f6bd.png","sheet_x":38,"sheet_y":18,"short_name":"toilet","short_names":["toilet"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1385,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WATER CLOSET","unified":"1F6BE","non_qualified":null,"docomo":"E66E","au":"E4A5","softbank":"E309","google":"FE508","image":"1f6be.png","sheet_x":38,"sheet_y":19,"short_name":"wc","short_names":["wc"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1420,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHOWER","unified":"1F6BF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6bf.png","sheet_x":38,"sheet_y":20,"short_name":"shower","short_names":["shower"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1387,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BATH","unified":"1F6C0","non_qualified":null,"docomo":"E6F7","au":"E5D8","softbank":"E13F","google":"FE505","image":"1f6c0.png","sheet_x":38,"sheet_y":21,"short_name":"bath","short_names":["bath"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-resting","sort_order":505,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6C0-1F3FB","non_qualified":null,"image":"1f6c0-1f3fb.png","sheet_x":38,"sheet_y":22,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6C0-1F3FC","non_qualified":null,"image":"1f6c0-1f3fc.png","sheet_x":38,"sheet_y":23,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6C0-1F3FD","non_qualified":null,"image":"1f6c0-1f3fd.png","sheet_x":38,"sheet_y":24,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6C0-1F3FE","non_qualified":null,"image":"1f6c0-1f3fe.png","sheet_x":38,"sheet_y":25,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6C0-1F3FF","non_qualified":null,"image":"1f6c0-1f3ff.png","sheet_x":38,"sheet_y":26,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"BATHTUB","unified":"1F6C1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6c1.png","sheet_x":38,"sheet_y":27,"short_name":"bathtub","short_names":["bathtub"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1388,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PASSPORT CONTROL","unified":"1F6C2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6c2.png","sheet_x":38,"sheet_y":28,"short_name":"passport_control","short_names":["passport_control"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1421,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CUSTOMS","unified":"1F6C3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6c3.png","sheet_x":38,"sheet_y":29,"short_name":"customs","short_names":["customs"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1422,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BAGGAGE CLAIM","unified":"1F6C4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6c4.png","sheet_x":38,"sheet_y":30,"short_name":"baggage_claim","short_names":["baggage_claim"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1423,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEFT LUGGAGE","unified":"1F6C5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6c5.png","sheet_x":38,"sheet_y":31,"short_name":"left_luggage","short_names":["left_luggage"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1424,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COUCH AND LAMP","unified":"1F6CB-FE0F","non_qualified":"1F6CB","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6cb-fe0f.png","sheet_x":38,"sheet_y":32,"short_name":"couch_and_lamp","short_names":["couch_and_lamp"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1383,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SLEEPING ACCOMMODATION","unified":"1F6CC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6cc.png","sheet_x":38,"sheet_y":33,"short_name":"sleeping_accommodation","short_names":["sleeping_accommodation"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-resting","sort_order":506,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F6CC-1F3FB","non_qualified":null,"image":"1f6cc-1f3fb.png","sheet_x":38,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F6CC-1F3FC","non_qualified":null,"image":"1f6cc-1f3fc.png","sheet_x":38,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F6CC-1F3FD","non_qualified":null,"image":"1f6cc-1f3fd.png","sheet_x":38,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F6CC-1F3FE","non_qualified":null,"image":"1f6cc-1f3fe.png","sheet_x":38,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F6CC-1F3FF","non_qualified":null,"image":"1f6cc-1f3ff.png","sheet_x":38,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SHOPPING BAGS","unified":"1F6CD-FE0F","non_qualified":"1F6CD","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6cd-fe0f.png","sheet_x":38,"sheet_y":39,"short_name":"shopping_bags","short_names":["shopping_bags"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1174,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BELLHOP BELL","unified":"1F6CE-FE0F","non_qualified":"1F6CE","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6ce-fe0f.png","sheet_x":38,"sheet_y":40,"short_name":"bellhop_bell","short_names":["bellhop_bell"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"hotel","sort_order":985,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BED","unified":"1F6CF-FE0F","non_qualified":"1F6CF","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6cf-fe0f.png","sheet_x":38,"sheet_y":41,"short_name":"bed","short_names":["bed"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1382,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PLACE OF WORSHIP","unified":"1F6D0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6d0.png","sheet_x":38,"sheet_y":42,"short_name":"place_of_worship","short_names":["place_of_worship"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1459,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OCTAGONAL SIGN","unified":"1F6D1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6d1.png","sheet_x":38,"sheet_y":43,"short_name":"octagonal_sign","short_names":["octagonal_sign"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":961,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHOPPING TROLLEY","unified":"1F6D2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6d2.png","sheet_x":38,"sheet_y":44,"short_name":"shopping_trolley","short_names":["shopping_trolley"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1402,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HINDU TEMPLE","unified":"1F6D5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6d5.png","sheet_x":38,"sheet_y":45,"short_name":"hindu_temple","short_names":["hindu_temple"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-religious","sort_order":892,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HUT","unified":"1F6D6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6d6.png","sheet_x":38,"sheet_y":46,"short_name":"hut","short_names":["hut"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":869,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ELEVATOR","unified":"1F6D7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6d7.png","sheet_x":38,"sheet_y":47,"short_name":"elevator","short_names":["elevator"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1379,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WIRELESS","unified":"1F6DC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6dc.png","sheet_x":38,"sheet_y":48,"short_name":"wireless","short_names":["wireless"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1507,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PLAYGROUND SLIDE","unified":"1F6DD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6dd.png","sheet_x":38,"sheet_y":49,"short_name":"playground_slide","short_names":["playground_slide"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":908,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHEEL","unified":"1F6DE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6de.png","sheet_x":38,"sheet_y":50,"short_name":"wheel","short_names":["wheel"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":957,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RING BUOY","unified":"1F6DF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6df.png","sheet_x":38,"sheet_y":51,"short_name":"ring_buoy","short_names":["ring_buoy"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-water","sort_order":964,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HAMMER AND WRENCH","unified":"1F6E0-FE0F","non_qualified":"1F6E0","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6e0-fe0f.png","sheet_x":38,"sheet_y":52,"short_name":"hammer_and_wrench","short_names":["hammer_and_wrench"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1342,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHIELD","unified":"1F6E1-FE0F","non_qualified":"1F6E1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6e1-fe0f.png","sheet_x":38,"sheet_y":53,"short_name":"shield","short_names":["shield"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1348,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OIL DRUM","unified":"1F6E2-FE0F","non_qualified":"1F6E2","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6e2-fe0f.png","sheet_x":38,"sheet_y":54,"short_name":"oil_drum","short_names":["oil_drum"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":955,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOTORWAY","unified":"1F6E3-FE0F","non_qualified":"1F6E3","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6e3-fe0f.png","sheet_x":38,"sheet_y":55,"short_name":"motorway","short_names":["motorway"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":953,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RAILWAY TRACK","unified":"1F6E4-FE0F","non_qualified":"1F6E4","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6e4-fe0f.png","sheet_x":38,"sheet_y":56,"short_name":"railway_track","short_names":["railway_track"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":954,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOTOR BOAT","unified":"1F6E5-FE0F","non_qualified":"1F6E5","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6e5-fe0f.png","sheet_x":38,"sheet_y":57,"short_name":"motor_boat","short_names":["motor_boat"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-water","sort_order":970,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMALL AIRPLANE","unified":"1F6E9-FE0F","non_qualified":"1F6E9","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6e9-fe0f.png","sheet_x":38,"sheet_y":58,"short_name":"small_airplane","short_names":["small_airplane"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":973,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AIRPLANE DEPARTURE","unified":"1F6EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6eb.png","sheet_x":38,"sheet_y":59,"short_name":"airplane_departure","short_names":["airplane_departure"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":974,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AIRPLANE ARRIVING","unified":"1F6EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6ec.png","sheet_x":38,"sheet_y":60,"short_name":"airplane_arriving","short_names":["airplane_arriving"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":975,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SATELLITE","unified":"1F6F0-FE0F","non_qualified":"1F6F0","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6f0-fe0f.png","sheet_x":38,"sheet_y":61,"short_name":"satellite","short_names":["satellite"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":982,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PASSENGER SHIP","unified":"1F6F3-FE0F","non_qualified":"1F6F3","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6f3-fe0f.png","sheet_x":39,"sheet_y":0,"short_name":"passenger_ship","short_names":["passenger_ship"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-water","sort_order":968,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SCOOTER","unified":"1F6F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6f4.png","sheet_x":39,"sheet_y":1,"short_name":"scooter","short_names":["scooter"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":949,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOTOR SCOOTER","unified":"1F6F5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6f5.png","sheet_x":39,"sheet_y":2,"short_name":"motor_scooter","short_names":["motor_scooter"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":944,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CANOE","unified":"1F6F6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6f6.png","sheet_x":39,"sheet_y":3,"short_name":"canoe","short_names":["canoe"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-water","sort_order":966,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SLED","unified":"1F6F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6f7.png","sheet_x":39,"sheet_y":4,"short_name":"sled","short_names":["sled"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1117,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLYING SAUCER","unified":"1F6F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6f8.png","sheet_x":39,"sheet_y":5,"short_name":"flying_saucer","short_names":["flying_saucer"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":984,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SKATEBOARD","unified":"1F6F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6f9.png","sheet_x":39,"sheet_y":6,"short_name":"skateboard","short_names":["skateboard"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":950,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AUTO RICKSHAW","unified":"1F6FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6fa.png","sheet_x":39,"sheet_y":7,"short_name":"auto_rickshaw","short_names":["auto_rickshaw"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":947,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PICKUP TRUCK","unified":"1F6FB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6fb.png","sheet_x":39,"sheet_y":8,"short_name":"pickup_truck","short_names":["pickup_truck"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":938,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROLLER SKATE","unified":"1F6FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f6fc.png","sheet_x":39,"sheet_y":9,"short_name":"roller_skate","short_names":["roller_skate"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":951,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE ORANGE CIRCLE","unified":"1F7E0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e0.png","sheet_x":39,"sheet_y":10,"short_name":"large_orange_circle","short_names":["large_orange_circle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1602,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE YELLOW CIRCLE","unified":"1F7E1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e1.png","sheet_x":39,"sheet_y":11,"short_name":"large_yellow_circle","short_names":["large_yellow_circle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1603,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE GREEN CIRCLE","unified":"1F7E2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e2.png","sheet_x":39,"sheet_y":12,"short_name":"large_green_circle","short_names":["large_green_circle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1604,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE PURPLE CIRCLE","unified":"1F7E3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e3.png","sheet_x":39,"sheet_y":13,"short_name":"large_purple_circle","short_names":["large_purple_circle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1606,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE BROWN CIRCLE","unified":"1F7E4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e4.png","sheet_x":39,"sheet_y":14,"short_name":"large_brown_circle","short_names":["large_brown_circle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1607,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE RED SQUARE","unified":"1F7E5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e5.png","sheet_x":39,"sheet_y":15,"short_name":"large_red_square","short_names":["large_red_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1610,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE BLUE SQUARE","unified":"1F7E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e6.png","sheet_x":39,"sheet_y":16,"short_name":"large_blue_square","short_names":["large_blue_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1614,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE ORANGE SQUARE","unified":"1F7E7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e7.png","sheet_x":39,"sheet_y":17,"short_name":"large_orange_square","short_names":["large_orange_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1611,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE YELLOW SQUARE","unified":"1F7E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e8.png","sheet_x":39,"sheet_y":18,"short_name":"large_yellow_square","short_names":["large_yellow_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1612,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE GREEN SQUARE","unified":"1F7E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7e9.png","sheet_x":39,"sheet_y":19,"short_name":"large_green_square","short_names":["large_green_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1613,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE PURPLE SQUARE","unified":"1F7EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7ea.png","sheet_x":39,"sheet_y":20,"short_name":"large_purple_square","short_names":["large_purple_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1615,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LARGE BROWN SQUARE","unified":"1F7EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7eb.png","sheet_x":39,"sheet_y":21,"short_name":"large_brown_square","short_names":["large_brown_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1616,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY EQUALS SIGN","unified":"1F7F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f7f0.png","sheet_x":39,"sheet_y":22,"short_name":"heavy_equals_sign","short_names":["heavy_equals_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"math","sort_order":1517,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PINCHED FINGERS","unified":"1F90C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f90c.png","sheet_x":39,"sheet_y":23,"short_name":"pinched_fingers","short_names":["pinched_fingers"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-partial","sort_order":181,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F90C-1F3FB","non_qualified":null,"image":"1f90c-1f3fb.png","sheet_x":39,"sheet_y":24,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F90C-1F3FC","non_qualified":null,"image":"1f90c-1f3fc.png","sheet_x":39,"sheet_y":25,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F90C-1F3FD","non_qualified":null,"image":"1f90c-1f3fd.png","sheet_x":39,"sheet_y":26,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F90C-1F3FE","non_qualified":null,"image":"1f90c-1f3fe.png","sheet_x":39,"sheet_y":27,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F90C-1F3FF","non_qualified":null,"image":"1f90c-1f3ff.png","sheet_x":39,"sheet_y":28,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WHITE HEART","unified":"1F90D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f90d.png","sheet_x":39,"sheet_y":29,"short_name":"white_heart","short_names":["white_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":154,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BROWN HEART","unified":"1F90E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f90e.png","sheet_x":39,"sheet_y":30,"short_name":"brown_heart","short_names":["brown_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":151,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PINCHING HAND","unified":"1F90F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f90f.png","sheet_x":39,"sheet_y":31,"short_name":"pinching_hand","short_names":["pinching_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-partial","sort_order":182,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F90F-1F3FB","non_qualified":null,"image":"1f90f-1f3fb.png","sheet_x":39,"sheet_y":32,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F90F-1F3FC","non_qualified":null,"image":"1f90f-1f3fc.png","sheet_x":39,"sheet_y":33,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F90F-1F3FD","non_qualified":null,"image":"1f90f-1f3fd.png","sheet_x":39,"sheet_y":34,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F90F-1F3FE","non_qualified":null,"image":"1f90f-1f3fe.png","sheet_x":39,"sheet_y":35,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F90F-1F3FF","non_qualified":null,"image":"1f90f-1f3ff.png","sheet_x":39,"sheet_y":36,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"ZIPPER-MOUTH FACE","unified":"1F910","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f910.png","sheet_x":39,"sheet_y":37,"short_name":"zipper_mouth_face","short_names":["zipper_mouth_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":37,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MONEY-MOUTH FACE","unified":"1F911","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f911.png","sheet_x":39,"sheet_y":38,"short_name":"money_mouth_face","short_names":["money_mouth_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-tongue","sort_order":29,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH THERMOMETER","unified":"1F912","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f912.png","sheet_x":39,"sheet_y":39,"short_name":"face_with_thermometer","short_names":["face_with_thermometer"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":59,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NERD FACE","unified":"1F913","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f913.png","sheet_x":39,"sheet_y":40,"short_name":"nerd_face","short_names":["nerd_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-glasses","sort_order":74,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"THINKING FACE","unified":"1F914","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f914.png","sheet_x":39,"sheet_y":41,"short_name":"thinking_face","short_names":["thinking_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hand","sort_order":35,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH HEAD-BANDAGE","unified":"1F915","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f915.png","sheet_x":39,"sheet_y":42,"short_name":"face_with_head_bandage","short_names":["face_with_head_bandage"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":60,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROBOT FACE","unified":"1F916","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f916.png","sheet_x":39,"sheet_y":43,"short_name":"robot_face","short_names":["robot_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-costume","sort_order":117,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HUGGING FACE","unified":"1F917","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f917.png","sheet_x":39,"sheet_y":44,"short_name":"hugging_face","short_names":["hugging_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hand","sort_order":30,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SIGN OF THE HORNS","unified":"1F918","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f918.png","sheet_x":39,"sheet_y":45,"short_name":"the_horns","short_names":["the_horns","sign_of_the_horns"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-partial","sort_order":187,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F918-1F3FB","non_qualified":null,"image":"1f918-1f3fb.png","sheet_x":39,"sheet_y":46,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F918-1F3FC","non_qualified":null,"image":"1f918-1f3fc.png","sheet_x":39,"sheet_y":47,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F918-1F3FD","non_qualified":null,"image":"1f918-1f3fd.png","sheet_x":39,"sheet_y":48,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F918-1F3FE","non_qualified":null,"image":"1f918-1f3fe.png","sheet_x":39,"sheet_y":49,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F918-1F3FF","non_qualified":null,"image":"1f918-1f3ff.png","sheet_x":39,"sheet_y":50,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"CALL ME HAND","unified":"1F919","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f919.png","sheet_x":39,"sheet_y":51,"short_name":"call_me_hand","short_names":["call_me_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-partial","sort_order":188,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F919-1F3FB","non_qualified":null,"image":"1f919-1f3fb.png","sheet_x":39,"sheet_y":52,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F919-1F3FC","non_qualified":null,"image":"1f919-1f3fc.png","sheet_x":39,"sheet_y":53,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F919-1F3FD","non_qualified":null,"image":"1f919-1f3fd.png","sheet_x":39,"sheet_y":54,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F919-1F3FE","non_qualified":null,"image":"1f919-1f3fe.png","sheet_x":39,"sheet_y":55,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F919-1F3FF","non_qualified":null,"image":"1f919-1f3ff.png","sheet_x":39,"sheet_y":56,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"RAISED BACK OF HAND","unified":"1F91A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f91a.png","sheet_x":39,"sheet_y":57,"short_name":"raised_back_of_hand","short_names":["raised_back_of_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":170,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F91A-1F3FB","non_qualified":null,"image":"1f91a-1f3fb.png","sheet_x":39,"sheet_y":58,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F91A-1F3FC","non_qualified":null,"image":"1f91a-1f3fc.png","sheet_x":39,"sheet_y":59,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F91A-1F3FD","non_qualified":null,"image":"1f91a-1f3fd.png","sheet_x":39,"sheet_y":60,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F91A-1F3FE","non_qualified":null,"image":"1f91a-1f3fe.png","sheet_x":39,"sheet_y":61,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F91A-1F3FF","non_qualified":null,"image":"1f91a-1f3ff.png","sheet_x":40,"sheet_y":0,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"LEFT-FACING FIST","unified":"1F91B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f91b.png","sheet_x":40,"sheet_y":1,"short_name":"left-facing_fist","short_names":["left-facing_fist"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-closed","sort_order":200,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F91B-1F3FB","non_qualified":null,"image":"1f91b-1f3fb.png","sheet_x":40,"sheet_y":2,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F91B-1F3FC","non_qualified":null,"image":"1f91b-1f3fc.png","sheet_x":40,"sheet_y":3,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F91B-1F3FD","non_qualified":null,"image":"1f91b-1f3fd.png","sheet_x":40,"sheet_y":4,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F91B-1F3FE","non_qualified":null,"image":"1f91b-1f3fe.png","sheet_x":40,"sheet_y":5,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F91B-1F3FF","non_qualified":null,"image":"1f91b-1f3ff.png","sheet_x":40,"sheet_y":6,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"RIGHT-FACING FIST","unified":"1F91C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f91c.png","sheet_x":40,"sheet_y":7,"short_name":"right-facing_fist","short_names":["right-facing_fist"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-closed","sort_order":201,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F91C-1F3FB","non_qualified":null,"image":"1f91c-1f3fb.png","sheet_x":40,"sheet_y":8,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F91C-1F3FC","non_qualified":null,"image":"1f91c-1f3fc.png","sheet_x":40,"sheet_y":9,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F91C-1F3FD","non_qualified":null,"image":"1f91c-1f3fd.png","sheet_x":40,"sheet_y":10,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F91C-1F3FE","non_qualified":null,"image":"1f91c-1f3fe.png","sheet_x":40,"sheet_y":11,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F91C-1F3FF","non_qualified":null,"image":"1f91c-1f3ff.png","sheet_x":40,"sheet_y":12,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"HANDSHAKE","unified":"1F91D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f91d.png","sheet_x":40,"sheet_y":13,"short_name":"handshake","short_names":["handshake"],"text":null,"texts":null,"category":"People & Body","subcategory":"hands","sort_order":207,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F91D-1F3FB","non_qualified":null,"image":"1f91d-1f3fb.png","sheet_x":40,"sheet_y":14,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F91D-1F3FC","non_qualified":null,"image":"1f91d-1f3fc.png","sheet_x":40,"sheet_y":15,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F91D-1F3FD","non_qualified":null,"image":"1f91d-1f3fd.png","sheet_x":40,"sheet_y":16,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F91D-1F3FE","non_qualified":null,"image":"1f91d-1f3fe.png","sheet_x":40,"sheet_y":17,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F91D-1F3FF","non_qualified":null,"image":"1f91d-1f3ff.png","sheet_x":40,"sheet_y":18,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1FAF1-1F3FB-200D-1FAF2-1F3FC","non_qualified":null,"image":"1faf1-1f3fb-200d-1faf2-1f3fc.png","sheet_x":40,"sheet_y":19,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1FAF1-1F3FB-200D-1FAF2-1F3FD","non_qualified":null,"image":"1faf1-1f3fb-200d-1faf2-1f3fd.png","sheet_x":40,"sheet_y":20,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1FAF1-1F3FB-200D-1FAF2-1F3FE","non_qualified":null,"image":"1faf1-1f3fb-200d-1faf2-1f3fe.png","sheet_x":40,"sheet_y":21,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1FAF1-1F3FB-200D-1FAF2-1F3FF","non_qualified":null,"image":"1faf1-1f3fb-200d-1faf2-1f3ff.png","sheet_x":40,"sheet_y":22,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1FAF1-1F3FC-200D-1FAF2-1F3FB","non_qualified":null,"image":"1faf1-1f3fc-200d-1faf2-1f3fb.png","sheet_x":40,"sheet_y":23,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1FAF1-1F3FC-200D-1FAF2-1F3FD","non_qualified":null,"image":"1faf1-1f3fc-200d-1faf2-1f3fd.png","sheet_x":40,"sheet_y":24,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1FAF1-1F3FC-200D-1FAF2-1F3FE","non_qualified":null,"image":"1faf1-1f3fc-200d-1faf2-1f3fe.png","sheet_x":40,"sheet_y":25,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1FAF1-1F3FC-200D-1FAF2-1F3FF","non_qualified":null,"image":"1faf1-1f3fc-200d-1faf2-1f3ff.png","sheet_x":40,"sheet_y":26,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1FAF1-1F3FD-200D-1FAF2-1F3FB","non_qualified":null,"image":"1faf1-1f3fd-200d-1faf2-1f3fb.png","sheet_x":40,"sheet_y":27,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1FAF1-1F3FD-200D-1FAF2-1F3FC","non_qualified":null,"image":"1faf1-1f3fd-200d-1faf2-1f3fc.png","sheet_x":40,"sheet_y":28,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1FAF1-1F3FD-200D-1FAF2-1F3FE","non_qualified":null,"image":"1faf1-1f3fd-200d-1faf2-1f3fe.png","sheet_x":40,"sheet_y":29,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1FAF1-1F3FD-200D-1FAF2-1F3FF","non_qualified":null,"image":"1faf1-1f3fd-200d-1faf2-1f3ff.png","sheet_x":40,"sheet_y":30,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1FAF1-1F3FE-200D-1FAF2-1F3FB","non_qualified":null,"image":"1faf1-1f3fe-200d-1faf2-1f3fb.png","sheet_x":40,"sheet_y":31,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1FAF1-1F3FE-200D-1FAF2-1F3FC","non_qualified":null,"image":"1faf1-1f3fe-200d-1faf2-1f3fc.png","sheet_x":40,"sheet_y":32,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1FAF1-1F3FE-200D-1FAF2-1F3FD","non_qualified":null,"image":"1faf1-1f3fe-200d-1faf2-1f3fd.png","sheet_x":40,"sheet_y":33,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1FAF1-1F3FE-200D-1FAF2-1F3FF","non_qualified":null,"image":"1faf1-1f3fe-200d-1faf2-1f3ff.png","sheet_x":40,"sheet_y":34,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1FAF1-1F3FF-200D-1FAF2-1F3FB","non_qualified":null,"image":"1faf1-1f3ff-200d-1faf2-1f3fb.png","sheet_x":40,"sheet_y":35,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1FAF1-1F3FF-200D-1FAF2-1F3FC","non_qualified":null,"image":"1faf1-1f3ff-200d-1faf2-1f3fc.png","sheet_x":40,"sheet_y":36,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1FAF1-1F3FF-200D-1FAF2-1F3FD","non_qualified":null,"image":"1faf1-1f3ff-200d-1faf2-1f3fd.png","sheet_x":40,"sheet_y":37,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1FAF1-1F3FF-200D-1FAF2-1F3FE","non_qualified":null,"image":"1faf1-1f3ff-200d-1faf2-1f3fe.png","sheet_x":40,"sheet_y":38,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"HAND WITH INDEX AND MIDDLE FINGERS CROSSED","unified":"1F91E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f91e.png","sheet_x":40,"sheet_y":39,"short_name":"crossed_fingers","short_names":["crossed_fingers","hand_with_index_and_middle_fingers_crossed"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-partial","sort_order":184,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F91E-1F3FB","non_qualified":null,"image":"1f91e-1f3fb.png","sheet_x":40,"sheet_y":40,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F91E-1F3FC","non_qualified":null,"image":"1f91e-1f3fc.png","sheet_x":40,"sheet_y":41,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F91E-1F3FD","non_qualified":null,"image":"1f91e-1f3fd.png","sheet_x":40,"sheet_y":42,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F91E-1F3FE","non_qualified":null,"image":"1f91e-1f3fe.png","sheet_x":40,"sheet_y":43,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F91E-1F3FF","non_qualified":null,"image":"1f91e-1f3ff.png","sheet_x":40,"sheet_y":44,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"I LOVE YOU HAND SIGN","unified":"1F91F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f91f.png","sheet_x":40,"sheet_y":45,"short_name":"i_love_you_hand_sign","short_names":["i_love_you_hand_sign"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-partial","sort_order":186,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F91F-1F3FB","non_qualified":null,"image":"1f91f-1f3fb.png","sheet_x":40,"sheet_y":46,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F91F-1F3FC","non_qualified":null,"image":"1f91f-1f3fc.png","sheet_x":40,"sheet_y":47,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F91F-1F3FD","non_qualified":null,"image":"1f91f-1f3fd.png","sheet_x":40,"sheet_y":48,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F91F-1F3FE","non_qualified":null,"image":"1f91f-1f3fe.png","sheet_x":40,"sheet_y":49,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F91F-1F3FF","non_qualified":null,"image":"1f91f-1f3ff.png","sheet_x":40,"sheet_y":50,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FACE WITH COWBOY HAT","unified":"1F920","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f920.png","sheet_x":40,"sheet_y":51,"short_name":"face_with_cowboy_hat","short_names":["face_with_cowboy_hat"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hat","sort_order":70,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOWN FACE","unified":"1F921","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f921.png","sheet_x":40,"sheet_y":52,"short_name":"clown_face","short_names":["clown_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-costume","sort_order":111,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NAUSEATED FACE","unified":"1F922","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f922.png","sheet_x":40,"sheet_y":53,"short_name":"nauseated_face","short_names":["nauseated_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":61,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROLLING ON THE FLOOR LAUGHING","unified":"1F923","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f923.png","sheet_x":40,"sheet_y":54,"short_name":"rolling_on_the_floor_laughing","short_names":["rolling_on_the_floor_laughing"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":7,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DROOLING FACE","unified":"1F924","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f924.png","sheet_x":40,"sheet_y":55,"short_name":"drooling_face","short_names":["drooling_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-sleepy","sort_order":56,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LYING FACE","unified":"1F925","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f925.png","sheet_x":40,"sheet_y":56,"short_name":"lying_face","short_names":["lying_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":49,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN FACEPALMING","unified":"1F926-200D-2640-FE0F","non_qualified":"1F926-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f926-200d-2640-fe0f.png","sheet_x":40,"sheet_y":57,"short_name":"woman-facepalming","short_names":["woman-facepalming"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":284,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F926-1F3FB-200D-2640-FE0F","non_qualified":"1F926-1F3FB-200D-2640","image":"1f926-1f3fb-200d-2640-fe0f.png","sheet_x":40,"sheet_y":58,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F926-1F3FC-200D-2640-FE0F","non_qualified":"1F926-1F3FC-200D-2640","image":"1f926-1f3fc-200d-2640-fe0f.png","sheet_x":40,"sheet_y":59,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F926-1F3FD-200D-2640-FE0F","non_qualified":"1F926-1F3FD-200D-2640","image":"1f926-1f3fd-200d-2640-fe0f.png","sheet_x":40,"sheet_y":60,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F926-1F3FE-200D-2640-FE0F","non_qualified":"1F926-1F3FE-200D-2640","image":"1f926-1f3fe-200d-2640-fe0f.png","sheet_x":40,"sheet_y":61,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F926-1F3FF-200D-2640-FE0F","non_qualified":"1F926-1F3FF-200D-2640","image":"1f926-1f3ff-200d-2640-fe0f.png","sheet_x":41,"sheet_y":0,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN FACEPALMING","unified":"1F926-200D-2642-FE0F","non_qualified":"1F926-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f926-200d-2642-fe0f.png","sheet_x":41,"sheet_y":1,"short_name":"man-facepalming","short_names":["man-facepalming"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":283,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F926-1F3FB-200D-2642-FE0F","non_qualified":"1F926-1F3FB-200D-2642","image":"1f926-1f3fb-200d-2642-fe0f.png","sheet_x":41,"sheet_y":2,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F926-1F3FC-200D-2642-FE0F","non_qualified":"1F926-1F3FC-200D-2642","image":"1f926-1f3fc-200d-2642-fe0f.png","sheet_x":41,"sheet_y":3,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F926-1F3FD-200D-2642-FE0F","non_qualified":"1F926-1F3FD-200D-2642","image":"1f926-1f3fd-200d-2642-fe0f.png","sheet_x":41,"sheet_y":4,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F926-1F3FE-200D-2642-FE0F","non_qualified":"1F926-1F3FE-200D-2642","image":"1f926-1f3fe-200d-2642-fe0f.png","sheet_x":41,"sheet_y":5,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F926-1F3FF-200D-2642-FE0F","non_qualified":"1F926-1F3FF-200D-2642","image":"1f926-1f3ff-200d-2642-fe0f.png","sheet_x":41,"sheet_y":6,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FACE PALM","unified":"1F926","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f926.png","sheet_x":41,"sheet_y":7,"short_name":"face_palm","short_names":["face_palm"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":282,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F926-1F3FB","non_qualified":null,"image":"1f926-1f3fb.png","sheet_x":41,"sheet_y":8,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F926-1F3FC","non_qualified":null,"image":"1f926-1f3fc.png","sheet_x":41,"sheet_y":9,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F926-1F3FD","non_qualified":null,"image":"1f926-1f3fd.png","sheet_x":41,"sheet_y":10,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F926-1F3FE","non_qualified":null,"image":"1f926-1f3fe.png","sheet_x":41,"sheet_y":11,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F926-1F3FF","non_qualified":null,"image":"1f926-1f3ff.png","sheet_x":41,"sheet_y":12,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SNEEZING FACE","unified":"1F927","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f927.png","sheet_x":41,"sheet_y":13,"short_name":"sneezing_face","short_names":["sneezing_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":63,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH ONE EYEBROW RAISED","unified":"1F928","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f928.png","sheet_x":41,"sheet_y":14,"short_name":"face_with_raised_eyebrow","short_names":["face_with_raised_eyebrow","face_with_one_eyebrow_raised"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":38,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GRINNING FACE WITH STAR EYES","unified":"1F929","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f929.png","sheet_x":41,"sheet_y":15,"short_name":"star-struck","short_names":["star-struck","grinning_face_with_star_eyes"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-affection","sort_order":17,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GRINNING FACE WITH ONE LARGE AND ONE SMALL EYE","unified":"1F92A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f92a.png","sheet_x":41,"sheet_y":16,"short_name":"zany_face","short_names":["zany_face","grinning_face_with_one_large_and_one_small_eye"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-tongue","sort_order":27,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH FINGER COVERING CLOSED LIPS","unified":"1F92B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f92b.png","sheet_x":41,"sheet_y":17,"short_name":"shushing_face","short_names":["shushing_face","face_with_finger_covering_closed_lips"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hand","sort_order":34,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SERIOUS FACE WITH SYMBOLS COVERING MOUTH","unified":"1F92C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f92c.png","sheet_x":41,"sheet_y":18,"short_name":"face_with_symbols_on_mouth","short_names":["face_with_symbols_on_mouth","serious_face_with_symbols_covering_mouth"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-negative","sort_order":105,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH SMILING EYES AND HAND COVERING MOUTH","unified":"1F92D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f92d.png","sheet_x":41,"sheet_y":19,"short_name":"face_with_hand_over_mouth","short_names":["face_with_hand_over_mouth","smiling_face_with_smiling_eyes_and_hand_covering_mouth"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hand","sort_order":31,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH OPEN MOUTH VOMITING","unified":"1F92E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f92e.png","sheet_x":41,"sheet_y":20,"short_name":"face_vomiting","short_names":["face_vomiting","face_with_open_mouth_vomiting"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":62,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHOCKED FACE WITH EXPLODING HEAD","unified":"1F92F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f92f.png","sheet_x":41,"sheet_y":21,"short_name":"exploding_head","short_names":["exploding_head","shocked_face_with_exploding_head"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":69,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PREGNANT WOMAN","unified":"1F930","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f930.png","sheet_x":41,"sheet_y":22,"short_name":"pregnant_woman","short_names":["pregnant_woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":363,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F930-1F3FB","non_qualified":null,"image":"1f930-1f3fb.png","sheet_x":41,"sheet_y":23,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F930-1F3FC","non_qualified":null,"image":"1f930-1f3fc.png","sheet_x":41,"sheet_y":24,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F930-1F3FD","non_qualified":null,"image":"1f930-1f3fd.png","sheet_x":41,"sheet_y":25,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F930-1F3FE","non_qualified":null,"image":"1f930-1f3fe.png","sheet_x":41,"sheet_y":26,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F930-1F3FF","non_qualified":null,"image":"1f930-1f3ff.png","sheet_x":41,"sheet_y":27,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"BREAST-FEEDING","unified":"1F931","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f931.png","sheet_x":41,"sheet_y":28,"short_name":"breast-feeding","short_names":["breast-feeding"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":366,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F931-1F3FB","non_qualified":null,"image":"1f931-1f3fb.png","sheet_x":41,"sheet_y":29,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F931-1F3FC","non_qualified":null,"image":"1f931-1f3fc.png","sheet_x":41,"sheet_y":30,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F931-1F3FD","non_qualified":null,"image":"1f931-1f3fd.png","sheet_x":41,"sheet_y":31,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F931-1F3FE","non_qualified":null,"image":"1f931-1f3fe.png","sheet_x":41,"sheet_y":32,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F931-1F3FF","non_qualified":null,"image":"1f931-1f3ff.png","sheet_x":41,"sheet_y":33,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PALMS UP TOGETHER","unified":"1F932","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f932.png","sheet_x":41,"sheet_y":34,"short_name":"palms_up_together","short_names":["palms_up_together"],"text":null,"texts":null,"category":"People & Body","subcategory":"hands","sort_order":206,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F932-1F3FB","non_qualified":null,"image":"1f932-1f3fb.png","sheet_x":41,"sheet_y":35,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F932-1F3FC","non_qualified":null,"image":"1f932-1f3fc.png","sheet_x":41,"sheet_y":36,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F932-1F3FD","non_qualified":null,"image":"1f932-1f3fd.png","sheet_x":41,"sheet_y":37,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F932-1F3FE","non_qualified":null,"image":"1f932-1f3fe.png","sheet_x":41,"sheet_y":38,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F932-1F3FF","non_qualified":null,"image":"1f932-1f3ff.png","sheet_x":41,"sheet_y":39,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SELFIE","unified":"1F933","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f933.png","sheet_x":41,"sheet_y":40,"short_name":"selfie","short_names":["selfie"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-prop","sort_order":211,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F933-1F3FB","non_qualified":null,"image":"1f933-1f3fb.png","sheet_x":41,"sheet_y":41,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F933-1F3FC","non_qualified":null,"image":"1f933-1f3fc.png","sheet_x":41,"sheet_y":42,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F933-1F3FD","non_qualified":null,"image":"1f933-1f3fd.png","sheet_x":41,"sheet_y":43,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F933-1F3FE","non_qualified":null,"image":"1f933-1f3fe.png","sheet_x":41,"sheet_y":44,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F933-1F3FF","non_qualified":null,"image":"1f933-1f3ff.png","sheet_x":41,"sheet_y":45,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PRINCE","unified":"1F934","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f934.png","sheet_x":41,"sheet_y":46,"short_name":"prince","short_names":["prince"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":350,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F934-1F3FB","non_qualified":null,"image":"1f934-1f3fb.png","sheet_x":41,"sheet_y":47,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F934-1F3FC","non_qualified":null,"image":"1f934-1f3fc.png","sheet_x":41,"sheet_y":48,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F934-1F3FD","non_qualified":null,"image":"1f934-1f3fd.png","sheet_x":41,"sheet_y":49,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F934-1F3FE","non_qualified":null,"image":"1f934-1f3fe.png","sheet_x":41,"sheet_y":50,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F934-1F3FF","non_qualified":null,"image":"1f934-1f3ff.png","sheet_x":41,"sheet_y":51,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN IN TUXEDO","unified":"1F935-200D-2640-FE0F","non_qualified":"1F935-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f935-200d-2640-fe0f.png","sheet_x":41,"sheet_y":52,"short_name":"woman_in_tuxedo","short_names":["woman_in_tuxedo"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":359,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F935-1F3FB-200D-2640-FE0F","non_qualified":"1F935-1F3FB-200D-2640","image":"1f935-1f3fb-200d-2640-fe0f.png","sheet_x":41,"sheet_y":53,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F935-1F3FC-200D-2640-FE0F","non_qualified":"1F935-1F3FC-200D-2640","image":"1f935-1f3fc-200d-2640-fe0f.png","sheet_x":41,"sheet_y":54,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F935-1F3FD-200D-2640-FE0F","non_qualified":"1F935-1F3FD-200D-2640","image":"1f935-1f3fd-200d-2640-fe0f.png","sheet_x":41,"sheet_y":55,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F935-1F3FE-200D-2640-FE0F","non_qualified":"1F935-1F3FE-200D-2640","image":"1f935-1f3fe-200d-2640-fe0f.png","sheet_x":41,"sheet_y":56,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F935-1F3FF-200D-2640-FE0F","non_qualified":"1F935-1F3FF-200D-2640","image":"1f935-1f3ff-200d-2640-fe0f.png","sheet_x":41,"sheet_y":57,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN IN TUXEDO","unified":"1F935-200D-2642-FE0F","non_qualified":"1F935-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f935-200d-2642-fe0f.png","sheet_x":41,"sheet_y":58,"short_name":"man_in_tuxedo","short_names":["man_in_tuxedo"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":358,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F935-1F3FB-200D-2642-FE0F","non_qualified":"1F935-1F3FB-200D-2642","image":"1f935-1f3fb-200d-2642-fe0f.png","sheet_x":41,"sheet_y":59,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F935-1F3FC-200D-2642-FE0F","non_qualified":"1F935-1F3FC-200D-2642","image":"1f935-1f3fc-200d-2642-fe0f.png","sheet_x":41,"sheet_y":60,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F935-1F3FD-200D-2642-FE0F","non_qualified":"1F935-1F3FD-200D-2642","image":"1f935-1f3fd-200d-2642-fe0f.png","sheet_x":41,"sheet_y":61,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F935-1F3FE-200D-2642-FE0F","non_qualified":"1F935-1F3FE-200D-2642","image":"1f935-1f3fe-200d-2642-fe0f.png","sheet_x":42,"sheet_y":0,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F935-1F3FF-200D-2642-FE0F","non_qualified":"1F935-1F3FF-200D-2642","image":"1f935-1f3ff-200d-2642-fe0f.png","sheet_x":42,"sheet_y":1,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN IN TUXEDO","unified":"1F935","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f935.png","sheet_x":42,"sheet_y":2,"short_name":"person_in_tuxedo","short_names":["person_in_tuxedo"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":357,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F935-1F3FB","non_qualified":null,"image":"1f935-1f3fb.png","sheet_x":42,"sheet_y":3,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F935-1F3FC","non_qualified":null,"image":"1f935-1f3fc.png","sheet_x":42,"sheet_y":4,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F935-1F3FD","non_qualified":null,"image":"1f935-1f3fd.png","sheet_x":42,"sheet_y":5,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F935-1F3FE","non_qualified":null,"image":"1f935-1f3fe.png","sheet_x":42,"sheet_y":6,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F935-1F3FF","non_qualified":null,"image":"1f935-1f3ff.png","sheet_x":42,"sheet_y":7,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MOTHER CHRISTMAS","unified":"1F936","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f936.png","sheet_x":42,"sheet_y":8,"short_name":"mrs_claus","short_names":["mrs_claus","mother_christmas"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":372,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F936-1F3FB","non_qualified":null,"image":"1f936-1f3fb.png","sheet_x":42,"sheet_y":9,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F936-1F3FC","non_qualified":null,"image":"1f936-1f3fc.png","sheet_x":42,"sheet_y":10,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F936-1F3FD","non_qualified":null,"image":"1f936-1f3fd.png","sheet_x":42,"sheet_y":11,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F936-1F3FE","non_qualified":null,"image":"1f936-1f3fe.png","sheet_x":42,"sheet_y":12,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F936-1F3FF","non_qualified":null,"image":"1f936-1f3ff.png","sheet_x":42,"sheet_y":13,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN SHRUGGING","unified":"1F937-200D-2640-FE0F","non_qualified":"1F937-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f937-200d-2640-fe0f.png","sheet_x":42,"sheet_y":14,"short_name":"woman-shrugging","short_names":["woman-shrugging"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":287,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F937-1F3FB-200D-2640-FE0F","non_qualified":"1F937-1F3FB-200D-2640","image":"1f937-1f3fb-200d-2640-fe0f.png","sheet_x":42,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F937-1F3FC-200D-2640-FE0F","non_qualified":"1F937-1F3FC-200D-2640","image":"1f937-1f3fc-200d-2640-fe0f.png","sheet_x":42,"sheet_y":16,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F937-1F3FD-200D-2640-FE0F","non_qualified":"1F937-1F3FD-200D-2640","image":"1f937-1f3fd-200d-2640-fe0f.png","sheet_x":42,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F937-1F3FE-200D-2640-FE0F","non_qualified":"1F937-1F3FE-200D-2640","image":"1f937-1f3fe-200d-2640-fe0f.png","sheet_x":42,"sheet_y":18,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F937-1F3FF-200D-2640-FE0F","non_qualified":"1F937-1F3FF-200D-2640","image":"1f937-1f3ff-200d-2640-fe0f.png","sheet_x":42,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN SHRUGGING","unified":"1F937-200D-2642-FE0F","non_qualified":"1F937-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f937-200d-2642-fe0f.png","sheet_x":42,"sheet_y":20,"short_name":"man-shrugging","short_names":["man-shrugging"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":286,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F937-1F3FB-200D-2642-FE0F","non_qualified":"1F937-1F3FB-200D-2642","image":"1f937-1f3fb-200d-2642-fe0f.png","sheet_x":42,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F937-1F3FC-200D-2642-FE0F","non_qualified":"1F937-1F3FC-200D-2642","image":"1f937-1f3fc-200d-2642-fe0f.png","sheet_x":42,"sheet_y":22,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F937-1F3FD-200D-2642-FE0F","non_qualified":"1F937-1F3FD-200D-2642","image":"1f937-1f3fd-200d-2642-fe0f.png","sheet_x":42,"sheet_y":23,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F937-1F3FE-200D-2642-FE0F","non_qualified":"1F937-1F3FE-200D-2642","image":"1f937-1f3fe-200d-2642-fe0f.png","sheet_x":42,"sheet_y":24,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F937-1F3FF-200D-2642-FE0F","non_qualified":"1F937-1F3FF-200D-2642","image":"1f937-1f3ff-200d-2642-fe0f.png","sheet_x":42,"sheet_y":25,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SHRUG","unified":"1F937","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f937.png","sheet_x":42,"sheet_y":26,"short_name":"shrug","short_names":["shrug"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":285,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F937-1F3FB","non_qualified":null,"image":"1f937-1f3fb.png","sheet_x":42,"sheet_y":27,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F937-1F3FC","non_qualified":null,"image":"1f937-1f3fc.png","sheet_x":42,"sheet_y":28,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F937-1F3FD","non_qualified":null,"image":"1f937-1f3fd.png","sheet_x":42,"sheet_y":29,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F937-1F3FE","non_qualified":null,"image":"1f937-1f3fe.png","sheet_x":42,"sheet_y":30,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F937-1F3FF","non_qualified":null,"image":"1f937-1f3ff.png","sheet_x":42,"sheet_y":31,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN CARTWHEELING","unified":"1F938-200D-2640-FE0F","non_qualified":"1F938-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f938-200d-2640-fe0f.png","sheet_x":42,"sheet_y":32,"short_name":"woman-cartwheeling","short_names":["woman-cartwheeling"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":489,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F938-1F3FB-200D-2640-FE0F","non_qualified":"1F938-1F3FB-200D-2640","image":"1f938-1f3fb-200d-2640-fe0f.png","sheet_x":42,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F938-1F3FC-200D-2640-FE0F","non_qualified":"1F938-1F3FC-200D-2640","image":"1f938-1f3fc-200d-2640-fe0f.png","sheet_x":42,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F938-1F3FD-200D-2640-FE0F","non_qualified":"1F938-1F3FD-200D-2640","image":"1f938-1f3fd-200d-2640-fe0f.png","sheet_x":42,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F938-1F3FE-200D-2640-FE0F","non_qualified":"1F938-1F3FE-200D-2640","image":"1f938-1f3fe-200d-2640-fe0f.png","sheet_x":42,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F938-1F3FF-200D-2640-FE0F","non_qualified":"1F938-1F3FF-200D-2640","image":"1f938-1f3ff-200d-2640-fe0f.png","sheet_x":42,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN CARTWHEELING","unified":"1F938-200D-2642-FE0F","non_qualified":"1F938-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f938-200d-2642-fe0f.png","sheet_x":42,"sheet_y":38,"short_name":"man-cartwheeling","short_names":["man-cartwheeling"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":488,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F938-1F3FB-200D-2642-FE0F","non_qualified":"1F938-1F3FB-200D-2642","image":"1f938-1f3fb-200d-2642-fe0f.png","sheet_x":42,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F938-1F3FC-200D-2642-FE0F","non_qualified":"1F938-1F3FC-200D-2642","image":"1f938-1f3fc-200d-2642-fe0f.png","sheet_x":42,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F938-1F3FD-200D-2642-FE0F","non_qualified":"1F938-1F3FD-200D-2642","image":"1f938-1f3fd-200d-2642-fe0f.png","sheet_x":42,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F938-1F3FE-200D-2642-FE0F","non_qualified":"1F938-1F3FE-200D-2642","image":"1f938-1f3fe-200d-2642-fe0f.png","sheet_x":42,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F938-1F3FF-200D-2642-FE0F","non_qualified":"1F938-1F3FF-200D-2642","image":"1f938-1f3ff-200d-2642-fe0f.png","sheet_x":42,"sheet_y":43,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON DOING CARTWHEEL","unified":"1F938","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f938.png","sheet_x":42,"sheet_y":44,"short_name":"person_doing_cartwheel","short_names":["person_doing_cartwheel"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":487,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F938-1F3FB","non_qualified":null,"image":"1f938-1f3fb.png","sheet_x":42,"sheet_y":45,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F938-1F3FC","non_qualified":null,"image":"1f938-1f3fc.png","sheet_x":42,"sheet_y":46,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F938-1F3FD","non_qualified":null,"image":"1f938-1f3fd.png","sheet_x":42,"sheet_y":47,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F938-1F3FE","non_qualified":null,"image":"1f938-1f3fe.png","sheet_x":42,"sheet_y":48,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F938-1F3FF","non_qualified":null,"image":"1f938-1f3ff.png","sheet_x":42,"sheet_y":49,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN JUGGLING","unified":"1F939-200D-2640-FE0F","non_qualified":"1F939-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f939-200d-2640-fe0f.png","sheet_x":42,"sheet_y":50,"short_name":"woman-juggling","short_names":["woman-juggling"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":501,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F939-1F3FB-200D-2640-FE0F","non_qualified":"1F939-1F3FB-200D-2640","image":"1f939-1f3fb-200d-2640-fe0f.png","sheet_x":42,"sheet_y":51,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F939-1F3FC-200D-2640-FE0F","non_qualified":"1F939-1F3FC-200D-2640","image":"1f939-1f3fc-200d-2640-fe0f.png","sheet_x":42,"sheet_y":52,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F939-1F3FD-200D-2640-FE0F","non_qualified":"1F939-1F3FD-200D-2640","image":"1f939-1f3fd-200d-2640-fe0f.png","sheet_x":42,"sheet_y":53,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F939-1F3FE-200D-2640-FE0F","non_qualified":"1F939-1F3FE-200D-2640","image":"1f939-1f3fe-200d-2640-fe0f.png","sheet_x":42,"sheet_y":54,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F939-1F3FF-200D-2640-FE0F","non_qualified":"1F939-1F3FF-200D-2640","image":"1f939-1f3ff-200d-2640-fe0f.png","sheet_x":42,"sheet_y":55,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN JUGGLING","unified":"1F939-200D-2642-FE0F","non_qualified":"1F939-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f939-200d-2642-fe0f.png","sheet_x":42,"sheet_y":56,"short_name":"man-juggling","short_names":["man-juggling"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":500,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F939-1F3FB-200D-2642-FE0F","non_qualified":"1F939-1F3FB-200D-2642","image":"1f939-1f3fb-200d-2642-fe0f.png","sheet_x":42,"sheet_y":57,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F939-1F3FC-200D-2642-FE0F","non_qualified":"1F939-1F3FC-200D-2642","image":"1f939-1f3fc-200d-2642-fe0f.png","sheet_x":42,"sheet_y":58,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F939-1F3FD-200D-2642-FE0F","non_qualified":"1F939-1F3FD-200D-2642","image":"1f939-1f3fd-200d-2642-fe0f.png","sheet_x":42,"sheet_y":59,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F939-1F3FE-200D-2642-FE0F","non_qualified":"1F939-1F3FE-200D-2642","image":"1f939-1f3fe-200d-2642-fe0f.png","sheet_x":42,"sheet_y":60,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F939-1F3FF-200D-2642-FE0F","non_qualified":"1F939-1F3FF-200D-2642","image":"1f939-1f3ff-200d-2642-fe0f.png","sheet_x":42,"sheet_y":61,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"JUGGLING","unified":"1F939","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f939.png","sheet_x":43,"sheet_y":0,"short_name":"juggling","short_names":["juggling"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":499,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F939-1F3FB","non_qualified":null,"image":"1f939-1f3fb.png","sheet_x":43,"sheet_y":1,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F939-1F3FC","non_qualified":null,"image":"1f939-1f3fc.png","sheet_x":43,"sheet_y":2,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F939-1F3FD","non_qualified":null,"image":"1f939-1f3fd.png","sheet_x":43,"sheet_y":3,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F939-1F3FE","non_qualified":null,"image":"1f939-1f3fe.png","sheet_x":43,"sheet_y":4,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F939-1F3FF","non_qualified":null,"image":"1f939-1f3ff.png","sheet_x":43,"sheet_y":5,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FENCER","unified":"1F93A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93a.png","sheet_x":43,"sheet_y":6,"short_name":"fencer","short_names":["fencer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":459,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMEN WRESTLING","unified":"1F93C-200D-2640-FE0F","non_qualified":"1F93C-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93c-200d-2640-fe0f.png","sheet_x":43,"sheet_y":7,"short_name":"woman-wrestling","short_names":["woman-wrestling"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":492,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MEN WRESTLING","unified":"1F93C-200D-2642-FE0F","non_qualified":"1F93C-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93c-200d-2642-fe0f.png","sheet_x":43,"sheet_y":8,"short_name":"man-wrestling","short_names":["man-wrestling"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":491,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WRESTLERS","unified":"1F93C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93c.png","sheet_x":43,"sheet_y":9,"short_name":"wrestlers","short_names":["wrestlers"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":490,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN PLAYING WATER POLO","unified":"1F93D-200D-2640-FE0F","non_qualified":"1F93D-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93d-200d-2640-fe0f.png","sheet_x":43,"sheet_y":10,"short_name":"woman-playing-water-polo","short_names":["woman-playing-water-polo"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":495,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F93D-1F3FB-200D-2640-FE0F","non_qualified":"1F93D-1F3FB-200D-2640","image":"1f93d-1f3fb-200d-2640-fe0f.png","sheet_x":43,"sheet_y":11,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F93D-1F3FC-200D-2640-FE0F","non_qualified":"1F93D-1F3FC-200D-2640","image":"1f93d-1f3fc-200d-2640-fe0f.png","sheet_x":43,"sheet_y":12,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F93D-1F3FD-200D-2640-FE0F","non_qualified":"1F93D-1F3FD-200D-2640","image":"1f93d-1f3fd-200d-2640-fe0f.png","sheet_x":43,"sheet_y":13,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F93D-1F3FE-200D-2640-FE0F","non_qualified":"1F93D-1F3FE-200D-2640","image":"1f93d-1f3fe-200d-2640-fe0f.png","sheet_x":43,"sheet_y":14,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F93D-1F3FF-200D-2640-FE0F","non_qualified":"1F93D-1F3FF-200D-2640","image":"1f93d-1f3ff-200d-2640-fe0f.png","sheet_x":43,"sheet_y":15,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN PLAYING WATER POLO","unified":"1F93D-200D-2642-FE0F","non_qualified":"1F93D-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93d-200d-2642-fe0f.png","sheet_x":43,"sheet_y":16,"short_name":"man-playing-water-polo","short_names":["man-playing-water-polo"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":494,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F93D-1F3FB-200D-2642-FE0F","non_qualified":"1F93D-1F3FB-200D-2642","image":"1f93d-1f3fb-200d-2642-fe0f.png","sheet_x":43,"sheet_y":17,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F93D-1F3FC-200D-2642-FE0F","non_qualified":"1F93D-1F3FC-200D-2642","image":"1f93d-1f3fc-200d-2642-fe0f.png","sheet_x":43,"sheet_y":18,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F93D-1F3FD-200D-2642-FE0F","non_qualified":"1F93D-1F3FD-200D-2642","image":"1f93d-1f3fd-200d-2642-fe0f.png","sheet_x":43,"sheet_y":19,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F93D-1F3FE-200D-2642-FE0F","non_qualified":"1F93D-1F3FE-200D-2642","image":"1f93d-1f3fe-200d-2642-fe0f.png","sheet_x":43,"sheet_y":20,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F93D-1F3FF-200D-2642-FE0F","non_qualified":"1F93D-1F3FF-200D-2642","image":"1f93d-1f3ff-200d-2642-fe0f.png","sheet_x":43,"sheet_y":21,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WATER POLO","unified":"1F93D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93d.png","sheet_x":43,"sheet_y":22,"short_name":"water_polo","short_names":["water_polo"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":493,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F93D-1F3FB","non_qualified":null,"image":"1f93d-1f3fb.png","sheet_x":43,"sheet_y":23,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F93D-1F3FC","non_qualified":null,"image":"1f93d-1f3fc.png","sheet_x":43,"sheet_y":24,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F93D-1F3FD","non_qualified":null,"image":"1f93d-1f3fd.png","sheet_x":43,"sheet_y":25,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F93D-1F3FE","non_qualified":null,"image":"1f93d-1f3fe.png","sheet_x":43,"sheet_y":26,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F93D-1F3FF","non_qualified":null,"image":"1f93d-1f3ff.png","sheet_x":43,"sheet_y":27,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN PLAYING HANDBALL","unified":"1F93E-200D-2640-FE0F","non_qualified":"1F93E-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93e-200d-2640-fe0f.png","sheet_x":43,"sheet_y":28,"short_name":"woman-playing-handball","short_names":["woman-playing-handball"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":498,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F93E-1F3FB-200D-2640-FE0F","non_qualified":"1F93E-1F3FB-200D-2640","image":"1f93e-1f3fb-200d-2640-fe0f.png","sheet_x":43,"sheet_y":29,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F93E-1F3FC-200D-2640-FE0F","non_qualified":"1F93E-1F3FC-200D-2640","image":"1f93e-1f3fc-200d-2640-fe0f.png","sheet_x":43,"sheet_y":30,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F93E-1F3FD-200D-2640-FE0F","non_qualified":"1F93E-1F3FD-200D-2640","image":"1f93e-1f3fd-200d-2640-fe0f.png","sheet_x":43,"sheet_y":31,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F93E-1F3FE-200D-2640-FE0F","non_qualified":"1F93E-1F3FE-200D-2640","image":"1f93e-1f3fe-200d-2640-fe0f.png","sheet_x":43,"sheet_y":32,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F93E-1F3FF-200D-2640-FE0F","non_qualified":"1F93E-1F3FF-200D-2640","image":"1f93e-1f3ff-200d-2640-fe0f.png","sheet_x":43,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN PLAYING HANDBALL","unified":"1F93E-200D-2642-FE0F","non_qualified":"1F93E-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93e-200d-2642-fe0f.png","sheet_x":43,"sheet_y":34,"short_name":"man-playing-handball","short_names":["man-playing-handball"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":497,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F93E-1F3FB-200D-2642-FE0F","non_qualified":"1F93E-1F3FB-200D-2642","image":"1f93e-1f3fb-200d-2642-fe0f.png","sheet_x":43,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F93E-1F3FC-200D-2642-FE0F","non_qualified":"1F93E-1F3FC-200D-2642","image":"1f93e-1f3fc-200d-2642-fe0f.png","sheet_x":43,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F93E-1F3FD-200D-2642-FE0F","non_qualified":"1F93E-1F3FD-200D-2642","image":"1f93e-1f3fd-200d-2642-fe0f.png","sheet_x":43,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F93E-1F3FE-200D-2642-FE0F","non_qualified":"1F93E-1F3FE-200D-2642","image":"1f93e-1f3fe-200d-2642-fe0f.png","sheet_x":43,"sheet_y":38,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F93E-1F3FF-200D-2642-FE0F","non_qualified":"1F93E-1F3FF-200D-2642","image":"1f93e-1f3ff-200d-2642-fe0f.png","sheet_x":43,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"HANDBALL","unified":"1F93E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93e.png","sheet_x":43,"sheet_y":40,"short_name":"handball","short_names":["handball"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":496,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F93E-1F3FB","non_qualified":null,"image":"1f93e-1f3fb.png","sheet_x":43,"sheet_y":41,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F93E-1F3FC","non_qualified":null,"image":"1f93e-1f3fc.png","sheet_x":43,"sheet_y":42,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F93E-1F3FD","non_qualified":null,"image":"1f93e-1f3fd.png","sheet_x":43,"sheet_y":43,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F93E-1F3FE","non_qualified":null,"image":"1f93e-1f3fe.png","sheet_x":43,"sheet_y":44,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F93E-1F3FF","non_qualified":null,"image":"1f93e-1f3ff.png","sheet_x":43,"sheet_y":45,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"DIVING MASK","unified":"1F93F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f93f.png","sheet_x":43,"sheet_y":46,"short_name":"diving_mask","short_names":["diving_mask"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1114,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WILTED FLOWER","unified":"1F940","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f940.png","sheet_x":43,"sheet_y":47,"short_name":"wilted_flower","short_names":["wilted_flower"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":690,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DRUM WITH DRUMSTICKS","unified":"1F941","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f941.png","sheet_x":43,"sheet_y":48,"short_name":"drum_with_drumsticks","short_names":["drum_with_drumsticks"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1222,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLINKING GLASSES","unified":"1F942","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f942.png","sheet_x":43,"sheet_y":49,"short_name":"clinking_glasses","short_names":["clinking_glasses"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":832,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TUMBLER GLASS","unified":"1F943","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f943.png","sheet_x":43,"sheet_y":50,"short_name":"tumbler_glass","short_names":["tumbler_glass"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":833,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPOON","unified":"1F944","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f944.png","sheet_x":43,"sheet_y":51,"short_name":"spoon","short_names":["spoon"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"dishware","sort_order":843,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GOAL NET","unified":"1F945","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f945.png","sheet_x":43,"sheet_y":52,"short_name":"goal_net","short_names":["goal_net"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1110,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FIRST PLACE MEDAL","unified":"1F947","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f947.png","sheet_x":43,"sheet_y":53,"short_name":"first_place_medal","short_names":["first_place_medal"],"text":null,"texts":null,"category":"Activities","subcategory":"award-medal","sort_order":1089,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SECOND PLACE MEDAL","unified":"1F948","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f948.png","sheet_x":43,"sheet_y":54,"short_name":"second_place_medal","short_names":["second_place_medal"],"text":null,"texts":null,"category":"Activities","subcategory":"award-medal","sort_order":1090,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"THIRD PLACE MEDAL","unified":"1F949","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f949.png","sheet_x":43,"sheet_y":55,"short_name":"third_place_medal","short_names":["third_place_medal"],"text":null,"texts":null,"category":"Activities","subcategory":"award-medal","sort_order":1091,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOXING GLOVE","unified":"1F94A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f94a.png","sheet_x":43,"sheet_y":56,"short_name":"boxing_glove","short_names":["boxing_glove"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1108,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MARTIAL ARTS UNIFORM","unified":"1F94B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f94b.png","sheet_x":43,"sheet_y":57,"short_name":"martial_arts_uniform","short_names":["martial_arts_uniform"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1109,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CURLING STONE","unified":"1F94C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f94c.png","sheet_x":43,"sheet_y":58,"short_name":"curling_stone","short_names":["curling_stone"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1118,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LACROSSE STICK AND BALL","unified":"1F94D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f94d.png","sheet_x":43,"sheet_y":59,"short_name":"lacrosse","short_names":["lacrosse"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1105,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SOFTBALL","unified":"1F94E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f94e.png","sheet_x":43,"sheet_y":60,"short_name":"softball","short_names":["softball"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1094,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLYING DISC","unified":"1F94F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f94f.png","sheet_x":43,"sheet_y":61,"short_name":"flying_disc","short_names":["flying_disc"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1100,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CROISSANT","unified":"1F950","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f950.png","sheet_x":44,"sheet_y":0,"short_name":"croissant","short_names":["croissant"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":751,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AVOCADO","unified":"1F951","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f951.png","sheet_x":44,"sheet_y":1,"short_name":"avocado","short_names":["avocado"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":732,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CUCUMBER","unified":"1F952","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f952.png","sheet_x":44,"sheet_y":2,"short_name":"cucumber","short_names":["cucumber"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":739,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BACON","unified":"1F953","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f953.png","sheet_x":44,"sheet_y":3,"short_name":"bacon","short_names":["bacon"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":762,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POTATO","unified":"1F954","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f954.png","sheet_x":44,"sheet_y":4,"short_name":"potato","short_names":["potato"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":734,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CARROT","unified":"1F955","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f955.png","sheet_x":44,"sheet_y":5,"short_name":"carrot","short_names":["carrot"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":735,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BAGUETTE BREAD","unified":"1F956","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f956.png","sheet_x":44,"sheet_y":6,"short_name":"baguette_bread","short_names":["baguette_bread"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":752,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GREEN SALAD","unified":"1F957","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f957.png","sheet_x":44,"sheet_y":7,"short_name":"green_salad","short_names":["green_salad"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":779,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHALLOW PAN OF FOOD","unified":"1F958","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f958.png","sheet_x":44,"sheet_y":8,"short_name":"shallow_pan_of_food","short_names":["shallow_pan_of_food"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":775,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STUFFED FLATBREAD","unified":"1F959","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f959.png","sheet_x":44,"sheet_y":9,"short_name":"stuffed_flatbread","short_names":["stuffed_flatbread"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":771,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EGG","unified":"1F95A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f95a.png","sheet_x":44,"sheet_y":10,"short_name":"egg","short_names":["egg"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":773,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GLASS OF MILK","unified":"1F95B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f95b.png","sheet_x":44,"sheet_y":11,"short_name":"glass_of_milk","short_names":["glass_of_milk"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":821,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PEANUTS","unified":"1F95C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f95c.png","sheet_x":44,"sheet_y":12,"short_name":"peanuts","short_names":["peanuts"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":744,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KIWIFRUIT","unified":"1F95D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f95d.png","sheet_x":44,"sheet_y":13,"short_name":"kiwifruit","short_names":["kiwifruit"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":728,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PANCAKES","unified":"1F95E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f95e.png","sheet_x":44,"sheet_y":14,"short_name":"pancakes","short_names":["pancakes"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":756,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DUMPLING","unified":"1F95F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f95f.png","sheet_x":44,"sheet_y":15,"short_name":"dumpling","short_names":["dumpling"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":798,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FORTUNE COOKIE","unified":"1F960","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f960.png","sheet_x":44,"sheet_y":16,"short_name":"fortune_cookie","short_names":["fortune_cookie"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":799,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TAKEOUT BOX","unified":"1F961","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f961.png","sheet_x":44,"sheet_y":17,"short_name":"takeout_box","short_names":["takeout_box"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":800,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHOPSTICKS","unified":"1F962","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f962.png","sheet_x":44,"sheet_y":18,"short_name":"chopsticks","short_names":["chopsticks"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"dishware","sort_order":840,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOWL WITH SPOON","unified":"1F963","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f963.png","sheet_x":44,"sheet_y":19,"short_name":"bowl_with_spoon","short_names":["bowl_with_spoon"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":778,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CUP WITH STRAW","unified":"1F964","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f964.png","sheet_x":44,"sheet_y":20,"short_name":"cup_with_straw","short_names":["cup_with_straw"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":835,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COCONUT","unified":"1F965","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f965.png","sheet_x":44,"sheet_y":21,"short_name":"coconut","short_names":["coconut"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":731,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BROCCOLI","unified":"1F966","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f966.png","sheet_x":44,"sheet_y":22,"short_name":"broccoli","short_names":["broccoli"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":741,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PIE","unified":"1F967","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f967.png","sheet_x":44,"sheet_y":23,"short_name":"pie","short_names":["pie"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":814,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PRETZEL","unified":"1F968","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f968.png","sheet_x":44,"sheet_y":24,"short_name":"pretzel","short_names":["pretzel"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":754,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CUT OF MEAT","unified":"1F969","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f969.png","sheet_x":44,"sheet_y":25,"short_name":"cut_of_meat","short_names":["cut_of_meat"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":761,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SANDWICH","unified":"1F96A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f96a.png","sheet_x":44,"sheet_y":26,"short_name":"sandwich","short_names":["sandwich"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":767,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CANNED FOOD","unified":"1F96B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f96b.png","sheet_x":44,"sheet_y":27,"short_name":"canned_food","short_names":["canned_food"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":783,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEAFY GREEN","unified":"1F96C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f96c.png","sheet_x":44,"sheet_y":28,"short_name":"leafy_green","short_names":["leafy_green"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":740,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MANGO","unified":"1F96D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f96d.png","sheet_x":44,"sheet_y":29,"short_name":"mango","short_names":["mango"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":720,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOON CAKE","unified":"1F96E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f96e.png","sheet_x":44,"sheet_y":30,"short_name":"moon_cake","short_names":["moon_cake"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-asian","sort_order":796,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BAGEL","unified":"1F96F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f96f.png","sheet_x":44,"sheet_y":31,"short_name":"bagel","short_names":["bagel"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":755,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH SMILING EYES AND THREE HEARTS","unified":"1F970","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f970.png","sheet_x":44,"sheet_y":32,"short_name":"smiling_face_with_3_hearts","short_names":["smiling_face_with_3_hearts"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-affection","sort_order":15,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"YAWNING FACE","unified":"1F971","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f971.png","sheet_x":44,"sheet_y":33,"short_name":"yawning_face","short_names":["yawning_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":101,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SMILING FACE WITH TEAR","unified":"1F972","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f972.png","sheet_x":44,"sheet_y":34,"short_name":"smiling_face_with_tear","short_names":["smiling_face_with_tear"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-affection","sort_order":23,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH PARTY HORN AND PARTY HAT","unified":"1F973","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f973.png","sheet_x":44,"sheet_y":35,"short_name":"partying_face","short_names":["partying_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hat","sort_order":71,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH UNEVEN EYES AND WAVY MOUTH","unified":"1F974","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f974.png","sheet_x":44,"sheet_y":36,"short_name":"woozy_face","short_names":["woozy_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":66,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OVERHEATED FACE","unified":"1F975","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f975.png","sheet_x":44,"sheet_y":37,"short_name":"hot_face","short_names":["hot_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":64,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FREEZING FACE","unified":"1F976","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f976.png","sheet_x":44,"sheet_y":38,"short_name":"cold_face","short_names":["cold_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-unwell","sort_order":65,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NINJA","unified":"1F977","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f977.png","sheet_x":44,"sheet_y":39,"short_name":"ninja","short_names":["ninja"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":345,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F977-1F3FB","non_qualified":null,"image":"1f977-1f3fb.png","sheet_x":44,"sheet_y":40,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F977-1F3FC","non_qualified":null,"image":"1f977-1f3fc.png","sheet_x":44,"sheet_y":41,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F977-1F3FD","non_qualified":null,"image":"1f977-1f3fd.png","sheet_x":44,"sheet_y":42,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F977-1F3FE","non_qualified":null,"image":"1f977-1f3fe.png","sheet_x":44,"sheet_y":43,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F977-1F3FF","non_qualified":null,"image":"1f977-1f3ff.png","sheet_x":44,"sheet_y":44,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"DISGUISED FACE","unified":"1F978","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f978.png","sheet_x":44,"sheet_y":45,"short_name":"disguised_face","short_names":["disguised_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hat","sort_order":72,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE HOLDING BACK TEARS","unified":"1F979","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f979.png","sheet_x":44,"sheet_y":46,"short_name":"face_holding_back_tears","short_names":["face_holding_back_tears"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":86,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH PLEADING EYES","unified":"1F97A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f97a.png","sheet_x":44,"sheet_y":47,"short_name":"pleading_face","short_names":["pleading_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":85,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SARI","unified":"1F97B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f97b.png","sheet_x":44,"sheet_y":48,"short_name":"sari","short_names":["sari"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1164,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LAB COAT","unified":"1F97C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f97c.png","sheet_x":44,"sheet_y":49,"short_name":"lab_coat","short_names":["lab_coat"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1153,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GOGGLES","unified":"1F97D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f97d.png","sheet_x":44,"sheet_y":50,"short_name":"goggles","short_names":["goggles"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1152,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HIKING BOOT","unified":"1F97E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f97e.png","sheet_x":44,"sheet_y":51,"short_name":"hiking_boot","short_names":["hiking_boot"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1179,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLAT SHOE","unified":"1F97F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f97f.png","sheet_x":44,"sheet_y":52,"short_name":"womans_flat_shoe","short_names":["womans_flat_shoe"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1180,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CRAB","unified":"1F980","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f980.png","sheet_x":44,"sheet_y":53,"short_name":"crab","short_names":["crab"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-marine","sort_order":801,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LION FACE","unified":"1F981","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f981.png","sheet_x":44,"sheet_y":54,"short_name":"lion_face","short_names":["lion_face"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":574,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SCORPION","unified":"1F982","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f982.png","sheet_x":44,"sheet_y":55,"short_name":"scorpion","short_names":["scorpion"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":679,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TURKEY","unified":"1F983","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f983.png","sheet_x":44,"sheet_y":56,"short_name":"turkey","short_names":["turkey"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":625,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UNICORN FACE","unified":"1F984","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f984.png","sheet_x":44,"sheet_y":57,"short_name":"unicorn_face","short_names":["unicorn_face"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":582,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EAGLE","unified":"1F985","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f985.png","sheet_x":44,"sheet_y":58,"short_name":"eagle","short_names":["eagle"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":634,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DUCK","unified":"1F986","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f986.png","sheet_x":44,"sheet_y":59,"short_name":"duck","short_names":["duck"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":635,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BAT","unified":"1F987","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f987.png","sheet_x":44,"sheet_y":60,"short_name":"bat","short_names":["bat"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":614,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHARK","unified":"1F988","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f988.png","sheet_x":44,"sheet_y":61,"short_name":"shark","short_names":["shark"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":663,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OWL","unified":"1F989","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f989.png","sheet_x":45,"sheet_y":0,"short_name":"owl","short_names":["owl"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":637,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FOX FACE","unified":"1F98A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f98a.png","sheet_x":45,"sheet_y":1,"short_name":"fox_face","short_names":["fox_face"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":569,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUTTERFLY","unified":"1F98B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f98b.png","sheet_x":45,"sheet_y":2,"short_name":"butterfly","short_names":["butterfly"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":669,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DEER","unified":"1F98C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f98c.png","sheet_x":45,"sheet_y":3,"short_name":"deer","short_names":["deer"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":584,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GORILLA","unified":"1F98D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f98d.png","sheet_x":45,"sheet_y":4,"short_name":"gorilla","short_names":["gorilla"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":561,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LIZARD","unified":"1F98E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f98e.png","sheet_x":45,"sheet_y":5,"short_name":"lizard","short_names":["lizard"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-reptile","sort_order":650,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RHINOCEROS","unified":"1F98F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f98f.png","sheet_x":45,"sheet_y":6,"short_name":"rhinoceros","short_names":["rhinoceros"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":603,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHRIMP","unified":"1F990","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f990.png","sheet_x":45,"sheet_y":7,"short_name":"shrimp","short_names":["shrimp"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-marine","sort_order":803,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SQUID","unified":"1F991","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f991.png","sheet_x":45,"sheet_y":8,"short_name":"squid","short_names":["squid"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-marine","sort_order":804,"added_in":"3.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GIRAFFE FACE","unified":"1F992","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f992.png","sheet_x":45,"sheet_y":9,"short_name":"giraffe_face","short_names":["giraffe_face"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":600,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ZEBRA FACE","unified":"1F993","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f993.png","sheet_x":45,"sheet_y":10,"short_name":"zebra_face","short_names":["zebra_face"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":583,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEDGEHOG","unified":"1F994","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f994.png","sheet_x":45,"sheet_y":11,"short_name":"hedgehog","short_names":["hedgehog"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":613,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SAUROPOD","unified":"1F995","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f995.png","sheet_x":45,"sheet_y":12,"short_name":"sauropod","short_names":["sauropod"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-reptile","sort_order":654,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"T-REX","unified":"1F996","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f996.png","sheet_x":45,"sheet_y":13,"short_name":"t-rex","short_names":["t-rex"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-reptile","sort_order":655,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CRICKET","unified":"1F997","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f997.png","sheet_x":45,"sheet_y":14,"short_name":"cricket","short_names":["cricket"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":675,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KANGAROO","unified":"1F998","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f998.png","sheet_x":45,"sheet_y":15,"short_name":"kangaroo","short_names":["kangaroo"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":622,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LLAMA","unified":"1F999","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f999.png","sheet_x":45,"sheet_y":16,"short_name":"llama","short_names":["llama"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":599,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PEACOCK","unified":"1F99A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f99a.png","sheet_x":45,"sheet_y":17,"short_name":"peacock","short_names":["peacock"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":641,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HIPPOPOTAMUS","unified":"1F99B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f99b.png","sheet_x":45,"sheet_y":18,"short_name":"hippopotamus","short_names":["hippopotamus"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":604,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PARROT","unified":"1F99C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f99c.png","sheet_x":45,"sheet_y":19,"short_name":"parrot","short_names":["parrot"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":642,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RACCOON","unified":"1F99D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f99d.png","sheet_x":45,"sheet_y":20,"short_name":"raccoon","short_names":["raccoon"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":570,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOBSTER","unified":"1F99E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f99e.png","sheet_x":45,"sheet_y":21,"short_name":"lobster","short_names":["lobster"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-marine","sort_order":802,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOSQUITO","unified":"1F99F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f99f.png","sheet_x":45,"sheet_y":22,"short_name":"mosquito","short_names":["mosquito"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":680,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MICROBE","unified":"1F9A0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a0.png","sheet_x":45,"sheet_y":23,"short_name":"microbe","short_names":["microbe"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":683,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BADGER","unified":"1F9A1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a1.png","sheet_x":45,"sheet_y":24,"short_name":"badger","short_names":["badger"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":623,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SWAN","unified":"1F9A2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a2.png","sheet_x":45,"sheet_y":25,"short_name":"swan","short_names":["swan"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":636,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MAMMOTH","unified":"1F9A3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a3.png","sheet_x":45,"sheet_y":26,"short_name":"mammoth","short_names":["mammoth"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":602,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DODO","unified":"1F9A4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a4.png","sheet_x":45,"sheet_y":27,"short_name":"dodo","short_names":["dodo"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":638,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SLOTH","unified":"1F9A5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a5.png","sheet_x":45,"sheet_y":28,"short_name":"sloth","short_names":["sloth"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":619,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OTTER","unified":"1F9A6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a6.png","sheet_x":45,"sheet_y":29,"short_name":"otter","short_names":["otter"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":620,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ORANGUTAN","unified":"1F9A7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a7.png","sheet_x":45,"sheet_y":30,"short_name":"orangutan","short_names":["orangutan"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":562,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SKUNK","unified":"1F9A8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a8.png","sheet_x":45,"sheet_y":31,"short_name":"skunk","short_names":["skunk"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":621,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLAMINGO","unified":"1F9A9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9a9.png","sheet_x":45,"sheet_y":32,"short_name":"flamingo","short_names":["flamingo"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":640,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OYSTER","unified":"1F9AA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9aa.png","sheet_x":45,"sheet_y":33,"short_name":"oyster","short_names":["oyster"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-marine","sort_order":805,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BEAVER","unified":"1F9AB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ab.png","sheet_x":45,"sheet_y":34,"short_name":"beaver","short_names":["beaver"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":612,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BISON","unified":"1F9AC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ac.png","sheet_x":45,"sheet_y":35,"short_name":"bison","short_names":["bison"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":585,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SEAL","unified":"1F9AD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ad.png","sheet_x":45,"sheet_y":36,"short_name":"seal","short_names":["seal"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":659,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GUIDE DOG","unified":"1F9AE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ae.png","sheet_x":45,"sheet_y":37,"short_name":"guide_dog","short_names":["guide_dog"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":565,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PROBING CANE","unified":"1F9AF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9af.png","sheet_x":45,"sheet_y":38,"short_name":"probing_cane","short_names":["probing_cane"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1356,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BONE","unified":"1F9B4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b4.png","sheet_x":45,"sheet_y":39,"short_name":"bone","short_names":["bone"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":224,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEG","unified":"1F9B5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b5.png","sheet_x":45,"sheet_y":40,"short_name":"leg","short_names":["leg"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":215,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9B5-1F3FB","non_qualified":null,"image":"1f9b5-1f3fb.png","sheet_x":45,"sheet_y":41,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9B5-1F3FC","non_qualified":null,"image":"1f9b5-1f3fc.png","sheet_x":45,"sheet_y":42,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9B5-1F3FD","non_qualified":null,"image":"1f9b5-1f3fd.png","sheet_x":45,"sheet_y":43,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9B5-1F3FE","non_qualified":null,"image":"1f9b5-1f3fe.png","sheet_x":45,"sheet_y":44,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9B5-1F3FF","non_qualified":null,"image":"1f9b5-1f3ff.png","sheet_x":45,"sheet_y":45,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FOOT","unified":"1F9B6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b6.png","sheet_x":45,"sheet_y":46,"short_name":"foot","short_names":["foot"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":216,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9B6-1F3FB","non_qualified":null,"image":"1f9b6-1f3fb.png","sheet_x":45,"sheet_y":47,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9B6-1F3FC","non_qualified":null,"image":"1f9b6-1f3fc.png","sheet_x":45,"sheet_y":48,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9B6-1F3FD","non_qualified":null,"image":"1f9b6-1f3fd.png","sheet_x":45,"sheet_y":49,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9B6-1F3FE","non_qualified":null,"image":"1f9b6-1f3fe.png","sheet_x":45,"sheet_y":50,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9B6-1F3FF","non_qualified":null,"image":"1f9b6-1f3ff.png","sheet_x":45,"sheet_y":51,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"TOOTH","unified":"1F9B7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b7.png","sheet_x":45,"sheet_y":52,"short_name":"tooth","short_names":["tooth"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":223,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN SUPERHERO","unified":"1F9B8-200D-2640-FE0F","non_qualified":"1F9B8-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b8-200d-2640-fe0f.png","sheet_x":45,"sheet_y":53,"short_name":"female_superhero","short_names":["female_superhero"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":376,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9B8-1F3FB-200D-2640-FE0F","non_qualified":"1F9B8-1F3FB-200D-2640","image":"1f9b8-1f3fb-200d-2640-fe0f.png","sheet_x":45,"sheet_y":54,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9B8-1F3FC-200D-2640-FE0F","non_qualified":"1F9B8-1F3FC-200D-2640","image":"1f9b8-1f3fc-200d-2640-fe0f.png","sheet_x":45,"sheet_y":55,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9B8-1F3FD-200D-2640-FE0F","non_qualified":"1F9B8-1F3FD-200D-2640","image":"1f9b8-1f3fd-200d-2640-fe0f.png","sheet_x":45,"sheet_y":56,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9B8-1F3FE-200D-2640-FE0F","non_qualified":"1F9B8-1F3FE-200D-2640","image":"1f9b8-1f3fe-200d-2640-fe0f.png","sheet_x":45,"sheet_y":57,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9B8-1F3FF-200D-2640-FE0F","non_qualified":"1F9B8-1F3FF-200D-2640","image":"1f9b8-1f3ff-200d-2640-fe0f.png","sheet_x":45,"sheet_y":58,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN SUPERHERO","unified":"1F9B8-200D-2642-FE0F","non_qualified":"1F9B8-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b8-200d-2642-fe0f.png","sheet_x":45,"sheet_y":59,"short_name":"male_superhero","short_names":["male_superhero"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":375,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9B8-1F3FB-200D-2642-FE0F","non_qualified":"1F9B8-1F3FB-200D-2642","image":"1f9b8-1f3fb-200d-2642-fe0f.png","sheet_x":45,"sheet_y":60,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9B8-1F3FC-200D-2642-FE0F","non_qualified":"1F9B8-1F3FC-200D-2642","image":"1f9b8-1f3fc-200d-2642-fe0f.png","sheet_x":45,"sheet_y":61,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9B8-1F3FD-200D-2642-FE0F","non_qualified":"1F9B8-1F3FD-200D-2642","image":"1f9b8-1f3fd-200d-2642-fe0f.png","sheet_x":46,"sheet_y":0,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9B8-1F3FE-200D-2642-FE0F","non_qualified":"1F9B8-1F3FE-200D-2642","image":"1f9b8-1f3fe-200d-2642-fe0f.png","sheet_x":46,"sheet_y":1,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9B8-1F3FF-200D-2642-FE0F","non_qualified":"1F9B8-1F3FF-200D-2642","image":"1f9b8-1f3ff-200d-2642-fe0f.png","sheet_x":46,"sheet_y":2,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SUPERHERO","unified":"1F9B8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b8.png","sheet_x":46,"sheet_y":3,"short_name":"superhero","short_names":["superhero"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":374,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9B8-1F3FB","non_qualified":null,"image":"1f9b8-1f3fb.png","sheet_x":46,"sheet_y":4,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9B8-1F3FC","non_qualified":null,"image":"1f9b8-1f3fc.png","sheet_x":46,"sheet_y":5,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9B8-1F3FD","non_qualified":null,"image":"1f9b8-1f3fd.png","sheet_x":46,"sheet_y":6,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9B8-1F3FE","non_qualified":null,"image":"1f9b8-1f3fe.png","sheet_x":46,"sheet_y":7,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9B8-1F3FF","non_qualified":null,"image":"1f9b8-1f3ff.png","sheet_x":46,"sheet_y":8,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN SUPERVILLAIN","unified":"1F9B9-200D-2640-FE0F","non_qualified":"1F9B9-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b9-200d-2640-fe0f.png","sheet_x":46,"sheet_y":9,"short_name":"female_supervillain","short_names":["female_supervillain"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":379,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9B9-1F3FB-200D-2640-FE0F","non_qualified":"1F9B9-1F3FB-200D-2640","image":"1f9b9-1f3fb-200d-2640-fe0f.png","sheet_x":46,"sheet_y":10,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9B9-1F3FC-200D-2640-FE0F","non_qualified":"1F9B9-1F3FC-200D-2640","image":"1f9b9-1f3fc-200d-2640-fe0f.png","sheet_x":46,"sheet_y":11,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9B9-1F3FD-200D-2640-FE0F","non_qualified":"1F9B9-1F3FD-200D-2640","image":"1f9b9-1f3fd-200d-2640-fe0f.png","sheet_x":46,"sheet_y":12,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9B9-1F3FE-200D-2640-FE0F","non_qualified":"1F9B9-1F3FE-200D-2640","image":"1f9b9-1f3fe-200d-2640-fe0f.png","sheet_x":46,"sheet_y":13,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9B9-1F3FF-200D-2640-FE0F","non_qualified":"1F9B9-1F3FF-200D-2640","image":"1f9b9-1f3ff-200d-2640-fe0f.png","sheet_x":46,"sheet_y":14,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN SUPERVILLAIN","unified":"1F9B9-200D-2642-FE0F","non_qualified":"1F9B9-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b9-200d-2642-fe0f.png","sheet_x":46,"sheet_y":15,"short_name":"male_supervillain","short_names":["male_supervillain"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":378,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9B9-1F3FB-200D-2642-FE0F","non_qualified":"1F9B9-1F3FB-200D-2642","image":"1f9b9-1f3fb-200d-2642-fe0f.png","sheet_x":46,"sheet_y":16,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9B9-1F3FC-200D-2642-FE0F","non_qualified":"1F9B9-1F3FC-200D-2642","image":"1f9b9-1f3fc-200d-2642-fe0f.png","sheet_x":46,"sheet_y":17,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9B9-1F3FD-200D-2642-FE0F","non_qualified":"1F9B9-1F3FD-200D-2642","image":"1f9b9-1f3fd-200d-2642-fe0f.png","sheet_x":46,"sheet_y":18,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9B9-1F3FE-200D-2642-FE0F","non_qualified":"1F9B9-1F3FE-200D-2642","image":"1f9b9-1f3fe-200d-2642-fe0f.png","sheet_x":46,"sheet_y":19,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9B9-1F3FF-200D-2642-FE0F","non_qualified":"1F9B9-1F3FF-200D-2642","image":"1f9b9-1f3ff-200d-2642-fe0f.png","sheet_x":46,"sheet_y":20,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SUPERVILLAIN","unified":"1F9B9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9b9.png","sheet_x":46,"sheet_y":21,"short_name":"supervillain","short_names":["supervillain"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":377,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9B9-1F3FB","non_qualified":null,"image":"1f9b9-1f3fb.png","sheet_x":46,"sheet_y":22,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9B9-1F3FC","non_qualified":null,"image":"1f9b9-1f3fc.png","sheet_x":46,"sheet_y":23,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9B9-1F3FD","non_qualified":null,"image":"1f9b9-1f3fd.png","sheet_x":46,"sheet_y":24,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9B9-1F3FE","non_qualified":null,"image":"1f9b9-1f3fe.png","sheet_x":46,"sheet_y":25,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9B9-1F3FF","non_qualified":null,"image":"1f9b9-1f3ff.png","sheet_x":46,"sheet_y":26,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SAFETY VEST","unified":"1F9BA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ba.png","sheet_x":46,"sheet_y":27,"short_name":"safety_vest","short_names":["safety_vest"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1154,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EAR WITH HEARING AID","unified":"1F9BB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9bb.png","sheet_x":46,"sheet_y":28,"short_name":"ear_with_hearing_aid","short_names":["ear_with_hearing_aid"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":218,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9BB-1F3FB","non_qualified":null,"image":"1f9bb-1f3fb.png","sheet_x":46,"sheet_y":29,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9BB-1F3FC","non_qualified":null,"image":"1f9bb-1f3fc.png","sheet_x":46,"sheet_y":30,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9BB-1F3FD","non_qualified":null,"image":"1f9bb-1f3fd.png","sheet_x":46,"sheet_y":31,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9BB-1F3FE","non_qualified":null,"image":"1f9bb-1f3fe.png","sheet_x":46,"sheet_y":32,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9BB-1F3FF","non_qualified":null,"image":"1f9bb-1f3ff.png","sheet_x":46,"sheet_y":33,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MOTORIZED WHEELCHAIR","unified":"1F9BC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9bc.png","sheet_x":46,"sheet_y":34,"short_name":"motorized_wheelchair","short_names":["motorized_wheelchair"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":946,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MANUAL WHEELCHAIR","unified":"1F9BD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9bd.png","sheet_x":46,"sheet_y":35,"short_name":"manual_wheelchair","short_names":["manual_wheelchair"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":945,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MECHANICAL ARM","unified":"1F9BE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9be.png","sheet_x":46,"sheet_y":36,"short_name":"mechanical_arm","short_names":["mechanical_arm"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":213,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MECHANICAL LEG","unified":"1F9BF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9bf.png","sheet_x":46,"sheet_y":37,"short_name":"mechanical_leg","short_names":["mechanical_leg"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":214,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHEESE WEDGE","unified":"1F9C0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c0.png","sheet_x":46,"sheet_y":38,"short_name":"cheese_wedge","short_names":["cheese_wedge"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":758,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CUPCAKE","unified":"1F9C1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c1.png","sheet_x":46,"sheet_y":39,"short_name":"cupcake","short_names":["cupcake"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-sweet","sort_order":813,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SALT SHAKER","unified":"1F9C2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c2.png","sheet_x":46,"sheet_y":40,"short_name":"salt","short_names":["salt"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":782,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BEVERAGE BOX","unified":"1F9C3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c3.png","sheet_x":46,"sheet_y":41,"short_name":"beverage_box","short_names":["beverage_box"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":837,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GARLIC","unified":"1F9C4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c4.png","sheet_x":46,"sheet_y":42,"short_name":"garlic","short_names":["garlic"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":742,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ONION","unified":"1F9C5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c5.png","sheet_x":46,"sheet_y":43,"short_name":"onion","short_names":["onion"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":743,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FALAFEL","unified":"1F9C6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c6.png","sheet_x":46,"sheet_y":44,"short_name":"falafel","short_names":["falafel"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":772,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WAFFLE","unified":"1F9C7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c7.png","sheet_x":46,"sheet_y":45,"short_name":"waffle","short_names":["waffle"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":757,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUTTER","unified":"1F9C8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c8.png","sheet_x":46,"sheet_y":46,"short_name":"butter","short_names":["butter"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":781,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MATE DRINK","unified":"1F9C9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9c9.png","sheet_x":46,"sheet_y":47,"short_name":"mate_drink","short_names":["mate_drink"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":838,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ICE CUBE","unified":"1F9CA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ca.png","sheet_x":46,"sheet_y":48,"short_name":"ice_cube","short_names":["ice_cube"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":839,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUBBLE TEA","unified":"1F9CB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9cb.png","sheet_x":46,"sheet_y":49,"short_name":"bubble_tea","short_names":["bubble_tea"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":836,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TROLL","unified":"1F9CC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9cc.png","sheet_x":46,"sheet_y":50,"short_name":"troll","short_names":["troll"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":401,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN STANDING","unified":"1F9CD-200D-2640-FE0F","non_qualified":"1F9CD-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9cd-200d-2640-fe0f.png","sheet_x":46,"sheet_y":51,"short_name":"woman_standing","short_names":["woman_standing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":416,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9CD-1F3FB-200D-2640-FE0F","non_qualified":"1F9CD-1F3FB-200D-2640","image":"1f9cd-1f3fb-200d-2640-fe0f.png","sheet_x":46,"sheet_y":52,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9CD-1F3FC-200D-2640-FE0F","non_qualified":"1F9CD-1F3FC-200D-2640","image":"1f9cd-1f3fc-200d-2640-fe0f.png","sheet_x":46,"sheet_y":53,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9CD-1F3FD-200D-2640-FE0F","non_qualified":"1F9CD-1F3FD-200D-2640","image":"1f9cd-1f3fd-200d-2640-fe0f.png","sheet_x":46,"sheet_y":54,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9CD-1F3FE-200D-2640-FE0F","non_qualified":"1F9CD-1F3FE-200D-2640","image":"1f9cd-1f3fe-200d-2640-fe0f.png","sheet_x":46,"sheet_y":55,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9CD-1F3FF-200D-2640-FE0F","non_qualified":"1F9CD-1F3FF-200D-2640","image":"1f9cd-1f3ff-200d-2640-fe0f.png","sheet_x":46,"sheet_y":56,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN STANDING","unified":"1F9CD-200D-2642-FE0F","non_qualified":"1F9CD-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9cd-200d-2642-fe0f.png","sheet_x":46,"sheet_y":57,"short_name":"man_standing","short_names":["man_standing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":415,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9CD-1F3FB-200D-2642-FE0F","non_qualified":"1F9CD-1F3FB-200D-2642","image":"1f9cd-1f3fb-200d-2642-fe0f.png","sheet_x":46,"sheet_y":58,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9CD-1F3FC-200D-2642-FE0F","non_qualified":"1F9CD-1F3FC-200D-2642","image":"1f9cd-1f3fc-200d-2642-fe0f.png","sheet_x":46,"sheet_y":59,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9CD-1F3FD-200D-2642-FE0F","non_qualified":"1F9CD-1F3FD-200D-2642","image":"1f9cd-1f3fd-200d-2642-fe0f.png","sheet_x":46,"sheet_y":60,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9CD-1F3FE-200D-2642-FE0F","non_qualified":"1F9CD-1F3FE-200D-2642","image":"1f9cd-1f3fe-200d-2642-fe0f.png","sheet_x":46,"sheet_y":61,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9CD-1F3FF-200D-2642-FE0F","non_qualified":"1F9CD-1F3FF-200D-2642","image":"1f9cd-1f3ff-200d-2642-fe0f.png","sheet_x":47,"sheet_y":0,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"STANDING PERSON","unified":"1F9CD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9cd.png","sheet_x":47,"sheet_y":1,"short_name":"standing_person","short_names":["standing_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":414,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9CD-1F3FB","non_qualified":null,"image":"1f9cd-1f3fb.png","sheet_x":47,"sheet_y":2,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9CD-1F3FC","non_qualified":null,"image":"1f9cd-1f3fc.png","sheet_x":47,"sheet_y":3,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9CD-1F3FD","non_qualified":null,"image":"1f9cd-1f3fd.png","sheet_x":47,"sheet_y":4,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9CD-1F3FE","non_qualified":null,"image":"1f9cd-1f3fe.png","sheet_x":47,"sheet_y":5,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9CD-1F3FF","non_qualified":null,"image":"1f9cd-1f3ff.png","sheet_x":47,"sheet_y":6,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN KNEELING","unified":"1F9CE-200D-2640-FE0F","non_qualified":"1F9CE-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ce-200d-2640-fe0f.png","sheet_x":47,"sheet_y":7,"short_name":"woman_kneeling","short_names":["woman_kneeling"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":419,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9CE-1F3FB-200D-2640-FE0F","non_qualified":"1F9CE-1F3FB-200D-2640","image":"1f9ce-1f3fb-200d-2640-fe0f.png","sheet_x":47,"sheet_y":8,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9CE-1F3FC-200D-2640-FE0F","non_qualified":"1F9CE-1F3FC-200D-2640","image":"1f9ce-1f3fc-200d-2640-fe0f.png","sheet_x":47,"sheet_y":9,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9CE-1F3FD-200D-2640-FE0F","non_qualified":"1F9CE-1F3FD-200D-2640","image":"1f9ce-1f3fd-200d-2640-fe0f.png","sheet_x":47,"sheet_y":10,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9CE-1F3FE-200D-2640-FE0F","non_qualified":"1F9CE-1F3FE-200D-2640","image":"1f9ce-1f3fe-200d-2640-fe0f.png","sheet_x":47,"sheet_y":11,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9CE-1F3FF-200D-2640-FE0F","non_qualified":"1F9CE-1F3FF-200D-2640","image":"1f9ce-1f3ff-200d-2640-fe0f.png","sheet_x":47,"sheet_y":12,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN KNEELING FACING RIGHT","unified":"1F9CE-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-200D-2640-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ce-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":13,"short_name":"woman_kneeling_facing_right","short_names":["woman_kneeling_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":421,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F9CE-1F3FB-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FB-200D-2640-200D-27A1","image":"1f9ce-1f3fb-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":14,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F9CE-1F3FC-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FC-200D-2640-200D-27A1","image":"1f9ce-1f3fc-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":15,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F9CE-1F3FD-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FD-200D-2640-200D-27A1","image":"1f9ce-1f3fd-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":16,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F9CE-1F3FE-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FE-200D-2640-200D-27A1","image":"1f9ce-1f3fe-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":17,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F9CE-1F3FF-200D-2640-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FF-200D-2640-200D-27A1","image":"1f9ce-1f3ff-200d-2640-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":18,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"MAN KNEELING","unified":"1F9CE-200D-2642-FE0F","non_qualified":"1F9CE-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ce-200d-2642-fe0f.png","sheet_x":47,"sheet_y":19,"short_name":"man_kneeling","short_names":["man_kneeling"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":418,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9CE-1F3FB-200D-2642-FE0F","non_qualified":"1F9CE-1F3FB-200D-2642","image":"1f9ce-1f3fb-200d-2642-fe0f.png","sheet_x":47,"sheet_y":20,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9CE-1F3FC-200D-2642-FE0F","non_qualified":"1F9CE-1F3FC-200D-2642","image":"1f9ce-1f3fc-200d-2642-fe0f.png","sheet_x":47,"sheet_y":21,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9CE-1F3FD-200D-2642-FE0F","non_qualified":"1F9CE-1F3FD-200D-2642","image":"1f9ce-1f3fd-200d-2642-fe0f.png","sheet_x":47,"sheet_y":22,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9CE-1F3FE-200D-2642-FE0F","non_qualified":"1F9CE-1F3FE-200D-2642","image":"1f9ce-1f3fe-200d-2642-fe0f.png","sheet_x":47,"sheet_y":23,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9CE-1F3FF-200D-2642-FE0F","non_qualified":"1F9CE-1F3FF-200D-2642","image":"1f9ce-1f3ff-200d-2642-fe0f.png","sheet_x":47,"sheet_y":24,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN KNEELING FACING RIGHT","unified":"1F9CE-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-200D-2642-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ce-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":25,"short_name":"man_kneeling_facing_right","short_names":["man_kneeling_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":422,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F9CE-1F3FB-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FB-200D-2642-200D-27A1","image":"1f9ce-1f3fb-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":26,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F9CE-1F3FC-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FC-200D-2642-200D-27A1","image":"1f9ce-1f3fc-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":27,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F9CE-1F3FD-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FD-200D-2642-200D-27A1","image":"1f9ce-1f3fd-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":28,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F9CE-1F3FE-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FE-200D-2642-200D-27A1","image":"1f9ce-1f3fe-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":29,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F9CE-1F3FF-200D-2642-FE0F-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FF-200D-2642-200D-27A1","image":"1f9ce-1f3ff-200d-2642-fe0f-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":30,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"PERSON KNEELING FACING RIGHT","unified":"1F9CE-200D-27A1-FE0F","non_qualified":"1F9CE-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ce-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":31,"short_name":"person_kneeling_facing_right","short_names":["person_kneeling_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":420,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F9CE-1F3FB-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FB-200D-27A1","image":"1f9ce-1f3fb-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":32,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F9CE-1F3FC-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FC-200D-27A1","image":"1f9ce-1f3fc-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":33,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F9CE-1F3FD-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FD-200D-27A1","image":"1f9ce-1f3fd-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":34,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F9CE-1F3FE-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FE-200D-27A1","image":"1f9ce-1f3fe-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":35,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F9CE-1F3FF-200D-27A1-FE0F","non_qualified":"1F9CE-1F3FF-200D-27A1","image":"1f9ce-1f3ff-200d-27a1-fe0f.png","sheet_x":47,"sheet_y":36,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"KNEELING PERSON","unified":"1F9CE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ce.png","sheet_x":47,"sheet_y":37,"short_name":"kneeling_person","short_names":["kneeling_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":417,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9CE-1F3FB","non_qualified":null,"image":"1f9ce-1f3fb.png","sheet_x":47,"sheet_y":38,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9CE-1F3FC","non_qualified":null,"image":"1f9ce-1f3fc.png","sheet_x":47,"sheet_y":39,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9CE-1F3FD","non_qualified":null,"image":"1f9ce-1f3fd.png","sheet_x":47,"sheet_y":40,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9CE-1F3FE","non_qualified":null,"image":"1f9ce-1f3fe.png","sheet_x":47,"sheet_y":41,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9CE-1F3FF","non_qualified":null,"image":"1f9ce-1f3ff.png","sheet_x":47,"sheet_y":42,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"DEAF WOMAN","unified":"1F9CF-200D-2640-FE0F","non_qualified":"1F9CF-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9cf-200d-2640-fe0f.png","sheet_x":47,"sheet_y":43,"short_name":"deaf_woman","short_names":["deaf_woman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":278,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9CF-1F3FB-200D-2640-FE0F","non_qualified":"1F9CF-1F3FB-200D-2640","image":"1f9cf-1f3fb-200d-2640-fe0f.png","sheet_x":47,"sheet_y":44,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9CF-1F3FC-200D-2640-FE0F","non_qualified":"1F9CF-1F3FC-200D-2640","image":"1f9cf-1f3fc-200d-2640-fe0f.png","sheet_x":47,"sheet_y":45,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9CF-1F3FD-200D-2640-FE0F","non_qualified":"1F9CF-1F3FD-200D-2640","image":"1f9cf-1f3fd-200d-2640-fe0f.png","sheet_x":47,"sheet_y":46,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9CF-1F3FE-200D-2640-FE0F","non_qualified":"1F9CF-1F3FE-200D-2640","image":"1f9cf-1f3fe-200d-2640-fe0f.png","sheet_x":47,"sheet_y":47,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9CF-1F3FF-200D-2640-FE0F","non_qualified":"1F9CF-1F3FF-200D-2640","image":"1f9cf-1f3ff-200d-2640-fe0f.png","sheet_x":47,"sheet_y":48,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"DEAF MAN","unified":"1F9CF-200D-2642-FE0F","non_qualified":"1F9CF-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9cf-200d-2642-fe0f.png","sheet_x":47,"sheet_y":49,"short_name":"deaf_man","short_names":["deaf_man"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":277,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9CF-1F3FB-200D-2642-FE0F","non_qualified":"1F9CF-1F3FB-200D-2642","image":"1f9cf-1f3fb-200d-2642-fe0f.png","sheet_x":47,"sheet_y":50,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9CF-1F3FC-200D-2642-FE0F","non_qualified":"1F9CF-1F3FC-200D-2642","image":"1f9cf-1f3fc-200d-2642-fe0f.png","sheet_x":47,"sheet_y":51,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9CF-1F3FD-200D-2642-FE0F","non_qualified":"1F9CF-1F3FD-200D-2642","image":"1f9cf-1f3fd-200d-2642-fe0f.png","sheet_x":47,"sheet_y":52,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9CF-1F3FE-200D-2642-FE0F","non_qualified":"1F9CF-1F3FE-200D-2642","image":"1f9cf-1f3fe-200d-2642-fe0f.png","sheet_x":47,"sheet_y":53,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9CF-1F3FF-200D-2642-FE0F","non_qualified":"1F9CF-1F3FF-200D-2642","image":"1f9cf-1f3ff-200d-2642-fe0f.png","sheet_x":47,"sheet_y":54,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"DEAF PERSON","unified":"1F9CF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9cf.png","sheet_x":47,"sheet_y":55,"short_name":"deaf_person","short_names":["deaf_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-gesture","sort_order":276,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9CF-1F3FB","non_qualified":null,"image":"1f9cf-1f3fb.png","sheet_x":47,"sheet_y":56,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9CF-1F3FC","non_qualified":null,"image":"1f9cf-1f3fc.png","sheet_x":47,"sheet_y":57,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9CF-1F3FD","non_qualified":null,"image":"1f9cf-1f3fd.png","sheet_x":47,"sheet_y":58,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9CF-1F3FE","non_qualified":null,"image":"1f9cf-1f3fe.png","sheet_x":47,"sheet_y":59,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9CF-1F3FF","non_qualified":null,"image":"1f9cf-1f3ff.png","sheet_x":47,"sheet_y":60,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FACE WITH MONOCLE","unified":"1F9D0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d0.png","sheet_x":47,"sheet_y":61,"short_name":"face_with_monocle","short_names":["face_with_monocle"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-glasses","sort_order":75,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FARMER","unified":"1F9D1-200D-1F33E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f33e.png","sheet_x":48,"sheet_y":0,"short_name":"farmer","short_names":["farmer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":300,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F33E","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f33e.png","sheet_x":48,"sheet_y":1,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F33E","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f33e.png","sheet_x":48,"sheet_y":2,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F33E","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f33e.png","sheet_x":48,"sheet_y":3,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F33E","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f33e.png","sheet_x":48,"sheet_y":4,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F33E","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f33e.png","sheet_x":48,"sheet_y":5,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"COOK","unified":"1F9D1-200D-1F373","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f373.png","sheet_x":48,"sheet_y":6,"short_name":"cook","short_names":["cook"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":303,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F373","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f373.png","sheet_x":48,"sheet_y":7,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F373","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f373.png","sheet_x":48,"sheet_y":8,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F373","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f373.png","sheet_x":48,"sheet_y":9,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F373","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f373.png","sheet_x":48,"sheet_y":10,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F373","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f373.png","sheet_x":48,"sheet_y":11,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON FEEDING BABY","unified":"1F9D1-200D-1F37C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f37c.png","sheet_x":48,"sheet_y":12,"short_name":"person_feeding_baby","short_names":["person_feeding_baby"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":369,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F37C","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f37c.png","sheet_x":48,"sheet_y":13,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F37C","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f37c.png","sheet_x":48,"sheet_y":14,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F37C","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f37c.png","sheet_x":48,"sheet_y":15,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F37C","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f37c.png","sheet_x":48,"sheet_y":16,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F37C","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f37c.png","sheet_x":48,"sheet_y":17,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MX CLAUS","unified":"1F9D1-200D-1F384","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f384.png","sheet_x":48,"sheet_y":18,"short_name":"mx_claus","short_names":["mx_claus"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":373,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F384","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f384.png","sheet_x":48,"sheet_y":19,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F384","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f384.png","sheet_x":48,"sheet_y":20,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F384","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f384.png","sheet_x":48,"sheet_y":21,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F384","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f384.png","sheet_x":48,"sheet_y":22,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F384","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f384.png","sheet_x":48,"sheet_y":23,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"STUDENT","unified":"1F9D1-200D-1F393","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f393.png","sheet_x":48,"sheet_y":24,"short_name":"student","short_names":["student"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":291,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F393","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f393.png","sheet_x":48,"sheet_y":25,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F393","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f393.png","sheet_x":48,"sheet_y":26,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F393","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f393.png","sheet_x":48,"sheet_y":27,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F393","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f393.png","sheet_x":48,"sheet_y":28,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F393","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f393.png","sheet_x":48,"sheet_y":29,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SINGER","unified":"1F9D1-200D-1F3A4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f3a4.png","sheet_x":48,"sheet_y":30,"short_name":"singer","short_names":["singer"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":321,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F3A4","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f3a4.png","sheet_x":48,"sheet_y":31,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F3A4","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f3a4.png","sheet_x":48,"sheet_y":32,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F3A4","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f3a4.png","sheet_x":48,"sheet_y":33,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F3A4","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f3a4.png","sheet_x":48,"sheet_y":34,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F3A4","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f3a4.png","sheet_x":48,"sheet_y":35,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"ARTIST","unified":"1F9D1-200D-1F3A8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f3a8.png","sheet_x":48,"sheet_y":36,"short_name":"artist","short_names":["artist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":324,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F3A8","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f3a8.png","sheet_x":48,"sheet_y":37,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F3A8","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f3a8.png","sheet_x":48,"sheet_y":38,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F3A8","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f3a8.png","sheet_x":48,"sheet_y":39,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F3A8","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f3a8.png","sheet_x":48,"sheet_y":40,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F3A8","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f3a8.png","sheet_x":48,"sheet_y":41,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"TEACHER","unified":"1F9D1-200D-1F3EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f3eb.png","sheet_x":48,"sheet_y":42,"short_name":"teacher","short_names":["teacher"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":294,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F3EB","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f3eb.png","sheet_x":48,"sheet_y":43,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F3EB","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f3eb.png","sheet_x":48,"sheet_y":44,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F3EB","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f3eb.png","sheet_x":48,"sheet_y":45,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F3EB","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f3eb.png","sheet_x":48,"sheet_y":46,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F3EB","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f3eb.png","sheet_x":48,"sheet_y":47,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FACTORY WORKER","unified":"1F9D1-200D-1F3ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f3ed.png","sheet_x":48,"sheet_y":48,"short_name":"factory_worker","short_names":["factory_worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":309,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F3ED","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f3ed.png","sheet_x":48,"sheet_y":49,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F3ED","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f3ed.png","sheet_x":48,"sheet_y":50,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F3ED","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f3ed.png","sheet_x":48,"sheet_y":51,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F3ED","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f3ed.png","sheet_x":48,"sheet_y":52,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F3ED","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f3ed.png","sheet_x":48,"sheet_y":53,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"TECHNOLOGIST","unified":"1F9D1-200D-1F4BB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f4bb.png","sheet_x":48,"sheet_y":54,"short_name":"technologist","short_names":["technologist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":318,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F4BB","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f4bb.png","sheet_x":48,"sheet_y":55,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F4BB","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f4bb.png","sheet_x":48,"sheet_y":56,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F4BB","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f4bb.png","sheet_x":48,"sheet_y":57,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F4BB","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f4bb.png","sheet_x":48,"sheet_y":58,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F4BB","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f4bb.png","sheet_x":48,"sheet_y":59,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"OFFICE WORKER","unified":"1F9D1-200D-1F4BC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f4bc.png","sheet_x":48,"sheet_y":60,"short_name":"office_worker","short_names":["office_worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":312,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F4BC","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f4bc.png","sheet_x":48,"sheet_y":61,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F4BC","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f4bc.png","sheet_x":49,"sheet_y":0,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F4BC","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f4bc.png","sheet_x":49,"sheet_y":1,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F4BC","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f4bc.png","sheet_x":49,"sheet_y":2,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F4BC","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f4bc.png","sheet_x":49,"sheet_y":3,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MECHANIC","unified":"1F9D1-200D-1F527","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f527.png","sheet_x":49,"sheet_y":4,"short_name":"mechanic","short_names":["mechanic"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":306,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F527","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f527.png","sheet_x":49,"sheet_y":5,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F527","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f527.png","sheet_x":49,"sheet_y":6,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F527","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f527.png","sheet_x":49,"sheet_y":7,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F527","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f527.png","sheet_x":49,"sheet_y":8,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F527","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f527.png","sheet_x":49,"sheet_y":9,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SCIENTIST","unified":"1F9D1-200D-1F52C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f52c.png","sheet_x":49,"sheet_y":10,"short_name":"scientist","short_names":["scientist"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":315,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F52C","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f52c.png","sheet_x":49,"sheet_y":11,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F52C","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f52c.png","sheet_x":49,"sheet_y":12,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F52C","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f52c.png","sheet_x":49,"sheet_y":13,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F52C","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f52c.png","sheet_x":49,"sheet_y":14,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F52C","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f52c.png","sheet_x":49,"sheet_y":15,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"ASTRONAUT","unified":"1F9D1-200D-1F680","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f680.png","sheet_x":49,"sheet_y":16,"short_name":"astronaut","short_names":["astronaut"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":330,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F680","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f680.png","sheet_x":49,"sheet_y":17,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F680","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f680.png","sheet_x":49,"sheet_y":18,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F680","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f680.png","sheet_x":49,"sheet_y":19,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F680","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f680.png","sheet_x":49,"sheet_y":20,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F680","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f680.png","sheet_x":49,"sheet_y":21,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FIREFIGHTER","unified":"1F9D1-200D-1F692","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f692.png","sheet_x":49,"sheet_y":22,"short_name":"firefighter","short_names":["firefighter"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":333,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F692","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f692.png","sheet_x":49,"sheet_y":23,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F692","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f692.png","sheet_x":49,"sheet_y":24,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F692","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f692.png","sheet_x":49,"sheet_y":25,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F692","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f692.png","sheet_x":49,"sheet_y":26,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F692","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f692.png","sheet_x":49,"sheet_y":27,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PEOPLE HOLDING HANDS","unified":"1F9D1-200D-1F91D-200D-1F9D1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f91d-200d-1f9d1.png","sheet_x":49,"sheet_y":28,"short_name":"people_holding_hands","short_names":["people_holding_hands"],"text":null,"texts":null,"category":"People & Body","subcategory":"family","sort_order":507,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB-1F3FB":{"unified":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FB","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f91d-200d-1f9d1-1f3fb.png","sheet_x":49,"sheet_y":29,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FC":{"unified":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FC","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f91d-200d-1f9d1-1f3fc.png","sheet_x":49,"sheet_y":30,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FD":{"unified":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FD","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f91d-200d-1f9d1-1f3fd.png","sheet_x":49,"sheet_y":31,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FE":{"unified":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FE","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f91d-200d-1f9d1-1f3fe.png","sheet_x":49,"sheet_y":32,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FB-1F3FF":{"unified":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FF","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f91d-200d-1f9d1-1f3ff.png","sheet_x":49,"sheet_y":33,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FB":{"unified":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FB","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f91d-200d-1f9d1-1f3fb.png","sheet_x":49,"sheet_y":34,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FC":{"unified":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FC","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f91d-200d-1f9d1-1f3fc.png","sheet_x":49,"sheet_y":35,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FD":{"unified":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FD","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f91d-200d-1f9d1-1f3fd.png","sheet_x":49,"sheet_y":36,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FE":{"unified":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FE","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f91d-200d-1f9d1-1f3fe.png","sheet_x":49,"sheet_y":37,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC-1F3FF":{"unified":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FF","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f91d-200d-1f9d1-1f3ff.png","sheet_x":49,"sheet_y":38,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FB":{"unified":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FB","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f91d-200d-1f9d1-1f3fb.png","sheet_x":49,"sheet_y":39,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FC":{"unified":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FC","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f91d-200d-1f9d1-1f3fc.png","sheet_x":49,"sheet_y":40,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FD":{"unified":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FD","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f91d-200d-1f9d1-1f3fd.png","sheet_x":49,"sheet_y":41,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FE":{"unified":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FE","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f91d-200d-1f9d1-1f3fe.png","sheet_x":49,"sheet_y":42,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD-1F3FF":{"unified":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FF","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f91d-200d-1f9d1-1f3ff.png","sheet_x":49,"sheet_y":43,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FB":{"unified":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FB","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f91d-200d-1f9d1-1f3fb.png","sheet_x":49,"sheet_y":44,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FC":{"unified":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FC","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f91d-200d-1f9d1-1f3fc.png","sheet_x":49,"sheet_y":45,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FD":{"unified":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FD","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f91d-200d-1f9d1-1f3fd.png","sheet_x":49,"sheet_y":46,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FE":{"unified":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FE","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f91d-200d-1f9d1-1f3fe.png","sheet_x":49,"sheet_y":47,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE-1F3FF":{"unified":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FF","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f91d-200d-1f9d1-1f3ff.png","sheet_x":49,"sheet_y":48,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FB":{"unified":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FB","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f91d-200d-1f9d1-1f3fb.png","sheet_x":49,"sheet_y":49,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FC":{"unified":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FC","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f91d-200d-1f9d1-1f3fc.png","sheet_x":49,"sheet_y":50,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FD":{"unified":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FD","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f91d-200d-1f9d1-1f3fd.png","sheet_x":49,"sheet_y":51,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FE":{"unified":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FE","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f91d-200d-1f9d1-1f3fe.png","sheet_x":49,"sheet_y":52,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF-1F3FF":{"unified":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FF","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f91d-200d-1f9d1-1f3ff.png","sheet_x":49,"sheet_y":53,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON WITH WHITE CANE FACING RIGHT","unified":"1F9D1-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F9D1-200D-1F9AF-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9af-200d-27a1-fe0f.png","sheet_x":49,"sheet_y":54,"short_name":"person_with_white_cane_facing_right","short_names":["person_with_white_cane_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":424,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FB-200D-1F9AF-200D-27A1","image":"1f9d1-1f3fb-200d-1f9af-200d-27a1-fe0f.png","sheet_x":49,"sheet_y":55,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FC-200D-1F9AF-200D-27A1","image":"1f9d1-1f3fc-200d-1f9af-200d-27a1-fe0f.png","sheet_x":49,"sheet_y":56,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FD-200D-1F9AF-200D-27A1","image":"1f9d1-1f3fd-200d-1f9af-200d-27a1-fe0f.png","sheet_x":49,"sheet_y":57,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FE-200D-1F9AF-200D-27A1","image":"1f9d1-1f3fe-200d-1f9af-200d-27a1-fe0f.png","sheet_x":49,"sheet_y":58,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9AF-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FF-200D-1F9AF-200D-27A1","image":"1f9d1-1f3ff-200d-1f9af-200d-27a1-fe0f.png","sheet_x":49,"sheet_y":59,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"PERSON WITH WHITE CANE","unified":"1F9D1-200D-1F9AF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9af.png","sheet_x":49,"sheet_y":60,"short_name":"person_with_probing_cane","short_names":["person_with_probing_cane"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":423,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9AF","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f9af.png","sheet_x":49,"sheet_y":61,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9AF","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f9af.png","sheet_x":50,"sheet_y":0,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9AF","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f9af.png","sheet_x":50,"sheet_y":1,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9AF","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f9af.png","sheet_x":50,"sheet_y":2,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9AF","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f9af.png","sheet_x":50,"sheet_y":3,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON: RED HAIR","unified":"1F9D1-200D-1F9B0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9b0.png","sheet_x":50,"sheet_y":4,"short_name":"red_haired_person","short_names":["red_haired_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":246,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9B0","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f9b0.png","sheet_x":50,"sheet_y":5,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9B0","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f9b0.png","sheet_x":50,"sheet_y":6,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9B0","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f9b0.png","sheet_x":50,"sheet_y":7,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9B0","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f9b0.png","sheet_x":50,"sheet_y":8,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9B0","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f9b0.png","sheet_x":50,"sheet_y":9,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON: CURLY HAIR","unified":"1F9D1-200D-1F9B1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9b1.png","sheet_x":50,"sheet_y":10,"short_name":"curly_haired_person","short_names":["curly_haired_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":248,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9B1","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f9b1.png","sheet_x":50,"sheet_y":11,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9B1","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f9b1.png","sheet_x":50,"sheet_y":12,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9B1","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f9b1.png","sheet_x":50,"sheet_y":13,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9B1","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f9b1.png","sheet_x":50,"sheet_y":14,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9B1","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f9b1.png","sheet_x":50,"sheet_y":15,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON: BALD","unified":"1F9D1-200D-1F9B2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9b2.png","sheet_x":50,"sheet_y":16,"short_name":"bald_person","short_names":["bald_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":252,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9B2","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f9b2.png","sheet_x":50,"sheet_y":17,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9B2","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f9b2.png","sheet_x":50,"sheet_y":18,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9B2","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f9b2.png","sheet_x":50,"sheet_y":19,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9B2","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f9b2.png","sheet_x":50,"sheet_y":20,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9B2","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f9b2.png","sheet_x":50,"sheet_y":21,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON: WHITE HAIR","unified":"1F9D1-200D-1F9B3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9b3.png","sheet_x":50,"sheet_y":22,"short_name":"white_haired_person","short_names":["white_haired_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":250,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9B3","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f9b3.png","sheet_x":50,"sheet_y":23,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9B3","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f9b3.png","sheet_x":50,"sheet_y":24,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9B3","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f9b3.png","sheet_x":50,"sheet_y":25,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9B3","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f9b3.png","sheet_x":50,"sheet_y":26,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9B3","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f9b3.png","sheet_x":50,"sheet_y":27,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON IN MOTORIZED WHEELCHAIR FACING RIGHT","unified":"1F9D1-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F9D1-200D-1F9BC-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":28,"short_name":"person_in_motorized_wheelchair_facing_right","short_names":["person_in_motorized_wheelchair_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":430,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FB-200D-1F9BC-200D-27A1","image":"1f9d1-1f3fb-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":29,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FC-200D-1F9BC-200D-27A1","image":"1f9d1-1f3fc-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":30,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FD-200D-1F9BC-200D-27A1","image":"1f9d1-1f3fd-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":31,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FE-200D-1F9BC-200D-27A1","image":"1f9d1-1f3fe-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":32,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9BC-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FF-200D-1F9BC-200D-27A1","image":"1f9d1-1f3ff-200d-1f9bc-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":33,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"PERSON IN MOTORIZED WHEELCHAIR","unified":"1F9D1-200D-1F9BC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9bc.png","sheet_x":50,"sheet_y":34,"short_name":"person_in_motorized_wheelchair","short_names":["person_in_motorized_wheelchair"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":429,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9BC","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f9bc.png","sheet_x":50,"sheet_y":35,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9BC","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f9bc.png","sheet_x":50,"sheet_y":36,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9BC","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f9bc.png","sheet_x":50,"sheet_y":37,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9BC","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f9bc.png","sheet_x":50,"sheet_y":38,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9BC","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f9bc.png","sheet_x":50,"sheet_y":39,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON IN MANUAL WHEELCHAIR FACING RIGHT","unified":"1F9D1-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F9D1-200D-1F9BD-200D-27A1","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":40,"short_name":"person_in_manual_wheelchair_facing_right","short_names":["person_in_manual_wheelchair_facing_right"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":436,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FB-200D-1F9BD-200D-27A1","image":"1f9d1-1f3fb-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":41,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FC-200D-1F9BD-200D-27A1","image":"1f9d1-1f3fc-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":42,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FD-200D-1F9BD-200D-27A1","image":"1f9d1-1f3fd-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":43,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FE-200D-1F9BD-200D-27A1","image":"1f9d1-1f3fe-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":44,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9BD-200D-27A1-FE0F","non_qualified":"1F9D1-1F3FF-200D-1F9BD-200D-27A1","image":"1f9d1-1f3ff-200d-1f9bd-200d-27a1-fe0f.png","sheet_x":50,"sheet_y":45,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false}}},{"name":"PERSON IN MANUAL WHEELCHAIR","unified":"1F9D1-200D-1F9BD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9bd.png","sheet_x":50,"sheet_y":46,"short_name":"person_in_manual_wheelchair","short_names":["person_in_manual_wheelchair"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":435,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-1F9BD","non_qualified":null,"image":"1f9d1-1f3fb-200d-1f9bd.png","sheet_x":50,"sheet_y":47,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-1F9BD","non_qualified":null,"image":"1f9d1-1f3fc-200d-1f9bd.png","sheet_x":50,"sheet_y":48,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-1F9BD","non_qualified":null,"image":"1f9d1-1f3fd-200d-1f9bd.png","sheet_x":50,"sheet_y":49,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-1F9BD","non_qualified":null,"image":"1f9d1-1f3fe-200d-1f9bd.png","sheet_x":50,"sheet_y":50,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-1F9BD","non_qualified":null,"image":"1f9d1-1f3ff-200d-1f9bd.png","sheet_x":50,"sheet_y":51,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FAMILY: ADULT, ADULT, CHILD","unified":"1F9D1-200D-1F9D1-200D-1F9D2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9d1-200d-1f9d2.png","sheet_x":50,"sheet_y":52,"short_name":"family_adult_adult_child","short_names":["family_adult_adult_child"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":549,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"FAMILY: ADULT, ADULT, CHILD, CHILD","unified":"1F9D1-200D-1F9D1-200D-1F9D2-200D-1F9D2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9d1-200d-1f9d2-200d-1f9d2.png","sheet_x":50,"sheet_y":53,"short_name":"family_adult_adult_child_child","short_names":["family_adult_adult_child_child"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":550,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"FAMILY: ADULT, CHILD, CHILD","unified":"1F9D1-200D-1F9D2-200D-1F9D2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9d2-200d-1f9d2.png","sheet_x":50,"sheet_y":54,"short_name":"family_adult_child_child","short_names":["family_adult_child_child"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":552,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"FAMILY: ADULT, CHILD","unified":"1F9D1-200D-1F9D2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-1f9d2.png","sheet_x":50,"sheet_y":55,"short_name":"family_adult_child","short_names":["family_adult_child"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":551,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"HEALTH WORKER","unified":"1F9D1-200D-2695-FE0F","non_qualified":"1F9D1-200D-2695","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-2695-fe0f.png","sheet_x":50,"sheet_y":56,"short_name":"health_worker","short_names":["health_worker"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":288,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-2695-FE0F","non_qualified":"1F9D1-1F3FB-200D-2695","image":"1f9d1-1f3fb-200d-2695-fe0f.png","sheet_x":50,"sheet_y":57,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-2695-FE0F","non_qualified":"1F9D1-1F3FC-200D-2695","image":"1f9d1-1f3fc-200d-2695-fe0f.png","sheet_x":50,"sheet_y":58,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-2695-FE0F","non_qualified":"1F9D1-1F3FD-200D-2695","image":"1f9d1-1f3fd-200d-2695-fe0f.png","sheet_x":50,"sheet_y":59,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-2695-FE0F","non_qualified":"1F9D1-1F3FE-200D-2695","image":"1f9d1-1f3fe-200d-2695-fe0f.png","sheet_x":50,"sheet_y":60,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-2695-FE0F","non_qualified":"1F9D1-1F3FF-200D-2695","image":"1f9d1-1f3ff-200d-2695-fe0f.png","sheet_x":50,"sheet_y":61,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"JUDGE","unified":"1F9D1-200D-2696-FE0F","non_qualified":"1F9D1-200D-2696","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-2696-fe0f.png","sheet_x":51,"sheet_y":0,"short_name":"judge","short_names":["judge"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":297,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-2696-FE0F","non_qualified":"1F9D1-1F3FB-200D-2696","image":"1f9d1-1f3fb-200d-2696-fe0f.png","sheet_x":51,"sheet_y":1,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-2696-FE0F","non_qualified":"1F9D1-1F3FC-200D-2696","image":"1f9d1-1f3fc-200d-2696-fe0f.png","sheet_x":51,"sheet_y":2,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-2696-FE0F","non_qualified":"1F9D1-1F3FD-200D-2696","image":"1f9d1-1f3fd-200d-2696-fe0f.png","sheet_x":51,"sheet_y":3,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-2696-FE0F","non_qualified":"1F9D1-1F3FE-200D-2696","image":"1f9d1-1f3fe-200d-2696-fe0f.png","sheet_x":51,"sheet_y":4,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-2696-FE0F","non_qualified":"1F9D1-1F3FF-200D-2696","image":"1f9d1-1f3ff-200d-2696-fe0f.png","sheet_x":51,"sheet_y":5,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PILOT","unified":"1F9D1-200D-2708-FE0F","non_qualified":"1F9D1-200D-2708","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1-200d-2708-fe0f.png","sheet_x":51,"sheet_y":6,"short_name":"pilot","short_names":["pilot"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":327,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB-200D-2708-FE0F","non_qualified":"1F9D1-1F3FB-200D-2708","image":"1f9d1-1f3fb-200d-2708-fe0f.png","sheet_x":51,"sheet_y":7,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC-200D-2708-FE0F","non_qualified":"1F9D1-1F3FC-200D-2708","image":"1f9d1-1f3fc-200d-2708-fe0f.png","sheet_x":51,"sheet_y":8,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD-200D-2708-FE0F","non_qualified":"1F9D1-1F3FD-200D-2708","image":"1f9d1-1f3fd-200d-2708-fe0f.png","sheet_x":51,"sheet_y":9,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE-200D-2708-FE0F","non_qualified":"1F9D1-1F3FE-200D-2708","image":"1f9d1-1f3fe-200d-2708-fe0f.png","sheet_x":51,"sheet_y":10,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF-200D-2708-FE0F","non_qualified":"1F9D1-1F3FF-200D-2708","image":"1f9d1-1f3ff-200d-2708-fe0f.png","sheet_x":51,"sheet_y":11,"added_in":"12.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"ADULT","unified":"1F9D1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d1.png","sheet_x":51,"sheet_y":12,"short_name":"adult","short_names":["adult"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":234,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D1-1F3FB","non_qualified":null,"image":"1f9d1-1f3fb.png","sheet_x":51,"sheet_y":13,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D1-1F3FC","non_qualified":null,"image":"1f9d1-1f3fc.png","sheet_x":51,"sheet_y":14,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D1-1F3FD","non_qualified":null,"image":"1f9d1-1f3fd.png","sheet_x":51,"sheet_y":15,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D1-1F3FE","non_qualified":null,"image":"1f9d1-1f3fe.png","sheet_x":51,"sheet_y":16,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D1-1F3FF","non_qualified":null,"image":"1f9d1-1f3ff.png","sheet_x":51,"sheet_y":17,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"CHILD","unified":"1F9D2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d2.png","sheet_x":51,"sheet_y":18,"short_name":"child","short_names":["child"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":231,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D2-1F3FB","non_qualified":null,"image":"1f9d2-1f3fb.png","sheet_x":51,"sheet_y":19,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D2-1F3FC","non_qualified":null,"image":"1f9d2-1f3fc.png","sheet_x":51,"sheet_y":20,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D2-1F3FD","non_qualified":null,"image":"1f9d2-1f3fd.png","sheet_x":51,"sheet_y":21,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D2-1F3FE","non_qualified":null,"image":"1f9d2-1f3fe.png","sheet_x":51,"sheet_y":22,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D2-1F3FF","non_qualified":null,"image":"1f9d2-1f3ff.png","sheet_x":51,"sheet_y":23,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"OLDER ADULT","unified":"1F9D3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d3.png","sheet_x":51,"sheet_y":24,"short_name":"older_adult","short_names":["older_adult"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":255,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D3-1F3FB","non_qualified":null,"image":"1f9d3-1f3fb.png","sheet_x":51,"sheet_y":25,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D3-1F3FC","non_qualified":null,"image":"1f9d3-1f3fc.png","sheet_x":51,"sheet_y":26,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D3-1F3FD","non_qualified":null,"image":"1f9d3-1f3fd.png","sheet_x":51,"sheet_y":27,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D3-1F3FE","non_qualified":null,"image":"1f9d3-1f3fe.png","sheet_x":51,"sheet_y":28,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D3-1F3FF","non_qualified":null,"image":"1f9d3-1f3ff.png","sheet_x":51,"sheet_y":29,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN: BEARD","unified":"1F9D4-200D-2640-FE0F","non_qualified":"1F9D4-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d4-200d-2640-fe0f.png","sheet_x":51,"sheet_y":30,"short_name":"woman_with_beard","short_names":["woman_with_beard"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":239,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D4-1F3FB-200D-2640-FE0F","non_qualified":"1F9D4-1F3FB-200D-2640","image":"1f9d4-1f3fb-200d-2640-fe0f.png","sheet_x":51,"sheet_y":31,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D4-1F3FC-200D-2640-FE0F","non_qualified":"1F9D4-1F3FC-200D-2640","image":"1f9d4-1f3fc-200d-2640-fe0f.png","sheet_x":51,"sheet_y":32,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D4-1F3FD-200D-2640-FE0F","non_qualified":"1F9D4-1F3FD-200D-2640","image":"1f9d4-1f3fd-200d-2640-fe0f.png","sheet_x":51,"sheet_y":33,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D4-1F3FE-200D-2640-FE0F","non_qualified":"1F9D4-1F3FE-200D-2640","image":"1f9d4-1f3fe-200d-2640-fe0f.png","sheet_x":51,"sheet_y":34,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D4-1F3FF-200D-2640-FE0F","non_qualified":"1F9D4-1F3FF-200D-2640","image":"1f9d4-1f3ff-200d-2640-fe0f.png","sheet_x":51,"sheet_y":35,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN: BEARD","unified":"1F9D4-200D-2642-FE0F","non_qualified":"1F9D4-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d4-200d-2642-fe0f.png","sheet_x":51,"sheet_y":36,"short_name":"man_with_beard","short_names":["man_with_beard"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":238,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D4-1F3FB-200D-2642-FE0F","non_qualified":"1F9D4-1F3FB-200D-2642","image":"1f9d4-1f3fb-200d-2642-fe0f.png","sheet_x":51,"sheet_y":37,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D4-1F3FC-200D-2642-FE0F","non_qualified":"1F9D4-1F3FC-200D-2642","image":"1f9d4-1f3fc-200d-2642-fe0f.png","sheet_x":51,"sheet_y":38,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D4-1F3FD-200D-2642-FE0F","non_qualified":"1F9D4-1F3FD-200D-2642","image":"1f9d4-1f3fd-200d-2642-fe0f.png","sheet_x":51,"sheet_y":39,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D4-1F3FE-200D-2642-FE0F","non_qualified":"1F9D4-1F3FE-200D-2642","image":"1f9d4-1f3fe-200d-2642-fe0f.png","sheet_x":51,"sheet_y":40,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D4-1F3FF-200D-2642-FE0F","non_qualified":"1F9D4-1F3FF-200D-2642","image":"1f9d4-1f3ff-200d-2642-fe0f.png","sheet_x":51,"sheet_y":41,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"BEARDED PERSON","unified":"1F9D4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d4.png","sheet_x":51,"sheet_y":42,"short_name":"bearded_person","short_names":["bearded_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person","sort_order":237,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D4-1F3FB","non_qualified":null,"image":"1f9d4-1f3fb.png","sheet_x":51,"sheet_y":43,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D4-1F3FC","non_qualified":null,"image":"1f9d4-1f3fc.png","sheet_x":51,"sheet_y":44,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D4-1F3FD","non_qualified":null,"image":"1f9d4-1f3fd.png","sheet_x":51,"sheet_y":45,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D4-1F3FE","non_qualified":null,"image":"1f9d4-1f3fe.png","sheet_x":51,"sheet_y":46,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D4-1F3FF","non_qualified":null,"image":"1f9d4-1f3ff.png","sheet_x":51,"sheet_y":47,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON WITH HEADSCARF","unified":"1F9D5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d5.png","sheet_x":51,"sheet_y":48,"short_name":"person_with_headscarf","short_names":["person_with_headscarf"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":356,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D5-1F3FB","non_qualified":null,"image":"1f9d5-1f3fb.png","sheet_x":51,"sheet_y":49,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D5-1F3FC","non_qualified":null,"image":"1f9d5-1f3fc.png","sheet_x":51,"sheet_y":50,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D5-1F3FD","non_qualified":null,"image":"1f9d5-1f3fd.png","sheet_x":51,"sheet_y":51,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D5-1F3FE","non_qualified":null,"image":"1f9d5-1f3fe.png","sheet_x":51,"sheet_y":52,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D5-1F3FF","non_qualified":null,"image":"1f9d5-1f3ff.png","sheet_x":51,"sheet_y":53,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WOMAN IN STEAMY ROOM","unified":"1F9D6-200D-2640-FE0F","non_qualified":"1F9D6-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d6-200d-2640-fe0f.png","sheet_x":51,"sheet_y":54,"short_name":"woman_in_steamy_room","short_names":["woman_in_steamy_room"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":455,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D6-1F3FB-200D-2640-FE0F","non_qualified":"1F9D6-1F3FB-200D-2640","image":"1f9d6-1f3fb-200d-2640-fe0f.png","sheet_x":51,"sheet_y":55,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D6-1F3FC-200D-2640-FE0F","non_qualified":"1F9D6-1F3FC-200D-2640","image":"1f9d6-1f3fc-200d-2640-fe0f.png","sheet_x":51,"sheet_y":56,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D6-1F3FD-200D-2640-FE0F","non_qualified":"1F9D6-1F3FD-200D-2640","image":"1f9d6-1f3fd-200d-2640-fe0f.png","sheet_x":51,"sheet_y":57,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D6-1F3FE-200D-2640-FE0F","non_qualified":"1F9D6-1F3FE-200D-2640","image":"1f9d6-1f3fe-200d-2640-fe0f.png","sheet_x":51,"sheet_y":58,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D6-1F3FF-200D-2640-FE0F","non_qualified":"1F9D6-1F3FF-200D-2640","image":"1f9d6-1f3ff-200d-2640-fe0f.png","sheet_x":51,"sheet_y":59,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN IN STEAMY ROOM","unified":"1F9D6-200D-2642-FE0F","non_qualified":"1F9D6-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d6-200d-2642-fe0f.png","sheet_x":51,"sheet_y":60,"short_name":"man_in_steamy_room","short_names":["man_in_steamy_room"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":454,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D6-1F3FB-200D-2642-FE0F","non_qualified":"1F9D6-1F3FB-200D-2642","image":"1f9d6-1f3fb-200d-2642-fe0f.png","sheet_x":51,"sheet_y":61,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D6-1F3FB"},"1F3FC":{"unified":"1F9D6-1F3FC-200D-2642-FE0F","non_qualified":"1F9D6-1F3FC-200D-2642","image":"1f9d6-1f3fc-200d-2642-fe0f.png","sheet_x":52,"sheet_y":0,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D6-1F3FC"},"1F3FD":{"unified":"1F9D6-1F3FD-200D-2642-FE0F","non_qualified":"1F9D6-1F3FD-200D-2642","image":"1f9d6-1f3fd-200d-2642-fe0f.png","sheet_x":52,"sheet_y":1,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D6-1F3FD"},"1F3FE":{"unified":"1F9D6-1F3FE-200D-2642-FE0F","non_qualified":"1F9D6-1F3FE-200D-2642","image":"1f9d6-1f3fe-200d-2642-fe0f.png","sheet_x":52,"sheet_y":2,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D6-1F3FE"},"1F3FF":{"unified":"1F9D6-1F3FF-200D-2642-FE0F","non_qualified":"1F9D6-1F3FF-200D-2642","image":"1f9d6-1f3ff-200d-2642-fe0f.png","sheet_x":52,"sheet_y":3,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D6-1F3FF"}},"obsoletes":"1F9D6"},{"name":"PERSON IN STEAMY ROOM","unified":"1F9D6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d6.png","sheet_x":52,"sheet_y":4,"short_name":"person_in_steamy_room","short_names":["person_in_steamy_room"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":453,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D6-1F3FB","non_qualified":null,"image":"1f9d6-1f3fb.png","sheet_x":52,"sheet_y":5,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D6-1F3FB-200D-2642-FE0F"},"1F3FC":{"unified":"1F9D6-1F3FC","non_qualified":null,"image":"1f9d6-1f3fc.png","sheet_x":52,"sheet_y":6,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D6-1F3FC-200D-2642-FE0F"},"1F3FD":{"unified":"1F9D6-1F3FD","non_qualified":null,"image":"1f9d6-1f3fd.png","sheet_x":52,"sheet_y":7,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D6-1F3FD-200D-2642-FE0F"},"1F3FE":{"unified":"1F9D6-1F3FE","non_qualified":null,"image":"1f9d6-1f3fe.png","sheet_x":52,"sheet_y":8,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D6-1F3FE-200D-2642-FE0F"},"1F3FF":{"unified":"1F9D6-1F3FF","non_qualified":null,"image":"1f9d6-1f3ff.png","sheet_x":52,"sheet_y":9,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D6-1F3FF-200D-2642-FE0F"}},"obsoleted_by":"1F9D6-200D-2642-FE0F"},{"name":"WOMAN CLIMBING","unified":"1F9D7-200D-2640-FE0F","non_qualified":"1F9D7-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d7-200d-2640-fe0f.png","sheet_x":52,"sheet_y":10,"short_name":"woman_climbing","short_names":["woman_climbing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":458,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D7-1F3FB-200D-2640-FE0F","non_qualified":"1F9D7-1F3FB-200D-2640","image":"1f9d7-1f3fb-200d-2640-fe0f.png","sheet_x":52,"sheet_y":11,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D7-1F3FB"},"1F3FC":{"unified":"1F9D7-1F3FC-200D-2640-FE0F","non_qualified":"1F9D7-1F3FC-200D-2640","image":"1f9d7-1f3fc-200d-2640-fe0f.png","sheet_x":52,"sheet_y":12,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D7-1F3FC"},"1F3FD":{"unified":"1F9D7-1F3FD-200D-2640-FE0F","non_qualified":"1F9D7-1F3FD-200D-2640","image":"1f9d7-1f3fd-200d-2640-fe0f.png","sheet_x":52,"sheet_y":13,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D7-1F3FD"},"1F3FE":{"unified":"1F9D7-1F3FE-200D-2640-FE0F","non_qualified":"1F9D7-1F3FE-200D-2640","image":"1f9d7-1f3fe-200d-2640-fe0f.png","sheet_x":52,"sheet_y":14,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D7-1F3FE"},"1F3FF":{"unified":"1F9D7-1F3FF-200D-2640-FE0F","non_qualified":"1F9D7-1F3FF-200D-2640","image":"1f9d7-1f3ff-200d-2640-fe0f.png","sheet_x":52,"sheet_y":15,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D7-1F3FF"}},"obsoletes":"1F9D7"},{"name":"MAN CLIMBING","unified":"1F9D7-200D-2642-FE0F","non_qualified":"1F9D7-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d7-200d-2642-fe0f.png","sheet_x":52,"sheet_y":16,"short_name":"man_climbing","short_names":["man_climbing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":457,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D7-1F3FB-200D-2642-FE0F","non_qualified":"1F9D7-1F3FB-200D-2642","image":"1f9d7-1f3fb-200d-2642-fe0f.png","sheet_x":52,"sheet_y":17,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D7-1F3FC-200D-2642-FE0F","non_qualified":"1F9D7-1F3FC-200D-2642","image":"1f9d7-1f3fc-200d-2642-fe0f.png","sheet_x":52,"sheet_y":18,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D7-1F3FD-200D-2642-FE0F","non_qualified":"1F9D7-1F3FD-200D-2642","image":"1f9d7-1f3fd-200d-2642-fe0f.png","sheet_x":52,"sheet_y":19,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D7-1F3FE-200D-2642-FE0F","non_qualified":"1F9D7-1F3FE-200D-2642","image":"1f9d7-1f3fe-200d-2642-fe0f.png","sheet_x":52,"sheet_y":20,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D7-1F3FF-200D-2642-FE0F","non_qualified":"1F9D7-1F3FF-200D-2642","image":"1f9d7-1f3ff-200d-2642-fe0f.png","sheet_x":52,"sheet_y":21,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON CLIMBING","unified":"1F9D7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d7.png","sheet_x":52,"sheet_y":22,"short_name":"person_climbing","short_names":["person_climbing"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-activity","sort_order":456,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D7-1F3FB","non_qualified":null,"image":"1f9d7-1f3fb.png","sheet_x":52,"sheet_y":23,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D7-1F3FB-200D-2640-FE0F"},"1F3FC":{"unified":"1F9D7-1F3FC","non_qualified":null,"image":"1f9d7-1f3fc.png","sheet_x":52,"sheet_y":24,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D7-1F3FC-200D-2640-FE0F"},"1F3FD":{"unified":"1F9D7-1F3FD","non_qualified":null,"image":"1f9d7-1f3fd.png","sheet_x":52,"sheet_y":25,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D7-1F3FD-200D-2640-FE0F"},"1F3FE":{"unified":"1F9D7-1F3FE","non_qualified":null,"image":"1f9d7-1f3fe.png","sheet_x":52,"sheet_y":26,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D7-1F3FE-200D-2640-FE0F"},"1F3FF":{"unified":"1F9D7-1F3FF","non_qualified":null,"image":"1f9d7-1f3ff.png","sheet_x":52,"sheet_y":27,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D7-1F3FF-200D-2640-FE0F"}},"obsoleted_by":"1F9D7-200D-2640-FE0F"},{"name":"WOMAN IN LOTUS POSITION","unified":"1F9D8-200D-2640-FE0F","non_qualified":"1F9D8-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d8-200d-2640-fe0f.png","sheet_x":52,"sheet_y":28,"short_name":"woman_in_lotus_position","short_names":["woman_in_lotus_position"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-resting","sort_order":504,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D8-1F3FB-200D-2640-FE0F","non_qualified":"1F9D8-1F3FB-200D-2640","image":"1f9d8-1f3fb-200d-2640-fe0f.png","sheet_x":52,"sheet_y":29,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D8-1F3FB"},"1F3FC":{"unified":"1F9D8-1F3FC-200D-2640-FE0F","non_qualified":"1F9D8-1F3FC-200D-2640","image":"1f9d8-1f3fc-200d-2640-fe0f.png","sheet_x":52,"sheet_y":30,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D8-1F3FC"},"1F3FD":{"unified":"1F9D8-1F3FD-200D-2640-FE0F","non_qualified":"1F9D8-1F3FD-200D-2640","image":"1f9d8-1f3fd-200d-2640-fe0f.png","sheet_x":52,"sheet_y":31,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D8-1F3FD"},"1F3FE":{"unified":"1F9D8-1F3FE-200D-2640-FE0F","non_qualified":"1F9D8-1F3FE-200D-2640","image":"1f9d8-1f3fe-200d-2640-fe0f.png","sheet_x":52,"sheet_y":32,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D8-1F3FE"},"1F3FF":{"unified":"1F9D8-1F3FF-200D-2640-FE0F","non_qualified":"1F9D8-1F3FF-200D-2640","image":"1f9d8-1f3ff-200d-2640-fe0f.png","sheet_x":52,"sheet_y":33,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D8-1F3FF"}},"obsoletes":"1F9D8"},{"name":"MAN IN LOTUS POSITION","unified":"1F9D8-200D-2642-FE0F","non_qualified":"1F9D8-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d8-200d-2642-fe0f.png","sheet_x":52,"sheet_y":34,"short_name":"man_in_lotus_position","short_names":["man_in_lotus_position"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-resting","sort_order":503,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D8-1F3FB-200D-2642-FE0F","non_qualified":"1F9D8-1F3FB-200D-2642","image":"1f9d8-1f3fb-200d-2642-fe0f.png","sheet_x":52,"sheet_y":35,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D8-1F3FC-200D-2642-FE0F","non_qualified":"1F9D8-1F3FC-200D-2642","image":"1f9d8-1f3fc-200d-2642-fe0f.png","sheet_x":52,"sheet_y":36,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D8-1F3FD-200D-2642-FE0F","non_qualified":"1F9D8-1F3FD-200D-2642","image":"1f9d8-1f3fd-200d-2642-fe0f.png","sheet_x":52,"sheet_y":37,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D8-1F3FE-200D-2642-FE0F","non_qualified":"1F9D8-1F3FE-200D-2642","image":"1f9d8-1f3fe-200d-2642-fe0f.png","sheet_x":52,"sheet_y":38,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D8-1F3FF-200D-2642-FE0F","non_qualified":"1F9D8-1F3FF-200D-2642","image":"1f9d8-1f3ff-200d-2642-fe0f.png","sheet_x":52,"sheet_y":39,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON IN LOTUS POSITION","unified":"1F9D8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d8.png","sheet_x":52,"sheet_y":40,"short_name":"person_in_lotus_position","short_names":["person_in_lotus_position"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-resting","sort_order":502,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D8-1F3FB","non_qualified":null,"image":"1f9d8-1f3fb.png","sheet_x":52,"sheet_y":41,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D8-1F3FB-200D-2640-FE0F"},"1F3FC":{"unified":"1F9D8-1F3FC","non_qualified":null,"image":"1f9d8-1f3fc.png","sheet_x":52,"sheet_y":42,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D8-1F3FC-200D-2640-FE0F"},"1F3FD":{"unified":"1F9D8-1F3FD","non_qualified":null,"image":"1f9d8-1f3fd.png","sheet_x":52,"sheet_y":43,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D8-1F3FD-200D-2640-FE0F"},"1F3FE":{"unified":"1F9D8-1F3FE","non_qualified":null,"image":"1f9d8-1f3fe.png","sheet_x":52,"sheet_y":44,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D8-1F3FE-200D-2640-FE0F"},"1F3FF":{"unified":"1F9D8-1F3FF","non_qualified":null,"image":"1f9d8-1f3ff.png","sheet_x":52,"sheet_y":45,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D8-1F3FF-200D-2640-FE0F"}},"obsoleted_by":"1F9D8-200D-2640-FE0F"},{"name":"WOMAN MAGE","unified":"1F9D9-200D-2640-FE0F","non_qualified":"1F9D9-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d9-200d-2640-fe0f.png","sheet_x":52,"sheet_y":46,"short_name":"female_mage","short_names":["female_mage"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":382,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D9-1F3FB-200D-2640-FE0F","non_qualified":"1F9D9-1F3FB-200D-2640","image":"1f9d9-1f3fb-200d-2640-fe0f.png","sheet_x":52,"sheet_y":47,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D9-1F3FB"},"1F3FC":{"unified":"1F9D9-1F3FC-200D-2640-FE0F","non_qualified":"1F9D9-1F3FC-200D-2640","image":"1f9d9-1f3fc-200d-2640-fe0f.png","sheet_x":52,"sheet_y":48,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D9-1F3FC"},"1F3FD":{"unified":"1F9D9-1F3FD-200D-2640-FE0F","non_qualified":"1F9D9-1F3FD-200D-2640","image":"1f9d9-1f3fd-200d-2640-fe0f.png","sheet_x":52,"sheet_y":49,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D9-1F3FD"},"1F3FE":{"unified":"1F9D9-1F3FE-200D-2640-FE0F","non_qualified":"1F9D9-1F3FE-200D-2640","image":"1f9d9-1f3fe-200d-2640-fe0f.png","sheet_x":52,"sheet_y":50,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D9-1F3FE"},"1F3FF":{"unified":"1F9D9-1F3FF-200D-2640-FE0F","non_qualified":"1F9D9-1F3FF-200D-2640","image":"1f9d9-1f3ff-200d-2640-fe0f.png","sheet_x":52,"sheet_y":51,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9D9-1F3FF"}},"obsoletes":"1F9D9"},{"name":"MAN MAGE","unified":"1F9D9-200D-2642-FE0F","non_qualified":"1F9D9-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d9-200d-2642-fe0f.png","sheet_x":52,"sheet_y":52,"short_name":"male_mage","short_names":["male_mage"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":381,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D9-1F3FB-200D-2642-FE0F","non_qualified":"1F9D9-1F3FB-200D-2642","image":"1f9d9-1f3fb-200d-2642-fe0f.png","sheet_x":52,"sheet_y":53,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9D9-1F3FC-200D-2642-FE0F","non_qualified":"1F9D9-1F3FC-200D-2642","image":"1f9d9-1f3fc-200d-2642-fe0f.png","sheet_x":52,"sheet_y":54,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9D9-1F3FD-200D-2642-FE0F","non_qualified":"1F9D9-1F3FD-200D-2642","image":"1f9d9-1f3fd-200d-2642-fe0f.png","sheet_x":52,"sheet_y":55,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9D9-1F3FE-200D-2642-FE0F","non_qualified":"1F9D9-1F3FE-200D-2642","image":"1f9d9-1f3fe-200d-2642-fe0f.png","sheet_x":52,"sheet_y":56,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9D9-1F3FF-200D-2642-FE0F","non_qualified":"1F9D9-1F3FF-200D-2642","image":"1f9d9-1f3ff-200d-2642-fe0f.png","sheet_x":52,"sheet_y":57,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAGE","unified":"1F9D9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9d9.png","sheet_x":52,"sheet_y":58,"short_name":"mage","short_names":["mage"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":380,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9D9-1F3FB","non_qualified":null,"image":"1f9d9-1f3fb.png","sheet_x":52,"sheet_y":59,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D9-1F3FB-200D-2640-FE0F"},"1F3FC":{"unified":"1F9D9-1F3FC","non_qualified":null,"image":"1f9d9-1f3fc.png","sheet_x":52,"sheet_y":60,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D9-1F3FC-200D-2640-FE0F"},"1F3FD":{"unified":"1F9D9-1F3FD","non_qualified":null,"image":"1f9d9-1f3fd.png","sheet_x":52,"sheet_y":61,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D9-1F3FD-200D-2640-FE0F"},"1F3FE":{"unified":"1F9D9-1F3FE","non_qualified":null,"image":"1f9d9-1f3fe.png","sheet_x":53,"sheet_y":0,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D9-1F3FE-200D-2640-FE0F"},"1F3FF":{"unified":"1F9D9-1F3FF","non_qualified":null,"image":"1f9d9-1f3ff.png","sheet_x":53,"sheet_y":1,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9D9-1F3FF-200D-2640-FE0F"}},"obsoleted_by":"1F9D9-200D-2640-FE0F"},{"name":"WOMAN FAIRY","unified":"1F9DA-200D-2640-FE0F","non_qualified":"1F9DA-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9da-200d-2640-fe0f.png","sheet_x":53,"sheet_y":2,"short_name":"female_fairy","short_names":["female_fairy"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":385,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DA-1F3FB-200D-2640-FE0F","non_qualified":"1F9DA-1F3FB-200D-2640","image":"1f9da-1f3fb-200d-2640-fe0f.png","sheet_x":53,"sheet_y":3,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DA-1F3FB"},"1F3FC":{"unified":"1F9DA-1F3FC-200D-2640-FE0F","non_qualified":"1F9DA-1F3FC-200D-2640","image":"1f9da-1f3fc-200d-2640-fe0f.png","sheet_x":53,"sheet_y":4,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DA-1F3FC"},"1F3FD":{"unified":"1F9DA-1F3FD-200D-2640-FE0F","non_qualified":"1F9DA-1F3FD-200D-2640","image":"1f9da-1f3fd-200d-2640-fe0f.png","sheet_x":53,"sheet_y":5,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DA-1F3FD"},"1F3FE":{"unified":"1F9DA-1F3FE-200D-2640-FE0F","non_qualified":"1F9DA-1F3FE-200D-2640","image":"1f9da-1f3fe-200d-2640-fe0f.png","sheet_x":53,"sheet_y":6,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DA-1F3FE"},"1F3FF":{"unified":"1F9DA-1F3FF-200D-2640-FE0F","non_qualified":"1F9DA-1F3FF-200D-2640","image":"1f9da-1f3ff-200d-2640-fe0f.png","sheet_x":53,"sheet_y":7,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DA-1F3FF"}},"obsoletes":"1F9DA"},{"name":"MAN FAIRY","unified":"1F9DA-200D-2642-FE0F","non_qualified":"1F9DA-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9da-200d-2642-fe0f.png","sheet_x":53,"sheet_y":8,"short_name":"male_fairy","short_names":["male_fairy"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":384,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DA-1F3FB-200D-2642-FE0F","non_qualified":"1F9DA-1F3FB-200D-2642","image":"1f9da-1f3fb-200d-2642-fe0f.png","sheet_x":53,"sheet_y":9,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9DA-1F3FC-200D-2642-FE0F","non_qualified":"1F9DA-1F3FC-200D-2642","image":"1f9da-1f3fc-200d-2642-fe0f.png","sheet_x":53,"sheet_y":10,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9DA-1F3FD-200D-2642-FE0F","non_qualified":"1F9DA-1F3FD-200D-2642","image":"1f9da-1f3fd-200d-2642-fe0f.png","sheet_x":53,"sheet_y":11,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9DA-1F3FE-200D-2642-FE0F","non_qualified":"1F9DA-1F3FE-200D-2642","image":"1f9da-1f3fe-200d-2642-fe0f.png","sheet_x":53,"sheet_y":12,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9DA-1F3FF-200D-2642-FE0F","non_qualified":"1F9DA-1F3FF-200D-2642","image":"1f9da-1f3ff-200d-2642-fe0f.png","sheet_x":53,"sheet_y":13,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"FAIRY","unified":"1F9DA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9da.png","sheet_x":53,"sheet_y":14,"short_name":"fairy","short_names":["fairy"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":383,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DA-1F3FB","non_qualified":null,"image":"1f9da-1f3fb.png","sheet_x":53,"sheet_y":15,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DA-1F3FB-200D-2640-FE0F"},"1F3FC":{"unified":"1F9DA-1F3FC","non_qualified":null,"image":"1f9da-1f3fc.png","sheet_x":53,"sheet_y":16,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DA-1F3FC-200D-2640-FE0F"},"1F3FD":{"unified":"1F9DA-1F3FD","non_qualified":null,"image":"1f9da-1f3fd.png","sheet_x":53,"sheet_y":17,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DA-1F3FD-200D-2640-FE0F"},"1F3FE":{"unified":"1F9DA-1F3FE","non_qualified":null,"image":"1f9da-1f3fe.png","sheet_x":53,"sheet_y":18,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DA-1F3FE-200D-2640-FE0F"},"1F3FF":{"unified":"1F9DA-1F3FF","non_qualified":null,"image":"1f9da-1f3ff.png","sheet_x":53,"sheet_y":19,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DA-1F3FF-200D-2640-FE0F"}},"obsoleted_by":"1F9DA-200D-2640-FE0F"},{"name":"WOMAN VAMPIRE","unified":"1F9DB-200D-2640-FE0F","non_qualified":"1F9DB-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9db-200d-2640-fe0f.png","sheet_x":53,"sheet_y":20,"short_name":"female_vampire","short_names":["female_vampire"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":388,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DB-1F3FB-200D-2640-FE0F","non_qualified":"1F9DB-1F3FB-200D-2640","image":"1f9db-1f3fb-200d-2640-fe0f.png","sheet_x":53,"sheet_y":21,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DB-1F3FB"},"1F3FC":{"unified":"1F9DB-1F3FC-200D-2640-FE0F","non_qualified":"1F9DB-1F3FC-200D-2640","image":"1f9db-1f3fc-200d-2640-fe0f.png","sheet_x":53,"sheet_y":22,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DB-1F3FC"},"1F3FD":{"unified":"1F9DB-1F3FD-200D-2640-FE0F","non_qualified":"1F9DB-1F3FD-200D-2640","image":"1f9db-1f3fd-200d-2640-fe0f.png","sheet_x":53,"sheet_y":23,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DB-1F3FD"},"1F3FE":{"unified":"1F9DB-1F3FE-200D-2640-FE0F","non_qualified":"1F9DB-1F3FE-200D-2640","image":"1f9db-1f3fe-200d-2640-fe0f.png","sheet_x":53,"sheet_y":24,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DB-1F3FE"},"1F3FF":{"unified":"1F9DB-1F3FF-200D-2640-FE0F","non_qualified":"1F9DB-1F3FF-200D-2640","image":"1f9db-1f3ff-200d-2640-fe0f.png","sheet_x":53,"sheet_y":25,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DB-1F3FF"}},"obsoletes":"1F9DB"},{"name":"MAN VAMPIRE","unified":"1F9DB-200D-2642-FE0F","non_qualified":"1F9DB-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9db-200d-2642-fe0f.png","sheet_x":53,"sheet_y":26,"short_name":"male_vampire","short_names":["male_vampire"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":387,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DB-1F3FB-200D-2642-FE0F","non_qualified":"1F9DB-1F3FB-200D-2642","image":"1f9db-1f3fb-200d-2642-fe0f.png","sheet_x":53,"sheet_y":27,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9DB-1F3FC-200D-2642-FE0F","non_qualified":"1F9DB-1F3FC-200D-2642","image":"1f9db-1f3fc-200d-2642-fe0f.png","sheet_x":53,"sheet_y":28,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9DB-1F3FD-200D-2642-FE0F","non_qualified":"1F9DB-1F3FD-200D-2642","image":"1f9db-1f3fd-200d-2642-fe0f.png","sheet_x":53,"sheet_y":29,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9DB-1F3FE-200D-2642-FE0F","non_qualified":"1F9DB-1F3FE-200D-2642","image":"1f9db-1f3fe-200d-2642-fe0f.png","sheet_x":53,"sheet_y":30,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9DB-1F3FF-200D-2642-FE0F","non_qualified":"1F9DB-1F3FF-200D-2642","image":"1f9db-1f3ff-200d-2642-fe0f.png","sheet_x":53,"sheet_y":31,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"VAMPIRE","unified":"1F9DB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9db.png","sheet_x":53,"sheet_y":32,"short_name":"vampire","short_names":["vampire"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":386,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DB-1F3FB","non_qualified":null,"image":"1f9db-1f3fb.png","sheet_x":53,"sheet_y":33,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DB-1F3FB-200D-2640-FE0F"},"1F3FC":{"unified":"1F9DB-1F3FC","non_qualified":null,"image":"1f9db-1f3fc.png","sheet_x":53,"sheet_y":34,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DB-1F3FC-200D-2640-FE0F"},"1F3FD":{"unified":"1F9DB-1F3FD","non_qualified":null,"image":"1f9db-1f3fd.png","sheet_x":53,"sheet_y":35,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DB-1F3FD-200D-2640-FE0F"},"1F3FE":{"unified":"1F9DB-1F3FE","non_qualified":null,"image":"1f9db-1f3fe.png","sheet_x":53,"sheet_y":36,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DB-1F3FE-200D-2640-FE0F"},"1F3FF":{"unified":"1F9DB-1F3FF","non_qualified":null,"image":"1f9db-1f3ff.png","sheet_x":53,"sheet_y":37,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DB-1F3FF-200D-2640-FE0F"}},"obsoleted_by":"1F9DB-200D-2640-FE0F"},{"name":"MERMAID","unified":"1F9DC-200D-2640-FE0F","non_qualified":"1F9DC-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9dc-200d-2640-fe0f.png","sheet_x":53,"sheet_y":38,"short_name":"mermaid","short_names":["mermaid"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":391,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DC-1F3FB-200D-2640-FE0F","non_qualified":"1F9DC-1F3FB-200D-2640","image":"1f9dc-1f3fb-200d-2640-fe0f.png","sheet_x":53,"sheet_y":39,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9DC-1F3FC-200D-2640-FE0F","non_qualified":"1F9DC-1F3FC-200D-2640","image":"1f9dc-1f3fc-200d-2640-fe0f.png","sheet_x":53,"sheet_y":40,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9DC-1F3FD-200D-2640-FE0F","non_qualified":"1F9DC-1F3FD-200D-2640","image":"1f9dc-1f3fd-200d-2640-fe0f.png","sheet_x":53,"sheet_y":41,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9DC-1F3FE-200D-2640-FE0F","non_qualified":"1F9DC-1F3FE-200D-2640","image":"1f9dc-1f3fe-200d-2640-fe0f.png","sheet_x":53,"sheet_y":42,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9DC-1F3FF-200D-2640-FE0F","non_qualified":"1F9DC-1F3FF-200D-2640","image":"1f9dc-1f3ff-200d-2640-fe0f.png","sheet_x":53,"sheet_y":43,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MERMAN","unified":"1F9DC-200D-2642-FE0F","non_qualified":"1F9DC-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9dc-200d-2642-fe0f.png","sheet_x":53,"sheet_y":44,"short_name":"merman","short_names":["merman"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":390,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DC-1F3FB-200D-2642-FE0F","non_qualified":"1F9DC-1F3FB-200D-2642","image":"1f9dc-1f3fb-200d-2642-fe0f.png","sheet_x":53,"sheet_y":45,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DC-1F3FB"},"1F3FC":{"unified":"1F9DC-1F3FC-200D-2642-FE0F","non_qualified":"1F9DC-1F3FC-200D-2642","image":"1f9dc-1f3fc-200d-2642-fe0f.png","sheet_x":53,"sheet_y":46,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DC-1F3FC"},"1F3FD":{"unified":"1F9DC-1F3FD-200D-2642-FE0F","non_qualified":"1F9DC-1F3FD-200D-2642","image":"1f9dc-1f3fd-200d-2642-fe0f.png","sheet_x":53,"sheet_y":47,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DC-1F3FD"},"1F3FE":{"unified":"1F9DC-1F3FE-200D-2642-FE0F","non_qualified":"1F9DC-1F3FE-200D-2642","image":"1f9dc-1f3fe-200d-2642-fe0f.png","sheet_x":53,"sheet_y":48,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DC-1F3FE"},"1F3FF":{"unified":"1F9DC-1F3FF-200D-2642-FE0F","non_qualified":"1F9DC-1F3FF-200D-2642","image":"1f9dc-1f3ff-200d-2642-fe0f.png","sheet_x":53,"sheet_y":49,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DC-1F3FF"}},"obsoletes":"1F9DC"},{"name":"MERPERSON","unified":"1F9DC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9dc.png","sheet_x":53,"sheet_y":50,"short_name":"merperson","short_names":["merperson"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":389,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DC-1F3FB","non_qualified":null,"image":"1f9dc-1f3fb.png","sheet_x":53,"sheet_y":51,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DC-1F3FB-200D-2642-FE0F"},"1F3FC":{"unified":"1F9DC-1F3FC","non_qualified":null,"image":"1f9dc-1f3fc.png","sheet_x":53,"sheet_y":52,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DC-1F3FC-200D-2642-FE0F"},"1F3FD":{"unified":"1F9DC-1F3FD","non_qualified":null,"image":"1f9dc-1f3fd.png","sheet_x":53,"sheet_y":53,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DC-1F3FD-200D-2642-FE0F"},"1F3FE":{"unified":"1F9DC-1F3FE","non_qualified":null,"image":"1f9dc-1f3fe.png","sheet_x":53,"sheet_y":54,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DC-1F3FE-200D-2642-FE0F"},"1F3FF":{"unified":"1F9DC-1F3FF","non_qualified":null,"image":"1f9dc-1f3ff.png","sheet_x":53,"sheet_y":55,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DC-1F3FF-200D-2642-FE0F"}},"obsoleted_by":"1F9DC-200D-2642-FE0F"},{"name":"WOMAN ELF","unified":"1F9DD-200D-2640-FE0F","non_qualified":"1F9DD-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9dd-200d-2640-fe0f.png","sheet_x":53,"sheet_y":56,"short_name":"female_elf","short_names":["female_elf"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":394,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DD-1F3FB-200D-2640-FE0F","non_qualified":"1F9DD-1F3FB-200D-2640","image":"1f9dd-1f3fb-200d-2640-fe0f.png","sheet_x":53,"sheet_y":57,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1F9DD-1F3FC-200D-2640-FE0F","non_qualified":"1F9DD-1F3FC-200D-2640","image":"1f9dd-1f3fc-200d-2640-fe0f.png","sheet_x":53,"sheet_y":58,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1F9DD-1F3FD-200D-2640-FE0F","non_qualified":"1F9DD-1F3FD-200D-2640","image":"1f9dd-1f3fd-200d-2640-fe0f.png","sheet_x":53,"sheet_y":59,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1F9DD-1F3FE-200D-2640-FE0F","non_qualified":"1F9DD-1F3FE-200D-2640","image":"1f9dd-1f3fe-200d-2640-fe0f.png","sheet_x":53,"sheet_y":60,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1F9DD-1F3FF-200D-2640-FE0F","non_qualified":"1F9DD-1F3FF-200D-2640","image":"1f9dd-1f3ff-200d-2640-fe0f.png","sheet_x":53,"sheet_y":61,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN ELF","unified":"1F9DD-200D-2642-FE0F","non_qualified":"1F9DD-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9dd-200d-2642-fe0f.png","sheet_x":54,"sheet_y":0,"short_name":"male_elf","short_names":["male_elf"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":393,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DD-1F3FB-200D-2642-FE0F","non_qualified":"1F9DD-1F3FB-200D-2642","image":"1f9dd-1f3fb-200d-2642-fe0f.png","sheet_x":54,"sheet_y":1,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DD-1F3FB"},"1F3FC":{"unified":"1F9DD-1F3FC-200D-2642-FE0F","non_qualified":"1F9DD-1F3FC-200D-2642","image":"1f9dd-1f3fc-200d-2642-fe0f.png","sheet_x":54,"sheet_y":2,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DD-1F3FC"},"1F3FD":{"unified":"1F9DD-1F3FD-200D-2642-FE0F","non_qualified":"1F9DD-1F3FD-200D-2642","image":"1f9dd-1f3fd-200d-2642-fe0f.png","sheet_x":54,"sheet_y":3,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DD-1F3FD"},"1F3FE":{"unified":"1F9DD-1F3FE-200D-2642-FE0F","non_qualified":"1F9DD-1F3FE-200D-2642","image":"1f9dd-1f3fe-200d-2642-fe0f.png","sheet_x":54,"sheet_y":4,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DD-1F3FE"},"1F3FF":{"unified":"1F9DD-1F3FF-200D-2642-FE0F","non_qualified":"1F9DD-1F3FF-200D-2642","image":"1f9dd-1f3ff-200d-2642-fe0f.png","sheet_x":54,"sheet_y":5,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DD-1F3FF"}},"obsoletes":"1F9DD"},{"name":"ELF","unified":"1F9DD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9dd.png","sheet_x":54,"sheet_y":6,"short_name":"elf","short_names":["elf"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":392,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1F9DD-1F3FB","non_qualified":null,"image":"1f9dd-1f3fb.png","sheet_x":54,"sheet_y":7,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DD-1F3FB-200D-2642-FE0F"},"1F3FC":{"unified":"1F9DD-1F3FC","non_qualified":null,"image":"1f9dd-1f3fc.png","sheet_x":54,"sheet_y":8,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DD-1F3FC-200D-2642-FE0F"},"1F3FD":{"unified":"1F9DD-1F3FD","non_qualified":null,"image":"1f9dd-1f3fd.png","sheet_x":54,"sheet_y":9,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DD-1F3FD-200D-2642-FE0F"},"1F3FE":{"unified":"1F9DD-1F3FE","non_qualified":null,"image":"1f9dd-1f3fe.png","sheet_x":54,"sheet_y":10,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DD-1F3FE-200D-2642-FE0F"},"1F3FF":{"unified":"1F9DD-1F3FF","non_qualified":null,"image":"1f9dd-1f3ff.png","sheet_x":54,"sheet_y":11,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DD-1F3FF-200D-2642-FE0F"}},"obsoleted_by":"1F9DD-200D-2642-FE0F"},{"name":"WOMAN GENIE","unified":"1F9DE-200D-2640-FE0F","non_qualified":"1F9DE-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9de-200d-2640-fe0f.png","sheet_x":54,"sheet_y":12,"short_name":"female_genie","short_names":["female_genie"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":397,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MAN GENIE","unified":"1F9DE-200D-2642-FE0F","non_qualified":"1F9DE-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9de-200d-2642-fe0f.png","sheet_x":54,"sheet_y":13,"short_name":"male_genie","short_names":["male_genie"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":396,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DE"},{"name":"GENIE","unified":"1F9DE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9de.png","sheet_x":54,"sheet_y":14,"short_name":"genie","short_names":["genie"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":395,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DE-200D-2642-FE0F"},{"name":"WOMAN ZOMBIE","unified":"1F9DF-200D-2640-FE0F","non_qualified":"1F9DF-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9df-200d-2640-fe0f.png","sheet_x":54,"sheet_y":15,"short_name":"female_zombie","short_names":["female_zombie"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":400,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MAN ZOMBIE","unified":"1F9DF-200D-2642-FE0F","non_qualified":"1F9DF-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9df-200d-2642-fe0f.png","sheet_x":54,"sheet_y":16,"short_name":"male_zombie","short_names":["male_zombie"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":399,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoletes":"1F9DF"},{"name":"ZOMBIE","unified":"1F9DF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9df.png","sheet_x":54,"sheet_y":17,"short_name":"zombie","short_names":["zombie"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-fantasy","sort_order":398,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"obsoleted_by":"1F9DF-200D-2642-FE0F"},{"name":"BRAIN","unified":"1F9E0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e0.png","sheet_x":54,"sheet_y":18,"short_name":"brain","short_names":["brain"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":220,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ORANGE HEART","unified":"1F9E1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e1.png","sheet_x":54,"sheet_y":19,"short_name":"orange_heart","short_names":["orange_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":145,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BILLED CAP","unified":"1F9E2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e2.png","sheet_x":54,"sheet_y":20,"short_name":"billed_cap","short_names":["billed_cap"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1190,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SCARF","unified":"1F9E3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e3.png","sheet_x":54,"sheet_y":21,"short_name":"scarf","short_names":["scarf"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1158,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GLOVES","unified":"1F9E4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e4.png","sheet_x":54,"sheet_y":22,"short_name":"gloves","short_names":["gloves"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1159,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COAT","unified":"1F9E5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e5.png","sheet_x":54,"sheet_y":23,"short_name":"coat","short_names":["coat"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1160,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SOCKS","unified":"1F9E6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e6.png","sheet_x":54,"sheet_y":24,"short_name":"socks","short_names":["socks"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1161,"added_in":"5.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RED GIFT ENVELOPE","unified":"1F9E7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e7.png","sheet_x":54,"sheet_y":25,"short_name":"red_envelope","short_names":["red_envelope"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1080,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FIRECRACKER","unified":"1F9E8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e8.png","sheet_x":54,"sheet_y":26,"short_name":"firecracker","short_names":["firecracker"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1069,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JIGSAW PUZZLE PIECE","unified":"1F9E9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9e9.png","sheet_x":54,"sheet_y":27,"short_name":"jigsaw","short_names":["jigsaw"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1130,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TEST TUBE","unified":"1F9EA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ea.png","sheet_x":54,"sheet_y":28,"short_name":"test_tube","short_names":["test_tube"],"text":null,"texts":null,"category":"Objects","subcategory":"science","sort_order":1365,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PETRI DISH","unified":"1F9EB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9eb.png","sheet_x":54,"sheet_y":29,"short_name":"petri_dish","short_names":["petri_dish"],"text":null,"texts":null,"category":"Objects","subcategory":"science","sort_order":1366,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DNA DOUBLE HELIX","unified":"1F9EC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ec.png","sheet_x":54,"sheet_y":30,"short_name":"dna","short_names":["dna"],"text":null,"texts":null,"category":"Objects","subcategory":"science","sort_order":1367,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COMPASS","unified":"1F9ED","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ed.png","sheet_x":54,"sheet_y":31,"short_name":"compass","short_names":["compass"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-map","sort_order":853,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ABACUS","unified":"1F9EE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ee.png","sheet_x":54,"sheet_y":32,"short_name":"abacus","short_names":["abacus"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1245,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FIRE EXTINGUISHER","unified":"1F9EF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ef.png","sheet_x":54,"sheet_y":33,"short_name":"fire_extinguisher","short_names":["fire_extinguisher"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1401,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TOOLBOX","unified":"1F9F0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f0.png","sheet_x":54,"sheet_y":34,"short_name":"toolbox","short_names":["toolbox"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1361,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BRICK","unified":"1F9F1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f1.png","sheet_x":54,"sheet_y":35,"short_name":"bricks","short_names":["bricks"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":866,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MAGNET","unified":"1F9F2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f2.png","sheet_x":54,"sheet_y":36,"short_name":"magnet","short_names":["magnet"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1362,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LUGGAGE","unified":"1F9F3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f3.png","sheet_x":54,"sheet_y":37,"short_name":"luggage","short_names":["luggage"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"hotel","sort_order":986,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOTION BOTTLE","unified":"1F9F4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f4.png","sheet_x":54,"sheet_y":38,"short_name":"lotion_bottle","short_names":["lotion_bottle"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1391,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPOOL OF THREAD","unified":"1F9F5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f5.png","sheet_x":54,"sheet_y":39,"short_name":"thread","short_names":["thread"],"text":null,"texts":null,"category":"Activities","subcategory":"arts & crafts","sort_order":1146,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BALL OF YARN","unified":"1F9F6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f6.png","sheet_x":54,"sheet_y":40,"short_name":"yarn","short_names":["yarn"],"text":null,"texts":null,"category":"Activities","subcategory":"arts & crafts","sort_order":1148,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SAFETY PIN","unified":"1F9F7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f7.png","sheet_x":54,"sheet_y":41,"short_name":"safety_pin","short_names":["safety_pin"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1392,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TEDDY BEAR","unified":"1F9F8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f8.png","sheet_x":54,"sheet_y":42,"short_name":"teddy_bear","short_names":["teddy_bear"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1131,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BROOM","unified":"1F9F9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9f9.png","sheet_x":54,"sheet_y":43,"short_name":"broom","short_names":["broom"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1393,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BASKET","unified":"1F9FA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9fa.png","sheet_x":54,"sheet_y":44,"short_name":"basket","short_names":["basket"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1394,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROLL OF PAPER","unified":"1F9FB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9fb.png","sheet_x":54,"sheet_y":45,"short_name":"roll_of_paper","short_names":["roll_of_paper"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1395,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BAR OF SOAP","unified":"1F9FC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9fc.png","sheet_x":54,"sheet_y":46,"short_name":"soap","short_names":["soap"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1397,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPONGE","unified":"1F9FD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9fd.png","sheet_x":54,"sheet_y":47,"short_name":"sponge","short_names":["sponge"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1400,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RECEIPT","unified":"1F9FE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9fe.png","sheet_x":54,"sheet_y":48,"short_name":"receipt","short_names":["receipt"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1287,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NAZAR AMULET","unified":"1F9FF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1f9ff.png","sheet_x":54,"sheet_y":49,"short_name":"nazar_amulet","short_names":["nazar_amulet"],"text":null,"texts":null,"category":"Objects","subcategory":"other-object","sort_order":1407,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BALLET SHOES","unified":"1FA70","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa70.png","sheet_x":54,"sheet_y":50,"short_name":"ballet_shoes","short_names":["ballet_shoes"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1183,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ONE-PIECE SWIMSUIT","unified":"1FA71","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa71.png","sheet_x":54,"sheet_y":51,"short_name":"one-piece_swimsuit","short_names":["one-piece_swimsuit"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1165,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BRIEFS","unified":"1FA72","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa72.png","sheet_x":54,"sheet_y":52,"short_name":"briefs","short_names":["briefs"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1166,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHORTS","unified":"1FA73","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa73.png","sheet_x":54,"sheet_y":53,"short_name":"shorts","short_names":["shorts"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1167,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"THONG SANDAL","unified":"1FA74","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa74.png","sheet_x":54,"sheet_y":54,"short_name":"thong_sandal","short_names":["thong_sandal"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1176,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LIGHT BLUE HEART","unified":"1FA75","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa75.png","sheet_x":54,"sheet_y":55,"short_name":"light_blue_heart","short_names":["light_blue_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":149,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GREY HEART","unified":"1FA76","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa76.png","sheet_x":54,"sheet_y":56,"short_name":"grey_heart","short_names":["grey_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":153,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PINK HEART","unified":"1FA77","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa77.png","sheet_x":54,"sheet_y":57,"short_name":"pink_heart","short_names":["pink_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":144,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DROP OF BLOOD","unified":"1FA78","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa78.png","sheet_x":54,"sheet_y":58,"short_name":"drop_of_blood","short_names":["drop_of_blood"],"text":null,"texts":null,"category":"Objects","subcategory":"medical","sort_order":1372,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ADHESIVE BANDAGE","unified":"1FA79","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa79.png","sheet_x":54,"sheet_y":59,"short_name":"adhesive_bandage","short_names":["adhesive_bandage"],"text":null,"texts":null,"category":"Objects","subcategory":"medical","sort_order":1374,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STETHOSCOPE","unified":"1FA7A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa7a.png","sheet_x":54,"sheet_y":60,"short_name":"stethoscope","short_names":["stethoscope"],"text":null,"texts":null,"category":"Objects","subcategory":"medical","sort_order":1376,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"X-RAY","unified":"1FA7B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa7b.png","sheet_x":54,"sheet_y":61,"short_name":"x-ray","short_names":["x-ray"],"text":null,"texts":null,"category":"Objects","subcategory":"medical","sort_order":1377,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CRUTCH","unified":"1FA7C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa7c.png","sheet_x":55,"sheet_y":0,"short_name":"crutch","short_names":["crutch"],"text":null,"texts":null,"category":"Objects","subcategory":"medical","sort_order":1375,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"YO-YO","unified":"1FA80","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa80.png","sheet_x":55,"sheet_y":1,"short_name":"yo-yo","short_names":["yo-yo"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1120,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KITE","unified":"1FA81","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa81.png","sheet_x":55,"sheet_y":2,"short_name":"kite","short_names":["kite"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1121,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PARACHUTE","unified":"1FA82","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa82.png","sheet_x":55,"sheet_y":3,"short_name":"parachute","short_names":["parachute"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":976,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BOOMERANG","unified":"1FA83","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa83.png","sheet_x":55,"sheet_y":4,"short_name":"boomerang","short_names":["boomerang"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1346,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MAGIC WAND","unified":"1FA84","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa84.png","sheet_x":55,"sheet_y":5,"short_name":"magic_wand","short_names":["magic_wand"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1125,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PINATA","unified":"1FA85","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa85.png","sheet_x":55,"sheet_y":6,"short_name":"pinata","short_names":["pinata"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1132,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NESTING DOLLS","unified":"1FA86","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa86.png","sheet_x":55,"sheet_y":7,"short_name":"nesting_dolls","short_names":["nesting_dolls"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1134,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MARACAS","unified":"1FA87","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa87.png","sheet_x":55,"sheet_y":8,"short_name":"maracas","short_names":["maracas"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1224,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLUTE","unified":"1FA88","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa88.png","sheet_x":55,"sheet_y":9,"short_name":"flute","short_names":["flute"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1225,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RINGED PLANET","unified":"1FA90","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa90.png","sheet_x":55,"sheet_y":10,"short_name":"ringed_planet","short_names":["ringed_planet"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1034,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHAIR","unified":"1FA91","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa91.png","sheet_x":55,"sheet_y":11,"short_name":"chair","short_names":["chair"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1384,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RAZOR","unified":"1FA92","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa92.png","sheet_x":55,"sheet_y":12,"short_name":"razor","short_names":["razor"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1390,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AXE","unified":"1FA93","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa93.png","sheet_x":55,"sheet_y":13,"short_name":"axe","short_names":["axe"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1339,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DIYA LAMP","unified":"1FA94","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa94.png","sheet_x":55,"sheet_y":14,"short_name":"diya_lamp","short_names":["diya_lamp"],"text":null,"texts":null,"category":"Objects","subcategory":"light & video","sort_order":1261,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BANJO","unified":"1FA95","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa95.png","sheet_x":55,"sheet_y":15,"short_name":"banjo","short_names":["banjo"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1221,"added_in":"12.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MILITARY HELMET","unified":"1FA96","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa96.png","sheet_x":55,"sheet_y":16,"short_name":"military_helmet","short_names":["military_helmet"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1191,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ACCORDION","unified":"1FA97","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa97.png","sheet_x":55,"sheet_y":17,"short_name":"accordion","short_names":["accordion"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1216,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LONG DRUM","unified":"1FA98","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa98.png","sheet_x":55,"sheet_y":18,"short_name":"long_drum","short_names":["long_drum"],"text":null,"texts":null,"category":"Objects","subcategory":"musical-instrument","sort_order":1223,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COIN","unified":"1FA99","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa99.png","sheet_x":55,"sheet_y":19,"short_name":"coin","short_names":["coin"],"text":null,"texts":null,"category":"Objects","subcategory":"money","sort_order":1280,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CARPENTRY SAW","unified":"1FA9A","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa9a.png","sheet_x":55,"sheet_y":20,"short_name":"carpentry_saw","short_names":["carpentry_saw"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1349,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SCREWDRIVER","unified":"1FA9B","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa9b.png","sheet_x":55,"sheet_y":21,"short_name":"screwdriver","short_names":["screwdriver"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1351,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LADDER","unified":"1FA9C","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa9c.png","sheet_x":55,"sheet_y":22,"short_name":"ladder","short_names":["ladder"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1363,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOOK","unified":"1FA9D","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa9d.png","sheet_x":55,"sheet_y":23,"short_name":"hook","short_names":["hook"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1360,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MIRROR","unified":"1FA9E","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa9e.png","sheet_x":55,"sheet_y":24,"short_name":"mirror","short_names":["mirror"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1380,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WINDOW","unified":"1FA9F","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fa9f.png","sheet_x":55,"sheet_y":25,"short_name":"window","short_names":["window"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1381,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PLUNGER","unified":"1FAA0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa0.png","sheet_x":55,"sheet_y":26,"short_name":"plunger","short_names":["plunger"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1386,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SEWING NEEDLE","unified":"1FAA1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa1.png","sheet_x":55,"sheet_y":27,"short_name":"sewing_needle","short_names":["sewing_needle"],"text":null,"texts":null,"category":"Activities","subcategory":"arts & crafts","sort_order":1147,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KNOT","unified":"1FAA2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa2.png","sheet_x":55,"sheet_y":28,"short_name":"knot","short_names":["knot"],"text":null,"texts":null,"category":"Activities","subcategory":"arts & crafts","sort_order":1149,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUCKET","unified":"1FAA3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa3.png","sheet_x":55,"sheet_y":29,"short_name":"bucket","short_names":["bucket"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1396,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOUSE TRAP","unified":"1FAA4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa4.png","sheet_x":55,"sheet_y":30,"short_name":"mouse_trap","short_names":["mouse_trap"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1389,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TOOTHBRUSH","unified":"1FAA5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa5.png","sheet_x":55,"sheet_y":31,"short_name":"toothbrush","short_names":["toothbrush"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1399,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEADSTONE","unified":"1FAA6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa6.png","sheet_x":55,"sheet_y":32,"short_name":"headstone","short_names":["headstone"],"text":null,"texts":null,"category":"Objects","subcategory":"other-object","sort_order":1405,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PLACARD","unified":"1FAA7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa7.png","sheet_x":55,"sheet_y":33,"short_name":"placard","short_names":["placard"],"text":null,"texts":null,"category":"Objects","subcategory":"other-object","sort_order":1410,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ROCK","unified":"1FAA8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa8.png","sheet_x":55,"sheet_y":34,"short_name":"rock","short_names":["rock"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":867,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MIRROR BALL","unified":"1FAA9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faa9.png","sheet_x":55,"sheet_y":35,"short_name":"mirror_ball","short_names":["mirror_ball"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1133,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"IDENTIFICATION CARD","unified":"1FAAA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faaa.png","sheet_x":55,"sheet_y":36,"short_name":"identification_card","short_names":["identification_card"],"text":null,"texts":null,"category":"Objects","subcategory":"other-object","sort_order":1411,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOW BATTERY","unified":"1FAAB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faab.png","sheet_x":55,"sheet_y":37,"short_name":"low_battery","short_names":["low_battery"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1233,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HAMSA","unified":"1FAAC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faac.png","sheet_x":55,"sheet_y":38,"short_name":"hamsa","short_names":["hamsa"],"text":null,"texts":null,"category":"Objects","subcategory":"other-object","sort_order":1408,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FOLDING HAND FAN","unified":"1FAAD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faad.png","sheet_x":55,"sheet_y":39,"short_name":"folding_hand_fan","short_names":["folding_hand_fan"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1170,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HAIR PICK","unified":"1FAAE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faae.png","sheet_x":55,"sheet_y":40,"short_name":"hair_pick","short_names":["hair_pick"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1185,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KHANDA","unified":"1FAAF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faaf.png","sheet_x":55,"sheet_y":41,"short_name":"khanda","short_names":["khanda"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1471,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLY","unified":"1FAB0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab0.png","sheet_x":55,"sheet_y":42,"short_name":"fly","short_names":["fly"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":681,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WORM","unified":"1FAB1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab1.png","sheet_x":55,"sheet_y":43,"short_name":"worm","short_names":["worm"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":682,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BEETLE","unified":"1FAB2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab2.png","sheet_x":55,"sheet_y":44,"short_name":"beetle","short_names":["beetle"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":673,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COCKROACH","unified":"1FAB3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab3.png","sheet_x":55,"sheet_y":45,"short_name":"cockroach","short_names":["cockroach"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bug","sort_order":676,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POTTED PLANT","unified":"1FAB4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab4.png","sheet_x":55,"sheet_y":46,"short_name":"potted_plant","short_names":["potted_plant"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":697,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOOD","unified":"1FAB5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab5.png","sheet_x":55,"sheet_y":47,"short_name":"wood","short_names":["wood"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-building","sort_order":868,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FEATHER","unified":"1FAB6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab6.png","sheet_x":55,"sheet_y":48,"short_name":"feather","short_names":["feather"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":639,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LOTUS","unified":"1FAB7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab7.png","sheet_x":55,"sheet_y":49,"short_name":"lotus","short_names":["lotus"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":687,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CORAL","unified":"1FAB8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab8.png","sheet_x":55,"sheet_y":50,"short_name":"coral","short_names":["coral"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":666,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EMPTY NEST","unified":"1FAB9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fab9.png","sheet_x":55,"sheet_y":51,"short_name":"empty_nest","short_names":["empty_nest"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":709,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEST WITH EGGS","unified":"1FABA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faba.png","sheet_x":55,"sheet_y":52,"short_name":"nest_with_eggs","short_names":["nest_with_eggs"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":710,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HYACINTH","unified":"1FABB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fabb.png","sheet_x":55,"sheet_y":53,"short_name":"hyacinth","short_names":["hyacinth"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-flower","sort_order":695,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JELLYFISH","unified":"1FABC","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fabc.png","sheet_x":55,"sheet_y":54,"short_name":"jellyfish","short_names":["jellyfish"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-marine","sort_order":667,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WING","unified":"1FABD","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fabd.png","sheet_x":55,"sheet_y":55,"short_name":"wing","short_names":["wing"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":643,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GOOSE","unified":"1FABF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fabf.png","sheet_x":55,"sheet_y":56,"short_name":"goose","short_names":["goose"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-bird","sort_order":645,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ANATOMICAL HEART","unified":"1FAC0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fac0.png","sheet_x":55,"sheet_y":57,"short_name":"anatomical_heart","short_names":["anatomical_heart"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":221,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LUNGS","unified":"1FAC1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fac1.png","sheet_x":55,"sheet_y":58,"short_name":"lungs","short_names":["lungs"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":222,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PEOPLE HUGGING","unified":"1FAC2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fac2.png","sheet_x":55,"sheet_y":59,"short_name":"people_hugging","short_names":["people_hugging"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-symbol","sort_order":547,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PREGNANT MAN","unified":"1FAC3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fac3.png","sheet_x":55,"sheet_y":60,"short_name":"pregnant_man","short_names":["pregnant_man"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":364,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAC3-1F3FB","non_qualified":null,"image":"1fac3-1f3fb.png","sheet_x":55,"sheet_y":61,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAC3-1F3FC","non_qualified":null,"image":"1fac3-1f3fc.png","sheet_x":56,"sheet_y":0,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAC3-1F3FD","non_qualified":null,"image":"1fac3-1f3fd.png","sheet_x":56,"sheet_y":1,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAC3-1F3FE","non_qualified":null,"image":"1fac3-1f3fe.png","sheet_x":56,"sheet_y":2,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAC3-1F3FF","non_qualified":null,"image":"1fac3-1f3ff.png","sheet_x":56,"sheet_y":3,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PREGNANT PERSON","unified":"1FAC4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fac4.png","sheet_x":56,"sheet_y":4,"short_name":"pregnant_person","short_names":["pregnant_person"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":365,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAC4-1F3FB","non_qualified":null,"image":"1fac4-1f3fb.png","sheet_x":56,"sheet_y":5,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAC4-1F3FC","non_qualified":null,"image":"1fac4-1f3fc.png","sheet_x":56,"sheet_y":6,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAC4-1F3FD","non_qualified":null,"image":"1fac4-1f3fd.png","sheet_x":56,"sheet_y":7,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAC4-1F3FE","non_qualified":null,"image":"1fac4-1f3fe.png","sheet_x":56,"sheet_y":8,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAC4-1F3FF","non_qualified":null,"image":"1fac4-1f3ff.png","sheet_x":56,"sheet_y":9,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PERSON WITH CROWN","unified":"1FAC5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fac5.png","sheet_x":56,"sheet_y":10,"short_name":"person_with_crown","short_names":["person_with_crown"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-role","sort_order":349,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAC5-1F3FB","non_qualified":null,"image":"1fac5-1f3fb.png","sheet_x":56,"sheet_y":11,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAC5-1F3FC","non_qualified":null,"image":"1fac5-1f3fc.png","sheet_x":56,"sheet_y":12,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAC5-1F3FD","non_qualified":null,"image":"1fac5-1f3fd.png","sheet_x":56,"sheet_y":13,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAC5-1F3FE","non_qualified":null,"image":"1fac5-1f3fe.png","sheet_x":56,"sheet_y":14,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAC5-1F3FF","non_qualified":null,"image":"1fac5-1f3ff.png","sheet_x":56,"sheet_y":15,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MOOSE","unified":"1FACE","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1face.png","sheet_x":56,"sheet_y":16,"short_name":"moose","short_names":["moose"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":579,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DONKEY","unified":"1FACF","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1facf.png","sheet_x":56,"sheet_y":17,"short_name":"donkey","short_names":["donkey"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"animal-mammal","sort_order":580,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLUEBERRIES","unified":"1FAD0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad0.png","sheet_x":56,"sheet_y":18,"short_name":"blueberries","short_names":["blueberries"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":727,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BELL PEPPER","unified":"1FAD1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad1.png","sheet_x":56,"sheet_y":19,"short_name":"bell_pepper","short_names":["bell_pepper"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":738,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OLIVE","unified":"1FAD2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad2.png","sheet_x":56,"sheet_y":20,"short_name":"olive","short_names":["olive"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-fruit","sort_order":730,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLATBREAD","unified":"1FAD3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad3.png","sheet_x":56,"sheet_y":21,"short_name":"flatbread","short_names":["flatbread"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":753,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TAMALE","unified":"1FAD4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad4.png","sheet_x":56,"sheet_y":22,"short_name":"tamale","short_names":["tamale"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":770,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FONDUE","unified":"1FAD5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad5.png","sheet_x":56,"sheet_y":23,"short_name":"fondue","short_names":["fondue"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-prepared","sort_order":777,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TEAPOT","unified":"1FAD6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad6.png","sheet_x":56,"sheet_y":24,"short_name":"teapot","short_names":["teapot"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":823,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"POURING LIQUID","unified":"1FAD7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad7.png","sheet_x":56,"sheet_y":25,"short_name":"pouring_liquid","short_names":["pouring_liquid"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":834,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BEANS","unified":"1FAD8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad8.png","sheet_x":56,"sheet_y":26,"short_name":"beans","short_names":["beans"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":745,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"JAR","unified":"1FAD9","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fad9.png","sheet_x":56,"sheet_y":27,"short_name":"jar","short_names":["jar"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"dishware","sort_order":845,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GINGER ROOT","unified":"1FADA","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fada.png","sheet_x":56,"sheet_y":28,"short_name":"ginger_root","short_names":["ginger_root"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":747,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PEA POD","unified":"1FADB","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fadb.png","sheet_x":56,"sheet_y":29,"short_name":"pea_pod","short_names":["pea_pod"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"food-vegetable","sort_order":748,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MELTING FACE","unified":"1FAE0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fae0.png","sheet_x":56,"sheet_y":30,"short_name":"melting_face","short_names":["melting_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-smiling","sort_order":11,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SALUTING FACE","unified":"1FAE1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fae1.png","sheet_x":56,"sheet_y":31,"short_name":"saluting_face","short_names":["saluting_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hand","sort_order":36,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH OPEN EYES AND HAND OVER MOUTH","unified":"1FAE2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fae2.png","sheet_x":56,"sheet_y":32,"short_name":"face_with_open_eyes_and_hand_over_mouth","short_names":["face_with_open_eyes_and_hand_over_mouth"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hand","sort_order":32,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH PEEKING EYE","unified":"1FAE3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fae3.png","sheet_x":56,"sheet_y":33,"short_name":"face_with_peeking_eye","short_names":["face_with_peeking_eye"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-hand","sort_order":33,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FACE WITH DIAGONAL MOUTH","unified":"1FAE4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fae4.png","sheet_x":56,"sheet_y":34,"short_name":"face_with_diagonal_mouth","short_names":["face_with_diagonal_mouth"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":77,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOTTED LINE FACE","unified":"1FAE5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fae5.png","sheet_x":56,"sheet_y":35,"short_name":"dotted_line_face","short_names":["dotted_line_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":42,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BITING LIP","unified":"1FAE6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fae6.png","sheet_x":56,"sheet_y":36,"short_name":"biting_lip","short_names":["biting_lip"],"text":null,"texts":null,"category":"People & Body","subcategory":"body-parts","sort_order":229,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BUBBLES","unified":"1FAE7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fae7.png","sheet_x":56,"sheet_y":37,"short_name":"bubbles","short_names":["bubbles"],"text":null,"texts":null,"category":"Objects","subcategory":"household","sort_order":1398,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHAKING FACE","unified":"1FAE8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1fae8.png","sheet_x":56,"sheet_y":38,"short_name":"shaking_face","short_names":["shaking_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-neutral-skeptical","sort_order":50,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HAND WITH INDEX FINGER AND THUMB CROSSED","unified":"1FAF0","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faf0.png","sheet_x":56,"sheet_y":39,"short_name":"hand_with_index_finger_and_thumb_crossed","short_names":["hand_with_index_finger_and_thumb_crossed"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-partial","sort_order":185,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAF0-1F3FB","non_qualified":null,"image":"1faf0-1f3fb.png","sheet_x":56,"sheet_y":40,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAF0-1F3FC","non_qualified":null,"image":"1faf0-1f3fc.png","sheet_x":56,"sheet_y":41,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAF0-1F3FD","non_qualified":null,"image":"1faf0-1f3fd.png","sheet_x":56,"sheet_y":42,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAF0-1F3FE","non_qualified":null,"image":"1faf0-1f3fe.png","sheet_x":56,"sheet_y":43,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAF0-1F3FF","non_qualified":null,"image":"1faf0-1f3ff.png","sheet_x":56,"sheet_y":44,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"RIGHTWARDS HAND","unified":"1FAF1","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faf1.png","sheet_x":56,"sheet_y":45,"short_name":"rightwards_hand","short_names":["rightwards_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":174,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAF1-1F3FB","non_qualified":null,"image":"1faf1-1f3fb.png","sheet_x":56,"sheet_y":46,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAF1-1F3FC","non_qualified":null,"image":"1faf1-1f3fc.png","sheet_x":56,"sheet_y":47,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAF1-1F3FD","non_qualified":null,"image":"1faf1-1f3fd.png","sheet_x":56,"sheet_y":48,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAF1-1F3FE","non_qualified":null,"image":"1faf1-1f3fe.png","sheet_x":56,"sheet_y":49,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAF1-1F3FF","non_qualified":null,"image":"1faf1-1f3ff.png","sheet_x":56,"sheet_y":50,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"LEFTWARDS HAND","unified":"1FAF2","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faf2.png","sheet_x":56,"sheet_y":51,"short_name":"leftwards_hand","short_names":["leftwards_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":175,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAF2-1F3FB","non_qualified":null,"image":"1faf2-1f3fb.png","sheet_x":56,"sheet_y":52,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAF2-1F3FC","non_qualified":null,"image":"1faf2-1f3fc.png","sheet_x":56,"sheet_y":53,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAF2-1F3FD","non_qualified":null,"image":"1faf2-1f3fd.png","sheet_x":56,"sheet_y":54,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAF2-1F3FE","non_qualified":null,"image":"1faf2-1f3fe.png","sheet_x":56,"sheet_y":55,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAF2-1F3FF","non_qualified":null,"image":"1faf2-1f3ff.png","sheet_x":56,"sheet_y":56,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PALM DOWN HAND","unified":"1FAF3","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faf3.png","sheet_x":56,"sheet_y":57,"short_name":"palm_down_hand","short_names":["palm_down_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":176,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAF3-1F3FB","non_qualified":null,"image":"1faf3-1f3fb.png","sheet_x":56,"sheet_y":58,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAF3-1F3FC","non_qualified":null,"image":"1faf3-1f3fc.png","sheet_x":56,"sheet_y":59,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAF3-1F3FD","non_qualified":null,"image":"1faf3-1f3fd.png","sheet_x":56,"sheet_y":60,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAF3-1F3FE","non_qualified":null,"image":"1faf3-1f3fe.png","sheet_x":56,"sheet_y":61,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAF3-1F3FF","non_qualified":null,"image":"1faf3-1f3ff.png","sheet_x":57,"sheet_y":0,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PALM UP HAND","unified":"1FAF4","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faf4.png","sheet_x":57,"sheet_y":1,"short_name":"palm_up_hand","short_names":["palm_up_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":177,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAF4-1F3FB","non_qualified":null,"image":"1faf4-1f3fb.png","sheet_x":57,"sheet_y":2,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAF4-1F3FC","non_qualified":null,"image":"1faf4-1f3fc.png","sheet_x":57,"sheet_y":3,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAF4-1F3FD","non_qualified":null,"image":"1faf4-1f3fd.png","sheet_x":57,"sheet_y":4,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAF4-1F3FE","non_qualified":null,"image":"1faf4-1f3fe.png","sheet_x":57,"sheet_y":5,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAF4-1F3FF","non_qualified":null,"image":"1faf4-1f3ff.png","sheet_x":57,"sheet_y":6,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"INDEX POINTING AT THE VIEWER","unified":"1FAF5","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faf5.png","sheet_x":57,"sheet_y":7,"short_name":"index_pointing_at_the_viewer","short_names":["index_pointing_at_the_viewer"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-single-finger","sort_order":195,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAF5-1F3FB","non_qualified":null,"image":"1faf5-1f3fb.png","sheet_x":57,"sheet_y":8,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAF5-1F3FC","non_qualified":null,"image":"1faf5-1f3fc.png","sheet_x":57,"sheet_y":9,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAF5-1F3FD","non_qualified":null,"image":"1faf5-1f3fd.png","sheet_x":57,"sheet_y":10,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAF5-1F3FE","non_qualified":null,"image":"1faf5-1f3fe.png","sheet_x":57,"sheet_y":11,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAF5-1F3FF","non_qualified":null,"image":"1faf5-1f3ff.png","sheet_x":57,"sheet_y":12,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"HEART HANDS","unified":"1FAF6","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faf6.png","sheet_x":57,"sheet_y":13,"short_name":"heart_hands","short_names":["heart_hands"],"text":null,"texts":null,"category":"People & Body","subcategory":"hands","sort_order":204,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAF6-1F3FB","non_qualified":null,"image":"1faf6-1f3fb.png","sheet_x":57,"sheet_y":14,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAF6-1F3FC","non_qualified":null,"image":"1faf6-1f3fc.png","sheet_x":57,"sheet_y":15,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAF6-1F3FD","non_qualified":null,"image":"1faf6-1f3fd.png","sheet_x":57,"sheet_y":16,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAF6-1F3FE","non_qualified":null,"image":"1faf6-1f3fe.png","sheet_x":57,"sheet_y":17,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAF6-1F3FF","non_qualified":null,"image":"1faf6-1f3ff.png","sheet_x":57,"sheet_y":18,"added_in":"14.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"LEFTWARDS PUSHING HAND","unified":"1FAF7","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faf7.png","sheet_x":57,"sheet_y":19,"short_name":"leftwards_pushing_hand","short_names":["leftwards_pushing_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":178,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAF7-1F3FB","non_qualified":null,"image":"1faf7-1f3fb.png","sheet_x":57,"sheet_y":20,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAF7-1F3FC","non_qualified":null,"image":"1faf7-1f3fc.png","sheet_x":57,"sheet_y":21,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAF7-1F3FD","non_qualified":null,"image":"1faf7-1f3fd.png","sheet_x":57,"sheet_y":22,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAF7-1F3FE","non_qualified":null,"image":"1faf7-1f3fe.png","sheet_x":57,"sheet_y":23,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAF7-1F3FF","non_qualified":null,"image":"1faf7-1f3ff.png","sheet_x":57,"sheet_y":24,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"RIGHTWARDS PUSHING HAND","unified":"1FAF8","non_qualified":null,"docomo":null,"au":null,"softbank":null,"google":null,"image":"1faf8.png","sheet_x":57,"sheet_y":25,"short_name":"rightwards_pushing_hand","short_names":["rightwards_pushing_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":179,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"1FAF8-1F3FB","non_qualified":null,"image":"1faf8-1f3fb.png","sheet_x":57,"sheet_y":26,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"1FAF8-1F3FC","non_qualified":null,"image":"1faf8-1f3fc.png","sheet_x":57,"sheet_y":27,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"1FAF8-1F3FD","non_qualified":null,"image":"1faf8-1f3fd.png","sheet_x":57,"sheet_y":28,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"1FAF8-1F3FE","non_qualified":null,"image":"1faf8-1f3fe.png","sheet_x":57,"sheet_y":29,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"1FAF8-1F3FF","non_qualified":null,"image":"1faf8-1f3ff.png","sheet_x":57,"sheet_y":30,"added_in":"15.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"DOUBLE EXCLAMATION MARK","unified":"203C-FE0F","non_qualified":"203C","docomo":"E704","au":"EB30","softbank":null,"google":"FEB06","image":"203c-fe0f.png","sheet_x":57,"sheet_y":31,"short_name":"bangbang","short_names":["bangbang"],"text":null,"texts":null,"category":"Symbols","subcategory":"punctuation","sort_order":1519,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EXCLAMATION QUESTION MARK","unified":"2049-FE0F","non_qualified":"2049","docomo":"E703","au":"EB2F","softbank":null,"google":"FEB05","image":"2049-fe0f.png","sheet_x":57,"sheet_y":32,"short_name":"interrobang","short_names":["interrobang"],"text":null,"texts":null,"category":"Symbols","subcategory":"punctuation","sort_order":1520,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRADE MARK SIGN","unified":"2122-FE0F","non_qualified":"2122","docomo":"E732","au":"E54E","softbank":"E537","google":"FEB2A","image":"2122-fe0f.png","sheet_x":57,"sheet_y":33,"short_name":"tm","short_names":["tm"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1548,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"INFORMATION SOURCE","unified":"2139-FE0F","non_qualified":"2139","docomo":null,"au":"E533","softbank":null,"google":"FEB47","image":"2139-fe0f.png","sheet_x":57,"sheet_y":34,"short_name":"information_source","short_names":["information_source"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1573,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEFT RIGHT ARROW","unified":"2194-FE0F","non_qualified":"2194","docomo":"E73C","au":"EB7A","softbank":null,"google":"FEAF6","image":"2194-fe0f.png","sheet_x":57,"sheet_y":35,"short_name":"left_right_arrow","short_names":["left_right_arrow"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1447,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UP DOWN ARROW","unified":"2195-FE0F","non_qualified":"2195","docomo":"E73D","au":"EB7B","softbank":null,"google":"FEAF7","image":"2195-fe0f.png","sheet_x":57,"sheet_y":36,"short_name":"arrow_up_down","short_names":["arrow_up_down"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1446,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NORTH WEST ARROW","unified":"2196-FE0F","non_qualified":"2196","docomo":"E697","au":"E54C","softbank":"E237","google":"FEAF2","image":"2196-fe0f.png","sheet_x":57,"sheet_y":37,"short_name":"arrow_upper_left","short_names":["arrow_upper_left"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1445,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NORTH EAST ARROW","unified":"2197-FE0F","non_qualified":"2197","docomo":"E678","au":"E555","softbank":"E236","google":"FEAF0","image":"2197-fe0f.png","sheet_x":57,"sheet_y":38,"short_name":"arrow_upper_right","short_names":["arrow_upper_right"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1439,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SOUTH EAST ARROW","unified":"2198-FE0F","non_qualified":"2198","docomo":"E696","au":"E54D","softbank":"E238","google":"FEAF1","image":"2198-fe0f.png","sheet_x":57,"sheet_y":39,"short_name":"arrow_lower_right","short_names":["arrow_lower_right"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1441,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SOUTH WEST ARROW","unified":"2199-FE0F","non_qualified":"2199","docomo":"E6A5","au":"E556","softbank":"E239","google":"FEAF3","image":"2199-fe0f.png","sheet_x":57,"sheet_y":40,"short_name":"arrow_lower_left","short_names":["arrow_lower_left"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1443,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEFTWARDS ARROW WITH HOOK","unified":"21A9-FE0F","non_qualified":"21A9","docomo":"E6DA","au":"E55D","softbank":null,"google":"FEB83","image":"21a9-fe0f.png","sheet_x":57,"sheet_y":41,"short_name":"leftwards_arrow_with_hook","short_names":["leftwards_arrow_with_hook"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1448,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RIGHTWARDS ARROW WITH HOOK","unified":"21AA-FE0F","non_qualified":"21AA","docomo":null,"au":"E55C","softbank":null,"google":"FEB88","image":"21aa-fe0f.png","sheet_x":57,"sheet_y":42,"short_name":"arrow_right_hook","short_names":["arrow_right_hook"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1449,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WATCH","unified":"231A","non_qualified":null,"docomo":"E71F","au":"E57A","softbank":null,"google":"FE01D","image":"231a.png","sheet_x":57,"sheet_y":43,"short_name":"watch","short_names":["watch"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":989,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOURGLASS","unified":"231B","non_qualified":null,"docomo":"E71C","au":"E57B","softbank":null,"google":"FE01C","image":"231b.png","sheet_x":57,"sheet_y":44,"short_name":"hourglass","short_names":["hourglass"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":987,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"KEYBOARD","unified":"2328-FE0F","non_qualified":"2328","docomo":null,"au":null,"softbank":null,"google":null,"image":"2328-fe0f.png","sheet_x":57,"sheet_y":45,"short_name":"keyboard","short_names":["keyboard"],"text":null,"texts":null,"category":"Objects","subcategory":"computer","sort_order":1238,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EJECT BUTTON","unified":"23CF-FE0F","non_qualified":"23CF","docomo":null,"au":null,"softbank":null,"google":null,"image":"23cf-fe0f.png","sheet_x":57,"sheet_y":46,"short_name":"eject","short_names":["eject"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1502,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK RIGHT-POINTING DOUBLE TRIANGLE","unified":"23E9","non_qualified":null,"docomo":null,"au":"E530","softbank":"E23C","google":"FEAFE","image":"23e9.png","sheet_x":57,"sheet_y":47,"short_name":"fast_forward","short_names":["fast_forward"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1489,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK LEFT-POINTING DOUBLE TRIANGLE","unified":"23EA","non_qualified":null,"docomo":null,"au":"E52F","softbank":"E23D","google":"FEAFF","image":"23ea.png","sheet_x":57,"sheet_y":48,"short_name":"rewind","short_names":["rewind"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1493,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK UP-POINTING DOUBLE TRIANGLE","unified":"23EB","non_qualified":null,"docomo":null,"au":"E545","softbank":null,"google":"FEB03","image":"23eb.png","sheet_x":57,"sheet_y":49,"short_name":"arrow_double_up","short_names":["arrow_double_up"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1496,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK DOWN-POINTING DOUBLE TRIANGLE","unified":"23EC","non_qualified":null,"docomo":null,"au":"E544","softbank":null,"google":"FEB02","image":"23ec.png","sheet_x":57,"sheet_y":50,"short_name":"arrow_double_down","short_names":["arrow_double_down"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1498,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEXT TRACK BUTTON","unified":"23ED-FE0F","non_qualified":"23ED","docomo":null,"au":null,"softbank":null,"google":null,"image":"23ed-fe0f.png","sheet_x":57,"sheet_y":51,"short_name":"black_right_pointing_double_triangle_with_vertical_bar","short_names":["black_right_pointing_double_triangle_with_vertical_bar"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1490,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LAST TRACK BUTTON","unified":"23EE-FE0F","non_qualified":"23EE","docomo":null,"au":null,"softbank":null,"google":null,"image":"23ee-fe0f.png","sheet_x":57,"sheet_y":52,"short_name":"black_left_pointing_double_triangle_with_vertical_bar","short_names":["black_left_pointing_double_triangle_with_vertical_bar"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1494,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PLAY OR PAUSE BUTTON","unified":"23EF-FE0F","non_qualified":"23EF","docomo":null,"au":null,"softbank":null,"google":null,"image":"23ef-fe0f.png","sheet_x":57,"sheet_y":53,"short_name":"black_right_pointing_triangle_with_double_vertical_bar","short_names":["black_right_pointing_triangle_with_double_vertical_bar"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1491,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ALARM CLOCK","unified":"23F0","non_qualified":null,"docomo":"E6BA","au":"E594","softbank":null,"google":"FE02A","image":"23f0.png","sheet_x":57,"sheet_y":54,"short_name":"alarm_clock","short_names":["alarm_clock"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":990,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STOPWATCH","unified":"23F1-FE0F","non_qualified":"23F1","docomo":null,"au":null,"softbank":null,"google":null,"image":"23f1-fe0f.png","sheet_x":57,"sheet_y":55,"short_name":"stopwatch","short_names":["stopwatch"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":991,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TIMER CLOCK","unified":"23F2-FE0F","non_qualified":"23F2","docomo":null,"au":null,"softbank":null,"google":null,"image":"23f2-fe0f.png","sheet_x":57,"sheet_y":56,"short_name":"timer_clock","short_names":["timer_clock"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":992,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOURGLASS WITH FLOWING SAND","unified":"23F3","non_qualified":null,"docomo":"E71C","au":"E47C","softbank":null,"google":"FE01B","image":"23f3.png","sheet_x":57,"sheet_y":57,"short_name":"hourglass_flowing_sand","short_names":["hourglass_flowing_sand"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"time","sort_order":988,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PAUSE BUTTON","unified":"23F8-FE0F","non_qualified":"23F8","docomo":null,"au":null,"softbank":null,"google":null,"image":"23f8-fe0f.png","sheet_x":57,"sheet_y":58,"short_name":"double_vertical_bar","short_names":["double_vertical_bar"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1499,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STOP BUTTON","unified":"23F9-FE0F","non_qualified":"23F9","docomo":null,"au":null,"softbank":null,"google":null,"image":"23f9-fe0f.png","sheet_x":57,"sheet_y":59,"short_name":"black_square_for_stop","short_names":["black_square_for_stop"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1500,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RECORD BUTTON","unified":"23FA-FE0F","non_qualified":"23FA","docomo":null,"au":null,"softbank":null,"google":null,"image":"23fa-fe0f.png","sheet_x":57,"sheet_y":60,"short_name":"black_circle_for_record","short_names":["black_circle_for_record"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1501,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CIRCLED LATIN CAPITAL LETTER M","unified":"24C2-FE0F","non_qualified":"24C2","docomo":"E65C","au":"E5BC","softbank":null,"google":"FE7E1","image":"24c2-fe0f.png","sheet_x":57,"sheet_y":61,"short_name":"m","short_names":["m"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1575,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK SMALL SQUARE","unified":"25AA-FE0F","non_qualified":"25AA","docomo":null,"au":"E532","softbank":null,"google":"FEB6E","image":"25aa-fe0f.png","sheet_x":58,"sheet_y":0,"short_name":"black_small_square","short_names":["black_small_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1623,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE SMALL SQUARE","unified":"25AB-FE0F","non_qualified":"25AB","docomo":null,"au":"E531","softbank":null,"google":"FEB6D","image":"25ab-fe0f.png","sheet_x":58,"sheet_y":1,"short_name":"white_small_square","short_names":["white_small_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1624,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK RIGHT-POINTING TRIANGLE","unified":"25B6-FE0F","non_qualified":"25B6","docomo":null,"au":"E52E","softbank":"E23A","google":"FEAFC","image":"25b6-fe0f.png","sheet_x":58,"sheet_y":2,"short_name":"arrow_forward","short_names":["arrow_forward"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1488,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK LEFT-POINTING TRIANGLE","unified":"25C0-FE0F","non_qualified":"25C0","docomo":null,"au":"E52D","softbank":"E23B","google":"FEAFD","image":"25c0-fe0f.png","sheet_x":58,"sheet_y":3,"short_name":"arrow_backward","short_names":["arrow_backward"],"text":null,"texts":null,"category":"Symbols","subcategory":"av-symbol","sort_order":1492,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE MEDIUM SQUARE","unified":"25FB-FE0F","non_qualified":"25FB","docomo":null,"au":"E538","softbank":null,"google":"FEB71","image":"25fb-fe0f.png","sheet_x":58,"sheet_y":4,"short_name":"white_medium_square","short_names":["white_medium_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1620,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK MEDIUM SQUARE","unified":"25FC-FE0F","non_qualified":"25FC","docomo":null,"au":"E539","softbank":null,"google":"FEB72","image":"25fc-fe0f.png","sheet_x":58,"sheet_y":5,"short_name":"black_medium_square","short_names":["black_medium_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1619,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE MEDIUM SMALL SQUARE","unified":"25FD","non_qualified":null,"docomo":null,"au":"E534","softbank":null,"google":"FEB6F","image":"25fd.png","sheet_x":58,"sheet_y":6,"short_name":"white_medium_small_square","short_names":["white_medium_small_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1622,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK MEDIUM SMALL SQUARE","unified":"25FE","non_qualified":null,"docomo":null,"au":"E535","softbank":null,"google":"FEB70","image":"25fe.png","sheet_x":58,"sheet_y":7,"short_name":"black_medium_small_square","short_names":["black_medium_small_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1621,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK SUN WITH RAYS","unified":"2600-FE0F","non_qualified":"2600","docomo":"E63E","au":"E488","softbank":"E04A","google":"FE000","image":"2600-fe0f.png","sheet_x":58,"sheet_y":8,"short_name":"sunny","short_names":["sunny"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1031,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOUD","unified":"2601-FE0F","non_qualified":"2601","docomo":"E63F","au":"E48D","softbank":"E049","google":"FE001","image":"2601-fe0f.png","sheet_x":58,"sheet_y":9,"short_name":"cloud","short_names":["cloud"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1039,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UMBRELLA","unified":"2602-FE0F","non_qualified":"2602","docomo":null,"au":null,"softbank":null,"google":null,"image":"2602-fe0f.png","sheet_x":58,"sheet_y":10,"short_name":"umbrella","short_names":["umbrella"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1054,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SNOWMAN","unified":"2603-FE0F","non_qualified":"2603","docomo":null,"au":null,"softbank":null,"google":null,"image":"2603-fe0f.png","sheet_x":58,"sheet_y":11,"short_name":"snowman","short_names":["snowman"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1059,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COMET","unified":"2604-FE0F","non_qualified":"2604","docomo":null,"au":null,"softbank":null,"google":null,"image":"2604-fe0f.png","sheet_x":58,"sheet_y":12,"short_name":"comet","short_names":["comet"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1061,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK TELEPHONE","unified":"260E-FE0F","non_qualified":"260E","docomo":"E687","au":"E596","softbank":"E009","google":"FE523","image":"260e-fe0f.png","sheet_x":58,"sheet_y":13,"short_name":"phone","short_names":["phone","telephone"],"text":null,"texts":null,"category":"Objects","subcategory":"phone","sort_order":1228,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BALLOT BOX WITH CHECK","unified":"2611-FE0F","non_qualified":"2611","docomo":null,"au":"EB02","softbank":null,"google":"FEB8B","image":"2611-fe0f.png","sheet_x":58,"sheet_y":14,"short_name":"ballot_box_with_check","short_names":["ballot_box_with_check"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1536,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UMBRELLA WITH RAIN DROPS","unified":"2614","non_qualified":null,"docomo":"E640","au":"E48C","softbank":"E04B","google":"FE002","image":"2614.png","sheet_x":58,"sheet_y":15,"short_name":"umbrella_with_rain_drops","short_names":["umbrella_with_rain_drops"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1055,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOT BEVERAGE","unified":"2615","non_qualified":null,"docomo":"E670","au":"E597","softbank":"E045","google":"FE981","image":"2615.png","sheet_x":58,"sheet_y":16,"short_name":"coffee","short_names":["coffee"],"text":null,"texts":null,"category":"Food & Drink","subcategory":"drink","sort_order":822,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHAMROCK","unified":"2618-FE0F","non_qualified":"2618","docomo":null,"au":null,"softbank":null,"google":null,"image":"2618-fe0f.png","sheet_x":58,"sheet_y":17,"short_name":"shamrock","short_names":["shamrock"],"text":null,"texts":null,"category":"Animals & Nature","subcategory":"plant-other","sort_order":704,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE UP POINTING INDEX","unified":"261D-FE0F","non_qualified":"261D","docomo":null,"au":"E4F6","softbank":"E00F","google":"FEB98","image":"261d-fe0f.png","sheet_x":58,"sheet_y":18,"short_name":"point_up","short_names":["point_up"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-single-finger","sort_order":194,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"261D-1F3FB","non_qualified":null,"image":"261d-1f3fb.png","sheet_x":58,"sheet_y":19,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"261D-1F3FC","non_qualified":null,"image":"261d-1f3fc.png","sheet_x":58,"sheet_y":20,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"261D-1F3FD","non_qualified":null,"image":"261d-1f3fd.png","sheet_x":58,"sheet_y":21,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"261D-1F3FE","non_qualified":null,"image":"261d-1f3fe.png","sheet_x":58,"sheet_y":22,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"261D-1F3FF","non_qualified":null,"image":"261d-1f3ff.png","sheet_x":58,"sheet_y":23,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"SKULL AND CROSSBONES","unified":"2620-FE0F","non_qualified":"2620","docomo":null,"au":null,"softbank":null,"google":null,"image":"2620-fe0f.png","sheet_x":58,"sheet_y":24,"short_name":"skull_and_crossbones","short_names":["skull_and_crossbones"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-negative","sort_order":109,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RADIOACTIVE","unified":"2622-FE0F","non_qualified":"2622","docomo":null,"au":null,"softbank":null,"google":null,"image":"2622-fe0f.png","sheet_x":58,"sheet_y":25,"short_name":"radioactive_sign","short_names":["radioactive_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1436,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BIOHAZARD","unified":"2623-FE0F","non_qualified":"2623","docomo":null,"au":null,"softbank":null,"google":null,"image":"2623-fe0f.png","sheet_x":58,"sheet_y":26,"short_name":"biohazard_sign","short_names":["biohazard_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1437,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ORTHODOX CROSS","unified":"2626-FE0F","non_qualified":"2626","docomo":null,"au":null,"softbank":null,"google":null,"image":"2626-fe0f.png","sheet_x":58,"sheet_y":27,"short_name":"orthodox_cross","short_names":["orthodox_cross"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1466,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STAR AND CRESCENT","unified":"262A-FE0F","non_qualified":"262A","docomo":null,"au":null,"softbank":null,"google":null,"image":"262a-fe0f.png","sheet_x":58,"sheet_y":28,"short_name":"star_and_crescent","short_names":["star_and_crescent"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1467,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PEACE SYMBOL","unified":"262E-FE0F","non_qualified":"262E","docomo":null,"au":null,"softbank":null,"google":null,"image":"262e-fe0f.png","sheet_x":58,"sheet_y":29,"short_name":"peace_symbol","short_names":["peace_symbol"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1468,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"YIN YANG","unified":"262F-FE0F","non_qualified":"262F","docomo":null,"au":null,"softbank":null,"google":null,"image":"262f-fe0f.png","sheet_x":58,"sheet_y":30,"short_name":"yin_yang","short_names":["yin_yang"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1464,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHEEL OF DHARMA","unified":"2638-FE0F","non_qualified":"2638","docomo":null,"au":null,"softbank":null,"google":null,"image":"2638-fe0f.png","sheet_x":58,"sheet_y":31,"short_name":"wheel_of_dharma","short_names":["wheel_of_dharma"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1463,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FROWNING FACE","unified":"2639-FE0F","non_qualified":"2639","docomo":null,"au":null,"softbank":null,"google":null,"image":"2639-fe0f.png","sheet_x":58,"sheet_y":32,"short_name":"white_frowning_face","short_names":["white_frowning_face"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-concerned","sort_order":80,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE SMILING FACE","unified":"263A-FE0F","non_qualified":"263A","docomo":"E6F0","au":"E4FB","softbank":"E414","google":"FE336","image":"263a-fe0f.png","sheet_x":58,"sheet_y":33,"short_name":"relaxed","short_names":["relaxed"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"face-affection","sort_order":20,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FEMALE SIGN","unified":"2640-FE0F","non_qualified":"2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"2640-fe0f.png","sheet_x":58,"sheet_y":34,"short_name":"female_sign","short_names":["female_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"gender","sort_order":1510,"added_in":"4.0","has_img_apple":false,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MALE SIGN","unified":"2642-FE0F","non_qualified":"2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"2642-fe0f.png","sheet_x":58,"sheet_y":35,"short_name":"male_sign","short_names":["male_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"gender","sort_order":1511,"added_in":"4.0","has_img_apple":false,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ARIES","unified":"2648","non_qualified":null,"docomo":"E646","au":"E48F","softbank":"E23F","google":"FE02B","image":"2648.png","sheet_x":58,"sheet_y":36,"short_name":"aries","short_names":["aries"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1472,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TAURUS","unified":"2649","non_qualified":null,"docomo":"E647","au":"E490","softbank":"E240","google":"FE02C","image":"2649.png","sheet_x":58,"sheet_y":37,"short_name":"taurus","short_names":["taurus"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1473,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GEMINI","unified":"264A","non_qualified":null,"docomo":"E648","au":"E491","softbank":"E241","google":"FE02D","image":"264a.png","sheet_x":58,"sheet_y":38,"short_name":"gemini","short_names":["gemini"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1474,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CANCER","unified":"264B","non_qualified":null,"docomo":"E649","au":"E492","softbank":"E242","google":"FE02E","image":"264b.png","sheet_x":58,"sheet_y":39,"short_name":"cancer","short_names":["cancer"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1475,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEO","unified":"264C","non_qualified":null,"docomo":"E64A","au":"E493","softbank":"E243","google":"FE02F","image":"264c.png","sheet_x":58,"sheet_y":40,"short_name":"leo","short_names":["leo"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1476,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"VIRGO","unified":"264D","non_qualified":null,"docomo":"E64B","au":"E494","softbank":"E244","google":"FE030","image":"264d.png","sheet_x":58,"sheet_y":41,"short_name":"virgo","short_names":["virgo"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1477,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LIBRA","unified":"264E","non_qualified":null,"docomo":"E64C","au":"E495","softbank":"E245","google":"FE031","image":"264e.png","sheet_x":58,"sheet_y":42,"short_name":"libra","short_names":["libra"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1478,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SCORPIUS","unified":"264F","non_qualified":null,"docomo":"E64D","au":"E496","softbank":"E246","google":"FE032","image":"264f.png","sheet_x":58,"sheet_y":43,"short_name":"scorpius","short_names":["scorpius"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1479,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SAGITTARIUS","unified":"2650","non_qualified":null,"docomo":"E64E","au":"E497","softbank":"E247","google":"FE033","image":"2650.png","sheet_x":58,"sheet_y":44,"short_name":"sagittarius","short_names":["sagittarius"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1480,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CAPRICORN","unified":"2651","non_qualified":null,"docomo":"E64F","au":"E498","softbank":"E248","google":"FE034","image":"2651.png","sheet_x":58,"sheet_y":45,"short_name":"capricorn","short_names":["capricorn"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1481,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AQUARIUS","unified":"2652","non_qualified":null,"docomo":"E650","au":"E499","softbank":"E249","google":"FE035","image":"2652.png","sheet_x":58,"sheet_y":46,"short_name":"aquarius","short_names":["aquarius"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1482,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PISCES","unified":"2653","non_qualified":null,"docomo":"E651","au":"E49A","softbank":"E24A","google":"FE036","image":"2653.png","sheet_x":58,"sheet_y":47,"short_name":"pisces","short_names":["pisces"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1483,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHESS PAWN","unified":"265F-FE0F","non_qualified":"265F","docomo":null,"au":null,"softbank":null,"google":null,"image":"265f-fe0f.png","sheet_x":58,"sheet_y":48,"short_name":"chess_pawn","short_names":["chess_pawn"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1139,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK SPADE SUIT","unified":"2660-FE0F","non_qualified":"2660","docomo":"E68E","au":"E5A1","softbank":"E20E","google":"FEB1B","image":"2660-fe0f.png","sheet_x":58,"sheet_y":49,"short_name":"spades","short_names":["spades"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1135,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK CLUB SUIT","unified":"2663-FE0F","non_qualified":"2663","docomo":"E690","au":"E5A3","softbank":"E20F","google":"FEB1D","image":"2663-fe0f.png","sheet_x":58,"sheet_y":50,"short_name":"clubs","short_names":["clubs"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1138,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK HEART SUIT","unified":"2665-FE0F","non_qualified":"2665","docomo":"E68D","au":"EAA5","softbank":"E20C","google":"FEB1A","image":"2665-fe0f.png","sheet_x":58,"sheet_y":51,"short_name":"hearts","short_names":["hearts"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1136,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK DIAMOND SUIT","unified":"2666-FE0F","non_qualified":"2666","docomo":"E68F","au":"E5A2","softbank":"E20D","google":"FEB1C","image":"2666-fe0f.png","sheet_x":58,"sheet_y":52,"short_name":"diamonds","short_names":["diamonds"],"text":null,"texts":null,"category":"Activities","subcategory":"game","sort_order":1137,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HOT SPRINGS","unified":"2668-FE0F","non_qualified":"2668","docomo":"E6F7","au":"E4BC","softbank":"E123","google":"FE7FA","image":"2668-fe0f.png","sheet_x":58,"sheet_y":53,"short_name":"hotsprings","short_names":["hotsprings"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":906,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK UNIVERSAL RECYCLING SYMBOL","unified":"267B-FE0F","non_qualified":"267B","docomo":"E735","au":"EB79","softbank":null,"google":"FEB2C","image":"267b-fe0f.png","sheet_x":58,"sheet_y":54,"short_name":"recycle","short_names":["recycle"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1529,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"INFINITY","unified":"267E-FE0F","non_qualified":"267E","docomo":null,"au":null,"softbank":null,"google":null,"image":"267e-fe0f.png","sheet_x":58,"sheet_y":55,"short_name":"infinity","short_names":["infinity"],"text":null,"texts":null,"category":"Symbols","subcategory":"math","sort_order":1518,"added_in":"11.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHEELCHAIR SYMBOL","unified":"267F","non_qualified":null,"docomo":"E69B","au":"E47F","softbank":"E20A","google":"FEB20","image":"267f.png","sheet_x":58,"sheet_y":56,"short_name":"wheelchair","short_names":["wheelchair"],"text":null,"texts":null,"category":"Symbols","subcategory":"transport-sign","sort_order":1415,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HAMMER AND PICK","unified":"2692-FE0F","non_qualified":"2692","docomo":null,"au":null,"softbank":null,"google":null,"image":"2692-fe0f.png","sheet_x":58,"sheet_y":57,"short_name":"hammer_and_pick","short_names":["hammer_and_pick"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1341,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ANCHOR","unified":"2693","non_qualified":null,"docomo":"E661","au":"E4A9","softbank":null,"google":"FE4C1","image":"2693.png","sheet_x":58,"sheet_y":58,"short_name":"anchor","short_names":["anchor"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-water","sort_order":963,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CROSSED SWORDS","unified":"2694-FE0F","non_qualified":"2694","docomo":null,"au":null,"softbank":null,"google":null,"image":"2694-fe0f.png","sheet_x":58,"sheet_y":59,"short_name":"crossed_swords","short_names":["crossed_swords"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1344,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MEDICAL SYMBOL","unified":"2695-FE0F","non_qualified":"2695","docomo":null,"au":null,"softbank":null,"google":null,"image":"2695-fe0f.png","sheet_x":58,"sheet_y":60,"short_name":"medical_symbol","short_names":["medical_symbol","staff_of_aesculapius"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1528,"added_in":"4.0","has_img_apple":false,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BALANCE SCALE","unified":"2696-FE0F","non_qualified":"2696","docomo":null,"au":null,"softbank":null,"google":null,"image":"2696-fe0f.png","sheet_x":58,"sheet_y":61,"short_name":"scales","short_names":["scales"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1355,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ALEMBIC","unified":"2697-FE0F","non_qualified":"2697","docomo":null,"au":null,"softbank":null,"google":null,"image":"2697-fe0f.png","sheet_x":59,"sheet_y":0,"short_name":"alembic","short_names":["alembic"],"text":null,"texts":null,"category":"Objects","subcategory":"science","sort_order":1364,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"GEAR","unified":"2699-FE0F","non_qualified":"2699","docomo":null,"au":null,"softbank":null,"google":null,"image":"2699-fe0f.png","sheet_x":59,"sheet_y":1,"short_name":"gear","short_names":["gear"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1353,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ATOM SYMBOL","unified":"269B-FE0F","non_qualified":"269B","docomo":null,"au":null,"softbank":null,"google":null,"image":"269b-fe0f.png","sheet_x":59,"sheet_y":2,"short_name":"atom_symbol","short_names":["atom_symbol"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1460,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLEUR-DE-LIS","unified":"269C-FE0F","non_qualified":"269C","docomo":null,"au":null,"softbank":null,"google":null,"image":"269c-fe0f.png","sheet_x":59,"sheet_y":3,"short_name":"fleur_de_lis","short_names":["fleur_de_lis"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1530,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WARNING SIGN","unified":"26A0-FE0F","non_qualified":"26A0","docomo":"E737","au":"E481","softbank":"E252","google":"FEB23","image":"26a0-fe0f.png","sheet_x":59,"sheet_y":4,"short_name":"warning","short_names":["warning"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1425,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HIGH VOLTAGE SIGN","unified":"26A1","non_qualified":null,"docomo":"E642","au":"E487","softbank":"E13D","google":"FE004","image":"26a1.png","sheet_x":59,"sheet_y":5,"short_name":"zap","short_names":["zap"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1057,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"TRANSGENDER SYMBOL","unified":"26A7-FE0F","non_qualified":"26A7","docomo":null,"au":null,"softbank":null,"google":null,"image":"26a7-fe0f.png","sheet_x":59,"sheet_y":6,"short_name":"transgender_symbol","short_names":["transgender_symbol"],"text":null,"texts":null,"category":"Symbols","subcategory":"gender","sort_order":1512,"added_in":"13.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MEDIUM WHITE CIRCLE","unified":"26AA","non_qualified":null,"docomo":"E69C","au":"E53A","softbank":null,"google":"FEB65","image":"26aa.png","sheet_x":59,"sheet_y":7,"short_name":"white_circle","short_names":["white_circle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1609,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MEDIUM BLACK CIRCLE","unified":"26AB","non_qualified":null,"docomo":"E69C","au":"E53B","softbank":null,"google":"FEB66","image":"26ab.png","sheet_x":59,"sheet_y":8,"short_name":"black_circle","short_names":["black_circle"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1608,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"COFFIN","unified":"26B0-FE0F","non_qualified":"26B0","docomo":null,"au":null,"softbank":null,"google":null,"image":"26b0-fe0f.png","sheet_x":59,"sheet_y":9,"short_name":"coffin","short_names":["coffin"],"text":null,"texts":null,"category":"Objects","subcategory":"other-object","sort_order":1404,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FUNERAL URN","unified":"26B1-FE0F","non_qualified":"26B1","docomo":null,"au":null,"softbank":null,"google":null,"image":"26b1-fe0f.png","sheet_x":59,"sheet_y":10,"short_name":"funeral_urn","short_names":["funeral_urn"],"text":null,"texts":null,"category":"Objects","subcategory":"other-object","sort_order":1406,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SOCCER BALL","unified":"26BD","non_qualified":null,"docomo":"E656","au":"E4B6","softbank":"E018","google":"FE7D4","image":"26bd.png","sheet_x":59,"sheet_y":11,"short_name":"soccer","short_names":["soccer"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1092,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BASEBALL","unified":"26BE","non_qualified":null,"docomo":"E653","au":"E4BA","softbank":"E016","google":"FE7D1","image":"26be.png","sheet_x":59,"sheet_y":12,"short_name":"baseball","short_names":["baseball"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1093,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SNOWMAN WITHOUT SNOW","unified":"26C4","non_qualified":null,"docomo":"E641","au":"E485","softbank":"E048","google":"FE003","image":"26c4.png","sheet_x":59,"sheet_y":13,"short_name":"snowman_without_snow","short_names":["snowman_without_snow"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1060,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SUN BEHIND CLOUD","unified":"26C5","non_qualified":null,"docomo":"E63E-E63F","au":"E48E","softbank":null,"google":"FE00F","image":"26c5.png","sheet_x":59,"sheet_y":14,"short_name":"partly_sunny","short_names":["partly_sunny"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1040,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CLOUD WITH LIGHTNING AND RAIN","unified":"26C8-FE0F","non_qualified":"26C8","docomo":null,"au":null,"softbank":null,"google":null,"image":"26c8-fe0f.png","sheet_x":59,"sheet_y":15,"short_name":"thunder_cloud_and_rain","short_names":["thunder_cloud_and_rain"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1041,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"OPHIUCHUS","unified":"26CE","non_qualified":null,"docomo":null,"au":"E49B","softbank":"E24B","google":"FE037","image":"26ce.png","sheet_x":59,"sheet_y":16,"short_name":"ophiuchus","short_names":["ophiuchus"],"text":null,"texts":null,"category":"Symbols","subcategory":"zodiac","sort_order":1484,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PICK","unified":"26CF-FE0F","non_qualified":"26CF","docomo":null,"au":null,"softbank":null,"google":null,"image":"26cf-fe0f.png","sheet_x":59,"sheet_y":17,"short_name":"pick","short_names":["pick"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1340,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RESCUE WORKER\u2019S HELMET","unified":"26D1-FE0F","non_qualified":"26D1","docomo":null,"au":null,"softbank":null,"google":null,"image":"26d1-fe0f.png","sheet_x":59,"sheet_y":18,"short_name":"helmet_with_white_cross","short_names":["helmet_with_white_cross"],"text":null,"texts":null,"category":"Objects","subcategory":"clothing","sort_order":1192,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BROKEN CHAIN","unified":"26D3-FE0F-200D-1F4A5","non_qualified":"26D3-200D-1F4A5","docomo":null,"au":null,"softbank":null,"google":null,"image":"26d3-fe0f-200d-1f4a5.png","sheet_x":59,"sheet_y":19,"short_name":"broken_chain","short_names":["broken_chain"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1358,"added_in":"15.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":false,"has_img_facebook":false},{"name":"CHAINS","unified":"26D3-FE0F","non_qualified":"26D3","docomo":null,"au":null,"softbank":null,"google":null,"image":"26d3-fe0f.png","sheet_x":59,"sheet_y":20,"short_name":"chains","short_names":["chains"],"text":null,"texts":null,"category":"Objects","subcategory":"tool","sort_order":1359,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NO ENTRY","unified":"26D4","non_qualified":null,"docomo":"E72F","au":"E484","softbank":null,"google":"FEB26","image":"26d4.png","sheet_x":59,"sheet_y":21,"short_name":"no_entry","short_names":["no_entry"],"text":null,"texts":null,"category":"Symbols","subcategory":"warning","sort_order":1427,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SHINTO SHRINE","unified":"26E9-FE0F","non_qualified":"26E9","docomo":null,"au":null,"softbank":null,"google":null,"image":"26e9-fe0f.png","sheet_x":59,"sheet_y":22,"short_name":"shinto_shrine","short_names":["shinto_shrine"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-religious","sort_order":894,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CHURCH","unified":"26EA","non_qualified":null,"docomo":null,"au":"E5BB","softbank":"E037","google":"FE4BB","image":"26ea.png","sheet_x":59,"sheet_y":23,"short_name":"church","short_names":["church"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-religious","sort_order":890,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MOUNTAIN","unified":"26F0-FE0F","non_qualified":"26F0","docomo":null,"au":null,"softbank":null,"google":null,"image":"26f0-fe0f.png","sheet_x":59,"sheet_y":24,"short_name":"mountain","short_names":["mountain"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-geographic","sort_order":855,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UMBRELLA ON GROUND","unified":"26F1-FE0F","non_qualified":"26F1","docomo":null,"au":null,"softbank":null,"google":null,"image":"26f1-fe0f.png","sheet_x":59,"sheet_y":25,"short_name":"umbrella_on_ground","short_names":["umbrella_on_ground"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1056,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FOUNTAIN","unified":"26F2","non_qualified":null,"docomo":null,"au":"E5CF","softbank":"E121","google":"FE4BC","image":"26f2.png","sheet_x":59,"sheet_y":26,"short_name":"fountain","short_names":["fountain"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":896,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FLAG IN HOLE","unified":"26F3","non_qualified":null,"docomo":"E654","au":"E599","softbank":"E014","google":"FE7D2","image":"26f3.png","sheet_x":59,"sheet_y":27,"short_name":"golf","short_names":["golf"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1111,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FERRY","unified":"26F4-FE0F","non_qualified":"26F4","docomo":null,"au":null,"softbank":null,"google":null,"image":"26f4-fe0f.png","sheet_x":59,"sheet_y":28,"short_name":"ferry","short_names":["ferry"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-water","sort_order":969,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SAILBOAT","unified":"26F5","non_qualified":null,"docomo":"E6A3","au":"E4B4","softbank":"E01C","google":"FE7EA","image":"26f5.png","sheet_x":59,"sheet_y":29,"short_name":"boat","short_names":["boat","sailboat"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-water","sort_order":965,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SKIER","unified":"26F7-FE0F","non_qualified":"26F7","docomo":null,"au":null,"softbank":null,"google":null,"image":"26f7-fe0f.png","sheet_x":59,"sheet_y":30,"short_name":"skier","short_names":["skier"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":461,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ICE SKATE","unified":"26F8-FE0F","non_qualified":"26F8","docomo":null,"au":null,"softbank":null,"google":null,"image":"26f8-fe0f.png","sheet_x":59,"sheet_y":31,"short_name":"ice_skate","short_names":["ice_skate"],"text":null,"texts":null,"category":"Activities","subcategory":"sport","sort_order":1112,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WOMAN BOUNCING BALL","unified":"26F9-FE0F-200D-2640-FE0F","non_qualified":"26F9-200D-2640","docomo":null,"au":null,"softbank":null,"google":null,"image":"26f9-fe0f-200d-2640-fe0f.png","sheet_x":59,"sheet_y":32,"short_name":"woman-bouncing-ball","short_names":["woman-bouncing-ball"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":477,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"26F9-1F3FB-200D-2640-FE0F","non_qualified":"26F9-1F3FB-200D-2640","image":"26f9-1f3fb-200d-2640-fe0f.png","sheet_x":59,"sheet_y":33,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"26F9-1F3FC-200D-2640-FE0F","non_qualified":"26F9-1F3FC-200D-2640","image":"26f9-1f3fc-200d-2640-fe0f.png","sheet_x":59,"sheet_y":34,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"26F9-1F3FD-200D-2640-FE0F","non_qualified":"26F9-1F3FD-200D-2640","image":"26f9-1f3fd-200d-2640-fe0f.png","sheet_x":59,"sheet_y":35,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"26F9-1F3FE-200D-2640-FE0F","non_qualified":"26F9-1F3FE-200D-2640","image":"26f9-1f3fe-200d-2640-fe0f.png","sheet_x":59,"sheet_y":36,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"26F9-1F3FF-200D-2640-FE0F","non_qualified":"26F9-1F3FF-200D-2640","image":"26f9-1f3ff-200d-2640-fe0f.png","sheet_x":59,"sheet_y":37,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"MAN BOUNCING BALL","unified":"26F9-FE0F-200D-2642-FE0F","non_qualified":"26F9-200D-2642","docomo":null,"au":null,"softbank":null,"google":null,"image":"26f9-fe0f-200d-2642-fe0f.png","sheet_x":59,"sheet_y":38,"short_name":"man-bouncing-ball","short_names":["man-bouncing-ball"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":476,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":false,"skin_variations":{"1F3FB":{"unified":"26F9-1F3FB-200D-2642-FE0F","non_qualified":"26F9-1F3FB-200D-2642","image":"26f9-1f3fb-200d-2642-fe0f.png","sheet_x":59,"sheet_y":39,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"26F9-1F3FC-200D-2642-FE0F","non_qualified":"26F9-1F3FC-200D-2642","image":"26f9-1f3fc-200d-2642-fe0f.png","sheet_x":59,"sheet_y":40,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"26F9-1F3FD-200D-2642-FE0F","non_qualified":"26F9-1F3FD-200D-2642","image":"26f9-1f3fd-200d-2642-fe0f.png","sheet_x":59,"sheet_y":41,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"26F9-1F3FE-200D-2642-FE0F","non_qualified":"26F9-1F3FE-200D-2642","image":"26f9-1f3fe-200d-2642-fe0f.png","sheet_x":59,"sheet_y":42,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"26F9-1F3FF-200D-2642-FE0F","non_qualified":"26F9-1F3FF-200D-2642","image":"26f9-1f3ff-200d-2642-fe0f.png","sheet_x":59,"sheet_y":43,"added_in":"4.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoletes":"26F9-FE0F"},{"name":"PERSON BOUNCING BALL","unified":"26F9-FE0F","non_qualified":"26F9","docomo":null,"au":null,"softbank":null,"google":null,"image":"26f9-fe0f.png","sheet_x":59,"sheet_y":44,"short_name":"person_with_ball","short_names":["person_with_ball"],"text":null,"texts":null,"category":"People & Body","subcategory":"person-sport","sort_order":475,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"26F9-1F3FB","non_qualified":null,"image":"26f9-1f3fb.png","sheet_x":59,"sheet_y":45,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"26F9-1F3FC","non_qualified":null,"image":"26f9-1f3fc.png","sheet_x":59,"sheet_y":46,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"26F9-1F3FD","non_qualified":null,"image":"26f9-1f3fd.png","sheet_x":59,"sheet_y":47,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"26F9-1F3FE","non_qualified":null,"image":"26f9-1f3fe.png","sheet_x":59,"sheet_y":48,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"26F9-1F3FF","non_qualified":null,"image":"26f9-1f3ff.png","sheet_x":59,"sheet_y":49,"added_in":"2.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}},"obsoleted_by":"26F9-FE0F-200D-2642-FE0F"},{"name":"TENT","unified":"26FA","non_qualified":null,"docomo":null,"au":"E5D0","softbank":"E122","google":"FE7FB","image":"26fa.png","sheet_x":59,"sheet_y":50,"short_name":"tent","short_names":["tent"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"place-other","sort_order":897,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"FUEL PUMP","unified":"26FD","non_qualified":null,"docomo":"E66B","au":"E571","softbank":"E03A","google":"FE7F5","image":"26fd.png","sheet_x":59,"sheet_y":51,"short_name":"fuelpump","short_names":["fuelpump"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-ground","sort_order":956,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK SCISSORS","unified":"2702-FE0F","non_qualified":"2702","docomo":"E675","au":"E516","softbank":"E313","google":"FE53E","image":"2702-fe0f.png","sheet_x":59,"sheet_y":52,"short_name":"scissors","short_names":["scissors"],"text":null,"texts":null,"category":"Objects","subcategory":"office","sort_order":1328,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE HEAVY CHECK MARK","unified":"2705","non_qualified":null,"docomo":null,"au":"E55E","softbank":null,"google":"FEB4A","image":"2705.png","sheet_x":59,"sheet_y":53,"short_name":"white_check_mark","short_names":["white_check_mark"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1535,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"AIRPLANE","unified":"2708-FE0F","non_qualified":"2708","docomo":"E662","au":"E4B3","softbank":"E01D","google":"FE7E9","image":"2708-fe0f.png","sheet_x":59,"sheet_y":54,"short_name":"airplane","short_names":["airplane"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"transport-air","sort_order":972,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ENVELOPE","unified":"2709-FE0F","non_qualified":"2709","docomo":"E6D3","au":"E521","softbank":null,"google":"FE529","image":"2709-fe0f.png","sheet_x":59,"sheet_y":55,"short_name":"email","short_names":["email","envelope"],"text":null,"texts":null,"category":"Objects","subcategory":"mail","sort_order":1289,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"RAISED FIST","unified":"270A","non_qualified":null,"docomo":"E693","au":"EB83","softbank":"E010","google":"FEB93","image":"270a.png","sheet_x":59,"sheet_y":56,"short_name":"fist","short_names":["fist"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-closed","sort_order":198,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"270A-1F3FB","non_qualified":null,"image":"270a-1f3fb.png","sheet_x":59,"sheet_y":57,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"270A-1F3FC","non_qualified":null,"image":"270a-1f3fc.png","sheet_x":59,"sheet_y":58,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"270A-1F3FD","non_qualified":null,"image":"270a-1f3fd.png","sheet_x":59,"sheet_y":59,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"270A-1F3FE","non_qualified":null,"image":"270a-1f3fe.png","sheet_x":59,"sheet_y":60,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"270A-1F3FF","non_qualified":null,"image":"270a-1f3ff.png","sheet_x":59,"sheet_y":61,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"RAISED HAND","unified":"270B","non_qualified":null,"docomo":"E695","au":"E5A7","softbank":"E012","google":"FEB95","image":"270b.png","sheet_x":60,"sheet_y":0,"short_name":"hand","short_names":["hand","raised_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-open","sort_order":172,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"270B-1F3FB","non_qualified":null,"image":"270b-1f3fb.png","sheet_x":60,"sheet_y":1,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"270B-1F3FC","non_qualified":null,"image":"270b-1f3fc.png","sheet_x":60,"sheet_y":2,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"270B-1F3FD","non_qualified":null,"image":"270b-1f3fd.png","sheet_x":60,"sheet_y":3,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"270B-1F3FE","non_qualified":null,"image":"270b-1f3fe.png","sheet_x":60,"sheet_y":4,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"270B-1F3FF","non_qualified":null,"image":"270b-1f3ff.png","sheet_x":60,"sheet_y":5,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"VICTORY HAND","unified":"270C-FE0F","non_qualified":"270C","docomo":"E694","au":"E5A6","softbank":"E011","google":"FEB94","image":"270c-fe0f.png","sheet_x":60,"sheet_y":6,"short_name":"v","short_names":["v"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-fingers-partial","sort_order":183,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"270C-1F3FB","non_qualified":null,"image":"270c-1f3fb.png","sheet_x":60,"sheet_y":7,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"270C-1F3FC","non_qualified":null,"image":"270c-1f3fc.png","sheet_x":60,"sheet_y":8,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"270C-1F3FD","non_qualified":null,"image":"270c-1f3fd.png","sheet_x":60,"sheet_y":9,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"270C-1F3FE","non_qualified":null,"image":"270c-1f3fe.png","sheet_x":60,"sheet_y":10,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"270C-1F3FF","non_qualified":null,"image":"270c-1f3ff.png","sheet_x":60,"sheet_y":11,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"WRITING HAND","unified":"270D-FE0F","non_qualified":"270D","docomo":null,"au":null,"softbank":null,"google":null,"image":"270d-fe0f.png","sheet_x":60,"sheet_y":12,"short_name":"writing_hand","short_names":["writing_hand"],"text":null,"texts":null,"category":"People & Body","subcategory":"hand-prop","sort_order":209,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true,"skin_variations":{"1F3FB":{"unified":"270D-1F3FB","non_qualified":null,"image":"270d-1f3fb.png","sheet_x":60,"sheet_y":13,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FC":{"unified":"270D-1F3FC","non_qualified":null,"image":"270d-1f3fc.png","sheet_x":60,"sheet_y":14,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FD":{"unified":"270D-1F3FD","non_qualified":null,"image":"270d-1f3fd.png","sheet_x":60,"sheet_y":15,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FE":{"unified":"270D-1F3FE","non_qualified":null,"image":"270d-1f3fe.png","sheet_x":60,"sheet_y":16,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},"1F3FF":{"unified":"270D-1F3FF","non_qualified":null,"image":"270d-1f3ff.png","sheet_x":60,"sheet_y":17,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}}},{"name":"PENCIL","unified":"270F-FE0F","non_qualified":"270F","docomo":"E719","au":"E4A1","softbank":null,"google":"FE539","image":"270f-fe0f.png","sheet_x":60,"sheet_y":18,"short_name":"pencil2","short_names":["pencil2"],"text":null,"texts":null,"category":"Objects","subcategory":"writing","sort_order":1302,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK NIB","unified":"2712-FE0F","non_qualified":"2712","docomo":"E6AE","au":"EB03","softbank":null,"google":"FE536","image":"2712-fe0f.png","sheet_x":60,"sheet_y":19,"short_name":"black_nib","short_names":["black_nib"],"text":null,"texts":null,"category":"Objects","subcategory":"writing","sort_order":1303,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY CHECK MARK","unified":"2714-FE0F","non_qualified":"2714","docomo":null,"au":"E557","softbank":null,"google":"FEB49","image":"2714-fe0f.png","sheet_x":60,"sheet_y":20,"short_name":"heavy_check_mark","short_names":["heavy_check_mark"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1537,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY MULTIPLICATION X","unified":"2716-FE0F","non_qualified":"2716","docomo":null,"au":"E54F","softbank":null,"google":"FEB53","image":"2716-fe0f.png","sheet_x":60,"sheet_y":21,"short_name":"heavy_multiplication_x","short_names":["heavy_multiplication_x"],"text":null,"texts":null,"category":"Symbols","subcategory":"math","sort_order":1513,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LATIN CROSS","unified":"271D-FE0F","non_qualified":"271D","docomo":null,"au":null,"softbank":null,"google":null,"image":"271d-fe0f.png","sheet_x":60,"sheet_y":22,"short_name":"latin_cross","short_names":["latin_cross"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1465,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"STAR OF DAVID","unified":"2721-FE0F","non_qualified":"2721","docomo":null,"au":null,"softbank":null,"google":null,"image":"2721-fe0f.png","sheet_x":60,"sheet_y":23,"short_name":"star_of_david","short_names":["star_of_david"],"text":null,"texts":null,"category":"Symbols","subcategory":"religion","sort_order":1462,"added_in":"0.7","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPARKLES","unified":"2728","non_qualified":null,"docomo":"E6FA","au":"EAAB","softbank":"E32E","google":"FEB60","image":"2728.png","sheet_x":60,"sheet_y":24,"short_name":"sparkles","short_names":["sparkles"],"text":null,"texts":null,"category":"Activities","subcategory":"event","sort_order":1070,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EIGHT SPOKED ASTERISK","unified":"2733-FE0F","non_qualified":"2733","docomo":"E6F8","au":"E53E","softbank":"E206","google":"FEB62","image":"2733-fe0f.png","sheet_x":60,"sheet_y":25,"short_name":"eight_spoked_asterisk","short_names":["eight_spoked_asterisk"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1543,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"EIGHT POINTED BLACK STAR","unified":"2734-FE0F","non_qualified":"2734","docomo":"E6F8","au":"E479","softbank":"E205","google":"FEB61","image":"2734-fe0f.png","sheet_x":60,"sheet_y":26,"short_name":"eight_pointed_black_star","short_names":["eight_pointed_black_star"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1544,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SNOWFLAKE","unified":"2744-FE0F","non_qualified":"2744","docomo":null,"au":"E48A","softbank":null,"google":"FE00E","image":"2744-fe0f.png","sheet_x":60,"sheet_y":27,"short_name":"snowflake","short_names":["snowflake"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1058,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"SPARKLE","unified":"2747-FE0F","non_qualified":"2747","docomo":"E6FA","au":"E46C","softbank":null,"google":"FEB77","image":"2747-fe0f.png","sheet_x":60,"sheet_y":28,"short_name":"sparkle","short_names":["sparkle"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1545,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CROSS MARK","unified":"274C","non_qualified":null,"docomo":null,"au":"E550","softbank":"E333","google":"FEB45","image":"274c.png","sheet_x":60,"sheet_y":29,"short_name":"x","short_names":["x"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1538,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"NEGATIVE SQUARED CROSS MARK","unified":"274E","non_qualified":null,"docomo":null,"au":"E551","softbank":null,"google":"FEB46","image":"274e.png","sheet_x":60,"sheet_y":30,"short_name":"negative_squared_cross_mark","short_names":["negative_squared_cross_mark"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1539,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK QUESTION MARK ORNAMENT","unified":"2753","non_qualified":null,"docomo":null,"au":"E483","softbank":"E020","google":"FEB09","image":"2753.png","sheet_x":60,"sheet_y":31,"short_name":"question","short_names":["question"],"text":null,"texts":null,"category":"Symbols","subcategory":"punctuation","sort_order":1521,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE QUESTION MARK ORNAMENT","unified":"2754","non_qualified":null,"docomo":null,"au":"E483","softbank":"E336","google":"FEB0A","image":"2754.png","sheet_x":60,"sheet_y":32,"short_name":"grey_question","short_names":["grey_question"],"text":null,"texts":null,"category":"Symbols","subcategory":"punctuation","sort_order":1522,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE EXCLAMATION MARK ORNAMENT","unified":"2755","non_qualified":null,"docomo":"E702","au":"E482","softbank":"E337","google":"FEB0B","image":"2755.png","sheet_x":60,"sheet_y":33,"short_name":"grey_exclamation","short_names":["grey_exclamation"],"text":null,"texts":null,"category":"Symbols","subcategory":"punctuation","sort_order":1523,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY EXCLAMATION MARK SYMBOL","unified":"2757","non_qualified":null,"docomo":"E702","au":"E482","softbank":"E021","google":"FEB04","image":"2757.png","sheet_x":60,"sheet_y":34,"short_name":"exclamation","short_names":["exclamation","heavy_exclamation_mark"],"text":null,"texts":null,"category":"Symbols","subcategory":"punctuation","sort_order":1524,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEART EXCLAMATION","unified":"2763-FE0F","non_qualified":"2763","docomo":null,"au":null,"softbank":null,"google":null,"image":"2763-fe0f.png","sheet_x":60,"sheet_y":35,"short_name":"heavy_heart_exclamation_mark_ornament","short_names":["heavy_heart_exclamation_mark_ornament"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":139,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEART ON FIRE","unified":"2764-FE0F-200D-1F525","non_qualified":"2764-200D-1F525","docomo":null,"au":null,"softbank":null,"google":null,"image":"2764-fe0f-200d-1f525.png","sheet_x":60,"sheet_y":36,"short_name":"heart_on_fire","short_names":["heart_on_fire"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":141,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"MENDING HEART","unified":"2764-FE0F-200D-1FA79","non_qualified":"2764-200D-1FA79","docomo":null,"au":null,"softbank":null,"google":null,"image":"2764-fe0f-200d-1fa79.png","sheet_x":60,"sheet_y":37,"short_name":"mending_heart","short_names":["mending_heart"],"text":null,"texts":null,"category":"Smileys & Emotion","subcategory":"heart","sort_order":142,"added_in":"13.1","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY BLACK HEART","unified":"2764-FE0F","non_qualified":"2764","docomo":"E6EC","au":"E595","softbank":"E022","google":"FEB0C","image":"2764-fe0f.png","sheet_x":60,"sheet_y":38,"short_name":"heart","short_names":["heart"],"text":"<3","texts":["<3"],"category":"Smileys & Emotion","subcategory":"heart","sort_order":143,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY PLUS SIGN","unified":"2795","non_qualified":null,"docomo":null,"au":"E53C","softbank":null,"google":"FEB51","image":"2795.png","sheet_x":60,"sheet_y":39,"short_name":"heavy_plus_sign","short_names":["heavy_plus_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"math","sort_order":1514,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY MINUS SIGN","unified":"2796","non_qualified":null,"docomo":null,"au":"E53D","softbank":null,"google":"FEB52","image":"2796.png","sheet_x":60,"sheet_y":40,"short_name":"heavy_minus_sign","short_names":["heavy_minus_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"math","sort_order":1515,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY DIVISION SIGN","unified":"2797","non_qualified":null,"docomo":null,"au":"E554","softbank":null,"google":"FEB54","image":"2797.png","sheet_x":60,"sheet_y":41,"short_name":"heavy_division_sign","short_names":["heavy_division_sign"],"text":null,"texts":null,"category":"Symbols","subcategory":"math","sort_order":1516,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK RIGHTWARDS ARROW","unified":"27A1-FE0F","non_qualified":"27A1","docomo":null,"au":"E552","softbank":"E234","google":"FEAFA","image":"27a1-fe0f.png","sheet_x":60,"sheet_y":42,"short_name":"arrow_right","short_names":["arrow_right"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1440,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CURLY LOOP","unified":"27B0","non_qualified":null,"docomo":"E70A","au":"EB31","softbank":null,"google":"FEB08","image":"27b0.png","sheet_x":60,"sheet_y":43,"short_name":"curly_loop","short_names":["curly_loop"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1540,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOUBLE CURLY LOOP","unified":"27BF","non_qualified":null,"docomo":"E6DF","au":null,"softbank":"E211","google":"FE82B","image":"27bf.png","sheet_x":60,"sheet_y":44,"short_name":"loop","short_names":["loop"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1541,"added_in":"1.0","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS","unified":"2934-FE0F","non_qualified":"2934","docomo":"E6F5","au":"EB2D","softbank":null,"google":"FEAF4","image":"2934-fe0f.png","sheet_x":60,"sheet_y":45,"short_name":"arrow_heading_up","short_names":["arrow_heading_up"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1450,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS","unified":"2935-FE0F","non_qualified":"2935","docomo":"E700","au":"EB2E","softbank":null,"google":"FEAF5","image":"2935-fe0f.png","sheet_x":60,"sheet_y":46,"short_name":"arrow_heading_down","short_names":["arrow_heading_down"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1451,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"LEFTWARDS BLACK ARROW","unified":"2B05-FE0F","non_qualified":"2B05","docomo":null,"au":"E553","softbank":"E235","google":"FEAFB","image":"2b05-fe0f.png","sheet_x":60,"sheet_y":47,"short_name":"arrow_left","short_names":["arrow_left"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1444,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"UPWARDS BLACK ARROW","unified":"2B06-FE0F","non_qualified":"2B06","docomo":null,"au":"E53F","softbank":"E232","google":"FEAF8","image":"2b06-fe0f.png","sheet_x":60,"sheet_y":48,"short_name":"arrow_up","short_names":["arrow_up"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1438,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"DOWNWARDS BLACK ARROW","unified":"2B07-FE0F","non_qualified":"2B07","docomo":null,"au":"E540","softbank":"E233","google":"FEAF9","image":"2b07-fe0f.png","sheet_x":60,"sheet_y":49,"short_name":"arrow_down","short_names":["arrow_down"],"text":null,"texts":null,"category":"Symbols","subcategory":"arrow","sort_order":1442,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"BLACK LARGE SQUARE","unified":"2B1B","non_qualified":null,"docomo":null,"au":"E549","softbank":null,"google":"FEB6C","image":"2b1b.png","sheet_x":60,"sheet_y":50,"short_name":"black_large_square","short_names":["black_large_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1617,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE LARGE SQUARE","unified":"2B1C","non_qualified":null,"docomo":null,"au":"E548","softbank":null,"google":"FEB6B","image":"2b1c.png","sheet_x":60,"sheet_y":51,"short_name":"white_large_square","short_names":["white_large_square"],"text":null,"texts":null,"category":"Symbols","subcategory":"geometric","sort_order":1618,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WHITE MEDIUM STAR","unified":"2B50","non_qualified":null,"docomo":null,"au":"E48B","softbank":"E32F","google":"FEB68","image":"2b50.png","sheet_x":60,"sheet_y":52,"short_name":"star","short_names":["star"],"text":null,"texts":null,"category":"Travel & Places","subcategory":"sky & weather","sort_order":1035,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"HEAVY LARGE CIRCLE","unified":"2B55","non_qualified":null,"docomo":"E6A0","au":"EAAD","softbank":"E332","google":"FEB44","image":"2b55.png","sheet_x":60,"sheet_y":53,"short_name":"o","short_names":["o"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1534,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"WAVY DASH","unified":"3030-FE0F","non_qualified":"3030","docomo":"E709","au":null,"softbank":null,"google":"FEB07","image":"3030-fe0f.png","sheet_x":60,"sheet_y":54,"short_name":"wavy_dash","short_names":["wavy_dash"],"text":null,"texts":null,"category":"Symbols","subcategory":"punctuation","sort_order":1525,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"PART ALTERNATION MARK","unified":"303D-FE0F","non_qualified":"303D","docomo":null,"au":null,"softbank":"E12C","google":"FE81B","image":"303d-fe0f.png","sheet_x":60,"sheet_y":55,"short_name":"part_alternation_mark","short_names":["part_alternation_mark"],"text":null,"texts":null,"category":"Symbols","subcategory":"other-symbol","sort_order":1542,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CIRCLED IDEOGRAPH CONGRATULATION","unified":"3297-FE0F","non_qualified":"3297","docomo":null,"au":"EA99","softbank":"E30D","google":"FEB43","image":"3297-fe0f.png","sheet_x":60,"sheet_y":56,"short_name":"congratulations","short_names":["congratulations"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1597,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true},{"name":"CIRCLED IDEOGRAPH SECRET","unified":"3299-FE0F","non_qualified":"3299","docomo":"E734","au":"E4F1","softbank":"E315","google":"FEB2B","image":"3299-fe0f.png","sheet_x":60,"sheet_y":57,"short_name":"secret","short_names":["secret"],"text":null,"texts":null,"category":"Symbols","subcategory":"alphanum","sort_order":1598,"added_in":"0.6","has_img_apple":true,"has_img_google":true,"has_img_twitter":true,"has_img_facebook":true}]
\ No newline at end of file
diff --git a/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/init.lua b/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/init.lua
new file mode 100644
index 00000000..11791d68
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/init.lua
@@ -0,0 +1,47 @@
+local source = {}
+
+source.new = function()
+ local self = setmetatable({}, { __index = source })
+ self.commit_items = nil
+ self.insert_items = nil
+ return self
+end
+
+source.get_trigger_characters = function()
+ return { ':' }
+end
+
+source.get_keyword_pattern = function()
+ return [=[\%([[:space:]"'`]\|^\)\zs:[[:alnum:]_\-\+]*:\?]=]
+end
+
+source.complete = function(self, params, callback)
+ -- Avoid unexpected completion.
+ if not vim.regex(self.get_keyword_pattern() .. '$'):match_str(params.context.cursor_before_line) then
+ return callback()
+ end
+
+ if self:option(params).insert then
+ if not self.insert_items then
+ self.insert_items = vim.tbl_map(function(item)
+ item.word = nil
+ return item
+ end, require('cmp_emoji.items')())
+ end
+ callback(self.insert_items)
+ else
+ if not self.commit_items then
+ self.commit_items = require('cmp_emoji.items')()
+ end
+ callback(self.commit_items)
+ end
+end
+
+source.option = function(_, params)
+ return vim.tbl_extend('force', {
+ insert = false,
+ }, params.option)
+end
+
+return source
+
diff --git a/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/items.lua b/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/items.lua
new file mode 100644
index 00000000..9ced1c83
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/items.lua
@@ -0,0 +1,1444 @@
+return function() return {
+{ word = ':hash:'; label = '#️⃣ :hash:'; insertText = '#️⃣'; filterText = ':hash:' };
+{ word = ':keycap_star:'; label = '*️⃣ :keycap_star:'; insertText = '*️⃣'; filterText = ':keycap_star:' };
+{ word = ':zero:'; label = '0️⃣ :zero:'; insertText = '0️⃣'; filterText = ':zero:' };
+{ word = ':one:'; label = '1️⃣ :one:'; insertText = '1️⃣'; filterText = ':one:' };
+{ word = ':two:'; label = '2️⃣ :two:'; insertText = '2️⃣'; filterText = ':two:' };
+{ word = ':three:'; label = '3️⃣ :three:'; insertText = '3️⃣'; filterText = ':three:' };
+{ word = ':four:'; label = '4️⃣ :four:'; insertText = '4️⃣'; filterText = ':four:' };
+{ word = ':five:'; label = '5️⃣ :five:'; insertText = '5️⃣'; filterText = ':five:' };
+{ word = ':six:'; label = '6️⃣ :six:'; insertText = '6️⃣'; filterText = ':six:' };
+{ word = ':seven:'; label = '7️⃣ :seven:'; insertText = '7️⃣'; filterText = ':seven:' };
+{ word = ':eight:'; label = '8️⃣ :eight:'; insertText = '8️⃣'; filterText = ':eight:' };
+{ word = ':nine:'; label = '9️⃣ :nine:'; insertText = '9️⃣'; filterText = ':nine:' };
+{ word = ':copyright:'; label = '©️ :copyright:'; insertText = '©️'; filterText = ':copyright:' };
+{ word = ':registered:'; label = '®️ :registered:'; insertText = '®️'; filterText = ':registered:' };
+{ word = ':mahjong:'; label = '🀄 :mahjong:'; insertText = '🀄'; filterText = ':mahjong:' };
+{ word = ':black_joker:'; label = '🃏 :black_joker:'; insertText = '🃏'; filterText = ':black_joker:' };
+{ word = ':a:'; label = '🅰️ :a:'; insertText = '🅰️'; filterText = ':a:' };
+{ word = ':b:'; label = '🅱️ :b:'; insertText = '🅱️'; filterText = ':b:' };
+{ word = ':o2:'; label = '🅾️ :o2:'; insertText = '🅾️'; filterText = ':o2:' };
+{ word = ':parking:'; label = '🅿️ :parking:'; insertText = '🅿️'; filterText = ':parking:' };
+{ word = ':ab:'; label = '🆎 :ab:'; insertText = '🆎'; filterText = ':ab:' };
+{ word = ':cl:'; label = '🆑 :cl:'; insertText = '🆑'; filterText = ':cl:' };
+{ word = ':cool:'; label = '🆒 :cool:'; insertText = '🆒'; filterText = ':cool:' };
+{ word = ':free:'; label = '🆓 :free:'; insertText = '🆓'; filterText = ':free:' };
+{ word = ':id:'; label = '🆔 :id:'; insertText = '🆔'; filterText = ':id:' };
+{ word = ':new:'; label = '🆕 :new:'; insertText = '🆕'; filterText = ':new:' };
+{ word = ':ng:'; label = '🆖 :ng:'; insertText = '🆖'; filterText = ':ng:' };
+{ word = ':ok:'; label = '🆗 :ok:'; insertText = '🆗'; filterText = ':ok:' };
+{ word = ':sos:'; label = '🆘 :sos:'; insertText = '🆘'; filterText = ':sos:' };
+{ word = ':up:'; label = '🆙 :up:'; insertText = '🆙'; filterText = ':up:' };
+{ word = ':vs:'; label = '🆚 :vs:'; insertText = '🆚'; filterText = ':vs:' };
+{ word = ':koko:'; label = '🈁 :koko:'; insertText = '🈁'; filterText = ':koko:' };
+{ word = ':sa:'; label = '🈂️ :sa:'; insertText = '🈂️'; filterText = ':sa:' };
+{ word = ':u7121:'; label = '🈚 :u7121:'; insertText = '🈚'; filterText = ':u7121:' };
+{ word = ':u6307:'; label = '🈯 :u6307:'; insertText = '🈯'; filterText = ':u6307:' };
+{ word = ':u7981:'; label = '🈲 :u7981:'; insertText = '🈲'; filterText = ':u7981:' };
+{ word = ':u7a7a:'; label = '🈳 :u7a7a:'; insertText = '🈳'; filterText = ':u7a7a:' };
+{ word = ':u5408:'; label = '🈴 :u5408:'; insertText = '🈴'; filterText = ':u5408:' };
+{ word = ':u6e80:'; label = '🈵 :u6e80:'; insertText = '🈵'; filterText = ':u6e80:' };
+{ word = ':u6709:'; label = '🈶 :u6709:'; insertText = '🈶'; filterText = ':u6709:' };
+{ word = ':u6708:'; label = '🈷️ :u6708:'; insertText = '🈷️'; filterText = ':u6708:' };
+{ word = ':u7533:'; label = '🈸 :u7533:'; insertText = '🈸'; filterText = ':u7533:' };
+{ word = ':u5272:'; label = '🈹 :u5272:'; insertText = '🈹'; filterText = ':u5272:' };
+{ word = ':u55b6:'; label = '🈺 :u55b6:'; insertText = '🈺'; filterText = ':u55b6:' };
+{ word = ':ideograph_advantage:'; label = '🉐 :ideograph_advantage:'; insertText = '🉐'; filterText = ':ideograph_advantage:' };
+{ word = ':accept:'; label = '🉑 :accept:'; insertText = '🉑'; filterText = ':accept:' };
+{ word = ':cyclone:'; label = '🌀 :cyclone:'; insertText = '🌀'; filterText = ':cyclone:' };
+{ word = ':foggy:'; label = '🌁 :foggy:'; insertText = '🌁'; filterText = ':foggy:' };
+{ word = ':closed_umbrella:'; label = '🌂 :closed_umbrella:'; insertText = '🌂'; filterText = ':closed_umbrella:' };
+{ word = ':night_with_stars:'; label = '🌃 :night_with_stars:'; insertText = '🌃'; filterText = ':night_with_stars:' };
+{ word = ':sunrise_over_mountains:'; label = '🌄 :sunrise_over_mountains:'; insertText = '🌄'; filterText = ':sunrise_over_mountains:' };
+{ word = ':sunrise:'; label = '🌅 :sunrise:'; insertText = '🌅'; filterText = ':sunrise:' };
+{ word = ':city_sunset:'; label = '🌆 :city_sunset:'; insertText = '🌆'; filterText = ':city_sunset:' };
+{ word = ':city_sunrise:'; label = '🌇 :city_sunrise:'; insertText = '🌇'; filterText = ':city_sunrise:' };
+{ word = ':rainbow:'; label = '🌈 :rainbow:'; insertText = '🌈'; filterText = ':rainbow:' };
+{ word = ':bridge_at_night:'; label = '🌉 :bridge_at_night:'; insertText = '🌉'; filterText = ':bridge_at_night:' };
+{ word = ':ocean:'; label = '🌊 :ocean:'; insertText = '🌊'; filterText = ':ocean:' };
+{ word = ':volcano:'; label = '🌋 :volcano:'; insertText = '🌋'; filterText = ':volcano:' };
+{ word = ':milky_way:'; label = '🌌 :milky_way:'; insertText = '🌌'; filterText = ':milky_way:' };
+{ word = ':earth_africa:'; label = '🌍 :earth_africa:'; insertText = '🌍'; filterText = ':earth_africa:' };
+{ word = ':earth_americas:'; label = '🌎 :earth_americas:'; insertText = '🌎'; filterText = ':earth_americas:' };
+{ word = ':earth_asia:'; label = '🌏 :earth_asia:'; insertText = '🌏'; filterText = ':earth_asia:' };
+{ word = ':globe_with_meridians:'; label = '🌐 :globe_with_meridians:'; insertText = '🌐'; filterText = ':globe_with_meridians:' };
+{ word = ':new_moon:'; label = '🌑 :new_moon:'; insertText = '🌑'; filterText = ':new_moon:' };
+{ word = ':waxing_crescent_moon:'; label = '🌒 :waxing_crescent_moon:'; insertText = '🌒'; filterText = ':waxing_crescent_moon:' };
+{ word = ':first_quarter_moon:'; label = '🌓 :first_quarter_moon:'; insertText = '🌓'; filterText = ':first_quarter_moon:' };
+{ word = ':moon:'; label = '🌔 :moon:'; insertText = '🌔'; filterText = ':moon:' };
+{ word = ':waxing_gibbous_moon:'; label = '🌔 :waxing_gibbous_moon:'; insertText = '🌔'; filterText = ':waxing_gibbous_moon:' };
+{ word = ':full_moon:'; label = '🌕 :full_moon:'; insertText = '🌕'; filterText = ':full_moon:' };
+{ word = ':waning_gibbous_moon:'; label = '🌖 :waning_gibbous_moon:'; insertText = '🌖'; filterText = ':waning_gibbous_moon:' };
+{ word = ':last_quarter_moon:'; label = '🌗 :last_quarter_moon:'; insertText = '🌗'; filterText = ':last_quarter_moon:' };
+{ word = ':waning_crescent_moon:'; label = '🌘 :waning_crescent_moon:'; insertText = '🌘'; filterText = ':waning_crescent_moon:' };
+{ word = ':crescent_moon:'; label = '🌙 :crescent_moon:'; insertText = '🌙'; filterText = ':crescent_moon:' };
+{ word = ':new_moon_with_face:'; label = '🌚 :new_moon_with_face:'; insertText = '🌚'; filterText = ':new_moon_with_face:' };
+{ word = ':first_quarter_moon_with_face:'; label = '🌛 :first_quarter_moon_with_face:'; insertText = '🌛'; filterText = ':first_quarter_moon_with_face:' };
+{ word = ':last_quarter_moon_with_face:'; label = '🌜 :last_quarter_moon_with_face:'; insertText = '🌜'; filterText = ':last_quarter_moon_with_face:' };
+{ word = ':full_moon_with_face:'; label = '🌝 :full_moon_with_face:'; insertText = '🌝'; filterText = ':full_moon_with_face:' };
+{ word = ':sun_with_face:'; label = '🌞 :sun_with_face:'; insertText = '🌞'; filterText = ':sun_with_face:' };
+{ word = ':star2:'; label = '🌟 :star2:'; insertText = '🌟'; filterText = ':star2:' };
+{ word = ':stars:'; label = '🌠 :stars:'; insertText = '🌠'; filterText = ':stars:' };
+{ word = ':thermometer:'; label = '🌡️ :thermometer:'; insertText = '🌡️'; filterText = ':thermometer:' };
+{ word = ':mostly_sunny:'; label = '🌤️ :mostly_sunny:'; insertText = '🌤️'; filterText = ':mostly_sunny:' };
+{ word = ':sun_small_cloud:'; label = '🌤️ :sun_small_cloud:'; insertText = '🌤️'; filterText = ':sun_small_cloud:' };
+{ word = ':barely_sunny:'; label = '🌥️ :barely_sunny:'; insertText = '🌥️'; filterText = ':barely_sunny:' };
+{ word = ':sun_behind_cloud:'; label = '🌥️ :sun_behind_cloud:'; insertText = '🌥️'; filterText = ':sun_behind_cloud:' };
+{ word = ':partly_sunny_rain:'; label = '🌦️ :partly_sunny_rain:'; insertText = '🌦️'; filterText = ':partly_sunny_rain:' };
+{ word = ':sun_behind_rain_cloud:'; label = '🌦️ :sun_behind_rain_cloud:'; insertText = '🌦️'; filterText = ':sun_behind_rain_cloud:' };
+{ word = ':rain_cloud:'; label = '🌧️ :rain_cloud:'; insertText = '🌧️'; filterText = ':rain_cloud:' };
+{ word = ':snow_cloud:'; label = '🌨️ :snow_cloud:'; insertText = '🌨️'; filterText = ':snow_cloud:' };
+{ word = ':lightning:'; label = '🌩️ :lightning:'; insertText = '🌩️'; filterText = ':lightning:' };
+{ word = ':lightning_cloud:'; label = '🌩️ :lightning_cloud:'; insertText = '🌩️'; filterText = ':lightning_cloud:' };
+{ word = ':tornado:'; label = '🌪️ :tornado:'; insertText = '🌪️'; filterText = ':tornado:' };
+{ word = ':tornado_cloud:'; label = '🌪️ :tornado_cloud:'; insertText = '🌪️'; filterText = ':tornado_cloud:' };
+{ word = ':fog:'; label = '🌫️ :fog:'; insertText = '🌫️'; filterText = ':fog:' };
+{ word = ':wind_blowing_face:'; label = '🌬️ :wind_blowing_face:'; insertText = '🌬️'; filterText = ':wind_blowing_face:' };
+{ word = ':hotdog:'; label = '🌭 :hotdog:'; insertText = '🌭'; filterText = ':hotdog:' };
+{ word = ':taco:'; label = '🌮 :taco:'; insertText = '🌮'; filterText = ':taco:' };
+{ word = ':burrito:'; label = '🌯 :burrito:'; insertText = '🌯'; filterText = ':burrito:' };
+{ word = ':chestnut:'; label = '🌰 :chestnut:'; insertText = '🌰'; filterText = ':chestnut:' };
+{ word = ':seedling:'; label = '🌱 :seedling:'; insertText = '🌱'; filterText = ':seedling:' };
+{ word = ':evergreen_tree:'; label = '🌲 :evergreen_tree:'; insertText = '🌲'; filterText = ':evergreen_tree:' };
+{ word = ':deciduous_tree:'; label = '🌳 :deciduous_tree:'; insertText = '🌳'; filterText = ':deciduous_tree:' };
+{ word = ':palm_tree:'; label = '🌴 :palm_tree:'; insertText = '🌴'; filterText = ':palm_tree:' };
+{ word = ':cactus:'; label = '🌵 :cactus:'; insertText = '🌵'; filterText = ':cactus:' };
+{ word = ':hot_pepper:'; label = '🌶️ :hot_pepper:'; insertText = '🌶️'; filterText = ':hot_pepper:' };
+{ word = ':tulip:'; label = '🌷 :tulip:'; insertText = '🌷'; filterText = ':tulip:' };
+{ word = ':cherry_blossom:'; label = '🌸 :cherry_blossom:'; insertText = '🌸'; filterText = ':cherry_blossom:' };
+{ word = ':rose:'; label = '🌹 :rose:'; insertText = '🌹'; filterText = ':rose:' };
+{ word = ':hibiscus:'; label = '🌺 :hibiscus:'; insertText = '🌺'; filterText = ':hibiscus:' };
+{ word = ':sunflower:'; label = '🌻 :sunflower:'; insertText = '🌻'; filterText = ':sunflower:' };
+{ word = ':blossom:'; label = '🌼 :blossom:'; insertText = '🌼'; filterText = ':blossom:' };
+{ word = ':corn:'; label = '🌽 :corn:'; insertText = '🌽'; filterText = ':corn:' };
+{ word = ':ear_of_rice:'; label = '🌾 :ear_of_rice:'; insertText = '🌾'; filterText = ':ear_of_rice:' };
+{ word = ':herb:'; label = '🌿 :herb:'; insertText = '🌿'; filterText = ':herb:' };
+{ word = ':four_leaf_clover:'; label = '🍀 :four_leaf_clover:'; insertText = '🍀'; filterText = ':four_leaf_clover:' };
+{ word = ':maple_leaf:'; label = '🍁 :maple_leaf:'; insertText = '🍁'; filterText = ':maple_leaf:' };
+{ word = ':fallen_leaf:'; label = '🍂 :fallen_leaf:'; insertText = '🍂'; filterText = ':fallen_leaf:' };
+{ word = ':leaves:'; label = '🍃 :leaves:'; insertText = '🍃'; filterText = ':leaves:' };
+{ word = ':mushroom:'; label = '🍄 :mushroom:'; insertText = '🍄'; filterText = ':mushroom:' };
+{ word = ':tomato:'; label = '🍅 :tomato:'; insertText = '🍅'; filterText = ':tomato:' };
+{ word = ':eggplant:'; label = '🍆 :eggplant:'; insertText = '🍆'; filterText = ':eggplant:' };
+{ word = ':grapes:'; label = '🍇 :grapes:'; insertText = '🍇'; filterText = ':grapes:' };
+{ word = ':melon:'; label = '🍈 :melon:'; insertText = '🍈'; filterText = ':melon:' };
+{ word = ':watermelon:'; label = '🍉 :watermelon:'; insertText = '🍉'; filterText = ':watermelon:' };
+{ word = ':tangerine:'; label = '🍊 :tangerine:'; insertText = '🍊'; filterText = ':tangerine:' };
+{ word = ':lemon:'; label = '🍋 :lemon:'; insertText = '🍋'; filterText = ':lemon:' };
+{ word = ':banana:'; label = '🍌 :banana:'; insertText = '🍌'; filterText = ':banana:' };
+{ word = ':pineapple:'; label = '🍍 :pineapple:'; insertText = '🍍'; filterText = ':pineapple:' };
+{ word = ':apple:'; label = '🍎 :apple:'; insertText = '🍎'; filterText = ':apple:' };
+{ word = ':green_apple:'; label = '🍏 :green_apple:'; insertText = '🍏'; filterText = ':green_apple:' };
+{ word = ':pear:'; label = '🍐 :pear:'; insertText = '🍐'; filterText = ':pear:' };
+{ word = ':peach:'; label = '🍑 :peach:'; insertText = '🍑'; filterText = ':peach:' };
+{ word = ':cherries:'; label = '🍒 :cherries:'; insertText = '🍒'; filterText = ':cherries:' };
+{ word = ':strawberry:'; label = '🍓 :strawberry:'; insertText = '🍓'; filterText = ':strawberry:' };
+{ word = ':hamburger:'; label = '🍔 :hamburger:'; insertText = '🍔'; filterText = ':hamburger:' };
+{ word = ':pizza:'; label = '🍕 :pizza:'; insertText = '🍕'; filterText = ':pizza:' };
+{ word = ':meat_on_bone:'; label = '🍖 :meat_on_bone:'; insertText = '🍖'; filterText = ':meat_on_bone:' };
+{ word = ':poultry_leg:'; label = '🍗 :poultry_leg:'; insertText = '🍗'; filterText = ':poultry_leg:' };
+{ word = ':rice_cracker:'; label = '🍘 :rice_cracker:'; insertText = '🍘'; filterText = ':rice_cracker:' };
+{ word = ':rice_ball:'; label = '🍙 :rice_ball:'; insertText = '🍙'; filterText = ':rice_ball:' };
+{ word = ':rice:'; label = '🍚 :rice:'; insertText = '🍚'; filterText = ':rice:' };
+{ word = ':curry:'; label = '🍛 :curry:'; insertText = '🍛'; filterText = ':curry:' };
+{ word = ':ramen:'; label = '🍜 :ramen:'; insertText = '🍜'; filterText = ':ramen:' };
+{ word = ':spaghetti:'; label = '🍝 :spaghetti:'; insertText = '🍝'; filterText = ':spaghetti:' };
+{ word = ':bread:'; label = '🍞 :bread:'; insertText = '🍞'; filterText = ':bread:' };
+{ word = ':fries:'; label = '🍟 :fries:'; insertText = '🍟'; filterText = ':fries:' };
+{ word = ':sweet_potato:'; label = '🍠 :sweet_potato:'; insertText = '🍠'; filterText = ':sweet_potato:' };
+{ word = ':dango:'; label = '🍡 :dango:'; insertText = '🍡'; filterText = ':dango:' };
+{ word = ':oden:'; label = '🍢 :oden:'; insertText = '🍢'; filterText = ':oden:' };
+{ word = ':sushi:'; label = '🍣 :sushi:'; insertText = '🍣'; filterText = ':sushi:' };
+{ word = ':fried_shrimp:'; label = '🍤 :fried_shrimp:'; insertText = '🍤'; filterText = ':fried_shrimp:' };
+{ word = ':fish_cake:'; label = '🍥 :fish_cake:'; insertText = '🍥'; filterText = ':fish_cake:' };
+{ word = ':icecream:'; label = '🍦 :icecream:'; insertText = '🍦'; filterText = ':icecream:' };
+{ word = ':shaved_ice:'; label = '🍧 :shaved_ice:'; insertText = '🍧'; filterText = ':shaved_ice:' };
+{ word = ':ice_cream:'; label = '🍨 :ice_cream:'; insertText = '🍨'; filterText = ':ice_cream:' };
+{ word = ':doughnut:'; label = '🍩 :doughnut:'; insertText = '🍩'; filterText = ':doughnut:' };
+{ word = ':cookie:'; label = '🍪 :cookie:'; insertText = '🍪'; filterText = ':cookie:' };
+{ word = ':chocolate_bar:'; label = '🍫 :chocolate_bar:'; insertText = '🍫'; filterText = ':chocolate_bar:' };
+{ word = ':candy:'; label = '🍬 :candy:'; insertText = '🍬'; filterText = ':candy:' };
+{ word = ':lollipop:'; label = '🍭 :lollipop:'; insertText = '🍭'; filterText = ':lollipop:' };
+{ word = ':custard:'; label = '🍮 :custard:'; insertText = '🍮'; filterText = ':custard:' };
+{ word = ':honey_pot:'; label = '🍯 :honey_pot:'; insertText = '🍯'; filterText = ':honey_pot:' };
+{ word = ':cake:'; label = '🍰 :cake:'; insertText = '🍰'; filterText = ':cake:' };
+{ word = ':bento:'; label = '🍱 :bento:'; insertText = '🍱'; filterText = ':bento:' };
+{ word = ':stew:'; label = '🍲 :stew:'; insertText = '🍲'; filterText = ':stew:' };
+{ word = ':fried_egg:'; label = '🍳 :fried_egg:'; insertText = '🍳'; filterText = ':fried_egg:' };
+{ word = ':cooking:'; label = '🍳 :cooking:'; insertText = '🍳'; filterText = ':cooking:' };
+{ word = ':fork_and_knife:'; label = '🍴 :fork_and_knife:'; insertText = '🍴'; filterText = ':fork_and_knife:' };
+{ word = ':tea:'; label = '🍵 :tea:'; insertText = '🍵'; filterText = ':tea:' };
+{ word = ':sake:'; label = '🍶 :sake:'; insertText = '🍶'; filterText = ':sake:' };
+{ word = ':wine_glass:'; label = '🍷 :wine_glass:'; insertText = '🍷'; filterText = ':wine_glass:' };
+{ word = ':cocktail:'; label = '🍸 :cocktail:'; insertText = '🍸'; filterText = ':cocktail:' };
+{ word = ':tropical_drink:'; label = '🍹 :tropical_drink:'; insertText = '🍹'; filterText = ':tropical_drink:' };
+{ word = ':beer:'; label = '🍺 :beer:'; insertText = '🍺'; filterText = ':beer:' };
+{ word = ':beers:'; label = '🍻 :beers:'; insertText = '🍻'; filterText = ':beers:' };
+{ word = ':baby_bottle:'; label = '🍼 :baby_bottle:'; insertText = '🍼'; filterText = ':baby_bottle:' };
+{ word = ':knife_fork_plate:'; label = '🍽️ :knife_fork_plate:'; insertText = '🍽️'; filterText = ':knife_fork_plate:' };
+{ word = ':champagne:'; label = '🍾 :champagne:'; insertText = '🍾'; filterText = ':champagne:' };
+{ word = ':popcorn:'; label = '🍿 :popcorn:'; insertText = '🍿'; filterText = ':popcorn:' };
+{ word = ':ribbon:'; label = '🎀 :ribbon:'; insertText = '🎀'; filterText = ':ribbon:' };
+{ word = ':gift:'; label = '🎁 :gift:'; insertText = '🎁'; filterText = ':gift:' };
+{ word = ':birthday:'; label = '🎂 :birthday:'; insertText = '🎂'; filterText = ':birthday:' };
+{ word = ':jack_o_lantern:'; label = '🎃 :jack_o_lantern:'; insertText = '🎃'; filterText = ':jack_o_lantern:' };
+{ word = ':christmas_tree:'; label = '🎄 :christmas_tree:'; insertText = '🎄'; filterText = ':christmas_tree:' };
+{ word = ':santa:'; label = '🎅 :santa:'; insertText = '🎅'; filterText = ':santa:' };
+{ word = ':fireworks:'; label = '🎆 :fireworks:'; insertText = '🎆'; filterText = ':fireworks:' };
+{ word = ':sparkler:'; label = '🎇 :sparkler:'; insertText = '🎇'; filterText = ':sparkler:' };
+{ word = ':balloon:'; label = '🎈 :balloon:'; insertText = '🎈'; filterText = ':balloon:' };
+{ word = ':tada:'; label = '🎉 :tada:'; insertText = '🎉'; filterText = ':tada:' };
+{ word = ':confetti_ball:'; label = '🎊 :confetti_ball:'; insertText = '🎊'; filterText = ':confetti_ball:' };
+{ word = ':tanabata_tree:'; label = '🎋 :tanabata_tree:'; insertText = '🎋'; filterText = ':tanabata_tree:' };
+{ word = ':crossed_flags:'; label = '🎌 :crossed_flags:'; insertText = '🎌'; filterText = ':crossed_flags:' };
+{ word = ':bamboo:'; label = '🎍 :bamboo:'; insertText = '🎍'; filterText = ':bamboo:' };
+{ word = ':dolls:'; label = '🎎 :dolls:'; insertText = '🎎'; filterText = ':dolls:' };
+{ word = ':flags:'; label = '🎏 :flags:'; insertText = '🎏'; filterText = ':flags:' };
+{ word = ':wind_chime:'; label = '🎐 :wind_chime:'; insertText = '🎐'; filterText = ':wind_chime:' };
+{ word = ':rice_scene:'; label = '🎑 :rice_scene:'; insertText = '🎑'; filterText = ':rice_scene:' };
+{ word = ':school_satchel:'; label = '🎒 :school_satchel:'; insertText = '🎒'; filterText = ':school_satchel:' };
+{ word = ':mortar_board:'; label = '🎓 :mortar_board:'; insertText = '🎓'; filterText = ':mortar_board:' };
+{ word = ':medal:'; label = '🎖️ :medal:'; insertText = '🎖️'; filterText = ':medal:' };
+{ word = ':reminder_ribbon:'; label = '🎗️ :reminder_ribbon:'; insertText = '🎗️'; filterText = ':reminder_ribbon:' };
+{ word = ':studio_microphone:'; label = '🎙️ :studio_microphone:'; insertText = '🎙️'; filterText = ':studio_microphone:' };
+{ word = ':level_slider:'; label = '🎚️ :level_slider:'; insertText = '🎚️'; filterText = ':level_slider:' };
+{ word = ':control_knobs:'; label = '🎛️ :control_knobs:'; insertText = '🎛️'; filterText = ':control_knobs:' };
+{ word = ':film_frames:'; label = '🎞️ :film_frames:'; insertText = '🎞️'; filterText = ':film_frames:' };
+{ word = ':admission_tickets:'; label = '🎟️ :admission_tickets:'; insertText = '🎟️'; filterText = ':admission_tickets:' };
+{ word = ':carousel_horse:'; label = '🎠 :carousel_horse:'; insertText = '🎠'; filterText = ':carousel_horse:' };
+{ word = ':ferris_wheel:'; label = '🎡 :ferris_wheel:'; insertText = '🎡'; filterText = ':ferris_wheel:' };
+{ word = ':roller_coaster:'; label = '🎢 :roller_coaster:'; insertText = '🎢'; filterText = ':roller_coaster:' };
+{ word = ':fishing_pole_and_fish:'; label = '🎣 :fishing_pole_and_fish:'; insertText = '🎣'; filterText = ':fishing_pole_and_fish:' };
+{ word = ':microphone:'; label = '🎤 :microphone:'; insertText = '🎤'; filterText = ':microphone:' };
+{ word = ':movie_camera:'; label = '🎥 :movie_camera:'; insertText = '🎥'; filterText = ':movie_camera:' };
+{ word = ':cinema:'; label = '🎦 :cinema:'; insertText = '🎦'; filterText = ':cinema:' };
+{ word = ':headphones:'; label = '🎧 :headphones:'; insertText = '🎧'; filterText = ':headphones:' };
+{ word = ':art:'; label = '🎨 :art:'; insertText = '🎨'; filterText = ':art:' };
+{ word = ':tophat:'; label = '🎩 :tophat:'; insertText = '🎩'; filterText = ':tophat:' };
+{ word = ':circus_tent:'; label = '🎪 :circus_tent:'; insertText = '🎪'; filterText = ':circus_tent:' };
+{ word = ':ticket:'; label = '🎫 :ticket:'; insertText = '🎫'; filterText = ':ticket:' };
+{ word = ':clapper:'; label = '🎬 :clapper:'; insertText = '🎬'; filterText = ':clapper:' };
+{ word = ':performing_arts:'; label = '🎭 :performing_arts:'; insertText = '🎭'; filterText = ':performing_arts:' };
+{ word = ':video_game:'; label = '🎮 :video_game:'; insertText = '🎮'; filterText = ':video_game:' };
+{ word = ':dart:'; label = '🎯 :dart:'; insertText = '🎯'; filterText = ':dart:' };
+{ word = ':slot_machine:'; label = '🎰 :slot_machine:'; insertText = '🎰'; filterText = ':slot_machine:' };
+{ word = ':8ball:'; label = '🎱 :8ball:'; insertText = '🎱'; filterText = ':8ball:' };
+{ word = ':game_die:'; label = '🎲 :game_die:'; insertText = '🎲'; filterText = ':game_die:' };
+{ word = ':bowling:'; label = '🎳 :bowling:'; insertText = '🎳'; filterText = ':bowling:' };
+{ word = ':flower_playing_cards:'; label = '🎴 :flower_playing_cards:'; insertText = '🎴'; filterText = ':flower_playing_cards:' };
+{ word = ':musical_note:'; label = '🎵 :musical_note:'; insertText = '🎵'; filterText = ':musical_note:' };
+{ word = ':notes:'; label = '🎶 :notes:'; insertText = '🎶'; filterText = ':notes:' };
+{ word = ':saxophone:'; label = '🎷 :saxophone:'; insertText = '🎷'; filterText = ':saxophone:' };
+{ word = ':guitar:'; label = '🎸 :guitar:'; insertText = '🎸'; filterText = ':guitar:' };
+{ word = ':musical_keyboard:'; label = '🎹 :musical_keyboard:'; insertText = '🎹'; filterText = ':musical_keyboard:' };
+{ word = ':trumpet:'; label = '🎺 :trumpet:'; insertText = '🎺'; filterText = ':trumpet:' };
+{ word = ':violin:'; label = '🎻 :violin:'; insertText = '🎻'; filterText = ':violin:' };
+{ word = ':musical_score:'; label = '🎼 :musical_score:'; insertText = '🎼'; filterText = ':musical_score:' };
+{ word = ':running_shirt_with_sash:'; label = '🎽 :running_shirt_with_sash:'; insertText = '🎽'; filterText = ':running_shirt_with_sash:' };
+{ word = ':tennis:'; label = '🎾 :tennis:'; insertText = '🎾'; filterText = ':tennis:' };
+{ word = ':ski:'; label = '🎿 :ski:'; insertText = '🎿'; filterText = ':ski:' };
+{ word = ':basketball:'; label = '🏀 :basketball:'; insertText = '🏀'; filterText = ':basketball:' };
+{ word = ':checkered_flag:'; label = '🏁 :checkered_flag:'; insertText = '🏁'; filterText = ':checkered_flag:' };
+{ word = ':snowboarder:'; label = '🏂 :snowboarder:'; insertText = '🏂'; filterText = ':snowboarder:' };
+{ word = ':runner:'; label = '🏃 :runner:'; insertText = '🏃'; filterText = ':runner:' };
+{ word = ':running:'; label = '🏃 :running:'; insertText = '🏃'; filterText = ':running:' };
+{ word = ':surfer:'; label = '🏄 :surfer:'; insertText = '🏄'; filterText = ':surfer:' };
+{ word = ':sports_medal:'; label = '🏅 :sports_medal:'; insertText = '🏅'; filterText = ':sports_medal:' };
+{ word = ':trophy:'; label = '🏆 :trophy:'; insertText = '🏆'; filterText = ':trophy:' };
+{ word = ':horse_racing:'; label = '🏇 :horse_racing:'; insertText = '🏇'; filterText = ':horse_racing:' };
+{ word = ':football:'; label = '🏈 :football:'; insertText = '🏈'; filterText = ':football:' };
+{ word = ':rugby_football:'; label = '🏉 :rugby_football:'; insertText = '🏉'; filterText = ':rugby_football:' };
+{ word = ':swimmer:'; label = '🏊 :swimmer:'; insertText = '🏊'; filterText = ':swimmer:' };
+{ word = ':weight_lifter:'; label = '🏋️ :weight_lifter:'; insertText = '🏋️'; filterText = ':weight_lifter:' };
+{ word = ':golfer:'; label = '🏌️ :golfer:'; insertText = '🏌️'; filterText = ':golfer:' };
+{ word = ':racing_motorcycle:'; label = '🏍️ :racing_motorcycle:'; insertText = '🏍️'; filterText = ':racing_motorcycle:' };
+{ word = ':racing_car:'; label = '🏎️ :racing_car:'; insertText = '🏎️'; filterText = ':racing_car:' };
+{ word = ':cricket_bat_and_ball:'; label = '🏏 :cricket_bat_and_ball:'; insertText = '🏏'; filterText = ':cricket_bat_and_ball:' };
+{ word = ':volleyball:'; label = '🏐 :volleyball:'; insertText = '🏐'; filterText = ':volleyball:' };
+{ word = ':field_hockey_stick_and_ball:'; label = '🏑 :field_hockey_stick_and_ball:'; insertText = '🏑'; filterText = ':field_hockey_stick_and_ball:' };
+{ word = ':ice_hockey_stick_and_puck:'; label = '🏒 :ice_hockey_stick_and_puck:'; insertText = '🏒'; filterText = ':ice_hockey_stick_and_puck:' };
+{ word = ':table_tennis_paddle_and_ball:'; label = '🏓 :table_tennis_paddle_and_ball:'; insertText = '🏓'; filterText = ':table_tennis_paddle_and_ball:' };
+{ word = ':snow_capped_mountain:'; label = '🏔️ :snow_capped_mountain:'; insertText = '🏔️'; filterText = ':snow_capped_mountain:' };
+{ word = ':camping:'; label = '🏕️ :camping:'; insertText = '🏕️'; filterText = ':camping:' };
+{ word = ':beach_with_umbrella:'; label = '🏖️ :beach_with_umbrella:'; insertText = '🏖️'; filterText = ':beach_with_umbrella:' };
+{ word = ':building_construction:'; label = '🏗️ :building_construction:'; insertText = '🏗️'; filterText = ':building_construction:' };
+{ word = ':house_buildings:'; label = '🏘️ :house_buildings:'; insertText = '🏘️'; filterText = ':house_buildings:' };
+{ word = ':cityscape:'; label = '🏙️ :cityscape:'; insertText = '🏙️'; filterText = ':cityscape:' };
+{ word = ':derelict_house_building:'; label = '🏚️ :derelict_house_building:'; insertText = '🏚️'; filterText = ':derelict_house_building:' };
+{ word = ':classical_building:'; label = '🏛️ :classical_building:'; insertText = '🏛️'; filterText = ':classical_building:' };
+{ word = ':desert:'; label = '🏜️ :desert:'; insertText = '🏜️'; filterText = ':desert:' };
+{ word = ':desert_island:'; label = '🏝️ :desert_island:'; insertText = '🏝️'; filterText = ':desert_island:' };
+{ word = ':national_park:'; label = '🏞️ :national_park:'; insertText = '🏞️'; filterText = ':national_park:' };
+{ word = ':stadium:'; label = '🏟️ :stadium:'; insertText = '🏟️'; filterText = ':stadium:' };
+{ word = ':house:'; label = '🏠 :house:'; insertText = '🏠'; filterText = ':house:' };
+{ word = ':house_with_garden:'; label = '🏡 :house_with_garden:'; insertText = '🏡'; filterText = ':house_with_garden:' };
+{ word = ':office:'; label = '🏢 :office:'; insertText = '🏢'; filterText = ':office:' };
+{ word = ':post_office:'; label = '🏣 :post_office:'; insertText = '🏣'; filterText = ':post_office:' };
+{ word = ':european_post_office:'; label = '🏤 :european_post_office:'; insertText = '🏤'; filterText = ':european_post_office:' };
+{ word = ':hospital:'; label = '🏥 :hospital:'; insertText = '🏥'; filterText = ':hospital:' };
+{ word = ':bank:'; label = '🏦 :bank:'; insertText = '🏦'; filterText = ':bank:' };
+{ word = ':atm:'; label = '🏧 :atm:'; insertText = '🏧'; filterText = ':atm:' };
+{ word = ':hotel:'; label = '🏨 :hotel:'; insertText = '🏨'; filterText = ':hotel:' };
+{ word = ':love_hotel:'; label = '🏩 :love_hotel:'; insertText = '🏩'; filterText = ':love_hotel:' };
+{ word = ':convenience_store:'; label = '🏪 :convenience_store:'; insertText = '🏪'; filterText = ':convenience_store:' };
+{ word = ':school:'; label = '🏫 :school:'; insertText = '🏫'; filterText = ':school:' };
+{ word = ':department_store:'; label = '🏬 :department_store:'; insertText = '🏬'; filterText = ':department_store:' };
+{ word = ':factory:'; label = '🏭 :factory:'; insertText = '🏭'; filterText = ':factory:' };
+{ word = ':izakaya_lantern:'; label = '🏮 :izakaya_lantern:'; insertText = '🏮'; filterText = ':izakaya_lantern:' };
+{ word = ':lantern:'; label = '🏮 :lantern:'; insertText = '🏮'; filterText = ':lantern:' };
+{ word = ':japanese_castle:'; label = '🏯 :japanese_castle:'; insertText = '🏯'; filterText = ':japanese_castle:' };
+{ word = ':european_castle:'; label = '🏰 :european_castle:'; insertText = '🏰'; filterText = ':european_castle:' };
+{ word = ':waving_white_flag:'; label = '🏳️ :waving_white_flag:'; insertText = '🏳️'; filterText = ':waving_white_flag:' };
+{ word = ':waving_black_flag:'; label = '🏴 :waving_black_flag:'; insertText = '🏴'; filterText = ':waving_black_flag:' };
+{ word = ':rosette:'; label = '🏵️ :rosette:'; insertText = '🏵️'; filterText = ':rosette:' };
+{ word = ':label:'; label = '🏷️ :label:'; insertText = '🏷️'; filterText = ':label:' };
+{ word = ':badminton_racquet_and_shuttlecock:'; label = '🏸 :badminton_racquet_and_shuttlecock:'; insertText = '🏸'; filterText = ':badminton_racquet_and_shuttlecock:' };
+{ word = ':bow_and_arrow:'; label = '🏹 :bow_and_arrow:'; insertText = '🏹'; filterText = ':bow_and_arrow:' };
+{ word = ':amphora:'; label = '🏺 :amphora:'; insertText = '🏺'; filterText = ':amphora:' };
+{ word = ':skin-tone-2:'; label = '🏻 :skin-tone-2:'; insertText = '🏻'; filterText = ':skin-tone-2:' };
+{ word = ':skin-tone-3:'; label = '🏼 :skin-tone-3:'; insertText = '🏼'; filterText = ':skin-tone-3:' };
+{ word = ':skin-tone-4:'; label = '🏽 :skin-tone-4:'; insertText = '🏽'; filterText = ':skin-tone-4:' };
+{ word = ':skin-tone-5:'; label = '🏾 :skin-tone-5:'; insertText = '🏾'; filterText = ':skin-tone-5:' };
+{ word = ':skin-tone-6:'; label = '🏿 :skin-tone-6:'; insertText = '🏿'; filterText = ':skin-tone-6:' };
+{ word = ':rat:'; label = '🐀 :rat:'; insertText = '🐀'; filterText = ':rat:' };
+{ word = ':mouse2:'; label = '🐁 :mouse2:'; insertText = '🐁'; filterText = ':mouse2:' };
+{ word = ':ox:'; label = '🐂 :ox:'; insertText = '🐂'; filterText = ':ox:' };
+{ word = ':water_buffalo:'; label = '🐃 :water_buffalo:'; insertText = '🐃'; filterText = ':water_buffalo:' };
+{ word = ':cow2:'; label = '🐄 :cow2:'; insertText = '🐄'; filterText = ':cow2:' };
+{ word = ':tiger2:'; label = '🐅 :tiger2:'; insertText = '🐅'; filterText = ':tiger2:' };
+{ word = ':leopard:'; label = '🐆 :leopard:'; insertText = '🐆'; filterText = ':leopard:' };
+{ word = ':rabbit2:'; label = '🐇 :rabbit2:'; insertText = '🐇'; filterText = ':rabbit2:' };
+{ word = ':cat2:'; label = '🐈 :cat2:'; insertText = '🐈'; filterText = ':cat2:' };
+{ word = ':dragon:'; label = '🐉 :dragon:'; insertText = '🐉'; filterText = ':dragon:' };
+{ word = ':crocodile:'; label = '🐊 :crocodile:'; insertText = '🐊'; filterText = ':crocodile:' };
+{ word = ':whale2:'; label = '🐋 :whale2:'; insertText = '🐋'; filterText = ':whale2:' };
+{ word = ':snail:'; label = '🐌 :snail:'; insertText = '🐌'; filterText = ':snail:' };
+{ word = ':snake:'; label = '🐍 :snake:'; insertText = '🐍'; filterText = ':snake:' };
+{ word = ':racehorse:'; label = '🐎 :racehorse:'; insertText = '🐎'; filterText = ':racehorse:' };
+{ word = ':ram:'; label = '🐏 :ram:'; insertText = '🐏'; filterText = ':ram:' };
+{ word = ':goat:'; label = '🐐 :goat:'; insertText = '🐐'; filterText = ':goat:' };
+{ word = ':sheep:'; label = '🐑 :sheep:'; insertText = '🐑'; filterText = ':sheep:' };
+{ word = ':monkey:'; label = '🐒 :monkey:'; insertText = '🐒'; filterText = ':monkey:' };
+{ word = ':rooster:'; label = '🐓 :rooster:'; insertText = '🐓'; filterText = ':rooster:' };
+{ word = ':chicken:'; label = '🐔 :chicken:'; insertText = '🐔'; filterText = ':chicken:' };
+{ word = ':dog2:'; label = '🐕 :dog2:'; insertText = '🐕'; filterText = ':dog2:' };
+{ word = ':pig2:'; label = '🐖 :pig2:'; insertText = '🐖'; filterText = ':pig2:' };
+{ word = ':boar:'; label = '🐗 :boar:'; insertText = '🐗'; filterText = ':boar:' };
+{ word = ':elephant:'; label = '🐘 :elephant:'; insertText = '🐘'; filterText = ':elephant:' };
+{ word = ':octopus:'; label = '🐙 :octopus:'; insertText = '🐙'; filterText = ':octopus:' };
+{ word = ':shell:'; label = '🐚 :shell:'; insertText = '🐚'; filterText = ':shell:' };
+{ word = ':bug:'; label = '🐛 :bug:'; insertText = '🐛'; filterText = ':bug:' };
+{ word = ':ant:'; label = '🐜 :ant:'; insertText = '🐜'; filterText = ':ant:' };
+{ word = ':bee:'; label = '🐝 :bee:'; insertText = '🐝'; filterText = ':bee:' };
+{ word = ':honeybee:'; label = '🐝 :honeybee:'; insertText = '🐝'; filterText = ':honeybee:' };
+{ word = ':ladybug:'; label = '🐞 :ladybug:'; insertText = '🐞'; filterText = ':ladybug:' };
+{ word = ':lady_beetle:'; label = '🐞 :lady_beetle:'; insertText = '🐞'; filterText = ':lady_beetle:' };
+{ word = ':fish:'; label = '🐟 :fish:'; insertText = '🐟'; filterText = ':fish:' };
+{ word = ':tropical_fish:'; label = '🐠 :tropical_fish:'; insertText = '🐠'; filterText = ':tropical_fish:' };
+{ word = ':blowfish:'; label = '🐡 :blowfish:'; insertText = '🐡'; filterText = ':blowfish:' };
+{ word = ':turtle:'; label = '🐢 :turtle:'; insertText = '🐢'; filterText = ':turtle:' };
+{ word = ':hatching_chick:'; label = '🐣 :hatching_chick:'; insertText = '🐣'; filterText = ':hatching_chick:' };
+{ word = ':baby_chick:'; label = '🐤 :baby_chick:'; insertText = '🐤'; filterText = ':baby_chick:' };
+{ word = ':hatched_chick:'; label = '🐥 :hatched_chick:'; insertText = '🐥'; filterText = ':hatched_chick:' };
+{ word = ':bird:'; label = '🐦 :bird:'; insertText = '🐦'; filterText = ':bird:' };
+{ word = ':penguin:'; label = '🐧 :penguin:'; insertText = '🐧'; filterText = ':penguin:' };
+{ word = ':koala:'; label = '🐨 :koala:'; insertText = '🐨'; filterText = ':koala:' };
+{ word = ':poodle:'; label = '🐩 :poodle:'; insertText = '🐩'; filterText = ':poodle:' };
+{ word = ':dromedary_camel:'; label = '🐪 :dromedary_camel:'; insertText = '🐪'; filterText = ':dromedary_camel:' };
+{ word = ':camel:'; label = '🐫 :camel:'; insertText = '🐫'; filterText = ':camel:' };
+{ word = ':dolphin:'; label = '🐬 :dolphin:'; insertText = '🐬'; filterText = ':dolphin:' };
+{ word = ':flipper:'; label = '🐬 :flipper:'; insertText = '🐬'; filterText = ':flipper:' };
+{ word = ':mouse:'; label = '🐭 :mouse:'; insertText = '🐭'; filterText = ':mouse:' };
+{ word = ':cow:'; label = '🐮 :cow:'; insertText = '🐮'; filterText = ':cow:' };
+{ word = ':tiger:'; label = '🐯 :tiger:'; insertText = '🐯'; filterText = ':tiger:' };
+{ word = ':rabbit:'; label = '🐰 :rabbit:'; insertText = '🐰'; filterText = ':rabbit:' };
+{ word = ':cat:'; label = '🐱 :cat:'; insertText = '🐱'; filterText = ':cat:' };
+{ word = ':dragon_face:'; label = '🐲 :dragon_face:'; insertText = '🐲'; filterText = ':dragon_face:' };
+{ word = ':whale:'; label = '🐳 :whale:'; insertText = '🐳'; filterText = ':whale:' };
+{ word = ':horse:'; label = '🐴 :horse:'; insertText = '🐴'; filterText = ':horse:' };
+{ word = ':monkey_face:'; label = '🐵 :monkey_face:'; insertText = '🐵'; filterText = ':monkey_face:' };
+{ word = ':dog:'; label = '🐶 :dog:'; insertText = '🐶'; filterText = ':dog:' };
+{ word = ':pig:'; label = '🐷 :pig:'; insertText = '🐷'; filterText = ':pig:' };
+{ word = ':frog:'; label = '🐸 :frog:'; insertText = '🐸'; filterText = ':frog:' };
+{ word = ':hamster:'; label = '🐹 :hamster:'; insertText = '🐹'; filterText = ':hamster:' };
+{ word = ':wolf:'; label = '🐺 :wolf:'; insertText = '🐺'; filterText = ':wolf:' };
+{ word = ':bear:'; label = '🐻 :bear:'; insertText = '🐻'; filterText = ':bear:' };
+{ word = ':panda_face:'; label = '🐼 :panda_face:'; insertText = '🐼'; filterText = ':panda_face:' };
+{ word = ':pig_nose:'; label = '🐽 :pig_nose:'; insertText = '🐽'; filterText = ':pig_nose:' };
+{ word = ':feet:'; label = '🐾 :feet:'; insertText = '🐾'; filterText = ':feet:' };
+{ word = ':paw_prints:'; label = '🐾 :paw_prints:'; insertText = '🐾'; filterText = ':paw_prints:' };
+{ word = ':chipmunk:'; label = '🐿️ :chipmunk:'; insertText = '🐿️'; filterText = ':chipmunk:' };
+{ word = ':eyes:'; label = '👀 :eyes:'; insertText = '👀'; filterText = ':eyes:' };
+{ word = ':eye:'; label = '👁️ :eye:'; insertText = '👁️'; filterText = ':eye:' };
+{ word = ':ear:'; label = '👂 :ear:'; insertText = '👂'; filterText = ':ear:' };
+{ word = ':nose:'; label = '👃 :nose:'; insertText = '👃'; filterText = ':nose:' };
+{ word = ':lips:'; label = '👄 :lips:'; insertText = '👄'; filterText = ':lips:' };
+{ word = ':tongue:'; label = '👅 :tongue:'; insertText = '👅'; filterText = ':tongue:' };
+{ word = ':point_up_2:'; label = '👆 :point_up_2:'; insertText = '👆'; filterText = ':point_up_2:' };
+{ word = ':point_down:'; label = '👇 :point_down:'; insertText = '👇'; filterText = ':point_down:' };
+{ word = ':point_left:'; label = '👈 :point_left:'; insertText = '👈'; filterText = ':point_left:' };
+{ word = ':point_right:'; label = '👉 :point_right:'; insertText = '👉'; filterText = ':point_right:' };
+{ word = ':facepunch:'; label = '👊 :facepunch:'; insertText = '👊'; filterText = ':facepunch:' };
+{ word = ':punch:'; label = '👊 :punch:'; insertText = '👊'; filterText = ':punch:' };
+{ word = ':wave:'; label = '👋 :wave:'; insertText = '👋'; filterText = ':wave:' };
+{ word = ':ok_hand:'; label = '👌 :ok_hand:'; insertText = '👌'; filterText = ':ok_hand:' };
+{ word = ':+1:'; label = '👍 :+1:'; insertText = '👍'; filterText = ':+1:' };
+{ word = ':thumbsup:'; label = '👍 :thumbsup:'; insertText = '👍'; filterText = ':thumbsup:' };
+{ word = ':-1:'; label = '👎 :-1:'; insertText = '👎'; filterText = ':-1:' };
+{ word = ':thumbsdown:'; label = '👎 :thumbsdown:'; insertText = '👎'; filterText = ':thumbsdown:' };
+{ word = ':clap:'; label = '👏 :clap:'; insertText = '👏'; filterText = ':clap:' };
+{ word = ':open_hands:'; label = '👐 :open_hands:'; insertText = '👐'; filterText = ':open_hands:' };
+{ word = ':crown:'; label = '👑 :crown:'; insertText = '👑'; filterText = ':crown:' };
+{ word = ':womans_hat:'; label = '👒 :womans_hat:'; insertText = '👒'; filterText = ':womans_hat:' };
+{ word = ':eyeglasses:'; label = '👓 :eyeglasses:'; insertText = '👓'; filterText = ':eyeglasses:' };
+{ word = ':necktie:'; label = '👔 :necktie:'; insertText = '👔'; filterText = ':necktie:' };
+{ word = ':shirt:'; label = '👕 :shirt:'; insertText = '👕'; filterText = ':shirt:' };
+{ word = ':tshirt:'; label = '👕 :tshirt:'; insertText = '👕'; filterText = ':tshirt:' };
+{ word = ':jeans:'; label = '👖 :jeans:'; insertText = '👖'; filterText = ':jeans:' };
+{ word = ':dress:'; label = '👗 :dress:'; insertText = '👗'; filterText = ':dress:' };
+{ word = ':kimono:'; label = '👘 :kimono:'; insertText = '👘'; filterText = ':kimono:' };
+{ word = ':bikini:'; label = '👙 :bikini:'; insertText = '👙'; filterText = ':bikini:' };
+{ word = ':womans_clothes:'; label = '👚 :womans_clothes:'; insertText = '👚'; filterText = ':womans_clothes:' };
+{ word = ':purse:'; label = '👛 :purse:'; insertText = '👛'; filterText = ':purse:' };
+{ word = ':handbag:'; label = '👜 :handbag:'; insertText = '👜'; filterText = ':handbag:' };
+{ word = ':pouch:'; label = '👝 :pouch:'; insertText = '👝'; filterText = ':pouch:' };
+{ word = ':mans_shoe:'; label = '👞 :mans_shoe:'; insertText = '👞'; filterText = ':mans_shoe:' };
+{ word = ':shoe:'; label = '👞 :shoe:'; insertText = '👞'; filterText = ':shoe:' };
+{ word = ':athletic_shoe:'; label = '👟 :athletic_shoe:'; insertText = '👟'; filterText = ':athletic_shoe:' };
+{ word = ':high_heel:'; label = '👠 :high_heel:'; insertText = '👠'; filterText = ':high_heel:' };
+{ word = ':sandal:'; label = '👡 :sandal:'; insertText = '👡'; filterText = ':sandal:' };
+{ word = ':boot:'; label = '👢 :boot:'; insertText = '👢'; filterText = ':boot:' };
+{ word = ':footprints:'; label = '👣 :footprints:'; insertText = '👣'; filterText = ':footprints:' };
+{ word = ':bust_in_silhouette:'; label = '👤 :bust_in_silhouette:'; insertText = '👤'; filterText = ':bust_in_silhouette:' };
+{ word = ':busts_in_silhouette:'; label = '👥 :busts_in_silhouette:'; insertText = '👥'; filterText = ':busts_in_silhouette:' };
+{ word = ':boy:'; label = '👦 :boy:'; insertText = '👦'; filterText = ':boy:' };
+{ word = ':girl:'; label = '👧 :girl:'; insertText = '👧'; filterText = ':girl:' };
+{ word = ':man:'; label = '👨 :man:'; insertText = '👨'; filterText = ':man:' };
+{ word = ':woman:'; label = '👩 :woman:'; insertText = '👩'; filterText = ':woman:' };
+{ word = ':family:'; label = '👪 :family:'; insertText = '👪'; filterText = ':family:' };
+{ word = ':man_and_woman_holding_hands:'; label = '👫 :man_and_woman_holding_hands:'; insertText = '👫'; filterText = ':man_and_woman_holding_hands:' };
+{ word = ':woman_and_man_holding_hands:'; label = '👫 :woman_and_man_holding_hands:'; insertText = '👫'; filterText = ':woman_and_man_holding_hands:' };
+{ word = ':couple:'; label = '👫 :couple:'; insertText = '👫'; filterText = ':couple:' };
+{ word = ':two_men_holding_hands:'; label = '👬 :two_men_holding_hands:'; insertText = '👬'; filterText = ':two_men_holding_hands:' };
+{ word = ':men_holding_hands:'; label = '👬 :men_holding_hands:'; insertText = '👬'; filterText = ':men_holding_hands:' };
+{ word = ':two_women_holding_hands:'; label = '👭 :two_women_holding_hands:'; insertText = '👭'; filterText = ':two_women_holding_hands:' };
+{ word = ':women_holding_hands:'; label = '👭 :women_holding_hands:'; insertText = '👭'; filterText = ':women_holding_hands:' };
+{ word = ':cop:'; label = '👮 :cop:'; insertText = '👮'; filterText = ':cop:' };
+{ word = ':dancers:'; label = '👯 :dancers:'; insertText = '👯'; filterText = ':dancers:' };
+{ word = ':bride_with_veil:'; label = '👰 :bride_with_veil:'; insertText = '👰'; filterText = ':bride_with_veil:' };
+{ word = ':person_with_blond_hair:'; label = '👱 :person_with_blond_hair:'; insertText = '👱'; filterText = ':person_with_blond_hair:' };
+{ word = ':man_with_gua_pi_mao:'; label = '👲 :man_with_gua_pi_mao:'; insertText = '👲'; filterText = ':man_with_gua_pi_mao:' };
+{ word = ':man_with_turban:'; label = '👳 :man_with_turban:'; insertText = '👳'; filterText = ':man_with_turban:' };
+{ word = ':older_man:'; label = '👴 :older_man:'; insertText = '👴'; filterText = ':older_man:' };
+{ word = ':older_woman:'; label = '👵 :older_woman:'; insertText = '👵'; filterText = ':older_woman:' };
+{ word = ':baby:'; label = '👶 :baby:'; insertText = '👶'; filterText = ':baby:' };
+{ word = ':construction_worker:'; label = '👷 :construction_worker:'; insertText = '👷'; filterText = ':construction_worker:' };
+{ word = ':princess:'; label = '👸 :princess:'; insertText = '👸'; filterText = ':princess:' };
+{ word = ':japanese_ogre:'; label = '👹 :japanese_ogre:'; insertText = '👹'; filterText = ':japanese_ogre:' };
+{ word = ':japanese_goblin:'; label = '👺 :japanese_goblin:'; insertText = '👺'; filterText = ':japanese_goblin:' };
+{ word = ':ghost:'; label = '👻 :ghost:'; insertText = '👻'; filterText = ':ghost:' };
+{ word = ':angel:'; label = '👼 :angel:'; insertText = '👼'; filterText = ':angel:' };
+{ word = ':alien:'; label = '👽 :alien:'; insertText = '👽'; filterText = ':alien:' };
+{ word = ':space_invader:'; label = '👾 :space_invader:'; insertText = '👾'; filterText = ':space_invader:' };
+{ word = ':imp:'; label = '👿 :imp:'; insertText = '👿'; filterText = ':imp:' };
+{ word = ':skull:'; label = '💀 :skull:'; insertText = '💀'; filterText = ':skull:' };
+{ word = ':information_desk_person:'; label = '💁 :information_desk_person:'; insertText = '💁'; filterText = ':information_desk_person:' };
+{ word = ':guardsman:'; label = '💂 :guardsman:'; insertText = '💂'; filterText = ':guardsman:' };
+{ word = ':dancer:'; label = '💃 :dancer:'; insertText = '💃'; filterText = ':dancer:' };
+{ word = ':lipstick:'; label = '💄 :lipstick:'; insertText = '💄'; filterText = ':lipstick:' };
+{ word = ':nail_care:'; label = '💅 :nail_care:'; insertText = '💅'; filterText = ':nail_care:' };
+{ word = ':massage:'; label = '💆 :massage:'; insertText = '💆'; filterText = ':massage:' };
+{ word = ':haircut:'; label = '💇 :haircut:'; insertText = '💇'; filterText = ':haircut:' };
+{ word = ':barber:'; label = '💈 :barber:'; insertText = '💈'; filterText = ':barber:' };
+{ word = ':syringe:'; label = '💉 :syringe:'; insertText = '💉'; filterText = ':syringe:' };
+{ word = ':pill:'; label = '💊 :pill:'; insertText = '💊'; filterText = ':pill:' };
+{ word = ':kiss:'; label = '💋 :kiss:'; insertText = '💋'; filterText = ':kiss:' };
+{ word = ':love_letter:'; label = '💌 :love_letter:'; insertText = '💌'; filterText = ':love_letter:' };
+{ word = ':ring:'; label = '💍 :ring:'; insertText = '💍'; filterText = ':ring:' };
+{ word = ':gem:'; label = '💎 :gem:'; insertText = '💎'; filterText = ':gem:' };
+{ word = ':couplekiss:'; label = '💏 :couplekiss:'; insertText = '💏'; filterText = ':couplekiss:' };
+{ word = ':bouquet:'; label = '💐 :bouquet:'; insertText = '💐'; filterText = ':bouquet:' };
+{ word = ':couple_with_heart:'; label = '💑 :couple_with_heart:'; insertText = '💑'; filterText = ':couple_with_heart:' };
+{ word = ':wedding:'; label = '💒 :wedding:'; insertText = '💒'; filterText = ':wedding:' };
+{ word = ':heartbeat:'; label = '💓 :heartbeat:'; insertText = '💓'; filterText = ':heartbeat:' };
+{ word = ':broken_heart:'; label = '💔 :broken_heart:'; insertText = '💔'; filterText = ':broken_heart:' };
+{ word = ':two_hearts:'; label = '💕 :two_hearts:'; insertText = '💕'; filterText = ':two_hearts:' };
+{ word = ':sparkling_heart:'; label = '💖 :sparkling_heart:'; insertText = '💖'; filterText = ':sparkling_heart:' };
+{ word = ':heartpulse:'; label = '💗 :heartpulse:'; insertText = '💗'; filterText = ':heartpulse:' };
+{ word = ':cupid:'; label = '💘 :cupid:'; insertText = '💘'; filterText = ':cupid:' };
+{ word = ':blue_heart:'; label = '💙 :blue_heart:'; insertText = '💙'; filterText = ':blue_heart:' };
+{ word = ':green_heart:'; label = '💚 :green_heart:'; insertText = '💚'; filterText = ':green_heart:' };
+{ word = ':yellow_heart:'; label = '💛 :yellow_heart:'; insertText = '💛'; filterText = ':yellow_heart:' };
+{ word = ':purple_heart:'; label = '💜 :purple_heart:'; insertText = '💜'; filterText = ':purple_heart:' };
+{ word = ':gift_heart:'; label = '💝 :gift_heart:'; insertText = '💝'; filterText = ':gift_heart:' };
+{ word = ':revolving_hearts:'; label = '💞 :revolving_hearts:'; insertText = '💞'; filterText = ':revolving_hearts:' };
+{ word = ':heart_decoration:'; label = '💟 :heart_decoration:'; insertText = '💟'; filterText = ':heart_decoration:' };
+{ word = ':diamond_shape_with_a_dot_inside:'; label = '💠 :diamond_shape_with_a_dot_inside:'; insertText = '💠'; filterText = ':diamond_shape_with_a_dot_inside:' };
+{ word = ':bulb:'; label = '💡 :bulb:'; insertText = '💡'; filterText = ':bulb:' };
+{ word = ':anger:'; label = '💢 :anger:'; insertText = '💢'; filterText = ':anger:' };
+{ word = ':bomb:'; label = '💣 :bomb:'; insertText = '💣'; filterText = ':bomb:' };
+{ word = ':zzz:'; label = '💤 :zzz:'; insertText = '💤'; filterText = ':zzz:' };
+{ word = ':boom:'; label = '💥 :boom:'; insertText = '💥'; filterText = ':boom:' };
+{ word = ':collision:'; label = '💥 :collision:'; insertText = '💥'; filterText = ':collision:' };
+{ word = ':sweat_drops:'; label = '💦 :sweat_drops:'; insertText = '💦'; filterText = ':sweat_drops:' };
+{ word = ':droplet:'; label = '💧 :droplet:'; insertText = '💧'; filterText = ':droplet:' };
+{ word = ':dash:'; label = '💨 :dash:'; insertText = '💨'; filterText = ':dash:' };
+{ word = ':hankey:'; label = '💩 :hankey:'; insertText = '💩'; filterText = ':hankey:' };
+{ word = ':poop:'; label = '💩 :poop:'; insertText = '💩'; filterText = ':poop:' };
+{ word = ':shit:'; label = '💩 :shit:'; insertText = '💩'; filterText = ':shit:' };
+{ word = ':muscle:'; label = '💪 :muscle:'; insertText = '💪'; filterText = ':muscle:' };
+{ word = ':dizzy:'; label = '💫 :dizzy:'; insertText = '💫'; filterText = ':dizzy:' };
+{ word = ':speech_balloon:'; label = '💬 :speech_balloon:'; insertText = '💬'; filterText = ':speech_balloon:' };
+{ word = ':thought_balloon:'; label = '💭 :thought_balloon:'; insertText = '💭'; filterText = ':thought_balloon:' };
+{ word = ':white_flower:'; label = '💮 :white_flower:'; insertText = '💮'; filterText = ':white_flower:' };
+{ word = ':100:'; label = '💯 :100:'; insertText = '💯'; filterText = ':100:' };
+{ word = ':moneybag:'; label = '💰 :moneybag:'; insertText = '💰'; filterText = ':moneybag:' };
+{ word = ':currency_exchange:'; label = '💱 :currency_exchange:'; insertText = '💱'; filterText = ':currency_exchange:' };
+{ word = ':heavy_dollar_sign:'; label = '💲 :heavy_dollar_sign:'; insertText = '💲'; filterText = ':heavy_dollar_sign:' };
+{ word = ':credit_card:'; label = '💳 :credit_card:'; insertText = '💳'; filterText = ':credit_card:' };
+{ word = ':yen:'; label = '💴 :yen:'; insertText = '💴'; filterText = ':yen:' };
+{ word = ':dollar:'; label = '💵 :dollar:'; insertText = '💵'; filterText = ':dollar:' };
+{ word = ':euro:'; label = '💶 :euro:'; insertText = '💶'; filterText = ':euro:' };
+{ word = ':pound:'; label = '💷 :pound:'; insertText = '💷'; filterText = ':pound:' };
+{ word = ':money_with_wings:'; label = '💸 :money_with_wings:'; insertText = '💸'; filterText = ':money_with_wings:' };
+{ word = ':chart:'; label = '💹 :chart:'; insertText = '💹'; filterText = ':chart:' };
+{ word = ':seat:'; label = '💺 :seat:'; insertText = '💺'; filterText = ':seat:' };
+{ word = ':computer:'; label = '💻 :computer:'; insertText = '💻'; filterText = ':computer:' };
+{ word = ':briefcase:'; label = '💼 :briefcase:'; insertText = '💼'; filterText = ':briefcase:' };
+{ word = ':minidisc:'; label = '💽 :minidisc:'; insertText = '💽'; filterText = ':minidisc:' };
+{ word = ':floppy_disk:'; label = '💾 :floppy_disk:'; insertText = '💾'; filterText = ':floppy_disk:' };
+{ word = ':cd:'; label = '💿 :cd:'; insertText = '💿'; filterText = ':cd:' };
+{ word = ':dvd:'; label = '📀 :dvd:'; insertText = '📀'; filterText = ':dvd:' };
+{ word = ':file_folder:'; label = '📁 :file_folder:'; insertText = '📁'; filterText = ':file_folder:' };
+{ word = ':open_file_folder:'; label = '📂 :open_file_folder:'; insertText = '📂'; filterText = ':open_file_folder:' };
+{ word = ':page_with_curl:'; label = '📃 :page_with_curl:'; insertText = '📃'; filterText = ':page_with_curl:' };
+{ word = ':page_facing_up:'; label = '📄 :page_facing_up:'; insertText = '📄'; filterText = ':page_facing_up:' };
+{ word = ':date:'; label = '📅 :date:'; insertText = '📅'; filterText = ':date:' };
+{ word = ':calendar:'; label = '📆 :calendar:'; insertText = '📆'; filterText = ':calendar:' };
+{ word = ':card_index:'; label = '📇 :card_index:'; insertText = '📇'; filterText = ':card_index:' };
+{ word = ':chart_with_upwards_trend:'; label = '📈 :chart_with_upwards_trend:'; insertText = '📈'; filterText = ':chart_with_upwards_trend:' };
+{ word = ':chart_with_downwards_trend:'; label = '📉 :chart_with_downwards_trend:'; insertText = '📉'; filterText = ':chart_with_downwards_trend:' };
+{ word = ':bar_chart:'; label = '📊 :bar_chart:'; insertText = '📊'; filterText = ':bar_chart:' };
+{ word = ':clipboard:'; label = '📋 :clipboard:'; insertText = '📋'; filterText = ':clipboard:' };
+{ word = ':pushpin:'; label = '📌 :pushpin:'; insertText = '📌'; filterText = ':pushpin:' };
+{ word = ':round_pushpin:'; label = '📍 :round_pushpin:'; insertText = '📍'; filterText = ':round_pushpin:' };
+{ word = ':paperclip:'; label = '📎 :paperclip:'; insertText = '📎'; filterText = ':paperclip:' };
+{ word = ':straight_ruler:'; label = '📏 :straight_ruler:'; insertText = '📏'; filterText = ':straight_ruler:' };
+{ word = ':triangular_ruler:'; label = '📐 :triangular_ruler:'; insertText = '📐'; filterText = ':triangular_ruler:' };
+{ word = ':bookmark_tabs:'; label = '📑 :bookmark_tabs:'; insertText = '📑'; filterText = ':bookmark_tabs:' };
+{ word = ':ledger:'; label = '📒 :ledger:'; insertText = '📒'; filterText = ':ledger:' };
+{ word = ':notebook:'; label = '📓 :notebook:'; insertText = '📓'; filterText = ':notebook:' };
+{ word = ':notebook_with_decorative_cover:'; label = '📔 :notebook_with_decorative_cover:'; insertText = '📔'; filterText = ':notebook_with_decorative_cover:' };
+{ word = ':closed_book:'; label = '📕 :closed_book:'; insertText = '📕'; filterText = ':closed_book:' };
+{ word = ':book:'; label = '📖 :book:'; insertText = '📖'; filterText = ':book:' };
+{ word = ':open_book:'; label = '📖 :open_book:'; insertText = '📖'; filterText = ':open_book:' };
+{ word = ':green_book:'; label = '📗 :green_book:'; insertText = '📗'; filterText = ':green_book:' };
+{ word = ':blue_book:'; label = '📘 :blue_book:'; insertText = '📘'; filterText = ':blue_book:' };
+{ word = ':orange_book:'; label = '📙 :orange_book:'; insertText = '📙'; filterText = ':orange_book:' };
+{ word = ':books:'; label = '📚 :books:'; insertText = '📚'; filterText = ':books:' };
+{ word = ':name_badge:'; label = '📛 :name_badge:'; insertText = '📛'; filterText = ':name_badge:' };
+{ word = ':scroll:'; label = '📜 :scroll:'; insertText = '📜'; filterText = ':scroll:' };
+{ word = ':memo:'; label = '📝 :memo:'; insertText = '📝'; filterText = ':memo:' };
+{ word = ':pencil:'; label = '📝 :pencil:'; insertText = '📝'; filterText = ':pencil:' };
+{ word = ':telephone_receiver:'; label = '📞 :telephone_receiver:'; insertText = '📞'; filterText = ':telephone_receiver:' };
+{ word = ':pager:'; label = '📟 :pager:'; insertText = '📟'; filterText = ':pager:' };
+{ word = ':fax:'; label = '📠 :fax:'; insertText = '📠'; filterText = ':fax:' };
+{ word = ':satellite_antenna:'; label = '📡 :satellite_antenna:'; insertText = '📡'; filterText = ':satellite_antenna:' };
+{ word = ':loudspeaker:'; label = '📢 :loudspeaker:'; insertText = '📢'; filterText = ':loudspeaker:' };
+{ word = ':mega:'; label = '📣 :mega:'; insertText = '📣'; filterText = ':mega:' };
+{ word = ':outbox_tray:'; label = '📤 :outbox_tray:'; insertText = '📤'; filterText = ':outbox_tray:' };
+{ word = ':inbox_tray:'; label = '📥 :inbox_tray:'; insertText = '📥'; filterText = ':inbox_tray:' };
+{ word = ':package:'; label = '📦 :package:'; insertText = '📦'; filterText = ':package:' };
+{ word = ':e-mail:'; label = '📧 :e-mail:'; insertText = '📧'; filterText = ':e-mail:' };
+{ word = ':incoming_envelope:'; label = '📨 :incoming_envelope:'; insertText = '📨'; filterText = ':incoming_envelope:' };
+{ word = ':envelope_with_arrow:'; label = '📩 :envelope_with_arrow:'; insertText = '📩'; filterText = ':envelope_with_arrow:' };
+{ word = ':mailbox_closed:'; label = '📪 :mailbox_closed:'; insertText = '📪'; filterText = ':mailbox_closed:' };
+{ word = ':mailbox:'; label = '📫 :mailbox:'; insertText = '📫'; filterText = ':mailbox:' };
+{ word = ':mailbox_with_mail:'; label = '📬 :mailbox_with_mail:'; insertText = '📬'; filterText = ':mailbox_with_mail:' };
+{ word = ':mailbox_with_no_mail:'; label = '📭 :mailbox_with_no_mail:'; insertText = '📭'; filterText = ':mailbox_with_no_mail:' };
+{ word = ':postbox:'; label = '📮 :postbox:'; insertText = '📮'; filterText = ':postbox:' };
+{ word = ':postal_horn:'; label = '📯 :postal_horn:'; insertText = '📯'; filterText = ':postal_horn:' };
+{ word = ':newspaper:'; label = '📰 :newspaper:'; insertText = '📰'; filterText = ':newspaper:' };
+{ word = ':iphone:'; label = '📱 :iphone:'; insertText = '📱'; filterText = ':iphone:' };
+{ word = ':calling:'; label = '📲 :calling:'; insertText = '📲'; filterText = ':calling:' };
+{ word = ':vibration_mode:'; label = '📳 :vibration_mode:'; insertText = '📳'; filterText = ':vibration_mode:' };
+{ word = ':mobile_phone_off:'; label = '📴 :mobile_phone_off:'; insertText = '📴'; filterText = ':mobile_phone_off:' };
+{ word = ':no_mobile_phones:'; label = '📵 :no_mobile_phones:'; insertText = '📵'; filterText = ':no_mobile_phones:' };
+{ word = ':signal_strength:'; label = '📶 :signal_strength:'; insertText = '📶'; filterText = ':signal_strength:' };
+{ word = ':camera:'; label = '📷 :camera:'; insertText = '📷'; filterText = ':camera:' };
+{ word = ':camera_with_flash:'; label = '📸 :camera_with_flash:'; insertText = '📸'; filterText = ':camera_with_flash:' };
+{ word = ':video_camera:'; label = '📹 :video_camera:'; insertText = '📹'; filterText = ':video_camera:' };
+{ word = ':tv:'; label = '📺 :tv:'; insertText = '📺'; filterText = ':tv:' };
+{ word = ':radio:'; label = '📻 :radio:'; insertText = '📻'; filterText = ':radio:' };
+{ word = ':vhs:'; label = '📼 :vhs:'; insertText = '📼'; filterText = ':vhs:' };
+{ word = ':film_projector:'; label = '📽️ :film_projector:'; insertText = '📽️'; filterText = ':film_projector:' };
+{ word = ':prayer_beads:'; label = '📿 :prayer_beads:'; insertText = '📿'; filterText = ':prayer_beads:' };
+{ word = ':twisted_rightwards_arrows:'; label = '🔀 :twisted_rightwards_arrows:'; insertText = '🔀'; filterText = ':twisted_rightwards_arrows:' };
+{ word = ':repeat:'; label = '🔁 :repeat:'; insertText = '🔁'; filterText = ':repeat:' };
+{ word = ':repeat_one:'; label = '🔂 :repeat_one:'; insertText = '🔂'; filterText = ':repeat_one:' };
+{ word = ':arrows_clockwise:'; label = '🔃 :arrows_clockwise:'; insertText = '🔃'; filterText = ':arrows_clockwise:' };
+{ word = ':arrows_counterclockwise:'; label = '🔄 :arrows_counterclockwise:'; insertText = '🔄'; filterText = ':arrows_counterclockwise:' };
+{ word = ':low_brightness:'; label = '🔅 :low_brightness:'; insertText = '🔅'; filterText = ':low_brightness:' };
+{ word = ':high_brightness:'; label = '🔆 :high_brightness:'; insertText = '🔆'; filterText = ':high_brightness:' };
+{ word = ':mute:'; label = '🔇 :mute:'; insertText = '🔇'; filterText = ':mute:' };
+{ word = ':speaker:'; label = '🔈 :speaker:'; insertText = '🔈'; filterText = ':speaker:' };
+{ word = ':sound:'; label = '🔉 :sound:'; insertText = '🔉'; filterText = ':sound:' };
+{ word = ':loud_sound:'; label = '🔊 :loud_sound:'; insertText = '🔊'; filterText = ':loud_sound:' };
+{ word = ':battery:'; label = '🔋 :battery:'; insertText = '🔋'; filterText = ':battery:' };
+{ word = ':electric_plug:'; label = '🔌 :electric_plug:'; insertText = '🔌'; filterText = ':electric_plug:' };
+{ word = ':mag:'; label = '🔍 :mag:'; insertText = '🔍'; filterText = ':mag:' };
+{ word = ':mag_right:'; label = '🔎 :mag_right:'; insertText = '🔎'; filterText = ':mag_right:' };
+{ word = ':lock_with_ink_pen:'; label = '🔏 :lock_with_ink_pen:'; insertText = '🔏'; filterText = ':lock_with_ink_pen:' };
+{ word = ':closed_lock_with_key:'; label = '🔐 :closed_lock_with_key:'; insertText = '🔐'; filterText = ':closed_lock_with_key:' };
+{ word = ':key:'; label = '🔑 :key:'; insertText = '🔑'; filterText = ':key:' };
+{ word = ':lock:'; label = '🔒 :lock:'; insertText = '🔒'; filterText = ':lock:' };
+{ word = ':unlock:'; label = '🔓 :unlock:'; insertText = '🔓'; filterText = ':unlock:' };
+{ word = ':bell:'; label = '🔔 :bell:'; insertText = '🔔'; filterText = ':bell:' };
+{ word = ':no_bell:'; label = '🔕 :no_bell:'; insertText = '🔕'; filterText = ':no_bell:' };
+{ word = ':bookmark:'; label = '🔖 :bookmark:'; insertText = '🔖'; filterText = ':bookmark:' };
+{ word = ':link:'; label = '🔗 :link:'; insertText = '🔗'; filterText = ':link:' };
+{ word = ':radio_button:'; label = '🔘 :radio_button:'; insertText = '🔘'; filterText = ':radio_button:' };
+{ word = ':back:'; label = '🔙 :back:'; insertText = '🔙'; filterText = ':back:' };
+{ word = ':end:'; label = '🔚 :end:'; insertText = '🔚'; filterText = ':end:' };
+{ word = ':on:'; label = '🔛 :on:'; insertText = '🔛'; filterText = ':on:' };
+{ word = ':soon:'; label = '🔜 :soon:'; insertText = '🔜'; filterText = ':soon:' };
+{ word = ':top:'; label = '🔝 :top:'; insertText = '🔝'; filterText = ':top:' };
+{ word = ':underage:'; label = '🔞 :underage:'; insertText = '🔞'; filterText = ':underage:' };
+{ word = ':keycap_ten:'; label = '🔟 :keycap_ten:'; insertText = '🔟'; filterText = ':keycap_ten:' };
+{ word = ':capital_abcd:'; label = '🔠 :capital_abcd:'; insertText = '🔠'; filterText = ':capital_abcd:' };
+{ word = ':abcd:'; label = '🔡 :abcd:'; insertText = '🔡'; filterText = ':abcd:' };
+{ word = ':1234:'; label = '🔢 :1234:'; insertText = '🔢'; filterText = ':1234:' };
+{ word = ':symbols:'; label = '🔣 :symbols:'; insertText = '🔣'; filterText = ':symbols:' };
+{ word = ':abc:'; label = '🔤 :abc:'; insertText = '🔤'; filterText = ':abc:' };
+{ word = ':fire:'; label = '🔥 :fire:'; insertText = '🔥'; filterText = ':fire:' };
+{ word = ':flashlight:'; label = '🔦 :flashlight:'; insertText = '🔦'; filterText = ':flashlight:' };
+{ word = ':wrench:'; label = '🔧 :wrench:'; insertText = '🔧'; filterText = ':wrench:' };
+{ word = ':hammer:'; label = '🔨 :hammer:'; insertText = '🔨'; filterText = ':hammer:' };
+{ word = ':nut_and_bolt:'; label = '🔩 :nut_and_bolt:'; insertText = '🔩'; filterText = ':nut_and_bolt:' };
+{ word = ':hocho:'; label = '🔪 :hocho:'; insertText = '🔪'; filterText = ':hocho:' };
+{ word = ':knife:'; label = '🔪 :knife:'; insertText = '🔪'; filterText = ':knife:' };
+{ word = ':gun:'; label = '🔫 :gun:'; insertText = '🔫'; filterText = ':gun:' };
+{ word = ':microscope:'; label = '🔬 :microscope:'; insertText = '🔬'; filterText = ':microscope:' };
+{ word = ':telescope:'; label = '🔭 :telescope:'; insertText = '🔭'; filterText = ':telescope:' };
+{ word = ':crystal_ball:'; label = '🔮 :crystal_ball:'; insertText = '🔮'; filterText = ':crystal_ball:' };
+{ word = ':six_pointed_star:'; label = '🔯 :six_pointed_star:'; insertText = '🔯'; filterText = ':six_pointed_star:' };
+{ word = ':beginner:'; label = '🔰 :beginner:'; insertText = '🔰'; filterText = ':beginner:' };
+{ word = ':trident:'; label = '🔱 :trident:'; insertText = '🔱'; filterText = ':trident:' };
+{ word = ':black_square_button:'; label = '🔲 :black_square_button:'; insertText = '🔲'; filterText = ':black_square_button:' };
+{ word = ':white_square_button:'; label = '🔳 :white_square_button:'; insertText = '🔳'; filterText = ':white_square_button:' };
+{ word = ':red_circle:'; label = '🔴 :red_circle:'; insertText = '🔴'; filterText = ':red_circle:' };
+{ word = ':large_blue_circle:'; label = '🔵 :large_blue_circle:'; insertText = '🔵'; filterText = ':large_blue_circle:' };
+{ word = ':large_orange_diamond:'; label = '🔶 :large_orange_diamond:'; insertText = '🔶'; filterText = ':large_orange_diamond:' };
+{ word = ':large_blue_diamond:'; label = '🔷 :large_blue_diamond:'; insertText = '🔷'; filterText = ':large_blue_diamond:' };
+{ word = ':small_orange_diamond:'; label = '🔸 :small_orange_diamond:'; insertText = '🔸'; filterText = ':small_orange_diamond:' };
+{ word = ':small_blue_diamond:'; label = '🔹 :small_blue_diamond:'; insertText = '🔹'; filterText = ':small_blue_diamond:' };
+{ word = ':small_red_triangle:'; label = '🔺 :small_red_triangle:'; insertText = '🔺'; filterText = ':small_red_triangle:' };
+{ word = ':small_red_triangle_down:'; label = '🔻 :small_red_triangle_down:'; insertText = '🔻'; filterText = ':small_red_triangle_down:' };
+{ word = ':arrow_up_small:'; label = '🔼 :arrow_up_small:'; insertText = '🔼'; filterText = ':arrow_up_small:' };
+{ word = ':arrow_down_small:'; label = '🔽 :arrow_down_small:'; insertText = '🔽'; filterText = ':arrow_down_small:' };
+{ word = ':om_symbol:'; label = '🕉️ :om_symbol:'; insertText = '🕉️'; filterText = ':om_symbol:' };
+{ word = ':dove_of_peace:'; label = '🕊️ :dove_of_peace:'; insertText = '🕊️'; filterText = ':dove_of_peace:' };
+{ word = ':kaaba:'; label = '🕋 :kaaba:'; insertText = '🕋'; filterText = ':kaaba:' };
+{ word = ':mosque:'; label = '🕌 :mosque:'; insertText = '🕌'; filterText = ':mosque:' };
+{ word = ':synagogue:'; label = '🕍 :synagogue:'; insertText = '🕍'; filterText = ':synagogue:' };
+{ word = ':menorah_with_nine_branches:'; label = '🕎 :menorah_with_nine_branches:'; insertText = '🕎'; filterText = ':menorah_with_nine_branches:' };
+{ word = ':clock1:'; label = '🕐 :clock1:'; insertText = '🕐'; filterText = ':clock1:' };
+{ word = ':clock2:'; label = '🕑 :clock2:'; insertText = '🕑'; filterText = ':clock2:' };
+{ word = ':clock3:'; label = '🕒 :clock3:'; insertText = '🕒'; filterText = ':clock3:' };
+{ word = ':clock4:'; label = '🕓 :clock4:'; insertText = '🕓'; filterText = ':clock4:' };
+{ word = ':clock5:'; label = '🕔 :clock5:'; insertText = '🕔'; filterText = ':clock5:' };
+{ word = ':clock6:'; label = '🕕 :clock6:'; insertText = '🕕'; filterText = ':clock6:' };
+{ word = ':clock7:'; label = '🕖 :clock7:'; insertText = '🕖'; filterText = ':clock7:' };
+{ word = ':clock8:'; label = '🕗 :clock8:'; insertText = '🕗'; filterText = ':clock8:' };
+{ word = ':clock9:'; label = '🕘 :clock9:'; insertText = '🕘'; filterText = ':clock9:' };
+{ word = ':clock10:'; label = '🕙 :clock10:'; insertText = '🕙'; filterText = ':clock10:' };
+{ word = ':clock11:'; label = '🕚 :clock11:'; insertText = '🕚'; filterText = ':clock11:' };
+{ word = ':clock12:'; label = '🕛 :clock12:'; insertText = '🕛'; filterText = ':clock12:' };
+{ word = ':clock130:'; label = '🕜 :clock130:'; insertText = '🕜'; filterText = ':clock130:' };
+{ word = ':clock230:'; label = '🕝 :clock230:'; insertText = '🕝'; filterText = ':clock230:' };
+{ word = ':clock330:'; label = '🕞 :clock330:'; insertText = '🕞'; filterText = ':clock330:' };
+{ word = ':clock430:'; label = '🕟 :clock430:'; insertText = '🕟'; filterText = ':clock430:' };
+{ word = ':clock530:'; label = '🕠 :clock530:'; insertText = '🕠'; filterText = ':clock530:' };
+{ word = ':clock630:'; label = '🕡 :clock630:'; insertText = '🕡'; filterText = ':clock630:' };
+{ word = ':clock730:'; label = '🕢 :clock730:'; insertText = '🕢'; filterText = ':clock730:' };
+{ word = ':clock830:'; label = '🕣 :clock830:'; insertText = '🕣'; filterText = ':clock830:' };
+{ word = ':clock930:'; label = '🕤 :clock930:'; insertText = '🕤'; filterText = ':clock930:' };
+{ word = ':clock1030:'; label = '🕥 :clock1030:'; insertText = '🕥'; filterText = ':clock1030:' };
+{ word = ':clock1130:'; label = '🕦 :clock1130:'; insertText = '🕦'; filterText = ':clock1130:' };
+{ word = ':clock1230:'; label = '🕧 :clock1230:'; insertText = '🕧'; filterText = ':clock1230:' };
+{ word = ':candle:'; label = '🕯️ :candle:'; insertText = '🕯️'; filterText = ':candle:' };
+{ word = ':mantelpiece_clock:'; label = '🕰️ :mantelpiece_clock:'; insertText = '🕰️'; filterText = ':mantelpiece_clock:' };
+{ word = ':hole:'; label = '🕳️ :hole:'; insertText = '🕳️'; filterText = ':hole:' };
+{ word = ':man_in_business_suit_levitating:'; label = '🕴️ :man_in_business_suit_levitating:'; insertText = '🕴️'; filterText = ':man_in_business_suit_levitating:' };
+{ word = ':sleuth_or_spy:'; label = '🕵️ :sleuth_or_spy:'; insertText = '🕵️'; filterText = ':sleuth_or_spy:' };
+{ word = ':dark_sunglasses:'; label = '🕶️ :dark_sunglasses:'; insertText = '🕶️'; filterText = ':dark_sunglasses:' };
+{ word = ':spider:'; label = '🕷️ :spider:'; insertText = '🕷️'; filterText = ':spider:' };
+{ word = ':spider_web:'; label = '🕸️ :spider_web:'; insertText = '🕸️'; filterText = ':spider_web:' };
+{ word = ':joystick:'; label = '🕹️ :joystick:'; insertText = '🕹️'; filterText = ':joystick:' };
+{ word = ':man_dancing:'; label = '🕺 :man_dancing:'; insertText = '🕺'; filterText = ':man_dancing:' };
+{ word = ':linked_paperclips:'; label = '🖇️ :linked_paperclips:'; insertText = '🖇️'; filterText = ':linked_paperclips:' };
+{ word = ':lower_left_ballpoint_pen:'; label = '🖊️ :lower_left_ballpoint_pen:'; insertText = '🖊️'; filterText = ':lower_left_ballpoint_pen:' };
+{ word = ':lower_left_fountain_pen:'; label = '🖋️ :lower_left_fountain_pen:'; insertText = '🖋️'; filterText = ':lower_left_fountain_pen:' };
+{ word = ':lower_left_paintbrush:'; label = '🖌️ :lower_left_paintbrush:'; insertText = '🖌️'; filterText = ':lower_left_paintbrush:' };
+{ word = ':lower_left_crayon:'; label = '🖍️ :lower_left_crayon:'; insertText = '🖍️'; filterText = ':lower_left_crayon:' };
+{ word = ':raised_hand_with_fingers_splayed:'; label = '🖐️ :raised_hand_with_fingers_splayed:'; insertText = '🖐️'; filterText = ':raised_hand_with_fingers_splayed:' };
+{ word = ':middle_finger:'; label = '🖕 :middle_finger:'; insertText = '🖕'; filterText = ':middle_finger:' };
+{ word = ':reversed_hand_with_middle_finger_extended:'; label = '🖕 :reversed_hand_with_middle_finger_extended:'; insertText = '🖕'; filterText = ':reversed_hand_with_middle_finger_extended:' };
+{ word = ':spock-hand:'; label = '🖖 :spock-hand:'; insertText = '🖖'; filterText = ':spock-hand:' };
+{ word = ':black_heart:'; label = '🖤 :black_heart:'; insertText = '🖤'; filterText = ':black_heart:' };
+{ word = ':desktop_computer:'; label = '🖥️ :desktop_computer:'; insertText = '🖥️'; filterText = ':desktop_computer:' };
+{ word = ':printer:'; label = '🖨️ :printer:'; insertText = '🖨️'; filterText = ':printer:' };
+{ word = ':three_button_mouse:'; label = '🖱️ :three_button_mouse:'; insertText = '🖱️'; filterText = ':three_button_mouse:' };
+{ word = ':trackball:'; label = '🖲️ :trackball:'; insertText = '🖲️'; filterText = ':trackball:' };
+{ word = ':frame_with_picture:'; label = '🖼️ :frame_with_picture:'; insertText = '🖼️'; filterText = ':frame_with_picture:' };
+{ word = ':card_index_dividers:'; label = '🗂️ :card_index_dividers:'; insertText = '🗂️'; filterText = ':card_index_dividers:' };
+{ word = ':card_file_box:'; label = '🗃️ :card_file_box:'; insertText = '🗃️'; filterText = ':card_file_box:' };
+{ word = ':file_cabinet:'; label = '🗄️ :file_cabinet:'; insertText = '🗄️'; filterText = ':file_cabinet:' };
+{ word = ':wastebasket:'; label = '🗑️ :wastebasket:'; insertText = '🗑️'; filterText = ':wastebasket:' };
+{ word = ':spiral_note_pad:'; label = '🗒️ :spiral_note_pad:'; insertText = '🗒️'; filterText = ':spiral_note_pad:' };
+{ word = ':spiral_calendar_pad:'; label = '🗓️ :spiral_calendar_pad:'; insertText = '🗓️'; filterText = ':spiral_calendar_pad:' };
+{ word = ':compression:'; label = '🗜️ :compression:'; insertText = '🗜️'; filterText = ':compression:' };
+{ word = ':old_key:'; label = '🗝️ :old_key:'; insertText = '🗝️'; filterText = ':old_key:' };
+{ word = ':rolled_up_newspaper:'; label = '🗞️ :rolled_up_newspaper:'; insertText = '🗞️'; filterText = ':rolled_up_newspaper:' };
+{ word = ':dagger_knife:'; label = '🗡️ :dagger_knife:'; insertText = '🗡️'; filterText = ':dagger_knife:' };
+{ word = ':speaking_head_in_silhouette:'; label = '🗣️ :speaking_head_in_silhouette:'; insertText = '🗣️'; filterText = ':speaking_head_in_silhouette:' };
+{ word = ':left_speech_bubble:'; label = '🗨️ :left_speech_bubble:'; insertText = '🗨️'; filterText = ':left_speech_bubble:' };
+{ word = ':right_anger_bubble:'; label = '🗯️ :right_anger_bubble:'; insertText = '🗯️'; filterText = ':right_anger_bubble:' };
+{ word = ':ballot_box_with_ballot:'; label = '🗳️ :ballot_box_with_ballot:'; insertText = '🗳️'; filterText = ':ballot_box_with_ballot:' };
+{ word = ':world_map:'; label = '🗺️ :world_map:'; insertText = '🗺️'; filterText = ':world_map:' };
+{ word = ':mount_fuji:'; label = '🗻 :mount_fuji:'; insertText = '🗻'; filterText = ':mount_fuji:' };
+{ word = ':tokyo_tower:'; label = '🗼 :tokyo_tower:'; insertText = '🗼'; filterText = ':tokyo_tower:' };
+{ word = ':statue_of_liberty:'; label = '🗽 :statue_of_liberty:'; insertText = '🗽'; filterText = ':statue_of_liberty:' };
+{ word = ':japan:'; label = '🗾 :japan:'; insertText = '🗾'; filterText = ':japan:' };
+{ word = ':moyai:'; label = '🗿 :moyai:'; insertText = '🗿'; filterText = ':moyai:' };
+{ word = ':grinning:'; label = '😀 :grinning:'; insertText = '😀'; filterText = ':grinning:' };
+{ word = ':grin:'; label = '😁 :grin:'; insertText = '😁'; filterText = ':grin:' };
+{ word = ':joy:'; label = '😂 :joy:'; insertText = '😂'; filterText = ':joy:' };
+{ word = ':smiley:'; label = '😃 :smiley:'; insertText = '😃'; filterText = ':smiley:' };
+{ word = ':smile:'; label = '😄 :smile:'; insertText = '😄'; filterText = ':smile:' };
+{ word = ':sweat_smile:'; label = '😅 :sweat_smile:'; insertText = '😅'; filterText = ':sweat_smile:' };
+{ word = ':laughing:'; label = '😆 :laughing:'; insertText = '😆'; filterText = ':laughing:' };
+{ word = ':satisfied:'; label = '😆 :satisfied:'; insertText = '😆'; filterText = ':satisfied:' };
+{ word = ':innocent:'; label = '😇 :innocent:'; insertText = '😇'; filterText = ':innocent:' };
+{ word = ':smiling_imp:'; label = '😈 :smiling_imp:'; insertText = '😈'; filterText = ':smiling_imp:' };
+{ word = ':wink:'; label = '😉 :wink:'; insertText = '😉'; filterText = ':wink:' };
+{ word = ':blush:'; label = '😊 :blush:'; insertText = '😊'; filterText = ':blush:' };
+{ word = ':yum:'; label = '😋 :yum:'; insertText = '😋'; filterText = ':yum:' };
+{ word = ':relieved:'; label = '😌 :relieved:'; insertText = '😌'; filterText = ':relieved:' };
+{ word = ':heart_eyes:'; label = '😍 :heart_eyes:'; insertText = '😍'; filterText = ':heart_eyes:' };
+{ word = ':sunglasses:'; label = '😎 :sunglasses:'; insertText = '😎'; filterText = ':sunglasses:' };
+{ word = ':smirk:'; label = '😏 :smirk:'; insertText = '😏'; filterText = ':smirk:' };
+{ word = ':neutral_face:'; label = '😐 :neutral_face:'; insertText = '😐'; filterText = ':neutral_face:' };
+{ word = ':expressionless:'; label = '😑 :expressionless:'; insertText = '😑'; filterText = ':expressionless:' };
+{ word = ':unamused:'; label = '😒 :unamused:'; insertText = '😒'; filterText = ':unamused:' };
+{ word = ':sweat:'; label = '😓 :sweat:'; insertText = '😓'; filterText = ':sweat:' };
+{ word = ':pensive:'; label = '😔 :pensive:'; insertText = '😔'; filterText = ':pensive:' };
+{ word = ':confused:'; label = '😕 :confused:'; insertText = '😕'; filterText = ':confused:' };
+{ word = ':confounded:'; label = '😖 :confounded:'; insertText = '😖'; filterText = ':confounded:' };
+{ word = ':kissing:'; label = '😗 :kissing:'; insertText = '😗'; filterText = ':kissing:' };
+{ word = ':kissing_heart:'; label = '😘 :kissing_heart:'; insertText = '😘'; filterText = ':kissing_heart:' };
+{ word = ':kissing_smiling_eyes:'; label = '😙 :kissing_smiling_eyes:'; insertText = '😙'; filterText = ':kissing_smiling_eyes:' };
+{ word = ':kissing_closed_eyes:'; label = '😚 :kissing_closed_eyes:'; insertText = '😚'; filterText = ':kissing_closed_eyes:' };
+{ word = ':stuck_out_tongue:'; label = '😛 :stuck_out_tongue:'; insertText = '😛'; filterText = ':stuck_out_tongue:' };
+{ word = ':stuck_out_tongue_winking_eye:'; label = '😜 :stuck_out_tongue_winking_eye:'; insertText = '😜'; filterText = ':stuck_out_tongue_winking_eye:' };
+{ word = ':stuck_out_tongue_closed_eyes:'; label = '😝 :stuck_out_tongue_closed_eyes:'; insertText = '😝'; filterText = ':stuck_out_tongue_closed_eyes:' };
+{ word = ':disappointed:'; label = '😞 :disappointed:'; insertText = '😞'; filterText = ':disappointed:' };
+{ word = ':worried:'; label = '😟 :worried:'; insertText = '😟'; filterText = ':worried:' };
+{ word = ':angry:'; label = '😠 :angry:'; insertText = '😠'; filterText = ':angry:' };
+{ word = ':rage:'; label = '😡 :rage:'; insertText = '😡'; filterText = ':rage:' };
+{ word = ':cry:'; label = '😢 :cry:'; insertText = '😢'; filterText = ':cry:' };
+{ word = ':persevere:'; label = '😣 :persevere:'; insertText = '😣'; filterText = ':persevere:' };
+{ word = ':triumph:'; label = '😤 :triumph:'; insertText = '😤'; filterText = ':triumph:' };
+{ word = ':disappointed_relieved:'; label = '😥 :disappointed_relieved:'; insertText = '😥'; filterText = ':disappointed_relieved:' };
+{ word = ':frowning:'; label = '😦 :frowning:'; insertText = '😦'; filterText = ':frowning:' };
+{ word = ':anguished:'; label = '😧 :anguished:'; insertText = '😧'; filterText = ':anguished:' };
+{ word = ':fearful:'; label = '😨 :fearful:'; insertText = '😨'; filterText = ':fearful:' };
+{ word = ':weary:'; label = '😩 :weary:'; insertText = '😩'; filterText = ':weary:' };
+{ word = ':sleepy:'; label = '😪 :sleepy:'; insertText = '😪'; filterText = ':sleepy:' };
+{ word = ':tired_face:'; label = '😫 :tired_face:'; insertText = '😫'; filterText = ':tired_face:' };
+{ word = ':grimacing:'; label = '😬 :grimacing:'; insertText = '😬'; filterText = ':grimacing:' };
+{ word = ':sob:'; label = '😭 :sob:'; insertText = '😭'; filterText = ':sob:' };
+{ word = ':open_mouth:'; label = '😮 :open_mouth:'; insertText = '😮'; filterText = ':open_mouth:' };
+{ word = ':hushed:'; label = '😯 :hushed:'; insertText = '😯'; filterText = ':hushed:' };
+{ word = ':cold_sweat:'; label = '😰 :cold_sweat:'; insertText = '😰'; filterText = ':cold_sweat:' };
+{ word = ':scream:'; label = '😱 :scream:'; insertText = '😱'; filterText = ':scream:' };
+{ word = ':astonished:'; label = '😲 :astonished:'; insertText = '😲'; filterText = ':astonished:' };
+{ word = ':flushed:'; label = '😳 :flushed:'; insertText = '😳'; filterText = ':flushed:' };
+{ word = ':sleeping:'; label = '😴 :sleeping:'; insertText = '😴'; filterText = ':sleeping:' };
+{ word = ':dizzy_face:'; label = '😵 :dizzy_face:'; insertText = '😵'; filterText = ':dizzy_face:' };
+{ word = ':no_mouth:'; label = '😶 :no_mouth:'; insertText = '😶'; filterText = ':no_mouth:' };
+{ word = ':mask:'; label = '😷 :mask:'; insertText = '😷'; filterText = ':mask:' };
+{ word = ':smile_cat:'; label = '😸 :smile_cat:'; insertText = '😸'; filterText = ':smile_cat:' };
+{ word = ':joy_cat:'; label = '😹 :joy_cat:'; insertText = '😹'; filterText = ':joy_cat:' };
+{ word = ':smiley_cat:'; label = '😺 :smiley_cat:'; insertText = '😺'; filterText = ':smiley_cat:' };
+{ word = ':heart_eyes_cat:'; label = '😻 :heart_eyes_cat:'; insertText = '😻'; filterText = ':heart_eyes_cat:' };
+{ word = ':smirk_cat:'; label = '😼 :smirk_cat:'; insertText = '😼'; filterText = ':smirk_cat:' };
+{ word = ':kissing_cat:'; label = '😽 :kissing_cat:'; insertText = '😽'; filterText = ':kissing_cat:' };
+{ word = ':pouting_cat:'; label = '😾 :pouting_cat:'; insertText = '😾'; filterText = ':pouting_cat:' };
+{ word = ':crying_cat_face:'; label = '😿 :crying_cat_face:'; insertText = '😿'; filterText = ':crying_cat_face:' };
+{ word = ':scream_cat:'; label = '🙀 :scream_cat:'; insertText = '🙀'; filterText = ':scream_cat:' };
+{ word = ':slightly_frowning_face:'; label = '🙁 :slightly_frowning_face:'; insertText = '🙁'; filterText = ':slightly_frowning_face:' };
+{ word = ':slightly_smiling_face:'; label = '🙂 :slightly_smiling_face:'; insertText = '🙂'; filterText = ':slightly_smiling_face:' };
+{ word = ':upside_down_face:'; label = '🙃 :upside_down_face:'; insertText = '🙃'; filterText = ':upside_down_face:' };
+{ word = ':face_with_rolling_eyes:'; label = '🙄 :face_with_rolling_eyes:'; insertText = '🙄'; filterText = ':face_with_rolling_eyes:' };
+{ word = ':no_good:'; label = '🙅 :no_good:'; insertText = '🙅'; filterText = ':no_good:' };
+{ word = ':ok_woman:'; label = '🙆 :ok_woman:'; insertText = '🙆'; filterText = ':ok_woman:' };
+{ word = ':bow:'; label = '🙇 :bow:'; insertText = '🙇'; filterText = ':bow:' };
+{ word = ':see_no_evil:'; label = '🙈 :see_no_evil:'; insertText = '🙈'; filterText = ':see_no_evil:' };
+{ word = ':hear_no_evil:'; label = '🙉 :hear_no_evil:'; insertText = '🙉'; filterText = ':hear_no_evil:' };
+{ word = ':speak_no_evil:'; label = '🙊 :speak_no_evil:'; insertText = '🙊'; filterText = ':speak_no_evil:' };
+{ word = ':raising_hand:'; label = '🙋 :raising_hand:'; insertText = '🙋'; filterText = ':raising_hand:' };
+{ word = ':raised_hands:'; label = '🙌 :raised_hands:'; insertText = '🙌'; filterText = ':raised_hands:' };
+{ word = ':person_frowning:'; label = '🙍 :person_frowning:'; insertText = '🙍'; filterText = ':person_frowning:' };
+{ word = ':person_with_pouting_face:'; label = '🙎 :person_with_pouting_face:'; insertText = '🙎'; filterText = ':person_with_pouting_face:' };
+{ word = ':pray:'; label = '🙏 :pray:'; insertText = '🙏'; filterText = ':pray:' };
+{ word = ':rocket:'; label = '🚀 :rocket:'; insertText = '🚀'; filterText = ':rocket:' };
+{ word = ':helicopter:'; label = '🚁 :helicopter:'; insertText = '🚁'; filterText = ':helicopter:' };
+{ word = ':steam_locomotive:'; label = '🚂 :steam_locomotive:'; insertText = '🚂'; filterText = ':steam_locomotive:' };
+{ word = ':railway_car:'; label = '🚃 :railway_car:'; insertText = '🚃'; filterText = ':railway_car:' };
+{ word = ':bullettrain_side:'; label = '🚄 :bullettrain_side:'; insertText = '🚄'; filterText = ':bullettrain_side:' };
+{ word = ':bullettrain_front:'; label = '🚅 :bullettrain_front:'; insertText = '🚅'; filterText = ':bullettrain_front:' };
+{ word = ':train2:'; label = '🚆 :train2:'; insertText = '🚆'; filterText = ':train2:' };
+{ word = ':metro:'; label = '🚇 :metro:'; insertText = '🚇'; filterText = ':metro:' };
+{ word = ':light_rail:'; label = '🚈 :light_rail:'; insertText = '🚈'; filterText = ':light_rail:' };
+{ word = ':station:'; label = '🚉 :station:'; insertText = '🚉'; filterText = ':station:' };
+{ word = ':tram:'; label = '🚊 :tram:'; insertText = '🚊'; filterText = ':tram:' };
+{ word = ':train:'; label = '🚋 :train:'; insertText = '🚋'; filterText = ':train:' };
+{ word = ':bus:'; label = '🚌 :bus:'; insertText = '🚌'; filterText = ':bus:' };
+{ word = ':oncoming_bus:'; label = '🚍 :oncoming_bus:'; insertText = '🚍'; filterText = ':oncoming_bus:' };
+{ word = ':trolleybus:'; label = '🚎 :trolleybus:'; insertText = '🚎'; filterText = ':trolleybus:' };
+{ word = ':busstop:'; label = '🚏 :busstop:'; insertText = '🚏'; filterText = ':busstop:' };
+{ word = ':minibus:'; label = '🚐 :minibus:'; insertText = '🚐'; filterText = ':minibus:' };
+{ word = ':ambulance:'; label = '🚑 :ambulance:'; insertText = '🚑'; filterText = ':ambulance:' };
+{ word = ':fire_engine:'; label = '🚒 :fire_engine:'; insertText = '🚒'; filterText = ':fire_engine:' };
+{ word = ':police_car:'; label = '🚓 :police_car:'; insertText = '🚓'; filterText = ':police_car:' };
+{ word = ':oncoming_police_car:'; label = '🚔 :oncoming_police_car:'; insertText = '🚔'; filterText = ':oncoming_police_car:' };
+{ word = ':taxi:'; label = '🚕 :taxi:'; insertText = '🚕'; filterText = ':taxi:' };
+{ word = ':oncoming_taxi:'; label = '🚖 :oncoming_taxi:'; insertText = '🚖'; filterText = ':oncoming_taxi:' };
+{ word = ':car:'; label = '🚗 :car:'; insertText = '🚗'; filterText = ':car:' };
+{ word = ':red_car:'; label = '🚗 :red_car:'; insertText = '🚗'; filterText = ':red_car:' };
+{ word = ':oncoming_automobile:'; label = '🚘 :oncoming_automobile:'; insertText = '🚘'; filterText = ':oncoming_automobile:' };
+{ word = ':blue_car:'; label = '🚙 :blue_car:'; insertText = '🚙'; filterText = ':blue_car:' };
+{ word = ':truck:'; label = '🚚 :truck:'; insertText = '🚚'; filterText = ':truck:' };
+{ word = ':articulated_lorry:'; label = '🚛 :articulated_lorry:'; insertText = '🚛'; filterText = ':articulated_lorry:' };
+{ word = ':tractor:'; label = '🚜 :tractor:'; insertText = '🚜'; filterText = ':tractor:' };
+{ word = ':monorail:'; label = '🚝 :monorail:'; insertText = '🚝'; filterText = ':monorail:' };
+{ word = ':mountain_railway:'; label = '🚞 :mountain_railway:'; insertText = '🚞'; filterText = ':mountain_railway:' };
+{ word = ':suspension_railway:'; label = '🚟 :suspension_railway:'; insertText = '🚟'; filterText = ':suspension_railway:' };
+{ word = ':mountain_cableway:'; label = '🚠 :mountain_cableway:'; insertText = '🚠'; filterText = ':mountain_cableway:' };
+{ word = ':aerial_tramway:'; label = '🚡 :aerial_tramway:'; insertText = '🚡'; filterText = ':aerial_tramway:' };
+{ word = ':ship:'; label = '🚢 :ship:'; insertText = '🚢'; filterText = ':ship:' };
+{ word = ':rowboat:'; label = '🚣 :rowboat:'; insertText = '🚣'; filterText = ':rowboat:' };
+{ word = ':speedboat:'; label = '🚤 :speedboat:'; insertText = '🚤'; filterText = ':speedboat:' };
+{ word = ':traffic_light:'; label = '🚥 :traffic_light:'; insertText = '🚥'; filterText = ':traffic_light:' };
+{ word = ':vertical_traffic_light:'; label = '🚦 :vertical_traffic_light:'; insertText = '🚦'; filterText = ':vertical_traffic_light:' };
+{ word = ':construction:'; label = '🚧 :construction:'; insertText = '🚧'; filterText = ':construction:' };
+{ word = ':rotating_light:'; label = '🚨 :rotating_light:'; insertText = '🚨'; filterText = ':rotating_light:' };
+{ word = ':triangular_flag_on_post:'; label = '🚩 :triangular_flag_on_post:'; insertText = '🚩'; filterText = ':triangular_flag_on_post:' };
+{ word = ':door:'; label = '🚪 :door:'; insertText = '🚪'; filterText = ':door:' };
+{ word = ':no_entry_sign:'; label = '🚫 :no_entry_sign:'; insertText = '🚫'; filterText = ':no_entry_sign:' };
+{ word = ':smoking:'; label = '🚬 :smoking:'; insertText = '🚬'; filterText = ':smoking:' };
+{ word = ':no_smoking:'; label = '🚭 :no_smoking:'; insertText = '🚭'; filterText = ':no_smoking:' };
+{ word = ':put_litter_in_its_place:'; label = '🚮 :put_litter_in_its_place:'; insertText = '🚮'; filterText = ':put_litter_in_its_place:' };
+{ word = ':do_not_litter:'; label = '🚯 :do_not_litter:'; insertText = '🚯'; filterText = ':do_not_litter:' };
+{ word = ':potable_water:'; label = '🚰 :potable_water:'; insertText = '🚰'; filterText = ':potable_water:' };
+{ word = ':non-potable_water:'; label = '🚱 :non-potable_water:'; insertText = '🚱'; filterText = ':non-potable_water:' };
+{ word = ':bike:'; label = '🚲 :bike:'; insertText = '🚲'; filterText = ':bike:' };
+{ word = ':no_bicycles:'; label = '🚳 :no_bicycles:'; insertText = '🚳'; filterText = ':no_bicycles:' };
+{ word = ':bicyclist:'; label = '🚴 :bicyclist:'; insertText = '🚴'; filterText = ':bicyclist:' };
+{ word = ':mountain_bicyclist:'; label = '🚵 :mountain_bicyclist:'; insertText = '🚵'; filterText = ':mountain_bicyclist:' };
+{ word = ':walking:'; label = '🚶 :walking:'; insertText = '🚶'; filterText = ':walking:' };
+{ word = ':no_pedestrians:'; label = '🚷 :no_pedestrians:'; insertText = '🚷'; filterText = ':no_pedestrians:' };
+{ word = ':children_crossing:'; label = '🚸 :children_crossing:'; insertText = '🚸'; filterText = ':children_crossing:' };
+{ word = ':mens:'; label = '🚹 :mens:'; insertText = '🚹'; filterText = ':mens:' };
+{ word = ':womens:'; label = '🚺 :womens:'; insertText = '🚺'; filterText = ':womens:' };
+{ word = ':restroom:'; label = '🚻 :restroom:'; insertText = '🚻'; filterText = ':restroom:' };
+{ word = ':baby_symbol:'; label = '🚼 :baby_symbol:'; insertText = '🚼'; filterText = ':baby_symbol:' };
+{ word = ':toilet:'; label = '🚽 :toilet:'; insertText = '🚽'; filterText = ':toilet:' };
+{ word = ':wc:'; label = '🚾 :wc:'; insertText = '🚾'; filterText = ':wc:' };
+{ word = ':shower:'; label = '🚿 :shower:'; insertText = '🚿'; filterText = ':shower:' };
+{ word = ':bath:'; label = '🛀 :bath:'; insertText = '🛀'; filterText = ':bath:' };
+{ word = ':bathtub:'; label = '🛁 :bathtub:'; insertText = '🛁'; filterText = ':bathtub:' };
+{ word = ':passport_control:'; label = '🛂 :passport_control:'; insertText = '🛂'; filterText = ':passport_control:' };
+{ word = ':customs:'; label = '🛃 :customs:'; insertText = '🛃'; filterText = ':customs:' };
+{ word = ':baggage_claim:'; label = '🛄 :baggage_claim:'; insertText = '🛄'; filterText = ':baggage_claim:' };
+{ word = ':left_luggage:'; label = '🛅 :left_luggage:'; insertText = '🛅'; filterText = ':left_luggage:' };
+{ word = ':couch_and_lamp:'; label = '🛋️ :couch_and_lamp:'; insertText = '🛋️'; filterText = ':couch_and_lamp:' };
+{ word = ':sleeping_accommodation:'; label = '🛌 :sleeping_accommodation:'; insertText = '🛌'; filterText = ':sleeping_accommodation:' };
+{ word = ':shopping_bags:'; label = '🛍️ :shopping_bags:'; insertText = '🛍️'; filterText = ':shopping_bags:' };
+{ word = ':bellhop_bell:'; label = '🛎️ :bellhop_bell:'; insertText = '🛎️'; filterText = ':bellhop_bell:' };
+{ word = ':bed:'; label = '🛏️ :bed:'; insertText = '🛏️'; filterText = ':bed:' };
+{ word = ':place_of_worship:'; label = '🛐 :place_of_worship:'; insertText = '🛐'; filterText = ':place_of_worship:' };
+{ word = ':octagonal_sign:'; label = '🛑 :octagonal_sign:'; insertText = '🛑'; filterText = ':octagonal_sign:' };
+{ word = ':shopping_trolley:'; label = '🛒 :shopping_trolley:'; insertText = '🛒'; filterText = ':shopping_trolley:' };
+{ word = ':hindu_temple:'; label = '🛕 :hindu_temple:'; insertText = '🛕'; filterText = ':hindu_temple:' };
+{ word = ':hut:'; label = '🛖 :hut:'; insertText = '🛖'; filterText = ':hut:' };
+{ word = ':elevator:'; label = '🛗 :elevator:'; insertText = '🛗'; filterText = ':elevator:' };
+{ word = ':wireless:'; label = '🛜 :wireless:'; insertText = '🛜'; filterText = ':wireless:' };
+{ word = ':playground_slide:'; label = '🛝 :playground_slide:'; insertText = '🛝'; filterText = ':playground_slide:' };
+{ word = ':wheel:'; label = '🛞 :wheel:'; insertText = '🛞'; filterText = ':wheel:' };
+{ word = ':ring_buoy:'; label = '🛟 :ring_buoy:'; insertText = '🛟'; filterText = ':ring_buoy:' };
+{ word = ':hammer_and_wrench:'; label = '🛠️ :hammer_and_wrench:'; insertText = '🛠️'; filterText = ':hammer_and_wrench:' };
+{ word = ':shield:'; label = '🛡️ :shield:'; insertText = '🛡️'; filterText = ':shield:' };
+{ word = ':oil_drum:'; label = '🛢️ :oil_drum:'; insertText = '🛢️'; filterText = ':oil_drum:' };
+{ word = ':motorway:'; label = '🛣️ :motorway:'; insertText = '🛣️'; filterText = ':motorway:' };
+{ word = ':railway_track:'; label = '🛤️ :railway_track:'; insertText = '🛤️'; filterText = ':railway_track:' };
+{ word = ':motor_boat:'; label = '🛥️ :motor_boat:'; insertText = '🛥️'; filterText = ':motor_boat:' };
+{ word = ':small_airplane:'; label = '🛩️ :small_airplane:'; insertText = '🛩️'; filterText = ':small_airplane:' };
+{ word = ':airplane_departure:'; label = '🛫 :airplane_departure:'; insertText = '🛫'; filterText = ':airplane_departure:' };
+{ word = ':airplane_arriving:'; label = '🛬 :airplane_arriving:'; insertText = '🛬'; filterText = ':airplane_arriving:' };
+{ word = ':satellite:'; label = '🛰️ :satellite:'; insertText = '🛰️'; filterText = ':satellite:' };
+{ word = ':passenger_ship:'; label = '🛳️ :passenger_ship:'; insertText = '🛳️'; filterText = ':passenger_ship:' };
+{ word = ':scooter:'; label = '🛴 :scooter:'; insertText = '🛴'; filterText = ':scooter:' };
+{ word = ':motor_scooter:'; label = '🛵 :motor_scooter:'; insertText = '🛵'; filterText = ':motor_scooter:' };
+{ word = ':canoe:'; label = '🛶 :canoe:'; insertText = '🛶'; filterText = ':canoe:' };
+{ word = ':sled:'; label = '🛷 :sled:'; insertText = '🛷'; filterText = ':sled:' };
+{ word = ':flying_saucer:'; label = '🛸 :flying_saucer:'; insertText = '🛸'; filterText = ':flying_saucer:' };
+{ word = ':skateboard:'; label = '🛹 :skateboard:'; insertText = '🛹'; filterText = ':skateboard:' };
+{ word = ':auto_rickshaw:'; label = '🛺 :auto_rickshaw:'; insertText = '🛺'; filterText = ':auto_rickshaw:' };
+{ word = ':pickup_truck:'; label = '🛻 :pickup_truck:'; insertText = '🛻'; filterText = ':pickup_truck:' };
+{ word = ':roller_skate:'; label = '🛼 :roller_skate:'; insertText = '🛼'; filterText = ':roller_skate:' };
+{ word = ':large_orange_circle:'; label = '🟠 :large_orange_circle:'; insertText = '🟠'; filterText = ':large_orange_circle:' };
+{ word = ':large_yellow_circle:'; label = '🟡 :large_yellow_circle:'; insertText = '🟡'; filterText = ':large_yellow_circle:' };
+{ word = ':large_green_circle:'; label = '🟢 :large_green_circle:'; insertText = '🟢'; filterText = ':large_green_circle:' };
+{ word = ':large_purple_circle:'; label = '🟣 :large_purple_circle:'; insertText = '🟣'; filterText = ':large_purple_circle:' };
+{ word = ':large_brown_circle:'; label = '🟤 :large_brown_circle:'; insertText = '🟤'; filterText = ':large_brown_circle:' };
+{ word = ':large_red_square:'; label = '🟥 :large_red_square:'; insertText = '🟥'; filterText = ':large_red_square:' };
+{ word = ':large_blue_square:'; label = '🟦 :large_blue_square:'; insertText = '🟦'; filterText = ':large_blue_square:' };
+{ word = ':large_orange_square:'; label = '🟧 :large_orange_square:'; insertText = '🟧'; filterText = ':large_orange_square:' };
+{ word = ':large_yellow_square:'; label = '🟨 :large_yellow_square:'; insertText = '🟨'; filterText = ':large_yellow_square:' };
+{ word = ':large_green_square:'; label = '🟩 :large_green_square:'; insertText = '🟩'; filterText = ':large_green_square:' };
+{ word = ':large_purple_square:'; label = '🟪 :large_purple_square:'; insertText = '🟪'; filterText = ':large_purple_square:' };
+{ word = ':large_brown_square:'; label = '🟫 :large_brown_square:'; insertText = '🟫'; filterText = ':large_brown_square:' };
+{ word = ':heavy_equals_sign:'; label = '🟰 :heavy_equals_sign:'; insertText = '🟰'; filterText = ':heavy_equals_sign:' };
+{ word = ':pinched_fingers:'; label = '🤌 :pinched_fingers:'; insertText = '🤌'; filterText = ':pinched_fingers:' };
+{ word = ':white_heart:'; label = '🤍 :white_heart:'; insertText = '🤍'; filterText = ':white_heart:' };
+{ word = ':brown_heart:'; label = '🤎 :brown_heart:'; insertText = '🤎'; filterText = ':brown_heart:' };
+{ word = ':pinching_hand:'; label = '🤏 :pinching_hand:'; insertText = '🤏'; filterText = ':pinching_hand:' };
+{ word = ':zipper_mouth_face:'; label = '🤐 :zipper_mouth_face:'; insertText = '🤐'; filterText = ':zipper_mouth_face:' };
+{ word = ':money_mouth_face:'; label = '🤑 :money_mouth_face:'; insertText = '🤑'; filterText = ':money_mouth_face:' };
+{ word = ':face_with_thermometer:'; label = '🤒 :face_with_thermometer:'; insertText = '🤒'; filterText = ':face_with_thermometer:' };
+{ word = ':nerd_face:'; label = '🤓 :nerd_face:'; insertText = '🤓'; filterText = ':nerd_face:' };
+{ word = ':thinking_face:'; label = '🤔 :thinking_face:'; insertText = '🤔'; filterText = ':thinking_face:' };
+{ word = ':face_with_head_bandage:'; label = '🤕 :face_with_head_bandage:'; insertText = '🤕'; filterText = ':face_with_head_bandage:' };
+{ word = ':robot_face:'; label = '🤖 :robot_face:'; insertText = '🤖'; filterText = ':robot_face:' };
+{ word = ':hugging_face:'; label = '🤗 :hugging_face:'; insertText = '🤗'; filterText = ':hugging_face:' };
+{ word = ':the_horns:'; label = '🤘 :the_horns:'; insertText = '🤘'; filterText = ':the_horns:' };
+{ word = ':sign_of_the_horns:'; label = '🤘 :sign_of_the_horns:'; insertText = '🤘'; filterText = ':sign_of_the_horns:' };
+{ word = ':call_me_hand:'; label = '🤙 :call_me_hand:'; insertText = '🤙'; filterText = ':call_me_hand:' };
+{ word = ':raised_back_of_hand:'; label = '🤚 :raised_back_of_hand:'; insertText = '🤚'; filterText = ':raised_back_of_hand:' };
+{ word = ':left-facing_fist:'; label = '🤛 :left-facing_fist:'; insertText = '🤛'; filterText = ':left-facing_fist:' };
+{ word = ':right-facing_fist:'; label = '🤜 :right-facing_fist:'; insertText = '🤜'; filterText = ':right-facing_fist:' };
+{ word = ':handshake:'; label = '🤝 :handshake:'; insertText = '🤝'; filterText = ':handshake:' };
+{ word = ':crossed_fingers:'; label = '🤞 :crossed_fingers:'; insertText = '🤞'; filterText = ':crossed_fingers:' };
+{ word = ':hand_with_index_and_middle_fingers_crossed:'; label = '🤞 :hand_with_index_and_middle_fingers_crossed:'; insertText = '🤞'; filterText = ':hand_with_index_and_middle_fingers_crossed:' };
+{ word = ':i_love_you_hand_sign:'; label = '🤟 :i_love_you_hand_sign:'; insertText = '🤟'; filterText = ':i_love_you_hand_sign:' };
+{ word = ':face_with_cowboy_hat:'; label = '🤠 :face_with_cowboy_hat:'; insertText = '🤠'; filterText = ':face_with_cowboy_hat:' };
+{ word = ':clown_face:'; label = '🤡 :clown_face:'; insertText = '🤡'; filterText = ':clown_face:' };
+{ word = ':nauseated_face:'; label = '🤢 :nauseated_face:'; insertText = '🤢'; filterText = ':nauseated_face:' };
+{ word = ':rolling_on_the_floor_laughing:'; label = '🤣 :rolling_on_the_floor_laughing:'; insertText = '🤣'; filterText = ':rolling_on_the_floor_laughing:' };
+{ word = ':drooling_face:'; label = '🤤 :drooling_face:'; insertText = '🤤'; filterText = ':drooling_face:' };
+{ word = ':lying_face:'; label = '🤥 :lying_face:'; insertText = '🤥'; filterText = ':lying_face:' };
+{ word = ':face_palm:'; label = '🤦 :face_palm:'; insertText = '🤦'; filterText = ':face_palm:' };
+{ word = ':sneezing_face:'; label = '🤧 :sneezing_face:'; insertText = '🤧'; filterText = ':sneezing_face:' };
+{ word = ':face_with_raised_eyebrow:'; label = '🤨 :face_with_raised_eyebrow:'; insertText = '🤨'; filterText = ':face_with_raised_eyebrow:' };
+{ word = ':face_with_one_eyebrow_raised:'; label = '🤨 :face_with_one_eyebrow_raised:'; insertText = '🤨'; filterText = ':face_with_one_eyebrow_raised:' };
+{ word = ':star-struck:'; label = '🤩 :star-struck:'; insertText = '🤩'; filterText = ':star-struck:' };
+{ word = ':grinning_face_with_star_eyes:'; label = '🤩 :grinning_face_with_star_eyes:'; insertText = '🤩'; filterText = ':grinning_face_with_star_eyes:' };
+{ word = ':zany_face:'; label = '🤪 :zany_face:'; insertText = '🤪'; filterText = ':zany_face:' };
+{ word = ':grinning_face_with_one_large_and_one_small_eye:'; label = '🤪 :grinning_face_with_one_large_and_one_small_eye:'; insertText = '🤪'; filterText = ':grinning_face_with_one_large_and_one_small_eye:' };
+{ word = ':shushing_face:'; label = '🤫 :shushing_face:'; insertText = '🤫'; filterText = ':shushing_face:' };
+{ word = ':face_with_finger_covering_closed_lips:'; label = '🤫 :face_with_finger_covering_closed_lips:'; insertText = '🤫'; filterText = ':face_with_finger_covering_closed_lips:' };
+{ word = ':face_with_symbols_on_mouth:'; label = '🤬 :face_with_symbols_on_mouth:'; insertText = '🤬'; filterText = ':face_with_symbols_on_mouth:' };
+{ word = ':serious_face_with_symbols_covering_mouth:'; label = '🤬 :serious_face_with_symbols_covering_mouth:'; insertText = '🤬'; filterText = ':serious_face_with_symbols_covering_mouth:' };
+{ word = ':face_with_hand_over_mouth:'; label = '🤭 :face_with_hand_over_mouth:'; insertText = '🤭'; filterText = ':face_with_hand_over_mouth:' };
+{ word = ':smiling_face_with_smiling_eyes_and_hand_covering_mouth:'; label = '🤭 :smiling_face_with_smiling_eyes_and_hand_covering_mouth:'; insertText = '🤭'; filterText = ':smiling_face_with_smiling_eyes_and_hand_covering_mouth:' };
+{ word = ':face_vomiting:'; label = '🤮 :face_vomiting:'; insertText = '🤮'; filterText = ':face_vomiting:' };
+{ word = ':face_with_open_mouth_vomiting:'; label = '🤮 :face_with_open_mouth_vomiting:'; insertText = '🤮'; filterText = ':face_with_open_mouth_vomiting:' };
+{ word = ':exploding_head:'; label = '🤯 :exploding_head:'; insertText = '🤯'; filterText = ':exploding_head:' };
+{ word = ':shocked_face_with_exploding_head:'; label = '🤯 :shocked_face_with_exploding_head:'; insertText = '🤯'; filterText = ':shocked_face_with_exploding_head:' };
+{ word = ':pregnant_woman:'; label = '🤰 :pregnant_woman:'; insertText = '🤰'; filterText = ':pregnant_woman:' };
+{ word = ':breast-feeding:'; label = '🤱 :breast-feeding:'; insertText = '🤱'; filterText = ':breast-feeding:' };
+{ word = ':palms_up_together:'; label = '🤲 :palms_up_together:'; insertText = '🤲'; filterText = ':palms_up_together:' };
+{ word = ':selfie:'; label = '🤳 :selfie:'; insertText = '🤳'; filterText = ':selfie:' };
+{ word = ':prince:'; label = '🤴 :prince:'; insertText = '🤴'; filterText = ':prince:' };
+{ word = ':person_in_tuxedo:'; label = '🤵 :person_in_tuxedo:'; insertText = '🤵'; filterText = ':person_in_tuxedo:' };
+{ word = ':mrs_claus:'; label = '🤶 :mrs_claus:'; insertText = '🤶'; filterText = ':mrs_claus:' };
+{ word = ':mother_christmas:'; label = '🤶 :mother_christmas:'; insertText = '🤶'; filterText = ':mother_christmas:' };
+{ word = ':shrug:'; label = '🤷 :shrug:'; insertText = '🤷'; filterText = ':shrug:' };
+{ word = ':person_doing_cartwheel:'; label = '🤸 :person_doing_cartwheel:'; insertText = '🤸'; filterText = ':person_doing_cartwheel:' };
+{ word = ':juggling:'; label = '🤹 :juggling:'; insertText = '🤹'; filterText = ':juggling:' };
+{ word = ':fencer:'; label = '🤺 :fencer:'; insertText = '🤺'; filterText = ':fencer:' };
+{ word = ':wrestlers:'; label = '🤼 :wrestlers:'; insertText = '🤼'; filterText = ':wrestlers:' };
+{ word = ':water_polo:'; label = '🤽 :water_polo:'; insertText = '🤽'; filterText = ':water_polo:' };
+{ word = ':handball:'; label = '🤾 :handball:'; insertText = '🤾'; filterText = ':handball:' };
+{ word = ':diving_mask:'; label = '🤿 :diving_mask:'; insertText = '🤿'; filterText = ':diving_mask:' };
+{ word = ':wilted_flower:'; label = '🥀 :wilted_flower:'; insertText = '🥀'; filterText = ':wilted_flower:' };
+{ word = ':drum_with_drumsticks:'; label = '🥁 :drum_with_drumsticks:'; insertText = '🥁'; filterText = ':drum_with_drumsticks:' };
+{ word = ':clinking_glasses:'; label = '🥂 :clinking_glasses:'; insertText = '🥂'; filterText = ':clinking_glasses:' };
+{ word = ':tumbler_glass:'; label = '🥃 :tumbler_glass:'; insertText = '🥃'; filterText = ':tumbler_glass:' };
+{ word = ':spoon:'; label = '🥄 :spoon:'; insertText = '🥄'; filterText = ':spoon:' };
+{ word = ':goal_net:'; label = '🥅 :goal_net:'; insertText = '🥅'; filterText = ':goal_net:' };
+{ word = ':first_place_medal:'; label = '🥇 :first_place_medal:'; insertText = '🥇'; filterText = ':first_place_medal:' };
+{ word = ':second_place_medal:'; label = '🥈 :second_place_medal:'; insertText = '🥈'; filterText = ':second_place_medal:' };
+{ word = ':third_place_medal:'; label = '🥉 :third_place_medal:'; insertText = '🥉'; filterText = ':third_place_medal:' };
+{ word = ':boxing_glove:'; label = '🥊 :boxing_glove:'; insertText = '🥊'; filterText = ':boxing_glove:' };
+{ word = ':martial_arts_uniform:'; label = '🥋 :martial_arts_uniform:'; insertText = '🥋'; filterText = ':martial_arts_uniform:' };
+{ word = ':curling_stone:'; label = '🥌 :curling_stone:'; insertText = '🥌'; filterText = ':curling_stone:' };
+{ word = ':lacrosse:'; label = '🥍 :lacrosse:'; insertText = '🥍'; filterText = ':lacrosse:' };
+{ word = ':softball:'; label = '🥎 :softball:'; insertText = '🥎'; filterText = ':softball:' };
+{ word = ':flying_disc:'; label = '🥏 :flying_disc:'; insertText = '🥏'; filterText = ':flying_disc:' };
+{ word = ':croissant:'; label = '🥐 :croissant:'; insertText = '🥐'; filterText = ':croissant:' };
+{ word = ':avocado:'; label = '🥑 :avocado:'; insertText = '🥑'; filterText = ':avocado:' };
+{ word = ':cucumber:'; label = '🥒 :cucumber:'; insertText = '🥒'; filterText = ':cucumber:' };
+{ word = ':bacon:'; label = '🥓 :bacon:'; insertText = '🥓'; filterText = ':bacon:' };
+{ word = ':potato:'; label = '🥔 :potato:'; insertText = '🥔'; filterText = ':potato:' };
+{ word = ':carrot:'; label = '🥕 :carrot:'; insertText = '🥕'; filterText = ':carrot:' };
+{ word = ':baguette_bread:'; label = '🥖 :baguette_bread:'; insertText = '🥖'; filterText = ':baguette_bread:' };
+{ word = ':green_salad:'; label = '🥗 :green_salad:'; insertText = '🥗'; filterText = ':green_salad:' };
+{ word = ':shallow_pan_of_food:'; label = '🥘 :shallow_pan_of_food:'; insertText = '🥘'; filterText = ':shallow_pan_of_food:' };
+{ word = ':stuffed_flatbread:'; label = '🥙 :stuffed_flatbread:'; insertText = '🥙'; filterText = ':stuffed_flatbread:' };
+{ word = ':egg:'; label = '🥚 :egg:'; insertText = '🥚'; filterText = ':egg:' };
+{ word = ':glass_of_milk:'; label = '🥛 :glass_of_milk:'; insertText = '🥛'; filterText = ':glass_of_milk:' };
+{ word = ':peanuts:'; label = '🥜 :peanuts:'; insertText = '🥜'; filterText = ':peanuts:' };
+{ word = ':kiwifruit:'; label = '🥝 :kiwifruit:'; insertText = '🥝'; filterText = ':kiwifruit:' };
+{ word = ':pancakes:'; label = '🥞 :pancakes:'; insertText = '🥞'; filterText = ':pancakes:' };
+{ word = ':dumpling:'; label = '🥟 :dumpling:'; insertText = '🥟'; filterText = ':dumpling:' };
+{ word = ':fortune_cookie:'; label = '🥠 :fortune_cookie:'; insertText = '🥠'; filterText = ':fortune_cookie:' };
+{ word = ':takeout_box:'; label = '🥡 :takeout_box:'; insertText = '🥡'; filterText = ':takeout_box:' };
+{ word = ':chopsticks:'; label = '🥢 :chopsticks:'; insertText = '🥢'; filterText = ':chopsticks:' };
+{ word = ':bowl_with_spoon:'; label = '🥣 :bowl_with_spoon:'; insertText = '🥣'; filterText = ':bowl_with_spoon:' };
+{ word = ':cup_with_straw:'; label = '🥤 :cup_with_straw:'; insertText = '🥤'; filterText = ':cup_with_straw:' };
+{ word = ':coconut:'; label = '🥥 :coconut:'; insertText = '🥥'; filterText = ':coconut:' };
+{ word = ':broccoli:'; label = '🥦 :broccoli:'; insertText = '🥦'; filterText = ':broccoli:' };
+{ word = ':pie:'; label = '🥧 :pie:'; insertText = '🥧'; filterText = ':pie:' };
+{ word = ':pretzel:'; label = '🥨 :pretzel:'; insertText = '🥨'; filterText = ':pretzel:' };
+{ word = ':cut_of_meat:'; label = '🥩 :cut_of_meat:'; insertText = '🥩'; filterText = ':cut_of_meat:' };
+{ word = ':sandwich:'; label = '🥪 :sandwich:'; insertText = '🥪'; filterText = ':sandwich:' };
+{ word = ':canned_food:'; label = '🥫 :canned_food:'; insertText = '🥫'; filterText = ':canned_food:' };
+{ word = ':leafy_green:'; label = '🥬 :leafy_green:'; insertText = '🥬'; filterText = ':leafy_green:' };
+{ word = ':mango:'; label = '🥭 :mango:'; insertText = '🥭'; filterText = ':mango:' };
+{ word = ':moon_cake:'; label = '🥮 :moon_cake:'; insertText = '🥮'; filterText = ':moon_cake:' };
+{ word = ':bagel:'; label = '🥯 :bagel:'; insertText = '🥯'; filterText = ':bagel:' };
+{ word = ':smiling_face_with_3_hearts:'; label = '🥰 :smiling_face_with_3_hearts:'; insertText = '🥰'; filterText = ':smiling_face_with_3_hearts:' };
+{ word = ':yawning_face:'; label = '🥱 :yawning_face:'; insertText = '🥱'; filterText = ':yawning_face:' };
+{ word = ':smiling_face_with_tear:'; label = '🥲 :smiling_face_with_tear:'; insertText = '🥲'; filterText = ':smiling_face_with_tear:' };
+{ word = ':partying_face:'; label = '🥳 :partying_face:'; insertText = '🥳'; filterText = ':partying_face:' };
+{ word = ':woozy_face:'; label = '🥴 :woozy_face:'; insertText = '🥴'; filterText = ':woozy_face:' };
+{ word = ':hot_face:'; label = '🥵 :hot_face:'; insertText = '🥵'; filterText = ':hot_face:' };
+{ word = ':cold_face:'; label = '🥶 :cold_face:'; insertText = '🥶'; filterText = ':cold_face:' };
+{ word = ':ninja:'; label = '🥷 :ninja:'; insertText = '🥷'; filterText = ':ninja:' };
+{ word = ':disguised_face:'; label = '🥸 :disguised_face:'; insertText = '🥸'; filterText = ':disguised_face:' };
+{ word = ':face_holding_back_tears:'; label = '🥹 :face_holding_back_tears:'; insertText = '🥹'; filterText = ':face_holding_back_tears:' };
+{ word = ':pleading_face:'; label = '🥺 :pleading_face:'; insertText = '🥺'; filterText = ':pleading_face:' };
+{ word = ':sari:'; label = '🥻 :sari:'; insertText = '🥻'; filterText = ':sari:' };
+{ word = ':lab_coat:'; label = '🥼 :lab_coat:'; insertText = '🥼'; filterText = ':lab_coat:' };
+{ word = ':goggles:'; label = '🥽 :goggles:'; insertText = '🥽'; filterText = ':goggles:' };
+{ word = ':hiking_boot:'; label = '🥾 :hiking_boot:'; insertText = '🥾'; filterText = ':hiking_boot:' };
+{ word = ':womans_flat_shoe:'; label = '🥿 :womans_flat_shoe:'; insertText = '🥿'; filterText = ':womans_flat_shoe:' };
+{ word = ':crab:'; label = '🦀 :crab:'; insertText = '🦀'; filterText = ':crab:' };
+{ word = ':lion_face:'; label = '🦁 :lion_face:'; insertText = '🦁'; filterText = ':lion_face:' };
+{ word = ':scorpion:'; label = '🦂 :scorpion:'; insertText = '🦂'; filterText = ':scorpion:' };
+{ word = ':turkey:'; label = '🦃 :turkey:'; insertText = '🦃'; filterText = ':turkey:' };
+{ word = ':unicorn_face:'; label = '🦄 :unicorn_face:'; insertText = '🦄'; filterText = ':unicorn_face:' };
+{ word = ':eagle:'; label = '🦅 :eagle:'; insertText = '🦅'; filterText = ':eagle:' };
+{ word = ':duck:'; label = '🦆 :duck:'; insertText = '🦆'; filterText = ':duck:' };
+{ word = ':bat:'; label = '🦇 :bat:'; insertText = '🦇'; filterText = ':bat:' };
+{ word = ':shark:'; label = '🦈 :shark:'; insertText = '🦈'; filterText = ':shark:' };
+{ word = ':owl:'; label = '🦉 :owl:'; insertText = '🦉'; filterText = ':owl:' };
+{ word = ':fox_face:'; label = '🦊 :fox_face:'; insertText = '🦊'; filterText = ':fox_face:' };
+{ word = ':butterfly:'; label = '🦋 :butterfly:'; insertText = '🦋'; filterText = ':butterfly:' };
+{ word = ':deer:'; label = '🦌 :deer:'; insertText = '🦌'; filterText = ':deer:' };
+{ word = ':gorilla:'; label = '🦍 :gorilla:'; insertText = '🦍'; filterText = ':gorilla:' };
+{ word = ':lizard:'; label = '🦎 :lizard:'; insertText = '🦎'; filterText = ':lizard:' };
+{ word = ':rhinoceros:'; label = '🦏 :rhinoceros:'; insertText = '🦏'; filterText = ':rhinoceros:' };
+{ word = ':shrimp:'; label = '🦐 :shrimp:'; insertText = '🦐'; filterText = ':shrimp:' };
+{ word = ':squid:'; label = '🦑 :squid:'; insertText = '🦑'; filterText = ':squid:' };
+{ word = ':giraffe_face:'; label = '🦒 :giraffe_face:'; insertText = '🦒'; filterText = ':giraffe_face:' };
+{ word = ':zebra_face:'; label = '🦓 :zebra_face:'; insertText = '🦓'; filterText = ':zebra_face:' };
+{ word = ':hedgehog:'; label = '🦔 :hedgehog:'; insertText = '🦔'; filterText = ':hedgehog:' };
+{ word = ':sauropod:'; label = '🦕 :sauropod:'; insertText = '🦕'; filterText = ':sauropod:' };
+{ word = ':t-rex:'; label = '🦖 :t-rex:'; insertText = '🦖'; filterText = ':t-rex:' };
+{ word = ':cricket:'; label = '🦗 :cricket:'; insertText = '🦗'; filterText = ':cricket:' };
+{ word = ':kangaroo:'; label = '🦘 :kangaroo:'; insertText = '🦘'; filterText = ':kangaroo:' };
+{ word = ':llama:'; label = '🦙 :llama:'; insertText = '🦙'; filterText = ':llama:' };
+{ word = ':peacock:'; label = '🦚 :peacock:'; insertText = '🦚'; filterText = ':peacock:' };
+{ word = ':hippopotamus:'; label = '🦛 :hippopotamus:'; insertText = '🦛'; filterText = ':hippopotamus:' };
+{ word = ':parrot:'; label = '🦜 :parrot:'; insertText = '🦜'; filterText = ':parrot:' };
+{ word = ':raccoon:'; label = '🦝 :raccoon:'; insertText = '🦝'; filterText = ':raccoon:' };
+{ word = ':lobster:'; label = '🦞 :lobster:'; insertText = '🦞'; filterText = ':lobster:' };
+{ word = ':mosquito:'; label = '🦟 :mosquito:'; insertText = '🦟'; filterText = ':mosquito:' };
+{ word = ':microbe:'; label = '🦠 :microbe:'; insertText = '🦠'; filterText = ':microbe:' };
+{ word = ':badger:'; label = '🦡 :badger:'; insertText = '🦡'; filterText = ':badger:' };
+{ word = ':swan:'; label = '🦢 :swan:'; insertText = '🦢'; filterText = ':swan:' };
+{ word = ':mammoth:'; label = '🦣 :mammoth:'; insertText = '🦣'; filterText = ':mammoth:' };
+{ word = ':dodo:'; label = '🦤 :dodo:'; insertText = '🦤'; filterText = ':dodo:' };
+{ word = ':sloth:'; label = '🦥 :sloth:'; insertText = '🦥'; filterText = ':sloth:' };
+{ word = ':otter:'; label = '🦦 :otter:'; insertText = '🦦'; filterText = ':otter:' };
+{ word = ':orangutan:'; label = '🦧 :orangutan:'; insertText = '🦧'; filterText = ':orangutan:' };
+{ word = ':skunk:'; label = '🦨 :skunk:'; insertText = '🦨'; filterText = ':skunk:' };
+{ word = ':flamingo:'; label = '🦩 :flamingo:'; insertText = '🦩'; filterText = ':flamingo:' };
+{ word = ':oyster:'; label = '🦪 :oyster:'; insertText = '🦪'; filterText = ':oyster:' };
+{ word = ':beaver:'; label = '🦫 :beaver:'; insertText = '🦫'; filterText = ':beaver:' };
+{ word = ':bison:'; label = '🦬 :bison:'; insertText = '🦬'; filterText = ':bison:' };
+{ word = ':seal:'; label = '🦭 :seal:'; insertText = '🦭'; filterText = ':seal:' };
+{ word = ':guide_dog:'; label = '🦮 :guide_dog:'; insertText = '🦮'; filterText = ':guide_dog:' };
+{ word = ':probing_cane:'; label = '🦯 :probing_cane:'; insertText = '🦯'; filterText = ':probing_cane:' };
+{ word = ':bone:'; label = '🦴 :bone:'; insertText = '🦴'; filterText = ':bone:' };
+{ word = ':leg:'; label = '🦵 :leg:'; insertText = '🦵'; filterText = ':leg:' };
+{ word = ':foot:'; label = '🦶 :foot:'; insertText = '🦶'; filterText = ':foot:' };
+{ word = ':tooth:'; label = '🦷 :tooth:'; insertText = '🦷'; filterText = ':tooth:' };
+{ word = ':superhero:'; label = '🦸 :superhero:'; insertText = '🦸'; filterText = ':superhero:' };
+{ word = ':supervillain:'; label = '🦹 :supervillain:'; insertText = '🦹'; filterText = ':supervillain:' };
+{ word = ':safety_vest:'; label = '🦺 :safety_vest:'; insertText = '🦺'; filterText = ':safety_vest:' };
+{ word = ':ear_with_hearing_aid:'; label = '🦻 :ear_with_hearing_aid:'; insertText = '🦻'; filterText = ':ear_with_hearing_aid:' };
+{ word = ':motorized_wheelchair:'; label = '🦼 :motorized_wheelchair:'; insertText = '🦼'; filterText = ':motorized_wheelchair:' };
+{ word = ':manual_wheelchair:'; label = '🦽 :manual_wheelchair:'; insertText = '🦽'; filterText = ':manual_wheelchair:' };
+{ word = ':mechanical_arm:'; label = '🦾 :mechanical_arm:'; insertText = '🦾'; filterText = ':mechanical_arm:' };
+{ word = ':mechanical_leg:'; label = '🦿 :mechanical_leg:'; insertText = '🦿'; filterText = ':mechanical_leg:' };
+{ word = ':cheese_wedge:'; label = '🧀 :cheese_wedge:'; insertText = '🧀'; filterText = ':cheese_wedge:' };
+{ word = ':cupcake:'; label = '🧁 :cupcake:'; insertText = '🧁'; filterText = ':cupcake:' };
+{ word = ':salt:'; label = '🧂 :salt:'; insertText = '🧂'; filterText = ':salt:' };
+{ word = ':beverage_box:'; label = '🧃 :beverage_box:'; insertText = '🧃'; filterText = ':beverage_box:' };
+{ word = ':garlic:'; label = '🧄 :garlic:'; insertText = '🧄'; filterText = ':garlic:' };
+{ word = ':onion:'; label = '🧅 :onion:'; insertText = '🧅'; filterText = ':onion:' };
+{ word = ':falafel:'; label = '🧆 :falafel:'; insertText = '🧆'; filterText = ':falafel:' };
+{ word = ':waffle:'; label = '🧇 :waffle:'; insertText = '🧇'; filterText = ':waffle:' };
+{ word = ':butter:'; label = '🧈 :butter:'; insertText = '🧈'; filterText = ':butter:' };
+{ word = ':mate_drink:'; label = '🧉 :mate_drink:'; insertText = '🧉'; filterText = ':mate_drink:' };
+{ word = ':ice_cube:'; label = '🧊 :ice_cube:'; insertText = '🧊'; filterText = ':ice_cube:' };
+{ word = ':bubble_tea:'; label = '🧋 :bubble_tea:'; insertText = '🧋'; filterText = ':bubble_tea:' };
+{ word = ':troll:'; label = '🧌 :troll:'; insertText = '🧌'; filterText = ':troll:' };
+{ word = ':standing_person:'; label = '🧍 :standing_person:'; insertText = '🧍'; filterText = ':standing_person:' };
+{ word = ':kneeling_person:'; label = '🧎 :kneeling_person:'; insertText = '🧎'; filterText = ':kneeling_person:' };
+{ word = ':deaf_person:'; label = '🧏 :deaf_person:'; insertText = '🧏'; filterText = ':deaf_person:' };
+{ word = ':face_with_monocle:'; label = '🧐 :face_with_monocle:'; insertText = '🧐'; filterText = ':face_with_monocle:' };
+{ word = ':adult:'; label = '🧑 :adult:'; insertText = '🧑'; filterText = ':adult:' };
+{ word = ':child:'; label = '🧒 :child:'; insertText = '🧒'; filterText = ':child:' };
+{ word = ':older_adult:'; label = '🧓 :older_adult:'; insertText = '🧓'; filterText = ':older_adult:' };
+{ word = ':bearded_person:'; label = '🧔 :bearded_person:'; insertText = '🧔'; filterText = ':bearded_person:' };
+{ word = ':person_with_headscarf:'; label = '🧕 :person_with_headscarf:'; insertText = '🧕'; filterText = ':person_with_headscarf:' };
+{ word = ':person_in_steamy_room:'; label = '🧖 :person_in_steamy_room:'; insertText = '🧖'; filterText = ':person_in_steamy_room:' };
+{ word = ':person_climbing:'; label = '🧗 :person_climbing:'; insertText = '🧗'; filterText = ':person_climbing:' };
+{ word = ':person_in_lotus_position:'; label = '🧘 :person_in_lotus_position:'; insertText = '🧘'; filterText = ':person_in_lotus_position:' };
+{ word = ':mage:'; label = '🧙 :mage:'; insertText = '🧙'; filterText = ':mage:' };
+{ word = ':fairy:'; label = '🧚 :fairy:'; insertText = '🧚'; filterText = ':fairy:' };
+{ word = ':vampire:'; label = '🧛 :vampire:'; insertText = '🧛'; filterText = ':vampire:' };
+{ word = ':merperson:'; label = '🧜 :merperson:'; insertText = '🧜'; filterText = ':merperson:' };
+{ word = ':elf:'; label = '🧝 :elf:'; insertText = '🧝'; filterText = ':elf:' };
+{ word = ':genie:'; label = '🧞 :genie:'; insertText = '🧞'; filterText = ':genie:' };
+{ word = ':zombie:'; label = '🧟 :zombie:'; insertText = '🧟'; filterText = ':zombie:' };
+{ word = ':brain:'; label = '🧠 :brain:'; insertText = '🧠'; filterText = ':brain:' };
+{ word = ':orange_heart:'; label = '🧡 :orange_heart:'; insertText = '🧡'; filterText = ':orange_heart:' };
+{ word = ':billed_cap:'; label = '🧢 :billed_cap:'; insertText = '🧢'; filterText = ':billed_cap:' };
+{ word = ':scarf:'; label = '🧣 :scarf:'; insertText = '🧣'; filterText = ':scarf:' };
+{ word = ':gloves:'; label = '🧤 :gloves:'; insertText = '🧤'; filterText = ':gloves:' };
+{ word = ':coat:'; label = '🧥 :coat:'; insertText = '🧥'; filterText = ':coat:' };
+{ word = ':socks:'; label = '🧦 :socks:'; insertText = '🧦'; filterText = ':socks:' };
+{ word = ':red_envelope:'; label = '🧧 :red_envelope:'; insertText = '🧧'; filterText = ':red_envelope:' };
+{ word = ':firecracker:'; label = '🧨 :firecracker:'; insertText = '🧨'; filterText = ':firecracker:' };
+{ word = ':jigsaw:'; label = '🧩 :jigsaw:'; insertText = '🧩'; filterText = ':jigsaw:' };
+{ word = ':test_tube:'; label = '🧪 :test_tube:'; insertText = '🧪'; filterText = ':test_tube:' };
+{ word = ':petri_dish:'; label = '🧫 :petri_dish:'; insertText = '🧫'; filterText = ':petri_dish:' };
+{ word = ':dna:'; label = '🧬 :dna:'; insertText = '🧬'; filterText = ':dna:' };
+{ word = ':compass:'; label = '🧭 :compass:'; insertText = '🧭'; filterText = ':compass:' };
+{ word = ':abacus:'; label = '🧮 :abacus:'; insertText = '🧮'; filterText = ':abacus:' };
+{ word = ':fire_extinguisher:'; label = '🧯 :fire_extinguisher:'; insertText = '🧯'; filterText = ':fire_extinguisher:' };
+{ word = ':toolbox:'; label = '🧰 :toolbox:'; insertText = '🧰'; filterText = ':toolbox:' };
+{ word = ':bricks:'; label = '🧱 :bricks:'; insertText = '🧱'; filterText = ':bricks:' };
+{ word = ':magnet:'; label = '🧲 :magnet:'; insertText = '🧲'; filterText = ':magnet:' };
+{ word = ':luggage:'; label = '🧳 :luggage:'; insertText = '🧳'; filterText = ':luggage:' };
+{ word = ':lotion_bottle:'; label = '🧴 :lotion_bottle:'; insertText = '🧴'; filterText = ':lotion_bottle:' };
+{ word = ':thread:'; label = '🧵 :thread:'; insertText = '🧵'; filterText = ':thread:' };
+{ word = ':yarn:'; label = '🧶 :yarn:'; insertText = '🧶'; filterText = ':yarn:' };
+{ word = ':safety_pin:'; label = '🧷 :safety_pin:'; insertText = '🧷'; filterText = ':safety_pin:' };
+{ word = ':teddy_bear:'; label = '🧸 :teddy_bear:'; insertText = '🧸'; filterText = ':teddy_bear:' };
+{ word = ':broom:'; label = '🧹 :broom:'; insertText = '🧹'; filterText = ':broom:' };
+{ word = ':basket:'; label = '🧺 :basket:'; insertText = '🧺'; filterText = ':basket:' };
+{ word = ':roll_of_paper:'; label = '🧻 :roll_of_paper:'; insertText = '🧻'; filterText = ':roll_of_paper:' };
+{ word = ':soap:'; label = '🧼 :soap:'; insertText = '🧼'; filterText = ':soap:' };
+{ word = ':sponge:'; label = '🧽 :sponge:'; insertText = '🧽'; filterText = ':sponge:' };
+{ word = ':receipt:'; label = '🧾 :receipt:'; insertText = '🧾'; filterText = ':receipt:' };
+{ word = ':nazar_amulet:'; label = '🧿 :nazar_amulet:'; insertText = '🧿'; filterText = ':nazar_amulet:' };
+{ word = ':ballet_shoes:'; label = '🩰 :ballet_shoes:'; insertText = '🩰'; filterText = ':ballet_shoes:' };
+{ word = ':one-piece_swimsuit:'; label = '🩱 :one-piece_swimsuit:'; insertText = '🩱'; filterText = ':one-piece_swimsuit:' };
+{ word = ':briefs:'; label = '🩲 :briefs:'; insertText = '🩲'; filterText = ':briefs:' };
+{ word = ':shorts:'; label = '🩳 :shorts:'; insertText = '🩳'; filterText = ':shorts:' };
+{ word = ':thong_sandal:'; label = '🩴 :thong_sandal:'; insertText = '🩴'; filterText = ':thong_sandal:' };
+{ word = ':light_blue_heart:'; label = '🩵 :light_blue_heart:'; insertText = '🩵'; filterText = ':light_blue_heart:' };
+{ word = ':grey_heart:'; label = '🩶 :grey_heart:'; insertText = '🩶'; filterText = ':grey_heart:' };
+{ word = ':pink_heart:'; label = '🩷 :pink_heart:'; insertText = '🩷'; filterText = ':pink_heart:' };
+{ word = ':drop_of_blood:'; label = '🩸 :drop_of_blood:'; insertText = '🩸'; filterText = ':drop_of_blood:' };
+{ word = ':adhesive_bandage:'; label = '🩹 :adhesive_bandage:'; insertText = '🩹'; filterText = ':adhesive_bandage:' };
+{ word = ':stethoscope:'; label = '🩺 :stethoscope:'; insertText = '🩺'; filterText = ':stethoscope:' };
+{ word = ':x-ray:'; label = '🩻 :x-ray:'; insertText = '🩻'; filterText = ':x-ray:' };
+{ word = ':crutch:'; label = '🩼 :crutch:'; insertText = '🩼'; filterText = ':crutch:' };
+{ word = ':yo-yo:'; label = '🪀 :yo-yo:'; insertText = '🪀'; filterText = ':yo-yo:' };
+{ word = ':kite:'; label = '🪁 :kite:'; insertText = '🪁'; filterText = ':kite:' };
+{ word = ':parachute:'; label = '🪂 :parachute:'; insertText = '🪂'; filterText = ':parachute:' };
+{ word = ':boomerang:'; label = '🪃 :boomerang:'; insertText = '🪃'; filterText = ':boomerang:' };
+{ word = ':magic_wand:'; label = '🪄 :magic_wand:'; insertText = '🪄'; filterText = ':magic_wand:' };
+{ word = ':pinata:'; label = '🪅 :pinata:'; insertText = '🪅'; filterText = ':pinata:' };
+{ word = ':nesting_dolls:'; label = '🪆 :nesting_dolls:'; insertText = '🪆'; filterText = ':nesting_dolls:' };
+{ word = ':maracas:'; label = '🪇 :maracas:'; insertText = '🪇'; filterText = ':maracas:' };
+{ word = ':flute:'; label = '🪈 :flute:'; insertText = '🪈'; filterText = ':flute:' };
+{ word = ':ringed_planet:'; label = '🪐 :ringed_planet:'; insertText = '🪐'; filterText = ':ringed_planet:' };
+{ word = ':chair:'; label = '🪑 :chair:'; insertText = '🪑'; filterText = ':chair:' };
+{ word = ':razor:'; label = '🪒 :razor:'; insertText = '🪒'; filterText = ':razor:' };
+{ word = ':axe:'; label = '🪓 :axe:'; insertText = '🪓'; filterText = ':axe:' };
+{ word = ':diya_lamp:'; label = '🪔 :diya_lamp:'; insertText = '🪔'; filterText = ':diya_lamp:' };
+{ word = ':banjo:'; label = '🪕 :banjo:'; insertText = '🪕'; filterText = ':banjo:' };
+{ word = ':military_helmet:'; label = '🪖 :military_helmet:'; insertText = '🪖'; filterText = ':military_helmet:' };
+{ word = ':accordion:'; label = '🪗 :accordion:'; insertText = '🪗'; filterText = ':accordion:' };
+{ word = ':long_drum:'; label = '🪘 :long_drum:'; insertText = '🪘'; filterText = ':long_drum:' };
+{ word = ':coin:'; label = '🪙 :coin:'; insertText = '🪙'; filterText = ':coin:' };
+{ word = ':carpentry_saw:'; label = '🪚 :carpentry_saw:'; insertText = '🪚'; filterText = ':carpentry_saw:' };
+{ word = ':screwdriver:'; label = '🪛 :screwdriver:'; insertText = '🪛'; filterText = ':screwdriver:' };
+{ word = ':ladder:'; label = '🪜 :ladder:'; insertText = '🪜'; filterText = ':ladder:' };
+{ word = ':hook:'; label = '🪝 :hook:'; insertText = '🪝'; filterText = ':hook:' };
+{ word = ':mirror:'; label = '🪞 :mirror:'; insertText = '🪞'; filterText = ':mirror:' };
+{ word = ':window:'; label = '🪟 :window:'; insertText = '🪟'; filterText = ':window:' };
+{ word = ':plunger:'; label = '🪠 :plunger:'; insertText = '🪠'; filterText = ':plunger:' };
+{ word = ':sewing_needle:'; label = '🪡 :sewing_needle:'; insertText = '🪡'; filterText = ':sewing_needle:' };
+{ word = ':knot:'; label = '🪢 :knot:'; insertText = '🪢'; filterText = ':knot:' };
+{ word = ':bucket:'; label = '🪣 :bucket:'; insertText = '🪣'; filterText = ':bucket:' };
+{ word = ':mouse_trap:'; label = '🪤 :mouse_trap:'; insertText = '🪤'; filterText = ':mouse_trap:' };
+{ word = ':toothbrush:'; label = '🪥 :toothbrush:'; insertText = '🪥'; filterText = ':toothbrush:' };
+{ word = ':headstone:'; label = '🪦 :headstone:'; insertText = '🪦'; filterText = ':headstone:' };
+{ word = ':placard:'; label = '🪧 :placard:'; insertText = '🪧'; filterText = ':placard:' };
+{ word = ':rock:'; label = '🪨 :rock:'; insertText = '🪨'; filterText = ':rock:' };
+{ word = ':mirror_ball:'; label = '🪩 :mirror_ball:'; insertText = '🪩'; filterText = ':mirror_ball:' };
+{ word = ':identification_card:'; label = '🪪 :identification_card:'; insertText = '🪪'; filterText = ':identification_card:' };
+{ word = ':low_battery:'; label = '🪫 :low_battery:'; insertText = '🪫'; filterText = ':low_battery:' };
+{ word = ':hamsa:'; label = '🪬 :hamsa:'; insertText = '🪬'; filterText = ':hamsa:' };
+{ word = ':folding_hand_fan:'; label = '🪭 :folding_hand_fan:'; insertText = '🪭'; filterText = ':folding_hand_fan:' };
+{ word = ':hair_pick:'; label = '🪮 :hair_pick:'; insertText = '🪮'; filterText = ':hair_pick:' };
+{ word = ':khanda:'; label = '🪯 :khanda:'; insertText = '🪯'; filterText = ':khanda:' };
+{ word = ':fly:'; label = '🪰 :fly:'; insertText = '🪰'; filterText = ':fly:' };
+{ word = ':worm:'; label = '🪱 :worm:'; insertText = '🪱'; filterText = ':worm:' };
+{ word = ':beetle:'; label = '🪲 :beetle:'; insertText = '🪲'; filterText = ':beetle:' };
+{ word = ':cockroach:'; label = '🪳 :cockroach:'; insertText = '🪳'; filterText = ':cockroach:' };
+{ word = ':potted_plant:'; label = '🪴 :potted_plant:'; insertText = '🪴'; filterText = ':potted_plant:' };
+{ word = ':wood:'; label = '🪵 :wood:'; insertText = '🪵'; filterText = ':wood:' };
+{ word = ':feather:'; label = '🪶 :feather:'; insertText = '🪶'; filterText = ':feather:' };
+{ word = ':lotus:'; label = '🪷 :lotus:'; insertText = '🪷'; filterText = ':lotus:' };
+{ word = ':coral:'; label = '🪸 :coral:'; insertText = '🪸'; filterText = ':coral:' };
+{ word = ':empty_nest:'; label = '🪹 :empty_nest:'; insertText = '🪹'; filterText = ':empty_nest:' };
+{ word = ':nest_with_eggs:'; label = '🪺 :nest_with_eggs:'; insertText = '🪺'; filterText = ':nest_with_eggs:' };
+{ word = ':hyacinth:'; label = '🪻 :hyacinth:'; insertText = '🪻'; filterText = ':hyacinth:' };
+{ word = ':jellyfish:'; label = '🪼 :jellyfish:'; insertText = '🪼'; filterText = ':jellyfish:' };
+{ word = ':wing:'; label = '🪽 :wing:'; insertText = '🪽'; filterText = ':wing:' };
+{ word = ':goose:'; label = '🪿 :goose:'; insertText = '🪿'; filterText = ':goose:' };
+{ word = ':anatomical_heart:'; label = '🫀 :anatomical_heart:'; insertText = '🫀'; filterText = ':anatomical_heart:' };
+{ word = ':lungs:'; label = '🫁 :lungs:'; insertText = '🫁'; filterText = ':lungs:' };
+{ word = ':people_hugging:'; label = '🫂 :people_hugging:'; insertText = '🫂'; filterText = ':people_hugging:' };
+{ word = ':pregnant_man:'; label = '🫃 :pregnant_man:'; insertText = '🫃'; filterText = ':pregnant_man:' };
+{ word = ':pregnant_person:'; label = '🫄 :pregnant_person:'; insertText = '🫄'; filterText = ':pregnant_person:' };
+{ word = ':person_with_crown:'; label = '🫅 :person_with_crown:'; insertText = '🫅'; filterText = ':person_with_crown:' };
+{ word = ':moose:'; label = '🫎 :moose:'; insertText = '🫎'; filterText = ':moose:' };
+{ word = ':donkey:'; label = '🫏 :donkey:'; insertText = '🫏'; filterText = ':donkey:' };
+{ word = ':blueberries:'; label = '🫐 :blueberries:'; insertText = '🫐'; filterText = ':blueberries:' };
+{ word = ':bell_pepper:'; label = '🫑 :bell_pepper:'; insertText = '🫑'; filterText = ':bell_pepper:' };
+{ word = ':olive:'; label = '🫒 :olive:'; insertText = '🫒'; filterText = ':olive:' };
+{ word = ':flatbread:'; label = '🫓 :flatbread:'; insertText = '🫓'; filterText = ':flatbread:' };
+{ word = ':tamale:'; label = '🫔 :tamale:'; insertText = '🫔'; filterText = ':tamale:' };
+{ word = ':fondue:'; label = '🫕 :fondue:'; insertText = '🫕'; filterText = ':fondue:' };
+{ word = ':teapot:'; label = '🫖 :teapot:'; insertText = '🫖'; filterText = ':teapot:' };
+{ word = ':pouring_liquid:'; label = '🫗 :pouring_liquid:'; insertText = '🫗'; filterText = ':pouring_liquid:' };
+{ word = ':beans:'; label = '🫘 :beans:'; insertText = '🫘'; filterText = ':beans:' };
+{ word = ':jar:'; label = '🫙 :jar:'; insertText = '🫙'; filterText = ':jar:' };
+{ word = ':ginger_root:'; label = '🫚 :ginger_root:'; insertText = '🫚'; filterText = ':ginger_root:' };
+{ word = ':pea_pod:'; label = '🫛 :pea_pod:'; insertText = '🫛'; filterText = ':pea_pod:' };
+{ word = ':melting_face:'; label = '🫠 :melting_face:'; insertText = '🫠'; filterText = ':melting_face:' };
+{ word = ':saluting_face:'; label = '🫡 :saluting_face:'; insertText = '🫡'; filterText = ':saluting_face:' };
+{ word = ':face_with_open_eyes_and_hand_over_mouth:'; label = '🫢 :face_with_open_eyes_and_hand_over_mouth:'; insertText = '🫢'; filterText = ':face_with_open_eyes_and_hand_over_mouth:' };
+{ word = ':face_with_peeking_eye:'; label = '🫣 :face_with_peeking_eye:'; insertText = '🫣'; filterText = ':face_with_peeking_eye:' };
+{ word = ':face_with_diagonal_mouth:'; label = '🫤 :face_with_diagonal_mouth:'; insertText = '🫤'; filterText = ':face_with_diagonal_mouth:' };
+{ word = ':dotted_line_face:'; label = '🫥 :dotted_line_face:'; insertText = '🫥'; filterText = ':dotted_line_face:' };
+{ word = ':biting_lip:'; label = '🫦 :biting_lip:'; insertText = '🫦'; filterText = ':biting_lip:' };
+{ word = ':bubbles:'; label = '🫧 :bubbles:'; insertText = '🫧'; filterText = ':bubbles:' };
+{ word = ':shaking_face:'; label = '🫨 :shaking_face:'; insertText = '🫨'; filterText = ':shaking_face:' };
+{ word = ':hand_with_index_finger_and_thumb_crossed:'; label = '🫰 :hand_with_index_finger_and_thumb_crossed:'; insertText = '🫰'; filterText = ':hand_with_index_finger_and_thumb_crossed:' };
+{ word = ':rightwards_hand:'; label = '🫱 :rightwards_hand:'; insertText = '🫱'; filterText = ':rightwards_hand:' };
+{ word = ':leftwards_hand:'; label = '🫲 :leftwards_hand:'; insertText = '🫲'; filterText = ':leftwards_hand:' };
+{ word = ':palm_down_hand:'; label = '🫳 :palm_down_hand:'; insertText = '🫳'; filterText = ':palm_down_hand:' };
+{ word = ':palm_up_hand:'; label = '🫴 :palm_up_hand:'; insertText = '🫴'; filterText = ':palm_up_hand:' };
+{ word = ':index_pointing_at_the_viewer:'; label = '🫵 :index_pointing_at_the_viewer:'; insertText = '🫵'; filterText = ':index_pointing_at_the_viewer:' };
+{ word = ':heart_hands:'; label = '🫶 :heart_hands:'; insertText = '🫶'; filterText = ':heart_hands:' };
+{ word = ':leftwards_pushing_hand:'; label = '🫷 :leftwards_pushing_hand:'; insertText = '🫷'; filterText = ':leftwards_pushing_hand:' };
+{ word = ':rightwards_pushing_hand:'; label = '🫸 :rightwards_pushing_hand:'; insertText = '🫸'; filterText = ':rightwards_pushing_hand:' };
+{ word = ':bangbang:'; label = '‼️ :bangbang:'; insertText = '‼️'; filterText = ':bangbang:' };
+{ word = ':interrobang:'; label = '⁉️ :interrobang:'; insertText = '⁉️'; filterText = ':interrobang:' };
+{ word = ':tm:'; label = '™️ :tm:'; insertText = '™️'; filterText = ':tm:' };
+{ word = ':information_source:'; label = 'ℹ️ :information_source:'; insertText = 'ℹ️'; filterText = ':information_source:' };
+{ word = ':left_right_arrow:'; label = '↔️ :left_right_arrow:'; insertText = '↔️'; filterText = ':left_right_arrow:' };
+{ word = ':arrow_up_down:'; label = '↕️ :arrow_up_down:'; insertText = '↕️'; filterText = ':arrow_up_down:' };
+{ word = ':arrow_upper_left:'; label = '↖️ :arrow_upper_left:'; insertText = '↖️'; filterText = ':arrow_upper_left:' };
+{ word = ':arrow_upper_right:'; label = '↗️ :arrow_upper_right:'; insertText = '↗️'; filterText = ':arrow_upper_right:' };
+{ word = ':arrow_lower_right:'; label = '↘️ :arrow_lower_right:'; insertText = '↘️'; filterText = ':arrow_lower_right:' };
+{ word = ':arrow_lower_left:'; label = '↙️ :arrow_lower_left:'; insertText = '↙️'; filterText = ':arrow_lower_left:' };
+{ word = ':leftwards_arrow_with_hook:'; label = '↩️ :leftwards_arrow_with_hook:'; insertText = '↩️'; filterText = ':leftwards_arrow_with_hook:' };
+{ word = ':arrow_right_hook:'; label = '↪️ :arrow_right_hook:'; insertText = '↪️'; filterText = ':arrow_right_hook:' };
+{ word = ':watch:'; label = '⌚ :watch:'; insertText = '⌚'; filterText = ':watch:' };
+{ word = ':hourglass:'; label = '⌛ :hourglass:'; insertText = '⌛'; filterText = ':hourglass:' };
+{ word = ':keyboard:'; label = '⌨️ :keyboard:'; insertText = '⌨️'; filterText = ':keyboard:' };
+{ word = ':eject:'; label = '⏏️ :eject:'; insertText = '⏏️'; filterText = ':eject:' };
+{ word = ':fast_forward:'; label = '⏩ :fast_forward:'; insertText = '⏩'; filterText = ':fast_forward:' };
+{ word = ':rewind:'; label = '⏪ :rewind:'; insertText = '⏪'; filterText = ':rewind:' };
+{ word = ':arrow_double_up:'; label = '⏫ :arrow_double_up:'; insertText = '⏫'; filterText = ':arrow_double_up:' };
+{ word = ':arrow_double_down:'; label = '⏬ :arrow_double_down:'; insertText = '⏬'; filterText = ':arrow_double_down:' };
+{ word = ':black_right_pointing_double_triangle_with_vertical_bar:'; label = '⏭️ :black_right_pointing_double_triangle_with_vertical_bar:'; insertText = '⏭️'; filterText = ':black_right_pointing_double_triangle_with_vertical_bar:' };
+{ word = ':black_left_pointing_double_triangle_with_vertical_bar:'; label = '⏮️ :black_left_pointing_double_triangle_with_vertical_bar:'; insertText = '⏮️'; filterText = ':black_left_pointing_double_triangle_with_vertical_bar:' };
+{ word = ':black_right_pointing_triangle_with_double_vertical_bar:'; label = '⏯️ :black_right_pointing_triangle_with_double_vertical_bar:'; insertText = '⏯️'; filterText = ':black_right_pointing_triangle_with_double_vertical_bar:' };
+{ word = ':alarm_clock:'; label = '⏰ :alarm_clock:'; insertText = '⏰'; filterText = ':alarm_clock:' };
+{ word = ':stopwatch:'; label = '⏱️ :stopwatch:'; insertText = '⏱️'; filterText = ':stopwatch:' };
+{ word = ':timer_clock:'; label = '⏲️ :timer_clock:'; insertText = '⏲️'; filterText = ':timer_clock:' };
+{ word = ':hourglass_flowing_sand:'; label = '⏳ :hourglass_flowing_sand:'; insertText = '⏳'; filterText = ':hourglass_flowing_sand:' };
+{ word = ':double_vertical_bar:'; label = '⏸️ :double_vertical_bar:'; insertText = '⏸️'; filterText = ':double_vertical_bar:' };
+{ word = ':black_square_for_stop:'; label = '⏹️ :black_square_for_stop:'; insertText = '⏹️'; filterText = ':black_square_for_stop:' };
+{ word = ':black_circle_for_record:'; label = '⏺️ :black_circle_for_record:'; insertText = '⏺️'; filterText = ':black_circle_for_record:' };
+{ word = ':m:'; label = 'Ⓜ️ :m:'; insertText = 'Ⓜ️'; filterText = ':m:' };
+{ word = ':black_small_square:'; label = '▪️ :black_small_square:'; insertText = '▪️'; filterText = ':black_small_square:' };
+{ word = ':white_small_square:'; label = '▫️ :white_small_square:'; insertText = '▫️'; filterText = ':white_small_square:' };
+{ word = ':arrow_forward:'; label = '▶️ :arrow_forward:'; insertText = '▶️'; filterText = ':arrow_forward:' };
+{ word = ':arrow_backward:'; label = '◀️ :arrow_backward:'; insertText = '◀️'; filterText = ':arrow_backward:' };
+{ word = ':white_medium_square:'; label = '◻️ :white_medium_square:'; insertText = '◻️'; filterText = ':white_medium_square:' };
+{ word = ':black_medium_square:'; label = '◼️ :black_medium_square:'; insertText = '◼️'; filterText = ':black_medium_square:' };
+{ word = ':white_medium_small_square:'; label = '◽ :white_medium_small_square:'; insertText = '◽'; filterText = ':white_medium_small_square:' };
+{ word = ':black_medium_small_square:'; label = '◾ :black_medium_small_square:'; insertText = '◾'; filterText = ':black_medium_small_square:' };
+{ word = ':sunny:'; label = '☀️ :sunny:'; insertText = '☀️'; filterText = ':sunny:' };
+{ word = ':cloud:'; label = '☁️ :cloud:'; insertText = '☁️'; filterText = ':cloud:' };
+{ word = ':umbrella:'; label = '☂️ :umbrella:'; insertText = '☂️'; filterText = ':umbrella:' };
+{ word = ':snowman:'; label = '☃️ :snowman:'; insertText = '☃️'; filterText = ':snowman:' };
+{ word = ':comet:'; label = '☄️ :comet:'; insertText = '☄️'; filterText = ':comet:' };
+{ word = ':phone:'; label = '☎️ :phone:'; insertText = '☎️'; filterText = ':phone:' };
+{ word = ':telephone:'; label = '☎️ :telephone:'; insertText = '☎️'; filterText = ':telephone:' };
+{ word = ':ballot_box_with_check:'; label = '☑️ :ballot_box_with_check:'; insertText = '☑️'; filterText = ':ballot_box_with_check:' };
+{ word = ':umbrella_with_rain_drops:'; label = '☔ :umbrella_with_rain_drops:'; insertText = '☔'; filterText = ':umbrella_with_rain_drops:' };
+{ word = ':coffee:'; label = '☕ :coffee:'; insertText = '☕'; filterText = ':coffee:' };
+{ word = ':shamrock:'; label = '☘️ :shamrock:'; insertText = '☘️'; filterText = ':shamrock:' };
+{ word = ':point_up:'; label = '☝️ :point_up:'; insertText = '☝️'; filterText = ':point_up:' };
+{ word = ':skull_and_crossbones:'; label = '☠️ :skull_and_crossbones:'; insertText = '☠️'; filterText = ':skull_and_crossbones:' };
+{ word = ':radioactive_sign:'; label = '☢️ :radioactive_sign:'; insertText = '☢️'; filterText = ':radioactive_sign:' };
+{ word = ':biohazard_sign:'; label = '☣️ :biohazard_sign:'; insertText = '☣️'; filterText = ':biohazard_sign:' };
+{ word = ':orthodox_cross:'; label = '☦️ :orthodox_cross:'; insertText = '☦️'; filterText = ':orthodox_cross:' };
+{ word = ':star_and_crescent:'; label = '☪️ :star_and_crescent:'; insertText = '☪️'; filterText = ':star_and_crescent:' };
+{ word = ':peace_symbol:'; label = '☮️ :peace_symbol:'; insertText = '☮️'; filterText = ':peace_symbol:' };
+{ word = ':yin_yang:'; label = '☯️ :yin_yang:'; insertText = '☯️'; filterText = ':yin_yang:' };
+{ word = ':wheel_of_dharma:'; label = '☸️ :wheel_of_dharma:'; insertText = '☸️'; filterText = ':wheel_of_dharma:' };
+{ word = ':white_frowning_face:'; label = '☹️ :white_frowning_face:'; insertText = '☹️'; filterText = ':white_frowning_face:' };
+{ word = ':relaxed:'; label = '☺️ :relaxed:'; insertText = '☺️'; filterText = ':relaxed:' };
+{ word = ':female_sign:'; label = '♀️ :female_sign:'; insertText = '♀️'; filterText = ':female_sign:' };
+{ word = ':male_sign:'; label = '♂️ :male_sign:'; insertText = '♂️'; filterText = ':male_sign:' };
+{ word = ':aries:'; label = '♈ :aries:'; insertText = '♈'; filterText = ':aries:' };
+{ word = ':taurus:'; label = '♉ :taurus:'; insertText = '♉'; filterText = ':taurus:' };
+{ word = ':gemini:'; label = '♊ :gemini:'; insertText = '♊'; filterText = ':gemini:' };
+{ word = ':cancer:'; label = '♋ :cancer:'; insertText = '♋'; filterText = ':cancer:' };
+{ word = ':leo:'; label = '♌ :leo:'; insertText = '♌'; filterText = ':leo:' };
+{ word = ':virgo:'; label = '♍ :virgo:'; insertText = '♍'; filterText = ':virgo:' };
+{ word = ':libra:'; label = '♎ :libra:'; insertText = '♎'; filterText = ':libra:' };
+{ word = ':scorpius:'; label = '♏ :scorpius:'; insertText = '♏'; filterText = ':scorpius:' };
+{ word = ':sagittarius:'; label = '♐ :sagittarius:'; insertText = '♐'; filterText = ':sagittarius:' };
+{ word = ':capricorn:'; label = '♑ :capricorn:'; insertText = '♑'; filterText = ':capricorn:' };
+{ word = ':aquarius:'; label = '♒ :aquarius:'; insertText = '♒'; filterText = ':aquarius:' };
+{ word = ':pisces:'; label = '♓ :pisces:'; insertText = '♓'; filterText = ':pisces:' };
+{ word = ':chess_pawn:'; label = '♟️ :chess_pawn:'; insertText = '♟️'; filterText = ':chess_pawn:' };
+{ word = ':spades:'; label = '♠️ :spades:'; insertText = '♠️'; filterText = ':spades:' };
+{ word = ':clubs:'; label = '♣️ :clubs:'; insertText = '♣️'; filterText = ':clubs:' };
+{ word = ':hearts:'; label = '♥️ :hearts:'; insertText = '♥️'; filterText = ':hearts:' };
+{ word = ':diamonds:'; label = '♦️ :diamonds:'; insertText = '♦️'; filterText = ':diamonds:' };
+{ word = ':hotsprings:'; label = '♨️ :hotsprings:'; insertText = '♨️'; filterText = ':hotsprings:' };
+{ word = ':recycle:'; label = '♻️ :recycle:'; insertText = '♻️'; filterText = ':recycle:' };
+{ word = ':infinity:'; label = '♾️ :infinity:'; insertText = '♾️'; filterText = ':infinity:' };
+{ word = ':wheelchair:'; label = '♿ :wheelchair:'; insertText = '♿'; filterText = ':wheelchair:' };
+{ word = ':hammer_and_pick:'; label = '⚒️ :hammer_and_pick:'; insertText = '⚒️'; filterText = ':hammer_and_pick:' };
+{ word = ':anchor:'; label = '⚓ :anchor:'; insertText = '⚓'; filterText = ':anchor:' };
+{ word = ':crossed_swords:'; label = '⚔️ :crossed_swords:'; insertText = '⚔️'; filterText = ':crossed_swords:' };
+{ word = ':medical_symbol:'; label = '⚕️ :medical_symbol:'; insertText = '⚕️'; filterText = ':medical_symbol:' };
+{ word = ':staff_of_aesculapius:'; label = '⚕️ :staff_of_aesculapius:'; insertText = '⚕️'; filterText = ':staff_of_aesculapius:' };
+{ word = ':scales:'; label = '⚖️ :scales:'; insertText = '⚖️'; filterText = ':scales:' };
+{ word = ':alembic:'; label = '⚗️ :alembic:'; insertText = '⚗️'; filterText = ':alembic:' };
+{ word = ':gear:'; label = '⚙️ :gear:'; insertText = '⚙️'; filterText = ':gear:' };
+{ word = ':atom_symbol:'; label = '⚛️ :atom_symbol:'; insertText = '⚛️'; filterText = ':atom_symbol:' };
+{ word = ':fleur_de_lis:'; label = '⚜️ :fleur_de_lis:'; insertText = '⚜️'; filterText = ':fleur_de_lis:' };
+{ word = ':warning:'; label = '⚠️ :warning:'; insertText = '⚠️'; filterText = ':warning:' };
+{ word = ':zap:'; label = '⚡ :zap:'; insertText = '⚡'; filterText = ':zap:' };
+{ word = ':transgender_symbol:'; label = '⚧️ :transgender_symbol:'; insertText = '⚧️'; filterText = ':transgender_symbol:' };
+{ word = ':white_circle:'; label = '⚪ :white_circle:'; insertText = '⚪'; filterText = ':white_circle:' };
+{ word = ':black_circle:'; label = '⚫ :black_circle:'; insertText = '⚫'; filterText = ':black_circle:' };
+{ word = ':coffin:'; label = '⚰️ :coffin:'; insertText = '⚰️'; filterText = ':coffin:' };
+{ word = ':funeral_urn:'; label = '⚱️ :funeral_urn:'; insertText = '⚱️'; filterText = ':funeral_urn:' };
+{ word = ':soccer:'; label = '⚽ :soccer:'; insertText = '⚽'; filterText = ':soccer:' };
+{ word = ':baseball:'; label = '⚾ :baseball:'; insertText = '⚾'; filterText = ':baseball:' };
+{ word = ':snowman_without_snow:'; label = '⛄ :snowman_without_snow:'; insertText = '⛄'; filterText = ':snowman_without_snow:' };
+{ word = ':partly_sunny:'; label = '⛅ :partly_sunny:'; insertText = '⛅'; filterText = ':partly_sunny:' };
+{ word = ':thunder_cloud_and_rain:'; label = '⛈️ :thunder_cloud_and_rain:'; insertText = '⛈️'; filterText = ':thunder_cloud_and_rain:' };
+{ word = ':ophiuchus:'; label = '⛎ :ophiuchus:'; insertText = '⛎'; filterText = ':ophiuchus:' };
+{ word = ':pick:'; label = '⛏️ :pick:'; insertText = '⛏️'; filterText = ':pick:' };
+{ word = ':helmet_with_white_cross:'; label = '⛑️ :helmet_with_white_cross:'; insertText = '⛑️'; filterText = ':helmet_with_white_cross:' };
+{ word = ':chains:'; label = '⛓️ :chains:'; insertText = '⛓️'; filterText = ':chains:' };
+{ word = ':no_entry:'; label = '⛔ :no_entry:'; insertText = '⛔'; filterText = ':no_entry:' };
+{ word = ':shinto_shrine:'; label = '⛩️ :shinto_shrine:'; insertText = '⛩️'; filterText = ':shinto_shrine:' };
+{ word = ':church:'; label = '⛪ :church:'; insertText = '⛪'; filterText = ':church:' };
+{ word = ':mountain:'; label = '⛰️ :mountain:'; insertText = '⛰️'; filterText = ':mountain:' };
+{ word = ':umbrella_on_ground:'; label = '⛱️ :umbrella_on_ground:'; insertText = '⛱️'; filterText = ':umbrella_on_ground:' };
+{ word = ':fountain:'; label = '⛲ :fountain:'; insertText = '⛲'; filterText = ':fountain:' };
+{ word = ':golf:'; label = '⛳ :golf:'; insertText = '⛳'; filterText = ':golf:' };
+{ word = ':ferry:'; label = '⛴️ :ferry:'; insertText = '⛴️'; filterText = ':ferry:' };
+{ word = ':boat:'; label = '⛵ :boat:'; insertText = '⛵'; filterText = ':boat:' };
+{ word = ':sailboat:'; label = '⛵ :sailboat:'; insertText = '⛵'; filterText = ':sailboat:' };
+{ word = ':skier:'; label = '⛷️ :skier:'; insertText = '⛷️'; filterText = ':skier:' };
+{ word = ':ice_skate:'; label = '⛸️ :ice_skate:'; insertText = '⛸️'; filterText = ':ice_skate:' };
+{ word = ':person_with_ball:'; label = '⛹️ :person_with_ball:'; insertText = '⛹️'; filterText = ':person_with_ball:' };
+{ word = ':tent:'; label = '⛺ :tent:'; insertText = '⛺'; filterText = ':tent:' };
+{ word = ':fuelpump:'; label = '⛽ :fuelpump:'; insertText = '⛽'; filterText = ':fuelpump:' };
+{ word = ':scissors:'; label = '✂️ :scissors:'; insertText = '✂️'; filterText = ':scissors:' };
+{ word = ':white_check_mark:'; label = '✅ :white_check_mark:'; insertText = '✅'; filterText = ':white_check_mark:' };
+{ word = ':airplane:'; label = '✈️ :airplane:'; insertText = '✈️'; filterText = ':airplane:' };
+{ word = ':email:'; label = '✉️ :email:'; insertText = '✉️'; filterText = ':email:' };
+{ word = ':envelope:'; label = '✉️ :envelope:'; insertText = '✉️'; filterText = ':envelope:' };
+{ word = ':fist:'; label = '✊ :fist:'; insertText = '✊'; filterText = ':fist:' };
+{ word = ':hand:'; label = '✋ :hand:'; insertText = '✋'; filterText = ':hand:' };
+{ word = ':raised_hand:'; label = '✋ :raised_hand:'; insertText = '✋'; filterText = ':raised_hand:' };
+{ word = ':v:'; label = '✌️ :v:'; insertText = '✌️'; filterText = ':v:' };
+{ word = ':writing_hand:'; label = '✍️ :writing_hand:'; insertText = '✍️'; filterText = ':writing_hand:' };
+{ word = ':pencil2:'; label = '✏️ :pencil2:'; insertText = '✏️'; filterText = ':pencil2:' };
+{ word = ':black_nib:'; label = '✒️ :black_nib:'; insertText = '✒️'; filterText = ':black_nib:' };
+{ word = ':heavy_check_mark:'; label = '✔️ :heavy_check_mark:'; insertText = '✔️'; filterText = ':heavy_check_mark:' };
+{ word = ':heavy_multiplication_x:'; label = '✖️ :heavy_multiplication_x:'; insertText = '✖️'; filterText = ':heavy_multiplication_x:' };
+{ word = ':latin_cross:'; label = '✝️ :latin_cross:'; insertText = '✝️'; filterText = ':latin_cross:' };
+{ word = ':star_of_david:'; label = '✡️ :star_of_david:'; insertText = '✡️'; filterText = ':star_of_david:' };
+{ word = ':sparkles:'; label = '✨ :sparkles:'; insertText = '✨'; filterText = ':sparkles:' };
+{ word = ':eight_spoked_asterisk:'; label = '✳️ :eight_spoked_asterisk:'; insertText = '✳️'; filterText = ':eight_spoked_asterisk:' };
+{ word = ':eight_pointed_black_star:'; label = '✴️ :eight_pointed_black_star:'; insertText = '✴️'; filterText = ':eight_pointed_black_star:' };
+{ word = ':snowflake:'; label = '❄️ :snowflake:'; insertText = '❄️'; filterText = ':snowflake:' };
+{ word = ':sparkle:'; label = '❇️ :sparkle:'; insertText = '❇️'; filterText = ':sparkle:' };
+{ word = ':x:'; label = '❌ :x:'; insertText = '❌'; filterText = ':x:' };
+{ word = ':negative_squared_cross_mark:'; label = '❎ :negative_squared_cross_mark:'; insertText = '❎'; filterText = ':negative_squared_cross_mark:' };
+{ word = ':question:'; label = '❓ :question:'; insertText = '❓'; filterText = ':question:' };
+{ word = ':grey_question:'; label = '❔ :grey_question:'; insertText = '❔'; filterText = ':grey_question:' };
+{ word = ':grey_exclamation:'; label = '❕ :grey_exclamation:'; insertText = '❕'; filterText = ':grey_exclamation:' };
+{ word = ':exclamation:'; label = '❗ :exclamation:'; insertText = '❗'; filterText = ':exclamation:' };
+{ word = ':heavy_exclamation_mark:'; label = '❗ :heavy_exclamation_mark:'; insertText = '❗'; filterText = ':heavy_exclamation_mark:' };
+{ word = ':heavy_heart_exclamation_mark_ornament:'; label = '❣️ :heavy_heart_exclamation_mark_ornament:'; insertText = '❣️'; filterText = ':heavy_heart_exclamation_mark_ornament:' };
+{ word = ':heart:'; label = '❤️ :heart:'; insertText = '❤️'; filterText = ':heart:' };
+{ word = ':heavy_plus_sign:'; label = '➕ :heavy_plus_sign:'; insertText = '➕'; filterText = ':heavy_plus_sign:' };
+{ word = ':heavy_minus_sign:'; label = '➖ :heavy_minus_sign:'; insertText = '➖'; filterText = ':heavy_minus_sign:' };
+{ word = ':heavy_division_sign:'; label = '➗ :heavy_division_sign:'; insertText = '➗'; filterText = ':heavy_division_sign:' };
+{ word = ':arrow_right:'; label = '➡️ :arrow_right:'; insertText = '➡️'; filterText = ':arrow_right:' };
+{ word = ':curly_loop:'; label = '➰ :curly_loop:'; insertText = '➰'; filterText = ':curly_loop:' };
+{ word = ':loop:'; label = '➿ :loop:'; insertText = '➿'; filterText = ':loop:' };
+{ word = ':arrow_heading_up:'; label = '⤴️ :arrow_heading_up:'; insertText = '⤴️'; filterText = ':arrow_heading_up:' };
+{ word = ':arrow_heading_down:'; label = '⤵️ :arrow_heading_down:'; insertText = '⤵️'; filterText = ':arrow_heading_down:' };
+{ word = ':arrow_left:'; label = '⬅️ :arrow_left:'; insertText = '⬅️'; filterText = ':arrow_left:' };
+{ word = ':arrow_up:'; label = '⬆️ :arrow_up:'; insertText = '⬆️'; filterText = ':arrow_up:' };
+{ word = ':arrow_down:'; label = '⬇️ :arrow_down:'; insertText = '⬇️'; filterText = ':arrow_down:' };
+{ word = ':black_large_square:'; label = '⬛ :black_large_square:'; insertText = '⬛'; filterText = ':black_large_square:' };
+{ word = ':white_large_square:'; label = '⬜ :white_large_square:'; insertText = '⬜'; filterText = ':white_large_square:' };
+{ word = ':star:'; label = '⭐ :star:'; insertText = '⭐'; filterText = ':star:' };
+{ word = ':o:'; label = '⭕ :o:'; insertText = '⭕'; filterText = ':o:' };
+{ word = ':wavy_dash:'; label = '〰️ :wavy_dash:'; insertText = '〰️'; filterText = ':wavy_dash:' };
+{ word = ':part_alternation_mark:'; label = '〽️ :part_alternation_mark:'; insertText = '〽️'; filterText = ':part_alternation_mark:' };
+{ word = ':congratulations:'; label = '㊗️ :congratulations:'; insertText = '㊗️'; filterText = ':congratulations:' };
+{ word = ':secret:'; label = '㊙️ :secret:'; insertText = '㊙️'; filterText = ':secret:' };
+} end
\ No newline at end of file
diff --git a/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/update.lua b/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/update.lua
new file mode 100644
index 00000000..2f4c7681
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-emoji/lua/cmp_emoji/update.lua
@@ -0,0 +1,58 @@
+-- Generates the emoji data Lua file using this as a source: https://raw.githubusercontent.com/iamcal/emoji-data/master/emoji.json
+
+local M = {}
+
+M._read = function(path)
+ return vim.fn.json_decode(vim.fn.readfile(path))
+end
+
+M._write = function(path, data)
+ local h = io.open(path, 'w')
+ h:write(data)
+ io.close(h)
+end
+
+M.to_string = function(chars)
+ local nrs = {}
+ for _, char in ipairs(chars) do
+ table.insert(nrs, vim.fn.eval(([[char2nr("\U%s")]]):format(char)))
+ end
+ return vim.fn.list2str(nrs, true)
+end
+
+M.to_item = function(emoji, short_name)
+ short_name = ':' .. short_name .. ':'
+ return ("{ word = '%s'; label = '%s'; insertText = '%s'; filterText = '%s' };\n"):format(
+ short_name,
+ emoji .. ' ' .. short_name,
+ emoji,
+ short_name
+ )
+end
+
+M.to_items = function(emoji, short_names)
+ local variants = ''
+
+ for _, short_name in ipairs(short_names) do
+ variants = variants .. M.to_item(emoji, short_name)
+ end
+
+ return variants
+end
+
+M.update = function()
+ local items = ''
+ for _, emoji in ipairs(M._read('./emoji.json')) do
+ local char = M.to_string(vim.split(emoji.unified, '-'))
+
+ local valid = true
+ valid = valid and vim.fn.strdisplaywidth(char) <= 2 -- Ignore invalid ligatures
+ if valid then
+ items = items .. M.to_items(char, emoji.short_names)
+ end
+ end
+ M._write('./items.lua', ('return function() return {\n%s} end'):format(items))
+end
+
+return M
+
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help/README.md b/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help/README.md
new file mode 100644
index 00000000..5d600322
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help/README.md
@@ -0,0 +1,16 @@
+# cmp-nvim-lsp-signature-help
+
+nvim-cmp source for displaying function signatures with the current parameter emphasized:
+
+
+# Setup
+
+```lua
+
+require'cmp'.setup {
+ sources = {
+ { name = 'nvim_lsp_signature_help' }
+ }
+}
+```
+
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help/after/plugin/cmp_nvim_lsp_signature_help.lua b/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help/after/plugin/cmp_nvim_lsp_signature_help.lua
new file mode 100644
index 00000000..6c30f657
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help/after/plugin/cmp_nvim_lsp_signature_help.lua
@@ -0,0 +1 @@
+require('cmp').register_source('nvim_lsp_signature_help', require('cmp_nvim_lsp_signature_help').new())
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help/lua/cmp_nvim_lsp_signature_help/init.lua b/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help/lua/cmp_nvim_lsp_signature_help/init.lua
new file mode 100644
index 00000000..57046414
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help/lua/cmp_nvim_lsp_signature_help/init.lua
@@ -0,0 +1,218 @@
+local cmp = require('cmp')
+
+local source = {}
+
+source.new = function()
+ return setmetatable({
+ signature_help = nil,
+ }, { __index = source })
+end
+
+source.is_available = function(self)
+ return self:_get_client() ~= nil
+end
+
+source.get_keyword_pattern = function(self)
+ return ([=[\%%(\V%s\m\)\s*\zs]=]):format(table.concat(self:get_trigger_characters(), [[\m\|\V]]))
+end
+
+source.get_trigger_characters = function(self)
+ local trigger_characters = {}
+ for _, c in ipairs(self:_get(self:_get_client().server_capabilities, { 'signatureHelpProvider', 'triggerCharacters' })
+ or {}) do
+ table.insert(trigger_characters, c)
+ end
+ for _, c in ipairs(self:_get(self:_get_client().server_capabilities, { 'signatureHelpProvider', 'retriggerCharacters' })
+ or {}) do
+ table.insert(trigger_characters, c)
+ end
+ table.insert(trigger_characters, ' ')
+ return trigger_characters
+end
+
+source.complete = function(self, params, callback)
+ local client = self:_get_client()
+ local trigger_characters = {}
+ for _, c in ipairs(self:_get(client.server_capabilities, { 'signatureHelpProvider', 'triggerCharacters' }) or {}) do
+ table.insert(trigger_characters, c)
+ end
+ for _, c in ipairs(self:_get(client.server_capabilities, { 'signatureHelpProvider', 'retriggerCharacters' }) or {}) do
+ table.insert(trigger_characters, c)
+ end
+
+ local trigger_character = nil
+ for _, c in ipairs(trigger_characters) do
+ local s, e = string.find(params.context.cursor_before_line, '(' .. vim.pesc(c) .. ')%s*$')
+ if s and e then
+ trigger_character = string.sub(params.context.cursor_before_line, s, s)
+ break
+ end
+ end
+ if not trigger_character then
+ return callback({ isIncomplete = true })
+ end
+
+ local request = vim.lsp.util.make_position_params(0, self:_get_client().offset_encoding)
+ request.context = {
+ triggerKind = 2,
+ triggerCharacter = trigger_character,
+ isRetrigger = not not self.signature_help,
+ activeSignatureHelp = self.signature_help,
+ }
+ client.request('textDocument/signatureHelp', request, function(_, signature_help)
+ self.signature_help = signature_help
+
+ if not signature_help then
+ return callback({ isIncomplete = true })
+ end
+
+ self.signature_help.activeSignature = self.signature_help.activeSignature or 0
+ callback({
+ isIncomplete = true,
+ items = self:_items(self.signature_help),
+ })
+ end)
+end
+
+source._items = function(self, signature_help)
+ if not signature_help or not signature_help.signatures then
+ return {}
+ end
+
+ local items = {}
+ for _, signature in ipairs(signature_help.signatures) do
+ local item = self:_item(signature, signature_help.activeParameter)
+ if item then
+ table.insert(items, item)
+ end
+ end
+
+ return items
+end
+
+source._item = function(self, signature, parameter_index)
+ local parameters = signature.parameters
+ if not parameters then
+ return nil
+ end
+
+ parameter_index = (signature.activeParameter or parameter_index or 0) + 1
+
+ -- @see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#signatureHelp
+ if #parameters < parameter_index or parameter_index < 1 then
+ parameter_index = 1
+ end
+
+ local arguments = {}
+ for i, parameter in ipairs(parameters) do
+ if i == parameter_index then
+ table.insert(arguments, self:_parameter_label(signature, parameter))
+ end
+ end
+
+ if #arguments == 0 then
+ return nil
+ end
+
+ local label = table.concat(arguments, ', ')
+ return {
+ label = label,
+ filterText = ' ',
+ insertText = self:_matchstr(label, [[\k\+]]),
+ word = '',
+ preselect = true,
+ documentation = self:_docs(signature, parameter_index),
+ }
+end
+
+source._docs = function(self, signature, parameter_index)
+ local documentation = {}
+
+ -- signature label.
+ if signature.label then
+ table.insert(documentation, self:_signature_label(signature, parameter_index))
+ end
+
+ -- parameter docs.
+ local parameter = signature.parameters[parameter_index]
+ if parameter then
+ if parameter.documentation then
+ table.insert(documentation, '---')
+ if type(parameter.documentation) == 'table' then
+ table.insert(documentation, '```' .. parameter.documentation.kind)
+ table.insert(documentation, parameter.documentation.value)
+ table.insert(documentation, '```')
+ else
+ table.insert(documentation, parameter.documentation)
+ end
+ end
+ end
+
+ -- signature docs.
+ if signature.documentation then
+ table.insert(documentation, '---')
+ if type(signature.documentation) == 'table' then
+ table.insert(documentation, '```' .. signature.documentation.kind)
+ table.insert(documentation, signature.documentation.value)
+ table.insert(documentation, '```')
+ else
+ table.insert(documentation, signature.documentation)
+ end
+ end
+
+ return { kind = 'markdown', value = table.concat(documentation, '\n') }
+end
+
+source._signature_label = function(self, signature, parameter_index)
+ local label = signature.label
+ if parameter_index then
+ local s, e = string.find(label, self:_parameter_label(signature, signature.parameters[parameter_index]), 1, true)
+ if s and e then
+ local active = string.sub(label, s, e)
+ label = string.gsub(label, vim.pesc(active), '***' .. active .. '***')
+ end
+ end
+ return label
+end
+
+source._parameter_label = function(_, signature, parameter)
+ local label = parameter.label
+ if type(label) == 'table' then
+ label = signature.label:sub(
+ 1 + vim.str_byteindex(signature.label, label[1]),
+ vim.str_byteindex(signature.label, label[2])
+ )
+ end
+ return label
+end
+
+source._get_client = function(self)
+ local get_clients = vim.lsp.get_clients or vim.lsp.buf_get_clients
+ for _, client in pairs(get_clients()) do
+ if self:_get(client.server_capabilities, { 'signatureHelpProvider' }) then
+ return client
+ end
+ end
+ return nil
+end
+
+source._get = function(_, root, paths)
+ local c = root
+ for _, path in ipairs(paths) do
+ c = c[path]
+ if not c then
+ return nil
+ end
+ end
+ return c
+end
+
+source._matchstr = function(_, str, pattern)
+ local s, e = vim.regex(pattern):match_str(str)
+ if s and e then
+ return string.sub(str, s+1, e)
+ end
+ return ''
+end
+
+return source
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp/.gitignore b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/.gitignore
new file mode 100644
index 00000000..0a56e3fc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/.gitignore
@@ -0,0 +1 @@
+/doc/tags
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp/LICENSE b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/LICENSE
new file mode 100644
index 00000000..ae725ef1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 hrsh7th
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp/README.md b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/README.md
new file mode 100644
index 00000000..dba8c530
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/README.md
@@ -0,0 +1,59 @@
+# cmp-nvim-lsp
+
+nvim-cmp source for neovim's built-in language server client.
+
+## Capabilities
+
+Language servers provide different completion results depending on the capabilities of the client. Neovim's default omnifunc has basic support for serving completion candidates. nvim-cmp supports more types of completion candidates, so users must override the capabilities sent to the server such that it can provide these candidates during a completion request. These capabilities are provided via the helper function `require('cmp_nvim_lsp').default_capabilities`
+
+As these candidates are sent on each request, **adding these capabilities will break the built-in omnifunc support for neovim's language server client**. `nvim-cmp` provides manually triggered completion that can replace omnifunc. See `:help cmp-faq` for more details.
+
+## Setup
+
+```lua
+
+require'cmp'.setup {
+ sources = {
+ { name = 'nvim_lsp' }
+ }
+}
+
+-- The nvim-cmp almost supports LSP's capabilities so You should advertise it to LSP servers..
+local capabilities = require('cmp_nvim_lsp').default_capabilities()
+
+-- An example for configuring `clangd` LSP to use nvim-cmp as a completion engine
+require('lspconfig').clangd.setup {
+ capabilities = capabilities,
+ ... -- other lspconfig configs
+}
+```
+
+## Option
+
+`[%LSPCONFIG-NAME%].keyword_pattern`
+
+You can override keyword_pattern for specific language-server like this.
+
+```lua
+cmp.setup {
+ ...
+ sources = {
+ {
+ name = 'nvim_lsp',
+ option = {
+ php = {
+ keyword_pattern = [=[[\%(\$\k*\)\|\k\+]]=],
+ }
+ }
+ }
+ }
+ ...
+}
+```
+
+
+## Readme!
+
+1. There is a Github issue that documents [breaking changes](https://github.com/hrsh7th/cmp-nvim-lsp/issues/38) for cmp-nvim-lsp. Subscribe to the issue to be notified of upcoming breaking changes.
+2. This is my hobby project. You can support me via GitHub sponsors.
+3. Bug reports are welcome, but don't expect a fix unless you provide minimal configuration and steps to reproduce your issue.
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp/after/plugin/cmp_nvim_lsp.lua b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/after/plugin/cmp_nvim_lsp.lua
new file mode 100644
index 00000000..6d566fa0
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/after/plugin/cmp_nvim_lsp.lua
@@ -0,0 +1 @@
+require('cmp_nvim_lsp').setup()
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp/doc/cmp-nvim-lsp.txt b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/doc/cmp-nvim-lsp.txt
new file mode 100644
index 00000000..28e3700a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/doc/cmp-nvim-lsp.txt
@@ -0,0 +1,29 @@
+*cmp-nvim-lsp*
+
+==============================================================================
+CONTENTS *cmp-nvim-lsp-contents*
+
+FAQ |cmp-nvim-lsp-faq|
+
+
+
+==============================================================================
+FAQ *cmp-nvim-lsp-faq*
+
+How to disable specific LSP server's cmpletion?~
+
+ You can disable specific LSP server's cmpletion by adding the following
+
+>
+ require('lspconfig')[%YOUR_LSP_SERVER%].setup {
+ on_attach = function(client)
+ client.server_capabilities.completionProvider = false
+ end
+ }
+<
+
+
+
+==============================================================================
+ vim:tw=78:ts=2:et:ft=help:norl:
+
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp/lua/cmp_nvim_lsp/init.lua b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/lua/cmp_nvim_lsp/init.lua
new file mode 100644
index 00000000..23722af3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/lua/cmp_nvim_lsp/init.lua
@@ -0,0 +1,142 @@
+local source = require('cmp_nvim_lsp.source')
+
+local M = {}
+
+---Registered client and source mapping.
+M.client_source_map = {}
+
+---Setup cmp-nvim-lsp source.
+M.setup = function()
+ vim.api.nvim_create_autocmd('InsertEnter', {
+ group = vim.api.nvim_create_augroup('cmp_nvim_lsp', { clear = true }),
+ pattern = '*',
+ callback = M._on_insert_enter
+ })
+end
+
+local if_nil = function(val, default)
+ if val == nil then return default end
+ return val
+end
+
+-- Backported from vim.deprecate (0.9.0+)
+local function deprecate(name, alternative, version, plugin, backtrace)
+ local message = name .. ' is deprecated'
+ plugin = plugin or 'Nvim'
+ message = alternative and (message .. ', use ' .. alternative .. ' instead.') or message
+ message = message
+ .. ' See :h deprecated\nThis function will be removed in '
+ .. plugin
+ .. ' version '
+ .. version
+ if vim.notify_once(message, vim.log.levels.WARN) and backtrace ~= false then
+ vim.notify(debug.traceback('', 2):sub(2), vim.log.levels.WARN)
+ end
+end
+
+M.default_capabilities = function(override)
+ override = override or {}
+
+ return {
+ textDocument = {
+ completion = {
+ dynamicRegistration = if_nil(override.dynamicRegistration, false),
+ completionItem = {
+ snippetSupport = if_nil(override.snippetSupport, true),
+ commitCharactersSupport = if_nil(override.commitCharactersSupport, true),
+ deprecatedSupport = if_nil(override.deprecatedSupport, true),
+ preselectSupport = if_nil(override.preselectSupport, true),
+ tagSupport = if_nil(override.tagSupport, {
+ valueSet = {
+ 1, -- Deprecated
+ }
+ }),
+ insertReplaceSupport = if_nil(override.insertReplaceSupport, true),
+ resolveSupport = if_nil(override.resolveSupport, {
+ properties = {
+ "documentation",
+ "detail",
+ "additionalTextEdits",
+ "sortText",
+ "filterText",
+ "insertText",
+ "textEdit",
+ "insertTextFormat",
+ "insertTextMode",
+ },
+ }),
+ insertTextModeSupport = if_nil(override.insertTextModeSupport, {
+ valueSet = {
+ 1, -- asIs
+ 2, -- adjustIndentation
+ }
+ }),
+ labelDetailsSupport = if_nil(override.labelDetailsSupport, true),
+ },
+ contextSupport = if_nil(override.snippetSupport, true),
+ insertTextMode = if_nil(override.insertTextMode, 1),
+ completionList = if_nil(override.completionList, {
+ itemDefaults = {
+ 'commitCharacters',
+ 'editRange',
+ 'insertTextFormat',
+ 'insertTextMode',
+ 'data',
+ }
+ })
+ },
+ },
+ }
+end
+
+---Backwards compatibility
+M.update_capabilities = function(_, override)
+ local _deprecate = vim.deprecate or deprecate
+ _deprecate('cmp_nvim_lsp.update_capabilities', 'cmp_nvim_lsp.default_capabilities', '1.0.0', 'cmp-nvim-lsp')
+ return M.default_capabilities(override)
+end
+
+
+---Refresh sources on InsertEnter.
+M._on_insert_enter = function()
+ local cmp = require('cmp')
+
+ local allowed_clients = {}
+
+ local get_clients = (
+ vim.lsp.get_clients ~= nil and vim.lsp.get_clients -- nvim 0.10+
+ or vim.lsp.get_active_clients
+ )
+
+ -- register all active clients.
+ for _, client in ipairs(get_clients()) do
+ allowed_clients[client.id] = client
+ if not M.client_source_map[client.id] then
+ local s = source.new(client)
+ if s:is_available() then
+ M.client_source_map[client.id] = cmp.register_source('nvim_lsp', s)
+ end
+ end
+ end
+
+ -- register all buffer clients (early register before activation)
+ for _, client in ipairs(get_clients({ bufnr = 0 })) do
+ allowed_clients[client.id] = client
+ if not M.client_source_map[client.id] then
+ local s = source.new(client)
+ if s:is_available() then
+ M.client_source_map[client.id] = cmp.register_source('nvim_lsp', s)
+ end
+ end
+ end
+
+ -- unregister stopped/detached clients.
+ for client_id, source_id in pairs(M.client_source_map) do
+ if not allowed_clients[client_id] or allowed_clients[client_id]:is_stopped() then
+ cmp.unregister_source(source_id)
+ M.client_source_map[client_id] = nil
+ end
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/cmp-nvim-lsp/lua/cmp_nvim_lsp/source.lua b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/lua/cmp_nvim_lsp/source.lua
new file mode 100644
index 00000000..43ccac10
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp-nvim-lsp/lua/cmp_nvim_lsp/source.lua
@@ -0,0 +1,160 @@
+local source = {}
+
+source.new = function(client)
+ local self = setmetatable({}, { __index = source })
+ self.client = client
+ self.request_ids = {}
+ return self
+end
+
+---Get debug name.
+---@return string
+source.get_debug_name = function(self)
+ return table.concat({ 'nvim_lsp', self.client.name }, ':')
+end
+
+---Return the source is available.
+---@return boolean
+source.is_available = function(self)
+ -- client is stopped.
+ if self.client.is_stopped() then
+ return false
+ end
+
+ -- client is not attached to current buffer.
+ local bufnr = vim.api.nvim_get_current_buf()
+ local get_clients = (
+ vim.lsp.get_clients ~= nil and vim.lsp.get_clients -- nvim 0.10+
+ or vim.lsp.get_active_clients
+ )
+ if vim.tbl_isempty(get_clients({ bufnr = bufnr, id = self.client.id })) then
+ return false
+ end
+
+ -- client has no completion capability.
+ if not self:_get(self.client.server_capabilities, { 'completionProvider' }) then
+ return false
+ end
+ return true;
+end
+
+---Get LSP's PositionEncodingKind.
+---@return lsp.PositionEncodingKind
+source.get_position_encoding_kind = function(self)
+ return self:_get(self.client.server_capabilities, { 'positionEncoding' }) or self.client.offset_encoding or 'utf-16'
+end
+
+---Get triggerCharacters.
+---@return string[]
+source.get_trigger_characters = function(self)
+ return self:_get(self.client.server_capabilities, { 'completionProvider', 'triggerCharacters' }) or {}
+end
+
+---Get get_keyword_pattern.
+---@param params cmp.SourceApiParams
+---@return string
+source.get_keyword_pattern = function(self, params)
+ local option
+ option = params.option or {}
+ option = option[self.client.name] or {}
+ return option.keyword_pattern or require('cmp').get_config().completion.keyword_pattern
+end
+
+---Resolve LSP CompletionItem.
+---@param params cmp.SourceCompletionApiParams
+---@param callback function
+source.complete = function(self, params, callback)
+ local lsp_params = vim.lsp.util.make_position_params(0, self.client.offset_encoding)
+ lsp_params.context = {}
+ lsp_params.context.triggerKind = params.completion_context.triggerKind
+ lsp_params.context.triggerCharacter = params.completion_context.triggerCharacter
+ self:_request('textDocument/completion', lsp_params, function(_, response)
+ callback(response)
+ end)
+end
+
+---Resolve LSP CompletionItem.
+---@param completion_item lsp.CompletionItem
+---@param callback function
+source.resolve = function(self, completion_item, callback)
+ -- client is stopped.
+ if self.client.is_stopped() then
+ return callback()
+ end
+
+ -- client has no completion capability.
+ if not self:_get(self.client.server_capabilities, { 'completionProvider', 'resolveProvider' }) then
+ return callback()
+ end
+
+ self:_request('completionItem/resolve', completion_item, function(_, response)
+ callback(response or completion_item)
+ end)
+end
+
+---Execute LSP CompletionItem.
+---@param completion_item lsp.CompletionItem
+---@param callback function
+source.execute = function(self, completion_item, callback)
+ -- client is stopped.
+ if self.client.is_stopped() then
+ return callback()
+ end
+
+ -- completion_item has no command.
+ if not completion_item.command then
+ return callback()
+ end
+
+ self:_request('workspace/executeCommand', completion_item.command, function(_, _)
+ callback()
+ end)
+end
+
+---Get object path.
+---@param root table
+---@param paths string[]
+---@return any
+source._get = function(_, root, paths)
+ local c = root
+ for _, path in ipairs(paths) do
+ c = c[path]
+ if not c then
+ return nil
+ end
+ end
+ return c
+end
+
+---Send request to nvim-lsp servers with backward compatibility.
+---@param method string
+---@param params table
+---@param callback function
+source._request = function(self, method, params, callback)
+ if self.request_ids[method] ~= nil then
+ self.client.cancel_request(self.request_ids[method])
+ self.request_ids[method] = nil
+ end
+ local _, request_id
+ _, request_id = self.client.request(method, params, function(arg1, arg2, arg3)
+ if self.request_ids[method] ~= request_id then
+ return
+ end
+ self.request_ids[method] = nil
+
+ -- Text changed, retry
+ if arg1 and arg1.code == -32801 then
+ self:_request(method, params, callback)
+ return
+ end
+
+ if method == arg2 then
+ callback(arg1, arg3) -- old signature
+ else
+ callback(arg1, arg2) -- new signature
+ end
+ end)
+ self.request_ids[method] = request_id
+end
+
+return source
diff --git a/config/neovim/store/lazy-plugins/cmp_luasnip/LICENSE b/config/neovim/store/lazy-plugins/cmp_luasnip/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp_luasnip/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/config/neovim/store/lazy-plugins/cmp_luasnip/README.md b/config/neovim/store/lazy-plugins/cmp_luasnip/README.md
new file mode 100644
index 00000000..eb692f3d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp_luasnip/README.md
@@ -0,0 +1,55 @@
+# cmp_luasnip
+
+[luasnip](https://github.com/L3MON4D3/LuaSnip) completion source for [nvim-cmp](https://github.com/hrsh7th/nvim-cmp)
+
+```lua
+-- Installation
+use { 'L3MON4D3/LuaSnip' }
+use {
+ 'hrsh7th/nvim-cmp',
+ config = function ()
+ require'cmp'.setup {
+ snippet = {
+ expand = function(args)
+ require'luasnip'.lsp_expand(args.body)
+ end
+ },
+
+ sources = {
+ { name = 'luasnip' },
+ -- more sources
+ },
+ }
+ end
+}
+use { 'saadparwaiz1/cmp_luasnip' }
+```
+
+To disable filtering completion candidates by snippet's `show_condition`
+use the following options in `sources`:
+
+```lua
+sources = {
+ { name = 'luasnip', option = { use_show_condition = false } },
+ -- more sources
+},
+```
+
+This can also be configured on per-buffer basis as described in cmp's README
+[here](https://github.com/hrsh7th/nvim-cmp#how-to-disable-nvim-cmp-on-the-specific-buffer)
+and [here](https://github.com/hrsh7th/nvim-cmp#sources-type-tablecmpsourceconfig).
+
+The same way you can de-/activate whether autosnippets should be included in the
+completion list or not (including them can be a bit problematic since when you
+select the entry, the text gets inserted and the snippet automatically
+triggers). This option defaults to `false` to be backwards compatible. Example:
+
+```lua
+sources = {
+ { name = 'luasnip', option = { show_autosnippets = true } },
+ -- more sources
+},
+```
+
+Hint: If you want to just hide some autosnippets consider the `hidden` option of
+luaSnip
diff --git a/config/neovim/store/lazy-plugins/cmp_luasnip/after/plugin/cmp_luasnip.lua b/config/neovim/store/lazy-plugins/cmp_luasnip/after/plugin/cmp_luasnip.lua
new file mode 100644
index 00000000..0ddc5b6c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp_luasnip/after/plugin/cmp_luasnip.lua
@@ -0,0 +1,19 @@
+require("cmp").register_source("luasnip", require("cmp_luasnip").new())
+
+local cmp_luasnip = vim.api.nvim_create_augroup("cmp_luasnip", {})
+
+vim.api.nvim_create_autocmd("User", {
+ pattern = "LuasnipCleanup",
+ callback = function ()
+ require("cmp_luasnip").clear_cache()
+ end,
+ group = cmp_luasnip
+})
+
+vim.api.nvim_create_autocmd("User", {
+ pattern = "LuasnipSnippetsAdded",
+ callback = function ()
+ require("cmp_luasnip").refresh()
+ end,
+ group = cmp_luasnip
+})
diff --git a/config/neovim/store/lazy-plugins/cmp_luasnip/lua/cmp_luasnip/init.lua b/config/neovim/store/lazy-plugins/cmp_luasnip/lua/cmp_luasnip/init.lua
new file mode 100644
index 00000000..46415795
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp_luasnip/lua/cmp_luasnip/init.lua
@@ -0,0 +1,178 @@
+local cmp = require("cmp")
+local util = require("vim.lsp.util")
+
+local source = {}
+
+local defaults = {
+ use_show_condition = true,
+ show_autosnippets = false,
+}
+
+-- the options are being passed via cmp.setup.sources, e.g.
+-- require('cmp').setup { sources = { { name = 'luasnip', opts = {...} } } }
+local function init_options(params)
+ params.option = vim.tbl_deep_extend('keep', params.option, defaults)
+ vim.validate({
+ use_show_condition = { params.option.use_show_condition, 'boolean' },
+ show_autosnippets = { params.option.show_autosnippets, 'boolean' },
+ })
+end
+
+local snip_cache = {}
+local doc_cache = {}
+
+source.clear_cache = function()
+ snip_cache = {}
+ doc_cache = {}
+end
+
+source.refresh = function()
+ local ft = require("luasnip.session").latest_load_ft
+ snip_cache[ft] = nil
+ doc_cache[ft] = nil
+end
+
+local function get_documentation(snip, data)
+ local header = (snip.name or "") .. " _ `[" .. data.filetype .. "]`\n"
+ local docstring = { "", "```" .. vim.bo.filetype, snip:get_docstring(), "```" }
+ local documentation = { header .. "---", (snip.dscr or ""), docstring }
+ documentation = util.convert_input_to_markdown_lines(documentation)
+ documentation = table.concat(documentation, "\n")
+
+ doc_cache[data.filetype] = doc_cache[data.filetype] or {}
+ doc_cache[data.filetype][data.snip_id] = documentation
+ return documentation
+end
+
+source.new = function()
+ return setmetatable({}, { __index = source })
+end
+
+source.get_keyword_pattern = function()
+ return "\\%([^[:alnum:][:blank:]]\\|\\w\\+\\)"
+end
+
+function source:is_available()
+ local ok, _ = pcall(require, "luasnip")
+ return ok
+end
+
+function source:get_debug_name()
+ return "luasnip"
+end
+
+function source:complete(params, callback)
+ init_options(params)
+
+ local filetypes = require("luasnip.util.util").get_snippet_filetypes()
+ local items = {}
+
+ for i = 1, #filetypes do
+ local ft = filetypes[i]
+ if not snip_cache[ft] then
+ -- ft not yet in cache.
+ local ft_items = {}
+ local ft_table = require("luasnip").get_snippets(ft, {type = "snippets"})
+ local iter_tab
+ if params.option.show_autosnippets then
+ local auto_table = require('luasnip').get_snippets(ft, {type="autosnippets"})
+ iter_tab = {{ft_table, false}, {auto_table, true}}
+ else
+ iter_tab = {{ft_table, false}}
+ end
+ for _,ele in ipairs(iter_tab) do
+ local tab,auto = unpack(ele)
+ for j, snip in pairs(tab) do
+ if not snip.hidden then
+ ft_items[#ft_items + 1] = {
+ word = snip.trigger,
+ label = snip.trigger,
+ kind = cmp.lsp.CompletionItemKind.Snippet,
+ data = {
+ filetype = ft,
+ snip_id = snip.id,
+ show_condition = snip.show_condition,
+ auto = auto
+ },
+ }
+ end
+ end
+ end
+ snip_cache[ft] = ft_items
+ end
+ vim.list_extend(items, snip_cache[ft])
+ end
+
+ if params.option.use_show_condition then
+ local line_to_cursor = params.context.cursor_before_line
+ items = vim.tbl_filter(function(i)
+ -- check if show_condition exists in case (somehow) user updated cmp_luasnip but not luasnip
+ return not i.data.show_condition or i.data.show_condition(line_to_cursor)
+ end, items)
+ end
+
+ callback(items)
+end
+
+function source:resolve(completion_item, callback)
+ local item_snip_id = completion_item.data.snip_id
+ local snip = require("luasnip").get_id_snippet(item_snip_id)
+ local doc_itm = doc_cache[completion_item.data.filetype] or {}
+ doc_itm = doc_itm[completion_item.data.snip_id] or get_documentation(snip, completion_item.data)
+ completion_item.documentation = {
+ kind = cmp.lsp.MarkupKind.Markdown,
+ value = doc_itm,
+ }
+ callback(completion_item)
+end
+
+function source:execute(completion_item, callback)
+ local snip = require("luasnip").get_id_snippet(completion_item.data.snip_id)
+
+ -- if trigger is a pattern, expand "pattern" instead of actual snippet.
+ if snip.regTrig then
+ snip = snip:get_pattern_expand_helper()
+ end
+
+ local cursor = vim.api.nvim_win_get_cursor(0)
+ -- get_cursor returns (1,0)-indexed position, clear_region expects (0,0)-indexed.
+ cursor[1] = cursor[1] - 1
+ local line = require("luasnip.util.util").get_current_line_to_cursor()
+
+ local expand_params = snip:matches(line)
+
+ local clear_region = {
+ from = {
+ cursor[1],
+ cursor[2] - #completion_item.word
+ },
+ to = cursor
+ }
+ if expand_params ~= nil then
+ if expand_params.clear_region ~= nil then
+ clear_region = expand_params.clear_region
+ else
+ if expand_params.trigger ~= nil then
+ clear_region = {
+ from = {
+ cursor[1],
+ cursor[2] - #expand_params.trigger,
+ },
+ to = cursor,
+ }
+ end
+ end
+ end
+
+ -- text cannot be cleared before, as TM_CURRENT_LINE and
+ -- TM_CURRENT_WORD couldn't be set correctly.
+ require("luasnip").snip_expand(snip, {
+ -- clear word inserted into buffer by cmp.
+ -- cursor is currently behind word.
+ clear_region = clear_region,
+ expand_params = expand_params,
+ })
+ callback(completion_item)
+end
+
+return source
diff --git a/config/neovim/store/lazy-plugins/cmp_luasnip/stylua.toml b/config/neovim/store/lazy-plugins/cmp_luasnip/stylua.toml
new file mode 100644
index 00000000..25e10305
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/cmp_luasnip/stylua.toml
@@ -0,0 +1,6 @@
+column_width = 120
+line_endings = "Unix"
+indent_type = "Tabs"
+indent_width = 4
+quote_style = "AutoPreferDouble"
+no_call_parentheses = false
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/.github/workflows/ci.yaml b/config/neovim/store/lazy-plugins/comment.nvim/.github/workflows/ci.yaml
new file mode 100644
index 00000000..0b734385
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/.github/workflows/ci.yaml
@@ -0,0 +1,33 @@
+name: ci
+
+on:
+ push:
+ paths:
+ - "**.lua"
+ branches:
+ - master
+
+env:
+ PLUGIN_NAME: Comment
+
+jobs:
+ docs:
+ runs-on: ubuntu-latest
+ name: emmylua to help doc
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Generating help
+ shell: bash
+ run: |
+ curl -Lq https://github.com/numToStr/lemmy-help/releases/latest/download/lemmy-help-x86_64-unknown-linux-gnu.tar.gz | tar xz
+ ./lemmy-help -fact \
+ lua/Comment/{init.lua,config.lua} plugin/Comment.lua \
+ lua/Comment/{api.lua,ft.lua,utils.lua,opfunc.lua,extra.lua} > doc/${{env.PLUGIN_NAME}}.txt
+
+ - name: Commit
+ uses: stefanzweifel/git-auto-commit-action@v4
+ with:
+ branch: ${{ github.head_ref }}
+ commit_message: "chore(docs): auto-generate `:help` doc"
+ file_pattern: doc/*.txt
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/.gitignore b/config/neovim/store/lazy-plugins/comment.nvim/.gitignore
new file mode 100644
index 00000000..8aa6b8d5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/.gitignore
@@ -0,0 +1,46 @@
+# Compiled Lua sources
+luac.out
+
+# luarocks build files
+*.src.rock
+*.zip
+*.tar.gz
+
+# Object files
+*.o
+*.os
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+*.def
+*.exp
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+tmp
+scratch
+
+# ignore generated doc tags
+doc/tags
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/LICENSE b/config/neovim/store/lazy-plugins/comment.nvim/LICENSE
new file mode 100644
index 00000000..e7f6a020
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Vikas Raj
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/README.md b/config/neovim/store/lazy-plugins/comment.nvim/README.md
new file mode 100644
index 00000000..0f8454cd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/README.md
@@ -0,0 +1,360 @@
+// Comment.nvim
+⚡ Smart and Powerful commenting plugin for neovim ⚡
+
+
+
+### ✨ Features
+
+- Supports treesitter. [Read more](#treesitter)
+- Supports `commentstring`. Read `:h comment.commentstring`
+- Supports line (`//`) and block (`/* */`) comments
+- Dot (`.`) repeat support for `gcc`, `gbc` and friends
+- Count support for `[count]gcc` and `[count]gbc`
+- Left-right (`gcw` `gc$`) and Up-Down (`gc2j` `gc4k`) motions
+- Use with text-objects (`gci{` `gbat`)
+- Supports pre and post hooks
+- Ignore certain lines, powered by Lua regex
+
+### 🚀 Installation
+
+- With [lazy.nvim](https://github.com/folke/lazy.nvim)
+
+```lua
+-- add this to your lua/plugins.lua, lua/plugins/init.lua, or the file you keep your other plugins:
+{
+ 'numToStr/Comment.nvim',
+ opts = {
+ -- add any options here
+ },
+ lazy = false,
+}
+
+```
+
+- With [packer.nvim](https://github.com/wbthomason/packer.nvim)
+
+```lua
+use {
+ 'numToStr/Comment.nvim',
+ config = function()
+ require('Comment').setup()
+ end
+}
+```
+
+- With [vim-plug](https://github.com/junegunn/vim-plug)
+
+```vim
+Plug 'numToStr/Comment.nvim'
+
+" Somewhere after plug#end()
+lua require('Comment').setup()
+```
+
+### 📖 Getting Help
+
+`Comment.nvim` provides help docs which can be accessed by running `:help comment-nvim`
+
+
+
+### ⚒️ Setup
+
+First you need to call the `setup()` method to create the default mappings.
+
+> **Note** - If you are facing **Keybindings are mapped but they are not working** issue then please try [this](https://github.com/numToStr/Comment.nvim/issues/115#issuecomment-1032290098)
+
+- Lua
+
+```lua
+require('Comment').setup()
+```
+
+- VimL
+
+```vim
+lua << EOF
+require('Comment').setup()
+EOF
+```
+
+
+
+#### Configuration (optional)
+
+Following are the **default** config for the [`setup()`](#setup). If you want to override, just modify the option that you want then it will be merged with the default config. Read `:h comment.config` for more info.
+
+```lua
+{
+ ---Add a space b/w comment and the line
+ padding = true,
+ ---Whether the cursor should stay at its position
+ sticky = true,
+ ---Lines to be ignored while (un)comment
+ ignore = nil,
+ ---LHS of toggle mappings in NORMAL mode
+ toggler = {
+ ---Line-comment toggle keymap
+ line = 'gcc',
+ ---Block-comment toggle keymap
+ block = 'gbc',
+ },
+ ---LHS of operator-pending mappings in NORMAL and VISUAL mode
+ opleader = {
+ ---Line-comment keymap
+ line = 'gc',
+ ---Block-comment keymap
+ block = 'gb',
+ },
+ ---LHS of extra mappings
+ extra = {
+ ---Add comment on the line above
+ above = 'gcO',
+ ---Add comment on the line below
+ below = 'gco',
+ ---Add comment at the end of line
+ eol = 'gcA',
+ },
+ ---Enable keybindings
+ ---NOTE: If given `false` then the plugin won't create any mappings
+ mappings = {
+ ---Operator-pending mapping; `gcc` `gbc` `gc[count]{motion}` `gb[count]{motion}`
+ basic = true,
+ ---Extra mapping; `gco`, `gcO`, `gcA`
+ extra = true,
+ },
+ ---Function to call before (un)comment
+ pre_hook = nil,
+ ---Function to call after (un)comment
+ post_hook = nil,
+}
+```
+
+### 🔥 Usage
+
+When you call [`setup()`](#setup) method, `Comment.nvim` sets up some basic mapping which can be used in NORMAL and VISUAL mode to get you started with the pleasure of commenting stuff out.
+
+
+
+#### Basic mappings
+
+These mappings are enabled by default. (config: `mappings.basic`)
+
+- NORMAL mode
+
+```help
+`gcc` - Toggles the current line using linewise comment
+`gbc` - Toggles the current line using blockwise comment
+`[count]gcc` - Toggles the number of line given as a prefix-count using linewise
+`[count]gbc` - Toggles the number of line given as a prefix-count using blockwise
+`gc[count]{motion}` - (Op-pending) Toggles the region using linewise comment
+`gb[count]{motion}` - (Op-pending) Toggles the region using blockwise comment
+```
+
+- VISUAL mode
+
+```help
+`gc` - Toggles the region using linewise comment
+`gb` - Toggles the region using blockwise comment
+```
+
+
+
+#### Extra mappings
+
+These mappings are enabled by default. (config: `mappings.extra`)
+
+- NORMAL mode
+
+```help
+`gco` - Insert comment to the next line and enters INSERT mode
+`gcO` - Insert comment to the previous line and enters INSERT mode
+`gcA` - Insert comment to end of the current line and enters INSERT mode
+```
+
+##### Examples
+
+```help
+# Linewise
+
+`gcw` - Toggle from the current cursor position to the next word
+`gc$` - Toggle from the current cursor position to the end of line
+`gc}` - Toggle until the next blank line
+`gc5j` - Toggle 5 lines after the current cursor position
+`gc8k` - Toggle 8 lines before the current cursor position
+`gcip` - Toggle inside of paragraph
+`gca}` - Toggle around curly brackets
+
+# Blockwise
+
+`gb2}` - Toggle until the 2 next blank line
+`gbaf` - Toggle comment around a function (w/ LSP/treesitter support)
+`gbac` - Toggle comment around a class (w/ LSP/treesitter support)
+```
+
+
+
+### 🌳 Treesitter
+
+This plugin has native **treesitter** support for calculating `commentstring` which works for multiple (injected/embedded) languages like Vue or Markdown. But due to the nature of the parsed tree, this implementation has some known limitations.
+
+1. No `jsx/tsx` support. Its implementation was quite complicated.
+2. Invalid comment on the region where one language ends and the other starts. [Read more](https://github.com/numToStr/Comment.nvim/pull/62#issuecomment-972790418)
+3. Unexpected comment on a line with multiple languages. [#144](https://github.com/numToStr/Comment.nvim/issues/144)
+
+For advance use cases, use [nvim-ts-context-commentstring](https://github.com/JoosepAlviste/nvim-ts-context-commentstring). See [`pre_hook`](#pre-hook) section for the integration.
+
+> **Note** - This plugin does not depend on [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) however it is recommended in order to easily install tree-sitter parsers.
+
+
+
+### 🎣 Hooks
+
+There are two hook methods i.e `pre_hook` and `post_hook` which are called before comment and after comment respectively. Both should be provided during [`setup()`](#setup).
+
+
+
+- `pre_hook` - Called with a `ctx` argument (Read `:h comment.utils.CommentCtx`) before (un)comment. Can optionally return a `commentstring` to be used for (un)commenting.
+
+```lua
+{
+ pre_hook = function(ctx)
+ if ctx.range.srow == ctx.range.erow then
+ -- do something with the current line
+ else
+ -- do something with lines range
+ end
+ end,
+}
+```
+
+You can also integrate [nvim-ts-context-commentstring](https://github.com/JoosepAlviste/nvim-ts-context-commentstring#commentnvim) using `pre_hook` to easily comment `tsx/jsx` files.
+
+> **Note** - `Comment.nvim` already supports [`treesitter`](#treesitter) out-of-the-box for all the languages except `tsx/jsx`.
+
+```lua
+{
+ pre_hook = require('ts_context_commentstring.integrations.comment_nvim').create_pre_hook(),
+}
+```
+
+
+
+- `post_hook` - This method is called after (un)commenting. It receives the same `ctx` (Read `:h comment.utils.CommentCtx`) argument as [`pre_hook`](#pre_hook).
+
+```lua
+{
+ post_hook = function(ctx)
+ if ctx.range.srow == ctx.range.erow then
+ -- do something with the current line
+ else
+ -- do something with lines range
+ end
+ end,
+}
+```
+
+The `post_hook` can be implemented to cover some niche use cases like the following:
+
+- Using newlines instead of padding e.g. for commenting out code in C with `#if 0`. See an example [here](https://github.com/numToStr/Comment.nvim/issues/38#issuecomment-945082507).
+- Duplicating the commented block (using `pre_hook`) and moving the cursor to the next block (using `post_hook`). See [this](https://github.com/numToStr/Comment.nvim/issues/70).
+
+> NOTE: When pressing `gc`, `gb` and friends, `cmode` (Comment mode) inside `pre_hook` will always be toggle because when pre-hook is called, in that moment we don't know whether `gc` or `gb` will comment or uncomment the lines. But luckily, we do know this before `post_hook` and this will always receive either comment or uncomment status
+
+### 🚫 Ignoring lines
+
+You can use `ignore` to ignore certain lines during comment/uncomment. It can takes lua regex string or a function that returns a regex string and should be provided during [`setup()`](#setup).
+
+> NOTE: Ignore only works when with linewise comment. This is by design. As ignoring lines in block comments doesn't make that much sense.
+
+- With `string`
+
+```lua
+-- ignores empty lines
+ignore = '^$'
+
+-- ignores line that starts with `local` (excluding any leading whitespace)
+ignore = '^(%s*)local'
+
+-- ignores any lines similar to arrow function
+ignore = '^const(.*)=(%s?)%((.*)%)(%s?)=>'
+```
+
+- With `function`
+
+```lua
+{
+ ignore = function()
+ -- Only ignore empty lines for lua files
+ if vim.bo.filetype == 'lua' then
+ return '^$'
+ end
+ end,
+}
+```
+
+
+
+### 🗨️ Filetypes + Languages
+
+Most languages/filetypes have native support for comments via `commentstring` but there might be a filetype that is not supported. There are two ways to enable commenting for unsupported filetypes:
+
+1. You can set `commentstring` for that particular filetype like the following. Read `:h commentstring` for more info.
+
+```lua
+vim.bo.commentstring = '//%s'
+
+-- or
+vim.api.nvim_command('set commentstring=//%s')
+```
+
+
+
+2. You can also use this plugin interface to store both line and block commentstring for the filetype. You can treat this as a more powerful version of the `commentstring`. Read `:h comment.ft` for more info.
+
+```lua
+local ft = require('Comment.ft')
+
+-- 1. Using set function
+
+ft
+ -- Set only line comment
+ .set('yaml', '#%s')
+ -- Or set both line and block commentstring
+ .set('javascript', {'//%s', '/*%s*/'})
+
+-- 2. Metatable magic
+
+ft.javascript = {'//%s', '/*%s*/'}
+ft.yaml = '#%s'
+
+-- Multiple filetypes
+ft({'go', 'rust'}, ft.get('c'))
+ft({'toml', 'graphql'}, '#%s')
+```
+
+> PR(s) are welcome to add more commentstring inside the plugin
+
+### 🤝 Contributing
+
+There are multiple ways to contribute reporting/fixing bugs, feature requests. You can also submit commentstring to this plugin by updating [ft.lua](./lua/Comment/ft.lua) and sending PR.
+
+### 📺 Videos
+
+- [TakeTuesday E02: Comment.nvim](https://www.youtube.com/watch?v=-InmtHhk2qM) by [TJ DeVries](https://github.com/tjdevries)
+
+### 💐 Credits
+
+- [tcomment](https://github.com/tomtom/tcomment_vim) - To be with me forever and motivated me to write this.
+- [nvim-comment](https://github.com/terrortylor/nvim-comment) - Little and less powerful cousin. Also I took some code from it.
+- [kommentary](https://github.com/b3nj5m1n/kommentary) - Nicely done plugin but lacks some features. But it helped me to design this plugin.
+
+### 🚗 Roadmap
+
+- Doc comment i.e `/**%s*/` (js), `///%s` (rust)
+- Header comment
+
+```lua
+----------------------
+-- This is a header --
+----------------------
+```
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/doc/API.md b/config/neovim/store/lazy-plugins/comment.nvim/doc/API.md
new file mode 100644
index 00000000..ecc574fc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/doc/API.md
@@ -0,0 +1 @@
+`Comment.nvim` now has `:help` docs 🎉. Read `:h comment.api` for the Lua API documentation and usage.
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/doc/Comment.txt b/config/neovim/store/lazy-plugins/comment.nvim/doc/Comment.txt
new file mode 100644
index 00000000..2bf2b641
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/doc/Comment.txt
@@ -0,0 +1,910 @@
+*comment-nvim.txt* For Neovim version 0.7 Last change: 2021 July 11
+
+ _____ _ _
+ / ____/ / / (_)
+ / / ___ _ __ ___ _ __ ___ ___ _ __ / /_ _ ____ ___ _ __ ___
+ / / / _ \/ '_ ` _ \/ '_ ` _ \ / _ \ '_ \/ __/ / '_ \ \ / / / '_ ` _ \
+ / /___/ (_) / / / / / / / / / / / __/ / / / /_ _/ / / \ V // / / / / / /
+ \_____\___//_/ /_/ /_/_/ /_/ /_/\___/_/ /_/\__(_)_/ /_/\_/ /_/_/ /_/ /_/
+
+ · Smart and Powerful comment plugin ·
+
+
+==============================================================================
+Table of Contents *comment.contents*
+
+Introduction ···················································· |comment-nvim|
+Usage ·························································· |comment.usage|
+Configuration ················································· |comment.config|
+Keybindings ·············································· |comment.keybindings|
+Plug Mappings ················································ |comment.plugmap|
+Core Lua API ····················································· |comment.api|
+Language/Filetype detection ······································· |comment.ft|
+Utilities ······················································ |comment.utils|
+Operator-mode API ············································· |comment.opfunc|
+Extra API ······················································ |comment.extra|
+
+==============================================================================
+Introduction *comment-nvim*
+
+Comment.nvim is a smart and powerful comment plugin for neovim. It supports
+dot-repeat, counts, line ('//') and block ('/* */') comments, and can be used
+with motion and text-objects. It has native integration with |treesitter| to
+support embedded filetypes like html, vue, markdown with codeblocks etc.
+
+ *comment.dotrepeat*
+Comment.nvim uses |operatorfunc| combined with |g@| to support dot-repeat, and
+various marks i.e., |'[| |']| |'<| |'>| to deduce the region with the {motion}
+argument provided by 'operatorfunc'. See |comment.api.call|
+
+ *comment.commentstring*
+Comment.nvim picks commentstring, either linewise/blockwise, from one of the
+following places
+
+ 1. 'pre_hook'
+ If a string is returned from this function then it will be used for
+ (un)commenting. See |comment.config|
+
+ 2. |comment.ft|
+ Using the commentstring table inside the plugin (using treesitter).
+ Fallback to |commentstring|, if not found.
+
+ 3. |commentstring| - Neovim's native commentstring for the filetype
+
+Although Comment.nvim supports native 'commentstring' but unfortunately it has
+the least priority. The caveat with this approach is that if someone sets the
+`commentstring`, without returning it, from the 'pre_hook' and the current
+filetype also exists in the |comment.ft| then the commenting will be done using
+the string in |comment.ft| instead of using 'commentstring'. To override this
+behavior, you have to manually return the 'commentstring' from 'pre_hook'.
+
+ *comment.sourcecode*
+Comment.nvim is FOSS and distributed under MIT license. All the source code is
+available at https://github.com/numToStr/Comment.nvim
+
+==============================================================================
+Usage *comment.usage*
+
+Before using the plugin, you need to call the `setup()` function to create the
+default mappings. If you want, you can also override the default configuration
+by giving it a partial 'comment.config.Config' object, it will then be merged
+with the default configuration.
+
+C.setup({config?}) *comment.usage.setup*
+ Configures the plugin
+
+ Parameters: ~
+ {config?} (CommentConfig) User configuration
+
+ Returns: ~
+ (CommentConfig) Returns the modified config
+
+ See: ~
+ |comment.config|
+
+ Usage: ~
+>lua
+ -- Use default configuration
+ require('Comment').setup()
+
+ -- or with custom configuration
+ require('Comment').setup({
+ ignore = '^$',
+ toggler = {
+ line = 'cc',
+ block = 'bc',
+ },
+ opleader = {
+ line = 'c',
+ block = 'b',
+ },
+ })
+<
+
+
+==============================================================================
+Configuration *comment.config*
+
+ *comment.config.defaults*
+Following is the default config for the |comment.usage.setup|. If you want to
+override, just modify the option that you want, then it will be merged with the
+default config.
+>lua
+ {
+ padding = true,
+ sticky = true,
+ ignore = nil,
+ toggler = { line = 'gcc', block = 'gbc' },
+ opleader = { line = 'gc', block = 'gb' },
+ extra = { above = 'gcO', below = 'gco', eol = 'gcA' },
+ mappings = { basic = true, extra = true },
+ pre_hook = nil,
+ post_hook = nil,
+ }
+<
+
+CommentConfig *comment.config.CommentConfig*
+ Plugin's configuration
+
+ Fields: ~
+ {padding} (boolean|fun():boolean) Controls space between the comment
+ and the line (default: 'true')
+ {sticky} (boolean) Whether cursor should stay at the
+ same position. Only works in NORMAL
+ mode mappings (default: 'true')
+ {ignore} (string|fun():string) Lua pattern used to ignore lines
+ during (un)comment (default: 'nil')
+ {mappings} (Mappings|false) Enables |comment.keybindings|
+ NOTE: If given 'false', then the
+ plugin won't create any mappings
+ {toggler} (Toggler) See |comment.config.Toggler|
+ {opleader} (Opleader) See |comment.config.Opleader|
+ {extra} (ExtraMapping) See |comment.config.ExtraMapping|
+ {pre_hook} (fun(c:CommentCtx):string) Function to call before (un)comment.
+ It is called with a {ctx} argument
+ of type |comment.utils.CommentCtx|
+ (default: 'nil')
+ {post_hook} (fun(c:CommentCtx)) Function to call after (un)comment.
+ It is called with a {ctx} argument
+ of type |comment.utils.CommentCtx|
+ (default: 'nil')
+
+
+Mappings *comment.config.Mappings*
+ Create default mappings
+
+ Fields: ~
+ {basic} (boolean) Enables operator-pending mapping; `gcc`, `gbc`,
+ `gc{motion}` and `gb{motion}` (default: 'true')
+ {extra} (boolean) Enable extra mapping; `gco`, `gcO` and `gcA`
+ (default: 'true')
+
+
+Toggler *comment.config.Toggler*
+ LHS of toggle mappings in NORMAL
+
+ Fields: ~
+ {line} (string) Linewise comment (default: 'gcc')
+ {block} (string) Blockwise comment (default: 'gbc')
+
+
+Opleader *comment.config.Opleader*
+ LHS of operator-mode mappings in NORMAL and VISUAL mode
+
+ Fields: ~
+ {line} (string) Linewise comment (default: 'gc')
+ {block} (string) Blockwise comment (default: 'gb')
+
+
+ExtraMapping *comment.config.ExtraMapping*
+ LHS of extra mappings
+
+ Fields: ~
+ {below} (string) Inserts comment below (default: 'gco')
+ {above} (string) Inserts comment above (default: 'gcO')
+ {eol} (string) Inserts comment at the end of line (default: 'gcA')
+
+
+Config:get() *comment.config:get*
+ Get the config
+
+ Returns: ~
+ (CommentConfig)
+
+ Usage: ~
+>lua
+ require('Comment.config'):get()
+<
+
+
+==============================================================================
+Keybindings *comment.keybindings*
+
+Comment.nvim provides default keybindings for (un)comment your code. These
+keybinds are enabled upon calling |comment.usage.setup| and can be configured
+or disabled, if desired.
+
+Basic: ~
+
+ *gc*
+ *gb*
+ *gc[count]{motion}*
+ *gb[count]{motion}*
+
+ Toggle comment on a region using linewise/blockwise comment. In 'NORMAL'
+ mode, it uses 'Operator-Pending' mode to listen for an operator/motion.
+ In 'VISUAL' mode it simply comment the selected region.
+
+ *gcc*
+ *gbc*
+ *[count]gcc*
+ *[count]gbc*
+
+ Toggle comment on the current line using linewise/blockwise comment. If
+ prefixed with a 'v:count' then it will comment over the number of lines
+ corresponding to the {count}. These are only available in 'NORMAL' mode.
+
+
+Extra: ~
+
+ *gco* - Inserts comment below and enters INSERT mode
+ *gcO* - Inserts comment above and enters INSERT mode
+ *gcA* - Inserts comment at the end of line and enters INSERT mode
+
+==============================================================================
+Plug Mappings *comment.plugmap*
+
+Comment.nvim provides mappings for most commonly used actions. These
+are enabled by default and can be used to make custom keybindings. All plug
+mappings have support for dot-repeat except VISUAL mode keybindings. To create
+custom comment function, check out 'comment.api' section.
+
+ *(comment_toggle_linewise)*
+ *(comment_toggle_blockwise)*
+
+ Toggle comment on a region with linewise/blockwise comment in NORMAL mode.
+ using |Operator-Pending| mode (or |g@|) to get the region to comment.
+ These powers the |gc| and |gb| keybindings.
+
+ *(comment_toggle_linewise_current)*
+ *(comment_toggle_blockwise_current)*
+
+ Toggle comment on the current line with linewise/blockwise comment in
+ NORMAL mode. These powers the |gcc| and 'gbc' keybindings.
+
+ *(comment_toggle_linewise_count)*
+ *(comment_toggle_blockwise_count)*
+
+ Toggle comment on a region using 'v:count' with linewise/blockwise comment
+ in NORMAL mode. These powers the |[count]gcc| and |[count]gbc| keybindings.
+
+ *(comment_toggle_linewise_visual)*
+ *(comment_toggle_blockwise_visual)*
+
+ Toggle comment on the selected region with linewise/blockwise comment in
+ NORMAL mode. These powers the |{visual}gc| and |{visual}gb| keybindings.
+
+Usage: ~
+>lua
+ -- Toggle current line or with count
+ vim.keymap.set('n', 'gcc', function()
+ return vim.v.count == 0
+ and '(comment_toggle_linewise_current)'
+ or '(comment_toggle_linewise_count)'
+ end, { expr = true })
+
+ -- Toggle in Op-pending mode
+ vim.keymap.set('n', 'gc', '(comment_toggle_linewise)')
+
+ -- Toggle in VISUAL mode
+ vim.keymap.set('x', 'gc', '(comment_toggle_linewise_visual)')
+<
+
+==============================================================================
+Core Lua API *comment.api*
+
+This module provides the core lua APIs which is used by the default keybindings
+and (Read |comment.plugmap|) mappings. These API can be used to setup your
+own custom keybindings or to even make your (un)comment function.
+
+ *comment.api.toggle.linewise*
+ *comment.api.toggle.blockwise*
+api.toggle *comment.api.toggle*
+ Provides API to toggle comments over a region, on current-line, or with a
+ count using line or block comment string.
+
+ Every function takes a {motion} argument, except '*.count()' function which
+ takes an {count} argument, and an optional {config} parameter.
+
+ Type: ~
+ (table) A metatable containing API functions
+
+ See: ~
+ |comment.opfunc.OpMotion|
+ |comment.config|
+
+ Usage: ~
+>lua
+ local api = require('Comment.api')
+ local config = require('Comment.config'):get()
+
+ api.toggle.linewise(motion, config?)
+ api.toggle.linewise.current(motion?, config?)
+ api.toggle.linewise.count(count, config?)
+
+ api.toggle.blockwise(motion, config?)
+ api.toggle.blockwise.current(motion?, config?)
+ api.toggle.blockwise.count(count, config?)
+
+ -- Toggle current line (linewise) using C-/
+ vim.keymap.set('n', '', api.toggle.linewise.current)
+
+ -- Toggle current line (blockwise) using C-\
+ vim.keymap.set('n', '', api.toggle.blockwise.current)
+
+ -- Toggle lines (linewise) with dot-repeat support
+ -- Example: gc3j will comment 4 lines
+ vim.keymap.set(
+ 'n', 'gc', api.call('toggle.linewise', 'g@'),
+ { expr = true }
+ )
+
+ -- Toggle lines (blockwise) with dot-repeat support
+ -- Example: gb3j will comment 4 lines
+ vim.keymap.set(
+ 'n', 'gb', api.call('toggle.blockwise', 'g@'),
+ { expr = true }
+ )
+
+ local esc = vim.api.nvim_replace_termcodes(
+ '', true, false, true
+ )
+
+ -- Toggle selection (linewise)
+ vim.keymap.set('x', 'c', function()
+ vim.api.nvim_feedkeys(esc, 'nx', false)
+ api.toggle.linewise(vim.fn.visualmode())
+ end)
+
+ -- Toggle selection (blockwise)
+ vim.keymap.set('x', 'b', function()
+ vim.api.nvim_feedkeys(esc, 'nx', false)
+ api.toggle.blockwise(vim.fn.visualmode())
+ end)
+<
+
+
+ *comment.api.comment.linewise*
+ *comment.api.comment.blockwise*
+api.comment *comment.api.comment*
+ Provides API to (only) comment a region, on current-line, or with a
+ count using line or block comment string.
+
+ Every function takes a {motion} argument, except '*.count()' function which
+ takes an {count} argument, and an optional {config} parameter.
+
+ Type: ~
+ (table) A metatable containing API functions
+
+ See: ~
+ |comment.opfunc.OpMotion|
+ |comment.config|
+
+ Usage: ~
+>lua
+ local api = require('Comment.api')
+ local config = require('Comment.config'):get()
+
+ api.comment.linewise(motion, config?)
+ api.comment.linewise.current(motion?, config?)
+ api.comment.linewise.count(count, config?)
+
+ api.comment.blockwise(motion, config?)
+ api.comment.blockwise.current(motion?, config?)
+ api.comment.blockwise.count(count, config?)
+<
+
+
+ *comment.api.uncomment.linewise*
+ *comment.api.uncomment.blockwise*
+api.uncomment *comment.api.uncomment*
+ Provides API to (only) uncomment a region, on current-line, or with a
+ count using line or block comment string.
+
+ Every function takes a {motion} argument, except '*.count()' function which
+ takes an {count} argument, and an optional {config} parameter.
+
+ Type: ~
+ (table) A metatable containing API functions
+
+ See: ~
+ |comment.opfunc.OpMotion|
+ |comment.config|
+
+ Usage: ~
+>lua
+ local api = require('Comment.api')
+ local config = require('Comment.config'):get()
+
+ api.uncomment.linewise(motion, config?)
+ api.uncomment.linewise.current(motion?, config?)
+ api.uncomment.linewise.count(count, config?)
+
+ api.uncomment.blockwise(motion, config?)
+ api.uncomment.blockwise.current(motion?, config?)
+ api.uncomment.blockwise.count(count, config?)
+<
+
+
+api.insert *comment.api.insert*
+ Provides API to to insert comment on previous, next or at the end-of-line.
+ Every function takes an optional {config} parameter.
+
+ Type: ~
+ (table) A metatable containing API functions
+
+ See: ~
+ |comment.config|
+
+ Usage: ~
+>lua
+ local api = require('Comment.api')
+ local config = require('Comment.config'):get()
+
+ api.insert.linewise.above(config?)
+ api.insert.linewise.below(config?)
+ api.insert.linewise.eol(config?)
+
+ api.insert.blockwise.above(config?)
+ api.insert.blockwise.below(config?)
+ api.insert.blockwise.eol(config?)
+<
+
+
+api.locked({cb}) *comment.api.locked*
+ Wraps the given API function with 'lockmarks' to preserve marks/jumps
+
+ Parameters: ~
+ {cb} (string) Name of API function
+
+ Returns: ~
+ (fun(motion:OpMotion)) Callback function
+
+ See: ~
+ |lockmarks|
+ |comment.opfunc.OpMotion|
+
+ Usage: ~
+>lua
+ local api = require('Comment.api')
+
+ vim.keymap.set(
+ 'n', 'c', api.locked('toggle.linewise.current')
+ )
+
+ local esc = vim.api.nvim_replace_termcodes(
+ '', true, false, true
+ )
+ vim.keymap.set('x', 'c', function()
+ vim.api.nvim_feedkeys(esc, 'nx', false)
+ api.locked('toggle.linewise')(vim.fn.visualmode())
+ end)
+
+ -- NOTE: `locked` method is just a wrapper around `lockmarks`
+ vim.api.nvim_command([[
+ lockmarks lua require('Comment.api').toggle.linewise.current()
+ ]])
+<
+
+
+api.call({cb}, {op}) *comment.api.call*
+ Callback function which does the following
+ 1. Sets 'operatorfunc' for dot-repeat
+ 2. Preserves jumps and marks
+ 3. Stores last cursor position
+
+ Parameters: ~
+ {cb} (string) Name of the API function to call
+ {op} ("g@"|"g@$") Operator-mode expression
+
+ Returns: ~
+ (fun():string) Keymap RHS callback
+
+ See: ~
+ |g@|
+ |operatorfunc|
+
+ Usage: ~
+>lua
+ local api = require('Comment.api')
+ vim.keymap.set(
+ 'n', 'gc', api.call('toggle.linewise', 'g@'),
+ { expr = true }
+ )
+ vim.keymap.set(
+ 'n', 'gcc', api.call('toggle.linewise.current', 'g@$'),
+ { expr = true }
+ )
+<
+
+
+==============================================================================
+Language/Filetype detection *comment.ft*
+
+This module is the core of filetype and commentstring detection and uses the
+|lua-treesitter| APIs to accurately detect filetype and gives the corresponding
+commentstring, stored inside the plugin, for the filetype/langauge.
+
+Compound (dot-separated) filetypes are also supported i.e. 'ansible.yaml',
+'ios.swift' etc. The commentstring resolution will be done from left to right.
+For example, If the filetype is 'ansible.yaml' then 'ansible' commenstring will
+be used if found otherwise it'll fallback to 'yaml'. Read `:h 'filetype'`
+
+ft.set({lang}, {val}) *comment.ft.set*
+ Sets a commentstring(s) for a filetype/language
+
+ Parameters: ~
+ {lang} (string) Filetype/Language of the buffer
+ {val} (string|string[])
+
+ Returns: ~
+ (table) Returns itself
+
+ Usage: ~
+>lua
+ local ft = require('Comment.ft')
+
+ --1. Using method signature
+ -- Set only line comment or both
+ -- You can also chain the set calls
+ ft.set('yaml', '#%s').set('javascript', {'//%s', '/*%s*/'})
+
+ -- 2. Metatable magic
+ ft.javascript = {'//%s', '/*%s*/'}
+ ft.yaml = '#%s'
+
+ -- 3. Multiple filetypes
+ ft({'go', 'rust'}, {'//%s', '/*%s*/'})
+ ft({'toml', 'graphql'}, '#%s')
+<
+
+
+ft.get({lang}, {ctype?}) *comment.ft.get*
+ Get line/block/both commentstring(s) for a given filetype
+
+ Parameters: ~
+ {lang} (string) Filetype/Language of the buffer
+ {ctype?} (integer) See |comment.utils.ctype|. If given `nil`, it'll
+ return a copy of { line, block } commentstring.
+
+ Returns: ~
+ (nil|string|string[]) Returns stored commentstring
+
+ Usage: ~
+>lua
+ local ft = require('Comment.ft')
+ local U = require('Comment.utils')
+
+ -- 1. Primary filetype
+ ft.get('rust', U.ctype.linewise) -- `//%s`
+ ft.get('rust') -- `{ '//%s', '/*%s*/' }`
+
+ -- 2. Compound filetype
+ -- NOTE: This will return `yaml` commenstring(s),
+ -- as `ansible` commentstring is not found.
+ ft.get('ansible.yaml', U.ctype.linewise) -- `#%s`
+ ft.get('ansible.yaml') -- { '#%s' }
+<
+
+
+ft.contains({tree}, {range}) *comment.ft.contains*
+ Get a language tree for a given range by walking the parse tree recursively.
+ This uses 'lua-treesitter' API under the hood. This can be used to calculate
+ language of a particular region which embedded multiple filetypes like html,
+ vue, markdown etc.
+
+ NOTE: This ignores `tree-sitter-comment` parser, if installed.
+
+ Parameters: ~
+ {tree} (userdata) Parse tree to be walked
+ {range} (integer[]) Range to check
+ {start_row, start_col, end_row, end_col}
+
+ Returns: ~
+ (userdata) Returns a |treesitter-languagetree|
+
+ See: ~
+ |treesitter-languagetree|
+ |lua-treesitter-core|
+
+ Usage: ~
+>lua
+ local ok, parser = pcall(vim.treesitter.get_parser, 0)
+ assert(ok, "No parser found!")
+ local tree = require('Comment.ft').contains(parser, {0, 0, -1, 0})
+ print('Lang:', tree:lang())
+<
+
+
+ft.calculate({ctx}) *comment.ft.calculate*
+ Calculate commentstring with the power of treesitter
+
+ Parameters: ~
+ {ctx} (CommentCtx)
+
+ Returns: ~
+ (nil|string) Commentstring
+
+ See: ~
+ |comment.utils.CommentCtx|
+
+
+==============================================================================
+Utilities *comment.utils*
+
+CommentCtx *comment.utils.CommentCtx*
+ Comment context
+
+ Fields: ~
+ {ctype} (integer) See |comment.utils.ctype|
+ {cmode} (integer) See |comment.utils.cmode|
+ {cmotion} (integer) See |comment.utils.cmotion|
+ {range} (CommentRange)
+
+
+CommentRange *comment.utils.CommentRange*
+ Range of the selection that needs to be commented
+
+ Fields: ~
+ {srow} (integer) Starting row
+ {scol} (integer) Starting column
+ {erow} (integer) Ending row
+ {ecol} (integer) Ending column
+
+
+CommentMode *comment.utils.CommentMode*
+ Comment modes - Can be manual or computed via operator-mode
+
+ Fields: ~
+ {toggle} (integer) Toggle action
+ {comment} (integer) Comment action
+ {uncomment} (integer) Uncomment action
+
+
+U.cmode *comment.utils.cmode*
+ An object containing comment modes
+
+ Type: ~
+ (CommentMode)
+
+
+CommentType *comment.utils.CommentType*
+ Comment types
+
+ Fields: ~
+ {linewise} (integer) Use linewise commentstring
+ {blockwise} (integer) Use blockwise commentstring
+
+
+U.ctype *comment.utils.ctype*
+ An object containing comment types
+
+ Type: ~
+ (CommentType)
+
+
+CommentMotion *comment.utils.CommentMotion*
+ Comment motion types
+
+ Fields: ~
+ {line} (integer) Line motion (ie. 'gc2j')
+ {char} (integer) Character/left-right motion (ie. 'gc2w')
+ {block} (integer) Visual operator-pending motion
+ {v} (integer) Visual motion (ie. 'v3jgc')
+ {V} (integer) Visual-line motion (ie. 'V10kgc')
+
+
+U.cmotion *comment.utils.cmotion*
+ An object containing comment motions
+
+ Type: ~
+ (CommentMotion)
+
+
+U.get_region({opmode?}) *comment.utils.get_region*
+ Get region for line movement or visual selection
+ NOTE: Returns the current line region, if `opmode` is not given.
+
+ Parameters: ~
+ {opmode?} (OpMotion)
+
+ Returns: ~
+ (CommentRange)
+
+
+U.get_count_lines({count}) *comment.utils.get_count_lines*
+ Get lines from the current position to the given count
+
+ Parameters: ~
+ {count} (integer) Probably 'vim.v.count'
+
+ Returns: ~
+ (string[]) List of lines
+ (CommentRange)
+
+
+U.get_lines({range}) *comment.utils.get_lines*
+ Get lines from a NORMAL/VISUAL mode
+
+ Parameters: ~
+ {range} (CommentRange)
+
+ Returns: ~
+ (string[]) List of lines
+
+
+U.unwrap_cstr({cstr}) *comment.utils.unwrap_cstr*
+ Validates and unwraps the given commentstring
+
+ Parameters: ~
+ {cstr} (string) See 'commentstring'
+
+ Returns: ~
+ (string) Left side of the commentstring
+ (string) Right side of the commentstring
+
+
+U.parse_cstr({cfg}, {ctx}) *comment.utils.parse_cstr*
+ Parses commentstring from the following places in the respective order
+ 1. pre_hook - commentstring returned from the function
+ 2. ft.lua - commentstring table bundled with the plugin
+ 3. commentstring - Neovim's native. See 'commentstring'
+
+ Parameters: ~
+ {cfg} (CommentConfig)
+ {ctx} (CommentCtx)
+
+ Returns: ~
+ (string) Left side of the commentstring
+ (string) Right side of the commentstring
+
+
+ *comment.utils.commenter*
+U.commenter({left}, {right}, {padding}, {scol?}, {ecol?}, {tabbed?})
+ Returns a closure which is used to do comments
+
+ If given {string[]} to the closure then it will do blockwise comment
+ else linewise comment will be done with the given {string}
+
+ Parameters: ~
+ {left} (string) Left side of the commentstring
+ {right} (string) Right side of the commentstring
+ {padding} (boolean) Is padding enabled?
+ {scol?} (integer) Starting column
+ {ecol?} (integer) Ending column
+ {tabbed?} (boolean) Using tab indentation
+
+ Returns: ~
+ (fun(line:string|string[]):string|string[])
+
+
+ *comment.utils.uncommenter*
+U.uncommenter({left}, {right}, {padding}, {scol?}, {ecol?})
+ Returns a closure which is used to uncomment a line
+
+ If given {string[]} to the closure then it will block uncomment
+ else linewise uncomment will be done with the given {string}
+
+ Parameters: ~
+ {left} (string) Left side of the commentstring
+ {right} (string) Right side of the commentstring
+ {padding} (boolean) Is padding enabled?
+ {scol?} (integer) Starting column
+ {ecol?} (integer) Ending column
+
+ Returns: ~
+ (fun(line:string|string[]):string|string[])
+
+
+ *comment.utils.is_commented*
+U.is_commented({left}, {right}, {padding}, {scol?}, {ecol?})
+ Check if the given string is commented or not
+
+ If given {string[]} to the closure, it will check the first and last line
+ with LHS and RHS of commentstring respectively else it will check the given
+ line with LHS and RHS (if given) of the commenstring
+
+ Parameters: ~
+ {left} (string) Left side of the commentstring
+ {right} (string) Right side of the commentstring
+ {padding} (boolean) Is padding enabled?
+ {scol?} (integer) Starting column
+ {ecol?} (integer) Ending column
+
+ Returns: ~
+ (fun(line:string|string[]):boolean)
+
+
+==============================================================================
+Operator-mode API *comment.opfunc*
+
+Underlying functions that powers the |comment.api.toggle|, |comment.api.comment|,
+and |comment.api.uncomment| lua API.
+
+OpMotion *comment.opfunc.OpMotion*
+ Vim operator-mode motion enum. Read |:map-operator|
+
+ Variants: ~
+ ("line") Vertical motion
+ ("char") Horizontal motion
+ ("v") Visual Block motion
+ ("V") Visual Line motion
+
+
+ *comment.opfunc.opfunc*
+Op.opfunc({motion?}, {cfg}, {cmode}, {ctype})
+ Common operatorfunc callback
+ This function contains the core logic for comment/uncomment
+
+ Parameters: ~
+ {motion?} (OpMotion) If given 'nil', it'll only (un)comment
+ the current line
+ {cfg} (CommentConfig)
+ {cmode} (integer) See |comment.utils.cmode|
+ {ctype} (integer) See |comment.utils.ctype|
+
+
+ *comment.opfunc.count*
+Op.count({count}, {cfg}, {cmode}, {ctype})
+ Line commenting with count
+
+ Parameters: ~
+ {count} (integer) Value of |v:count|
+ {cfg} (CommentConfig)
+ {cmode} (integer) See |comment.utils.cmode|
+ {ctype} (integer) See |comment.utils.ctype|
+
+
+OpFnParams *comment.opfunc.OpFnParams*
+ Operator-mode function parameters
+
+ Fields: ~
+ {cfg} (CommentConfig)
+ {cmode} (integer) See |comment.utils.cmode|
+ {lines} (string[]) List of lines
+ {rcs} (string) RHS of commentstring
+ {lcs} (string) LHS of commentstring
+ {range} (CommentRange)
+
+
+Op.linewise({param}) *comment.opfunc.linewise*
+ Line commenting
+
+ Parameters: ~
+ {param} (OpFnParams)
+
+ Returns: ~
+ (integer) Returns a calculated comment mode
+
+
+Op.blockwise({param}, {partial?}) *comment.opfunc.blockwise*
+ Full/Partial/Current-Line Block commenting
+
+ Parameters: ~
+ {param} (OpFnParams)
+ {partial?} (boolean) Comment the partial region (visual mode)
+
+ Returns: ~
+ (integer) Returns a calculated comment mode
+
+
+==============================================================================
+Extra API *comment.extra*
+
+Underlying functions that powers the |comment.api.insert| lua API.
+
+extra.insert_below({ctype}, {cfg}) *comment.extra.insert_below*
+ Add a comment below the current line and goes to INSERT mode
+
+ Parameters: ~
+ {ctype} (integer) See |comment.utils.ctype|
+ {cfg} (CommentConfig)
+
+
+extra.insert_above({ctype}, {cfg}) *comment.extra.insert_above*
+ Add a comment above the current line and goes to INSERT mode
+
+ Parameters: ~
+ {ctype} (integer) See |comment.utils.ctype|
+ {cfg} (CommentConfig)
+
+
+extra.insert_eol({ctype}, {cfg}) *comment.extra.insert_eol*
+ Add a comment at the end of current line and goes to INSERT mode
+
+ Parameters: ~
+ {ctype} (integer) See |comment.utils.ctype|
+ {cfg} (CommentConfig)
+
+
+vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/doc/plugs.md b/config/neovim/store/lazy-plugins/comment.nvim/doc/plugs.md
new file mode 100644
index 00000000..b1fdf315
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/doc/plugs.md
@@ -0,0 +1 @@
+`Comment.nvim` now has `:help` docs 🎉. Read `:h comment.plugmap` for the `` mappings documentation and usage.
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/api.lua b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/api.lua
new file mode 100644
index 00000000..e92757f7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/api.lua
@@ -0,0 +1,253 @@
+---@mod comment.api Core Lua API
+---@brief [[
+---This module provides the core lua APIs which is used by the default keybindings
+---and (Read |comment.plugmap|) mappings. These API can be used to setup your
+---own custom keybindings or to even make your (un)comment function.
+---@brief ]]
+
+local Config = require('Comment.config')
+local U = require('Comment.utils')
+local Op = require('Comment.opfunc')
+local Ex = require('Comment.extra')
+local A = vim.api
+
+local api, core = {}, {}
+
+---API metamethods
+---@param that table
+---@param ctype CommentType
+---@return table
+function core.__index(that, ctype)
+ local idxd = {}
+ local mode, type = that.cmode, U.ctype[ctype]
+
+ ---To comment the current-line
+ ---NOTE:
+ ---In current-line linewise method, 'opmode' is not useful which is always equals to `char`
+ ---but we need 'nil' here which is used for current-line
+ function idxd.current(_, cfg)
+ U.catch(Op.opfunc, nil, cfg or Config:get(), mode, type)
+ end
+
+ ---To comment lines with a count
+ function idxd.count(count, cfg)
+ U.catch(Op.count, count or A.nvim_get_vvar('count'), cfg or Config:get(), mode, type)
+ end
+
+ ---@private
+ ---To comment lines with a count, also dot-repeatable
+ ---WARN: This is not part of the API but anyone case use it, if they want
+ function idxd.count_repeat(_, count, cfg)
+ idxd.count(count, cfg)
+ end
+
+ return setmetatable({}, {
+ __index = idxd,
+ __call = function(_, motion, cfg)
+ U.catch(Op.opfunc, motion, cfg or Config:get(), mode, type)
+ end,
+ })
+end
+
+---@tag comment.api.toggle.linewise
+---@tag comment.api.toggle.blockwise
+---Provides API to toggle comments over a region, on current-line, or with a
+---count using line or block comment string.
+---
+---Every function takes a {motion} argument, except '*.count()' function which
+---takes an {count} argument, and an optional {config} parameter.
+---@type table A metatable containing API functions
+---@see comment.opfunc.OpMotion
+---@see comment.config
+---@usage [[
+---local api = require('Comment.api')
+---local config = require('Comment.config'):get()
+---
+---api.toggle.linewise(motion, config?)
+---api.toggle.linewise.current(motion?, config?)
+---api.toggle.linewise.count(count, config?)
+---
+---api.toggle.blockwise(motion, config?)
+---api.toggle.blockwise.current(motion?, config?)
+---api.toggle.blockwise.count(count, config?)
+---
+----- Toggle current line (linewise) using C-/
+---vim.keymap.set('n', '', api.toggle.linewise.current)
+---
+----- Toggle current line (blockwise) using C-\
+---vim.keymap.set('n', '', api.toggle.blockwise.current)
+---
+----- Toggle lines (linewise) with dot-repeat support
+----- Example: gc3j will comment 4 lines
+---vim.keymap.set(
+--- 'n', 'gc', api.call('toggle.linewise', 'g@'),
+--- { expr = true }
+---)
+---
+----- Toggle lines (blockwise) with dot-repeat support
+----- Example: gb3j will comment 4 lines
+---vim.keymap.set(
+--- 'n', 'gb', api.call('toggle.blockwise', 'g@'),
+--- { expr = true }
+---)
+---
+---local esc = vim.api.nvim_replace_termcodes(
+--- '', true, false, true
+---)
+---
+----- Toggle selection (linewise)
+---vim.keymap.set('x', 'c', function()
+--- vim.api.nvim_feedkeys(esc, 'nx', false)
+--- api.toggle.linewise(vim.fn.visualmode())
+---end)
+---
+----- Toggle selection (blockwise)
+---vim.keymap.set('x', 'b', function()
+--- vim.api.nvim_feedkeys(esc, 'nx', false)
+--- api.toggle.blockwise(vim.fn.visualmode())
+---end)
+---@usage ]]
+api.toggle = setmetatable({ cmode = U.cmode.toggle }, core)
+
+---@tag comment.api.comment.linewise
+---@tag comment.api.comment.blockwise
+---Provides API to (only) comment a region, on current-line, or with a
+---count using line or block comment string.
+---
+---Every function takes a {motion} argument, except '*.count()' function which
+---takes an {count} argument, and an optional {config} parameter.
+---@type table A metatable containing API functions
+---@see comment.opfunc.OpMotion
+---@see comment.config
+---@usage [[
+---local api = require('Comment.api')
+---local config = require('Comment.config'):get()
+---
+---api.comment.linewise(motion, config?)
+---api.comment.linewise.current(motion?, config?)
+---api.comment.linewise.count(count, config?)
+---
+---api.comment.blockwise(motion, config?)
+---api.comment.blockwise.current(motion?, config?)
+---api.comment.blockwise.count(count, config?)
+---@usage ]]
+api.comment = setmetatable({ cmode = U.cmode.comment }, core)
+
+---@tag comment.api.uncomment.linewise
+---@tag comment.api.uncomment.blockwise
+---Provides API to (only) uncomment a region, on current-line, or with a
+---count using line or block comment string.
+---
+---Every function takes a {motion} argument, except '*.count()' function which
+---takes an {count} argument, and an optional {config} parameter.
+---@type table A metatable containing API functions
+---@see comment.opfunc.OpMotion
+---@see comment.config
+---@usage [[
+---local api = require('Comment.api')
+---local config = require('Comment.config'):get()
+---
+---api.uncomment.linewise(motion, config?)
+---api.uncomment.linewise.current(motion?, config?)
+---api.uncomment.linewise.count(count, config?)
+---
+---api.uncomment.blockwise(motion, config?)
+---api.uncomment.blockwise.current(motion?, config?)
+---api.uncomment.blockwise.count(count, config?)
+---@usage ]]
+api.uncomment = setmetatable({ cmode = U.cmode.uncomment }, core)
+
+---Provides API to to insert comment on previous, next or at the end-of-line.
+---Every function takes an optional {config} parameter.
+---@type table A metatable containing API functions
+---@see comment.config
+---@usage [[
+---local api = require('Comment.api')
+---local config = require('Comment.config'):get()
+---
+---api.insert.linewise.above(config?)
+---api.insert.linewise.below(config?)
+---api.insert.linewise.eol(config?)
+---
+---api.insert.blockwise.above(config?)
+---api.insert.blockwise.below(config?)
+---api.insert.blockwise.eol(config?)
+---@usage ]]
+api.insert = setmetatable({}, {
+ __index = function(_, ctype)
+ return {
+ above = function(cfg)
+ U.catch(Ex.insert_above, U.ctype[ctype], cfg or Config:get())
+ end,
+ below = function(cfg)
+ U.catch(Ex.insert_below, U.ctype[ctype], cfg or Config:get())
+ end,
+ eol = function(cfg)
+ U.catch(Ex.insert_eol, U.ctype[ctype], cfg or Config:get())
+ end,
+ }
+ end,
+})
+
+---Wraps the given API function with 'lockmarks' to preserve marks/jumps
+---@param cb string Name of API function
+---@return fun(motion:OpMotion) #Callback function
+---@see lockmarks
+---@see comment.opfunc.OpMotion
+---@usage [[
+---local api = require('Comment.api')
+---
+---vim.keymap.set(
+--- 'n', 'c', api.locked('toggle.linewise.current')
+---)
+---
+---local esc = vim.api.nvim_replace_termcodes(
+--- '', true, false, true
+---)
+---vim.keymap.set('x', 'c', function()
+--- vim.api.nvim_feedkeys(esc, 'nx', false)
+--- api.locked('toggle.linewise')(vim.fn.visualmode())
+---end)
+---
+----- NOTE: `locked` method is just a wrapper around `lockmarks`
+---vim.api.nvim_command([[
+--- lockmarks lua require('Comment.api').toggle.linewise.current()
+---]])
+---@usage ]]
+function api.locked(cb)
+ return function(motion)
+ return A.nvim_command(
+ ('lockmarks lua require("Comment.api").%s(%s)'):format(cb, motion and ('%q'):format(motion))
+ )
+ end
+end
+
+---Callback function which does the following
+--- 1. Sets 'operatorfunc' for dot-repeat
+--- 2. Preserves jumps and marks
+--- 3. Stores last cursor position
+---@param cb string Name of the API function to call
+---@param op '"g@"'|'"g@$"' Operator-mode expression
+---@return fun():string #Keymap RHS callback
+---@see g@
+---@see operatorfunc
+---@usage [[
+---local api = require('Comment.api')
+---vim.keymap.set(
+--- 'n', 'gc', api.call('toggle.linewise', 'g@'),
+--- { expr = true }
+---)
+---vim.keymap.set(
+--- 'n', 'gcc', api.call('toggle.linewise.current', 'g@$'),
+--- { expr = true }
+---)
+---@usage ]]
+function api.call(cb, op)
+ return function()
+ A.nvim_set_option('operatorfunc', ("v:lua.require'Comment.api'.locked'%s'"):format(cb))
+ Config.position = Config:get().sticky and A.nvim_win_get_cursor(0) or nil
+ return op
+ end
+end
+
+return api
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/config.lua b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/config.lua
new file mode 100644
index 00000000..01be20f0
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/config.lua
@@ -0,0 +1,134 @@
+---@mod comment.config Configuration
+---@tag comment.config.defaults
+---@brief [[
+---Following is the default config for the |comment.usage.setup|. If you want to
+---override, just modify the option that you want, then it will be merged with the
+---default config.
+--->lua
+--- {
+--- padding = true,
+--- sticky = true,
+--- ignore = nil,
+--- toggler = { line = 'gcc', block = 'gbc' },
+--- opleader = { line = 'gc', block = 'gb' },
+--- extra = { above = 'gcO', below = 'gco', eol = 'gcA' },
+--- mappings = { basic = true, extra = true },
+--- pre_hook = nil,
+--- post_hook = nil,
+--- }
+---<
+---@brief ]]
+
+---Plugin's configuration
+---@class CommentConfig
+---Controls space between the comment
+---and the line (default: 'true')
+---@field padding boolean|fun():boolean
+---Whether cursor should stay at the
+---same position. Only works in NORMAL
+---mode mappings (default: 'true')
+---@field sticky boolean
+---Lua pattern used to ignore lines
+---during (un)comment (default: 'nil')
+---@field ignore string|fun():string
+---Enables |comment.keybindings|
+---NOTE: If given 'false', then the
+---plugin won't create any mappings
+---@field mappings Mappings|false
+---@field toggler Toggler See |comment.config.Toggler|
+---@field opleader Opleader See |comment.config.Opleader|
+---@field extra ExtraMapping See |comment.config.ExtraMapping|
+---Function to call before (un)comment.
+---It is called with a {ctx} argument
+---of type |comment.utils.CommentCtx|
+---(default: 'nil')
+---@field pre_hook fun(c: CommentCtx): string
+---Function to call after (un)comment.
+---It is called with a {ctx} argument
+---of type |comment.utils.CommentCtx|
+---(default: 'nil')
+---@field post_hook fun(c: CommentCtx)
+
+---Create default mappings
+---@class Mappings
+---Enables operator-pending mapping; `gcc`, `gbc`,
+---`gc{motion}` and `gb{motion}` (default: 'true')
+---@field basic boolean
+---Enable extra mapping; `gco`, `gcO` and `gcA`
+---(default: 'true')
+---@field extra boolean
+
+---LHS of toggle mappings in NORMAL
+---@class Toggler
+---@field line string Linewise comment (default: 'gcc')
+---@field block string Blockwise comment (default: 'gbc')
+
+---LHS of operator-mode mappings in NORMAL and VISUAL mode
+---@class Opleader
+---@field line string Linewise comment (default: 'gc')
+---@field block string Blockwise comment (default: 'gb')
+
+---LHS of extra mappings
+---@class ExtraMapping
+---@field below string Inserts comment below (default: 'gco')
+---@field above string Inserts comment above (default: 'gcO')
+---@field eol string Inserts comment at the end of line (default: 'gcA')
+
+---@private
+---@class RootConfig
+---@field config CommentConfig
+---@field position? integer[] To be used to restore cursor position
+local Config = {
+ state = {},
+ config = {
+ padding = true,
+ sticky = true,
+ mappings = {
+ basic = true,
+ extra = true,
+ },
+ toggler = {
+ line = 'gcc',
+ block = 'gbc',
+ },
+ opleader = {
+ line = 'gc',
+ block = 'gb',
+ },
+ extra = {
+ above = 'gcO',
+ below = 'gco',
+ eol = 'gcA',
+ },
+ },
+}
+
+---@package
+---Updates the default config
+---@param cfg? CommentConfig
+---@return RootConfig
+---@see comment.usage.setup
+---@usage `require('Comment.config'):set({config})`
+function Config:set(cfg)
+ if cfg then
+ self.config = vim.tbl_deep_extend('force', self.config, cfg)
+ end
+ return self
+end
+
+---Get the config
+---@return CommentConfig
+---@usage `require('Comment.config'):get()`
+function Config:get()
+ return self.config
+end
+
+---@export Config
+return setmetatable(Config, {
+ __index = function(this, k)
+ return this.state[k]
+ end,
+ __newindex = function(this, k, v)
+ this.state[k] = v
+ end,
+})
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/extra.lua b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/extra.lua
new file mode 100644
index 00000000..6c3dcc4a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/extra.lua
@@ -0,0 +1,105 @@
+---@mod comment.extra Extra API
+---@brief [[
+---Underlying functions that powers the |comment.api.insert| lua API.
+---@brief ]]
+
+local U = require('Comment.utils')
+local A = vim.api
+
+local extra = {}
+
+-- FIXME This prints `a` in i_CTRL-o
+---Moves the cursor and enters INSERT mode
+---@param row integer Starting row
+---@param col integer Ending column
+local function move_n_insert(row, col)
+ A.nvim_win_set_cursor(0, { row, col })
+ A.nvim_feedkeys('a', 'ni', true)
+end
+
+---@param lnum integer Line index
+---@param ctype integer
+---@param cfg CommentConfig
+local function ins_on_line(lnum, ctype, cfg)
+ local row, col = unpack(A.nvim_win_get_cursor(0))
+
+ ---@type CommentCtx
+ local ctx = {
+ cmode = U.cmode.comment,
+ cmotion = U.cmotion.line,
+ ctype = ctype,
+ range = { srow = row, scol = col, erow = row, ecol = col },
+ }
+
+ local srow = row + lnum
+ local lcs, rcs = U.parse_cstr(cfg, ctx)
+ local padding = U.get_pad(U.is_fn(cfg.padding))
+
+ -- We need RHS of cstr, if we are doing block comments or if RHS exists
+ -- because even in line comment RHS do exists for some filetypes like jsx_element, ocaml
+ local if_rcs = U.is_empty(rcs) and rcs or padding .. rcs
+
+ A.nvim_buf_set_lines(0, srow, srow, false, { lcs .. padding .. if_rcs })
+ A.nvim_win_set_cursor(0, { srow + 1, 0 })
+ A.nvim_command('normal! ==')
+ move_n_insert(srow + 1, #A.nvim_get_current_line() - #if_rcs - 1)
+ U.is_fn(cfg.post_hook, ctx)
+end
+
+---Add a comment below the current line and goes to INSERT mode
+---@param ctype integer See |comment.utils.ctype|
+---@param cfg CommentConfig
+function extra.insert_below(ctype, cfg)
+ ins_on_line(0, ctype, cfg)
+end
+
+---Add a comment above the current line and goes to INSERT mode
+---@param ctype integer See |comment.utils.ctype|
+---@param cfg CommentConfig
+function extra.insert_above(ctype, cfg)
+ ins_on_line(-1, ctype, cfg)
+end
+
+---Add a comment at the end of current line and goes to INSERT mode
+---@param ctype integer See |comment.utils.ctype|
+---@param cfg CommentConfig
+function extra.insert_eol(ctype, cfg)
+ local srow, scol = unpack(A.nvim_win_get_cursor(0))
+
+ ---@type CommentCtx
+ local ctx = {
+ cmode = U.cmode.comment,
+ cmotion = U.cmotion.line,
+ ctype = ctype,
+ range = { srow = srow, scol = scol, erow = srow, ecol = scol },
+ }
+ local lcs, rcs = U.parse_cstr(cfg, ctx)
+
+ local line = A.nvim_get_current_line()
+ local padding = U.get_pad(U.is_fn(cfg.padding))
+
+ -- We need RHS of cstr, if we are doing block comments or if RHS exists
+ -- because even in line comment RHS do exists for some filetypes like jsx_element, ocaml
+ local if_rcs = U.is_empty(rcs) and rcs or padding .. rcs
+
+ local ecol
+ if U.is_empty(line) then
+ -- If line is empty, start comment at the correct indentation level
+ A.nvim_set_current_line(lcs .. padding .. if_rcs)
+ A.nvim_command('normal! ==')
+ ecol = #A.nvim_get_current_line() - #if_rcs - 1
+ else
+ -- NOTE:
+ -- 1. Python is the only language that recommends 2 spaces between the statement and the comment
+ -- 2. Other than that, I am assuming that the users wants a space b/w the end of line and start of the comment
+ local space = vim.bo.filetype == 'python' and ' ' or ' '
+ local ll = line .. space .. lcs .. padding
+ A.nvim_set_current_line(ll .. if_rcs)
+ ecol = #ll - 1
+ end
+
+ move_n_insert(srow, ecol)
+ U.is_fn(cfg.post_hook, ctx)
+end
+
+return extra
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/ft.lua b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/ft.lua
new file mode 100644
index 00000000..812eacd2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/ft.lua
@@ -0,0 +1,297 @@
+---@mod comment.ft Language/Filetype detection
+---@brief [[
+---This module is the core of filetype and commentstring detection and uses the
+---|lua-treesitter| APIs to accurately detect filetype and gives the corresponding
+---commentstring, stored inside the plugin, for the filetype/langauge.
+---
+---Compound (dot-separated) filetypes are also supported i.e. 'ansible.yaml',
+---'ios.swift' etc. The commentstring resolution will be done from left to right.
+---For example, If the filetype is 'ansible.yaml' then 'ansible' commenstring will
+---be used if found otherwise it'll fallback to 'yaml'. Read `:h 'filetype'`
+---@brief ]]
+
+local A = vim.api
+
+---Common commentstring shared b/w multiple languages
+local M = {
+ cxx_l = '//%s',
+ cxx_b = '/*%s*/',
+ dbl_hash = '##%s',
+ dash = '--%s',
+ dash_bracket = '--[[%s]]',
+ handlebars = '{{!--%s--}}',
+ hash = '#%s',
+ hash_bracket = '#[[%s]]',
+ haskell_b = '{-%s-}',
+ fsharp_b = '(*%s*)',
+ html = '',
+ latex = '%%s',
+ semicolon = ';%s',
+ lisp_l = ';;%s',
+ lisp_b = '#|%s|#',
+ twig = '{#%s#}',
+ vim = '"%s',
+ lean_b = '/-%s-/',
+}
+
+---Lang table that contains commentstring (linewise/blockwise) for multiple filetypes
+---Structure = { filetype = { linewise, blockwise } }
+---@type table
+local L = setmetatable({
+ arduino = { M.cxx_l, M.cxx_b },
+ applescript = { M.hash },
+ astro = { M.html },
+ autohotkey = { M.semicolon, M.cxx_b },
+ bash = { M.hash },
+ beancount = { M.semicolon },
+ bib = { M.latex },
+ c = { M.cxx_l, M.cxx_b },
+ cabal = { M.dash },
+ cmake = { M.hash, M.hash_bracket },
+ conf = { M.hash },
+ conkyrc = { M.dash, M.dash_bracket },
+ coq = { M.fsharp_b },
+ cpp = { M.cxx_l, M.cxx_b },
+ cs = { M.cxx_l, M.cxx_b },
+ css = { M.cxx_b, M.cxx_b },
+ cuda = { M.cxx_l, M.cxx_b },
+ dart = { M.cxx_l, M.cxx_b },
+ dhall = { M.dash, M.haskell_b },
+ dosbatch = { 'REM%s' },
+ dot = { M.cxx_l, M.cxx_b },
+ dts = { M.cxx_l, M.cxx_b },
+ editorconfig = { M.hash },
+ eelixir = { M.html, M.html },
+ elixir = { M.hash },
+ elm = { M.dash, M.haskell_b },
+ elvish = { M.hash },
+ faust = { M.cxx_l, M.cxx_b },
+ fennel = { M.semicolon },
+ fish = { M.hash },
+ func = { M.lisp_l },
+ fsharp = { M.cxx_l, M.fsharp_b },
+ gdb = { M.hash },
+ gdscript = { M.hash },
+ gitignore = { M.hash },
+ gleam = { M.cxx_l },
+ glsl = { M.cxx_l, M.cxx_b },
+ gnuplot = { M.hash, M.hash_bracket },
+ go = { M.cxx_l, M.cxx_b },
+ gomod = { M.cxx_l },
+ graphql = { M.hash },
+ groovy = { M.cxx_l, M.cxx_b },
+ handlebars = { M.handlebars, M.handlebars },
+ haskell = { M.dash, M.haskell_b },
+ haxe = { M.cxx_l, M.cxx_b },
+ heex = { M.html, M.html },
+ html = { M.html, M.html },
+ htmldjango = { M.html, M.html },
+ idris = { M.dash, M.haskell_b },
+ idris2 = { M.dash, M.haskell_b },
+ ini = { M.hash },
+ java = { M.cxx_l, M.cxx_b },
+ javascript = { M.cxx_l, M.cxx_b },
+ javascriptreact = { M.cxx_l, M.cxx_b },
+ jsonc = { M.cxx_l },
+ jsonnet = { M.cxx_l, M.cxx_b },
+ julia = { M.hash, '#=%s=#' },
+ kotlin = { M.cxx_l, M.cxx_b },
+ lean = { M.dash, M.lean_b },
+ lean3 = { M.dash, M.lean_b },
+ lidris = { M.dash, M.haskell_b },
+ lilypond = { M.latex, '%{%s%}' },
+ lisp = { M.lisp_l, M.lisp_b },
+ lua = { M.dash, M.dash_bracket },
+ luau = { M.dash, M.dash_bracket },
+ markdown = { M.html, M.html },
+ make = { M.hash },
+ mbsyncrc = { M.dbl_hash },
+ mermaid = { '%%%s' },
+ meson = { M.hash },
+ nextflow = { M.cxx_l, M.cxx_b },
+ nim = { M.hash, '#[%s]#' },
+ nix = { M.hash, M.cxx_b },
+ nu = { M.hash },
+ ocaml = { M.fsharp_b, M.fsharp_b },
+ odin = { M.cxx_l, M.cxx_b },
+ plantuml = { "'%s", "/'%s'/" },
+ purescript = { M.dash, M.haskell_b },
+ python = { M.hash }, -- Python doesn't have block comments
+ php = { M.cxx_l, M.cxx_b },
+ prisma = { M.cxx_l },
+ proto = { M.cxx_l, M.cxx_b },
+ quarto = { M.html, M.html },
+ r = { M.hash }, -- R doesn't have block comments
+ racket = { M.lisp_l, M.lisp_b },
+ rasi = { M.cxx_l, M.cxx_b },
+ readline = { M.hash },
+ rego = { M.hash },
+ remind = { M.hash },
+ rescript = { M.cxx_l, M.cxx_b },
+ robot = { M.hash }, -- Robotframework doesn't have block comments
+ ron = { M.cxx_l, M.cxx_b },
+ ruby = { M.hash },
+ rust = { M.cxx_l, M.cxx_b },
+ sbt = { M.cxx_l, M.cxx_b },
+ scala = { M.cxx_l, M.cxx_b },
+ scheme = { M.lisp_l, M.lisp_b },
+ sh = { M.hash },
+ solidity = { M.cxx_l, M.cxx_b },
+ supercollider = { M.cxx_l, M.cxx_b },
+ sql = { M.dash, M.cxx_b },
+ stata = { M.cxx_l, M.cxx_b },
+ svelte = { M.html, M.html },
+ swift = { M.cxx_l, M.cxx_b },
+ sxhkdrc = { M.hash },
+ tablegen = { M.cxx_l, M.cxx_b },
+ teal = { M.dash, M.dash_bracket },
+ terraform = { M.hash, M.cxx_b },
+ tex = { M.latex },
+ template = { M.dbl_hash },
+ tmux = { M.hash },
+ toml = { M.hash },
+ twig = { M.twig, M.twig },
+ typescript = { M.cxx_l, M.cxx_b },
+ typescriptreact = { M.cxx_l, M.cxx_b },
+ typst = { M.cxx_l, M.cxx_b },
+ v = { M.cxx_l, M.cxx_b },
+ verilog = { M.cxx_l },
+ vhdl = { M.dash },
+ vim = { M.vim },
+ vifm = { M.vim },
+ vue = { M.html, M.html },
+ xdefaults = { '!%s' },
+ xml = { M.html, M.html },
+ xonsh = { M.hash }, -- Xonsh doesn't have block comments
+ yaml = { M.hash },
+ yuck = { M.lisp_l },
+ zig = { M.cxx_l }, -- Zig doesn't have block comments
+}, {
+ -- Support for compound filetype i.e. 'ios.swift', 'ansible.yaml' etc.
+ __index = function(this, k)
+ local base, fallback = string.match(k, '^(.-)%.(.*)')
+ if not (base or fallback) then
+ return nil
+ end
+ return this[base] or this[fallback]
+ end,
+})
+
+local ft = {}
+
+---Sets a commentstring(s) for a filetype/language
+---@param lang string Filetype/Language of the buffer
+---@param val string|string[]
+---@return table self Returns itself
+---@usage [[
+---local ft = require('Comment.ft')
+---
+-----1. Using method signature
+----- Set only line comment or both
+----- You can also chain the set calls
+---ft.set('yaml', '#%s').set('javascript', {'//%s', '/*%s*/'})
+---
+----- 2. Metatable magic
+---ft.javascript = {'//%s', '/*%s*/'}
+---ft.yaml = '#%s'
+---
+----- 3. Multiple filetypes
+---ft({'go', 'rust'}, {'//%s', '/*%s*/'})
+---ft({'toml', 'graphql'}, '#%s')
+---@usage ]]
+function ft.set(lang, val)
+ L[lang] = type(val) == 'string' and { val } or val --[[ @as string[] ]]
+ return ft
+end
+
+---Get line/block/both commentstring(s) for a given filetype
+---@param lang string Filetype/Language of the buffer
+---@param ctype? integer See |comment.utils.ctype|. If given `nil`, it'll
+---return a copy of { line, block } commentstring.
+---@return nil|string|string[] #Returns stored commentstring
+---@usage [[
+---local ft = require('Comment.ft')
+---local U = require('Comment.utils')
+---
+----- 1. Primary filetype
+---ft.get('rust', U.ctype.linewise) -- `//%s`
+---ft.get('rust') -- `{ '//%s', '/*%s*/' }`
+---
+----- 2. Compound filetype
+----- NOTE: This will return `yaml` commenstring(s),
+----- as `ansible` commentstring is not found.
+---ft.get('ansible.yaml', U.ctype.linewise) -- `#%s`
+---ft.get('ansible.yaml') -- { '#%s' }
+---@usage ]]
+function ft.get(lang, ctype)
+ local tuple = L[lang]
+ if not tuple then
+ return nil
+ end
+ if not ctype then
+ return vim.deepcopy(tuple)
+ end
+ return tuple[ctype]
+end
+
+---Get a language tree for a given range by walking the parse tree recursively.
+---This uses 'lua-treesitter' API under the hood. This can be used to calculate
+---language of a particular region which embedded multiple filetypes like html,
+---vue, markdown etc.
+---
+---NOTE: This ignores `tree-sitter-comment` parser, if installed.
+---@param tree userdata Parse tree to be walked
+---@param range integer[] Range to check
+---{start_row, start_col, end_row, end_col}
+---@return userdata #Returns a |treesitter-languagetree|
+---@see treesitter-languagetree
+---@see lua-treesitter-core
+---@usage [[
+---local ok, parser = pcall(vim.treesitter.get_parser, 0)
+---assert(ok, "No parser found!")
+---local tree = require('Comment.ft').contains(parser, {0, 0, -1, 0})
+---print('Lang:', tree:lang())
+---@usage ]]
+function ft.contains(tree, range)
+ for lang, child in pairs(tree:children()) do
+ if lang ~= 'comment' and child:contains(range) then
+ return ft.contains(child, range)
+ end
+ end
+
+ return tree
+end
+
+---Calculate commentstring with the power of treesitter
+---@param ctx CommentCtx
+---@return nil|string #Commentstring
+---@see comment.utils.CommentCtx
+function ft.calculate(ctx)
+ local ok, parser = pcall(vim.treesitter.get_parser, A.nvim_get_current_buf())
+
+ if not ok then
+ return ft.get(vim.bo.filetype, ctx.ctype) --[[ @as string ]]
+ end
+
+ local lang = ft.contains(parser, {
+ ctx.range.srow - 1,
+ ctx.range.scol,
+ ctx.range.erow - 1,
+ ctx.range.ecol,
+ }):lang()
+
+ return ft.get(lang, ctx.ctype) or ft.get(vim.bo.filetype, ctx.ctype) --[[ @as string ]]
+end
+
+---@export ft
+return setmetatable(ft, {
+ __newindex = function(this, k, v)
+ this.set(k, v)
+ end,
+ __call = function(this, langs, spec)
+ for _, lang in ipairs(langs) do
+ this.set(lang, spec)
+ end
+ return this
+ end,
+})
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/init.lua b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/init.lua
new file mode 100644
index 00000000..2cdfc7b8
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/init.lua
@@ -0,0 +1,138 @@
+---@brief [[
+---*comment-nvim.txt* For Neovim version 0.7 Last change: 2021 July 11
+---
+--- _____ _ _
+--- / ____/ / / (_)
+--- / / ___ _ __ ___ _ __ ___ ___ _ __ / /_ _ ____ ___ _ __ ___
+--- / / / _ \/ '_ ` _ \/ '_ ` _ \ / _ \ '_ \/ __/ / '_ \ \ / / / '_ ` _ \
+--- / /___/ (_) / / / / / / / / / / / __/ / / / /_ _/ / / \ V // / / / / / /
+--- \_____\___//_/ /_/ /_/_/ /_/ /_/\___/_/ /_/\__(_)_/ /_/\_/ /_/_/ /_/ /_/
+---
+--- · Smart and Powerful comment plugin ·
+---
+---@brief ]]
+
+---@toc comment.contents
+
+---@mod comment-nvim Introduction
+---@brief [[
+---Comment.nvim is a smart and powerful comment plugin for neovim. It supports
+---dot-repeat, counts, line ('//') and block ('/* */') comments, and can be used
+---with motion and text-objects. It has native integration with |treesitter| to
+---support embedded filetypes like html, vue, markdown with codeblocks etc.
+---@brief ]]
+---@tag comment.dotrepeat
+---@brief [[
+---Comment.nvim uses |operatorfunc| combined with |g@| to support dot-repeat, and
+---various marks i.e., |'[| |']| |'<| |'>| to deduce the region with the {motion}
+---argument provided by 'operatorfunc'. See |comment.api.call|
+---@brief ]]
+---@tag comment.commentstring
+---@brief [[
+---Comment.nvim picks commentstring, either linewise/blockwise, from one of the
+---following places
+---
+--- 1. 'pre_hook'
+--- If a string is returned from this function then it will be used for
+--- (un)commenting. See |comment.config|
+---
+--- 2. |comment.ft|
+--- Using the commentstring table inside the plugin (using treesitter).
+--- Fallback to |commentstring|, if not found.
+---
+--- 3. |commentstring| - Neovim's native commentstring for the filetype
+---
+---Although Comment.nvim supports native 'commentstring' but unfortunately it has
+---the least priority. The caveat with this approach is that if someone sets the
+---`commentstring`, without returning it, from the 'pre_hook' and the current
+---filetype also exists in the |comment.ft| then the commenting will be done using
+---the string in |comment.ft| instead of using 'commentstring'. To override this
+---behavior, you have to manually return the 'commentstring' from 'pre_hook'.
+---@brief ]]
+---@tag comment.sourcecode
+---@brief [[
+---Comment.nvim is FOSS and distributed under MIT license. All the source code is
+---available at https://github.com/numToStr/Comment.nvim
+---@brief ]]
+
+---@mod comment.usage Usage
+---@brief [[
+---Before using the plugin, you need to call the `setup()` function to create the
+---default mappings. If you want, you can also override the default configuration
+---by giving it a partial 'comment.config.Config' object, it will then be merged
+---with the default configuration.
+---@brief ]]
+
+local C = {}
+
+---Configures the plugin
+---@param config? CommentConfig User configuration
+---@return CommentConfig #Returns the modified config
+---@see comment.config
+---@usage [[
+----- Use default configuration
+---require('Comment').setup()
+---
+----- or with custom configuration
+---require('Comment').setup({
+--- ignore = '^$',
+--- toggler = {
+--- line = 'cc',
+--- block = 'bc',
+--- },
+--- opleader = {
+--- line = 'c',
+--- block = 'b',
+--- },
+---})
+---@usage ]]
+function C.setup(config)
+ local cfg = require('Comment.config'):set(config):get()
+
+ if cfg.mappings then
+ local api = require('Comment.api')
+ local vvar = vim.api.nvim_get_vvar
+ local K = vim.keymap.set
+
+ -- Basic Mappings
+ if cfg.mappings.basic then
+ -- NORMAL mode mappings
+ K('n', cfg.opleader.line, '(comment_toggle_linewise)', { desc = 'Comment toggle linewise' })
+ K('n', cfg.opleader.block, '(comment_toggle_blockwise)', { desc = 'Comment toggle blockwise' })
+
+ K('n', cfg.toggler.line, function()
+ return vvar('count') == 0 and '(comment_toggle_linewise_current)'
+ or '(comment_toggle_linewise_count)'
+ end, { expr = true, desc = 'Comment toggle current line' })
+ K('n', cfg.toggler.block, function()
+ return vvar('count') == 0 and '(comment_toggle_blockwise_current)'
+ or '(comment_toggle_blockwise_count)'
+ end, { expr = true, desc = 'Comment toggle current block' })
+
+ -- VISUAL mode mappings
+ K(
+ 'x',
+ cfg.opleader.line,
+ '(comment_toggle_linewise_visual)',
+ { desc = 'Comment toggle linewise (visual)' }
+ )
+ K(
+ 'x',
+ cfg.opleader.block,
+ '(comment_toggle_blockwise_visual)',
+ { desc = 'Comment toggle blockwise (visual)' }
+ )
+ end
+
+ -- Extra Mappings
+ if cfg.mappings.extra then
+ K('n', cfg.extra.below, api.insert.linewise.below, { desc = 'Comment insert below' })
+ K('n', cfg.extra.above, api.insert.linewise.above, { desc = 'Comment insert above' })
+ K('n', cfg.extra.eol, api.locked('insert.linewise.eol'), { desc = 'Comment insert end of line' })
+ end
+ end
+
+ return cfg
+end
+
+return C
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/opfunc.lua b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/opfunc.lua
new file mode 100644
index 00000000..02585a63
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/opfunc.lua
@@ -0,0 +1,228 @@
+---@mod comment.opfunc Operator-mode API
+---@brief [[
+---Underlying functions that powers the |comment.api.toggle|, |comment.api.comment|,
+---and |comment.api.uncomment| lua API.
+---@brief ]]
+
+local U = require('Comment.utils')
+local Config = require('Comment.config')
+local A = vim.api
+
+local Op = {}
+
+---Vim operator-mode motion enum. Read |:map-operator|
+---@alias OpMotion
+---| '"line"' # Vertical motion
+---| '"char"' # Horizontal motion
+---| '"v"' # Visual Block motion
+---| '"V"' # Visual Line motion
+
+---Common operatorfunc callback
+---This function contains the core logic for comment/uncomment
+---@param motion? OpMotion
+---If given 'nil', it'll only (un)comment
+---the current line
+---@param cfg CommentConfig
+---@param cmode integer See |comment.utils.cmode|
+---@param ctype integer See |comment.utils.ctype|
+function Op.opfunc(motion, cfg, cmode, ctype)
+ local range = U.get_region(motion)
+ local cmotion = motion == nil and U.cmotion.line or U.cmotion[motion]
+
+ -- If we are doing char or visual motion on the same line
+ -- then we would probably want block comment instead of line comment
+ local is_partial = cmotion == U.cmotion.char or cmotion == U.cmotion.v
+ local is_blockx = is_partial and range.srow == range.erow
+
+ local lines = U.get_lines(range)
+
+ -- sometimes there might be a case when there are no lines
+ -- like, executing a text object returns nothing
+ if U.is_empty(lines) then
+ return
+ end
+
+ ---@type CommentCtx
+ local ctx = {
+ cmode = cmode,
+ cmotion = cmotion,
+ ctype = is_blockx and U.ctype.blockwise or ctype,
+ range = range,
+ }
+
+ local lcs, rcs = U.parse_cstr(cfg, ctx)
+
+ ---@type OpFnParams
+ local params = {
+ cfg = cfg,
+ lines = lines,
+ lcs = lcs,
+ rcs = rcs,
+ cmode = cmode,
+ range = range,
+ }
+
+ if motion ~= nil and (is_blockx or ctype == U.ctype.blockwise) then
+ ctx.cmode = Op.blockwise(params, is_partial)
+ else
+ ctx.cmode = Op.linewise(params)
+ end
+
+ -- We only need to restore cursor if both sticky and position are available
+ -- As this function is also called for visual mapping where we are not storing the position
+ --
+ -- And I found out that if someone presses `gc` but doesn't provide operators and
+ -- does visual comments then cursor jumps to previous stored position. Thus the check for visual modes
+ if cfg.sticky and Config.position and cmotion ~= U.cmotion.v and cmotion ~= U.cmotion.V then
+ A.nvim_win_set_cursor(0, Config.position)
+ Config.position = nil
+ end
+
+ U.is_fn(cfg.post_hook, ctx)
+end
+
+---Line commenting with count
+---@param count integer Value of |v:count|
+---@param cfg CommentConfig
+---@param cmode integer See |comment.utils.cmode|
+---@param ctype integer See |comment.utils.ctype|
+function Op.count(count, cfg, cmode, ctype)
+ local lines, range = U.get_count_lines(count)
+
+ ---@type CommentCtx
+ local ctx = {
+ cmode = cmode,
+ cmotion = U.cmotion.line,
+ ctype = ctype,
+ range = range,
+ }
+ local lcs, rcs = U.parse_cstr(cfg, ctx)
+
+ ---@type OpFnParams
+ local params = {
+ cfg = cfg,
+ cmode = ctx.cmode,
+ lines = lines,
+ lcs = lcs,
+ rcs = rcs,
+ range = range,
+ }
+
+ if ctype == U.ctype.blockwise then
+ ctx.cmode = Op.blockwise(params)
+ else
+ ctx.cmode = Op.linewise(params)
+ end
+
+ U.is_fn(cfg.post_hook, ctx)
+end
+
+---Operator-mode function parameters
+---@class OpFnParams
+---@field cfg CommentConfig
+---@field cmode integer See |comment.utils.cmode|
+---@field lines string[] List of lines
+---@field rcs string RHS of commentstring
+---@field lcs string LHS of commentstring
+---@field range CommentRange
+
+---Line commenting
+---@param param OpFnParams
+---@return integer _ Returns a calculated comment mode
+function Op.linewise(param)
+ local pattern = U.is_fn(param.cfg.ignore)
+ local padding = U.is_fn(param.cfg.padding)
+ local check_comment = U.is_commented(param.lcs, param.rcs, padding)
+
+ -- While commenting a region, there could be lines being both commented and non-commented
+ -- So, if any line is uncommented then we should comment the whole block or vise-versa
+ local cmode = U.cmode.uncomment
+
+ ---When commenting multiple line, it is to be expected that indentation should be preserved
+ ---So, When looping over multiple lines we need to store the indentation of the mininum length (except empty line)
+ ---Which will be used to semantically comment rest of the lines
+ local min_indent, tabbed = -1, false
+
+ -- If the given cmode is uncomment then we actually don't want to compute the cmode or min_indent
+ if param.cmode ~= U.cmode.uncomment then
+ for _, line in ipairs(param.lines) do
+ -- I wish lua had `continue` statement [sad noises]
+ if not U.ignore(line, pattern) then
+ if cmode == U.cmode.uncomment and param.cmode == U.cmode.toggle and (not check_comment(line)) then
+ cmode = U.cmode.comment
+ end
+
+ if not U.is_empty(line) and param.cmode ~= U.cmode.uncomment then
+ local _, len = string.find(line, '^%s*')
+ if min_indent == -1 or min_indent > len then
+ min_indent, tabbed = len, string.find(line, '^\t') ~= nil
+ end
+ end
+ end
+ end
+ end
+
+ -- If the comment mode given is not toggle than force that mode
+ if param.cmode ~= U.cmode.toggle then
+ cmode = param.cmode
+ end
+
+ if cmode == U.cmode.uncomment then
+ local uncomment = U.uncommenter(param.lcs, param.rcs, padding)
+ for i, line in ipairs(param.lines) do
+ if not U.ignore(line, pattern) then
+ param.lines[i] = uncomment(line) --[[@as string]]
+ end
+ end
+ else
+ local comment = U.commenter(param.lcs, param.rcs, padding, min_indent, nil, tabbed)
+ for i, line in ipairs(param.lines) do
+ if not U.ignore(line, pattern) then
+ param.lines[i] = comment(line) --[[@as string]]
+ end
+ end
+ end
+
+ A.nvim_buf_set_lines(0, param.range.srow - 1, param.range.erow, false, param.lines)
+
+ return cmode
+end
+
+---Full/Partial/Current-Line Block commenting
+---@param param OpFnParams
+---@param partial? boolean Comment the partial region (visual mode)
+---@return integer _ Returns a calculated comment mode
+function Op.blockwise(param, partial)
+ local is_x = #param.lines == 1 -- current-line blockwise
+ local lines = is_x and param.lines[1] or param.lines
+
+ local padding = U.is_fn(param.cfg.padding)
+
+ local scol, ecol = nil, nil
+ if is_x or partial then
+ scol, ecol = param.range.scol, param.range.ecol
+ end
+
+ -- If given mode is toggle then determine whether to comment or not
+ local cmode = param.cmode
+ if cmode == U.cmode.toggle then
+ local is_cmt = U.is_commented(param.lcs, param.rcs, padding, scol, ecol)(lines)
+ cmode = is_cmt and U.cmode.uncomment or U.cmode.comment
+ end
+
+ if cmode == U.cmode.uncomment then
+ lines = U.uncommenter(param.lcs, param.rcs, padding, scol, ecol)(lines)
+ else
+ lines = U.commenter(param.lcs, param.rcs, padding, scol, ecol)(lines)
+ end
+
+ if is_x then
+ A.nvim_set_current_line(lines)
+ else
+ A.nvim_buf_set_lines(0, param.range.srow - 1, param.range.erow, false, lines)
+ end
+
+ return cmode
+end
+
+return Op
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/utils.lua b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/utils.lua
new file mode 100644
index 00000000..e95ee2c3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/lua/Comment/utils.lua
@@ -0,0 +1,376 @@
+---@mod comment.utils Utilities
+
+local F = require('Comment.ft')
+local A = vim.api
+
+local U = {}
+
+---Comment context
+---@class CommentCtx
+---@field ctype integer See |comment.utils.ctype|
+---@field cmode integer See |comment.utils.cmode|
+---@field cmotion integer See |comment.utils.cmotion|
+---@field range CommentRange
+
+---Range of the selection that needs to be commented
+---@class CommentRange
+---@field srow integer Starting row
+---@field scol integer Starting column
+---@field erow integer Ending row
+---@field ecol integer Ending column
+
+---Comment modes - Can be manual or computed via operator-mode
+---@class CommentMode
+---@field toggle integer Toggle action
+---@field comment integer Comment action
+---@field uncomment integer Uncomment action
+
+---An object containing comment modes
+---@type CommentMode
+U.cmode = {
+ toggle = 0,
+ comment = 1,
+ uncomment = 2,
+}
+
+---Comment types
+---@class CommentType
+---@field linewise integer Use linewise commentstring
+---@field blockwise integer Use blockwise commentstring
+
+---An object containing comment types
+---@type CommentType
+U.ctype = {
+ linewise = 1,
+ blockwise = 2,
+}
+
+---Comment motion types
+---@class CommentMotion
+---@field line integer Line motion (ie. 'gc2j')
+---@field char integer Character/left-right motion (ie. 'gc2w')
+---@field block integer Visual operator-pending motion
+---@field v integer Visual motion (ie. 'v3jgc')
+---@field V integer Visual-line motion (ie. 'V10kgc')
+
+---An object containing comment motions
+---@type CommentMotion
+U.cmotion = {
+ line = 1,
+ char = 2,
+ block = 3,
+ v = 4,
+ V = 5,
+}
+
+---@private
+---Check whether the line is empty
+---@param iter string|string[]
+---@return boolean
+function U.is_empty(iter)
+ return #iter == 0
+end
+
+---@private
+---Helper to get padding character
+---@param flag boolean
+---@return string string
+function U.get_pad(flag)
+ return flag and ' ' or ''
+end
+
+---@private
+---Helper to get padding pattern
+---@param flag boolean
+---@return string string
+function U.get_padpat(flag)
+ return flag and '%s?' or ''
+end
+
+---@private
+---Call a function if exists
+---@param fn unknown|fun(...):unknown Wanna be function
+---@return unknown
+function U.is_fn(fn, ...)
+ if type(fn) == 'function' then
+ return fn(...)
+ end
+ return fn
+end
+
+---@private
+---Check if the given line is ignored or not with the given pattern
+---@param ln string Line to be ignored
+---@param pat string Lua regex
+---@return boolean
+function U.ignore(ln, pat)
+ return pat and string.find(ln, pat) ~= nil
+end
+
+---Get region for line movement or visual selection
+---NOTE: Returns the current line region, if `opmode` is not given.
+---@param opmode? OpMotion
+---@return CommentRange
+function U.get_region(opmode)
+ if not opmode then
+ local row = unpack(A.nvim_win_get_cursor(0))
+ return { srow = row, scol = 0, erow = row, ecol = 0 }
+ end
+
+ local marks = string.match(opmode, '[vV]') and { '<', '>' } or { '[', ']' }
+ local sln, eln = A.nvim_buf_get_mark(0, marks[1]), A.nvim_buf_get_mark(0, marks[2])
+
+ return { srow = sln[1], scol = sln[2], erow = eln[1], ecol = eln[2] }
+end
+
+---Get lines from the current position to the given count
+---@param count integer Probably 'vim.v.count'
+---@return string[] #List of lines
+---@return CommentRange
+function U.get_count_lines(count)
+ local srow = unpack(A.nvim_win_get_cursor(0))
+ local erow = (srow + count) - 1
+ local lines = A.nvim_buf_get_lines(0, srow - 1, erow, false)
+
+ return lines, { srow = srow, scol = 0, erow = erow, ecol = 0 }
+end
+
+---Get lines from a NORMAL/VISUAL mode
+---@param range CommentRange
+---@return string[] #List of lines
+function U.get_lines(range)
+ -- If start and end is same, then just return the current line
+ if range.srow == range.erow then
+ return { A.nvim_get_current_line() }
+ end
+
+ return A.nvim_buf_get_lines(0, range.srow - 1, range.erow, false)
+end
+
+---Validates and unwraps the given commentstring
+---@param cstr string See 'commentstring'
+---@return string string Left side of the commentstring
+---@return string string Right side of the commentstring
+function U.unwrap_cstr(cstr)
+ local left, right = string.match(cstr, '(.*)%%s(.*)')
+
+ assert(
+ (left or right),
+ { msg = string.format('Invalid commentstring for %s! Read `:h commentstring` for help.', vim.bo.filetype) }
+ )
+
+ return vim.trim(left), vim.trim(right)
+end
+
+---Parses commentstring from the following places in the respective order
+--- 1. pre_hook - commentstring returned from the function
+--- 2. ft.lua - commentstring table bundled with the plugin
+--- 3. commentstring - Neovim's native. See 'commentstring'
+---@param cfg CommentConfig
+---@param ctx CommentCtx
+---@return string string Left side of the commentstring
+---@return string string Right side of the commentstring
+function U.parse_cstr(cfg, ctx)
+ -- 1. We ask `pre_hook` for a commentstring
+ local inbuilt = U.is_fn(cfg.pre_hook, ctx)
+ -- 2. Calculate w/ the help of treesitter
+ or F.calculate(ctx)
+
+ assert(inbuilt or (ctx.ctype ~= U.ctype.blockwise), {
+ msg = vim.bo.filetype .. " doesn't support block comments!",
+ })
+
+ -- 3. Last resort to use native commentstring
+ return U.unwrap_cstr(inbuilt or vim.bo.commentstring)
+end
+
+---Returns a closure which is used to do comments
+---
+---If given {string[]} to the closure then it will do blockwise comment
+---else linewise comment will be done with the given {string}
+---@param left string Left side of the commentstring
+---@param right string Right side of the commentstring
+---@param padding boolean Is padding enabled?
+---@param scol? integer Starting column
+---@param ecol? integer Ending column
+---@param tabbed? boolean Using tab indentation
+---@return fun(line: string|string[]):string|string[]
+function U.commenter(left, right, padding, scol, ecol, tabbed)
+ local pad = U.get_pad(padding)
+ local ll = U.is_empty(left) and left or (left .. pad)
+ local rr = U.is_empty(right) and right or (pad .. right)
+ local empty = string.rep(tabbed and '\t' or ' ', scol or 0) .. left .. right
+ local is_lw = scol and not ecol
+
+ return function(line)
+ ------------------
+ -- for linewise --
+ ------------------
+ if is_lw then
+ if U.is_empty(line) then
+ return empty
+ end
+ -- line == 0 -> start from 0 col
+ if scol == 0 then
+ return (ll .. line .. rr)
+ end
+ local first = string.sub(line --[[@as string]], 0, scol)
+ local last = string.sub(line --[[@as string]], scol + 1, -1)
+ return first .. ll .. last .. rr
+ end
+
+ -------------------
+ -- for blockwise --
+ -------------------
+ if type(line) == 'table' then
+ local first, last = line[1], line[#line]
+ -- If both columns are given then we can assume it's a partial block
+ if scol and ecol then
+ local sfirst = string.sub(first, 0, scol)
+ local slast = string.sub(first, scol + 1, -1)
+ local efirst = string.sub(last, 0, ecol + 1)
+ local elast = string.sub(last, ecol + 2, -1)
+ line[1] = sfirst .. ll .. slast
+ line[#line] = efirst .. rr .. elast
+ else
+ line[1] = U.is_empty(first) and left or string.gsub(first, '^(%s*)', '%1' .. vim.pesc(ll))
+ line[#line] = U.is_empty(last) and right or (last .. rr)
+ end
+ return line
+ end
+
+ --------------------------------
+ -- for current-line blockwise --
+ --------------------------------
+ -- SOURCE: https://github.com/numToStr/Comment.nvim/issues/224
+ if ecol > #line then
+ return ll .. line .. rr
+ end
+ local first = string.sub(line, 0, scol)
+ local mid = string.sub(line, scol + 1, ecol + 1)
+ local last = string.sub(line, ecol + 2, -1)
+ return first .. ll .. mid .. rr .. last
+ end
+end
+
+---Returns a closure which is used to uncomment a line
+---
+---If given {string[]} to the closure then it will block uncomment
+---else linewise uncomment will be done with the given {string}
+---@param left string Left side of the commentstring
+---@param right string Right side of the commentstring
+---@param padding boolean Is padding enabled?
+---@param scol? integer Starting column
+---@param ecol? integer Ending column
+---@return fun(line: string|string[]):string|string[]
+function U.uncommenter(left, right, padding, scol, ecol)
+ local pp, plen = U.get_padpat(padding), padding and 1 or 0
+ local left_len, right_len = #left + plen, #right + plen
+ local ll = U.is_empty(left) and left or vim.pesc(left) .. pp
+ local rr = U.is_empty(right) and right or pp .. vim.pesc(right)
+ local is_lw = not (scol and scol)
+ local pattern = is_lw and '^(%s*)' .. ll .. '(.-)' .. rr .. '$' or ''
+
+ return function(line)
+ -------------------
+ -- for blockwise --
+ -------------------
+ if type(line) == 'table' then
+ local first, last = line[1], line[#line]
+ -- If both columns are given then we can assume it's a partial block
+ if scol and ecol then
+ local sfirst = string.sub(first, 0, scol)
+ local slast = string.sub(first, scol + left_len + 1, -1)
+ local efirst = string.sub(last, 0, ecol - right_len + 1)
+ local elast = string.sub(last, ecol + 2, -1)
+ line[1] = sfirst .. slast
+ line[#line] = efirst .. elast
+ else
+ line[1] = string.gsub(first, '^(%s*)' .. ll, '%1')
+ line[#line] = string.gsub(last, rr .. '$', '')
+ end
+ return line
+ end
+
+ ------------------
+ -- for linewise --
+ ------------------
+ if is_lw then
+ local a, b, c = string.match(line, pattern)
+ -- When user tries to uncomment when there is nothing to uncomment. See #221
+ assert(a and b, { msg = 'Nothing to uncomment!' })
+ -- If there is nothing after LHS then just return ''
+ -- bcz the line previously (before comment) was empty
+ return U.is_empty(b) and b or a .. b .. (c or '')
+ end
+
+ --------------------------------
+ -- for current-line blockwise --
+ --------------------------------
+ -- SOURCE: https://github.com/numToStr/Comment.nvim/issues/224
+ if ecol > #line then
+ return string.sub(line, scol + left_len + 1, #line - right_len)
+ end
+ local first = string.sub(line, 0, scol)
+ local mid = string.sub(line, scol + left_len + 1, ecol - right_len + 1)
+ local last = string.sub(line, ecol + 2, -1)
+ return first .. mid .. last
+ end
+end
+
+---Check if the given string is commented or not
+---
+---If given {string[]} to the closure, it will check the first and last line
+---with LHS and RHS of commentstring respectively else it will check the given
+---line with LHS and RHS (if given) of the commenstring
+---@param left string Left side of the commentstring
+---@param right string Right side of the commentstring
+---@param padding boolean Is padding enabled?
+---@param scol? integer Starting column
+---@param ecol? integer Ending column
+---@return fun(line: string|string[]):boolean
+function U.is_commented(left, right, padding, scol, ecol)
+ local pp = U.get_padpat(padding)
+ local ll = U.is_empty(left) and left or '^%s*' .. vim.pesc(left) .. pp
+ local rr = U.is_empty(right) and right or pp .. vim.pesc(right) .. '$'
+ local pattern = ll .. '.-' .. rr
+ local is_full = scol == nil or ecol == nil
+
+ return function(line)
+ -------------------
+ -- for blockwise --
+ -------------------
+ if type(line) == 'table' then
+ local first, last = line[1], line[#line]
+ if is_full then
+ return (string.find(first, ll) and string.find(last, rr)) ~= nil
+ end
+ return (string.find(string.sub(first, scol + 1, -1), ll) and string.find(string.sub(last, 0, ecol + 1), rr))
+ ~= nil
+ end
+
+ ------------------
+ -- for linewise --
+ ------------------
+ if is_full then
+ return string.find(line, pattern) ~= nil
+ end
+
+ --------------------------------
+ -- for current-line blockwise --
+ --------------------------------
+ -- SOURCE: https://github.com/numToStr/Comment.nvim/issues/224
+ return string.find(string.sub(line, scol + 1, (ecol > #line and #line or ecol + 1)), pattern) ~= nil
+ end
+end
+
+---@private
+---Error handler
+---@param ... unknown
+function U.catch(fn, ...)
+ xpcall(fn, function(err)
+ vim.notify(string.format('[Comment.nvim] %s', err.msg), vim.log.levels.WARN)
+ end, ...)
+end
+
+return U
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/plugin/Comment.lua b/config/neovim/store/lazy-plugins/comment.nvim/plugin/Comment.lua
new file mode 100644
index 00000000..485b97cb
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/plugin/Comment.lua
@@ -0,0 +1,142 @@
+local K = vim.keymap.set
+local call = require('Comment.api').call
+
+---@mod comment.keybindings Keybindings
+---@brief [[
+---Comment.nvim provides default keybindings for (un)comment your code. These
+---keybinds are enabled upon calling |comment.usage.setup| and can be configured
+---or disabled, if desired.
+---
+---Basic: ~
+---
+--- *gc*
+--- *gb*
+--- *gc[count]{motion}*
+--- *gb[count]{motion}*
+---
+--- Toggle comment on a region using linewise/blockwise comment. In 'NORMAL'
+--- mode, it uses 'Operator-Pending' mode to listen for an operator/motion.
+--- In 'VISUAL' mode it simply comment the selected region.
+---
+--- *gcc*
+--- *gbc*
+--- *[count]gcc*
+--- *[count]gbc*
+---
+--- Toggle comment on the current line using linewise/blockwise comment. If
+--- prefixed with a 'v:count' then it will comment over the number of lines
+--- corresponding to the {count}. These are only available in 'NORMAL' mode.
+---
+---
+---Extra: ~
+---
+--- *gco* - Inserts comment below and enters INSERT mode
+--- *gcO* - Inserts comment above and enters INSERT mode
+--- *gcA* - Inserts comment at the end of line and enters INSERT mode
+---@brief ]]
+
+---@mod comment.plugmap Plug Mappings
+---@brief [[
+---Comment.nvim provides mappings for most commonly used actions. These
+---are enabled by default and can be used to make custom keybindings. All plug
+---mappings have support for dot-repeat except VISUAL mode keybindings. To create
+---custom comment function, check out 'comment.api' section.
+---
+--- *(comment_toggle_linewise)*
+--- *(comment_toggle_blockwise)*
+---
+--- Toggle comment on a region with linewise/blockwise comment in NORMAL mode.
+--- using |Operator-Pending| mode (or |g@|) to get the region to comment.
+--- These powers the |gc| and |gb| keybindings.
+---
+--- *(comment_toggle_linewise_current)*
+--- *(comment_toggle_blockwise_current)*
+---
+--- Toggle comment on the current line with linewise/blockwise comment in
+--- NORMAL mode. These powers the |gcc| and 'gbc' keybindings.
+---
+--- *(comment_toggle_linewise_count)*
+--- *(comment_toggle_blockwise_count)*
+---
+--- Toggle comment on a region using 'v:count' with linewise/blockwise comment
+--- in NORMAL mode. These powers the |[count]gcc| and |[count]gbc| keybindings.
+---
+--- *(comment_toggle_linewise_visual)*
+--- *(comment_toggle_blockwise_visual)*
+---
+--- Toggle comment on the selected region with linewise/blockwise comment in
+--- NORMAL mode. These powers the |{visual}gc| and |{visual}gb| keybindings.
+---
+---Usage: ~
+--->lua
+--- -- Toggle current line or with count
+--- vim.keymap.set('n', 'gcc', function()
+--- return vim.v.count == 0
+--- and '(comment_toggle_linewise_current)'
+--- or '(comment_toggle_linewise_count)'
+--- end, { expr = true })
+---
+--- -- Toggle in Op-pending mode
+--- vim.keymap.set('n', 'gc', '(comment_toggle_linewise)')
+---
+--- -- Toggle in VISUAL mode
+--- vim.keymap.set('x', 'gc', '(comment_toggle_linewise_visual)')
+---<
+---@brief ]]
+---@export plugs
+
+-- Operator-Pending mappings
+K(
+ 'n',
+ '(comment_toggle_linewise)',
+ call('toggle.linewise', 'g@'),
+ { expr = true, desc = 'Comment toggle linewise' }
+)
+K(
+ 'n',
+ '(comment_toggle_blockwise)',
+ call('toggle.blockwise', 'g@'),
+ { expr = true, desc = 'Comment toggle blockwise' }
+)
+
+-- Toggle mappings
+K(
+ 'n',
+ '(comment_toggle_linewise_current)',
+ call('toggle.linewise.current', 'g@$'),
+ { expr = true, desc = 'Comment toggle current line' }
+)
+K(
+ 'n',
+ '(comment_toggle_blockwise_current)',
+ call('toggle.blockwise.current', 'g@$'),
+ { expr = true, desc = 'Comment toggle current block' }
+)
+
+-- Count mappings
+K(
+ 'n',
+ '(comment_toggle_linewise_count)',
+ call('toggle.linewise.count_repeat', 'g@$'),
+ { expr = true, desc = 'Comment toggle linewise with count' }
+)
+K(
+ 'n',
+ '(comment_toggle_blockwise_count)',
+ call('toggle.blockwise.count_repeat', 'g@$'),
+ { expr = true, desc = 'Comment toggle blockwise with count' }
+)
+
+-- Visual-Mode mappings
+K(
+ 'x',
+ '(comment_toggle_linewise_visual)',
+ 'lua require("Comment.api").locked("toggle.linewise")(vim.fn.visualmode())',
+ { desc = 'Comment toggle linewise (visual)' }
+)
+K(
+ 'x',
+ '(comment_toggle_blockwise_visual)',
+ 'lua require("Comment.api").locked("toggle.blockwise")(vim.fn.visualmode())',
+ { desc = 'Comment toggle blockwise (visual)' }
+)
diff --git a/config/neovim/store/lazy-plugins/comment.nvim/stylua.toml b/config/neovim/store/lazy-plugins/comment.nvim/stylua.toml
new file mode 100644
index 00000000..46b71c37
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/comment.nvim/stylua.toml
@@ -0,0 +1,4 @@
+line_endings = "Unix"
+indent_type = "Spaces"
+indent_width = 4
+quote_style = "AutoPreferSingle"
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.envrc b/config/neovim/store/lazy-plugins/conform.nvim/.envrc
new file mode 100644
index 00000000..6a2e7a85
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.envrc
@@ -0,0 +1,2 @@
+layout python
+python -c 'import pyparsing' 2> /dev/null || pip install pyparsing==3.0.9 black isort mypy
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.github/ISSUE_TEMPLATE/bug_report.yml b/config/neovim/store/lazy-plugins/conform.nvim/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 00000000..f7c26327
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,129 @@
+name: Bug Report
+description: File a bug/issue
+title: "bug: "
+labels: [bug]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Before reporting a bug, make sure to search [existing issues](https://github.com/stevearc/conform.nvim/issues)
+ - type: input
+ attributes:
+ label: "Neovim version (nvim -v)"
+ placeholder: "0.8.0 commit db1b0ee3b30f"
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: "Operating system/version"
+ placeholder: "MacOS 11.5"
+ validations:
+ required: true
+ - type: checkboxes
+ attributes:
+ label: Add the debug logs
+ options:
+ - label: I have set `log_level = vim.log.levels.DEBUG` and pasted the log contents below.
+ required: true
+ - type: textarea
+ attributes:
+ label: "Log file"
+ description: "Recent contents from the log file. You can find it with :ConformInfo"
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe the bug
+ description: A clear and concise description of what the bug is.
+ validations:
+ required: true
+ - type: dropdown
+ attributes:
+ label: What is the severity of this bug?
+ options:
+ - minor (annoyance)
+ - tolerable (can work around it)
+ - breaking (some functionality is broken)
+ - blocking (cannot use plugin)
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Steps To Reproduce
+ description: Steps to reproduce the behavior.
+ placeholder: |
+ 1. nvim -u repro.lua
+ 2.
+ 3.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Expected Behavior
+ description: A concise description of what you expected to happen.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Minimal example file
+ description: A small example file you are editing that produces the issue
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Minimal init.lua
+ description:
+ Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
+ This uses lazy.nvim (a plugin manager).
+ value: |
+ -- DO NOT change the paths and don't remove the colorscheme
+ local root = vim.fn.fnamemodify("./.repro", ":p")
+
+ -- set stdpaths to use .repro
+ for _, name in ipairs({ "config", "data", "state", "cache" }) do
+ vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
+ end
+
+ -- bootstrap lazy
+ local lazypath = root .. "/plugins/lazy.nvim"
+ if not vim.loop.fs_stat(lazypath) then
+ vim.fn.system({
+ "git",
+ "clone",
+ "--filter=blob:none",
+ "--single-branch",
+ "https://github.com/folke/lazy.nvim.git",
+ lazypath,
+ })
+ end
+ vim.opt.runtimepath:prepend(lazypath)
+
+ -- install plugins
+ local plugins = {
+ "folke/tokyonight.nvim",
+ {
+ "stevearc/conform.nvim",
+ config = function()
+ require("conform").setup({
+ log_level = vim.log.levels.DEBUG,
+ -- add your config here
+ })
+ end,
+ },
+ -- add any other plugins here
+ }
+ require("lazy").setup(plugins, {
+ root = root .. "/plugins",
+ })
+
+ vim.cmd.colorscheme("tokyonight")
+ -- add anything else here
+ render: Lua
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Additional context
+ description: Any additional information or screenshots you would like to provide
+ validations:
+ required: false
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.github/ISSUE_TEMPLATE/feature_request.yml b/config/neovim/store/lazy-plugins/conform.nvim/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 00000000..452e7f87
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,43 @@
+name: Feature Request
+description: Submit a feature request
+title: "feature request: "
+labels: [enhancement]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Before submitting a feature request, make sure to search for [existing requests](https://github.com/stevearc/conform.nvim/issues)
+ - type: checkboxes
+ attributes:
+ label: Did you check existing requests?
+ options:
+ - label: I have searched the existing issues
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe the feature
+ description: A short summary of the feature you want
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Provide background
+ description: Describe the reasoning behind why you want the feature.
+ placeholder: I am trying to do X. My current workflow is Y.
+ validations:
+ required: false
+ - type: dropdown
+ attributes:
+ label: What is the significance of this feature?
+ options:
+ - nice to have
+ - strongly desired
+ - cannot use this plugin without it
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Additional details
+ description: Any additional information you would like to provide. Things you've tried, alternatives considered, examples from other plugins, etc.
+ validations:
+ required: false
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.github/pre-commit b/config/neovim/store/lazy-plugins/conform.nvim/.github/pre-commit
new file mode 100755
index 00000000..a9dca986
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.github/pre-commit
@@ -0,0 +1,3 @@
+#!/nix/store/306znyj77fv49kwnkpxmb0j2znqpa8bj-bash-5.2p26/bin/bash
+set -e
+make fastlint
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.github/pre-push b/config/neovim/store/lazy-plugins/conform.nvim/.github/pre-push
new file mode 100755
index 00000000..084e2873
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.github/pre-push
@@ -0,0 +1,11 @@
+#!/nix/store/306znyj77fv49kwnkpxmb0j2znqpa8bj-bash-5.2p26/bin/bash
+set -e
+IFS=' '
+while read local_ref _local_sha _remote_ref _remote_sha; do
+ remote_main=$( (git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || echo "///master") | cut -f 4 -d / | tr -d "[:space:]")
+ local_ref_short=$(echo "$local_ref" | cut -f 3 -d / | tr -d "[:space:]")
+ if [ "$local_ref_short" = "$remote_main" ]; then
+ make lint
+ make test
+ fi
+done
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/automation_remove_question_label_on_comment.yml b/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/automation_remove_question_label_on_comment.yml
new file mode 100644
index 00000000..f99bba89
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/automation_remove_question_label_on_comment.yml
@@ -0,0 +1,16 @@
+name: Remove Question Label on Issue Comment
+
+on: [issue_comment]
+
+jobs:
+ # Remove the "question" label when a new comment is added.
+ # This lets me ask a question, tag the issue with "question", and filter out all "question"-tagged
+ # issues in my "needs triage" filter.
+ remove_question:
+ runs-on: ubuntu-latest
+ if: github.event.sender.login != 'stevearc'
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions-ecosystem/action-remove-labels@v1
+ with:
+ labels: question
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/automation_request_review.yml b/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/automation_request_review.yml
new file mode 100644
index 00000000..c31f5828
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/automation_request_review.yml
@@ -0,0 +1,27 @@
+name: Request Review
+permissions:
+ pull-requests: write
+on:
+ pull_request_target:
+ types: [opened, reopened, ready_for_review, synchronize]
+ branches-ignore:
+ - "release-please--**"
+
+jobs:
+ # Request review automatically when PRs are opened
+ request_review:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Request Review
+ uses: actions/github-script@v7
+ if: github.actor != 'stevearc'
+ with:
+ github-token: ${{secrets.GITHUB_TOKEN}}
+ script: |
+ const pr = context.payload.pull_request;
+ github.rest.pulls.requestReviewers({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: pr.number,
+ reviewers: ['stevearc']
+ });
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/install_nvim.sh b/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/install_nvim.sh
new file mode 100644
index 00000000..4c0203ce
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/install_nvim.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -e
+PLUGINS="$HOME/.local/share/nvim/site/pack/plugins/start"
+mkdir -p "$PLUGINS"
+
+wget "https://github.com/neovim/neovim/releases/download/${NVIM_TAG-stable}/nvim.appimage"
+chmod +x nvim.appimage
+./nvim.appimage --appimage-extract >/dev/null
+rm -f nvim.appimage
+mkdir -p ~/.local/share/nvim
+mv squashfs-root ~/.local/share/nvim/appimage
+sudo ln -s "$HOME/.local/share/nvim/appimage/AppRun" /usr/bin/nvim
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/tests.yml b/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/tests.yml
new file mode 100644
index 00000000..7e62300e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.github/workflows/tests.yml
@@ -0,0 +1,124 @@
+name: Run tests
+
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+
+jobs:
+ luacheck:
+ name: Luacheck
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Prepare
+ run: |
+ sudo apt-get update
+ sudo add-apt-repository universe
+ sudo apt install luarocks -y
+ sudo luarocks install luacheck
+
+ - name: Run Luacheck
+ run: luacheck lua tests
+
+ typecheck:
+ name: typecheck
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+ - uses: stevearc/nvim-typecheck-action@v1
+ with:
+ path: lua
+
+ stylua:
+ name: StyLua
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+ - name: Stylua
+ uses: JohnnyMorganz/stylua-action@v4
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ version: v0.20.0
+ args: --check lua tests
+
+ run_tests:
+ strategy:
+ matrix:
+ include:
+ - nvim_tag: v0.8.3
+ - nvim_tag: v0.9.4
+ - nvim_tag: v0.10.0
+
+ name: Run tests
+ runs-on: ubuntu-22.04
+ env:
+ NVIM_TAG: ${{ matrix.nvim_tag }}
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Neovim and dependencies
+ run: |
+ bash ./.github/workflows/install_nvim.sh
+
+ - name: Run tests
+ run: |
+ bash ./run_tests.sh
+
+ update_docs:
+ name: Update docs
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Neovim and dependencies
+ run: |
+ bash ./.github/workflows/install_nvim.sh
+
+ - name: Update docs
+ run: |
+ python -m pip install pyparsing==3.0.9
+ make doc
+ - name: Commit changes
+ if: ${{ github.ref == 'refs/heads/master' }}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ COMMIT_MSG: |
+ [docgen] Update docs
+ skip-checks: true
+ run: |
+ git config user.email "actions@github"
+ git config user.name "Github Actions"
+ git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
+ git add README.md doc
+ # Only commit and push if we have changes
+ git diff --quiet && git diff --staged --quiet || (git commit -m "${COMMIT_MSG}"; git push origin HEAD:${GITHUB_REF})
+
+ release:
+ name: release
+
+ if: ${{ github.ref == 'refs/heads/master' }}
+ needs:
+ - luacheck
+ - stylua
+ - typecheck
+ - run_tests
+ - update_docs
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: googleapis/release-please-action@v4
+ id: release
+ with:
+ release-type: simple
+ - uses: actions/checkout@v4
+ - uses: rickstaa/action-create-tag@v1
+ if: ${{ steps.release.outputs.release_created }}
+ with:
+ tag: stable
+ message: "Current stable release: ${{ steps.release.outputs.tag_name }}"
+ tag_exists_error: false
+ force_push_tag: true
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.gitignore b/config/neovim/store/lazy-plugins/conform.nvim/.gitignore
new file mode 100644
index 00000000..edbf0df5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.gitignore
@@ -0,0 +1,48 @@
+# Compiled Lua sources
+luac.out
+
+# luarocks build files
+*.src.rock
+*.zip
+*.tar.gz
+
+# Object files
+*.o
+*.os
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+*.def
+*.exp
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+.direnv/
+.testenv/
+doc/tags
+tests/testfile.txt
+tests/fake_formatter_output
+scripts/nvim_doc_tools
+scripts/nvim-typecheck-action
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.gitmodules b/config/neovim/store/lazy-plugins/conform.nvim/.gitmodules
new file mode 100644
index 00000000..e69de29b
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.luacheckrc b/config/neovim/store/lazy-plugins/conform.nvim/.luacheckrc
new file mode 100644
index 00000000..7efefde4
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.luacheckrc
@@ -0,0 +1,19 @@
+max_comment_line_length = false
+codes = true
+
+exclude_files = {
+ "tests/treesitter",
+}
+
+ignore = {
+ "212", -- Unused argument
+ "631", -- Line is too long
+ "122", -- Setting a readonly global
+ "542", -- Empty if branch
+}
+
+read_globals = {
+ "vim",
+ "a",
+ "assert",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/.stylua.toml b/config/neovim/store/lazy-plugins/conform.nvim/.stylua.toml
new file mode 100644
index 00000000..020ce912
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/.stylua.toml
@@ -0,0 +1,5 @@
+column_width = 100
+indent_type = "Spaces"
+indent_width = 2
+[sort_requires]
+enabled = true
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/CHANGELOG.md b/config/neovim/store/lazy-plugins/conform.nvim/CHANGELOG.md
new file mode 100644
index 00000000..cde701cd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/CHANGELOG.md
@@ -0,0 +1,571 @@
+# Changelog
+
+## [5.8.0](https://github.com/stevearc/conform.nvim/compare/v5.7.0...v5.8.0) (2024-05-22)
+
+
+### Features
+
+* add `ruff_organize_imports` formatter ([#418](https://github.com/stevearc/conform.nvim/issues/418)) ([184756b](https://github.com/stevearc/conform.nvim/commit/184756b7522f82ccdac0013adff1caa313cb897a))
+* add forge_fmt formatter support for solidity filetype ([#417](https://github.com/stevearc/conform.nvim/issues/417)) ([18a3fa4](https://github.com/stevearc/conform.nvim/commit/18a3fa45d841c941399b4559ef60b39f2e3ded7c))
+* add support for leptosfmt ([#415](https://github.com/stevearc/conform.nvim/issues/415)) ([b999fad](https://github.com/stevearc/conform.nvim/commit/b999fad66fd797a57d745c1a999d000b889bd587))
+* add support for typstyle ([#412](https://github.com/stevearc/conform.nvim/issues/412)) ([e47dcde](https://github.com/stevearc/conform.nvim/commit/e47dcde340c80645ab32b09da2c492174e6660c4))
+
+## [5.7.0](https://github.com/stevearc/conform.nvim/compare/v5.6.0...v5.7.0) (2024-05-16)
+
+
+### Features
+
+* add hcl formatter (hclfmt) ([#402](https://github.com/stevearc/conform.nvim/issues/402)) ([37cbcea](https://github.com/stevearc/conform.nvim/commit/37cbceab0a3b4979c4f0f1ae7aede0d0fa84c1d1))
+* add ktfmt formatter for Kotlin ([#392](https://github.com/stevearc/conform.nvim/issues/392)) ([b72f650](https://github.com/stevearc/conform.nvim/commit/b72f650206ddfeadd6c7df0f775a928e82ece353))
+* add ormolu formatter for Haskell ([#377](https://github.com/stevearc/conform.nvim/issues/377)) ([#397](https://github.com/stevearc/conform.nvim/issues/397)) ([6207f41](https://github.com/stevearc/conform.nvim/commit/6207f41e8f3813d72ef4499a8132c11d8baabe9f))
+* add snakefmt formatter for snakemake files ([#399](https://github.com/stevearc/conform.nvim/issues/399)) ([dc950e5](https://github.com/stevearc/conform.nvim/commit/dc950e5717f1da65b1fcd986b1bbff0d6bd0e2ee))
+* add support for bicep ([#368](https://github.com/stevearc/conform.nvim/issues/368)) ([588f357](https://github.com/stevearc/conform.nvim/commit/588f357d305943371de5c945aea65959fd4d80b9))
+* add support for bpfmt ([#405](https://github.com/stevearc/conform.nvim/issues/405)) ([3c278a7](https://github.com/stevearc/conform.nvim/commit/3c278a7e09e135e524545adcd725f89bfcc7ffbd))
+* add support for mdsf ([#380](https://github.com/stevearc/conform.nvim/issues/380)) ([34d3c5f](https://github.com/stevearc/conform.nvim/commit/34d3c5f58017b1a7e1cd23739b263d7af0f66d7c))
+* add support for yew-fmt ([#398](https://github.com/stevearc/conform.nvim/issues/398)) ([b52d462](https://github.com/stevearc/conform.nvim/commit/b52d462cb7bea5e81174ece43eb349357add2f11))
+* add verible formatter for SystemVerilog ([#391](https://github.com/stevearc/conform.nvim/issues/391)) ([fb2d35f](https://github.com/stevearc/conform.nvim/commit/fb2d35f2875967b92af9e1e7d31724ce0456fa83))
+* formatters can use $RELATIVE_FILEPATH in args ([#349](https://github.com/stevearc/conform.nvim/issues/349)) ([6dc1603](https://github.com/stevearc/conform.nvim/commit/6dc1603ea408f476a57937bbeaf7f86520a21a98))
+
+
+### Bug Fixes
+
+* **biome-check:** use safe fixes ([#373](https://github.com/stevearc/conform.nvim/issues/373)) ([500a6ae](https://github.com/stevearc/conform.nvim/commit/500a6ae6c10b2a96e85e64045ad9f3b16e2af7f8))
+* **biome:** support biome.jsonc file ([#394](https://github.com/stevearc/conform.nvim/issues/394)) ([3cd1135](https://github.com/stevearc/conform.nvim/commit/3cd1135cb2978c9d45b8dc6afc80045fb8a93157))
+* handle windows line ending when config.stdin is true ([#361](https://github.com/stevearc/conform.nvim/issues/361)) ([820eec9](https://github.com/stevearc/conform.nvim/commit/820eec990d5f332d30cf939954c8672a43a0459e))
+* **isort:** explicitly pass line endings ([#395](https://github.com/stevearc/conform.nvim/issues/395)) ([a3e3e0e](https://github.com/stevearc/conform.nvim/commit/a3e3e0e2966a9fa477bbc86487e920ee0c34f133))
+* lazily compute relative filepath ([40faaa8](https://github.com/stevearc/conform.nvim/commit/40faaa8fdd0b7f98f58070943306fd93abb5caad))
+* **mix:** allow mix formatter to format different filetypes ([#389](https://github.com/stevearc/conform.nvim/issues/389)) ([12b3995](https://github.com/stevearc/conform.nvim/commit/12b3995537f52ba2810a9857e8ca256881febbda))
+* **prettierd:** correctly find prettierd executable on windows ([#378](https://github.com/stevearc/conform.nvim/issues/378)) ([a6965ac](https://github.com/stevearc/conform.nvim/commit/a6965ac128eba75537ec2bc5ddd5d5e357062bdc))
+* refactor deprecated methods in neovim 0.10 ([7a205c9](https://github.com/stevearc/conform.nvim/commit/7a205c944d228ca0a5ec67656f59d20ba11ccca2))
+* **util:** new function throwing an error when the given extended value is nil ([#385](https://github.com/stevearc/conform.nvim/issues/385)) ([4660e53](https://github.com/stevearc/conform.nvim/commit/4660e534bf7678ee0f85879aa75fdcb6855612c2))
+* warning messages for improper async in format_on_save ([#401](https://github.com/stevearc/conform.nvim/issues/401)) ([59d0dd2](https://github.com/stevearc/conform.nvim/commit/59d0dd233a2cafacfa1235ab22054c4d80a72319))
+* **windows:** assertion failure when computing relative path ([#400](https://github.com/stevearc/conform.nvim/issues/400)) ([4f0cdf0](https://github.com/stevearc/conform.nvim/commit/4f0cdf07b5498935c34d6cfefde059a3a91584c4))
+
+## [5.6.0](https://github.com/stevearc/conform.nvim/compare/v5.5.0...v5.6.0) (2024-03-28)
+
+
+### Features
+
+* a formatter for SML (Standard ML) ([#353](https://github.com/stevearc/conform.nvim/issues/353)) ([ae6a069](https://github.com/stevearc/conform.nvim/commit/ae6a069e33027fc522151bf656ab06cf93abca46))
+* add formatter for Inko ([#351](https://github.com/stevearc/conform.nvim/issues/351)) ([6874087](https://github.com/stevearc/conform.nvim/commit/68740871bd1b7aecc3759136d576ecb704c4a636))
+* add ocp-indent for OCaml formatting ([#335](https://github.com/stevearc/conform.nvim/issues/335)) ([551d02f](https://github.com/stevearc/conform.nvim/commit/551d02f472b646cb82657700e3459f16d9933005))
+* add support for nimpretty ([#343](https://github.com/stevearc/conform.nvim/issues/343)) ([67f7fb2](https://github.com/stevearc/conform.nvim/commit/67f7fb2fe82d170c681e6c0da67aa848e6f5a742))
+* add support for purs-tidy ([#345](https://github.com/stevearc/conform.nvim/issues/345)) ([bf109f0](https://github.com/stevearc/conform.nvim/commit/bf109f061fc3cd75394b7823923187ae045cbf22))
+* add support for roc format ([#342](https://github.com/stevearc/conform.nvim/issues/342)) ([293236a](https://github.com/stevearc/conform.nvim/commit/293236aa7445fb24aba56d8e9a03be54d0c1c2e8))
+* **prettier, prettierd:** add mjs files to supported config files ([#350](https://github.com/stevearc/conform.nvim/issues/350)) ([ac4a022](https://github.com/stevearc/conform.nvim/commit/ac4a022c9e10e9697235f657f166372326139e8b))
+* support crystal tool format ([#344](https://github.com/stevearc/conform.nvim/issues/344)) ([f8c64b8](https://github.com/stevearc/conform.nvim/commit/f8c64b835f60a80639375500a80e8cd303d8eda6))
+
+
+### Bug Fixes
+
+* **injected:** ignore indentation of final whitespace line ([#340](https://github.com/stevearc/conform.nvim/issues/340)) ([0a530b3](https://github.com/stevearc/conform.nvim/commit/0a530b31acacf10eca9f9a74b2434ece4d232ca3))
+* **terraform_fmt:** do not output color escape codes ([#354](https://github.com/stevearc/conform.nvim/issues/354)) ([f3363ad](https://github.com/stevearc/conform.nvim/commit/f3363ad4b1453b0c9a591d2571c540ed145323d7))
+* use `--force-exclude` with Ruff ([#348](https://github.com/stevearc/conform.nvim/issues/348)) ([93f3d4c](https://github.com/stevearc/conform.nvim/commit/93f3d4cabe41473477a314c731e635175458f591))
+
+## [5.5.0](https://github.com/stevearc/conform.nvim/compare/v5.4.0...v5.5.0) (2024-03-17)
+
+
+### Features
+
+* add formatter config option to change name of temporary file ([#332](https://github.com/stevearc/conform.nvim/issues/332)) ([b059626](https://github.com/stevearc/conform.nvim/commit/b05962622d3eebeefe6b1a90deb9eb86947e0349))
+
+
+### Bug Fixes
+
+* **phpcbf:** use non-stdin formatting and customize tempfile name ([#333](https://github.com/stevearc/conform.nvim/issues/333)) ([67ee225](https://github.com/stevearc/conform.nvim/commit/67ee2258e08ccb91345d52f62484b657feccef25))
+* **rustfmt:** parse edition from Cargo.toml ([#330](https://github.com/stevearc/conform.nvim/issues/330)) ([a605ce4](https://github.com/stevearc/conform.nvim/commit/a605ce4b2db397c84ae6fa8bcfc85f00b985bc73))
+* **sqlfluff:** remove --force flag since it's default now ([#338](https://github.com/stevearc/conform.nvim/issues/338)) ([42f3d8e](https://github.com/stevearc/conform.nvim/commit/42f3d8e1c1a90e1114d12a49be838409cbbd1239))
+
+## [5.4.0](https://github.com/stevearc/conform.nvim/compare/v5.3.0...v5.4.0) (2024-03-13)
+
+
+### Features
+
+* add `gersemi` formatter ([#305](https://github.com/stevearc/conform.nvim/issues/305)) ([79d7fd9](https://github.com/stevearc/conform.nvim/commit/79d7fd9ee84e603bdb66038b1d1ed2703ec08d14))
+* add formatter sqlfmt ([#307](https://github.com/stevearc/conform.nvim/issues/307)) ([015f9e9](https://github.com/stevearc/conform.nvim/commit/015f9e90d945545b665dfda52e6c96590c3d1292))
+* add gleam formatter ([#327](https://github.com/stevearc/conform.nvim/issues/327)) ([2ebfcaa](https://github.com/stevearc/conform.nvim/commit/2ebfcaa4f2e85550d985eae8ed417401319ebccd))
+* add OpenTofu formatter ([#313](https://github.com/stevearc/conform.nvim/issues/313)) ([68dad93](https://github.com/stevearc/conform.nvim/commit/68dad93cde8d8b71e53d07ac43029d0fca06bf26))
+* add the cabal-fmt formatter ([#318](https://github.com/stevearc/conform.nvim/issues/318)) ([ea73026](https://github.com/stevearc/conform.nvim/commit/ea73026a163e124edb47fe48075091d924d139af))
+* **formatter:** add liquidsoap-prettier ([#312](https://github.com/stevearc/conform.nvim/issues/312)) ([dc873e9](https://github.com/stevearc/conform.nvim/commit/dc873e94f300cdadf0c1949c14b6e9137e7a9981))
+
+
+### Bug Fixes
+
+* add cwd to honor project php-cs-fixer ([#325](https://github.com/stevearc/conform.nvim/issues/325)) ([f5f8498](https://github.com/stevearc/conform.nvim/commit/f5f8498cf27931e06645c9fe020b9c28dce49d98))
+* **prettier:** Fix range formatting of buffer ([#322](https://github.com/stevearc/conform.nvim/issues/322)) ([bc93756](https://github.com/stevearc/conform.nvim/commit/bc937565f251866c0ff344fd13fe27f00a4c0d25))
+* remove call to deprecated tbl_add_reverse_lookup ([5a15cc4](https://github.com/stevearc/conform.nvim/commit/5a15cc46e75cad804fd51ec5af9227aeb1d1bdaa))
+* **rustfmt:** use Cargo.toml settings and default to recent edition ([#328](https://github.com/stevearc/conform.nvim/issues/328)) ([0ff1b7d](https://github.com/stevearc/conform.nvim/commit/0ff1b7d32fd3e8df194ca5ebec1dab9c61fb9911))
+* **swiftformat:** range formatting support and add cwd ([#326](https://github.com/stevearc/conform.nvim/issues/326)) ([db2c697](https://github.com/stevearc/conform.nvim/commit/db2c697fe8302f0328b50b480204be1b577a1e2f))
+
+## [5.3.0](https://github.com/stevearc/conform.nvim/compare/v5.2.1...v5.3.0) (2024-02-20)
+
+
+### Features
+
+* add awk formatter ([#286](https://github.com/stevearc/conform.nvim/issues/286)) ([338c307](https://github.com/stevearc/conform.nvim/commit/338c3070ae7f7028185ae6123541c2ca71cfe7ff))
+* add biome-check formatter ([#287](https://github.com/stevearc/conform.nvim/issues/287)) ([5a71b60](https://github.com/stevearc/conform.nvim/commit/5a71b6064ec6ecf0fff91af67e95200aae9e9562))
+* add fantomas formatter ([#302](https://github.com/stevearc/conform.nvim/issues/302)) ([0d99714](https://github.com/stevearc/conform.nvim/commit/0d997149a0472ab811bcfdca5dc45d9db483f949))
+* Add reorder-python-imports formatter ([#284](https://github.com/stevearc/conform.nvim/issues/284)) ([9a07f60](https://github.com/stevearc/conform.nvim/commit/9a07f60f7499cdc76ed40af62bb9a50ac928d7d2))
+* add ReScript formatter ([#293](https://github.com/stevearc/conform.nvim/issues/293)) ([a34b66f](https://github.com/stevearc/conform.nvim/commit/a34b66f9a4a8f4fb8e270ebfa9c8836fdb8381c1))
+* add terragrunt_hclfmt formatter ([#278](https://github.com/stevearc/conform.nvim/issues/278)) ([375258f](https://github.com/stevearc/conform.nvim/commit/375258f1fe1500f175d7135aef1dc6a87dbd83b2))
+* add twig-cs-fixer ([#304](https://github.com/stevearc/conform.nvim/issues/304)) ([766812b](https://github.com/stevearc/conform.nvim/commit/766812b0e830c2e40613f99f89102d8840431c6a))
+* add yq formatter ([#288](https://github.com/stevearc/conform.nvim/issues/288)) ([15c4a02](https://github.com/stevearc/conform.nvim/commit/15c4a0273bb5468004bb46f632dc5326bc5634d7))
+
+
+### Bug Fixes
+
+* `swift_format` doesn't respect `.swift-format` file ([#283](https://github.com/stevearc/conform.nvim/issues/283)) ([4588008](https://github.com/stevearc/conform.nvim/commit/4588008a7c5b57fbff97fdfb529c059235cdc7ee))
+* set a cwd for biome ([#282](https://github.com/stevearc/conform.nvim/issues/282)) ([03feeb5](https://github.com/stevearc/conform.nvim/commit/03feeb5024a4b44754d63dec55b79b8133a8ea9f))
+
+## [5.2.1](https://github.com/stevearc/conform.nvim/compare/v5.2.0...v5.2.1) (2024-01-21)
+
+
+### Bug Fixes
+
+* handle windows line endings ([#274](https://github.com/stevearc/conform.nvim/issues/274)) ([9a785eb](https://github.com/stevearc/conform.nvim/commit/9a785eb8f0199ac47ce8bb9e9b6103de5ad8e3a7))
+
+## [5.2.0](https://github.com/stevearc/conform.nvim/compare/v5.1.0...v5.2.0) (2024-01-16)
+
+
+### Features
+
+* add cue_fmt formatter ([#265](https://github.com/stevearc/conform.nvim/issues/265)) ([03de11a](https://github.com/stevearc/conform.nvim/commit/03de11a0dcf686fda58d64a895483e284dd0c5b6))
+* Add dry_run option and report if buffer was/would be changed by formatters ([#273](https://github.com/stevearc/conform.nvim/issues/273)) ([e0276bb](https://github.com/stevearc/conform.nvim/commit/e0276bb32e9b33ece11fef2a5cfc8fb2108df0df))
+* add opa_fmt formatter ([#267](https://github.com/stevearc/conform.nvim/issues/267)) ([a4e84d5](https://github.com/stevearc/conform.nvim/commit/a4e84d56d5959dae685c5e22db202cd86b5b322b))
+* add xmllint formatter ([#259](https://github.com/stevearc/conform.nvim/issues/259)) ([c50ba4b](https://github.com/stevearc/conform.nvim/commit/c50ba4baad90f02840cc31ee745b09078b7a1777))
+* **formatexpr:** don't require LSP range formatting if operating on whole file ([#272](https://github.com/stevearc/conform.nvim/issues/272)) ([47ceff6](https://github.com/stevearc/conform.nvim/commit/47ceff644e9d00872f410be374cc973eefa20ba9))
+
+
+### Bug Fixes
+
+* **black:** formatting excluded files results in blank buffer ([#254](https://github.com/stevearc/conform.nvim/issues/254)) ([c4b2efb](https://github.com/stevearc/conform.nvim/commit/c4b2efb8aee4af0ef179a9b49ba401de3c4ef5d2))
+* copy input parameters for will_fallback_lsp ([ad347d7](https://github.com/stevearc/conform.nvim/commit/ad347d70e66737a8b9d62c19df1c0e2c5b2cd008))
+* injected formatter works on nightly ([#270](https://github.com/stevearc/conform.nvim/issues/270)) ([229e9ab](https://github.com/stevearc/conform.nvim/commit/229e9ab5d6e90bc5e6d24141dce3cc28ba95293a))
+* LSP deprecated method warning on nvim nightly ([75e7c5c](https://github.com/stevearc/conform.nvim/commit/75e7c5c7eb5fbd53f8b12dc420b31ec70770b231))
+* pass explicit bufnr to avoid race conditions ([#260](https://github.com/stevearc/conform.nvim/issues/260)) ([a8e3935](https://github.com/stevearc/conform.nvim/commit/a8e39359814b7b5df5fac7423b4dc93826d64464))
+* set a cwd for djlint ([#264](https://github.com/stevearc/conform.nvim/issues/264)) ([0802406](https://github.com/stevearc/conform.nvim/commit/08024063232a7bd38ecdfaf89f06162a5ba2df91))
+* set a cwd for dprint ([#263](https://github.com/stevearc/conform.nvim/issues/263)) ([e6c1353](https://github.com/stevearc/conform.nvim/commit/e6c135338257f69c018e8351a6e5f63683f86318))
+
+## [5.1.0](https://github.com/stevearc/conform.nvim/compare/v5.0.0...v5.1.0) (2023-12-26)
+
+
+### Features
+
+* add fnlfmt formatter ([#247](https://github.com/stevearc/conform.nvim/issues/247)) ([af6643a](https://github.com/stevearc/conform.nvim/commit/af6643afa10e17c0228da97c84d4c32f144a6ad3))
+* ConformInfo shows path to executable ([#244](https://github.com/stevearc/conform.nvim/issues/244)) ([fb9b050](https://github.com/stevearc/conform.nvim/commit/fb9b0500270ba05b89cc27cd8b7762443bcfae22))
+* **prettier:** add `options` for configuring prettier parser based on filetype and extension ([#241](https://github.com/stevearc/conform.nvim/issues/241)) ([8df1bed](https://github.com/stevearc/conform.nvim/commit/8df1bed7b8de9cf40476996fb5ab73ed667aed35))
+
+
+### Bug Fixes
+
+* crash in error handling ([4185249](https://github.com/stevearc/conform.nvim/commit/41852493b5abd7b5a0fd61ff007994c777a08ec9))
+* **formatexpr:** does not fallback to the built-in formatexpr ([#238](https://github.com/stevearc/conform.nvim/issues/238)) ([48bc999](https://github.com/stevearc/conform.nvim/commit/48bc9996ebfe90e7766f46338360f75fd6ecb174))
+* **injected:** code block at end of markdown file ([9245b61](https://github.com/stevearc/conform.nvim/commit/9245b616d1edb159775a0832c03324bf92884494))
+* **injected:** handle inline injections ([#251](https://github.com/stevearc/conform.nvim/issues/251)) ([f245cca](https://github.com/stevearc/conform.nvim/commit/f245cca8ad42c9d344b53a18c3fc1a3c6724c2d4))
+* **prettier:** use correct prettier executable on windows ([#236](https://github.com/stevearc/conform.nvim/issues/236)) ([7396fc0](https://github.com/stevearc/conform.nvim/commit/7396fc0208539e2bd70e3e446f27529e28dba12b))
+* **rubocop:** pass --server for faster execution ([#246](https://github.com/stevearc/conform.nvim/issues/246)) ([0ec6edd](https://github.com/stevearc/conform.nvim/commit/0ec6edd67689e8df6726b83333106bcec13c36d4))
+
+## [5.0.0](https://github.com/stevearc/conform.nvim/compare/v4.3.0...v5.0.0) (2023-12-07)
+
+
+### ⚠ BREAKING CHANGES
+
+* formatter config functions take self as first argument ([#233](https://github.com/stevearc/conform.nvim/issues/233))
+
+### Features
+
+* add asmfmt ([#239](https://github.com/stevearc/conform.nvim/issues/239)) ([a5ef494](https://github.com/stevearc/conform.nvim/commit/a5ef4943f6382f36a5a8d6e16eb0a0c60af5e7a5))
+* add joker for clojure formatting ([#240](https://github.com/stevearc/conform.nvim/issues/240)) ([6b13100](https://github.com/stevearc/conform.nvim/commit/6b1310014ceec5752fd5859f9cc62ef7c93d72b2))
+
+
+### Code Refactoring
+
+* formatter config functions take self as first argument ([#233](https://github.com/stevearc/conform.nvim/issues/233)) ([659838f](https://github.com/stevearc/conform.nvim/commit/659838ff4244ef6af095395ce68aaaf99fa8e696))
+
+## [4.3.0](https://github.com/stevearc/conform.nvim/compare/v4.2.0...v4.3.0) (2023-12-07)
+
+
+### Features
+
+* add `auto-optional` ([#196](https://github.com/stevearc/conform.nvim/issues/196)) ([9156364](https://github.com/stevearc/conform.nvim/commit/9156364c23cff19734a0055377321c22b1484c0f))
+* add `typos` ([#214](https://github.com/stevearc/conform.nvim/issues/214)) ([d86c186](https://github.com/stevearc/conform.nvim/commit/d86c186ba910d28a6266c4d6210578dca984f3e3))
+* add autocorrect ([#223](https://github.com/stevearc/conform.nvim/issues/223)) ([cd81d21](https://github.com/stevearc/conform.nvim/commit/cd81d215d39b16186186a1539c71b48705bb081d))
+* add beancount formatter ([#212](https://github.com/stevearc/conform.nvim/issues/212)) ([c0924a6](https://github.com/stevearc/conform.nvim/commit/c0924a61e079d94f0be40da2d4188210c6e4ffea))
+* add cbfmt ([#198](https://github.com/stevearc/conform.nvim/issues/198)) ([aa36bc0](https://github.com/stevearc/conform.nvim/commit/aa36bc05563d5390a2ef67956d72560048acdc2e))
+* add fourmolu support ([#209](https://github.com/stevearc/conform.nvim/issues/209)) ([e688864](https://github.com/stevearc/conform.nvim/commit/e688864883aa4f468cc73a4c1db661c7c94addc4))
+* add jsonnetfmt ([#230](https://github.com/stevearc/conform.nvim/issues/230)) ([769dde8](https://github.com/stevearc/conform.nvim/commit/769dde8ddccf8338c68da706e46fd2fb004e6455))
+* add packer formatter ([#202](https://github.com/stevearc/conform.nvim/issues/202)) ([a0cabaa](https://github.com/stevearc/conform.nvim/commit/a0cabaaf5c94137c8dc34043244a34b552860af6))
+* add pangu ([#188](https://github.com/stevearc/conform.nvim/issues/188)) ([f0780e2](https://github.com/stevearc/conform.nvim/commit/f0780e2231df2e4751e31db32c1545872412ba75))
+* add phpinsights ([#170](https://github.com/stevearc/conform.nvim/issues/170)) ([5235405](https://github.com/stevearc/conform.nvim/commit/5235405cc6d4ac98dc9008ffa850038e3325bbce))
+* add styler formatter for R ([#184](https://github.com/stevearc/conform.nvim/issues/184)) ([6afc64e](https://github.com/stevearc/conform.nvim/commit/6afc64e9f36cbae35c2a8b6852d0b91c9807a72a))
+* add support for buildifier ([#216](https://github.com/stevearc/conform.nvim/issues/216)) ([e478834](https://github.com/stevearc/conform.nvim/commit/e478834227e0958e21a54f31c9cd896a3a8bdde0))
+* add support for sqlfluff ([#213](https://github.com/stevearc/conform.nvim/issues/213)) ([e8c8683](https://github.com/stevearc/conform.nvim/commit/e8c8683a00fb932dfe669e1c96832da12b8054bd))
+
+
+### Bug Fixes
+
+* **biome:** perform formatting over stdin ([#220](https://github.com/stevearc/conform.nvim/issues/220)) ([eddd643](https://github.com/stevearc/conform.nvim/commit/eddd6431370814caacec1d1e3c7d6d95d41b133d))
+* **biome:** use binary from node_modules ([#226](https://github.com/stevearc/conform.nvim/issues/226)) ([5bf1405](https://github.com/stevearc/conform.nvim/commit/5bf1405fd234d469243ea6f394e0aeec9ea53bd8))
+* injected formatter adds language to file extension ([#199](https://github.com/stevearc/conform.nvim/issues/199)) ([e2b889e](https://github.com/stevearc/conform.nvim/commit/e2b889e26586acf30dda7b4a5c3f1a063bc18f18))
+* injected parser shouldn't format combined injections ([#205](https://github.com/stevearc/conform.nvim/issues/205)) ([eeef888](https://github.com/stevearc/conform.nvim/commit/eeef88849fb644d84a5856524adf10d0ad2d7cbe))
+* invalid prettier configuration in last commit ([e8ac7f1](https://github.com/stevearc/conform.nvim/commit/e8ac7f1a9a3973ecce6942b2f26d16e65902aa70))
+* range format method for async formatters and injected ([a36c68d](https://github.com/stevearc/conform.nvim/commit/a36c68d2cd551e49883ddb2492c178d915567f58))
+* respect excluded-files-config from `typos.toml` ([#219](https://github.com/stevearc/conform.nvim/issues/219)) ([db9da1a](https://github.com/stevearc/conform.nvim/commit/db9da1aa57e8be683ada1b1e5f8129c28d2576eb))
+* show more logs in ConformInfo when log level is TRACE ([0963118](https://github.com/stevearc/conform.nvim/commit/0963118e60e0895e2e4842aeffc67cdf9e2bcd10))
+* various fixes for the `injected` formatter ([#235](https://github.com/stevearc/conform.nvim/issues/235)) ([07fcbfc](https://github.com/stevearc/conform.nvim/commit/07fcbfc13490786f5983bce3f404643fcfd83775))
+
+## [4.2.0](https://github.com/stevearc/conform.nvim/compare/v4.1.0...v4.2.0) (2023-11-09)
+
+
+### Features
+
+* add typstfmt ([#180](https://github.com/stevearc/conform.nvim/issues/180)) ([b1f1194](https://github.com/stevearc/conform.nvim/commit/b1f1194338c96d385ec6370ac734ab63c0289776))
+
+
+### Bug Fixes
+
+* catch jobstart errors ([#183](https://github.com/stevearc/conform.nvim/issues/183)) ([dcbe650](https://github.com/stevearc/conform.nvim/commit/dcbe650bd4811cefe5a885fafb6309c7d592bda6))
+* injected formatter not working ([#187](https://github.com/stevearc/conform.nvim/issues/187)) ([68abada](https://github.com/stevearc/conform.nvim/commit/68abada5a348f448eabdbd7d71884c195969484f))
+* nonzero exit code on :wq ([#176](https://github.com/stevearc/conform.nvim/issues/176)) ([161d95b](https://github.com/stevearc/conform.nvim/commit/161d95bfbb1ad1a2b89ba2ea75ca1b5e012a111e))
+* rename `astgrep` to `ast-grep` ([#178](https://github.com/stevearc/conform.nvim/issues/178)) ([bfa69a9](https://github.com/stevearc/conform.nvim/commit/bfa69a942e19159d3a3e958a5be85cb7cdae19a7))
+
+## [4.1.0](https://github.com/stevearc/conform.nvim/compare/v4.0.0...v4.1.0) (2023-11-05)
+
+
+### Features
+
+* add `ast-grep` ([#177](https://github.com/stevearc/conform.nvim/issues/177)) ([fa3cf1c](https://github.com/stevearc/conform.nvim/commit/fa3cf1c40716492fd0df0c3dedd54c8018f9ea70))
+* add CSharpier ([#165](https://github.com/stevearc/conform.nvim/issues/165)) ([b2368ff](https://github.com/stevearc/conform.nvim/commit/b2368ff18a9dd9452170d3a6f41b1f872ae5d0b2))
+* add markdownlint-cli2 ([#171](https://github.com/stevearc/conform.nvim/issues/171)) ([9bb3a94](https://github.com/stevearc/conform.nvim/commit/9bb3a940389dda796192a477a016069472692526))
+* add mdslw markdown formatter ([#175](https://github.com/stevearc/conform.nvim/issues/175)) ([369c7fe](https://github.com/stevearc/conform.nvim/commit/369c7fe690b3fec0ecdd7c17faeebf3f8113a0f5))
+* add pretty-php ([#161](https://github.com/stevearc/conform.nvim/issues/161)) ([4653408](https://github.com/stevearc/conform.nvim/commit/4653408d5c270168e31ffd0585d1cf2de27fc827))
+* add puppet-lint formatter ([#153](https://github.com/stevearc/conform.nvim/issues/153)) ([0219648](https://github.com/stevearc/conform.nvim/commit/0219648cd9a2bafc13fda64903e49fda5db0016b))
+* add tlint ([#162](https://github.com/stevearc/conform.nvim/issues/162)) ([2538784](https://github.com/stevearc/conform.nvim/commit/253878436e2b6d73dfd91ccf0ac12d04cc683d34))
+* add usort ([#167](https://github.com/stevearc/conform.nvim/issues/167)) ([f7766d2](https://github.com/stevearc/conform.nvim/commit/f7766d2fbe23f0f22a3db1513beba7d03a8dc261))
+* allow formatters_by_ft to be a function ([#174](https://github.com/stevearc/conform.nvim/issues/174)) ([0bbe838](https://github.com/stevearc/conform.nvim/commit/0bbe83830be5a07a1161bb1a23d7280310656177))
+* gn build file format cmd ([#155](https://github.com/stevearc/conform.nvim/issues/155)) ([3716927](https://github.com/stevearc/conform.nvim/commit/37169273a0776752a3c01cbe01227e275b642b89))
+* zprint formatter for clojure ([#146](https://github.com/stevearc/conform.nvim/issues/146)) ([2800552](https://github.com/stevearc/conform.nvim/commit/280055248661a4fc7b692db2d5ee80a465ebb577))
+
+
+### Bug Fixes
+
+* **formatexpr:** use default formatexpr if no formatters or LSP clients ([#55](https://github.com/stevearc/conform.nvim/issues/55)) ([278bcd8](https://github.com/stevearc/conform.nvim/commit/278bcd8bf2017e187e963b515017341fdd87fe2f))
+* **rubyfmt:** exit code 1 should not be a success ([#157](https://github.com/stevearc/conform.nvim/issues/157)) ([e4ecb6e](https://github.com/stevearc/conform.nvim/commit/e4ecb6e8ed3163c86d7e647f1dc3d94de77ca687))
+
+## [4.0.0](https://github.com/stevearc/conform.nvim/compare/v3.10.0...v4.0.0) (2023-10-16)
+
+
+### ⚠ BREAKING CHANGES
+
+* merge configs in conform.formatters with defaults ([#140](https://github.com/stevearc/conform.nvim/issues/140))
+
+### Features
+
+* add blade-formatter ([#136](https://github.com/stevearc/conform.nvim/issues/136)) ([f90b222](https://github.com/stevearc/conform.nvim/commit/f90b2229c481252c43a71a004972b473952c1c3c))
+* add blue formatter ([#142](https://github.com/stevearc/conform.nvim/issues/142)) ([a97ddff](https://github.com/stevearc/conform.nvim/commit/a97ddfff2d701245ad49daf24ef436a50ee72a50))
+* Add config for laravel/pint ([#144](https://github.com/stevearc/conform.nvim/issues/144)) ([43414c8](https://github.com/stevearc/conform.nvim/commit/43414c8ebd22921f44806fb9612a2f4f376419af))
+* add goimports-reviser ([#143](https://github.com/stevearc/conform.nvim/issues/143)) ([3fcebb0](https://github.com/stevearc/conform.nvim/commit/3fcebb0001e6d5b943dbb36fe5c035e3ef8c3509))
+* add ktlint ([#137](https://github.com/stevearc/conform.nvim/issues/137)) ([8b02f47](https://github.com/stevearc/conform.nvim/commit/8b02f478fefe93f76a7f57c983418744287f4c69))
+* add rufo support ([#132](https://github.com/stevearc/conform.nvim/issues/132)) ([aca5d30](https://github.com/stevearc/conform.nvim/commit/aca5d307232a22600bd0ab57571a8b6e2dc9a12c))
+* merge configs in conform.formatters with defaults ([#140](https://github.com/stevearc/conform.nvim/issues/140)) ([7027ebb](https://github.com/stevearc/conform.nvim/commit/7027ebbd772e2d3593f7dd566dea06d2d20622ee))
+* support for rubyfmt ([#139](https://github.com/stevearc/conform.nvim/issues/139)) ([ae33777](https://github.com/stevearc/conform.nvim/commit/ae337775e46804a8347ea7c3da92be5587e5850e))
+
+
+### Bug Fixes
+
+* prevent format-after-save autocmd from running on invalid buffers ([80f2f70](https://github.com/stevearc/conform.nvim/commit/80f2f70740431b07d725cc66f63abbfd66aaae6d))
+* prevent format-on-save autocmd from running on invalid buffers ([#128](https://github.com/stevearc/conform.nvim/issues/128)) ([69ee0bf](https://github.com/stevearc/conform.nvim/commit/69ee0bfde439e30344ae57de6227cb3a035dd0bb))
+* **shellcheck:** support filenames with spaces ([#135](https://github.com/stevearc/conform.nvim/issues/135)) ([64a8956](https://github.com/stevearc/conform.nvim/commit/64a89568925c3f62b7ecdcf60b612001d2749eb1))
+
+## [3.10.0](https://github.com/stevearc/conform.nvim/compare/v3.9.0...v3.10.0) (2023-10-09)
+
+
+### Features
+
+* add easy-coding-standard ([#121](https://github.com/stevearc/conform.nvim/issues/121)) ([e758196](https://github.com/stevearc/conform.nvim/commit/e75819642c36810a55a7235b6b5e16a5ce896ed3))
+* add fixjson ([#126](https://github.com/stevearc/conform.nvim/issues/126)) ([280360e](https://github.com/stevearc/conform.nvim/commit/280360eb019fe52433a68b7918790c9187076865))
+* add justfile formatter ([#114](https://github.com/stevearc/conform.nvim/issues/114)) ([4c91b52](https://github.com/stevearc/conform.nvim/commit/4c91b5270a6f741850de2eef3a804ff1dc6ec3ee))
+* errors do not stop formatting early ([a94f686](https://github.com/stevearc/conform.nvim/commit/a94f686986631d5b97bd75b3877813c39de55c47))
+* expose configuration options for injected formatter ([#118](https://github.com/stevearc/conform.nvim/issues/118)) ([ba1ca20](https://github.com/stevearc/conform.nvim/commit/ba1ca20bb5f89a8bdd94b268411263275550843a))
+
+
+### Bug Fixes
+
+* **biome:** do not use stdin due to biome bug ([#120](https://github.com/stevearc/conform.nvim/issues/120)) ([e5ed063](https://github.com/stevearc/conform.nvim/commit/e5ed0635d9aa66c6c2f7eac3235e6a8eb2de0653))
+* catch and fix more cases of bad-behaving LSP formatters ([#119](https://github.com/stevearc/conform.nvim/issues/119)) ([9bd1690](https://github.com/stevearc/conform.nvim/commit/9bd169029ac7fac5d0b3899a47556549d113a4c2))
+* handle one failure mode with range formatting ([#123](https://github.com/stevearc/conform.nvim/issues/123)) ([b5a2da9](https://github.com/stevearc/conform.nvim/commit/b5a2da9410d56bd7bc229d0185ad427a966cac50))
+* injected formatter handles markdown code blocks in blockquotes ([#117](https://github.com/stevearc/conform.nvim/issues/117)) ([0bffab5](https://github.com/stevearc/conform.nvim/commit/0bffab53672d62cbfe8fc450e78757982e656318))
+* move justfile formatter to correct directory ([8217144](https://github.com/stevearc/conform.nvim/commit/8217144491e8aba3a24828a71ee768b007a2ec43))
+
+## [3.9.0](https://github.com/stevearc/conform.nvim/compare/v3.8.0...v3.9.0) (2023-10-04)
+
+
+### Features
+
+* add phpcbf ([#103](https://github.com/stevearc/conform.nvim/issues/103)) ([db5af4b](https://github.com/stevearc/conform.nvim/commit/db5af4b04e5d61236a142ab78ec3f9416aab848c))
+* gci formatter for Go ([#109](https://github.com/stevearc/conform.nvim/issues/109)) ([362e4ec](https://github.com/stevearc/conform.nvim/commit/362e4ec709d241e47d6093dd4b030125ce214cfa))
+
+
+### Bug Fixes
+
+* format on save autocmds ignore nonstandard buffers ([cb87cab](https://github.com/stevearc/conform.nvim/commit/cb87cab7a6baa6192bf13123c2a5af6fd059d62c))
+* injected formatter silent failure on nvim nightly ([#100](https://github.com/stevearc/conform.nvim/issues/100)) ([0156beb](https://github.com/stevearc/conform.nvim/commit/0156beb8397169d7ec18d4f4ea8dd002ee9bcc96))
+* phpcbf invalid stdin-path arguments ([#108](https://github.com/stevearc/conform.nvim/issues/108)) ([ce427b0](https://github.com/stevearc/conform.nvim/commit/ce427b03b9cc428ee7a64cb77487ed19efec202d))
+* support for mix format ([#107](https://github.com/stevearc/conform.nvim/issues/107)) ([6836930](https://github.com/stevearc/conform.nvim/commit/6836930ed5a0ec6e8bb531116c62cc10f475c298))
+
+## [3.8.0](https://github.com/stevearc/conform.nvim/compare/v3.7.2...v3.8.0) (2023-10-02)
+
+
+### Features
+
+* add 'google-java-format' formatter ([#99](https://github.com/stevearc/conform.nvim/issues/99)) ([e887736](https://github.com/stevearc/conform.nvim/commit/e8877369df244515af20e18bf1307632fc638d2a))
+* add standardrb ([#91](https://github.com/stevearc/conform.nvim/issues/91)) ([37d0367](https://github.com/stevearc/conform.nvim/commit/37d036704a100ef6e6457be45b4dfc2f8e429572))
+* metatable to make accessing formatters a bit easier ([#89](https://github.com/stevearc/conform.nvim/issues/89)) ([d8170c1](https://github.com/stevearc/conform.nvim/commit/d8170c14db0f3c90fa799db3bca29d3fb3c089c3))
+
+
+### Bug Fixes
+
+* alternations follow notification rules ([3f89275](https://github.com/stevearc/conform.nvim/commit/3f8927532bc8ce4fc4b5b75eab1bf8f1fc83f6b9))
+* error handling for injected formatter ([f7b82fb](https://github.com/stevearc/conform.nvim/commit/f7b82fb395a4cd636a26ee879b5fd7690612e5a9))
+* injected formatter doesn't have interruption errors ([af3d59d](https://github.com/stevearc/conform.nvim/commit/af3d59da20d2bc37933df409f8fc9e24ec15e066))
+* injected formatter operates on input lines ([501319e](https://github.com/stevearc/conform.nvim/commit/501319eed2ff26f856ea91b5456bef1d00f77df7))
+
+## [3.7.2](https://github.com/stevearc/conform.nvim/compare/v3.7.1...v3.7.2) (2023-09-29)
+
+
+### Bug Fixes
+
+* injected formatter hangs on empty file ([671186e](https://github.com/stevearc/conform.nvim/commit/671186e4b29e26ee9fc0f1df4e529134bc334666))
+* injected formatter preserves indentation of code blocks ([470d419](https://github.com/stevearc/conform.nvim/commit/470d41988e83913df428c9e832c15b8bb84301ad))
+* lsp format calls method from wrong util file ([df69e3e](https://github.com/stevearc/conform.nvim/commit/df69e3ee61e1a0cbb960c8466ace74c696cc7830))
+
+## [3.7.1](https://github.com/stevearc/conform.nvim/compare/v3.7.0...v3.7.1) (2023-09-29)
+
+
+### Bug Fixes
+
+* format_after_save blocks on exit for lsp formatting ([0c52ee2](https://github.com/stevearc/conform.nvim/commit/0c52ee248245f40610a4957b6bc9515ce1fd9ab6))
+
+## [3.7.0](https://github.com/stevearc/conform.nvim/compare/v3.6.0...v3.7.0) (2023-09-29)
+
+
+### Features
+
+* add 'JavaScript Standard Style' formatter ([#82](https://github.com/stevearc/conform.nvim/issues/82)) ([971fa7f](https://github.com/stevearc/conform.nvim/commit/971fa7f2e4005454ce141ca8ee0462a3c34d2922))
+* add darker ([#80](https://github.com/stevearc/conform.nvim/issues/80)) ([e359687](https://github.com/stevearc/conform.nvim/commit/e359687e3684452ff45d7a5f1a59cd40b0bfa320))
+* format injected languages ([#83](https://github.com/stevearc/conform.nvim/issues/83)) ([a5526fb](https://github.com/stevearc/conform.nvim/commit/a5526fb2ee963cf426ab6d6ba1f3eb82887b1c22))
+
+
+### Bug Fixes
+
+* format_after_save autocmd blocks nvim exit until complete ([388d6e2](https://github.com/stevearc/conform.nvim/commit/388d6e2440bccded26d5e67ce6a7039c1953ae70))
+* only show "no formatters" warning if formatters passed in explicitly ([#85](https://github.com/stevearc/conform.nvim/issues/85)) ([45edf94](https://github.com/stevearc/conform.nvim/commit/45edf9462d06db0809d4a4a7afc6b7896b63fa35))
+
+## [3.6.0](https://github.com/stevearc/conform.nvim/compare/v3.5.0...v3.6.0) (2023-09-27)
+
+
+### Features
+
+* add `markdown-toc` ([#75](https://github.com/stevearc/conform.nvim/issues/75)) ([de58b06](https://github.com/stevearc/conform.nvim/commit/de58b06d434047c6ecd5ec2d52877335d37b05fd))
+* Add support for php-cs-fixer ([#78](https://github.com/stevearc/conform.nvim/issues/78)) ([e691eca](https://github.com/stevearc/conform.nvim/commit/e691ecaf41139a68ccb79fde824cb534ca11abd2))
+* add templ support ([#73](https://github.com/stevearc/conform.nvim/issues/73)) ([28ecd5c](https://github.com/stevearc/conform.nvim/commit/28ecd5cf9132213417bff41d79477354cb81f50c))
+* another utility for extending formatter arguments ([aada09c](https://github.com/stevearc/conform.nvim/commit/aada09c9cfea38187966ce47f34b9008e1104d21))
+* new utility function ([9e1fcd5](https://github.com/stevearc/conform.nvim/commit/9e1fcd5cafc42b5dfbe2e942ddbece0dada4e1d0))
+
+
+### Bug Fixes
+
+* rubocop succeeds even if some errors are not autocorrected ([#74](https://github.com/stevearc/conform.nvim/issues/74)) ([34daf23](https://github.com/stevearc/conform.nvim/commit/34daf23415e9d212697f79506039498db2b35240))
+
+## [3.5.0](https://github.com/stevearc/conform.nvim/compare/v3.4.1...v3.5.0) (2023-09-22)
+
+
+### Features
+
+* add `bibtex-tidy` ([#69](https://github.com/stevearc/conform.nvim/issues/69)) ([f5e7f84](https://github.com/stevearc/conform.nvim/commit/f5e7f84fb27f05d9a3f3893634cbb6c7f7f89056))
+* add dprint ([#71](https://github.com/stevearc/conform.nvim/issues/71)) ([0e2c97a](https://github.com/stevearc/conform.nvim/commit/0e2c97ab640f14f7da92278c731879efcb11f563))
+* add mdformat ([#68](https://github.com/stevearc/conform.nvim/issues/68)) ([4a4c927](https://github.com/stevearc/conform.nvim/commit/4a4c92715b174b847ba0fcdccf9dfea71c8ed33e))
+* add ruff formatter and improve ruff root finding ([#66](https://github.com/stevearc/conform.nvim/issues/66)) ([44e9e82](https://github.com/stevearc/conform.nvim/commit/44e9e8292d552f9a35498612a93dff934cc8802f))
+
+
+### Bug Fixes
+
+* `stylelint` and `markdownlint` when there are non-autofixable errors ([#70](https://github.com/stevearc/conform.nvim/issues/70)) ([5454fb5](https://github.com/stevearc/conform.nvim/commit/5454fb5a72a957b550fb7a0f5c4e84684c529920))
+
+## [3.4.1](https://github.com/stevearc/conform.nvim/compare/v3.4.0...v3.4.1) (2023-09-19)
+
+
+### Bug Fixes
+
+* range formatting for LSP formatters ([#63](https://github.com/stevearc/conform.nvim/issues/63)) ([52280f0](https://github.com/stevearc/conform.nvim/commit/52280f032653e98dd6ecbb61488afcca39671964))
+
+## [3.4.0](https://github.com/stevearc/conform.nvim/compare/v3.3.0...v3.4.0) (2023-09-18)
+
+
+### Features
+
+* add `squeeze_blanks` ([#62](https://github.com/stevearc/conform.nvim/issues/62)) ([3fa2a7b](https://github.com/stevearc/conform.nvim/commit/3fa2a7be8d91c3f0d7b79dde70d7849518cdc5bf))
+* make lsp_fallback behavior more intuitive ([#59](https://github.com/stevearc/conform.nvim/issues/59)) ([1abbb82](https://github.com/stevearc/conform.nvim/commit/1abbb82bb8e519e652d8b31b12a311872e9090d1))
+
+## [3.3.0](https://github.com/stevearc/conform.nvim/compare/v3.2.0...v3.3.0) (2023-09-17)
+
+
+### Features
+
+* '_' filetype to define fallback formatters ([a589750](https://github.com/stevearc/conform.nvim/commit/a589750635fcc5bb52c7e572cd853446c2c63855))
+* add GNU/BSD indent ([#54](https://github.com/stevearc/conform.nvim/issues/54)) ([5abf6c2](https://github.com/stevearc/conform.nvim/commit/5abf6c2c89ff6ed7d17285ec1da759013463bfc7))
+* Add rustywind formatter ([#56](https://github.com/stevearc/conform.nvim/issues/56)) ([a839ed1](https://github.com/stevearc/conform.nvim/commit/a839ed1384c21cbd8861f2850b552a4db10ead2f))
+* add shellcheck ([#44](https://github.com/stevearc/conform.nvim/issues/44)) ([508ec8a](https://github.com/stevearc/conform.nvim/commit/508ec8a899e039a56f9110011125ab56284db1fa))
+* alejandra formatter ([#52](https://github.com/stevearc/conform.nvim/issues/52)) ([e6552b5](https://github.com/stevearc/conform.nvim/commit/e6552b5c9b3a2b12bacb476b00c80c736b9f7963))
+* allow running commands in a shell ([#49](https://github.com/stevearc/conform.nvim/issues/49)) ([fbb18a5](https://github.com/stevearc/conform.nvim/commit/fbb18a5b92e2f11aaaef379d74d4a1132a138cb3))
+* format_on_save functions can return a callback as the second value ([1a568c6](https://github.com/stevearc/conform.nvim/commit/1a568c66f16650290fffcfbf5aefebe2d8254b83))
+* provide a formatexpr ([#55](https://github.com/stevearc/conform.nvim/issues/55)) ([aa38b05](https://github.com/stevearc/conform.nvim/commit/aa38b05575dab57b813ddcd14780f65ff20a6d49))
+* utility function to extend the built-in formatter args ([#50](https://github.com/stevearc/conform.nvim/issues/50)) ([cb5f939](https://github.com/stevearc/conform.nvim/commit/cb5f939ab27b2c2ef2e1d4ac6fe16c5ba6332f39))
+
+
+### Bug Fixes
+
+* `q` keymap in ConformInfo and `codespell` exit codes ([#53](https://github.com/stevearc/conform.nvim/issues/53)) ([d3fe431](https://github.com/stevearc/conform.nvim/commit/d3fe43167c7d96036c8c037ef1b4e03b448efbe7))
+* ConformInfo shows available LSP formatters ([3aa2fd5](https://github.com/stevearc/conform.nvim/commit/3aa2fd5f828f8fcabd65605a41953aba1f0f5cb0))
+* LSP formatter respects quiet = true ([5e4d258](https://github.com/stevearc/conform.nvim/commit/5e4d258f8eba4090b9a515ee9b77d8647394b2cd))
+* unify timeout error message format with LSP ([0d963f8](https://github.com/stevearc/conform.nvim/commit/0d963f82add9ca4faf49b54fc28f57038742ded3))
+* use non-deprecated health report functions if available ([#48](https://github.com/stevearc/conform.nvim/issues/48)) ([b436902](https://github.com/stevearc/conform.nvim/commit/b43690264ebcb152365d5b46faa6561f12ea062a))
+
+## [3.2.0](https://github.com/stevearc/conform.nvim/compare/v3.1.0...v3.2.0) (2023-09-14)
+
+
+### Features
+
+* add `markdownlint`, `stylelint`, `codespell`, and `biome` ([#45](https://github.com/stevearc/conform.nvim/issues/45)) ([580ab18](https://github.com/stevearc/conform.nvim/commit/580ab1880e740f4aebbc72a05350461f3cdef53d))
+* add buf as protobuf linter ([#43](https://github.com/stevearc/conform.nvim/issues/43)) ([2b73887](https://github.com/stevearc/conform.nvim/commit/2b73887fd75e1f6efc352cec6bd7e39157c3732e))
+* add deno fmt ([#46](https://github.com/stevearc/conform.nvim/issues/46)) ([db7461a](https://github.com/stevearc/conform.nvim/commit/db7461afcf751023adeb346d833f2e5d40a420c4))
+* add djlint ([#47](https://github.com/stevearc/conform.nvim/issues/47)) ([ead0257](https://github.com/stevearc/conform.nvim/commit/ead025784c8e31b8e45016e620c2f17a13ff741a))
+* latexindent ([#42](https://github.com/stevearc/conform.nvim/issues/42)) ([502a358](https://github.com/stevearc/conform.nvim/commit/502a3583663ede11c8db1e9980db342b117d79f2))
+* ruff ([#41](https://github.com/stevearc/conform.nvim/issues/41)) ([fdc4a0f](https://github.com/stevearc/conform.nvim/commit/fdc4a0f05c21012f2445a993ebdad700380dcfbf))
+
+
+### Bug Fixes
+
+* extra trailing newline for LSP formatters that replace entire file ([e18cdaf](https://github.com/stevearc/conform.nvim/commit/e18cdaf529b94465592d0c2afe1b62bc26155070))
+
+## [3.1.0](https://github.com/stevearc/conform.nvim/compare/v3.0.0...v3.1.0) (2023-09-13)
+
+
+### Features
+
+* format_on_save and format_after_save can be functions ([dd5b2f2](https://github.com/stevearc/conform.nvim/commit/dd5b2f2f7ca01c2f28239cbbc7f97e6f9024cd94))
+
+
+### Bug Fixes
+
+* modify diff calculation to handle end-of-file newlines better ([#35](https://github.com/stevearc/conform.nvim/issues/35)) ([00a5288](https://github.com/stevearc/conform.nvim/commit/00a528818463b10d84699b2e0f4a960d5a4aeb5c))
+
+## [3.0.0](https://github.com/stevearc/conform.nvim/compare/v2.3.0...v3.0.0) (2023-09-08)
+
+
+### ⚠ BREAKING CHANGES
+
+* remove run_all_formatters config option
+
+### Features
+
+* add beautysh, taplo, trim_newlines and trim_whitespace ([#29](https://github.com/stevearc/conform.nvim/issues/29)) ([37a2d65](https://github.com/stevearc/conform.nvim/commit/37a2d65bd2ee41540cc426d2cffef6d6f8648357))
+* format() can always fall back to LSP formatting ([c3028b3](https://github.com/stevearc/conform.nvim/commit/c3028b327bc44335cc2b5c3014cd6d5c12a54ee4))
+* syntax for using first available formatter ([2568d74](https://github.com/stevearc/conform.nvim/commit/2568d746abbadf66a03c62b568ee73d874cd8617))
+
+
+### Code Refactoring
+
+* remove run_all_formatters config option ([bd1aa02](https://github.com/stevearc/conform.nvim/commit/bd1aa02ef191410b2ea0b3ef5caabe06592d9c51))
+
+## [2.3.0](https://github.com/stevearc/conform.nvim/compare/v2.2.0...v2.3.0) (2023-09-06)
+
+
+### Features
+
+* format() takes an optional callback ([#21](https://github.com/stevearc/conform.nvim/issues/21)) ([3f34f2d](https://github.com/stevearc/conform.nvim/commit/3f34f2de48e393b2ee289f2c8fa613c7eabae6d8))
+
+
+### Bug Fixes
+
+* callback should always be called ([eb3ebb6](https://github.com/stevearc/conform.nvim/commit/eb3ebb6d2d114f6476a8f8d21d74f99c6d231a53))
+
+## [2.2.0](https://github.com/stevearc/conform.nvim/compare/v2.1.0...v2.2.0) (2023-08-31)
+
+
+### Features
+
+* apply changes as text edits using LSP utils ([#18](https://github.com/stevearc/conform.nvim/issues/18)) ([92393f0](https://github.com/stevearc/conform.nvim/commit/92393f02efadfb1d9f97c74c8feb853c1caea9de))
+
+## [2.1.0](https://github.com/stevearc/conform.nvim/compare/v2.0.0...v2.1.0) (2023-08-30)
+
+
+### Features
+
+* add golines ([#11](https://github.com/stevearc/conform.nvim/issues/11)) ([e1d68a5](https://github.com/stevearc/conform.nvim/commit/e1d68a58fa29d2a24f1a976c3c60521ffb31f32e))
+* add perlimports ([#13](https://github.com/stevearc/conform.nvim/issues/13)) ([e6e99af](https://github.com/stevearc/conform.nvim/commit/e6e99af64db3f364086aaf55b8b5854ccd62bac4))
+* add perltidy ([#12](https://github.com/stevearc/conform.nvim/issues/12)) ([882b759](https://github.com/stevearc/conform.nvim/commit/882b75994af34fed3c4fe6f1a97ad58b352ec25f))
+* add shellharden ([#14](https://github.com/stevearc/conform.nvim/issues/14)) ([863fb46](https://github.com/stevearc/conform.nvim/commit/863fb46fc7a7fa66fafb4bb8fd8093c700c472e5))
+* add support for environment variables ([#8](https://github.com/stevearc/conform.nvim/issues/8)) ([03a37f1](https://github.com/stevearc/conform.nvim/commit/03a37f1b53d83af7aee10fc3ffee9f3a05d09e2e))
+* display last few lines of the log file in :ConformInfo ([c9327f2](https://github.com/stevearc/conform.nvim/commit/c9327f2af541e4a17a6e2e05682122f8c8455d29))
+* formatter config function is passed the buffer number ([#9](https://github.com/stevearc/conform.nvim/issues/9)) ([8b2a574](https://github.com/stevearc/conform.nvim/commit/8b2a5741e07e2d6d5e8103e5e12356d3a9f0b8ba))
+* notify when formatter errors, and add notify_on_error config option ([#16](https://github.com/stevearc/conform.nvim/issues/16)) ([08dc913](https://github.com/stevearc/conform.nvim/commit/08dc913fb22d402a98d1d9733536f2876c6f6314))
+
+
+### Bug Fixes
+
+* shellharden ([#15](https://github.com/stevearc/conform.nvim/issues/15)) ([288068b](https://github.com/stevearc/conform.nvim/commit/288068b1b78c79e64054ef443afbf6f2f5145da4))
+
+## [2.0.0](https://github.com/stevearc/conform.nvim/compare/v1.1.0...v2.0.0) (2023-08-29)
+
+
+### ⚠ BREAKING CHANGES
+
+* remove ability for formatter list to disable autoformat
+
+### Features
+
+* can silence notification when running formatters ([#7](https://github.com/stevearc/conform.nvim/issues/7)) ([a4d793e](https://github.com/stevearc/conform.nvim/commit/a4d793e941e8e497ab9149ed09c946473d795c1b))
+* ConformInfo command for debugging formatter status ([1fd547f](https://github.com/stevearc/conform.nvim/commit/1fd547fe98a5100a041106e2bc353363ab0d5ad8))
+* range formatting ([cddd536](https://github.com/stevearc/conform.nvim/commit/cddd536e087a9fd3d2c9ea5b0a44e46c7b4b54c2))
+
+
+### Bug Fixes
+
+* don't show 'no formatters' warning if none configured ([9376d37](https://github.com/stevearc/conform.nvim/commit/9376d37bd7ab456b7df8e3d6f1ba75c05b4e5a8f))
+* keep window position stable when LSP formatting ([90e8a8d](https://github.com/stevearc/conform.nvim/commit/90e8a8d63c7d77d1872dca3da720abfa07271054))
+* remove unnecessary notify ([6082883](https://github.com/stevearc/conform.nvim/commit/6082883585a5c61c7a5c6697517931bc6e39f546))
+* stable ordering when specifying multiple formatters ([69c4495](https://github.com/stevearc/conform.nvim/commit/69c4495ab5ad3c07c3a4f3c2bcac2f070718b4cb))
+
+
+### Code Refactoring
+
+* remove ability for formatter list to disable autoformat ([d508ae8](https://github.com/stevearc/conform.nvim/commit/d508ae8f46b5b41e2806b412311719a941167c1a))
+
+## [1.1.0](https://github.com/stevearc/conform.nvim/compare/v1.0.0...v1.1.0) (2023-08-28)
+
+
+### Features
+
+* new formatter: fish_indent ([#5](https://github.com/stevearc/conform.nvim/issues/5)) ([446aa57](https://github.com/stevearc/conform.nvim/commit/446aa570048586f9c13f1ea88e280567f336691e))
+
+
+### Bug Fixes
+
+* gracefully handle another timeout case ([500d24d](https://github.com/stevearc/conform.nvim/commit/500d24dc1a2447a3c8f3f4f756f40bd27ff0b283))
+* no need to save/restore window view ([5bc69d5](https://github.com/stevearc/conform.nvim/commit/5bc69d500a14fb06bf8f36005f76a7825be25931))
+
+## 1.0.0 (2023-08-25)
+
+
+### Features
+
+* first working version ([eb5987e](https://github.com/stevearc/conform.nvim/commit/eb5987e9dd40ce1e27c9c07e41d09571f1bd876e))
+
+
+### Bug Fixes
+
+* don't modify files when no styling changes ([08b54ba](https://github.com/stevearc/conform.nvim/commit/08b54ba11e29e6df9f83c02539976331617a412c))
+* ensure real buffer numbers get logged ([33ee8ba](https://github.com/stevearc/conform.nvim/commit/33ee8ba8cb6f29caec1edf01fa4987bbae52f18b))
+* notification when no formatters available ([a757225](https://github.com/stevearc/conform.nvim/commit/a75722517d17d749a5ee86c8a3bbb098a61265fc))
+* set a cwd for stylua ([a22781e](https://github.com/stevearc/conform.nvim/commit/a22781e0c3b609a5f90095f388589744567476c7))
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/LICENSE b/config/neovim/store/lazy-plugins/conform.nvim/LICENSE
new file mode 100644
index 00000000..d6cdf38f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Steven Arcangeli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/Makefile b/config/neovim/store/lazy-plugins/conform.nvim/Makefile
new file mode 100644
index 00000000..71447f8f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/Makefile
@@ -0,0 +1,27 @@
+.PHONY: all doc test lint fastlint clean
+
+all: doc lint test
+
+doc: scripts/nvim_doc_tools
+ python scripts/main.py generate
+ python scripts/main.py lint
+
+test:
+ ./run_tests.sh
+
+lint: scripts/nvim-typecheck-action fastlint
+ ./scripts/nvim-typecheck-action/typecheck.sh --workdir scripts/nvim-typecheck-action lua
+
+fastlint: scripts/nvim_doc_tools
+ python scripts/main.py lint
+ luacheck lua tests --formatter plain
+ stylua --check lua tests
+
+scripts/nvim_doc_tools:
+ git clone https://github.com/stevearc/nvim_doc_tools scripts/nvim_doc_tools
+
+scripts/nvim-typecheck-action:
+ git clone https://github.com/stevearc/nvim-typecheck-action scripts/nvim-typecheck-action
+
+clean:
+ rm -rf scripts/nvim_doc_tools scripts/nvim-typecheck-action
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/README.md b/config/neovim/store/lazy-plugins/conform.nvim/README.md
new file mode 100644
index 00000000..5b3f2cf6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/README.md
@@ -0,0 +1,620 @@
+# conform.nvim
+
+Lightweight yet powerful formatter plugin for Neovim
+
+
+
+- [Requirements](#requirements)
+- [Features](#features)
+- [Installation](#installation)
+- [Setup](#setup)
+- [Formatters](#formatters)
+- [Customizing formatters](#customizing-formatters)
+- [Recipes](#recipes)
+- [Advanced topics](#advanced-topics)
+- [Options](#options)
+- [Formatter options](#formatter-options)
+- [API](#api)
+ - [setup(opts)](#setupopts)
+ - [format(opts, callback)](#formatopts-callback)
+ - [list_formatters(bufnr)](#list_formattersbufnr)
+ - [list_all_formatters()](#list_all_formatters)
+ - [get_formatter_info(formatter, bufnr)](#get_formatter_infoformatter-bufnr)
+ - [will_fallback_lsp(options)](#will_fallback_lspoptions)
+- [Acknowledgements](#acknowledgements)
+
+
+
+## Requirements
+
+- Neovim 0.8+
+
+## Features
+
+- **Preserves extmarks and folds** - Most formatters replace the entire buffer, which clobbers extmarks and folds, and can cause the viewport and cursor to jump unexpectedly. Conform calculates minimal diffs and applies them using the built-in LSP format utilities.
+- **Fixes bad-behaving LSP formatters** - Some LSP servers are lazy and simply replace the entire buffer, leading to the problems mentioned above. Conform hooks into the LSP handler and turns these responses into proper piecewise changes.
+- **Enables range formatting for all formatters** - Since conform calculates minimal diffs, it can perform range formatting [even if the underlying formatter doesn't support it.](doc/advanced_topics.md#range-formatting)
+- **Simple API** - Conform exposes a simple, imperative API modeled after `vim.lsp.buf.format()`.
+- **Formats embedded code blocks** - Can format code blocks inside markdown files or similar (see [injected language formatting](doc/advanced_topics.md#injected-language-formatting-code-blocks))
+
+## Installation
+
+conform.nvim supports all the usual plugin managers
+
+
+ lazy.nvim
+
+```lua
+{
+ 'stevearc/conform.nvim',
+ opts = {},
+}
+```
+
+For a more thorough configuration involving lazy-loading, see [Lazy loading with lazy.nvim](doc/recipes.md#lazy-loading-with-lazynvim).
+
+
+
+
+ Packer
+
+```lua
+require("packer").startup(function()
+ use({
+ "stevearc/conform.nvim",
+ config = function()
+ require("conform").setup()
+ end,
+ })
+end)
+```
+
+
+
+
+ Paq
+
+```lua
+require("paq")({
+ { "stevearc/conform.nvim" },
+})
+```
+
+
+
+
+ vim-plug
+
+```vim
+Plug 'stevearc/conform.nvim'
+```
+
+
+
+
+ dein
+
+```vim
+call dein#add('stevearc/conform.nvim')
+```
+
+
+
+
+ Pathogen
+
+```sh
+git clone --depth=1 https://github.com/stevearc/conform.nvim.git ~/.vim/bundle/
+```
+
+
+
+
+ Neovim native package
+
+```sh
+git clone --depth=1 https://github.com/stevearc/conform.nvim.git \
+ "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/pack/conform/start/conform.nvim
+```
+
+
+
+## Setup
+
+At a minimum, you will need to set up some formatters by filetype
+
+```lua
+require("conform").setup({
+ formatters_by_ft = {
+ lua = { "stylua" },
+ -- Conform will run multiple formatters sequentially
+ python = { "isort", "black" },
+ -- Use a sub-list to run only the first available formatter
+ javascript = { { "prettierd", "prettier" } },
+ },
+})
+```
+
+Then you can use `conform.format()` just like you would `vim.lsp.buf.format()`. For example, to format on save:
+
+```lua
+vim.api.nvim_create_autocmd("BufWritePre", {
+ pattern = "*",
+ callback = function(args)
+ require("conform").format({ bufnr = args.buf })
+ end,
+})
+```
+
+As a shortcut, conform will optionally set up this format-on-save autocmd for you
+
+```lua
+require("conform").setup({
+ format_on_save = {
+ -- These options will be passed to conform.format()
+ timeout_ms = 500,
+ lsp_fallback = true,
+ },
+})
+```
+
+See [conform.format()](#formatopts-callback) for more details about the parameters.
+
+Conform also provides a formatexpr, same as the LSP client:
+
+```lua
+vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"
+```
+
+To view configured and available formatters, as well as to see the log file, run `:ConformInfo`
+
+## Formatters
+
+You can view this list in vim with `:help conform-formatters`
+
+
+ Expand to see all formatters
+
+
+
+- [alejandra](https://kamadorueda.com/alejandra/) - The Uncompromising Nix Code Formatter.
+- [asmfmt](https://github.com/klauspost/asmfmt) - Go Assembler Formatter
+- [ast-grep](https://ast-grep.github.io/) - A CLI tool for code structural search, lint and rewriting. Written in Rust.
+- [astyle](https://astyle.sourceforge.net/astyle.html) - A Free, Fast, and Small Automatic Formatter for C, C++, C++/CLI, Objective-C, C#, and Java Source Code.
+- [auto_optional](https://auto-optional.daanluttik.nl/) - Adds the Optional type-hint to arguments where the default value is None.
+- [autocorrect](https://github.com/huacnlee/autocorrect) - A linter and formatter to help you to improve copywriting, correct spaces, words, and punctuations between CJK.
+- [autoflake](https://github.com/PyCQA/autoflake) - Removes unused imports and unused variables as reported by pyflakes.
+- [autopep8](https://github.com/hhatto/autopep8) - A tool that automatically formats Python code to conform to the PEP 8 style guide.
+- [awk](https://www.gnu.org/software/gawk/manual/gawk.html) - Format awk programs with awk
+- [bean-format](https://beancount.github.io/docs/running_beancount_and_generating_reports.html#bean-format) - Reformat Beancount files to right-align all the numbers at the same, minimal column.
+- [beautysh](https://github.com/lovesegfault/beautysh) - A Bash beautifier for the masses.
+- [bibtex-tidy](https://github.com/FlamingTempura/bibtex-tidy) - Cleaner and Formatter for BibTeX files.
+- [bicep](https://github.com/Azure/bicep) - Bicep is a Domain Specific Language (DSL) for deploying Azure resources declaratively.
+- [biome](https://github.com/biomejs/biome) - A toolchain for web projects, aimed to provide functionalities to maintain them.
+- [biome-check](https://github.com/biomejs/biome) - A toolchain for web projects, aimed to provide functionalities to maintain them.
+- [black](https://github.com/psf/black) - The uncompromising Python code formatter.
+- [blade-formatter](https://github.com/shufo/blade-formatter) - An opinionated blade template formatter for Laravel that respects readability.
+- [blue](https://github.com/grantjenks/blue) - The slightly less uncompromising Python code formatter.
+- [bpfmt](https://source.android.com/docs/setup/reference/androidbp) - Android Blueprint file formatter.
+- [buf](https://buf.build/docs/reference/cli/buf/format) - A new way of working with Protocol Buffers.
+- [buildifier](https://github.com/bazelbuild/buildtools/tree/master/buildifier) - buildifier is a tool for formatting bazel BUILD and .bzl files with a standard convention.
+- [cabal_fmt](https://hackage.haskell.org/package/cabal-fmt) - Format cabal files with cabal-fmt
+- [cbfmt](https://github.com/lukas-reineke/cbfmt) - A tool to format codeblocks inside markdown and org documents.
+- [clang-format](https://www.kernel.org/doc/html/latest/process/clang-format.html) - Tool to format C/C++/… code according to a set of rules and heuristics.
+- [cljstyle](https://github.com/greglook/cljstyle) - Formatter for Clojure code.
+- [cmake_format](https://github.com/cheshirekow/cmake_format) - Parse cmake listfiles and format them nicely.
+- [codespell](https://github.com/codespell-project/codespell) - Check code for common misspellings.
+- [crystal](https://crystal-lang.org/) - Format Crystal code.
+- [csharpier](https://github.com/belav/csharpier) - The opinionated C# code formatter.
+- [cue_fmt](https://cuelang.org) - Format CUE files using `cue fmt` command.
+- [darker](https://github.com/akaihola/darker) - Run black only on changed lines.
+- [dart_format](https://dart.dev/tools/dart-format) - Replace the whitespace in your program with formatting that follows Dart guidelines.
+- [deno_fmt](https://deno.land/manual/tools/formatter) - Use [Deno](https://deno.land/) to format TypeScript, JavaScript/JSON and markdown.
+- [dfmt](https://github.com/dlang-community/dfmt) - Formatter for D source code.
+- [djlint](https://github.com/Riverside-Healthcare/djLint) - ✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang.
+- [dprint](https://github.com/dprint/dprint) - Pluggable and configurable code formatting platform written in Rust.
+- [easy-coding-standard](https://github.com/easy-coding-standard/easy-coding-standard) - ecs - Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer.
+- [elm_format](https://github.com/avh4/elm-format) - elm-format formats Elm source code according to a standard set of rules based on the official [Elm Style Guide](https://elm-lang.org/docs/style-guide).
+- [erb_format](https://github.com/nebulab/erb-formatter) - Format ERB files with speed and precision.
+- [eslint_d](https://github.com/mantoni/eslint_d.js/) - Like ESLint, but faster.
+- [fantomas](https://github.com/fsprojects/fantomas) - F# source code formatter.
+- [fish_indent](https://fishshell.com/docs/current/cmds/fish_indent.html) - Indent or otherwise prettify a piece of fish code.
+- [fixjson](https://github.com/rhysd/fixjson) - JSON Fixer for Humans using (relaxed) JSON5.
+- [fnlfmt](https://git.sr.ht/~technomancy/fnlfmt) - A formatter for Fennel code.
+- [forge_fmt](https://github.com/foundry-rs/foundry) - Forge is a command-line tool that ships with Foundry. Forge tests, builds, and deploys your smart contracts.
+- [fourmolu](https://hackage.haskell.org/package/fourmolu) - A fork of ormolu that uses four space indentation and allows arbitrary configuration.
+- [gci](https://github.com/daixiang0/gci) - GCI, a tool that controls Go package import order and makes it always deterministic.
+- [gdformat](https://github.com/Scony/godot-gdscript-toolkit) - A formatter for Godot's gdscript.
+- [gersemi](https://github.com/BlankSpruce/gersemi) - A formatter to make your CMake code the real treasure.
+- [gleam](https://github.com/gleam-lang/gleam) - ⭐️ A friendly language for building type-safe, scalable systems!
+- [gn](https://gn.googlesource.com/gn/) - gn build system.
+- [gofmt](https://pkg.go.dev/cmd/gofmt) - Formats go programs.
+- [gofumpt](https://github.com/mvdan/gofumpt) - Enforce a stricter format than gofmt, while being backwards compatible. That is, gofumpt is happy with a subset of the formats that gofmt is happy with.
+- [goimports](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) - Updates your Go import lines, adding missing ones and removing unreferenced ones.
+- [goimports-reviser](https://github.com/incu6us/goimports-reviser) - Right imports sorting & code formatting tool (goimports alternative).
+- [golines](https://github.com/segmentio/golines) - A golang formatter that fixes long lines.
+- [google-java-format](https://github.com/google/google-java-format) - Reformats Java source code according to Google Java Style.
+- [hcl](https://github.com/hashicorp/hcl) - A formatter for HCL files.
+- [htmlbeautifier](https://github.com/threedaymonk/htmlbeautifier) - A normaliser/beautifier for HTML that also understands embedded Ruby. Ideal for tidying up Rails templates.
+- [indent](https://www.gnu.org/software/indent/) - GNU Indent.
+- [injected](doc/advanced_topics.md#injected-language-formatting-code-blocks) - Format treesitter injected languages.
+- [inko](https://inko-lang.org/) - A language for building concurrent software with confidence
+- [isort](https://github.com/PyCQA/isort) - Python utility / library to sort imports alphabetically and automatically separate them into sections and by type.
+- [joker](https://github.com/candid82/joker) - Small Clojure interpreter, linter and formatter.
+- [jq](https://github.com/stedolan/jq) - Command-line JSON processor.
+- [jsonnetfmt](https://github.com/google/go-jsonnet/tree/master/cmd/jsonnetfmt) - jsonnetfmt is a command line tool to format jsonnet files.
+- [just](https://github.com/casey/just) - Format Justfile.
+- [ktfmt](https://github.com/facebook/ktfmt) - Reformats Kotlin source code to comply with the common community standard conventions.
+- [ktlint](https://ktlint.github.io/) - An anti-bikeshedding Kotlin linter with built-in formatter.
+- [latexindent](https://github.com/cmhughes/latexindent.pl) - A perl script for formatting LaTeX files that is generally included in major TeX distributions.
+- [leptosfmt](https://github.com/bram209/leptosfmt) - A formatter for the Leptos view! macro.
+- [liquidsoap-prettier](https://github.com/savonet/liquidsoap-prettier) - A binary to format Liquidsoap scripts
+- [markdown-toc](https://github.com/jonschlinkert/markdown-toc) - API and CLI for generating a markdown TOC (table of contents) for a README or any markdown files.
+- [markdownlint](https://github.com/DavidAnson/markdownlint) - A Node.js style checker and lint tool for Markdown/CommonMark files.
+- [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) - A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the markdownlint library.
+- [mdformat](https://github.com/executablebooks/mdformat) - An opinionated Markdown formatter.
+- [mdsf](https://github.com/hougesen/mdsf) - Format markdown code blocks using your favorite code formatters.
+- [mdslw](https://github.com/razziel89/mdslw) - Prepare your markdown for easy diff'ing by adding line breaks after every sentence.
+- [mix](https://hexdocs.pm/mix/main/Mix.Tasks.Format.html) - Format Elixir files using the mix format command.
+- [nimpretty](https://github.com/nim-lang/nim) - nimpretty is a Nim source code beautifier that follows the official style guide.
+- [nixfmt](https://github.com/serokell/nixfmt) - nixfmt is a formatter for Nix code, intended to apply a uniform style.
+- [nixpkgs_fmt](https://github.com/nix-community/nixpkgs-fmt) - nixpkgs-fmt is a Nix code formatter for nixpkgs.
+- [ocamlformat](https://github.com/ocaml-ppx/ocamlformat) - Auto-formatter for OCaml code.
+- [ocp-indent](https://github.com/OCamlPro/ocp-indent) - Automatic indentation of OCaml source files.
+- [opa_fmt](https://www.openpolicyagent.org/docs/latest/cli/#opa-fmt) - Format Rego files using `opa fmt` command.
+- [ormolu](https://hackage.haskell.org/package/ormolu) - A formatter for Haskell source code.
+- [packer_fmt](https://developer.hashicorp.com/packer/docs/commands/fmt) - The packer fmt Packer command is used to format HCL2 configuration files to a canonical format and style.
+- [pangu](https://github.com/vinta/pangu.py) - Insert whitespace between CJK and half-width characters.
+- [perlimports](https://github.com/perl-ide/App-perlimports) - Make implicit Perl imports explicit.
+- [perltidy](https://github.com/perltidy/perltidy) - Perl::Tidy, a source code formatter for Perl.
+- [pg_format](https://github.com/darold/pgFormatter) - PostgreSQL SQL syntax beautifier.
+- [php_cs_fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) - The PHP Coding Standards Fixer.
+- [phpcbf](https://phpqa.io/projects/phpcbf.html) - PHP Code Beautifier and Fixer fixes violations of a defined coding standard.
+- [phpinsights](https://github.com/nunomaduro/phpinsights) - The perfect starting point to analyze the code quality of your PHP projects.
+- [pint](https://github.com/laravel/pint) - Laravel Pint is an opinionated PHP code style fixer for minimalists.
+- [prettier](https://github.com/prettier/prettier) - Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.
+- [prettierd](https://github.com/fsouza/prettierd) - prettier, as a daemon, for ludicrous formatting speed.
+- [pretty-php](https://github.com/lkrms/pretty-php) - The opinionated PHP code formatter.
+- [puppet-lint](https://github.com/puppetlabs/puppet-lint) - Check that your Puppet manifests conform to the style guide.
+- [purs-tidy](https://github.com/natefaubion/purescript-tidy) - A syntax tidy-upper for PureScript.
+- [reorder-python-imports](https://github.com/asottile/reorder-python-imports) - Rewrites source to reorder python imports
+- [rescript-format](https://rescript-lang.org/) - The built-in ReScript formatter.
+- [roc](https://github.com/roc-lang/roc) - A fast, friendly, functional language.
+- [rubocop](https://github.com/rubocop/rubocop) - Ruby static code analyzer and formatter, based on the community Ruby style guide.
+- [rubyfmt](https://github.com/fables-tales/rubyfmt) - Ruby Autoformatter! (Written in Rust)
+- [ruff_fix](https://docs.astral.sh/ruff/) - An extremely fast Python linter, written in Rust. Fix lint errors.
+- [ruff_format](https://docs.astral.sh/ruff/) - An extremely fast Python linter, written in Rust. Formatter subcommand.
+- [ruff_organize_imports](https://docs.astral.sh/ruff/) - An extremely fast Python linter, written in Rust. Organize imports.
+- [rufo](https://github.com/ruby-formatter/rufo) - Rufo is an opinionated ruby formatter.
+- [rustfmt](https://github.com/rust-lang/rustfmt) - A tool for formatting rust code according to style guidelines.
+- [rustywind](https://github.com/avencera/rustywind) - A tool for formatting Tailwind CSS classes.
+- [scalafmt](https://github.com/scalameta/scalafmt) - Code formatter for Scala.
+- [shellcheck](https://github.com/koalaman/shellcheck) - A static analysis tool for shell scripts.
+- [shellharden](https://github.com/anordal/shellharden) - The corrective bash syntax highlighter.
+- [shfmt](https://github.com/mvdan/sh) - A shell parser, formatter, and interpreter with `bash` support.
+- [smlfmt](https://github.com/shwestrick/smlfmt) - A custom parser and code formatter for Standard ML.
+- [snakefmt](https://github.com/snakemake/snakefmt) - a formatting tool for Snakemake files following the design of Black.
+- [sql_formatter](https://github.com/sql-formatter-org/sql-formatter) - A whitespace formatter for different query languages.
+- [sqlfluff](https://github.com/sqlfluff/sqlfluff) - A modular SQL linter and auto-formatter with support for multiple dialects and templated code.
+- [sqlfmt](https://docs.sqlfmt.com) - sqlfmt formats your dbt SQL files so you don't have to. It is similar in nature to Black, gofmt, and rustfmt (but for SQL)
+- [squeeze_blanks](https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html#cat-invocation) - Squeeze repeated blank lines into a single blank line via `cat -s`.
+- [standardjs](https://standardjs.com) - JavaScript Standard style guide, linter, and formatter.
+- [standardrb](https://github.com/standardrb/standard) - Ruby's bikeshed-proof linter and formatter.
+- [stylelint](https://github.com/stylelint/stylelint) - A mighty CSS linter that helps you avoid errors and enforce conventions.
+- [styler](https://github.com/devOpifex/r.nvim) - R formatter and linter.
+- [stylua](https://github.com/JohnnyMorganz/StyLua) - An opinionated code formatter for Lua.
+- [swift_format](https://github.com/apple/swift-format) - Swift formatter from apple. Requires building from source with `swift build`.
+- [swiftformat](https://github.com/nicklockwood/SwiftFormat) - SwiftFormat is a code library and command-line tool for reformatting `swift` code on macOS or Linux.
+- [taplo](https://github.com/tamasfe/taplo) - A TOML toolkit written in Rust.
+- [templ](https://templ.guide/commands-and-tools/cli/#formatting-templ-files) - Formats templ template files.
+- [terraform_fmt](https://www.terraform.io/docs/cli/commands/fmt.html) - The terraform-fmt command rewrites `terraform` configuration files to a canonical format and style.
+- [terragrunt_hclfmt](https://terragrunt.gruntwork.io/docs/reference/cli-options/#hclfmt) - Format hcl files into a canonical format.
+- [tlint](https://github.com/tighten/tlint) - Tighten linter for Laravel conventions with support for auto-formatting.
+- [tofu_fmt](https://opentofu.org/docs/cli/commands/fmt/) - The tofu-fmt command rewrites OpenTofu configuration files to a canonical format and style.
+- [trim_newlines](https://www.gnu.org/software/gawk/manual/gawk.html) - Trim new lines with awk.
+- [trim_whitespace](https://www.gnu.org/software/gawk/manual/gawk.html) - Trim whitespaces with awk.
+- [twig-cs-fixer](https://github.com/VincentLanglet/Twig-CS-Fixer) - Automatically fix Twig Coding Standards issues
+- [typos](https://github.com/crate-ci/typos) - Source code spell checker
+- [typstfmt](https://github.com/astrale-sharp/typstfmt) - Basic formatter for the Typst language with a future!
+- [typstyle](https://github.com/Enter-tainer/typstyle) - Beautiful and reliable typst code formatter.
+- [uncrustify](https://github.com/uncrustify/uncrustify) - A source code beautifier for C, C++, C#, ObjectiveC, D, Java, Pawn and Vala.
+- [usort](https://github.com/facebook/usort) - Safe, minimal import sorting for Python projects.
+- [verible](https://github.com/chipsalliance/verible/blob/master/verilog/tools/formatter/README.md) - The SystemVerilog formatter.
+- [xmlformat](https://github.com/pamoller/xmlformatter) - xmlformatter is an Open Source Python package, which provides formatting of XML documents.
+- [xmllint](http://xmlsoft.org/xmllint.html) - Despite the name, xmllint can be used to format XML files as well as lint them.
+- [yamlfix](https://github.com/lyz-code/yamlfix) - A configurable YAML formatter that keeps comments.
+- [yamlfmt](https://github.com/google/yamlfmt) - yamlfmt is an extensible command line tool or library to format yaml files.
+- [yapf](https://github.com/google/yapf) - Yet Another Python Formatter.
+- [yew-fmt](https://github.com/schvv31n/yew-fmt) - Code formatter for the Yew framework.
+- [yq](https://github.com/mikefarah/yq) - YAML/JSON processor
+- [zigfmt](https://github.com/ziglang/zig) - Reformat Zig source into canonical form.
+- [zprint](https://github.com/kkinnear/zprint) - Formatter for Clojure and EDN.
+
+
+
+
+## Customizing formatters
+
+You can override/add to the default values of formatters
+
+```lua
+require("conform").setup({
+ formatters = {
+ yamlfix = {
+ -- Change where to find the command
+ command = "local/path/yamlfix",
+ -- Adds environment args to the yamlfix formatter
+ env = {
+ YAMLFIX_SEQUENCE_STYLE = "block_style",
+ },
+ },
+ },
+})
+
+-- These can also be set directly
+require("conform").formatters.yamlfix = {
+ env = {
+ YAMLFIX_SEQUENCE_STYLE = "block_style",
+ },
+}
+
+-- This can also be a function that returns the config,
+-- which can be useful if you're doing lazy loading
+require("conform").formatters.yamlfix = function(bufnr)
+ return {
+ command = require("conform.util").find_executable({
+ "local/path/yamlfix",
+ }, "yamlfix"),
+ }
+end
+```
+
+In addition to being able to override any of the original properties on the formatter, there is another property for easily adding additional arguments to the format command
+
+```lua
+require("conform").formatters.shfmt = {
+ prepend_args = { "-i", "2" },
+ -- The base args are { "-filename", "$FILENAME" } so the final args will be
+ -- { "-i", "2", "-filename", "$FILENAME" }
+}
+-- prepend_args can be a function, just like args
+require("conform").formatters.shfmt = {
+ prepend_args = function(self, ctx)
+ return { "-i", "2" }
+ end,
+}
+```
+
+If you want to overwrite the entire formatter definition and _not_ merge with the default values, pass `inherit = false`. This is also the default behavior if there is no built-in formatter with the given name, which can be used to add your own custom formatters.
+
+```lua
+require("conform").formatters.shfmt = {
+ inherit = false,
+ command = "shfmt",
+ args = { "-i", "2", "-filename", "$FILENAME" },
+}
+```
+
+## Recipes
+
+
+
+- [Format command](doc/recipes.md#format-command)
+- [Autoformat with extra features](doc/recipes.md#autoformat-with-extra-features)
+- [Command to toggle format-on-save](doc/recipes.md#command-to-toggle-format-on-save)
+- [Automatically run slow formatters async](doc/recipes.md#automatically-run-slow-formatters-async)
+- [Lazy loading with lazy.nvim](doc/recipes.md#lazy-loading-with-lazynvim)
+
+
+
+## Advanced topics
+
+
+
+- [Minimal format diffs](doc/advanced_topics.md#minimal-format-diffs)
+- [Range formatting](doc/advanced_topics.md#range-formatting)
+- [Injected language formatting (code blocks)](doc/advanced_topics.md#injected-language-formatting-code-blocks)
+
+
+
+## Options
+
+A complete list of all configuration options
+
+
+
+```lua
+require("conform").setup({
+ -- Map of filetype to formatters
+ formatters_by_ft = {
+ lua = { "stylua" },
+ -- Conform will run multiple formatters sequentially
+ go = { "goimports", "gofmt" },
+ -- Use a sub-list to run only the first available formatter
+ javascript = { { "prettierd", "prettier" } },
+ -- You can use a function here to determine the formatters dynamically
+ python = function(bufnr)
+ if require("conform").get_formatter_info("ruff_format", bufnr).available then
+ return { "ruff_format" }
+ else
+ return { "isort", "black" }
+ end
+ end,
+ -- Use the "*" filetype to run formatters on all filetypes.
+ ["*"] = { "codespell" },
+ -- Use the "_" filetype to run formatters on filetypes that don't
+ -- have other formatters configured.
+ ["_"] = { "trim_whitespace" },
+ },
+ -- If this is set, Conform will run the formatter on save.
+ -- It will pass the table to conform.format().
+ -- This can also be a function that returns the table.
+ format_on_save = {
+ -- I recommend these options. See :help conform.format for details.
+ lsp_fallback = true,
+ timeout_ms = 500,
+ },
+ -- If this is set, Conform will run the formatter asynchronously after save.
+ -- It will pass the table to conform.format().
+ -- This can also be a function that returns the table.
+ format_after_save = {
+ lsp_fallback = true,
+ },
+ -- Set the log level. Use `:ConformInfo` to see the location of the log file.
+ log_level = vim.log.levels.ERROR,
+ -- Conform will notify you when a formatter errors
+ notify_on_error = true,
+ -- Custom formatters and overrides for built-in formatters
+ formatters = {
+ my_formatter = {
+ -- This can be a string or a function that returns a string.
+ -- When defining a new formatter, this is the only field that is required
+ command = "my_cmd",
+ -- A list of strings, or a function that returns a list of strings
+ -- Return a single string instead of a list to run the command in a shell
+ args = { "--stdin-from-filename", "$FILENAME" },
+ -- If the formatter supports range formatting, create the range arguments here
+ range_args = function(self, ctx)
+ return { "--line-start", ctx.range.start[1], "--line-end", ctx.range["end"][1] }
+ end,
+ -- Send file contents to stdin, read new contents from stdout (default true)
+ -- When false, will create a temp file (will appear in "$FILENAME" args). The temp
+ -- file is assumed to be modified in-place by the format command.
+ stdin = true,
+ -- A function that calculates the directory to run the command in
+ cwd = require("conform.util").root_file({ ".editorconfig", "package.json" }),
+ -- When cwd is not found, don't run the formatter (default false)
+ require_cwd = true,
+ -- When stdin=false, use this template to generate the temporary file that gets formatted
+ tmpfile_format = ".conform.$RANDOM.$FILENAME",
+ -- When returns false, the formatter will not be used
+ condition = function(self, ctx)
+ return vim.fs.basename(ctx.filename) ~= "README.md"
+ end,
+ -- Exit codes that indicate success (default { 0 })
+ exit_codes = { 0, 1 },
+ -- Environment variables. This can also be a function that returns a table.
+ env = {
+ VAR = "value",
+ },
+ -- Set to false to disable merging the config with the base definition
+ inherit = true,
+ -- When inherit = true, add these additional arguments to the command.
+ -- This can also be a function, like args
+ prepend_args = { "--use-tabs" },
+ },
+ -- These can also be a function that returns the formatter
+ other_formatter = function(bufnr)
+ return {
+ command = "my_cmd",
+ }
+ end,
+ },
+})
+
+-- You can set formatters_by_ft and formatters directly
+require("conform").formatters_by_ft.lua = { "stylua" }
+require("conform").formatters.my_formatter = {
+ command = "my_cmd",
+}
+```
+
+
+
+## Formatter options
+
+
+
+- [injected](doc/formatter_options.md#injected)
+- [prettier](doc/formatter_options.md#prettier)
+- [rustfmt](doc/formatter_options.md#rustfmt)
+- [yew-fmt](doc/formatter_options.md#yew-fmt)
+
+
+
+## API
+
+
+
+### setup(opts)
+
+`setup(opts)`
+
+| Param | Type | Desc | |
+| ----- | ------------------------ | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| opts | `nil\|conform.setupOpts` | | |
+| | formatters_by_ft | `nil\|table` | Map of filetype to formatters |
+| | format_on_save | `nil\|conform.FormatOpts\|fun(bufnr: integer): conform.FormatOpts` | If this is set, Conform will run the formatter on save. It will pass the table to conform.format(). This can also be a function that returns the table. |
+| | format_after_save | `nil\|conform.FormatOpts\|fun(bufnr: integer): conform.FormatOpts` | If this is set, Conform will run the formatter asynchronously after save. It will pass the table to conform.format(). This can also be a function that returns the table. |
+| | log_level | `nil\|integer` | Set the log level (e.g. `vim.log.levels.DEBUG`). Use `:ConformInfo` to see the location of the log file. |
+| | notify_on_error | `nil\|boolean` | Conform will notify you when a formatter errors (default true). |
+| | formatters | `nil\|table` | Custom formatters and overrides for built-in formatters. |
+
+### format(opts, callback)
+
+`format(opts, callback): boolean` \
+Format a buffer
+
+| Param | Type | Desc | |
+| -------- | ---------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
+| opts | `nil\|conform.FormatOpts` | | |
+| | timeout_ms | `nil\|integer` | Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true. |
+| | bufnr | `nil\|integer` | Format this buffer (default 0) |
+| | async | `nil\|boolean` | If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded. |
+| | dry_run | `nil\|boolean` | If true don't apply formatting changes to the buffer |
+| | formatters | `nil\|string[]` | List of formatters to run. Defaults to all formatters for the buffer filetype. |
+| | lsp_fallback | `nil\|boolean\|"always"` | Attempt LSP formatting if no formatters are available. Defaults to false. If "always", will attempt LSP formatting even if formatters are available. |
+| | quiet | `nil\|boolean` | Don't show any notifications for warnings or failures. Defaults to false. |
+| | range | `nil\|table` | Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode |
+| | id | `nil\|integer` | Passed to vim.lsp.buf.format when lsp_fallback = true |
+| | name | `nil\|string` | Passed to vim.lsp.buf.format when lsp_fallback = true |
+| | filter | `nil\|fun(client: table): boolean` | Passed to vim.lsp.buf.format when lsp_fallback = true |
+| callback | `nil\|fun(err: nil\|string, did_edit: nil\|boolean)` | Called once formatting has completed | |
+
+Returns:
+
+| Type | Desc |
+| ------- | ------------------------------------- |
+| boolean | True if any formatters were attempted |
+
+### list_formatters(bufnr)
+
+`list_formatters(bufnr): conform.FormatterInfo[]` \
+Retrieve the available formatters for a buffer
+
+| Param | Type | Desc |
+| ----- | -------------- | ---- |
+| bufnr | `nil\|integer` | |
+
+### list_all_formatters()
+
+`list_all_formatters(): conform.FormatterInfo[]` \
+List information about all filetype-configured formatters
+
+
+### get_formatter_info(formatter, bufnr)
+
+`get_formatter_info(formatter, bufnr): conform.FormatterInfo` \
+Get information about a formatter (including availability)
+
+| Param | Type | Desc |
+| --------- | -------------- | ------------------------- |
+| formatter | `string` | The name of the formatter |
+| bufnr | `nil\|integer` | |
+
+### will_fallback_lsp(options)
+
+`will_fallback_lsp(options): boolean` \
+Check if the buffer will use LSP formatting when lsp_fallback = true
+
+| Param | Type | Desc |
+| ------- | ------------ | ------------------------------------ |
+| options | `nil\|table` | Options passed to vim.lsp.buf.format |
+
+
+## Acknowledgements
+
+Thanks to
+
+- [nvim-lint](https://github.com/mfussenegger/nvim-lint) for providing inspiration for the config and API. It's an excellent plugin that balances power and simplicity.
+- [null-ls](https://github.com/jose-elias-alvarez/null-ls.nvim) for formatter configurations and being my formatter/linter of choice for a long time.
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/doc/advanced_topics.md b/config/neovim/store/lazy-plugins/conform.nvim/doc/advanced_topics.md
new file mode 100644
index 00000000..4dcc4212
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/doc/advanced_topics.md
@@ -0,0 +1,31 @@
+# Advanced topics
+
+
+
+- [Minimal format diffs](#minimal-format-diffs)
+- [Range formatting](#range-formatting)
+- [Injected language formatting (code blocks)](#injected-language-formatting-code-blocks)
+
+
+
+## Minimal format diffs
+
+To understand why this is important and why conform.nvim is different we need a bit of historical context. Formatting tools work by taking in the current state of the file and outputting the same contents, with formatting applied. The way most formatting plugins work is they take the new content and replace the entire buffer. The benefit of this approach is that it's very simple. It's easy to code, it's easy to reason about, and it's easy to debug.
+
+What conform does differently is it leverages `:help vim.diff`, Neovim's lua bindings for xdiff. We use this to compare the formatted lines to the original content and calculate minimal chunks where changes need to be applied. From there, we convert these chunks into LSP TextEdit objects and use `vim.lsp.util.apply_text_edits()` to actually apply the changes. Since we're using the built-in LSP utility, we get the benefits of all the work that was put into improving the LSP formatting experience, such as the preservation of extmarks. The piecewise update also does a better job of preserving cursor position, folds, viewport position, etc.
+
+## Range formatting
+
+When a formatting tool doesn't have built-in support for range formatting, conform will attempt to "fake it" when requested. This is necessarily a **best effort** operation and is **not** guaranteed to be correct or error-free, however in _most_ cases it should produce acceptable results.
+
+The way this "aftermarket" range formatting works is conform will format the entire buffer as per usual, but during the diff process it will discard diffs that fall outside of the selected range. This usually approximates a correct result, but as you can guess it's possible for the formatting to exceed the range (if the diff covering the range is large) or for the results to be incorrect (if the formatting changes require two diffs in different locations to be semantically correct).
+
+## Injected language formatting (code blocks)
+
+Requires: Neovim 0.9+
+
+Sometimes you may have a file that contains small chunks of code in another language. This is most common for markup formats like markdown and neorg, but can theoretically be present in any filetype (for example, embedded SQL queries in a host language). For files like this, it would be nice to be able to format these code chunks using their language-specific formatters.
+
+The way that conform supports this is via the `injected` formatter. If you run this formatter on a file, it will use treesitter to parse out the blocks in the file that have different languages and runs the formatters for that filetype (configured with `formatters_by_ft`). The formatters are run in parallel, one job for each language block.
+
+This formatter is experimental; the behavior and configuration options are still subject to change. The current list of configuration options can be found at [formatter options](formatter_options.md#injected)
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/doc/conform.txt b/config/neovim/store/lazy-plugins/conform.nvim/doc/conform.txt
new file mode 100644
index 00000000..4271e950
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/doc/conform.txt
@@ -0,0 +1,413 @@
+*conform.txt*
+*Conform* *conform* *conform.nvim*
+--------------------------------------------------------------------------------
+CONTENTS *conform-contents*
+
+ 1. Options |conform-options|
+ 2. Api |conform-api|
+ 3. Formatters |conform-formatters|
+
+--------------------------------------------------------------------------------
+OPTIONS *conform-options*
+
+>lua
+ require("conform").setup({
+ -- Map of filetype to formatters
+ formatters_by_ft = {
+ lua = { "stylua" },
+ -- Conform will run multiple formatters sequentially
+ go = { "goimports", "gofmt" },
+ -- Use a sub-list to run only the first available formatter
+ javascript = { { "prettierd", "prettier" } },
+ -- You can use a function here to determine the formatters dynamically
+ python = function(bufnr)
+ if require("conform").get_formatter_info("ruff_format", bufnr).available then
+ return { "ruff_format" }
+ else
+ return { "isort", "black" }
+ end
+ end,
+ -- Use the "*" filetype to run formatters on all filetypes.
+ ["*"] = { "codespell" },
+ -- Use the "_" filetype to run formatters on filetypes that don't
+ -- have other formatters configured.
+ ["_"] = { "trim_whitespace" },
+ },
+ -- If this is set, Conform will run the formatter on save.
+ -- It will pass the table to conform.format().
+ -- This can also be a function that returns the table.
+ format_on_save = {
+ -- I recommend these options. See :help conform.format for details.
+ lsp_fallback = true,
+ timeout_ms = 500,
+ },
+ -- If this is set, Conform will run the formatter asynchronously after save.
+ -- It will pass the table to conform.format().
+ -- This can also be a function that returns the table.
+ format_after_save = {
+ lsp_fallback = true,
+ },
+ -- Set the log level. Use `:ConformInfo` to see the location of the log file.
+ log_level = vim.log.levels.ERROR,
+ -- Conform will notify you when a formatter errors
+ notify_on_error = true,
+ -- Custom formatters and overrides for built-in formatters
+ formatters = {
+ my_formatter = {
+ -- This can be a string or a function that returns a string.
+ -- When defining a new formatter, this is the only field that is required
+ command = "my_cmd",
+ -- A list of strings, or a function that returns a list of strings
+ -- Return a single string instead of a list to run the command in a shell
+ args = { "--stdin-from-filename", "$FILENAME" },
+ -- If the formatter supports range formatting, create the range arguments here
+ range_args = function(self, ctx)
+ return { "--line-start", ctx.range.start[1], "--line-end", ctx.range["end"][1] }
+ end,
+ -- Send file contents to stdin, read new contents from stdout (default true)
+ -- When false, will create a temp file (will appear in "$FILENAME" args). The temp
+ -- file is assumed to be modified in-place by the format command.
+ stdin = true,
+ -- A function that calculates the directory to run the command in
+ cwd = require("conform.util").root_file({ ".editorconfig", "package.json" }),
+ -- When cwd is not found, don't run the formatter (default false)
+ require_cwd = true,
+ -- When stdin=false, use this template to generate the temporary file that gets formatted
+ tmpfile_format = ".conform.$RANDOM.$FILENAME",
+ -- When returns false, the formatter will not be used
+ condition = function(self, ctx)
+ return vim.fs.basename(ctx.filename) ~= "README.md"
+ end,
+ -- Exit codes that indicate success (default { 0 })
+ exit_codes = { 0, 1 },
+ -- Environment variables. This can also be a function that returns a table.
+ env = {
+ VAR = "value",
+ },
+ -- Set to false to disable merging the config with the base definition
+ inherit = true,
+ -- When inherit = true, add these additional arguments to the command.
+ -- This can also be a function, like args
+ prepend_args = { "--use-tabs" },
+ },
+ -- These can also be a function that returns the formatter
+ other_formatter = function(bufnr)
+ return {
+ command = "my_cmd",
+ }
+ end,
+ },
+ })
+
+ -- You can set formatters_by_ft and formatters directly
+ require("conform").formatters_by_ft.lua = { "stylua" }
+ require("conform").formatters.my_formatter = {
+ command = "my_cmd",
+ }
+<
+
+--------------------------------------------------------------------------------
+API *conform-api*
+
+setup({opts}) *conform.setup*
+
+ Parameters:
+ {opts} `nil|conform.setupOpts`
+ {formatters_by_ft} `nil|table` Map
+ of filetype to formatters
+ {format_on_save} `nil|conform.FormatOpts|fun(bufnr: integer): conform.FormatOpts` I
+ f this is set, Conform will run the formatter on
+ save. It will pass the table to conform.format().
+ This can also be a function that returns the table.
+ {format_after_save} `nil|conform.FormatOpts|fun(bufnr: integer): conform.FormatOpts` I
+ f this is set, Conform will run the formatter
+ asynchronously after save. It will pass the table
+ to conform.format(). This can also be a function
+ that returns the table.
+ {log_level} `nil|integer` Set the log level (e.g.
+ `vim.log.levels.DEBUG`). Use `:ConformInfo` to see
+ the location of the log file.
+ {notify_on_error} `nil|boolean` Conform will notify you when a
+ formatter errors (default true).
+ {formatters} `nil|table` C
+ ustom formatters and overrides for built-in
+ formatters.
+
+format({opts}, {callback}): boolean *conform.format*
+ Format a buffer
+
+ Parameters:
+ {opts} `nil|conform.FormatOpts`
+ {timeout_ms} `nil|integer` Time in milliseconds to block for
+ formatting. Defaults to 1000. No effect if async =
+ true.
+ {bufnr} `nil|integer` Format this buffer (default 0)
+ {async} `nil|boolean` If true the method won't block. Defaults
+ to false. If the buffer is modified before the
+ formatter completes, the formatting will be discarded.
+ {dry_run} `nil|boolean` If true don't apply formatting changes to
+ the buffer
+ {formatters} `nil|string[]` List of formatters to run. Defaults to
+ all formatters for the buffer filetype.
+ {lsp_fallback} `nil|boolean|"always"` Attempt LSP formatting if no
+ formatters are available. Defaults to false. If
+ "always", will attempt LSP formatting even if
+ formatters are available.
+ {quiet} `nil|boolean` Don't show any notifications for warnings
+ or failures. Defaults to false.
+ {range} `nil|table` Range to format. Table must contain `start`
+ and `end` keys with {row, col} tuples using (1,0)
+ indexing. Defaults to current selection in visual mode
+ {id} `nil|integer` Passed to |vim.lsp.buf.format| when
+ lsp_fallback = true
+ {name} `nil|string` Passed to |vim.lsp.buf.format| when
+ lsp_fallback = true
+ {filter} `nil|fun(client: table): boolean` Passed to
+ |vim.lsp.buf.format| when lsp_fallback = true
+ {callback} `nil|fun(err: nil|string, did_edit: nil|boolean)` Called once
+ formatting has completed
+ Returns:
+ `boolean` True if any formatters were attempted
+
+list_formatters({bufnr}): conform.FormatterInfo[] *conform.list_formatters*
+ Retrieve the available formatters for a buffer
+
+ Parameters:
+ {bufnr} `nil|integer`
+
+list_all_formatters(): conform.FormatterInfo[] *conform.list_all_formatters*
+ List information about all filetype-configured formatters
+
+
+get_formatter_info({formatter}, {bufnr}): conform.FormatterInfo *conform.get_formatter_info*
+ Get information about a formatter (including availability)
+
+ Parameters:
+ {formatter} `string` The name of the formatter
+ {bufnr} `nil|integer`
+
+will_fallback_lsp({options}): boolean *conform.will_fallback_lsp*
+ Check if the buffer will use LSP formatting when lsp_fallback = true
+
+ Parameters:
+ {options} `nil|table` Options passed to |vim.lsp.buf.format|
+
+--------------------------------------------------------------------------------
+FORMATTERS *conform-formatters*
+
+`alejandra` - The Uncompromising Nix Code Formatter.
+`asmfmt` - Go Assembler Formatter
+`ast-grep` - A CLI tool for code structural search, lint and rewriting. Written
+ in Rust.
+`astyle` - A Free, Fast, and Small Automatic Formatter for C, C++, C++/CLI,
+ Objective-C, C#, and Java Source Code.
+`auto_optional` - Adds the Optional type-hint to arguments where the default
+ value is None.
+`autocorrect` - A linter and formatter to help you to improve copywriting,
+ correct spaces, words, and punctuations between CJK.
+`autoflake` - Removes unused imports and unused variables as reported by
+ pyflakes.
+`autopep8` - A tool that automatically formats Python code to conform to the PEP
+ 8 style guide.
+`awk` - Format awk programs with awk
+`bean-format` - Reformat Beancount files to right-align all the numbers at the
+ same, minimal column.
+`beautysh` - A Bash beautifier for the masses.
+`bibtex-tidy` - Cleaner and Formatter for BibTeX files.
+`bicep` - Bicep is a Domain Specific Language (DSL) for deploying Azure
+ resources declaratively.
+`biome` - A toolchain for web projects, aimed to provide functionalities to
+ maintain them.
+`biome-check` - A toolchain for web projects, aimed to provide functionalities
+ to maintain them.
+`black` - The uncompromising Python code formatter.
+`blade-formatter` - An opinionated blade template formatter for Laravel that
+ respects readability.
+`blue` - The slightly less uncompromising Python code formatter.
+`bpfmt` - Android Blueprint file formatter.
+`buf` - A new way of working with Protocol Buffers.
+`buildifier` - buildifier is a tool for formatting bazel BUILD and .bzl files
+ with a standard convention.
+`cabal_fmt` - Format cabal files with cabal-fmt
+`cbfmt` - A tool to format codeblocks inside markdown and org documents.
+`clang-format` - Tool to format C/C++/… code according to a set of rules and
+ heuristics.
+`cljstyle` - Formatter for Clojure code.
+`cmake_format` - Parse cmake listfiles and format them nicely.
+`codespell` - Check code for common misspellings.
+`crystal` - Format Crystal code.
+`csharpier` - The opinionated C# code formatter.
+`cue_fmt` - Format CUE files using `cue fmt` command.
+`darker` - Run black only on changed lines.
+`dart_format` - Replace the whitespace in your program with formatting that
+ follows Dart guidelines.
+`deno_fmt` - Use [Deno](https://deno.land/) to format TypeScript,
+ JavaScript/JSON and markdown.
+`dfmt` - Formatter for D source code.
+`djlint` - ✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks -
+ Handlebars - GoLang.
+`dprint` - Pluggable and configurable code formatting platform written in Rust.
+`easy-coding-standard` - ecs - Use Coding Standard with 0-knowledge of PHP-CS-
+ Fixer and PHP_CodeSniffer.
+`elm_format` - elm-format formats Elm source code according to a standard set of
+ rules based on the official [Elm Style Guide](https://elm-
+ lang.org/docs/style-guide).
+`erb_format` - Format ERB files with speed and precision.
+`eslint_d` - Like ESLint, but faster.
+`fantomas` - F# source code formatter.
+`fish_indent` - Indent or otherwise prettify a piece of fish code.
+`fixjson` - JSON Fixer for Humans using (relaxed) JSON5.
+`fnlfmt` - A formatter for Fennel code.
+`forge_fmt` - Forge is a command-line tool that ships with Foundry. Forge tests,
+ builds, and deploys your smart contracts.
+`fourmolu` - A fork of ormolu that uses four space indentation and allows
+ arbitrary configuration.
+`gci` - GCI, a tool that controls Go package import order and makes it always
+ deterministic.
+`gdformat` - A formatter for Godot's gdscript.
+`gersemi` - A formatter to make your CMake code the real treasure.
+`gleam` - ⭐️ A friendly language for building type-safe, scalable systems!
+`gn` - gn build system.
+`gofmt` - Formats go programs.
+`gofumpt` - Enforce a stricter format than gofmt, while being backwards
+ compatible. That is, gofumpt is happy with a subset of the formats
+ that gofmt is happy with.
+`goimports` - Updates your Go import lines, adding missing ones and removing
+ unreferenced ones.
+`goimports-reviser` - Right imports sorting & code formatting tool (goimports
+ alternative).
+`golines` - A golang formatter that fixes long lines.
+`google-java-format` - Reformats Java source code according to Google Java
+ Style.
+`hcl` - A formatter for HCL files.
+`htmlbeautifier` - A normaliser/beautifier for HTML that also understands
+ embedded Ruby. Ideal for tidying up Rails templates.
+`indent` - GNU Indent.
+`injected` - Format treesitter injected languages.
+`inko` - A language for building concurrent software with confidence
+`isort` - Python utility / library to sort imports alphabetically and
+ automatically separate them into sections and by type.
+`joker` - Small Clojure interpreter, linter and formatter.
+`jq` - Command-line JSON processor.
+`jsonnetfmt` - jsonnetfmt is a command line tool to format jsonnet files.
+`just` - Format Justfile.
+`ktfmt` - Reformats Kotlin source code to comply with the common community
+ standard conventions.
+`ktlint` - An anti-bikeshedding Kotlin linter with built-in formatter.
+`latexindent` - A perl script for formatting LaTeX files that is generally
+ included in major TeX distributions.
+`leptosfmt` - A formatter for the Leptos view! macro.
+`liquidsoap-prettier` - A binary to format Liquidsoap scripts
+`markdown-toc` - API and CLI for generating a markdown TOC (table of contents)
+ for a README or any markdown files.
+`markdownlint` - A Node.js style checker and lint tool for Markdown/CommonMark
+ files.
+`markdownlint-cli2` - A fast, flexible, configuration-based command-line
+ interface for linting Markdown/CommonMark files with the
+ markdownlint library.
+`mdformat` - An opinionated Markdown formatter.
+`mdsf` - Format markdown code blocks using your favorite code formatters.
+`mdslw` - Prepare your markdown for easy diff'ing by adding line breaks after
+ every sentence.
+`mix` - Format Elixir files using the mix format command.
+`nimpretty` - nimpretty is a Nim source code beautifier that follows the
+ official style guide.
+`nixfmt` - nixfmt is a formatter for Nix code, intended to apply a uniform
+ style.
+`nixpkgs_fmt` - nixpkgs-fmt is a Nix code formatter for nixpkgs.
+`ocamlformat` - Auto-formatter for OCaml code.
+`ocp-indent` - Automatic indentation of OCaml source files.
+`opa_fmt` - Format Rego files using `opa fmt` command.
+`ormolu` - A formatter for Haskell source code.
+`packer_fmt` - The packer fmt Packer command is used to format HCL2
+ configuration files to a canonical format and style.
+`pangu` - Insert whitespace between CJK and half-width characters.
+`perlimports` - Make implicit Perl imports explicit.
+`perltidy` - Perl::Tidy, a source code formatter for Perl.
+`pg_format` - PostgreSQL SQL syntax beautifier.
+`php_cs_fixer` - The PHP Coding Standards Fixer.
+`phpcbf` - PHP Code Beautifier and Fixer fixes violations of a defined coding
+ standard.
+`phpinsights` - The perfect starting point to analyze the code quality of your
+ PHP projects.
+`pint` - Laravel Pint is an opinionated PHP code style fixer for minimalists.
+`prettier` - Prettier is an opinionated code formatter. It enforces a consistent
+ style by parsing your code and re-printing it with its own rules that
+ take the maximum line length into account, wrapping code when
+ necessary.
+`prettierd` - prettier, as a daemon, for ludicrous formatting speed.
+`pretty-php` - The opinionated PHP code formatter.
+`puppet-lint` - Check that your Puppet manifests conform to the style guide.
+`purs-tidy` - A syntax tidy-upper for PureScript.
+`reorder-python-imports` - Rewrites source to reorder python imports
+`rescript-format` - The built-in ReScript formatter.
+`roc` - A fast, friendly, functional language.
+`rubocop` - Ruby static code analyzer and formatter, based on the community Ruby
+ style guide.
+`rubyfmt` - Ruby Autoformatter! (Written in Rust)
+`ruff_fix` - An extremely fast Python linter, written in Rust. Fix lint errors.
+`ruff_format` - An extremely fast Python linter, written in Rust. Formatter
+ subcommand.
+`ruff_organize_imports` - An extremely fast Python linter, written in Rust.
+ Organize imports.
+`rufo` - Rufo is an opinionated ruby formatter.
+`rustfmt` - A tool for formatting rust code according to style guidelines.
+`rustywind` - A tool for formatting Tailwind CSS classes.
+`scalafmt` - Code formatter for Scala.
+`shellcheck` - A static analysis tool for shell scripts.
+`shellharden` - The corrective bash syntax highlighter.
+`shfmt` - A shell parser, formatter, and interpreter with `bash` support.
+`smlfmt` - A custom parser and code formatter for Standard ML.
+`snakefmt` - a formatting tool for Snakemake files following the design of
+ Black.
+`sql_formatter` - A whitespace formatter for different query languages.
+`sqlfluff` - A modular SQL linter and auto-formatter with support for multiple
+ dialects and templated code.
+`sqlfmt` - sqlfmt formats your dbt SQL files so you don't have to. It is similar
+ in nature to Black, gofmt, and rustfmt (but for SQL)
+`squeeze_blanks` - Squeeze repeated blank lines into a single blank line via
+ `cat -s`.
+`standardjs` - JavaScript Standard style guide, linter, and formatter.
+`standardrb` - Ruby's bikeshed-proof linter and formatter.
+`stylelint` - A mighty CSS linter that helps you avoid errors and enforce
+ conventions.
+`styler` - R formatter and linter.
+`stylua` - An opinionated code formatter for Lua.
+`swift_format` - Swift formatter from apple. Requires building from source with
+ `swift build`.
+`swiftformat` - SwiftFormat is a code library and command-line tool for
+ reformatting `swift` code on macOS or Linux.
+`taplo` - A TOML toolkit written in Rust.
+`templ` - Formats templ template files.
+`terraform_fmt` - The terraform-fmt command rewrites `terraform` configuration
+ files to a canonical format and style.
+`terragrunt_hclfmt` - Format hcl files into a canonical format.
+`tlint` - Tighten linter for Laravel conventions with support for auto-
+ formatting.
+`tofu_fmt` - The tofu-fmt command rewrites OpenTofu configuration files to a
+ canonical format and style.
+`trim_newlines` - Trim new lines with awk.
+`trim_whitespace` - Trim whitespaces with awk.
+`twig-cs-fixer` - Automatically fix Twig Coding Standards issues
+`typos` - Source code spell checker
+`typstfmt` - Basic formatter for the Typst language with a future!
+`typstyle` - Beautiful and reliable typst code formatter.
+`uncrustify` - A source code beautifier for C, C++, C#, ObjectiveC, D, Java,
+ Pawn and Vala.
+`usort` - Safe, minimal import sorting for Python projects.
+`verible` - The SystemVerilog formatter.
+`xmlformat` - xmlformatter is an Open Source Python package, which provides
+ formatting of XML documents.
+`xmllint` - Despite the name, xmllint can be used to format XML files as well as
+ lint them.
+`yamlfix` - A configurable YAML formatter that keeps comments.
+`yamlfmt` - yamlfmt is an extensible command line tool or library to format yaml
+ files.
+`yapf` - Yet Another Python Formatter.
+`yew-fmt` - Code formatter for the Yew framework.
+`yq` - YAML/JSON processor
+`zigfmt` - Reformat Zig source into canonical form.
+`zprint` - Formatter for Clojure and EDN.
+
+================================================================================
+vim:tw=80:ts=2:ft=help:norl:syntax=help:
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/doc/formatter_options.md b/config/neovim/store/lazy-plugins/conform.nvim/doc/formatter_options.md
new file mode 100644
index 00000000..5d3adb11
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/doc/formatter_options.md
@@ -0,0 +1,108 @@
+# Formatter Options
+
+
+
+- [injected](#injected)
+- [prettier](#prettier)
+- [rustfmt](#rustfmt)
+- [yew-fmt](#yew-fmt)
+
+
+
+All formatters can be customized by directly changing the command, args, or other values (see [customizing formatters](../README.md#customizing-formatters)). Some formatters have a bit more advanced logic built in to those functions and expose additional configuration options. You can pass these values in like so:
+
+```lua
+-- Customize the "injected" formatter
+require("conform").formatters.injected = {
+ -- Set the options field
+ options = {
+ -- Set individual option values
+ ignore_errors = true,
+ lang_to_formatters = {
+ json = { "jq" },
+ },
+ },
+}
+```
+
+
+
+## injected
+
+```lua
+options = {
+ -- Set to true to ignore errors
+ ignore_errors = false,
+ -- Map of treesitter language to file extension
+ -- A temporary file name with this extension will be generated during formatting
+ -- because some formatters care about the filename.
+ lang_to_ext = {
+ bash = "sh",
+ c_sharp = "cs",
+ elixir = "exs",
+ javascript = "js",
+ julia = "jl",
+ latex = "tex",
+ markdown = "md",
+ python = "py",
+ ruby = "rb",
+ rust = "rs",
+ teal = "tl",
+ typescript = "ts",
+ },
+ -- Map of treesitter language to formatters to use
+ -- (defaults to the value from formatters_by_ft)
+ lang_to_formatters = {},
+}
+```
+
+## prettier
+
+```lua
+options = {
+ -- Use a specific prettier parser for a filetype
+ -- Otherwise, prettier will try to infer the parser from the file name
+ ft_parsers = {
+ -- javascript = "babel",
+ -- javascriptreact = "babel",
+ -- typescript = "typescript",
+ -- typescriptreact = "typescript",
+ -- vue = "vue",
+ -- css = "css",
+ -- scss = "scss",
+ -- less = "less",
+ -- html = "html",
+ -- json = "json",
+ -- jsonc = "json",
+ -- yaml = "yaml",
+ -- markdown = "markdown",
+ -- ["markdown.mdx"] = "mdx",
+ -- graphql = "graphql",
+ -- handlebars = "glimmer",
+ },
+ -- Use a specific prettier parser for a file extension
+ ext_parsers = {
+ -- qmd = "markdown",
+ },
+}
+```
+
+## rustfmt
+
+```lua
+options = {
+ -- The default edition of Rust to use when no Cargo.toml file is found
+ default_edition = "2021",
+}
+```
+
+## yew-fmt
+
+```lua
+options = {
+ -- The default edition of Rust to use when no Cargo.toml file is found
+ default_edition = "2021",
+}
+```
+
+
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/doc/recipes.md b/config/neovim/store/lazy-plugins/conform.nvim/doc/recipes.md
new file mode 100644
index 00000000..97eaa16e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/doc/recipes.md
@@ -0,0 +1,180 @@
+# Recipes
+
+
+
+- [Format command](#format-command)
+- [Autoformat with extra features](#autoformat-with-extra-features)
+- [Command to toggle format-on-save](#command-to-toggle-format-on-save)
+- [Automatically run slow formatters async](#automatically-run-slow-formatters-async)
+- [Lazy loading with lazy.nvim](#lazy-loading-with-lazynvim)
+
+
+
+## Format command
+
+Define a command to run async formatting
+
+```lua
+vim.api.nvim_create_user_command("Format", function(args)
+ local range = nil
+ if args.count ~= -1 then
+ local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1]
+ range = {
+ start = { args.line1, 0 },
+ ["end"] = { args.line2, end_line:len() },
+ }
+ end
+ require("conform").format({ async = true, lsp_fallback = true, range = range })
+end, { range = true })
+```
+
+## Autoformat with extra features
+
+If you want more complex logic than the basic `format_on_save` option allows, you can use a function instead.
+
+
+
+```lua
+-- if format_on_save is a function, it will be called during BufWritePre
+require("conform").setup({
+ format_on_save = function(bufnr)
+ -- Disable autoformat on certain filetypes
+ local ignore_filetypes = { "sql", "java" }
+ if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then
+ return
+ end
+ -- Disable with a global or buffer-local variable
+ if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
+ return
+ end
+ -- Disable autoformat for files in a certain path
+ local bufname = vim.api.nvim_buf_get_name(bufnr)
+ if bufname:match("/node_modules/") then
+ return
+ end
+ -- ...additional logic...
+ return { timeout_ms = 500, lsp_fallback = true }
+ end,
+})
+
+-- There is a similar affordance for format_after_save, which uses BufWritePost.
+-- This is good for formatters that are too slow to run synchronously.
+require("conform").setup({
+ format_after_save = function(bufnr)
+ if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
+ return
+ end
+ -- ...additional logic...
+ return { lsp_fallback = true }
+ end,
+})
+```
+
+
+
+## Command to toggle format-on-save
+
+Create user commands to quickly enable/disable autoformatting
+
+```lua
+require("conform").setup({
+ format_on_save = function(bufnr)
+ -- Disable with a global or buffer-local variable
+ if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
+ return
+ end
+ return { timeout_ms = 500, lsp_fallback = true }
+ end,
+})
+
+vim.api.nvim_create_user_command("FormatDisable", function(args)
+ if args.bang then
+ -- FormatDisable! will disable formatting just for this buffer
+ vim.b.disable_autoformat = true
+ else
+ vim.g.disable_autoformat = true
+ end
+end, {
+ desc = "Disable autoformat-on-save",
+ bang = true,
+})
+vim.api.nvim_create_user_command("FormatEnable", function()
+ vim.b.disable_autoformat = false
+ vim.g.disable_autoformat = false
+end, {
+ desc = "Re-enable autoformat-on-save",
+})
+```
+
+## Automatically run slow formatters async
+
+This snippet will automatically detect which formatters take too long to run synchronously and will run them async on save instead.
+
+```lua
+local slow_format_filetypes = {}
+require("conform").setup({
+ format_on_save = function(bufnr)
+ if slow_format_filetypes[vim.bo[bufnr].filetype] then
+ return
+ end
+ local function on_format(err)
+ if err and err:match("timeout$") then
+ slow_format_filetypes[vim.bo[bufnr].filetype] = true
+ end
+ end
+
+ return { timeout_ms = 200, lsp_fallback = true }, on_format
+ end,
+
+ format_after_save = function(bufnr)
+ if not slow_format_filetypes[vim.bo[bufnr].filetype] then
+ return
+ end
+ return { lsp_fallback = true }
+ end,
+})
+```
+
+## Lazy loading with lazy.nvim
+
+Here is the recommended config for lazy-loading using lazy.nvim
+
+```lua
+return {
+ "stevearc/conform.nvim",
+ event = { "BufWritePre" },
+ cmd = { "ConformInfo" },
+ keys = {
+ {
+ -- Customize or remove this keymap to your liking
+ "f",
+ function()
+ require("conform").format({ async = true, lsp_fallback = true })
+ end,
+ mode = "",
+ desc = "Format buffer",
+ },
+ },
+ -- Everything in opts will be passed to setup()
+ opts = {
+ -- Define your formatters
+ formatters_by_ft = {
+ lua = { "stylua" },
+ python = { "isort", "black" },
+ javascript = { { "prettierd", "prettier" } },
+ },
+ -- Set up format-on-save
+ format_on_save = { timeout_ms = 500, lsp_fallback = true },
+ -- Customize formatters
+ formatters = {
+ shfmt = {
+ prepend_args = { "-i", "2" },
+ },
+ },
+ },
+ init = function()
+ -- If you want the formatexpr, here is the place to set it
+ vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"
+ end,
+}
+```
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/errors.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/errors.lua
new file mode 100644
index 00000000..43e9a7b2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/errors.lua
@@ -0,0 +1,66 @@
+local M = {}
+
+---@class conform.Error
+---@field code conform.ERROR_CODE
+---@field message string
+---@field debounce_message? boolean
+
+---@enum conform.ERROR_CODE
+M.ERROR_CODE = {
+ -- Command was passed invalid arguments
+ INVALID_ARGS = 1,
+ -- Command was not executable
+ NOT_EXECUTABLE = 2,
+ -- Error occurred during when calling jobstart
+ JOBSTART = 3,
+ -- Command timed out during execution
+ TIMEOUT = 4,
+ -- Command was pre-empted by another call to format
+ INTERRUPTED = 5,
+ -- Command produced an error during execution
+ RUNTIME = 6,
+ -- Asynchronous formatter results were discarded due to a concurrent modification
+ CONCURRENT_MODIFICATION = 7,
+}
+
+---@param code conform.ERROR_CODE
+---@return integer
+M.level_for_code = function(code)
+ if code == M.ERROR_CODE.CONCURRENT_MODIFICATION then
+ return vim.log.levels.INFO
+ elseif code == M.ERROR_CODE.TIMEOUT or code == M.ERROR_CODE.INTERRUPTED then
+ return vim.log.levels.WARN
+ else
+ return vim.log.levels.ERROR
+ end
+end
+
+---Returns true if the error occurred while attempting to run the formatter
+---@param code conform.ERROR_CODE
+---@return boolean
+M.is_execution_error = function(code)
+ return code == M.ERROR_CODE.RUNTIME
+ or code == M.ERROR_CODE.NOT_EXECUTABLE
+ or code == M.ERROR_CODE.INVALID_ARGS
+ or code == M.ERROR_CODE.JOBSTART
+end
+
+---@param err1? conform.Error
+---@param err2? conform.Error
+---@return nil|conform.Error
+M.coalesce = function(err1, err2)
+ if not err1 then
+ return err2
+ elseif not err2 then
+ return err1
+ end
+ local level1 = M.level_for_code(err1.code)
+ local level2 = M.level_for_code(err2.code)
+ if level2 > level1 then
+ return err2
+ else
+ return err1
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/alejandra.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/alejandra.lua
new file mode 100644
index 00000000..3a712b9f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/alejandra.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://kamadorueda.com/alejandra/",
+ description = "The Uncompromising Nix Code Formatter.",
+ },
+ command = "alejandra",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/asmfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/asmfmt.lua
new file mode 100644
index 00000000..5c77ac4b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/asmfmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/klauspost/asmfmt",
+ description = "Go Assembler Formatter",
+ },
+ command = "asmfmt",
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ast-grep.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ast-grep.lua
new file mode 100644
index 00000000..0b47e397
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ast-grep.lua
@@ -0,0 +1,11 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://ast-grep.github.io/",
+ description = "A CLI tool for code structural search, lint and rewriting. Written in Rust.",
+ },
+ command = "ast-grep",
+ args = { "scan", "--update-all", "$FILENAME" },
+ stdin = false,
+ exit_codes = { 0, 5 }, -- 5 = no config file exists
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/astyle.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/astyle.lua
new file mode 100644
index 00000000..82743c4b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/astyle.lua
@@ -0,0 +1,14 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://astyle.sourceforge.net/astyle.html",
+ description = "A Free, Fast, and Small Automatic Formatter for C, C++, C++/CLI, Objective-C, C#, and Java Source Code.",
+ },
+ command = "astyle",
+ args = { "--quiet" },
+ cwd = util.root_file({
+ ".astylerc",
+ "_astylerc",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/auto_optional.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/auto_optional.lua
new file mode 100644
index 00000000..b0738dcc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/auto_optional.lua
@@ -0,0 +1,12 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://auto-optional.daanluttik.nl/",
+ description = "Adds the Optional type-hint to arguments where the default value is None.",
+ },
+ command = "auto-optional",
+ args = {
+ "$FILENAME",
+ },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/autocorrect.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/autocorrect.lua
new file mode 100644
index 00000000..b12e99ff
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/autocorrect.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/huacnlee/autocorrect",
+ description = "A linter and formatter to help you to improve copywriting, correct spaces, words, and punctuations between CJK.",
+ },
+ command = "autocorrect",
+ args = { "--stdin" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/autoflake.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/autoflake.lua
new file mode 100644
index 00000000..c7d0a3bf
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/autoflake.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/PyCQA/autoflake",
+ description = "Removes unused imports and unused variables as reported by pyflakes.",
+ },
+ command = "autoflake",
+ args = { "--stdin-display-name", "$FILENAME", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/autopep8.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/autopep8.lua
new file mode 100644
index 00000000..3d5b015c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/autopep8.lua
@@ -0,0 +1,12 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/hhatto/autopep8",
+ description = "A tool that automatically formats Python code to conform to the PEP 8 style guide.",
+ },
+ command = "autopep8",
+ args = { "-" },
+ range_args = function(self, ctx)
+ return { "-", "--line-range", tostring(ctx.range.start[1]), tostring(ctx.range["end"][1]) }
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/awk.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/awk.lua
new file mode 100644
index 00000000..00df393e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/awk.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://www.gnu.org/software/gawk/manual/gawk.html",
+ description = "Format awk programs with awk",
+ },
+ command = "awk",
+ args = { "-f", "-", "-o-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bean-format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bean-format.lua
new file mode 100644
index 00000000..c985bfa5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bean-format.lua
@@ -0,0 +1,11 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://beancount.github.io/docs/running_beancount_and_generating_reports.html#bean-format",
+ description = "Reformat Beancount files to right-align all the numbers at the same, minimal column.",
+ },
+ command = "bean-format",
+ args = {
+ "-",
+ },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/beautysh.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/beautysh.lua
new file mode 100644
index 00000000..4dac4e66
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/beautysh.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/lovesegfault/beautysh",
+ description = "A Bash beautifier for the masses.",
+ },
+ command = "beautysh",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bibtex-tidy.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bibtex-tidy.lua
new file mode 100644
index 00000000..e68a3816
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bibtex-tidy.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/FlamingTempura/bibtex-tidy",
+ description = "Cleaner and Formatter for BibTeX files.",
+ },
+ command = "bibtex-tidy",
+ stdin = true,
+ args = { "--quiet" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bicep.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bicep.lua
new file mode 100644
index 00000000..17ccbf1a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bicep.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/Azure/bicep",
+ description = "Bicep is a Domain Specific Language (DSL) for deploying Azure resources declaratively.",
+ },
+ command = "bicep",
+ args = { "format", "--stdout", "$FILENAME" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/biome-check.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/biome-check.lua
new file mode 100644
index 00000000..5033cc32
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/biome-check.lua
@@ -0,0 +1,15 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/biomejs/biome",
+ description = "A toolchain for web projects, aimed to provide functionalities to maintain them.",
+ },
+ command = util.from_node_modules("biome"),
+ stdin = true,
+ args = { "check", "--apply", "--stdin-file-path", "$FILENAME" },
+ cwd = util.root_file({
+ "biome.json",
+ "biome.jsonc",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/biome.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/biome.lua
new file mode 100644
index 00000000..99af89ed
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/biome.lua
@@ -0,0 +1,15 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/biomejs/biome",
+ description = "A toolchain for web projects, aimed to provide functionalities to maintain them.",
+ },
+ command = util.from_node_modules("biome"),
+ stdin = true,
+ args = { "format", "--stdin-file-path", "$FILENAME" },
+ cwd = util.root_file({
+ "biome.json",
+ "biome.jsonc",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/black.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/black.lua
new file mode 100644
index 00000000..e27ed90d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/black.lua
@@ -0,0 +1,19 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/psf/black",
+ description = "The uncompromising Python code formatter.",
+ },
+ command = "black",
+ args = {
+ "--stdin-filename",
+ "$FILENAME",
+ "--quiet",
+ "-",
+ },
+ cwd = util.root_file({
+ -- https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-via-a-file
+ "pyproject.toml",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/blade-formatter.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/blade-formatter.lua
new file mode 100644
index 00000000..8b552d9c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/blade-formatter.lua
@@ -0,0 +1,12 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/shufo/blade-formatter",
+ description = "An opinionated blade template formatter for Laravel that respects readability.",
+ },
+ command = "blade-formatter",
+ args = { "--stdin" },
+ stdin = true,
+ cwd = util.root_file({ "composer.json", "composer.lock" }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/blue.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/blue.lua
new file mode 100644
index 00000000..6869339b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/blue.lua
@@ -0,0 +1,21 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/grantjenks/blue",
+ description = "The slightly less uncompromising Python code formatter.",
+ },
+ command = "blue",
+ args = {
+ "--stdin-filename",
+ "$FILENAME",
+ "--quiet",
+ "-",
+ },
+ cwd = util.root_file({
+ "setup.cfg",
+ "pyproject.toml",
+ "tox.ini",
+ ".blue",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bpfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bpfmt.lua
new file mode 100644
index 00000000..5f7c66d0
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/bpfmt.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://source.android.com/docs/setup/reference/androidbp",
+ description = "Android Blueprint file formatter.",
+ },
+ command = "bpfmt",
+ args = { "-w", "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/buf.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/buf.lua
new file mode 100644
index 00000000..e430bf6d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/buf.lua
@@ -0,0 +1,11 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://buf.build/docs/reference/cli/buf/format",
+ description = "A new way of working with Protocol Buffers.",
+ },
+ command = "buf",
+ args = { "format", "-w", "$FILENAME" },
+ stdin = false,
+ cwd = require("conform.util").root_file({ "buf.yaml" }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/buildifier.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/buildifier.lua
new file mode 100644
index 00000000..cd5e5cb6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/buildifier.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/bazelbuild/buildtools/tree/master/buildifier",
+ description = "buildifier is a tool for formatting bazel BUILD and .bzl files with a standard convention.",
+ },
+ command = "buildifier",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cabal_fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cabal_fmt.lua
new file mode 100644
index 00000000..698e22c3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cabal_fmt.lua
@@ -0,0 +1,8 @@
+return {
+ meta = {
+ url = "https://hackage.haskell.org/package/cabal-fmt",
+ description = "Format cabal files with cabal-fmt",
+ },
+ command = "cabal-fmt",
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cbfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cbfmt.lua
new file mode 100644
index 00000000..57c48e42
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cbfmt.lua
@@ -0,0 +1,15 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/lukas-reineke/cbfmt",
+ description = "A tool to format codeblocks inside markdown and org documents.",
+ },
+ command = "cbfmt",
+ args = { "--write", "--best-effort", "$FILENAME" },
+ cwd = util.root_file({
+ -- https://github.com/lukas-reineke/cbfmt#config
+ ".cbfmt.toml",
+ }),
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/clang-format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/clang-format.lua
new file mode 100644
index 00000000..2e68fc1b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/clang-format.lua
@@ -0,0 +1,22 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://www.kernel.org/doc/html/latest/process/clang-format.html",
+ description = "Tool to format C/C++/… code according to a set of rules and heuristics.",
+ },
+ command = "clang-format",
+ args = { "-assume-filename", "$FILENAME" },
+ range_args = function(self, ctx)
+ local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
+ local length = end_offset - start_offset
+ return {
+ "-assume-filename",
+ "$FILENAME",
+ "--offset",
+ tostring(start_offset),
+ "--length",
+ tostring(length),
+ }
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/clang_format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/clang_format.lua
new file mode 100644
index 00000000..72e545bb
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/clang_format.lua
@@ -0,0 +1,4 @@
+-- This was renamed to clang-format
+local conf = vim.deepcopy(require("conform.formatters.clang-format"))
+conf.meta.deprecated = true
+return conf
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cljstyle.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cljstyle.lua
new file mode 100644
index 00000000..21205a5a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cljstyle.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/greglook/cljstyle",
+ description = "Formatter for Clojure code.",
+ },
+ command = "cljstyle",
+ args = { "pipe" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cmake_format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cmake_format.lua
new file mode 100644
index 00000000..0e981083
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cmake_format.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/cheshirekow/cmake_format",
+ description = "Parse cmake listfiles and format them nicely.",
+ },
+ command = "cmake-format",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/codespell.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/codespell.lua
new file mode 100644
index 00000000..88e01091
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/codespell.lua
@@ -0,0 +1,15 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/codespell-project/codespell",
+ description = "Check code for common misspellings.",
+ },
+ command = "codespell",
+ stdin = false,
+ args = {
+ "$FILENAME",
+ "--write-changes",
+ "--check-hidden", -- conform's temp file is hidden
+ },
+ exit_codes = { 0, 65 }, -- code 65 is given when trying to format an ambiguous misspelling
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/crystal.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/crystal.lua
new file mode 100644
index 00000000..1f9e12bd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/crystal.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://crystal-lang.org/",
+ description = "Format Crystal code.",
+ },
+ command = "crystal",
+ args = { "tool", "format", "-" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/csharpier.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/csharpier.lua
new file mode 100644
index 00000000..0da7da5d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/csharpier.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/belav/csharpier",
+ description = "The opinionated C# code formatter.",
+ },
+ command = "dotnet-csharpier",
+ args = { "--write-stdout" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cue_fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cue_fmt.lua
new file mode 100644
index 00000000..e9787d68
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/cue_fmt.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://cuelang.org",
+ description = "Format CUE files using `cue fmt` command.",
+ },
+ command = "cue",
+ args = { "fmt", "-" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/darker.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/darker.lua
new file mode 100644
index 00000000..9fe9b205
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/darker.lua
@@ -0,0 +1,35 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/akaihola/darker",
+ description = "Run black only on changed lines.",
+ },
+ command = "darker",
+ args = function(self, ctx)
+ -- make sure pre-save doesn't lose changes while post-save respects
+ -- the revision setting potentially set in pyproject.toml
+ if vim.bo[ctx.buf].modified then
+ return {
+ "--quiet",
+ "--no-color",
+ "--stdout",
+ "--revision",
+ "HEAD..:STDIN:",
+ "--stdin-filename",
+ "$FILENAME",
+ }
+ else
+ return {
+ "--quiet",
+ "--no-color",
+ "--stdout",
+ "$FILENAME",
+ }
+ end
+ end,
+ cwd = util.root_file({
+ -- https://github.com/akaihola/darker#customizing-darker-black-isort-flynt-and-linter-behavior
+ "pyproject.toml",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/dart_format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/dart_format.lua
new file mode 100644
index 00000000..e110b06e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/dart_format.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://dart.dev/tools/dart-format",
+ description = "Replace the whitespace in your program with formatting that follows Dart guidelines.",
+ },
+ command = "dart",
+ args = { "format" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/deno_fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/deno_fmt.lua
new file mode 100644
index 00000000..5e7f4523
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/deno_fmt.lua
@@ -0,0 +1,25 @@
+local extensions = {
+ javascript = "js",
+ javascriptreact = "jsx",
+ json = "json",
+ jsonc = "jsonc",
+ markdown = "md",
+ typescript = "ts",
+ typescriptreact = "tsx",
+}
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://deno.land/manual/tools/formatter",
+ description = "Use [Deno](https://deno.land/) to format TypeScript, JavaScript/JSON and markdown.",
+ },
+ command = "deno",
+ args = function(self, ctx)
+ return {
+ "fmt",
+ "-",
+ "--ext",
+ extensions[vim.bo[ctx.buf].filetype],
+ }
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/dfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/dfmt.lua
new file mode 100644
index 00000000..41dd667e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/dfmt.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/dlang-community/dfmt",
+ description = "Formatter for D source code.",
+ },
+ command = "dfmt",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/djlint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/djlint.lua
new file mode 100644
index 00000000..03922bdd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/djlint.lua
@@ -0,0 +1,16 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/Riverside-Healthcare/djLint",
+ description = "✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang.",
+ },
+ command = "djlint",
+ args = {
+ "--reformat",
+ "-",
+ },
+ cwd = util.root_file({
+ ".djlintrc",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/dprint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/dprint.lua
new file mode 100644
index 00000000..8c792216
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/dprint.lua
@@ -0,0 +1,16 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/dprint/dprint",
+ description = "Pluggable and configurable code formatting platform written in Rust.",
+ },
+ command = "dprint",
+ args = { "fmt", "--stdin", "$FILENAME" },
+ cwd = util.root_file({
+ "dprint.json",
+ ".dprint.json",
+ "dprint.jsonc",
+ ".dprint.jsonc",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/easy-coding-standard.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/easy-coding-standard.lua
new file mode 100644
index 00000000..d1ed3a6c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/easy-coding-standard.lua
@@ -0,0 +1,18 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/easy-coding-standard/easy-coding-standard",
+ description = "ecs - Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer.",
+ },
+ command = util.find_executable({
+ "vendor/bin/ecs",
+ }, "ecs"),
+ args = { "check", "$FILENAME", "--fix", "--no-interaction" },
+ cwd = util.root_file({
+ "ecs.php",
+ }),
+ require_cwd = true,
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/elm_format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/elm_format.lua
new file mode 100644
index 00000000..5b0db5c7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/elm_format.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/avh4/elm-format",
+ description = "elm-format formats Elm source code according to a standard set of rules based on the official [Elm Style Guide](https://elm-lang.org/docs/style-guide).",
+ },
+ command = "elm-format",
+ args = { "--stdin" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/erb_format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/erb_format.lua
new file mode 100644
index 00000000..65d7d10b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/erb_format.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/nebulab/erb-formatter",
+ description = "Format ERB files with speed and precision.",
+ },
+ command = "erb-format",
+ args = { "--stdin" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/eslint_d.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/eslint_d.lua
new file mode 100644
index 00000000..e7a52277
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/eslint_d.lua
@@ -0,0 +1,13 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/mantoni/eslint_d.js/",
+ description = "Like ESLint, but faster.",
+ },
+ command = util.from_node_modules("eslint_d"),
+ args = { "--fix-to-stdout", "--stdin", "--stdin-filename", "$FILENAME" },
+ cwd = util.root_file({
+ "package.json",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fantomas.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fantomas.lua
new file mode 100644
index 00000000..9244feb6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fantomas.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/fsprojects/fantomas",
+ description = "F# source code formatter.",
+ },
+ command = "fantomas",
+ args = { "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fish_indent.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fish_indent.lua
new file mode 100644
index 00000000..7e10ed47
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fish_indent.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://fishshell.com/docs/current/cmds/fish_indent.html",
+ description = "Indent or otherwise prettify a piece of fish code.",
+ },
+ command = "fish_indent",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fixjson.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fixjson.lua
new file mode 100644
index 00000000..fee611c9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fixjson.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/rhysd/fixjson",
+ description = "JSON Fixer for Humans using (relaxed) JSON5.",
+ },
+ command = "fixjson",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fnlfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fnlfmt.lua
new file mode 100644
index 00000000..3cc03b81
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fnlfmt.lua
@@ -0,0 +1,9 @@
+--@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://git.sr.ht/~technomancy/fnlfmt",
+ description = "A formatter for Fennel code.",
+ },
+ command = "fnlfmt",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/forge_fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/forge_fmt.lua
new file mode 100644
index 00000000..c6bdafba
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/forge_fmt.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/foundry-rs/foundry",
+ description = "Forge is a command-line tool that ships with Foundry. Forge tests, builds, and deploys your smart contracts.",
+ },
+ command = "forge",
+ args = { "fmt", "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fourmolu.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fourmolu.lua
new file mode 100644
index 00000000..4e1db8ed
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/fourmolu.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://hackage.haskell.org/package/fourmolu",
+ description = "A fork of ormolu that uses four space indentation and allows arbitrary configuration.",
+ },
+ command = "fourmolu",
+ args = { "--stdin-input-file", "$FILENAME" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gci.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gci.lua
new file mode 100644
index 00000000..88293d78
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gci.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/daixiang0/gci",
+ description = "GCI, a tool that controls Go package import order and makes it always deterministic.",
+ },
+ command = "gci",
+ args = { "write", "--skip-generated", "--skip-vendor", "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gdformat.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gdformat.lua
new file mode 100644
index 00000000..d180f125
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gdformat.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/Scony/godot-gdscript-toolkit",
+ description = "A formatter for Godot's gdscript.",
+ },
+ command = "gdformat",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gersemi.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gersemi.lua
new file mode 100644
index 00000000..4c977170
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gersemi.lua
@@ -0,0 +1,11 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/BlankSpruce/gersemi",
+ description = "A formatter to make your CMake code the real treasure.",
+ },
+ command = "gersemi",
+ args = { "--quiet", "-" },
+ cwd = util.root_file({ ".gersemirc" }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gleam.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gleam.lua
new file mode 100644
index 00000000..a03afac1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gleam.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/gleam-lang/gleam",
+ description = "⭐️ A friendly language for building type-safe, scalable systems!",
+ },
+ command = "gleam",
+ args = { "format", "--stdin" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gn.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gn.lua
new file mode 100644
index 00000000..fd576d94
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gn.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://gn.googlesource.com/gn/",
+ description = "gn build system.",
+ },
+ command = "gn",
+ args = { "format", "--stdin" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gofmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gofmt.lua
new file mode 100644
index 00000000..2bfd6b4d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gofmt.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://pkg.go.dev/cmd/gofmt",
+ description = "Formats go programs.",
+ },
+ command = "gofmt",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gofumpt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gofumpt.lua
new file mode 100644
index 00000000..2d4f9a5f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/gofumpt.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/mvdan/gofumpt",
+ description = "Enforce a stricter format than gofmt, while being backwards compatible. That is, gofumpt is happy with a subset of the formats that gofmt is happy with.",
+ },
+ command = "gofumpt",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/goimports-reviser.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/goimports-reviser.lua
new file mode 100644
index 00000000..9d28c07c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/goimports-reviser.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/incu6us/goimports-reviser",
+ description = "Right imports sorting & code formatting tool (goimports alternative).",
+ },
+ command = "goimports-reviser",
+ args = { "-format", "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/goimports.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/goimports.lua
new file mode 100644
index 00000000..64efea6a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/goimports.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://pkg.go.dev/golang.org/x/tools/cmd/goimports",
+ description = "Updates your Go import lines, adding missing ones and removing unreferenced ones.",
+ },
+ command = "goimports",
+ args = { "-srcdir", "$DIRNAME" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/golines.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/golines.lua
new file mode 100644
index 00000000..1f33668d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/golines.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/segmentio/golines",
+ description = "A golang formatter that fixes long lines.",
+ },
+ command = "golines",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/google-java-format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/google-java-format.lua
new file mode 100644
index 00000000..8bcb82a2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/google-java-format.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/google/google-java-format",
+ description = "Reformats Java source code according to Google Java Style.",
+ },
+ command = "google-java-format",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/hcl.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/hcl.lua
new file mode 100644
index 00000000..8cffc7fb
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/hcl.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/hashicorp/hcl",
+ description = "A formatter for HCL files.",
+ },
+ command = "hclfmt",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/htmlbeautifier.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/htmlbeautifier.lua
new file mode 100644
index 00000000..73b9275e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/htmlbeautifier.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/threedaymonk/htmlbeautifier",
+ description = "A normaliser/beautifier for HTML that also understands embedded Ruby. Ideal for tidying up Rails templates.",
+ },
+ command = "htmlbeautifier",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/indent.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/indent.lua
new file mode 100644
index 00000000..cb4631c6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/indent.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://www.gnu.org/software/indent/",
+ description = "GNU Indent.",
+ },
+ command = "indent",
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/init.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/init.lua
new file mode 100644
index 00000000..237d39c0
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/init.lua
@@ -0,0 +1,37 @@
+local M = {}
+local uv = vim.uv or vim.loop
+
+---@private
+---This is used for documentation generation
+M.list_all_formatters = function()
+ local ret = {}
+ for path in vim.gsplit(vim.o.runtimepath, ",", { plain = true }) do
+ local formatter_path = path .. "/lua/conform/formatters"
+ local formatter_dir = uv.fs_opendir(formatter_path)
+ if formatter_dir then
+ local entries = uv.fs_readdir(formatter_dir)
+ while entries do
+ for _, entry in ipairs(entries) do
+ if entry.name ~= "init.lua" then
+ local basename = string.match(entry.name, "^(.*)%.lua$")
+ local module = require("conform.formatters." .. basename)
+ local module_data = vim.deepcopy(module.meta)
+ module_data.has_options = module.options ~= nil
+ ret[basename] = module_data
+ end
+ end
+ entries = uv.fs_readdir(formatter_dir)
+ end
+ uv.fs_closedir(formatter_dir)
+ end
+ end
+ return ret
+end
+
+-- A little metatable magic to allow accessing formatters like
+-- require("conform.formatters").prettier
+return setmetatable(M, {
+ __index = function(_, k)
+ return require("conform.formatters." .. k)
+ end,
+})
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/injected.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/injected.lua
new file mode 100644
index 00000000..4dbf1eb3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/injected.lua
@@ -0,0 +1,324 @@
+---@param range? conform.Range
+---@param start_lnum integer
+---@param end_lnum integer
+---@return boolean
+local function in_range(range, start_lnum, end_lnum)
+ return not range or (start_lnum <= range["end"][1] and range["start"][1] <= end_lnum)
+end
+
+---@param lines string[]
+---@param language? string The language of the buffer
+---@return string?
+local function get_indent(lines, language)
+ local indent = nil
+ -- Handle markdown code blocks that are inside blockquotes
+ -- > ```lua
+ -- > local x = 1
+ -- > ```
+ local pattern = language == "markdown" and "^>?%s*" or "^%s*"
+ for _, line in ipairs(lines) do
+ if line ~= "" then
+ local whitespace = line:match(pattern)
+ if whitespace == "" then
+ return nil
+ elseif not indent or whitespace:len() < indent:len() then
+ indent = whitespace
+ end
+ end
+ end
+ return indent
+end
+
+---@class (exact) conform.Injected.Surrounding
+---@field indent string?
+---@field postfix string?
+
+---Remove leading indentation from lines and return the indentation string
+---@param lines string[]
+---@param language? string The language of the buffer
+---@return conform.Injected.Surrounding
+local function remove_surrounding(lines, language)
+ local surrounding = {}
+ if lines[#lines]:match("^%s*$") then
+ surrounding.postfix = lines[#lines]
+ table.remove(lines)
+ end
+
+ local indent = get_indent(lines, language)
+ if not indent then
+ return surrounding
+ end
+ local sub_start = indent:len() + 1
+ for i, line in ipairs(lines) do
+ if line ~= "" then
+ lines[i] = line:sub(sub_start)
+ end
+ end
+ surrounding.indent = indent
+ return surrounding
+end
+
+---@param lines string[]?
+---@param surrounding conform.Injected.Surrounding
+local function restore_surrounding(lines, surrounding)
+ if not lines then
+ return
+ end
+
+ local indent = surrounding.indent
+ if indent then
+ for i, line in ipairs(lines) do
+ if line ~= "" then
+ lines[i] = indent .. line
+ end
+ end
+ end
+
+ local postfix = surrounding.postfix
+ if postfix then
+ table.insert(lines, postfix)
+ end
+end
+
+---@class LangRange
+---@field [1] string language
+---@field [2] integer start lnum
+---@field [3] integer start col
+---@field [4] integer end lnum
+---@field [5] integer end col
+
+---@param ranges LangRange[]
+---@param range LangRange
+local function accum_range(ranges, range)
+ local last_range = ranges[#ranges]
+ if last_range then
+ if last_range[1] == range[1] and last_range[4] == range[2] and last_range[5] == range[3] then
+ last_range[4] = range[4]
+ last_range[5] = range[5]
+ return
+ end
+ end
+ table.insert(ranges, range)
+end
+
+---@class (exact) conform.InjectedFormatterOptions
+---@field ignore_errors boolean
+---@field lang_to_ext table
+---@field lang_to_formatters table
+
+---@type conform.FileLuaFormatterConfig
+return {
+ meta = {
+ url = "doc/advanced_topics.md#injected-language-formatting-code-blocks",
+ description = "Format treesitter injected languages.",
+ },
+ options = {
+ -- Set to true to ignore errors
+ ignore_errors = false,
+ -- Map of treesitter language to file extension
+ -- A temporary file name with this extension will be generated during formatting
+ -- because some formatters care about the filename.
+ lang_to_ext = {
+ bash = "sh",
+ c_sharp = "cs",
+ elixir = "exs",
+ javascript = "js",
+ julia = "jl",
+ latex = "tex",
+ markdown = "md",
+ python = "py",
+ ruby = "rb",
+ rust = "rs",
+ teal = "tl",
+ typescript = "ts",
+ },
+ -- Map of treesitter language to formatters to use
+ -- (defaults to the value from formatters_by_ft)
+ lang_to_formatters = {},
+ },
+ condition = function(self, ctx)
+ local ok, parser = pcall(vim.treesitter.get_parser, ctx.buf)
+ -- Require Neovim 0.9 because the treesitter API has changed significantly
+ ---@diagnostic disable-next-line: invisible
+ return ok and parser._injection_query and vim.fn.has("nvim-0.9") == 1
+ end,
+ format = function(self, ctx, lines, callback)
+ local conform = require("conform")
+ local errors = require("conform.errors")
+ local log = require("conform.log")
+ local util = require("conform.util")
+ -- Need to add a trailing newline; some parsers need this.
+ -- For example, if a markdown code block ends at the end of the file, a trailing newline is
+ -- required otherwise the ``` will be grabbed as part of the injected block
+ local text = table.concat(lines, "\n") .. "\n"
+ local buf_lang = vim.treesitter.language.get_lang(vim.bo[ctx.buf].filetype)
+ local ok, parser = pcall(vim.treesitter.get_string_parser, text, buf_lang)
+ if not ok then
+ callback("No treesitter parser for buffer")
+ return
+ end
+ ---@type conform.InjectedFormatterOptions
+ local options = self.options
+
+ ---@param lang string
+ ---@return nil|conform.FiletypeFormatter
+ local function get_formatters(lang)
+ return options.lang_to_formatters[lang] or conform.formatters_by_ft[lang]
+ end
+
+ --- Disable diagnostic to pass the typecheck github action
+ --- This is available on nightly, but not on stable
+ --- Stable doesn't have any parameters, so it's safe
+ ---@diagnostic disable-next-line: redundant-parameter
+ parser:parse(true)
+ local root_lang = parser:lang()
+ ---@type LangRange[]
+ local regions = {}
+
+ for lang, lang_tree in pairs(parser:children()) do
+ if lang ~= root_lang then
+ for _, ranges in ipairs(lang_tree:included_regions()) do
+ for _, region in ipairs(ranges) do
+ local formatters = get_formatters(lang)
+ if formatters ~= nil then
+ -- The types are wrong. included_regions should be Range[][] not integer[][]
+ ---@diagnostic disable-next-line: param-type-mismatch
+ local start_row, start_col, _, end_row, end_col, _ = unpack(region)
+ accum_range(regions, { lang, start_row + 1, start_col, end_row + 1, end_col })
+ end
+ end
+ end
+ end
+ end
+
+ if ctx.range then
+ regions = vim.tbl_filter(function(region)
+ return in_range(ctx.range, region[2], region[4])
+ end, regions)
+ end
+
+ -- Sort from largest start_lnum to smallest
+ table.sort(regions, function(a, b)
+ return a[2] > b[2]
+ end)
+ log.trace("Injected formatter regions %s", regions)
+
+ local replacements = {}
+ local format_error = nil
+
+ local function apply_format_results()
+ if format_error then
+ -- Find all of the conform errors in the replacements table and remove them
+ local i = 1
+ while i <= #replacements do
+ if replacements[i].code then
+ table.remove(replacements, i)
+ else
+ i = i + 1
+ end
+ end
+ if options.ignore_errors then
+ format_error = nil
+ end
+ end
+
+ local formatted_lines = vim.deepcopy(lines)
+ for _, replacement in ipairs(replacements) do
+ local start_lnum, start_col, end_lnum, end_col, new_lines = unpack(replacement)
+ local prefix = formatted_lines[start_lnum]:sub(1, start_col)
+ local suffix = formatted_lines[end_lnum]:sub(end_col + 1)
+ new_lines[1] = prefix .. new_lines[1]
+ new_lines[#new_lines] = new_lines[#new_lines] .. suffix
+ for _ = start_lnum, end_lnum do
+ table.remove(formatted_lines, start_lnum)
+ end
+ for i = #new_lines, 1, -1 do
+ table.insert(formatted_lines, start_lnum, new_lines[i])
+ end
+ end
+ callback(format_error, formatted_lines)
+ end
+
+ local num_format = 0
+ local tmp_bufs = {}
+ local formatter_cb = function(err, idx, region, input_lines, new_lines)
+ if err then
+ format_error = errors.coalesce(format_error, err)
+ replacements[idx] = err
+ else
+ -- If the original lines started/ended with a newline, preserve that newline.
+ -- Many formatters will trim them, but they're important for the document structure.
+ if input_lines[1] == "" and new_lines[1] ~= "" then
+ table.insert(new_lines, 1, "")
+ end
+ if input_lines[#input_lines] == "" and new_lines[#new_lines] ~= "" then
+ table.insert(new_lines, "")
+ end
+ replacements[idx] = { region[2], region[3], region[4], region[5], new_lines }
+ end
+ num_format = num_format - 1
+ if num_format == 0 then
+ for buf in pairs(tmp_bufs) do
+ vim.api.nvim_buf_delete(buf, { force = true })
+ end
+ apply_format_results()
+ end
+ end
+ local last_start_lnum = #lines + 1
+ for i, region in ipairs(regions) do
+ local lang = region[1]
+ local start_lnum = region[2]
+ local start_col = region[3]
+ local end_lnum = region[4]
+ local end_col = region[5]
+ -- Ignore regions that overlap (contain) other regions
+ if end_lnum < last_start_lnum then
+ num_format = num_format + 1
+ last_start_lnum = start_lnum
+ local input_lines = util.tbl_slice(lines, start_lnum, end_lnum)
+ input_lines[#input_lines] = input_lines[#input_lines]:sub(1, end_col)
+ if start_col > 0 then
+ input_lines[1] = input_lines[1]:sub(start_col + 1)
+ end
+ local ft_formatters = assert(get_formatters(lang))
+ ---@type string[]
+ local formatter_names
+ if type(ft_formatters) == "function" then
+ formatter_names = ft_formatters(ctx.buf)
+ else
+ local formatters = require("conform").resolve_formatters(ft_formatters, ctx.buf, false)
+ formatter_names = vim.tbl_map(function(f)
+ return f.name
+ end, formatters)
+ end
+ local idx = num_format
+ log.debug("Injected format %s:%d:%d: %s", lang, start_lnum, end_lnum, formatter_names)
+ log.trace("Injected format lines %s", input_lines)
+ local surrounding = remove_surrounding(input_lines, buf_lang)
+ -- Create a temporary buffer. This is only needed because some formatters rely on the file
+ -- extension to determine a run mode (see https://github.com/stevearc/conform.nvim/issues/194)
+ -- This is using lang_to_ext to map the language name to the file extension, and falls back
+ -- to using the language name itself.
+ local extension = options.lang_to_ext[lang] or lang
+ local buf =
+ vim.fn.bufadd(string.format("%s.%d.%s", vim.api.nvim_buf_get_name(ctx.buf), i, extension))
+ -- Actually load the buffer to set the buffer context which is required by some formatters such as `filetype`
+ vim.fn.bufload(buf)
+ tmp_bufs[buf] = true
+ local format_opts = { async = true, bufnr = buf, quiet = true }
+ conform.format_lines(formatter_names, input_lines, format_opts, function(err, new_lines)
+ log.trace("Injected %s:%d:%d formatted lines %s", lang, start_lnum, end_lnum, new_lines)
+ -- Preserve indentation in case the code block is indented
+ restore_surrounding(new_lines, surrounding)
+ vim.schedule_wrap(formatter_cb)(err, idx, region, input_lines, new_lines)
+ end)
+ end
+ end
+ if num_format == 0 then
+ apply_format_results()
+ end
+ end,
+ -- TODO this is kind of a hack. It's here to ensure all_support_range_formatting is set properly.
+ -- Should figure out a better way to do this.
+ range_args = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/inko.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/inko.lua
new file mode 100644
index 00000000..4c501d07
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/inko.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://inko-lang.org/",
+ description = "A language for building concurrent software with confidence",
+ },
+ command = "inko",
+ args = { "fmt", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/isort.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/isort.lua
new file mode 100644
index 00000000..72368736
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/isort.lua
@@ -0,0 +1,38 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/PyCQA/isort",
+ description = "Python utility / library to sort imports alphabetically and automatically separate them into sections and by type.",
+ },
+ command = "isort",
+ args = function(self, ctx)
+ -- isort doesn't do a good job of auto-detecting the line endings.
+ local line_ending
+ local file_format = vim.bo[ctx.buf].fileformat
+ if file_format == "dos" then
+ line_ending = "\r\n"
+ elseif file_format == "mac" then
+ line_ending = "\r"
+ else
+ line_ending = "\n"
+ end
+ return {
+ "--stdout",
+ "--line-ending",
+ line_ending,
+ "--filename",
+ "$FILENAME",
+ "-",
+ }
+ end,
+ cwd = util.root_file({
+ -- https://pycqa.github.io/isort/docs/configuration/config_files.html
+ ".isort.cfg",
+ "pyproject.toml",
+ "setup.py",
+ "setup.cfg",
+ "tox.ini",
+ ".editorconfig",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/joker.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/joker.lua
new file mode 100644
index 00000000..c87f4178
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/joker.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/candid82/joker",
+ description = "Small Clojure interpreter, linter and formatter.",
+ },
+ command = "joker",
+ args = { "--format", "--write", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/jq.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/jq.lua
new file mode 100644
index 00000000..061ed032
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/jq.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/stedolan/jq",
+ description = "Command-line JSON processor.",
+ },
+ command = "jq",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/jsonnetfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/jsonnetfmt.lua
new file mode 100644
index 00000000..edddbb9c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/jsonnetfmt.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/google/go-jsonnet/tree/master/cmd/jsonnetfmt",
+ description = "jsonnetfmt is a command line tool to format jsonnet files.",
+ },
+ command = "jsonnetfmt",
+ args = { "-" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/just.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/just.lua
new file mode 100644
index 00000000..d1664843
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/just.lua
@@ -0,0 +1,9 @@
+return {
+ meta = {
+ url = "https://github.com/casey/just",
+ description = "Format Justfile.",
+ },
+ command = "just",
+ args = { "--fmt", "--unstable", "-f", "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ktfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ktfmt.lua
new file mode 100644
index 00000000..7be580b7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ktfmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/facebook/ktfmt",
+ description = "Reformats Kotlin source code to comply with the common community standard conventions.",
+ },
+ command = "ktfmt",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ktlint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ktlint.lua
new file mode 100644
index 00000000..886157fa
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ktlint.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://ktlint.github.io/",
+ description = "An anti-bikeshedding Kotlin linter with built-in formatter.",
+ },
+ command = "ktlint",
+ args = { "--format", "--stdin", "--log-level=none" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/latexindent.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/latexindent.lua
new file mode 100644
index 00000000..64451e9d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/latexindent.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/cmhughes/latexindent.pl",
+ description = "A perl script for formatting LaTeX files that is generally included in major TeX distributions.",
+ },
+ command = "latexindent",
+ args = { "-" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/leptosfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/leptosfmt.lua
new file mode 100644
index 00000000..4fd2d982
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/leptosfmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/bram209/leptosfmt",
+ description = "A formatter for the Leptos view! macro.",
+ },
+ command = "leptosfmt",
+ args = { "--stdin" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/liquidsoap-prettier.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/liquidsoap-prettier.lua
new file mode 100644
index 00000000..e6ffb87e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/liquidsoap-prettier.lua
@@ -0,0 +1,11 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/savonet/liquidsoap-prettier",
+ description = "A binary to format Liquidsoap scripts",
+ },
+ command = util.from_node_modules("liquidsoap-prettier"),
+ args = { "-w", "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/markdown-toc.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/markdown-toc.lua
new file mode 100644
index 00000000..a7a96945
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/markdown-toc.lua
@@ -0,0 +1,15 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/jonschlinkert/markdown-toc",
+ description = "API and CLI for generating a markdown TOC (table of contents) for a README or any markdown files.",
+ },
+ command = "markdown-toc",
+ stdin = false,
+ args = function(self, ctx)
+ -- use the indentation set in the current buffer, effectively allowing us to
+ -- use values from .editorconfig
+ local indent = vim.bo[ctx.buf].expandtab and (" "):rep(vim.bo[ctx.buf].tabstop) or "\t"
+ return { "--indent=" .. indent, "-i", "$FILENAME" }
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/markdownlint-cli2.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/markdownlint-cli2.lua
new file mode 100644
index 00000000..b95c8cc9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/markdownlint-cli2.lua
@@ -0,0 +1,11 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/DavidAnson/markdownlint-cli2",
+ description = "A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the markdownlint library.",
+ },
+ command = "markdownlint-cli2",
+ args = { "--fix", "$FILENAME" },
+ exit_codes = { 0, 1 }, -- code 1 is returned when linting/formatter was successful and there were errors
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/markdownlint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/markdownlint.lua
new file mode 100644
index 00000000..40de29b5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/markdownlint.lua
@@ -0,0 +1,11 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/DavidAnson/markdownlint",
+ description = "A Node.js style checker and lint tool for Markdown/CommonMark files.",
+ },
+ command = "markdownlint",
+ args = { "--fix", "$FILENAME" },
+ exit_codes = { 0, 1 }, -- code 1 is given when trying a file that includes non-autofixable errors
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mdformat.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mdformat.lua
new file mode 100644
index 00000000..e291fafb
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mdformat.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/executablebooks/mdformat",
+ description = "An opinionated Markdown formatter.",
+ },
+ command = "mdformat",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mdsf.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mdsf.lua
new file mode 100644
index 00000000..98ceaefa
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mdsf.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/hougesen/mdsf",
+ description = "Format markdown code blocks using your favorite code formatters.",
+ },
+ command = "mdsf",
+ args = { "format", "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mdslw.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mdslw.lua
new file mode 100644
index 00000000..cab5347f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mdslw.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/razziel89/mdslw",
+ description = "Prepare your markdown for easy diff'ing by adding line breaks after every sentence.",
+ },
+ command = "mdslw",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mix.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mix.lua
new file mode 100644
index 00000000..970d0efd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/mix.lua
@@ -0,0 +1,13 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://hexdocs.pm/mix/main/Mix.Tasks.Format.html",
+ description = "Format Elixir files using the mix format command.",
+ },
+ command = "mix",
+ args = { "format", "--stdin-filename", "$FILENAME", "-" },
+ cwd = require("conform.util").root_file({
+ ".formatter.exs",
+ "mix.exs",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/nimpretty.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/nimpretty.lua
new file mode 100644
index 00000000..0cb5be2e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/nimpretty.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/nim-lang/nim",
+ description = "nimpretty is a Nim source code beautifier that follows the official style guide.",
+ },
+ command = "nimpretty",
+ args = { "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/nixfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/nixfmt.lua
new file mode 100644
index 00000000..27029d51
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/nixfmt.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/serokell/nixfmt",
+ description = "nixfmt is a formatter for Nix code, intended to apply a uniform style.",
+ },
+ command = "nixfmt",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/nixpkgs_fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/nixpkgs_fmt.lua
new file mode 100644
index 00000000..9ca6a8ad
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/nixpkgs_fmt.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/nix-community/nixpkgs-fmt",
+ description = "nixpkgs-fmt is a Nix code formatter for nixpkgs.",
+ },
+ command = "nixpkgs-fmt",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ocamlformat.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ocamlformat.lua
new file mode 100644
index 00000000..0305083d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ocamlformat.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/ocaml-ppx/ocamlformat",
+ description = "Auto-formatter for OCaml code.",
+ },
+ command = "ocamlformat",
+ args = { "--enable-outside-detected-project", "--name", "$FILENAME", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ocp-indent.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ocp-indent.lua
new file mode 100644
index 00000000..ca069b9c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ocp-indent.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/OCamlPro/ocp-indent",
+ description = "Automatic indentation of OCaml source files.",
+ },
+ command = "ocp-indent",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/opa_fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/opa_fmt.lua
new file mode 100644
index 00000000..b4f95dd1
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/opa_fmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://www.openpolicyagent.org/docs/latest/cli/#opa-fmt",
+ description = "Format Rego files using `opa fmt` command.",
+ },
+ command = "opa",
+ args = { "fmt" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ormolu.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ormolu.lua
new file mode 100644
index 00000000..4c36929a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ormolu.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://hackage.haskell.org/package/ormolu",
+ description = "A formatter for Haskell source code.",
+ },
+ command = "ormolu",
+ args = { "--stdin-input-file", "$FILENAME" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/packer_fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/packer_fmt.lua
new file mode 100644
index 00000000..572b5f48
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/packer_fmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://developer.hashicorp.com/packer/docs/commands/fmt",
+ description = "The packer fmt Packer command is used to format HCL2 configuration files to a canonical format and style.",
+ },
+ command = "packer",
+ args = { "fmt", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pangu.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pangu.lua
new file mode 100644
index 00000000..af10b8b9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pangu.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/vinta/pangu.py",
+ description = "Insert whitespace between CJK and half-width characters.",
+ },
+ command = "pangu",
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/perlimports.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/perlimports.lua
new file mode 100644
index 00000000..88405085
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/perlimports.lua
@@ -0,0 +1,13 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/perl-ide/App-perlimports",
+ description = "Make implicit Perl imports explicit.",
+ },
+ command = "perlimports",
+ args = {
+ "--read-stdin",
+ "--filename",
+ "$FILENAME",
+ },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/perltidy.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/perltidy.lua
new file mode 100644
index 00000000..5f6d857c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/perltidy.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/perltidy/perltidy",
+ description = "Perl::Tidy, a source code formatter for Perl.",
+ },
+ command = "perltidy",
+ args = { "--quiet" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pg_format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pg_format.lua
new file mode 100644
index 00000000..f0164546
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pg_format.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/darold/pgFormatter",
+ description = "PostgreSQL SQL syntax beautifier.",
+ },
+ command = "pg_format",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/php_cs_fixer.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/php_cs_fixer.lua
new file mode 100644
index 00000000..bff5a621
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/php_cs_fixer.lua
@@ -0,0 +1,16 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer",
+ description = "The PHP Coding Standards Fixer.",
+ },
+ command = util.find_executable({
+ "tools/php-cs-fixer/vendor/bin/php-cs-fixer",
+ "vendor/bin/php-cs-fixer",
+ }, "php-cs-fixer"),
+ args = { "fix", "$FILENAME" },
+ stdin = false,
+ cwd = util.root_file({ "composer.json" }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/phpcbf.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/phpcbf.lua
new file mode 100644
index 00000000..7f81b8b2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/phpcbf.lua
@@ -0,0 +1,21 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://phpqa.io/projects/phpcbf.html",
+ description = "PHP Code Beautifier and Fixer fixes violations of a defined coding standard.",
+ },
+ command = util.find_executable({
+ "vendor/bin/phpcbf",
+ }, "phpcbf"),
+ args = { "$FILENAME" },
+ stdin = false,
+ -- phpcbf ignores hidden files, so we have to override the default here
+ tmpfile_format = "conform.$RANDOM.$FILENAME",
+ -- 0: no errors found
+ -- 1: errors found
+ -- 2: fixable errors found
+ -- 3: processing error
+ exit_codes = { 0, 1, 2 },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/phpinsights.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/phpinsights.lua
new file mode 100644
index 00000000..c2575d18
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/phpinsights.lua
@@ -0,0 +1,17 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/nunomaduro/phpinsights",
+ description = "The perfect starting point to analyze the code quality of your PHP projects.",
+ },
+ command = util.find_executable({
+ "vendor/bin/phpinsights",
+ }, "phpinsights"),
+ args = { "fix", "$FILENAME", "--no-interaction", "--quiet" },
+ cwd = util.root_file({
+ "phpinsights.php",
+ }),
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pint.lua
new file mode 100644
index 00000000..e0bffb46
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pint.lua
@@ -0,0 +1,14 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/laravel/pint",
+ description = "Laravel Pint is an opinionated PHP code style fixer for minimalists.",
+ },
+ command = util.find_executable({
+ "vendor/bin/pint",
+ }, "pint"),
+ args = { "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/prettier.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/prettier.lua
new file mode 100644
index 00000000..a72f1308
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/prettier.lua
@@ -0,0 +1,79 @@
+local fs = require("conform.fs")
+local util = require("conform.util")
+
+--- Helper function to parse options to into a parser if available
+---@param self conform.JobFormatterConfig
+---@param ctx conform.Context|conform.RangeContext
+---@return string[]|nil args the arguments for setting a `prettier` parser if they exist in the options, nil otherwise
+local function eval_parser(self, ctx)
+ local ft = vim.bo[ctx.buf].filetype
+ local ext = vim.fn.fnamemodify(ctx.filename, ":e")
+ local options = self.options
+ local parser = options
+ and (
+ (options.ft_parsers and options.ft_parsers[ft])
+ or (options.ext_parsers and options.ext_parsers[ext])
+ )
+ if parser then
+ return { "--parser", parser }
+ end
+end
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/prettier/prettier",
+ description = [[Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.]],
+ },
+ options = {
+ -- Use a specific prettier parser for a filetype
+ -- Otherwise, prettier will try to infer the parser from the file name
+ ft_parsers = {
+ -- javascript = "babel",
+ -- javascriptreact = "babel",
+ -- typescript = "typescript",
+ -- typescriptreact = "typescript",
+ -- vue = "vue",
+ -- css = "css",
+ -- scss = "scss",
+ -- less = "less",
+ -- html = "html",
+ -- json = "json",
+ -- jsonc = "json",
+ -- yaml = "yaml",
+ -- markdown = "markdown",
+ -- ["markdown.mdx"] = "mdx",
+ -- graphql = "graphql",
+ -- handlebars = "glimmer",
+ },
+ -- Use a specific prettier parser for a file extension
+ ext_parsers = {
+ -- qmd = "markdown",
+ },
+ },
+ command = util.from_node_modules(fs.is_windows and "prettier.cmd" or "prettier"),
+ args = function(self, ctx)
+ return eval_parser(self, ctx) or { "--stdin-filepath", "$FILENAME" }
+ end,
+ range_args = function(self, ctx)
+ local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
+ local args = eval_parser(self, ctx) or { "--stdin-filepath", "$FILENAME" }
+ return vim.list_extend(args, { "--range-start=" .. start_offset, "--range-end=" .. end_offset })
+ end,
+ cwd = util.root_file({
+ -- https://prettier.io/docs/en/configuration.html
+ ".prettierrc",
+ ".prettierrc.json",
+ ".prettierrc.yml",
+ ".prettierrc.yaml",
+ ".prettierrc.json5",
+ ".prettierrc.js",
+ ".prettierrc.cjs",
+ ".prettierrc.mjs",
+ ".prettierrc.toml",
+ "prettier.config.js",
+ "prettier.config.cjs",
+ "prettier.config.mjs",
+ "package.json",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/prettierd.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/prettierd.lua
new file mode 100644
index 00000000..2dcd4977
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/prettierd.lua
@@ -0,0 +1,31 @@
+local fs = require("conform.fs")
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/fsouza/prettierd",
+ description = "prettier, as a daemon, for ludicrous formatting speed.",
+ },
+ command = util.from_node_modules(fs.is_windows and "prettierd.cmd" or "prettierd"),
+ args = { "$FILENAME" },
+ range_args = function(self, ctx)
+ local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
+ return { "$FILENAME", "--range-start=" .. start_offset, "--range-end=" .. end_offset }
+ end,
+ cwd = util.root_file({
+ -- https://prettier.io/docs/en/configuration.html
+ ".prettierrc",
+ ".prettierrc.json",
+ ".prettierrc.yml",
+ ".prettierrc.yaml",
+ ".prettierrc.json5",
+ ".prettierrc.js",
+ ".prettierrc.cjs",
+ ".prettierrc.mjs",
+ ".prettierrc.toml",
+ "prettier.config.js",
+ "prettier.config.cjs",
+ "prettier.config.mjs",
+ "package.json",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pretty-php.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pretty-php.lua
new file mode 100644
index 00000000..270a8d65
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/pretty-php.lua
@@ -0,0 +1,14 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/lkrms/pretty-php",
+ description = "The opinionated PHP code formatter.",
+ },
+ command = util.find_executable({
+ "vendor/bin/pretty-php",
+ }, "pretty-php"),
+ args = { "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/puppet-lint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/puppet-lint.lua
new file mode 100644
index 00000000..6cc231e9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/puppet-lint.lua
@@ -0,0 +1,11 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/puppetlabs/puppet-lint",
+ description = "Check that your Puppet manifests conform to the style guide.",
+ },
+ command = "puppet-lint",
+ args = { "--fix", "$FILENAME" },
+ stdin = false,
+ exit_codes = { 0, 1 },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/purs-tidy.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/purs-tidy.lua
new file mode 100644
index 00000000..a89ed07f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/purs-tidy.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/natefaubion/purescript-tidy",
+ description = "A syntax tidy-upper for PureScript.",
+ },
+ command = "purs-tidy",
+ args = { "format" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/reorder-python-imports.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/reorder-python-imports.lua
new file mode 100644
index 00000000..e8d1c754
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/reorder-python-imports.lua
@@ -0,0 +1,10 @@
+--@type conform.FileFormatterConfig-
+return {
+ meta = {
+ url = "https://github.com/asottile/reorder-python-imports",
+ description = "Rewrites source to reorder python imports",
+ },
+ command = "reorder-python-imports",
+ args = { "--exit-zero-even-if-changed", "-" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rescript-format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rescript-format.lua
new file mode 100644
index 00000000..806b3805
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rescript-format.lua
@@ -0,0 +1,40 @@
+-- The formatter expects one of [.res | .resi | .ml | .mli] passed as
+-- the value to the '-stdin' argument.
+local valid_extensions = {
+ res = true,
+ resi = true,
+ ml = true,
+ mli = true,
+}
+
+local default_extension = "res"
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://rescript-lang.org/",
+ description = "The built-in ReScript formatter.",
+ },
+ command = "rescript",
+ args = function(self, ctx)
+ local extension = vim.fn.fnamemodify(ctx.filename, ":e")
+
+ local is_invalid_extension = valid_extensions[extension] == nil
+ if is_invalid_extension then
+ extension = default_extension
+ end
+
+ return {
+ "format",
+ "-stdin",
+ "." .. extension,
+ }
+ end,
+ stdin = true,
+
+ require_cwd = true,
+ cwd = require("conform.util").root_file({
+ "rescript.json",
+ "bsconfig.json",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/roc.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/roc.lua
new file mode 100644
index 00000000..49fe6194
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/roc.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/roc-lang/roc",
+ description = "A fast, friendly, functional language.",
+ },
+ command = "roc",
+ args = { "format", "--stdin", "--stdout" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rubocop.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rubocop.lua
new file mode 100644
index 00000000..c8e027c3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rubocop.lua
@@ -0,0 +1,18 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/rubocop/rubocop",
+ description = "Ruby static code analyzer and formatter, based on the community Ruby style guide.",
+ },
+ command = "rubocop",
+ args = {
+ "--server",
+ "-a",
+ "-f",
+ "quiet",
+ "--stderr",
+ "--stdin",
+ "$FILENAME",
+ },
+ exit_codes = { 0, 1 },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rubyfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rubyfmt.lua
new file mode 100644
index 00000000..9c513db3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rubyfmt.lua
@@ -0,0 +1,7 @@
+return {
+ meta = {
+ url = "https://github.com/fables-tales/rubyfmt",
+ description = "Ruby Autoformatter! (Written in Rust)",
+ },
+ command = "rubyfmt",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff.lua
new file mode 100644
index 00000000..9a1d780b
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff.lua
@@ -0,0 +1,4 @@
+-- This was renamed to ruff_fix
+local conf = vim.deepcopy(require("conform.formatters.ruff_fix"))
+conf.meta.deprecated = true
+return conf
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff_fix.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff_fix.lua
new file mode 100644
index 00000000..ecf3ed7e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff_fix.lua
@@ -0,0 +1,24 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://docs.astral.sh/ruff/",
+ description = "An extremely fast Python linter, written in Rust. Fix lint errors.",
+ },
+ command = "ruff",
+ args = {
+ "check",
+ "--fix",
+ "--force-exclude",
+ "--exit-zero",
+ "--no-cache",
+ "--stdin-filename",
+ "$FILENAME",
+ "-",
+ },
+ stdin = true,
+ cwd = require("conform.util").root_file({
+ "pyproject.toml",
+ "ruff.toml",
+ ".ruff.toml",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff_format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff_format.lua
new file mode 100644
index 00000000..20a2e952
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff_format.lua
@@ -0,0 +1,21 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://docs.astral.sh/ruff/",
+ description = "An extremely fast Python linter, written in Rust. Formatter subcommand.",
+ },
+ command = "ruff",
+ args = {
+ "format",
+ "--force-exclude",
+ "--stdin-filename",
+ "$FILENAME",
+ "-",
+ },
+ stdin = true,
+ cwd = require("conform.util").root_file({
+ "pyproject.toml",
+ "ruff.toml",
+ ".ruff.toml",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff_organize_imports.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff_organize_imports.lua
new file mode 100644
index 00000000..03ab8421
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/ruff_organize_imports.lua
@@ -0,0 +1,25 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://docs.astral.sh/ruff/",
+ description = "An extremely fast Python linter, written in Rust. Organize imports.",
+ },
+ command = "ruff",
+ args = {
+ "check",
+ "--fix",
+ "--force-exclude",
+ "--select=I001",
+ "--exit-zero",
+ "--no-cache",
+ "--stdin-filename",
+ "$FILENAME",
+ "-",
+ },
+ stdin = true,
+ cwd = require("conform.util").root_file({
+ "pyproject.toml",
+ "ruff.toml",
+ ".ruff.toml",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rufo.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rufo.lua
new file mode 100644
index 00000000..11eb20df
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rufo.lua
@@ -0,0 +1,8 @@
+return {
+ meta = {
+ url = "https://github.com/ruby-formatter/rufo",
+ description = "Rufo is an opinionated ruby formatter.",
+ },
+ command = "rufo",
+ exit_codes = { 0, 3 },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rustfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rustfmt.lua
new file mode 100644
index 00000000..e33fb862
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rustfmt.lua
@@ -0,0 +1,21 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/rust-lang/rustfmt",
+ description = "A tool for formatting rust code according to style guidelines.",
+ },
+ command = "rustfmt",
+ options = {
+ -- The default edition of Rust to use when no Cargo.toml file is found
+ default_edition = "2021",
+ },
+ args = function(self, ctx)
+ local args = { "--emit=stdout" }
+ local edition = util.parse_rust_edition(ctx.dirname) or self.options.default_edition
+ table.insert(args, "--edition=" .. edition)
+
+ return args
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rustywind.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rustywind.lua
new file mode 100644
index 00000000..d905212a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/rustywind.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/avencera/rustywind",
+ description = "A tool for formatting Tailwind CSS classes.",
+ },
+ command = "rustywind",
+ args = { "--stdin" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/scalafmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/scalafmt.lua
new file mode 100644
index 00000000..ea82624d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/scalafmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/scalameta/scalafmt",
+ description = "Code formatter for Scala.",
+ },
+ command = "scalafmt",
+ args = { "--stdin" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/shellcheck.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/shellcheck.lua
new file mode 100644
index 00000000..f478d52f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/shellcheck.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/koalaman/shellcheck",
+ description = "A static analysis tool for shell scripts.",
+ },
+ command = "shellcheck",
+ args = "'$FILENAME' --format=diff | patch -p1 '$FILENAME'",
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/shellharden.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/shellharden.lua
new file mode 100644
index 00000000..c775072c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/shellharden.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/anordal/shellharden",
+ description = "The corrective bash syntax highlighter.",
+ },
+ command = "shellharden",
+ args = { "--transform", "" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/shfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/shfmt.lua
new file mode 100644
index 00000000..29b8615e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/shfmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/mvdan/sh",
+ description = "A shell parser, formatter, and interpreter with `bash` support.",
+ },
+ command = "shfmt",
+ args = { "-filename", "$FILENAME" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/smlfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/smlfmt.lua
new file mode 100644
index 00000000..babd8f06
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/smlfmt.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/shwestrick/smlfmt",
+ description = "A custom parser and code formatter for Standard ML.",
+ },
+ command = "smlfmt",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/snakefmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/snakefmt.lua
new file mode 100644
index 00000000..fccdeaa5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/snakefmt.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/snakemake/snakefmt",
+ description = "a formatting tool for Snakemake files following the design of Black.",
+ },
+ command = "snakefmt",
+ args = "$FILENAME",
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/sql_formatter.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/sql_formatter.lua
new file mode 100644
index 00000000..9452a61c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/sql_formatter.lua
@@ -0,0 +1,8 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/sql-formatter-org/sql-formatter",
+ description = "A whitespace formatter for different query languages.",
+ },
+ command = "sql-formatter",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/sqlfluff.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/sqlfluff.lua
new file mode 100644
index 00000000..23441c20
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/sqlfluff.lua
@@ -0,0 +1,20 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/sqlfluff/sqlfluff",
+ description = "A modular SQL linter and auto-formatter with support for multiple dialects and templated code.",
+ },
+ command = "sqlfluff",
+ args = { "fix", "--dialect=ansi", "-" },
+ stdin = true,
+ cwd = util.root_file({
+ ".sqlfluff",
+ "pep8.ini",
+ "pyproject.toml",
+ "setup.cfg",
+ "tox.ini",
+ }),
+ require_cwd = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/sqlfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/sqlfmt.lua
new file mode 100644
index 00000000..83bcad39
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/sqlfmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://docs.sqlfmt.com",
+ description = "sqlfmt formats your dbt SQL files so you don't have to. It is similar in nature to Black, gofmt, and rustfmt (but for SQL)",
+ },
+ command = "sqlfmt",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/squeeze_blanks.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/squeeze_blanks.lua
new file mode 100644
index 00000000..591d5427
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/squeeze_blanks.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html#cat-invocation",
+ description = "Squeeze repeated blank lines into a single blank line via `cat -s`.",
+ },
+ command = "cat",
+ args = { "-s" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/standardjs.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/standardjs.lua
new file mode 100644
index 00000000..365e738c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/standardjs.lua
@@ -0,0 +1,11 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://standardjs.com",
+ description = "JavaScript Standard style guide, linter, and formatter.",
+ },
+ command = util.from_node_modules("standard"),
+ args = { "--fix", "--stdin" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/standardrb.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/standardrb.lua
new file mode 100644
index 00000000..ae860ea2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/standardrb.lua
@@ -0,0 +1,17 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/standardrb/standard",
+ description = "Ruby's bikeshed-proof linter and formatter.",
+ },
+ command = "standardrb",
+ args = {
+ "--fix",
+ "-f",
+ "quiet",
+ "--stderr",
+ "--stdin",
+ "$FILENAME",
+ },
+ exit_codes = { 0, 1 },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/stylelint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/stylelint.lua
new file mode 100644
index 00000000..e102d84c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/stylelint.lua
@@ -0,0 +1,11 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/stylelint/stylelint",
+ description = "A mighty CSS linter that helps you avoid errors and enforce conventions.",
+ },
+ command = "stylelint",
+ args = { "--stdin", "--fix" },
+ exit_codes = { 0, 2 }, -- code 2 is given when trying file includees some non-autofixable errors
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/styler.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/styler.lua
new file mode 100644
index 00000000..d9052c1f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/styler.lua
@@ -0,0 +1,11 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/devOpifex/r.nvim",
+ description = "R formatter and linter.",
+ },
+ command = util.find_executable({ "usr/bin/" }, "R"),
+ args = { "-s", "-e", "r.nvim::format()", "--args", "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/stylua.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/stylua.lua
new file mode 100644
index 00000000..25012bfc
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/stylua.lua
@@ -0,0 +1,27 @@
+local util = require("conform.util")
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/JohnnyMorganz/StyLua",
+ description = "An opinionated code formatter for Lua.",
+ },
+ command = "stylua",
+ args = { "--search-parent-directories", "--stdin-filepath", "$FILENAME", "-" },
+ range_args = function(self, ctx)
+ local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
+ return {
+ "--search-parent-directories",
+ "--stdin-filepath",
+ "$FILENAME",
+ "--range-start",
+ tostring(start_offset),
+ "--range-end",
+ tostring(end_offset),
+ "-",
+ }
+ end,
+ cwd = util.root_file({
+ ".stylua.toml",
+ "stylua.toml",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/swift_format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/swift_format.lua
new file mode 100644
index 00000000..1473c194
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/swift_format.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/apple/swift-format",
+ description = "Swift formatter from apple. Requires building from source with `swift build`.",
+ },
+ command = "swift-format",
+ args = { "$FILENAME", "--in-place" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/swiftformat.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/swiftformat.lua
new file mode 100644
index 00000000..adde245e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/swiftformat.lua
@@ -0,0 +1,20 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/nicklockwood/SwiftFormat",
+ description = "SwiftFormat is a code library and command-line tool for reformatting `swift` code on macOS or Linux.",
+ },
+ command = "swiftformat",
+ stdin = true,
+ args = { "--stdinpath", "$FILENAME" },
+ range_args = function(self, ctx)
+ local startOffset = tonumber(ctx.range.start[1]) - 1
+ local endOffset = tonumber(ctx.range["end"][1]) - 1
+
+ return {
+ "--linerange",
+ startOffset .. "," .. endOffset,
+ }
+ end,
+ cwd = require("conform.util").root_file({ ".swiftformat", "Package.swift", "buildServer.json" }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/taplo.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/taplo.lua
new file mode 100644
index 00000000..fb2d67ac
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/taplo.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/tamasfe/taplo",
+ description = "A TOML toolkit written in Rust.",
+ },
+ command = "taplo",
+ args = { "format", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/templ.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/templ.lua
new file mode 100644
index 00000000..74c6f7a5
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/templ.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://templ.guide/commands-and-tools/cli/#formatting-templ-files",
+ description = "Formats templ template files.",
+ },
+ command = "templ",
+ args = { "fmt" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/terraform_fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/terraform_fmt.lua
new file mode 100644
index 00000000..4bfd2f50
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/terraform_fmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://www.terraform.io/docs/cli/commands/fmt.html",
+ description = "The terraform-fmt command rewrites `terraform` configuration files to a canonical format and style.",
+ },
+ command = "terraform",
+ args = { "fmt", "-no-color", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/terragrunt_hclfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/terragrunt_hclfmt.lua
new file mode 100644
index 00000000..71807466
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/terragrunt_hclfmt.lua
@@ -0,0 +1,13 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://terragrunt.gruntwork.io/docs/reference/cli-options/#hclfmt",
+ description = "Format hcl files into a canonical format.",
+ },
+ command = "terragrunt",
+ args = { "hclfmt", "--terragrunt-hclfmt-file", "$FILENAME" },
+ stdin = false,
+ condition = function(self, ctx)
+ return vim.fs.basename(ctx.filename) ~= "terragrunt.hcl"
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/tlint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/tlint.lua
new file mode 100644
index 00000000..b1f34e6f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/tlint.lua
@@ -0,0 +1,14 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/tighten/tlint",
+ description = "Tighten linter for Laravel conventions with support for auto-formatting.",
+ },
+ command = util.find_executable({
+ "vendor/bin/tlint",
+ }, "tlint"),
+ args = { "format", "$FILENAME" },
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/tofu_fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/tofu_fmt.lua
new file mode 100644
index 00000000..00a21082
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/tofu_fmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://opentofu.org/docs/cli/commands/fmt/",
+ description = "The tofu-fmt command rewrites OpenTofu configuration files to a canonical format and style.",
+ },
+ command = "tofu",
+ args = { "fmt", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/trim_newlines.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/trim_newlines.lua
new file mode 100644
index 00000000..434f35bf
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/trim_newlines.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://www.gnu.org/software/gawk/manual/gawk.html",
+ description = "Trim new lines with awk.",
+ },
+ command = "awk",
+ args = { 'NF{print s $0; s=""; next} {s=s ORS}' },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/trim_whitespace.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/trim_whitespace.lua
new file mode 100644
index 00000000..3bbd89ea
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/trim_whitespace.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://www.gnu.org/software/gawk/manual/gawk.html",
+ description = "Trim whitespaces with awk.",
+ },
+ command = "awk",
+ args = { '{ sub(/[ \t]+$/, ""); print }' },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/twig-cs-fixer.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/twig-cs-fixer.lua
new file mode 100644
index 00000000..b248e6cb
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/twig-cs-fixer.lua
@@ -0,0 +1,20 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/VincentLanglet/Twig-CS-Fixer",
+ description = "Automatically fix Twig Coding Standards issues",
+ },
+ command = util.find_executable({
+ "vendor/bin/twig-cs-fixer",
+ }, "twig-cs-fixer"),
+ args = { "lint", "$FILENAME", "--fix", "--no-interaction", "--quiet" },
+ cwd = util.root_file({
+ ".twig-cs-fixer.php",
+ ".twig-cs-fixer.dist.php",
+ "composer.json",
+ }),
+ require_cwd = false,
+ stdin = false,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/typos.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/typos.lua
new file mode 100644
index 00000000..c5716295
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/typos.lua
@@ -0,0 +1,17 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/crate-ci/typos",
+ description = "Source code spell checker",
+ },
+ command = "typos",
+ -- cannot use stdin, as otherwise `typos` has no information on the filename,
+ -- making excluded-file-configs ineffective
+ stdin = false,
+ args = {
+ "--write-changes",
+ "--force-exclude", -- so excluded files in the config take effect
+ "$FILENAME",
+ },
+ exit_codes = { 0, 2 },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/typstfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/typstfmt.lua
new file mode 100644
index 00000000..e5d0e5fd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/typstfmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/astrale-sharp/typstfmt",
+ description = "Basic formatter for the Typst language with a future!",
+ },
+ command = "typstfmt",
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/typstyle.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/typstyle.lua
new file mode 100644
index 00000000..eaae7b04
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/typstyle.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/Enter-tainer/typstyle",
+ description = "Beautiful and reliable typst code formatter.",
+ },
+ command = "typstyle",
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/uncrustify.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/uncrustify.lua
new file mode 100644
index 00000000..aec93c26
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/uncrustify.lua
@@ -0,0 +1,11 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/uncrustify/uncrustify",
+ description = "A source code beautifier for C, C++, C#, ObjectiveC, D, Java, Pawn and Vala.",
+ },
+ command = "uncrustify",
+ args = function(self, ctx)
+ return { "-q", "-l", vim.bo[ctx.buf].filetype:upper() }
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/usort.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/usort.lua
new file mode 100644
index 00000000..f2a141ab
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/usort.lua
@@ -0,0 +1,15 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/facebook/usort",
+ description = "Safe, minimal import sorting for Python projects.",
+ },
+ command = "usort",
+ args = { "format", "-" },
+ stdin = true,
+ cwd = util.root_file({
+ "pyproject.toml",
+ }),
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/verible.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/verible.lua
new file mode 100644
index 00000000..6a58d76f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/verible.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/chipsalliance/verible/blob/master/verilog/tools/formatter/README.md",
+ description = "The SystemVerilog formatter.",
+ },
+ command = "verible-verilog-format",
+ args = { "--stdin_name", "$FILENAME", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/xmlformat.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/xmlformat.lua
new file mode 100644
index 00000000..d04c9cce
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/xmlformat.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/pamoller/xmlformatter",
+ description = "xmlformatter is an Open Source Python package, which provides formatting of XML documents.",
+ },
+ command = "xmlformat",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/xmllint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/xmllint.lua
new file mode 100644
index 00000000..3e06400f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/xmllint.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "http://xmlsoft.org/xmllint.html",
+ description = "Despite the name, xmllint can be used to format XML files as well as lint them.",
+ },
+ command = "xmllint",
+ args = { "--format", "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yamlfix.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yamlfix.lua
new file mode 100644
index 00000000..75923400
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yamlfix.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/lyz-code/yamlfix",
+ description = "A configurable YAML formatter that keeps comments.",
+ },
+ command = "yamlfix",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yamlfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yamlfmt.lua
new file mode 100644
index 00000000..8f188ab7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yamlfmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/google/yamlfmt",
+ description = "yamlfmt is an extensible command line tool or library to format yaml files.",
+ },
+ command = "yamlfmt",
+ args = { "-" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yapf.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yapf.lua
new file mode 100644
index 00000000..63bff837
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yapf.lua
@@ -0,0 +1,12 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/google/yapf",
+ description = "Yet Another Python Formatter.",
+ },
+ command = "yapf",
+ args = { "--quiet" },
+ range_args = function(self, ctx)
+ return { "--quiet", "--lines", string.format("%d-%d", ctx.range.start[1], ctx.range["end"][1]) }
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yew-fmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yew-fmt.lua
new file mode 100644
index 00000000..f441fdff
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yew-fmt.lua
@@ -0,0 +1,21 @@
+local util = require("conform.util")
+
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/schvv31n/yew-fmt",
+ description = "Code formatter for the Yew framework.",
+ },
+ command = "yew-fmt",
+ options = {
+ -- The default edition of Rust to use when no Cargo.toml file is found
+ default_edition = "2021",
+ },
+ args = function(self, ctx)
+ local args = { "--emit=stdout" }
+ local edition = util.parse_rust_edition(ctx.dirname) or self.options.default_edition
+ table.insert(args, "--edition=" .. edition)
+
+ return args
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yq.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yq.lua
new file mode 100644
index 00000000..29cf9b46
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/yq.lua
@@ -0,0 +1,10 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/mikefarah/yq",
+ description = "YAML/JSON processor",
+ },
+ command = "yq",
+ args = { "-P", "-" },
+ stdin = true,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/zigfmt.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/zigfmt.lua
new file mode 100644
index 00000000..8097d9c3
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/zigfmt.lua
@@ -0,0 +1,9 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/ziglang/zig",
+ description = "Reformat Zig source into canonical form.",
+ },
+ command = "zig",
+ args = { "fmt", "--stdin" },
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/zprint.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/zprint.lua
new file mode 100644
index 00000000..240b7ed0
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/formatters/zprint.lua
@@ -0,0 +1,17 @@
+---@type conform.FileFormatterConfig
+return {
+ meta = {
+ url = "https://github.com/kkinnear/zprint",
+ description = "Formatter for Clojure and EDN.",
+ },
+ command = "zprint",
+ range_args = function(self, ctx)
+ return {
+ string.format(
+ "{:input {:range {:start %d :end %d :use-previous-!zprint? true :continue-after-!zprint-error? true}}}",
+ ctx.range.start[1] - 1,
+ ctx.range["end"][1] - 1
+ ),
+ }
+ end,
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/fs.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/fs.lua
new file mode 100644
index 00000000..d3b5fed9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/fs.lua
@@ -0,0 +1,94 @@
+local M = {}
+
+local uv = vim.uv or vim.loop
+
+---@type boolean
+M.is_windows = uv.os_uname().version:match("Windows")
+
+M.is_mac = uv.os_uname().sysname == "Darwin"
+
+---@type string
+M.sep = M.is_windows and "\\" or "/"
+
+---@param ... string
+M.join = function(...)
+ return table.concat({ ... }, M.sep)
+end
+
+M.is_absolute = function(path)
+ if M.is_windows then
+ return path:lower():match("^%a:")
+ else
+ return vim.startswith(path, "/")
+ end
+end
+
+M.abspath = function(path)
+ if not M.is_absolute(path) then
+ path = vim.fn.fnamemodify(path, ":p")
+ end
+ return path
+end
+
+---Returns true if candidate is a subpath of root, or if they are the same path.
+---@param root string
+---@param candidate string
+---@return boolean
+M.is_subpath = function(root, candidate)
+ if candidate == "" then
+ return false
+ end
+ root = vim.fs.normalize(M.abspath(root))
+ -- Trim trailing "/" from the root
+ if root:find("/", -1) then
+ root = root:sub(1, -2)
+ end
+ candidate = vim.fs.normalize(M.abspath(candidate))
+ if M.is_windows then
+ root = root:lower()
+ candidate = candidate:lower()
+ end
+ if root == candidate then
+ return true
+ end
+ local prefix = candidate:sub(1, root:len())
+ if prefix ~= root then
+ return false
+ end
+
+ local candidate_starts_with_sep = candidate:find("/", root:len() + 1, true) == root:len() + 1
+ local root_ends_with_sep = root:find("/", root:len(), true) == root:len()
+
+ return candidate_starts_with_sep or root_ends_with_sep
+end
+
+---Create a relative path from the source to the target
+---@param source string
+---@param target string
+---@return string
+M.relative_path = function(source, target)
+ source = M.abspath(source)
+ target = M.abspath(target)
+ local path = {}
+ while not M.is_subpath(source, target) do
+ table.insert(path, "..")
+ local new_source = vim.fs.dirname(source)
+
+ -- If source is a root directory, we can't go up further so there is no relative path to the
+ -- target. This should only happen on Windows, which prohibits relative paths between drives.
+ if source == new_source then
+ local log = require("conform.log")
+ log.warn("Could not find relative path from %s to %s", source, target)
+ return target
+ end
+
+ source = new_source
+ end
+
+ local offset = vim.endswith(source, M.sep) and 1 or 2
+ local rel_target = target:sub(source:len() + offset)
+ table.insert(path, rel_target)
+ return M.join(unpack(path))
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/health.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/health.lua
new file mode 100644
index 00000000..3ee75677
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/health.lua
@@ -0,0 +1,210 @@
+local M = {}
+
+---@diagnostic disable: deprecated
+-- The "report_" functions have been deprecated, so use the new ones if defined.
+local health_start = vim.health.start or vim.health.report_start
+local health_warn = vim.health.warn or vim.health.report_warn
+local health_info = vim.health.info or vim.health.report_info
+local health_ok = vim.health.ok or vim.health.report_ok
+local islist = vim.islist or vim.tbl_islist
+
+---@param name string
+---@return string[]
+local function get_formatter_filetypes(name)
+ local conform = require("conform")
+ local filetypes = {}
+ for filetype, formatters in pairs(conform.formatters_by_ft) do
+ if type(formatters) == "function" then
+ formatters = formatters(0)
+ -- support the old structure where formatters could be a subkey
+ elseif not islist(formatters) then
+ vim.notify_once(
+ "Using deprecated structure for formatters_by_ft. See :help conform-options for details.",
+ vim.log.levels.ERROR
+ )
+ ---@diagnostic disable-next-line: undefined-field
+ formatters = formatters.formatters
+ end
+
+ for _, ft_name in ipairs(formatters) do
+ if type(ft_name) == "string" then
+ if ft_name == name then
+ table.insert(filetypes, filetype)
+ break
+ end
+ else
+ if vim.tbl_contains(ft_name, name) then
+ table.insert(filetypes, filetype)
+ break
+ end
+ end
+ end
+ end
+ return filetypes
+end
+
+M.check = function()
+ local conform = require("conform")
+ health_start("conform.nvim report")
+
+ local log = require("conform.log")
+ health_info(string.format("Log file: %s", log.get_logfile()))
+
+ local all_formatters = conform.list_all_formatters()
+ for _, formatter in ipairs(all_formatters) do
+ if not formatter.available then
+ health_warn(string.format("%s unavailable: %s", formatter.name, formatter.available_msg))
+ else
+ local filetypes = get_formatter_filetypes(formatter.name)
+ health_ok(string.format("%s ready (%s)", formatter.name, table.concat(filetypes, ", ")))
+ end
+ end
+end
+
+---@param formatters conform.FormatterUnit[]
+---@return string[]
+local function flatten_formatters(formatters)
+ local flat = {}
+ for _, name in ipairs(formatters) do
+ if type(name) == "string" then
+ table.insert(flat, name)
+ else
+ for _, f in ipairs(flatten_formatters(name)) do
+ table.insert(flat, f)
+ end
+ end
+ end
+ return flat
+end
+
+M.show_window = function()
+ local conform = require("conform")
+ local log = require("conform.log")
+ local lsp_format = require("conform.lsp_format")
+ local lines = {}
+ local highlights = {}
+ local logfile = log.get_logfile()
+ table.insert(lines, string.format("Log file: %s", logfile))
+ table.insert(highlights, { "Title", #lines, 0, 10 })
+ if vim.fn.filereadable(logfile) == 1 then
+ local f = io.open(logfile, "r")
+ if f then
+ local context = -1024
+ -- Show more logs if the log level is set to trace.
+ if log.level == vim.log.levels.TRACE then
+ context = 3 * context
+ end
+ f:seek("end", context)
+ local text = f:read("*a")
+ f:close()
+ local log_lines = vim.split(text, "\r?\n", { trimempty = true })
+ for i = 2, #log_lines do
+ table.insert(lines, string.rep(" ", 10) .. log_lines[i])
+ end
+ end
+ end
+ table.insert(lines, "")
+
+ ---@param formatter conform.FormatterInfo
+ local function append_formatter_info(formatter)
+ if not formatter.available then
+ local line = string.format("%s unavailable: %s", formatter.name, formatter.available_msg)
+ table.insert(lines, line)
+ table.insert(
+ highlights,
+ { "DiagnosticWarn", #lines, formatter.name:len(), formatter.name:len() + 12 }
+ )
+ else
+ local filetypes = get_formatter_filetypes(formatter.name)
+ local filetypes_list = table.concat(filetypes, ", ")
+ local path = vim.fn.exepath(formatter.command)
+ local line = string.format("%s ready (%s) %s", formatter.name, filetypes_list, path)
+ table.insert(lines, line)
+ table.insert(
+ highlights,
+ { "DiagnosticInfo", #lines, formatter.name:len(), formatter.name:len() + 6 }
+ )
+ table.insert(highlights, {
+ "DiagnosticInfo",
+ #lines,
+ formatter.name:len() + 7 + filetypes_list:len() + 3,
+ line:len(),
+ })
+ end
+ end
+
+ local seen = {}
+ ---@param formatters string[]
+ local function append_formatters(formatters)
+ for _, name in ipairs(formatters) do
+ if type(name) == "table" then
+ append_formatters(name)
+ else
+ seen[name] = true
+ local formatter = conform.get_formatter_info(name)
+ append_formatter_info(formatter)
+ end
+ end
+ end
+
+ table.insert(lines, "Formatters for this buffer:")
+ table.insert(highlights, { "Title", #lines, 0, -1 })
+ local lsp_clients = lsp_format.get_format_clients({ bufnr = vim.api.nvim_get_current_buf() })
+ local has_lsp_formatter = not vim.tbl_isempty(lsp_clients)
+ if has_lsp_formatter then
+ table.insert(lines, "LSP: " .. table.concat(
+ vim.tbl_map(function(c)
+ return c.name
+ end, lsp_clients),
+ ", "
+ ))
+ end
+ local buf_formatters = flatten_formatters(conform.list_formatters_for_buffer())
+ append_formatters(buf_formatters)
+ if vim.tbl_isempty(buf_formatters) and not has_lsp_formatter then
+ table.insert(lines, "")
+ end
+
+ table.insert(lines, "")
+ table.insert(lines, "Other formatters:")
+ table.insert(highlights, { "Title", #lines, 0, -1 })
+ for _, formatter in ipairs(conform.list_all_formatters()) do
+ if not seen[formatter.name] then
+ append_formatter_info(formatter)
+ end
+ end
+
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ local winid = vim.api.nvim_open_win(bufnr, true, {
+ relative = "editor",
+ border = "rounded",
+ width = vim.o.columns - 6,
+ height = vim.o.lines - 6,
+ col = 2,
+ row = 2,
+ style = "minimal",
+ })
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, lines)
+ vim.bo[bufnr].modifiable = false
+ vim.bo[bufnr].modified = false
+ vim.bo[bufnr].bufhidden = "wipe"
+ vim.keymap.set("n", "q", "close", { buffer = bufnr, nowait = true })
+ vim.keymap.set("n", "", "close", { buffer = bufnr })
+ vim.api.nvim_create_autocmd("BufLeave", {
+ desc = "Close info window when leaving buffer",
+ buffer = bufnr,
+ once = true,
+ nested = true,
+ callback = function()
+ if vim.api.nvim_win_is_valid(winid) then
+ vim.api.nvim_win_close(winid, true)
+ end
+ end,
+ })
+ local ns = vim.api.nvim_create_namespace("conform")
+ for _, hl in ipairs(highlights) do
+ vim.api.nvim_buf_add_highlight(bufnr, ns, hl[1], hl[2] - 1, hl[3], hl[4])
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/init.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/init.lua
new file mode 100644
index 00000000..705cf6ab
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/init.lua
@@ -0,0 +1,711 @@
+---@diagnostic disable-next-line: deprecated
+local islist = vim.islist or vim.tbl_islist
+local M = {}
+
+---@type table
+M.formatters_by_ft = {}
+
+---@type table
+M.formatters = {}
+
+M.notify_on_error = true
+
+---@param opts? conform.setupOpts
+M.setup = function(opts)
+ opts = opts or {}
+
+ M.formatters = vim.tbl_extend("force", M.formatters, opts.formatters or {})
+ M.formatters_by_ft = vim.tbl_extend("force", M.formatters_by_ft, opts.formatters_by_ft or {})
+
+ if opts.log_level then
+ require("conform.log").level = opts.log_level
+ end
+ local notify_on_error = opts.notify_on_error
+ if notify_on_error ~= nil then
+ M.notify_on_error = notify_on_error
+ end
+
+ local aug = vim.api.nvim_create_augroup("Conform", { clear = true })
+ if opts.format_on_save then
+ if type(opts.format_on_save) == "boolean" then
+ opts.format_on_save = {}
+ end
+ vim.api.nvim_create_autocmd("BufWritePre", {
+ desc = "Format on save",
+ pattern = "*",
+ group = aug,
+ callback = function(args)
+ if not vim.api.nvim_buf_is_valid(args.buf) or vim.bo[args.buf].buftype ~= "" then
+ return
+ end
+ local format_args, callback = opts.format_on_save, nil
+ if type(format_args) == "function" then
+ format_args, callback = format_args(args.buf)
+ end
+ if format_args then
+ if format_args.async then
+ vim.notify_once(
+ "Conform format_on_save cannot use async=true. Use format_after_save instead.",
+ vim.log.levels.ERROR
+ )
+ end
+ M.format(
+ vim.tbl_deep_extend("force", format_args, {
+ buf = args.buf,
+ async = false,
+ }),
+ callback
+ )
+ end
+ end,
+ })
+ vim.api.nvim_create_autocmd("VimLeavePre", {
+ desc = "conform.nvim hack to work around Neovim bug",
+ pattern = "*",
+ group = aug,
+ callback = function()
+ -- HACK: Work around https://github.com/neovim/neovim/issues/21856
+ -- causing exit code 134 on :wq
+ vim.cmd.sleep({ args = { "1m" } })
+ end,
+ })
+ end
+
+ if opts.format_after_save then
+ if type(opts.format_after_save) == "boolean" then
+ opts.format_after_save = {}
+ end
+ local exit_timeout = 1000
+ local num_running_format_jobs = 0
+ vim.api.nvim_create_autocmd("BufWritePost", {
+ desc = "Format after save",
+ pattern = "*",
+ group = aug,
+ callback = function(args)
+ if
+ not vim.api.nvim_buf_is_valid(args.buf)
+ or vim.b[args.buf].conform_applying_formatting
+ or vim.bo[args.buf].buftype ~= ""
+ then
+ return
+ end
+ local format_args, callback = opts.format_after_save, nil
+ if type(format_args) == "function" then
+ format_args, callback = format_args(args.buf)
+ end
+ if format_args then
+ exit_timeout = format_args.timeout_ms or exit_timeout
+ num_running_format_jobs = num_running_format_jobs + 1
+ if format_args.async == false then
+ vim.notify_once(
+ "Conform format_after_save cannot use async=false. Use format_on_save instead.",
+ vim.log.levels.ERROR
+ )
+ end
+ M.format(
+ vim.tbl_deep_extend("force", format_args, {
+ buf = args.buf,
+ async = true,
+ }),
+ function(err)
+ num_running_format_jobs = num_running_format_jobs - 1
+ if not err and vim.api.nvim_buf_is_valid(args.buf) then
+ vim.api.nvim_buf_call(args.buf, function()
+ vim.b[args.buf].conform_applying_formatting = true
+ vim.cmd.update()
+ vim.b[args.buf].conform_applying_formatting = false
+ end)
+ end
+ if callback then
+ callback(err)
+ end
+ end
+ )
+ end
+ end,
+ })
+
+ vim.api.nvim_create_autocmd("BufWinLeave", {
+ desc = "conform.nvim store changedtick for use during Neovim exit",
+ pattern = "*",
+ group = aug,
+ callback = function(args)
+ -- We store this because when vim is exiting it will set changedtick = -1 for visible
+ -- buffers right after firing BufWinLeave
+ vim.b[args.buf].last_changedtick = vim.api.nvim_buf_get_changedtick(args.buf)
+ end,
+ })
+
+ vim.api.nvim_create_autocmd("VimLeavePre", {
+ desc = "conform.nvim wait for running formatters before exit",
+ pattern = "*",
+ group = aug,
+ callback = function()
+ if num_running_format_jobs == 0 then
+ return
+ end
+ local uv = vim.uv or vim.loop
+ local start = uv.hrtime() / 1e6
+ vim.wait(exit_timeout, function()
+ return num_running_format_jobs == 0
+ end, 10)
+ local elapsed = uv.hrtime() / 1e6 - start
+ if elapsed > 200 then
+ local log = require("conform.log")
+ log.warn("Delayed Neovim exit by %dms to wait for formatting to complete", elapsed)
+ end
+ -- HACK: Work around https://github.com/neovim/neovim/issues/21856
+ -- causing exit code 134 on :wq
+ vim.cmd.sleep({ args = { "1m" } })
+ end,
+ })
+ end
+
+ vim.api.nvim_create_user_command("ConformInfo", function()
+ require("conform.health").show_window()
+ end, { desc = "Show information about Conform formatters" })
+end
+
+---Get the configured formatter filetype for a buffer
+---@param bufnr? integer
+---@return nil|string filetype or nil if no formatter is configured
+local function get_matching_filetype(bufnr)
+ if not bufnr or bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ local filetypes = vim.split(vim.bo[bufnr].filetype, ".", { plain = true })
+ table.insert(filetypes, "_")
+ for _, filetype in ipairs(filetypes) do
+ local ft_formatters = M.formatters_by_ft[filetype]
+ if ft_formatters then
+ return filetype
+ end
+ end
+end
+
+---@private
+---@param bufnr? integer
+---@return conform.FormatterUnit[]
+M.list_formatters_for_buffer = function(bufnr)
+ if not bufnr or bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ local formatters = {}
+ local seen = {}
+
+ local function dedupe_formatters(names, collect)
+ for _, name in ipairs(names) do
+ if type(name) == "table" then
+ local alternation = {}
+ dedupe_formatters(name, alternation)
+ if not vim.tbl_isempty(alternation) then
+ table.insert(collect, alternation)
+ end
+ elseif not seen[name] then
+ table.insert(collect, name)
+ seen[name] = true
+ end
+ end
+ end
+
+ local filetypes = {}
+ local matching_filetype = get_matching_filetype(bufnr)
+ if matching_filetype then
+ table.insert(filetypes, matching_filetype)
+ end
+ table.insert(filetypes, "*")
+ for _, ft in ipairs(filetypes) do
+ local ft_formatters = M.formatters_by_ft[ft]
+ if ft_formatters then
+ if type(ft_formatters) == "function" then
+ dedupe_formatters(ft_formatters(bufnr), formatters)
+ else
+ -- support the old structure where formatters could be a subkey
+ if not islist(ft_formatters) then
+ vim.notify_once(
+ "Using deprecated structure for formatters_by_ft. See :help conform-options for details.",
+ vim.log.levels.ERROR
+ )
+ ---@diagnostic disable-next-line: undefined-field
+ ft_formatters = ft_formatters.formatters
+ end
+
+ dedupe_formatters(ft_formatters, formatters)
+ end
+ end
+ end
+
+ return formatters
+end
+
+---@param bufnr integer
+---@param mode "v"|"V"
+---@return table {start={row,col}, end={row,col}} using (1, 0) indexing
+local function range_from_selection(bufnr, mode)
+ -- [bufnum, lnum, col, off]; both row and column 1-indexed
+ local start = vim.fn.getpos("v")
+ local end_ = vim.fn.getpos(".")
+ local start_row = start[2]
+ local start_col = start[3]
+ local end_row = end_[2]
+ local end_col = end_[3]
+
+ -- A user can start visual selection at the end and move backwards
+ -- Normalize the range to start < end
+ if start_row == end_row and end_col < start_col then
+ end_col, start_col = start_col, end_col
+ elseif end_row < start_row then
+ start_row, end_row = end_row, start_row
+ start_col, end_col = end_col, start_col
+ end
+ if mode == "V" then
+ start_col = 1
+ local lines = vim.api.nvim_buf_get_lines(bufnr, end_row - 1, end_row, true)
+ end_col = #lines[1]
+ end
+ return {
+ ["start"] = { start_row, start_col - 1 },
+ ["end"] = { end_row, end_col - 1 },
+ }
+end
+
+---@private
+---@param names conform.FormatterUnit[]
+---@param bufnr integer
+---@param warn_on_missing boolean
+---@return conform.FormatterInfo[]
+M.resolve_formatters = function(names, bufnr, warn_on_missing)
+ local all_info = {}
+ local function add_info(info, warn)
+ if info.available then
+ table.insert(all_info, info)
+ elseif warn then
+ vim.notify(
+ string.format("Formatter '%s' unavailable: %s", info.name, info.available_msg),
+ vim.log.levels.WARN
+ )
+ end
+ return info.available
+ end
+
+ for _, name in ipairs(names) do
+ if type(name) == "string" then
+ local info = M.get_formatter_info(name, bufnr)
+ add_info(info, warn_on_missing)
+ else
+ -- If this is an alternation, take the first one that's available
+ for i, v in ipairs(name) do
+ local info = M.get_formatter_info(v, bufnr)
+ if add_info(info, warn_on_missing and i == #name) then
+ break
+ end
+ end
+ end
+ end
+ return all_info
+end
+
+---@class conform.FormatOpts
+---@field timeout_ms nil|integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
+---@field bufnr nil|integer Format this buffer (default 0)
+---@field async nil|boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
+---@field dry_run nil|boolean If true don't apply formatting changes to the buffer
+---@field formatters nil|string[] List of formatters to run. Defaults to all formatters for the buffer filetype.
+---@field lsp_fallback nil|boolean|"always" Attempt LSP formatting if no formatters are available. Defaults to false. If "always", will attempt LSP formatting even if formatters are available.
+---@field quiet nil|boolean Don't show any notifications for warnings or failures. Defaults to false.
+---@field range nil|table Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode
+---@field id nil|integer Passed to |vim.lsp.buf.format| when lsp_fallback = true
+---@field name nil|string Passed to |vim.lsp.buf.format| when lsp_fallback = true
+---@field filter nil|fun(client: table): boolean Passed to |vim.lsp.buf.format| when lsp_fallback = true
+
+---Format a buffer
+---@param opts? conform.FormatOpts
+---@param callback? fun(err: nil|string, did_edit: nil|boolean) Called once formatting has completed
+---@return boolean True if any formatters were attempted
+M.format = function(opts, callback)
+ ---@type {timeout_ms: integer, bufnr: integer, async: boolean, dry_run: boolean, lsp_fallback: boolean|"always", quiet: boolean, formatters?: string[], range?: conform.Range}
+ opts = vim.tbl_extend("keep", opts or {}, {
+ timeout_ms = 1000,
+ bufnr = 0,
+ async = false,
+ dry_run = false,
+ lsp_fallback = false,
+ quiet = false,
+ })
+ if opts.bufnr == 0 then
+ opts.bufnr = vim.api.nvim_get_current_buf()
+ end
+ local mode = vim.api.nvim_get_mode().mode
+ if not opts.range and mode == "v" or mode == "V" then
+ opts.range = range_from_selection(opts.bufnr, mode)
+ end
+ callback = callback or function(_err, _did_edit) end
+ local errors = require("conform.errors")
+ local log = require("conform.log")
+ local lsp_format = require("conform.lsp_format")
+ local runner = require("conform.runner")
+
+ local explicit_formatters = opts.formatters ~= nil
+ local formatter_names = opts.formatters or M.list_formatters_for_buffer(opts.bufnr)
+ local formatters =
+ M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet and explicit_formatters)
+
+ local any_formatters = not vim.tbl_isempty(formatters)
+ if not explicit_formatters and opts.lsp_fallback == true and M.will_fallback_lsp(opts) then
+ -- use the LSP formatter when the configured formatters are from the fallback "_" filetype
+ any_formatters = false
+ else
+ local resolved_names = vim.tbl_map(function(f)
+ return f.name
+ end, formatters)
+ log.debug("Running formatters on %s: %s", vim.api.nvim_buf_get_name(opts.bufnr), resolved_names)
+ end
+
+ if any_formatters then
+ ---@param err? conform.Error
+ ---@param did_edit? boolean
+ local function handle_result(err, did_edit)
+ if err then
+ local level = errors.level_for_code(err.code)
+ log.log(level, err.message)
+ local should_notify = not opts.quiet and level >= vim.log.levels.WARN
+ -- Execution errors have special handling. Maybe should reconsider this.
+ local notify_msg = err.message
+ if errors.is_execution_error(err.code) then
+ should_notify = should_notify and M.notify_on_error and not err.debounce_message
+ notify_msg = "Formatter failed. See :ConformInfo for details"
+ end
+ if should_notify then
+ vim.notify(notify_msg, level)
+ end
+ end
+ local err_message = err and err.message
+ if not err_message and not vim.api.nvim_buf_is_valid(opts.bufnr) then
+ err_message = "buffer was deleted"
+ end
+ if err_message then
+ return callback(err_message)
+ end
+
+ if opts.dry_run and did_edit then
+ callback(nil, true)
+ elseif
+ opts.lsp_fallback == "always" and not vim.tbl_isempty(lsp_format.get_format_clients(opts))
+ then
+ log.debug("Running LSP formatter on %s", vim.api.nvim_buf_get_name(opts.bufnr))
+ lsp_format.format(opts, callback)
+ else
+ callback(nil, did_edit)
+ end
+ end
+
+ local run_opts = { exclusive = true, dry_run = opts.dry_run }
+ if opts.async then
+ runner.format_async(opts.bufnr, formatters, opts.range, run_opts, handle_result)
+ else
+ local err, did_edit =
+ runner.format_sync(opts.bufnr, formatters, opts.timeout_ms, opts.range, run_opts)
+ handle_result(err, did_edit)
+ end
+ return true
+ elseif opts.lsp_fallback and not vim.tbl_isempty(lsp_format.get_format_clients(opts)) then
+ log.debug("Running LSP formatter on %s", vim.api.nvim_buf_get_name(opts.bufnr))
+ lsp_format.format(opts, callback)
+ return true
+ else
+ local level = vim.tbl_isempty(formatter_names) and "debug" or "warn"
+ log[level]("No formatters found for %s", vim.api.nvim_buf_get_name(opts.bufnr))
+ callback("No formatters found for buffer")
+ return false
+ end
+end
+
+---@class conform.FormatLinesOpts
+---@field timeout_ms nil|integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
+---@field bufnr nil|integer use this as the working buffer (default 0)
+---@field async nil|boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
+---@field quiet nil|boolean Don't show any notifications for warnings or failures. Defaults to false.
+
+---Process lines with formatters
+---@private
+---@param formatter_names string[]
+---@param lines string[]
+---@param opts? conform.FormatLinesOpts
+---@param callback? fun(err: nil|conform.Error, lines: nil|string[]) Called once formatting has completed
+---@return nil|conform.Error error Only present if async = false
+---@return nil|string[] new_lines Only present if async = false
+M.format_lines = function(formatter_names, lines, opts, callback)
+ ---@type {timeout_ms: integer, bufnr: integer, async: boolean, quiet: boolean}
+ opts = vim.tbl_extend("keep", opts or {}, {
+ timeout_ms = 1000,
+ bufnr = 0,
+ async = false,
+ quiet = false,
+ })
+ callback = callback or function(_err, _lines) end
+ local errors = require("conform.errors")
+ local log = require("conform.log")
+ local runner = require("conform.runner")
+ local formatters = M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet)
+ if vim.tbl_isempty(formatters) then
+ callback(nil, lines)
+ return
+ end
+
+ ---@param err? conform.Error
+ ---@param new_lines? string[]
+ local function handle_err(err, new_lines)
+ if err then
+ local level = errors.level_for_code(err.code)
+ log.log(level, err.message)
+ end
+ callback(err, new_lines)
+ end
+
+ local run_opts = { exclusive = false, dry_run = false }
+ if opts.async then
+ runner.format_lines_async(opts.bufnr, formatters, nil, lines, run_opts, handle_err)
+ else
+ local err, new_lines =
+ runner.format_lines_sync(opts.bufnr, formatters, opts.timeout_ms, nil, lines, run_opts)
+ handle_err(err, new_lines)
+ return err, new_lines
+ end
+end
+
+---Retrieve the available formatters for a buffer
+---@param bufnr? integer
+---@return conform.FormatterInfo[]
+M.list_formatters = function(bufnr)
+ if not bufnr or bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ local formatters = M.list_formatters_for_buffer(bufnr)
+ return M.resolve_formatters(formatters, bufnr, false)
+end
+
+---List information about all filetype-configured formatters
+---@return conform.FormatterInfo[]
+M.list_all_formatters = function()
+ local formatters = {}
+ for _, ft_formatters in pairs(M.formatters_by_ft) do
+ if type(ft_formatters) == "function" then
+ ft_formatters = ft_formatters(0)
+ end
+ -- support the old structure where formatters could be a subkey
+ if not islist(ft_formatters) then
+ vim.notify_once(
+ "Using deprecated structure for formatters_by_ft. See :help conform-options for details.",
+ vim.log.levels.ERROR
+ )
+ ---@diagnostic disable-next-line: undefined-field
+ ft_formatters = ft_formatters.formatters
+ end
+
+ for _, formatter in ipairs(ft_formatters) do
+ if type(formatter) == "table" then
+ for _, v in ipairs(formatter) do
+ formatters[v] = true
+ end
+ else
+ formatters[formatter] = true
+ end
+ end
+ end
+
+ ---@type conform.FormatterInfo[]
+ local all_info = {}
+ for formatter in pairs(formatters) do
+ local info = M.get_formatter_info(formatter)
+ table.insert(all_info, info)
+ end
+
+ table.sort(all_info, function(a, b)
+ return a.name < b.name
+ end)
+ return all_info
+end
+
+---@private
+---@param formatter string
+---@param bufnr? integer
+---@return nil|conform.FormatterConfig
+M.get_formatter_config = function(formatter, bufnr)
+ if not bufnr or bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ ---@type nil|conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride
+ local override = M.formatters[formatter]
+ if type(override) == "function" then
+ override = override(bufnr)
+ end
+ if override and override.command and override.format then
+ local msg =
+ string.format("Formatter '%s' cannot define both 'command' and 'format' function", formatter)
+ vim.notify_once(msg, vim.log.levels.ERROR)
+ return nil
+ end
+
+ ---@type nil|conform.FormatterConfig
+ local config = override
+ if not override or override.inherit ~= false then
+ local ok, mod_config = pcall(require, "conform.formatters." .. formatter)
+ if ok then
+ if override then
+ config = require("conform.util").merge_formatter_configs(mod_config, override)
+ else
+ config = mod_config
+ end
+ elseif override then
+ if override.command or override.format then
+ config = override
+ else
+ local msg = string.format(
+ "Formatter '%s' missing built-in definition\nSet `command` to get rid of this error.",
+ formatter
+ )
+ vim.notify_once(msg, vim.log.levels.ERROR)
+ return nil
+ end
+ else
+ return nil
+ end
+ end
+
+ if config and config.stdin == nil then
+ config.stdin = true
+ end
+ return config
+end
+
+---Get information about a formatter (including availability)
+---@param formatter string The name of the formatter
+---@param bufnr? integer
+---@return conform.FormatterInfo
+M.get_formatter_info = function(formatter, bufnr)
+ if not bufnr or bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ local config = M.get_formatter_config(formatter, bufnr)
+ if not config then
+ return {
+ name = formatter,
+ command = formatter,
+ available = false,
+ available_msg = "No config found",
+ }
+ end
+
+ local ctx = require("conform.runner").build_context(bufnr, config)
+
+ local available = true
+ local available_msg = nil
+ if config.format then
+ ---@cast config conform.LuaFormatterConfig
+ if config.condition and not config:condition(ctx) then
+ available = false
+ available_msg = "Condition failed"
+ end
+ return {
+ name = formatter,
+ command = formatter,
+ available = available,
+ available_msg = available_msg,
+ }
+ end
+
+ local command = config.command
+ if type(command) == "function" then
+ ---@cast config conform.JobFormatterConfig
+ command = command(config, ctx)
+ end
+
+ if vim.fn.executable(command) == 0 then
+ available = false
+ available_msg = "Command not found"
+ elseif config.condition and not config.condition(config, ctx) then
+ available = false
+ available_msg = "Condition failed"
+ end
+ local cwd = nil
+ if config.cwd then
+ ---@cast config conform.JobFormatterConfig
+ cwd = config.cwd(config, ctx)
+ if available and not cwd and config.require_cwd then
+ available = false
+ available_msg = "Root directory not found"
+ end
+ end
+
+ ---@type conform.FormatterInfo
+ return {
+ name = formatter,
+ command = command,
+ cwd = cwd,
+ available = available,
+ available_msg = available_msg,
+ }
+end
+
+---Check if the buffer will use LSP formatting when lsp_fallback = true
+---@param options? table Options passed to |vim.lsp.buf.format|
+---@return boolean
+M.will_fallback_lsp = function(options)
+ options = vim.tbl_deep_extend("keep", options or {}, {
+ bufnr = vim.api.nvim_get_current_buf(),
+ })
+ if options.bufnr == 0 then
+ options.bufnr = vim.api.nvim_get_current_buf()
+ end
+ local matching_filetype = get_matching_filetype(options.bufnr)
+ local has_primary_formatters = matching_filetype and matching_filetype ~= "_"
+ local lsp_clients = require("conform.lsp_format").get_format_clients(options)
+ return not has_primary_formatters and not vim.tbl_isempty(lsp_clients)
+end
+
+M.formatexpr = function(opts)
+ local lsp_format = require("conform.lsp_format")
+ -- Change the defaults slightly from conform.format
+ opts = vim.tbl_deep_extend("keep", opts or {}, {
+ timeout_ms = 500,
+ lsp_fallback = true,
+ })
+ -- Force async = false
+ opts.async = false
+ if vim.tbl_contains({ "i", "R", "ic", "ix" }, vim.fn.mode()) then
+ -- `formatexpr` is also called when exceeding `textwidth` in insert mode
+ -- fall back to internal formatting
+ return 1
+ end
+
+ local start_lnum = vim.v.lnum
+ local end_lnum = start_lnum + vim.v.count - 1
+
+ if start_lnum <= 0 or end_lnum <= 0 then
+ return 0
+ end
+ local end_line = vim.fn.getline(end_lnum)
+ local end_col = end_line:len()
+
+ if vim.v.count == vim.fn.line("$") then
+ -- Whole buffer is selected; use buffer formatting
+ opts.range = nil
+ else
+ opts.range = {
+ start = { start_lnum, 0 },
+ ["end"] = { end_lnum, end_col },
+ }
+ end
+
+ if M.format(opts) then
+ return 0
+ elseif opts.lsp_fallback and not vim.tbl_isempty(lsp_format.get_format_clients(opts)) then
+ -- No formatters were available; fall back to lsp formatter
+ return vim.lsp.formatexpr({ timeout_ms = opts.timeout_ms })
+ else
+ -- Do not fallback to built-in formatter.
+ return 0
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/log.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/log.lua
new file mode 100644
index 00000000..79ca15a0
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/log.lua
@@ -0,0 +1,124 @@
+local uv = vim.uv or vim.loop
+local levels_reverse = {}
+for k, v in pairs(vim.log.levels) do
+ levels_reverse[v] = k
+end
+
+local Log = {}
+
+---@type integer
+Log.level = vim.log.levels.WARN
+
+---@return string
+Log.get_logfile = function()
+ local fs = require("conform.fs")
+
+ local ok, stdpath = pcall(vim.fn.stdpath, "log")
+ if not ok then
+ stdpath = vim.fn.stdpath("cache")
+ end
+ assert(type(stdpath) == "string")
+ return fs.join(stdpath, "conform.log")
+end
+
+---@param level integer
+---@param msg string
+---@param ... any[]
+---@return string
+local function format(level, msg, ...)
+ local args = vim.F.pack_len(...)
+ for i = 1, args.n do
+ local v = args[i]
+ if type(v) == "table" then
+ args[i] = vim.inspect(v)
+ elseif v == nil then
+ args[i] = "nil"
+ end
+ end
+ local ok, text = pcall(string.format, msg, vim.F.unpack_len(args))
+ local timestr = vim.fn.strftime("%H:%M:%S")
+ if ok then
+ local str_level = levels_reverse[level]
+ return string.format("%s[%s] %s", timestr, str_level, text)
+ else
+ return string.format(
+ "%s[ERROR] error formatting log line: '%s' args %s",
+ timestr,
+ vim.inspect(msg),
+ vim.inspect(args)
+ )
+ end
+end
+
+---@param line string
+local function write(line)
+ -- This will be replaced during initialization
+end
+
+local initialized = false
+local function initialize()
+ if initialized then
+ return
+ end
+ initialized = true
+ local filepath = Log.get_logfile()
+
+ local stat = uv.fs_stat(filepath)
+ if stat and stat.size > 10 * 1024 * 1024 then
+ local backup = filepath .. ".1"
+ uv.fs_unlink(backup)
+ uv.fs_rename(filepath, backup)
+ end
+
+ local parent = vim.fs.dirname(filepath)
+ vim.fn.mkdir(parent, "p")
+
+ local logfile, openerr = io.open(filepath, "a+")
+ if not logfile then
+ local err_msg = string.format("Failed to open conform.nvim log file: %s", openerr)
+ vim.notify(err_msg, vim.log.levels.ERROR)
+ else
+ write = function(line)
+ logfile:write(line)
+ logfile:write("\n")
+ logfile:flush()
+ end
+ end
+end
+
+---Override the file handler e.g. for tests
+---@param handler fun(line: string)
+function Log.set_handler(handler)
+ write = handler
+ initialized = true
+end
+
+function Log.log(level, msg, ...)
+ if Log.level <= level then
+ initialize()
+ local text = format(level, msg, ...)
+ write(text)
+ end
+end
+
+function Log.trace(...)
+ Log.log(vim.log.levels.TRACE, ...)
+end
+
+function Log.debug(...)
+ Log.log(vim.log.levels.DEBUG, ...)
+end
+
+function Log.info(...)
+ Log.log(vim.log.levels.INFO, ...)
+end
+
+function Log.warn(...)
+ Log.log(vim.log.levels.WARN, ...)
+end
+
+function Log.error(...)
+ Log.log(vim.log.levels.ERROR, ...)
+end
+
+return Log
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/lsp_format.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/lsp_format.lua
new file mode 100644
index 00000000..a4f95567
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/lsp_format.lua
@@ -0,0 +1,167 @@
+---This module replaces the default vim.lsp.buf.format() so that we can inject our own logic
+local log = require("conform.log")
+local util = require("vim.lsp.util")
+
+local M = {}
+
+local function apply_text_edits(text_edits, bufnr, offset_encoding, dry_run)
+ if
+ #text_edits == 1
+ and text_edits[1].range.start.line == 0
+ and text_edits[1].range.start.character == 0
+ and text_edits[1].range["end"].line >= vim.api.nvim_buf_line_count(bufnr)
+ and text_edits[1].range["end"].character == 0
+ then
+ local original_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
+ local new_lines = vim.split(text_edits[1].newText, "\r?\n", {})
+ -- If it had a trailing newline, remove it to make the lines match the expected vim format
+ if #new_lines > 1 and new_lines[#new_lines] == "" then
+ table.remove(new_lines)
+ end
+ log.debug("Converting full-file LSP format to piecewise format")
+ return require("conform.runner").apply_format(
+ bufnr,
+ original_lines,
+ new_lines,
+ nil,
+ false,
+ dry_run
+ )
+ elseif dry_run then
+ return #text_edits > 0
+ else
+ vim.lsp.util.apply_text_edits(text_edits, bufnr, offset_encoding)
+ return #text_edits > 0
+ end
+end
+
+---@param options table
+---@return table[] clients
+function M.get_format_clients(options)
+ local method = options.range and "textDocument/rangeFormatting" or "textDocument/formatting"
+
+ local clients
+ if vim.lsp.get_clients then
+ clients = vim.lsp.get_clients({
+ id = options.id,
+ bufnr = options.bufnr,
+ name = options.name,
+ method = method,
+ })
+ else
+ ---@diagnostic disable-next-line: deprecated
+ clients = vim.lsp.get_active_clients({
+ id = options.id,
+ bufnr = options.bufnr,
+ name = options.name,
+ })
+
+ clients = vim.tbl_filter(function(client)
+ return client.supports_method(method, { bufnr = options.bufnr })
+ end, clients)
+ end
+ if options.filter then
+ clients = vim.tbl_filter(options.filter, clients)
+ end
+ return clients
+end
+
+---@param options table
+---@param callback fun(err?: string, did_edit?: boolean)
+function M.format(options, callback)
+ options = options or {}
+ if not options.bufnr or options.bufnr == 0 then
+ options.bufnr = vim.api.nvim_get_current_buf()
+ end
+ local bufnr = options.bufnr
+ local range = options.range
+ local method = range and "textDocument/rangeFormatting" or "textDocument/formatting"
+
+ local clients = M.get_format_clients(options)
+
+ if #clients == 0 then
+ return callback("[LSP] Format request failed, no matching language servers.")
+ end
+
+ local function set_range(client, params)
+ if range then
+ local range_params =
+ util.make_given_range_params(range.start, range["end"], bufnr, client.offset_encoding)
+ params.range = range_params.range
+ end
+ return params
+ end
+
+ if options.async then
+ local changedtick = vim.b[bufnr].changedtick
+ local do_format
+ local did_edit = false
+ do_format = function(idx, client)
+ if not client then
+ return callback(nil, did_edit)
+ end
+ local params = set_range(client, util.make_formatting_params(options.formatting_options))
+ local auto_id = vim.api.nvim_create_autocmd("LspDetach", {
+ buffer = bufnr,
+ callback = function(args)
+ if args.data.client_id == client.id then
+ log.warn("LSP %s detached during format request", client.name)
+ callback("LSP detached")
+ end
+ end,
+ })
+ client.request(method, params, function(err, result, ctx, _)
+ vim.api.nvim_del_autocmd(auto_id)
+ if not result then
+ return callback(err or "No result returned from LSP formatter")
+ elseif not vim.api.nvim_buf_is_valid(bufnr) then
+ return callback("buffer was deleted")
+ elseif changedtick ~= require("conform.util").buf_get_changedtick(bufnr) then
+ return callback(
+ string.format(
+ "Async LSP formatter discarding changes for %s: concurrent modification",
+ vim.api.nvim_buf_get_name(bufnr)
+ )
+ )
+ else
+ local this_did_edit =
+ apply_text_edits(result, ctx.bufnr, client.offset_encoding, options.dry_run)
+ changedtick = vim.b[bufnr].changedtick
+
+ if options.dry_run and this_did_edit then
+ callback(nil, true)
+ else
+ did_edit = did_edit or this_did_edit
+ do_format(next(clients, idx))
+ end
+ end
+ end, bufnr)
+ end
+ do_format(next(clients))
+ else
+ local timeout_ms = options.timeout_ms or 1000
+ local did_edit = false
+ for _, client in pairs(clients) do
+ local params = set_range(client, util.make_formatting_params(options.formatting_options))
+ local result, err = client.request_sync(method, params, timeout_ms, bufnr)
+ if result and result.result then
+ local this_did_edit =
+ apply_text_edits(result.result, bufnr, client.offset_encoding, options.dry_run)
+ did_edit = did_edit or this_did_edit
+
+ if options.dry_run and did_edit then
+ callback(nil, true)
+ return true
+ end
+ elseif err then
+ if not options.quiet then
+ vim.notify(string.format("[LSP][%s] %s", client.name, err), vim.log.levels.WARN)
+ end
+ return callback(string.format("[LSP][%s] %s", client.name, err))
+ end
+ end
+ callback(nil, did_edit)
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/runner.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/runner.lua
new file mode 100644
index 00000000..fd998077
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/runner.lua
@@ -0,0 +1,684 @@
+local errors = require("conform.errors")
+local fs = require("conform.fs")
+local log = require("conform.log")
+local util = require("conform.util")
+local uv = vim.uv or vim.loop
+local M = {}
+
+---@class (exact) conform.RunOpts
+---@field exclusive boolean If true, ensure only a single formatter is running per buffer
+---@field dry_run boolean If true, do not apply changes and stop after the first formatter attempts to do so
+
+---@param formatter_name string
+---@param ctx conform.Context
+---@param config conform.JobFormatterConfig
+---@return string|string[]
+M.build_cmd = function(formatter_name, ctx, config)
+ local command = config.command
+ if type(command) == "function" then
+ command = command(config, ctx)
+ end
+ ---@type string|string[]
+ local args = {}
+ if ctx.range and config.range_args then
+ ---@cast ctx conform.RangeContext
+ args = config.range_args(config, ctx)
+ elseif config.args then
+ local computed_args = config.args
+ if type(computed_args) == "function" then
+ args = computed_args(config, ctx)
+ else
+ ---@diagnostic disable-next-line: cast-local-type
+ args = computed_args
+ end
+ end
+
+ local function compute_relative_filepath()
+ local cwd
+ if config.cwd then
+ cwd = config.cwd(config, ctx)
+ end
+ return fs.relative_path(cwd or vim.fn.getcwd(), ctx.filename)
+ end
+
+ if type(args) == "string" then
+ local interpolated = args
+ :gsub("$FILENAME", ctx.filename)
+ :gsub("$DIRNAME", ctx.dirname)
+ :gsub("$RELATIVE_FILEPATH", compute_relative_filepath)
+ return command .. " " .. interpolated
+ else
+ local cmd = { command }
+ ---@diagnostic disable-next-line: param-type-mismatch
+ for _, v in ipairs(args) do
+ if v == "$FILENAME" then
+ v = ctx.filename
+ elseif v == "$DIRNAME" then
+ v = ctx.dirname
+ elseif v == "$RELATIVE_FILEPATH" then
+ v = compute_relative_filepath()
+ end
+ table.insert(cmd, v)
+ end
+ return cmd
+ end
+end
+
+---@param value any
+---@return boolean
+local function truthy(value)
+ return value ~= nil and value ~= false
+end
+
+---@param range conform.Range
+---@param start_a integer
+---@param end_a integer
+---@return boolean
+local function indices_in_range(range, start_a, end_a)
+ return start_a <= range["end"][1] and range["start"][1] <= end_a
+end
+
+---@param a? string
+---@param b? string
+---@return integer
+local function common_prefix_len(a, b)
+ if not a or not b then
+ return 0
+ end
+ local min_len = math.min(#a, #b)
+ for i = 1, min_len do
+ if string.byte(a, i) ~= string.byte(b, i) then
+ return i - 1
+ end
+ end
+ return min_len
+end
+
+---@param a string
+---@param b string
+---@return integer
+local function common_suffix_len(a, b)
+ local a_len = #a
+ local b_len = #b
+ local min_len = math.min(a_len, b_len)
+ for i = 0, min_len - 1 do
+ if string.byte(a, a_len - i) ~= string.byte(b, b_len - i) then
+ return i
+ end
+ end
+ return min_len
+end
+
+local function create_text_edit(
+ original_lines,
+ replacement,
+ is_insert,
+ is_replace,
+ orig_line_start,
+ orig_line_end
+)
+ local start_line, end_line = orig_line_start - 1, orig_line_end - 1
+ local start_char, end_char = 0, 0
+ if is_replace then
+ -- If we're replacing text, see if we can avoid replacing the entire line
+ start_char = common_prefix_len(original_lines[orig_line_start], replacement[1])
+ if start_char > 0 then
+ replacement[1] = replacement[1]:sub(start_char + 1)
+ end
+
+ if original_lines[orig_line_end] then
+ local last_line = replacement[#replacement]
+ local suffix = common_suffix_len(original_lines[orig_line_end], last_line)
+ -- If we're only replacing one line, make sure the prefix/suffix calculations don't overlap
+ if orig_line_end == orig_line_start then
+ suffix = math.min(suffix, original_lines[orig_line_end]:len() - start_char)
+ end
+ end_char = original_lines[orig_line_end]:len() - suffix
+ if suffix > 0 then
+ replacement[#replacement] = last_line:sub(1, last_line:len() - suffix)
+ end
+ end
+ end
+ -- If we're inserting text, make sure the text includes a newline at the end.
+ -- The one exception is if we're inserting at the end of the file, in which case the newline is
+ -- implicit
+ if is_insert and start_line < #original_lines then
+ table.insert(replacement, "")
+ end
+ local new_text = table.concat(replacement, "\n")
+
+ return {
+ newText = new_text,
+ range = {
+ start = {
+ line = start_line,
+ character = start_char,
+ },
+ ["end"] = {
+ line = end_line,
+ character = end_char,
+ },
+ },
+ }
+end
+
+---@param bufnr integer
+---@param original_lines string[]
+---@param new_lines string[]
+---@param range? conform.Range
+---@param only_apply_range boolean
+---@return boolean any_changes
+M.apply_format = function(bufnr, original_lines, new_lines, range, only_apply_range, dry_run)
+ if bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ if not vim.api.nvim_buf_is_valid(bufnr) then
+ return false
+ end
+ local bufname = vim.api.nvim_buf_get_name(bufnr)
+ log.trace("Applying formatting to %s", bufname)
+ -- The vim.diff algorithm doesn't handle changes in newline-at-end-of-file well. The unified
+ -- result_type has some text to indicate that the eol changed, but the indices result_type has no
+ -- such indication. To work around this, we just add a trailing newline to the end of both the old
+ -- and the new text.
+ table.insert(original_lines, "")
+ table.insert(new_lines, "")
+ local original_text = table.concat(original_lines, "\n")
+ local new_text = table.concat(new_lines, "\n")
+ table.remove(original_lines)
+ table.remove(new_lines)
+
+ -- Abort if output is empty but input is not (i.e. has some non-whitespace characters).
+ -- This is to hack around oddly behaving formatters (e.g black outputs nothing for excluded files).
+ if new_text:match("^%s*$") and not original_text:match("^%s*$") then
+ log.warn("Aborting because a formatter returned empty output for buffer %s", bufname)
+ return false
+ end
+
+ log.trace("Comparing lines %s and %s", original_lines, new_lines)
+ local indices = vim.diff(original_text, new_text, {
+ result_type = "indices",
+ algorithm = "histogram",
+ })
+ assert(type(indices) == "table")
+ log.trace("Diff indices %s", indices)
+ local text_edits = {}
+ for _, idx in ipairs(indices) do
+ local orig_line_start, orig_line_count, new_line_start, new_line_count = unpack(idx)
+ local is_insert = orig_line_count == 0
+ local is_delete = new_line_count == 0
+ local is_replace = not is_insert and not is_delete
+ local orig_line_end = orig_line_start + orig_line_count
+ local new_line_end = new_line_start + new_line_count
+
+ if is_insert then
+ -- When the diff is an insert, it actually means to insert after the mentioned line
+ orig_line_start = orig_line_start + 1
+ orig_line_end = orig_line_end + 1
+ end
+
+ local replacement = util.tbl_slice(new_lines, new_line_start, new_line_end - 1)
+
+ -- For replacement edits, convert the end line to be inclusive
+ if is_replace then
+ orig_line_end = orig_line_end - 1
+ end
+ local should_apply_diff = not only_apply_range
+ or not range
+ or indices_in_range(range, orig_line_start, orig_line_end)
+ if should_apply_diff then
+ local text_edit = create_text_edit(
+ original_lines,
+ replacement,
+ is_insert,
+ is_replace,
+ orig_line_start,
+ orig_line_end
+ )
+ table.insert(text_edits, text_edit)
+
+ -- If we're using the aftermarket range formatting, diffs often have paired delete/insert
+ -- diffs. We should make sure that if one of them overlaps our selected range, extend the
+ -- range so that we pick up the other diff as well.
+ if range and only_apply_range then
+ range = vim.deepcopy(range)
+ range["end"][1] = math.max(range["end"][1], orig_line_end + 1)
+ end
+ end
+ end
+
+ if not dry_run then
+ log.trace("Applying text edits: %s", text_edits)
+ vim.lsp.util.apply_text_edits(text_edits, bufnr, "utf-8")
+ log.trace("Done formatting %s", bufname)
+ end
+
+ return not vim.tbl_isempty(text_edits)
+end
+
+---Map of formatter name to if the last run of that formatter produced an error
+---@type table
+local last_run_errored = {}
+
+---@param bufnr integer
+---@param formatter conform.FormatterInfo
+---@param config conform.FormatterConfig
+---@param ctx conform.Context
+---@param input_lines string[]
+---@param opts conform.RunOpts
+---@param callback fun(err?: conform.Error, output?: string[])
+---@return integer? job_id
+local function run_formatter(bufnr, formatter, config, ctx, input_lines, opts, callback)
+ log.info("Run %s on %s", formatter.name, vim.api.nvim_buf_get_name(bufnr))
+ log.trace("Input lines: %s", input_lines)
+ callback = util.wrap_callback(callback, function(err)
+ if err then
+ if last_run_errored[formatter.name] then
+ err.debounce_message = true
+ end
+ last_run_errored[formatter.name] = true
+ else
+ last_run_errored[formatter.name] = false
+ end
+ end)
+ if config.format then
+ ---@cast config conform.LuaFormatterConfig
+ local ok, err = pcall(config.format, config, ctx, input_lines, callback)
+ if not ok then
+ callback({
+ code = errors.ERROR_CODE.RUNTIME,
+ message = string.format("Formatter '%s' error: %s", formatter.name, err),
+ })
+ end
+ return
+ end
+ ---@cast config conform.JobFormatterConfig
+ local cmd = M.build_cmd(formatter.name, ctx, config)
+ local cwd = nil
+ if config.cwd then
+ cwd = config.cwd(config, ctx)
+ end
+ local env = config.env
+ if type(env) == "function" then
+ env = env(config, ctx)
+ end
+
+ local buffer_text
+ -- If the buffer has a newline at the end, make sure we include that in the input to the formatter
+ local add_extra_newline = vim.bo[bufnr].eol
+ if add_extra_newline then
+ table.insert(input_lines, "")
+ end
+ buffer_text = table.concat(input_lines, "\n")
+ if add_extra_newline then
+ table.remove(input_lines)
+ end
+
+ if not config.stdin then
+ log.debug("Creating temp file %s", ctx.filename)
+ local fd = assert(uv.fs_open(ctx.filename, "w", 448)) -- 0700
+ uv.fs_write(fd, buffer_text)
+ uv.fs_close(fd)
+ callback = util.wrap_callback(callback, function()
+ log.debug("Cleaning up temp file %s", ctx.filename)
+ uv.fs_unlink(ctx.filename)
+ end)
+ end
+
+ log.debug("Run command: %s", cmd)
+ if cwd then
+ log.debug("Run CWD: %s", cwd)
+ end
+ if env then
+ log.debug("Run ENV: %s", env)
+ end
+ local stdout
+ local stderr
+ local exit_codes = config.exit_codes or { 0 }
+ local jid
+ local ok, jid_or_err = pcall(vim.fn.jobstart, cmd, {
+ cwd = cwd,
+ env = env,
+ stdout_buffered = true,
+ stderr_buffered = true,
+ stdin = config.stdin and "pipe" or "null",
+ on_stdout = function(_, data)
+ if config.stdin then
+ stdout = data
+ end
+ end,
+ on_stderr = function(_, data)
+ stderr = data
+ end,
+ on_exit = function(_, code)
+ if vim.tbl_contains(exit_codes, code) then
+ local output
+ if not config.stdin then
+ local fd = assert(uv.fs_open(ctx.filename, "r", 448)) -- 0700
+ local stat = assert(uv.fs_fstat(fd))
+ local content = assert(uv.fs_read(fd, stat.size))
+ uv.fs_close(fd)
+ output = vim.split(content, "\r?\n", {})
+ else
+ output = stdout
+ -- trim trailing \r in every line
+ -- so that both branches of this if block behaves the same
+ for i, line in ipairs(output) do
+ output[i] = string.gsub(line, "\r$", "")
+ end
+ end
+ -- Remove the trailing newline from the output to convert back to vim lines representation
+ if add_extra_newline and output[#output] == "" then
+ table.remove(output)
+ end
+ -- Vim will never let the lines array be empty. An empty file will still look like { "" }
+ if #output == 0 then
+ table.insert(output, "")
+ end
+ log.debug("%s exited with code %d", formatter.name, code)
+ log.trace("Output lines: %s", output)
+ log.trace("%s stderr: %s", formatter.name, stderr)
+ callback(nil, output)
+ else
+ log.info("%s exited with code %d", formatter.name, code)
+ log.debug("%s stdout: %s", formatter.name, stdout)
+ log.debug("%s stderr: %s", formatter.name, stderr)
+ local err_str
+ if stderr and not vim.tbl_isempty(stderr) then
+ err_str = table.concat(stderr, "\n")
+ elseif stdout and not vim.tbl_isempty(stdout) then
+ err_str = table.concat(stdout, "\n")
+ end
+ if
+ vim.api.nvim_buf_is_valid(bufnr)
+ and jid ~= vim.b[bufnr].conform_jid
+ and opts.exclusive
+ then
+ callback({
+ code = errors.ERROR_CODE.INTERRUPTED,
+ message = string.format("Formatter '%s' was interrupted", formatter.name),
+ })
+ else
+ callback({
+ code = errors.ERROR_CODE.RUNTIME,
+ message = string.format("Formatter '%s' error: %s", formatter.name, err_str),
+ })
+ end
+ end
+ end,
+ })
+ if not ok then
+ callback({
+ code = errors.ERROR_CODE.JOBSTART,
+ message = string.format("Formatter '%s' error in jobstart: %s", formatter.name, jid_or_err),
+ })
+ return
+ end
+ jid = jid_or_err
+ if jid == 0 then
+ callback({
+ code = errors.ERROR_CODE.INVALID_ARGS,
+ message = string.format("Formatter '%s' invalid arguments", formatter.name),
+ })
+ elseif jid == -1 then
+ callback({
+ code = errors.ERROR_CODE.NOT_EXECUTABLE,
+ message = string.format("Formatter '%s' command is not executable", formatter.name),
+ })
+ elseif config.stdin then
+ vim.api.nvim_chan_send(jid, buffer_text)
+ vim.fn.chanclose(jid, "stdin")
+ end
+ if opts.exclusive then
+ vim.b[bufnr].conform_jid = jid
+ end
+
+ return jid
+end
+
+---@param bufnr integer
+---@param config conform.FormatterConfig
+---@param range? conform.Range
+---@return conform.Context
+M.build_context = function(bufnr, config, range)
+ if bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ local filename = vim.api.nvim_buf_get_name(bufnr)
+
+ -- Hack around checkhealth. For buffers that are not files, we need to fabricate a filename
+ if vim.bo[bufnr].buftype ~= "" then
+ filename = ""
+ end
+ local dirname
+ if filename == "" then
+ dirname = vim.fn.getcwd()
+ filename = fs.join(dirname, "unnamed_temp")
+ local ft = vim.bo[bufnr].filetype
+ if ft and ft ~= "" then
+ filename = filename .. "." .. ft
+ end
+ else
+ dirname = vim.fs.dirname(filename)
+ end
+
+ if not config.stdin then
+ local template = config.tmpfile_format
+ if not template then
+ template = ".conform.$RANDOM.$FILENAME"
+ end
+ local basename = vim.fs.basename(filename)
+ local tmpname =
+ template:gsub("$FILENAME", basename):gsub("$RANDOM", tostring(math.random(1000000, 9999999)))
+ local parent = vim.fs.dirname(filename)
+ filename = fs.join(parent, tmpname)
+ end
+ return {
+ buf = bufnr,
+ filename = filename,
+ dirname = dirname,
+ range = range,
+ }
+end
+
+---@param bufnr integer
+---@param formatters conform.FormatterInfo[]
+---@param range? conform.Range
+---@param opts conform.RunOpts
+---@param callback fun(err?: conform.Error, did_edit?: boolean)
+M.format_async = function(bufnr, formatters, range, opts, callback)
+ if bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+
+ -- kill previous jobs for buffer
+ local prev_jid = vim.b[bufnr].conform_jid
+ if prev_jid and opts.exclusive then
+ if vim.fn.jobstop(prev_jid) == 1 then
+ log.info("Canceled previous format job for %s", vim.api.nvim_buf_get_name(bufnr))
+ end
+ end
+
+ local original_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
+ local changedtick = vim.b[bufnr].changedtick
+ M.format_lines_async(
+ bufnr,
+ formatters,
+ range,
+ original_lines,
+ opts,
+ function(err, output_lines, all_support_range_formatting)
+ local did_edit = nil
+ -- discard formatting if buffer has changed
+ if not vim.api.nvim_buf_is_valid(bufnr) or changedtick ~= util.buf_get_changedtick(bufnr) then
+ err = {
+ code = errors.ERROR_CODE.CONCURRENT_MODIFICATION,
+ message = string.format(
+ "Async formatter discarding changes for %d: concurrent modification",
+ bufnr
+ ),
+ }
+ else
+ did_edit = M.apply_format(
+ bufnr,
+ original_lines,
+ output_lines,
+ range,
+ not all_support_range_formatting,
+ opts.dry_run
+ )
+ end
+ callback(err, did_edit)
+ end
+ )
+end
+
+---@param bufnr integer
+---@param formatters conform.FormatterInfo[]
+---@param range? conform.Range
+---@param input_lines string[]
+---@param opts conform.RunOpts
+---@param callback fun(err?: conform.Error, output_lines: string[], all_support_range_formatting: boolean)
+M.format_lines_async = function(bufnr, formatters, range, input_lines, opts, callback)
+ if bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ local idx = 1
+ local all_support_range_formatting = true
+ local final_err = nil
+
+ local function run_next_formatter()
+ local formatter = formatters[idx]
+ if not formatter then
+ callback(final_err, input_lines, all_support_range_formatting)
+ return
+ end
+ idx = idx + 1
+
+ local config = assert(require("conform").get_formatter_config(formatter.name, bufnr))
+ local ctx = M.build_context(bufnr, config, range)
+ run_formatter(bufnr, formatter, config, ctx, input_lines, opts, function(err, output)
+ if err then
+ final_err = errors.coalesce(final_err, err)
+ end
+ input_lines = output or input_lines
+ all_support_range_formatting = all_support_range_formatting and truthy(config.range_args)
+ run_next_formatter()
+ end)
+ end
+ run_next_formatter()
+end
+
+---@param bufnr integer
+---@param formatters conform.FormatterInfo[]
+---@param timeout_ms integer
+---@param range? conform.Range
+---@param opts conform.RunOpts
+---@return conform.Error? error
+---@return boolean did_edit
+M.format_sync = function(bufnr, formatters, timeout_ms, range, opts)
+ if bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ local original_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
+
+ -- kill previous jobs for buffer
+ local prev_jid = vim.b[bufnr].conform_jid
+ if prev_jid and opts.exclusive then
+ if vim.fn.jobstop(prev_jid) == 1 then
+ log.info("Canceled previous format job for %s", vim.api.nvim_buf_get_name(bufnr))
+ end
+ end
+
+ local err, final_result, all_support_range_formatting =
+ M.format_lines_sync(bufnr, formatters, timeout_ms, range, original_lines, opts)
+
+ local did_edit = M.apply_format(
+ bufnr,
+ original_lines,
+ final_result,
+ range,
+ not all_support_range_formatting,
+ opts.dry_run
+ )
+ return err, did_edit
+end
+
+---@param bufnr integer
+---@param formatters conform.FormatterInfo[]
+---@param timeout_ms integer
+---@param range? conform.Range
+---@param opts conform.RunOpts
+---@return conform.Error? error
+---@return string[] output_lines
+---@return boolean all_support_range_formatting
+M.format_lines_sync = function(bufnr, formatters, timeout_ms, range, input_lines, opts)
+ if bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ local start = uv.hrtime() / 1e6
+
+ local all_support_range_formatting = true
+ local final_err = nil
+ for _, formatter in ipairs(formatters) do
+ local remaining = timeout_ms - (uv.hrtime() / 1e6 - start)
+ if remaining <= 0 then
+ return errors.coalesce(final_err, {
+ code = errors.ERROR_CODE.TIMEOUT,
+ message = string.format("Formatter '%s' timeout", formatter.name),
+ }),
+ input_lines,
+ all_support_range_formatting
+ end
+ local done = false
+ local result = nil
+ ---@type conform.FormatterConfig
+ local config = assert(require("conform").get_formatter_config(formatter.name, bufnr))
+ local ctx = M.build_context(bufnr, config, range)
+ local jid = run_formatter(
+ bufnr,
+ formatter,
+ config,
+ ctx,
+ input_lines,
+ opts,
+ function(err, output)
+ final_err = errors.coalesce(final_err, err)
+ done = true
+ result = output
+ end
+ )
+ all_support_range_formatting = all_support_range_formatting and truthy(config.range_args)
+
+ local wait_result, wait_reason = vim.wait(remaining, function()
+ return done
+ end, 5)
+
+ if not wait_result then
+ if jid then
+ vim.fn.jobstop(jid)
+ end
+ if wait_reason == -1 then
+ return errors.coalesce(final_err, {
+ code = errors.ERROR_CODE.TIMEOUT,
+ message = string.format("Formatter '%s' timeout", formatter.name),
+ }),
+ input_lines,
+ all_support_range_formatting
+ else
+ return errors.coalesce(final_err, {
+ code = errors.ERROR_CODE.INTERRUPTED,
+ message = string.format("Formatter '%s' was interrupted", formatter.name),
+ }),
+ input_lines,
+ all_support_range_formatting
+ end
+ end
+
+ input_lines = result or input_lines
+ end
+
+ return final_err, input_lines, all_support_range_formatting
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/types.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/types.lua
new file mode 100644
index 00000000..bd984269
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/types.lua
@@ -0,0 +1,68 @@
+---@class (exact) conform.FormatterInfo
+---@field name string
+---@field command string
+---@field cwd? string
+---@field available boolean
+---@field available_msg? string
+
+---@class (exact) conform.JobFormatterConfig
+---@field command string|fun(self: conform.JobFormatterConfig, ctx: conform.Context): string
+---@field args? string|string[]|fun(self: conform.JobFormatterConfig, ctx: conform.Context): string|string[]
+---@field range_args? fun(self: conform.JobFormatterConfig, ctx: conform.RangeContext): string|string[]
+---@field cwd? fun(self: conform.JobFormatterConfig, ctx: conform.Context): nil|string
+---@field require_cwd? boolean When cwd is not found, don't run the formatter (default false)
+---@field stdin? boolean Send buffer contents to stdin (default true)
+---@field tmpfile_format? string When stdin=false, use this format for temporary files (default ".conform.$RANDOM.$FILENAME")
+---@field condition? fun(self: conform.JobFormatterConfig, ctx: conform.Context): boolean
+---@field exit_codes? integer[] Exit codes that indicate success (default {0})
+---@field env? table|fun(self: conform.JobFormatterConfig, ctx: conform.Context): table
+---@field options? table
+
+---@class (exact) conform.LuaFormatterConfig
+---@field format fun(self: conform.LuaFormatterConfig, ctx: conform.Context, lines: string[], callback: fun(err: nil|string, new_lines: nil|string[]))
+---@field condition? fun(self: conform.LuaFormatterConfig, ctx: conform.Context): boolean
+---@field options? table
+
+---@class (exact) conform.FileLuaFormatterConfig : conform.LuaFormatterConfig
+---@field meta conform.FormatterMeta
+
+---@class (exact) conform.FileFormatterConfig : conform.JobFormatterConfig
+---@field meta conform.FormatterMeta
+
+---@alias conform.FormatterConfig conform.JobFormatterConfig|conform.LuaFormatterConfig
+
+---@class (exact) conform.FormatterConfigOverride : conform.JobFormatterConfig
+---@field inherit? boolean
+---@field command? string|fun(self: conform.FormatterConfig, ctx: conform.Context): string
+---@field prepend_args? string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
+---@field format? fun(self: conform.LuaFormatterConfig, ctx: conform.Context, lines: string[], callback: fun(err: nil|string, new_lines: nil|string[])) Mutually exclusive with command
+---@field options? table
+
+---@class (exact) conform.FormatterMeta
+---@field url string
+---@field description string
+---@field deprecated? boolean
+
+---@class (exact) conform.Context
+---@field buf integer
+---@field filename string
+---@field dirname string
+---@field range? conform.Range
+
+---@class (exact) conform.RangeContext : conform.Context
+---@field range conform.Range
+
+---@class (exact) conform.Range
+---@field start integer[]
+---@field end integer[]
+
+---@alias conform.FormatterUnit string|string[]
+---@alias conform.FiletypeFormatter conform.FormatterUnit[]|fun(bufnr: integer): string[]
+
+---@class (exact) conform.setupOpts
+---@field formatters_by_ft? table Map of filetype to formatters
+---@field format_on_save? conform.FormatOpts|fun(bufnr: integer): conform.FormatOpts If this is set, Conform will run the formatter on save. It will pass the table to conform.format(). This can also be a function that returns the table.
+---@field format_after_save? conform.FormatOpts|fun(bufnr: integer): conform.FormatOpts If this is set, Conform will run the formatter asynchronously after save. It will pass the table to conform.format(). This can also be a function that returns the table.
+---@field log_level? integer Set the log level (e.g. `vim.log.levels.DEBUG`). Use `:ConformInfo` to see the location of the log file.
+---@field notify_on_error? boolean Conform will notify you when a formatter errors (default true).
+---@field formatters? table Custom formatters and overrides for built-in formatters.
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/util.lua b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/util.lua
new file mode 100644
index 00000000..fe2a306e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/lua/conform/util.lua
@@ -0,0 +1,207 @@
+local M = {}
+
+---Find a command in node_modules
+---@param cmd string
+---@return fun(ctx: conform.Context): string
+M.from_node_modules = function(cmd)
+ return M.find_executable({ "node_modules/.bin/" .. cmd }, cmd)
+end
+
+---Search parent directories for a relative path to a command
+---@param paths string[]
+---@param default string
+---@return fun(self: conform.FormatterConfig, ctx: conform.Context): string
+---@example
+--- local cmd = require("conform.util").find_executable({ "node_modules/.bin/prettier" }, "prettier")
+M.find_executable = function(paths, default)
+ return function(self, ctx)
+ for _, path in ipairs(paths) do
+ local normpath = vim.fs.normalize(path)
+ local is_absolute = vim.startswith(normpath, "/")
+ if is_absolute and vim.fn.executable(normpath) then
+ return normpath
+ end
+
+ local idx = normpath:find("/", 1, true)
+ local dir, subpath
+ if idx then
+ dir = normpath:sub(1, idx - 1)
+ subpath = normpath:sub(idx)
+ else
+ -- This is a bare relative-path executable
+ dir = normpath
+ subpath = ""
+ end
+ local results = vim.fs.find(dir, { upward = true, path = ctx.dirname, limit = math.huge })
+ for _, result in ipairs(results) do
+ local fullpath = result .. subpath
+ if vim.fn.executable(fullpath) == 1 then
+ return fullpath
+ end
+ end
+ end
+
+ return default
+ end
+end
+
+---@param files string|string[]
+---@return fun(self: conform.FormatterConfig, ctx: conform.Context): nil|string
+M.root_file = function(files)
+ return function(self, ctx)
+ local found = vim.fs.find(files, { upward = true, path = ctx.dirname })[1]
+ if found then
+ return vim.fs.dirname(found)
+ end
+ end
+end
+
+---@param bufnr integer
+---@param range conform.Range
+---@return integer start_offset
+---@return integer end_offset
+M.get_offsets_from_range = function(bufnr, range)
+ local row = range.start[1] - 1
+ local end_row = range["end"][1] - 1
+ local col = range.start[2]
+ local end_col = range["end"][2]
+ local start_offset = vim.api.nvim_buf_get_offset(bufnr, row) + col
+ local end_offset = vim.api.nvim_buf_get_offset(bufnr, end_row) + end_col
+ return start_offset, end_offset
+end
+
+---@generic T : any
+---@param tbl T[]
+---@param start_idx? number
+---@param end_idx? number
+---@return T[]
+M.tbl_slice = function(tbl, start_idx, end_idx)
+ local ret = {}
+ if not start_idx then
+ start_idx = 1
+ end
+ if not end_idx then
+ end_idx = #tbl
+ end
+ for i = start_idx, end_idx do
+ table.insert(ret, tbl[i])
+ end
+ return ret
+end
+
+---@generic T : fun()
+---@param cb T
+---@param wrapper T
+---@return T
+M.wrap_callback = function(cb, wrapper)
+ return function(...)
+ wrapper(...)
+ cb(...)
+ end
+end
+
+---Helper function to add to the default args of a formatter.
+---@param args string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
+---@param extra_args string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
+---@param opts? { append?: boolean }
+---@example
+--- local util = require("conform.util")
+--- local prettier = require("conform.formatters.prettier")
+--- require("conform").formatters.prettier = vim.tbl_deep_extend("force", prettier, {
+--- args = util.extend_args(prettier.args, { "--tab", "--indent", "2" }),
+--- range_args = util.extend_args(prettier.range_args, { "--tab", "--indent", "2" }),
+--- })
+M.extend_args = function(args, extra_args, opts)
+ opts = opts or {}
+ return function(self, ctx)
+ if type(args) == "function" then
+ args = args(self, ctx)
+ end
+ if type(extra_args) == "function" then
+ extra_args = extra_args(self, ctx)
+ end
+ if type(args) == "string" then
+ if type(extra_args) ~= "string" then
+ extra_args = table.concat(extra_args, " ")
+ end
+ if opts.append then
+ return args .. " " .. extra_args
+ else
+ return extra_args .. " " .. args
+ end
+ else
+ if type(extra_args) == "string" then
+ error("extra_args must be a table when args is a table")
+ end
+ local ret = {}
+ if opts.append then
+ vim.list_extend(ret, args or {})
+ vim.list_extend(ret, extra_args or {})
+ else
+ vim.list_extend(ret, extra_args or {})
+ vim.list_extend(ret, args or {})
+ end
+ return ret
+ end
+ end
+end
+
+---@param formatter conform.FormatterConfig
+---@param extra_args string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
+---@param opts? { append?: boolean }
+---@example
+--- local util = require("conform.util")
+--- local prettier = require("conform.formatters.prettier")
+--- util.add_formatter_args(prettier, { "--tab", "--indent", "2" })
+M.add_formatter_args = function(formatter, extra_args, opts)
+ formatter.args = M.extend_args(formatter.args, extra_args, opts)
+ if formatter.range_args then
+ formatter.range_args = M.extend_args(formatter.range_args, extra_args, opts)
+ end
+end
+
+---@param config conform.FormatterConfig
+---@param override conform.FormatterConfigOverride
+---@return conform.FormatterConfig
+M.merge_formatter_configs = function(config, override)
+ local ret = vim.tbl_deep_extend("force", config, override)
+ if override.prepend_args then
+ M.add_formatter_args(ret, override.prepend_args, { append = false })
+ end
+ return ret
+end
+
+---@param bufnr integer
+---@return integer
+M.buf_get_changedtick = function(bufnr)
+ if not vim.api.nvim_buf_is_valid(bufnr) then
+ return -2
+ end
+ local changedtick = vim.b[bufnr].changedtick
+ -- changedtick gets set to -1 when vim is exiting. We have an autocmd that should store it in
+ -- last_changedtick before it is set to -1.
+ if changedtick == -1 then
+ return vim.b[bufnr].last_changedtick or -1
+ else
+ return changedtick
+ end
+end
+
+---Parse the rust edition from the Cargo.toml file
+---@param dir string
+---@return string?
+M.parse_rust_edition = function(dir)
+ local manifest = vim.fs.find("Cargo.toml", { upward = true, path = dir })[1]
+ if manifest then
+ for line in io.lines(manifest) do
+ if line:match("^edition *=") then
+ local edition = line:match("%d+")
+ if edition then
+ return edition
+ end
+ end
+ end
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/run_tests.sh b/config/neovim/store/lazy-plugins/conform.nvim/run_tests.sh
new file mode 100755
index 00000000..b8ef9ed6
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/run_tests.sh
@@ -0,0 +1,30 @@
+#!/nix/store/306znyj77fv49kwnkpxmb0j2znqpa8bj-bash-5.2p26/bin/bash
+set -e
+
+mkdir -p ".testenv/config/nvim"
+mkdir -p ".testenv/data/nvim"
+mkdir -p ".testenv/state/nvim"
+mkdir -p ".testenv/run/nvim"
+mkdir -p ".testenv/cache/nvim"
+PLUGINS=".testenv/data/nvim/site/pack/plugins/start"
+
+if [ ! -e "$PLUGINS/plenary.nvim" ]; then
+ git clone --depth=1 https://github.com/nvim-lua/plenary.nvim.git "$PLUGINS/plenary.nvim"
+else
+ (cd "$PLUGINS/plenary.nvim" && git pull)
+fi
+
+if [ ! -e "$PLUGINS/nvim-treesitter" ]; then
+ git clone --depth=1 https://github.com/nvim-treesitter/nvim-treesitter.git "$PLUGINS/nvim-treesitter"
+else
+ (cd "$PLUGINS/nvim-treesitter" && git pull)
+fi
+
+XDG_CONFIG_HOME=".testenv/config" \
+ XDG_DATA_HOME=".testenv/data" \
+ XDG_STATE_HOME=".testenv/state" \
+ XDG_RUNTIME_DIR=".testenv/run" \
+ XDG_CACHE_HOME=".testenv/cache" \
+ nvim --headless -u tests/minimal_init.lua \
+ -c "RunTests ${1-tests}"
+echo "Success"
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/scripts/autoformat_doc.lua b/config/neovim/store/lazy-plugins/conform.nvim/scripts/autoformat_doc.lua
new file mode 100644
index 00000000..f6476d47
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/scripts/autoformat_doc.lua
@@ -0,0 +1,33 @@
+-- if format_on_save is a function, it will be called during BufWritePre
+require("conform").setup({
+ format_on_save = function(bufnr)
+ -- Disable autoformat on certain filetypes
+ local ignore_filetypes = { "sql", "java" }
+ if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then
+ return
+ end
+ -- Disable with a global or buffer-local variable
+ if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
+ return
+ end
+ -- Disable autoformat for files in a certain path
+ local bufname = vim.api.nvim_buf_get_name(bufnr)
+ if bufname:match("/node_modules/") then
+ return
+ end
+ -- ...additional logic...
+ return { timeout_ms = 500, lsp_fallback = true }
+ end,
+})
+
+-- There is a similar affordance for format_after_save, which uses BufWritePost.
+-- This is good for formatters that are too slow to run synchronously.
+require("conform").setup({
+ format_after_save = function(bufnr)
+ if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
+ return
+ end
+ -- ...additional logic...
+ return { lsp_fallback = true }
+ end,
+})
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/scripts/generate.py b/config/neovim/store/lazy-plugins/conform.nvim/scripts/generate.py
new file mode 100755
index 00000000..30c3b125
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/scripts/generate.py
@@ -0,0 +1,217 @@
+import os
+import os.path
+import re
+from dataclasses import dataclass
+from functools import lru_cache
+from typing import List
+
+from nvim_doc_tools import (
+ Vimdoc,
+ VimdocSection,
+ dedent,
+ generate_md_toc,
+ indent,
+ parse_directory,
+ read_nvim_json,
+ read_section,
+ render_md_api2,
+ render_vimdoc_api2,
+ replace_section,
+ wrap,
+)
+
+HERE = os.path.dirname(__file__)
+ROOT = os.path.abspath(os.path.join(HERE, os.path.pardir))
+README = os.path.join(ROOT, "README.md")
+DOC = os.path.join(ROOT, "doc")
+RECIPES = os.path.join(DOC, "recipes.md")
+ADVANCED = os.path.join(DOC, "advanced_topics.md")
+FORMATTER_OPTIONS = os.path.join(DOC, "formatter_options.md")
+VIMDOC = os.path.join(DOC, "conform.txt")
+OPTIONS = os.path.join(ROOT, "scripts", "options_doc.lua")
+AUTOFORMAT = os.path.join(ROOT, "scripts", "autoformat_doc.lua")
+
+
+@dataclass
+class Formatter:
+ name: str
+ description: str
+ url: str
+ has_options: bool
+ deprecated: bool = False
+
+
+@lru_cache
+def get_all_formatters() -> List[Formatter]:
+ formatters = []
+ formatter_map = read_nvim_json(
+ 'require("conform.formatters").list_all_formatters()'
+ )
+ for name, meta in formatter_map.items():
+ formatter = Formatter(name, **meta)
+ if not formatter.deprecated:
+ formatters.append(formatter)
+ formatters.sort(key=lambda f: f.name)
+ return formatters
+
+
+def update_formatter_list():
+ formatter_lines = ["\n"]
+ for formatter in get_all_formatters():
+ formatter_lines.append(
+ f"- [{formatter.name}]({formatter.url}) - {formatter.description}\n"
+ )
+ replace_section(
+ README,
+ r"^$",
+ r"^$",
+ formatter_lines,
+ )
+
+
+def update_options():
+ option_lines = ["\n", "```lua\n"]
+ with open(OPTIONS, "r", encoding="utf-8") as f:
+ option_lines.extend(f.readlines())
+ option_lines.extend(["```\n", "\n"])
+ replace_section(
+ README,
+ r"^$",
+ r"^$",
+ option_lines,
+ )
+
+
+def update_autocmd_md():
+ example_lines = ["\n", "```lua\n"]
+ with open(AUTOFORMAT, "r", encoding="utf-8") as f:
+ example_lines.extend(f.readlines())
+ example_lines.extend(["```\n", "\n"])
+ replace_section(
+ RECIPES,
+ r"^$",
+ r"^$",
+ example_lines,
+ )
+
+
+def update_formatter_options_md():
+ lines = ["\n"]
+ for formatter in get_all_formatters():
+ if formatter.has_options:
+ lines.extend([f"## {formatter.name}\n", "\n", "```lua\n", "options = {\n"])
+ formatter_file = os.path.join(
+ ROOT, "lua", "conform", "formatters", f"{formatter.name}.lua"
+ )
+ code = read_section(formatter_file, r"^ options = {$", r"^ },$")
+ lines.extend(dedent(code, 2))
+ lines.extend(["}\n", "```\n", "\n"])
+ replace_section(
+ FORMATTER_OPTIONS,
+ r"^$",
+ r"^$",
+ lines,
+ )
+
+
+def add_md_link_path(path: str, lines: List[str]) -> List[str]:
+ ret = []
+ for line in lines:
+ ret.append(re.sub(r"(\(#)", "(" + path + "#", line))
+ return ret
+
+
+def update_md_api():
+ types = parse_directory(os.path.join(ROOT, "lua"))
+ funcs = types.files["conform/init.lua"].functions
+ lines = ["\n"] + render_md_api2(funcs, types, 3)[:-1] # trim last newline
+ replace_section(
+ README,
+ r"^$",
+ r"^$",
+ lines,
+ )
+
+
+def update_readme_toc():
+ toc = ["\n"] + generate_md_toc(README) + ["\n"]
+ replace_section(
+ README,
+ r"^$",
+ r"^$",
+ toc,
+ )
+
+
+def update_recipes_toc():
+ toc = ["\n"] + generate_md_toc(RECIPES) + ["\n"]
+ replace_section(RECIPES, r"^$", r"^$", toc)
+ subtoc = add_md_link_path("doc/recipes.md", toc)
+ replace_section(README, r"^$", r"^$", subtoc)
+
+
+def update_advanced_toc():
+ toc = ["\n"] + generate_md_toc(ADVANCED) + ["\n"]
+ replace_section(ADVANCED, r"^$", r"^$", toc)
+ subtoc = add_md_link_path("doc/advanced_topics.md", toc)
+ replace_section(README, r"^$", r"^$", subtoc)
+
+
+def update_formatter_options_toc():
+ toc = ["\n"] + generate_md_toc(FORMATTER_OPTIONS) + ["\n"]
+ replace_section(FORMATTER_OPTIONS, r"^$", r"^$", toc)
+ subtoc = add_md_link_path("doc/formatter_options.md", toc)
+ replace_section(
+ README,
+ r"^$",
+ r"^$",
+ subtoc,
+ )
+
+
+def gen_options_vimdoc() -> VimdocSection:
+ section = VimdocSection("Options", "conform-options", ["\n", ">lua\n"])
+ with open(OPTIONS, "r", encoding="utf-8") as f:
+ section.body.extend(indent(f.readlines(), 4))
+ section.body.append("<\n")
+ return section
+
+
+def gen_formatter_vimdoc() -> VimdocSection:
+ section = VimdocSection("Formatters", "conform-formatters", ["\n"])
+ for formatter in get_all_formatters():
+ line = f"`{formatter.name}` - {formatter.description}\n"
+ section.body.extend(wrap(line, sub_indent=len(formatter.name) + 3))
+ return section
+
+
+def generate_vimdoc():
+ doc = Vimdoc("conform.txt", "conform")
+ types = parse_directory(os.path.join(ROOT, "lua"))
+ funcs = types.files["conform/init.lua"].functions
+ doc.sections.extend(
+ [
+ gen_options_vimdoc(),
+ VimdocSection(
+ "API", "conform-api", render_vimdoc_api2("conform", funcs, types)
+ ),
+ gen_formatter_vimdoc(),
+ ]
+ )
+
+ with open(VIMDOC, "w", encoding="utf-8") as ofile:
+ ofile.writelines(doc.render())
+
+
+def main() -> None:
+ """Update the README"""
+ update_formatter_list()
+ update_options()
+ update_autocmd_md()
+ update_formatter_options_md()
+ update_md_api()
+ update_recipes_toc()
+ update_advanced_toc()
+ update_formatter_options_toc()
+ update_readme_toc()
+ generate_vimdoc()
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/scripts/main.py b/config/neovim/store/lazy-plugins/conform.nvim/scripts/main.py
new file mode 100755
index 00000000..4dffddfb
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/scripts/main.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+import argparse
+import os
+import sys
+
+HERE = os.path.dirname(__file__)
+ROOT = os.path.abspath(os.path.join(HERE, os.path.pardir))
+DOC = os.path.join(ROOT, "doc")
+
+
+def main() -> None:
+ """Generate docs"""
+ sys.path.append(HERE)
+ parser = argparse.ArgumentParser(description=main.__doc__)
+ parser.add_argument("command", choices=["generate", "lint"])
+ args = parser.parse_args()
+ if args.command == "generate":
+ import generate
+
+ generate.main()
+ elif args.command == "lint":
+ from nvim_doc_tools import lint_md_links
+
+ files = [os.path.join(ROOT, "README.md")] + [
+ os.path.join(DOC, file) for file in os.listdir(DOC) if file.endswith(".md")
+ ]
+ lint_md_links.main(ROOT, files)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/scripts/options_doc.lua b/config/neovim/store/lazy-plugins/conform.nvim/scripts/options_doc.lua
new file mode 100644
index 00000000..238cd33f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/scripts/options_doc.lua
@@ -0,0 +1,93 @@
+require("conform").setup({
+ -- Map of filetype to formatters
+ formatters_by_ft = {
+ lua = { "stylua" },
+ -- Conform will run multiple formatters sequentially
+ go = { "goimports", "gofmt" },
+ -- Use a sub-list to run only the first available formatter
+ javascript = { { "prettierd", "prettier" } },
+ -- You can use a function here to determine the formatters dynamically
+ python = function(bufnr)
+ if require("conform").get_formatter_info("ruff_format", bufnr).available then
+ return { "ruff_format" }
+ else
+ return { "isort", "black" }
+ end
+ end,
+ -- Use the "*" filetype to run formatters on all filetypes.
+ ["*"] = { "codespell" },
+ -- Use the "_" filetype to run formatters on filetypes that don't
+ -- have other formatters configured.
+ ["_"] = { "trim_whitespace" },
+ },
+ -- If this is set, Conform will run the formatter on save.
+ -- It will pass the table to conform.format().
+ -- This can also be a function that returns the table.
+ format_on_save = {
+ -- I recommend these options. See :help conform.format for details.
+ lsp_fallback = true,
+ timeout_ms = 500,
+ },
+ -- If this is set, Conform will run the formatter asynchronously after save.
+ -- It will pass the table to conform.format().
+ -- This can also be a function that returns the table.
+ format_after_save = {
+ lsp_fallback = true,
+ },
+ -- Set the log level. Use `:ConformInfo` to see the location of the log file.
+ log_level = vim.log.levels.ERROR,
+ -- Conform will notify you when a formatter errors
+ notify_on_error = true,
+ -- Custom formatters and overrides for built-in formatters
+ formatters = {
+ my_formatter = {
+ -- This can be a string or a function that returns a string.
+ -- When defining a new formatter, this is the only field that is required
+ command = "my_cmd",
+ -- A list of strings, or a function that returns a list of strings
+ -- Return a single string instead of a list to run the command in a shell
+ args = { "--stdin-from-filename", "$FILENAME" },
+ -- If the formatter supports range formatting, create the range arguments here
+ range_args = function(self, ctx)
+ return { "--line-start", ctx.range.start[1], "--line-end", ctx.range["end"][1] }
+ end,
+ -- Send file contents to stdin, read new contents from stdout (default true)
+ -- When false, will create a temp file (will appear in "$FILENAME" args). The temp
+ -- file is assumed to be modified in-place by the format command.
+ stdin = true,
+ -- A function that calculates the directory to run the command in
+ cwd = require("conform.util").root_file({ ".editorconfig", "package.json" }),
+ -- When cwd is not found, don't run the formatter (default false)
+ require_cwd = true,
+ -- When stdin=false, use this template to generate the temporary file that gets formatted
+ tmpfile_format = ".conform.$RANDOM.$FILENAME",
+ -- When returns false, the formatter will not be used
+ condition = function(self, ctx)
+ return vim.fs.basename(ctx.filename) ~= "README.md"
+ end,
+ -- Exit codes that indicate success (default { 0 })
+ exit_codes = { 0, 1 },
+ -- Environment variables. This can also be a function that returns a table.
+ env = {
+ VAR = "value",
+ },
+ -- Set to false to disable merging the config with the base definition
+ inherit = true,
+ -- When inherit = true, add these additional arguments to the command.
+ -- This can also be a function, like args
+ prepend_args = { "--use-tabs" },
+ },
+ -- These can also be a function that returns the formatter
+ other_formatter = function(bufnr)
+ return {
+ command = "my_cmd",
+ }
+ end,
+ },
+})
+
+-- You can set formatters_by_ft and formatters directly
+require("conform").formatters_by_ft.lua = { "stylua" }
+require("conform").formatters.my_formatter = {
+ command = "my_cmd",
+}
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/api_spec.lua b/config/neovim/store/lazy-plugins/conform.nvim/tests/api_spec.lua
new file mode 100644
index 00000000..ea263438
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/api_spec.lua
@@ -0,0 +1,98 @@
+require("plenary.async").tests.add_to_env()
+local conform = require("conform")
+local test_util = require("tests.test_util")
+
+describe("api", function()
+ after_each(function()
+ test_util.reset_editor()
+ end)
+
+ it("retrieves info about a formatter", function()
+ local info = conform.get_formatter_info("stylua")
+ assert.equal("stylua", info.name)
+ assert.equal("stylua", info.command)
+ assert.equal("boolean", type(info.available))
+ end)
+
+ it("retrieves unavailable info if formatter does not exist", function()
+ local info = conform.get_formatter_info("asdf")
+ assert.equal("asdf", info.name)
+ assert.equal("asdf", info.command)
+ assert.falsy(info.available)
+ end)
+
+ describe("list_formatters", function()
+ local get_formatter_info = conform.get_formatter_info
+ before_each(function()
+ conform.get_formatter_info = function(...)
+ local info = get_formatter_info(...)
+ info.available = true
+ return info
+ end
+ end)
+ after_each(function()
+ conform.get_formatter_info = get_formatter_info
+ end)
+
+ it("lists all formatters configured for buffer", function()
+ conform.formatters_by_ft.lua = { "stylua", "lua-format" }
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_set_current_buf(bufnr)
+ vim.bo[bufnr].filetype = "lua"
+ local formatters = conform.list_formatters()
+ local formatter_names = vim.tbl_map(function(f)
+ return f.name
+ end, formatters)
+ assert.are.same({ "stylua", "lua-format" }, formatter_names)
+ end)
+
+ it("merges formatters from mixed filetypes", function()
+ conform.formatters_by_ft.lua = { "stylua", "lua-format" }
+ conform.formatters_by_ft["*"] = { "trim_whitespace" }
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_set_current_buf(bufnr)
+ vim.bo[bufnr].filetype = "lua"
+ local formatters = conform.list_formatters()
+ local formatter_names = vim.tbl_map(function(f)
+ return f.name
+ end, formatters)
+ assert.are.same({ "stylua", "lua-format", "trim_whitespace" }, formatter_names)
+ end)
+
+ it("flattens formatters in alternation groups", function()
+ conform.formatters_by_ft.lua = { { "stylua", "lua-format" }, "trim_whitespace" }
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_set_current_buf(bufnr)
+ vim.bo[bufnr].filetype = "lua"
+ local formatters = conform.list_formatters()
+ local formatter_names = vim.tbl_map(function(f)
+ return f.name
+ end, formatters)
+ assert.are.same({ "stylua", "trim_whitespace" }, formatter_names)
+ end)
+ end)
+
+ describe("list_all_formatters", function()
+ it("lists all formatters configured for all buffers", function()
+ conform.formatters_by_ft.lua = { "stylua", "lua-format" }
+ conform.formatters_by_ft["*"] = { "trim_whitespace" }
+ local formatters = conform.list_all_formatters()
+ local formatter_names = vim.tbl_map(function(f)
+ return f.name
+ end, formatters)
+ table.sort(formatter_names)
+ assert.are.same({ "lua-format", "stylua", "trim_whitespace" }, formatter_names)
+ end)
+
+ it("flattens formatters in alternation groups", function()
+ conform.formatters_by_ft.lua = { { "stylua", "lua-format" } }
+ conform.formatters_by_ft["*"] = { "trim_whitespace" }
+ local formatters = conform.list_all_formatters()
+ local formatter_names = vim.tbl_map(function(f)
+ return f.name
+ end, formatters)
+ table.sort(formatter_names)
+ assert.are.same({ "lua-format", "stylua", "trim_whitespace" }, formatter_names)
+ end)
+ end)
+end)
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/fake_formatter.sh b/config/neovim/store/lazy-plugins/conform.nvim/tests/fake_formatter.sh
new file mode 100755
index 00000000..9179c9c4
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/fake_formatter.sh
@@ -0,0 +1,25 @@
+#!/nix/store/306znyj77fv49kwnkpxmb0j2znqpa8bj-bash-5.2p26/bin/bash
+
+set -e
+
+CODE=0
+if [ "$1" = "--fail" ]; then
+ shift
+ echo "failure" >&2
+ CODE=1
+fi
+if [ "$1" = "--timeout" ]; then
+ shift
+ echo "timeout" >&2
+ sleep 4
+fi
+
+output_file="$1"
+
+if [ -n "$output_file" ] && [ -e "$output_file" ]; then
+ cat "$output_file"
+else
+ cat
+fi
+
+exit $CODE
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/fs_spec.lua b/config/neovim/store/lazy-plugins/conform.nvim/tests/fs_spec.lua
new file mode 100644
index 00000000..2d788c96
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/fs_spec.lua
@@ -0,0 +1,22 @@
+local fs = require("conform.fs")
+
+describe("fs", function()
+ local relative_paths = {
+ { "/home", "/home/file.txt", "file.txt" },
+ { "/home/", "/home/file.txt", "file.txt" },
+ { "/home", "/foo/file.txt", "../foo/file.txt" },
+ { "/home/foo", "/home/bar/file.txt", "../bar/file.txt" },
+ { "/home", "/file.txt", "../file.txt" },
+ { "/home", "/home/foo/file.txt", "foo/file.txt" },
+ { ".", "foo/file.txt", "foo/file.txt" },
+ { "home", "home/file.txt", "file.txt" },
+ { "home", "file.txt", "../file.txt" },
+ }
+
+ it("relative_path", function()
+ for _, paths in ipairs(relative_paths) do
+ local source, target, expected = unpack(paths)
+ assert.are.same(fs.relative_path(source, target), expected)
+ end
+ end)
+end)
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/fuzzer_spec.lua b/config/neovim/store/lazy-plugins/conform.nvim/tests/fuzzer_spec.lua
new file mode 100644
index 00000000..c47f1e50
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/fuzzer_spec.lua
@@ -0,0 +1,130 @@
+require("plenary.async").tests.add_to_env()
+local conform = require("conform")
+local log = require("conform.log")
+local runner = require("conform.runner")
+local test_util = require("tests.test_util")
+
+describe("fuzzer", function()
+ before_each(function()
+ conform.formatters.test = {
+ meta = { url = "", description = "" },
+ command = "tests/fake_formatter.sh",
+ }
+ end)
+
+ after_each(function()
+ test_util.reset_editor()
+ end)
+
+ ---@param buf_content string[]
+ ---@param expected string[]
+ ---@param opts? table
+ local function run_formatter(buf_content, expected, opts)
+ local bufnr = vim.fn.bufadd("testfile")
+ vim.fn.bufload(bufnr)
+ vim.api.nvim_set_current_buf(bufnr)
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, buf_content)
+ vim.bo[bufnr].modified = false
+ runner.apply_format(0, buf_content, expected, nil, false)
+ assert.are.same(expected, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end
+
+ local function make_word()
+ local chars = {}
+ for _ = 1, math.random(1, 10) do
+ table.insert(chars, string.char(math.random(97, 122)))
+ end
+ return table.concat(chars, "")
+ end
+
+ local function make_line()
+ local words = {}
+ for _ = 1, math.random(0, 6) do
+ table.insert(words, make_word())
+ end
+ return table.concat(words, " ")
+ end
+
+ local function make_file(num_lines)
+ local lines = {}
+ for _ = 1, math.random(1, num_lines) do
+ table.insert(lines, make_line())
+ end
+ return lines
+ end
+
+ local function do_insert(lines)
+ local idx = math.random(1, #lines + 1)
+ for _ = 1, math.random(1, 3) do
+ table.insert(lines, idx, make_line())
+ end
+ end
+
+ local function do_replace(lines)
+ local num_lines = math.random(1, math.min(3, #lines))
+ local idx = math.random(1, #lines - num_lines + 1)
+ local replacement = {}
+ local num_replace = math.random(1, 5)
+ for _ = 1, num_replace do
+ table.insert(replacement, make_line())
+ end
+ local col = math.random(1, lines[idx]:len())
+ replacement[1] = lines[idx]:sub(1, col) .. replacement[1]
+ col = math.random(1, lines[idx + num_lines - 1]:len())
+ replacement[#replacement] = replacement[#replacement] .. lines[idx + num_lines - 1]:sub(col)
+
+ for _ = 1, num_lines - num_replace do
+ table.remove(lines, idx)
+ end
+ for _ = 1, num_replace - num_lines do
+ table.insert(lines, idx, "")
+ end
+ for i = 1, num_replace do
+ lines[idx + i - 1] = replacement[i]
+ end
+ end
+
+ local function do_delete(lines)
+ local num_lines = math.random(1, 3)
+ local idx = math.random(1, #lines - num_lines)
+ for _ = 1, num_lines do
+ table.remove(lines, idx)
+ end
+ -- vim will never let the lines be empty. An empty file has a single blank line.
+ if #lines == 0 then
+ table.insert(lines, "")
+ end
+ end
+
+ local function make_edits(lines)
+ local was_empty = table.concat(lines):match("^%s*$")
+ lines = vim.deepcopy(lines)
+ for _ = 1, math.random(0, 3) do
+ do_insert(lines)
+ end
+ for _ = 1, math.random(0, 3) do
+ do_replace(lines)
+ end
+ for _ = 1, math.random(0, 3) do
+ do_delete(lines)
+ end
+ -- avoid blank output (whitepsace only) which is ignored when applying formatting
+ if not was_empty then
+ while table.concat(lines):match("^%s*$") do
+ do_replace(lines)
+ end
+ end
+ return lines
+ end
+
+ it("formats correctly", function()
+ -- log.level = vim.log.levels.TRACE
+ for i = 1, 50000 do
+ math.randomseed(i)
+ log.info("Fuzz testing with seed %d", i)
+ local content = make_file(20)
+ local formatted = make_edits(content)
+ run_formatter(content, formatted)
+ end
+ end)
+end)
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/block_quote.md b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/block_quote.md
new file mode 100644
index 00000000..cd56ae88
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/block_quote.md
@@ -0,0 +1,5 @@
+text
+
+> ```lua
+> local foo = 'bar'
+> ```
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/block_quote.md.formatted b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/block_quote.md.formatted
new file mode 100644
index 00000000..f7728013
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/block_quote.md.formatted
@@ -0,0 +1,5 @@
+text
+
+> ```lua
+> |local foo = 'bar'|
+> ```
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/combined_injections.md b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/combined_injections.md
new file mode 100644
index 00000000..47aeeb49
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/combined_injections.md
@@ -0,0 +1,14 @@
+text
+
+
+
+```lua
+local foo = 'bar'
+```
+
+
+
+
+```lua
+local foo = 'bar'
+```
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/combined_injections.md.formatted b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/combined_injections.md.formatted
new file mode 100644
index 00000000..50dea5fb
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/combined_injections.md.formatted
@@ -0,0 +1,14 @@
+text
+
+||
+
+```lua
+|local foo = 'bar'|
+```
+
+
+||
+
+```lua
+|local foo = 'bar'|
+```
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/inline.ts b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/inline.ts
new file mode 100644
index 00000000..88478fd9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/inline.ts
@@ -0,0 +1,9 @@
+foo.innerHTML = ` hello
`;
+
+bar.innerHTML = `
+ world
+`;
+
+baz.innerHTML = `
+ world
+ `;
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/inline.ts.formatted b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/inline.ts.formatted
new file mode 100644
index 00000000..7763c1b9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/inline.ts.formatted
@@ -0,0 +1,9 @@
+foo.innerHTML = `| hello
|`;
+
+bar.innerHTML = `
+| world
|
+`;
+
+baz.innerHTML = `
+ | world
|
+ `;
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/simple.md b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/simple.md
new file mode 100644
index 00000000..c9685d78
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/simple.md
@@ -0,0 +1,5 @@
+text
+
+```lua
+local foo = "bar"
+```
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/simple.md.formatted b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/simple.md.formatted
new file mode 100644
index 00000000..4f68718a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected/simple.md.formatted
@@ -0,0 +1,5 @@
+text
+
+```lua
+|local foo = "bar"|
+```
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/injected_spec.lua b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected_spec.lua
new file mode 100644
index 00000000..f6c7175f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/injected_spec.lua
@@ -0,0 +1,88 @@
+require("plenary.async").tests.add_to_env()
+local conform = require("conform")
+local injected = require("conform.formatters.injected")
+local runner = require("conform.runner")
+local test_util = require("tests.test_util")
+
+-- injected formatter only supported on neovim 0.9+
+if vim.fn.has("nvim-0.9") == 0 then
+ return
+end
+
+---@param dir string
+---@return string[]
+local function list_test_files(dir)
+ ---@diagnostic disable-next-line: param-type-mismatch
+ local fd = vim.loop.fs_opendir(dir, nil, 32)
+ ---@diagnostic disable-next-line: param-type-mismatch
+ local entries = vim.loop.fs_readdir(fd)
+ local ret = {}
+ while entries do
+ for _, entry in ipairs(entries) do
+ if entry.type == "file" and not vim.endswith(entry.name, ".formatted") then
+ table.insert(ret, entry.name)
+ end
+ end
+ ---@diagnostic disable-next-line: param-type-mismatch
+ entries = vim.loop.fs_readdir(fd)
+ end
+ ---@diagnostic disable-next-line: param-type-mismatch
+ vim.loop.fs_closedir(fd)
+ return ret
+end
+
+describe("injected formatter", function()
+ before_each(function()
+ -- require("conform.log").level = vim.log.levels.TRACE
+ conform.formatters_by_ft = {
+ lua = { "test_mark" },
+ html = { "test_mark" },
+ }
+ -- A test formatter that bookends lines with "|" so we can check what was passed in
+ conform.formatters.test_mark = {
+ format = function(self, ctx, lines, callback)
+ local ret = {}
+ for i, line in ipairs(lines) do
+ if i == 1 and line == "" then
+ -- Simulate formatters removing starting newline
+ elseif i == #lines and line == "" then
+ -- Simulate formatters removing trailing newline
+ else
+ table.insert(ret, "|" .. line .. "|")
+ end
+ end
+ callback(nil, ret)
+ end,
+ }
+ end)
+
+ after_each(function()
+ test_util.reset_editor()
+ end)
+
+ for _, filename in ipairs(list_test_files("tests/injected")) do
+ local filepath = "./tests/injected/" .. filename
+ local formatted_file = filepath .. ".formatted"
+ it(filename, function()
+ local bufnr = vim.fn.bufadd(filepath)
+ vim.fn.bufload(bufnr)
+ local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
+ local config = assert(conform.get_formatter_config("injected", bufnr))
+ local ctx = runner.build_context(bufnr, config)
+ local err, new_lines, done
+ injected.format(injected, ctx, lines, function(e, formatted)
+ done = true
+ err = e
+ new_lines = formatted
+ end)
+ vim.wait(1000, function()
+ return done
+ end)
+ assert(err == nil, err)
+ local expected_bufnr = vim.fn.bufadd(formatted_file)
+ vim.fn.bufload(expected_bufnr)
+ local expected_lines = vim.api.nvim_buf_get_lines(expected_bufnr, 0, -1, true)
+ assert.are.same(expected_lines, new_lines)
+ end)
+ end
+end)
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/minimal_init.lua b/config/neovim/store/lazy-plugins/conform.nvim/tests/minimal_init.lua
new file mode 100644
index 00000000..0afbd90d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/minimal_init.lua
@@ -0,0 +1,21 @@
+vim.cmd([[set runtimepath+=.]])
+
+vim.o.swapfile = false
+vim.bo.swapfile = false
+require("tests.test_util").reset_editor()
+
+local configs = require("nvim-treesitter.configs")
+configs.setup({
+ ensure_installed = { "markdown", "markdown_inline", "lua", "typescript", "html" },
+ sync_install = true,
+})
+-- this needs to be run a second time to make tests behave
+require("nvim-treesitter").setup()
+
+vim.api.nvim_create_user_command("RunTests", function(opts)
+ local path = opts.fargs[1] or "tests"
+ require("plenary.test_harness").test_directory(
+ path,
+ { minimal_init = "./tests/minimal_init.lua" }
+ )
+end, { nargs = "?" })
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/runner_spec.lua b/config/neovim/store/lazy-plugins/conform.nvim/tests/runner_spec.lua
new file mode 100644
index 00000000..8c0dadfb
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/runner_spec.lua
@@ -0,0 +1,389 @@
+require("plenary.async").tests.add_to_env()
+local conform = require("conform")
+local runner = require("conform.runner")
+local test_util = require("tests.test_util")
+local util = require("conform.util")
+
+describe("runner", function()
+ local OUTPUT_FILE
+ local CLEANUP_FILES = {}
+
+ ---@param lines string[]
+ local function set_formatter_output(lines)
+ local fd, output_file = vim.loop.fs_mkstemp(".testenv/outputXXXXXXXXX")
+ assert(type(fd) == "number" and output_file, fd)
+ local content = table.concat(lines, "\n")
+ vim.loop.fs_write(fd, content)
+ -- Make sure we add the final newline
+ vim.loop.fs_write(fd, "\n")
+ vim.loop.fs_fsync(fd)
+ vim.loop.fs_close(fd)
+ OUTPUT_FILE = output_file
+ table.insert(CLEANUP_FILES, output_file)
+ end
+
+ after_each(function()
+ test_util.reset_editor()
+ OUTPUT_FILE = nil
+ for _, file in ipairs(CLEANUP_FILES) do
+ if vim.loop.fs_stat(file) then
+ vim.loop.fs_unlink(file)
+ end
+ end
+ CLEANUP_FILES = {}
+ end)
+
+ it("resolves config function", function()
+ conform.formatters.test = function()
+ return {
+ meta = { url = "", description = "" },
+ command = "echo",
+ }
+ end
+ local config = assert(conform.get_formatter_config("test"))
+ assert.are.same({
+ meta = { url = "", description = "" },
+ command = "echo",
+ stdin = true,
+ }, config)
+ end)
+
+ describe("build_context", function()
+ it("sets the filename and dirname", function()
+ vim.cmd.edit({ args = { "README.md" } })
+ local bufnr = vim.api.nvim_get_current_buf()
+ conform.formatters.test = {
+ meta = { url = "", description = "" },
+ command = "echo",
+ }
+ local config = assert(conform.get_formatter_config("test"))
+ local ctx = runner.build_context(0, config)
+ local filename = vim.api.nvim_buf_get_name(bufnr)
+ assert.are.same({
+ buf = bufnr,
+ filename = filename,
+ dirname = vim.fs.dirname(filename),
+ }, ctx)
+ end)
+
+ it("sets temp file when stdin = false", function()
+ vim.cmd.edit({ args = { "README.md" } })
+ local bufnr = vim.api.nvim_get_current_buf()
+ conform.formatters.test = {
+ meta = { url = "", description = "" },
+ command = "echo",
+ stdin = false,
+ }
+ local config = assert(conform.get_formatter_config("test"))
+ local ctx = runner.build_context(0, config)
+ local bufname = vim.api.nvim_buf_get_name(bufnr)
+ local dirname = vim.fs.dirname(bufname)
+ assert.equal(bufnr, ctx.buf)
+ assert.equal(dirname, ctx.dirname)
+ assert.truthy(ctx.filename:match(dirname .. "/.conform.%d+.README.md$"))
+ end)
+ end)
+
+ describe("build_cmd", function()
+ it("replaces $FILENAME in args", function()
+ vim.cmd.edit({ args = { "README.md" } })
+ local bufnr = vim.api.nvim_get_current_buf()
+ conform.formatters.test = {
+ meta = { url = "", description = "" },
+ command = "echo",
+ args = { "$FILENAME" },
+ }
+ local config = assert(conform.get_formatter_config("test"))
+ local ctx = runner.build_context(0, config)
+ local cmd = runner.build_cmd("", ctx, config)
+ assert.are.same({ "echo", vim.api.nvim_buf_get_name(bufnr) }, cmd)
+ end)
+
+ it("replaces $DIRNAME in args", function()
+ vim.cmd.edit({ args = { "README.md" } })
+ local bufnr = vim.api.nvim_get_current_buf()
+ conform.formatters.test = {
+ meta = { url = "", description = "" },
+ command = "echo",
+ args = { "$DIRNAME" },
+ }
+ local config = assert(conform.get_formatter_config("test"))
+ local ctx = runner.build_context(0, config)
+ local cmd = runner.build_cmd("", ctx, config)
+ assert.are.same({ "echo", vim.fs.dirname(vim.api.nvim_buf_get_name(bufnr)) }, cmd)
+ end)
+
+ it("resolves arg function", function()
+ vim.cmd.edit({ args = { "README.md" } })
+ conform.formatters.test = {
+ meta = { url = "", description = "" },
+ command = "echo",
+ args = function()
+ return { "--stdin" }
+ end,
+ }
+ local config = assert(conform.get_formatter_config("test"))
+ local ctx = runner.build_context(0, config)
+ local cmd = runner.build_cmd("", ctx, config)
+ assert.are.same({ "echo", "--stdin" }, cmd)
+ end)
+
+ it("replaces $FILENAME in string args", function()
+ vim.cmd.edit({ args = { "README.md" } })
+ local bufnr = vim.api.nvim_get_current_buf()
+ conform.formatters.test = {
+ meta = { url = "", description = "" },
+ command = "echo",
+ args = "$FILENAME | patch",
+ }
+ local config = assert(conform.get_formatter_config("test"))
+ local ctx = runner.build_context(0, config)
+ local cmd = runner.build_cmd("", ctx, config)
+ assert.equal("echo " .. vim.api.nvim_buf_get_name(bufnr) .. " | patch", cmd)
+ end)
+
+ it("replaces $DIRNAME in string args", function()
+ vim.cmd.edit({ args = { "README.md" } })
+ local bufnr = vim.api.nvim_get_current_buf()
+ conform.formatters.test = {
+ meta = { url = "", description = "" },
+ command = "echo",
+ args = "$DIRNAME | patch",
+ }
+ local config = assert(conform.get_formatter_config("test"))
+ local ctx = runner.build_context(0, config)
+ local cmd = runner.build_cmd("", ctx, config)
+ assert.equal("echo " .. vim.fs.dirname(vim.api.nvim_buf_get_name(bufnr)) .. " | patch", cmd)
+ end)
+
+ it("resolves arg function with string results", function()
+ vim.cmd.edit({ args = { "README.md" } })
+ conform.formatters.test = {
+ meta = { url = "", description = "" },
+ command = "echo",
+ args = function()
+ return "| patch"
+ end,
+ }
+ local config = assert(conform.get_formatter_config("test"))
+ local ctx = runner.build_context(0, config)
+ local cmd = runner.build_cmd("", ctx, config)
+ assert.equal("echo | patch", cmd)
+ end)
+ end)
+
+ describe("e2e", function()
+ before_each(function()
+ conform.formatters.test = {
+ command = "tests/fake_formatter.sh",
+ args = function()
+ if OUTPUT_FILE then
+ return { OUTPUT_FILE }
+ end
+ return {}
+ end,
+ }
+ end)
+
+ ---@param buf_content string
+ ---@param expected string
+ ---@param opts? table
+ local function run_formatter(buf_content, expected, opts)
+ local bufnr = vim.fn.bufadd("testfile")
+ vim.fn.bufload(bufnr)
+ vim.api.nvim_set_current_buf(bufnr)
+ local lines = vim.split(buf_content, "\n", { plain = true })
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, lines)
+ vim.bo[bufnr].modified = false
+ local expected_lines = vim.split(expected, "\n", { plain = true })
+ set_formatter_output(expected_lines)
+ conform.format(vim.tbl_extend("keep", opts or {}, { formatters = { "test" }, quiet = true }))
+ return expected_lines
+ end
+
+ ---@param buf_content string
+ ---@param new_content string
+ local function run_formatter_test(buf_content, new_content)
+ local lines = run_formatter(buf_content, new_content)
+ assert.are.same(lines, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end
+
+ it("sets the correct output", function()
+ run_formatter_test(
+ [[
+ if true {
+ print("hello")
+ }]],
+ [[
+ if true {
+ print("hello")
+ }]]
+ )
+ run_formatter_test(
+ [[
+ if true {
+ print("hello")
+ }]],
+ [[
+ if true {
+ print("goodbye")
+ }]]
+ )
+ run_formatter_test(
+ [[
+ if true {
+ print("hello")
+ }]],
+ [[
+ if true {
+ print("hello world")
+ print("hello world")
+ print("hello world")
+ }]]
+ )
+ run_formatter_test(
+ [[
+print("a")
+print("b")
+print("c")
+ ]],
+ [[
+print("c")
+print("b")
+print("a")
+ ]]
+ )
+ run_formatter_test("hello\ngoodbye", "hello\n\n\ngoodbye")
+ run_formatter_test("hello", "hello\ngoodbye")
+ run_formatter_test("hello\ngoodbye", "hello")
+ run_formatter_test("", "hello")
+ run_formatter_test("\nfoo", "\nhello\nfoo")
+ run_formatter_test("hello", "hello\n")
+ run_formatter_test("hello", "hello\n\n")
+ run_formatter_test("hello\n", "hello")
+ run_formatter_test("hello\n ", "hello")
+
+ -- These should generate no changes to the buffer
+ run_formatter_test("hello\n", "hello\n")
+ assert.falsy(vim.bo.modified)
+ run_formatter_test("hello", "hello")
+ assert.falsy(vim.bo.modified)
+ end)
+
+ it("does not change output if formatter fails", function()
+ conform.formatters.test.args = util.extend_args(conform.formatters.test.args, { "--fail" })
+ run_formatter("hello", "goodbye")
+ assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+
+ it("allows nonzero exit codes", function()
+ conform.formatters.test.args = util.extend_args(conform.formatters.test.args, { "--fail" })
+ conform.formatters.test.exit_codes = { 0, 1 }
+ run_formatter_test("hello", "goodbye")
+ end)
+
+ it("does not format if it times out", function()
+ conform.formatters.test.args = util.extend_args(conform.formatters.test.args, { "--timeout" })
+ run_formatter("hello", "goodbye", { timeout_ms = 10 })
+ assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+
+ it("can format async", function()
+ run_formatter("hello", "goodbye", { async = true })
+ assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ vim.wait(1000, function()
+ return vim.api.nvim_buf_get_lines(0, 0, -1, false)[1] == "goodbye"
+ end)
+ assert.are.same({ "goodbye" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+
+ it("discards formatting changes if buffer has been concurrently modified", function()
+ run_formatter("hello", "goodbye", { async = true })
+ assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ vim.api.nvim_buf_set_lines(0, 0, -1, true, { "newcontent" })
+ vim.wait(1000, function()
+ return vim.api.nvim_buf_get_lines(0, 0, -1, false)[1] == "newcontent"
+ end)
+ assert.are.same({ "newcontent" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+
+ it("discards formatting changes if formatter output is empty /w non-empty input", function()
+ local bufnr = vim.fn.bufadd("testfile")
+ vim.fn.bufload(bufnr)
+ vim.api.nvim_set_current_buf(bufnr)
+ local original_lines = { "line one", "line two" }
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, original_lines)
+ vim.bo[bufnr].modified = false
+ set_formatter_output({ "" })
+ conform.format({ formatters = { "test" }, quiet = true })
+ local output_lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
+ assert.are.same(original_lines, output_lines)
+ end)
+
+ it("formats on save", function()
+ conform.setup({
+ formatters_by_ft = { ["*"] = { "test" } },
+ format_on_save = true,
+ })
+ vim.cmd.edit({ args = { "tests/testfile.txt" } })
+ vim.api.nvim_buf_set_lines(0, 0, -1, true, { "hello" })
+ set_formatter_output({ "goodbye" })
+ vim.cmd.write()
+ local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
+ vim.fn.delete("tests/testfile.txt")
+ assert.are.same({ "goodbye" }, lines)
+ end)
+
+ it("formats file even if one formatter errors", function()
+ conform.formatters.test2 = {
+ command = "tests/fake_formatter.sh",
+ args = { "--fail" },
+ }
+ local lines = run_formatter("hello", "goodbye", { formatters = { "test2", "test" } })
+ assert.are.same(lines, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+
+ it("does not change output if dry_run is true", function()
+ run_formatter("hello", "foo", { dry_run = true })
+ assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+
+ describe("range formatting", function()
+ it("applies edits that overlap the range start", function()
+ run_formatter(
+ "a\nb\nc",
+ "d\nb\nd",
+ { range = {
+ start = { 1, 0 },
+ ["end"] = { 2, 0 },
+ } }
+ )
+ assert.are.same({ "d", "b", "c" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+
+ it("applies edits that overlap the range end", function()
+ run_formatter(
+ "a\nb\nc",
+ "d\nb\nd",
+ { range = {
+ start = { 3, 0 },
+ ["end"] = { 3, 1 },
+ } }
+ )
+ assert.are.same({ "a", "b", "d" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+
+ it("applies edits that are completely contained by the range", function()
+ run_formatter(
+ "a\nb\nc",
+ "a\nd\nc",
+ { range = {
+ start = { 1, 0 },
+ ["end"] = { 3, 0 },
+ } }
+ )
+ assert.are.same({ "a", "d", "c" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+ end)
+ end)
+end)
diff --git a/config/neovim/store/lazy-plugins/conform.nvim/tests/test_util.lua b/config/neovim/store/lazy-plugins/conform.nvim/tests/test_util.lua
new file mode 100644
index 00000000..7e132388
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/conform.nvim/tests/test_util.lua
@@ -0,0 +1,24 @@
+require("plenary.async").tests.add_to_env()
+local conform = require("conform")
+local log = require("conform.log")
+local M = {}
+
+M.reset_editor = function()
+ vim.cmd.tabonly({ mods = { silent = true } })
+ for i, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
+ if i > 1 then
+ vim.api.nvim_win_close(winid, true)
+ end
+ end
+ vim.api.nvim_win_set_buf(0, vim.api.nvim_create_buf(false, true))
+ for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
+ vim.api.nvim_buf_delete(bufnr, { force = true })
+ end
+ conform.formatters = {}
+ conform.formatters_by_ft = {}
+ pcall(vim.api.nvim_del_augroup_by_name, "Conform")
+ log.level = vim.log.levels.ERROR
+ log.set_handler(print)
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/.github/ISSUE_TEMPLATE/bug_report.yml b/config/neovim/store/lazy-plugins/flash.nvim/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 00000000..72230e7f
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,89 @@
+name: Bug Report
+description: File a bug/issue
+title: "bug: "
+labels: [bug]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ **Before** reporting an issue, make sure to read the [documentation](https://github.com/folke/flash.nvim) and search [existing issues](https://github.com/folke/flash.nvim/issues). Usage questions such as ***"How do I...?"*** belong in [Discussions](https://github.com/folke/flash.nvim/discussions) and will be closed.
+ - type: checkboxes
+ attributes:
+ label: Did you check docs and existing issues?
+ description: Make sure you checked all of the below before submitting an issue
+ options:
+ - label: I have read all the flash.nvim docs
+ required: true
+ - label: I have searched the existing issues of flash.nvim
+ required: true
+ - label: I have searched the existing issues of plugins related to this issue
+ required: true
+ - type: input
+ attributes:
+ label: "Neovim version (nvim -v)"
+ placeholder: "0.8.0 commit db1b0ee3b30f"
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: "Operating system/version"
+ placeholder: "MacOS 11.5"
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe the bug
+ description: A clear and concise description of what the bug is. Please include any related errors you see in Neovim.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Steps To Reproduce
+ description: Steps to reproduce the behavior.
+ placeholder: |
+ 1.
+ 2.
+ 3.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Expected Behavior
+ description: A concise description of what you expected to happen.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Repro
+ description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
+ value: |
+ -- DO NOT change the paths and don't remove the colorscheme
+ local root = vim.fn.fnamemodify("./.repro", ":p")
+
+ -- set stdpaths to use .repro
+ for _, name in ipairs({ "config", "data", "state", "cache" }) do
+ vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
+ end
+
+ -- bootstrap lazy
+ local lazypath = root .. "/plugins/lazy.nvim"
+ if not vim.loop.fs_stat(lazypath) then
+ vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
+ end
+ vim.opt.runtimepath:prepend(lazypath)
+
+ -- install plugins
+ local plugins = {
+ "folke/tokyonight.nvim",
+ { "folke/flash.nvim", opts = {} },
+ -- add any other plugins here
+ }
+ require("lazy").setup(plugins, {
+ root = root .. "/plugins",
+ })
+
+ vim.cmd.colorscheme("tokyonight")
+ -- add anything else here
+ render: Lua
+ validations:
+ required: false
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/.github/ISSUE_TEMPLATE/feature_request.yml b/config/neovim/store/lazy-plugins/flash.nvim/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 00000000..b53d2593
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,36 @@
+name: Feature Request
+description: Suggest a new feature
+title: "feature: "
+labels: [enhancement]
+body:
+ - type: checkboxes
+ attributes:
+ label: Did you check the docs?
+ description: Make sure you read all the docs before submitting a feature request
+ options:
+ - label: I have read all the flash.nvim docs
+ required: true
+ - type: textarea
+ validations:
+ required: true
+ attributes:
+ label: Is your feature request related to a problem? Please describe.
+ description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+ - type: textarea
+ validations:
+ required: true
+ attributes:
+ label: Describe the solution you'd like
+ description: A clear and concise description of what you want to happen.
+ - type: textarea
+ validations:
+ required: true
+ attributes:
+ label: Describe alternatives you've considered
+ description: A clear and concise description of any alternative solutions or features you've considered.
+ - type: textarea
+ validations:
+ required: false
+ attributes:
+ label: Additional context
+ description: Add any other context or screenshots about the feature request here.
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/.github/workflows/ci.yml b/config/neovim/store/lazy-plugins/flash.nvim/.github/workflows/ci.yml
new file mode 100644
index 00000000..12ed564d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/.github/workflows/ci.yml
@@ -0,0 +1,72 @@
+name: CI
+on:
+ push:
+ pull_request:
+
+jobs:
+ tests:
+ strategy:
+ matrix:
+ # os: [ubuntu-latest, windows-latest]
+ os: [ubuntu-latest]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install Neovim
+ shell: bash
+ run: |
+ mkdir -p /tmp/nvim
+ wget -q https://github.com/neovim/neovim/releases/download/nightly/nvim.appimage -O /tmp/nvim/nvim.appimage
+ cd /tmp/nvim
+ chmod a+x ./nvim.appimage
+ ./nvim.appimage --appimage-extract
+ echo "/tmp/nvim/squashfs-root/usr/bin/" >> $GITHUB_PATH
+ - name: Run Tests
+ run: |
+ nvim --version
+ [ ! -d tests ] && exit 0
+ nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.lua', sequential = true}"
+ docs:
+ runs-on: ubuntu-latest
+ needs: tests
+ if: ${{ github.ref == 'refs/heads/main' }}
+ steps:
+ - uses: actions/checkout@v3
+ - name: panvimdoc
+ uses: kdheepak/panvimdoc@main
+ with:
+ vimdoc: flash.nvim
+ version: "Neovim >= 0.8.0"
+ demojify: true
+ treesitter: true
+ - name: Push changes
+ uses: stefanzweifel/git-auto-commit-action@v4
+ with:
+ commit_message: "chore(build): auto-generate vimdoc"
+ commit_user_name: "github-actions[bot]"
+ commit_user_email: "github-actions[bot]@users.noreply.github.com"
+ commit_author: "github-actions[bot] "
+ release:
+ name: release
+ if: ${{ github.ref == 'refs/heads/main' }}
+ needs:
+ - docs
+ - tests
+ runs-on: ubuntu-latest
+ steps:
+ - uses: google-github-actions/release-please-action@v3
+ id: release
+ with:
+ release-type: simple
+ package-name: flash.nvim
+ - uses: actions/checkout@v3
+ - name: tag stable versions
+ if: ${{ steps.release.outputs.release_created }}
+ run: |
+ git config user.name github-actions[bot]
+ git config user.email github-actions[bot]@users.noreply.github.com
+ git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/google-github-actions/release-please-action.git"
+ git tag -d stable || true
+ git push origin :stable || true
+ git tag -a stable -m "Last Stable Release"
+ git push origin stable
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/.gitignore b/config/neovim/store/lazy-plugins/flash.nvim/.gitignore
new file mode 100644
index 00000000..cc5457ab
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/.gitignore
@@ -0,0 +1,8 @@
+tt.*
+.tests
+doc/tags
+debug
+.repro
+foo.*
+*.log
+data
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/.neoconf.json b/config/neovim/store/lazy-plugins/flash.nvim/.neoconf.json
new file mode 100644
index 00000000..bbc416f2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/.neoconf.json
@@ -0,0 +1,10 @@
+{
+ "neodev": {
+ "library": {
+ "plugins": [
+ "plenary.nvim",
+ "lazy.nvim"
+ ]
+ }
+ }
+}
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/CHANGELOG.md b/config/neovim/store/lazy-plugins/flash.nvim/CHANGELOG.md
new file mode 100644
index 00000000..9c0e3e19
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/CHANGELOG.md
@@ -0,0 +1,474 @@
+# Changelog
+
+## [1.18.3](https://github.com/folke/flash.nvim/compare/v1.18.2...v1.18.3) (2024-05-03)
+
+
+### Bug Fixes
+
+* **hacks:** use `vim.api.nvim__redraw` to fix the cursor instead of ffi. Fixes [#333](https://github.com/folke/flash.nvim/issues/333) ([1b128ff](https://github.com/folke/flash.nvim/commit/1b128ff527c3938460ef83fe6403ce6ce3f53b53))
+
+## [1.18.2](https://github.com/folke/flash.nvim/compare/v1.18.1...v1.18.2) (2023-10-17)
+
+
+### Bug Fixes
+
+* **treesitter:** show warning when treesitter not available. Fixes [#261](https://github.com/folke/flash.nvim/issues/261) ([77c66d8](https://github.com/folke/flash.nvim/commit/77c66d84be3e2a2ef2e6689de668fe156af74498))
+
+## [1.18.1](https://github.com/folke/flash.nvim/compare/v1.18.0...v1.18.1) (2023-10-16)
+
+
+### Bug Fixes
+
+* **char:** allow setting autohide=true for char mode. Fixes [#231](https://github.com/folke/flash.nvim/issues/231) ([71040c8](https://github.com/folke/flash.nvim/commit/71040c87bd64d2719727006f51f8679352eb6146))
+* **jump:** send `esc` when cancelling flash. Fixes [#212](https://github.com/folke/flash.nvim/issues/212). Fixes [#233](https://github.com/folke/flash.nvim/issues/233) ([677eb59](https://github.com/folke/flash.nvim/commit/677eb59f0a94ed3b735168d9e6738723fd44796d))
+* **treesitter:** include treesitter injections. Fixes [#242](https://github.com/folke/flash.nvim/issues/242) ([5fe47ba](https://github.com/folke/flash.nvim/commit/5fe47baf1be05ea34abb6912ed89a5a17cbf5661))
+* **treesitter:** keep treesitter sorting when doing ;,. Fixes [#219](https://github.com/folke/flash.nvim/issues/219) ([aae8352](https://github.com/folke/flash.nvim/commit/aae83521091fac904b8584bb2dffe13420b7adc7))
+
+## [1.18.0](https://github.com/folke/flash.nvim/compare/v1.17.3...v1.18.0) (2023-10-02)
+
+
+### Features
+
+* **char:** allow disabling clever-f motions. Fixes [#245](https://github.com/folke/flash.nvim/issues/245) ([bc1f49f](https://github.com/folke/flash.nvim/commit/bc1f49f428655b645948a3489bf0efcded6f46e6))
+* enable multi window in vscode ([#230](https://github.com/folke/flash.nvim/issues/230)) ([65bd3ee](https://github.com/folke/flash.nvim/commit/65bd3ee715229fecdb5a9727e8dcd099c187622b))
+* **highlight:** allow overriding flash cursor hl. Fixes [#228](https://github.com/folke/flash.nvim/issues/228) ([79d67c6](https://github.com/folke/flash.nvim/commit/79d67c6d29cd3d784eb5f1410ba057e1f1499fe9))
+
+
+### Bug Fixes
+
+* **char:** disable jump labels when reg recording/executing ([#226](https://github.com/folke/flash.nvim/issues/226)) ([503b0ab](https://github.com/folke/flash.nvim/commit/503b0ab0091776d2c40541507114ff4b2f24f5b9))
+* **jump:** only open folds containing match. Fixes [#224](https://github.com/folke/flash.nvim/issues/224). Fixes [#225](https://github.com/folke/flash.nvim/issues/225) ([a74d31f](https://github.com/folke/flash.nvim/commit/a74d31ffec4a6e9feb6adc33efdba247d5d912f0))
+* **search:** allow disabling multi window for search. Fixes [#198](https://github.com/folke/flash.nvim/issues/198). Fixes [#197](https://github.com/folke/flash.nvim/issues/197) ([0256d8e](https://github.com/folke/flash.nvim/commit/0256d8ecab33a9aa69fdaaf885db22e1103e2a3a))
+* **state:** use actions instead of opts.actions ([30442c8](https://github.com/folke/flash.nvim/commit/30442c88b817b5d00fcbe2f88977bbd5d0221a20))
+
+## [1.17.3](https://github.com/folke/flash.nvim/compare/v1.17.2...v1.17.3) (2023-07-20)
+
+
+### Bug Fixes
+
+* **jump:** disable operator keymaps when replaying remote. Fixes [#165](https://github.com/folke/flash.nvim/issues/165) ([9f30d48](https://github.com/folke/flash.nvim/commit/9f30d48e2f509723e59c5b0915f343ce297cf386))
+
+## [1.17.2](https://github.com/folke/flash.nvim/compare/v1.17.1...v1.17.2) (2023-07-18)
+
+
+### Bug Fixes
+
+* **char:** only use c for first search (of count) when current=true ([c92ecbf](https://github.com/folke/flash.nvim/commit/c92ecbff98fdc8770c283aa3934349e6889195dd))
+* **config:** run `setup` when using flash and it wasn't run yet. Fixes [#162](https://github.com/folke/flash.nvim/issues/162) ([c81e0d1](https://github.com/folke/flash.nvim/commit/c81e0d11b9e6e1279321e12a5d87dd3fac593854))
+* **state:** feed char when incremental and no match. Fixes [#57](https://github.com/folke/flash.nvim/issues/57) ([925f733](https://github.com/folke/flash.nvim/commit/925f733a731f8ed351e47d434e3a353995761012))
+
+## [1.17.1](https://github.com/folke/flash.nvim/compare/v1.17.0...v1.17.1) (2023-07-16)
+
+
+### Bug Fixes
+
+* **char:** fix current for tT when count=0. Fixes [#159](https://github.com/folke/flash.nvim/issues/159) ([8604b56](https://github.com/folke/flash.nvim/commit/8604b562d919772dc161ac831dd7bfa948833fdd))
+* **char:** never add mappings for mapleader and maplocalleader ([6e3dab6](https://github.com/folke/flash.nvim/commit/6e3dab6b011bb7661b16e14dd4aa4215894c9291))
+* **char:** never overwrite existing mappings for ; and , ([abda6b8](https://github.com/folke/flash.nvim/commit/abda6b848bb11051e6a789f8a8572da3d3840bf1))
+* **char:** reset including current for tT searches. Fixes [#152](https://github.com/folke/flash.nvim/issues/152) ([9c53dad](https://github.com/folke/flash.nvim/commit/9c53dad391801acb9ce9aa49820f15f6692aec91))
+* **highlight:** set hl of target to current if it's a single character only. See [#158](https://github.com/folke/flash.nvim/issues/158) ([47d147b](https://github.com/folke/flash.nvim/commit/47d147b9527025b2ee73631b098edb5798afef4b))
+* **remote:** properly pass register for remote ops. Fixes [#156](https://github.com/folke/flash.nvim/issues/156) ([34cf6f6](https://github.com/folke/flash.nvim/commit/34cf6f685d2eabc8de438fdbaa41c8c17e9da459))
+
+## [1.17.0](https://github.com/folke/flash.nvim/compare/v1.16.0...v1.17.0) (2023-07-14)
+
+
+### Features
+
+* **labels:** allow disabling reusing labels. Closes [#147](https://github.com/folke/flash.nvim/issues/147) ([4b73e61](https://github.com/folke/flash.nvim/commit/4b73e6124f4e9b44713cb85ec5db3809923d2374))
+
+
+### Bug Fixes
+
+* **char:** properly exit op mode when doing esc with ftFT and jump labels ([4731cc4](https://github.com/folke/flash.nvim/commit/4731cc47459f66f9a73d19e11ea157e105384fd6))
+* **char:** set inclusive=false for FT. Fixes [#149](https://github.com/folke/flash.nvim/issues/149) ([b1af2b7](https://github.com/folke/flash.nvim/commit/b1af2b78b30e814c08840a5bb7f7ccef726ea771))
+* **jump:** better way to cancel operator pending mode ([4a980ea](https://github.com/folke/flash.nvim/commit/4a980ea7fedf20c902375fe7aa1141d671b0ffa7))
+
+## [1.16.0](https://github.com/folke/flash.nvim/compare/v1.15.0...v1.16.0) (2023-07-12)
+
+
+### Features
+
+* **fold:** show first label inside a fold on the folded text line. Fixes [#39](https://github.com/folke/flash.nvim/issues/39) ([2846324](https://github.com/folke/flash.nvim/commit/28463247f21a6e0b5486dc6d31c7ace0e43a4877))
+* **jump:** open folds when jumping to a folded position. See [#39](https://github.com/folke/flash.nvim/issues/39) ([dcb494c](https://github.com/folke/flash.nvim/commit/dcb494cfa79aae32e17a44026591564793b75434))
+* **search:** when nohlsearch=false, matches will now be shown after jump. Fixes [#142](https://github.com/folke/flash.nvim/issues/142) ([6e7d6c2](https://github.com/folke/flash.nvim/commit/6e7d6c26a4528a8d6a17e2d23c3f5738491d736d))
+
+
+### Bug Fixes
+
+* **repeat:** no dot repeat inside macros. Fixes [#143](https://github.com/folke/flash.nvim/issues/143) ([f7218c2](https://github.com/folke/flash.nvim/commit/f7218c2d44a8d67c5c4b40edd569c55f95754354))
+
+## [1.15.0](https://github.com/folke/flash.nvim/compare/v1.14.0...v1.15.0) (2023-07-07)
+
+
+### Features
+
+* **search:** flash toggle in search is now permanent until you toggle again. Closes [#134](https://github.com/folke/flash.nvim/issues/134) ([7ceee0d](https://github.com/folke/flash.nvim/commit/7ceee0de7e96c7453d5f82dcfc938f08d8029703))
+
+
+### Bug Fixes
+
+* **char:** special handling for t/T at current position. Fixes [#137](https://github.com/folke/flash.nvim/issues/137) ([268bffe](https://github.com/folke/flash.nvim/commit/268bffe7b9b1b9a3a4bb64a5bc8ac0627b4b7c14))
+
+## [1.14.0](https://github.com/folke/flash.nvim/compare/v1.13.2...v1.14.0) (2023-07-05)
+
+
+### Features
+
+* **char:** added optional multi_line=false for ftFT motions. See [#102](https://github.com/folke/flash.nvim/issues/102) ([2f92418](https://github.com/folke/flash.nvim/commit/2f924186255a56cab4cf22e13b0bc1fb906b11fa))
+* **char:** option for behavior of ;, and char repeats. Closes [#124](https://github.com/folke/flash.nvim/issues/124) ([97eba7d](https://github.com/folke/flash.nvim/commit/97eba7df4454097c1f6cc447de2a4e9230831ffb))
+* **search:** allow finding current ([6659a94](https://github.com/folke/flash.nvim/commit/6659a94a033c2f6fec1e142451aa264f03e5da90))
+* **state:** added optional `filter` for matches by non-search matcher. See [#118](https://github.com/folke/flash.nvim/issues/118) ([780ad57](https://github.com/folke/flash.nvim/commit/780ad57dedb464bfe8361356959b3ac5aaed533d))
+* **treesitter:** added `node:TSNode` to ts `Flash.Match.TS` ([1cbaff4](https://github.com/folke/flash.nvim/commit/1cbaff4a7f074c1121c89207210e4588321acd40))
+
+
+### Bug Fixes
+
+* **char:** fixed tT at current. Fixes [#128](https://github.com/folke/flash.nvim/issues/128) ([a1c8aa6](https://github.com/folke/flash.nvim/commit/a1c8aa62204d5eb2036e819f5b919b1fe4b88918))
+* **jump:** move offset calc outside op mode ([69141ea](https://github.com/folke/flash.nvim/commit/69141ea571602a9202ad51fae1cfe7c1894fe036))
+* **search:** count=0 ([6d1d066](https://github.com/folke/flash.nvim/commit/6d1d066e6b5fcc2ed3ca446d229c0a0d306acf17))
+* take into count of multi-width characters on offset of highlights and jump ([#125](https://github.com/folke/flash.nvim/issues/125)) ([41c09fa](https://github.com/folke/flash.nvim/commit/41c09faf8588887c7c15d8ca63c9ede805437da2))
+
+## [1.13.2](https://github.com/folke/flash.nvim/compare/v1.13.1...v1.13.2) (2023-07-02)
+
+
+### Bug Fixes
+
+* **highlight:** dont use current when rainbow is used and match == target. Fixes [#109](https://github.com/folke/flash.nvim/issues/109) ([edb82f7](https://github.com/folke/flash.nvim/commit/edb82f763ac2b63006154e9da8b6629b570de551))
+
+## [1.13.1](https://github.com/folke/flash.nvim/compare/v1.13.0...v1.13.1) (2023-07-02)
+
+
+### Bug Fixes
+
+* **config:** dont show jumpt labels by default! Fixup. See [#103](https://github.com/folke/flash.nvim/issues/103) ([7bb89b2](https://github.com/folke/flash.nvim/commit/7bb89b20fd42037c1cd7ed8d3193081d86f8c39b))
+* **highlight:** don't show the label when at cursor in same window and not a range. See [#74](https://github.com/folke/flash.nvim/issues/74) ([7a8e07e](https://github.com/folke/flash.nvim/commit/7a8e07e62ad1a378d6eca958aad90fc071d14e9c))
+* **labeler:** don't label folded lines. Fixes [#39](https://github.com/folke/flash.nvim/issues/39). See [#106](https://github.com/folke/flash.nvim/issues/106) ([8af3773](https://github.com/folke/flash.nvim/commit/8af3773b7b960b053038868ea18867b94abae9c8))
+
+## [1.13.0](https://github.com/folke/flash.nvim/compare/v1.12.0...v1.13.0) (2023-07-01)
+
+
+### Features
+
+* **config:** added `opts.config` for dynamically configuring flash. Closes [#103](https://github.com/folke/flash.nvim/issues/103) ([3829d81](https://github.com/folke/flash.nvim/commit/3829d81fd6f5f6ca784bb9628a1b99298b88a3af))
+
+
+### Bug Fixes
+
+* **state:** use strchars instead of strcharlen for compat 0.8.2. Fixes [#105](https://github.com/folke/flash.nvim/issues/105) ([33e0793](https://github.com/folke/flash.nvim/commit/33e0793a614735a3fffb93763c4c9bd81b55433b))
+
+## [1.12.0](https://github.com/folke/flash.nvim/compare/v1.11.0...v1.12.0) (2023-06-30)
+
+
+### Features
+
+* **state:** added support for custom keymaps and lmap. See [#66](https://github.com/folke/flash.nvim/issues/66) ([9aa7805](https://github.com/folke/flash.nvim/commit/9aa78057cf13dde3d39bf25cfe5caf092083cc0c))
+
+
+### Bug Fixes
+
+* **labeler:** fixed calculating skip labels for mbyte keymaps. See [#66](https://github.com/folke/flash.nvim/issues/66) ([2da635f](https://github.com/folke/flash.nvim/commit/2da635f54b81538a1e12b4859bc292d7d3e5f1b9))
+* **treesitter:** added support for Nvim 0.8.0. Fixes [#100](https://github.com/folke/flash.nvim/issues/100) ([67ed44d](https://github.com/folke/flash.nvim/commit/67ed44d5efd2d05b49af861859740eedf3a076b6))
+* **treesitter:** some nodes were missing ([7f4e25f](https://github.com/folke/flash.nvim/commit/7f4e25fae0fa1d3adfeb3e3e87fba9ff914032a0))
+
+## [1.11.0](https://github.com/folke/flash.nvim/compare/v1.10.1...v1.11.0) (2023-06-29)
+
+
+### Features
+
+* **char:** hide flash when doing an ftFT search while yanking. Closes [#6](https://github.com/folke/flash.nvim/issues/6) ([feda1d5](https://github.com/folke/flash.nvim/commit/feda1d5a98a1705e86966e62a052661a7369b3c0))
+* **char:** optional jump labels for ftFT searches ([d2ad5e0](https://github.com/folke/flash.nvim/commit/d2ad5e0d776a89ee424a7e0cd4364ec5dbf11dc4))
+* **char:** support alternative f/F/t/T/;/, keymaps (fix [#96](https://github.com/folke/flash.nvim/issues/96)) ([#99](https://github.com/folke/flash.nvim/issues/99)) ([c0c006a](https://github.com/folke/flash.nvim/commit/c0c006a7bb694b4cec9a5f40e632f871b478e0d0))
+* **label:** added `opts.label.format` for formatting rendered labels. Closes [#84](https://github.com/folke/flash.nvim/issues/84) ([2d3e7b9](https://github.com/folke/flash.nvim/commit/2d3e7b90c568083e9857b100dc2570d269da0a0c))
+* **labeler:** allow excluding certain labels with a specific case ([6b255d3](https://github.com/folke/flash.nvim/commit/6b255d37505445da3db6fae5d79dff63529cd222))
+* **pos:** Pos can now be initialized with window or current window cursor ([7a05cd5](https://github.com/folke/flash.nvim/commit/7a05cd5dadb78b8d475526157e464f24d14ff5b2))
+* **search:** you can now `toggle` flash while using regular search ([e761182](https://github.com/folke/flash.nvim/commit/e761182f6c79ff5f88c877729465ece05b01c65a))
+* **state:** custom char actions ([4f44bb4](https://github.com/folke/flash.nvim/commit/4f44bb454df0c6f598e75cd8501a1eb8e1bd2df5))
+
+
+### Bug Fixes
+
+* **hacks:** make sure to render the cursor before getchar ([2b328d1](https://github.com/folke/flash.nvim/commit/2b328d121c2b56cf25e1eb9ba92c7459beb241be))
+* **highlight:** never put an extmark on the current cursor position ([8434130](https://github.com/folke/flash.nvim/commit/843413028843d1c3ce29449fe9ff62af8f642540))
+* **highlight:** use current hl if pos == label pos ([56531ee](https://github.com/folke/flash.nvim/commit/56531ee85d919e787dbb247aabedb5d3dd0b7bd1))
+* **jump:** replace opfunc by noop to properly cancel custom operators. Fixes [#93](https://github.com/folke/flash.nvim/issues/93) ([40b2bcb](https://github.com/folke/flash.nvim/commit/40b2bcbb05f1452f2ee7d21b79ce8ba77ea6cc94))
+* **jump:** temporarily set selection=inclusive. Closes [#81](https://github.com/folke/flash.nvim/issues/81) ([5c9505a](https://github.com/folke/flash.nvim/commit/5c9505a19edcbb236d367282584ed5f02ccd4fb4))
+* **labeler:** fixed label distance calculation ([1d941de](https://github.com/folke/flash.nvim/commit/1d941de722564a8ac2f07c2df262a48c49c1cdb9))
+* **labeler:** put original pattern in a `\%()` group. Fixes some skip label issues ([6102a7c](https://github.com/folke/flash.nvim/commit/6102a7c0e93dbcf592a7ed2b7a2a5c2a84c5033e))
+* **labeler:** skip all labels on invalid regex. Fixes [#94](https://github.com/folke/flash.nvim/issues/94) ([1fff746](https://github.com/folke/flash.nvim/commit/1fff746049253b10a008d60e1752065a98fd8614))
+* **remote:** use nvim_input instead of nvim_feedkeys for clearing op mode ([c90eae5](https://github.com/folke/flash.nvim/commit/c90eae5172a00551d51883cf8b67306a812a713f))
+* **search:** correctly set match end pos for multi byte characters. Fixes [#90](https://github.com/folke/flash.nvim/issues/90) ([0193d52](https://github.com/folke/flash.nvim/commit/0193d52af38d228b79569c62e06ee36b77a1a85e))
+* **treesitter:** ignore windows without ts parser. Fixes [#91](https://github.com/folke/flash.nvim/issues/91) ([13022c0](https://github.com/folke/flash.nvim/commit/13022c09fa30fb03d14110a380238f6a75b42ab4))
+
+## [1.10.1](https://github.com/folke/flash.nvim/compare/v1.10.0...v1.10.1) (2023-06-27)
+
+
+### Bug Fixes
+
+* **highlight:** apply after labels and then before ([4439fca](https://github.com/folke/flash.nvim/commit/4439fca240a54ef4d4537102668285e9cbb6f23c))
+* **highlight:** correctly order after labels at the same column ([b096797](https://github.com/folke/flash.nvim/commit/b096797b64f56357c40222f5a3cff6f25ac3b5dc))
+* **highlight:** make sure col is not negative with label.before = true ([cbce7f9](https://github.com/folke/flash.nvim/commit/cbce7f923c74fb75be030273c0d49f6a3447a95f))
+* **prompt:** never show the prompt when in regular search ([51149ba](https://github.com/folke/flash.nvim/commit/51149ba2e6bcba0a28e67b9654450835437a2914))
+* **rainbow:** stable rainbow label highlight groups ([937df4f](https://github.com/folke/flash.nvim/commit/937df4f097781e3e91594bf69425f3e74044b711))
+
+## [1.10.0](https://github.com/folke/flash.nvim/compare/v1.9.0...v1.10.0) (2023-06-27)
+
+
+### Features
+
+* **highlight:** added optional rainbow labels. Disabled by default. Useful for Treesitter ranges. ([#74](https://github.com/folke/flash.nvim/issues/74)) ([ffb865b](https://github.com/folke/flash.nvim/commit/ffb865b1a60732d9ce2c9bffe3fb6724e1004ebb))
+
+
+### Bug Fixes
+
+* **char:** force before=false with f, F motion ([#75](https://github.com/folke/flash.nvim/issues/75)) ([40313ec](https://github.com/folke/flash.nvim/commit/40313ecf3140264b6e9d9611a3832a32e5ab7a46))
+* **search:** fixup for search commmands ([0f2d53d](https://github.com/folke/flash.nvim/commit/0f2d53d63e9d90f7a310509fbf4e98fbe21be56e))
+
+## [1.9.0](https://github.com/folke/flash.nvim/compare/v1.8.0...v1.9.0) (2023-06-26)
+
+
+### Features
+
+* **treesitter:** added treesitter search to label ts nodes around search matches ([6f791d4](https://github.com/folke/flash.nvim/commit/6f791d4709a2c8ef2373302d3a067ae45fdc2f8d))
+
+
+### Bug Fixes
+
+* added unicode support for labels/skips and fuzzy search. See [#66](https://github.com/folke/flash.nvim/issues/66) ([2528752](https://github.com/folke/flash.nvim/commit/2528752b7efbf3f67cce8b9d0d75ee769f72c01e))
+* **state:** restore window views on esc or ctrl-c ([7b21dfd](https://github.com/folke/flash.nvim/commit/7b21dfddcf7ccc4fb665ca0db80810210f8cde7c))
+* **treesitter:** add incremental = false to default settings of treesitter ([1cf706f](https://github.com/folke/flash.nvim/commit/1cf706f342bea4447c2f8ac13c2fab9df060ce1e))
+
+## [1.8.0](https://github.com/folke/flash.nvim/compare/v1.7.0...v1.8.0) (2023-06-26)
+
+
+### Features
+
+* added prompt window that shows pattern during jump (can be disabled) ([3fff703](https://github.com/folke/flash.nvim/commit/3fff7033f53b8f0714efd0dd56b03aa3f22c6376))
+* **api:** allow a match to disable getting a label ([ea56cea](https://github.com/folke/flash.nvim/commit/ea56ceaea4760b2031719d8e5eb1b6231ef9f43c))
+* **api:** allow a match to enable/disable highlight ([38eca97](https://github.com/folke/flash.nvim/commit/38eca97c8bdbbbd7be64b562eeb9f964cf8bc145))
+* **ffi:** added `mappings_enabled` ([6f6af15](https://github.com/folke/flash.nvim/commit/6f6af15b491bee14460873fe63fc7b20e7c73dd8))
+* **hacks:** added support for detecting user input waiting ([81c610a](https://github.com/folke/flash.nvim/commit/81c610acd374b40fc7a7fa4b493b1b9783d3d52d))
+* **highlight:** added option to disable distance based labeling ([ad9212f](https://github.com/folke/flash.nvim/commit/ad9212f28ef37e893a5a4113f8757052b2035c36))
+* **highlight:** show fake cursor in all windows when flash is active ([471b165](https://github.com/folke/flash.nvim/commit/471b165722ae5db4ddad7cbaf1d351127fb55529))
+* **highlight:** when running in vscode, set default hl groups to something that works ([d4c30b1](https://github.com/folke/flash.nvim/commit/d4c30b169f01b8108c5bc38e230a975408133603))
+* **jump:** added jump offset ([0f2dfac](https://github.com/folke/flash.nvim/commit/0f2dfaca329ed9a7db9e5062d964492cf51765eb))
+* **jump:** added options for remote operator pending mode ([436d1f4](https://github.com/folke/flash.nvim/commit/436d1f402a696733b8a1512072bbd0ac8da72cea))
+* **jump:** remote operator pending operations will now always return to the original window ([c11d0d1](https://github.com/folke/flash.nvim/commit/c11d0d15660ce309c733982b2c34cd54c9c9d9f0))
+* **label:** minimum pattern length to show labels. Closes [#68](https://github.com/folke/flash.nvim/issues/68) ([2c2302a](https://github.com/folke/flash.nvim/commit/2c2302a3eae1dc72d2140c58974e2f73df41556d))
+* matcher function now has a from/to opts param ([1cb669d](https://github.com/folke/flash.nvim/commit/1cb669d2ce074ea39722da9fec6b0c2686b3b484))
+* **remote_op:** allow setting motion to `nil` to automatically start a new motion when needed ([259062d](https://github.com/folke/flash.nvim/commit/259062ddc47f9de11e0e498cd58040705d7b6f5c))
+* **remote:** implement remote using new `remote_op` options ([51f5c35](https://github.com/folke/flash.nvim/commit/51f5c352db8791f4218e19cc7fa40948cdda9647))
+* searches can now be continued. Closes [#54](https://github.com/folke/flash.nvim/issues/54) ([487aa52](https://github.com/folke/flash.nvim/commit/487aa52956fdf79ba545151227b0ad39c5276c69))
+* **state:** added support for restoring all window views and current window ([01736c0](https://github.com/folke/flash.nvim/commit/01736c01eb43dcf497a946689c7f434b1d13b4a8))
+* **util:** luv check that does something when something finishes ([a3643eb](https://github.com/folke/flash.nvim/commit/a3643eb5424c12b5abc7b08a74d0d53fa5a29af0))
+* **vscode:** make flash work properly in vscode by updating/changing the default config. Fixes [#58](https://github.com/folke/flash.nvim/issues/58) ([fa72836](https://github.com/folke/flash.nvim/commit/fa72836760417436cfe8e33ee74edaefd8ee9e00))
+
+
+### Bug Fixes
+
+* **config:** process modes in correct order. Fixes [#50](https://github.com/folke/flash.nvim/issues/50) again ([919cbe4](https://github.com/folke/flash.nvim/commit/919cbe49b66758cf57529847c396e718a9883de0))
+* disable prompt on vscode ([f93b33d](https://github.com/folke/flash.nvim/commit/f93b33d736fb2eb6f28526ab465cfe7f32e7d96f))
+* **jump:** fixup to always use a motion for remote ops ([11fa883](https://github.com/folke/flash.nvim/commit/11fa8833c62175a88fc35c50f1d23d5002d20fda))
+* **jump:** improved operator pending mode for jumps ([16f785f](https://github.com/folke/flash.nvim/commit/16f785f26e74b8f0b49901356c57cda2a06379f5))
+* **jump:** operator pending mode for remote jumps now behaves correctly ([cb24e66](https://github.com/folke/flash.nvim/commit/cb24e667ea58cfa7ea9df9fdf41bb6a26ea13da1))
+* **remote:** make sure opts always exists ([7083750](https://github.com/folke/flash.nvim/commit/7083750697dea16b3943ca8a92c958acd83c2126))
+* **search:** added support for search-commands. Fixes [#67](https://github.com/folke/flash.nvim/issues/67) ([7a59c42](https://github.com/folke/flash.nvim/commit/7a59c4239ed11ca3ec91cd7544535d836f09eb20))
+
+## [1.7.0](https://github.com/folke/flash.nvim/compare/v1.6.0...v1.7.0) (2023-06-24)
+
+
+### Features
+
+* **config:** allow mode inheritance. Closes [#50](https://github.com/folke/flash.nvim/issues/50) ([3deefe8](https://github.com/folke/flash.nvim/commit/3deefe88e02e68c163c320614be1727fa887cd65))
+* **jump:** added option to force inclusive/exclusive. Closes [#49](https://github.com/folke/flash.nvim/issues/49) ([e71efbf](https://github.com/folke/flash.nvim/commit/e71efbfbc73df21d3e79d30c4c27bd29892c216c))
+* **remote:** peoperly deal with c for remote. Will jump back when leaving insert mode ([1075013](https://github.com/folke/flash.nvim/commit/10750139d3d4f2fb6c7bb8cc33aef988a7b26b7c))
+* **state:** allow passing a callable object as matcher ([f49fa9c](https://github.com/folke/flash.nvim/commit/f49fa9cbddd6a30c59420892e09f57f391bd9516))
+
+
+### Bug Fixes
+
+* **cache:** allow current window to be excluded ([770763c](https://github.com/folke/flash.nvim/commit/770763ce2d2b4c340249cb7000de81c2085438c8))
+* **cache:** fixup for window selection ([ed3bec6](https://github.com/folke/flash.nvim/commit/ed3bec6da9b92cee4954bfb71c4e71d06406191c))
+* **char:** add group to autocmd ([fc08d27](https://github.com/folke/flash.nvim/commit/fc08d279ddb92ba2323684a2077aa7797384fc3c))
+* **remote:** properly restore remote window as well. Also remove the `normal! o` ([587a243](https://github.com/folke/flash.nvim/commit/587a2436f84301b84937242657dcc03be4a80702))
+
+
+### Performance Improvements
+
+* **remote:** restore views on TextYankPost ([d4dadc8](https://github.com/folke/flash.nvim/commit/d4dadc8fae53ded2a51a2ca0a9d82889e148e0b7))
+
+## [1.6.0](https://github.com/folke/flash.nvim/compare/v1.5.0...v1.6.0) (2023-06-24)
+
+
+### Features
+
+* **config:** pattern can now have a `max_length`. When length is reached, labels are no longer skipped. When it exceeds, either a jump is followed or the search is ended ([bd9dbee](https://github.com/folke/flash.nvim/commit/bd9dbee041296a582faa6dfe25e1af87d65614c7))
+
+
+### Bug Fixes
+
+* **config:** exclude noice by default ([bc9a599](https://github.com/folke/flash.nvim/commit/bc9a5992b947ae84b5c1458f0b117abda1b61154))
+* **repeat:** make sure repeat is enabled for char searches. Fixes [#40](https://github.com/folke/flash.nvim/issues/40) ([219f0c0](https://github.com/folke/flash.nvim/commit/219f0c09b664257a7d9b46023bcb24563ae49832))
+* **state:** always reposition the cursor on incremental mode ([81e38d6](https://github.com/folke/flash.nvim/commit/81e38d604d285d835a9186f82e28a302bc048128))
+
+## [1.5.0](https://github.com/folke/flash.nvim/compare/v1.4.1...v1.5.0) (2023-06-23)
+
+
+### Features
+
+* added remote plugin ([fb50450](https://github.com/folke/flash.nvim/commit/fb5045044f28caf08ca6d89e9fe40874138faeef))
+* flash remote. thank you [@max397574](https://github.com/max397574)! ([809ea4f](https://github.com/folke/flash.nvim/commit/809ea4f804d831ca5ff26c94b8d409ad9dfec8eb))
+
+
+### Bug Fixes
+
+* **char:** always stop highlights in insert mode ([64e5129](https://github.com/folke/flash.nvim/commit/64e51292e83e7ce409248fd07ff00b51a993a6c0))
+
+## [1.4.1](https://github.com/folke/flash.nvim/compare/v1.4.0...v1.4.1) (2023-06-23)
+
+
+### Bug Fixes
+
+* **char:** don't repeat on motion char when executing a macro. See [#34](https://github.com/folke/flash.nvim/issues/34) ([674cfb4](https://github.com/folke/flash.nvim/commit/674cfb43e5424a5405661ba632810bacfc0a9c37))
+
+## [1.4.0](https://github.com/folke/flash.nvim/compare/v1.3.0...v1.4.0) (2023-06-23)
+
+
+### Features
+
+* **char:** tfTF now behave like clever-f when repeating the motion. Fixes [#26](https://github.com/folke/flash.nvim/issues/26) ([97c3a99](https://github.com/folke/flash.nvim/commit/97c3a993e60ebdd42c7671af07620f705ee6378f))
+* **config:** allow custom window filters. Added non-focusable windows by default ([e6ee00d](https://github.com/folke/flash.nvim/commit/e6ee00d4e76edac8cbcabe0f442a5ec34450d1f6))
+
+
+### Bug Fixes
+
+* **config:** dont show flash in cmp_menu ([29c35de](https://github.com/folke/flash.nvim/commit/29c35dec5f81504ee63a39fec90597222620af0a))
+* **treesitter:** always disable incremental mode for treesitter. Fixes [#27](https://github.com/folke/flash.nvim/issues/27) ([6e84716](https://github.com/folke/flash.nvim/commit/6e8471673a7158a8820986f6aad770a912a66eed))
+
+## [1.3.0](https://github.com/folke/flash.nvim/compare/v1.2.0...v1.3.0) (2023-06-22)
+
+
+### Features
+
+* **char:** optionally disable some ftFT keymaps ([3e27d9a](https://github.com/folke/flash.nvim/commit/3e27d9ab07b9363b0ecb94645eae38909f7baa5a))
+* **config:** show labels for current jump target by default ([0dcc00e](https://github.com/folke/flash.nvim/commit/0dcc00ea6a3b312b8e081f3f582adc26a4721ac7))
+* **search:** optional trigger character. Not recommended. Fixes [#21](https://github.com/folke/flash.nvim/issues/21) ([cb0977c](https://github.com/folke/flash.nvim/commit/cb0977cd0f7cec4573ee1210edc2032739866b2b))
+
+
+### Bug Fixes
+
+* **char:** fixup for keys ([81469aa](https://github.com/folke/flash.nvim/commit/81469aaf3ccf15d7c942bbd9144f2c06f68fe1ee))
+* **treesitter:** properly deal with nodes ending at col 0. Fixes [#17](https://github.com/folke/flash.nvim/issues/17) ([6cd4414](https://github.com/folke/flash.nvim/commit/6cd44145f75392fbfe67700b59517dbf8324bd21))
+* **treesitter:** removed debug print ([0fabd1b](https://github.com/folke/flash.nvim/commit/0fabd1b4ddea5754576ccc09a515867a3ac129ce))
+
+## [1.2.0](https://github.com/folke/flash.nvim/compare/v1.1.0...v1.2.0) (2023-06-21)
+
+
+### Features
+
+* added example that matches beginning of words only ([1e2c61d](https://github.com/folke/flash.nvim/commit/1e2c61d8db882cc001fcebff9eba2549336ce87a))
+* **config:** setting to disable uppercase labels. Fixes [#11](https://github.com/folke/flash.nvim/issues/11) ([13d7b3e](https://github.com/folke/flash.nvim/commit/13d7b3e70cadc7e4d64f818a04fbca2b33ac1d4f))
+* **labeler:** reuse only lowercase labels by default. See [#11](https://github.com/folke/flash.nvim/issues/11) ([8f0b9ed](https://github.com/folke/flash.nvim/commit/8f0b9ed656d7b92eb0d60c34b6a5bd3803cc0e0b))
+
+## [1.1.0](https://github.com/folke/flash.nvim/compare/v1.0.0...v1.1.0) (2023-06-21)
+
+
+### Features
+
+* added config.jump.autojump. Fixes [#5](https://github.com/folke/flash.nvim/issues/5) ([1808d3e](https://github.com/folke/flash.nvim/commit/1808d3ebb6ea5810957b8f8e32aab8f4e9e7f14c))
+* added custom actions on label select ([eb0769f](https://github.com/folke/flash.nvim/commit/eb0769ff38001ed3eead9e54289b7f63387e1525))
+* added example plugin that shows a diagnostic at a certain label without moving the cursor ([7a9bd11](https://github.com/folke/flash.nvim/commit/7a9bd118a3b4d2829d4718c26d8af21b36ebfb87))
+
+
+### Bug Fixes
+
+* **config:** get mode opts from options instead of defaults. Fixes [#4](https://github.com/folke/flash.nvim/issues/4) ([41fab4c](https://github.com/folke/flash.nvim/commit/41fab4cb225d9233fec7987bb1445c9768d84caf))
+* **diag:** always hide when done ([226c634](https://github.com/folke/flash.nvim/commit/226c634e3db6f02eb734d37c16d729bae41a77ef))
+* **jump:** register and history should use pattern.search instead of pattern. Fixes [#7](https://github.com/folke/flash.nvim/issues/7) ([a11cf6a](https://github.com/folke/flash.nvim/commit/a11cf6ad205dd2493d2af6643bc20bef925004f5))
+* **treesitter:** make treesitter plugin work with custom labels. Fixes [#9](https://github.com/folke/flash.nvim/issues/9) ([3fac625](https://github.com/folke/flash.nvim/commit/3fac6253fd59e7c32300e6209c8f1e60ea8a3c81))
+
+## 1.0.0 (2023-06-21)
+
+
+### Features
+
+* abort_pattern can now be false ([e036667](https://github.com/folke/flash.nvim/commit/e0366678e337df4a93c0704e77a6909e617950c3))
+* add option to save loc to jumplist before jump ([0aae816](https://github.com/folke/flash.nvim/commit/0aae816ef419ad4554a784a07fe239aeee9a6934))
+* added char searches, f, F, t, T ([06839d8](https://github.com/folke/flash.nvim/commit/06839d8ac7f2ca42b639fc8f90e2c655234bba9a))
+* added config for forward/wrap ([b9649bd](https://github.com/folke/flash.nvim/commit/b9649bd226da89bcbef7fb6b27e5d3a08d0fe6b4))
+* added config.search.regex ([bda1be0](https://github.com/folke/flash.nvim/commit/bda1be00bca62d7ebd9de4c7848e7c70a65f2f91))
+* added ffi based searcher. Finally 100% correct end pos for matches ([46b41d1](https://github.com/folke/flash.nvim/commit/46b41d13d6943443c20b3bf87fdf8eb495fee4c2))
+* added option to label the first match ([63b75ed](https://github.com/folke/flash.nvim/commit/63b75ed8dcaec7efaf6e67e3913b59f2e614f043))
+* added optional backdrop ([2172a90](https://github.com/folke/flash.nvim/commit/2172a907aeba4a3961e399044a2f4ca1087e044d))
+* added support for label offsets and label styles ([3e9f630](https://github.com/folke/flash.nvim/commit/3e9f630ce04bdda14669592bc5d36af594077e95))
+* added treesitter command ([fd9bd80](https://github.com/folke/flash.nvim/commit/fd9bd8015a7df2b8aedc294bc517264837d218f9))
+* advance for results ([9d70126](https://github.com/folke/flash.nvim/commit/9d70126e09b20125752a43c1e26041eecc4f721c))
+* allow to always render search highlight to prevent flickering when updating ui ([ff0e25f](https://github.com/folke/flash.nvim/commit/ff0e25f63ae98f7ab2735293a40f02e8cfc85d2a))
+* **charsearch:** close on <esc> ([ee3228a](https://github.com/folke/flash.nvim/commit/ee3228af6b82204cb03c317526a0212229953272))
+* **charsearch:** make char search dot repeatable ([91485c1](https://github.com/folke/flash.nvim/commit/91485c12b2685bdde097b2351725e973cc2e1274))
+* dont stabalize labels for treesitter ([b20ad86](https://github.com/folke/flash.nvim/commit/b20ad8652f34a477f6bdab912258b176aeebdd0d))
+* expose commands on main module ([70130d2](https://github.com/folke/flash.nvim/commit/70130d29a3c4c8d90d96caae5871d0cc19e3f283))
+* fuzzy matching ([7407dd6](https://github.com/folke/flash.nvim/commit/7407dd679c90986dff09b22a690feb52aa5ea31a))
+* highlight groups config ([313e252](https://github.com/folke/flash.nvim/commit/313e252ecfd3252d2e39d7c012b0674388d65f8d))
+* **highlight:** added support for before/after labels ([d0133d2](https://github.com/folke/flash.nvim/commit/d0133d2966695f063f8909a0d80a97cd90d2848c))
+* **highlight:** allow diffrerent namespaces for highlight ([2649b18](https://github.com/folke/flash.nvim/commit/2649b1888fd84d1cee0ab3d5fdc5e82c8a5f391c))
+* initial version ([22913c6](https://github.com/folke/flash.nvim/commit/22913c65a1c960e3449c813824351abbdb327c7b))
+* jump position (start, end or range) ([335a5a9](https://github.com/folke/flash.nvim/commit/335a5a91222680f92c585c16d94d183a57b13c8d))
+* labels are now skipped based on regex searches to be able to fully support regex patterns ([e704d88](https://github.com/folke/flash.nvim/commit/e704d8846fd2d8189f127f2b080812ed2518fdc4))
+* lazy require ([171b9ff](https://github.com/folke/flash.nvim/commit/171b9ff3034b2afb5ad9a0420a906a8c597037ba))
+* make all the things repeatable without needing `expr=true` ([ec3a8ac](https://github.com/folke/flash.nvim/commit/ec3a8ac3ebfc9957c65620bcae7d91ed38a334b2))
+* much improved repeat api ([2f76471](https://github.com/folke/flash.nvim/commit/2f76471f3a178234a3b08a6ae5ca9f8082bacc46))
+* multiple modes ([ed1150f](https://github.com/folke/flash.nvim/commit/ed1150f2cabcca526894423de8fda74d756a0cff))
+* **pattern:** custom pattern functions ([b9e13f2](https://github.com/folke/flash.nvim/commit/b9e13f2c8cf603e70d7eff410ffbd88c8611d6d0))
+* **repeat:** show warning when keymap expr didn't execute. probably because expr=true was not used ([789d3b2](https://github.com/folke/flash.nvim/commit/789d3b22610fe8f45f7451afac5b1921db852dd6))
+* stable labels ([3e6b345](https://github.com/folke/flash.nvim/commit/3e6b345f590c70c83ccbe720afc268ba9ba3b442))
+* **state:** proper support for incremental search ([8a0fa11](https://github.com/folke/flash.nvim/commit/8a0fa1147cfad21b6576ee4d9320de6e78b1c24c))
+* **state:** state will now automatically updated on changedtick or when buf changes ([60193cb](https://github.com/folke/flash.nvim/commit/60193cb3aa384938bd7b9be8d5b594c0ebe0c867))
+* **state:** update matcher when view changed ([9f4dc50](https://github.com/folke/flash.nvim/commit/9f4dc506987a9381d67e3e602e9950a622c76276))
+* treesitter node jumping ([119643f](https://github.com/folke/flash.nvim/commit/119643fd672a959233da3b1c3b61de965dfe765b))
+* **treesitter:** ; & , to expand/descrease selection ([6551d97](https://github.com/folke/flash.nvim/commit/6551d970d270bda2b6bf9be09944196d8782a329))
+* **treesitter:** allow custom options ([d9d5e75](https://github.com/folke/flash.nvim/commit/d9d5e7558e11e1cdb9a48c87e442444664b3c0cf))
+* util module for dot-repeat ([e6f02b1](https://github.com/folke/flash.nvim/commit/e6f02b15608b625266f1564b8005c36d56f7fa71))
+
+
+### Bug Fixes
+
+* allow space in string ([f1b8691](https://github.com/folke/flash.nvim/commit/f1b86913daa85aef94fae07e03cab8ccf7f9137f))
+* calculate target in update ([f3f915a](https://github.com/folke/flash.nvim/commit/f3f915ac0b5c4ff4598dd73b65cff9f9c0d3e57b))
+* **charsearch:** inclusive/exclusive operator pending fix ([fb1867c](https://github.com/folke/flash.nvim/commit/fb1867c908e488a7dbe1a83f7cad57a826bf977f))
+* **charsearch:** mode ([b8c18ba](https://github.com/folke/flash.nvim/commit/b8c18baad82145fe097db4d13440d44a9005f30d))
+* **config:** register and nohlsearch are disables by default ([f20d2f8](https://github.com/folke/flash.nvim/commit/f20d2f8d34142ec1674284f582e57f6f66a99cd8))
+* dont set search register by default ([f7352f7](https://github.com/folke/flash.nvim/commit/f7352f7c7e90e3e0b5818b398d543e2146f045ad))
+* fixup for first -> current ([43b96c6](https://github.com/folke/flash.nvim/commit/43b96c69d7f7fd97f5c9ec316cf8ee3c30badc48))
+* **highlight:** highlight each line of the backdrop separately to fix extmark priorities ([08bf4f6](https://github.com/folke/flash.nvim/commit/08bf4f6fad136743c6791f6db4659f314fe69104))
+* **highlight:** proper nvim 0.10.0 check for inline extmarks ([6da8904](https://github.com/folke/flash.nvim/commit/6da8904ed698069395baab49b168b37b0a35b839))
+* **highlight:** set cursorline hl group ([8715685](https://github.com/folke/flash.nvim/commit/8715685cd24e5d5727442063ce7e347bb0b567b7))
+* **init:** pass opts to config ([0627e2f](https://github.com/folke/flash.nvim/commit/0627e2f09e9a7b26d8755d8e4994e38cfdd58ba5))
+* **jump:** check pattern for jump target ([d29d5fc](https://github.com/folke/flash.nvim/commit/d29d5fc41dcbe6e7c751c30d28b362400f45f870))
+* **jump:** dont change ordering of matches when calculating labels ([8611eab](https://github.com/folke/flash.nvim/commit/8611eaba93c080175026dbd41fac9a7a9e535637))
+* **jump:** fix inclusive/excusive for operator pending mode ([99c99a7](https://github.com/folke/flash.nvim/commit/99c99a75754f107eef0cbc23f4745e7c0d784848))
+* **jump:** make it all work in operator pending mode ([1005faa](https://github.com/folke/flash.nvim/commit/1005faa1c21dcaa37232fd93c2ef7c71fc3b3099))
+* **labeler:** dont include end_pos to re-use stable labels ([dadca0e](https://github.com/folke/flash.nvim/commit/dadca0e75335dd9e3083ea11cd41f1d197ebe1a7))
+* **labels:** fixed some edge cases regarding labels ([124d1b6](https://github.com/folke/flash.nvim/commit/124d1b6900b30f5a2e1c60bc6a4ac0e1a0de889a))
+* **matcher:** match end_pos when finding relative to another match ([0794ba2](https://github.com/folke/flash.nvim/commit/0794ba238ada4ab820940a63dbd54f29679d10be))
+* **matcher:** ordering ([e46a629](https://github.com/folke/flash.nvim/commit/e46a629c679a022e822a4243ad15ebcb1474412d))
+* **search:** added support for match ([e3e3958](https://github.com/folke/flash.nvim/commit/e3e3958c871bf46d808605afbdcf07cafb1e98e4))
+* **search:** cleanup and add search to history ([175ffd9](https://github.com/folke/flash.nvim/commit/175ffd9960fdaf65b00d00782fdc0505678e9162))
+* **search:** dont add labels if too many results ([959af4e](https://github.com/folke/flash.nvim/commit/959af4e095df35a62200a35b1f3aef2e652c8dd5))
+* **searcher:** don't use ignore case for labels and skip both upper/lower when needed ([1b48511](https://github.com/folke/flash.nvim/commit/1b48511efa0834deb07461b3e076c8bafb66d876))
+* **searcher:** finally was able to properly fix finding ends of matches ([4251741](https://github.com/folke/flash.nvim/commit/4251741114187823b94957dfad40e7dcfa82ac2d))
+* **searcher:** skip all labels when pattern ends with escape character ([530038d](https://github.com/folke/flash.nvim/commit/530038d05925373feddb4742dcf742401532ed69))
+* **searcher:** use vim.regex to get match end and added support for multi-line ([ffcdf20](https://github.com/folke/flash.nvim/commit/ffcdf20d7ff15117a984244e1258794fef10efe8))
+* **search:** properly deal with invalid patterns ([46d6655](https://github.com/folke/flash.nvim/commit/46d6655891238b569ffa8c0334f2bdae39adc21e))
+* **search:** skip all labels when pattern is invalid regex ([9bb8079](https://github.com/folke/flash.nvim/commit/9bb8079c82dccccc54ec107e243f845e996a492b))
+* **state:** better operator pending mode detection for search ([f53dd07](https://github.com/folke/flash.nvim/commit/f53dd076af1e2f6f9374f6c26c8f474c83c5815d))
+* **state:** force update when making visible ([ada913d](https://github.com/folke/flash.nvim/commit/ada913d2a1cbdb765493419202a48addaf2c873a))
+* **state:** keep states as a key in a table to prevent double work ([4a6ea98](https://github.com/folke/flash.nvim/commit/4a6ea985c88eb8503515131f422d4cb856db4b3b))
+* **state:** results sorting ([9da4d28](https://github.com/folke/flash.nvim/commit/9da4d285d0d453fc9eb0f3bfcebde68be334f066))
+* **state:** stop searching when max matches reached ([4245e49](https://github.com/folke/flash.nvim/commit/4245e49fb878459bb5a074c9c8023900baf321cd))
+* **treesitter:** use state.pos as cursor to get nodes ([d1185ad](https://github.com/folke/flash.nvim/commit/d1185add4a6f624b150896ba4eb32855ef9e35b7))
+
+
+### Performance Improvements
+
+* cache window matches ([678532a](https://github.com/folke/flash.nvim/commit/678532a956562a53887a5dda2e4513c3ba216de9))
+* lazy require/setup ([2bbf721](https://github.com/folke/flash.nvim/commit/2bbf72189c875509ac37130f56fc4cb6e0f65139))
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/LICENSE b/config/neovim/store/lazy-plugins/flash.nvim/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/README.md b/config/neovim/store/lazy-plugins/flash.nvim/README.md
new file mode 100644
index 00000000..0f83f756
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/README.md
@@ -0,0 +1,705 @@
+# ⚡flash.nvim
+
+`flash.nvim` lets you navigate your code with search labels,
+enhanced character motions, and Treesitter integration.
+
+
+
+ | Search Integration |
+ Standalone Jump |
+
+
+
+
+ |
+
+
+ |
+
+
+ f, t, F, T |
+ Treesitter |
+
+
+
+
+ |
+
+
+ |
+
+
+
+## ✨ Features
+
+- 🔍 **Search Integration**: integrate **flash.nvim** with your regular
+ search using `/` or `?`. Labels appear next to the matches,
+ allowing you to quickly jump to any location. Labels are
+ guaranteed not to exist as a continuation of the search pattern.
+- ⌨️ **type as many characters as you want** before using a jump label.
+- ⚡ **Enhanced `f`, `t`, `F`, `T` motions**
+- 🌳 **Treesitter Integration**: all parents of the Treesitter node
+ under your cursor are highlighted with a label for quick selection
+ of a specific Treesitter node.
+- 🎯 **Jump Mode**: a standalone jumping mode similar to search
+- 🔎 **Search Modes**: `exact`, `search` (regex), and `fuzzy` search modes
+- 🪟 **Multi Window** jumping
+- 🌐 **Remote Actions**: perform motions in remote locations
+- ⚫ **dot-repeatable** jumps
+- 📡 **highly extensible**: check the [examples](https://github.com/folke/flash.nvim#-examples)
+
+## 📋 Requirements
+
+- Neovim >= **0.8.0** (needs to be built with **LuaJIT**)
+
+## 📦 Installation
+
+Install the plugin with your preferred package manager:
+
+[lazy.nvim](https://github.com/folke/lazy.nvim):
+
+
+
+```lua
+{
+ "folke/flash.nvim",
+ event = "VeryLazy",
+ ---@type Flash.Config
+ opts = {},
+ -- stylua: ignore
+ keys = {
+ { "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" },
+ { "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
+ { "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
+ { "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
+ { "", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
+ },
+}
+```
+
+
+
+> ⚠️ When creating the keymaps manually either use a lua function like
+> `function() require("flash").jump() end` as the **rhs**, or a string
+> like `lua require("flash").jump()`.
+> **DO NOT** use `:lua`, since that will break **_dot-repeat_**
+
+## ⚙️ Configuration
+
+**flash.nvim** is highly configurable. Please refer to the default settings below.
+
+Default Settings
+
+
+
+```lua
+{
+ -- labels = "abcdefghijklmnopqrstuvwxyz",
+ labels = "asdfghjklqwertyuiopzxcvbnm",
+ search = {
+ -- search/jump in all windows
+ multi_window = true,
+ -- search direction
+ forward = true,
+ -- when `false`, find only matches in the given direction
+ wrap = true,
+ ---@type Flash.Pattern.Mode
+ -- Each mode will take ignorecase and smartcase into account.
+ -- * exact: exact match
+ -- * search: regular search
+ -- * fuzzy: fuzzy search
+ -- * fun(str): custom function that returns a pattern
+ -- For example, to only match at the beginning of a word:
+ -- mode = function(str)
+ -- return "\\<" .. str
+ -- end,
+ mode = "exact",
+ -- behave like `incsearch`
+ incremental = false,
+ -- Excluded filetypes and custom window filters
+ ---@type (string|fun(win:window))[]
+ exclude = {
+ "notify",
+ "cmp_menu",
+ "noice",
+ "flash_prompt",
+ function(win)
+ -- exclude non-focusable windows
+ return not vim.api.nvim_win_get_config(win).focusable
+ end,
+ },
+ -- Optional trigger character that needs to be typed before
+ -- a jump label can be used. It's NOT recommended to set this,
+ -- unless you know what you're doing
+ trigger = "",
+ -- max pattern length. If the pattern length is equal to this
+ -- labels will no longer be skipped. When it exceeds this length
+ -- it will either end in a jump or terminate the search
+ max_length = false, ---@type number|false
+ },
+ jump = {
+ -- save location in the jumplist
+ jumplist = true,
+ -- jump position
+ pos = "start", ---@type "start" | "end" | "range"
+ -- add pattern to search history
+ history = false,
+ -- add pattern to search register
+ register = false,
+ -- clear highlight after jump
+ nohlsearch = false,
+ -- automatically jump when there is only one match
+ autojump = false,
+ -- You can force inclusive/exclusive jumps by setting the
+ -- `inclusive` option. By default it will be automatically
+ -- set based on the mode.
+ inclusive = nil, ---@type boolean?
+ -- jump position offset. Not used for range jumps.
+ -- 0: default
+ -- 1: when pos == "end" and pos < current position
+ offset = nil, ---@type number
+ },
+ label = {
+ -- allow uppercase labels
+ uppercase = true,
+ -- add any labels with the correct case here, that you want to exclude
+ exclude = "",
+ -- add a label for the first match in the current window.
+ -- you can always jump to the first match with ``
+ current = true,
+ -- show the label after the match
+ after = true, ---@type boolean|number[]
+ -- show the label before the match
+ before = false, ---@type boolean|number[]
+ -- position of the label extmark
+ style = "overlay", ---@type "eol" | "overlay" | "right_align" | "inline"
+ -- flash tries to re-use labels that were already assigned to a position,
+ -- when typing more characters. By default only lower-case labels are re-used.
+ reuse = "lowercase", ---@type "lowercase" | "all" | "none"
+ -- for the current window, label targets closer to the cursor first
+ distance = true,
+ -- minimum pattern length to show labels
+ -- Ignored for custom labelers.
+ min_pattern_length = 0,
+ -- Enable this to use rainbow colors to highlight labels
+ -- Can be useful for visualizing Treesitter ranges.
+ rainbow = {
+ enabled = false,
+ -- number between 1 and 9
+ shade = 5,
+ },
+ -- With `format`, you can change how the label is rendered.
+ -- Should return a list of `[text, highlight]` tuples.
+ ---@class Flash.Format
+ ---@field state Flash.State
+ ---@field match Flash.Match
+ ---@field hl_group string
+ ---@field after boolean
+ ---@type fun(opts:Flash.Format): string[][]
+ format = function(opts)
+ return { { opts.match.label, opts.hl_group } }
+ end,
+ },
+ highlight = {
+ -- show a backdrop with hl FlashBackdrop
+ backdrop = true,
+ -- Highlight the search matches
+ matches = true,
+ -- extmark priority
+ priority = 5000,
+ groups = {
+ match = "FlashMatch",
+ current = "FlashCurrent",
+ backdrop = "FlashBackdrop",
+ label = "FlashLabel",
+ },
+ },
+ -- action to perform when picking a label.
+ -- defaults to the jumping logic depending on the mode.
+ ---@type fun(match:Flash.Match, state:Flash.State)|nil
+ action = nil,
+ -- initial pattern to use when opening flash
+ pattern = "",
+ -- When `true`, flash will try to continue the last search
+ continue = false,
+ -- Set config to a function to dynamically change the config
+ config = nil, ---@type fun(opts:Flash.Config)|nil
+ -- You can override the default options for a specific mode.
+ -- Use it with `require("flash").jump({mode = "forward"})`
+ ---@type table
+ modes = {
+ -- options used when flash is activated through
+ -- a regular search with `/` or `?`
+ search = {
+ -- when `true`, flash will be activated during regular search by default.
+ -- You can always toggle when searching with `require("flash").toggle()`
+ enabled = false,
+ highlight = { backdrop = false },
+ jump = { history = true, register = true, nohlsearch = true },
+ search = {
+ -- `forward` will be automatically set to the search direction
+ -- `mode` is always set to `search`
+ -- `incremental` is set to `true` when `incsearch` is enabled
+ },
+ },
+ -- options used when flash is activated through
+ -- `f`, `F`, `t`, `T`, `;` and `,` motions
+ char = {
+ enabled = true,
+ -- dynamic configuration for ftFT motions
+ config = function(opts)
+ -- autohide flash when in operator-pending mode
+ opts.autohide = opts.autohide or (vim.fn.mode(true):find("no") and vim.v.operator == "y")
+
+ -- disable jump labels when not enabled, when using a count,
+ -- or when recording/executing registers
+ opts.jump_labels = opts.jump_labels
+ and vim.v.count == 0
+ and vim.fn.reg_executing() == ""
+ and vim.fn.reg_recording() == ""
+
+ -- Show jump labels only in operator-pending mode
+ -- opts.jump_labels = vim.v.count == 0 and vim.fn.mode(true):find("o")
+ end,
+ -- hide after jump when not using jump labels
+ autohide = false,
+ -- show jump labels
+ jump_labels = false,
+ -- set to `false` to use the current line only
+ multi_line = true,
+ -- When using jump labels, don't use these keys
+ -- This allows using those keys directly after the motion
+ label = { exclude = "hjkliardc" },
+ -- by default all keymaps are enabled, but you can disable some of them,
+ -- by removing them from the list.
+ -- If you rather use another key, you can map them
+ -- to something else, e.g., { [";"] = "L", [","] = H }
+ keys = { "f", "F", "t", "T", ";", "," },
+ ---@alias Flash.CharActions table
+ -- The direction for `prev` and `next` is determined by the motion.
+ -- `left` and `right` are always left and right.
+ char_actions = function(motion)
+ return {
+ [";"] = "next", -- set to `right` to always go right
+ [","] = "prev", -- set to `left` to always go left
+ -- clever-f style
+ [motion:lower()] = "next",
+ [motion:upper()] = "prev",
+ -- jump2d style: same case goes next, opposite case goes prev
+ -- [motion] = "next",
+ -- [motion:match("%l") and motion:upper() or motion:lower()] = "prev",
+ }
+ end,
+ search = { wrap = false },
+ highlight = { backdrop = true },
+ jump = { register = false },
+ },
+ -- options used for treesitter selections
+ -- `require("flash").treesitter()`
+ treesitter = {
+ labels = "abcdefghijklmnopqrstuvwxyz",
+ jump = { pos = "range" },
+ search = { incremental = false },
+ label = { before = true, after = true, style = "inline" },
+ highlight = {
+ backdrop = false,
+ matches = false,
+ },
+ },
+ treesitter_search = {
+ jump = { pos = "range" },
+ search = { multi_window = true, wrap = true, incremental = false },
+ remote_op = { restore = true },
+ label = { before = true, after = true, style = "inline" },
+ },
+ -- options used for remote flash
+ remote = {
+ remote_op = { restore = true, motion = true },
+ },
+ },
+ -- options for the floating window that shows the prompt,
+ -- for regular jumps
+ prompt = {
+ enabled = true,
+ prefix = { { "⚡", "FlashPromptIcon" } },
+ win_config = {
+ relative = "editor",
+ width = 1, -- when <=1 it's a percentage of the editor width
+ height = 1,
+ row = -1, -- when negative it's an offset from the bottom
+ col = 0, -- when negative it's an offset from the right
+ zindex = 1000,
+ },
+ },
+ -- options for remote operator pending mode
+ remote_op = {
+ -- restore window views and cursor position
+ -- after doing a remote operation
+ restore = false,
+ -- For `jump.pos = "range"`, this setting is ignored.
+ -- `true`: always enter a new motion when doing a remote operation
+ -- `false`: use the window's cursor position and jump target
+ -- `nil`: act as `true` for remote windows, `false` for the current window
+ motion = false,
+ },
+}
+```
+
+
+
+
+
+## 🚀 Usage
+
+- **Treesitter**: `require("flash").treesitter(opts?)` opens **flash** in **Treesitter** mode
+ - use a jump label, or use `;` and `,` to increase/decrease the selection
+- **regular search**: search as you normally do, but enhanced with jump labels.
+ You need to set `opts.modes.search.enabled = true`, or toggle it with `require("flash").toggle()`
+- `f`, `t`, `F`, `T` motions:
+ - After typing `f{char}` or `F{char},` you can repeat the motion with `f`
+ or go to the previous match with `F` to undo a jump.
+ - Similarly, after typing `t{char}` or `T{char},` you can repeat the motion
+ with `t` or go to the previous match with `T`.
+ - You can also go to the next match with `;` or previous match with `,`
+ - Any highlights clear automatically when moving, changing buffers,
+ or pressing ``.
+- **toggle Search**: `require("flash").toggle(boolean?)`
+ - toggles **flash** on or off while using regular search
+- **Treesitter Search**: `require("flash").treesitter_search(opts?)` opens **flash** in **Treesitter Search** mode
+ - combination of **Treesitter** and **Search** modes
+ - do something like `yR`
+ - you can now start typing a search pattern.
+ - arround your matches, all the surrounding Treesitter nodes will be labeled.
+ - select a label to perform the operator on the new selection
+- **remote**: `require("flash").remote(opts?)` opens **flash** in **remote** mode
+
+ - equivalent to:
+
+ ```lua
+ require("flash").jump({
+ remote_op = {
+ restore = true,
+ motion = true,
+ },
+ })
+ ```
+
+ - this is only useful in operator pending mode.
+ - For example, press `yr` to start yanking and open flash
+ - select a label to set the cursor position
+ - perform any motion, like `iw` or even start flash Treesitter with `S`
+ - the yank will be performed on the new selection
+ - you'll be back in the original window / position
+ - You can also configure the `remote_op` options by default, so that `ys`,
+ behaves like `yr` for remote operations
+
+ ```lua
+ require("flash").jump({
+ remote_op = {
+ restore = true,
+ motion = nil,
+ },
+ })
+ ```
+
+- **jump**: `require("flash").jump(opts?)` opens **flash** with the given options
+ - type any number of characters before typing a jump label
+- **VS Code**: some functionality is changed/disabled when running **flash** in **VS Code**:
+ - `prompt` is disabled
+ - `highlights` are set to different defaults that will actually work in VS Code
+
+## 📡 API
+
+The options for `require("flash").jump(opts?)`, are the same as
+those in the config section, but can additionally have the following fields:
+
+- `matcher`: a custom function that generates matches for a given window
+- `labeler`: a custom function to label matches
+
+You can also add labels in the `matcher` function and then set `labeler`
+to an empty function `labeler = function() end`
+
+Type Definitions
+
+```typescript
+type FlashMatcher = (win: number, state: FlashState) => FlashMatch[];
+type FlashLabeler = (matches: FlashMatch[], state: FlashState) => void;
+
+interface FlashMatch {
+ win: number;
+ pos: [number, number]; // (1,0)-indexed
+ end_pos: [number, number]; // (1,0)-indexed
+ label?: string | false; // set to false to never show a label for this match
+ highlight?: boolean; // override opts.highlight.matches for this match
+}
+
+// Check the code for the full definition
+// of Flash.State at `lua/flash/state.lua`
+type FlashState = {};
+```
+
+
+
+## 💡 Examples
+
+Forward search only
+
+```lua
+require("flash").jump({
+ search = { forward = true, wrap = false, multi_window = false },
+})
+```
+
+
+
+Backward search only
+
+```lua
+require("flash").jump({
+ search = { forward = false, wrap = false, multi_window = false },
+})
+```
+
+
+
+Show diagnostics at target, without changing cursor position
+
+```lua
+require("flash").jump({
+ action = function(match, state)
+ vim.api.nvim_win_call(match.win, function()
+ vim.api.nvim_win_set_cursor(match.win, match.pos)
+ vim.diagnostic.open_float()
+ end)
+ state:restore()
+ end,
+})
+
+-- More advanced example that also highlights diagnostics:
+require("flash").jump({
+ matcher = function(win)
+ ---@param diag Diagnostic
+ return vim.tbl_map(function(diag)
+ return {
+ pos = { diag.lnum + 1, diag.col },
+ end_pos = { diag.end_lnum + 1, diag.end_col - 1 },
+ }
+ end, vim.diagnostic.get(vim.api.nvim_win_get_buf(win)))
+ end,
+ action = function(match, state)
+ vim.api.nvim_win_call(match.win, function()
+ vim.api.nvim_win_set_cursor(match.win, match.pos)
+ vim.diagnostic.open_float()
+ end)
+ state:restore()
+ end,
+})
+```
+
+
+
+Match beginning of words only
+
+```lua
+require("flash").jump({
+ search = {
+ mode = function(str)
+ return "\\<" .. str
+ end,
+ },
+})
+```
+
+
+
+Initialize flash with the word under the cursor
+
+```lua
+require("flash").jump({
+ pattern = vim.fn.expand(""),
+})
+```
+
+
+
+Jump to a line
+
+```lua
+require("flash").jump({
+ search = { mode = "search", max_length = 0 },
+ label = { after = { 0, 0 } },
+ pattern = "^"
+})
+```
+
+
+
+Select any word
+
+```lua
+require("flash").jump({
+ pattern = ".", -- initialize pattern with any char
+ search = {
+ mode = function(pattern)
+ -- remove leading dot
+ if pattern:sub(1, 1) == "." then
+ pattern = pattern:sub(2)
+ end
+ -- return word pattern and proper skip pattern
+ return ([[\<%s\w*\>]]):format(pattern), ([[\<%s]]):format(pattern)
+ end,
+ },
+ -- select the range
+ jump = { pos = "range" },
+})
+```
+
+
+
+f, t, F, T with labels
+
+Use the options below:
+
+```lua
+{
+ modes = {
+ char = {
+ jump_labels = true
+ }
+ }
+}
+```
+
+
+
+Telescope integration
+
+This will allow you to use `s` in normal mode
+and `` in insert mode, to jump to a label in Telescope results.
+
+```lua
+{
+ "nvim-telescope/telescope.nvim",
+ optional = true,
+ opts = function(_, opts)
+ local function flash(prompt_bufnr)
+ require("flash").jump({
+ pattern = "^",
+ label = { after = { 0, 0 } },
+ search = {
+ mode = "search",
+ exclude = {
+ function(win)
+ return vim.bo[vim.api.nvim_win_get_buf(win)].filetype ~= "TelescopeResults"
+ end,
+ },
+ },
+ action = function(match)
+ local picker = require("telescope.actions.state").get_current_picker(prompt_bufnr)
+ picker:set_selection(match.pos[1] - 1)
+ end,
+ })
+ end
+ opts.defaults = vim.tbl_deep_extend("force", opts.defaults or {}, {
+ mappings = {
+ n = { s = flash },
+ i = { [""] = flash },
+ },
+ })
+ end,
+ }
+```
+
+
+
+Continue last search
+
+```lua
+require("flash").jump({continue = true})
+```
+
+
+
+
+ 2-char jump, similar to
+
+ mini.jump2d
+
+ or
+
+ HopWord (hop.nvim)
+
+
+
+```lua
+local Flash = require("flash")
+
+---@param opts Flash.Format
+local function format(opts)
+ -- always show first and second label
+ return {
+ { opts.match.label1, "FlashMatch" },
+ { opts.match.label2, "FlashLabel" },
+ }
+end
+
+Flash.jump({
+ search = { mode = "search" },
+ label = { after = false, before = { 0, 0 }, uppercase = false, format = format },
+ pattern = [[\<]],
+ action = function(match, state)
+ state:hide()
+ Flash.jump({
+ search = { max_length = 0 },
+ highlight = { matches = false },
+ label = { format = format },
+ matcher = function(win)
+ -- limit matches to the current label
+ return vim.tbl_filter(function(m)
+ return m.label == match.label and m.win == win
+ end, state.results)
+ end,
+ labeler = function(matches)
+ for _, m in ipairs(matches) do
+ m.label = m.label2 -- use the second label
+ end
+ end,
+ })
+ end,
+ labeler = function(matches, state)
+ local labels = state:labels()
+ for m, match in ipairs(matches) do
+ match.label1 = labels[math.floor((m - 1) / #labels) + 1]
+ match.label2 = labels[(m - 1) % #labels + 1]
+ match.label = match.label1
+ end
+ end,
+})
+```
+
+
+
+## 🌈 Highlights
+
+| Group | Default | Description |
+| ----------------- | ------------ | -------------- |
+| `FlashBackdrop` | `Comment` | backdrop |
+| `FlashMatch` | `Search` | search matches |
+| `FlashCurrent` | `IncSearch` | current match |
+| `FlashLabel` | `Substitute` | jump label |
+| `FlashPrompt` | `MsgArea` | prompt |
+| `FlashPromptIcon` | `Special` | prompt icon |
+| `FlashCursor` | `Cursor` | cursor |
+
+## 📦 Alternatives
+
+- [leap.nvim](https://github.com/ggandor/leap.nvim)
+- [lightspeed.nvim](https://github.com/ggandor/lightspeed.nvim)
+- [vim-sneak](https://github.com/justinmk/vim-sneak)
+- [mini.jump](https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-jump.md)
+- [mini.jump2d](https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-jump2d.md)
+- [hop.nvim](https://github.com/phaazon/hop.nvim)
+- [pounce.nvim](https://github.com/rlane/pounce.nvim)
+- [sj.nvim](https://github.com/woosaaahh/sj.nvim)
+- [nvim-treehopper](https://github.com/mfussenegger/nvim-treehopper)
+- [flit.nvim](https://github.com/ggandor/flit.nvim)
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/doc/flash.nvim.txt b/config/neovim/store/lazy-plugins/flash.nvim/doc/flash.nvim.txt
new file mode 100644
index 00000000..9692c2b2
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/doc/flash.nvim.txt
@@ -0,0 +1,671 @@
+*flash.nvim.txt* For Neovim >= 0.8.0 Last change: 2024 May 14
+
+==============================================================================
+Table of Contents *flash.nvim-table-of-contents*
+
+1. flash.nvim |flash.nvim-flash.nvim|
+ - Features |flash.nvim-flash.nvim-features|
+ - Requirements |flash.nvim-flash.nvim-requirements|
+ - Installation |flash.nvim-flash.nvim-installation|
+ - Configuration |flash.nvim-flash.nvim-configuration|
+ - Usage |flash.nvim-flash.nvim-usage|
+ - API |flash.nvim-flash.nvim-api|
+ - Examples |flash.nvim-flash.nvim-examples|
+ - Highlights |flash.nvim-flash.nvim-highlights|
+ - Alternatives |flash.nvim-flash.nvim-alternatives|
+
+==============================================================================
+1. flash.nvim *flash.nvim-flash.nvim*
+
+`flash.nvim` lets you navigate your code with search labels, enhanced character
+motions, and Treesitter integration.
+
+Search IntegrationStandalone Jumpf, t, F, TTreesitter
+FEATURES *flash.nvim-flash.nvim-features*
+
+- **Search Integration**integrate **flash.nvim** with your regular
+ search using `/` or `?`. Labels appear next to the matches,
+ allowing you to quickly jump to any location. Labels are
+ guaranteed not to exist as a continuation of the search pattern.
+- **type as many characters as you want** before using a jump label.
+- **Enhanced f, t, F, T motions**
+- **Treesitter Integration**all parents of the Treesitter node
+ under your cursor are highlighted with a label for quick selection
+ of a specific Treesitter node.
+- **Jump Mode**a standalone jumping mode similar to search
+- **Search Modes**`exact`, `search` (regex), and `fuzzy` search modes
+- **Multi Window** jumping
+- **Remote Actions**perform motions in remote locations
+- **dot-repeatable** jumps
+- **highly extensible**check the examples
+
+
+REQUIREMENTS *flash.nvim-flash.nvim-requirements*
+
+- Neovim >= **0.8.0** (needs to be built with **LuaJIT**)
+
+
+INSTALLATION *flash.nvim-flash.nvim-installation*
+
+Install the plugin with your preferred package manager:
+
+lazy.nvim
+
+>lua
+ {
+ "folke/flash.nvim",
+ event = "VeryLazy",
+ ---@type Flash.Config
+ opts = {},
+ -- stylua: ignore
+ keys = {
+ { "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" },
+ { "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
+ { "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
+ { "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
+ { "", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
+ },
+ }
+<
+
+
+ When creating the keymaps manually either use a lua function like `function()
+ require("flash").jump() end` as the **rhs**, or a string like `lua
+ require("flash").jump()`. **DO NOT** use `:lua`, since that will break
+ **dot-repeat**
+
+CONFIGURATION *flash.nvim-flash.nvim-configuration*
+
+**flash.nvim** is highly configurable. Please refer to the default settings
+below.
+
+Default Settings ~
+
+>lua
+ {
+ -- labels = "abcdefghijklmnopqrstuvwxyz",
+ labels = "asdfghjklqwertyuiopzxcvbnm",
+ search = {
+ -- search/jump in all windows
+ multi_window = true,
+ -- search direction
+ forward = true,
+ -- when `false`, find only matches in the given direction
+ wrap = true,
+ ---@type Flash.Pattern.Mode
+ -- Each mode will take ignorecase and smartcase into account.
+ -- * exact: exact match
+ -- * search: regular search
+ -- * fuzzy: fuzzy search
+ -- * fun(str): custom function that returns a pattern
+ -- For example, to only match at the beginning of a word:
+ -- mode = function(str)
+ -- return "\\<" .. str
+ -- end,
+ mode = "exact",
+ -- behave like `incsearch`
+ incremental = false,
+ -- Excluded filetypes and custom window filters
+ ---@type (string|fun(win:window))[]
+ exclude = {
+ "notify",
+ "cmp_menu",
+ "noice",
+ "flash_prompt",
+ function(win)
+ -- exclude non-focusable windows
+ return not vim.api.nvim_win_get_config(win).focusable
+ end,
+ },
+ -- Optional trigger character that needs to be typed before
+ -- a jump label can be used. It's NOT recommended to set this,
+ -- unless you know what you're doing
+ trigger = "",
+ -- max pattern length. If the pattern length is equal to this
+ -- labels will no longer be skipped. When it exceeds this length
+ -- it will either end in a jump or terminate the search
+ max_length = false, ---@type number|false
+ },
+ jump = {
+ -- save location in the jumplist
+ jumplist = true,
+ -- jump position
+ pos = "start", ---@type "start" | "end" | "range"
+ -- add pattern to search history
+ history = false,
+ -- add pattern to search register
+ register = false,
+ -- clear highlight after jump
+ nohlsearch = false,
+ -- automatically jump when there is only one match
+ autojump = false,
+ -- You can force inclusive/exclusive jumps by setting the
+ -- `inclusive` option. By default it will be automatically
+ -- set based on the mode.
+ inclusive = nil, ---@type boolean?
+ -- jump position offset. Not used for range jumps.
+ -- 0: default
+ -- 1: when pos == "end" and pos < current position
+ offset = nil, ---@type number
+ },
+ label = {
+ -- allow uppercase labels
+ uppercase = true,
+ -- add any labels with the correct case here, that you want to exclude
+ exclude = "",
+ -- add a label for the first match in the current window.
+ -- you can always jump to the first match with ``
+ current = true,
+ -- show the label after the match
+ after = true, ---@type boolean|number[]
+ -- show the label before the match
+ before = false, ---@type boolean|number[]
+ -- position of the label extmark
+ style = "overlay", ---@type "eol" | "overlay" | "right_align" | "inline"
+ -- flash tries to re-use labels that were already assigned to a position,
+ -- when typing more characters. By default only lower-case labels are re-used.
+ reuse = "lowercase", ---@type "lowercase" | "all" | "none"
+ -- for the current window, label targets closer to the cursor first
+ distance = true,
+ -- minimum pattern length to show labels
+ -- Ignored for custom labelers.
+ min_pattern_length = 0,
+ -- Enable this to use rainbow colors to highlight labels
+ -- Can be useful for visualizing Treesitter ranges.
+ rainbow = {
+ enabled = false,
+ -- number between 1 and 9
+ shade = 5,
+ },
+ -- With `format`, you can change how the label is rendered.
+ -- Should return a list of `[text, highlight]` tuples.
+ ---@class Flash.Format
+ ---@field state Flash.State
+ ---@field match Flash.Match
+ ---@field hl_group string
+ ---@field after boolean
+ ---@type fun(opts:Flash.Format): string[][]
+ format = function(opts)
+ return { { opts.match.label, opts.hl_group } }
+ end,
+ },
+ highlight = {
+ -- show a backdrop with hl FlashBackdrop
+ backdrop = true,
+ -- Highlight the search matches
+ matches = true,
+ -- extmark priority
+ priority = 5000,
+ groups = {
+ match = "FlashMatch",
+ current = "FlashCurrent",
+ backdrop = "FlashBackdrop",
+ label = "FlashLabel",
+ },
+ },
+ -- action to perform when picking a label.
+ -- defaults to the jumping logic depending on the mode.
+ ---@type fun(match:Flash.Match, state:Flash.State)|nil
+ action = nil,
+ -- initial pattern to use when opening flash
+ pattern = "",
+ -- When `true`, flash will try to continue the last search
+ continue = false,
+ -- Set config to a function to dynamically change the config
+ config = nil, ---@type fun(opts:Flash.Config)|nil
+ -- You can override the default options for a specific mode.
+ -- Use it with `require("flash").jump({mode = "forward"})`
+ ---@type table
+ modes = {
+ -- options used when flash is activated through
+ -- a regular search with `/` or `?`
+ search = {
+ -- when `true`, flash will be activated during regular search by default.
+ -- You can always toggle when searching with `require("flash").toggle()`
+ enabled = false,
+ highlight = { backdrop = false },
+ jump = { history = true, register = true, nohlsearch = true },
+ search = {
+ -- `forward` will be automatically set to the search direction
+ -- `mode` is always set to `search`
+ -- `incremental` is set to `true` when `incsearch` is enabled
+ },
+ },
+ -- options used when flash is activated through
+ -- `f`, `F`, `t`, `T`, `;` and `,` motions
+ char = {
+ enabled = true,
+ -- dynamic configuration for ftFT motions
+ config = function(opts)
+ -- autohide flash when in operator-pending mode
+ opts.autohide = opts.autohide or (vim.fn.mode(true):find("no") and vim.v.operator == "y")
+
+ -- disable jump labels when not enabled, when using a count,
+ -- or when recording/executing registers
+ opts.jump_labels = opts.jump_labels
+ and vim.v.count == 0
+ and vim.fn.reg_executing() == ""
+ and vim.fn.reg_recording() == ""
+
+ -- Show jump labels only in operator-pending mode
+ -- opts.jump_labels = vim.v.count == 0 and vim.fn.mode(true):find("o")
+ end,
+ -- hide after jump when not using jump labels
+ autohide = false,
+ -- show jump labels
+ jump_labels = false,
+ -- set to `false` to use the current line only
+ multi_line = true,
+ -- When using jump labels, don't use these keys
+ -- This allows using those keys directly after the motion
+ label = { exclude = "hjkliardc" },
+ -- by default all keymaps are enabled, but you can disable some of them,
+ -- by removing them from the list.
+ -- If you rather use another key, you can map them
+ -- to something else, e.g., { [";"] = "L", [","] = H }
+ keys = { "f", "F", "t", "T", ";", "," },
+ ---@alias Flash.CharActions table
+ -- The direction for `prev` and `next` is determined by the motion.
+ -- `left` and `right` are always left and right.
+ char_actions = function(motion)
+ return {
+ [";"] = "next", -- set to `right` to always go right
+ [","] = "prev", -- set to `left` to always go left
+ -- clever-f style
+ [motion:lower()] = "next",
+ [motion:upper()] = "prev",
+ -- jump2d style: same case goes next, opposite case goes prev
+ -- [motion] = "next",
+ -- [motion:match("%l") and motion:upper() or motion:lower()] = "prev",
+ }
+ end,
+ search = { wrap = false },
+ highlight = { backdrop = true },
+ jump = { register = false },
+ },
+ -- options used for treesitter selections
+ -- `require("flash").treesitter()`
+ treesitter = {
+ labels = "abcdefghijklmnopqrstuvwxyz",
+ jump = { pos = "range" },
+ search = { incremental = false },
+ label = { before = true, after = true, style = "inline" },
+ highlight = {
+ backdrop = false,
+ matches = false,
+ },
+ },
+ treesitter_search = {
+ jump = { pos = "range" },
+ search = { multi_window = true, wrap = true, incremental = false },
+ remote_op = { restore = true },
+ label = { before = true, after = true, style = "inline" },
+ },
+ -- options used for remote flash
+ remote = {
+ remote_op = { restore = true, motion = true },
+ },
+ },
+ -- options for the floating window that shows the prompt,
+ -- for regular jumps
+ prompt = {
+ enabled = true,
+ prefix = { { "⚡", "FlashPromptIcon" } },
+ win_config = {
+ relative = "editor",
+ width = 1, -- when <=1 it's a percentage of the editor width
+ height = 1,
+ row = -1, -- when negative it's an offset from the bottom
+ col = 0, -- when negative it's an offset from the right
+ zindex = 1000,
+ },
+ },
+ -- options for remote operator pending mode
+ remote_op = {
+ -- restore window views and cursor position
+ -- after doing a remote operation
+ restore = false,
+ -- For `jump.pos = "range"`, this setting is ignored.
+ -- `true`: always enter a new motion when doing a remote operation
+ -- `false`: use the window's cursor position and jump target
+ -- `nil`: act as `true` for remote windows, `false` for the current window
+ motion = false,
+ },
+ }
+<
+
+
+USAGE *flash.nvim-flash.nvim-usage*
+
+- **Treesitter**`require("flash").treesitter(opts?)` opens **flash** in
+ **Treesitter** mode
+ - use a jump label, or use `;` and `,` to increase/decrease the selection
+- **regular search**search as you normally do, but enhanced with jump labels. You
+ need to set `opts.modes.search.enabled = true`, or toggle it with
+ `require("flash").toggle()`
+- `f`, `t`, `F`, `T` motions:
+ - After typing `f{char}` or `F{char},` you can repeat the motion with `f`
+ or go to the previous match with `F` to undo a jump.
+ - Similarly, after typing `t{char}` or `T{char},` you can repeat the motion
+ with `t` or go to the previous match with `T`.
+ - You can also go to the next match with `;` or previous match with `,`
+ - Any highlights clear automatically when moving, changing buffers,
+ or pressing ``.
+- **toggle Search**`require("flash").toggle(boolean?)`
+ - toggles **flash** on or off while using regular search
+- **Treesitter Search**`require("flash").treesitter_search(opts?)` opens
+ **flash** in **Treesitter Search** mode
+ - combination of **Treesitter** and **Search** modes
+ - do something like `yR`
+ - you can now start typing a search pattern.
+ - arround your matches, all the surrounding Treesitter nodes will be labeled.
+ - select a label to perform the operator on the new selection
+- **remote**`require("flash").remote(opts?)` opens **flash** in **remote** mode
+ - equivalent to:
+ >lua
+ require("flash").jump({
+ remote_op = {
+ restore = true,
+ motion = true,
+ },
+ })
+ <
+ - this is only useful in operator pending mode.
+ - For example, press `yr` to start yanking and open flash
+ - select a label to set the cursor position
+ - perform any motion, like `iw` or even start flash Treesitter with `S`
+ - the yank will be performed on the new selection
+ - you’ll be back in the original window / position
+ - You can also configure the `remote_op` options by default, so that `ys`,
+ behaves like `yr` for remote operations
+ >lua
+ require("flash").jump({
+ remote_op = {
+ restore = true,
+ motion = nil,
+ },
+ })
+ <
+- **jump**`require("flash").jump(opts?)` opens **flash** with the given options
+ - type any number of characters before typing a jump label
+- **VS Code**some functionality is changed/disabled when running **flash** in
+ **VS Code**
+ - `prompt`is disabled
+ - `highlights` are set to different defaults that will actually work in VS Code
+
+
+API *flash.nvim-flash.nvim-api*
+
+The options for `require("flash").jump(opts?)`, are the same as those in the
+config section, but can additionally have the following fields:
+
+- `matcher`a custom function that generates matches for a given window
+- `labeler`a custom function to label matches
+
+You can also add labels in the `matcher` function and then set `labeler` to an
+empty function `labeler = function() end`
+
+Type Definitions ~
+
+>typescript
+ type FlashMatcher = (win: number, state: FlashState) => FlashMatch[];
+ type FlashLabeler = (matches: FlashMatch[], state: FlashState) => void;
+
+ interface FlashMatch {
+ win: number;
+ pos: [number, number]; // (1,0)-indexed
+ end_pos: [number, number]; // (1,0)-indexed
+ label?: string | false; // set to false to never show a label for this match
+ highlight?: boolean; // override opts.highlight.matches for this match
+ }
+
+ // Check the code for the full definition
+ // of Flash.State at `lua/flash/state.lua`
+ type FlashState = {};
+<
+
+
+EXAMPLES *flash.nvim-flash.nvim-examples*
+
+Forward search only ~
+
+>lua
+ require("flash").jump({
+ search = { forward = true, wrap = false, multi_window = false },
+ })
+<
+
+Backward search only ~
+
+>lua
+ require("flash").jump({
+ search = { forward = false, wrap = false, multi_window = false },
+ })
+<
+
+Show diagnostics at target, without changing cursor position ~
+
+>lua
+ require("flash").jump({
+ action = function(match, state)
+ vim.api.nvim_win_call(match.win, function()
+ vim.api.nvim_win_set_cursor(match.win, match.pos)
+ vim.diagnostic.open_float()
+ end)
+ state:restore()
+ end,
+ })
+
+ -- More advanced example that also highlights diagnostics:
+ require("flash").jump({
+ matcher = function(win)
+ ---@param diag Diagnostic
+ return vim.tbl_map(function(diag)
+ return {
+ pos = { diag.lnum + 1, diag.col },
+ end_pos = { diag.end_lnum + 1, diag.end_col - 1 },
+ }
+ end, vim.diagnostic.get(vim.api.nvim_win_get_buf(win)))
+ end,
+ action = function(match, state)
+ vim.api.nvim_win_call(match.win, function()
+ vim.api.nvim_win_set_cursor(match.win, match.pos)
+ vim.diagnostic.open_float()
+ end)
+ state:restore()
+ end,
+ })
+<
+
+Match beginning of words only ~
+
+>lua
+ require("flash").jump({
+ search = {
+ mode = function(str)
+ return "\\<" .. str
+ end,
+ },
+ })
+<
+
+Initialize flash with the word under the cursor ~
+
+>lua
+ require("flash").jump({
+ pattern = vim.fn.expand(""),
+ })
+<
+
+Jump to a line ~
+
+>lua
+ require("flash").jump({
+ search = { mode = "search", max_length = 0 },
+ label = { after = { 0, 0 } },
+ pattern = "^"
+ })
+<
+
+Select any word ~
+
+>lua
+ require("flash").jump({
+ pattern = ".", -- initialize pattern with any char
+ search = {
+ mode = function(pattern)
+ -- remove leading dot
+ if pattern:sub(1, 1) == "." then
+ pattern = pattern:sub(2)
+ end
+ -- return word pattern and proper skip pattern
+ return ([[\<%s\w*\>]]):format(pattern), ([[\<%s]]):format(pattern)
+ end,
+ },
+ -- select the range
+ jump = { pos = "range" },
+ })
+<
+
+f, t, F, T with labels ~
+
+Use the options below:
+
+>lua
+ {
+ modes = {
+ char = {
+ jump_labels = true
+ }
+ }
+ }
+<
+
+Telescope integration ~
+
+This will allow you to use `s` in normal mode and `` in insert mode, to
+jump to a label in Telescope results.
+
+>lua
+ {
+ "nvim-telescope/telescope.nvim",
+ optional = true,
+ opts = function(_, opts)
+ local function flash(prompt_bufnr)
+ require("flash").jump({
+ pattern = "^",
+ label = { after = { 0, 0 } },
+ search = {
+ mode = "search",
+ exclude = {
+ function(win)
+ return vim.bo[vim.api.nvim_win_get_buf(win)].filetype ~= "TelescopeResults"
+ end,
+ },
+ },
+ action = function(match)
+ local picker = require("telescope.actions.state").get_current_picker(prompt_bufnr)
+ picker:set_selection(match.pos[1] - 1)
+ end,
+ })
+ end
+ opts.defaults = vim.tbl_deep_extend("force", opts.defaults or {}, {
+ mappings = {
+ n = { s = flash },
+ i = { [""] = flash },
+ },
+ })
+ end,
+ }
+<
+
+Continue last search ~
+
+>lua
+ require("flash").jump({continue = true})
+<
+
+2-char jump, similar to
+
+mini.jump2d
+
+or
+
+HopWord (hop.nvim)
+ ~
+
+>lua
+ local Flash = require("flash")
+
+ ---@param opts Flash.Format
+ local function format(opts)
+ -- always show first and second label
+ return {
+ { opts.match.label1, "FlashMatch" },
+ { opts.match.label2, "FlashLabel" },
+ }
+ end
+
+ Flash.jump({
+ search = { mode = "search" },
+ label = { after = false, before = { 0, 0 }, uppercase = false, format = format },
+ pattern = [[\<]],
+ action = function(match, state)
+ state:hide()
+ Flash.jump({
+ search = { max_length = 0 },
+ highlight = { matches = false },
+ label = { format = format },
+ matcher = function(win)
+ -- limit matches to the current label
+ return vim.tbl_filter(function(m)
+ return m.label == match.label and m.win == win
+ end, state.results)
+ end,
+ labeler = function(matches)
+ for _, m in ipairs(matches) do
+ m.label = m.label2 -- use the second label
+ end
+ end,
+ })
+ end,
+ labeler = function(matches, state)
+ local labels = state:labels()
+ for m, match in ipairs(matches) do
+ match.label1 = labels[math.floor((m - 1) / #labels) + 1]
+ match.label2 = labels[(m - 1) % #labels + 1]
+ match.label = match.label1
+ end
+ end,
+ })
+<
+
+
+HIGHLIGHTS *flash.nvim-flash.nvim-highlights*
+
+ Group Default Description
+ ----------------- ------------ ----------------
+ FlashBackdrop Comment backdrop
+ FlashMatch Search search matches
+ FlashCurrent IncSearch current match
+ FlashLabel Substitute jump label
+ FlashPrompt MsgArea prompt
+ FlashPromptIcon Special prompt icon
+ FlashCursor Cursor cursor
+
+ALTERNATIVES *flash.nvim-flash.nvim-alternatives*
+
+- leap.nvim
+- lightspeed.nvim
+- vim-sneak
+- mini.jump
+- mini.jump2d
+- hop.nvim
+- pounce.nvim
+- sj.nvim
+- nvim-treehopper
+- flit.nvim
+
+Generated by panvimdoc
+
+vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/cache.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/cache.lua
new file mode 100644
index 00000000..3b4cb502
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/cache.lua
@@ -0,0 +1,149 @@
+local Pattern = require("flash.search.pattern")
+local Pos = require("flash.search.pos")
+local Util = require("flash.util")
+
+---@class Flash.State.Window
+---@field win number
+---@field buf number
+---@field topline number
+---@field botline number
+---@field changedtick number
+
+---@class Flash.Cache
+---@field state Flash.State
+---@field pattern Flash.Pattern
+---@field wins Flash.State.Window[]
+local M = {}
+M.__index = M
+
+---@type table
+M.cache = setmetatable({}, { __mode = "k" })
+
+---@param state Flash.State
+function M.new(state)
+ local self = setmetatable({}, M)
+ self.state = state
+ self.pattern = Pattern.new("", state.opts.search.mode, state.opts.search.trigger)
+ self.wins = {}
+ return self
+end
+
+---@return boolean dirty Returns true when dirty
+function M:update()
+ local dirty = false
+
+ if self.pattern ~= self.state.pattern then
+ self.pattern = self.state.pattern:clone()
+ dirty = true
+ M.cache = {}
+ end
+
+ local win = vim.api.nvim_get_current_win()
+ if self.state.win ~= win then
+ self.state.win = win
+ self.state.pos = Pos(win)
+ self.state.restore_windows = Util.save_layout()
+ M.cache = {}
+ dirty = true
+ end
+
+ self:_update_wins()
+
+ for _, w in ipairs(self.state.wins) do
+ if self:_dirty(w) then
+ dirty = true
+ end
+ end
+ return dirty
+end
+
+---@param win window
+function M:get_state(win)
+ local window = self:get(win)
+ if not window then
+ return
+ end
+ if M.cache[window] then
+ return M.cache[window]
+ end
+
+ local from = Pos({ window.topline, 0 })
+ local to = Pos({ window.botline + 1, 0 })
+
+ if not self.state.opts.search.wrap and win == self.state.win then
+ if self.state.opts.search.forward then
+ from = self.state.pos
+ else
+ to = self.state.pos
+ end
+ end
+
+ local matcher = self.state:get_matcher(win)
+ if matcher.update then
+ matcher:update()
+ end
+
+ M.cache[window] = {
+ matches = matcher:get({ from = from, to = to }),
+ }
+ return M.cache[window]
+end
+
+---@param win window
+---@return Flash.State.Window
+function M:get(win)
+ return self.wins[win]
+end
+
+function M:_update_wins()
+ -- prioritize current window
+ self.state.wins = { self.state.win }
+
+ if self.state.opts.search.multi_window then
+ local keep_current = false
+
+ ---@param w window
+ self.state.wins = vim.tbl_filter(function(w)
+ local buf = vim.api.nvim_win_get_buf(w)
+ local ft = vim.bo[buf].filetype
+
+ for _, exclude in ipairs(self.state.opts.search.exclude) do
+ if type(exclude) == "string" and exclude == ft then
+ return false
+ elseif type(exclude) == "function" and exclude(w) then
+ return false
+ end
+ end
+ if w == self.state.win then
+ keep_current = true
+ return false
+ end
+ return true
+ end, vim.api.nvim_tabpage_list_wins(0))
+ if keep_current then
+ table.insert(self.state.wins, 1, self.state.win)
+ end
+ end
+end
+
+---@param win window
+function M:_dirty(win)
+ local info = vim.fn.getwininfo(win)[1]
+ local buf = vim.api.nvim_win_get_buf(win)
+
+ ---@type Flash.State.Window
+ local state = {
+ win = win,
+ buf = buf,
+ cursor = vim.api.nvim_win_get_cursor(win),
+ topline = info.topline,
+ botline = info.botline,
+ changedtick = vim.b[buf].changedtick,
+ }
+ if not vim.deep_equal(state, self.wins[win]) then
+ self.wins[win] = state
+ return true
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/commands.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/commands.lua
new file mode 100644
index 00000000..6a7b1bce
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/commands.lua
@@ -0,0 +1,36 @@
+local Repeat = require("flash.repeat")
+
+---@class Flash.Commands
+local M = {}
+
+---@param opts? Flash.State.Config
+function M.jump(opts)
+ local state = Repeat.get_state("jump", opts)
+ state:loop()
+ return state
+end
+
+---@param opts? Flash.State.Config
+function M.treesitter(opts)
+ return require("flash.plugins.treesitter").jump(opts)
+end
+
+---@param opts? Flash.State.Config
+function M.treesitter_search(opts)
+ return require("flash.plugins.treesitter").search(opts)
+end
+
+---@param opts? Flash.State.Config
+function M.remote(opts)
+ local Config = require("flash.config")
+ opts = Config.get({ mode = "remote" }, opts)
+ return M.jump(opts)
+end
+
+---@param enabled? boolean
+function M.toggle(enabled)
+ local Search = require("flash.plugins.search")
+ return Search.toggle(enabled)
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/config.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/config.lua
new file mode 100644
index 00000000..06af1787
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/config.lua
@@ -0,0 +1,345 @@
+---@type Flash.Config
+local M = {}
+
+---@class Flash.Config
+---@field mode? string
+---@field enabled? boolean
+---@field ns? string
+---@field config? fun(opts:Flash.Config)
+local defaults = {
+ -- labels = "abcdefghijklmnopqrstuvwxyz",
+ labels = "asdfghjklqwertyuiopzxcvbnm",
+ search = {
+ -- search/jump in all windows
+ multi_window = true,
+ -- search direction
+ forward = true,
+ -- when `false`, find only matches in the given direction
+ wrap = true,
+ ---@type Flash.Pattern.Mode
+ -- Each mode will take ignorecase and smartcase into account.
+ -- * exact: exact match
+ -- * search: regular search
+ -- * fuzzy: fuzzy search
+ -- * fun(str): custom function that returns a pattern
+ -- For example, to only match at the beginning of a word:
+ -- mode = function(str)
+ -- return "\\<" .. str
+ -- end,
+ mode = "exact",
+ -- behave like `incsearch`
+ incremental = false,
+ -- Excluded filetypes and custom window filters
+ ---@type (string|fun(win:window))[]
+ exclude = {
+ "notify",
+ "cmp_menu",
+ "noice",
+ "flash_prompt",
+ function(win)
+ -- exclude non-focusable windows
+ return not vim.api.nvim_win_get_config(win).focusable
+ end,
+ },
+ -- Optional trigger character that needs to be typed before
+ -- a jump label can be used. It's NOT recommended to set this,
+ -- unless you know what you're doing
+ trigger = "",
+ -- max pattern length. If the pattern length is equal to this
+ -- labels will no longer be skipped. When it exceeds this length
+ -- it will either end in a jump or terminate the search
+ max_length = false, ---@type number|false
+ },
+ jump = {
+ -- save location in the jumplist
+ jumplist = true,
+ -- jump position
+ pos = "start", ---@type "start" | "end" | "range"
+ -- add pattern to search history
+ history = false,
+ -- add pattern to search register
+ register = false,
+ -- clear highlight after jump
+ nohlsearch = false,
+ -- automatically jump when there is only one match
+ autojump = false,
+ -- You can force inclusive/exclusive jumps by setting the
+ -- `inclusive` option. By default it will be automatically
+ -- set based on the mode.
+ inclusive = nil, ---@type boolean?
+ -- jump position offset. Not used for range jumps.
+ -- 0: default
+ -- 1: when pos == "end" and pos < current position
+ offset = nil, ---@type number
+ },
+ label = {
+ -- allow uppercase labels
+ uppercase = true,
+ -- add any labels with the correct case here, that you want to exclude
+ exclude = "",
+ -- add a label for the first match in the current window.
+ -- you can always jump to the first match with ``
+ current = true,
+ -- show the label after the match
+ after = true, ---@type boolean|number[]
+ -- show the label before the match
+ before = false, ---@type boolean|number[]
+ -- position of the label extmark
+ style = "overlay", ---@type "eol" | "overlay" | "right_align" | "inline"
+ -- flash tries to re-use labels that were already assigned to a position,
+ -- when typing more characters. By default only lower-case labels are re-used.
+ reuse = "lowercase", ---@type "lowercase" | "all" | "none"
+ -- for the current window, label targets closer to the cursor first
+ distance = true,
+ -- minimum pattern length to show labels
+ -- Ignored for custom labelers.
+ min_pattern_length = 0,
+ -- Enable this to use rainbow colors to highlight labels
+ -- Can be useful for visualizing Treesitter ranges.
+ rainbow = {
+ enabled = false,
+ -- number between 1 and 9
+ shade = 5,
+ },
+ -- With `format`, you can change how the label is rendered.
+ -- Should return a list of `[text, highlight]` tuples.
+ ---@class Flash.Format
+ ---@field state Flash.State
+ ---@field match Flash.Match
+ ---@field hl_group string
+ ---@field after boolean
+ ---@type fun(opts:Flash.Format): string[][]
+ format = function(opts)
+ return { { opts.match.label, opts.hl_group } }
+ end,
+ },
+ highlight = {
+ -- show a backdrop with hl FlashBackdrop
+ backdrop = true,
+ -- Highlight the search matches
+ matches = true,
+ -- extmark priority
+ priority = 5000,
+ groups = {
+ match = "FlashMatch",
+ current = "FlashCurrent",
+ backdrop = "FlashBackdrop",
+ label = "FlashLabel",
+ },
+ },
+ -- action to perform when picking a label.
+ -- defaults to the jumping logic depending on the mode.
+ ---@type fun(match:Flash.Match, state:Flash.State)|nil
+ action = nil,
+ -- initial pattern to use when opening flash
+ pattern = "",
+ -- When `true`, flash will try to continue the last search
+ continue = false,
+ -- Set config to a function to dynamically change the config
+ config = nil, ---@type fun(opts:Flash.Config)|nil
+ -- You can override the default options for a specific mode.
+ -- Use it with `require("flash").jump({mode = "forward"})`
+ ---@type table
+ modes = {
+ -- options used when flash is activated through
+ -- a regular search with `/` or `?`
+ search = {
+ -- when `true`, flash will be activated during regular search by default.
+ -- You can always toggle when searching with `require("flash").toggle()`
+ enabled = false,
+ highlight = { backdrop = false },
+ jump = { history = true, register = true, nohlsearch = true },
+ search = {
+ -- `forward` will be automatically set to the search direction
+ -- `mode` is always set to `search`
+ -- `incremental` is set to `true` when `incsearch` is enabled
+ },
+ },
+ -- options used when flash is activated through
+ -- `f`, `F`, `t`, `T`, `;` and `,` motions
+ char = {
+ enabled = true,
+ -- dynamic configuration for ftFT motions
+ config = function(opts)
+ -- autohide flash when in operator-pending mode
+ opts.autohide = opts.autohide or (vim.fn.mode(true):find("no") and vim.v.operator == "y")
+
+ -- disable jump labels when not enabled, when using a count,
+ -- or when recording/executing registers
+ opts.jump_labels = opts.jump_labels
+ and vim.v.count == 0
+ and vim.fn.reg_executing() == ""
+ and vim.fn.reg_recording() == ""
+
+ -- Show jump labels only in operator-pending mode
+ -- opts.jump_labels = vim.v.count == 0 and vim.fn.mode(true):find("o")
+ end,
+ -- hide after jump when not using jump labels
+ autohide = false,
+ -- show jump labels
+ jump_labels = false,
+ -- set to `false` to use the current line only
+ multi_line = true,
+ -- When using jump labels, don't use these keys
+ -- This allows using those keys directly after the motion
+ label = { exclude = "hjkliardc" },
+ -- by default all keymaps are enabled, but you can disable some of them,
+ -- by removing them from the list.
+ -- If you rather use another key, you can map them
+ -- to something else, e.g., { [";"] = "L", [","] = H }
+ keys = { "f", "F", "t", "T", ";", "," },
+ ---@alias Flash.CharActions table
+ -- The direction for `prev` and `next` is determined by the motion.
+ -- `left` and `right` are always left and right.
+ char_actions = function(motion)
+ return {
+ [";"] = "next", -- set to `right` to always go right
+ [","] = "prev", -- set to `left` to always go left
+ -- clever-f style
+ [motion:lower()] = "next",
+ [motion:upper()] = "prev",
+ -- jump2d style: same case goes next, opposite case goes prev
+ -- [motion] = "next",
+ -- [motion:match("%l") and motion:upper() or motion:lower()] = "prev",
+ }
+ end,
+ search = { wrap = false },
+ highlight = { backdrop = true },
+ jump = { register = false },
+ },
+ -- options used for treesitter selections
+ -- `require("flash").treesitter()`
+ treesitter = {
+ labels = "abcdefghijklmnopqrstuvwxyz",
+ jump = { pos = "range" },
+ search = { incremental = false },
+ label = { before = true, after = true, style = "inline" },
+ highlight = {
+ backdrop = false,
+ matches = false,
+ },
+ },
+ treesitter_search = {
+ jump = { pos = "range" },
+ search = { multi_window = true, wrap = true, incremental = false },
+ remote_op = { restore = true },
+ label = { before = true, after = true, style = "inline" },
+ },
+ -- options used for remote flash
+ remote = {
+ remote_op = { restore = true, motion = true },
+ },
+ },
+ -- options for the floating window that shows the prompt,
+ -- for regular jumps
+ prompt = {
+ enabled = true,
+ prefix = { { "⚡", "FlashPromptIcon" } },
+ win_config = {
+ relative = "editor",
+ width = 1, -- when <=1 it's a percentage of the editor width
+ height = 1,
+ row = -1, -- when negative it's an offset from the bottom
+ col = 0, -- when negative it's an offset from the right
+ zindex = 1000,
+ },
+ },
+ -- options for remote operator pending mode
+ remote_op = {
+ -- restore window views and cursor position
+ -- after doing a remote operation
+ restore = false,
+ -- For `jump.pos = "range"`, this setting is ignored.
+ -- `true`: always enter a new motion when doing a remote operation
+ -- `false`: use the window's cursor position and jump target
+ -- `nil`: act as `true` for remote windows, `false` for the current window
+ motion = false,
+ },
+}
+
+---@type Flash.Config
+local options
+
+---@param opts? Flash.Config
+function M.setup(opts)
+ opts = opts or {}
+ opts.mode = nil
+ options = {}
+ options = M.get(opts)
+
+ require("flash.plugins.search").setup()
+ if options.modes.char.enabled then
+ require("flash.plugins.char").setup()
+ end
+end
+
+---@param ... Flash.Config|Flash.State.Config|nil
+---@return Flash.State.Config
+function M.get(...)
+ if options == nil then
+ M.setup()
+ end
+ ---@type Flash.Config[]
+ local all = { {}, defaults, options or {} }
+
+ ---@type table
+ local modes = {}
+
+ for i = 1, select("#", ...) do
+ ---@type Flash.Config?
+ local opts = select(i, ...)
+ if type(opts) == "string" then
+ opts = options.modes[opts]
+ end
+ if opts then
+ table.insert(all, opts)
+ local idx = #all
+ while opts.mode and not modes[opts.mode] do
+ modes[opts.mode or ""] = true
+ opts = options.modes[opts.mode] or {}
+ table.insert(all, idx, opts)
+ end
+ end
+ end
+
+ -- backward compatibility
+ for _, o in ipairs(all) do
+ if o.highlight and o.highlight.label then
+ o.label = vim.tbl_deep_extend("force", o.label or {}, o.highlight.label)
+ ---@diagnostic disable-next-line: no-unknown
+ o.highlight.label = nil
+ vim.notify_once(
+ "flash: `opts.highlight.label` is deprecated, use `opts.label` instead",
+ vim.log.levels.WARN
+ )
+ end
+ for _, field in ipairs({ "autohide", "jump_labels" }) do
+ if type(o[field]) == "function" then
+ local motion = require("flash.plugins.char").motion
+ ---@diagnostic disable-next-line: no-unknown
+ o[field] = o[field](motion)
+ end
+ end
+ end
+
+ local ret = vim.tbl_deep_extend("force", unpack(all))
+ ---@cast ret Flash.State.Config
+
+ if type(ret.config) == "function" then
+ ret.config(ret)
+ end
+
+ if vim.g.vscode then
+ ret.prompt.enabled = false
+ end
+ return ret
+end
+
+return setmetatable(M, {
+ __index = function(_, key)
+ if options == nil then
+ M.setup()
+ end
+ return options[key]
+ end,
+})
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/docs.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/docs.lua
new file mode 100644
index 00000000..6225e38d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/docs.lua
@@ -0,0 +1,32 @@
+local Docs = require("lazy.docs")
+
+local M = {}
+
+function M.update()
+ local config = Docs.extract("lua/flash/config.lua", "\nlocal defaults = ({.-\n})")
+ config = config:gsub("%s*debug = false.\n", "\n")
+ Docs.save({
+ config = config,
+ setup = Docs.extract("lua/flash/docs.lua", "function M%.suggested%(%)\n%s*return (.-)\nend"),
+ })
+end
+
+function M.suggested()
+ return {
+ "folke/flash.nvim",
+ event = "VeryLazy",
+ ---@type Flash.Config
+ opts = {},
+ -- stylua: ignore
+ keys = {
+ { "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" },
+ { "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
+ { "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
+ { "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
+ { "", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
+ },
+ }
+end
+M.update()
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/hacks.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/hacks.lua
new file mode 100644
index 00000000..8ebe94f7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/hacks.lua
@@ -0,0 +1,68 @@
+local Pos = require("flash.search.pos")
+
+local M = {}
+
+---@type ffi.namespace*
+local C
+local incsearch_state = {}
+
+local function _ffi()
+ if not C then
+ local ffi = require("ffi")
+ ffi.cdef([[
+ int search_match_endcol;
+ int no_mapping;
+ unsigned int search_match_lines;
+ void setcursor_mayforce(bool force);
+ ]])
+ C = ffi.C
+ end
+ return C
+end
+
+---@private
+---@param from Pos
+function M.get_end_pos(from)
+ _ffi()
+ local ret = Pos({
+ from[1] + C.search_match_lines,
+ math.max(0, C.search_match_endcol - 1),
+ })
+ local line = vim.api.nvim_buf_get_lines(0, ret[1] - 1, ret[1], false)[1]
+ local char_idx = vim.fn.charidx(line, ret[2])
+ ret[2] = vim.fn.byteidx(line, char_idx)
+ return ret
+end
+
+function M.save_incsearch_state()
+ _ffi()
+ incsearch_state = {
+ match_endcol = C.search_match_endcol,
+ match_lines = C.search_match_lines,
+ }
+end
+
+function M.mappings_enabled()
+ _ffi()
+ return C.no_mapping == 0
+end
+
+function M.setcursor(force)
+ if vim.api.nvim__redraw then
+ vim.api.nvim__redraw({ cursor = true })
+ else
+ if force == nil then
+ force = false
+ end
+ _ffi()
+ return C.setcursor_mayforce(force)
+ end
+end
+
+function M.restore_incsearch_state()
+ _ffi()
+ C.search_match_endcol = incsearch_state.match_endcol
+ C.search_match_lines = incsearch_state.match_lines
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/highlight.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/highlight.lua
new file mode 100644
index 00000000..a666f285
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/highlight.lua
@@ -0,0 +1,216 @@
+local M = {}
+
+function M.clear(ns)
+ for _, buf in ipairs(vim.api.nvim_list_bufs()) do
+ vim.api.nvim_buf_clear_namespace(buf, ns, 0, -1)
+ end
+end
+
+function M.setup()
+ if vim.g.vscode then
+ local hls = {
+ FlashBackdrop = { fg = "#545c7e" },
+ FlashCurrent = { bg = "#ff966c", fg = "#1b1d2b" },
+ FlashLabel = { bg = "#ff007c", bold = true, fg = "#c8d3f5" },
+ FlashMatch = { bg = "#3e68d7", fg = "#c8d3f5" },
+ FlashCursor = { reverse = true },
+ }
+ for hl_group, hl in pairs(hls) do
+ hl.default = true
+ vim.api.nvim_set_hl(0, hl_group, hl)
+ end
+ else
+ local links = {
+ FlashBackdrop = "Comment",
+ FlashMatch = "Search",
+ FlashCurrent = "IncSearch",
+ FlashLabel = "Substitute",
+ FlashPrompt = "MsgArea",
+ FlashPromptIcon = "Special",
+ FlashCursor = "Cursor",
+ }
+ for hl_group, link in pairs(links) do
+ vim.api.nvim_set_hl(0, hl_group, { link = link, default = true })
+ end
+ end
+end
+M.setup()
+
+---@param state Flash.State
+function M.backdrop(state)
+ for _, win in ipairs(state.wins) do
+ local info = vim.fn.getwininfo(win)[1]
+ local buf = vim.api.nvim_win_get_buf(win)
+ local from = { info.topline, 0 }
+ local to = { info.botline + 1, 0 }
+ if state.win == win and not state.opts.search.wrap then
+ if state.opts.search.forward then
+ from = { state.pos[1], state.pos[2] + 1 }
+ else
+ to = state.pos
+ end
+ end
+ -- we need to create a backdrop for each line because of the way
+ -- extmarks priority rendering works
+ for line = from[1], to[1] do
+ vim.api.nvim_buf_set_extmark(buf, state.ns, line - 1, line == from[1] and from[2] or 0, {
+ hl_group = state.opts.highlight.groups.backdrop,
+ end_row = line == to[1] and line - 1 or line,
+ hl_eol = line ~= to[1],
+ end_col = line == to[1] and to[2] or from[2],
+ priority = state.opts.highlight.priority,
+ strict = false,
+ })
+ end
+ end
+end
+
+---@param state Flash.State
+function M.cursor(state)
+ for _, win in ipairs(state.wins) do
+ local cursor = vim.api.nvim_win_get_cursor(win)
+ local buf = vim.api.nvim_win_get_buf(win)
+ vim.api.nvim_buf_set_extmark(buf, state.ns, cursor[1] - 1, cursor[2], {
+ hl_group = "FlashCursor",
+ end_col = cursor[2] + 1,
+ priority = state.opts.highlight.priority + 3,
+ strict = false,
+ })
+ end
+end
+
+---@param state Flash.State
+function M.update(state)
+ M.clear(state.ns)
+
+ if state.opts.highlight.backdrop then
+ M.backdrop(state)
+ end
+
+ local style = state.opts.label.style
+ if style == "inline" and vim.fn.has("nvim-0.10.0") == 0 then
+ style = "overlay"
+ end
+
+ local after = state.opts.label.after
+ after = after == true and { 0, 1 } or after
+ ---@cast after number[]
+ local before = state.opts.label.before
+ before = before == true and { 0, -1 } or before
+ ---@cast before number[]
+
+ if style == "inline" and before then
+ before[2] = before[2] + 1
+ end
+
+ local target = state.target
+
+ ---@type table
+ local extmarks = {}
+
+ ---@param match Flash.Match
+ ---@param pos number[]
+ ---@param offset number[]
+ ---@param is_after boolean
+ local function label(match, pos, offset, is_after)
+ local buf = vim.api.nvim_win_get_buf(match.win)
+ local cursor = vim.api.nvim_win_get_cursor(match.win)
+ local pos2 = require("flash.util").offset_pos(buf, pos, offset)
+ local row, col = pos2[1] - 1, pos2[2]
+ -- dont show the label if the cursor is on the same position
+ -- in the same window
+ -- and the label is not a range
+ if
+ cursor[1] == row + 1
+ and cursor[2] == col
+ and match.win == state.win
+ and state.opts.jump.pos ~= "range"
+ then
+ return
+ end
+ if match.fold then
+ -- set the row to the fold start
+ row = match.fold - 1
+ col = 0
+ end
+
+ local hl_group = state.opts.highlight.groups.label
+ if state.rainbow then
+ hl_group = state.rainbow:get(match)
+ elseif
+ -- set hl_group to current if the match is the current target
+ -- and the target is a single character
+ target
+ and target.pos[1] == row + 1
+ and target.pos[2] == col
+ and target.pos == target.end_pos
+ then
+ hl_group = state.opts.highlight.groups.current
+ end
+ if match.label == "" then
+ -- when empty label, highlight the position
+ vim.api.nvim_buf_set_extmark(buf, state.ns, row, col, {
+ hl_group = hl_group,
+ end_row = row,
+ end_col = col + 1,
+ strict = false,
+ priority = state.opts.highlight.priority + 2,
+ })
+ else
+ -- else highlight the label
+ local key = buf .. ":" .. row .. ":" .. col
+ extmarks[key] = extmarks[key] or { buf = buf, row = row, col = col, text = {} }
+ local text = state.opts.label.format({
+ state = state,
+ match = match,
+ hl_group = hl_group,
+ after = is_after,
+ })
+ for i = #text, 1, -1 do
+ table.insert(extmarks[key].text, 1, text[i])
+ end
+ end
+ end
+
+ for _, match in ipairs(state.results) do
+ local buf = vim.api.nvim_win_get_buf(match.win)
+
+ local highlight = state.opts.highlight.matches
+ if match.highlight ~= nil then
+ highlight = match.highlight
+ end
+
+ if highlight then
+ vim.api.nvim_buf_set_extmark(buf, state.ns, match.pos[1] - 1, match.pos[2], {
+ end_row = match.end_pos[1] - 1,
+ end_col = match.end_pos[2] + 1,
+ hl_group = target and match.pos == target.pos and state.opts.highlight.groups.current
+ or state.opts.highlight.groups.match,
+ strict = false,
+ priority = state.opts.highlight.priority + 1,
+ })
+ end
+ end
+
+ for _, match in ipairs(state.results) do
+ if match.label and after then
+ label(match, match.end_pos, after, true)
+ end
+ if match.label and before then
+ label(match, match.pos, before, false)
+ end
+ end
+
+ for _, extmark in pairs(extmarks) do
+ vim.api.nvim_buf_set_extmark(extmark.buf, state.ns, extmark.row, extmark.col, {
+ virt_text = extmark.text,
+ virt_text_pos = style,
+ strict = false,
+ priority = state.opts.highlight.priority + 2,
+ })
+ end
+
+ M.cursor(state)
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/init.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/init.lua
new file mode 100644
index 00000000..42f1305d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/init.lua
@@ -0,0 +1,13 @@
+---@type Flash.Commands
+local M = {}
+
+---@param opts? Flash.Config
+function M.setup(opts)
+ require("flash.config").setup(opts)
+end
+
+return setmetatable(M, {
+ __index = function(_, k)
+ return require("flash.commands")[k]
+ end,
+})
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/jump.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/jump.lua
new file mode 100644
index 00000000..b0735fad
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/jump.lua
@@ -0,0 +1,253 @@
+local Hacks = require("flash.hacks")
+local Pos = require("flash.search.pos")
+local Util = require("flash.util")
+local M = {}
+
+---@param match Flash.Match
+---@param state Flash.State
+---@return Flash.Match?
+function M.jump(match, state)
+ local register = vim.v.register
+ -- add to jump list
+ if state.opts.jump.jumplist then
+ vim.cmd("normal! m'")
+ end
+
+ local mode = vim.fn.mode(true)
+ local is_op = mode:sub(1, 2) == "no"
+ local is_visual = mode:sub(1, 1) == "v"
+
+ if is_op and (state.opts.remote_op.motion or match.win ~= vim.api.nvim_get_current_win()) then
+ -- use our special logic for remote operator pending mode
+ return M.remote_op(match, state, register)
+ end
+
+ -- change window if needed
+ if match.win ~= vim.api.nvim_get_current_win() then
+ if is_visual then
+ -- cancel visual mode in the current window,
+ -- to avoid issues with the remote window
+ vim.cmd("normal! v")
+ end
+
+ vim.api.nvim_set_current_win(match.win)
+
+ if is_visual then
+ -- enable visual mode in the remote window,
+ -- from its current cursor position
+ vim.cmd("normal! v")
+ end
+ end
+
+ M._jump(match, state, { op = is_op })
+end
+
+function M.fix_selection()
+ local selection = vim.go.selection
+ vim.go.selection = "inclusive"
+ vim.schedule(function()
+ vim.go.selection = selection
+ end)
+end
+
+-- Remote operator pending mode.Cancel the operator and
+-- re-trigger the operator in the remote window.
+---@param match Flash.Match
+---@param state Flash.State
+---@param register string
+---@return Flash.Match?
+function M.remote_op(match, state, register)
+ Util.exit()
+
+ -- schedule this so that the active operator is properly cancelled
+ vim.schedule(function()
+ local motion = state.opts.remote_op.motion
+ if motion == nil then
+ motion = match.win ~= vim.api.nvim_get_current_win()
+ end
+
+ vim.api.nvim_set_current_win(match.win)
+
+ -- use a new motion to select the text-object to act on,
+ -- unless we're jumping to a range
+ if motion then
+ if vim.fn.mode() == "v" then
+ vim.cmd("normal! v")
+ end
+
+ if state.opts.jump.pos == "range" then
+ vim.api.nvim_win_set_cursor(match.win, match.pos)
+ vim.cmd("normal! v")
+ vim.api.nvim_win_set_cursor(match.win, match.end_pos)
+ else
+ vim.api.nvim_win_set_cursor(
+ match.win,
+ state.opts.jump.pos == "start" and match.pos or match.end_pos
+ )
+ end
+
+ -- otherwise, use the remote window's cursor position
+ else
+ local from = vim.api.nvim_win_get_cursor(match.win)
+ M._jump(match, state, { op = true })
+ local to = vim.api.nvim_win_get_cursor(match.win)
+
+ -- if a range was selected, use that instead
+ if vim.fn.mode() == "v" then
+ vim.cmd("normal! v") -- end the selection
+ from = vim.api.nvim_buf_get_mark(0, "<")
+ to = vim.api.nvim_buf_get_mark(0, ">")
+ end
+
+ -- vim.api.nvim_buf_set_mark(0, "[", from[1], from[2], {})
+ -- vim.api.nvim_buf_set_mark(0, "]", to[1], to[2], {})
+
+ -- select the range for the operator
+ vim.api.nvim_win_set_cursor(0, from)
+ vim.cmd("normal! v")
+ vim.api.nvim_win_set_cursor(0, to)
+ end
+
+ ---@diagnostic disable-next-line: param-type-mismatch
+ local opmap = vim.fn.maparg(vim.v.operator, "", false, true) --[[@as any]]
+ if not vim.tbl_isempty(opmap) then
+ vim.keymap.del("", vim.v.operator)
+ end
+
+ -- re-trigger the operator
+ vim.api.nvim_input('"' .. register .. vim.v.operator)
+ if state.opts.remote_op.restore then
+ vim.schedule(function()
+ if not vim.tbl_isempty(opmap) then
+ vim.fn.mapset(opmap.mode, false, opmap)
+ end
+ M.restore_remote(state)
+ end)
+ end
+ end)
+end
+
+-- Restore window views after the remote operation ends
+---@param state Flash.State
+function M.restore_remote(state)
+ local restore = vim.schedule_wrap(function()
+ state:restore()
+ end)
+
+ -- wait till getting user input clears
+ if not Hacks.mappings_enabled() then
+ return Util.on_done(function()
+ return Hacks.mappings_enabled()
+ end, function()
+ M.restore_remote(state)
+ end)
+
+ -- wait till operator pending mode ends
+ elseif vim.fn.mode(true):sub(1, 2) == "no" then
+ return Util.on_done(function()
+ return vim.fn.mode(true):sub(1, 2) ~= "no"
+ end, function()
+ M.restore_remote(state)
+ end)
+
+ -- restore after making edits
+ elseif vim.fn.mode() == "i" and vim.v.operator == "c" then
+ vim.api.nvim_create_autocmd("InsertLeave", {
+ once = true,
+ callback = restore,
+ })
+ else
+ restore()
+ end
+end
+
+-- Performs the actual jump in the current window,
+-- taking operator-pending mode into account.
+---@param match Flash.Match
+---@param state Flash.State
+---@param opts? {op:boolean}
+---@return Flash.Match?
+function M._jump(match, state, opts)
+ opts = opts or {}
+ M.fix_selection()
+ M.open_folds(match)
+ -- select range
+ if state.opts.jump.pos == "range" then
+ if vim.fn.mode() == "v" then
+ vim.cmd("normal! v")
+ end
+ vim.api.nvim_win_set_cursor(match.win, match.pos)
+ vim.cmd("normal! v")
+ vim.api.nvim_win_set_cursor(match.win, match.end_pos)
+ else
+ local pos = state.opts.jump.pos == "start" and match.pos or match.end_pos
+
+ if opts.op then
+ -- fix inclusive/exclusive
+ -- default is exclusive
+ if state.opts.jump.inclusive ~= false then
+ vim.cmd("normal! v")
+ end
+ end
+ local current = Pos(match.win)
+ local offset = state.opts.jump.offset
+
+ if not offset and state.opts.jump.pos == "end" and pos < current then
+ offset = 1
+ end
+
+ pos = Pos(
+ require("flash.util").offset_pos(vim.api.nvim_win_get_buf(match.win), pos, { 0, offset or 0 })
+ )
+ pos[2] = math.max(0, pos[2])
+
+ vim.api.nvim_win_set_cursor(match.win, pos)
+ end
+end
+
+---@param match Flash.Match
+function M.open_folds(match)
+ local cursor = vim.api.nvim_win_get_cursor(match.win)
+ local from = match.pos[1]
+ local to = match.end_pos[1]
+ local is_visual = vim.fn.mode(true):find("v")
+ local opened = false
+ for line = from, to do
+ if vim.fn.foldclosed(line) ~= -1 then
+ vim.api.nvim_win_set_cursor(match.win, { line, 0 })
+ vim.cmd("normal! zO")
+ opened = true
+ end
+ end
+ if opened then
+ vim.api.nvim_win_set_cursor(match.win, cursor)
+ if is_visual then
+ vim.cmd("normal! v")
+ end
+ end
+end
+
+---@param state Flash.State
+function M.on_jump(state)
+ -- fix or restore the search register
+ local sf = vim.v.searchforward
+ if state.opts.jump.register then
+ vim.fn.setreg("/", state.pattern.search)
+ end
+ vim.v.searchforward = sf
+
+ -- add the real search pattern to the history
+ if state.opts.jump.history then
+ vim.fn.histadd("search", state.pattern.search)
+ end
+
+ -- clear the highlight
+ if state.opts.jump.nohlsearch then
+ vim.cmd.nohlsearch()
+ elseif state.opts.jump.register then
+ -- this will show the search matches again
+ vim.cmd("set hlsearch")
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/labeler.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/labeler.lua
new file mode 100644
index 00000000..35f7c17c
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/labeler.lua
@@ -0,0 +1,228 @@
+---@class Flash.Labeler
+---@field state Flash.State
+---@field used table
+---@field labels string[]
+local M = {}
+M.__index = M
+
+function M.new(state)
+ local self
+ self = setmetatable({}, M)
+ self.state = state
+ self.used = {}
+ self:reset()
+ return self
+end
+
+function M:labeler()
+ return function()
+ return self:update()
+ end
+end
+
+function M:update()
+ self:reset()
+
+ if #self.state.pattern() < self.state.opts.label.min_pattern_length then
+ return
+ end
+
+ local matches = self:filter()
+
+ for _, match in ipairs(matches) do
+ self:label(match, true)
+ end
+
+ for _, match in ipairs(matches) do
+ if not self:label(match) then
+ break
+ end
+ end
+end
+
+function M:reset()
+ local skip = {} ---@type table
+ self.labels = {}
+
+ for _, l in ipairs(self.state:labels()) do
+ if not skip[l] then
+ self.labels[#self.labels + 1] = l
+ skip[l] = true
+ end
+ end
+ if
+ not self.state.opts.search.max_length
+ or #self.state.pattern() < self.state.opts.search.max_length
+ then
+ for _, win in pairs(self.state.wins) do
+ self.labels = self:skip(win, self.labels)
+ end
+ end
+ for _, m in ipairs(self.state.results) do
+ if m.label ~= false then
+ m.label = nil
+ end
+ end
+end
+
+function M:valid(label)
+ return vim.tbl_contains(self.labels, label)
+end
+
+function M:use(label)
+ self.labels = vim.tbl_filter(function(c)
+ return c ~= label
+ end, self.labels)
+end
+
+---@param m Flash.Match
+---@param used boolean?
+function M:label(m, used)
+ if m.label ~= nil then
+ return true
+ end
+ local pos = m.pos:id(m.win)
+ local label ---@type string?
+ if used then
+ label = self.used[pos]
+ else
+ label = self.labels[1]
+ end
+ if label and self:valid(label) then
+ self:use(label)
+ local reuse = self.state.opts.label.reuse == "all"
+ or (self.state.opts.label.reuse == "lowercase" and label:lower() == label)
+
+ if reuse then
+ self.used[pos] = label
+ end
+ m.label = label
+ end
+ return #self.labels > 0
+end
+
+function M:filter()
+ ---@type Flash.Match[]
+ local ret = {}
+
+ local target = self.state.target
+
+ local from = vim.api.nvim_win_get_cursor(self.state.win)
+ ---@type table
+ local folds = {}
+
+ -- only label visible matches
+ for _, match in ipairs(self.state.results) do
+ -- and don't label the first match in the current window
+ local skip = (target and match.pos == target.pos)
+ and not self.state.opts.label.current
+ and match.win == self.state.win
+
+ -- Only label the first match in each fold
+ if not skip and match.fold then
+ if folds[match.fold] then
+ skip = true
+ else
+ folds[match.fold] = true
+ end
+ end
+
+ if not skip then
+ table.insert(ret, match)
+ end
+ end
+
+ -- sort by current win, other win, then by distance
+ table.sort(ret, function(a, b)
+ local use_distance = self.state.opts.label.distance and a.win == self.state.win
+
+ if a.win ~= b.win then
+ local aw = a.win == self.state.win and 0 or a.win
+ local bw = b.win == self.state.win and 0 or b.win
+ return aw < bw
+ end
+ if use_distance then
+ local dfrom = from[1] * vim.go.columns + from[2]
+ local da = a.pos[1] * vim.go.columns + a.pos[2]
+ local db = b.pos[1] * vim.go.columns + b.pos[2]
+ return math.abs(dfrom - da) < math.abs(dfrom - db)
+ end
+ if a.pos[1] ~= b.pos[1] then
+ return a.pos[1] < b.pos[1]
+ end
+ return a.pos[2] < b.pos[2]
+ end)
+ return ret
+end
+
+-- Returns valid labels for the current search pattern
+-- in this window.
+---@param labels string[]
+---@return string[] returns labels to skip or `nil` when all labels should be skipped
+function M:skip(win, labels)
+ local pattern = self.state.pattern.skip
+
+ -- skip all labels if the pattern is empty
+ if pattern == "" then
+ return {}
+ end
+
+ -- skip all labels if the pattern is invalid
+ local ok = pcall(vim.regex, pattern)
+ if not ok then
+ return {}
+ end
+
+ -- skip all labels if the pattern ends with a backslash
+ -- except if it's escaped
+ if pattern:find("\\$") and not pattern:find("\\\\$") then
+ return {}
+ end
+
+ vim.api.nvim_win_call(win, function()
+ while #labels > 0 do
+ -- this is needed, since an uppercase label would trigger smartcase
+ local label_group = table.concat(labels, "")
+ if vim.go.ignorecase then
+ label_group = label_group:lower()
+ end
+
+ local p = "\\%(" .. pattern .. "\\)\\m\\zs[" .. label_group .. "]"
+ local pos
+ ok, pos = pcall(vim.fn.searchpos, p, "cnw")
+
+ if not ok then
+ labels = {}
+ break
+ end
+
+ -- not found, we're done
+ if pos[1] == 0 then
+ return
+ end
+
+ local line = vim.api.nvim_buf_get_lines(0, pos[1] - 1, pos[1], false)[1]
+ local char = vim.fn.strpart(line, pos[2] - 1, 1, true)
+
+ local label_count = #labels
+ labels = vim.tbl_filter(function(c)
+ -- when ignorecase is set, we need to skip
+ -- both the upper and lower case labels
+ if vim.go.ignorecase then
+ return c:lower() ~= char:lower()
+ end
+ return c ~= char
+ end, labels)
+
+ -- HACK: this will fail if the pattern is an incomplete regex
+ -- In that case, we skip all labels
+ if label_count == #labels then
+ labels = {}
+ break
+ end
+ end
+ end)
+ return labels
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/plugins/char.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/plugins/char.lua
new file mode 100644
index 00000000..30e72097
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/plugins/char.lua
@@ -0,0 +1,299 @@
+local require = require("flash.require")
+
+local Config = require("flash.config")
+local Labeler = require("flash.labeler")
+local Repeat = require("flash.repeat")
+local Util = require("flash.util")
+
+local M = {}
+
+---@alias Flash.Char.Motion "'f'" | "'F'" | "'t'" | "'T'"
+M.motion = "f" ---@type Flash.Char.Motion
+M.char = nil ---@type string?
+M.jumping = false
+M.state = nil ---@type Flash.State?
+M.jump_labels = false
+
+---@type table
+M.motions = {
+ f = { label = { after = { 0, 0 }, before = false } },
+ t = {},
+ F = {
+ jump = { inclusive = false },
+ search = { forward = false },
+ label = { after = { 0, 0 }, before = false },
+ },
+ T = {
+ jump = { inclusive = false },
+ search = { forward = false },
+ label = { before = true, after = false },
+ },
+}
+
+function M.new()
+ local State = require("flash.state")
+ local opts = Config.get({
+ mode = "char",
+ labeler = M.labeler,
+ search = {
+ multi_window = false,
+ mode = M.mode(M.motion),
+ max_length = 1,
+ },
+ prompt = {
+ enabled = false,
+ },
+ }, M.motions[M.motion])
+
+ -- never show the current match label
+ opts.highlight.groups.current = M.motion:lower() == "f" and opts.highlight.groups.label
+ or opts.highlight.groups.match
+
+ -- exclude the motion labels so we can use them for next/prev
+ opts.labels = opts.labels:gsub(M.motion:lower(), "")
+ opts.labels = opts.labels:gsub(M.motion:upper(), "")
+ return State.new(opts)
+end
+
+function M.labeler(matches, state)
+ if M.jump_labels then
+ if not state._labeler then
+ state._labeler = Labeler.new(state)
+ end
+ state._labeler:update()
+ else
+ -- set to empty label, so that the character will just be highlighted
+ for _, m in ipairs(matches) do
+ m.label = ""
+ end
+ end
+end
+
+---@param motion Flash.Char.Motion
+function M.mode(motion)
+ ---@param c string
+ return function(c)
+ c = c:gsub("\\", "\\\\")
+ local pattern ---@type string
+ if motion == "t" then
+ pattern = "\\m.\\ze\\V" .. c
+ elseif motion == "T" then
+ pattern = "\\V" .. c .. "\\zs\\m."
+ else
+ pattern = "\\V" .. c
+ end
+ if not Config.get("char").multi_line then
+ local pos = vim.api.nvim_win_get_cursor(0)
+ pattern = ("\\%%%dl"):format(pos[1]) .. pattern
+ end
+
+ return pattern
+ end
+end
+
+function M.visible()
+ return M.state and M.state.visible
+end
+
+function M.setup()
+ Repeat.setup()
+
+ local keys = {}
+
+ for k, v in pairs(Config.modes.char.keys) do
+ if vim.g.mapleader ~= v and vim.g.maplocalleader ~= v then
+ keys[type(k) == "number" and v or k] = v
+ end
+ end
+
+ -- don't override ;, mappings if they exist
+ for _, key in ipairs({ ";", "," }) do
+ local mapping = vim.fn.maparg(key, "n", false, false)
+ if keys[key] == key and mapping ~= "" then
+ keys[key] = nil
+ end
+ end
+
+ for _, key in ipairs({ "f", "F", "t", "T", ";", "," }) do
+ if keys[key] then
+ vim.keymap.set({ "n", "x", "o" }, keys[key], function()
+ M.jumping = true
+ local autohide = Config.get("char").autohide
+ if Repeat.is_repeat then
+ M.jump_labels = false -- never show jump labels when repeating
+ M.state:jump({ count = vim.v.count1 })
+ M.state:show()
+ else
+ M.jump(key)
+ end
+ vim.schedule(function()
+ M.jumping = false
+ if M.state and autohide then
+ M.state:hide()
+ end
+ end)
+ end, {
+ silent = true,
+ })
+ end
+ end
+
+ vim.api.nvim_create_autocmd({ "BufLeave", "CursorMoved", "InsertEnter" }, {
+ group = vim.api.nvim_create_augroup("flash_char", { clear = true }),
+ callback = function(event)
+ local hide = event.event == "InsertEnter" or not M.jumping
+ if hide and M.state then
+ M.state:hide()
+ end
+ end,
+ })
+
+ vim.on_key(function(key)
+ if M.state and key == Util.ESC and (vim.fn.mode() == "n" or vim.fn.mode() == "v") then
+ M.state:hide()
+ end
+ end)
+end
+
+function M.parse(key)
+ ---@class Flash.Char.Parse
+ local ret = {
+ jump = M.next,
+ actions = {}, ---@type table
+ getchar = false,
+ }
+ -- repeat last search when hitting the same key
+ -- don't repeat when executing a macro
+ if M.visible() and vim.fn.reg_executing() == "" and M.motion:lower() == key:lower() then
+ ret.actions = M.actions(M.motion)
+ if ret.actions[key] then
+ ret.jump = ret.actions[key]
+ return ret
+ else
+ -- no action defined, so clear the state
+ M.motion = ""
+ end
+ end
+
+ -- different motion, clear the state
+ if M.motions[key] and M.motion ~= key then
+ if M.state then
+ M.state:hide()
+ end
+ M.motion = key
+ end
+
+ ret.actions = M.actions(M.motion)
+
+ if M.motions[key] then
+ ret.getchar = true
+ else -- ;,
+ ret.jump = ret.actions[key] or M.next
+ end
+
+ return ret
+end
+
+---@param motion Flash.Char.Motion
+---@return table
+function M.actions(motion)
+ local ret = Config.get("char").char_actions(motion)
+ for key, value in pairs(ret) do
+ ret[key] = M[value]
+ end
+ return ret
+end
+
+function M.jump(key)
+ local parsed = M.parse(key)
+ if not M.motion then
+ return
+ end
+
+ local is_op = vim.fn.mode(true):sub(1, 2) == "no"
+
+ -- always re-calculate when not visible
+ M.state = M.visible() and M.state or M.new()
+
+ -- get a new target
+ if parsed.getchar or not M.char then
+ local char = M.state:get_char()
+ if char then
+ M.char = char
+ else
+ return M.state:hide()
+ end
+ end
+
+ -- HACK: When the motion is t or T, we need to set the current position as a valid target
+ -- but only when we are not repeating
+ M.current = M.motion:lower() == "t" and parsed.getchar
+
+ -- update the state when needed
+ if M.state.pattern:empty() then
+ M.state:update({ pattern = M.char })
+ end
+
+ local jump = parsed.jump
+
+ M.jump_labels = Config.get("char").jump_labels
+ jump()
+ M.state:update({ force = true })
+
+ if M.jump_labels then
+ parsed.actions[Util.CR] = function()
+ return false
+ end
+ M.state:loop({
+ restore = is_op,
+ abort = function()
+ Util.exit()
+ end,
+ jump_on_max_length = false,
+ actions = parsed.actions,
+ })
+ end
+
+ return M.state
+end
+
+M.current = false
+
+function M.right()
+ return M.state.opts.search.forward and M.next() or M.prev()
+end
+
+function M.left()
+ return M.state.opts.search.forward and M.prev() or M.next()
+end
+
+function M.next()
+ M.state:jump({
+ count = vim.v.count1,
+ forward = M.state.opts.search.forward,
+ current = M.current,
+ })
+ M.current = false
+ return true
+end
+
+function M.prev()
+ M.state:jump({
+ count = vim.v.count1,
+ forward = not M.state.opts.search.forward,
+ current = M.current,
+ })
+ M.current = false
+ -- check if we should enable wrapping.
+ if not M.state.opts.search.wrap then
+ local before = M.state:find({ count = 1, forward = false })
+ if before and (before.pos < M.state.pos) == M.state.opts.search.forward then
+ M.state.opts.search.wrap = true
+ M.state._labeler = nil
+ M.state:update({ force = true })
+ end
+ end
+ return true
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/plugins/search.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/plugins/search.lua
new file mode 100644
index 00000000..ef7bf1b4
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/plugins/search.lua
@@ -0,0 +1,163 @@
+local require = require("flash.require")
+
+local Config = require("flash.config")
+local Jump = require("flash.jump")
+local State = require("flash.state")
+local Util = require("flash.util")
+
+local M = {}
+
+---@type Flash.State?
+M.state = nil
+M.op = false
+M.enabled = true
+
+---@param enabled? boolean
+function M.toggle(enabled)
+ if enabled == nil then
+ enabled = not M.enabled
+ end
+
+ if M.enabled == enabled then
+ return M.enabled
+ end
+
+ M.enabled = enabled
+
+ if State.is_search() then
+ if M.enabled then
+ M.start()
+ M.update(false)
+ elseif M.state then
+ M.state:hide()
+ M.state = nil
+ end
+ -- redraw to show the change
+ vim.cmd("redraw")
+ -- trigger incsearch to update the matches
+ vim.api.nvim_feedkeys(" " .. Util.BS, "n", true)
+ end
+ return M.enabled
+end
+
+---@param check_jump? boolean
+function M.update(check_jump)
+ if not M.state then
+ return
+ end
+
+ local pattern = vim.fn.getcmdline()
+
+ -- when doing // or ??, get the pattern from the search register
+ -- See :h search-commands
+ if pattern:sub(1, 1) == vim.fn.getcmdtype() then
+ pattern = vim.fn.getreg("/") .. pattern:sub(2)
+ end
+ M.state:update({ pattern = pattern, check_jump = check_jump })
+end
+
+function M.start()
+ M.state = State.new({
+ mode = "search",
+ action = M.jump,
+ search = {
+ forward = vim.fn.getcmdtype() == "/",
+ mode = "search",
+ incremental = vim.go.incsearch,
+ },
+ })
+ if M.op then
+ M.state.opts.search.multi_window = false
+ end
+end
+
+function M.setup()
+ local group = vim.api.nvim_create_augroup("flash", { clear = true })
+ M.enabled = Config.modes.search.enabled or false
+
+ local function wrap(fn)
+ return function(...)
+ if M.state then
+ return fn(...)
+ end
+ end
+ end
+
+ vim.api.nvim_create_autocmd("CmdlineChanged", {
+ group = group,
+ callback = wrap(function()
+ M.update()
+ end),
+ })
+
+ vim.api.nvim_create_autocmd("CmdlineLeave", {
+ group = group,
+ callback = wrap(function()
+ M.state:hide()
+ M.state = nil
+ end),
+ })
+ vim.api.nvim_create_autocmd("CmdlineEnter", {
+ group = group,
+ callback = function()
+ if State.is_search() and M.enabled then
+ M.start()
+ M.set_op(vim.fn.mode() == "v")
+ end
+ end,
+ })
+
+ vim.api.nvim_create_autocmd("ModeChanged", {
+ pattern = "*:c",
+ group = group,
+ callback = function()
+ M.set_op(vim.v.event.old_mode:sub(1, 2) == "no" or vim.fn.mode() == "v")
+ end,
+ })
+end
+
+function M.set_op(op)
+ M.op = op
+ if M.op and M.state then
+ M.state.opts.search.multi_window = false
+ end
+end
+
+---@param self Flash.State
+---@param match Flash.Match
+function M.jump(match, self)
+ local pos = match.pos
+ local search_reg = vim.fn.getreg("/")
+
+ -- For operator pending mode, set the search pattern to the
+ -- first character on the match position
+ if M.op then
+ local pos_pattern = ("\\%%%dl\\%%%dc."):format(pos[1], pos[2] + 1)
+ vim.fn.setcmdline(pos_pattern)
+ end
+
+ -- schedule a input to trigger the search
+ vim.schedule(function()
+ vim.api.nvim_input(M.op and "" or "")
+ end)
+
+ -- restore the real search pattern after the search
+ -- and perform the jump when not in operator pending mode
+ vim.api.nvim_create_autocmd("CmdlineLeave", {
+ once = true,
+ callback = vim.schedule_wrap(function()
+ -- delete the search pattern.
+ -- The correct one will be added in `on_jump`
+ vim.fn.histdel("search", -1)
+ if M.op then
+ -- restore original search pattern
+ vim.fn.setreg("/", search_reg)
+ else
+ Jump.jump(match, self)
+ end
+ Jump.on_jump(self)
+ end),
+ })
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/plugins/treesitter.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/plugins/treesitter.lua
new file mode 100644
index 00000000..223757bd
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/plugins/treesitter.lua
@@ -0,0 +1,181 @@
+local Config = require("flash.config")
+local Pos = require("flash.search.pos")
+local Repeat = require("flash.repeat")
+local Util = require("flash.util")
+
+local M = {}
+
+---@class Flash.Match.TS: Flash.Match
+---@field node TSNode
+---@field depth? number
+
+---@param win window
+---@param pos? Pos
+function M.get_nodes(win, pos)
+ local buf = vim.api.nvim_win_get_buf(win)
+ local line_count = vim.api.nvim_buf_line_count(buf)
+ pos = pos or Pos()
+
+ local nodes = {} ---@type TSNode[]
+
+ local ok, tree = pcall(vim.treesitter.get_parser, buf)
+ if not ok then
+ vim.notify(
+ "No treesitter parser for this buffer with filetype=" .. vim.bo[buf].filetype,
+ vim.log.levels.WARN,
+ { title = "flash.nvim" }
+ )
+ vim.api.nvim_input("")
+ end
+ if not (ok and tree) then
+ return {}
+ end
+
+ do
+ -- get all ranges of the current node and its parents
+ local node = tree:named_node_for_range({ pos[1] - 1, pos[2], pos[1] - 1, pos[2] }, {
+ ignore_injections = false,
+ })
+
+ while node do
+ nodes[#nodes + 1] = node
+ node = node:parent() ---@type TSNode
+ end
+ end
+
+ -- convert ranges to matches
+ ---@type Flash.Match.TS[]
+ local ret = {}
+ local first = true
+ ---@type table
+ local done = {}
+ for _, node in ipairs(nodes) do
+ local range = { node:range() }
+ ---@type Flash.Match.TS
+ local match = {
+ node = node,
+ pos = { range[1] + 1, range[2] },
+ end_pos = { range[3] + 1, range[4] - 1 },
+ first = first,
+ }
+ first = false
+ -- If the match is at the end of the buffer,
+ -- then move it to the last character of the last line.
+ if match.end_pos[1] > line_count then
+ match.end_pos[1] = line_count
+ match.end_pos[2] =
+ #vim.api.nvim_buf_get_lines(buf, match.end_pos[1] - 1, match.end_pos[1], false)[1]
+ elseif match.end_pos[2] == -1 then
+ -- If the end points to the start of the next line, move it to the
+ -- end of the previous line.
+ -- Otherwise operations include the first character of the next line
+ local line =
+ vim.api.nvim_buf_get_lines(buf, match.end_pos[1] - 2, match.end_pos[1] - 1, false)[1]
+ match.end_pos[1] = match.end_pos[1] - 1
+ match.end_pos[2] = #line
+ end
+ local id = table.concat(vim.tbl_flatten({ match.pos, match.end_pos }), ".")
+ if not done[id] then
+ done[id] = true
+ ret[#ret + 1] = match
+ end
+ end
+
+ for m, match in ipairs(ret) do
+ match.pos = Pos(match.pos)
+ match.end_pos = Pos(match.end_pos)
+ match.win = win
+ match.depth = #ret - m
+ end
+ return ret
+end
+
+---@param win window
+---@param state Flash.State
+function M.matcher(win, state)
+ local labels = state:labels()
+ local ret = M.get_nodes(win, state.pos)
+
+ for i = 1, #ret do
+ ret[i].label = table.remove(labels, 1)
+ end
+ return ret
+end
+
+---@param opts? Flash.Config
+function M.jump(opts)
+ local state = Repeat.get_state(
+ "treesitter",
+ Config.get({ mode = "treesitter" }, opts, {
+ matcher = M.matcher,
+ labeler = function() end,
+ search = { multi_window = false, wrap = true, incremental = false, max_length = 0 },
+ })
+ )
+
+ ---@type Flash.Match?
+ local current
+ for _, m in ipairs(state.results) do
+ ---@cast m Flash.Match.TS
+ if not current or m.depth > current.depth then
+ current = m
+ end
+ end
+ current = state:jump(current)
+
+ state:loop({
+ abort = function()
+ vim.cmd([[normal! v]])
+ end,
+ actions = {
+ [";"] = function()
+ current = state:jump({ match = current, forward = false })
+ end,
+ [","] = function()
+ current = state:jump({ forward = true, match = current })
+ end,
+ [Util.CR] = function()
+ state:jump(current and current.label or nil)
+ return false
+ end,
+ },
+ jump_on_max_length = false,
+ })
+
+ return state
+end
+
+---@param opts? Flash.Config
+function M.search(opts)
+ opts = Config.get({ mode = "treesitter_search" }, opts, {
+ matcher = function(win, _state, _opts)
+ local Search = require("flash.search")
+ local search = Search.new(win, _state)
+ local matches = {} ---@type Flash.Match[]
+ for _, m in ipairs(search:get(_opts)) do
+ -- don't add labels to the search results
+ m.label = false
+ table.insert(matches, m)
+ for _, n in ipairs(M.get_nodes(win, m.pos)) do
+ -- don't highlight treesitter nodes. Use labels only
+ n.highlight = false
+ table.insert(matches, n)
+ end
+ end
+ return matches
+ end,
+ jump = { pos = "range" },
+ })
+
+ opts.search.exclude = vim.deepcopy(opts.search.exclude)
+ table.insert(opts.search.exclude, function(win)
+ local buf = vim.api.nvim_win_get_buf(win)
+ return not pcall(vim.treesitter.get_parser, buf)
+ end)
+
+ local state = Repeat.get_state("treesitter-search", opts)
+ state:loop()
+ return state
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/prompt.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/prompt.lua
new file mode 100644
index 00000000..6a89c460
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/prompt.lua
@@ -0,0 +1,85 @@
+local Config = require("flash.config")
+
+---@class Flash.Prompt
+---@field win window
+---@field buf buffer
+local M = {}
+
+local ns = vim.api.nvim_create_namespace("flash_prompt")
+
+function M.visible()
+ return M.win and vim.api.nvim_win_is_valid(M.win) and M.buf and vim.api.nvim_buf_is_valid(M.buf)
+end
+
+function M.show()
+ if M.visible() then
+ return
+ end
+ require("flash.highlight")
+
+ M.buf = vim.api.nvim_create_buf(false, true)
+ vim.bo[M.buf].buftype = "nofile"
+ vim.bo[M.buf].bufhidden = "wipe"
+ vim.bo[M.buf].filetype = "flash_prompt"
+
+ local config = vim.deepcopy(Config.prompt.win_config)
+
+ if config.width <= 1 then
+ config.width = config.width * vim.go.columns
+ end
+
+ if config.row < 0 then
+ config.row = vim.go.lines + config.row
+ end
+
+ if config.col < 0 then
+ config.col = vim.go.columns + config.col
+ end
+
+ config = vim.tbl_extend("force", config, {
+ style = "minimal",
+ focusable = false,
+ noautocmd = true,
+ })
+
+ M.win = vim.api.nvim_open_win(M.buf, false, config)
+ vim.wo[M.win].winhighlight = "Normal:FlashPrompt"
+end
+
+function M.hide()
+ if M.win and vim.api.nvim_win_is_valid(M.win) then
+ vim.api.nvim_win_close(M.win, true)
+ M.win = nil
+ end
+ if M.buf and vim.api.nvim_buf_is_valid(M.buf) then
+ vim.api.nvim_buf_delete(M.buf, { force = true })
+ M.buf = nil
+ end
+end
+
+---@param pattern string
+function M.set(pattern)
+ M.show()
+ local text = vim.deepcopy(Config.prompt.prefix)
+ text[#text + 1] = { pattern }
+
+ local str = ""
+ for _, item in ipairs(text) do
+ str = str .. item[1]
+ end
+ vim.api.nvim_buf_set_lines(M.buf, 0, -1, false, { str })
+ vim.api.nvim_buf_clear_namespace(M.buf, ns, 0, -1)
+ local col = 0
+ for _, item in ipairs(text) do
+ local width = vim.fn.strlen(item[1])
+ if item[2] then
+ vim.api.nvim_buf_set_extmark(M.buf, ns, 0, col, {
+ hl_group = item[2],
+ end_col = col + width,
+ })
+ end
+ col = col + width
+ end
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/rainbow.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/rainbow.lua
new file mode 100644
index 00000000..c48a1384
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/rainbow.lua
@@ -0,0 +1,401 @@
+---@class Flash.Rainbow
+---@field cache table
+---@field count number
+---@field shade number
+local M = {}
+
+---@type table
+M.hl = {}
+
+function M.setup()
+ if M.did_setup then
+ return
+ end
+ M.did_setup = true
+ vim.api.nvim_create_autocmd("ColorScheme", {
+ callback = function()
+ M.hl = {}
+ end,
+ })
+end
+
+---@param state Flash.State
+function M.new(state)
+ local self = setmetatable({}, { __index = M })
+ self.cache = {}
+ self.count = 0
+ self.shade = state.opts.label.rainbow.shade
+ return self
+end
+
+---@param match Flash.Match
+function M:get(match)
+ local buf = vim.api.nvim_win_get_buf(match.win)
+ local id = match.pos:id(buf)
+ if match.depth then
+ id = id .. ":" .. tostring(match.depth)
+ end
+
+ if not self.cache[id] then
+ self.count = self.count + 1
+ self.cache[id] = M.get_color(self.count, self.shade)
+ end
+ return self.cache[id]
+end
+
+---@param idx number
+---@param shade number
+function M.get_color(idx, shade)
+ M.setup()
+ idx = (idx - 1) % #M.rainbow + 1
+ local color = M.rainbow[idx]
+ shade = (shade or 5) * 100
+ local bg = vim.tbl_get(M.colors, color, shade)
+ if bg then
+ local hl = "FlashColor" .. color .. shade
+ if not M.hl[hl] then
+ M.hl[hl] = true
+ local bg_shade = shade == 500 and 950 or shade < 500 and 900 or 50
+ local fg = vim.tbl_get(M.colors, color, bg_shade)
+ vim.api.nvim_set_hl(0, hl, { bg = "#" .. bg, fg = "#" .. fg, bold = true })
+ end
+ return hl
+ end
+end
+
+M.rainbow = {
+ -- "slate",
+ -- "gray",
+ -- "zinc",
+ -- "neutral",
+ -- "stone",
+ "red",
+ -- "orange",
+ "amber",
+ -- "yellow",
+ "lime",
+ "green",
+ -- "emerald",
+ "teal",
+ "cyan",
+ -- "sky",
+ "blue",
+ -- "indigo",
+ "violet",
+ -- "purple",
+ "fuchsia",
+ -- "pink",
+ "rose",
+}
+
+M.colors = {
+ slate = {
+ [50] = "f8fafc",
+ [100] = "f1f5f9",
+ [200] = "e2e8f0",
+ [300] = "cbd5e1",
+ [400] = "94a3b8",
+ [500] = "64748b",
+ [600] = "475569",
+ [700] = "334155",
+ [800] = "1e293b",
+ [900] = "0f172a",
+ [950] = "020617",
+ },
+
+ gray = {
+ [50] = "f9fafb",
+ [100] = "f3f4f6",
+ [200] = "e5e7eb",
+ [300] = "d1d5db",
+ [400] = "9ca3af",
+ [500] = "6b7280",
+ [600] = "4b5563",
+ [700] = "374151",
+ [800] = "1f2937",
+ [900] = "111827",
+ [950] = "030712",
+ },
+
+ zinc = {
+ [50] = "fafafa",
+ [100] = "f4f4f5",
+ [200] = "e4e4e7",
+ [300] = "d4d4d8",
+ [400] = "a1a1aa",
+ [500] = "71717a",
+ [600] = "52525b",
+ [700] = "3f3f46",
+ [800] = "27272a",
+ [900] = "18181b",
+ [950] = "09090B",
+ },
+
+ neutral = {
+ [50] = "fafafa",
+ [100] = "f5f5f5",
+ [200] = "e5e5e5",
+ [300] = "d4d4d4",
+ [400] = "a3a3a3",
+ [500] = "737373",
+ [600] = "525252",
+ [700] = "404040",
+ [800] = "262626",
+ [900] = "171717",
+ [950] = "0a0a0a",
+ },
+
+ stone = {
+ [50] = "fafaf9",
+ [100] = "f5f5f4",
+ [200] = "e7e5e4",
+ [300] = "d6d3d1",
+ [400] = "a8a29e",
+ [500] = "78716c",
+ [600] = "57534e",
+ [700] = "44403c",
+ [800] = "292524",
+ [900] = "1c1917",
+ [950] = "0a0a0a",
+ },
+
+ red = {
+ [50] = "fef2f2",
+ [100] = "fee2e2",
+ [200] = "fecaca",
+ [300] = "fca5a5",
+ [400] = "f87171",
+ [500] = "ef4444",
+ [600] = "dc2626",
+ [700] = "b91c1c",
+ [800] = "991b1b",
+ [900] = "7f1d1d",
+ [950] = "450a0a",
+ },
+
+ orange = {
+ [50] = "fff7ed",
+ [100] = "ffedd5",
+ [200] = "fed7aa",
+ [300] = "fdba74",
+ [400] = "fb923c",
+ [500] = "f97316",
+ [600] = "ea580c",
+ [700] = "c2410c",
+ [800] = "9a3412",
+ [900] = "7c2d12",
+ [950] = "431407",
+ },
+
+ amber = {
+ [50] = "fffbeb",
+ [100] = "fef3c7",
+ [200] = "fde68a",
+ [300] = "fcd34d",
+ [400] = "fbbf24",
+ [500] = "f59e0b",
+ [600] = "d97706",
+ [700] = "b45309",
+ [800] = "92400e",
+ [900] = "78350f",
+ [950] = "451a03",
+ },
+
+ yellow = {
+ [50] = "fefce8",
+ [100] = "fef9c3",
+ [200] = "fef08a",
+ [300] = "fde047",
+ [400] = "facc15",
+ [500] = "eab308",
+ [600] = "ca8a04",
+ [700] = "a16207",
+ [800] = "854d0e",
+ [900] = "713f12",
+ [950] = "422006",
+ },
+
+ lime = {
+ [50] = "f7fee7",
+ [100] = "ecfccb",
+ [200] = "d9f99d",
+ [300] = "bef264",
+ [400] = "a3e635",
+ [500] = "84cc16",
+ [600] = "65a30d",
+ [700] = "4d7c0f",
+ [800] = "3f6212",
+ [900] = "365314",
+ [950] = "1a2e05",
+ },
+
+ green = {
+ [50] = "f0fdf4",
+ [100] = "dcfce7",
+ [200] = "bbf7d0",
+ [300] = "86efac",
+ [400] = "4ade80",
+ [500] = "22c55e",
+ [600] = "16a34a",
+ [700] = "15803d",
+ [800] = "166534",
+ [900] = "14532d",
+ [950] = "052e16",
+ },
+
+ emerald = {
+ [50] = "ecfdf5",
+ [100] = "d1fae5",
+ [200] = "a7f3d0",
+ [300] = "6ee7b7",
+ [400] = "34d399",
+ [500] = "10b981",
+ [600] = "059669",
+ [700] = "047857",
+ [800] = "065f46",
+ [900] = "064e3b",
+ [950] = "022c22",
+ },
+
+ teal = {
+ [50] = "f0fdfa",
+ [100] = "ccfbf1",
+ [200] = "99f6e4",
+ [300] = "5eead4",
+ [400] = "2dd4bf",
+ [500] = "14b8a6",
+ [600] = "0d9488",
+ [700] = "0f766e",
+ [800] = "115e59",
+ [900] = "134e4a",
+ [950] = "042f2e",
+ },
+
+ cyan = {
+ [50] = "ecfeff",
+ [100] = "cffafe",
+ [200] = "a5f3fc",
+ [300] = "67e8f9",
+ [400] = "22d3ee",
+ [500] = "06b6d4",
+ [600] = "0891b2",
+ [700] = "0e7490",
+ [800] = "155e75",
+ [900] = "164e63",
+ [950] = "083344",
+ },
+
+ sky = {
+ [50] = "f0f9ff",
+ [100] = "e0f2fe",
+ [200] = "bae6fd",
+ [300] = "7dd3fc",
+ [400] = "38bdf8",
+ [500] = "0ea5e9",
+ [600] = "0284c7",
+ [700] = "0369a1",
+ [800] = "075985",
+ [900] = "0c4a6e",
+ [950] = "082f49",
+ },
+
+ blue = {
+ [50] = "eff6ff",
+ [100] = "dbeafe",
+ [200] = "bfdbfe",
+ [300] = "93c5fd",
+ [400] = "60a5fa",
+ [500] = "3b82f6",
+ [600] = "2563eb",
+ [700] = "1d4ed8",
+ [800] = "1e40af",
+ [900] = "1e3a8a",
+ [950] = "172554",
+ },
+
+ indigo = {
+ [50] = "eef2ff",
+ [100] = "e0e7ff",
+ [200] = "c7d2fe",
+ [300] = "a5b4fc",
+ [400] = "818cf8",
+ [500] = "6366f1",
+ [600] = "4f46e5",
+ [700] = "4338ca",
+ [800] = "3730a3",
+ [900] = "312e81",
+ [950] = "1e1b4b",
+ },
+
+ violet = {
+ [50] = "f5f3ff",
+ [100] = "ede9fe",
+ [200] = "ddd6fe",
+ [300] = "c4b5fd",
+ [400] = "a78bfa",
+ [500] = "8b5cf6",
+ [600] = "7c3aed",
+ [700] = "6d28d9",
+ [800] = "5b21b6",
+ [900] = "4c1d95",
+ [950] = "2e1065",
+ },
+
+ purple = {
+ [50] = "faf5ff",
+ [100] = "f3e8ff",
+ [200] = "e9d5ff",
+ [300] = "d8b4fe",
+ [400] = "c084fc",
+ [500] = "a855f7",
+ [600] = "9333ea",
+ [700] = "7e22ce",
+ [800] = "6b21a8",
+ [900] = "581c87",
+ [950] = "3b0764",
+ },
+
+ fuchsia = {
+ [50] = "fdf4ff",
+ [100] = "fae8ff",
+ [200] = "f5d0fe",
+ [300] = "f0abfc",
+ [400] = "e879f9",
+ [500] = "d946ef",
+ [600] = "c026d3",
+ [700] = "a21caf",
+ [800] = "86198f",
+ [900] = "701a75",
+ [950] = "4a044e",
+ },
+
+ pink = {
+ [50] = "fdf2f8",
+ [100] = "fce7f3",
+ [200] = "fbcfe8",
+ [300] = "f9a8d4",
+ [400] = "f472b6",
+ [500] = "ec4899",
+ [600] = "db2777",
+ [700] = "be185d",
+ [800] = "9d174d",
+ [900] = "831843",
+ [950] = "500724",
+ },
+
+ rose = {
+ [50] = "fff1f2",
+ [100] = "ffe4e6",
+ [200] = "fecdd3",
+ [300] = "fda4af",
+ [400] = "fb7185",
+ [500] = "f43f5e",
+ [600] = "e11d48",
+ [700] = "be123c",
+ [800] = "9f1239",
+ [900] = "881337",
+ [950] = "4c0519",
+ },
+}
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/repeat.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/repeat.lua
new file mode 100644
index 00000000..82a7c615
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/repeat.lua
@@ -0,0 +1,55 @@
+local require = require("flash.require")
+
+local State = require("flash.state")
+
+local M = {}
+
+---@type {is_repeat:boolean, fn:fun()}[]
+M._funcs = {}
+M._repeat = nil
+
+-- Sets the current operatorfunc to the given function.
+function M.set(fn)
+ vim.go.operatorfunc = [[{x -> x}]]
+ local visual = vim.fn.mode() == "v"
+ vim.cmd("normal! g@l")
+ if visual then
+ vim.cmd("normal! gv")
+ end
+ M._repeat = fn
+ vim.go.operatorfunc = [[v:lua.require'flash.repeat'._repeat]]
+end
+
+M.is_repeat = false
+function M.setup()
+ if M._did_setup then
+ return
+ end
+ M._did_setup = true
+ vim.on_key(function(key)
+ if key == "." and vim.fn.reg_executing() == "" and vim.fn.reg_recording() == "" then
+ M.is_repeat = true
+ vim.schedule(function()
+ M.is_repeat = false
+ end)
+ end
+ end)
+end
+
+---@type table
+M._states = {}
+
+---@param mode string
+---@param opts? Flash.State.Config
+function M.get_state(mode, opts)
+ M.setup()
+ local last = M._states[mode]
+ if (M.is_repeat or (opts and opts.continue)) and last then
+ last:show()
+ return last
+ end
+ M._states[mode] = State.new(opts)
+ return M._states[mode]
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/require.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/require.lua
new file mode 100644
index 00000000..3a63d155
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/require.lua
@@ -0,0 +1,25 @@
+return function(module)
+ local mod = nil
+
+ local function load()
+ if not mod then
+ mod = require(module)
+ package.loaded[module] = mod
+ end
+ return mod
+ end
+ -- if already loaded, return the module
+ -- otherwise return a lazy module
+ return type(package.loaded[module]) == "table" and package.loaded[module]
+ or setmetatable({}, {
+ __index = function(_, key)
+ return load()[key]
+ end,
+ __newindex = function(_, key, value)
+ load()[key] = value
+ end,
+ __call = function(_, ...)
+ return load()(...)
+ end,
+ })
+end
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/init.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/init.lua
new file mode 100644
index 00000000..865f1e5d
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/init.lua
@@ -0,0 +1,117 @@
+local require = require("flash.require")
+
+local Hacks = require("flash.hacks")
+local Matcher = require("flash.search.matcher")
+local Pos = require("flash.search.pos")
+
+---@class Flash.Search: Flash.Matcher
+---@field state Flash.State
+---@field win window
+local M = {}
+M.__index = M
+
+---@param win number
+---@param state Flash.State
+function M.new(win, state)
+ local self = setmetatable({}, M)
+ self.state = state
+ self.win = win
+ return self
+end
+
+---@param flags? string
+---@return Flash.Match?
+function M:_next(flags)
+ flags = flags or ""
+ local ok, pos = pcall(vim.fn.searchpos, self.state.pattern.search, flags or "")
+ -- incomplete or invalid pattern
+ if not ok then
+ return
+ end
+ if pos[1] == 0 then
+ return
+ end
+ pos = Pos({ pos[1], pos[2] - 1 })
+ return { win = self.win, pos = pos, end_pos = Hacks.get_end_pos(pos) }
+end
+
+---@param pos Pos
+---@param fn function
+function M:_call(pos, fn)
+ pos = Pos(pos)
+
+ local view = vim.api.nvim_win_call(self.win, vim.fn.winsaveview)
+ local buf = vim.api.nvim_win_get_buf(self.win)
+ local line_count = vim.api.nvim_buf_line_count(buf)
+ if pos[1] > line_count then
+ pos[1] = line_count
+ local line = vim.api.nvim_buf_get_lines(buf, pos[1] - 1, pos[1], false)[1]
+ pos[2] = #line - 1
+ end
+ vim.api.nvim_win_set_cursor(self.win, pos)
+ ---@type boolean, any?
+ local ok, err
+ vim.api.nvim_win_call(self.win, function()
+ ok, err = pcall(fn)
+ vim.fn.winrestview(view)
+ end)
+ return not ok and error(err) or err
+end
+
+---@param opts? {from?:Pos, to?:Pos}
+function M:get(opts)
+ if self.state.pattern:empty() then
+ return {}
+ end
+
+ opts = opts or {}
+ opts.from = opts.from and Pos(opts.from) or nil
+ opts.to = opts.to and Pos(opts.to) or nil
+
+ ---@type Flash.Match[]
+ local ret = {}
+
+ self:_call(opts.from or { 1, 0 }, function()
+ local next = self:_next("cW")
+ while next and (not opts.to or next.pos <= opts.to) do
+ table.insert(ret, next)
+ next = self:_next("W")
+ end
+ end)
+ return ret
+end
+
+-- Moves the results cursor by `amount` (default 1) and wraps around.
+-- When forward is `nil` it uses the current search direction.
+-- Otherwise it uses the given direction.
+---@param opts? Flash.Match.Find
+function M:find(opts)
+ if self.state.pattern:empty() then
+ return
+ end
+
+ opts = Matcher.defaults(opts)
+ local flags = (opts.forward and "" or "b")
+ .. (opts.wrap and "w" or "W")
+ .. ((opts.count == 0 or opts.current) and "c" or "")
+ if opts.match then
+ opts.pos = opts.match.pos
+ end
+
+ ---@type Flash.Match?
+ local ret
+
+ self:_call(opts.pos, function()
+ for _ = 1, math.max(opts.count, 1) do
+ ret = self:_next(flags)
+ flags = flags:gsub("c", "")
+ end
+ end)
+
+ if not ret or (opts.count == 0 and ret.pos ~= opts.pos) then
+ return
+ end
+ return ret
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/matcher.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/matcher.lua
new file mode 100644
index 00000000..a76fadd9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/matcher.lua
@@ -0,0 +1,179 @@
+local Pos = require("flash.search.pos")
+
+---@class Flash.Match
+---@field win window
+---@field pos Pos -- (1,0) indexed
+---@field end_pos Pos -- (1,0) indexed
+---@field label? string|false -- set to false to disable label
+---@field highlight? boolean
+---@field fold? number
+
+---@alias Flash.Match.Find {forward?:boolean, wrap?:boolean, count?:number, pos?: Pos, match?:Flash.Match, current?:boolean}
+
+---@class Flash.Matcher
+---@field win window
+---@field get fun(self, opts?: {from?:Pos, to?:Pos}): Flash.Match[]
+---@field find fun(self, opts?: Flash.Match.Find): Flash.Match
+---@field labels fun(self, labels: string[]): string[]
+---@field update? fun(self)
+
+---@class Flash.Matcher.Custom: Flash.Matcher
+---@field matches Flash.Match[]
+local M = {}
+M.__index = M
+
+function M.new(win)
+ local self = setmetatable({}, M)
+ self.matches = {}
+ self.win = win
+ return self
+end
+
+---@param fn fun(win: window, state:Flash.State, opts: {from:Pos, to:Pos}): Flash.Match[]
+function M.from(fn)
+ ---@param win window
+ ---@param state Flash.State
+ return function(win, state)
+ local ret = M.new(win)
+ ret.get = function(self, opts)
+ local matches = fn(win, state, opts)
+ if state.opts.filter then
+ matches = state.opts.filter(matches, state) or matches
+ end
+ self:set(matches)
+ return M.get(self, opts)
+ end
+
+ return ret
+ end
+end
+
+---@param ...? Flash.Match.Find
+---@return Flash.Match.Find
+function M.defaults(...)
+ local other = vim.tbl_filter(function(k)
+ return k ~= nil
+ end, { ... })
+
+ local opts = vim.tbl_extend("force", {
+ pos = vim.api.nvim_win_get_cursor(0),
+ forward = true,
+ wrap = true,
+ count = 1,
+ }, {}, unpack(other))
+ opts.pos = Pos(opts.pos)
+ return opts
+end
+
+---@param opts? Flash.Match.Find
+function M:find(opts)
+ opts = M.defaults(opts)
+
+ if opts.count == 0 then
+ for _, match in ipairs(self.matches) do
+ if match.pos == opts.pos then
+ return match
+ end
+ end
+ return
+ end
+
+ ---@type number?
+ local idx
+
+ if opts.match then
+ for m, match in ipairs(self.matches) do
+ if match.pos == opts.match.pos and match.end_pos == opts.match.end_pos then
+ idx = m + (opts.forward and 1 or -1)
+ break
+ end
+ end
+ elseif opts.forward then
+ for i = 1, #self.matches, 1 do
+ if self.matches[i].pos > opts.pos then
+ idx = i
+ break
+ end
+ end
+ else
+ for i = #self.matches, 1, -1 do
+ if self.matches[i].pos < opts.pos then
+ idx = i
+ break
+ end
+ end
+ end
+
+ if not idx then
+ if not opts.wrap then
+ return
+ end
+ idx = opts.forward and 1 or #self.matches
+ end
+
+ if opts.forward then
+ idx = idx + opts.count - 1
+ else
+ idx = idx - opts.count + 1
+ end
+
+ if opts.wrap then
+ idx = (idx - 1) % #self.matches + 1
+ end
+ return self.matches[idx]
+end
+
+---@param labels string[]
+function M:labels(labels)
+ return labels
+end
+
+---@param opts? {from?:Pos, to?:Pos}
+function M:get(opts)
+ return M.filter(self.matches, opts)
+end
+
+---@param matches Flash.Match[]
+---@param opts? {from?:Pos, to?:Pos}
+function M.filter(matches, opts)
+ opts = opts or {}
+ opts.from = opts.from and Pos(opts.from)
+ opts.to = opts.to and Pos(opts.to)
+ ---@param match Flash.Match
+ return vim.tbl_filter(function(match)
+ if opts.from and match.end_pos < opts.from then
+ return false
+ end
+ if opts.to and match.pos > opts.to then
+ return false
+ end
+ return true
+ end, matches)
+end
+
+---@param matches Flash.Match[]
+function M:set(matches)
+ for _, match in ipairs(matches) do
+ match.pos = Pos(match.pos)
+ match.end_pos = Pos(match.end_pos)
+ match.win = match.win or self.win
+ end
+
+ table.sort(matches, function(a, b)
+ if a.win ~= b.win then
+ return a.win < b.win
+ end
+ if a.pos ~= b.pos then
+ return a.pos < b.pos
+ end
+ local da = a.depth or 0
+ local db = b.depth or 0
+ if da ~= db then
+ return da < db
+ end
+ return a.end_pos < b.end_pos
+ end)
+ self.matches = matches
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/pattern.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/pattern.lua
new file mode 100644
index 00000000..0bdf0d01
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/pattern.lua
@@ -0,0 +1,108 @@
+local Util = require("flash.util")
+
+---@class Flash.Pattern
+---@field pattern string
+---@field search string
+---@field skip string
+---@field trigger string
+---@field mode Flash.Pattern.Mode
+---@operator call:string Returns the input pattern
+local M = {}
+M.__index = M
+
+---@alias Flash.Pattern.Mode "exact" | "fuzzy" | "search" | (fun(input:string):string,string?)
+
+---@param pattern string
+---@param mode Flash.Pattern.Mode
+---@param trigger string
+function M.new(pattern, mode, trigger)
+ local self = setmetatable({}, M)
+ self.mode = mode
+ self.trigger = trigger or ""
+ self:set(pattern or "")
+ return self
+end
+
+function M:__eq(other)
+ return other and other.pattern == self.pattern and other.mode == self.mode
+end
+
+function M:clone()
+ return M.new(self.pattern, self.mode, self.trigger)
+end
+
+function M:empty()
+ return self.pattern == ""
+end
+
+---@param pattern string
+---@return boolean updated
+function M:set(pattern)
+ if pattern ~= self.pattern then
+ self.pattern = pattern
+ if pattern == "" then
+ self.search = ""
+ self.skip = ""
+ else
+ if self.trigger ~= "" and pattern:sub(-1) == self.trigger then
+ pattern = pattern:sub(1, -2)
+ end
+ self.search, self.skip = M._get(pattern, self.mode)
+ end
+ return false
+ end
+ return true
+end
+
+---@param char string
+function M:extend(char)
+ if char == Util.BS then
+ return self.pattern:sub(1, -2)
+ end
+ return self.pattern .. char
+end
+
+---@return string the input pattern
+function M:__call()
+ return self.pattern
+end
+
+---@param pattern string
+---@param mode Flash.Pattern.Mode
+---@private
+function M._get(pattern, mode)
+ local skip ---@type string?
+ if type(mode) == "function" then
+ pattern, skip = mode(pattern)
+ elseif mode == "exact" then
+ pattern, skip = M._exact(pattern)
+ elseif mode == "fuzzy" then
+ pattern, skip = M._fuzzy(pattern)
+ end
+ return pattern, skip or pattern
+end
+
+---@param pattern string
+function M._exact(pattern)
+ return "\\V" .. pattern:gsub("\\", "\\\\")
+end
+
+---@param opts? {ignorecase: boolean, whitespace:boolean}
+function M._fuzzy(pattern, opts)
+ opts = vim.tbl_deep_extend("force", {
+ ignorecase = vim.go.ignorecase,
+ whitespace = false,
+ }, opts or {})
+
+ local sep = opts.whitespace and ".\\{-}" or "\\[^\\ ]\\{-}"
+
+ ---@param c string
+ local chars = vim.tbl_map(function(c)
+ return c == "\\" and "\\\\" or c
+ end, vim.fn.split(pattern, "\\zs"))
+
+ local ret = "\\V" .. table.concat(chars, sep) .. (opts.ignorecase and "\\c" or "\\C")
+ return ret, ret .. sep
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/pos.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/pos.lua
new file mode 100644
index 00000000..35045ba7
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/search/pos.lua
@@ -0,0 +1,85 @@
+---@class Pos
+---@field row number
+---@field col number
+---@field [1] number
+---@field [2] number
+---@overload fun(pos?: number[] | { row: number, col: number } | number): Pos
+local P = {}
+
+---@param pos? number[] | { row: number, col: number } | number
+function P.new(pos)
+ if pos == nil then
+ pos = vim.api.nvim_win_get_cursor(0)
+ elseif type(pos) == "number" then
+ pos = vim.api.nvim_win_get_cursor(pos)
+ end
+
+ if getmetatable(pos) == P then
+ return pos
+ end
+ local self = setmetatable({}, P)
+ self[1] = pos[1] or pos.row
+ self[2] = pos[2] or pos.col
+ return self
+end
+
+function P:__index(key)
+ if key == "row" then
+ return rawget(self, 1)
+ elseif key == "col" then
+ return rawget(self, 2)
+ end
+ return P[key]
+end
+
+function P:__newindex(key, value)
+ if key == "row" then
+ rawset(self, 1, value)
+ elseif key == "col" then
+ rawset(self, 2, value)
+ else
+ rawset(self, key, value)
+ end
+end
+
+function P:__eq(other)
+ return self[1] == other[1] and self[2] == other[2]
+end
+
+function P:__tostring()
+ return ("[%d, %d]"):format(self[1], self[2])
+end
+
+function P:id(buf)
+ return table.concat({ buf, self[1], self[2] }, ":")
+end
+
+function P:dist(other)
+ return math.abs(self[1] - other[1]) + math.abs(self[2] - other[2])
+end
+
+function P:__add(other)
+ other = P(other)
+ return P.new({ self[1] + other[1], self[2] + other[2] })
+end
+
+function P:__sub(other)
+ other = P(other)
+ return P.new({ self[1] - other[1], self[2] - other[2] })
+end
+
+function P:__lt(other)
+ other = P(other)
+ return self[1] < other[1] or (self[1] == other[1] and self[2] < other[2])
+end
+
+function P:__le(other)
+ other = P(other)
+ return self < other or self == other
+end
+
+return setmetatable(P, {
+ __call = function(_, pos)
+ return P.new(pos)
+ end,
+})
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/state.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/state.lua
new file mode 100644
index 00000000..82b8bb7a
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/state.lua
@@ -0,0 +1,420 @@
+local require = require("flash.require")
+
+local Cache = require("flash.cache")
+local Config = require("flash.config")
+local Hacks = require("flash.hacks")
+local Highlight = require("flash.highlight")
+local Jump = require("flash.jump")
+local Matcher = require("flash.search.matcher")
+local Pattern = require("flash.search.pattern")
+local Prompt = require("flash.prompt")
+local Rainbow = require("flash.rainbow")
+local Search = require("flash.search")
+local Util = require("flash.util")
+
+---@class Flash.State.Config: Flash.Config
+---@field matcher? fun(win: window, state:Flash.State, pos: {from:Pos, to:Pos}): Flash.Match[]
+---@field filter? fun(matches:Flash.Match[], state:Flash.State): Flash.Match[]
+---@field pattern? string
+---@field labeler? fun(matches:Flash.Match[], state:Flash.State)
+---@field actions? table
+
+---@class Flash.State
+---@field win window
+---@field wins window[]
+---@field cache Flash.Cache
+---@field pos Pos
+---@field view any
+---@field results Flash.Match[]
+---@field target? Flash.Match
+---@field pattern Flash.Pattern
+---@field opts Flash.State.Config
+---@field labeler fun(matches:Flash.Match[], state:Flash.State)
+---@field visible boolean
+---@field matcher fun(win: window, state:Flash.State): Flash.Matcher
+---@field matchers Flash.Matcher[]
+---@field restore_windows? fun()
+---@field rainbow? Flash.Rainbow
+---@field ns number
+---@field langmap table
+local M = {}
+M.__index = M
+
+---@type table
+M._states = setmetatable({}, { __mode = "k" })
+
+function M.setup()
+ if M._did_setup then
+ return
+ end
+ M._did_setup = true
+ local ns = vim.api.nvim_create_namespace("flash")
+ vim.api.nvim_set_decoration_provider(ns, {
+ on_start = function()
+ for state in pairs(M._states) do
+ if state.visible then
+ local ok, err = pcall(state.update, state)
+ if not ok then
+ vim.schedule(function()
+ vim.notify(
+ "Flash error during redraw:\n" .. err,
+ vim.log.levels.ERROR,
+ { title = "flash.nvim" }
+ )
+ end)
+ end
+ end
+ end
+ end,
+ })
+end
+
+---@param char string
+function M:lmap(char)
+ return vim.bo.iminsert == 1 and self.langmap[char] or char
+end
+
+function M:get_char()
+ local ret = Util.get_char()
+ return ret and self:lmap(ret) or nil
+end
+
+function M:labels()
+ local labels = self.opts.labels
+ if self.opts.label.uppercase then
+ labels = labels .. self.opts.labels:upper()
+ end
+ local list = vim.fn.split(labels, "\\zs")
+ local ret = {} ---@type string[]
+ local added = {} ---@type table
+ for _, l in ipairs(vim.fn.split(self.opts.label.exclude, "\\zs")) do
+ added[l] = true
+ end
+ for _, l in ipairs(list) do
+ if not added[l] then
+ added[l] = true
+ ret[#ret + 1] = self:lmap(l)
+ end
+ end
+ return ret
+end
+
+function M.is_search()
+ local t = vim.fn.getcmdtype()
+ return t == "/" or t == "?"
+end
+
+---@param opts? Flash.State.Config
+function M.new(opts)
+ M.setup()
+ local self = setmetatable({}, M)
+ self.opts = Config.get(opts)
+ self.langmap = {}
+ if vim.bo.iminsert == 1 then
+ local lmap = vim.api.nvim_buf_get_keymap(0, "l")
+ for _, m in ipairs(lmap) do
+ if m.lhs ~= "" then
+ self.langmap[m.lhs] = m.rhs
+ end
+ end
+ end
+ self.results = {}
+ self.matchers = {}
+ self.wins = {}
+ self.matcher = self.opts.matcher
+ if type(self.matcher) == "function" then
+ self.matcher = Matcher.from(self.opts.matcher)
+ elseif self.matcher == nil then
+ self.matcher = Search.new
+ end
+ self.pattern = Pattern.new(self.opts.pattern, self.opts.search.mode, self.opts.search.trigger)
+ self.visible = true
+ self.cache = Cache.new(self)
+ self.labeler = self.opts.labeler or require("flash.labeler").new(self):labeler()
+ self.ns = vim.api.nvim_create_namespace(self.opts.ns or "flash")
+ M._states[self] = true
+ if self.opts.label.rainbow.enabled then
+ self.rainbow = Rainbow.new(self)
+ end
+
+ self:update()
+ return self
+end
+
+---@param target? string|Flash.Match.Find|Flash.Match
+---@return Flash.Match?
+function M:jump(target)
+ local match ---@type Flash.Match?
+ if type(target) == "string" then
+ match = self:find({ label = target })
+ elseif target and target.end_pos then
+ match = target
+ elseif target then
+ match = self:find(target)
+ else
+ match = self.target
+ end
+ if match then
+ if self.opts.action then
+ self.opts.action(match, self)
+ else
+ Jump.jump(match, self)
+ Jump.on_jump(self)
+ end
+ return match
+ end
+end
+
+-- Will restore all window views
+function M:restore()
+ if self.restore_windows then
+ self.restore_windows()
+ end
+end
+
+function M:get_matcher(win)
+ self.matchers[win] = self.matchers[win] or self.matcher(win, self)
+ return self.matchers[win]
+end
+
+---@param opts? Flash.Match.Find | {label?:string, pos?: Pos}
+function M:find(opts)
+ if opts and opts.label then
+ for _, m in ipairs(self.results) do
+ if m.label == opts.label then
+ return m
+ end
+ end
+ return
+ end
+
+ opts = Matcher.defaults({
+ forward = self.opts.search.forward,
+ wrap = self.opts.search.wrap,
+ }, opts)
+
+ local matcher = self:get_matcher(self.win)
+ local ret = matcher:find(opts)
+
+ if ret then
+ for _, m in ipairs(self.results) do
+ if m.pos == ret.pos and m.end_pos == ret.end_pos then
+ return m
+ end
+ end
+ end
+ return ret
+end
+
+-- Checks if the given pattern is a jump label and jumps to it.
+---@param pattern string
+function M:check_jump(pattern)
+ if not self.visible then
+ return
+ end
+
+ if self.opts.search.trigger ~= "" and self.pattern():sub(-1) ~= self.opts.search.trigger then
+ return
+ end
+ local chars = vim.fn.strchars(pattern)
+ if
+ pattern:find(self.pattern(), 1, true) == 1 and chars == vim.fn.strchars(self.pattern()) + 1
+ then
+ local label = vim.fn.strcharpart(pattern, chars - 1, 1)
+ if self:jump(label) then
+ return true
+ end
+ end
+end
+
+---@param opts? {pattern:string, force:boolean, check_jump:boolean}
+---@return boolean? abort `true` if the search was aborted
+function M:update(opts)
+ opts = opts or {}
+
+ if opts.pattern then
+ -- abort if pattern is a jump label
+ if opts.check_jump ~= false and self:check_jump(opts.pattern) then
+ return true
+ end
+ self.pattern:set(opts.pattern)
+ end
+
+ if not self.visible then
+ return
+ end
+
+ if self.cache:update() or opts.force then
+ self:_update()
+ end
+end
+
+function M:hide()
+ if self.visible then
+ self.visible = false
+ Highlight.clear(self.ns)
+ end
+end
+
+function M:show()
+ if not self.visible then
+ self.visible = true
+ -- force cache to update win and position
+ self.win = nil
+ self:update({ force = true })
+ end
+end
+
+function M:_update()
+ -- This is needed because we trigger searches during redraw.
+ -- We need to save the state of the incsearch so that current match
+ -- will still be displayed correctly.
+ if M.is_search() then
+ Hacks.save_incsearch_state()
+ end
+
+ self.results = {}
+ local done = {} ---@type table
+ ---@type Flash.Matcher[]
+ local matchers = {}
+ for _, win in ipairs(self.wins) do
+ local buf = vim.api.nvim_win_get_buf(win)
+ matchers[win] = self:get_matcher(win)
+ local state = self.cache:get_state(win)
+ for _, m in ipairs(state and state.matches or {}) do
+ local id = m.pos:id(buf) .. m.end_pos:id(buf)
+ if not done[id] then
+ done[id] = true
+ table.insert(self.results, m)
+ end
+ end
+ end
+ self.matchers = matchers
+
+ for _, match in ipairs(self.results) do
+ vim.api.nvim_win_call(match.win, function()
+ local fold = vim.fn.foldclosed(match.pos[1])
+ match.fold = fold ~= -1 and fold or nil
+ end)
+ end
+
+ self:update_target()
+ self.labeler(self.results, self)
+
+ if M.is_search() then
+ Hacks.restore_incsearch_state()
+ end
+
+ Highlight.update(self)
+end
+
+function M:update_target()
+ -- set target to next match.
+ -- When not using incremental search,
+ -- we need to set the target to the previous match
+ self.target = self:find({
+ pos = self.pos,
+ count = vim.v.count1,
+ })
+
+ local info = vim.fn.getwininfo(self.win)[1]
+ local function is_visible()
+ return self.target and self.target.pos[1] >= info.topline and self.target.pos[1] <= info.botline
+ end
+
+ if self.opts.search.incremental then
+ -- only update cursor if the target is not visible
+ -- and we are not activated
+ if self.target and not self.is_search() then
+ vim.api.nvim_win_set_cursor(self.win, self.target.pos)
+ end
+ elseif not is_visible() then
+ self.target = self:find({
+ pos = self.pos,
+ count = vim.v.count1,
+ forward = not self.opts.search.forward,
+ })
+ if not is_visible() then
+ self.target = nil
+ end
+ end
+end
+
+---@class Flash.Step.Options
+---@field actions? table
+---@field restore? boolean
+---@field abort? fun()
+---@field jump_on_max_length? boolean
+
+---@param opts? Flash.Step.Options
+function M:step(opts)
+ opts = opts or {}
+ if self.opts.prompt.enabled and not M.is_search() then
+ Prompt.set(self.pattern())
+ end
+ local actions = opts.actions or self.opts.actions or {}
+ local c = self:get_char()
+ if c == nil then
+ vim.api.nvim_input("")
+ if opts.restore ~= false then
+ self:restore()
+ end
+ if opts.abort then
+ opts.abort()
+ end
+ return
+ elseif actions[c] then
+ local ret = actions[c](self, c)
+ if ret == nil then
+ return true
+ end
+ return ret
+ -- jump to first
+ elseif c == Util.CR then
+ self:jump()
+ return
+ end
+
+ local orig = self.pattern()
+
+ -- break if we jumped
+ if self:update({ pattern = self.pattern:extend(c) }) then
+ return
+ end
+
+ -- when we exceed max length, either jump to the label,
+ -- or input the last key and break
+ if self.opts.search.max_length and #self.pattern() > self.opts.search.max_length then
+ self:update({ pattern = orig })
+ if opts.jump_on_max_length ~= false then
+ self:jump()
+ end
+ vim.api.nvim_input(c)
+ return
+ end
+
+ -- exit if no results and not in regular search mode
+ if #self.results == 0 and not self.pattern:empty() and self.pattern.mode ~= 'search' then
+ if self.opts.search.incremental then
+ vim.api.nvim_input(c)
+ end
+ return
+ end
+
+ -- autojump if only one result
+ if #self.results == 1 and self.opts.jump.autojump then
+ self:jump()
+ return
+ end
+ return true
+end
+
+---@param opts? Flash.Step.Options
+function M:loop(opts)
+ while self:step(opts) do
+ end
+ self:hide()
+ Prompt.hide()
+end
+
+return M
diff --git a/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/util.lua b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/util.lua
new file mode 100644
index 00000000..fe4c32b9
--- /dev/null
+++ b/config/neovim/store/lazy-plugins/flash.nvim/lua/flash/util.lua
@@ -0,0 +1,105 @@
+local Hacks = require("flash.hacks")
+local require = require("flash.require")
+
+local M = {}
+
+function M.t(str)
+ return vim.api.nvim_replace_termcodes(str, true, true, true)
+end
+
+M.CR = M.t("")
+M.ESC = M.t("")
+M.BS = M.t("