Compare commits

..

11 Commits

Author SHA1 Message Date
82030bea78 karabiner 2026-04-01 23:11:25 +02:00
478ac65fd7 Stabilize Telescope and trim Mason health checks 2026-04-01 22:43:21 +02:00
9173d3332b TODO 2026-04-01 21:42:51 +02:00
89fda09d17 Add local Neovim migration notes 2026-04-01 21:04:03 +02:00
c7f0678ed4 Update Neovim UI tutorial config 2026-04-01 21:03:04 +02:00
f494b1840a added LSP and treesitter 2026-03-31 23:13:00 +02:00
455169b537 Add nvim-tree configuration 2026-03-30 23:47:46 +02:00
ffb21643d5 Set kitty cmd-enter to open in home directory 2026-03-30 22:45:03 +02:00
614784daf4 Fix kitty quick access Karabiner binding 2026-03-30 20:59:42 +02:00
e086d23d1c Merge branch 'master' of git.24unix.net:tracer/dotfiles 2026-03-30 20:36:00 +02:00
f3cb672d65 working on hud setup 2026-03-30 20:35:43 +02:00
18 changed files with 594 additions and 140 deletions

4
TODO Normal file
View File

@@ -0,0 +1,4 @@
- check for vimrc
- move to new packer
- for plugins with more config ines than 5, crezte a dedicatet folder/file

1
karabiner/assets Symbolic link
View File

@@ -0,0 +1 @@
/Users/tracer/.config/dotfiles/karabiner/assets

View File

@@ -1,18 +0,0 @@
{
"type": "basic",
"from": {
"key_code": "return_or_enter",
"modifiers": {
"mandatory": ["control"],
"optional": []
}
},
"to": [
{
"key_code": "vk_none"
},
{
"shell_command": "/Applications/kitty.app/Contents/MacOS/kitten quick-access-terminal >/tmp/kitty-quick-access.log 2>&1 &"
}
]
}

View File

@@ -1,25 +0,0 @@
{
"title": "Kitty quick access terminal",
"rules": [
{
"description": "Ctrl+Enter toggles kitty quick-access-terminal",
"manipulators": [
{
"type": "basic",
"from": {
"key_code": "return_or_enter",
"modifiers": {
"mandatory": ["control"],
"optional": ["any"]
}
},
"to": [
{
"shell_command": "/Applications/kitty.app/Contents/MacOS/kitten quick-access-terminal --detach"
}
]
}
]
}
]
}

View File

@@ -1,75 +0,0 @@
{
"profiles": [
{
"complex_modifications": {
"rules": [
{
"description": "kitty: map cmd+left/right to ctrl+left/right",
"manipulators": [
{
"conditions": [
{
"bundle_identifiers": [
"^net\\.kovidgoyal\\.kitty$"
],
"type": "frontmost_application_if"
}
],
"from": {
"key_code": "left_arrow",
"modifiers": {
"mandatory": ["command"],
"optional": ["any"]
}
},
"to": [
{
"key_code": "left_arrow",
"modifiers": ["control"]
}
],
"type": "basic"
},
{
"conditions": [
{
"bundle_identifiers": [
"^net\\.kovidgoyal\\.kitty$"
],
"type": "frontmost_application_if"
}
],
"from": {
"key_code": "right_arrow",
"modifiers": {
"mandatory": ["command"],
"optional": ["any"]
}
},
"to": [
{
"key_code": "right_arrow",
"modifiers": ["control"]
}
],
"type": "basic"
}
]
}
]
},
"fn_function_keys": [
{
"from": { "key_code": "f6" },
"to": [{ "key_code": "f6" }]
}
],
"name": "Default profile",
"selected": true,
"virtual_hid_keyboard": {
"country_code": 0,
"keyboard_type_v2": "ansi"
}
}
]
}

1
karabiner/karabiner.json Symbolic link
View File

@@ -0,0 +1 @@
/Users/tracer/.config/dotfiles/karabiner/karabiner.json

View File

@@ -9,9 +9,11 @@ enable_audio_bell 0
hide_window_decorations titlebar-only
macos_show_window_title_in none
macos_titlebar_color background
copy_on_select clipboard
term xterm-256color
map ctrl+left previous_tab
map ctrl+right next_tab
window_padding_width 10
map cmd+enter new_os_window
map ctrl+enter kitten quick-access-terminal
map cmd+shift+r load_config_file
map cmd+enter launch --type=os-window --cwd=~

