diff --git a/lua/octo/commands.lua b/lua/octo/commands.lua index 291140e4..954bba32 100644 --- a/lua/octo/commands.lua +++ b/lua/octo/commands.lua @@ -654,7 +654,7 @@ function M.delete_comment() cb = function(output) -- TODO: deleting the last review thread comment, it deletes the whole thread and review -- In issue buffers, we should hide the thread snippet - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) -- remove comment lines from the buffer if comment.reactionLine then @@ -788,7 +788,7 @@ function M.resolve_thread() if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local thread = resp.data.resolveReviewThread.thread if thread.isResolved then update_review_thread_header(bufnr, thread, thread_id, thread_line) @@ -818,7 +818,7 @@ function M.unresolve_thread() if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local thread = resp.data.unresolveReviewThread.thread if not thread.isResolved then update_review_thread_header(bufnr, thread, thread_id, thread_line) @@ -876,7 +876,7 @@ function M.change_state(state) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local obj = get_obj(resp) local new_state = obj.state @@ -961,7 +961,7 @@ function M.save_issue(opts) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) require("octo").create_buffer("issue", resp.data.createIssue.issue, opts.repo, true) vim.fn.execute "normal! Gk" vim.fn.execute "startinsert" @@ -1175,7 +1175,7 @@ function M.save_pr(opts) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local pr = resp.data.createPullRequest.pullRequest utils.info(string.format("#%d - `%s` created successfully", pr.number, pr.title)) require("octo").create_buffer("pull", pr, opts.repo, true) @@ -1401,7 +1401,7 @@ function M.reaction_action(reaction) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) if action == "add" then reaction_groups = resp.data.addReaction.subject.reactionGroups elseif action == "remove" then @@ -1527,7 +1527,7 @@ function M.set_project_v2_card() if add_stderr and not utils.is_blank(add_stderr) then utils.error(add_stderr) elseif add_output then - local resp = vim.fn.json_decode(add_output) + local resp = vim.json.decode(add_output) local update_query = graphql( "update_project_v2_item_mutation", project_id, @@ -1631,7 +1631,7 @@ function M.create_label(label) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local label = resp.data.createLabel.label utils.info("Created label: " .. label.name) diff --git a/lua/octo/gh/graphql.lua b/lua/octo/gh/graphql.lua index d191d96b..8084a2d1 100644 --- a/lua/octo/gh/graphql.lua +++ b/lua/octo/gh/graphql.lua @@ -1887,6 +1887,9 @@ query($name: String!, $owner: String!, $n_milestones: Int!) { } ]] +---@param query string +---@param ... string|table +---@return string return function(query, ...) local opts = { escape = true } for _, v in ipairs { ... } do diff --git a/lua/octo/init.lua b/lua/octo/init.lua index 7b57cba5..28f90137 100644 --- a/lua/octo/init.lua +++ b/lua/octo/init.lua @@ -152,7 +152,7 @@ function M.load(repo, kind, number, cb) local obj = resp.data.repository[key] cb(obj) elseif kind == "repo" then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local obj = resp.data.repository cb(obj) end @@ -184,7 +184,7 @@ function M.on_cursor_hold() if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local reactions = {} local reactionGroups = resp.data.node.reactionGroups for _, reactionGroup in ipairs(reactionGroups) do @@ -220,7 +220,7 @@ function M.on_cursor_hold() if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local user = resp.data.user local popup_bufnr = vim.api.nvim_create_buf(false, true) local lines, max_length = writers.write_user_profile(popup_bufnr, user) @@ -248,7 +248,7 @@ function M.on_cursor_hold() if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local issue = resp.data.repository.issueOrPullRequest local popup_bufnr = vim.api.nvim_create_buf(false, true) local max_length = 80 diff --git a/lua/octo/model/octo-buffer.lua b/lua/octo/model/octo-buffer.lua index 3c60eeb8..dc5e3de1 100644 --- a/lua/octo/model/octo-buffer.lua +++ b/lua/octo/model/octo-buffer.lua @@ -306,7 +306,7 @@ function OctoBuffer:async_fetch_taggable_users() args = { "api", string.format("repos/%s/contributors", self.repo) }, cb = function(response) if not utils.is_blank(response) then - local resp = vim.fn.json_decode(response) + local resp = vim.json.decode(response) for _, contributor in ipairs(resp) do table.insert(users, contributor.login) end @@ -322,7 +322,7 @@ function OctoBuffer:async_fetch_issues() args = { "api", string.format("repos/%s/issues", self.repo) }, cb = function(response) local issues_metadata = {} - local resp = vim.fn.json_decode(response) + local resp = vim.json.decode(response) for _, issue in ipairs(resp) do table.insert(issues_metadata, { number = issue.number, title = issue.title }) end @@ -399,7 +399,7 @@ function OctoBuffer:do_save_title_and_body() if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local obj if self:isPullRequest() then obj = resp.data.updatePullRequest.pullRequest @@ -437,7 +437,7 @@ function OctoBuffer:do_add_issue_comment(comment_metadata) if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local respBody = resp.data.addComment.commentEdge.node.body local respId = resp.data.addComment.commentEdge.node.id if utils.trim(comment_metadata.body) == utils.trim(respBody) then @@ -472,7 +472,7 @@ function OctoBuffer:do_add_thread_comment(comment_metadata) if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local resp_comment = resp.data.addPullRequestReviewComment.comment local comment_end if utils.trim(comment_metadata.body) == utils.trim(resp_comment.body) then @@ -584,7 +584,7 @@ function OctoBuffer:do_add_new_thread(comment_metadata) if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local resp = vim.fn.json_decode(output).data.addPullRequestReviewThread + local resp = vim.json.decode(output).data.addPullRequestReviewThread if not utils.is_blank(resp.thread) then local new_comment = resp.thread.comments.nodes[1] if utils.trim(comment_metadata.body) == utils.trim(new_comment.body) then @@ -681,7 +681,7 @@ function OctoBuffer:do_add_new_thread(comment_metadata) if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local r = vim.fn.json_decode(output) + local r = vim.json.decode(output) local resp = r.data.addPullRequestReviewComment if not utils.is_blank(resp.comment) then if utils.trim(comment_metadata.body) == utils.trim(resp.comment.body) then @@ -734,7 +734,7 @@ function OctoBuffer:do_add_pull_request_comment(comment_metadata) if not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) if not utils.is_blank(resp) then if utils.trim(comment_metadata.body) == utils.trim(resp.body) then local comments = self.commentsMetadata @@ -774,7 +774,7 @@ function OctoBuffer:do_update_comment(comment_metadata) if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local resp_comment if comment_metadata.kind == "IssueComment" then resp_comment = resp.data.updateIssueComment.issueComment diff --git a/lua/octo/model/pull-request.lua b/lua/octo/model/pull-request.lua index 19d96fe6..daee56fb 100644 --- a/lua/octo/model/pull-request.lua +++ b/lua/octo/model/pull-request.lua @@ -101,7 +101,7 @@ function PullRequest:get_changed_files(callback) utils.error(stderr) elseif output then local FileEntry = require("octo.reviews.file-entry").FileEntry - local results = vim.fn.json_decode(output) + local results = vim.json.decode(output) results = merge_pages(results) local files = {} for _, result in ipairs(results) do @@ -135,7 +135,7 @@ function PullRequest:get_commit_changed_files(rev, callback) utils.error(stderr) elseif output then local FileEntry = require("octo.reviews.file-entry").FileEntry - local results = vim.fn.json_decode(output) + local results = vim.json.decode(output) results = merge_pages(results) local files = {} if results.files then diff --git a/lua/octo/navigation.lua b/lua/octo/navigation.lua index f325445f..1c7cd124 100644 --- a/lua/octo/navigation.lua +++ b/lua/octo/navigation.lua @@ -123,7 +123,7 @@ function M.go_to_issue() if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local kind = resp.data.repository.issueOrPullRequest.__typename if kind == "Issue" then utils.get_issue(number, repo) diff --git a/lua/octo/pickers/fzf-lua/entry_maker.lua b/lua/octo/pickers/fzf-lua/entry_maker.lua index 49ca27b0..c13300fd 100644 --- a/lua/octo/pickers/fzf-lua/entry_maker.lua +++ b/lua/octo/pickers/fzf-lua/entry_maker.lua @@ -3,12 +3,14 @@ local fzf = require "fzf-lua" local M = {} +---@param issue_table table +---@return table|nil function M.gen_from_issue(issue_table) if not issue_table or vim.tbl_isempty(issue_table) then return nil end local kind = issue_table.__typename == "Issue" and "issue" or "pull_request" - local filename + local filename ---@type string if kind == "issue" then filename = utils.get_issue_uri(issue_table.number, issue_table.repository.nameWithOwner) else diff --git a/lua/octo/pickers/fzf-lua/pickers/assigned_labels.lua b/lua/octo/pickers/fzf-lua/pickers/assigned_labels.lua index f5b5a058..fe12dba1 100644 --- a/lua/octo/pickers/fzf-lua/pickers/assigned_labels.lua +++ b/lua/octo/pickers/fzf-lua/pickers/assigned_labels.lua @@ -28,7 +28,7 @@ return function(cb) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local labels = resp.data.repository[key].labels.nodes for _, label in ipairs(labels) do diff --git a/lua/octo/pickers/fzf-lua/pickers/assignees.lua b/lua/octo/pickers/fzf-lua/pickers/assignees.lua index a066ea84..9186aeeb 100644 --- a/lua/octo/pickers/fzf-lua/pickers/assignees.lua +++ b/lua/octo/pickers/fzf-lua/pickers/assignees.lua @@ -26,7 +26,7 @@ return function(cb) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local assignees = resp.data.repository[key].assignees.nodes for _, user in ipairs(assignees) do diff --git a/lua/octo/pickers/fzf-lua/pickers/changed_files.lua b/lua/octo/pickers/fzf-lua/pickers/changed_files.lua index 2acdd49a..73a246fc 100644 --- a/lua/octo/pickers/fzf-lua/pickers/changed_files.lua +++ b/lua/octo/pickers/fzf-lua/pickers/changed_files.lua @@ -23,7 +23,7 @@ return function(opts) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local results = vim.fn.json_decode(output) + local results = vim.json.decode(output) for _, result in ipairs(results) do local entry = entry_maker.gen_from_git_changed_files(result) diff --git a/lua/octo/pickers/fzf-lua/pickers/commits.lua b/lua/octo/pickers/fzf-lua/pickers/commits.lua index ecb801c7..68dd4564 100644 --- a/lua/octo/pickers/fzf-lua/pickers/commits.lua +++ b/lua/octo/pickers/fzf-lua/pickers/commits.lua @@ -23,7 +23,7 @@ return function(opts) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local results = vim.fn.json_decode(output) + local results = vim.json.decode(output) for _, result in ipairs(results) do local entry = entry_maker.gen_from_git_commits(result) diff --git a/lua/octo/pickers/fzf-lua/pickers/fzf_actions.lua b/lua/octo/pickers/fzf-lua/pickers/fzf_actions.lua index 05c8d2d8..bf19fd1b 100644 --- a/lua/octo/pickers/fzf-lua/pickers/fzf_actions.lua +++ b/lua/octo/pickers/fzf-lua/pickers/fzf_actions.lua @@ -3,6 +3,8 @@ local octo_config = require "octo.config" local utils = require "octo.utils" local M = {} +---@param formatted_items table entry.ordinal -> entry +---@return table M.common_buffer_actions = function(formatted_items) return { ["default"] = function(selected) @@ -20,6 +22,8 @@ M.common_buffer_actions = function(formatted_items) } end +---@param formatted_items table entry.ordinal -> entry +---@return table M.common_open_actions = function(formatted_items) local cfg = octo_config.values return vim.tbl_extend("force", M.common_buffer_actions(formatted_items), { diff --git a/lua/octo/pickers/fzf-lua/pickers/issues.lua b/lua/octo/pickers/fzf-lua/pickers/issues.lua index e95f2143..3c18a7ad 100644 --- a/lua/octo/pickers/fzf-lua/pickers/issues.lua +++ b/lua/octo/pickers/fzf-lua/pickers/issues.lua @@ -28,7 +28,7 @@ return function(opts) local query = graphql("issues_query", owner, name, filter, order_by.field, order_by.direction, { escape = false }) - local formatted_issues = {} + local formatted_issues = {} ---@type table entry.ordinal -> entry local get_contents = function(fzf_cb) gh.run { diff --git a/lua/octo/pickers/fzf-lua/pickers/labels.lua b/lua/octo/pickers/fzf-lua/pickers/labels.lua index c2923362..6fc5687b 100644 --- a/lua/octo/pickers/fzf-lua/pickers/labels.lua +++ b/lua/octo/pickers/fzf-lua/pickers/labels.lua @@ -21,7 +21,7 @@ return function(cb) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local labels = resp.data.repository.labels.nodes for _, label in ipairs(labels) do diff --git a/lua/octo/pickers/fzf-lua/pickers/project_columns.lua b/lua/octo/pickers/fzf-lua/pickers/project_columns.lua index 06f94042..4981aa6a 100644 --- a/lua/octo/pickers/fzf-lua/pickers/project_columns.lua +++ b/lua/octo/pickers/fzf-lua/pickers/project_columns.lua @@ -26,7 +26,7 @@ return function(cb) args = { "api", "graphql", "--paginate", "-f", string.format("query=%s", query) }, cb = function(output) if output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local projects = {} local user_projects = resp.data.user and resp.data.user.projects.nodes or {} diff --git a/lua/octo/pickers/fzf-lua/pickers/project_columns_v2.lua b/lua/octo/pickers/fzf-lua/pickers/project_columns_v2.lua index 3f0154b9..246e257a 100644 --- a/lua/octo/pickers/fzf-lua/pickers/project_columns_v2.lua +++ b/lua/octo/pickers/fzf-lua/pickers/project_columns_v2.lua @@ -13,7 +13,7 @@ return function(cb) return end - local formatted_projects = {} + local formatted_projects = {} ---@type table entry.ordinal -> entry local common_fzf_opts = vim.tbl_deep_extend("force", picker_utils.dropdown_opts, { fzf_opts = { ["--delimiter"] = "' '", @@ -27,7 +27,7 @@ return function(cb) args = { "api", "graphql", "--paginate", "-f", string.format("query=%s", query) }, cb = function(output) if output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local unsorted_projects = {} local user_projects = resp.data.user and resp.data.user.projects.nodes or {} diff --git a/lua/octo/pickers/fzf-lua/pickers/prs.lua b/lua/octo/pickers/fzf-lua/pickers/prs.lua index 96a6b1f0..e521abe8 100644 --- a/lua/octo/pickers/fzf-lua/pickers/prs.lua +++ b/lua/octo/pickers/fzf-lua/pickers/prs.lua @@ -43,7 +43,7 @@ return function(opts) local query = graphql("pull_requests_query", owner, name, filter, order_by.field, order_by.direction, { escape = false }) - local formatted_pulls = {} + local formatted_pulls = {} ---@type table entry.ordinal -> entry local get_contents = function(fzf_cb) gh.run { diff --git a/lua/octo/pickers/fzf-lua/pickers/repos.lua b/lua/octo/pickers/fzf-lua/pickers/repos.lua index 9ab93682..1030f52a 100644 --- a/lua/octo/pickers/fzf-lua/pickers/repos.lua +++ b/lua/octo/pickers/fzf-lua/pickers/repos.lua @@ -17,7 +17,7 @@ return function(opts) end end - local formatted_repos = {} + local formatted_repos = {} ---@type table entry.ordinal -> entry local get_contents = function(fzf_cb) local query = graphql("repos_query", opts.login) diff --git a/lua/octo/pickers/fzf-lua/pickers/review_commits.lua b/lua/octo/pickers/fzf-lua/pickers/review_commits.lua index 703af56d..08aa1558 100644 --- a/lua/octo/pickers/fzf-lua/pickers/review_commits.lua +++ b/lua/octo/pickers/fzf-lua/pickers/review_commits.lua @@ -44,7 +44,7 @@ return function(thread_cb) utils.error(err) fzf_cb() elseif output then - local results = vim.fn.json_decode(output) + local results = vim.json.decode(output) if #formatted_commits == 0 then local full_pr = entry_maker.gen_from_git_commits(make_full_pr(current_review)) diff --git a/lua/octo/pickers/fzf-lua/pickers/search.lua b/lua/octo/pickers/fzf-lua/pickers/search.lua index 998e0c2d..de8e01c8 100644 --- a/lua/octo/pickers/fzf-lua/pickers/search.lua +++ b/lua/octo/pickers/fzf-lua/pickers/search.lua @@ -7,6 +7,11 @@ local picker_utils = require "octo.pickers.fzf-lua.pickers.utils" local utils = require "octo.utils" local previewers = require "octo.pickers.fzf-lua.previewers" +---@param fzf_cb function +---@param issue table +---@param max_id_length integer +---@param formatted_issues table entry.ordinal -> entry +---@param co thread local handle_entry = function(fzf_cb, issue, max_id_length, formatted_issues, co) local entry = entry_maker.gen_from_issue(issue) if entry ~= nil then @@ -25,7 +30,7 @@ end return function(opts) opts = opts or {} - local formatted_items = {} + local formatted_items = {} ---@type table entry.ordinal -> entry local contents = function(query) return function(fzf_cb) @@ -54,7 +59,7 @@ return function(opts) return {} end - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local max_id_length = 1 for _, issue in ipairs(resp.data.search.nodes) do local s = tostring(issue.number) diff --git a/lua/octo/pickers/fzf-lua/pickers/utils.lua b/lua/octo/pickers/fzf-lua/pickers/utils.lua index c88e1176..4622bd72 100644 --- a/lua/octo/pickers/fzf-lua/pickers/utils.lua +++ b/lua/octo/pickers/fzf-lua/pickers/utils.lua @@ -18,6 +18,9 @@ M.dropdown_opts = vim.tbl_deep_extend("force", M.multi_dropdown_opts, { }, }) +---@param opts table +---@param kind string +---@return string function M.get_filter(opts, kind) local filter = "" local allowed_values = {} @@ -29,15 +32,16 @@ function M.get_filter(opts, kind) for _, value in pairs(allowed_values) do if opts[value] then - local val - if #vim.split(opts[value], ",") > 1 then + local val ---@type string|string[] + local splitted_val = vim.split(opts[value], ",") + if #splitted_val > 1 then -- list - val = vim.split(opts[value], ",") + val = splitted_val else -- string val = opts[value] end - val = vim.fn.json_encode(val) + val = vim.json.encode(val) val = string.gsub(val, '"OPEN"', "OPEN") val = string.gsub(val, '"CLOSED"', "CLOSED") val = string.gsub(val, '"MERGED"', "MERGED") @@ -48,12 +52,10 @@ function M.get_filter(opts, kind) return filter end ---[[ - Open the entry in a buffer. - - @param command One of 'default', 'horizontal', 'vertial', or 'tab' - @param entry The entry to open. -]] +---Open the entry in a buffer. +--- +---@param command 'default' |'horizontal' | 'vertical' | 'tab' +---@param entry table function M.open(command, entry) if command == "default" then vim.cmd [[:buffer %]] @@ -67,19 +69,17 @@ function M.open(command, entry) utils.get(entry.kind, entry.value, entry.repo) end ---[[ - Gets a consistent prompt. - - @param title The original prompt title. - @return A prompt smartly postfixed with "> ". - - > get_prompt(nil) == "> " - > get_prompt("") == "> " - > get_prompt("something") == "something> " - > get_prompt("something else>") == "something else> " - > get_prompt("penultimate thing > ") == "penultimate thing > " - > get_prompt("last th> ing") == "last th> ing> " -]] +---Gets a consistent prompt. +--- +---@param title string The original prompt title. +---@return string prompt A prompt smartly postfixed with "> ". +--- +---> get_prompt(nil) == "> " +---> get_prompt("") == "> " +---> get_prompt("something") == "something> " +---> get_prompt("something else>") == "something else> " +---> get_prompt("penultimate thing > ") == "penultimate thing > " +---> get_prompt("last th> ing") == "last th> ing> " function M.get_prompt(title) if title == nil or title == "" then return "> " @@ -92,13 +92,11 @@ function M.get_prompt(title) return title end ---[[ - Opens the entry in your default browser. - - @param entry The entry to open. -]] +---Opens the entry in your default browser. +--- +---@param entry table function M.open_in_browser(entry) - local number + local number ---@type integer local repo = entry.repo if entry.kind ~= "repo" then number = entry.value @@ -106,17 +104,18 @@ function M.open_in_browser(entry) navigation.open_in_browser(entry.kind, repo, number) end ---[[ - Copies the url to the clipboard. - - @param entry The entry to get the url from. -]] +---Copies the entry url to the clipboard. +--- +---@param entry table function M.copy_url(entry) local url = entry.obj.url vim.fn.setreg("+", url, "c") utils.info("Copied '" .. url .. "' to the system clipboard (+ register)") end +---@param s string +---@param hexcol string +---@return string|nil function M.color_string_with_hex(s, hexcol) local r, g, b = hexcol:match "#(..)(..)(..)" if not r or not g or not b then @@ -125,12 +124,14 @@ function M.color_string_with_hex(s, hexcol) r, g, b = tonumber(r, 16), tonumber(g, 16), tonumber(b, 16) -- Foreground code? - local escseq = ("[%d;2;%d;%d;%dm"):format(38, r, g, b) + local escseq = ("\27[%d;2;%d;%d;%dm"):format(38, r, g, b) -- \27 is the escape code of ctrl-[ and return ("%s%s%s"):format(escseq, s, fzf_utils.ansi_escseq.clear) end +---@param s unknown +---@param length integer +---@return string function M.pad_string(s, length) - -- Make sure it's a string. local string_s = tostring(s) return string.format("%s%" .. (length - #string_s) .. "s", string_s, " ") end diff --git a/lua/octo/pickers/fzf-lua/previewers.lua b/lua/octo/pickers/fzf-lua/previewers.lua index 9f093b97..e941081e 100644 --- a/lua/octo/pickers/fzf-lua/previewers.lua +++ b/lua/octo/pickers/fzf-lua/previewers.lua @@ -73,7 +73,7 @@ M.issue = function(formatted_issues) if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output and self.preview_bufnr == tmpbuf and vim.api.nvim_buf_is_valid(tmpbuf) then - local result = vim.fn.json_decode(output) + local result = vim.json.decode(output) local obj if entry.kind == "issue" then obj = result.data.repository.issue @@ -135,7 +135,7 @@ M.search = function() if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output and self.preview_bufnr == tmpbuf and vim.api.nvim_buf_is_valid(tmpbuf) then - local result = vim.fn.json_decode(output) + local result = vim.json.decode(output) local obj if kind == "issue" then obj = result.data.repository.issue @@ -340,7 +340,7 @@ M.repo = function(formatted_repos) -- when the entry changes `preview_bufnr` will also change (due to `set_preview_buf`) -- and `tmpbuf` within this context is already cleared and invalidated if self.preview_bufnr == tmpbuf and vim.api.nvim_buf_is_valid(tmpbuf) then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) buffer.node = resp.data.repository buffer:render_repo() end diff --git a/lua/octo/pickers/telescope/previewers.lua b/lua/octo/pickers/telescope/previewers.lua index 1bc0a1c2..1e9d56aa 100644 --- a/lua/octo/pickers/telescope/previewers.lua +++ b/lua/octo/pickers/telescope/previewers.lua @@ -36,7 +36,7 @@ local discussion = defaulter(function(opts) -- clear the buffer vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {}) - local result = vim.fn.json_decode(output) + local result = vim.json.decode(output) local obj = result.data.repository.discussion writers.write_title(bufnr, tostring(obj.title), 1) @@ -79,7 +79,7 @@ local issue = defaulter(function(opts) if stderr and not utils.is_blank(stderr) then vim.api.nvim_err_writeln(stderr) elseif output and vim.api.nvim_buf_is_valid(bufnr) then - local result = vim.fn.json_decode(output) + local result = vim.json.decode(output) local obj if entry.kind == "issue" then obj = result.data.repository.issue diff --git a/lua/octo/pickers/telescope/provider.lua b/lua/octo/pickers/telescope/provider.lua index e9e31806..8841cef0 100644 --- a/lua/octo/pickers/telescope/provider.lua +++ b/lua/octo/pickers/telescope/provider.lua @@ -52,7 +52,7 @@ local function get_filter(opts, kind) -- string val = opts[value] end - val = vim.fn.json_encode(val) + val = vim.json.encode(val) val = string.gsub(val, '"OPEN"', "OPEN") val = string.gsub(val, '"CLOSED"', "CLOSED") val = string.gsub(val, '"MERGED"', "MERGED") @@ -370,7 +370,7 @@ function M.commits() if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local results = vim.fn.json_decode(output) + local results = vim.json.decode(output) pickers .new({}, { prompt_title = false, @@ -410,7 +410,7 @@ function M.review_commits(callback) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local results = vim.fn.json_decode(output) + local results = vim.json.decode(output) -- add a fake entry to represent the entire pull request table.insert(results, { @@ -474,7 +474,7 @@ function M.changed_files() if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local results = vim.fn.json_decode(output) + local results = vim.json.decode(output) pickers .new({}, { prompt_title = false, @@ -564,7 +564,7 @@ function M.search(opts) mode = "sync", } if output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) for _, issue in ipairs(resp.data.search.nodes) do table.insert(results, issue) end @@ -686,7 +686,7 @@ function M.select_target_project_column(cb) args = { "api", "graphql", "--paginate", "-f", string.format("query=%s", query) }, cb = function(output) if output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local projects = {} local user_projects = resp.data.user and resp.data.user.projects.nodes or {} local repo_projects = resp.data.repository and resp.data.repository.projects.nodes or {} @@ -786,7 +786,7 @@ function M.select_label(cb) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local labels = resp.data.repository.labels.nodes pickers .new(opts, { @@ -836,7 +836,7 @@ function M.select_assigned_label(cb) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local labels = resp.data.repository[key].labels.nodes pickers .new(opts, { @@ -1062,7 +1062,7 @@ function M.select_assignee(cb) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local assignees = resp.data.repository[key].assignees.nodes pickers .new(opts, { @@ -1219,7 +1219,7 @@ function M.notifications() if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) pickers .new(opts, { @@ -1379,7 +1379,7 @@ function M.milestones(opts) return end - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local nodes = resp.data.repository.milestones.nodes if #nodes == 0 then diff --git a/lua/octo/reviews/init.lua b/lua/octo/reviews/init.lua index ebf3846e..7f7626fe 100644 --- a/lua/octo/reviews/init.lua +++ b/lua/octo/reviews/init.lua @@ -44,7 +44,7 @@ function Review:create(callback) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) callback(resp) end end, @@ -71,7 +71,7 @@ function Review:retrieve(callback) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) callback(resp) end end, @@ -203,7 +203,7 @@ function Review:discard() if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) if #resp.data.repository.pullRequest.reviews.nodes == 0 then utils.error "No pending reviews found" return diff --git a/lua/octo/ui/window.lua b/lua/octo/ui/window.lua index f11a3b21..dbb59aac 100644 --- a/lua/octo/ui/window.lua +++ b/lua/octo/ui/window.lua @@ -62,6 +62,9 @@ function M.create_content_float(opts) return winid, bufnr end +---@param opts table +---@return integer winid +---@return integer bufnr function M.create_centered_float(opts) opts = opts or {} opts.x_percent = opts.x_percent or 0.6 diff --git a/lua/octo/utils.lua b/lua/octo/utils.lua index b8ad3bd5..35d0a227 100644 --- a/lua/octo/utils.lua +++ b/lua/octo/utils.lua @@ -9,7 +9,8 @@ local M = {} ---@class OctoRepo ---@field host string ----@field name string +---@field name string? +---@field repo string? local repo_id_cache = {} local repo_templates_cache = {} @@ -161,6 +162,11 @@ M.reaction_map = { ["EYES"] = "👀 ", } +---@param tbl unknown[] +---@param first integer +---@param last integer +---@param step integer? +---@return unknown[] function M.tbl_slice(tbl, first, last, step) local sliced = {} for i = first or 1, last or #tbl, step or 1 do @@ -289,6 +295,8 @@ function M.get_all_remotes() return vim.tbl_values(M.parse_git_remote()) end +---@param remote table|nil +---@return string? function M.get_remote_name(remote) return M.get_remote(remote).repo end @@ -385,7 +393,7 @@ function M.create_milestone(title, description) if stderr and not M.is_blank(stderr) then M.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) M.info("Created milestone " .. resp.title) end end, @@ -705,7 +713,7 @@ function M.get_repo_id(repo) args = { "api", "graphql", "-f", string.format("query=%s", query) }, mode = "sync", } - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local id = resp.data.repository.id repo_id_cache[repo] = id return id @@ -731,7 +739,7 @@ function M.get_repo_info(repo) args = { "api", "graphql", "-f", string.format("query=%s", query) }, mode = "sync", } - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local info = resp.data.repository repo_info_cache[repo] = info return info @@ -749,7 +757,7 @@ function M.get_repo_templates(repo) args = { "api", "graphql", "-f", string.format("query=%s", query) }, mode = "sync", } - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local templates = resp.data.repository -- add an option to not use a template @@ -766,11 +774,13 @@ function M.get_repo_templates(repo) end ---Helper method to aggregate an API paginated response +---@param text string +---@return table[] function M.get_pages(text) local results = {} local page_outputs = vim.split(text, "\n") for _, page in ipairs(page_outputs) do - local decoded_page = vim.fn.json_decode(page) + local decoded_page = vim.json.decode(page) table.insert(results, decoded_page) end return results @@ -781,7 +791,7 @@ function M.get_flatten_pages(text) local results = {} local page_outputs = vim.split(text, "\n") for _, page in ipairs(page_outputs) do - local decoded_page = vim.fn.json_decode(page) + local decoded_page = vim.json.decode(page) for _, result in ipairs(decoded_page) do table.insert(results, result) end @@ -790,6 +800,9 @@ function M.get_flatten_pages(text) end --- Helper method to aggregate an API paginated response +---@param text string +---@param aggregation_key string +---@return table function M.aggregate_pages(text, aggregation_key) -- aggregation key can be at any level (eg: comments) -- take the first response and extend it with elements from the @@ -807,18 +820,18 @@ function M.aggregate_pages(text, aggregation_key) end --- Helper method to aggregate an API paginated response +---@param obj table +---@param prop string +---@return unknown function M.get_nested_prop(obj, prop) - while true do - local parts = vim.split(prop, "%.") - if #parts == 1 then - break - else - local part = parts[1] - local remaining = table.concat(M.tbl_slice(parts, 2, #parts), ".") - return M.get_nested_prop(obj[part], remaining) - end + local parts = vim.split(prop, "%.") + if #parts == 1 then + return obj[prop] + else + local part = parts[1] + local remaining = table.concat(M.tbl_slice(parts, 2, #parts), ".") + return M.get_nested_prop(obj[part], remaining) end - return obj[prop] end --- Escapes a characters on a string to be used as a JSON string @@ -829,8 +842,11 @@ function M.escape_char(string) end --- Extracts repo and number from Octo command varargs +---@param ... string|number +---@return string? repo +---@return integer? number function M.get_repo_number_from_varargs(...) - local repo, number + local repo, number ---@type string|nil, integer|nil local args = table.pack(...) if args.n == 0 then M.error "Missing arguments" @@ -851,8 +867,12 @@ function M.get_repo_number_from_varargs(...) M.error "Can not find repo name" return end - if not number then - M.error "Missing issue/PR number" + if type(repo) ~= "string" then + M.error(("Expected repo name, received %s"):format(args[2])) + return + end + if not number or type(number) ~= "number" then + M.error(("Expected issue/PR number, received %s"):format(args[1])) return end return repo, number @@ -933,7 +953,7 @@ function M.get_file_contents(repo, commit, path, cb) if stderr and not M.is_blank(stderr) then M.error(stderr) elseif output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) local blob = resp.data.repository.object local lines = {} if blob and blob ~= vim.NIL and type(blob.text) == "string" then @@ -1415,7 +1435,7 @@ function M.get_pull_request_for_current_branch(cb) M.error "No pr found for current branch" return end - local pr = vim.fn.json_decode(out) + local pr = vim.json.decode(out) local base_owner local base_name if pr.number then @@ -1519,7 +1539,7 @@ function M.get_user_id(login) mode = "sync", } if output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) if resp.data.user and resp.data.user ~= vim.NIL then return resp.data.user.id end @@ -1541,7 +1561,7 @@ function M.get_label_id(label) mode = "sync", } if output then - local resp = vim.fn.json_decode(output) + local resp = vim.json.decode(output) if resp.data.repository.labels.nodes and resp.data.repository.labels.nodes ~= vim.NIL then for _, l in ipairs(resp.data.repository.labels.nodes) do if l.name == label then @@ -1622,6 +1642,8 @@ function M.extract_rest_id(comment_url) end --- Apply mappings to a buffer +---@param kind string +---@param bufnr integer function M.apply_mappings(kind, bufnr) local mappings = require "octo.mappings" local conf = config.values