diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f055e1c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.github/workflows/pr_check.yml b/.github/workflows/pr_check.yml index d820cb5..8048e58 100644 --- a/.github/workflows/pr_check.yml +++ b/.github/workflows/pr_check.yml @@ -1,22 +1,43 @@ name: Pull request check on: - pull_request: + pull_request: jobs: - format: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: JohnnyMorganz/stylua-action@1.0.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --check . - - block-fixup: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Block Fixup Commit Merge - uses: 13rac1/block-fixup-merge-action@v2.0.0 + format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: JohnnyMorganz/stylua-action@1.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --check . + + block-fixup: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Block Fixup Commit Merge + uses: 13rac1/block-fixup-merge-action@v2.0.0 + + luacheck: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@master + + - uses: leafo/gh-actions-lua@v8.0.0 + with: + luaVersion: 'luajit-2.1.0-beta3' + + - uses: leafo/gh-actions-luarocks@v4.0.0 + + - name: build + run: | + luarocks install luacheck + + - name: test + run: | + luacheck lua + diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..35b522b --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,2 @@ +globals = { "vim", "_" } +max_line_length = false diff --git a/doc/cmp-rg.txt b/doc/cmp-rg.txt index 99bc995..6f45ad4 100644 --- a/doc/cmp-rg.txt +++ b/doc/cmp-rg.txt @@ -2,15 +2,14 @@ Author: Lukas Reineke -Version: 1.3.6 +Version: 1.3.7 ============================================================================== CONTENTS *cmp-rg* 1. Options |cmp-rg-options| 2. Setup |cmp-rg-setup| - 3. Changelog |cmp-rg-changelog| - 4. License |cmp-rg-license| + 3. License |cmp-rg-license| ============================================================================== 1. OPTIONS *cmp-rg-options* @@ -112,59 +111,7 @@ debug *cmp-rg-debug* } ============================================================================== - 3. CHANGELOG *cmp-rg-changelog* - -1.3.6 - * Change default pattern to fix `--smart-case` - -1.3.5 - * Update documentation - -1.3.4 - * ignore byte results - -1.3.3 - * use new cjson decode if on 0.6 - -1.3.2 - * handle json decode errors - -1.3.1 - * Un-indent context in documentation window - -1.3.0 - * Add context documentation window - * Add |cmp-rg-context_before| - * Add |cmp-rg-context_after| - -1.2.0 - * update documentation to move from `opts` to `option` - -1.1.3 - * Fix documentation - -1.1.2 - * Fix quotes for windows - -1.1.1 - * Add examples to the documentation - -1.1.0 - * Kill in progress ripgrep instances once a new one triggers. - * Add |cmp-rg-debug| option - * Add |cmp-rg-debounce| option - -1.0.2 - * Fix ripgrep pattern for zsh - -1.0.1 - * Remove `sort` dependency - -1.0.0 - * First release - -============================================================================== - 4. LICENSE *cmp-rg-license* + 3. LICENSE *cmp-rg-license* The MIT Licence http://www.opensource.org/licenses/mit-license.php diff --git a/lua/cmp-rg/init.lua b/lua/cmp-rg/init.lua index 26d7f0f..5f58c23 100644 --- a/lua/cmp-rg/init.lua +++ b/lua/cmp-rg/init.lua @@ -1,14 +1,16 @@ +require "cmp-rg.types" + +---@class Source +---@field public running_job_id number +---@field public json_decode fun(s: string): rg.Message +---@field public timer any local source = {} source.new = function() - local json_decode = vim.fn.json_decode - if vim.fn.has "nvim-0.6" == 1 then - json_decode = vim.json.decode - end return setmetatable({ running_job_id = 0, timer = vim.loop.new_timer(), - json_decode = json_decode, + json_decode = vim.fn.has "nvim-0.6" == 1 and vim.json.decode or vim.fn.json_decode, }, { __index = source }) end @@ -24,59 +26,88 @@ source.complete = function(self, request, callback) end local seen = {} local items = {} - local context = {} - local documentation_to_add = 0 - local function on_event(job_id, data, event) + local function on_event(_, data, event) if event == "stdout" then - for _, entry in ipairs(data) do - if entry ~= "" then - local ok, result = pcall(self.json_decode, entry) - if - not ok - or result.type == "end" - or (vim.tbl_contains({ "context", "match" }, result.type) and not result.data.lines.text) - then - context = {} - documentation_to_add = 0 - elseif result.type == "context" then - local documentation = result.data.lines.text:gsub("\n", "") - table.insert(context, documentation) - if documentation_to_add > 0 then - local d = items[#items].documentation - table.insert(d, documentation) - documentation_to_add = documentation_to_add - 1 + ---@type (string|rg.Message)[] + local messages = data - if documentation_to_add == 0 then - local min_indent = 1e309 - for i = 4, #d, 1 do - if d[i] ~= "" then - local _, indent = string.find(d[i], "^%s+") - min_indent = math.min(min_indent, indent or 0) - end - end - for i = 4, #d, 1 do - d[i] = d[i]:sub(min_indent) + --- Get a message that has `data.lines.text`. + --- If message is not yet decoded, decode it and update `messages` table. + --- `\n` at the end of `data.lines.text` is removed. + ---@param index number + ---@return rg.Message|nil + local function get_message_with_lines(index) + if index < 1 then + return nil + end + local m = messages[index] + if not m then + return nil + end + if type(m) == "string" then + local ok, decoded = pcall(self.json_decode, m) + if not ok then + return nil + end + m, messages[index] = decoded, decoded + end + if m.type ~= "match" and m.type ~= "context" then + return nil + end + if not m.data.lines.text then + return nil + end + m.data.lines.text = m.data.lines.text:gsub("\n", "") + return m + end + + for current = 1, #data, 1 do + local message = get_message_with_lines(current) + if message and message.type == "match" then + local label = message.data.submatches[1].match.text + if label and not seen[label] then + local path = message.data.path.text + local doc_lines = { path, "", "```" } + local doc_body = {} + if context_before > 0 then + for j = current - context_before, current - 1, 1 do + local before = get_message_with_lines(j) + if before then + table.insert(doc_body, before.data.lines.text) end - table.insert(d, "```") end end - elseif result.type == "match" then - local label = result.data.submatches[1].match.text - if label and not seen[label] then - local documentation = { result.data.path.text, "", "```" } - for i = context_before, 0, -1 do - table.insert(documentation, context[i]) + table.insert(doc_body, message.data.lines.text .. " <--") + if context_after > 0 then + for k = current + 1, current + context_after, 1 do + local after = get_message_with_lines(k) + if after then + table.insert(doc_body, after.data.lines.text) + end end - local match_line = result.data.lines.text:gsub("\n", "") .. " <--" - table.insert(documentation, match_line) - table.insert(items, { - label = label, - documentation = documentation, - }) - documentation_to_add = context_after - seen[label] = true end + + -- shallow indent + local min_indent = math.huge + for _, line in ipairs(doc_body) do + local _, indent = string.find(line, "^%s+") + min_indent = math.min(min_indent, indent or math.huge) + end + for _, line in ipairs(doc_body) do + table.insert(doc_lines, line:sub(min_indent)) + end + + table.insert(doc_lines, "```") + local documentation = { + value = table.concat(doc_lines, "\n"), + kind = "markdown", + } + table.insert(items, { + label = label, + documentation = documentation, + }) + seen[label] = true end end end diff --git a/lua/cmp-rg/types.lua b/lua/cmp-rg/types.lua new file mode 100644 index 0000000..4681211 --- /dev/null +++ b/lua/cmp-rg/types.lua @@ -0,0 +1,20 @@ +---@class rg.Message +---@field public type 'begin'|'match'|'context'|'end' +---@field public data rg.MessageData + +---@class rg.MessageData +---@field public path rg.MessageDataPath +---@field public lines rg.MessageDataLines|nil +---@field public submatches rg.MessageSubmatch[]|nil + +---@class rg.MessageDataPath +---@field public text string + +---@class rg.MessageDataLines +---@field public text string + +---@class rg.MessageSubmatch +---@field public match rg.MessageSubmatchMatch + +---@class rg.MessageSubmatchMatch +---@field public text string|nil