_:
let
  map = mode: key: action: {
    inherit mode key action;
  };
  luamap =
    mode: key: action:
    map mode key "<cmd>lua ${action}<cr>";
  telescope = "require('telescope.builtin')";
in
{
  programs.nixvim.keymaps = [
    (map "" "<f2>" "<cmd>Lspsaga rename<cr>")
    (map "" "<leader>o" "<cmd>Lspsaga outline<cr>")
    (map "" "<leader>." "<cmd>Lspsaga code_action<cr>")

    # splitting
    (map "n" "<leader>s" "<cmd>vertical sb<cr>")

    # jumplist
    (map "" "<C-a>" "<C-i>") # note: C-a is actually C-i, remapped through kitty.
    (luamap "n" "<leader>r" "${telescope}.jumplist()")
    (luamap "n" "<leader>R" "${telescope}.loclist()")

    # pickers
    (luamap "n" "<leader><leader>" "${telescope}.find_files()")
    (luamap "n" "<leader>f" "${telescope}.live_grep()")
    (luamap "n" "<leader>t" "${telescope}.lsp_document_symbols()")
    (luamap "n" "<leader>T" "${telescope}.lsp_dynamic_workspace_symbols()")
    (luamap "n" "<leader>/" "${telescope}.current_buffer_fuzzy_find()")
    # last used pickers/searches
    (luamap "n" "<leader>p" "${telescope}.pickers()")
    (luamap "n" "<leader>m" "${telescope}.search_history()")
    # open buffers
    (luamap "n" "<leader>b" "${telescope}.buffers({sort_mru = true})")
    (luamap "n" "<leader><Tab>" "${telescope}.buffers({sort_mru = true})")

    # diagnostics
    (map "n" "<leader>d" "<cmd>Trouble diagnostics toggle filter.buf=0<cr>")
    (map "n" "<leader>ad" "<cmd>Trouble diagnostics toggle<cr>")
    (luamap "n" "]d"
      "vim.diagnostic.goto_next({ severity = vim.diagnostic.severity.ERROR, wrap=true })"
    )
    (luamap "n" "[d"
      "vim.diagnostic.goto_prev({ severity = vim.diagnostic.severity.ERROR, wrap=true })"
    )
    (luamap "n" "]w" "vim.diagnostic.goto_next({ wrap=true })")
    (luamap "n" "[w" "vim.diagnostic.goto_prev({ wrap=true })")

    # docs with control-d just like in autocomplete
    (map "n" "<C-d>" "K")

    # expand macro
    (map "n" "<leader>em" "<cmd>RustLsp expandMacro<cr>")

    # navigation
    (map "" "<leader><Left>" "<C-w><Left>")
    (map "" "<leader><Right>" "<C-w><Right>")
    (map "" "<leader><Up>" "<C-w><Up>")
    (map "" "<leader><Down>" "<C-w><Down>")
    (map "" "<leader>h" "<C-w><Left>")
    (map "" "<leader>l" "<C-w><Right>")
    (map "" "<leader>k" "<C-w><Up>")
    (map "" "<leader>j" "<C-w><Down>")

    # close buffer
    (map "" "<leader>c" "<cmd>bd<cr>")

    # {
    # key = "/";
    # action = "<cmd>lua require('spectre').open_file_search({select_word=true})<CR>";
    # }

    # (map "n" "t" "<cmd>Neotree toggle<cr>")

    # tab for indent/dedent
    (map "n" "<tab>" ">>_")
    (map "n" "<S-tab>" "<<_")
    (map "i" "<S-tab>" "<c-d>")
    (map "v" "<tab>" ">gv")
    (map "v" "<S-tab>" "<gv")

    # to avoid many typos
    # easier quitting etc
    (map "n" ";" ":")
    (map "ca" "W" "w")
    (map "ca" "X" "x")
  ];
}
