Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Neovim v0.9 support #43

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ AstroUI provides a simple API for configuring and setting up the user interface

## ⚡️ Requirements

- Neovim >= 0.9
- Neovim >= 0.10
- [astrocore][astrocore] (_optional_)

## 📦 Installation
Expand Down Expand Up @@ -51,6 +51,13 @@ require("astroui").setup({
{
-- Colorscheme set on startup, a string that is used with `:colorscheme astrodark`
colorscheme = "astrodark",
-- Configure how folding works
folding = {
-- whether a buffer should have folding can be true/false for global enable/disable or fun(bufnr:integer):boolean
enabled = function(bufnr) return require("astrocore.buffer").is_valid(bufnr) end,
-- a priority list of fold methods to try using, available methods are "lsp", "treesitter", and "indent"
methods = { "lsp", "treesitter", "indent" },
},
-- Override highlights in any colorscheme
-- Keys can be:
-- `init`: table of highlights to apply to all colorschemes
Expand Down
20 changes: 20 additions & 0 deletions lua/astroui/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@
---```
---@field file_icon AstroUIFileIconHighlights?

---@alias AstroUIFoldingMethod
---| "indent" # indentation based folding (`:h fold-indent`)
---| "lsp" # LSP based folding (`:h vim.lsp.foldexpr`)
---| "treesitter" # Treesitter based folding (`:h vim.treesitter.foldexpr`)

---@class AstroUIFoldingOpts
---@field enabled (boolean|fun(bufnr:integer):boolean)? whether folding should be enabled in a buffer or not
---@field methods AstroUIFoldingMethod[]? a table of folding methods in priority order

---@class AstroUILazygitOpts
---@field theme_path string? the path to the storage location for the lazygit theme configuration
---@field theme table<string|number,{fg:string?,bg:string?,bold:boolean?,reverse:boolean?,underline:boolean?,strikethrough:boolean?}>? table of highlight groups to use for the lazygit theme
Expand Down Expand Up @@ -131,6 +140,16 @@
---colorscheme = "astrodark"
---```
---@field colorscheme string?
---Configure how folding works
---Example:
---
---```lua
---folding = {
--- enabled = function(bufnr) return require("astrocore.buffer").is_valid(bufnr) end,
--- methods = { "lsp", "treesitter", "indent" },
---}
---```
---@field folding AstroUIFoldingOpts|false?
---Override highlights in any colorscheme
---Keys can be:
--- `init`: table of highlights to apply to all colorschemes
Expand Down Expand Up @@ -218,6 +237,7 @@
---@type AstroUIOpts
local M = {
colorscheme = nil,
folding = {},
highlights = {},
icons = {},
text_icons = {},
Expand Down
116 changes: 116 additions & 0 deletions lua/astroui/folding.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
-- AstroNvim Folding Utilities
--
-- Helper functions for configuring folding in Neovim
--
-- This module can be loaded with `local astro = require "astroui.folding"`
--
-- copyright 2024
-- license GNU General Public License v3.0
local M = {}

local config = require("astroui").config.folding

local is_setup = false
local lsp_bufs = {}

local fold_methods = {
lsp = function(lnum, bufnr)
if lsp_bufs[bufnr or vim.api.nvim_get_current_buf()] then return vim.lsp.foldexpr(lnum) end
end,
treesitter = function(lnum, bufnr)
if vim.bo.filetype and pcall(vim.treesitter.get_parser, bufnr) then return vim.treesitter.foldexpr(lnum) end
end,
indent = function(lnum, bufnr)
if not lnum then lnum = vim.v.lnum end
if not bufnr then bufnr = vim.api.nvim_get_current_buf() end
return vim.api.nvim_buf_get_lines(bufnr, lnum - 1, lnum, false)[1]:match "^%s*$" and "="
or math.floor(vim.fn.indent(lnum) / vim.bo[bufnr].shiftwidth)
end,
}

--- Check if folding is enabled for a buffer
---@param bufnr integer The buffer to check (defaults to current buffer)
---@return boolean enabled whether or not the buffer is enabled for folding
function M.is_enabled(bufnr)
local enabled = config and config.enabled
if type(enabled) == "function" then enabled = enabled(bufnr or vim.api.nvim_get_current_buf()) end
return enabled == true
end

--- A fold expression for doing LSP and Treesitter based folding
---@param lnum? integer the current line number
---@return string foldlevel the calculated fold level
function M.foldexpr(lnum)
if not is_setup then M.setup() end
local bufnr = vim.api.nvim_get_current_buf()
if M.is_enabled(bufnr) then
for _, method in ipairs(config and config.methods or {}) do
local fold_method = fold_methods[method]
if fold_method then
local fold = fold_method(lnum, bufnr)
if fold then return fold end
end
end
end
-- fallback to no folds
return "0"
end

--- Get the current folding status of a given buffer
---@param bufnr? integer the buffer to check the folding status for
function M.info(bufnr)
if not bufnr then bufnr = vim.api.nvim_get_current_buf() end
local lines = {}
local enabled = M.is_enabled(bufnr)
table.insert(lines, "Buffer folding is **" .. (enabled and "Enabled" or "Disabled") .. "**\n")
local methods = config and config.methods or {}
for _, method in pairs(methods) do
local fold_method = fold_methods[method]
local available = "Unavailable"
local surround = ""
if not fold_method then
available = "*Invalid*"
elseif fold_method(1, bufnr) then
available = "Available"
if enabled then
surround = "**"
enabled = false
end
end
table.insert(lines, ("%s`%s`: %s%s"):format(surround, method, available, surround))
end
table.insert(lines, "```lua")
table.insert(lines, "methods = " .. vim.inspect(methods))
table.insert(lines, "```")
require("astrocore").notify(table.concat(lines, "\n"), vim.log.levels.INFO, { title = "AstroNvim Folding" })
end

function M.setup()
vim.api.nvim_create_user_command("AstroFoldInfo", function() M.info() end, { desc = "Display folding information" })
-- TODO: remove check when dropping support for Neovim v0.10
if vim.lsp.foldexpr then
local augroup = vim.api.nvim_create_augroup("astroui_foldexpr", { clear = true })
vim.api.nvim_create_autocmd("LspAttach", {
desc = "Monitor attached LSP clients with fold providers",
group = augroup,
callback = function(args)
local client = assert(vim.lsp.get_client_by_id(args.data.client_id))
if client.supports_method "textDocument/foldingRange" then lsp_bufs[args.buf] = true end
end,
})
vim.api.nvim_create_autocmd("LspDetach", {
group = augroup,
desc = "Safely remove LSP folding providers when language servers detach",
callback = function(args)
if not vim.api.nvim_buf_is_valid(args.buf) then return end
for _, client in pairs(vim.lsp.get_clients { bufnr = args.buf }) do
if client.id ~= args.data.client_id and client.supports_method "textDocument/foldingRange" then return end
end
lsp_bufs[args.buf] = nil
end,
})
end
is_setup = true
end

return M
5 changes: 0 additions & 5 deletions lua/astroui/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@ function M.setup(opts)
end,
})

local colorscheme = M.config.colorscheme
if colorscheme and not pcall(vim.cmd.colorscheme, colorscheme) then
vim.notify(("Error setting up colorscheme: `%s`"):format(colorscheme), vim.log.levels.ERROR, { title = "AstroUI" })
end

require("astroui.lazygit").setup()
end

Expand Down
4 changes: 2 additions & 2 deletions lua/astroui/lazygit.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ function M.setup()

vim.api.nvim_create_autocmd("User", {
pattern = "AstroColorScheme",
callback = M.update_config,
desc = "Update lazygit theme configuration when changing colorscheme",
group = vim.api.nvim_create_augroup("astroui_lazygit", { clear = true }),
desc = "Update lazygit theme configuration when changing colorscheme",
callback = M.update_config,
})
end

Expand Down
20 changes: 6 additions & 14 deletions lua/astroui/status/condition.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ local buf_matchers = {

--- A condition function if the buffer filetype,buftype,bufname match a pattern
---@param patterns table<BufMatcherKinds, BufMatcherPatterns> the table of patterns to match
---@param bufnr integer? of the buffer to match (Default: 0 [current])
---@param op "and"|"or"? whether or not to require all pattern types to match or any (Default: "or")
---@param bufnr? integer of the buffer to match (Default: 0 [current])
---@param op? "and"|"or" whether or not to require all pattern types to match or any (Default: "or")
---@return boolean # whether or not the buffer filetype,buftype,bufname match a pattern
-- @usage local heirline_component = { provider = "Example Provider", condition = function() return require("astroui.status").condition.buffer_matches { buftype = { "terminal" } } end }
function M.buffer_matches(patterns, bufnr, op)
Expand Down Expand Up @@ -75,7 +75,7 @@ function M.is_hlsearch() return vim.v.hlsearch ~= 0 end
--- A condition function if showcmdloc is set to statusline
---@return boolean # whether or not statusline showcmd is enabled
-- @usage local heirline_component = { provider = "Example Provider", condition = require("astroui.status").condition.is_statusline_showcmd }
function M.is_statusline_showcmd() return vim.fn.has "nvim-0.9" == 1 and vim.opt.showcmdloc:get() == "statusline" end
function M.is_statusline_showcmd() return vim.opt.showcmdloc:get() == "statusline" end

--- A condition function if the current file is in a git repo
---@param bufnr table|integer a buffer number to check the condition for, a table with bufnr property, or nil to get the current buffer
Expand Down Expand Up @@ -134,12 +134,7 @@ function M.has_diagnostics(bufnr)
if type(bufnr) == "table" then bufnr = bufnr.bufnr end
if not bufnr then bufnr = 0 end
if package.loaded["astrocore"] and require("astrocore").config.features.diagnostics_mode == 0 then return false end
-- TODO: remove when dropping support for neovim 0.9
if vim.diagnostic.count then
return vim.tbl_contains(vim.diagnostic.count(bufnr), function(v) return v > 0 end, { predicate = true })
else
return #vim.diagnostic.get(bufnr) > 0
end
return vim.tbl_contains(vim.diagnostic.count(bufnr), function(v) return v > 0 end, { predicate = true })
end

--- A condition function if there is a defined filetype
Expand Down Expand Up @@ -182,11 +177,8 @@ function M.lsp_attached(bufnr)
if type(bufnr) == "table" then bufnr = bufnr.bufnr end
if not bufnr then bufnr = 0 end
return (
-- HACK: Check for lsp utilities loaded first, get_active_clients seems to have a bug if called too early (tokyonight colorscheme seems to be a good way to expose this for some reason)
package.loaded["astrolsp"]
-- TODO: remove get_active_clients when dropping support for Neovim 0.9
---@diagnostic disable-next-line: deprecated
and next((vim.lsp.get_clients or vim.lsp.get_active_clients) { bufnr = bufnr }) ~= nil
-- HACK: Check for lsp utilities loaded first, get_clients seems to have a bug if called too early (tokyonight colorscheme seems to be a good way to expose this for some reason)
package.loaded["astrolsp"] and next(vim.lsp.get_clients { bufnr = bufnr }) ~= nil
)
or (package.loaded["conform"] and next(require("conform").list_formatters(bufnr)) ~= nil)
or (package.loaded["lint"] and next(require("lint")._resolve_linter_by_ft(vim.bo[bufnr].filetype or "")) ~= nil)
Expand Down
3 changes: 1 addition & 2 deletions lua/astroui/status/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ end
---@return function # The Heirline init function
-- @usage local heirline_component = { init = require("astroui.status").init.update_events { "BufEnter", { "User", pattern = "LspProgressUpdate" } } }
function M.update_events(opts)
-- TODO: remove check after dropping support for Neovim v0.9
if not (vim.islist or vim.tbl_islist)(opts) then opts = { opts } end
if not vim.islist(opts) then opts = { opts } end
---@cast opts AstroUIUpdateEvent[]
return function(self)
if not rawget(self, "once") then
Expand Down
23 changes: 3 additions & 20 deletions lua/astroui/status/provider.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ local M = {}
local astro = require "astrocore"
local extend_tbl = astro.extend_tbl
local is_available = astro.is_available
local luv = vim.uv or vim.loop -- TODO: REMOVE WHEN DROPPING SUPPORT FOR Neovim v0.9

local ui = require "astroui"
local config = assert(ui.config.status)
Expand All @@ -38,14 +37,6 @@ end
-- local function to resolve the first sign in the signcolumn
-- specifically for usage when `signcolumn=number`
local function resolve_sign(bufnr, lnum)
--- TODO: remove when dropping support for Neovim v0.9
if vim.fn.has "nvim-0.10" == 0 then
for _, sign in ipairs(vim.fn.sign_getplaced(bufnr, { group = "*", lnum = lnum })[1].signs) do
local defined = vim.fn.sign_getdefined(sign.name)[1]
if defined then return defined end
end
end

local row = lnum - 1
local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, -1, { row, 0 }, { row, -1 }, { details = true, type = "sign" })
local ret
Expand Down Expand Up @@ -462,13 +453,7 @@ function M.diagnostics(opts)
if not opts or not opts.severity then return end
return function(self)
local bufnr = self and self.bufnr or 0
local count
-- TODO: remove when dropping support for neovim 0.9
if vim.diagnostic.count then
count = vim.diagnostic.count(bufnr)[vim.diagnostic.severity[opts.severity]] or 0
else
count = #vim.diagnostic.get(bufnr, opts.severity and { severity = vim.diagnostic.severity[opts.severity] })
end
local count = vim.diagnostic.count(bufnr)[vim.diagnostic.severity[opts.severity]] or 0
return status_utils.stylize(count ~= 0 and tostring(count) or "", opts)
end
end
Expand All @@ -486,7 +471,7 @@ function M.lsp_progress(opts)
if astrolsp_avail and astrolsp.lsp_progress then
_, status = next(astrolsp.lsp_progress)
end
return status_utils.stylize(status and (spinner[math.floor(luv.hrtime() / 12e7) % #spinner + 1] .. table.concat({
return status_utils.stylize(status and (spinner[math.floor(vim.uv.hrtime() / 12e7) % #spinner + 1] .. table.concat({
status.title or "",
status.message or "",
status.percentage and "(" .. status.percentage .. "%)" or "",
Expand All @@ -511,9 +496,7 @@ function M.lsp_client_names(opts)
return function(self)
local bufnr = self and self.bufnr or 0
local buf_client_names = {}
-- TODO: remove get_active_clients when dropping support for Neovim 0.9
---@diagnostic disable-next-line: deprecated
for _, client in pairs((vim.lsp.get_clients or vim.lsp.get_active_clients) { bufnr = bufnr }) do
for _, client in pairs(vim.lsp.get_clients { bufnr = bufnr }) do
if client.name == "null-ls" and opts.integrations.null_ls then
local null_ls_sources = {}
local ft = vim.bo[bufnr].filetype
Expand Down
9 changes: 1 addition & 8 deletions lua/astroui/status/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ end
---@param color function|string|table the color to use as the separator foreground/component background
---@param component table the component to surround
---@param condition boolean|function the condition for displaying the surrounded component
---@param update AstroUIUpdateEvents? control updating of separators, either a list of events or true to update freely
---@param update? AstroUIUpdateEvents control updating of separators, either a list of events or true to update freely
---@return table # the new surrounded component
function M.surround(separator, color, component, condition, update)
local function surround_color(self)
Expand Down Expand Up @@ -255,13 +255,6 @@ function M.statuscolumn_clickargs(self, minwid, clicks, button, mods)
if not self.signs then self.signs = {} end
args.sign = self.signs[args.char]
if not args.sign then -- update signs if not found on first click
---TODO: remove when dropping support for Neovim v0.9
if vim.fn.has "nvim-0.10" == 0 then
for _, sign_def in ipairs(assert(vim.fn.sign_getdefined())) do
if sign_def.text then self.signs[sign_def.text:gsub("%s", "")] = sign_def end
end
end

if not self.bufnr then self.bufnr = vim.api.nvim_get_current_buf() end
local row = args.mousepos.line - 1
for _, extmark in
Expand Down
Loading