View File

@@ -0,0 +1 @@
--single-instance

View File

@@ -0,0 +1,128 @@
# vim:fileencoding=utf-8:foldmethod=marker
#: Window appearance {{{
# lines 25
#: The number of lines shown in the panel. Ignored for background,
#: centered, and vertical panels. If it has the suffix px then it sets
#: the height of the panel in pixels instead of lines.
# columns 80
#: The number of columns shown in the panel. Ignored for background,
#: centered, and horizontal panels. If it has the suffix px then it
#: sets the width of the panel in pixels instead of columns.
# edge top
#: Which edge of the screen to place the panel on. Note that some
#: window managers (such as i3) do not support placing docked windows
#: on the left and right edges. The value background means make the
#: panel the "desktop wallpaper". Note that when using sway if you set
#: a background in your sway config it will cover the background drawn
#: using this kitten. Additionally, there are three more values:
#: center, center-sized and none. The value center anchors the panel
#: to all sides and covers the entire display (on macOS the part of
#: the display not covered by titlebar and dock). The panel can be
#: shrunk and placed using the margin parameters. The value none
#: anchors the panel to the top left corner and should be placed using
#: the margin parameters. Its size is set by lines and columns. The
#: value center-sized is just like none except that the panel is
#: centered instead of in the top left corner and the margins have no
#: effect.
# background_opacity 0.85
#: The background opacity of the window. This works the same as the
#: kitty option of the same name, it is present here as it has a
#: different default value for the quick access terminal.
# hide_on_focus_loss no
#: Hide the window when it loses keyboard focus automatically. Using
#: this option will force focus_policy to on-demand.
# grab_keyboard no
#: Grab the keyboard. This means global shortcuts defined in the OS
#: will be passed to kitty instead. Useful if you want to create an OS
#: modal window. How well this works depends on the OS/window
#: manager/desktop environment. On Wayland it works only if the
#: compositor implements the inhibit-keyboard-shortcuts protocol
#: <https://wayland.app/protocols/keyboard-shortcuts-inhibit-
#: unstable-v1>. On macOS Apple doesn't allow applications to grab the
#: keyboard without special permissions, so it doesn't work.
# margin_left 0
#: Set the left margin for the panel, in pixels. Has no effect for
#: right edge panels. Only works on macOS and Wayland compositors that
#: supports the wlr layer shell protocol.
# margin_right 0
#: Set the right margin for the panel, in pixels. Has no effect for
#: left edge panels. Only works on macOS and Wayland compositors that
#: supports the wlr layer shell protocol.
# margin_top 0
#: Set the top margin for the panel, in pixels. Has no effect for
#: bottom edge panels. Only works on macOS and Wayland compositors
#: that supports the wlr layer shell protocol.
# margin_bottom 0
#: Set the bottom margin for the panel, in pixels. Has no effect for
#: top edge panels. Only works on macOS and Wayland compositors that
#: supports the wlr layer shell protocol.
# kitty_conf
#: Path to config file to use for kitty when drawing the window. Can
#: be specified multiple times. By default, the normal kitty.conf is
#: used. Relative paths are resolved with respect to the kitty config
#: directory.
# kitty_override
#: Override individual kitty configuration options, can be specified
#: multiple times. Syntax: kitty_override name=value. For example:
#: kitty_override font_size=20.
# app_id kitty-quick-access
#: On Wayland set the namespace of the layer shell surface. On X11 set
#: the WM_CLASS assigned to the quick access window. (Linux only)
# output_name
#: The panel can only be displayed on a single monitor (output) at a
#: time. This allows you to specify which output is used, by name. If
#: not specified the compositor will choose an output automatically,
#: typically the last output the user interacted with or the primary
#: monitor. Run kitten panel --output-name list to get a list of
#: available outputs. Use listjson for a json encoded output. Note
#: that on Wayland the output can only be set at panel creation time,
#: it cannot be changed after creation, nor is there anyway to display
#: a single panel on all outputs. Please complain to the Wayland
#: developers about this.
# start_as_hidden no
#: Whether to start the quick access terminal hidden. Useful if you
#: are starting it as part of system startup.
# focus_policy exclusive
#: On a Wayland compositor that supports the wlr layer shell protocol,
#: specify the focus policy for keyboard interactivity with the panel.
#: Please refer to the wlr layer shell protocol documentation for more
#: details. Note that different Wayland compositors behave very
#: differently with exclusive, your mileage may vary. On macOS,
#: exclusive and on-demand are currently the same.
#: }}}

