chore: format with stylua

This commit is contained in:
smjonas 2022-07-09 15:51:06 +02:00
parent 6863ccf6be
commit f7ec0ac130
62 changed files with 2017 additions and 1790 deletions

6
.stylua.toml Normal file
View file

@ -0,0 +1,6 @@
column_width = 110
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferDouble"
call_parentheses = "NoSingleTable"

View file

@ -5,10 +5,12 @@
--
-- The module returns true if everything went well, or false if any part of
-- the initialization failed.
local res, err = pcall(require, 'plenary')
local res, err = pcall(require, "plenary")
if not res then
print("WARNING: Neogit depends on `nvim-lua/plenary.nvim` to work, but loading the plugin failed!")
print("Make sure you add `nvim-lua/plenary.nvim` to your plugin manager BEFORE neogit for everything to work")
print(
"Make sure you add `nvim-lua/plenary.nvim` to your plugin manager BEFORE neogit for everything to work"
)
print(err) -- TODO: find out how to print the error without raising it AND properly print tabs
return false
end

View file

@ -1,5 +1,5 @@
local Buffer = require("neogit.lib.buffer")
local ui = require 'neogit.buffers.branch_select_view.ui'
local ui = require("neogit.buffers.branch_select_view.ui")
local M = {}
@ -17,7 +17,7 @@ function M.new(branches, action)
local instance = {
action = action,
branches = branches,
buffer = nil
buffer = nil,
}
setmetatable(instance, { __index = M })
@ -45,11 +45,11 @@ function M:open()
end
self:close()
end,
}
},
},
render = function()
return ui.View(self.branches)
end
return ui.View(self.branches)
end,
}
end

View file

@ -1,5 +1,5 @@
local Ui = require 'neogit.lib.ui'
local util = require 'neogit.lib.util'
local Ui = require("neogit.lib.ui")
local util = require("neogit.lib.util")
local row = Ui.row
local text = Ui.text
@ -9,8 +9,8 @@ local M = {}
function M.View(branches)
return map(branches, function(branch_name)
return row{
text(branch_name)
return row {
text(branch_name),
}
end)
end

View file

@ -1,10 +1,10 @@
local Buffer = require("neogit.lib.buffer")
local cli = require 'neogit.lib.git.cli'
local parser = require 'neogit.buffers.commit_view.parsing'
local ui = require 'neogit.buffers.commit_view.ui'
local cli = require("neogit.lib.git.cli")
local parser = require("neogit.buffers.commit_view.parsing")
local ui = require("neogit.buffers.commit_view.ui")
local M = {
instance = nil
instance = nil,
}
-- @class CommitViewBuffer
@ -22,15 +22,15 @@ local M = {
function M.new(commit_id, notify)
local notification
if notify then
local notif = require 'neogit.lib.notification'
notification = notif.create "Parsing commit..."
local notif = require("neogit.lib.notification")
notification = notif.create("Parsing commit...")
end
local instance = {
is_open = false,
commit_info = parser.parse_commit_info(cli.show.format("fuller").args(commit_id).call_sync()),
commit_overview = parser.parse_commit_overview(cli.show.stat.oneline.args(commit_id).call_sync()),
buffer = nil
buffer = nil,
}
if notification then
@ -42,15 +42,12 @@ function M.new(commit_id, notify)
return instance
end
function M:close()
self.is_open = false
self.buffer:close()
self.buffer = nil
end
function M:open()
if M.instance and M.instance.is_open then
M.instance:close()
@ -83,7 +80,7 @@ function M:open()
end,
["BufUnload"] = function()
M.instance.is_open = false
end
end,
},
mappings = {
n = {
@ -106,12 +103,12 @@ function M:open()
self.buffer.ui:update()
end
end
end
}
end,
},
},
render = function()
return ui.CommitView(self.commit_info, self.commit_overview)
end
end,
}
end

View file

@ -1,7 +1,7 @@
local M = {}
local util = require 'neogit.lib.util'
local diff_lib = require('neogit.lib.git.diff')
local util = require("neogit.lib.util")
local diff_lib = require("neogit.lib.git.diff")
-- @class CommitOverviewFile
-- @field path the path to the file relative to the git root
@ -10,18 +10,18 @@ local diff_lib = require('neogit.lib.git.diff')
-- @field deletions deletion count visualized as list of `-`
-- @class CommitOverview
-- @field summary a short summary about what happened
-- @field summary a short summary about what happened
-- @field files a list of CommitOverviewFile
-- @see CommitOverviewFile
local CommitOverview = {}
function M.parse_commit_overview(raw)
local overview = {
summary = util.trim(raw[#raw]),
files = {}
local overview = {
summary = util.trim(raw[#raw]),
files = {},
}
for i=2,#raw-1 do
for i = 2, #raw - 1 do
local file = {}
if raw[i] ~= "" then
file.path, file.changes, file.insertions, file.deletions = raw[i]:match(" (.*)%s+|%s+(%d+) (%+*)(%-*)")
@ -75,7 +75,7 @@ function M.parse_commit_info(raw_info)
info.committer_date = advance():match("CommitDate:%s*(.+)")
info.description = {}
info.diffs = {}
-- skip empty line
advance()

View file

@ -1,8 +1,8 @@
local M = {}
local Ui = require 'neogit.lib.ui'
local util = require 'neogit.lib.util'
local common_ui = require 'neogit.buffers.common'
local Ui = require("neogit.lib.ui")
local util = require("neogit.lib.util")
local common_ui = require("neogit.buffers.common")
local Diff = common_ui.Diff
local text = Ui.text
@ -14,9 +14,9 @@ local intersperse = util.intersperse
function M.OverviewFile(file)
return row.tag("OverviewFile") {
text.highlight("NeogitFilePath")(file.path),
text " | " ,
text(" | "),
text.highlight("Number")(file.changes),
text " " ,
text(" "),
text.highlight("NeogitDiffAdd")(file.insertions),
text.highlight("NeogitDiffDelete")(file.deletions),
}
@ -35,13 +35,13 @@ end
function M.CommitView(info, overview)
return {
M.CommitHeader(info),
text "" ,
text(""),
col(map(info.description, text), { sign = "NeogitCommitViewDescription", tag = "Description" }),
text "",
text(""),
text(overview.summary),
col(map(overview.files, M.OverviewFile), { tag = "OverviewFileList" }),
text "",
col(intersperse(map(info.diffs, Diff), text("")), { tag = "DiffList" })
text(""),
col(intersperse(map(info.diffs, Diff), text("")), { tag = "DiffList" }),
}
end

View file

@ -1,6 +1,6 @@
local Ui = require 'neogit.lib.ui'
local Component = require 'neogit.lib.ui.component'
local util = require 'neogit.lib.util'
local Ui = require("neogit.lib.ui")
local Component = require("neogit.lib.ui.component")
local util = require("neogit.lib.util")
local text = Ui.text
local col = Ui.col
@ -12,11 +12,11 @@ local range = util.range
local M = {}
local diff_add_matcher = vim.regex('^+')
local diff_delete_matcher = vim.regex('^-')
local diff_add_matcher = vim.regex("^+")
local diff_delete_matcher = vim.regex("^-")
M.Diff = Component.new(function(diff)
local hunk_props = map(diff.hunks, function(hunk)
local hunk_props = map(diff.hunks, function(hunk)
local header = diff.lines[hunk.diff_from]
local content = map(range(hunk.diff_from + 1, hunk.diff_to), function(i)
@ -25,13 +25,13 @@ M.Diff = Component.new(function(diff)
return {
header = header,
content = content
content = content,
}
end)
return col.tag("Diff") {
text(diff.kind .. " " .. diff.file),
col.tag("HunkList")(map(hunk_props, M.Hunk))
col.tag("HunkList")(map(hunk_props, M.Hunk)),
}
end)
@ -39,9 +39,9 @@ local HunkLine = Component.new(function(line)
local sign
if diff_add_matcher:match_str(line) then
sign = 'NeogitDiffAdd'
sign = "NeogitDiffAdd"
elseif diff_delete_matcher:match_str(line) then
sign = 'NeogitDiffDelete'
sign = "NeogitDiffDelete"
end
return text(line, { sign = sign })
@ -50,13 +50,13 @@ end)
M.Hunk = Component.new(function(props)
return col.tag("Hunk") {
text.sign("NeogitHunkHeader")(props.header),
col.tag("HunkContent")(map(props.content, HunkLine))
col.tag("HunkContent")(map(props.content, HunkLine)),
}
end)
M.List = Component.new(function(props)
local children = filter(props.items, function(x)
return type(x) == "table"
local children = filter(props.items, function(x)
return type(x) == "table"
end)
if props.separator then
@ -76,25 +76,25 @@ M.Grid = Component.new(function(props)
props = vim.tbl_extend("force", {
gap = 0,
columns = true, -- whether the items represents a list of columns instead of a list of row
items = {}
items = {},
}, props)
if props.columns then
local new_items = {}
local row_count = 0
for i=1,#props.items do
for i = 1, #props.items do
local l = #props.items[i]
if l > row_count then
row_count = l
end
end
for _=1,row_count do
for _ = 1, row_count do
table.insert(new_items, {})
end
for i=1,#props.items do
for j=1,row_count do
local x = props.items[i][j] or text ""
for i = 1, #props.items do
for j = 1, row_count do
local x = props.items[i][j] or text("")
table.insert(new_items[j], x)
end
end
@ -104,18 +104,18 @@ M.Grid = Component.new(function(props)
local rendered = {}
local column_widths = {}
for i=1,#props.items do
for i = 1, #props.items do
local children = {}
if i ~= 1 then
children = map(range(props.gap), function()
return text ""
children = map(range(props.gap), function()
return text("")
end)
end
-- current row
local r = props.items[i]
for j=1,#r do
for j = 1, #r do
local item = r[j]
local c = props.render_item(item)
@ -134,11 +134,11 @@ M.Grid = Component.new(function(props)
rendered[i] = row(children)
end
for i=1,#rendered do
for i = 1, #rendered do
-- current row
local r = rendered[i]
for j=1,#r.children do
for j = 1, #r.children do
local item = r.children[j]
local gap_str = ""
local column_width = column_widths[j]
@ -163,5 +163,4 @@ M.Grid = Component.new(function(props)
return col(rendered)
end)
return M

View file

@ -1,7 +1,7 @@
local Buffer = require("neogit.lib.buffer")
local Git = require("neogit.lib.git")
local Ui = require 'neogit.lib.ui'
local util = require 'neogit.lib.util'
local Ui = require("neogit.lib.ui")
local util = require("neogit.lib.util")
local map = util.map
@ -16,7 +16,7 @@ function GitCommandHistory:new(state)
local this = {
buffer = nil,
state = state or Git.cli.history,
open = false
open = false,
}
setmetatable(this, self)
@ -43,8 +43,8 @@ function GitCommandHistory:show()
c.children[2]:toggle_hidden()
self.buffer.ui:update()
end
end
}
end,
},
},
render = function()
return map(self.state, function(item)
@ -54,19 +54,25 @@ function GitCommandHistory:show()
highlight_code = "NeogitCommandCodeError"
end
return col {
row {
text.highlight(highlight_code)(string.format("%3d", item.code)),
text " ",
row {
text.highlight(highlight_code)(string.format("%3d", item.code)),
text(" "),
text(item.cmd),
text " ",
text(" "),
text.highlight("NeogitCommandTime")(string.format("(%3.3f ms)", item.time)),
text " ",
text.highlight("NeogitCommandTime")(string.format("[%s %d]", is_err and "stderr" or "stdout", is_err and #item.stderr or #item.stdout)),
text(" "),
text.highlight("NeogitCommandTime")(
string.format(
"[%s %d]",
is_err and "stderr" or "stdout",
is_err and #item.stderr or #item.stdout
)
),
},
col
.hidden(true)
.padding_left(" | ")
.highlight("NeogitCommandText")(map(is_err and item.stderr or item.stdout, text))
.highlight("NeogitCommandText")(map(is_err and item.stderr or item.stdout, text)),
}
end)
end,

View file

@ -1,6 +1,6 @@
local Buffer = require("neogit.lib.buffer")
local CommitViewBuffer = require 'neogit.buffers.commit_view'
local ui = require 'neogit.buffers.log_view.ui'
local CommitViewBuffer = require("neogit.buffers.commit_view")
local ui = require("neogit.buffers.log_view.ui")
local M = {}
@ -20,7 +20,7 @@ function M.new(data, show_graph)
is_open = false,
data = data,
show_graph = show_graph,
buffer = nil
buffer = nil,
}
setmetatable(instance, { __index = M })
@ -81,21 +81,21 @@ function M:open()
buffer.ui:update()
buffer:move_cursor(target.position.row_start)
vim.fn.feedkeys "zz"
vim.fn.feedkeys("zz")
end,
["<tab>"] = function()
local stack = self.buffer.ui:get_component_stack_under_cursor()
local c = stack[#stack]
c.children[2]:toggle_hidden()
c.children[2]:toggle_hidden()
self.buffer.ui:update()
vim.fn.feedkeys "zz"
end
}
vim.fn.feedkeys("zz")
end,
},
},
render = function()
return ui.LogView(self.data, self.show_graph)
end
end,
}
end

View file

@ -1,6 +1,6 @@
local Ui = require 'neogit.lib.ui'
local Component = require 'neogit.lib.ui.component'
local util = require 'neogit.lib.util'
local Ui = require("neogit.lib.ui")
local Component = require("neogit.lib.ui.component")
local util = require("neogit.lib.util")
local col = Ui.col
local row = Ui.row
@ -21,46 +21,44 @@ local M = {}
M.Commit = Component.new(function(commit, show_graph)
return col {
row {
text(show_graph
and ("* "):rep(commit.level + 1)
or "* ", { highlight = "Character" }),
text(commit.oid:sub(1, 7), { highlight = "Number" }),
text " ",
text(commit.description[1])
row {
text(show_graph and ("* "):rep(commit.level + 1) or "* ", { highlight = "Character" }),
text(commit.oid:sub(1, 7), { highlight = "Number" }),
text(" "),
text(commit.description[1]),
},
col.hidden(true).padding_left((commit.level + 1) * 2) {
row {
text "Author: ",
text("Author: "),
text(commit.author_name),
text " <",
text(" <"),
text(commit.author_date),
text ">"
text(">"),
},
row {
text "AuthorDate: ",
text(commit.author_date)
text("AuthorDate: "),
text(commit.author_date),
},
row {
text "Commit: ",
text("Commit: "),
text(commit.committer_name),
text " <",
text(" <"),
text(commit.committer_date),
text ">"
text(">"),
},
row {
text "CommitDate: ",
text(commit.committer_date)
text("CommitDate: "),
text(commit.committer_date),
},
text " ",
col(map(commit.description, text), { padding_left = 4 })
}
text(" "),
col(map(commit.description, text), { padding_left = 4 }),
},
}
end)
function M.LogView(data, show_graph)
return map(data, function(row)
return M.Commit(row, show_graph)
return M.Commit(row, show_graph)
end)
end

View file

@ -1,5 +1,5 @@
local Buffer = require 'neogit.lib.buffer'
local ui = require 'neogit.buffers.status.ui'
local Buffer = require("neogit.lib.buffer")
local ui = require("neogit.buffers.status.ui")
local M = {}
@ -14,10 +14,10 @@ function M.new(state)
local x = {
is_open = false,
state = state,
buffer = nil
buffer = nil,
}
setmetatable(x, { __index = M })
return x
return x
end
function M:open(kind)
@ -34,7 +34,7 @@ function M:open(kind)
end,
render = function()
return ui.Status(self.state)
end
end,
}
end

View file

@ -1,9 +1,9 @@
local Ui = require 'neogit.lib.ui'
local Component = require 'neogit.lib.ui.component'
local Job = require 'neogit.lib.job'
local difflib = require 'neogit.lib.git.diff'
local util = require 'neogit.lib.util'
local common = require 'neogit.buffers.common'
local Ui = require("neogit.lib.ui")
local Component = require("neogit.lib.ui.component")
local Job = require("neogit.lib.job")
local difflib = require("neogit.lib.git.diff")
local util = require("neogit.lib.util")
local common = require("neogit.buffers.common")
local col = Ui.col
local row = Ui.row
@ -22,16 +22,16 @@ local _mode_to_text = {
D = "Deleted",
C = "Copied",
U = "Updated",
R = "Renamed"
R = "Renamed",
}
local RemoteHeader = Component.new(function(props)
return row {
return row {
text(props.name),
text ": ",
text(": "),
text(props.branch),
text " ",
text(props.msg or '(no commits)'),
text(" "),
text(props.msg or "(no commits)"),
}
end)
@ -39,11 +39,11 @@ local Section = Component.new(function(props)
return col {
row {
text(props.title),
text ' (',
text(" ("),
text(#props.items),
text ')',
text(")"),
},
col(props.items)
col(props.items),
}
end)
@ -54,52 +54,53 @@ function M.Status(state)
items = {
col {
RemoteHeader {
name = "Head",
branch = state.head.branch,
msg = state.head.commit_message
name = "Head",
branch = state.head.branch,
msg = state.head.commit_message,
},
state.upstream.branch and RemoteHeader {
name = "Upstream",
branch = state.upstream.branch,
msg = state.upstream.commit_message
name = "Upstream",
branch = state.upstream.branch,
msg = state.upstream.commit_message,
},
},
-- #state.untracked_files > 0 and Section {
-- title = "Untracked files",
-- items = map(state.untracked_files, Diff)
-- },
-- #state.unstaged_changes > 0 and Section {
-- title = "Unstaged changes",
-- items = map(state.unstaged_changes, Diff)
-- },
-- #state.staged_changes > 0 and Section {
-- title = "Staged changes",
-- items = map(state.staged_changes, Diff)
-- },
#state.stashes > 0 and Section {
title = "Stashes",
items = map(state.stashes, function(s)
return row {
text.highlight("Comment")("stash@{", s.idx, "}: "),
text(s.message)
}
end)
},
-- #state.unpulled_changes > 0 and Section {
-- #state.untracked_files > 0 and Section {
-- title = "Untracked files",
-- items = map(state.untracked_files, Diff)
-- },
-- #state.unstaged_changes > 0 and Section {
-- title = "Unstaged changes",
-- items = map(state.unstaged_changes, Diff)
-- },
-- #state.staged_changes > 0 and Section {
-- title = "Staged changes",
-- items = map(state.staged_changes, Diff)
-- },
#state.stashes > 0
and Section {
title = "Stashes",
items = map(state.stashes, function(s)
return row {
text.highlight("Comment")("stash@{", s.idx, "}: "),
text(s.message),
}
end),
},
-- #state.unpulled_changes > 0 and Section {
-- title = "Unpulled changes",
-- items = map(state.unpulled_changes, Diff)
-- },
-- #state.unmerged_changes > 0 and Section {
-- #state.unmerged_changes > 0 and Section {
-- title = "Unmerged changes",
-- items = map(state.unmerged_changes, Diff)
-- },
}
}
},
},
}
end
function _load_diffs(repo)
local cli = require 'neogit.lib.git.cli'
local cli = require("neogit.lib.git.cli")
local unstaged_jobs = map(repo.unstaged.items, function(f)
return cli.diff.shortstat.patch.files(f.name).to_job()
@ -111,7 +112,7 @@ function _load_diffs(repo)
local jobs = {}
for _, x in ipairs({ unstaged_jobs, staged_jobs }) do
for _, x in ipairs { unstaged_jobs, staged_jobs } do
for _, j in ipairs(x) do
table.insert(jobs, j)
end
@ -130,18 +131,24 @@ function _load_diffs(repo)
end
function _TEST()
local repo = require('neogit').repo
require('neogit.buffers.status').new({
head = repo.head,
upstream = repo.upstream,
untracked_files = repo.untracked.items,
unstaged_changes = map(repo.unstaged.items, function(f) return f.diff end),
staged_changes = map(repo.staged.items, function(f) return f.diff end),
stashes = repo.stashes.items,
unpulled_changes = repo.unpulled.items,
unmerged_changes = repo.unmerged.items,
recent_changes = repo.recent.items,
}):open()
local repo = require("neogit").repo
require("neogit.buffers.status")
.new({
head = repo.head,
upstream = repo.upstream,
untracked_files = repo.untracked.items,
unstaged_changes = map(repo.unstaged.items, function(f)
return f.diff
end),
staged_changes = map(repo.staged.items, function(f)
return f.diff
end),
stashes = repo.stashes.items,
unpulled_changes = repo.unpulled.items,
unmerged_changes = repo.unmerged.items,
recent_changes = repo.recent.items,
})
:open()
end
return M

View file

@ -19,32 +19,32 @@ M.values = {
signs = {
hunk = { "", "" },
item = { ">", "v" },
section = { ">", "v" }
section = { ">", "v" },
},
integrations = {
diffview = false
diffview = false,
},
sections = {
untracked = {
folded = false
folded = false,
},
unstaged = {
folded = false
folded = false,
},
staged = {
folded = false
folded = false,
},
stashes = {
folded = true
folded = true,
},
unpulled = {
folded = true
folded = true,
},
unmerged = {
folded = false
folded = false,
},
recent = {
folded = true
folded = true,
},
},
mappings = {
@ -77,8 +77,8 @@ M.values = {
["L"] = "LogPopup",
["Z"] = "StashPopup",
["b"] = "BranchPopup",
}
}
},
},
}
function M.ensure_integration(name)

View file

@ -1,32 +1,31 @@
local M = {}
local dv = require 'diffview'
local dv_config = require 'diffview.config'
local Rev = require'diffview.git.rev'.Rev
local RevType = require'diffview.git.rev'.RevType
local CDiffView = require'diffview.api.views.diff.diff_view'.CDiffView
local dv_lib = require'diffview.lib'
local dv = require("diffview")
local dv_config = require("diffview.config")
local Rev = require("diffview.git.rev").Rev
local RevType = require("diffview.git.rev").RevType
local CDiffView = require("diffview.api.views.diff.diff_view").CDiffView
local dv_lib = require("diffview.lib")
local dv_utils = require("diffview.utils")
local neogit = require 'neogit'
local status = require'neogit.status'
local a = require 'plenary.async'
local neogit = require("neogit")
local status = require("neogit.status")
local a = require("plenary.async")
local old_config
M.diffview_mappings = {
close = function()
vim.cmd [[tabclose]]
vim.cmd([[tabclose]])
neogit.dispatch_refresh()
dv.setup(old_config)
end
end,
}
local function cb(name)
return string.format(":lua require('neogit.integrations.diffview').diffview_mappings['%s']()<CR>", name)
end
local function get_local_diff_view(selected_file_name)
local left = Rev(RevType.INDEX)
local right = Rev(RevType.LOCAL)
@ -37,7 +36,7 @@ local function get_local_diff_view(selected_file_name)
local repo = neogit.get_repo()
local sections = {
working = repo.unstaged,
staged = repo.staged
staged = repo.staged,
}
for kind, section in pairs(sections) do
files[kind] = {}
@ -47,11 +46,11 @@ local function get_local_diff_view(selected_file_name)
status = item.mode,
stats = (item.diff and item.diff.stats) and {
additions = item.diff.stats.additions or 0,
deletions = item.diff.stats.deletions or 0
deletions = item.diff.stats.deletions or 0,
} or nil,
left_null = vim.tbl_contains({ "A", "?" }, item.mode),
right_null = false,
selected = item.name == selected_file_name
selected = item.name == selected_file_name,
}
table.insert(files[kind], file)
@ -63,7 +62,7 @@ local function get_local_diff_view(selected_file_name)
local files = update_files()
local view = CDiffView({
local view = CDiffView {
git_root = git_root,
left = left,
right = right,
@ -77,15 +76,13 @@ local function get_local_diff_view(selected_file_name)
end
return neogit.cli.show.file(unpack(args)).call_sync()
elseif kind == "working" then
return side == "left"
and neogit.cli.show.file(path).call_sync()
or nil
return side == "left" and neogit.cli.show.file(path).call_sync() or nil
end
end
})
end,
}
view:on_files_staged(a.void(function (_)
status.refresh({ status = true, diffs = true })
view:on_files_staged(a.void(function(_)
status.refresh { status = true, diffs = true }
view:update_files()
end))
@ -101,13 +98,13 @@ function M.open(section_name, item_name)
key_bindings = {
view = {
["q"] = cb("close"),
["<esc>"] = cb("close")
["<esc>"] = cb("close"),
},
file_panel = {
["q"] = cb("close"),
["<esc>"] = cb("close")
}
}
["<esc>"] = cb("close"),
},
},
})
dv.setup(config)
@ -116,10 +113,10 @@ function M.open(section_name, item_name)
if section_name == "recent" or section_name == "unmerged" then
local commit_id = item_name:match("[a-f0-9]+")
view = dv_lib.diffview_open(dv_utils.tbl_pack(commit_id.."^.."..commit_id))
view = dv_lib.diffview_open(dv_utils.tbl_pack(commit_id .. "^.." .. commit_id))
elseif section_name == "stashes" then
local stash_id = item_name:match("stash@{%d+}")
view = dv_lib.diffview_open(dv_utils.tbl_pack(stash_id.."^.."..stash_id))
view = dv_lib.diffview_open(dv_utils.tbl_pack(stash_id .. "^.." .. stash_id))
else
view = get_local_diff_view(item_name)
end

