From 8795ccaa29ea5c5893b9ac505f72eaa4f74b2f0b Mon Sep 17 00:00:00 2001 From: Solomon Laing Date: Mon, 9 Jan 2023 23:25:14 +1030 Subject: [PATCH] better in many ways --- .config/nvim/lua/lazyvim/functions.lua | 183 +++++++------- .config/nvim/lua/lazyvim/plugins/color.lua | 18 +- .config/nvim/lua/lazyvim/plugins/git.lua | 2 +- .config/nvim/lua/lazyvim/plugins/lsp/init.lua | 73 +++--- .config/nvim/lua/lazyvim/plugins/lualine.lua | 225 +++++++++--------- .config/nvim/lua/lazyvim/plugins/noice.lua | 2 +- .config/nvim/lua/lazyvim/plugins/snippets.lua | 67 +++--- .../nvim/lua/lazyvim/plugins/telescope.lua | 2 +- .config/nvim/lua/lazyvim/plugins/trouble.lua | 2 +- .config/nvim/lua/lazyvim/plugins/utility.lua | 76 +++--- 10 files changed, 346 insertions(+), 304 deletions(-) diff --git a/.config/nvim/lua/lazyvim/functions.lua b/.config/nvim/lua/lazyvim/functions.lua index e4a8eb4..87651f6 100644 --- a/.config/nvim/lua/lazyvim/functions.lua +++ b/.config/nvim/lua/lazyvim/functions.lua @@ -4,13 +4,13 @@ M.root_patterns = { ".git", "/lua" } ---@param on_attach fun(client, buffer) function M.on_attach(on_attach) - vim.api.nvim_create_autocmd("LspAttach", { - callback = function(args) - local buffer = args.buf - local client = vim.lsp.get_client_by_id(args.data.client_id) - on_attach(client, buffer) - end, - }) + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(args) + local buffer = args.buf + local client = vim.lsp.get_client_by_id(args.data.client_id) + on_attach(client, buffer) + end, + }) end -- returns the root directory based on: @@ -20,110 +20,113 @@ end -- * root pattern of cwd ---@return string function M.get_root() - ---@type string? - local path = vim.api.nvim_buf_get_name(0) - path = path ~= "" and vim.loop.fs_realpath(path) or nil - ---@type string[] - local roots = {} - if path then - for _, client in pairs(vim.lsp.get_active_clients({ bufnr = 0 })) do - local workspace = client.config.workspace_folders - local paths = workspace and vim.tbl_map(function(ws) - return vim.uri_to_fname(ws.uri) - end, workspace) or client.config.root_dir and { client.config.root_dir } or {} - for _, p in ipairs(paths) do - local r = vim.loop.fs_realpath(p) - if path:find(r, 1, true) then - roots[#roots + 1] = r - end - end - end - end - table.sort(roots, function(a, b) - return #a > #b - end) - ---@type string? - local root = roots[1] - if not root then - path = path and vim.fs.dirname(path) or vim.loop.cwd() - ---@type string? - root = vim.fs.find(M.root_patterns, { path = path, upward = true })[1] - root = root and vim.fs.dirname(root) or vim.loop.cwd() - end - ---@cast root string - return root + ---@type string? + local path = vim.api.nvim_buf_get_name(0) + path = path ~= "" and vim.loop.fs_realpath(path) or nil + ---@type string[] + local roots = {} + if path then + for _, client in pairs(vim.lsp.get_active_clients({ bufnr = 0 })) do + local workspace = client.config.workspace_folders + local paths = workspace + and vim.tbl_map(function(ws) + return vim.uri_to_fname(ws.uri) + end, workspace) + or client.config.root_dir and { client.config.root_dir } + or {} + for _, p in ipairs(paths) do + local r = vim.loop.fs_realpath(p) + if path:find(r, 1, true) then + roots[#roots + 1] = r + end + end + end + end + table.sort(roots, function(a, b) + return #a > #b + end) + ---@type string? + local root = roots[1] + if not root then + path = path and vim.fs.dirname(path) or vim.loop.cwd() + ---@type string? + root = vim.fs.find(M.root_patterns, { path = path, upward = true })[1] + root = root and vim.fs.dirname(root) or vim.loop.cwd() + end + ---@cast root string + return root end ---@param silent boolean? ---@param values? {[1]:any, [2]:any}function function M.toggle(option, silent, values) - if values then - if vim.opt_local[option]:get() == values[1] then - vim.opt_local[option] = values[2] - else - vim.opt_local[option] = values[1] - end - return vim.notify( - "Set " .. option .. " to " .. vim.opt_local[option]:get(), - vim.log.levels.INFO, - { title = "Option" } - ) - end - vim.opt_local[option] = not vim.opt_local[option]:get() - if not silent then - vim.notify( - (vim.opt_local[option]:get() and "Enabled" or "Disabled") .. " " .. option, - vim.log.levels.INFO, - { title = "Option" } - ) - end + if values then + if vim.opt_local[option]:get() == values[1] then + vim.opt_local[option] = values[2] + else + vim.opt_local[option] = values[1] + end + return vim.notify( + "Set " .. option .. " to " .. vim.opt_local[option]:get(), + vim.log.levels.INFO, + { title = "Option" } + ) + end + vim.opt_local[option] = not vim.opt_local[option]:get() + if not silent then + vim.notify( + (vim.opt_local[option]:get() and "Enabled" or "Disabled") .. " " .. option, + vim.log.levels.INFO, + { title = "Option" } + ) + end end local enabled = true function M.toggle_diagnostics() - enabled = not enabled - if enabled then - vim.diagnostic.enable() - vim.notify("Enabled diagnostics", vim.log.levels.INFO, { title = "Diagnostics" }) - else - vim.diagnostic.disable() - vim.notify("Disabled diagnostics", vim.log.levels.INFO, { title = "Diagnostics" }) - end + enabled = not enabled + if enabled then + vim.diagnostic.enable() + vim.notify("Enabled diagnostics", vim.log.levels.INFO, { title = "Diagnostics" }) + else + vim.diagnostic.disable() + vim.notify("Disabled diagnostics", vim.log.levels.INFO, { title = "Diagnostics" }) + end end function M.smart_quit() - local bufnr = vim.api.nvim_get_current_buf() - local modified = vim.api.nvim_buf_get_option(bufnr, "modified") - if modified then - vim.ui.input({ - prompt = "You have unsaved changes. Quit anyway? (y/n) ", - }, function(input) - if input == "y" then - vim.cmd "q!" - end - end) - else - vim.cmd "q!" - end + local bufnr = vim.api.nvim_get_current_buf() + local modified = vim.api.nvim_buf_get_option(bufnr, "modified") + if modified then + vim.ui.input({ + prompt = "You have unsaved changes. Quit anyway? (y/n) ", + }, function(input) + if input == "y" then + vim.cmd("q!") + end + end) + else + vim.cmd("q!") + end end function M.isempty(s) - return s == nil or s == "" + return s == nil or s == "" end function M.get_buf_option(opt) - local status_ok, buf_option = pcall(vim.api.nvim_buf_get_option, 0, opt) - if not status_ok then - return nil - else - return buf_option - end + local status_ok, buf_option = pcall(vim.api.nvim_buf_get_option, 0, opt) + if not status_ok then + return nil + else + return buf_option + end end function M.telescope(builtin, opts) - return function() - require("telescope.builtin")[builtin](vim.tbl_deep_extend("force", { cwd = M.get_root() }, opts or {})) - end + return function() + require("telescope.builtin")[builtin](vim.tbl_deep_extend("force", { cwd = M.get_root() }, opts or {})) + end end return M diff --git a/.config/nvim/lua/lazyvim/plugins/color.lua b/.config/nvim/lua/lazyvim/plugins/color.lua index ea0819b..eb567a2 100644 --- a/.config/nvim/lua/lazyvim/plugins/color.lua +++ b/.config/nvim/lua/lazyvim/plugins/color.lua @@ -2,22 +2,36 @@ return { { "sainnhe/gruvbox-material", lazy = true, + priority = 1000, }, { "sainnhe/sonokai", lazy = true, + priority = 1000, }, { "dracula/vim", lazy = true, + priority = 1000, }, { - "RRethy/nvim-base16", + "folke/tokyonight.nvim", lazy = true, + priority = 1000, + }, + { + "echasnovski/mini.base16", + lazy = false, + priority = 1000, + }, + { + "chriskempson/base16-vim", + lazy = false, + priority = 1000, }, { "NvChad/nvim-colorizer.lua", - config = function() + opts = function() require("colorizer").setup({}) end, }, diff --git a/.config/nvim/lua/lazyvim/plugins/git.lua b/.config/nvim/lua/lazyvim/plugins/git.lua index 5ef557c..1c23704 100644 --- a/.config/nvim/lua/lazyvim/plugins/git.lua +++ b/.config/nvim/lua/lazyvim/plugins/git.lua @@ -2,7 +2,7 @@ return { { "lewis6991/gitsigns.nvim", event = "BufReadPre", - config = { + opns = { signs = { add = { text = "▎" }, change = { text = "▎" }, diff --git a/.config/nvim/lua/lazyvim/plugins/lsp/init.lua b/.config/nvim/lua/lazyvim/plugins/lsp/init.lua index da2b12c..899adee 100644 --- a/.config/nvim/lua/lazyvim/plugins/lsp/init.lua +++ b/.config/nvim/lua/lazyvim/plugins/lsp/init.lua @@ -11,29 +11,27 @@ return { "hrsh7th/cmp-nvim-lsp", }, ---@type lspconfig.options - servers = { - jsonls = {}, - sumneko_lua = { - settings = { - Lua = { - workspace = { - checkThirdParty = false, - }, - completion = { - callSnippet = "Replace", + opts = { + servers = { + jsonls = {}, + sumneko_lua = { + settings = { + Lua = { + workspace = { + checkThirdParty = false, + }, + completion = { + callSnippet = "Replace", + }, }, }, }, }, + setup = { + -- additional setup can be added here. + }, }, - -- you can do any additional lsp server setup here - -- return true if you don't want this server to be setup with lspconfig - ---@param server string lsp server name - ---@param opts _.lspconfig.options any options set for the server - setup_server = function(server, opts) - return false - end, - config = function(plugin) + config = function(plugin, opts) -- setup formatting and keymaps require("lazyvim.functions").on_attach(function(client, buffer) require("lazyvim.plugins.lsp.format").on_attach(client, buffer) @@ -53,18 +51,25 @@ return { }) ---@type lspconfig.options - local servers = plugin.servers or {} + local servers = opts.servers local capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()) require("mason-lspconfig").setup({ ensure_installed = vim.tbl_keys(servers) }) require("mason-lspconfig").setup_handlers({ function(server) - local opts = servers[server] or {} - opts.capabilities = capabilities - if not plugin.setup_server(server, opts) then - require("lspconfig")[server].setup(opts) + local server_opts = servers[server] or {} + server_opts.capabilities = capabilities + if opts.setup[server] then + if opts.setup[server](server, server_opts) then + return + end + elseif opts.setup["*"] then + if opts.setup["*"](server, server_opts) then + return + end end + require("lspconfig")[server].setup(server_opts) end, }) end, @@ -75,9 +80,9 @@ return { "jose-elias-alvarez/null-ls.nvim", event = "BufReadPre", dependencies = { "mason.nvim" }, - config = function() + opts = function() local nls = require("null-ls") - nls.setup({ + return { debug = false, sources = { nls.builtins.formatting.stylua, @@ -98,7 +103,7 @@ return { nls.builtins.formatting.beautysh, nls.builtins.diagnostics.shellcheck, }, - }) + } end, }, @@ -107,16 +112,18 @@ return { "williamboman/mason.nvim", cmd = "Mason", keys = { { "lM", "Mason", desc = "Mason" } }, - ensure_installed = { - "stylua", - "shellcheck", - "shfmt", - "flake8", + opts = { + ensure_installed = { + "stylua", + "shellcheck", + "shfmt", + "flake8", + }, }, - config = function(plugin) + config = function(plugin, opts) require("mason").setup() local mr = require("mason-registry") - for _, tool in ipairs(plugin.ensure_installed) do + for _, tool in ipairs(opts.ensure_installed) do local p = mr.get_package(tool) if not p:is_installed() then p:install() diff --git a/.config/nvim/lua/lazyvim/plugins/lualine.lua b/.config/nvim/lua/lazyvim/plugins/lualine.lua index 89e37dc..1c48052 100644 --- a/.config/nvim/lua/lazyvim/plugins/lualine.lua +++ b/.config/nvim/lua/lazyvim/plugins/lualine.lua @@ -1,118 +1,119 @@ return { - "nvim-lualine/lualine.nvim", - config = function () - local colors = { - red = "#ca1243", - grey = "#a0a1a7", - black = "#383a42", - white = "#f3f3f3", - light_green = "#83a598", - orange = "#fe8019", - green = "#8ec07c", - } + "nvim-lualine/lualine.nvim", + event = "VeryLazy", + opts = function() + local colors = { + red = "#ca1243", + grey = "#a0a1a7", + black = "#383a42", + white = "#f3f3f3", + light_green = "#83a598", + orange = "#fe8019", + green = "#8ec07c", + } - -- Put proper separators and gaps between components in sections - local function process_sections(sections) - for name, section in pairs(sections) do - local left = name:sub(9, 10) < "x" - for pos = 1, name ~= "lualine_z" and #section or #section - 1 do - table.insert(section, pos * 2, { empty, color = { fg = colors.white, bg = colors.white } }) - end - for id, comp in ipairs(section) do - if type(comp) ~= "table" then - comp = { comp } - section[id] = comp - end - comp.separator = left and { right = "" } or { left = "" } - end - end - return sections - end + -- Put proper separators and gaps between components in sections + local function process_sections(sections) + for name, section in pairs(sections) do + local left = name:sub(9, 10) < "x" + for pos = 1, name ~= "lualine_z" and #section or #section - 1 do + table.insert(section, pos * 2, { empty, color = { fg = colors.white, bg = colors.white } }) + end + for id, comp in ipairs(section) do + if type(comp) ~= "table" then + comp = { comp } + section[id] = comp + end + comp.separator = left and { right = "" } or { left = "" } + end + end + return sections + end - local function search_result() - if vim.v.hlsearch == 0 then - return '' - end - local last_search = vim.fn.getreg('/') - if not last_search or last_search == '' then - return '' - end - local searchcount = vim.fn.searchcount { maxcount = 9999 } - return last_search .. '(' .. searchcount.current .. '/' .. searchcount.total .. ')' - -- return "" - end + local function search_result() + if vim.v.hlsearch == 0 then + return "" + end + local last_search = vim.fn.getreg("/") + if not last_search or last_search == "" then + return "" + end + local searchcount = vim.fn.searchcount({ maxcount = 9999 }) + return last_search .. "(" .. searchcount.current .. "/" .. searchcount.total .. ")" + end - local function modified() - if vim.bo.modified then - return "+" - elseif vim.bo.modifiable == false or vim.bo.readonly == true then - return "-" - end - return "" - end + local function modified() + if vim.bo.modified then + return "+" + elseif vim.bo.modifiable == false or vim.bo.readonly == true then + return "-" + end + return "" + end - local status_ok, navic = pcall(require, "nvim-navic") - if not status_ok then - print("navic error!") - return - end - - require("lualine").setup({ - options = { - theme = "gruvbox", - component_separators = "", - section_separators = { left = "", right = "" }, - }, - sections = process_sections({ - lualine_a = { "mode" }, - lualine_b = { - "branch", - "diff", - { - "diagnostics", - source = { "nvim" }, - sections = { "error" }, - diagnostics_color = { error = { bg = colors.red, fg = colors.white } }, - }, - { - "diagnostics", - source = { "nvim" }, - sections = { "warn" }, - diagnostics_color = { warn = { bg = colors.orange, fg = colors.white } }, - }, - { "filename", file_status = false, path = 1 }, - { modified, color = { bg = colors.red } }, - { - "%w", - cond = function() - return vim.wo.previewwindow - end, - }, - { - "%r", - cond = function() - return vim.bo.readonly - end, - }, - { - "%q", - cond = function() - return vim.bo.buftype == "quickfix" - end, - }, - }, - lualine_c = { - { navic.get_location, cond = navic.is_available }, - }, - lualine_x = {}, - -- lualine_y = { search_result, 'filetype' }, - lualine_y = { "filetype " }, - lualine_z = { "%l:%c", "%p%%/%L" }, - }), - inactive_sections = { - lualine_c = { "%f %y %m" }, - lualine_x = {}, - }, - }) - end, + return { + options = { + theme = "auto", + globalstatus = true, + disabled_filetypes = { statusline = { "dashboard", "lazy", "alpha" } }, + }, + sections = process_sections({ + lualine_a = { "mode" }, + lualine_b = { + "branch", + "diff", + { + "diagnostics", + source = { "nvim" }, + sections = { "error" }, + diagnostics_color = { error = { bg = colors.red, fg = colors.white } }, + }, + { + "diagnostics", + source = { "nvim" }, + sections = { "warn" }, + diagnostics_color = { warn = { bg = colors.orange, fg = colors.white } }, + }, + { "filename", file_status = false, path = 1 }, + { modified, color = { bg = colors.red } }, + { + "%w", + cond = function() + return vim.wo.previewwindow + end, + }, + { + "%r", + cond = function() + return vim.bo.readonly + end, + }, + { + "%q", + cond = function() + return vim.bo.buftype == "quickfix" + end, + }, + }, + lualine_c = { + { + function() + return require("nvim-navic").get_location() + end, + cond = function() + return package.loaded["nvim-navic"] and require("nvim-navic").is_available() + end, + }, + }, + lualine_x = {}, + -- lualine_y = { search_result, 'filetype' }, + lualine_y = { "filetype " }, + lualine_z = { "%l:%c", "%p%%/%L" }, + }), + inactive_sections = { + lualine_c = { "%f %y %m" }, + lualine_x = {}, + }, + } + end, } diff --git a/.config/nvim/lua/lazyvim/plugins/noice.lua b/.config/nvim/lua/lazyvim/plugins/noice.lua index 1daaeae..1e97df6 100644 --- a/.config/nvim/lua/lazyvim/plugins/noice.lua +++ b/.config/nvim/lua/lazyvim/plugins/noice.lua @@ -2,7 +2,7 @@ return { { "folke/noice.nvim", event = "VeryLazy", - config = { + opts = { lsp = { override = { ["vim.lsp.util.convert_input_to_markdown_lines"] = true, diff --git a/.config/nvim/lua/lazyvim/plugins/snippets.lua b/.config/nvim/lua/lazyvim/plugins/snippets.lua index 7e7d1c2..0259b6f 100644 --- a/.config/nvim/lua/lazyvim/plugins/snippets.lua +++ b/.config/nvim/lua/lazyvim/plugins/snippets.lua @@ -1,30 +1,41 @@ return { - { - "L3MON4D3/LuaSnip", - dependencies = { - "rafamadriz/friendly-snippets", - config = function() - require("luasnip.loaders.from_vscode").lazy_load() - end, - }, - config = { - history = true, - delete_check_events = "TextChanged", - }, - -- stylua: ignore - keys = { - { - "", - function() - return require("luasnip").jumpable(1) and "luasnip-jump-next" or "" - end, - expr = true, remap = true, silent = true, mode = "i", - }, - { "", function() require("luasnip").jump(1) end, mode = "s" }, - { "", function() require("luasnip").jump(-1) end, mode = { "i", "s" } }, - }, - }, - { - "rafamadriz/friendly-snippets", -- collection of useful snippets - }, + { + "L3MON4D3/LuaSnip", + dependencies = { + "rafamadriz/friendly-snippets", + config = function() + require("luasnip.loaders.from_vscode").lazy_load() + end, + }, + opts = { + history = true, + delete_check_events = "TextChanged", + }, + keys = { + { + "", + function() + return require("luasnip").jumpable(1) and "luasnip-jump-next" or "" + end, + expr = true, + remap = true, + silent = true, + mode = "i", + }, + { + "", + function() + require("luasnip").jump(1) + end, + mode = "s", + }, + { + "", + function() + require("luasnip").jump(-1) + end, + mode = { "i", "s" }, + }, + }, + }, } diff --git a/.config/nvim/lua/lazyvim/plugins/telescope.lua b/.config/nvim/lua/lazyvim/plugins/telescope.lua index 089a720..d5374b0 100644 --- a/.config/nvim/lua/lazyvim/plugins/telescope.lua +++ b/.config/nvim/lua/lazyvim/plugins/telescope.lua @@ -51,7 +51,7 @@ return { { ",", "Telescope buffers show_all_buffers=true", desc = "Switch Buffer" }, { ":", "Telescope command_history", desc = "Command History" }, }, - config = { + opts = { defaults = { prompt_prefix = " ", selection_caret = " ", diff --git a/.config/nvim/lua/lazyvim/plugins/trouble.lua b/.config/nvim/lua/lazyvim/plugins/trouble.lua index 78180f6..c152530 100644 --- a/.config/nvim/lua/lazyvim/plugins/trouble.lua +++ b/.config/nvim/lua/lazyvim/plugins/trouble.lua @@ -2,7 +2,7 @@ return { { "folke/trouble.nvim", cmd = { "TroubleToggle", "Trouble" }, - config = { use_diagnostic_signs = true }, + opts = { use_diagnostic_signs = true }, keys = { { "lt", "TroubleToggle document_diagnostics", desc = "Document Diagnostics (Trouble)" }, { "lT", "TroubleToggle workspace_diagnostics", desc = "Workspace Diagnostics (Trouble)" }, diff --git a/.config/nvim/lua/lazyvim/plugins/utility.lua b/.config/nvim/lua/lazyvim/plugins/utility.lua index b6d46fe..2bcfb21 100644 --- a/.config/nvim/lua/lazyvim/plugins/utility.lua +++ b/.config/nvim/lua/lazyvim/plugins/utility.lua @@ -1,3 +1,5 @@ +local icons = require("lazyvim.config.icons") + return { { "nvim-lua/plenary.nvim", @@ -22,49 +24,40 @@ return { }, { "rcarriga/nvim-notify", - config = function() - local icons = require("lazyvim.config.icons") - require("notify").setup({ - -- Animation style (see below for details) - stages = "fade_in_slide_out", + opts = { + -- Animation style (see below for details) + stages = "fade_in_slide_out", - -- Render function for notifications. See notify-render() - render = "default", + -- Render function for notifications. See notify-render() + render = "default", - -- Default timeout for notifications - timeout = 2000, + -- Default timeout for notifications + timeout = 2000, - -- For stages that change opacity this is treated as the highlight behind the window - -- Set this to either a highlight group or an RGB hex value e.g. "#000000" - background_colour = "Normal", + -- For stages that change opacity this is treated as the highlight behind the window + -- Set this to either a highlight group or an RGB hex value e.g. "#000000" + background_colour = "Normal", - -- Minimum width for notification windows - minimum_width = 10, + -- Minimum width for notification windows + minimum_width = 10, - -- Icons for the different levels - icons = { - ERROR = icons.diagnostics.Error, - WARN = icons.diagnostics.Warning, - INFO = icons.diagnostics.Information, - DEBUG = icons.ui.Bug, - TRACE = icons.ui.Pencil, - }, - }) - end, + -- Icons for the different levels + icons = { + ERROR = icons.diagnostics.Error, + WARN = icons.diagnostics.Warning, + INFO = icons.diagnostics.Information, + DEBUG = icons.ui.Bug, + TRACE = icons.ui.Pencil, + }, + }, }, { "echasnovski/mini.bufremove", - -- stylua: ignore - keys = { - { "bd", function() require("mini.bufremove").delete(0, false) end, desc = "Delete Buffer" }, - { "bD", function() require("mini.bufremove").delete(0, true) end, desc = "Delete Buffer (Force)" }, - }, - }, - { - "lewis6991/impatient.nvim", - config = function() - require("impatient").enable_profile() - end, + -- stylua: ignore + keys = { + { "bd", function() require("mini.bufremove").delete(0, false) end, desc = "Delete Buffer" }, + { "bD", function() require("mini.bufremove").delete(0, true) end, desc = "Delete Buffer (Force)" }, + }, }, { "ghillb/cybu.nvim", @@ -111,6 +104,7 @@ return { }, { "lukas-reineke/indent-blankline.nvim", + event = "BufReadPre", config = function() vim.g.indent_blankline_buftype_exclude = { "terminal", "nofile" } vim.g.indent_blankline_filetype_exclude = { @@ -222,4 +216,16 @@ return { }) end, }, + { + "SmiteshP/nvim-navic", + init = function() + vim.g.navic_silence = true + require("lazyvim.functions").on_attach(function(client, buffer) + if client.server_capabilities.documentSymbolProvider then + require("nvim-navic").attach(client, buffer) + end + end) + end, + opts = { separator = " ", highlight = true, depth_limit = 5 }, + }, }