Skip to content

Commit

Permalink
feat: search forward when no diagnostic in current line
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisgrieser committed Sep 21, 2023
1 parent 142700b commit 508b1ef
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 22 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ defaultConfig = {
-- Default is the DDG "Ducky Search" (automatically opening first result).
fallback = "https://duckduckgo.com/?q=%s+%21ducky&kl=en-us",
}

-- If no diagnostic is found, in current line, search this meany lines
-- forward for diagnostics before aborting.
forwSearchLines = 10,
}
```

Expand Down
66 changes: 44 additions & 22 deletions lua/rulebook/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ local fn = vim.fn
local defaultConfig = {
ignoreComments = require("rulebook.rule-data").ignoreComments,
ruleDocs = require("rulebook.rule-data").ruleDocs,
forwSearchLines = 10,
}
defaultConfig.ruleDocs.fallback = "https://duckduckgo.com/?q=%s+%%21ducky&kl=en-us"

-- if user does not call setup, use default
local config = defaultConfig
Expand Down Expand Up @@ -47,6 +47,18 @@ local function validDiagObj(diag)
return true
end

---@param lnum number
---@param operationIsIgnore boolean
local function getDiagsInCurLine(lnum, operationIsIgnore)
local diags = vim.diagnostic.get(0, { lnum = lnum })
-- INFO for rule search, there is no need to filter the diagnostics, since there
-- is a fallback mechanic
if operationIsIgnore then
diags = vim.tbl_filter(function(d) return config.ignoreComments[d.source] ~= nil end, diags)
end
return diags
end

--------------------------------------------------------------------------------

---@param diag diagnostic
Expand Down Expand Up @@ -79,7 +91,6 @@ end
---@param diag diagnostic
local function addIgnoreComment(diag)
if not validDiagObj(diag) then return end
-- INFO no need to check that source has rule-data, since filtered beforehand

local ignoreData = config.ignoreComments

Expand Down Expand Up @@ -109,32 +120,43 @@ end

--------------------------------------------------------------------------------

---Selects a rule in the current line. If one rule, automatically selects it
---Selects a diagnostic in the current line. If one diagnostic, automatically
---selects it. If no diagnostic found, searches in the next lines.
---@param operation function(diag)
local function selectRuleInCurrentLine(operation)
local function selectRule(operation)
local operationIsIgnore = operation == addIgnoreComment
local lnum = vim.api.nvim_win_get_cursor(0)[1] - 1
local curLineDiags = vim.diagnostic.get(0, { lnum = lnum })

-- filter diagnostics for which there are no ignore comments defined
if operation == addIgnoreComment then
curLineDiags = vim.tbl_filter(
function(diag) return config.ignoreComments[diag.source] ~= nil end,
curLineDiags
)
local startLine = lnum
local lastLine = vim.api.nvim_buf_line_count(0)

local diagsAtLine = getDiagsInCurLine(lnum, operationIsIgnore)

-- no diagnostic -> search the next lines
while #diagsAtLine == 0 do
lnum = lnum + 1
if lnum > lastLine or lnum > startLine + config.forwSearchLines then
local msg = ("No diagnostics found in the next %s lines."):format(config.forwSearchLines)
notify(msg, "warn")
return
end
diagsAtLine = getDiagsInCurLine(lnum, operationIsIgnore)
end

-- one or zero diagnostics
if #curLineDiags == 0 then
notify("No supported diagnostics found in current line.", "warn")
return
elseif #curLineDiags == 1 then
operation(curLineDiags[1])
-- move cursor when adding comment
if operationIsIgnore and startLine ~= lnum then
vim.api.nvim_win_set_cursor(0, { lnum + 1, 0 }) -- +1 cause indexing difference
vim.cmd("normal! ^")
end

-- autoselect if one diagnostics
if #diagsAtLine == 1 then
operation(diagsAtLine[1])
return
end

-- select from multiple diagnostics
local title = operation == addIgnoreComment and "Ignore Rule:" or "Lookup Rule:"
vim.ui.select(curLineDiags, {
local title = operationIsIgnore and "Ignore Rule:" or "Lookup Rule:"
vim.ui.select(diagsAtLine, {
prompt = title,
format_item = function(diag)
local source = diag.source and "[" .. diag.source .. "] " or ""
Expand All @@ -153,9 +175,9 @@ end
-- COMMANDS FOR USER

---Search via DuckDuckGo for the rule
function M.lookupRule() selectRuleInCurrentLine(searchForTheRule) end
function M.lookupRule() selectRule(searchForTheRule) end

---Add ignore comment for the rule
function M.ignoreRule() selectRuleInCurrentLine(addIgnoreComment) end
function M.ignoreRule() selectRule(addIgnoreComment) end

return M
3 changes: 3 additions & 0 deletions lua/rulebook/rule-data.lua
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ M.ruleDocs = {

-- urls unfortunately use the rule-name, not the rule-id :/
pylint = "https://pylint.readthedocs.io/en/stable/search.html?q=%s",

-- INFO used when no docs found for the diagnostics source
fallback = "https://duckduckgo.com/?q=%s+%%21ducky&kl=en-us"
}

--------------------------------------------------------------------------------
Expand Down

0 comments on commit 508b1ef

Please sign in to comment.