8
nvim.log Normal file
View File

@@ -0,0 +1,8 @@
WRN 2026-04-01T22:04:13.317 ?.6087 server_start:197: Failed to start server: operation not permitted: /var/folders/jr/2c20bjfn48ld1tm7_75l6dz00000gn/T/nvim.tracer/BZ5xQs/nvim.6087.0
WRN 2026-04-01T22:04:13.317 ?.6086 server_start:197: Failed to start server: operation not permitted: /var/folders/jr/2c20bjfn48ld1tm7_75l6dz00000gn/T/nvim.tracer/W6ywmm/nvim.6086.0
WRN 2026-04-01T22:09:00.578 ?.7002 server_start:197: Failed to start server: operation not permitted: /var/folders/jr/2c20bjfn48ld1tm7_75l6dz00000gn/T/nvim.tracer/EE2fn7/nvim.7002.0
WRN 2026-04-01T22:10:22.134 ?.7483 server_start:197: Failed to start server: operation not permitted: /var/folders/jr/2c20bjfn48ld1tm7_75l6dz00000gn/T/nvim.tracer/q30iDC/nvim.7483.0
WRN 2026-04-01T22:10:22.134 ?.7481 server_start:197: Failed to start server: operation not permitted: /var/folders/jr/2c20bjfn48ld1tm7_75l6dz00000gn/T/nvim.tracer/JODETW/nvim.7481.0
WRN 2026-04-01T22:10:22.134 ?.7482 server_start:197: Failed to start server: operation not permitted: /var/folders/jr/2c20bjfn48ld1tm7_75l6dz00000gn/T/nvim.tracer/lKGUPU/nvim.7482.0
WRN 2026-04-01T22:10:29.772 ?.7512 server_start:197: Failed to start server: operation not permitted: /var/folders/jr/2c20bjfn48ld1tm7_75l6dz00000gn/T/nvim.tracer/84u53h/nvim.7512.0
WRN 2026-04-01T22:10:29.772 ?.7509 server_start:197: Failed to start server: operation not permitted: /var/folders/jr/2c20bjfn48ld1tm7_75l6dz00000gn/T/nvim.tracer/oWmRd9/nvim.7509.0

47
nvim/lua/mason/health.lua Normal file
View File

@@ -0,0 +1,47 @@
local health = vim.health or require("health")
local M = {}
local report_start = health.start or health.report_start
local report_ok = health.ok or health.report_ok
local report_warn = health.warn or health.report_warn
local function check_executable(name, command, advice)
if vim.fn.executable(command) == 1 then
report_ok(("%s: available"):format(name))
else
report_warn(("%s: not available"):format(name), advice and { advice } or {})
end
end
local function check_php()
local php_version = vim.fn.system({ "php", "-r", "echo PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;" })
if vim.v.shell_error ~= 0 then
report_warn("PHP: not available", {
"Required for your configured Intelephense language server.",
})
return
end
php_version = vim.trim(php_version)
if php_version:match("^8%.") then
report_ok(("PHP: `%s`"):format(php_version))
else
report_warn(("PHP: `%s`"):format(php_version), {
"PHP 8.x is recommended for your configured Intelephense language server.",
})
end
end
function M.check()
report_start("mason.nvim")
report_ok("Using local health override to skip unused language runtimes.")
report_ok("Skipped checks for Go, Rust/Cargo, LuaRocks, and Java.")
report_start("mason.nvim [Required runtimes]")
check_executable("node", "node", "Required for your configured TypeScript, ESLint, HTML, CSS, Emmet, and Intelephense language servers.")
check_executable("npm", "npm", "Required to install and manage the Mason packages used by your configured language servers.")
check_php()
end
return M

View File

@@ -1,4 +1,3 @@
require("tracer.options")
require("tracer.plugins")
pcall(require, "tracer.plugins.telescope")
require("tracer.statusline")

View File

