From ffb5c1b478161fc33db69bc3258187ed67fd0ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Thu, 25 Feb 2021 00:25:42 +0100 Subject: [PATCH 01/27] add review comments to pull request query --- lua/octo/graphql.lua | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lua/octo/graphql.lua b/lua/octo/graphql.lua index 980f6fa6..606949d7 100644 --- a/lua/octo/graphql.lua +++ b/lua/octo/graphql.lua @@ -413,8 +413,31 @@ query($endCursor: String) { login } state - comments { + comments(last:100) { totalCount + nodes{ + id + replyTo { + id + } + body + commit { + oid + } + author { login } + authorAssociation + originalPosition + position + state + outdated + diffHunk + reactions(last:20) { + totalCount + nodes{ + content + } + } + } } } } From 806c032fe7d62cfc8fb3dc12647e12128ec6bc1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Thu, 25 Feb 2021 00:26:27 +0100 Subject: [PATCH 02/27] initial implementation of review comments in PR buffer --- lua/octo/init.lua | 60 +++++++++++++++++++++++++++++++++----------- lua/octo/writers.lua | 2 +- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/lua/octo/init.lua b/lua/octo/init.lua index 76b672a2..8d1c00cb 100644 --- a/lua/octo/init.lua +++ b/lua/octo/init.lua @@ -199,17 +199,11 @@ function M.create_buffer(type, obj, repo, create) api.nvim_buf_set_var(bufnr, "body_reactions", obj.reactions) api.nvim_buf_set_var(bufnr, "body_reaction_line", reaction_line) - -- collect comments + -- initialize comments metadata api.nvim_buf_set_var(bufnr, "comments", {}) - local comments = obj.comments.nodes + -- PRs if obj.commits then - - -- collect review comments - if obj.reviews then - vim.list_extend(comments, obj.reviews.nodes) - end - -- for pulls, store some additional info api.nvim_buf_set_var( bufnr, @@ -227,14 +221,52 @@ function M.create_buffer(type, obj, repo, create) ) end - -- sort comments - table.sort(comments, function (c1, c2) - return date(c1.createdAt) < date(c2.createdAt) + -- collect items + local items = {} + + --- 1) comments + for _, comment in ipairs(obj.comments.nodes) do + table.insert(items, { + createdAt = comment.createdAt, + type = "comment", + item = comment + }) + end + + --- 2) collect reviews + if obj.reviews then + for _, review in ipairs(obj.reviews.nodes) do + table.insert(items, { + createdAt = review.createdAt, + type = "review", + item = review + }) + end + end + + -- sort items + table.sort(items, function (i1, i2) + return date(i1.createdAt) < date(i2.createdAt) end) - -- write comments - for _, c in ipairs(comments) do - writers.write_comment(bufnr, c) + -- write items + for _, item in ipairs(items) do + if item.type == "comment" then + + -- write the comment + writers.write_comment(bufnr, item.item) + elseif item.type == "review" then + + -- write top-level comment + writers.write_comment(bufnr, item.item) + + for _, comment in ipairs(item.item.comments.nodes) do + if comment.replyTo == vim.NIL then + writers.write_diff_hunk(bufnr, comment.diffHunk) + end + writers.write_comment(bufnr, comment) + end + end end async_fetch_taggable_users(bufnr, repo, obj.participants.nodes) diff --git a/lua/octo/writers.lua b/lua/octo/writers.lua index 76d5d549..3544ba42 100644 --- a/lua/octo/writers.lua +++ b/lua/octo/writers.lua @@ -407,7 +407,7 @@ function M.write_comment(bufnr, comment, line) end function M.write_diff_hunk(bufnr, diff_hunk, start_line) - start_line = start_line or 1 + start_line = start_line or api.nvim_buf_line_count(bufnr) + 1 -- clear virtual texts api.nvim_buf_clear_namespace(bufnr, constants.OCTO_DIFFHUNKS_VT_NS, 0, start_line - 1) From f3cc55e4cb5de5829ae308c804a616c5ca263fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Thu, 25 Feb 2021 11:35:14 +0100 Subject: [PATCH 03/27] better sorting/grouping of review/reviewthreads --- lua/octo/folds.lua | 12 +++++ lua/octo/graphql.lua | 107 +++++++++++++++++++++++++++++-------------- lua/octo/init.lua | 52 +++++++++++++++++---- lua/octo/writers.lua | 14 +++--- 4 files changed, 135 insertions(+), 50 deletions(-) diff --git a/lua/octo/folds.lua b/lua/octo/folds.lua index 3770c6cf..12b36c42 100644 --- a/lua/octo/folds.lua +++ b/lua/octo/folds.lua @@ -1,3 +1,15 @@ function _G.OctoFoldText() return "..." end + +local M = {} + +function M.create(start_line, end_line, is_opened) + print("Creating fold from", start_line, "to", end_line) + vim.cmd(string.format("%d,%dfold", start_line, end_line)) + if is_opened then + vim.cmd(string.format("%d,%dfoldopen!", start_line, end_line)) + end +end + +return M diff --git a/lua/octo/graphql.lua b/lua/octo/graphql.lua index 606949d7..ba34d753 100644 --- a/lua/octo/graphql.lua +++ b/lua/octo/graphql.lua @@ -271,44 +271,46 @@ M.review_threads_query = query($endCursor: String) { repository(owner:"%s", name:"%s") { pullRequest(number:%d) { - reviewThreads(last:80) { - nodes { - id - isResolved - isOutdated - path - resolvedBy { login } - line - originalLine - startLine - originalStartLine - comments(first: 100, after: $endCursor) { - nodes{ - id - body - commit { - oid - } - author { login } - authorAssociation - originalPosition - position - state - outdated - diffHunk - reactions(last:20) { - totalCount - nodes{ - content - } - } + reviewThreads(last:80) { + nodes { + id + isResolved + isOutdated + path + resolvedBy { login } + line + originalLine + startLine + originalStartLine + comments(first: 100, after: $endCursor) { + nodes{ + id + body + createdAt + commit { + oid } - pageInfo { - hasNextPage - endCursor + replyTo { id } + author { login } + authorAssociation + originalPosition + position + state + outdated + diffHunk + reactions(last:20) { + totalCount + nodes{ + content + } } } + pageInfo { + hasNextPage + endCursor + } } + } } } } @@ -398,6 +400,43 @@ query($endCursor: String) { } } reviewDecision + reviewThreads(last:100) { + nodes { + id + isResolved + isOutdated + path + resolvedBy { login } + line + originalLine + startLine + originalStartLine + comments(first: 100) { + nodes{ + id + body + createdAt + replyTo { id } + commit { + oid + } + author { login } + authorAssociation + originalPosition + position + state + outdated + diffHunk + reactions(last:20) { + totalCount + nodes{ + content + } + } + } + } + } + } reviews(last:100) { nodes { id diff --git a/lua/octo/init.lua b/lua/octo/init.lua index 8d1c00cb..ef25547e 100644 --- a/lua/octo/init.lua +++ b/lua/octo/init.lua @@ -5,6 +5,7 @@ local util = require "octo.util" local graphql = require "octo.graphql" local writers = require "octo.writers" local date = require "octo.date" +local folds = require "octo.folds" local vim = vim local api = vim.api local format = string.format @@ -244,6 +245,17 @@ function M.create_buffer(type, obj, repo, create) end end + -- --- 3) collect reviewThreads + -- if obj.reviewThreads then + -- for _, reviewThread in ipairs(obj.reviewThreads.nodes) do + -- table.insert(items, { + -- createdAt = reviewThread.comments.nodes[1].createdAt, + -- type = "reviewThread", + -- item = reviewThread + -- }) + -- end + -- end + -- sort items table.sort(items, function (i1, i2) return date(i1.createdAt) < date(i2.createdAt) @@ -252,20 +264,44 @@ function M.create_buffer(type, obj, repo, create) -- write items for _, item in ipairs(items) do if item.type == "comment" then - -- write the comment - writers.write_comment(bufnr, item.item) - elseif item.type == "review" then + local start_line, end_line = writers.write_comment(bufnr, item.item) + folds.create(start_line+1, end_line, true) - -- write top-level comment - writers.write_comment(bufnr, item.item) + elseif item.type == "review" then + -- A review can have 0+ threads + local threads = {} for _, comment in ipairs(item.item.comments.nodes) do - if comment.replyTo == vim.NIL then - writers.write_diff_hunk(bufnr, comment.diffHunk) + for _, reviewThread in ipairs(obj.reviewThreads.nodes) do + if comment.id == reviewThread.comments.nodes[1].id then + -- found a thread for the current review + table.insert(threads, reviewThread) + end + end + end + + if #threads > 0 then + -- print review header and top level comment + writers.write_comment(bufnr, item.item) + + -- print each of the threads + for _, thread in ipairs(threads) do + for _,comment in ipairs(thread.comments.nodes) do + if comment.replyTo == vim.NIL then + writers.write_diff_hunk(bufnr, comment.diffHunk) + end + writers.write_comment(bufnr, comment) + end end - writers.write_comment(bufnr, comment) end + + -- interesting PullRequestReviewComment fields: + -- isMinimized: Returns whether or not a comment has been minimized. + -- minimizedReason: Returns why the comment was minimized. + -- state: Identifies the state of the comment. + -- originalPosition: The original line index in the diff to which the comment applies. + -- position: The line index in the diff to which the comment applies. end end diff --git a/lua/octo/writers.lua b/lua/octo/writers.lua index 3544ba42..241833ec 100644 --- a/lua/octo/writers.lua +++ b/lua/octo/writers.lua @@ -345,6 +345,7 @@ function M.write_comment(bufnr, comment, line) -- heading line = line or api.nvim_buf_line_count(bufnr) + 1 + local start_line = line M.write_block({"", ""}, {bufnr = bufnr, mark = false, line = line}) local header_vt = { @@ -354,17 +355,15 @@ function M.write_comment(bufnr, comment, line) if comment.comments and comment.state then table.insert(header_vt, {" added a ", "OctoNvimCommentHeading"}) table.insert(header_vt, {comment.state, "OctoNvimCommentValue"}) - table.insert(header_vt, {format(" review (%d comments)", comment.comments.totalCount), "OctoNvimCommentHeading"}) + table.insert(header_vt, {format(" review (%d threads)", comment.comments.totalCount), "OctoNvimCommentHeading"}) else table.insert(header_vt, {" commented", "OctoNvimCommentHeading"}) end local comment_vt_ns = api.nvim_buf_set_virtual_text(bufnr, 0, line - 1, header_vt, {}) - local fold_start_line = line + 2 - -- body - line = fold_start_line + line = line + 2 local comment_body = string.gsub(comment.body, "\r\n", "\n") if vim.startswith(comment_body, constants.NO_BODY_MSG) or util.is_blank(comment_body) then comment_body = " " @@ -400,10 +399,7 @@ function M.write_comment(bufnr, comment, line) ) api.nvim_buf_set_var(bufnr, "comments", comments_metadata) - -- add fold - vim.cmd(format("%d,%dfold", fold_start_line - 1, line)) - vim.cmd(format("%d,%dfoldopen!", fold_start_line - 1, line)) - + return start_line, line end function M.write_diff_hunk(bufnr, diff_hunk, start_line) @@ -482,6 +478,8 @@ function M.write_diff_hunk(bufnr, diff_hunk, start_line) api.nvim_buf_set_virtual_text(bufnr, constants.OCTO_DETAILS_VT_NS, line, vt_line, {}) line = line + 1 end + + return start_line, line end return M From d68620696aeb5fe85260d9b0aa10ba16560f67e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Thu, 25 Feb 2021 14:40:32 +0100 Subject: [PATCH 04/27] multifold suppport + thread header stub --- lua/octo/folds.lua | 2 +- lua/octo/graphql.lua | 2 ++ lua/octo/init.lua | 28 +++++++++++++--------------- lua/octo/writers.lua | 2 +- plugin/octo.vim | 8 +++++++- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/lua/octo/folds.lua b/lua/octo/folds.lua index 12b36c42..9417b1ab 100644 --- a/lua/octo/folds.lua +++ b/lua/octo/folds.lua @@ -8,7 +8,7 @@ function M.create(start_line, end_line, is_opened) print("Creating fold from", start_line, "to", end_line) vim.cmd(string.format("%d,%dfold", start_line, end_line)) if is_opened then - vim.cmd(string.format("%d,%dfoldopen!", start_line, end_line)) + vim.cmd(string.format("%d,%dfoldopen", start_line, end_line)) end end diff --git a/lua/octo/graphql.lua b/lua/octo/graphql.lua index ba34d753..948c0de7 100644 --- a/lua/octo/graphql.lua +++ b/lua/octo/graphql.lua @@ -275,6 +275,7 @@ query($endCursor: String) { nodes { id isResolved + isCollapsed isOutdated path resolvedBy { login } @@ -404,6 +405,7 @@ query($endCursor: String) { nodes { id isResolved + isCollapsed isOutdated path resolvedBy { login } diff --git a/lua/octo/init.lua b/lua/octo/init.lua index ef25547e..a73f71ea 100644 --- a/lua/octo/init.lua +++ b/lua/octo/init.lua @@ -166,7 +166,7 @@ function M.create_buffer(type, obj, repo, create) vim.cmd [[setlocal foldtext=v:lua.OctoFoldText()]] vim.cmd [[setlocal foldmethod=manual]] vim.cmd [[setlocal foldenable]] - vim.cmd [[setlocal foldcolumn=1]] + vim.cmd [[setlocal foldcolumn=3]] vim.cmd [[setlocal foldlevelstart=99]] -- register issue @@ -245,17 +245,6 @@ function M.create_buffer(type, obj, repo, create) end end - -- --- 3) collect reviewThreads - -- if obj.reviewThreads then - -- for _, reviewThread in ipairs(obj.reviewThreads.nodes) do - -- table.insert(items, { - -- createdAt = reviewThread.comments.nodes[1].createdAt, - -- type = "reviewThread", - -- item = reviewThread - -- }) - -- end - -- end - -- sort items table.sort(items, function (i1, i2) return date(i1.createdAt) < date(i2.createdAt) @@ -283,17 +272,26 @@ function M.create_buffer(type, obj, repo, create) if #threads > 0 then -- print review header and top level comment - writers.write_comment(bufnr, item.item) + local review_start, review_end = writers.write_comment(bufnr, item.item) -- print each of the threads for _, thread in ipairs(threads) do + local thread_start, thread_end for _,comment in ipairs(thread.comments.nodes) do if comment.replyTo == vim.NIL then - writers.write_diff_hunk(bufnr, comment.diffHunk) + -- TODO: prettify and use virtual text + local header = format("%s (outdated:%s) (collapsed:%s) (resolved:%s) (lines:%s-%s)", thread.path, thread.isOutdated, thread.isCollapsed, thread.isResolved, thread.startLine, thread.line) + writers.write_block({header}, {bufnr = bufnr, mark = false }) + thread_start, thread_end = writers.write_diff_hunk(bufnr, comment.diffHunk) end - writers.write_comment(bufnr, comment) + local comment_start, comment_end = writers.write_comment(bufnr, comment) + folds.create(comment_start+1, comment_end, true) + thread_end = comment_end + review_end = comment_end end + folds.create(thread_start-1, thread_end, thread.isCollapsed) end + folds.create(review_start+1, review_end, true) end -- interesting PullRequestReviewComment fields: diff --git a/lua/octo/writers.lua b/lua/octo/writers.lua index 241833ec..80f2b728 100644 --- a/lua/octo/writers.lua +++ b/lua/octo/writers.lua @@ -419,7 +419,7 @@ function M.write_diff_hunk(bufnr, diff_hunk, start_line) max_length = #l end end - max_length = math.max(max_length, vim.fn.winwidth(0) - 8) + max_length = math.max(max_length, vim.fn.winwidth(0) - 10 - vim.wo.foldcolumn) vim.list_extend(empty_lines, {"", "", ""}) M.write_block(empty_lines, {bufnr = bufnr, mark = false, line = start_line}) diff --git a/plugin/octo.vim b/plugin/octo.vim index 00720ab6..27e70d72 100644 --- a/plugin/octo.vim +++ b/plugin/octo.vim @@ -64,8 +64,14 @@ function s:configure_octo_buffer() abort if match(bufname(), "octo://.\\+/.\\+/pull/\\d\\+/file/") == -1 setlocal omnifunc=octo#issue_complete setlocal nonumber norelativenumber nocursorline wrap - setlocal foldcolumn=1 + setlocal foldcolumn=3 setlocal signcolumn=yes + setlocal fillchars=fold:⠀,foldopen:⠀,foldclose:⠀,foldsep:⠀ + setlocal foldtext=v:lua.OctoFoldText() + setlocal foldmethod=manual + setlocal foldenable + setlocal foldcolumn=3 + setlocal foldlevelstart=99 end endfunction From 1bdf9bdfd9a057b781ee8826af9342c592df76a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Thu, 25 Feb 2021 17:17:29 +0100 Subject: [PATCH 05/27] prettified diff hunk visualization on review threads --- lua/octo/folds.lua | 1 - lua/octo/graphql.lua | 8 ++--- lua/octo/init.lua | 6 ++-- lua/octo/writers.lua | 85 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 84 insertions(+), 16 deletions(-) diff --git a/lua/octo/folds.lua b/lua/octo/folds.lua index 9417b1ab..54de722c 100644 --- a/lua/octo/folds.lua +++ b/lua/octo/folds.lua @@ -5,7 +5,6 @@ end local M = {} function M.create(start_line, end_line, is_opened) - print("Creating fold from", start_line, "to", end_line) vim.cmd(string.format("%d,%dfold", start_line, end_line)) if is_opened then vim.cmd(string.format("%d,%dfoldopen", start_line, end_line)) diff --git a/lua/octo/graphql.lua b/lua/octo/graphql.lua index 948c0de7..e0aceafa 100644 --- a/lua/octo/graphql.lua +++ b/lua/octo/graphql.lua @@ -283,6 +283,7 @@ query($endCursor: String) { originalLine startLine originalStartLine + diffSide comments(first: 100, after: $endCursor) { nodes{ id @@ -294,9 +295,6 @@ query($endCursor: String) { replyTo { id } author { login } authorAssociation - originalPosition - position - state outdated diffHunk reactions(last:20) { @@ -413,6 +411,7 @@ query($endCursor: String) { originalLine startLine originalStartLine + diffSide comments(first: 100) { nodes{ id @@ -424,9 +423,6 @@ query($endCursor: String) { } author { login } authorAssociation - originalPosition - position - state outdated diffHunk reactions(last:20) { diff --git a/lua/octo/init.lua b/lua/octo/init.lua index a73f71ea..674f347d 100644 --- a/lua/octo/init.lua +++ b/lua/octo/init.lua @@ -280,16 +280,16 @@ function M.create_buffer(type, obj, repo, create) for _,comment in ipairs(thread.comments.nodes) do if comment.replyTo == vim.NIL then -- TODO: prettify and use virtual text - local header = format("%s (outdated:%s) (collapsed:%s) (resolved:%s) (lines:%s-%s)", thread.path, thread.isOutdated, thread.isCollapsed, thread.isResolved, thread.startLine, thread.line) + local header = format("%s (outdated:%s) (collapsed:%s) (resolved:%s) (lines:%s-%s %s)", thread.path, thread.isOutdated, thread.isCollapsed, thread.isResolved, thread.originalStartLine, thread.originalLine, thread.diffSide) writers.write_block({header}, {bufnr = bufnr, mark = false }) - thread_start, thread_end = writers.write_diff_hunk(bufnr, comment.diffHunk) + thread_start, thread_end = writers.write_commented_lines(bufnr, comment.diffHunk, thread.diffSide, thread.originalStartLine, thread.originalLine) end local comment_start, comment_end = writers.write_comment(bufnr, comment) folds.create(comment_start+1, comment_end, true) thread_end = comment_end review_end = comment_end end - folds.create(thread_start-1, thread_end, thread.isCollapsed) + folds.create(thread_start-1, thread_end, not thread.isCollapsed) end folds.create(review_start+1, review_end, true) end diff --git a/lua/octo/writers.lua b/lua/octo/writers.lua index 80f2b728..d90e490b 100644 --- a/lua/octo/writers.lua +++ b/lua/octo/writers.lua @@ -402,7 +402,7 @@ function M.write_comment(bufnr, comment, line) return start_line, line end -function M.write_diff_hunk(bufnr, diff_hunk, start_line) +function M.write_diff_hunk(bufnr, diff_hunk, start_line, marker) start_line = start_line or api.nvim_buf_line_count(bufnr) + 1 -- clear virtual texts @@ -425,13 +425,15 @@ function M.write_diff_hunk(bufnr, diff_hunk, start_line) local vt_lines = {} table.insert(vt_lines, {{format("┌%s┐", string.rep("─", max_length + 2))}}) - for _, line in ipairs(lines) do + for i, line in ipairs(lines) do + + local arrow = i == marker and ">" or " " if vim.startswith(line, "@@ ") then local index = string.find(line, "@[^@]*$") table.insert( vt_lines, { - {"│ "}, + {"│"..arrow}, {string.sub(line, 0, index), "DiffLine"}, {string.sub(line, index + 1), "DiffSubname"}, {string.rep(" ", 1 + max_length - #line)}, @@ -442,7 +444,7 @@ function M.write_diff_hunk(bufnr, diff_hunk, start_line) table.insert( vt_lines, { - {"│ "}, + {"│"..arrow}, {line, "DiffAdd"}, {string.rep(" ", max_length - #line)}, {" │"} @@ -452,7 +454,7 @@ function M.write_diff_hunk(bufnr, diff_hunk, start_line) table.insert( vt_lines, { - {"│ "}, + {"│"..arrow}, {line, "DiffDelete"}, {string.rep(" ", max_length - #line)}, {" │"} @@ -462,7 +464,7 @@ function M.write_diff_hunk(bufnr, diff_hunk, start_line) table.insert( vt_lines, { - {"│ "}, + {"│"..arrow}, {line}, {string.rep(" ", max_length - #line)}, {" │"} @@ -482,4 +484,75 @@ function M.write_diff_hunk(bufnr, diff_hunk, start_line) return start_line, line end +function M.write_commented_lines(bufnr, diff_hunk, side, start_pos, end_pos, start_line) + start_line = start_line or api.nvim_buf_line_count(bufnr) + 1 + + start_pos = start_pos ~= vim.NIL and start_pos or end_pos + + -- clear virtual texts + api.nvim_buf_clear_namespace(bufnr, constants.OCTO_DIFFHUNKS_VT_NS, 0, start_line - 1) + + local lines = vim.split(diff_hunk, "\n") + + -- print end_pos - start_pos + 2 empty lines + local empty_lines = {} + for _=1,(end_pos-start_pos+2) do + table.insert(empty_lines, "") + end + local diff_directive = lines[1] + local side_lines = {} + for i=2,#lines do + local line = lines[i] + if vim.startswith(line, "+") and side == "RIGHT" then + table.insert(side_lines, line) + elseif vim.startswith(line, "-") and side == "LEFT" then + table.insert(side_lines, line) + elseif not vim.startswith(line, "-") and not vim.startswith(line, "+") then + table.insert(side_lines, line) + end + end + + local max_length = -1 + for _, line in ipairs(side_lines) do + max_length = math.max(max_length, #line) + end + max_length = math.min(max_length, vim.fn.winwidth(0) - 10 - vim.wo.foldcolumn) + 1 + + vim.list_extend(empty_lines, {"", ""}) + M.write_block(empty_lines, {bufnr = bufnr, mark = false, line = start_line}) + + local left_offset, right_offset = string.match(diff_directive, "@@%s%-(%d+),%d+%s%+(%d+),%d+%s@@") + local offset = side == "RIGHT" and right_offset or left_offset + local final_lines = {unpack(side_lines, start_pos - offset + 1, end_pos - offset + 1)} + local vt_lines = {} + table.insert(vt_lines, {{format("┌%s┐", string.rep("─", max_length + 2))}}) + for _, line in ipairs(final_lines) do + local hl_line, vt_line, fill + local stripped_line = line:gsub("^.", "") + if vim.startswith(line, "+") then + hl_line = "DiffAdd" + elseif vim.startswith(line, "-") then + hl_line = "DiffDelete" + end + if #stripped_line == 0 or not hl_line then + vt_line = {stripped_line} + fill = string.rep(" ", max_length - #stripped_line - 1) + else + vt_line = {stripped_line, hl_line} + fill = string.rep(" ", max_length - #stripped_line) + end + table.insert( vt_lines, { {"│ "}, vt_line, {fill}, {" │"} }) + end + table.insert(vt_lines, {{format("└%s┘", string.rep("─", max_length + 2))}}) + + -- print diff_hunk as virtual text + local line = start_line - 1 + for _, vt_line in ipairs(vt_lines) do + api.nvim_buf_set_virtual_text(bufnr, constants.OCTO_DETAILS_VT_NS, line, vt_line, {}) + line = line + 1 + end + + return start_line, line +end + return M From c2a7240e9c547d0ee7b07c253491a25d3e07d314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Fri, 26 Feb 2021 00:13:02 +0100 Subject: [PATCH 06/27] pretify thread header --- lua/octo/constants.lua | 1 + lua/octo/init.lua | 18 ++++++-- lua/octo/reviews.lua | 14 ++++-- lua/octo/writers.lua | 101 ++++++++++++++++++++++++++++------------- 4 files changed, 95 insertions(+), 39 deletions(-) diff --git a/lua/octo/constants.lua b/lua/octo/constants.lua index dc02828d..4482f0b6 100644 --- a/lua/octo/constants.lua +++ b/lua/octo/constants.lua @@ -9,6 +9,7 @@ M.OCTO_DETAILS_VT_NS = api.nvim_create_namespace("octo_details_vt") M.OCTO_DIFFHUNKS_VT_NS = api.nvim_create_namespace("octo_diffhunks_vt") M.OCTO_EMPTY_MSG_VT_NS = api.nvim_create_namespace("octo_empty_msg_vt") M.OCTO_HIGHLIGHT_NS = api.nvim_create_namespace("octo_highlight") +M.OCTO_THREAD_HEADER_VT_NS = api.nvim_create_namespace("octo_thread_header_vt") M.NO_BODY_MSG = "No description provided." return M diff --git a/lua/octo/init.lua b/lua/octo/init.lua index 674f347d..88fdb31c 100644 --- a/lua/octo/init.lua +++ b/lua/octo/init.lua @@ -279,10 +279,20 @@ function M.create_buffer(type, obj, repo, create) local thread_start, thread_end for _,comment in ipairs(thread.comments.nodes) do if comment.replyTo == vim.NIL then - -- TODO: prettify and use virtual text - local header = format("%s (outdated:%s) (collapsed:%s) (resolved:%s) (lines:%s-%s %s)", thread.path, thread.isOutdated, thread.isCollapsed, thread.isResolved, thread.originalStartLine, thread.originalLine, thread.diffSide) - writers.write_block({header}, {bufnr = bufnr, mark = false }) - thread_start, thread_end = writers.write_commented_lines(bufnr, comment.diffHunk, thread.diffSide, thread.originalStartLine, thread.originalLine) + + -- review thread header + local start_line = thread.originalStartLine ~= vim.NIL and thread.originalStartLine or thread.originalLine + local end_line = thread.originalLine + writers.write_review_thread_header(bufnr, { + path = thread.path, + start_line = start_line, + end_line = end_line, + isOutdated = thread.isOutdated, + isResolved = thread.isResolved, + }) + + -- write diff lines + thread_start, thread_end = writers.write_commented_lines(bufnr, comment.diffHunk, thread.diffSide, start_line, end_line) end local comment_start, comment_end = writers.write_comment(bufnr, comment) folds.create(comment_start+1, comment_end, true) diff --git a/lua/octo/reviews.lua b/lua/octo/reviews.lua index 0ab4cae9..53ca84b0 100644 --- a/lua/octo/reviews.lua +++ b/lua/octo/reviews.lua @@ -572,12 +572,18 @@ function M.show_reviewthread_qf_entry(repo, number, main_win) M.add_reviewthread_qf_mappings(repo, number, main_win) octo.apply_buffer_mappings(comment_bufnr, "reviewthread") - -- write path - writers.write_title(comment_bufnr, reviewthread.path, 1) - -- write diff hunk local main_comment = reviewthread.comments.nodes[1] - writers.write_diff_hunk(comment_bufnr, main_comment.diffHunk, 3) + local start_line = reviewthread.originalStartLine ~= vim.NIL and reviewthread.originalStartLine or reviewthread.originalLine + local end_line = reviewthread.originalLine + writers.write_review_thread_header(comment_bufnr, { + path = reviewthread.path, + start_line = start_line, + end_line = end_line, + isOutdated = reviewthread.isOutdated, + isResolved = reviewthread.isResolved + }) + writers.write_commented_lines(comment_bufnr, main_comment.diffHunk, reviewthread.diffSide, start_line, end_line) -- write thread api.nvim_buf_set_var(comment_bufnr, "comments", {}) diff --git a/lua/octo/writers.lua b/lua/octo/writers.lua index d90e490b..fbbb3c79 100644 --- a/lua/octo/writers.lua +++ b/lua/octo/writers.lua @@ -140,17 +140,18 @@ function M.write_reactions(bufnr, reactions, line) end if reaction_map.totalCount > 0 then - local reactions_vt = {} + local reactions_vt for reaction, count in pairs(reaction_map) do local content = util.reaction_map[reaction] if content and count > 0 then - table.insert(reactions_vt, {"", "OctoNvimBubbleDelimiter"}) - table.insert(reactions_vt, {content, "OctoNvimBubbleBody"}) - table.insert(reactions_vt, {"", "OctoNvimBubbleDelimiter"}) - table.insert(reactions_vt, {format(" %s ", count), "Normal"}) + reactions_vt = { + {"", "OctoNvimBubbleDelimiter"}, + {content, "OctoNvimBubbleBody"}, + {"", "OctoNvimBubbleDelimiter"}, + {format(" %s ", count), "Normal"} + } end end - api.nvim_buf_set_virtual_text(bufnr, constants.OCTO_REACTIONS_VT_NS, line - 1, reactions_vt, {}) end return line @@ -336,7 +337,8 @@ function M.write_details(bufnr, issue, update) -- print details as virtual text for _, d in ipairs(details) do - api.nvim_buf_set_virtual_text(bufnr, constants.OCTO_DETAILS_VT_NS, line - 1, d, {}) + --api.nvim_buf_set_virtual_text(bufnr, constants.OCTO_DETAILS_VT_NS, line - 1, d, {}) + api.nvim_buf_set_extmark(bufnr, constants.OCTO_DETAILS_VT_NS, line - 1, 0, { virt_text=d, virt_text_pos='overlay'}) line = line + 1 end end @@ -348,19 +350,33 @@ function M.write_comment(bufnr, comment, line) local start_line = line M.write_block({"", ""}, {bufnr = bufnr, mark = false, line = line}) - local header_vt = { - {format("On %s ", util.format_date(comment.createdAt)), "OctoNvimCommentHeading"}, - {comment.author.login, "OctoNvimCommentUser"}, - } + local header_vt if comment.comments and comment.state then - table.insert(header_vt, {" added a ", "OctoNvimCommentHeading"}) - table.insert(header_vt, {comment.state, "OctoNvimCommentValue"}) - table.insert(header_vt, {format(" review (%d threads)", comment.comments.totalCount), "OctoNvimCommentHeading"}) + -- Review comments + header_vt = { + {"REVIEW: ", "OctoNvimMissingDetails"}, + {comment.author.login.." ", "OctoNvimCommentUser"}, + {comment.state:lower().." ", "OctoNvimDetailsValue"}, + {"(", "OctoNvimCommentHeading"}, + {util.format_date(comment.createdAt), "OctoNvimMissingDetails"}, + {")", "OctoNvimCommentHeading"} + } else - table.insert(header_vt, {" commented", "OctoNvimCommentHeading"}) + -- Issue comments + header_vt = { + {format("On %s ", util.format_date(comment.createdAt)), "OctoNvimCommentHeading"}, + {comment.author.login, "OctoNvimCommentUser"}, + {" commented", "OctoNvimCommentHeading"} + } end + --local comment_vt_ns = api.nvim_buf_set_virtual_text(bufnr, 0, line - 1, header_vt, {}) + local comment_vt_ns = api.nvim_create_namespace("") + api.nvim_buf_set_extmark(bufnr, comment_vt_ns, line - 1, 0, { virt_text=header_vt, virt_text_pos='overlay'}) - local comment_vt_ns = api.nvim_buf_set_virtual_text(bufnr, 0, line - 1, header_vt, {}) + if comment.comments and comment.state and util.is_blank(comment.body) then + -- do not render empty review comments + return start_line, start_line+1 + end -- body line = line + 2 @@ -496,7 +512,7 @@ function M.write_commented_lines(bufnr, diff_hunk, side, start_pos, end_pos, sta -- print end_pos - start_pos + 2 empty lines local empty_lines = {} - for _=1,(end_pos-start_pos+2) do + for _=1,(end_pos-start_pos+4) do table.insert(empty_lines, "") end local diff_directive = lines[1] @@ -511,39 +527,39 @@ function M.write_commented_lines(bufnr, diff_hunk, side, start_pos, end_pos, sta table.insert(side_lines, line) end end - local max_length = -1 for _, line in ipairs(side_lines) do max_length = math.max(max_length, #line) end max_length = math.min(max_length, vim.fn.winwidth(0) - 10 - vim.wo.foldcolumn) + 1 - vim.list_extend(empty_lines, {"", ""}) M.write_block(empty_lines, {bufnr = bufnr, mark = false, line = start_line}) local left_offset, right_offset = string.match(diff_directive, "@@%s%-(%d+),%d+%s%+(%d+),%d+%s@@") local offset = side == "RIGHT" and right_offset or left_offset local final_lines = {unpack(side_lines, start_pos - offset + 1, end_pos - offset + 1)} local vt_lines = {} - table.insert(vt_lines, {{format("┌%s┐", string.rep("─", max_length + 2))}}) - for _, line in ipairs(final_lines) do - local hl_line, vt_line, fill + local max_lnum = math.max(#tostring(start_pos), #tostring(end_pos)) + table.insert(vt_lines, {{format("┌%s┐", string.rep("─", max_lnum + max_length + 2))}}) + for i, line in ipairs(final_lines) do local stripped_line = line:gsub("^.", "") - if vim.startswith(line, "+") then - hl_line = "DiffAdd" - elseif vim.startswith(line, "-") then - hl_line = "DiffDelete" - end + local hl_line = side == "RIGHT" and "DiffAdd" or "DiffDelete" + local vt_line = {stripped_line, hl_line} + local fill if #stripped_line == 0 or not hl_line then - vt_line = {stripped_line} fill = string.rep(" ", max_length - #stripped_line - 1) else - vt_line = {stripped_line, hl_line} fill = string.rep(" ", max_length - #stripped_line) end - table.insert( vt_lines, { {"│ "}, vt_line, {fill}, {" │"} }) + table.insert( vt_lines, { + {"│"}, + {" "..tostring(i + start_pos - 1).." ", "DiffChange"}, + vt_line, + {fill, hl_line}, + {"│"} + }) end - table.insert(vt_lines, {{format("└%s┘", string.rep("─", max_length + 2))}}) + table.insert(vt_lines, {{format("└%s┘", string.rep("─", max_lnum + max_length + 2))}}) -- print diff_hunk as virtual text local line = start_line - 1 @@ -555,4 +571,27 @@ function M.write_commented_lines(bufnr, diff_hunk, side, start_pos, end_pos, sta return start_line, line end +function M.write_review_thread_header(bufnr, opts) + local line = api.nvim_buf_line_count(bufnr) - 1 + local header_vt = { + {"[", "OctoNvimMissingDetails"}, + {opts.path.." ", "OctoNvimDetailsLabel"}, + {tostring(opts.start_line)..":"..tostring(opts.end_line), "OctoNvimDetailsValue"}, + {"]", "OctoNvimMissingDetails"}, + } + if opts.isOutdated then + table.insert(header_vt, {"", "OctoNvimBubbleDelimiter"}) + table.insert(header_vt, {"outdated", "OctoNvimBubbleRed"}) + table.insert(header_vt, {" ", "OctoNvimBubbleDelimiter"}) + end + if opts.isResolved then + table.insert(header_vt, {"", "OctoNvimBubbleDelimiter"}) + table.insert(header_vt, {"resolved", "OctoNvimBubbleGreen"}) + table.insert(header_vt, {" ", "OctoNvimBubbleDelimiter"}) + end + M.write_block({""}, {bufnr = bufnr, mark = false }) + --api.nvim_buf_set_virtual_text(bufnr, constants.OCTO_REACTIONS_VT_NS, line + 1, header_vt, {}) + api.nvim_buf_set_extmark(bufnr, constants.OCTO_THREAD_HEADER_VT_NS, line + 1, 0, { virt_text=header_vt, virt_text_pos='overlay'}) +end + return M From 60971066b70fffd375092d5c49a019e252780ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Sat, 27 Feb 2021 00:18:18 +0100 Subject: [PATCH 07/27] update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4cd48f07..acd7200d 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,8 @@ There is only an `Octo [arguments]` command: | gist | list | [repo] [key=value]*
[Available keys](https://cli.github.com/manual/gh_gist_list): `repo`\|`public`\|`secret`
Mappings:
``: Append Gist to buffer
``: Opens Gist in web browser | | comment | add | | | | delete | | -| | resolve | | -| | unresolve | | +| thread | resolve| Mark a review thread as resolved | +| | unresolve | Mark a review thread as unresolved | | label | add |