Skip to content

Commit

Permalink
feat #59 & feat #81
Browse files Browse the repository at this point in the history
  • Loading branch information
tanvirtin committed Aug 16, 2021
1 parent 01ab01f commit 3bf5dd5
Show file tree
Hide file tree
Showing 14 changed files with 853 additions and 139 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,17 @@ require('vgit').setup({
remove = 'VGitViewSignRemove',
},
},
hunk_lens = {
priority = 10,
window = {
border = { '', '', '', '', '', '', '', '' },
border_hl = 'VGitBorder',
},
signs = {
add = 'VGitViewSignAdd',
remove = 'VGitViewSignRemove',
},
},
hunk_sign = {
priority = 10,
signs = {
Expand Down Expand Up @@ -411,6 +422,7 @@ vim.api.nvim_set_keymap('n', '<leader>gq', ':VGit hunks_quickfix_list<CR>', {
| unstage_buffer | Unstages a buffer you are currently on |
| staged_buffer_preview | Shows staged changes in a preview window |
| buffer_preview | Shows the current differences in lines in the current buffer |
| buffer_hunk_lens | Gives you a lens view through which you can navigate and see the current hunk or other hunks, this is similar to buffer preview, also an alternate for hunk_preview |
| buffer_history | Opens a buffer preview along with a table of logs, enabling users to see different iterations of the buffer in the git history |
| buffer_reset | Resets the current buffer to HEAD |
| hunks_quickfix_list | Opens a populated quickfix window with all the hunks of the project |
Expand Down
35 changes: 34 additions & 1 deletion lua/vgit/HistoryPopup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ local function colorize_buf(lnum_changes, callback)
end

local function colorize_indicator(buf, lnum, namespace)
highlighter.highlight(buf, namespace, state:get('indicator').hl, { lnum, 0 }, { lnum, 1 })
highlighter.highlight(buf, namespace, state:get('indicator').hl, lnum, 0, 1)
end

local function create_history_lines(logs, selected)
Expand Down Expand Up @@ -265,9 +265,27 @@ local function new(opts)
layout_type = opts.layout_type,
history_namespace = vim.api.nvim_create_namespace('tanvirtin/vgit.nvim/history'),
selected = 1,
data = nil,
err = nil,
}, HistoryPopup)
end

function HistoryPopup:get_data()
return self.data
end

function HistoryPopup:get_preview_win_ids()
local widget = self.horizontal_widget
if self.layout_type == 'vertical' then
widget = self.vertical_widget
return {
widget:get_views().previous:get_win_id(),
widget:get_views().current:get_win_id(),
}
end
return { widget:get_views().preview:get_win_id() }
end

function HistoryPopup:get_name()
local widget = self.horizontal_widget
if self.layout_type == 'vertical' then
Expand Down Expand Up @@ -302,6 +320,18 @@ function HistoryPopup:set_error(value)
return self
end

function HistoryPopup:is_preview_focused()
local preview_win_ids = self:get_preview_win_ids()
local current_win_id = vim.api.nvim_get_current_win()
for i = 1, #preview_win_ids do
local win_id = preview_win_ids[i]
if win_id == current_win_id then
return true
end
end
return false
end

function HistoryPopup:mount()
local widget = self.horizontal_widget
if self.layout_type == 'vertical' then
Expand Down Expand Up @@ -352,6 +382,7 @@ function HistoryPopup:render()
if self.layout_type == 'horizontal' then
views.preview:set_cursor(1, 0)
views.preview:set_lines(data.lines)
sign.unplace(views.preview:get_buf())
colorize_buf(data.lnum_changes, function()
return views.preview:get_buf()
end)
Expand All @@ -360,6 +391,8 @@ function HistoryPopup:render()
views.current:set_cursor(1, 0)
views.previous:set_lines(data.previous_lines)
views.current:set_lines(data.current_lines)
sign.unplace(views.previous:get_buf())
sign.unplace(views.current:get_buf())
colorize_buf(data.lnum_changes, function(datum)
return views[datum.buftype]:get_buf()
end)
Expand Down
185 changes: 185 additions & 0 deletions lua/vgit/HunkLensPopup.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
local Interface = require('vgit.Interface')
local View = require('vgit.View')
local Widget = require('vgit.Widget')
local sign = require('vgit.sign')

local vim = vim

local HunkLensPopup = {}
HunkLensPopup.__index = HunkLensPopup

local state = Interface.new({
priority = 10,
window = {
border = { '', '', '', '', '', '', '', '' },
border_hl = 'VGitBorder',
},
signs = {
add = 'VGitViewSignAdd',
remove = 'VGitViewSignRemove',
},
})

local function setup(config)
state:assign(config)
end

local function colorize_buf(lnum_changes, callback)
for i = 1, #lnum_changes do
local datum = lnum_changes[i]
sign.place(callback(datum), datum.lnum, state:get('signs')[datum.type], state:get('priority'))
end
end

local function new(opts)
return setmetatable({
widget = Widget.new({
View.new({
border = state:get('window').border,
border_hl = state:get('window').border_hl,
win_options = { ['cursorline'] = true },
window_props = {
style = 'minimal',
relative = 'cursor',
width = vim.api.nvim_get_option('columns'),
row = 0,
col = 0,
},
filetype = opts.filetype,
}),
}, {
name = 'hunk_lens',
popup = true,
}),
data = {
-- TODO: NEED TO BE A defined DTO
lines = {},
current_lines = {},
previous_lines = {},
hunk = { diff = {} },
hunks = {},
lnum_changes = {},
marks = {},
},
err = nil,
}, HunkLensPopup)
end

function HunkLensPopup:get_name()
return self.widget:get_name()
end

function HunkLensPopup:get_data()
return self.data
end

function HunkLensPopup:get_preview_win_ids()
return { self.widget:get_views()[1]:get_win_id() }
end

function HunkLensPopup:get_win_ids()
return self.widget:get_win_ids()
end

function HunkLensPopup:set_loading(value)
self.widget:set_loading(value)
return self
end

function HunkLensPopup:set_error(value)
self.widget:set_error(value)
return self
end

function HunkLensPopup:set_cursor(row, col)
self.widget:get_views()[1]:set_cursor(row, col)
return self
end

function HunkLensPopup:is_preview_focused()
local preview_win_ids = self:get_preview_win_ids()
local current_win_id = vim.api.nvim_get_current_win()
for i = 1, #preview_win_ids do
local win_id = preview_win_ids[i]
if win_id == current_win_id then
return true
end
end
return false
end

function HunkLensPopup:reposition_cursor(lnum)
local new_lines_added = 0
for i = 1, #self.data.hunks do
local hunk = self.data.hunks[i]
local type = hunk.type
local diff = hunk.diff
local current_new_lines_added = 0
if type == 'remove' then
for _ = 1, #diff do
current_new_lines_added = current_new_lines_added + 1
end
elseif type == 'change' then
for j = 1, #diff do
local line = diff[j]
local line_type = line:sub(1, 1)
if line_type == '-' then
current_new_lines_added = current_new_lines_added + 1
end
end
end
new_lines_added = new_lines_added + current_new_lines_added
local start = hunk.start + new_lines_added
local finish = hunk.finish + new_lines_added
local padded_lnum = lnum + new_lines_added
if padded_lnum >= start and padded_lnum <= finish then
if type == 'remove' then
self:set_cursor(start - current_new_lines_added + 1, 0)
else
self:set_cursor(start - current_new_lines_added, 0)
end
vim.cmd('norm! zt')
break
end
end
end

function HunkLensPopup:mount()
self.widget:mount(true)
return self
end

function HunkLensPopup:unmount()
self.widget:unmount()
return self
end

function HunkLensPopup:render()
local err, data = self.err, self.data
if err then
self.widget:set_error(true)
return self
end
if data then
local views = self.widget:get_views()
local v = views[1]
v:set_lines(data.lines)
local new_width = #data.hunk.diff
if new_width ~= 0 then
if new_width > v:get_min_height() then
v:set_height(new_width)
else
v:set_height(v:get_min_height())
end
end
colorize_buf(data.lnum_changes, function()
return v:get_buf()
end)
end
return self
end

return {
new = new,
setup = setup,
}
38 changes: 38 additions & 0 deletions lua/vgit/ImmutableInterface.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
local assert = require('vgit.assertion').assert

local ImmutableInterface = {}
ImmutableInterface.__index = ImmutableInterface

local function readonly(tbl)
return setmetatable({}, {
__index = function(_, k)
return tbl[k]
end,
__newindex = function()
error('Table is readonly.')
end,
__metatable = {},
__len = function()
return #tbl
end,
__tostring = function()
return tostring(tbl)
end,
__call = function(_, ...)
return tbl(...)
end,
})
end

local function new(state)
assert(type(state) == 'table', 'type error :: expected table')
return setmetatable({ data = readonly(state) }, ImmutableInterface)
end

function ImmutableInterface:get(key)
assert(type(key) == 'string', 'type error :: expected string')
assert(self.data[key] ~= nil, string.format('key "%s" does not exist', key))
return self.data[key]
end

return { new = new }
30 changes: 30 additions & 0 deletions lua/vgit/PopupManager.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
local PopupManager = {}
PopupManager.__index = PopupManager

local function new()
return setmetatable({ current = {} }, PopupManager)
end

function PopupManager:get()
return self.current
end

function PopupManager:set(popup)
assert(type(popup) == 'table', 'type error :: expected table')
self.current = popup
return self
end

function PopupManager:exists()
return not vim.tbl_isempty(self:get())
end

function PopupManager:clear()
if self:exists() then
self:get():unmount()
self.current = {}
end
return self
end

return { new = new }
Loading

0 comments on commit 3bf5dd5

Please sign in to comment.