return{setup=function()local O=(require("\107\101\121\109\097\112\115")).setup()local function V(V)if not V.group then vim.notify(string.format("\091\037\115\093 \037\115","\103\108\111\098\097\108\115\046\107\101\121\109\097\112","\096\075\101\121\109\097\112\046\103\114\111\117\112\096 \114\101\113\117\105\114\101\115 \096\103\114\111\117\112\096 \102\105\101\108\100"),vim.log.levels.WARN)return end local G=V;(vim.iter(ipairs(G))):each(function(G,L)if#L<4 then vim.notify(string.format("\091\037\115\093 \037\115","\103\108\111\098\097\108\115\046\107\101\121\109\097\112","\096\075\101\121\109\097\112\046\103\114\111\117\112\096 \114\101\113\117\105\114\101\115 \052 \112\097\114\097\109\097\116\101\114\115 \112\101\114 \107\101\121\109\097\112"),vim.log.levels.WARN)return end local U=L[1]local o=L[2]local h=L[3]local H=L[4]if not O[U]then vim.notify(string.format("\091\037\115\093 \037\115","\103\108\111\098\097\108\115\046\107\101\121\109\097\112","\107\101\121\109\097\112 \109\111\100\101 \'"..(U.."\' \100\111\101\115 \110\111\116 \101\120\105\115\116")),vim.log.levels.WARN)return end O[U][o]={h,H,group=V.group}end)end local function G(O,V)return function()pcall(O,V)end end vim.g.mapleader=" "vim.g.maplocalleader=" \109"V({group="\107\101\121\109\097\112\115",{"\110\111\114\109\097\108";"\060\115\112\097\099\101\062\044\107";"\060\099\109\100\062\115\047\107\101\121\109\097\112\115\092\046\092\040\092\119\042\092\041\092\091\"\092\040\091\094\"\093\042\092\041\"\092\093 \061 \123 \092\040\091\094\044\093\042\092\041\044 \"\092\040\091\094\"\093\042\092\041\" \125\047\123 \"\092\049\"\044 \"\092\050\"\044 \092\051\044 \"\092\052\" \125\047\060\099\114\062","\116\114\097\110\115\102\111\114\109 \108\105\110\101 \116\111 \103\114\111\117\112 \105\116\101\109 \102\111\114\109\097\116"}})V({group="\109\111\118\101\109\101\110\116";{"\110\111\114\109\097\108";"\087";"\103\095","\103\111\116\111 \108\097\115\116 \110\111\110 \101\109\112\116\121 \111\102 \108\105\110\101"},{"\110\111\114\109\097\108","\066";"\094";"\103\111\116\111 \102\105\114\115\116 \110\111\110 \101\109\112\116\121 \111\102 \108\105\110\101"};{"\118\105\115\117\097\108","\087","\103\095";"\103\111\116\111 \108\097\115\116 \110\111\110 \101\109\112\116\121 \111\102 \108\105\110\101"},{"\118\105\115\117\097\108";"\066","\094","\103\111\116\111 \102\105\114\115\116 \110\111\110 \101\109\112\116\121 \111\102 \108\105\110\101"}})V({group="\118\101\114\116\105\099\097\108 \109\111\118\109\101\110\116";{"\110\111\114\109\097\108";"\060\067-\100\062","\060\067-\100\062\122\122","\103\111 \100\111\119\110 \097\110\100 \099\101\110\116\101\114 \108\105\110\101"};{"\110\111\114\109\097\108";"\060\067-\117\062","\060\067-\117\062\122\122","\103\111 \117\112 \097\110\100 \099\101\110\116\101\114 \108\105\110\101"},{"\110\111\114\109\097\108";"\110";"\110\122\122\122\118";"\103\111\116\111 \110\101\120\116 \115\101\097\114\099\104 \097\110\100 \117\110\099\111\118\101\114 \108\105\110\101"},{"\110\111\114\109\097\108","\078","\078\122\122\122\118";"\103\111\116\111 \112\114\101\118 \115\101\097\114\099\104 \097\110\100 \117\110\099\111\118\101\114 \108\105\110\101"}})V({group="\102\105\120\117\112";{"\110\111\114\109\097\108";"\060\083-\100\111\119\110\062","\060\110\111\112\062";"\114\101\109\111\118\101 \115\104\105\102\116 \100\111\119\110 \109\111\118\101\109\101\110\116"};{"\110\111\114\109\097\108","\060\083-\117\112\062","\060\110\111\112\062";"\114\101\109\111\118\101 \115\104\105\102\116 \117\112 \109\111\118\101\109\101\110\116"},{"\118\105\115\117\097\108","\060\083-\100\111\119\110\062","\060\110\111\112\062";"\114\101\109\111\118\101 \115\104\105\102\116 \100\111\119\110 \109\111\118\101\109\101\110\116"};{"\118\105\115\117\097\108","\060\083-\117\112\062","\060\110\111\112\062";"\114\101\109\111\118\101 \115\104\105\102\116 \117\112 \109\111\118\101\109\101\110\116"}})V({group="\119\111\114\107\115\112\097\099\101";{"\110\111\114\109\097\108";"\060\108\101\097\100\101\114\062\113";vim.cmd.quitall,"\113\117\105\116 \097\108\108"},{"\118\105\115\117\097\108";"\060\108\101\097\100\101\114\062\113";vim.cmd.quitall,"\113\117\105\116 \097\108\108"}})V({group="\102\105\108\101",{"\110\111\114\109\097\108";"\060\067-\115\062",vim.cmd.update,"\115\097\118\101 \102\105\108\101"}})for V,G in ipairs({"\104";"\106","\107";"\108"})do O.normal["\060\108\101\097\100\101\114\062"..G]={function()vim.cmd.wincmd(G)end,string.format("\115\119\105\116\099\104 \119\105\110\100\111\119 \096\037\115\096",G);group="\119\105\110\100\111\119\115"}end O.normal.s={"\060\110\111\112\062";"\102\105\120\117\112 \096\115\096";group="\102\105\120\117\112"}V({group="\119\105\110\100\111\119\115",{"\110\111\114\109\097\108";"\115\118";vim.cmd.vsplit,"\115\112\108\105\116 \119\105\110\100\111\119 \118\101\114\116\105\099\097\108"},{"\110\111\114\109\097\108";"\115\104";vim.cmd.split;"\115\112\108\105\116 \119\105\110\100\111\119 \104\111\114\105\122\111\110\116\097\108"};{"\110\111\114\109\097\108","\113",G(vim.cmd.wincmd,"\113"),"\099\108\111\115\101 \119\105\110\100\111\119"}})V({group="\116\097\098\115",{"\110\111\114\109\097\108","\060\115\112\097\099\101\062\060\116\097\098\062\093";vim.cmd.tabnext,"\110\101\120\116 \116\097\098"};{"\110\111\114\109\097\108";"\060\115\112\097\099\101\062\060\116\097\098\062\091";vim.cmd.tabprev;"\112\114\101\118 \116\097\098"};{"\110\111\114\109\097\108";"\060\115\112\097\099\101\062\060\116\097\098\062\110",G(vim.cmd,"\036\116\097\098\101\100\105\116");"\111\112\101\110 \110\101\119 \116\097\098"},{"\110\111\114\109\097\108","\060\115\112\097\099\101\062\060\116\097\098\062\100",vim.cmd.tabclose,"\099\108\111\115\101 \099\117\114\114\101\110\116 \116\097\098"},{"\110\111\114\109\097\108","\060\115\112\097\099\101\062\060\116\097\098\062\120",vim.cmd.tabclose,"\099\108\111\115\101 \099\117\114\114\101\110\116 \116\097\098"};{"\110\111\114\109\097\108";"\060\115\112\097\099\101\062\060\116\097\098\062\060";function()vim.cmd(" -\116\097\098\109\111\118\101 ")end;"\109\111\118\101 \116\097\098 \116\111 \116\104\101 \108\101\102\116"};{"\110\111\114\109\097\108";"\060\115\112\097\099\101\062\060\116\097\098\062\062";function()vim.cmd(" \043\116\097\098\109\111\118\101 ")end;"\109\111\118\101 \116\097\098 \116\111 \116\104\101 \114\105\103\104\116"}})V({group="\119\105\110\100\111\119\115";{"\110\111\114\109\097\108";"\060\067-\092\062",function()vim.cmd("\118\115 \124 \119\105\110\099\109\100 \108")end;"\115\112\108\105\116 \102\105\108\101 \118\101\114\116\105\099\097\108\108\121"};{"\110\111\114\109\097\108","\060\067-\104\062";"\060\067-\119\062\104";"\115\119\105\116\099\104 \119\105\110\100\111\119 \108\101\102\116"},{"\110\111\114\109\097\108";"\060\067-\108\062","\060\067-\119\062\108";"\115\119\105\116\099\104 \119\105\110\100\111\119 \114\105\103\104\116"},{"\110\111\114\109\097\108","\060\067-\106\062";"\060\067-\119\062\106","\115\119\105\116\099\104 \119\105\110\100\111\119 \100\111\119\110"};{"\110\111\114\109\097\108";"\060\067-\107\062";"\060\067-\119\062\107","\115\119\105\116\099\104 \119\105\110\100\111\119 \117\112"}})V({group="\115\101\108\101\099\116\105\111\110";{"\110\111\114\109\097\108","\060\077-\118\062","\094\118\103\095","\115\101\108\101\099\116 \099\111\110\116\101\110\116\115 \111\102 \099\117\114\114\101\110\116 \108\105\110\101"}})O.normal["\059"]={function()vim.notify("\117\115\101 \096\118\059\096",vim.log.levels.WARN)end;"\102\105\120\117\112 \096\118\059\096",group="\102\105\120\117\112"}vim.keymap.set("\111","\059","\105\119",{desc="\115\101\108\101\099\116 \105\110\115\105\100\101 \119\111\114\100"})vim.keymap.set("\118","\059","\105\119",{desc="\115\101\108\101\099\116 \105\110\115\105\100\101 \119\111\114\100"})O.normal.D={"\048\100\036","\099\108\101\097\114 \099\117\114\114\101\110\116 \108\105\110\101";group="\101\100\105\116"}V({group="\100\105\097\103\110\111\115\116\105\099\115";{"\110\111\114\109\097\108";"\060\108\101\097\100\101\114\062\100\100";vim.diagnostic.open_float;"\104\111\118\101\114 \100\105\097\103\110\111\115\116\105\099\115"}})V({group="\114\101\099\111\114\100\105\110\103",{"\110\111\114\109\097\108";"\081";"\113";"\114\101\099\111\114\100 \109\097\099\114\111"}})V({group="\116\114\101\101\115\105\116\116\101\114",{"\110\111\114\109\097\108","\103\109",vim.show_pos;"\105\110\115\112\101\099\116 \116\114\101\101\115\105\116\116\101\114 \110\111\100\101"}})local L=vim.api.nvim_create_namespace("\114\101\115\105\122\101-\109\111\100\101")O.normal["\060\115\112\097\099\101\062\119"]={function()vim.on_key(function(O,V)local G={["\060\067-\072\062"]=function()if vim.fn.winnr()==vim.fn.winnr("\108")then return vim.fn.win_move_separator(vim.fn.winnr("\104"),-1)end vim.fn.win_move_separator(vim.fn.winnr(),-1)end;["\060\067-\074\062"]=function()if vim.fn.winnr()~=vim.fn.winnr("\106")then vim.fn.win_move_statusline(vim.fn.winnr(),1)end vim.fn.win_move_statusline(vim.fn.winnr("\107"),1)end,["\060\067-\075\062"]=function()if vim.fn.winnr()~=vim.fn.winnr("\106")then vim.fn.win_move_statusline(vim.fn.winnr(),-1)end vim.fn.win_move_statusline(vim.fn.winnr("\107"),-1)end;["\060\067-\076\062"]=function()if vim.fn.winnr()==vim.fn.winnr("\108")then return vim.fn.win_move_separator(vim.fn.winnr("\104"),1)end vim.fn.win_move_separator(vim.fn.winnr(),1)end}local U=vim.fn.keytrans(V)if U=="\060\069\115\099\062"then vim.on_key(nil,L)elseif vim.tbl_contains({"\104","\106";"\107";"\108"},U)then vim.cmd.wincmd(U)elseif vim.tbl_contains(vim.tbl_keys(G),U)then local O=G[U]if O and type(O)=="\102\117\110\099\116\105\111\110"then O()end end return""end,L)end;"\101\110\116\101\114 \114\101\115\105\122\101 \109\111\100\101"}O.terminal["\060\101\115\099\062\060\101\115\099\062"]={"\060\067-\092\062\060\067-\110\062","\101\115\099\097\112\101 \116\101\114\109\105\110\097\108 \109\111\100\101"}end}
return {
  setup = function()
    ---@diagnostic disable-next-line: missing-fields
    local keymaps = require("keymaps").setup()

    local function kmgroup(props)
      if not props.group then
        vim.notify(
          string.format("[%s] %s", "globals.keymap", "`Keymap.group` requires `group` field"),
          vim.log.levels.WARN
        )
        return
      end
      local mappings = props
      vim.iter(ipairs(mappings)):each(function(_, map)
        if #map < 4 then
          vim.notify(
            string.format("[%s] %s", "globals.keymap", "`Keymap.group` requires 4 paramaters per keymap"),
            vim.log.levels.WARN
          )
          return
        end
        local mode = map[1]
        local lhs = map[2]
        local rhs = map[3]
        local desc = map[4]

        if not keymaps[mode] then
          vim.notify(
            string.format("[%s] %s", "globals.keymap", "keymap mode '" .. mode .. "' does not exist"),
            vim.log.levels.WARN
          )
          return
        end
        keymaps[mode][lhs] = { rhs, desc, group = props.group }
      end)
    end

    local function cbcall(fn, props)
      return function()
        pcall(fn, props)
      end
    end

    -- set space as leader
    vim.g.mapleader = " "
    vim.g.maplocalleader = " m"

    kmgroup({
      group = "keymaps",
      {
        "normal",
        "<space>,k",
        [[<cmd>s/keymaps\.\(\w*\)\["\([^"]*\)"\] = { \([^,]*\), "\([^"]*\)" }/{ "\1", "\2", \3, "\4" }/<cr>]],
        "transform line to group item format",
      },
    })

    kmgroup({
      group = "movement",
      { "normal", "W", "g_", "goto last non empty of line" },
      { "normal", "B", "^", "goto first non empty of line" },
      { "visual", "W", "g_", "goto last non empty of line" },
      { "visual", "B", "^", "goto first non empty of line" },
    })

    kmgroup({
      group = "vertical movment",
      { "normal", "<C-d>", "<C-d>zz", "go down and center line" },
      { "normal", "<C-u>", "<C-u>zz", "go up and center line" },
      { "normal", "n", "nzzzv", "goto next search and uncover line" },
      { "normal", "N", "Nzzzv", "goto prev search and uncover line" },
    })

    kmgroup({
      group = "fixup",
      { "normal", "<S-down>", "<nop>", "remove shift down movement" },
      { "normal", "<S-up>", "<nop>", "remove shift up movement" },
      { "visual", "<S-down>", "<nop>", "remove shift down movement" },
      { "visual", "<S-up>", "<nop>", "remove shift up movement" },
    })

    kmgroup({
      group = "workspace",
      { "normal", "<leader>q", vim.cmd.quitall, "quit all" },
      { "visual", "<leader>q", vim.cmd.quitall, "quit all" },
    })

    kmgroup({
      group = "file",
      { "normal", "<C-s>", vim.cmd.update, "save file" },
    })

    -- window movement
    for _, direction in ipairs({ "h", "j", "k", "l" }) do
      keymaps.normal["<leader>" .. direction] = {
        function()
          vim.cmd.wincmd(direction)
        end,
        string.format("switch window `%s`", direction),
        group = "windows",
      }
    end

    keymaps.normal["s"] = { "<nop>", "fixup `s`", group = "fixup" }

    kmgroup({
      group = "windows",
      { "normal", "sv", vim.cmd.vsplit, "split window vertical" },
      { "normal", "sh", vim.cmd.split, "split window horizontal" },
      { "normal", "q", cbcall(vim.cmd.wincmd, "q"), "close window" },
    })

    kmgroup({
      group = "tabs",
      { "normal", "<space><tab>]", vim.cmd.tabnext, "next tab" },
      { "normal", "<space><tab>[", vim.cmd.tabprev, "prev tab" },
      { "normal", "<space><tab>n", cbcall(vim.cmd, [[$tabedit]]), "open new tab" },
      { "normal", "<space><tab>d", vim.cmd.tabclose, "close current tab" },
      { "normal", "<space><tab>x", vim.cmd.tabclose, "close current tab" },
      {
        "normal",
        "<space><tab><",
        function()
          vim.cmd([[ -tabmove ]])
        end,
        "move tab to the left",
      },
      {
        "normal",
        "<space><tab>>",
        function()
          vim.cmd([[ +tabmove ]])
        end,
        "move tab to the right",
      },
    })

    kmgroup({
      group = "windows",
      {
        "normal",
        "<C-\\>",
        function()
          vim.cmd([[vs | wincmd l]])
        end,
        "split file vertically",
      },
      { "normal", "<C-h>", "<C-w>h", "switch window left" },
      { "normal", "<C-l>", "<C-w>l", "switch window right" },
      { "normal", "<C-j>", "<C-w>j", "switch window down" },
      { "normal", "<C-k>", "<C-w>k", "switch window up" },
    })

    kmgroup({
      group = "selection",
      { "normal", "<M-v>", "^vg_", "select contents of current line" },
    })

    keymaps.normal[";"] = {
      function()
        vim.notify("use `v;`", vim.log.levels.WARN)
      end,
      "fixup `v;`",
      group = "fixup",
    }
    vim.keymap.set("o", ";", "iw", { desc = "select inside word" })
    vim.keymap.set("v", ";", "iw", { desc = "select inside word" })

    keymaps.normal["D"] = { "0d$", "clear current line", group = "edit" }

    kmgroup({
      group = "diagnostics",
      { "normal", "<leader>dd", vim.diagnostic.open_float, "hover diagnostics" },
    })

    kmgroup({
      group = "recording",
      { "normal", "Q", "q", "record macro" },
    })

    kmgroup({
      group = "treesitter",
      { "normal", "gm", vim.show_pos, "inspect treesitter node" },
    })

    local ns = vim.api.nvim_create_namespace("resize-mode")
    keymaps.normal["<space>w"] = {
      function()
        vim.on_key(function(key, typed)
          local switch = {
            ["<C-H>"] = function()
              if vim.fn.winnr() == vim.fn.winnr("l") then
                return vim.fn.win_move_separator(vim.fn.winnr("h"), -1)
              end
              vim.fn.win_move_separator(vim.fn.winnr(), -1)
            end,
            ["<C-J>"] = function()
              if vim.fn.winnr() ~= vim.fn.winnr("j") then
                vim.fn.win_move_statusline(vim.fn.winnr(), 1)
              end
              vim.fn.win_move_statusline(vim.fn.winnr("k"), 1)
            end,
            ["<C-K>"] = function()
              if vim.fn.winnr() ~= vim.fn.winnr("j") then
                vim.fn.win_move_statusline(vim.fn.winnr(), -1)
              end
              vim.fn.win_move_statusline(vim.fn.winnr("k"), -1)
            end,
            ["<C-L>"] = function()
              if vim.fn.winnr() == vim.fn.winnr("l") then
                return vim.fn.win_move_separator(vim.fn.winnr("h"), 1)
              end
              vim.fn.win_move_separator(vim.fn.winnr(), 1)
            end,
          }

          local k = vim.fn.keytrans(typed)
          if k == "<Esc>" then
            vim.on_key(nil, ns)
          elseif vim.tbl_contains({ "h", "j", "k", "l" }, k) then
            vim.cmd.wincmd(k)
          elseif vim.tbl_contains(vim.tbl_keys(switch), k) then
            local fn = switch[k]
            if fn and type(fn) == "function" then
              fn()
            end
          end
          return ""
        end, ns)
      end,
      "enter resize mode",
    }

    keymaps.terminal["<esc><esc>"] = { [[<C-\><C-n>]], "escape terminal mode" }
  end,
}