@@ -7,6 +7,7 @@ opt.laststatus = 2
opt.termguicolors = true
opt.autoread = true
opt.mouse = "a"
opt.clipboard:append("unnamedplus")
opt.expandtab = true
opt.shiftwidth = 4
opt.tabstop = 4
@@ -15,24 +16,7 @@ opt.smartindent = true
opt.wrap = false
opt.wildmode = "longest:full,full"
opt.title = true
vim.cmd.colorscheme("slate")
local normalfloat_hl = vim.api.nvim_get_hl(0, { name = "NormalFloat", link = false })
if normalfloat_hl.bg then
vim.api.nvim_set_hl(0, "FloatBorder", {
fg = normalfloat_hl.bg,
bg = normalfloat_hl.bg,
})
end
local cursorline_hl = vim.api.nvim_get_hl(0, { name = "CursorLine", link = false })
if cursorline_hl.bg then
vim.api.nvim_set_hl(0, "CursorLineBg", {
fg = cursorline_hl.bg,
bg = cursorline_hl.bg,
})
end
opt.signcolumn = 'yes:1'
local autoread_group = vim.api.nvim_create_augroup("tracer_autoread", { clear = true })

View File

@@ -1,3 +1,6 @@
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
local ensure_packer = function()
local fn = vim.fn
local install_path = fn.stdpath("data") .. "/site/pack/packer/start/packer.nvim"
@@ -41,6 +44,39 @@ require("packer").startup(function(use)
use("tpope/vim-sleuth")
-- Allow plugins to enable repeating of commands.
use("tpope/vim-repeat")
-- One Dark theme.
use({
"jessarcher/onedark.nvim",
config = function()
vim.cmd.colorscheme("onedark")
local normalfloat_hl = vim.api.nvim_get_hl(0, { name = "NormalFloat", link = false })
if normalfloat_hl.bg then
vim.api.nvim_set_hl(0, "FloatBorder", {
fg = normalfloat_hl.bg,
bg = normalfloat_hl.bg,
})
end
local cursorline_hl = vim.api.nvim_get_hl(0, { name = "CursorLine", link = false })
if cursorline_hl.bg then
vim.api.nvim_set_hl(0, "CursorLineBg", {
fg = cursorline_hl.bg,
bg = cursorline_hl.bg,
})
end
vim.api.nvim_set_hl(0, "NvimTreeIndentMarker", { fg = "#30323E" })
local statusline_hl = vim.api.nvim_get_hl(0, { name = "StatusLine", link = false })
vim.api.nvim_set_hl(0, "StatusLineNonText", {
fg = "#5C6370",
bg = statusline_hl.bg,
})
vim.api.nvim_set_hl(0, "IndentBlanklineChar", { fg = "#2F313C" })
end,
})
-- Add more languages.
use("sheerun/vim-polyglot")
-- Navigate seamlessly between Vim windows and Tmux panes.
@@ -104,18 +140,96 @@ require("packer").startup(function(use)
vim.g.pasta_disabled_filetypes = { "fugitive" }
end,
})
-- Git integration.
use({
"lewis6991/gitsigns.nvim",
config = function()
require("gitsigns").setup({ current_line_blame = true })
vim.keymap.set("n", "]h", ":Gitsigns next_hunk<CR>")
vim.keymap.set("n", "[h", ":Gitsigns prev_hunk<CR>")
vim.keymap.set("n", "gs", ":Gitsigns stage_hunk<CR>")
vim.keymap.set("n", "gS", ":Gitsigns undo_stage_hunk<CR>")
vim.keymap.set("n", "gp", ":Gitsigns preview_hunk<CR>")
vim.keymap.set("n", "gb", ":Gitsigns blame_line<CR>")
end,
})
-- Git commands.
use({
"tpope/vim-fugitive",
requires = "tpope/vim-rhubarb",
config = function()
require("tracer.plugins.fugitive").setup()
end,
})
-- Improved syntax highlighting.
use({
"nvim-treesitter/nvim-treesitter",
run = function()
require("nvim-treesitter.install").update({ with_sync = true })
end,
requires = {
"JoosepAlviste/nvim-ts-context-commentstring",
"nvim-treesitter/nvim-treesitter-textobjects",
},
config = function()
pcall(require, "tracer.plugins.treesitter")
end,
})
-- Language Server Protocol.
use({
"neovim/nvim-lspconfig",
requires = {
"williamboman/mason.nvim",
"williamboman/mason-lspconfig.nvim",
},
config = function()
pcall(require, "tracer.plugins.lspconfig")
end,
})
-- Fuzzy finder
use({
"nvim-telescope/telescope.nvim",
tag = "0.2.2",
requires = {
"nvim-lua/plenary.nvim",
"kyazdani42/nvim-web-devicons",
"nvim-tree/nvim-web-devicons",
"nvim-telescope/telescope-live-grep-args.nvim",
{ "nvim-telescope/telescope-fzf-native.nvim", run = "make" },
},
config = function()
require("tracer.plugins.telescope")
end,
})
-- A status line.
use({
"nvim-lualine/lualine.nvim",
requires = "nvim-tree/nvim-web-devicons",
config = function()
require("tracer.plugins.lualine")
end,
})
-- Display buffers as tabs.
use({
"akinsho/bufferline.nvim",
requires = "nvim-tree/nvim-web-devicons",
after = "onedark.nvim",
config = function()
require("bufferline").setup()
end,
})
-- File tree sidebar for project-style navigation.
use({
"nvim-tree/nvim-tree.lua",
requires = {
"nvim-tree/nvim-web-devicons",
},
config = function()
require("tracer.plugins.nvim-tree")
end,
})