View file

@ -1,4 +1,4 @@
package.loaded['neogit.buffer'] = nil
package.loaded["neogit.buffer"] = nil
__BUFFER_AUTOCMD_STORE = {}
@ -15,7 +15,7 @@ function Buffer:new(handle)
handle = handle,
border = nil,
mmanager = mappings_manager.new(),
kind = nil -- how the buffer was opened. For more information look at the create function
kind = nil, -- how the buffer was opened. For more information look at the create function
}
this.ui = Ui.new(this)
@ -134,21 +134,21 @@ function Buffer:open_fold(line, reset_pos)
pos = vim.fn.getpos()
end
vim.fn.setpos('.', {self.handle, line, 0, 0})
vim.cmd('normal zo')
vim.fn.setpos(".", { self.handle, line, 0, 0 })
vim.cmd("normal zo")
if reset_pos == true then
vim.fn.setpos('.', pos)
vim.fn.setpos(".", pos)
end
end
function Buffer:add_highlight(line, col_start, col_end, name, ns_id)
local ns_id = ns_id or 0
vim.api.nvim_buf_add_highlight(self.handle, ns_id, name, line, col_start, col_end)
end
function Buffer:unplace_sign(id)
vim.cmd('sign unplace ' .. id)
vim.cmd("sign unplace " .. id)
end
function Buffer:place_sign(line, name, group, id)
-- Sign IDs should be unique within a group, however there's no downside as
@ -158,11 +158,11 @@ function Buffer:place_sign(line, name, group, id)
-- There's an equivalent function sign_place() which can automatically use
-- a free ID, but is considerable slower, so we use the command for now
local cmd = 'sign place '..sign_id..' line='..line..' name='..name
local cmd = "sign place " .. sign_id .. " line=" .. line .. " name=" .. name
if group ~= nil then
cmd = cmd..' group='..group
cmd = cmd .. " group=" .. group
end
cmd = cmd..' buffer='..self.handle
cmd = cmd .. " buffer=" .. self.handle
vim.cmd(cmd)
return sign_id
@ -172,12 +172,12 @@ function Buffer:get_sign_at_line(line, group)
group = group or "*"
return vim.fn.sign_getplaced(self.handle, {
group = group,
lnum = line
lnum = line,
})[1]
end
function Buffer:clear_sign_group(group)
vim.cmd('sign unplace * group='..group..' buffer='..self.handle)
vim.cmd("sign unplace * group=" .. group .. " buffer=" .. self.handle)
end
function Buffer:set_filetype(ft)
@ -226,8 +226,8 @@ function Buffer.create(config)
buffer = Buffer:new(vim.api.nvim_get_current_buf())
elseif kind == "floating" then
-- Creates the border window
local vim_height = vim.api.nvim_eval [[&lines]]
local vim_width = vim.api.nvim_eval [[&columns]]
local vim_height = vim.api.nvim_eval([[&lines]])
local vim_width = vim.api.nvim_eval([[&columns]])
local width = math.floor(vim_width * 0.8) + 3
local height = math.floor(vim_height * 0.7)
local col = vim_width * 0.1 - 1
@ -235,14 +235,14 @@ function Buffer.create(config)
local content_buffer = vim.api.nvim_create_buf(true, true)
local content_window = vim.api.nvim_open_win(content_buffer, true, {
relative = 'editor',
relative = "editor",
width = width,
height = height,
col = col,
row = row,
style = 'minimal',
style = "minimal",
focusable = false,
border = 'single',
border = "single",
})
vim.api.nvim_win_set_cursor(content_window, { 1, 0 })
@ -271,12 +271,12 @@ function Buffer.create(config)
if config.mappings then
for mode, val in pairs(config.mappings) do
for key, cb in pairs(val) do
buffer.mmanager.mappings[key] = {
mode,
function()
cb(buffer)
end,
mode:find("v") ~= nil
buffer.mmanager.mappings[key] = {
mode,
function()
cb(buffer)
end,
mode:find("v") ~= nil,
}
end
end

View file

@ -37,8 +37,8 @@ function M.filter(tbl, func)
local result = {}
for _, item in ipairs(tbl) do
if func(item) then
table.insert(result, item)
if func(item) then
table.insert(result, item)
end
end
@ -52,22 +52,24 @@ function M.each(tbl, func)
end
function M.reduce(tbl, func, ...)
local acc = {...}
tbl:each(function (item)
acc = {func(item, unpack(acc))}
local acc = { ... }
tbl:each(function(item)
acc = { func(item, unpack(acc)) }
end)
return unpack(acc)
end
function M.find(tbl, func)
for _, item in ipairs(tbl) do
if func(item) then return item end
if func(item) then
return item
end
end
return nil
end
return setmetatable(M, {
__call = function (_, tbl)
__call = function(_, tbl)
return M.new(tbl)
end
end,
})

View file

@ -1,15 +1,10 @@
local cli = require 'neogit.lib.git.cli'
local cli = require("neogit.lib.git.cli")
local M = {}
function M.relpath_from_repository(path)
local result = cli['ls-files']
.others
.cached
.modified
.deleted
.full_name
.cwd('<current>')
local result = cli["ls-files"].others.cached.modified.deleted.full_name
.cwd("<current>")
.args(path)
.show_popup(false)
.call()

View file

@ -1,13 +1,13 @@
local util = require 'neogit.lib.util'
local collect = require 'neogit.lib.collection'
local util = require("neogit.lib.util")
local collect = require("neogit.lib.collection")
local M = {}
function M.dot(chain)
local parts = collect(util.split(chain, '%.'))
return function (tbl)
parts:each(function (p)
if tbl then
tbl = tbl[p]
local parts = collect(util.split(chain, "%."))
return function(tbl)
parts:each(function(p)
if tbl then
tbl = tbl[p]
end
end)
return tbl
@ -15,9 +15,9 @@ function M.dot(chain)
end
function M.compose(...)
local funcs = collect({...})
return function (...)
return funcs:reduce(function (cur, ...)
local funcs = collect { ... }
return function(...)
return funcs:reduce(function(cur, ...)
return cur(...)
end, ...)
end
@ -25,10 +25,9 @@ end
M.C = M.compose
function M.eq(a)
return function (b)
return function(b)
return a == b
end
end
return M

View file

@ -1,12 +1,12 @@
local a = require 'plenary.async'
local cli = require('neogit.lib.git.cli')
local input = require('neogit.lib.input')
local a = require("plenary.async")
local cli = require("neogit.lib.git.cli")
local input = require("neogit.lib.input")
local M = {}
local function parse_branches(branches)
local other_branches = {}
for _, b in ipairs(branches) do
local branch_name = b:match('^ (.+)')
local branch_name = b:match("^ (.+)")
if branch_name then
table.insert(other_branches, branch_name)
end
@ -16,26 +16,19 @@ local function parse_branches(branches)
end
function M.get_local_branches()
local branches = cli.branch
.list
.call_sync()
local branches = cli.branch.list.call_sync()
return parse_branches(branches)
end
function M.get_remote_branches()
local branches = cli.branch
.remotes
.call_sync()
local branches = cli.branch.remotes.call_sync()
return parse_branches(branches)
end
function M.get_all_branches()
local branches = cli.branch
.list
.all
.call_sync()
local branches = cli.branch.list.all.call_sync()
return parse_branches(branches)
end
@ -45,10 +38,7 @@ function M.get_upstream()
local current = cli.branch.current.show_popup(false).call()
if #full_name > 0 and #current > 0 then
local remote = cli.config
.show_popup(false)
.get(string.format("branch.%s.remote", current[1]))
.call()
local remote = cli.config.show_popup(false).get(string.format("branch.%s.remote", current[1])).call()
if #remote > 0 then
return {
remote = remote[1],
@ -60,11 +50,13 @@ end
function M.prompt_for_branch(options)
a.util.scheduler()
local chosen = input.get_user_input_with_completion('branch > ', options)
if not chosen or chosen == '' then return nil end
local chosen = input.get_user_input_with_completion("branch > ", options)
if not chosen or chosen == "" then
return nil
end
local truncate_remote_name = chosen:match('.+/.+/(.+)')
if truncate_remote_name and truncate_remote_name ~= '' then
local truncate_remote_name = chosen:match(".+/.+/(.+)")
if truncate_remote_name and truncate_remote_name ~= "" then
return truncate_remote_name
end
@ -76,7 +68,9 @@ function M.checkout_local()
a.util.scheduler()
local chosen = M.prompt_for_branch(branches)
if not chosen then return end
if not chosen then
return
end
cli.checkout.branch(chosen).call()
end
@ -85,14 +79,18 @@ function M.checkout()
a.util.scheduler()
local chosen = M.prompt_for_branch(branches)
if not chosen then return end
if not chosen then
return
end
cli.checkout.branch(chosen).call()
end
function M.create()
a.util.scheduler()
local name = input.get_user_input('branch > ')
if not name or name == '' then return end
local name = input.get_user_input("branch > ")
if not name or name == "" then
return
end
cli.interactive_git_cmd(tostring(cli.branch.name(name)))
@ -104,7 +102,9 @@ function M.delete()
a.util.scheduler()
local chosen = M.prompt_for_branch(branches)
if not chosen then return end
if not chosen then
return
end
cli.interactive_git_cmd(tostring(cli.branch.delete.name(chosen)))
@ -113,8 +113,10 @@ end
function M.checkout_new()
a.util.scheduler()
local name = input.get_user_input('branch > ')
if not name or name == '' then return end
local name = input.get_user_input("branch > ")
if not name or name == "" then
return
end
cli.interactive_git_cmd(tostring(cli.checkout.new_branch(name)))
end

View file

@ -1,10 +1,10 @@
local notif = require("neogit.lib.notification")
local logger = require 'neogit.logger'
local a = require 'plenary.async'
local process = require('neogit.process')
local Job = require 'neogit.lib.job'
local util = require 'neogit.lib.util'
local split = require('neogit.lib.util').split
local logger = require("neogit.logger")
local a = require("plenary.async")
local process = require("neogit.process")
local Job = require("neogit.lib.job")
local util = require("neogit.lib.util")
local split = require("neogit.lib.util").split
local function config(setup)
setup = setup or {}
@ -16,55 +16,55 @@ local function config(setup)
end
local configurations = {
show = config({
show = config {
flags = {
stat = "--stat",
oneline = "--oneline"
oneline = "--oneline",
},
options = {
format = "--format"
format = "--format",
},
aliases = {
file = function(tbl)
return function(name, rev)
return tbl.args((rev or "") .. ":" .. name)
end
end
}
}),
status = config({
end,
},
},
status = config {
flags = {
short = "-s",
branch = "-b",
verbose = "-v",
null_terminated = "-z"
null_terminated = "-z",
},
options = {
porcelain = "--porcelain",
},
}),
log = config({
},
log = config {
flags = {
oneline = "--oneline",
branches = "--branches",
remotes = "--remotes",
all = "--all",
graph = "--graph"
graph = "--graph",
},
options = {
pretty = "--pretty",
max_count = "--max-count",
format = "--format"
format = "--format",
},
aliases = {
for_range = function (tbl)
return function (range)
for_range = function(tbl)
return function(range)
return tbl.args(range)
end
end
}
}),
config = config({
end,
},
},
config = config {
flags = {
_get = "--get",
},
@ -73,212 +73,212 @@ local configurations = {
return function(path)
return tbl._get.args(path)
end
end
}
}),
diff = config({
flags = {
null_terminated = '-z',
cached = '--cached',
shortstat = '--shortstat',
patch = '--patch',
name_only = '--name-only',
no_ext_diff = "--no-ext-diff"
end,
},
}),
stash = config({
},
diff = config {
flags = {
apply = 'apply',
drop = 'drop',
index = '--index'
}
}),
rebase = config({}),
reset = config({
null_terminated = "-z",
cached = "--cached",
shortstat = "--shortstat",
patch = "--patch",
name_only = "--name-only",
no_ext_diff = "--no-ext-diff",
},
},
stash = config {
flags = {
hard = '--hard',
apply = "apply",
drop = "drop",
index = "--index",
},
},
rebase = config {},
reset = config {
flags = {
hard = "--hard",
},
aliases = {
commit = function (tbl)
return function (cm)
commit = function(tbl)
return function(cm)
return tbl.args(cm)
end
end
}
}),
checkout = config({
end,
},
},
checkout = config {
short_opts = {
b = '-b',
b = "-b",
},
aliases = {
branch = function (tbl)
return function (branch)
branch = function(tbl)
return function(branch)
return tbl.args(branch)
end
end,
new_branch = function (tbl)
return function (branch)
new_branch = function(tbl)
return function(branch)
return tbl.b(branch)
end
end,
new_branch_with_start_point = function (tbl)
return function (branch, start_point)
new_branch_with_start_point = function(tbl)
return function(branch, start_point)
return tbl.args(branch, start_point).b()
end
end
}
}),
remote = config({
end,
},
},
remote = config {
flags = {
push = '--push'
push = "--push",
},
aliases = {
get_url = function (tbl)
get_url = function(tbl)
return function(remote)
tbl.prefix("get-url")
return tbl.args(remote)
end
end
}
}),
apply = config({
end,
},
},
apply = config {
flags = {
cached = '--cached',
reverse = '--reverse',
index = '--index'
cached = "--cached",
reverse = "--reverse",
index = "--index",
},
aliases = {
with_patch = function (tbl)
with_patch = function(tbl)
return tbl.input
end
}
}),
add = config({
flags = {
update = '-u',
all = '-A'
end,
},
}),
commit = config({
},
add = config {
flags = {
amend = '--amend',
only = '--only',
dry_run = '--dry-run',
no_edit = '--no-edit'
update = "-u",
all = "-A",
},
},
commit = config {
flags = {
amend = "--amend",
only = "--only",
dry_run = "--dry-run",
no_edit = "--no-edit",
},
options = {
commit_message_file = '--file'
}
}),
push = config({
commit_message_file = "--file",
},
},
push = config {
flags = {
delete = '--delete',
delete = "--delete",
},
aliases = {
remote = function (tbl)
return function (remote)
remote = function(tbl)
return function(remote)
return tbl.prefix(remote)
end
end,
to = function (tbl)
return function (to)
to = function(tbl)
return function(to)
return tbl.args(to)
end
end
}
}),
pull = config({
flags = {
no_commit = '--no-commit'
end,
},
}),
branch = config({
},
pull = config {
flags = {
list = '--list',
all = '-a',
delete = '-d',
remotes = '-r',
current = '--show-current',
very_verbose = '-vv',
move = '-m',
no_commit = "--no-commit",
},
},
branch = config {
flags = {
list = "--list",
all = "-a",
delete = "-d",
remotes = "-r",
current = "--show-current",
very_verbose = "-vv",
move = "-m",
},
aliases = {
name = function (tbl)
return function (name)
name = function(tbl)
return function(name)
return tbl.args(name)
end
end
}
}),
['read-tree'] = config({
end,
},
},
["read-tree"] = config {
flags = {
merge = '-m'
merge = "-m",
},
options = {
index_output = '--index-output'
index_output = "--index-output",
},
aliases = {
tree = function (tbl)
return function (tree)
tree = function(tbl)
return function(tree)
return tbl.args(tree)
end
end
}
}),
['write-tree'] = config({}),
['commit-tree'] = config({
end,
},
},
["write-tree"] = config {},
["commit-tree"] = config {
flags = {
no_gpg_sign = "--no-gpg-sign"
no_gpg_sign = "--no-gpg-sign",
},
short_opts = {
parent = "-p",
message = "-m"
message = "-m",
},
aliases = {
parents = function (tbl)
return function (...)
for _, p in ipairs({...}) do
parents = function(tbl)
return function(...)
for _, p in ipairs { ... } do
tbl.parent(p)
end
return tbl
end
end,
tree = function (tbl)
return function (tree)
tree = function(tbl)
return function(tree)
return tbl.args(tree)
end
end
}
}),
['update-index'] = config({
end,
},
},
["update-index"] = config {
flags = {
add = '--add',
remove = '--remove'
}
}),
['show-ref'] = config({
add = "--add",
remove = "--remove",
},
},
["show-ref"] = config {
flags = {
verify = '--verify',
}
}),
['update-ref'] = config({
verify = "--verify",
},
},
["update-ref"] = config {
flags = {
create_reflog = '--create-reflog'
create_reflog = "--create-reflog",
},
short_opts = {
message = '-m'
}
}),
['ls-files'] = config({
flags = {
others = '--others',
deleted = '--deleted',
modified = '--modified',
cached = '--cached',
full_name = '--full-name'
message = "-m",
},
}),
['rev-parse'] = config({
},
["ls-files"] = config {
flags = {
others = "--others",
deleted = "--deleted",
modified = "--modified",
cached = "--cached",
full_name = "--full-name",
},
},
["rev-parse"] = config {
flags = {
revs_only = "--revs-only",
no_revs = "--no-revs",
@ -290,11 +290,11 @@ local configurations = {
options = {
abbrev_ref = "--abbrev-ref",
},
}),
},
}
local function git_root()
return util.trim(process.spawn({cmd = 'git', args = {'rev-parse', '--show-toplevel'}}))
return util.trim(process.spawn { cmd = "git", args = { "rev-parse", "--show-toplevel" } })
end
local git_root_sync = function()
@ -318,7 +318,7 @@ local function handle_new_cmd(job, popup, hidden_text)
stdout = job.stdout,
stderr = job.stderr,
code = job.code,
time = job.time
time = job.time,
})
do
@ -334,8 +334,11 @@ local function handle_new_cmd(job, popup, hidden_text)
end
if popup and job.code ~= 0 then
vim.schedule(function ()
notif.create("Git Error (" .. job.code .. "), press $ to see the git command history", vim.log.levels.ERROR)
vim.schedule(function()
notif.create(
"Git Error (" .. job.code .. "), press $ to see the git command history",
vim.log.levels.ERROR
)
end)
end
end
@ -350,29 +353,29 @@ local function exec(cmd, args, cwd, stdin, env, show_popup, hide_text)
if not cwd then
cwd = git_root()
elseif cwd == '<current>' then
elseif cwd == "<current>" then
cwd = nil
end
local time = os.clock()
local opts = {
cmd = 'git',
cmd = "git",
args = args,
env = env,
input = stdin,
cwd = cwd
cwd = cwd,
}
local result, code, errors = process.spawn(opts)
local stdout = split(result, '\n')
local stderr = split(errors, '\n')
local stdout = split(result, "\n")
local stderr = split(errors, "\n")
handle_new_cmd({
cmd = 'git ' .. table.concat(args, ' '),
cmd = "git " .. table.concat(args, " "),
stdout = stdout,
stderr = stderr,
code = code,
time = os.clock() - time
time = os.clock() - time,
}, show_popup, hide_text)
--print('git', table.concat(args, ' '), '->', code, errors)
@ -381,19 +384,19 @@ end
local function new_job(cmd, args, cwd, _stdin, _env, show_popup, hide_text)
args = args or {}
if show_popup == nil then
show_popup = true
if show_popup == nil then
show_popup = true
end
table.insert(args, 1, cmd)
if not cwd then
cwd = git_root_sync()
elseif cwd == '<current>' then
elseif cwd == "<current>" then
cwd = nil
end
local cmd = "git " .. table.concat(args, ' ')
local job = Job.new({ cmd = cmd })
local cmd = "git " .. table.concat(args, " ")
local job = Job.new { cmd = cmd }
job.cwd = cwd
handle_new_cmd(job, show_popup, hide_text)
@ -415,48 +418,48 @@ local k_config = {}
local k_command = {}
local mt_builder = {
__index = function (tbl, action)
if action == 'args' or action == 'arguments' then
return function (...)
for _, v in ipairs({...}) do
__index = function(tbl, action)
if action == "args" or action == "arguments" then
return function(...)
for _, v in ipairs { ... } do
table.insert(tbl[k_state].arguments, v)
end
return tbl
end
end
if action == 'files' or action == 'paths' then
return function (...)
for _, v in ipairs({...}) do
if action == "files" or action == "paths" then
return function(...)
for _, v in ipairs { ... } do
table.insert(tbl[k_state].files, v)
end
return tbl
end
end
if action == 'input' or action == 'stdin' then
return function (value)
if action == "input" or action == "stdin" then
return function(value)
tbl[k_state].input = value
return tbl
end
end
if action == 'cwd' then
return function (cwd)
if action == "cwd" then
return function(cwd)
tbl[k_state].cwd = cwd
return tbl
end
end
if action == 'prefix' then
return function (x)
if action == "prefix" then
return function(x)
tbl[k_state].prefix = x
return tbl
end
end
if action == 'env' then
return function (cfg)
if action == "env" then
return function(cfg)
for k, v in pairs(cfg) do
tbl[k_state].env[k] = v
end
@ -464,15 +467,15 @@ local mt_builder = {
end
end
if action == 'show_popup' then
return function (show_popup)
if action == "show_popup" then
return function(show_popup)
tbl[k_state].show_popup = show_popup
return tbl
end
end
if action == 'hide_text' then
return function (hide_text)
if action == "hide_text" then
return function(hide_text)
tbl[k_state].hide_text = hide_text
return tbl
end
@ -484,7 +487,7 @@ local mt_builder = {
end
if tbl[k_config].options[action] then
return function (value)
return function(value)
if value then
table.insert(tbl[k_state].options, string.format("%s=%s", tbl[k_config].options[action], value))
else
@ -495,7 +498,7 @@ local mt_builder = {
end
if tbl[k_config].short_opts[action] then
return function (value)
return function(value)
table.insert(tbl[k_state].options, tbl[k_config].short_opts[action])
table.insert(tbl[k_state].options, value)
return tbl
@ -508,22 +511,24 @@ local mt_builder = {
error("unknown field: " .. action)
end,
__tostring = function (tbl)
return string.format('git %s %s %s -- %s',
__tostring = function(tbl)
return string.format(
"git %s %s %s -- %s",
tbl[k_command],
table.concat(tbl[k_state].options, ' '),
table.concat(tbl[k_state].arguments, ' '),
table.concat(tbl[k_state].files, ' '))
table.concat(tbl[k_state].options, " "),
table.concat(tbl[k_state].arguments, " "),
table.concat(tbl[k_state].files, " ")
)
end,
__call = function (tbl, ...)
__call = function(tbl, ...)
return tbl.call(...)
end
end,
}
local function new_builder(subcommand)
local configuration = configurations[subcommand]
if not configuration then
error("Command not found")
if not configuration then
error("Command not found")
end
local state = {
@ -533,72 +538,72 @@ local function new_builder(subcommand)
input = nil,
show_popup = true,
cwd = nil,
env = {}
env = {},
}
return setmetatable({
[k_state] = state,
[k_config] = configuration,
[k_command] = subcommand,
call = function ()
call = function()
local args = {}
for _,o in ipairs(state.options) do
table.insert(args, o)
for _, o in ipairs(state.options) do
table.insert(args, o)
end
for _,a in ipairs(state.arguments) do
table.insert(args, a)
for _, a in ipairs(state.arguments) do
table.insert(args, a)
end
if #state.files > 0 then
table.insert(args, '--')
if #state.files > 0 then
table.insert(args, "--")
end
for _,f in ipairs(state.files) do
table.insert(args, f)
for _, f in ipairs(state.files) do
table.insert(args, f)
end
if state.prefix then
table.insert(args, 1, state.prefix)
end
logger.debug(string.format("[CLI]: Executing '%s %s'", subcommand, table.concat(args, ' ')))
logger.debug(string.format("[CLI]: Executing '%s %s'", subcommand, table.concat(args, " ")))
return exec(subcommand, args, state.cwd, state.input, state.env, state.show_popup, state.hide_text)
end,
call_sync = function()
local args = {}
for _,o in ipairs(state.options) do
table.insert(args, o)
for _, o in ipairs(state.options) do
table.insert(args, o)
end
for _,a in ipairs(state.arguments) do
table.insert(args, a)
for _, a in ipairs(state.arguments) do
table.insert(args, a)
end
if #state.files > 0 then
table.insert(args, '--')
if #state.files > 0 then
table.insert(args, "--")
end
for _,f in ipairs(state.files) do
table.insert(args, f)
for _, f in ipairs(state.files) do
table.insert(args, f)
end
if state.prefix then
table.insert(args, 1, state.prefix)
end
logger.debug(string.format("[CLI]: Executing '%s %s'", subcommand, table.concat(args, ' ')))
logger.debug(string.format("[CLI]: Executing '%s %s'", subcommand, table.concat(args, " ")))
return exec_sync(subcommand, args, state.cwd, state.input, state.env, state.show_popup, state.hide_text)
end,
to_job = function()
local args = {}
for _,o in ipairs(state.options) do
table.insert(args, o)
for _, o in ipairs(state.options) do
table.insert(args, o)
end
for _,a in ipairs(state.arguments) do
table.insert(args, a)
for _, a in ipairs(state.arguments) do
table.insert(args, a)
end
if #state.files > 0 then
table.insert(args, '--')
if #state.files > 0 then
table.insert(args, "--")
end
for _,f in ipairs(state.files) do
table.insert(args, f)
for _, f in ipairs(state.files) do
table.insert(args, f)
end
if state.prefix then
@ -606,7 +611,7 @@ local function new_builder(subcommand)
end
return new_job(subcommand, args, state.cwd, state.input, state.env, state.show_popup)
end
end,
}, mt_builder)
end
@ -614,18 +619,22 @@ local function new_parallel_builder(calls)
local state = {
calls = calls,
show_popup = true,
cwd = nil
cwd = nil,
}
local function call()
if #state.calls == 0 then return end
if #state.calls == 0 then
return
end
if not state.cwd then
state.cwd = git_root()
end
if not state.cwd or state.cwd == "" then return end
if not state.cwd or state.cwd == "" then
return
end
for _,c in ipairs(state.calls) do
for _, c in ipairs(state.calls) do
c.cwd(state.cwd).show_popup(state.show_popup)
end
@ -638,81 +647,79 @@ local function new_parallel_builder(calls)
end
return setmetatable({
call = call
call = call,
}, {
__index = function (tbl, action)
if action == 'cwd' then
return function (cwd)
__index = function(tbl, action)
if action == "cwd" then
return function(cwd)
state.cwd = cwd
return tbl
end
end
if action == 'show_popup' then
return function (show_popup)
if action == "show_popup" then
return function(show_popup)
state.show_popup = show_popup
return tbl
end
end
end,
__call = call
__call = call,
})
end
local meta = {
__index = function (_tbl, key)
__index = function(_tbl, key)
if configurations[key] then
return new_builder(key)
end
error("unknown field")
end
end,
}
local function handle_interactive_password_questions(chan, line)
logger.debug(string.format("Matching interactive cmd output: '%s'", line))
if vim.startswith(line, "Are you sure you want to continue connecting ") then
logger.debug "[CLI]: Confirming whether to continue with unauthenticated host"
logger.debug("[CLI]: Confirming whether to continue with unauthenticated host")
local prompt = line
local value = vim.fn.input {
prompt = "The authenticity of the host can't be established. " .. prompt .. " ",
cancelreturn = "__CANCEL__"
cancelreturn = "__CANCEL__",
}
if value ~= "__CANCEL__" then
logger.debug "[CLI]: Received answer"
logger.debug("[CLI]: Received answer")
vim.fn.chansend(chan, value .. "\n")
else
logger.debug "[CLI]: Cancelling the interactive cmd"
logger.debug("[CLI]: Cancelling the interactive cmd")
vim.fn.chanclose(chan)
end
elseif vim.startswith(line, "Username for ") then
logger.debug "[CLI]: Asking for username"
logger.debug("[CLI]: Asking for username")
local prompt = line:match("(.*:?):.*")
local value = vim.fn.input {
prompt = prompt .. " ",
cancelreturn = "__CANCEL__"
cancelreturn = "__CANCEL__",
}
if value ~= "__CANCEL__" then
logger.debug "[CLI]: Received username"
logger.debug("[CLI]: Received username")
vim.fn.chansend(chan, value .. "\n")
else
logger.debug "[CLI]: Cancelling the interactive cmd"
logger.debug("[CLI]: Cancelling the interactive cmd")
vim.fn.chanclose(chan)
end
elseif vim.startswith(line, "Enter passphrase")
or vim.startswith(line, "Password for")
then
logger.debug "[CLI]: Asking for password"
elseif vim.startswith(line, "Enter passphrase") or vim.startswith(line, "Password for") then
logger.debug("[CLI]: Asking for password")
local prompt = line:match("(.*:?):.*")
local value = vim.fn.inputsecret {
prompt = prompt .. " ",
cancelreturn = "__CANCEL__"
cancelreturn = "__CANCEL__",
}
if value ~= "__CANCEL__" then
logger.debug "[CLI]: Received password"
logger.debug("[CLI]: Received password")
vim.fn.chansend(chan, value .. "\n")
else
logger.debug "[CLI]: Cancelling the interactive cmd"
logger.debug("[CLI]: Cancelling the interactive cmd")
vim.fn.chanclose(chan)
end
else
@ -736,7 +743,7 @@ local cli = setmetatable({
local started_at = os.clock()
logger.debug(string.format("[CLI]: Starting interactive git cmd '%s'", cmd))
chan = vim.fn.jobstart(vim.fn.has('win32') == 1 and { "cmd", "/C", cmd } or cmd, {
chan = vim.fn.jobstart(vim.fn.has("win32") == 1 and { "cmd", "/C", cmd } or cmd, {
pty = true,
width = 100,
on_stdout = function(_, data)
@ -749,7 +756,7 @@ local cli = setmetatable({
table.insert(stdout, data)
local lines = vim.split(data, "\r?[\r\n]")
for i=1,#lines do
for i = 1, #lines do
if lines[i] ~= "" then
if skip_count > 0 then
skip_count = skip_count - 1
@ -767,12 +774,12 @@ local cli = setmetatable({
stdout = stdout,
stderr = stdout,
code = code,
time = (os.clock() - started_at) * 1000
time = (os.clock() - started_at) * 1000,
}
cb({
cb {
code = code,
stdout = stdout
})
stdout = stdout,
}
end,
})
@ -783,7 +790,7 @@ local cli = setmetatable({
git_root_sync = git_root_sync,
git_dir_path_sync = git_dir_path_sync,
in_parallel = function(...)
local calls = {...}
local calls = { ... }
return new_parallel_builder(calls)
end,
}, meta)

View file

@ -1,9 +1,9 @@
local a = require 'plenary.async'
local util = require 'neogit.lib.util'
local logger = require 'neogit.logger'
local cli = require('neogit.lib.git.cli')
local Collection = require('neogit.lib.collection')
local md5 = require 'neogit.lib.md5'
local a = require("plenary.async")
local util = require("neogit.lib.util")
local logger = require("neogit.logger")
local cli = require("neogit.lib.git.cli")
local Collection = require("neogit.lib.collection")
local md5 = require("neogit.lib.md5")
local function parse_diff_stats(raw)
if type(raw) == "string" then
@ -11,7 +11,7 @@ local function parse_diff_stats(raw)
end
local stats = {
additions = 0,
deletions = 0
deletions = 0,
}
-- local matches raw:match('1 file changed, (%d+ insertions?%(%+%))?(, )?(%d+ deletions?%(%-%))?')
for _, part in ipairs(raw) do
@ -37,7 +37,7 @@ local function parse_diff(output, with_stats)
lines = {},
file = "",
hunks = {},
stats = {}
stats = {},
}
local start_idx = 1
@ -49,8 +49,8 @@ local function parse_diff(output, with_stats)
do
local header = {}
for i=start_idx,#output do
if output[i]:match('^@@@*.*@@@*') then
for i = start_idx, #output do
if output[i]:match("^@@@*.*@@@*") then
start_idx = i
break
end
@ -69,36 +69,35 @@ local function parse_diff(output, with_stats)
diff.file = header[4]:match("%-%-%- a/(.*)")
end
else
logger.debug "TODO: diff parser"
logger.debug("TODO: diff parser")
logger.debug(vim.inspect(header))
end
end
for i=start_idx,#output do
for i = start_idx, #output do
table.insert(diff.lines, output[i])
end
local len = #diff.lines
local hunk = nil
local hunk_content = ''
local hunk_content = ""
for i=1,len do
for i = 1, len do
local line = diff.lines[i]
if not vim.startswith(line, "+++") then
local index_from, index_len, disk_from, disk_len
if vim.startswith(line, "@@@") then
-- Combined diff header
index_from, index_len, disk_from, disk_len = line:match('@@@* %-(%d+),?(%d*) .* %+(%d+),?(%d*) @@@*')
index_from, index_len, disk_from, disk_len = line:match("@@@* %-(%d+),?(%d*) .* %+(%d+),?(%d*) @@@*")
else
-- Normal diff header
index_from, index_len, disk_from, disk_len = line:match('@@ %-(%d+),?(%d*) %+(%d+),?(%d*) @@')
index_from, index_len, disk_from, disk_len = line:match("@@ %-(%d+),?(%d*) %+(%d+),?(%d*) @@")
end
if index_from then
if hunk ~= nil then
hunk.hash = md5.sumhexa(hunk_content)
hunk_content = ''
hunk_content = ""
table.insert(diff.hunks, hunk)
end
hunk = {
@ -108,11 +107,11 @@ local function parse_diff(output, with_stats)
disk_len = tonumber(disk_len) or 1,
line = line,
diff_from = i,
diff_to = i
diff_to = i,
}
else
hunk_content = hunk_content .. '\n' .. line
if hunk then
hunk_content = hunk_content .. "\n" .. line
if hunk then
hunk.diff_to = hunk.diff_to + 1
end
end
@ -132,19 +131,18 @@ local diff = {
parse_stats = parse_diff_stats,
get_stats = function(name)
return parse_diff_stats(cli.diff.no_ext_diff.shortstat.files(name).call_sync())
end
end,
}
local ItemFilter = {}
function ItemFilter.new (tbl)
function ItemFilter.new(tbl)
return setmetatable(tbl, { __index = ItemFilter })
end
function ItemFilter.accepts (tbl, section, item)
function ItemFilter.accepts(tbl, section, item)
for _, f in ipairs(tbl) do
if (f.section == "*" or f.section == section)
and (f.file == "*" or f.file == item) then
if (f.section == "*" or f.section == section) and (f.file == "*" or f.file == item) then
return true
end
end
@ -153,15 +151,15 @@ function ItemFilter.accepts (tbl, section, item)
end
function diff.register(meta)
meta.load_diffs = function (repo, filter)
meta.load_diffs = function(repo, filter)
filter = filter or false
local executions = {}
if type(filter) == 'table' then
filter = ItemFilter.new(Collection.new(filter):map(function (item)
if type(filter) == "table" then
filter = ItemFilter.new(Collection.new(filter):map(function(item)
local section, file = item:match("^([^:]+):(.*)$")
if not section then
error('Invalid filter item: '..item, 3)
error("Invalid filter item: " .. item, 3)
end
return { section = section, file = file }
@ -169,8 +167,8 @@ function diff.register(meta)
end
for _, f in ipairs(repo.unstaged.items) do
if f.mode ~= 'D' and f.mode ~= 'F' and (not filter or filter:accepts('unstaged', f.name)) then
table.insert(executions, function ()
if f.mode ~= "D" and f.mode ~= "F" and (not filter or filter:accepts("unstaged", f.name)) then
table.insert(executions, function()
local raw_diff = cli.diff.no_ext_diff.files(f.name).call()
local raw_stats = cli.diff.no_ext_diff.shortstat.files(f.name).call()
f.diff = parse_diff(raw_diff)
@ -180,8 +178,8 @@ function diff.register(meta)
end
for _, f in ipairs(repo.staged.items) do
if f.mode ~= 'D' and f.mode ~= 'F' and (not filter or filter:accepts('staged', f.name)) then
table.insert(executions, function ()
if f.mode ~= "D" and f.mode ~= "F" and (not filter or filter:accepts("staged", f.name)) then
table.insert(executions, function()
local raw_diff = cli.diff.no_ext_diff.cached.files(f.name).call()
local raw_stats = cli.diff.no_ext_diff.cached.shortstat.files(f.name).call()
f.diff = parse_diff(raw_diff)

View file

@ -4,13 +4,13 @@ local config = require("neogit.config")
local function parse_log(output)
if type(output) == "string" then
output = vim.split(output, '\n')
output = vim.split(output, "\n")
end
local output_len = #output
local commits = {}
for i=1,output_len do
for i = 1, output_len do
local level, hash, rest = output[i]:match("([| *]*)([a-zA-Z0-9]+) (.*)")
if level ~= nil then
local remote, message = rest:match("%((.-)%) (.*)")
@ -22,7 +22,7 @@ local function parse_log(output)
level = util.str_count(level, "|"),
hash = hash,
remote = remote or "",
message = message
message = message,
}
table.insert(commits, commit)
end
@ -37,25 +37,21 @@ local function update_recent(state)
return
end
local result = cli.log.oneline
.max_count(count)
.show_popup(false)
.call()
local result = cli.log.oneline.max_count(count).show_popup(false).call()
state.recent.items = util.map(result, function (x)
state.recent.items = util.map(result, function(x)
return { name = x }
end)
end
return {
list = function(options)
options = util.split(options, ' ')
options = util.split(options, " ")
local output = cli.log.oneline.args(unpack(options)).call()
return parse_log(output)
end,
register = function(meta)
meta.update_recent = update_recent
end,
parse_log = parse_log
parse_log = parse_log,
}

View file

@ -1,5 +1,5 @@
local cli = require('neogit.lib.git.cli')
local util = require('neogit.lib.util')
local cli = require("neogit.lib.git.cli")
local util = require("neogit.lib.util")
local M = {}
@ -10,13 +10,14 @@ function M.pull_interactive(remote, branch, args)
end
local function update_unpulled(state)
if not state.upstream.branch then return end
if not state.upstream.branch then
return
end
local result =
cli.log.oneline.for_range('..@{upstream}').show_popup(false).call()
local result = cli.log.oneline.for_range("..@{upstream}").show_popup(false).call()
state.unpulled.items = util.map(result, function (x)
return { name = x }
state.unpulled.items = util.map(result, function(x)
return { name = x }
end)
end

View file

@ -1,5 +1,5 @@
local cli = require('neogit.lib.git.cli')
local util = require('neogit.lib.util')
local cli = require("neogit.lib.git.cli")
local util = require("neogit.lib.util")
local M = {}
@ -10,13 +10,14 @@ function M.push_interactive(remote, branch, args)
end
local function update_unmerged(state)
if not state.upstream.branch then return end
if not state.upstream.branch then
return
end
local result =
cli.log.oneline.for_range('@{upstream}..').show_popup(false).call()
local result = cli.log.oneline.for_range("@{upstream}..").show_popup(false).call()
state.unmerged.items = util.map(result, function (x)
return { name = x }
state.unmerged.items = util.map(result, function(x)
return { name = x }
end)
end

View file

@ -1,44 +1,44 @@
local M = {}
local meta = {
__index = {}
__index = {},
}
local modules = { 'status', 'diff', 'stash', 'pull', 'push', 'log' }
local modules = { "status", "diff", "stash", "pull", "push", "log" }
for _, m in ipairs(modules) do
require('neogit.lib.git.'..m).register(meta.__index)
require("neogit.lib.git." .. m).register(meta.__index)
end
M.create = function (_path)
M.create = function(_path)
local cache = {
head = {
branch = nil,
commit_message = ''
commit_message = "",
},
upstream = {
breanch = nil,
commit_message = ''
commit_message = "",
},
untracked = {
items = {}
items = {},
},
unstaged = {
items = {}
items = {},
},
staged = {
items = {}
items = {},
},
stashes = {
items = {}
items = {},
},
unpulled = {
items = {}
items = {},
},
unmerged = {
items = {}
items = {},
},
recent = {
items = {}
items = {},
},
}

View file

@ -1,10 +1,10 @@
local cli = require('neogit.lib.git.cli')
local cli = require("neogit.lib.git.cli")
local function parse(output)
local result = {}
for _, line in ipairs(output) do
local stash_num, stash_desc = line:match('stash@{(%d*)}: (.*)')
table.insert(result, { idx = tonumber(stash_num), name = line, message = stash_desc})
local stash_num, stash_desc = line:match("stash@{(%d*)}: (.*)")
table.insert(result, { idx = tonumber(stash_num), name = line, message = stash_desc })
end
return result
end
@ -14,61 +14,40 @@ local function trim_null_terminator(str)
end
local function perform_stash(include)
if not include then return end
local index =
cli['commit-tree']
.no_gpg_sign
.parent('HEAD')
.tree(cli['write-tree'].call())
.call()
cli['read-tree']
.merge
.index_output('.git/NEOGIT_TMP_INDEX')
.args(index)
.call()
if include.worktree then
local files =
cli.diff
.no_ext_diff
.name_only
.null_terminated
.args('HEAD')
.env({
GIT_INDEX_FILE = '.git/NEOGIT_TMP_INDEX'
})
.call()
files = vim.split(trim_null_terminator(files), '\0')
cli['update-index']
.add
.remove
.files(unpack(files))
.env({
GIT_INDEX_FILE = '.git/NEOGIT_TMP_INDEX'
})
.call()
if not include then
return
end
local tree =
cli['commit-tree']
.no_gpg_sign
.parents('HEAD', index)
.tree(cli['write-tree'].call())
local index = cli["commit-tree"].no_gpg_sign.parent("HEAD").tree(cli["write-tree"].call()).call()
cli["read-tree"].merge.index_output(".git/NEOGIT_TMP_INDEX").args(index).call()
if include.worktree then
local files = cli.diff.no_ext_diff.name_only.null_terminated
.args("HEAD")
.env({
GIT_INDEX_FILE = '.git/NEOGIT_TMP_INDEX'
GIT_INDEX_FILE = ".git/NEOGIT_TMP_INDEX",
})
.call()
files = vim.split(trim_null_terminator(files), "\0")
cli['update-ref']
.create_reflog
.args('refs/stash', tree)
cli["update-index"].add.remove
.files(unpack(files))
.env({
GIT_INDEX_FILE = ".git/NEOGIT_TMP_INDEX",
})
.call()
end
local tree = cli["commit-tree"].no_gpg_sign
.parents("HEAD", index)
.tree(cli["write-tree"].call())
.env({
GIT_INDEX_FILE = ".git/NEOGIT_TMP_INDEX",
})
.call()
cli["update-ref"].create_reflog.args("refs/stash", tree).call()
-- selene: allow(empty_if)
if include.worktree and include.index then
@ -76,92 +55,58 @@ local function perform_stash(include)
-- leaves a malformed stash entry, so reverting the changes is
-- destructive until fixed.
--
--cli.reset
--.hard
--.commit('HEAD')
--.call()
--cli.reset
--.hard
--.commit('HEAD')
--.call()
elseif include.index then
local diff =
cli.diff
.no_ext_diff
.cached
.call() .. '\n'
local diff = cli.diff.no_ext_diff.cached.call() .. "\n"
cli.apply
.reverse
.cached
.input(diff)
.call()
cli.apply
.reverse
.input(diff)
.call()
cli.apply.reverse.cached.input(diff).call()
cli.apply.reverse.input(diff).call()
end
end
local function update_stashes(state)
local result = cli.stash.args('list').call()
local result = cli.stash.args("list").call()
state.stashes.items = parse(result)
end
return {
parse = parse,
stash_all = function ()
stash_all = function()
cli.stash.call()
-- this should work, but for some reason doesn't.
--return perform_stash({ worktree = true, index = true })
end,
stash_index = function ()
return perform_stash({ worktree = false, index = true })
stash_index = function()
return perform_stash { worktree = false, index = true }
end,
pop = function (stash)
local _, code = cli.stash
.apply
.index
.args(stash)
.show_popup(false)
.call()
pop = function(stash)
local _, code = cli.stash.apply.index.args(stash).show_popup(false).call()
if code == 0 then
cli.stash
.drop
.args(stash)
.call()
cli.stash.drop.args(stash).call()
else
cli.stash
.apply
.args(stash)
.call()
cli.stash.apply.args(stash).call()
end
end,
apply = function (stash)
local _, code = cli.stash
.apply
.index
.args(stash)
.show_popup(false)
.call()
apply = function(stash)
local _, code = cli.stash.apply.index.args(stash).show_popup(false).call()
if code ~= 0 then
cli.stash
.apply
.args(stash)
.call()
cli.stash.apply.args(stash).call()
end
end,
drop = function (stash)
cli.stash
.drop
.args(stash)
.call()
drop = function(stash)
cli.stash.drop.args(stash).call()
end,
register = function (meta)
register = function(meta)
meta.update_stashes = update_stashes
end
end,
}

View file

@ -1,87 +1,80 @@
local git = {
cli = require("neogit.lib.git.cli"),
stash = require("neogit.lib.git.stash")
stash = require("neogit.lib.git.stash"),
}
local a = require 'plenary.async'
local a = require("plenary.async")
local util = require("neogit.lib.util")
local Collection = require('neogit.lib.collection')
local Collection = require("neogit.lib.collection")
local function update_status(state)
local result =
git.cli.status
.porcelain(2)
.branch
.null_terminated
.call()
local result = git.cli.status.porcelain(2).branch.null_terminated.call()
local untracked_files, unstaged_files, staged_files = {}, {}, {}
local append_original_path
local old_files_hash = {
staged_files = Collection.new(state.staged.items or {}):key_by('name'),
unstaged_files = Collection.new(state.unstaged.items or {}):key_by('name')
staged_files = Collection.new(state.staged.items or {}):key_by("name"),
unstaged_files = Collection.new(state.unstaged.items or {}):key_by("name"),
}
local head = {}
local upstream = {}
for _, l in ipairs(util.split(result[1], '\0')) do
for _, l in ipairs(util.split(result[1], "\0")) do
if append_original_path then
append_original_path(l)
else
local header, value = l:match('# ([%w%.]+) (.+)')
local header, value = l:match("# ([%w%.]+) (.+)")
if header then
if header == 'branch.head' then
if header == "branch.head" then
head.branch = value
elseif header == 'branch.oid' then
elseif header == "branch.oid" then
head.oid = value
elseif header == 'branch.upstream' then
elseif header == "branch.upstream" then
upstream.branch = value
end
else
local kind, rest = l:match('(.) (.+)')
if kind == '?' then
local kind, rest = l:match("(.) (.+)")
if kind == "?" then
table.insert(untracked_files, {
name = rest
name = rest,
})
-- selene: allow(empty_if)
elseif kind == '!' then
elseif kind == "!" then
-- we ignore ignored files for now
elseif kind == '1' then
elseif kind == "1" then
local mode_staged, mode_unstaged, _, _, _, _, _, _, name =
rest:match('(.)(.) (....) (%d+) (%d+) (%d+) (%w+) (%w+) (.+)')
if mode_staged ~= '.' then
rest:match("(.)(.) (....) (%d+) (%d+) (%d+) (%w+) (%w+) (.+)")
if mode_staged ~= "." then
table.insert(staged_files, {
mode = mode_staged,
name = name,
diff = old_files_hash.staged_files[name]
and old_files_hash.staged_files[name].diff
diff = old_files_hash.staged_files[name] and old_files_hash.staged_files[name].diff,
})
end
if mode_unstaged ~= '.' then
if mode_unstaged ~= "." then
table.insert(unstaged_files, {
mode = mode_unstaged,
name = name,
diff = old_files_hash.unstaged_files[name]
and old_files_hash.unstaged_files[name].diff
diff = old_files_hash.unstaged_files[name] and old_files_hash.unstaged_files[name].diff,
})
end
elseif kind == '2' then
elseif kind == "2" then
local mode_staged, mode_unstaged, _, _, _, _, _, _, _, name =
rest:match('(.)(.) (....) (%d+) (%d+) (%d+) (%w+) (%w+) (%a%d+) (.+)')
rest:match("(.)(.) (....) (%d+) (%d+) (%d+) (%w+) (%w+) (%a%d+) (.+)")
local entry = {
name = name
name = name,
}
if mode_staged ~= '.' then
if mode_staged ~= "." then
entry.mode = mode_staged
table.insert(staged_files, entry)
end
if mode_unstaged ~= '.' then
if mode_unstaged ~= "." then
entry.mode = mode_unstaged
table.insert(unstaged_files, entry)
end
append_original_path = function (orig)
append_original_path = function(orig)
entry.original_name = orig
append_original_path = nil
end
@ -90,11 +83,11 @@ local function update_status(state)
end
end
if head.branch == state.head.branch then
head.commit_message = state.head.commit_message
if head.branch == state.head.branch then
head.commit_message = state.head.commit_message
end
if upstream.branch == state.upstream.branch then
upstream.commit_message = state.upstream.commit_message
if upstream.branch == state.upstream.branch then
upstream.commit_message = state.upstream.commit_message
end
state.head = head
@ -107,15 +100,15 @@ end
local function update_branch_information(state)
local tasks = {}
if state.head.oid ~= '(initial)' then
table.insert(tasks, function ()
local result = git.cli.log.max_count(1).pretty('%B').call()
if state.head.oid ~= "(initial)" then
table.insert(tasks, function()
local result = git.cli.log.max_count(1).pretty("%B").call()
state.head.commit_message = result[1]
end)
if state.upstream.branch then
table.insert(tasks, function ()
local result = git.cli.log.max_count(1).pretty('%B').for_range('@{upstream}').show_popup(false).call()
table.insert(tasks, function()
local result = git.cli.log.max_count(1).pretty("%B").for_range("@{upstream}").show_popup(false).call()
state.upstream.commit_message = result[1]
end)
end
@ -144,7 +137,7 @@ local status = {
end,
}
status.register = function (meta)
status.register = function(meta)
meta.update_status = update_status
meta.update_branch_information = update_branch_information
end

View file

@ -22,29 +22,33 @@ local M = {}
---@param group string Syntax group name.
---@param opt HiSpec
function M.hi(group, opt)
vim.cmd(string.format(
"hi %s %s guifg=%s guibg=%s gui=%s guisp=%s blend=%s",
opt.default and "default" or "",
group,
opt.fg or "NONE",
opt.bg or "NONE",
opt.gui or "NONE",
opt.sp or "NONE",
opt.blend or "NONE"
))
vim.cmd(
string.format(
"hi %s %s guifg=%s guibg=%s gui=%s guisp=%s blend=%s",
opt.default and "default" or "",
group,
opt.fg or "NONE",
opt.bg or "NONE",
opt.gui or "NONE",
opt.sp or "NONE",
opt.blend or "NONE"
)
)
end
---@param from string Syntax group name.
---@param to string Syntax group name.
---@param opt HiLinkSpec
function M.hi_link(from, to, opt)
vim.cmd(string.format(
"hi%s %s link %s %s",
opt.force and "!" or "",
opt.default and "default" or "",
from,
to or ""
))
vim.cmd(
string.format(
"hi%s %s link %s %s",
opt.force and "!" or "",
opt.default and "default" or "",
from,
to or ""
)
)
end
---@param name string Syntax group name.
@ -99,7 +103,7 @@ function M.get_gui(group_name, trans)
"standout",
"underline",
"undercurl",
"strikethrough"
"strikethrough",
}
for _, attr in ipairs(attributes) do

View file

@ -1,42 +1,44 @@
local M = {}
-- selene: allow(global_usage)
if not _G.__NEOGIT then
_G.__NEOGIT = {}
if not _G.__NEOGIT then
_G.__NEOGIT = {}
end
-- selene: allow(global_usage)
if not _G.__NEOGIT.completers then
_G.__NEOGIT.completers = {}
if not _G.__NEOGIT.completers then
_G.__NEOGIT.completers = {}
end
local function user_input_prompt(prompt, default_value, completion_function)
vim.fn.inputsave()
local args = {
prompt = prompt
prompt = prompt,
}
if default_value then
args.default = default_value
if default_value then
args.default = default_value
end
if completion_function then
args.completion = 'customlist,v:lua.__NEOGIT.completers.'..completion_function
if completion_function then
args.completion = "customlist,v:lua.__NEOGIT.completers." .. completion_function
end
local status, result = pcall(vim.fn.input, args)
vim.fn.inputrestore()
if not status then return nil end
if not status then
return nil
end
return result
end
local COMPLETER_SEQ = 1
local function make_completion_function(options)
local id = 'completer'..tostring(COMPLETER_SEQ)
local id = "completer" .. tostring(COMPLETER_SEQ)
COMPLETER_SEQ = COMPLETER_SEQ + 1
-- selene: allow(global_usage)
_G.__NEOGIT.completers[id] = function (arg_lead)
_G.__NEOGIT.completers[id] = function(arg_lead)
local result = {}
for _, v in ipairs(options) do
if v:match(arg_lead) then
@ -73,7 +75,9 @@ function M.get_secret_user_input(prompt)
vim.fn.inputrestore()
if not status then return nil end
if not status then
return nil
end
return result
end

View file

@ -13,10 +13,10 @@ local Job = {
done = false,
on_stdout = nil,
on_stderr = nil,
on_exit = nil
on_exit = nil,
}
local is_win = vim.fn.has('win32') == 1
local is_win = vim.fn.has("win32") == 1
--- Creates a new Job
--@tparam string cmd the command to be executed
@ -43,11 +43,9 @@ function Job:start()
local task = self.cmd
if type(task) == "string"
and is_win
then
if type(task) == "string" and is_win then
task = task:gsub("%^", "%^%^")
task = { 'cmd', '/C', task }
task = { "cmd", "/C", task }
end
local stdout_line_buffer = ""
@ -68,7 +66,7 @@ function Job:start()
on_stdout = function(_, data)
data[1] = stdout_line_buffer .. data[1]
for i=1,#data-1 do
for i = 1, #data - 1 do
local data = data[i]:gsub("\r", "")
if type(self.on_stdout) == "function" then
self.on_stdout(data)
@ -81,7 +79,7 @@ function Job:start()
on_stderr = function(_, data)
data[1] = stderr_line_buffer .. data[1]
for i=1,#data-1 do
for i = 1, #data - 1 do
local data = data[i]:gsub("\r", "")
if type(self.on_stderr) == "function" then
self.on_stderr(data)
@ -96,7 +94,7 @@ end
--- Returns when the job is finished
function Job:wait()
vim.fn.jobwait({ self.channel })
vim.fn.jobwait { self.channel }
end
--- Writes the given strings to the stdin
@ -109,19 +107,19 @@ end
function Job.batch(cmds)
return util.map(cmds, function(cmd)
return Job.new({ cmd = cmd })
return Job.new { cmd = cmd }
end)
end
function Job.start_all(jobs)
for _,job in pairs(jobs) do
for _, job in pairs(jobs) do
job:start()
end
end
function Job.wait_all(jobs)
vim.fn.jobwait(util.map(jobs, function(job)
return job.channel
vim.fn.jobwait(util.map(jobs, function(job)
return job.channel
end))
end

View file

@ -2,21 +2,22 @@ local M = {}
function M.new(initial_value)
initial_value = initial_value or {}
if type(initial_value) ~= "table" then
error("Initial value must be a table", 2)
if type(initial_value) ~= "table" then
error("Initial value must be a table", 2)
end
return setmetatable(initial_value, { __index = M })
end
function M.append(tbl, data)
if type(data) == 'string' then table.insert(tbl, data)
elseif type(data) == 'table' then
for _, r in ipairs(data) do
table.insert(tbl, r)
if type(data) == "string" then
table.insert(tbl, data)
elseif type(data) == "table" then
for _, r in ipairs(data) do
table.insert(tbl, r)
end
else
error('invalid data type: ' .. type(data), 2)
else
error("invalid data type: " .. type(data), 2)
end
return tbl
end

View file

@ -25,11 +25,11 @@ local function new()
mappings = mappings,
map_id_to_key = map_id_to_key,
register = function()
for k,mapping in pairs(mappings) do
for k, mapping in pairs(mappings) do
local map_id = #map_id_to_key + 1
local f_call = build_call_string(id, map_id)
if type(mapping) == "table" then
for _,m in pairs(vim.split(mapping[1], "")) do
for _, m in pairs(vim.split(mapping[1], "")) do
if type(mapping[2]) == "string" then
f_call = mapping[2]
elseif mapping[3] and m == "v" then
@ -38,7 +38,7 @@ local function new()
vim.api.nvim_buf_set_keymap(id, m, k, f_call, {
silent = true,
noremap = true,
nowait = true
nowait = true,
})
end
else
@ -48,13 +48,13 @@ local function new()
vim.api.nvim_buf_set_keymap(id, "n", k, f_call, {
silent = true,
noremap = true,
nowait = true
nowait = true,
})
end
table.insert(map_id_to_key, k)
end
end
end,
}
managers[id] = manager
@ -70,5 +70,5 @@ return {
new = new,
build_call_string = build_call_string,
delete = delete,
invoke = invoke
invoke = invoke,
}

View file

@ -1,10 +1,10 @@
--# selene: allow(parenthese_conditions, multiple_statements, incorrect_standard_library_use)
local md5 = {
_VERSION = "md5.lua 1.1.0",
_VERSION = "md5.lua 1.1.0",
_DESCRIPTION = "MD5 computation in Lua (5.1-3, LuaJIT)",
_URL = "https://github.com/kikito/md5.lua",
_LICENSE = [[
_URL = "https://github.com/kikito/md5.lua",
_LICENSE = [[
MIT LICENSE
Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software
@ -27,23 +27,21 @@ local md5 = {
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
]],
}
-- bit lib implementions
local char, byte, format, rep, sub =
string.char, string.byte, string.format, string.rep, string.sub
local char, byte, format, rep, sub = string.char, string.byte, string.format, string.rep, string.sub
local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift
local ok, bit = pcall(require, 'bit')
local ok, bit = pcall(require, "bit")
if ok then
bit_or, bit_and, bit_xor, bit_rshift, bit_lshift = bit.bor, bit.band, bit.bxor, bit.rshift, bit.lshift
else
ok, bit = pcall(require, 'bit32')
ok, bit = pcall(require, "bit32")
if ok then
bit_not = bit.bnot
local tobit = function(n)
@ -51,16 +49,14 @@ else
end
local normalize = function(f)
return function(a,b)
return tobit(f(tobit(a), tobit(b)))
return function(a, b)
return tobit(f(tobit(a), tobit(b)))
end
end
bit_or, bit_and, bit_xor = normalize(bit.bor), normalize(bit.band), normalize(bit.bxor)
bit_rshift, bit_lshift = normalize(bit.rshift), normalize(bit.lshift)
else
local function tbl2number(tbl)
local result = 0
local power = 1
@ -98,7 +94,7 @@ else
end
-- defined as local above
to_bits = function (n)
to_bits = function(n)
if n < 0 then
-- negative
return to_bits(bit_not(math.abs(n)) + 1)
@ -108,10 +104,10 @@ else
local cnt = 1
local last
while n > 0 do
last = n % 2
tbl[cnt] = last
n = (n-last)/2
cnt = cnt + 1
last = n % 2
tbl[cnt] = last
n = (n - last) / 2
cnt = cnt + 1
end
return tbl
@ -141,7 +137,7 @@ else
local tbl = {}
for i = 1, #tbl_m do
if tbl_m[i]== 0 or tbl_n[i] == 0 then
if tbl_m[i] == 0 or tbl_n[i] == 0 then
tbl[i] = 0
else
tbl[i] = 1
@ -178,8 +174,8 @@ else
local floor = math.floor
for _=1, bits do
n = n/2
for _ = 1, bits do
n = n / 2
n = bit_or(floor(n), high_bit)
end
return floor(n)
@ -191,8 +187,8 @@ else
n = bit_not(math.abs(n)) + 1
end
for _=1, bits do
n = n*2
for _ = 1, bits do
n = n * 2
end
return bit_and(n, 0xFFFFFFFF)
end
@ -201,16 +197,16 @@ end
-- convert little-endian 32-bit int to a 4-char string
local function lei2str(i)
local f=function (s)
return char( bit_and( bit_rshift(i, s), 255))
local f = function(s)
return char(bit_and(bit_rshift(i, s), 255))
end
return f(0)..f(8)..f(16)..f(24)
return f(0) .. f(8) .. f(16) .. f(24)
end
-- convert raw string to big-endian int
local function str2bei(s)
local v=0
for i=1, #s do
local v = 0
for i = 1, #s do
v = v * 256 + byte(s, i)
end
return v
@ -218,18 +214,18 @@ end
-- convert raw string to little-endian int
local function str2lei(s)
local v=0
for i = #s,1,-1 do
v = v*256 + byte(s, i)
local v = 0
for i = #s, 1, -1 do
v = v * 256 + byte(s, i)
end
return v
end
-- cut up a string in little-endian ints of given size
local function cut_le_str(s,...)
local function cut_le_str(s, ...)
local o, r = 1, {}
local args = {...}
for i=1, #args do
local args = { ... }
for i = 1, #args do
table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
o = o + args[i]
end
@ -240,109 +236,170 @@ end
-- 10/02/2001 jcw@equi4.com
local CONSTS = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
0xd76aa478,
0xe8c7b756,
0x242070db,
0xc1bdceee,
0xf57c0faf,
0x4787c62a,
0xa8304613,
0xfd469501,
0x698098d8,
0x8b44f7af,
0xffff5bb1,
0x895cd7be,
0x6b901122,
0xfd987193,
0xa679438e,
0x49b40821,
0xf61e2562,
0xc040b340,
0x265e5a51,
0xe9b6c7aa,
0xd62f105d,
0x02441453,
0xd8a1e681,
0xe7d3fbc8,
0x21e1cde6,
0xc33707d6,
0xf4d50d87,
0x455a14ed,
0xa9e3e905,
0xfcefa3f8,
0x676f02d9,
0x8d2a4c8a,
0xfffa3942,
0x8771f681,
0x6d9d6122,
0xfde5380c,
0xa4beea44,
0x4bdecfa9,
0xf6bb4b60,
0xbebfbc70,
0x289b7ec6,
0xeaa127fa,
0xd4ef3085,
0x04881d05,
0xd9d4d039,
0xe6db99e5,
0x1fa27cf8,
0xc4ac5665,
0xf4292244,
0x432aff97,
0xab9423a7,
0xfc93a039,
0x655b59c3,
0x8f0ccc92,
0xffeff47d,
0x85845dd1,
0x6fa87e4f,
0xfe2ce6e0,
0xa3014314,
0x4e0811a1,
0xf7537e82,
0xbd3af235,
0x2ad7d2bb,
0xeb86d391,
0x67452301,
0xefcdab89,
0x98badcfe,
0x10325476,
}
local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
local z=function (ff,a,b,c,d,x,s,ac)
a=bit_and(a+ff(b,c,d)+x+ac,0xFFFFFFFF)
local f = function(x, y, z)
return bit_or(bit_and(x, y), bit_and(-x - 1, z))
end
local g = function(x, y, z)
return bit_or(bit_and(x, z), bit_and(y, -z - 1))
end
local h = function(x, y, z)
return bit_xor(x, bit_xor(y, z))
end
local i = function(x, y, z)
return bit_xor(y, bit_or(x, -z - 1))
end
local z = function(ff, a, b, c, d, x, s, ac)
a = bit_and(a + ff(b, c, d) + x + ac, 0xFFFFFFFF)
-- be *very* careful that left shift does not cause rounding!
return bit_or(bit_lshift(bit_and(a,bit_rshift(0xFFFFFFFF,s)),s),bit_rshift(a,32-s))+b
return bit_or(bit_lshift(bit_and(a, bit_rshift(0xFFFFFFFF, s)), s), bit_rshift(a, 32 - s)) + b
end
local function transform(A,B,C,D,X)
local a,b,c,d=A,B,C,D
local t=CONSTS
local function transform(A, B, C, D, X)
local a, b, c, d = A, B, C, D
local t = CONSTS
a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
d=z(f,d,a,b,c,X[ 1],12,t[ 2])
c=z(f,c,d,a,b,X[ 2],17,t[ 3])
b=z(f,b,c,d,a,X[ 3],22,t[ 4])
a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
d=z(f,d,a,b,c,X[ 5],12,t[ 6])
c=z(f,c,d,a,b,X[ 6],17,t[ 7])
b=z(f,b,c,d,a,X[ 7],22,t[ 8])
a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
d=z(f,d,a,b,c,X[ 9],12,t[10])
c=z(f,c,d,a,b,X[10],17,t[11])
b=z(f,b,c,d,a,X[11],22,t[12])
a=z(f,a,b,c,d,X[12], 7,t[13])
d=z(f,d,a,b,c,X[13],12,t[14])
c=z(f,c,d,a,b,X[14],17,t[15])
b=z(f,b,c,d,a,X[15],22,t[16])
a = z(f, a, b, c, d, X[0], 7, t[1])
d = z(f, d, a, b, c, X[1], 12, t[2])
c = z(f, c, d, a, b, X[2], 17, t[3])
b = z(f, b, c, d, a, X[3], 22, t[4])
a = z(f, a, b, c, d, X[4], 7, t[5])
d = z(f, d, a, b, c, X[5], 12, t[6])
c = z(f, c, d, a, b, X[6], 17, t[7])
b = z(f, b, c, d, a, X[7], 22, t[8])
a = z(f, a, b, c, d, X[8], 7, t[9])
d = z(f, d, a, b, c, X[9], 12, t[10])
c = z(f, c, d, a, b, X[10], 17, t[11])
b = z(f, b, c, d, a, X[11], 22, t[12])
a = z(f, a, b, c, d, X[12], 7, t[13])
d = z(f, d, a, b, c, X[13], 12, t[14])
c = z(f, c, d, a, b, X[14], 17, t[15])
b = z(f, b, c, d, a, X[15], 22, t[16])
a=z(g,a,b,c,d,X[ 1], 5,t[17])
d=z(g,d,a,b,c,X[ 6], 9,t[18])
c=z(g,c,d,a,b,X[11],14,t[19])
b=z(g,b,c,d,a,X[ 0],20,t[20])
a=z(g,a,b,c,d,X[ 5], 5,t[21])
d=z(g,d,a,b,c,X[10], 9,t[22])
c=z(g,c,d,a,b,X[15],14,t[23])
b=z(g,b,c,d,a,X[ 4],20,t[24])
a=z(g,a,b,c,d,X[ 9], 5,t[25])
d=z(g,d,a,b,c,X[14], 9,t[26])
c=z(g,c,d,a,b,X[ 3],14,t[27])
b=z(g,b,c,d,a,X[ 8],20,t[28])
a=z(g,a,b,c,d,X[13], 5,t[29])
d=z(g,d,a,b,c,X[ 2], 9,t[30])
c=z(g,c,d,a,b,X[ 7],14,t[31])
b=z(g,b,c,d,a,X[12],20,t[32])
a = z(g, a, b, c, d, X[1], 5, t[17])
d = z(g, d, a, b, c, X[6], 9, t[18])
c = z(g, c, d, a, b, X[11], 14, t[19])
b = z(g, b, c, d, a, X[0], 20, t[20])
a = z(g, a, b, c, d, X[5], 5, t[21])
d = z(g, d, a, b, c, X[10], 9, t[22])
c = z(g, c, d, a, b, X[15], 14, t[23])
b = z(g, b, c, d, a, X[4], 20, t[24])
a = z(g, a, b, c, d, X[9], 5, t[25])
d = z(g, d, a, b, c, X[14], 9, t[26])
c = z(g, c, d, a, b, X[3], 14, t[27])
b = z(g, b, c, d, a, X[8], 20, t[28])
a = z(g, a, b, c, d, X[13], 5, t[29])
d = z(g, d, a, b, c, X[2], 9, t[30])
c = z(g, c, d, a, b, X[7], 14, t[31])
b = z(g, b, c, d, a, X[12], 20, t[32])
a=z(h,a,b,c,d,X[ 5], 4,t[33])
d=z(h,d,a,b,c,X[ 8],11,t[34])
c=z(h,c,d,a,b,X[11],16,t[35])
b=z(h,b,c,d,a,X[14],23,t[36])
a=z(h,a,b,c,d,X[ 1], 4,t[37])
d=z(h,d,a,b,c,X[ 4],11,t[38])
c=z(h,c,d,a,b,X[ 7],16,t[39])
b=z(h,b,c,d,a,X[10],23,t[40])
a=z(h,a,b,c,d,X[13], 4,t[41])
d=z(h,d,a,b,c,X[ 0],11,t[42])
c=z(h,c,d,a,b,X[ 3],16,t[43])
b=z(h,b,c,d,a,X[ 6],23,t[44])
a=z(h,a,b,c,d,X[ 9], 4,t[45])
d=z(h,d,a,b,c,X[12],11,t[46])
c=z(h,c,d,a,b,X[15],16,t[47])
b=z(h,b,c,d,a,X[ 2],23,t[48])
a = z(h, a, b, c, d, X[5], 4, t[33])
d = z(h, d, a, b, c, X[8], 11, t[34])
c = z(h, c, d, a, b, X[11], 16, t[35])
b = z(h, b, c, d, a, X[14], 23, t[36])
a = z(h, a, b, c, d, X[1], 4, t[37])
d = z(h, d, a, b, c, X[4], 11, t[38])
c = z(h, c, d, a, b, X[7], 16, t[39])
b = z(h, b, c, d, a, X[10], 23, t[40])
a = z(h, a, b, c, d, X[13], 4, t[41])
d = z(h, d, a, b, c, X[0], 11, t[42])
c = z(h, c, d, a, b, X[3], 16, t[43])
b = z(h, b, c, d, a, X[6], 23, t[44])
a = z(h, a, b, c, d, X[9], 4, t[45])
d = z(h, d, a, b, c, X[12], 11, t[46])
c = z(h, c, d, a, b, X[15], 16, t[47])
b = z(h, b, c, d, a, X[2], 23, t[48])
a=z(i,a,b,c,d,X[ 0], 6,t[49])
d=z(i,d,a,b,c,X[ 7],10,t[50])
c=z(i,c,d,a,b,X[14],15,t[51])
b=z(i,b,c,d,a,X[ 5],21,t[52])
a=z(i,a,b,c,d,X[12], 6,t[53])
d=z(i,d,a,b,c,X[ 3],10,t[54])
c=z(i,c,d,a,b,X[10],15,t[55])
b=z(i,b,c,d,a,X[ 1],21,t[56])
a=z(i,a,b,c,d,X[ 8], 6,t[57])
d=z(i,d,a,b,c,X[15],10,t[58])
c=z(i,c,d,a,b,X[ 6],15,t[59])
b=z(i,b,c,d,a,X[13],21,t[60])
a=z(i,a,b,c,d,X[ 4], 6,t[61])
d=z(i,d,a,b,c,X[11],10,t[62])
c=z(i,c,d,a,b,X[ 2],15,t[63])
b=z(i,b,c,d,a,X[ 9],21,t[64])
a = z(i, a, b, c, d, X[0], 6, t[49])
d = z(i, d, a, b, c, X[7], 10, t[50])
c = z(i, c, d, a, b, X[14], 15, t[51])
b = z(i, b, c, d, a, X[5], 21, t[52])
a = z(i, a, b, c, d, X[12], 6, t[53])
d = z(i, d, a, b, c, X[3], 10, t[54])
c = z(i, c, d, a, b, X[10], 15, t[55])
b = z(i, b, c, d, a, X[1], 21, t[56])
a = z(i, a, b, c, d, X[8], 6, t[57])
d = z(i, d, a, b, c, X[15], 10, t[58])
c = z(i, c, d, a, b, X[6], 15, t[59])
b = z(i, b, c, d, a, X[13], 21, t[60])
a = z(i, a, b, c, d, X[4], 6, t[61])
d = z(i, d, a, b, c, X[11], 10, t[62])
c = z(i, c, d, a, b, X[2], 15, t[63])
b = z(i, b, c, d, a, X[9], 21, t[64])
return bit_and(A+a,0xFFFFFFFF),bit_and(B+b,0xFFFFFFFF),
bit_and(C+c,0xFFFFFFFF),bit_and(D+d,0xFFFFFFFF)
return bit_and(A + a, 0xFFFFFFFF),
bit_and(B + b, 0xFFFFFFFF),
bit_and(C + c, 0xFFFFFFFF),
bit_and(D + d, 0xFFFFFFFF)
end
----------------------------------------------------------------
@ -351,12 +408,12 @@ local function md5_update(self, s)
self.pos = self.pos + #s
s = self.buf .. s
for ii = 1, #s - 63, 64 do
local X = cut_le_str(sub(s,ii,ii+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
local X = cut_le_str(sub(s, ii, ii + 63), 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4)
assert(#X == 16)
X[0] = table.remove(X,1) -- zero based!
self.a,self.b,self.c,self.d = transform(self.a,self.b,self.c,self.d,X)
X[0] = table.remove(X, 1) -- zero based!
self.a, self.b, self.c, self.d = transform(self.a, self.b, self.c, self.d, X)
end
self.buf = sub(s, math.floor(#s/64)*64 + 1, #s)
self.buf = sub(s, math.floor(#s / 64) * 64 + 1, #s)
return self
end
@ -364,14 +421,18 @@ local function md5_finish(self)
local msgLen = self.pos
local padLen = 56 - msgLen % 64
if msgLen % 64 > 56 then padLen = padLen + 64 end
if msgLen % 64 > 56 then
padLen = padLen + 64
end
if padLen == 0 then padLen = 64 end
if padLen == 0 then
padLen = 64
end
local s = char(128)
.. rep(char(0),padLen-1)
.. lei2str(bit_and(8*msgLen, 0xFFFFFFFF))
.. lei2str(math.floor(msgLen/0x20000000))
.. rep(char(0), padLen - 1)
.. lei2str(bit_and(8 * msgLen, 0xFFFFFFFF))
.. lei2str(math.floor(msgLen / 0x20000000))
md5_update(self, s)
assert(self.pos % 64 == 0)
@ -381,11 +442,16 @@ end
----------------------------------------------------------------
function md5.new()
return { a = CONSTS[65], b = CONSTS[66], c = CONSTS[67], d = CONSTS[68],
pos = 0,
buf = '',
update = md5_update,
finish = md5_finish }
return {
a = CONSTS[65],
b = CONSTS[66],
c = CONSTS[67],
d = CONSTS[68],
pos = 0,
buf = "",
update = md5_update,
finish = md5_finish,
}
end
function md5.tohex(s)

View file

@ -19,7 +19,7 @@ local function create(message, level, delay)
notification_count = notification_count + 1
local prev_notification = notifications[notification_count - 1]
or {height = 0, row = vim.api.nvim_get_option("lines") - 2}
or { height = 0, row = vim.api.nvim_get_option("lines") - 2 }
local width = #message
local height = 1
local padding = 2 + prev_notification.height
@ -40,7 +40,7 @@ local function create(message, level, delay)
width = width,
anchor = "SE",
height = height,
style = "minimal"
style = "minimal",
})
local border_buf = vim.api.nvim_create_buf(false, true)
@ -52,7 +52,7 @@ local function create(message, level, delay)
table.insert(border_buf_lines, string.format("╭%s╮", string.rep("", width)))
for _=1,height do
for _ = 1, height do
table.insert(border_buf_lines, string.format("│%s│", string.rep(" ", width)))
end
@ -67,7 +67,7 @@ local function create(message, level, delay)
width = width + 3,
anchor = "SE",
height = height + 2,
style = "minimal"
style = "minimal",
})
if level == vim.log.levels.INFO then
@ -91,7 +91,7 @@ local function create(message, level, delay)
col = col,
border = {
window = border_win,
buffer = border_buf
buffer = border_buf,
},
content = message,
delete = function()
@ -113,14 +113,14 @@ local function create(message, level, delay)
table.insert(message_history, {
content = message,
level = level
level = level,
})
if vim.fn.winbufnr(window) ~= -1 then
vim.api.nvim_win_close(window, false)
vim.api.nvim_win_close(border_win, false)
end
end
end,
}
table.insert(notifications, notification)
@ -139,5 +139,7 @@ return {
end
notifications = {}
end,
get_history = function() return message_history end
get_history = function()
return message_history
end,
}

View file

@ -1,9 +1,9 @@
local PopupBuilder = require 'neogit.lib.popup.builder'
local Buffer = require 'neogit.lib.buffer'
local common = require 'neogit.buffers.common'
local Ui = require 'neogit.lib.ui'
local logger = require 'neogit.logger'
local util = require 'neogit.lib.util'
local PopupBuilder = require("neogit.lib.popup.builder")
local Buffer = require("neogit.lib.buffer")
local common = require("neogit.buffers.common")
local Ui = require("neogit.lib.ui")
local logger = require("neogit.logger")
local util = require("neogit.lib.util")
local col = Ui.col
local row = Ui.row
@ -22,7 +22,7 @@ end
function M.new(state)
local instance = {
state = state,
buffer = nil
buffer = nil,
}
setmetatable(instance, { __index = M })
return instance
@ -88,11 +88,11 @@ function M:toggle_switch(switch)
end
function M:set_option(option)
option.value = vim.fn.input({
option.value = vim.fn.input {
prompt = option.cli .. "=",
default = option.value,
cancelreturn = option.value
})
cancelreturn = option.value,
}
local c = self.buffer.ui:find_component(function(c)
return c.options.id == option.id
end)
@ -103,53 +103,53 @@ end
local Switches = Component.new(function(props)
return col {
text.highlight("NeogitPopupSectionTitle") "Switches",
text.highlight("NeogitPopupSectionTitle")("Switches"),
col(map(props.state, function(switch)
return row.tag("Switch").value(switch) {
row.highlight("NeogitPopupSwitchKey") {
text " -",
text(" -"),
text(switch.key),
},
text " ",
text(" "),
text(switch.description),
text " (",
text(" ("),
row.id(switch.id).highlight(get_highlight_for_switch(switch)) {
text "--",
text(switch.cli)
text("--"),
text(switch.cli),
},
text ")"
text(")"),
}
end))
end)),
}
end)
local Options = Component.new(function(props)
return col {
text.highlight("NeogitPopupSectionTitle") "Options",
text.highlight("NeogitPopupSectionTitle")("Options"),
col(map(props.state, function(option)
return row.tag("Option").value(option) {
row.highlight("NeogitPopupOptionKey") {
text " =",
text(" ="),
text(option.key),
},
text " ",
text(" "),
text(option.description),
text " (",
text(" ("),
row.id(option.id).highlight(get_highlight_for_option(option)) {
text "--",
text("--"),
text(option.cli),
text "=",
text(option.value or "")
text("="),
text(option.value or ""),
},
text ")"
text(")"),
}
end))
end)),
}
end)
local Actions = Component.new(function(props)
return col {
text.highlight("NeogitPopupSectionTitle") "Actions",
text.highlight("NeogitPopupSectionTitle")("Actions"),
Grid.padding_left(1) {
items = props.state,
gap = 1,
@ -157,18 +157,18 @@ local Actions = Component.new(function(props)
if not item.callback then
return row.highlight("NeogitPopupActionDisabled") {
text(item.key),
text " ",
text(" "),
text(item.description),
}
end
return row {
text.highlight("NeogitPopupActionKey")(item.key),
text " ",
text(" "),
text(item.description),
}
end
}
end,
},
}
end)
@ -181,7 +181,7 @@ function M:show()
["<tab>"] = function()
local stack = self.buffer.ui:get_component_stack_under_cursor()
for _,x in ipairs(stack) do
for _, x in ipairs(stack) do
if x.options.tag == "Switch" then
self:toggle_switch(x.options.value)
break
@ -191,7 +191,7 @@ function M:show()
end
end
end,
}
},
}
for _, switch in pairs(self.state.switches) do
@ -219,7 +219,7 @@ function M:show()
end
else
mappings.n[action.key] = function()
local notif = require 'neogit.lib.notification'
local notif = require("neogit.lib.notification")
notif.create(action.description .. " has not been implemented yet", vim.log.levels.WARN)
end
end
@ -238,15 +238,15 @@ function M:show()
items = {
Switches { state = self.state.switches },
Options { state = self.state.options },
Actions { state = self.state.actions }
}
}
Actions { state = self.state.actions },
},
},
}
end
end,
}
end
M.deprecated_create = require 'neogit.lib.popup.lib'.create
M.deprecated_create = require("neogit.lib.popup.lib").create
return M
-- return require("neogit.lib.popup.lib")

View file

@ -1,4 +1,4 @@
local a = require 'plenary.async'
local a = require("plenary.async")
local M = {}
@ -8,10 +8,10 @@ function M.new(builder_fn)
name = nil,
switches = {},
options = {},
actions = {{}},
actions = { {} },
env = {},
},
builder_fn = builder_fn
builder_fn = builder_fn,
}
setmetatable(instance, { __index = M })
@ -34,7 +34,7 @@ function M:new_action_group()
return self
end
--@param parse Whether the switch is internal to neogit or should be included in the cli command.
--@param parse Whether the switch is internal to neogit or should be included in the cli command.
-- If `false` we don't include it in the cli comand.
function M:switch(key, cli, description, enabled, parse)
if enabled == nil then
@ -46,12 +46,12 @@ function M:switch(key, cli, description, enabled, parse)
end
table.insert(self.state.switches, {
id = '-' .. key,
id = "-" .. key,
key = key,
cli = cli,
description = description,
enabled = enabled,
parse = parse
parse = parse,
})
return self
@ -59,7 +59,7 @@ end
function M:option(key, cli, value, description)
table.insert(self.state.options, {
id = '=' .. key,
id = "=" .. key,
key = key,
cli = cli,
value = value,
@ -73,7 +73,7 @@ function M:action(key, description, callback)
table.insert(self.state.actions[#self.state.actions], {
key = key,
description = description,
callback = callback and a.void(callback) or nil
callback = callback and a.void(callback) or nil,
})
return self
@ -84,7 +84,7 @@ function M:action_if(cond, key, description, callback)
table.insert(self.state.actions[#self.state.actions], {
key = key,
description = description,
callback = callback and a.void(callback) or nil
callback = callback and a.void(callback) or nil,
})
end

View file

@ -1,6 +1,6 @@
package.loaded['neogit.lib.popup.lib'] = nil
package.loaded["neogit.lib.popup.lib"] = nil
local a = require 'plenary.async'
local a = require("plenary.async")
local util = require("neogit.lib.util")
local popups = {}
@ -27,7 +27,7 @@ local function draw_popup(popup)
col = 6 + #switch.key + #switch.description,
length = 2 + #switch.cli,
id = 0,
enabled = switch.enabled
enabled = switch.enabled,
}
end
@ -41,7 +41,7 @@ local function draw_popup(popup)
col = 6 + #option.key + #option.description,
length = 3 + #option.cli,
id = 0,
enabled = #option.value ~= 0
enabled = #option.value ~= 0,
}
end
@ -72,13 +72,13 @@ local function draw_popup(popup)
end
table.insert(columns, {
k_width = k_width,
d_width = d_width,
items = col
k_width = k_width,
d_width = d_width,
items = col,
})
end
for i=1,actions_grid_height do
for i = 1, actions_grid_height do
local result = " "
for index, col in pairs(columns) do
local item = col.items[i]
@ -88,15 +88,12 @@ local function draw_popup(popup)
if item == nil then
local key = next_col and util.str_right_pad("", col.k_width + 1, " ") or ""
local description = next_col
and util.str_right_pad("", col.d_width + 6, " ")
or ""
local description = next_col and util.str_right_pad("", col.d_width + 6, " ") or ""
result = result .. key .. description
else
local key = util.str_right_pad(item.key, col.k_width + 1, " ")
local description = has_neighbour
and util.str_right_pad(item.description, col.d_width + 6, " ")
local description = has_neighbour and util.str_right_pad(item.description, col.d_width + 6, " ")
or item.description
result = result .. key .. description
@ -165,18 +162,18 @@ local function toggle_popup_option(buf_handle, key)
vim.api.nvim_buf_set_option(buf_handle, "modifiable", false)
end
option.value = vim.fn.input({
option.value = vim.fn.input {
prompt = option.cli .. "=",
default = option.value,
cancelreturn = option.value
})
cancelreturn = option.value,
}
h.enabled = #option.value ~= 0
if h.enabled then
vim.api.nvim_win_set_cursor(0, { h.line, h.col + h.length - 1 })
vim.api.nvim_buf_set_option(buf_handle, "modifiable", true)
vim.api.nvim_put({option.value}, "c", false, false)
vim.api.nvim_put({ option.value }, "c", false, false)
vim.api.nvim_buf_set_option(buf_handle, "modifiable", false)
end
@ -191,7 +188,7 @@ local function toggle_popup_option(buf_handle, key)
end
local function toggle(buf_handle)
local line = vim.fn.getline('.')
local line = vim.fn.getline(".")
local matches = vim.fn.matchlist(line, "^ \\([-=]\\)\\([a-zA-Z]\\)")
local is_switch = matches[2] == "-"
local key = matches[3]
@ -228,9 +225,9 @@ local function create_popup(id, switches, options, actions, env)
local flags = collect_arguments()
return table.concat(flags, " ")
end,
get_arguments = function ()
get_arguments = function()
return collect_arguments()
end
end,
}
local buf_handle = vim.fn.bufnr(popup.id)
@ -268,11 +265,15 @@ local function create_popup(id, switches, options, actions, env)
buf_handle,
"n",
"-" .. switch.key,
string.format("<cmd>lua require'neogit.lib.popup.lib'.toggle_switch(%d, '%s')<CR>", buf_handle, switch.key),
string.format(
"<cmd>lua require'neogit.lib.popup.lib'.toggle_switch(%d, '%s')<CR>",
buf_handle,
switch.key
),
{
noremap = true,
silent = true,
nowait = true
nowait = true,
}
)
end
@ -282,11 +283,15 @@ local function create_popup(id, switches, options, actions, env)
buf_handle,
"n",
"=" .. option.key,
string.format("<cmd>lua require'neogit.lib.popup.lib'.toggle_option(%d, '%s')<CR>", buf_handle, option.key),
string.format(
"<cmd>lua require'neogit.lib.popup.lib'.toggle_option(%d, '%s')<CR>",
buf_handle,
option.key
),
{
noremap = true,
silent = true,
nowait = true
nowait = true,
}
)
end
@ -301,23 +306,17 @@ local function create_popup(id, switches, options, actions, env)
{
noremap = true,
silent = true,
nowait = true
nowait = true,
}
)
end
end
vim.api.nvim_buf_set_keymap(
buf_handle,
"n",
"q",
"<cmd>bw<CR>",
{
noremap = true,
silent = true,
nowait = true
}
)
vim.api.nvim_buf_set_keymap(buf_handle, "n", "q", "<cmd>bw<CR>", {
noremap = true,
silent = true,
nowait = true,
})
vim.api.nvim_buf_set_keymap(
buf_handle,
"n",
@ -326,7 +325,7 @@ local function create_popup(id, switches, options, actions, env)
{
noremap = true,
silent = true,
nowait = true
nowait = true,
}
)
end
@ -337,16 +336,16 @@ local function new()
name = nil,
switches = {},
options = {},
actions = {{}},
env = {}
}
actions = { {} },
env = {},
},
}
function builder.name(name)
builder.state.name = name
return builder
end
function builder.env(env)
builder.state.env = env
return builder
@ -366,7 +365,7 @@ local function new()
key = key,
cli = cli,
description = description,
enabled = enabled
enabled = enabled,
})
return builder
@ -387,7 +386,7 @@ local function new()
table.insert(builder.state.actions[#builder.state.actions], {
key = key,
description = description,
callback = callback and a.void(callback) or function() end
callback = callback and a.void(callback) or function() end,
})
return builder
@ -416,5 +415,5 @@ return {
toggle = toggle,
toggle_switch = toggle_popup_switch,
toggle_option = toggle_popup_option,
do_action = do_action
do_action = do_action,
}

View file

@ -5,10 +5,10 @@ function M.setup()
for key, val in pairs(config.values.signs) do
if key == "hunk" or key == "item" or key == "section" then
vim.fn.sign_define("NeogitClosed:" .. key, {
text = val[1]
text = val[1],
})
vim.fn.sign_define("NeogitOpen:" .. key, {
text = val[2]
text = val[2],
})
end
end

View file

@ -1,8 +1,8 @@
local util = require 'neogit.lib.util'
local util = require("neogit.lib.util")
local default_component_options = {
folded = false,
hidden = false
hidden = false,
}
local Component = {}
@ -45,7 +45,7 @@ function Component:is_under_cursor(cursor)
local col = cursor[2]
local from, to = self:row_range_abs()
local row_ok = from <= row and row <= to
local col_ok = self.position.col_end == -1
local col_ok = self.position.col_end == -1
or (self.position.col_start <= col and col <= self.position.col_end)
return row_ok and col_ok
end
@ -57,7 +57,7 @@ function Component:get_width()
if self.tag == "row" then
local width = 0
for i=1,#self.children do
for i = 1, #self.children do
width = width + self.children[i]:get_width()
end
return width
@ -65,7 +65,7 @@ function Component:get_width()
if self.tag == "col" then
local width = 0
for i=1,#self.children do
for i = 1, #self.children do
local c_width = self.children[i]:get_width()
if c_width > width then
width = c_width
@ -95,7 +95,7 @@ end
function Component.new(f)
local x = {}
setmetatable(x, {
setmetatable(x, {
__call = function(tbl, ...)
local x = f(...)
local options = vim.tbl_extend("force", default_component_options, tbl, x.options or {})
@ -115,7 +115,7 @@ function Component.new(f)
end
return value
end
end,
})
return x
end

View file

@ -1,14 +1,14 @@
local Component = require 'neogit.lib.ui.component'
local util = require 'neogit.lib.util'
local Component = require("neogit.lib.ui.component")
local util = require("neogit.lib.util")
local filter = util.filter
local Ui = {}
function Ui.new(buf)
local this = {
local this = {
buf = buf,
layout = {}
layout = {},
}
setmetatable(this, { __index = Ui })
return this
@ -39,7 +39,7 @@ function Ui._print_component(indent, c, _options)
output = output .. " '" .. c.value .. "'"
end
for k,v in pairs(c.options) do
for k, v in pairs(c.options) do
if k ~= "tag" and k ~= "hidden" then
output = output .. " " .. k .. "=" .. tostring(v)
end
@ -51,9 +51,10 @@ end
function Ui._visualize_tree(indent, components, options)
for _, c in ipairs(components) do
Ui._print_component(indent, c, options)
if (c.tag == "col" or c.tag == "row")
if
(c.tag == "col" or c.tag == "row")
and not (options.collapse_hidden_components and c.options.hidden)
then
then
Ui._visualize_tree(indent + 1, c.children, options)
end
end
@ -129,7 +130,7 @@ end
function Ui:_render(first_line, first_col, parent, components, flags)
local curr_line = first_line
if flags.in_row then
local col_start = first_col
local col_end
@ -156,7 +157,7 @@ function Ui:_render(first_line, first_col, parent, components, flags)
table.insert(highlights, {
from = col_start,
to = col_end,
name = highlight
name = highlight,
})
end
col_start = col_end
@ -193,7 +194,7 @@ function Ui:_render(first_line, first_col, parent, components, flags)
if flags.in_nested_row then
return {
text = text,
highlights = highlights
highlights = highlights,
}
end
@ -253,9 +254,9 @@ function Ui:_render(first_line, first_col, parent, components, flags)
end
function Ui:render(...)
self.layout = {...}
self.layout = filter(self.layout, function(x)
return type(x) == "table"
self.layout = { ... }
self.layout = filter(self.layout, function(x)
return type(x) == "table"
end)
self:update()
end
@ -263,12 +264,18 @@ end
-- This shouldn't be called often as it completely rewrites the whole buffer
function Ui:update()
self.buf:unlock()
local lines_used = self:_render(1, 0, Component.new(function()
return {
tag = "_root",
children = self.layout
}
end)(), self.layout, {})
local lines_used = self:_render(
1,
0,
Component.new(function()
return {
tag = "_root",
children = self.layout,
}
end)(),
self.layout,
{}
)
self.buf:set_lines(lines_used, -1, false, {})
self.buf:lock()
end
@ -279,22 +286,26 @@ function Ui:print_layout_tree(options)
end
function Ui:debug(...)
Ui.visualize_tree({...}, {})
Ui.visualize_tree({ ... }, {})
end
Ui.col = Component.new(function(children, options)
return {
tag = "col",
children = filter(children, function(x) return type(x) == "table" end),
options = options
children = filter(children, function(x)
return type(x) == "table"
end),
options = options,
}
end)
Ui.row = Component.new(function(children, options)
return {
tag = "row",
children = filter(children, function(x) return type(x) == "table" end),
options = options
children = filter(children, function(x)
return type(x) == "table"
end),
options = options,
}
end)
@ -304,16 +315,16 @@ Ui.text = Component.new(function(value, options, ...)
end
vim.validate {
options = {options, "table", true}
options = { options, "table", true },
}
return {
tag = "text",
value = value or "",
options = type(options) == "table" and options or nil
options = type(options) == "table" and options or nil,
}
end)
Ui.Component = require 'neogit.lib.ui.component'
Ui.Component = require("neogit.lib.ui.component")
return Ui

View file

@ -1,8 +1,8 @@
local a = require 'plenary.async'
local a = require("plenary.async")
local function map(tbl, f)
local t = {}
for k,v in pairs(tbl) do
for k, v in pairs(tbl) do
t[k] = f(v)
end
return t
@ -43,7 +43,7 @@ local function range(from, to, step)
to = from
from = 1
end
for i=from, to, step do
for i = from, to, step do
table.insert(t, i)
end
return t
@ -52,7 +52,7 @@ end
local function intersperse(tbl, sep)
local t = {}
local len = #tbl
for i=1,len do
for i = 1, len do
table.insert(t, tbl[i])
if i ~= len then
@ -67,7 +67,7 @@ local function filter(tbl, f)
end
local function print_tbl(tbl)
for _,x in pairs(tbl) do
for _, x in pairs(tbl) do
print("| " .. x)
end
end
@ -75,12 +75,9 @@ end
local function get_keymaps(mode, startswith)
local maps = vim.api.nvim_get_keymap(mode)
if startswith then
return filter(
maps,
function (x)
return vim.startswith(x.lhs, startswith)
end
)
return filter(maps, function(x)
return vim.startswith(x.lhs, startswith)
end)
else
return maps
end
@ -104,7 +101,7 @@ local function str_right_pad(str, len, sep)
return str .. sep:rep(len - #str)
end
local function slice (tbl, s, e)
local function slice(tbl, s, e)
local pos, new = 1, {}
if e == nil then
@ -122,7 +119,7 @@ end
local function str_count(str, target)
local count = 0
local str_len = #str
for i=1,str_len do
for i = 1, str_len do
if str:sub(i, i) == target then
count = count + 1
end
@ -131,18 +128,22 @@ local function str_count(str, target)
end
local function split(str, sep)
if str == "" then return {} end
if str == "" then
return {}
end
return vim.split(str, sep)
end
local function split_lines(str)
if str == "" then return {} end
if str == "" then
return {}
end
-- we need \r? to support windows
return vim.split(str, '\r?\n')
return vim.split(str, "\r?\n")
end
local function parse_command_args(...)
local args = {...}
local args = { ... }
local tbl = {}
for _, val in pairs(args) do
@ -174,6 +175,5 @@ return {
split_lines = split_lines,
deepcopy = deepcopy,
trim = trim,
parse_command_args = parse_command_args
parse_command_args = parse_command_args,
}

View file

@ -1,19 +1,27 @@
local a = require 'plenary.async'
local a = require("plenary.async")
local M = {}
function M.read_file(path)
local err, fd = a.uv.fs_open(path, "r", 438)
if err then return err end
if err then
return err
end
local err, stat = a.uv.fs_fstat(fd)
if err then return err end
if err then
return err
end
local err, data = a.uv.fs_read(fd, stat.size, 0)
if err then return err end
if err then
return err
end
local err = a.uv.fs_close(fd)
if err then return err end
if err then
return err
end
return nil, data
end

View file

@ -1,8 +1,8 @@
local log = require "plenary.log"
local log = require("plenary.log")
return log.new {
plugin = "neogit",
highlights = false,
use_console = false,
level = "debug"
level = "debug",
}

View file

@ -1,4 +1,4 @@
local a = require 'plenary.async'
local a = require("plenary.async")
-- This is a table to look up pending neogit operations.
-- An operation is loosely defined as a user-triggered, top-level execution
-- like "commit", "stash" or "pull".
@ -14,14 +14,16 @@ local M = {}
local meta = {}
function M.wait(key, time)
if M[key] == nil then return end
vim.fn.wait(time or 1000, function ()
return M[key] == false
if M[key] == nil then
return
end
vim.fn.wait(time or 1000, function()
return M[key] == false
end, 100)
end
function meta.__call(_tbl, key, async_func)
return a.void(function (...)
return a.void(function(...)
M[key] = true
async_func(...)
M[key] = false

View file

@ -1,104 +1,151 @@
local M = {}
local status = require 'neogit.status'
local cli = require 'neogit.lib.git.cli'
local popup = require('neogit.lib.popup')
local branch = require('neogit.lib.git.branch')
local operation = require('neogit.operations')
local BranchSelectViewBuffer = require 'neogit.buffers.branch_select_view'
local input = require('neogit.lib.input')
local status = require("neogit.status")
local cli = require("neogit.lib.git.cli")
local popup = require("neogit.lib.popup")
local branch = require("neogit.lib.git.branch")
local operation = require("neogit.operations")
local BranchSelectViewBuffer = require("neogit.buffers.branch_select_view")
local input = require("neogit.lib.input")
local function format_branches(list)
local branches = {}
for _,name in ipairs(list) do
local name_formatted = name:match("^remotes/(.*)") or name
if not name_formatted:match('^(.*)/HEAD') then
table.insert(branches, name_formatted)
end
local branches = {}
for _, name in ipairs(list) do
local name_formatted = name:match("^remotes/(.*)") or name
if not name_formatted:match("^(.*)/HEAD") then
table.insert(branches, name_formatted)
end
end
return branches
end
local function parse_remote_branch_name(remote_name)
local offset = remote_name:find('/')
if not offset then return nil, nil end
local offset = remote_name:find("/")
if not offset then
return nil, nil
end
local remote = remote_name:sub(1, offset-1)
local branch_name = remote_name:sub(offset+1, remote_name:len())
local remote = remote_name:sub(1, offset - 1)
local branch_name = remote_name:sub(offset + 1, remote_name:len())
return remote, branch_name
return remote, branch_name
end
function M.create()
local p = popup.builder()
:name('NeogitBranchPopup')
:action("n", "create branch", operation('create_branch', function ()
branch.create()
status.refresh(true)
end))
:action("b", "checkout branch/revision", operation('checkout_branch', function ()
local branches = format_branches(branch.get_all_branches())
BranchSelectViewBuffer.new(branches, function (selected_branch)
if selected_branch == '' then return end
local p = popup
.builder()
:name("NeogitBranchPopup")
:action(
"n",
"create branch",
operation("create_branch", function()
branch.create()
status.refresh(true)
end)
)
:action(
"b",
"checkout branch/revision",
operation("checkout_branch", function()
local branches = format_branches(branch.get_all_branches())
BranchSelectViewBuffer.new(branches, function(selected_branch)
if selected_branch == "" then
return
end
cli.checkout.branch(selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("d", "delete local branch", operation('delete_branch', function ()
local branches = branch.get_local_branches()
BranchSelectViewBuffer.new(branches, function (selected_branch)
cli.branch.delete.name(selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("D", "delete local branch and remote", operation('delete_branch', function ()
local branches = format_branches(branch.get_remote_branches())
BranchSelectViewBuffer.new(branches, function (selected_branch)
if selected_branch == '' then return end
cli.checkout.branch(selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end)
)
:action(
"d",
"delete local branch",
operation("delete_branch", function()
local branches = branch.get_local_branches()
BranchSelectViewBuffer.new(branches, function(selected_branch)
cli.branch.delete.name(selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end)
)
:action(
"D",
"delete local branch and remote",
operation("delete_branch", function()
local branches = format_branches(branch.get_remote_branches())
BranchSelectViewBuffer.new(branches, function(selected_branch)
if selected_branch == "" then
return
end
local remote, branch_name = parse_remote_branch_name(selected_branch)
if not remote or not branch_name then return end
local remote, branch_name = parse_remote_branch_name(selected_branch)
if not remote or not branch_name then
return
end
cli.branch.delete.name(branch_name).call_sync()
cli.push.remote(remote).delete.to(branch_name).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("l", "checkout local branch", operation('checkout_local-branch', function ()
local branches = branch.get_local_branches()
BranchSelectViewBuffer.new(branches, function (selected_branch)
if selected_branch == '' then return end
cli.checkout.branch(selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("c", "checkout new branch", operation('checkout_create-branch', function ()
local branches = format_branches(branch.get_all_branches())
BranchSelectViewBuffer.new(branches, function(selected_branch)
if selected_branch == '' then return end
cli.branch.delete.name(branch_name).call_sync()
cli.push.remote(remote).delete.to(branch_name).call_sync()
status.dispatch_refresh(true)
end):open()
end)
)
:action(
"l",
"checkout local branch",
operation("checkout_local-branch", function()
local branches = branch.get_local_branches()
BranchSelectViewBuffer.new(branches, function(selected_branch)
if selected_branch == "" then
return
end
cli.checkout.branch(selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end)
)
:action(
"c",
"checkout new branch",
operation("checkout_create-branch", function()
local branches = format_branches(branch.get_all_branches())
BranchSelectViewBuffer.new(branches, function(selected_branch)
if selected_branch == "" then
return
end
local name = input.get_user_input('branch > ')
if not name or name == '' then return end
local name = input.get_user_input("branch > ")
if not name or name == "" then
return
end
cli.checkout.new_branch_with_start_point(name, selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end))
:action("m", "rename branch", operation('rename_branch', function ()
local current_branch = branch.current() or ''
local branches = branch.get_local_branches()
table.insert(branches, current_branch)
cli.checkout.new_branch_with_start_point(name, selected_branch).call_sync()
status.dispatch_refresh(true)
end):open()
end)
)
:action(
"m",
"rename branch",
operation("rename_branch", function()
local current_branch = branch.current() or ""
local branches = branch.get_local_branches()
table.insert(branches, current_branch)
BranchSelectViewBuffer.new(branches, function (selected_branch)
if selected_branch == '' then return end
BranchSelectViewBuffer.new(branches, function(selected_branch)
if selected_branch == "" then
return
end
local new_name = input.get_user_input('new branch name > ')
if not new_name or new_name == '' then return end
local new_name = input.get_user_input("new branch name > ")
if not new_name or new_name == "" then
return
end
cli.branch.move.args(selected_branch, new_name).call_sync()
status.dispatch_refresh(true)
end):open()
end))
cli.branch.move.args(selected_branch, new_name).call_sync()
status.dispatch_refresh(true)
end):open()
end)
)
:build()
p:show()

View file

@ -1,22 +1,22 @@
local popup = require("neogit.lib.popup")
local notif = require("neogit.lib.notification")
local status = require 'neogit.status'
local status = require("neogit.status")
local cli = require("neogit.lib.git.cli")
local input = require("neogit.lib.input")
local Buffer = require("neogit.lib.buffer")
local config = require("neogit.config")
local a = require 'plenary.async'
local split = require('neogit.lib.util').split
local uv_utils = require 'neogit.lib.uv'
local a = require("plenary.async")
local split = require("neogit.lib.util").split
local uv_utils = require("neogit.lib.uv")
local M = {}
local function get_commit_file()
return cli.git_dir_path_sync() .. '/' .. 'NEOGIT_COMMIT_EDITMSG'
return cli.git_dir_path_sync() .. "/" .. "NEOGIT_COMMIT_EDITMSG"
end
-- selene: allow(global_usage)
local get_commit_message = a.wrap(function (content, cb)
local get_commit_message = a.wrap(function(content, cb)
local written = false
Buffer.create {
name = get_commit_file(),
@ -31,12 +31,14 @@ local get_commit_message = a.wrap(function (content, cb)
end,
["BufUnload"] = function()
if written then
if config.values.disable_commit_confirmation or
input.get_confirmation("Are you sure you want to commit?") then
vim.cmd [[
if
config.values.disable_commit_confirmation
or input.get_confirmation("Are you sure you want to commit?")
then
vim.cmd([[
silent g/^#/d
silent w!
]]
]])
cb()
end
end
@ -46,15 +48,15 @@ local get_commit_message = a.wrap(function (content, cb)
n = {
["q"] = function(buffer)
buffer:close(true)
end
}
end,
},
},
initialize = function(buffer)
buffer:set_lines(0, -1, false, content)
if not config.values.disable_insert_on_commit then
vim.cmd(":startinsert")
end
end
end,
}
end, 2)
@ -117,7 +119,8 @@ local function do_commit(popup, data, cmd, skip_gen)
end
function M.create()
local p = popup.builder()
local p = popup
.builder()
:name("NeogitCommitPopup")
:switch("a", "all", "Stage all modified and deleted files", false)
:switch("e", "allow-empty", "Allow empty commit", false)
@ -134,10 +137,15 @@ function M.create()
local commit_file = get_commit_file()
local _, data = uv_utils.read_file(commit_file)
local skip_gen = data ~= nil
data = data or ''
data = data or ""
-- we need \r? to support windows
data = split(data, '\r?\n')
do_commit(popup, data, tostring(cli.commit.commit_message_file(commit_file).args(unpack(popup:get_arguments()))), skip_gen)
data = split(data, "\r?\n")
do_commit(
popup,
data,
tostring(cli.commit.commit_message_file(commit_file).args(unpack(popup:get_arguments()))),
skip_gen
)
end)
:action("e", "Extend", function(popup)
do_commit(popup, nil, tostring(cli.commit.no_edit.amend))
@ -145,14 +153,14 @@ function M.create()
:action("w", "Reword", function(popup)
a.util.scheduler()
local commit_file = get_commit_file()
local msg = cli.log.max_count(1).pretty('%B').call()
local msg = cli.log.max_count(1).pretty("%B").call()
do_commit(popup, msg, tostring(cli.commit.commit_message_file(commit_file).amend.only))
end)
:action("a", "Amend", function(popup)
a.util.scheduler()
local commit_file = get_commit_file()
local msg = cli.log.max_count(1).pretty('%B').call()
local msg = cli.log.max_count(1).pretty("%B").call()
do_commit(popup, msg, tostring(cli.commit.commit_message_file(commit_file).amend), true)
end)

View file

@ -1,17 +1,18 @@
local M = {}
local config = require 'neogit.config'
local popup = require 'neogit.lib.popup'
local config = require("neogit.config")
local popup = require("neogit.lib.popup")
function M.create()
if not config.ensure_integration 'diffview' then
if not config.ensure_integration("diffview") then
return
end
local p = popup.builder()
local p = popup
.builder()
:name("NeogitDiffPopup")
:action("D", "diff against head", function()
require 'neogit.integrations.diffview'.open()
require("neogit.integrations.diffview").open()
end)
:build()

View file

@ -1,34 +1,35 @@
local popup = require("neogit.lib.popup")
local status = require 'neogit.status'
local status = require("neogit.status")
local GitCommandHistory = require("neogit.buffers.git_command_history")
local M = {}
function M.create(env)
local m = env.use_magit_keybindings
local p = popup.builder()
local p = popup
.builder()
:name("NeogitHelpPopup")
:action(m and "F" or "p", "Pull", function()
require('neogit.popups.pull').create()
require("neogit.popups.pull").create()
end)
:action("P", "Push", function()
require('neogit.popups.push').create()
require("neogit.popups.push").create()
end)
:action("Z", "Stash", function(_popup)
require('neogit.popups.stash').create(env.get_stash())
require("neogit.popups.stash").create(env.get_stash())
end)
:action("L", "Log", function()
require('neogit.popups.log').create()
require("neogit.popups.log").create()
end)
:action("r", "Rebase", function()
require("neogit.popups.rebase").create()
end)
:new_action_group()
:action("c", "Commit", function()
require('neogit.popups.commit').create()
require("neogit.popups.commit").create()
end)
:action("b", "Branch", function()
require('neogit.popups.branch').create()
require("neogit.popups.branch").create()
end)
:action("$", "Git Command History", function()
GitCommandHistory:new():show()
@ -40,8 +41,8 @@ function M.create(env)
:build()
p:show()
return p
return p
end
return M

View file

@ -1,7 +1,7 @@
local popup = require("neogit.lib.popup")
local LogViewBuffer = require 'neogit.buffers.log_view'
local LogViewBuffer = require("neogit.buffers.log_view")
local git = require("neogit.lib.git")
local util = require 'neogit.lib.util'
local util = require("neogit.lib.util")
local M = {}
@ -45,7 +45,7 @@ local function parse(raw)
commit.level = util.str_count(s1, "|") + util.str_count(s2, "|")
local start_idx = #s1 + #s2 + 1
local function ladvance()
local line = advance()
return line and line:sub(start_idx + 1, -1) or nil
@ -55,22 +55,17 @@ local function parse(raw)
local line = ladvance()
if vim.startswith(line, "Merge:") then
commit.merge = line
:match("Merge:%s*(%w+) (%w+)")
commit.merge = line:match("Merge:%s*(%w+) (%w+)")
line = ladvance()
end
commit.author_name, commit.author_email = line
:match("Author:%s*(.+) <(.+)>")
commit.author_name, commit.author_email = line:match("Author:%s*(.+) <(.+)>")
end
commit.author_date = ladvance()
:match("AuthorDate:%s*(.+)")
commit.committer_name, commit.committer_email = ladvance()
:match("Commit:%s*(.+) <(.+)>")
commit.committer_date = ladvance()
:match("CommitDate:%s*(.+)")
commit.author_date = ladvance():match("AuthorDate:%s*(.+)")
commit.committer_name, commit.committer_email = ladvance():match("Commit:%s*(.+) <(.+)>")
commit.committer_date = ladvance():match("CommitDate:%s*(.+)")
advance()
@ -95,7 +90,8 @@ end
-- inspect(parse(git.cli.log.args("--max-count=5", "--graph", "--format=fuller").call_sync()))
function M.create()
local p = popup.builder()
local p = popup
.builder()
:name("NeogitLogPopup")
:switch("g", "graph", "Show graph", true, false)
:switch("c", "color", "Show graph in color", true, false)
@ -112,41 +108,30 @@ function M.create()
-- :option("G", "", "", "Search changes")
-- :option("S", "", "", "Search occurences")
-- :option("L", "", "", "Trace line evolution")
:action("l", "Log current", function(popup)
local output = git.cli.log.format("fuller").args("--graph", unpack(popup:get_arguments())).call_sync()
local parse_args = popup:get_parse_arguments()
LogViewBuffer.new(parse(output), parse_args.graph):open()
end)
:action(
"l",
"Log current",
function(popup)
local output = git.cli.log.format("fuller").args("--graph", unpack(popup:get_arguments())).call_sync()
local parse_args = popup:get_parse_arguments()
LogViewBuffer.new(parse(output), parse_args.graph):open()
end
)
:action("o", "Log other")
:action("h", "Log HEAD", function(popup)
local output =
git.cli.log
.format("fuller")
.args(unpack(popup:get_arguments()))
.for_range('HEAD')
.call_sync()
:action("h", "Log HEAD", function(popup)
local output =
git.cli.log.format("fuller").args(unpack(popup:get_arguments())).for_range("HEAD").call_sync()
LogViewBuffer.new(parse(output)):open()
end)
:new_action_group()
:action("b", "Log all branches", function(popup)
local output =
git.cli.log
.format("fuller")
.args(unpack(popup:get_arguments()))
.branches
.remotes
.call_sync()
local output =
git.cli.log.format("fuller").args(unpack(popup:get_arguments())).branches.remotes.call_sync()
LogViewBuffer.new(parse(output)):open()
end)
:action("a", "Log all references", function(popup)
local output =
git.cli.log
.format("fuller")
.args(unpack(popup:get_arguments()))
.all
.call_sync()
local output = git.cli.log.format("fuller").args(unpack(popup:get_arguments())).all.call_sync()
LogViewBuffer.new(parse(output)):open()
end)
:new_action_group()

View file

@ -1,10 +1,10 @@
local popup = require("neogit.lib.popup")
local status = require 'neogit.status'
local input = require 'neogit.lib.input'
local status = require("neogit.status")
local input = require("neogit.lib.input")
local notif = require("neogit.lib.notification")
local git = require("neogit.lib.git")
local pull_lib = require 'neogit.lib.git.pull'
local a = require 'plenary.async'
local pull_lib = require("neogit.lib.git.pull")
local a = require("plenary.async")
local M = {}
@ -21,7 +21,8 @@ local function pull_from(popup, name, remote, branch)
end
function M.create()
local p = popup.builder()
local p = popup
.builder()
:name("NeogitPullPopup")
:switch("r", "rebase", "Rebase local commits", false)
:action("p", "Pull from pushremote", function(popup)

View file

@ -1,12 +1,12 @@
local M = {}
local popup = require("neogit.lib.popup")
local input = require 'neogit.lib.input'
local push_lib = require 'neogit.lib.git.push'
local status = require 'neogit.status'
local input = require("neogit.lib.input")
local push_lib = require("neogit.lib.git.push")
local status = require("neogit.status")
local notif = require("neogit.lib.notification")
local logger = require 'neogit.logger'
local logger = require("neogit.logger")
local git = require("neogit.lib.git")
local a = require 'plenary.async'
local a = require("plenary.async")
local function push_to(popup, name, remote, branch)
logger.debug("Pushing to " .. name)
@ -26,7 +26,8 @@ local function push_to(popup, name, remote, branch)
end
function M.create()
local p = popup.builder()
local p = popup
.builder()
:name("NeogitPushPopup")
:switch("f", "force-with-lease", "Force with lease")
:switch("F", "force", "Force")
@ -44,10 +45,7 @@ function M.create()
return
end
push_to(popup,
upstream.remote.." "..upstream.branch,
upstream.remote,
upstream.branch)
push_to(popup, upstream.remote .. " " .. upstream.branch, upstream.remote, upstream.branch)
end)
:action("e", "Push to elsewhere", function(popup)
local remote = input.get_user_input("remote: ")
@ -57,7 +55,7 @@ function M.create()
:build()
p:show()
return p
end

View file

@ -5,14 +5,15 @@ local git = require("neogit.lib.git")
local popup = require("neogit.lib.popup")
function M.create()
local p = popup.builder()
local p = popup
.builder()
:name("NeogitRebasePopup")
:action("p", "Rebase onto master", function()
cli.rebase.args("master").call_sync()
end)
:action("e", "Rebase onto elsewhere", function()
local branch = git.branch.prompt_for_branch(git.branch.get_all_branches())
cli.rebase.args(branch).call_sync()
cli.rebase.args(branch).call_sync()
end)
:build()

View file

@ -1,11 +1,12 @@
local status = require 'neogit.status'
local stash_lib = require 'neogit.lib.git.stash'
local popup = require('neogit.lib.popup')
local status = require("neogit.status")
local stash_lib = require("neogit.lib.git.stash")
local popup = require("neogit.lib.popup")
local M = {}
function M.create(stash)
local p = popup.builder()
local p = popup
.builder()
:name("NeogitStashPopup")
:switch("a", "all", "", false)
:switch("u", "include-untracked", "", false)

View file

@ -1,14 +1,14 @@
local a = require 'plenary.async'
local a = require("plenary.async")
local function trim_newlines(s)
return (string.gsub(s, "^(.-)\n*$", "%1"))
end
local function spawn(options, cb)
assert(options ~= nil, 'Options parameter must be given')
assert(options.cmd, 'A command needs to be given!')
assert(options ~= nil, "Options parameter must be given")
assert(options.cmd, "A command needs to be given!")
local return_code, output, errors = nil, '', ''
local return_code, output, errors = nil, "", ""
local stdin, stdout, stderr = vim.loop.new_pipe(false), vim.loop.new_pipe(false), vim.loop.new_pipe(false)
local process_closed, stdout_closed, stderr_closed = false, false, false
local function raise_if_fully_closed()
@ -18,29 +18,29 @@ local function spawn(options, cb)
end
local params = {
stdio = {stdin, stdout, stderr},
stdio = { stdin, stdout, stderr },
}
if options.cwd then
params.cwd = options.cwd
if options.cwd then
params.cwd = options.cwd
end
if options.args then
params.args = options.args
if options.args then
params.args = options.args
end
if options.env and #options.env > 0 then
params.env = {}
-- setting 'env' completely overrides the parent environment, so we need to
-- append all variables that are necessary for git to work in addition to
-- all variables from passed object.
table.insert(params.env, string.format('%s=%s', 'HOME', os.getenv('HOME')))
table.insert(params.env, string.format('%s=%s', 'GNUPGHOME', os.getenv('GNUPGHOME')))
table.insert(params.env, string.format("%s=%s", "HOME", os.getenv("HOME")))
table.insert(params.env, string.format("%s=%s", "GNUPGHOME", os.getenv("GNUPGHOME")))
for k, v in pairs(options.env) do
table.insert(params.env, string.format('%s=%s', k, v))
table.insert(params.env, string.format("%s=%s", k, v))
end
end
local handle, err
handle, err = vim.loop.spawn(options.cmd, params, function (code, _)
handle, err = vim.loop.spawn(options.cmd, params, function(code, _)
handle:close()
--print('finished process', vim.inspect(params), vim.inspect({trim_newlines(output), errors}))
@ -70,7 +70,7 @@ local function spawn(options, cb)
output = output .. data
end)
vim.loop.read_start(stderr, function (err, data)
vim.loop.read_start(stderr, function(err, data)
assert(not err, err)
if not data then
stderr:read_stop()
@ -81,7 +81,7 @@ local function spawn(options, cb)
end
--print('STDERR', err, data)
errors = errors .. (data or '')
errors = errors .. (data or "")
end)
if options.input ~= nil then
@ -93,7 +93,7 @@ end
local M = {
spawn = a.wrap(spawn, 2),
spawn_sync = spawn
spawn_sync = spawn,
}
return M

View file

@ -2,17 +2,17 @@ local Buffer = require("neogit.lib.buffer")
local GitCommandHistory = require("neogit.buffers.git_command_history")
local CommitView = require("neogit.buffers.commit_view")
local git = require("neogit.lib.git")
local cli = require('neogit.lib.git.cli')
local cli = require("neogit.lib.git.cli")
local notif = require("neogit.lib.notification")
local config = require("neogit.config")
local a = require 'plenary.async'
local logger = require 'neogit.logger'
local repository = require 'neogit.lib.git.repository'
local Collection = require 'neogit.lib.collection'
local F = require 'neogit.lib.functional'
local LineBuffer = require 'neogit.lib.line_buffer'
local fs = require 'neogit.lib.fs'
local input = require 'neogit.lib.input'
local a = require("plenary.async")
local logger = require("neogit.logger")
local repository = require("neogit.lib.git.repository")
local Collection = require("neogit.lib.collection")
local F = require("neogit.lib.functional")
local LineBuffer = require("neogit.lib.line_buffer")
local fs = require("neogit.lib.fs")
local input = require("neogit.lib.input")
local M = {}
@ -24,9 +24,9 @@ M.status_buffer = nil
M.commit_view = nil
M.locations = {}
local hunk_header_matcher = vim.regex('^@@.*@@')
local diff_add_matcher = vim.regex('^+')
local diff_delete_matcher = vim.regex('^-')
local hunk_header_matcher = vim.regex("^@@.*@@")
local diff_add_matcher = vim.regex("^+")
local diff_delete_matcher = vim.regex("^-")
local function get_section_idx_for_line(linenr)
for i, l in pairs(M.locations) do
@ -77,53 +77,57 @@ local mode_to_text = {
C = "Copied",
U = "Updated",
UU = "Both Modified",
R = "Renamed"
R = "Renamed",
}
local function draw_sign_for_item(item, name)
if item.folded then
M.status_buffer:place_sign(item.first, "NeogitClosed:"..name, "fold_markers")
M.status_buffer:place_sign(item.first, "NeogitClosed:" .. name, "fold_markers")
else
M.status_buffer:place_sign(item.first, "NeogitOpen:"..name, "fold_markers")
M.status_buffer:place_sign(item.first, "NeogitOpen:" .. name, "fold_markers")
end
end
local function draw_signs()
if config.values.disable_signs then return end
if config.values.disable_signs then
return
end
for _, l in ipairs(M.locations) do
draw_sign_for_item(l, 'section')
draw_sign_for_item(l, "section")
if not l.folded then
Collection.new(l.files)
:filter(F.dot('hunks'))
:each(function (f)
draw_sign_for_item(f, 'item')
if not f.folded then
Collection.new(f.hunks):each(function (h)
draw_sign_for_item(h, 'hunk')
end)
end
end)
Collection.new(l.files):filter(F.dot("hunks")):each(function(f)
draw_sign_for_item(f, "item")
if not f.folded then
Collection.new(f.hunks):each(function(h)
draw_sign_for_item(h, "hunk")
end)
end
end)
end
end
end
local function draw_buffer()
M.status_buffer:clear_sign_group('hl')
M.status_buffer:clear_sign_group('fold_markers')
M.status_buffer:clear_sign_group("hl")
M.status_buffer:clear_sign_group("fold_markers")
local output = LineBuffer.new()
if not config.values.disable_hint then
output:append("Hint: [<tab>] toggle diff | [s]tage | [u]nstage | [x] discard | [c]ommit | [?] more help")
output:append("")
end
output:append(string.format("Head: %s %s", M.repo.head.branch, M.repo.head.commit_message or '(no commits)'))
output:append(
string.format("Head: %s %s", M.repo.head.branch, M.repo.head.commit_message or "(no commits)")
)
if M.repo.upstream.branch then
output:append(string.format("Push: %s %s", M.repo.upstream.branch, M.repo.upstream.commit_message or '(no commits)'))
output:append(
string.format("Push: %s %s", M.repo.upstream.branch, M.repo.upstream.commit_message or "(no commits)")
)
end
output:append('')
output:append("")
local new_locations = {}
local locations_lookup = Collection.new(M.locations):key_by('name')
local locations_lookup = Collection.new(M.locations):key_by("name")
local function render_section(header, key)
local section_config = config.values.sections[key]
@ -131,40 +135,44 @@ local function draw_buffer()
return
end
local data = M.repo[key]
if #data.items == 0 then return end
output:append(string.format('%s (%d)', header, #data.items))
if #data.items == 0 then
return
end
output:append(string.format("%s (%d)", header, #data.items))
local location = locations_lookup[key] or {
name = key,
folded = section_config.folded,
files = {}
}
local location = locations_lookup[key]
or {
name = key,
folded = section_config.folded,
files = {},
}
location.first = #output
if not location.folded then
local files_lookup = Collection.new(location.files):key_by('name')
local files_lookup = Collection.new(location.files):key_by("name")
location.files = {}
for _, f in ipairs(data.items) do
if f.mode and f.original_name then
output:append(string.format('%s %s -> %s', mode_to_text[f.mode], f.original_name, f.name))
elseif f.mode then output:append(string.format('%s %s', mode_to_text[f.mode], f.name))
else
output:append(f.name)
output:append(string.format("%s %s -> %s", mode_to_text[f.mode], f.original_name, f.name))
elseif f.mode then
output:append(string.format("%s %s", mode_to_text[f.mode], f.name))
else
output:append(f.name)
end
local file = files_lookup[f.name] or { folded = true }
file.first = #output
if f.diff and not file.folded then
local hunks_lookup = Collection.new(file.hunks or {}):key_by('hash')
local hunks_lookup = Collection.new(file.hunks or {}):key_by("hash")
local hunks = {}
for _, h in ipairs(f.diff.hunks) do
local current_hunk = hunks_lookup[h.hash] or { folded = false }
output:append(f.diff.lines[h.diff_from])
M.status_buffer:place_sign(#output, 'NeogitHunkHeader', 'hl')
M.status_buffer:place_sign(#output, "NeogitHunkHeader", "hl")
current_hunk.first = #output
if not current_hunk.folded then
@ -172,9 +180,9 @@ local function draw_buffer()
local l = f.diff.lines[i]
output:append(l)
if diff_add_matcher:match_str(l) then
M.status_buffer:place_sign(#output, 'NeogitDiffAdd', 'hl')
M.status_buffer:place_sign(#output, "NeogitDiffAdd", "hl")
elseif diff_delete_matcher:match_str(l) then
M.status_buffer:place_sign(#output, 'NeogitDiffDelete', 'hl')
M.status_buffer:place_sign(#output, "NeogitDiffDelete", "hl")
end
end
end
@ -193,17 +201,17 @@ local function draw_buffer()
end
location.last = #output
output:append('')
output:append("")
table.insert(new_locations, location)
end
render_section('Untracked files', 'untracked')
render_section('Unstaged changes', 'unstaged')
render_section('Staged changes', 'staged')
render_section('Stashes', 'stashes')
render_section('Unpulled changes', 'unpulled')
render_section('Unmerged changes', 'unmerged')
render_section('Recent commits', 'recent')
render_section("Untracked files", "untracked")
render_section("Unstaged changes", "unstaged")
render_section("Staged changes", "staged")
render_section("Stashes", "stashes")
render_section("Unpulled changes", "unpulled")
render_section("Unmerged changes", "unmerged")
render_section("Recent commits", "recent")
M.status_buffer:replace_content_with(output)
M.locations = new_locations
@ -216,26 +224,26 @@ end
-- the relative offset of the found item and the string is it's identifier.
-- The remaining 2 numbers are the first and last line of the found section.
local function save_cursor_location()
local line = vim.fn.line('.')
local line = vim.fn.line(".")
local section_loc, file_loc, hunk_loc, first, last
for li, loc in ipairs(M.locations) do
if line == loc.first then
section_loc = {li, loc.name}
section_loc = { li, loc.name }
first, last = loc.first, loc.last
break
elseif line >= loc.first and line <= loc.last then
section_loc = {li, loc.name}
section_loc = { li, loc.name }
for fi, file in ipairs(loc.files) do
if line == file.first then
file_loc = {fi, file.name}
file_loc = { fi, file.name }
first, last = file.first, file.last
break
elseif line >= file.first and line <= file.last then
file_loc = {fi, file.name}
file_loc = { fi, file.name }
for hi, hunk in ipairs(file.hunks) do
if line <= hunk.last then
hunk_loc = {hi, hunk.hash}
hunk_loc = { hi, hunk.hash }
first, last = hunk.first, hunk.last
break
end
@ -251,36 +259,40 @@ local function save_cursor_location()
end
local function restore_cursor_location(section_loc, file_loc, hunk_loc)
if #M.locations == 0 then return vim.fn.setpos('.', {0, 1, 0, 0}) end
if not section_loc then
section_loc = {1, ''}
if #M.locations == 0 then
return vim.fn.setpos(".", { 0, 1, 0, 0 })
end
if not section_loc then
section_loc = { 1, "" }
end
local section = Collection.new(M.locations):find(function (s)
return s.name == section_loc[2]
local section = Collection.new(M.locations):find(function(s)
return s.name == section_loc[2]
end)
if not section then
file_loc, hunk_loc = nil, nil
section = M.locations[section_loc[1]] or M.locations[#M.locations]
end
if not file_loc or not section.files or #section.files == 0 then
return vim.fn.setpos('.', {0, section.first, 0, 0})
return vim.fn.setpos(".", { 0, section.first, 0, 0 })
end
local file = Collection.new(section.files):find(function (f)
return f.name == file_loc[2]
local file = Collection.new(section.files):find(function(f)
return f.name == file_loc[2]
end)
if not file then
hunk_loc = nil
file = section.files[file_loc[1]] or section.files[#section.files]
end
if not hunk_loc or not file.hunks or #file.hunks == 0 then return vim.fn.setpos('.', {0, file.first, 0, 0}) end
if not hunk_loc or not file.hunks or #file.hunks == 0 then
return vim.fn.setpos(".", { 0, file.first, 0, 0 })
end
local hunk = Collection.new(file.hunks):find(function (h) return h.hash == hunk_loc[2] end)
or file.hunks[hunk_loc[1]]
or file.hunks[#file.hunks]
local hunk = Collection.new(file.hunks):find(function(h)
return h.hash == hunk_loc[2]
end) or file.hunks[hunk_loc[1]] or file.hunks[#file.hunks]
vim.fn.setpos('.', {0, hunk.first, 0, 0})
vim.fn.setpos(".", { 0, hunk.first, 0, 0 })
end
local function refresh_status()
@ -290,37 +302,37 @@ local function refresh_status()
M.status_buffer:unlock()
logger.debug "[STATUS BUFFER]: Redrawing"
logger.debug("[STATUS BUFFER]: Redrawing")
draw_buffer()
draw_signs()
logger.debug "[STATUS BUFFER]: Finished Redrawing"
logger.debug("[STATUS BUFFER]: Finished Redrawing")
M.status_buffer:lock()
vim.cmd('redraw')
vim.cmd("redraw")
end
local refresh_lock = a.control.Semaphore.new(1)
local function refresh (which)
local function refresh(which)
which = which or true
logger.debug "[STATUS BUFFER]: Starting refresh"
logger.debug("[STATUS BUFFER]: Starting refresh")
if refresh_lock.permits == 0 then
logger.debug "[STATUS BUFFER]: Refresh lock not available. Aborting refresh"
logger.debug("[STATUS BUFFER]: Refresh lock not available. Aborting refresh")
a.util.scheduler()
refresh_status()
return
end
local permit = refresh_lock:acquire()
logger.debug "[STATUS BUFFER]: Acquired refresh lock"
logger.debug("[STATUS BUFFER]: Acquired refresh lock")
a.util.scheduler()
local s, f, h = save_cursor_location()
if cli.git_root() ~= '' then
if cli.git_root() ~= "" then
if which == true or which.status then
M.repo:update_status()
a.util.scheduler()
@ -329,27 +341,27 @@ local function refresh (which)
local refreshes = {}
if which == true or which.branch_information then
table.insert(refreshes, function()
table.insert(refreshes, function()
logger.debug("[STATUS BUFFER]: Refreshing branch information")
M.repo:update_branch_information()
M.repo:update_branch_information()
end)
end
if which == true or which.stashes then
table.insert(refreshes, function()
table.insert(refreshes, function()
logger.debug("[STATUS BUFFER]: Refreshing stash")
M.repo:update_stashes()
M.repo:update_stashes()
end)
end
if which == true or which.unpulled then
table.insert(refreshes, function()
table.insert(refreshes, function()
logger.debug("[STATUS BUFFER]: Refreshing unpulled commits")
M.repo:update_unpulled()
M.repo:update_unpulled()
end)
end
if which == true or which.unmerged then
table.insert(refreshes, function()
table.insert(refreshes, function()
logger.debug("[STATUS BUFFER]: Refreshing unpushed commits")
M.repo:update_unmerged()
M.repo:update_unmerged()
end)
end
if which == true or which.recent then
@ -359,41 +371,43 @@ local function refresh (which)
end)
end
if which == true or which.diffs then
local filter = (type(which) == "table" and type(which.diffs) == "table")
and which.diffs
or nil
local filter = (type(which) == "table" and type(which.diffs) == "table") and which.diffs or nil
table.insert(refreshes, function()
table.insert(refreshes, function()
logger.debug("[STATUS BUFFER]: Refreshing diffs")
M.repo:load_diffs(filter)
M.repo:load_diffs(filter)
end)
end
logger.debug(string.format("[STATUS BUFFER]: Running %d refresh(es)", #refreshes))
a.util.join(refreshes)
logger.debug "[STATUS BUFFER]: Refreshes completed"
logger.debug("[STATUS BUFFER]: Refreshes completed")
a.util.scheduler()
refresh_status()
vim.cmd [[do <nomodeline> User NeogitStatusRefreshed]]
vim.cmd([[do <nomodeline> User NeogitStatusRefreshed]])
end
a.util.scheduler()
if vim.fn.bufname() == 'NeogitStatus' then
if vim.fn.bufname() == "NeogitStatus" then
restore_cursor_location(s, f, h)
end
logger.debug "[STATUS BUFFER]: Finished refresh"
logger.debug "[STATUS BUFFER]: Refresh lock is now free"
logger.debug("[STATUS BUFFER]: Finished refresh")
logger.debug("[STATUS BUFFER]: Refresh lock is now free")
permit:forget()
end
local dispatch_refresh = a.void(refresh)
local refresh_manually = a.void(function (fname)
if not fname or fname == "" then return end
local refresh_manually = a.void(function(fname)
if not fname or fname == "" then
return
end
local path = fs.relpath_from_repository(fname)
if not path then return end
refresh({ status = true, diffs = { "*:" .. path } })
if not path then
return
end
refresh { status = true, diffs = { "*:" .. path } }
end)
--- Compatibility endpoint to refresh data from an autocommand.
@ -401,13 +415,15 @@ end)
-- resolving the file name to the path relative to the repository root and
-- refresh that file's cache data.
local function refresh_viml_compat(fname)
if not config.values.auto_refresh then return end
if not config.values.auto_refresh then
return
end
refresh_manually(fname)
end
local function current_line_is_hunk()
local _,_,h = save_cursor_location()
local _, _, h = save_cursor_location()
return h ~= nil
end
@ -444,19 +460,21 @@ local function toggle()
if on_hunk then
local hunk = get_current_hunk_of_item(item)
hunk.folded = not hunk.folded
elseif item then
elseif item then
item.folded = not item.folded
else
section.folded = not section.folded
else
section.folded = not section.folded
end
refresh_status()
end
local reset = function ()
local reset = function()
M.repo = repository.create()
M.locations = {}
if not config.values.auto_refresh then return end
if not config.values.auto_refresh then
return
end
refresh(true)
end
local dispatch_reset = a.void(reset)
@ -469,7 +487,7 @@ local function close(skip_close)
M.status_buffer = nil
vim.o.autochdir = M.prev_autochdir
if M.cwd_changed then
vim.cmd "cd -"
vim.cmd("cd -")
end
end
@ -498,19 +516,18 @@ local function generate_patch_from_selection(item, hunk, from, to, reverse)
len_offset = len_offset + (operand == "+" and 1 or -1)
table.insert(diff_content, v)
else
-- If we want to apply the patch normally, we need to include every `-` line we skip as a normal line,
-- since we want to keep that line.
if not reverse then
if operand == "-" then
table.insert(diff_content, " "..line)
table.insert(diff_content, " " .. line)
end
-- If we want to apply the patch in reverse, we need to include every `+` line we skip as a normal line, since
-- it's unchanged as far as the diff is concerned and should not be reversed.
-- We also need to adapt the original line offset based on if we skip or not
elseif reverse then
if operand == "+" then
table.insert(diff_content, " "..line)
table.insert(diff_content, " " .. line)
end
len_start = len_start + (operand == "-" and -1 or 1)
end
@ -520,13 +537,8 @@ local function generate_patch_from_selection(item, hunk, from, to, reverse)
end
end
local diff_header = string.format(
"@@ -%d,%d +%d,%d @@",
hunk.index_from,
len_start,
hunk.index_from,
len_start + len_offset
)
local diff_header =
string.format("@@ -%d,%d +%d,%d @@", hunk.index_from, len_start, hunk.index_from, len_start + len_offset)
table.insert(diff_content, 1, diff_header)
table.insert(diff_content, 1, string.format("+++ b/%s", item.name))
@ -535,7 +547,6 @@ local function generate_patch_from_selection(item, hunk, from, to, reverse)
return table.concat(diff_content, "\n")
end
--- Validates the current selection and acts accordingly
--@return nil
--@return number, number
@ -546,11 +557,7 @@ local function get_selection()
local first_section, first_item = get_section_item_for_line(first_line)
local last_section, last_item = get_section_item_for_line(last_line)
if not first_section or
not first_item or
not last_section or
not last_item
then
if not first_section or not first_item or not last_section or not last_item then
return nil
end
@ -561,9 +568,10 @@ local function get_selection()
return nil
end
if first_section.name ~= last_section.name or
first_item.name ~= last_item.name or
first_hunk.first ~= last_hunk.first
if
first_section.name ~= last_section.name
or first_item.name ~= last_item.name
or first_hunk.first ~= last_hunk.first
then
return nil
end
@ -572,13 +580,15 @@ local function get_selection()
last_line = last_line - last_item.first
-- both hunks are the same anyway so only have to check one
if first_hunk.diff_from == first_line or
first_hunk.diff_from == last_line
then
if first_hunk.diff_from == first_line or first_hunk.diff_from == last_line then
return nil
end
return first_section, first_item, first_hunk, first_line - first_hunk.diff_from, last_line - first_hunk.diff_from
return first_section,
first_item,
first_hunk,
first_line - first_hunk.diff_from,
last_line - first_hunk.diff_from
end
local stage_selection = function()
@ -602,9 +612,11 @@ local stage = function()
local section, item = get_current_section_item()
local mode = vim.api.nvim_get_mode()
if section == nil
if
section == nil
or (section.name ~= "unstaged" and section.name ~= "untracked" and section.name ~= "unmerged")
or (mode.mode == "V" and item == nil) then
or (mode.mode == "V" and item == nil)
then
return
end
@ -616,9 +628,9 @@ local stage = function()
if section.name == "unstaged" then
git.status.stage_modified()
elseif section.name == "untracked" then
local add = git.cli.add;
for i,_ in ipairs(section.files) do
local item = section.files[i];
local add = git.cli.add
for i, _ in ipairs(section.files) do
local item = section.files[i]
add.files(item.name)
end
add.call()
@ -628,16 +640,16 @@ local stage = function()
return
else
if on_hunk and section.name ~= "untracked" then
local hunk = get_current_hunk_of_item(item)
local patch = generate_patch_from_selection(item, hunk)
cli.apply.cached.with_patch(patch).call()
else
git.status.stage(item.name)
end
local hunk = get_current_hunk_of_item(item)
local patch = generate_patch_from_selection(item, hunk)
cli.apply.cached.with_patch(patch).call()
else
git.status.stage(item.name)
end
end
end
refresh({status = true, diffs = {"*:"..item.name}})
refresh { status = true, diffs = { "*:" .. item.name } }
M.current_operation = nil
end
@ -671,7 +683,7 @@ local unstage = function()
end
end
refresh({status = true, diffs = {"*:"..item.name}})
refresh { status = true, diffs = { "*:" .. item.name } }
M.current_operation = nil
end
@ -683,10 +695,12 @@ local discard = function()
end
M.current_operation = "discard"
if not input.get_confirmation("Discard '"..item.name.."' ?", {
values = { "&Yes", "&No" },
default = 2
}) then
if
not input.get_confirmation("Discard '" .. item.name .. "' ?", {
values = { "&Yes", "&No" },
default = 2,
})
then
return
end
@ -703,16 +717,16 @@ local discard = function()
elseif section.name == "untracked" then
local repo_root = cli.git_root()
a.util.scheduler()
vim.fn.delete(repo_root .. '/' .. item.name)
vim.fn.delete(repo_root .. "/" .. item.name)
else
local on_hunk = current_line_is_hunk()
if on_hunk then
local hunk, lines = get_current_hunk_of_item(item)
lines[1] = string.format('@@ -%d,%d +%d,%d @@', hunk.index_from, hunk.index_len, hunk.index_from, hunk.disk_len)
lines[1] =
string.format("@@ -%d,%d +%d,%d @@", hunk.index_from, hunk.index_len, hunk.index_from, hunk.disk_len)
local diff = table.concat(lines, "\n")
diff = table.concat({'--- a/'..item.name, '+++ b/'..item.name, diff, ""}, "\n")
diff = table.concat({ "--- a/" .. item.name, "+++ b/" .. item.name, diff, "" }, "\n")
if section.name == "staged" then
cli.apply.reverse.index.with_patch(diff).call()
else
@ -724,23 +738,22 @@ local discard = function()
cli.reset.files(item.name).call()
cli.checkout.files(item.name).call()
end
end
refresh(true)
M.current_operation = nil
a.util.scheduler()
vim.cmd "checktime"
vim.cmd("checktime")
end
local set_folds = function(to)
Collection.new(M.locations):each(function (l)
Collection.new(M.locations):each(function(l)
l.folded = to[1]
Collection.new(l.files):each(function (f)
Collection.new(l.files):each(function(f)
f.folded = to[2]
if f.hunks then
Collection.new(f.hunks):each(function (h)
Collection.new(f.hunks):each(function(h)
h.folded = to[3]
end)
end
@ -749,41 +762,40 @@ local set_folds = function(to)
refresh(true)
end
--- These needs to be a function to avoid a circular dependency
-- between this module and the popup modules
local cmd_func_map = function ()
local cmd_func_map = function()
return {
["Close"] = function()
M.status_buffer:close()
end,
["Depth1"] = a.void(function()
set_folds({ true, true, false })
set_folds { true, true, false }
end),
["Depth2"] = a.void(function()
set_folds({ false, true, false })
set_folds { false, true, false }
end),
["Depth3"] = a.void(function()
set_folds({ false, false, true })
set_folds { false, false, true }
end),
["Depth4"] = a.void(function()
set_folds({ false, false, false })
set_folds { false, false, false }
end),
["Toggle"] = toggle,
["Discard"] = { "nv", a.void(discard), true },
["Stage"] = { "nv", a.void(stage), true },
["StageUnstaged"] = a.void(function ()
git.status.stage_modified()
refresh({status = true, diffs = true})
["StageUnstaged"] = a.void(function()
git.status.stage_modified()
refresh { status = true, diffs = true }
end),
["StageAll"] = a.void(function()
git.status.stage_all()
refresh({status = true, diffs = true})
git.status.stage_all()
refresh { status = true, diffs = true }
end),
["Unstage"] = { "nv", a.void(unstage), true },
["UnstageStaged"] = a.void(function ()
git.status.unstage_all()
refresh({status = true, diffs = true})
["UnstageStaged"] = a.void(function()
git.status.unstage_all()
refresh { status = true, diffs = true }
end),
["CommandHistory"] = function()
GitCommandHistory:new():show()
@ -813,7 +825,7 @@ local cmd_func_map = function ()
notif.delete_all()
M.status_buffer:close()
local relpath = vim.fn.fnamemodify(repo_root .. '/' .. path, ':.')
local relpath = vim.fn.fnamemodify(repo_root .. "/" .. path, ":.")
if not vim.o.hidden and vim.bo.buftype == "" and not vim.bo.readonly and vim.fn.bufname() ~= "" then
vim.cmd("update")
@ -824,7 +836,6 @@ local cmd_func_map = function ()
if hunk then
vim.cmd(tostring(hunk.disk_from))
end
elseif vim.tbl_contains({ "unmerged", "unpulled", "recent", "stashes" }, section.name) then
if M.commit_view and M.commit_view.is_open then
M.commit_view:close()
@ -836,24 +847,26 @@ local cmd_func_map = function ()
end
end
end),
["RefreshBuffer"] = function() dispatch_refresh(true) end,
["HelpPopup"] = function ()
["RefreshBuffer"] = function()
dispatch_refresh(true)
end,
["HelpPopup"] = function()
local line = M.status_buffer:get_current_line()
require("neogit.popups.help").create {
require("neogit.popups.help").create {
get_stash = function()
return {
name = line[1]:match('^(stash@{%d+})')
name = line[1]:match("^(stash@{%d+})"),
}
end,
use_magit_keybindings = config.values.use_magit_keybindings
use_magit_keybindings = config.values.use_magit_keybindings,
}
end,
["DiffAtFile"] = function()
if not config.ensure_integration 'diffview' then
if not config.ensure_integration("diffview") then
return
end
local dv = require 'neogit.integrations.diffview'
local dv = require("neogit.integrations.diffview")
local section, item = get_current_section_item()
if section and item then
@ -866,11 +879,11 @@ local cmd_func_map = function ()
["PushPopup"] = require("neogit.popups.push").create,
["CommitPopup"] = require("neogit.popups.commit").create,
["LogPopup"] = require("neogit.popups.log").create,
["StashPopup"] = function ()
["StashPopup"] = function()
local line = M.status_buffer:get_current_line()
require("neogit.popups.stash").create {
name = line[1]:match('^(stash@{%d+})')
require("neogit.popups.stash").create {
name = line[1]:match("^(stash@{%d+})"),
}
end,
["BranchPopup"] = require("neogit.popups.branch").create,
@ -881,19 +894,19 @@ local function create(kind, cwd)
kind = kind or config.values.kind
if M.status_buffer then
logger.debug "Status buffer already exists. Focusing the existing one"
logger.debug("Status buffer already exists. Focusing the existing one")
M.status_buffer:focus()
return
end
logger.debug "[STATUS BUFFER]: Creating..."
logger.debug("[STATUS BUFFER]: Creating...")
Buffer.create {
name = "NeogitStatus",
filetype = "NeogitStatus",
kind = kind,
initialize = function(buffer)
logger.debug "[STATUS BUFFER]: Initializing..."
logger.debug("[STATUS BUFFER]: Initializing...")
M.status_buffer = buffer
@ -917,45 +930,47 @@ local function create(kind, cwd)
elseif type(val) == "function" then
mappings[key] = val
elseif type(val) == "string" then
mappings[key] = function()
vim.cmd(val)
mappings[key] = function()
vim.cmd(val)
end
end
end
end
logger.debug "[STATUS BUFFER]: Dispatching initial render"
logger.debug("[STATUS BUFFER]: Dispatching initial render")
dispatch_refresh(true)
end
end,
}
end
local highlight_group = vim.api.nvim_create_namespace("section-highlight")
local function update_highlight()
if not M.status_buffer then
if not M.status_buffer then
return
end
if config.values.disable_context_highlighting then
return
end
if config.values.disable_context_highlighting then return end
vim.api.nvim_buf_clear_namespace(0, highlight_group, 0, -1)
M.status_buffer:clear_sign_group('ctx')
M.status_buffer:clear_sign_group("ctx")
local _,_,_, first, last = save_cursor_location()
local _, _, _, first, last = save_cursor_location()
if first == nil or last == nil then
return
end
for i=first,last do
for i = first, last do
local line = vim.fn.getline(i)
if hunk_header_matcher:match_str(line) then
M.status_buffer:place_sign(i, 'NeogitHunkHeaderHighlight', 'ctx')
M.status_buffer:place_sign(i, "NeogitHunkHeaderHighlight", "ctx")
elseif diff_add_matcher:match_str(line) then
M.status_buffer:place_sign(i, 'NeogitDiffAddHighlight', 'ctx')
M.status_buffer:place_sign(i, "NeogitDiffAddHighlight", "ctx")
elseif diff_delete_matcher:match_str(line) then
M.status_buffer:place_sign(i, 'NeogitDiffDeleteHighlight', 'ctx')
M.status_buffer:place_sign(i, "NeogitDiffDeleteHighlight", "ctx")
else
M.status_buffer:place_sign(i, 'NeogitDiffContextHighlight', 'ctx')
M.status_buffer:place_sign(i, "NeogitDiffContextHighlight", "ctx")
end
end
end
@ -985,8 +1000,8 @@ function M.get_status()
end
function M.wait_on_current_operation(ms)
vim.wait(ms or 1000, function()
return not M.current_operation
vim.wait(ms or 1000, function()
return not M.current_operation
end)
end

View file

@ -1,37 +1,45 @@
require 'plenary.async'.tests.add_to_env()
require("plenary.async").tests.add_to_env()
local eq = assert.are.same
local operations = require'neogit.operations'
local harness = require'tests.git_harness'
local operations = require("neogit.operations")
local harness = require("tests.git_harness")
local in_prepared_repo = harness.in_prepared_repo
local get_current_branch = harness.get_current_branch
--local status = require'neogit.status'
local input = require'tests.mocks.input'
local input = require("tests.mocks.input")
local function act(normal_cmd)
vim.cmd('normal '..normal_cmd)
vim.cmd("normal " .. normal_cmd)
end
describe('branch popup', function ()
it('can switch to another branch in the repository', in_prepared_repo(function ()
input.value = 'second-branch'
act('bb')
operations.wait('checkout_branch')
eq('second-branch', get_current_branch())
end))
describe("branch popup", function()
it(
"can switch to another branch in the repository",
in_prepared_repo(function()
input.value = "second-branch"
act("bb")
operations.wait("checkout_branch")
eq("second-branch", get_current_branch())
end)
)
it('can switch to another local branch in the repository', in_prepared_repo(function ()
input.value = 'second-branch'
act('bl')
operations.wait('checkout_local-branch')
eq('second-branch', get_current_branch())
end))
it(
"can switch to another local branch in the repository",
in_prepared_repo(function()
input.value = "second-branch"
act("bl")
operations.wait("checkout_local-branch")
eq("second-branch", get_current_branch())
end)
)
it('can create a new branch', in_prepared_repo(function ()
input.value = 'branch-from-test'
act('bc')
operations.wait('checkout_create-branch')
eq('branch-from-test', get_current_branch())
end))
it(
"can create a new branch",
in_prepared_repo(function()
input.value = "branch-from-test"
act("bc")
operations.wait("checkout_create-branch")
eq("branch-from-test", get_current_branch())
end)
)
end)

View file

@ -1,37 +1,37 @@
local status = require'neogit.status'
local a = require 'plenary.async'
local status = require("neogit.status")
local a = require("plenary.async")
local M = {}
local project_dir = vim.api.nvim_exec('pwd', true)
local project_dir = vim.api.nvim_exec("pwd", true)
-- very naiive implementation, we only use this to generate unique folder names
local function random_string(length)
math.randomseed(os.clock()^5)
math.randomseed(os.clock() ^ 5)
local res = ""
for _ = 1, length do
local res = ""
for _ = 1, length do
local r = math.random(97, 122)
res = res .. string.char(r)
end
return res
res = res .. string.char(r)
end
return res
end
local function prepare_repository(dir)
vim.cmd('silent !cp -r tests/.repo/ /tmp/'..dir)
vim.cmd('cd /tmp/'..dir)
vim.cmd('silent !cp -r .git.orig/ .git/')
vim.cmd("silent !cp -r tests/.repo/ /tmp/" .. dir)
vim.cmd("cd /tmp/" .. dir)
vim.cmd("silent !cp -r .git.orig/ .git/")
end
local function cleanup_repository(dir)
vim.cmd('cd '..project_dir)
vim.cmd('silent !rm -rf /tmp/'..dir)
vim.cmd("cd " .. project_dir)
vim.cmd("silent !rm -rf /tmp/" .. dir)
end
function M.in_prepared_repo(cb)
return function ()
local dir = 'neogit_test_'..random_string(5)
return function()
local dir = "neogit_test_" .. random_string(5)
prepare_repository(dir)
vim.cmd('Neogit')
vim.cmd("Neogit")
a.util.block_on(status.reset())
local _, err = pcall(cb)
cleanup_repository(dir)
@ -42,41 +42,45 @@ function M.in_prepared_repo(cb)
end
function M.get_git_status(files)
local result = vim.api.nvim_exec('!git status -s --porcelain=1 -- ' .. (files or ''), true)
local lines = vim.split(result, '\n')
local result = vim.api.nvim_exec("!git status -s --porcelain=1 -- " .. (files or ""), true)
local lines = vim.split(result, "\n")
local output = {}
for i=3,#lines do
for i = 3, #lines do
table.insert(output, lines[i])
end
return table.concat(output, '\n')
return table.concat(output, "\n")
end
function M.get_git_diff(files, flags)
local result = vim.api.nvim_exec('!git diff '..(flags or '')..' -- ' ..(files or ''), true)
local lines = vim.split(result, '\n')
local result = vim.api.nvim_exec("!git diff " .. (flags or "") .. " -- " .. (files or ""), true)
local lines = vim.split(result, "\n")
local output = {}
for i=5,#lines do
for i = 5, #lines do
table.insert(output, lines[i])
end
return table.concat(output, '\n')
return table.concat(output, "\n")
end
function M.get_git_branches()
local result = vim.api.nvim_exec('!git branch --list --all', true)
local lines = vim.split(result, '\n')
local result = vim.api.nvim_exec("!git branch --list --all", true)
local lines = vim.split(result, "\n")
local output = {}
local current_branch = nil
for _, l in ipairs(lines) do
local branch_state, name = l:match('^([* ]) (.+)')
if branch_state == '*' then current_branch = name end
if name then table.insert(output, name) end
local branch_state, name = l:match("^([* ]) (.+)")
if branch_state == "*" then
current_branch = name
end
if name then
table.insert(output, name)
end
end
return output, current_branch
end
function M.get_current_branch()
local result = vim.api.nvim_exec('!git branch --show-current', true)
local lines = vim.split(result, '\n')
local result = vim.api.nvim_exec("!git branch --show-current", true)
local lines = vim.split(result, "\n")
return lines[#lines - 1]
end

View file

@ -1,52 +1,60 @@
local eq = assert.are.same
local generate_patch_from_selection = require'neogit.status'.generate_patch_from_selection
local generate_patch_from_selection = require("neogit.status").generate_patch_from_selection
-- Helper-function to keep the testsuite clean, since the interface to the
-- function under test is quite bloated
local function run_with_hunk(hunk, from, to, reverse)
local lines = vim.split(hunk, '\n')
local header_matches = vim.fn.matchlist(lines[1], "@@ -\\(\\d\\+\\),\\(\\d\\+\\) +\\(\\d\\+\\),\\(\\d\\+\\) @@")
return generate_patch_from_selection(
{
name = 'test.txt',
diff = { lines = lines }
},
{
first = 1,
last = #lines,
index_from = header_matches[2],
index_len = header_matches[3],
diff_from = 1,
diff_to = #lines
},
from, to, reverse)
local lines = vim.split(hunk, "\n")
local header_matches =
vim.fn.matchlist(lines[1], "@@ -\\(\\d\\+\\),\\(\\d\\+\\) +\\(\\d\\+\\),\\(\\d\\+\\) @@")
return generate_patch_from_selection({
name = "test.txt",
diff = { lines = lines },
}, {
first = 1,
last = #lines,
index_from = header_matches[2],
index_len = header_matches[3],
diff_from = 1,
diff_to = #lines,
}, from, to, reverse)
end
describe('patch creation', function ()
it('creates a patch-formatted string from a hunk', function ()
describe("patch creation", function()
it("creates a patch-formatted string from a hunk", function()
local patch = run_with_hunk(
[['@@ -1,1 +1,1 @@
[['@@ -1,1 +1,1 @@
-some line
+another line]], 1, 2)
+another line]],
1,
2
)
eq([[--- a/test.txt
eq(
[[--- a/test.txt
+++ b/test.txt
@@ -1,1 +1,1 @@
-some line
+another line
]], patch)
]],
patch
)
end)
it('can take only part of a hunk', function ()
it("can take only part of a hunk", function()
local patch = run_with_hunk(
[[@@ -1,3 +1,3 @@
[[@@ -1,3 +1,3 @@
line1
-line2
+line two
line3]], 2, 3)
line3]],
2,
3
)
eq([[--- a/test.txt
eq(
[[--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,3 @@
line1
@ -54,76 +62,103 @@ line3]], 2, 3)
+line two
line3
]], patch)
]],
patch
)
end)
it('removes added lines outside of the selection', function ()
it("removes added lines outside of the selection", function()
local patch = run_with_hunk(
[[@@ -1,1 +1,4 @@
[[@@ -1,1 +1,4 @@
line1
+line2
+line3
+line4]], 3, 3)
+line4]],
3,
3
)
eq([[--- a/test.txt
eq(
[[--- a/test.txt
+++ b/test.txt
@@ -1,1 +1,2 @@
line1
+line3
]], patch)
]],
patch
)
end)
it('keeps removed lines outside of the selection as normal lines', function ()
it("keeps removed lines outside of the selection as normal lines", function()
local patch = run_with_hunk(
[[@@ -1,2 +1,2 @@
[[@@ -1,2 +1,2 @@
line1
-line2
+line two]], 3, 3)
+line two]],
3,
3
)
eq([[--- a/test.txt
eq(
[[--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,3 @@
line1
line2
+line two
]], patch)
]],
patch
)
end)
describe('in reverse', function ()
it('removes removed lines outside of the selection', function ()
describe("in reverse", function()
it("removes removed lines outside of the selection", function()
local patch = run_with_hunk(
[[@@ -1,2 +1,2 @@
[[@@ -1,2 +1,2 @@
line1
-line2
+line two]], 3, 3, true)
+line two]],
3,
3,
true
)
eq([[--- a/test.txt
eq(
[[--- a/test.txt
+++ b/test.txt
@@ -1,1 +1,2 @@
line1
+line two
]], patch)
]],
patch
)
end)
it('keeps added lines outside of the selection as normal lines', function ()
it("keeps added lines outside of the selection as normal lines", function()
local patch = run_with_hunk(
[[@@ -1,2 +1,2 @@
[[@@ -1,2 +1,2 @@
line1
-line2
+line two]], 2, 2, true)
+line two]],
2,
2,
true
)
eq([[--- a/test.txt
eq(
[[--- a/test.txt
+++ b/test.txt
@@ -1,3 +1,2 @@
line1
-line2
line two
]], patch)
]],
patch
)
end)
end)
end)

View file

@ -1,21 +1,19 @@
local input = require'neogit.lib.input'
local input = require("neogit.lib.input")
local M = {
value = '',
confirmed = true
value = "",
confirmed = true,
}
input.get_user_input = function (_)
input.get_user_input = function(_)
return M.value
end
input.get_user_input_with_completion = function (_, _)
input.get_user_input_with_completion = function(_, _)
return M.value
end
input.get_confirmation = function (_, _)
input.get_confirmation = function(_, _)
return M.confirmed
end
return M

View file

@ -1,21 +1,21 @@
local eq = assert.are.same
describe('proof of concept', function ()
it('should work', function ()
describe("proof of concept", function()
it("should work", function()
assert(true)
end)
it('should have access to vim global', function ()
it("should have access to vim global", function()
assert.is_not_nil(vim)
end)
it('should be able to interact with vim', function ()
it("should be able to interact with vim", function()
vim.cmd("let g:val = v:true")
eq(true, vim.g.val)
end)
it('has access to buffers', function ()
vim.cmd('Neogit')
it("has access to buffers", function()
vim.cmd("Neogit")
-- 1 is most likely the initial buffer nvim openes when starting?
-- 2 is the neogit buffer just opened
eq({ 1, 2 }, vim.api.nvim_list_bufs())

View file

@ -1,38 +1,47 @@
local eq = assert.are.same
local status = require'neogit.status'
local harness = require'tests.git_harness'
local _ = require 'tests.mocks.input'
local status = require("neogit.status")
local harness = require("tests.git_harness")
local _ = require("tests.mocks.input")
local in_prepared_repo = harness.in_prepared_repo
local get_git_status = harness.get_git_status
local get_git_diff = harness.get_git_diff
local function act(normal_cmd)
vim.fn.feedkeys(vim.api.nvim_replace_termcodes(normal_cmd, true, true, true))
vim.fn.feedkeys('', 'x') -- flush typeahead
vim.fn.feedkeys("", "x") -- flush typeahead
status.wait_on_current_operation()
end
describe('status buffer', function ()
describe('staging files - s', function ()
it('can stage an untracked file under the cursor', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 5, 1, 0})
act('s')
local result = get_git_status('untracked.txt')
eq('A untracked.txt\n', result)
end))
describe("status buffer", function()
describe("staging files - s", function()
it(
"can stage an untracked file under the cursor",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 5, 1, 0 })
act("s")
local result = get_git_status("untracked.txt")
eq("A untracked.txt\n", result)
end)
)
it('can stage a tracked file under the cursor', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 8, 1, 0})
act('s')
local result = get_git_status('a.txt')
eq('M a.txt\n', result)
end))
it(
"can stage a tracked file under the cursor",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 8, 1, 0 })
act("s")
local result = get_git_status("a.txt")
eq("M a.txt\n", result)
end)
)
it('can stage a hunk under the cursor of a tracked file', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 8, 1, 0})
act('<tab>jjs')
eq('MM a.txt\n', get_git_status('a.txt'))
eq([[--- a/a.txt
it(
"can stage a hunk under the cursor of a tracked file",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 8, 1, 0 })
act("<tab>jjs")
eq("MM a.txt\n", get_git_status("a.txt"))
eq(
[[--- a/a.txt
+++ b/a.txt
@@ -1,5 +1,5 @@
This is a text file under version control.
@ -41,14 +50,20 @@ describe('status buffer', function ()
Here are some lines we can change during the tests.
]], get_git_diff('a.txt', '--cached'))
end))
]],
get_git_diff("a.txt", "--cached")
)
end)
)
it('can stage a subsequent hunk under the cursor of a tracked file', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 8, 1, 0})
act('<tab>8js')
eq('MM a.txt\n', get_git_status('a.txt'))
eq([[--- a/a.txt
it(
"can stage a subsequent hunk under the cursor of a tracked file",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 8, 1, 0 })
act("<tab>8js")
eq("MM a.txt\n", get_git_status("a.txt"))
eq(
[[--- a/a.txt
+++ b/a.txt
@@ -7,4 +7,5 @@ Here are some lines we can change during the tests.
@ -56,14 +71,20 @@ describe('status buffer', function ()
It also has some line we can manipulate.
+Adding a new line right here!
Here is some more.
]], get_git_diff('a.txt', '--cached'))
end))
]],
get_git_diff("a.txt", "--cached")
)
end)
)
it('can stage from a selection in a hunk', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 8, 1, 0})
act('<tab>jjjjVs')
eq('MM a.txt\n', get_git_status('a.txt'))
eq([[--- a/a.txt
it(
"can stage from a selection in a hunk",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 8, 1, 0 })
act("<tab>jjjjVs")
eq("MM a.txt\n", get_git_status("a.txt"))
eq(
[[--- a/a.txt
+++ b/a.txt
@@ -1,5 +1,6 @@
This is a text file under version control.
@ -72,37 +93,52 @@ describe('status buffer', function ()
Here are some lines we can change during the tests.
]], get_git_diff('a.txt', '--cached'))
end))
]],
get_git_diff("a.txt", "--cached")
)
end)
)
end)
describe('unstaging files - u', function ()
it('can unstage a staged file under the cursor', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 11, 1, 0})
act('u')
local result = get_git_status('b.txt')
eq(' M b.txt\n', result)
end))
describe("unstaging files - u", function()
it(
"can unstage a staged file under the cursor",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 11, 1, 0 })
act("u")
local result = get_git_status("b.txt")
eq(" M b.txt\n", result)
end)
)
it('can unstage a hunk under the cursor of a staged file', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 11, 1, 0})
act('<tab>jju')
eq('MM b.txt\n', get_git_status('b.txt'))
eq([[--- a/b.txt
it(
"can unstage a hunk under the cursor of a staged file",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 11, 1, 0 })
act("<tab>jju")
eq("MM b.txt\n", get_git_status("b.txt"))
eq(
[[--- a/b.txt
+++ b/b.txt
@@ -7,3 +7,4 @@ This way, unstaging staged changes can be tested.
Some more lines down here to force a second hunk.
I can't think of anything else.
Duh.
+And here as well
]], get_git_diff('b.txt', '--cached'))
end))
]],
get_git_diff("b.txt", "--cached")
)
end)
)
it('can unstage from a selection in a hunk', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 11, 1, 0})
act('<tab>jjjjVu')
eq('MM b.txt\n', get_git_status('b.txt'))
eq([[--- a/b.txt
it(
"can unstage from a selection in a hunk",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 11, 1, 0 })
act("<tab>jjjjVu")
eq("MM b.txt\n", get_git_status("b.txt"))
eq(
[[--- a/b.txt
+++ b/b.txt
@@ -1,4 +1,5 @@
This is another test file.
@ -110,37 +146,52 @@ describe('status buffer', function ()
This way, unstaging staged changes can be tested.
]], get_git_diff('b.txt'))
end))
]],
get_git_diff("b.txt")
)
end)
)
it('can unstage a subsequent hunk from a staged file', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 11, 1, 0})
act('<tab>8ju')
eq('MM b.txt\n', get_git_status('b.txt'))
eq([[--- a/b.txt
it(
"can unstage a subsequent hunk from a staged file",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 11, 1, 0 })
act("<tab>8ju")
eq("MM b.txt\n", get_git_status("b.txt"))
eq(
[[--- a/b.txt
+++ b/b.txt
@@ -7,3 +7,4 @@ This way, unstaging staged changes can be tested.
Some more lines down here to force a second hunk.
I can't think of anything else.
Duh.
+And here as well
]], get_git_diff('b.txt'))
end))
]],
get_git_diff("b.txt")
)
end)
)
end)
describe('discarding files - x', function ()
it('can discard the changes of a file under the cursor', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 8, 1, 0})
act('x')
local result = get_git_status('a.txt')
eq('', result)
end))
describe("discarding files - x", function()
it(
"can discard the changes of a file under the cursor",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 8, 1, 0 })
act("x")
local result = get_git_status("a.txt")
eq("", result)
end)
)
it('can discard a hunk under the cursor', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 8, 1, 0})
act('<tab>jjx')
eq(' M a.txt\n', get_git_status('a.txt'))
eq([[--- a/a.txt
it(
"can discard a hunk under the cursor",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 8, 1, 0 })
act("<tab>jjx")
eq(" M a.txt\n", get_git_status("a.txt"))
eq(
[[--- a/a.txt
+++ b/a.txt
@@ -7,4 +7,5 @@ Here are some lines we can change during the tests.
@ -148,14 +199,20 @@ describe('status buffer', function ()
It also has some line we can manipulate.
+Adding a new line right here!
Here is some more.
]], get_git_diff('a.txt'))
end))
]],
get_git_diff("a.txt")
)
end)
)
it('can discard a selection of a hunk', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 8, 1, 0})
act('<tab>jjjjVx')
eq(' M a.txt\n', get_git_status('a.txt'))
eq([[--- a/a.txt
it(
"can discard a selection of a hunk",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 8, 1, 0 })
act("<tab>jjjjVx")
eq(" M a.txt\n", get_git_status("a.txt"))
eq(
[[--- a/a.txt
+++ b/a.txt
@@ -1,5 +1,4 @@
This is a text file under version control.
@ -169,42 +226,60 @@ describe('status buffer', function ()
It also has some line we can manipulate.
+Adding a new line right here!
Here is some more.
]], get_git_diff('a.txt'))
end))
]],
get_git_diff("a.txt")
)
end)
)
it('can delete an untracked file', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 5, 1, 0})
act('x')
local result = get_git_status('untracked.txt')
eq('', result)
end))
it(
"can delete an untracked file",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 5, 1, 0 })
act("x")
local result = get_git_status("untracked.txt")
eq("", result)
end)
)
it('can discard the changes of a staged file under the cursor', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 11, 1, 0})
act('x')
local result = get_git_status('b.txt')
eq('', result)
end))
it(
"can discard the changes of a staged file under the cursor",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 11, 1, 0 })
act("x")
local result = get_git_status("b.txt")
eq("", result)
end)
)
it('can discard a hunk of the staged file under the cursor', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 11, 1, 0})
act('<tab>jjx')
eq('M b.txt\n', get_git_status('b.txt'))
eq([[--- a/b.txt
it(
"can discard a hunk of the staged file under the cursor",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 11, 1, 0 })
act("<tab>jjx")
eq("M b.txt\n", get_git_status("b.txt"))
eq(
[[--- a/b.txt
+++ b/b.txt
@@ -7,3 +7,4 @@ This way, unstaging staged changes can be tested.
Some more lines down here to force a second hunk.
I can't think of anything else.
Duh.
+And here as well
]], get_git_diff('b.txt', '--cached'))
end))
]],
get_git_diff("b.txt", "--cached")
)
end)
)
it('can discard a selection of a staged file', in_prepared_repo(function ()
vim.fn.setpos('.', {0, 11, 1, 0})
act('<tab>jjjjVx')
eq('M b.txt\n', get_git_status('b.txt'))
eq([[--- a/b.txt
it(
"can discard a selection of a staged file",
in_prepared_repo(function()
vim.fn.setpos(".", { 0, 11, 1, 0 })
act("<tab>jjjjVx")
eq("M b.txt\n", get_git_status("b.txt"))
eq(
[[--- a/b.txt
+++ b/b.txt
@@ -1,5 +1,4 @@
This is another test file.
@ -217,7 +292,10 @@ describe('status buffer', function ()
I can't think of anything else.
Duh.
+And here as well
]], get_git_diff('b.txt', '--cached'))
end))
]],
get_git_diff("b.txt", "--cached")
)
end)
)
end)
end)