diff --git a/doc/octo.txt b/doc/octo.txt index efb2ccab..285100d1 100644 --- a/doc/octo.txt +++ b/doc/octo.txt @@ -57,7 +57,7 @@ See |octo-command-examples| for examples. Open PR in browser. Checkout PR. Copy URL to system clipboard. - Available filter keys: see + Available filter keys: author,assignee,label,state,head,base,search,limit search Live PR search. edit [number] {repo} Edits issue/PR with the given number in the current or specified repo. diff --git a/lua/octo/config.lua b/lua/octo/config.lua index a20f1f72..88f7cf3b 100644 --- a/lua/octo/config.lua +++ b/lua/octo/config.lua @@ -127,6 +127,7 @@ function M.get_default_values() field = "CREATED_AT", direction = "DESC", }, + limit = 50, always_select_remote_on_create = false, }, file_panel = { diff --git a/lua/octo/gh/graphql.lua b/lua/octo/gh/graphql.lua index b8ec1b0c..10154ae2 100644 --- a/lua/octo/gh/graphql.lua +++ b/lua/octo/gh/graphql.lua @@ -2129,6 +2129,7 @@ query($endCursor: String) { repository { nameWithOwner } headRefName isDraft + author { username: login } } pageInfo { hasNextPage diff --git a/lua/octo/pickers/fzf-lua/pickers/prs.lua b/lua/octo/pickers/fzf-lua/pickers/prs.lua index 90ae3e23..89cda8ed 100644 --- a/lua/octo/pickers/fzf-lua/pickers/prs.lua +++ b/lua/octo/pickers/fzf-lua/pickers/prs.lua @@ -66,7 +66,7 @@ return function(opts) highlight = "OctoStateOpen" end local prefix = fzf.utils.ansi_from_hl(highlight, entry.value) - fzf_cb(prefix .. " " .. entry.obj.title) + fzf_cb(prefix .. " " .. entry.obj.title .. " (" .. entry.obj.headRefName .. ")") end end end diff --git a/lua/octo/pickers/telescope/entry_maker.lua b/lua/octo/pickers/telescope/entry_maker.lua index 1555cfdc..aba47881 100644 --- a/lua/octo/pickers/telescope/entry_maker.lua +++ b/lua/octo/pickers/telescope/entry_maker.lua @@ -4,6 +4,58 @@ local utils = require "octo.utils" local M = {} +function M.gen_from_pull_request(max_number, username_col_len, branch_name_col_len, author_count) + local make_display = function(entry) + if not entry then + return nil + end + + local layout, columns + columns = { + { entry.value, "TelescopeResultsNumber" }, + { entry.obj.author.username }, + { entry.obj.headRefName }, + { entry.obj.title }, + } + layout = { + separator = " ", + items = { + { width = max_number }, + { width = username_col_len }, + { width = branch_name_col_len }, + { remaining = true }, + }, + } + + -- hide author column if there is just one author + if author_count == 1 then + table.remove(columns, 2) + table.remove(layout.items, 2) + end + + local displayer = entry_display.create(layout) + + return displayer(columns) + end + + return function(obj) + if not obj or vim.tbl_isempty(obj) then + return nil + end + local filename = utils.get_pull_request_uri(obj.repository.nameWithOwner, obj.number) + + return { + filename = filename, + kind = "pull_request", + value = obj.number, + ordinal = obj.number .. " " .. obj.title .. " " .. obj.author.username .. " " .. obj.headRefName, + display = make_display, + obj = obj, + repo = obj.repository.nameWithOwner, + } + end +end + function M.gen_from_issue(max_number, print_repo) local make_display = function(entry) if not entry then diff --git a/lua/octo/pickers/telescope/provider.lua b/lua/octo/pickers/telescope/provider.lua index 98c0cb1d..cc4b7c25 100644 --- a/lua/octo/pickers/telescope/provider.lua +++ b/lua/octo/pickers/telescope/provider.lua @@ -268,42 +268,63 @@ end function M.pull_requests(opts) opts = opts or {} - if not opts.states then - opts.states = "OPEN" + local cfg = octo_config.values + + if not opts.limit then + opts.limit = cfg.pull_requests.limit end - local filter = get_filter(opts, "pull_request") - if utils.is_blank(opts.repo) then - opts.repo = utils.get_remote_name() + + utils.info "Fetching pull requests (this may take a while) ..." + local args = { + "pr", "list", + "--limit", tostring(opts.limit), + "--json", "author,number,title,url,headRepository,headRepositoryOwner,headRefName,isDraft" + } + if opts.repo then + table.insert(args, "-R") + table.insert(args, opts.repo) end - if not opts.repo then - utils.error "Cannot find repo" - return + local keys = { "author", "assignee", "label", "state", "head", "base", "search" } + + for _, key in ipairs(keys) do + if opts[key] then + table.insert(args, "--" .. key) + table.insert(args, opts[key]) + end end - local owner, name = utils.split_repo(opts.repo) - local cfg = octo_config.values - local order_by = cfg.pull_requests.order_by - local query = - graphql("pull_requests_query", owner, name, filter, order_by.field, order_by.direction, { escape = false }) - utils.info "Fetching pull requests (this may take a while) ..." gh.run { - args = { "api", "graphql", "--paginate", "--jq", ".", "-f", string.format("query=%s", query) }, + args = args, + cb = function(output, stderr) if stderr and not utils.is_blank(stderr) then utils.error(stderr) elseif output then - local resp = utils.aggregate_pages(output, "data.repository.pullRequests.nodes") - local pull_requests = resp.data.repository.pullRequests.nodes + local pull_requests = vim.fn.json_decode(output) if #pull_requests == 0 then utils.error(string.format("There are no matching pull requests in %s.", opts.repo)) return end local max_number = -1 + local username_col_len = 0 + local branch_name_col_len = 0 + local authors = {} + local author_count = 0 for _, pull in ipairs(pull_requests) do - if #tostring(pull.number) > max_number then - max_number = #tostring(pull.number) - end + -- modify result to be consistent with GraphQL output. + pull["__typename"] = "pull_request" + pull.author.username = pull.author.login + pull.repository = { nameWithOwner = pull.headRepositoryOwner.login .. "/" .. pull.headRepository.name } + + authors[pull.author.id] = (authors[pull.author.id] or 0) + 1 + max_number = math.max(max_number, #tostring(pull.number)) + username_col_len = math.min(20, math.max(username_col_len, #tostring(pull.author.username))) + branch_name_col_len = math.min(20, math.max(branch_name_col_len, #tostring(pull.headRefName))) end + for _ in pairs(authors) do + author_count = author_count + 1 + end + opts.preview_title = opts.preview_title or "" opts.prompt_title = opts.prompt_title or "" opts.results_title = opts.results_title or "" @@ -311,7 +332,7 @@ function M.pull_requests(opts) .new(opts, { finder = finders.new_table { results = pull_requests, - entry_maker = entry_maker.gen_from_issue(max_number), + entry_maker = entry_maker.gen_from_pull_request(max_number, username_col_len, branch_name_col_len, author_count), }, sorter = conf.generic_sorter(opts), previewer = previewers.issue.new(opts),