View File

@@ -0,0 +1,90 @@
local M = {}
local function homepage_for_remote(remote)
local patterns = {
"^gitea@([^:]+):(.+)%.git$",
"^git@([^:]+):(.+)%.git$",
"^ssh://git@([^/]+)/(.+)%.git$",
"^https?://([^/]+)/(.+)%.git$",
"^https?://([^/]+)/(.+)$",
}
for _, pattern in ipairs(patterns) do
local host, repo = remote:match(pattern)
if host and repo then
return ("https://%s/%s"):format(host, repo)
end
end
return nil
end
local function url_escape(value)
return (value:gsub("#", "%%23"):gsub(" ", "%%20"))
end
local function gitea_browse(opts)
local root = homepage_for_remote(opts.remote or "")
if not root then
return nil
end
local path = (opts.path or ""):gsub("^/", "")
local ref = (opts.path or ""):match("^/?%.git/(refs/.*)")
if ref and ref:match("^refs/heads/") then
local branch = ref:gsub("^refs/heads/", "")
return root .. "/commits/branch/" .. url_escape(branch)
end
if ref and ref:match("^refs/tags/") then
local tag = ref:gsub("^refs/tags/", "")
return root .. "/releases/tag/" .. url_escape(tag)
end
if ref and ref:match("^refs/remotes/[^/]+/.+") then
local branch = ref:match("^refs/remotes/[^/]+/(.+)$")
return root .. "/commits/branch/" .. url_escape(branch)
end
if (opts.path or ""):match("^/?%.git") then
return root
end
local commit = url_escape(opts.commit or "HEAD")
local url
if opts.type == "tree" or path:match("/$") then
url = root .. "/src/commit/" .. commit
if path ~= "" then
url = url .. "/" .. url_escape(path):gsub("/$", "")
end
elseif opts.type == "blob" or path:match("[^/]$") then
url = root .. "/src/commit/" .. commit
if path ~= "" then
url = url .. "/" .. url_escape(path)
end
if opts.line2 and opts.line1 and opts.line1 > 0 and opts.line1 == opts.line2 then
url = url .. "#L" .. opts.line1
elseif opts.line1 and opts.line2 and opts.line1 > 0 and opts.line2 > 0 then
url = url .. "#L" .. opts.line1 .. "-L" .. opts.line2
end
else
url = root .. "/commit/" .. commit
end
return url
end
function M.setup()
if vim.g.tracer_fugitive_gitea_handler_loaded then
return
end
vim.g.tracer_fugitive_gitea_handler_loaded = true
vim.g.fugitive_browse_handlers = vim.g.fugitive_browse_handlers or {}
table.insert(vim.g.fugitive_browse_handlers, 1, gitea_browse)
end
return M

View File

