sync develop and main (#68)

* healthcheck: refactoring, remove deprecation wanings (#35)

* refactor(checkhealth): remove deprecation warnings, complete rewrite

* refactor(checkhealth): rename util file

* style(healthchecker): reformat lua in vim file

* refactor(health): move all report function into table

* add editorconfig (#36)

* refactor of public plugin's api (#37)

* refactor: move all plugin functionality to init.lua

* fix(commands): now it uses correct module paths

* refactor(config): change way how it handles options

* refactor(gotests): use correct config, change way how deps required, fix some typos

* fix(healthchecker): use correct config

* refactor(iferr): change api

* refactor(impl): change api

* refactor(installer): change api

* refactor(struct_tags): change way of importting deps

* refactor(struct_tags): rename M to struct_tags

* run stylua

* refactor(dap): make it all in one file, and make some refactoring

* refactor(_utils): change way how it organizes

* fix: use new _utils api

* refactor(_utils.health): reorganize module

* refactor(_utils.ts): some renameing, moving requires lines

* run stylua

* update tooling (#38)

* chore: delete pre-commit

* chore: switch from makefile to taskfile

* chore(ci): update and add one more linter

* chore(editorconfig): add config for Go

* chore(editorconfig): remove max_line_length

* fix: editorconfig-check on README.md

* feat: run tests independent from user's nvim config

* remove editorconfig-checker

* fix(config): now it not removes .setup() from itself after calling
.setup()

* fix(config): now it works correctly

* chore: update taskfile, and linter config

* feat(config): make it optional to call .setup()

* run tests independent of user nvim setup (#39)

* chore(lua_ls): now lua_ls knows about testing functions

* spec: change way how tests srtuctured

* test(config): refactor tests

* test: utils

* refactor(utils): remove not used function

* chore(ci): add test runner

* chore(ci): remove taskfile from deps

* fix: now it works

* fix(dap): now dlv uses cmd to run from config

* chore(ci): run tests on many versions of nvim

* refactor: commands runner (#42)

* feat(utils): first impl of own commands runner

* refactor(gotests): uses own runner instead of vendored

* refactor(utils): back to plenary.job

* refactor(gotests): use new runner, clean code

* fix(runner): now it returns output correctly

* refactor(iferr): use vim.system

i have tried to use _utils.runner, but i can't figure out how to make `< file.go` for the command

* refactor(impl): use new runner

* refactor(installer): use new runner

* refactor(struct_tags): use new runner

* refactor: commands such as :GoGet runs with new runner

* refactor: throw errors in more lua way, i think

* refactor(utils): notify now has title

* refactor: use more correct way of notifying

* refactor(runner): write error message on error

* add ability for setting custom tools options (#44)

* feat(gotests): add custom templates support

* feat(struct_tags): add support for custom `transform` option

* fix(health): check if bin is installed, and added message about treesitter parser

* fix: fix iferr config (#56)

* Add support for named tests (#50)

* fix(typo): README.md (#47)

* feat: add support for named tests

* test

* tags in table

* debug installer msg

* test

* hardcoded @develop

* get gotests tag from setup()

* update readme

* store install tag in urls table

* removed gotests tag

* update README.md

* remove urls installer index reference

* remove named arg from add_test()

* .

* update README.md

* update README.md

---------

Co-authored-by: Steve M <gearcog@users.noreply.github.com>

* reformat .editorconfig config

* refactor(api)!: mave tags and gotests api into their sub tables

* add help file, and docs (#59)

* idk how good this idea is

* this could be working but i still cant figure out how to run it

* ignore tags that mini.doc gens, but why?

* chore(taskfile): force exiting after tests

because i got infinit ci

* chore(ci): add more nvim versions to run on

* chore: update taskfile

* feat: add docs generator

* docs: its only begining

* refactor: update docgen script

* docs: write some more

* docs(config): update

* docs: update readme

* language

* hope it would work

* what about that?

* maybe this would work?

* update md

* upd

* WHY DOESNT IT WORKING

* idk by but 0.9.3 just fails the ci, so i deleted it from suite

* again update, why does markdown not work in embeded html

* maybe it can help?

* upd

* again update

* kinda fix

* fix: formatting

* again some updating

* some readme updating

* fix, this shouldnt be in repo

* i finnaly undertood how to fix this fking skill issue

* fix(struct_tags): typo

* refactor(docs): change the order in generated file

* docs: install deps

* refactor(scripts): rename doc-gen script

* docs(impl): write docs

* docs(dap): add doc

* stylua .

* docs(struct_tags): add doc

* docs(gotests): add docs

* docs(iferr): add docs

* docs(comment): add doc

* update CONTRIBUTING.md

* docs(README): talk about `develop` branch

* docs: update README.md

* refactor(health): keep in mind new way of health check (#63)

* feat: add logger (#64)

* refactor(health): keep in mind new way of health check (#63)

* feat(log): add logger module

* refactor(utils): remove unused code

* refactor(log, utils): get plugin name from config

* refactor(logger): add some type annotations

* refactor(utils): log notifications

* feat: LOGGER™

* feat(config): TYPES

* refactor(log): dont give a thing about var that is not even declared

* feat(log): add easy way to open log

* refactor(log): some types

* update types

* docs: regen

* fix(log): make setting log level by config work

* feat(iferr): write error to log file if occur

* feat(gotests): add logger

* add deprecation message (#67)

---------

Co-authored-by: Arne Van Maele <93863978+arnevm123@users.noreply.github.com>
Co-authored-by: Alex <49870662+ysomad@users.noreply.github.com>
Co-authored-by: Steve M <gearcog@users.noreply.github.com>
This commit is contained in:
Smirnov Oleksandr 2024-06-15 12:43:06 +03:00 committed by GitHub
parent ac27f4b679
commit a995af3415
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 1594 additions and 737 deletions

View file

@ -1,17 +0,0 @@
return {
---@param lib string
---@return boolean
lualib_is_found = function(lib)
local is_found, _ = pcall(require, lib)
return is_found
end,
---@param bin string
---@return boolean
binary_is_found = function(bin)
if vim.fn.executable(bin) == 1 then
return true
end
return false
end,
}

View file

@ -1,40 +0,0 @@
---Run any go commands like `go generate`, `go get`, `go mod`
---@param cmd string
---@param ... string|string[]
return function(cmd, ...)
local Job = require "plenary.job"
local c = require("gopher.config").config.commands
local u = require "gopher._utils"
local args = { ... }
if #args == 0 then
u.notify("please provice any arguments", "error")
return
end
if cmd == "generate" and #args == 1 and args[1] == "%" then
args[1] = vim.fn.expand "%" ---@diagnostic disable-line: missing-parameter
elseif cmd == "get" then
for i, arg in ipairs(args) do
---@diagnostic disable-next-line: param-type-mismatch
local m = string.match(arg, "^https://(.*)$") or string.match(arg, "^http://(.*)$") or arg
table.remove(args, i)
table.insert(args, i, m)
end
end
local cmd_args = vim.list_extend({ cmd }, args) ---@diagnostic disable-line: missing-parameter
Job:new({
command = c.go,
args = cmd_args,
on_exit = function(_, retval)
if retval ~= 0 then
u.notify("command 'go " .. unpack(cmd_args) .. "' exited with code " .. retval, "error")
u.notify(cmd .. " " .. unpack(cmd_args), "debug")
return
end
u.notify("go " .. cmd .. " was success runned", "info")
end,
}):start()
end

View file

@ -0,0 +1,33 @@
local h = vim.health or require "health"
local health = {}
health.start = h.start or h.report_start
health.ok = h.ok or h.report_ok
health.warn = h.warn or h.report_warn
health.error = h.error or h.report_error
health.info = h.info or h.report_info
---@param module string
---@return boolean
function health.is_lualib_found(module)
local is_found, _ = pcall(require, module)
return is_found
end
---@param bin string
---@return boolean
function health.is_binary_found(bin)
if vim.fn.executable(bin) == 1 then
return true
end
return false
end
---@param ft string
---@return boolean
function health.is_treesitter_parser_available(ft)
local ok, parser = pcall(vim.treesitter.get_parser, 0, ft)
return ok and parser ~= nil
end
return health

View file

@ -1,48 +1,34 @@
---@diagnostic disable: param-type-mismatch
return {
---@param t table
---@return boolean
empty = function(t)
if t == nil then
return true
end
local c = require "gopher.config"
local log = require "gopher._utils.log"
local utils = {}
return next(t) == nil
end,
---@param msg string
---@param lvl number
function utils.deferred_notify(msg, lvl)
vim.defer_fn(function()
vim.notify(msg, lvl, {
title = c.___plugin_name,
})
log.debug(msg)
end, 0)
end
---@param s string
---@return string
rtrim = function(s)
local n = #s
while n > 0 and s:find("^%s", n) do
n = n - 1
end
---@param msg string
---@param lvl? number
function utils.notify(msg, lvl)
lvl = lvl or vim.log.levels.INFO
vim.notify(msg, lvl, {
title = c.___plugin_name,
})
log.debug(msg)
end
return s:sub(1, n)
end,
-- safe require
---@param module string module name
function utils.sreq(module)
local ok, m = pcall(require, module)
assert(ok, string.format("gopher.nvim dependency error: %s not installed", module))
return m
end
---@param msg string
---@param lvl string|integer
notify = function(msg, lvl)
local l
if lvl == "error" or lvl == 4 then
l = vim.log.levels.ERROR
elseif lvl == "info" or lvl == 2 then
l = vim.log.levels.INFO
elseif lvl == "debug" or lvl == 1 then
l = vim.log.levels.DEBUG
end
vim.defer_fn(function()
vim.notify(msg, l)
end, 0)
end,
---safe require
---@param name string module name
sreq = function(name)
local ok, m = pcall(require, name)
assert(ok, string.format("gopher.nvim dependency error: %s not installed", name))
return m
end,
}
return utils

170
lua/gopher/_utils/log.lua Normal file
View file

@ -0,0 +1,170 @@
-- thanks https://github.com/tjdevries/vlog.nvim
-- and https://github.com/williamboman/mason.nvim
-- for the code i have stolen(or have inspected by idk)
local c = require "gopher.config"
---@class Gopher.Logger
---@field get_outfile fun():string
---@field trace fun(...)
---@field fmt_trace fun(...)
---@field debug fun(...)
---@field fmt_debug fun(...)
---@field info fun(...)
---@field fmt_info fun(...)
---@field warn fun(...)
---@field fmt_warn fun(...)
---@field error fun(...)
---@field fmt_error fun(...)
local config = {
-- Name of the plugin. Prepended to log messages
name = c.___plugin_name,
-- Should print the output to neovim while running
-- values: 'sync','async',false
use_console = vim.env.GOPHER_VERBOSE_LOGS == "1",
-- Should highlighting be used in console (using echohl)
highlights = true,
-- Should write to a file
use_file = true,
-- Level configuration
modes = {
{ name = "trace", hl = "Comment", level = vim.log.levels.TRACE },
{ name = "debug", hl = "Comment", level = vim.log.levels.DEBUG },
{ name = "info", hl = "None", level = vim.log.levels.INFO },
{ name = "warn", hl = "WarningMsg", level = vim.log.levels.WARN },
{ name = "error", hl = "ErrorMsg", level = vim.log.levels.ERROR },
},
-- Can limit the number of decimals displayed for floats
float_precision = 0.01,
}
---@type Gopher.Logger
---@diagnostic disable-next-line: missing-fields
local log = {}
---@return string
function log.get_outfile()
return table.concat {
(vim.fn.has "nvim-0.8.0" == 1) and vim.fn.stdpath "log" or vim.fn.stdpath "cache",
("/%s.log"):format(config.name),
}
end
-- selene: allow(incorrect_standard_library_use)
local unpack = unpack or table.unpack
do
local round = function(x, increment)
increment = increment or 1
x = x / increment
return (x > 0 and math.floor(x + 0.5) or math.ceil(x - 0.5)) * increment
end
local tbl_has_tostring = function(tbl)
local mt = getmetatable(tbl)
return mt and mt.__tostring ~= nil
end
local make_string = function(...)
local t = {}
for i = 1, select("#", ...) do
local x = select(i, ...)
if type(x) == "number" and config.float_precision then
x = tostring(round(x, config.float_precision))
elseif type(x) == "table" and not tbl_has_tostring(x) then
x = vim.inspect(x)
else
x = tostring(x)
end
t[#t + 1] = x
end
return table.concat(t, " ")
end
local log_at_level = function(level_config, message_maker, ...)
-- Return early if we're below the current_log_level
--
-- the log level source get from config directly because otherwise it doesnt work
if level_config.level < c.log_level then
return
end
local nameupper = level_config.name:upper()
local msg = message_maker(...)
local info = debug.getinfo(2, "Sl")
local lineinfo = info.short_src .. ":" .. info.currentline
-- Output to console
if config.use_console then
local log_to_console = function()
local console_string =
string.format("[%-6s%s] %s: %s", nameupper, os.date "%H:%M:%S", lineinfo, msg)
if config.highlights and level_config.hl then
vim.cmd(string.format("echohl %s", level_config.hl))
end
local split_console = vim.split(console_string, "\n")
for _, v in ipairs(split_console) do
local formatted_msg = string.format("[%s] %s", config.name, vim.fn.escape(v, [["\]]))
---@diagnostic disable-next-line: param-type-mismatch
local ok = pcall(vim.cmd, string.format([[echom "%s"]], formatted_msg))
if not ok then
vim.api.nvim_out_write(msg .. "\n")
end
end
if config.highlights and level_config.hl then
vim.cmd "echohl NONE"
end
end
if config.use_console == "sync" and not vim.in_fast_event() then
log_to_console()
else
vim.schedule(log_to_console)
end
end
-- Output to log file
if config.use_file then
local fp = assert(io.open(log.get_outfile(), "a"))
local str = string.format("[%-6s%s] %s: %s\n", nameupper, os.date(), lineinfo, msg)
fp:write(str)
fp:close()
end
end
for _, x in ipairs(config.modes) do
-- log.info("these", "are", "separated")
log[x.name] = function(...) ---@diagnostic disable-line: assign-type-mismatch
return log_at_level(x, make_string, ...)
end
-- log.fmt_info("These are %s strings", "formatted")
log[("fmt_%s"):format(x.name)] = function(...) ---@diagnostic disable-line: assign-type-mismatch
return log_at_level(x, function(...)
local passed = { ... }
local fmt = table.remove(passed, 1)
local inspected = {}
for _, v in ipairs(passed) do
if type(v) == "table" and tbl_has_tostring(v) then
table.insert(inspected, v)
else
table.insert(inspected, vim.inspect(v))
end
end
return string.format(fmt, unpack(inspected))
end, ...)
end
end
end
return log

View file

@ -0,0 +1,53 @@
local r = require "gopher._utils.runner"
local c = require("gopher.config").commands
local u = require "gopher._utils"
local gocmd = {}
---@param args string[]
---@return string[]
local function if_get(args)
for i, arg in ipairs(args) do
local m = string.match(arg, "^https://(.*)$") or string.match(arg, "^http://(.*)$") or arg
table.remove(args, i)
table.insert(args, i, m)
end
return args
end
---@param args unknown[]
---@return string[]
local function if_generate(args)
if #args == 1 and args[1] == "%" then
args[1] = vim.fn.expand "%"
end
return args
end
---@param subcmd string
---@param args string[]
---@return string[]|nil
function gocmd.run(subcmd, args)
if #args == 0 then
error "please provice any arguments"
end
if subcmd == "get" then
args = if_get(args)
end
if subcmd == "generate" then
args = if_generate(args)
end
return r.sync(c.go, {
args = { subcmd, unpack(args) },
on_exit = function(data, status)
if status ~= 0 then
error("gocmd failed: " .. data)
end
u.notify(c.go .. " " .. subcmd .. " successful runned")
end,
})
end
return gocmd

View file

@ -0,0 +1,33 @@
local Job = require "plenary.job"
local runner = {}
---@class gopher.RunnerOpts
---@field args? string[]
---@field cwd? string?
---@field on_exit? fun(data:string, status:number)
---@param cmd string
---@param opts gopher.RunnerOpts
---@return string[]|nil
function runner.sync(cmd, opts)
local output
Job:new({
command = cmd,
args = opts.args,
cwd = opts.cwd,
on_stderr = function(_, data)
vim.print(data)
end,
on_exit = function(data, status)
output = data:result()
vim.schedule(function()
if opts.on_exit then
opts.on_exit(output, status)
end
end)
end,
}):sync(60000 --[[1 min]])
return output
end
return runner

View file

@ -1,7 +1,7 @@
---@diagnostic disable: param-type-mismatch
local nodes = require "gopher._utils.ts.nodes"
local u = require "gopher._utils"
local M = {
local ts = {
querys = {
struct_block = [[((type_declaration (type_spec name:(type_identifier) @struct.name type: (struct_type)))@struct.declaration)]],
em_struct_block = [[(field_declaration name:(field_identifier)@struct.name type: (struct_type)) @struct.declaration]],
@ -27,14 +27,14 @@ end
---@param bufnr string|nil
---@param do_notify boolean|nil
---@return table|nil
function M.get_struct_node_at_pos(row, col, bufnr, do_notify)
function ts.get_struct_node_at_pos(row, col, bufnr, do_notify)
local notify = do_notify or true
local query = M.querys.struct_block .. " " .. M.querys.em_struct_block
local query = ts.querys.struct_block .. " " .. ts.querys.em_struct_block
local bufn = bufnr or vim.api.nvim_get_current_buf()
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, row, col)
if ns == nil then
if notify then
u.notify("struct not found", "warn")
u.deferred_notify("struct not found", vim.log.levels.WARN)
end
else
return ns[#ns]
@ -46,14 +46,14 @@ end
---@param bufnr string|nil
---@param do_notify boolean|nil
---@return table|nil
function M.get_func_method_node_at_pos(row, col, bufnr, do_notify)
function ts.get_func_method_node_at_pos(row, col, bufnr, do_notify)
local notify = do_notify or true
local query = M.querys.func .. " " .. M.querys.method_name
local query = ts.querys.func .. " " .. ts.querys.method_name
local bufn = bufnr or vim.api.nvim_get_current_buf()
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, row, col)
if ns == nil then
if notify then
u.notify("function not found", "warn")
u.deferred_notify("function not found", vim.log.levels.WARN)
end
else
return ns[#ns]
@ -65,16 +65,16 @@ end
---@param bufnr string|nil
---@param do_notify boolean|nil
---@return table|nil
function M.get_package_node_at_pos(row, col, bufnr, do_notify)
function ts.get_package_node_at_pos(row, col, bufnr, do_notify)
local notify = do_notify or true
-- stylua: ignore
if row > 10 then return end
local query = M.querys.package
local query = ts.querys.package
local bufn = bufnr or vim.api.nvim_get_current_buf()
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, row, col)
if ns == nil then
if notify then
u.notify("package not found", "warn")
u.deferred_notify("package not found", vim.log.levels.WARN)
return nil
end
else
@ -87,18 +87,18 @@ end
---@param bufnr string|nil
---@param do_notify boolean|nil
---@return table|nil
function M.get_interface_node_at_pos(row, col, bufnr, do_notify)
function ts.get_interface_node_at_pos(row, col, bufnr, do_notify)
local notify = do_notify or true
local query = M.querys.interface
local query = ts.querys.interface
local bufn = bufnr or vim.api.nvim_get_current_buf()
local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, row, col)
if ns == nil then
if notify then
u.notify("interface not found", "warn")
u.deferred_notify("interface not found", vim.log.levels.WARN)
end
else
return ns[#ns]
end
end
return M
return ts

View file

@ -1,3 +1,7 @@
local ts_query = require "nvim-treesitter.query"
local parsers = require "nvim-treesitter.parsers"
local locals = require "nvim-treesitter.locals"
local u = require "gopher._utils"
local M = {}
local function intersects(row, col, sRow, sCol, eRow, eCol)
@ -53,10 +57,6 @@ end
---@param pos_row string
---@return string
function M.get_all_nodes(query, lang, _, bufnr, pos_row, _)
local ts_query = require "nvim-treesitter.query"
local parsers = require "nvim-treesitter.parsers"
local locals = require "nvim-treesitter.locals"
bufnr = bufnr or 0
pos_row = pos_row or 30000
@ -113,8 +113,6 @@ end
---@param col string
---@return table
function M.nodes_at_cursor(query, default, bufnr, row, col)
local u = require "gopher._utils"
bufnr = bufnr or vim.api.nvim_get_current_buf()
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
if row == nil or col == nil then
@ -123,13 +121,19 @@ function M.nodes_at_cursor(query, default, bufnr, row, col)
local nodes = M.get_all_nodes(query, ft, default, bufnr, row, col)
if nodes == nil then
u.notify("Unable to find any nodes. Place your cursor on a go symbol and try again", "debug")
u.deferred_notify(
"Unable to find any nodes. Place your cursor on a go symbol and try again",
vim.log.levels.DEBUG
)
return nil
end
nodes = M.sort_nodes(M.intersect_nodes(nodes, row, col))
if nodes == nil or #nodes == 0 then
u.notify("Unable to find any nodes at pos. " .. tostring(row) .. ":" .. tostring(col), "debug")
u.deferred_notify(
"Unable to find any nodes at pos. " .. tostring(row) .. ":" .. tostring(col),
vim.log.levels.DEBUG
)
return nil
end