@@ -0,0 +1,34 @@
-- Setup Mason to automatically install LSP servers
require("mason").setup()
require("mason-lspconfig").setup({ automatic_installation = true })
-- Keymaps
vim.keymap.set("n", "<Leader>d", vim.diagnostic.open_float)
vim.keymap.set("n", "[d", vim.diagnostic.goto_prev)
vim.keymap.set("n", "]d", vim.diagnostic.goto_next)
vim.keymap.set("n", "gd", vim.lsp.buf.definition)
vim.keymap.set("n", "gi", "<cmd>Telescope lsp_implementations<CR>")
vim.keymap.set("n", "gr", "<cmd>Telescope lsp_references<CR>")
vim.keymap.set("n", "K", vim.lsp.buf.hover)
vim.keymap.set("n", "<Leader>rn", vim.lsp.buf.rename)
-- Emmet for HTML and JSX-style markup editing
vim.lsp.config("emmet_language_server", {
filetypes = {
"css",
"html",
"javascriptreact",
"less",
"sass",
"scss",
"typescriptreact",
},
})
vim.lsp.enable("intelephense")
vim.lsp.enable("ts_ls")
vim.lsp.enable("eslint")
vim.lsp.enable("html")
vim.lsp.enable("cssls")
vim.lsp.enable("emmet_language_server")

View File

@@ -0,0 +1,76 @@
local separator = {
"|",
color = "StatusLineNonText",
}
local non_text_hl = vim.api.nvim_get_hl(0, { name = "NonText" })
local statusline_hl = vim.api.nvim_get_hl(0, { name = "StatusLine" })
vim.api.nvim_set_hl(0, "StatusLineNonText", {
fg = non_text_hl.fg,
bg = statusline_hl.bg,
})
local function lsp_clients()
local clients = vim.lsp.get_clients({ bufnr = 0 })
if #clients == 0 then
return ""
end
local names = {}
for _, client in ipairs(clients) do
names[#names + 1] = client.name
end
return "LSP: " .. table.concat(names, ", ")
end
require("lualine").setup({
options = {
section_separators = '',
component_separators = "",
globalstatus = true,
theme = {
normal = {
a = "StatusLine",
b = "StatusLine",
c = "StatusLine",
},
},
},
sections = {
lualine_a = {
"mode",
separator,
},
lualine_b = {
"branch",
"diff",
separator,
lsp_clients,
{ "diagnostics", sources = { "nvim_diagnostic" } },
separator,
},
lualine_c = {
"filename",
},
lualine_x = {
"filetype",
"encoding",
"fileformat",
},
lualine_y = {
separator,
function()
return (vim.bo.expandtab and "s" or "t") .. "" .. vim.bo.shiftwidth
end,
separator,
},
lualine_z = {
"location",
"progress",
},
},
})

View File

@@ -0,0 +1,53 @@
require("nvim-tree").setup({
git = {
enable = false,
},
hijack_cursor = true,
sync_root_with_cwd = false,
update_focused_file = {
enable = true,
update_root = false,
},
view = {
width = 36,
preserve_window_proportions = true,
},
renderer = {
group_empty = true,
icons = {
show = {
folder_arrow = false,
},
},
indent_markers = {
enable = true,
},
},
filters = {
dotfiles = false,
},
actions = {
open_file = {
resize_window = true,
},
},
})
vim.keymap.set("n", "<leader>e", "<cmd>NvimTreeToggle<CR>", { silent = true })
vim.keymap.set("n", "<leader>t", ":NvimTreeFindFileToggle<CR>")
local project_tree_group = vim.api.nvim_create_augroup("tracer_project_tree", { clear = true })
vim.api.nvim_create_autocmd("VimEnter", {
group = project_tree_group,
callback = function(data)
if vim.fn.argc() ~= 1 or vim.fn.isdirectory(data.file) ~= 1 then
return
end
vim.cmd.cd(data.file)
vim.cmd.enew()
vim.cmd.bwipeout(data.buf)
require("nvim-tree.api").tree.open()
end,
})

View File

@@ -0,0 +1,30 @@
local ok, configs = pcall(require, "nvim-treesitter.configs")
if not ok then
return
end
configs.setup({
ensure_installed = "all",
highlight = {
enable = true,
additional_vim_regex_highlighting = true,
},
context_commentstring = {
enable = true,
},
indent = {
enable = true,
},
textobjects = {
select = {
enable = true,
lookahead = true,
keymaps = {
["if"] = "@function.inner",
["af"] = "@function.outer",
["ia"] = "@parameter.inner",
["aa"] = "@parameter.outer",
},
},
},
})