Skip to content

Commit 87dec80

Browse files
committed
feat: support for statuscolumn
1 parent 4a143f1 commit 87dec80

File tree

6 files changed

+120
-23
lines changed

6 files changed

+120
-23
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Super fast git decorations implemented purely in Lua.
3232
- Live intra-line word diff
3333
- Ability to display deleted/changed lines via virtual lines.
3434
- Support for detached working trees.
35+
- Support for `'statuscolumn'`.
3536

3637
## Requirements
3738

doc/gitsigns.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,19 @@ setup({cfg}) *gitsigns.setup()*
100100
{cfg} (table|nil): Configuration for Gitsigns.
101101
See |gitsigns-usage| for more details.
102102

103+
statuscolumn() *gitsigns.statuscolumn()*
104+
Function that can be used in the 'statuscolumn' option.
105+
106+
Note calling this function will automatically disable
107+
|gitsigns-config-signcolumn|.
108+
109+
e.g. >lua
110+
vim.o.statuscolumn = "%s%l%C%{%v:lua.require'gitsigns'.statuscolumn()%} "
111+
<
112+
113+
Returns: ~
114+
(string)
115+
103116
attach({bufnr}, {ctx}, {callback?}) *gitsigns.attach()*
104117
Attach Gitsigns to the buffer.
105118

gen_help.lua

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,19 @@ local function parse_param(x)
179179
return name, ty, des
180180
end
181181

182+
--- @param x string
183+
--- @return string? type
184+
--- @return string? name
185+
--- @return string? description
186+
local function parse_return(x)
187+
local ty, name, des = x:match('([^ ]+) +([^ ]+) *(.*)')
188+
if ty then
189+
return ty, name, des
190+
end
191+
ty = x:match('([^ ]+)')
192+
return ty
193+
end
194+
182195
--- @param x string[]
183196
--- @return string[]
184197
local function trim_lines(x)
@@ -207,11 +220,11 @@ local function render_param_or_return(name, ty, desc, name_pad)
207220
ty = ty:gsub('Gitsigns%.%w+', 'table')
208221

209222
name_pad = name_pad and (name_pad + 3) or 0
210-
local name_str --- @type string
223+
local name_str = '' --- @type string
211224

212225
if name == ':' then
213226
name_str = ''
214-
else
227+
elseif name then
215228
local nf = '%-' .. tostring(name_pad) .. 's'
216229
name_str = nf:format(string.format('{%s} ', name))
217230
end
@@ -266,7 +279,7 @@ local function process_doc_comment(state, doc_comment, desc, params, returns)
266279
end
267280

268281
if emmy_type == 'return' then
269-
local ty, name, rdesc = parse_param(emmy_str)
282+
local ty, name, rdesc = parse_return(emmy_str)
270283
returns[#returns + 1] = { name, ty, { rdesc } }
271284
return 'in_return'
272285
end

lua/gitsigns.lua

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
local async = require('gitsigns.async')
2-
local log = require('gitsigns.debug.log')
3-
4-
local gs_config = require('gitsigns.config')
5-
local config = gs_config.config
62

73
local api = vim.api
84
local uv = vim.uv or vim.loop
@@ -101,6 +97,7 @@ local update_cwd_head = async.create(function()
10197
{},
10298
async.create(function(err)
10399
local __FUNC__ = 'cwd_watcher_cb'
100+
local log = require('gitsigns.debug.log')
104101
if err then
105102
log.dprintf('Git dir update error: %s', err)
106103
return
@@ -125,13 +122,16 @@ local function setup_cli()
125122
})
126123
end
127124

128-
local function setup_debug()
125+
--- @param config Gitsigns.Config
126+
local function setup_debug(config)
127+
local log = require('gitsigns.debug.log')
129128
log.debug_mode = config.debug_mode
130129
log.verbose = config._verbose
131130
end
132131

133132
--- @async
134-
local function setup_attach()
133+
--- @param config Gitsigns.Config
134+
local function setup_attach(config)
135135
if not config.auto_attach then
136136
return
137137
end
@@ -146,6 +146,7 @@ local function setup_attach()
146146
local bufnr = args.buf --[[@as integer]]
147147
if attach_autocmd_disabled then
148148
local __FUNC__ = 'attach_autocmd'
149+
local log = require('gitsigns.debug.log')
149150
log.dprint('Attaching is disabled')
150151
return
151152
end
@@ -199,11 +200,25 @@ local function setup_cwd_head()
199200
})
200201
end
201202

203+
--- Function that can be used in the 'statuscolumn' option.
204+
---
205+
--- Note calling this function will automatically disable
206+
--- |gitsigns-config-signcolumn|.
207+
---
208+
--- e.g. >lua
209+
--- vim.o.statuscolumn = "%s%l%C%{%v:lua.require'gitsigns'.statuscolumn()%} "
210+
--- <
211+
--- @return string
212+
function M.statuscolumn()
213+
return require('gitsigns.manager').statuscolumn()
214+
end
215+
202216
--- Setup and start Gitsigns.
203217
---
204218
--- @param cfg table|nil Configuration for Gitsigns.
205219
--- See |gitsigns-usage| for more details.
206220
function M.setup(cfg)
221+
local gs_config = require('gitsigns.config')
207222
gs_config.build(cfg)
208223

209224
if vim.fn.executable('git') == 0 then
@@ -213,10 +228,12 @@ function M.setup(cfg)
213228

214229
api.nvim_create_augroup('gitsigns', {})
215230

216-
setup_debug()
231+
local config = gs_config.config
232+
233+
setup_debug(config)
217234
setup_cli()
218235
require('gitsigns.highlight').setup()
219-
setup_attach()
236+
setup_attach(config)
220237
setup_cwd_head()
221238
end
222239

@@ -232,7 +249,7 @@ return setmetatable(M, {
232249
return actions[f]
233250
end
234251

235-
if config.debug_mode then
252+
if require('gitsigns.config').config.debug_mode then
236253
local debug = require('gitsigns.debug')
237254
if debug[f] then
238255
return debug[f]

lua/gitsigns/manager.lua

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,52 @@ local signs_staged --- @type Gitsigns.Signs
2626

2727
local M = {}
2828

29+
local statuscolumn_active = false
30+
31+
--- @param bufnr? integer
32+
--- @param top? integer
33+
--- @param bot? integer
34+
local function redraw_statuscol(bufnr, top, bot)
35+
if statuscolumn_active then
36+
api.nvim__redraw({
37+
buf = bufnr,
38+
range = { top, bot },
39+
statuscolumn = true,
40+
})
41+
end
42+
end
43+
44+
function M.statuscolumn()
45+
if not statuscolumn_active then
46+
config.signcolumn = false
47+
statuscolumn_active = true
48+
end
49+
50+
local res = {}
51+
local res_len = 0
52+
local max_pad = 0
53+
local lnum = vim.v.lnum
54+
for _, signs in pairs({ signs_normal, signs_staged }) do
55+
if next(signs.signs) then
56+
max_pad = 2
57+
end
58+
local marks = api.nvim_buf_get_extmarks(0, signs.ns, { lnum - 1, 0 }, { lnum - 1, -1 }, {})
59+
for _, mark in pairs(marks) do
60+
local id = mark[1]
61+
local s = signs.signs[id]
62+
if s then
63+
table.insert(res, '%#' .. s[2] .. '#')
64+
table.insert(res, s[1])
65+
res_len = res_len + vim.str_utfindex(s[1])
66+
table.insert(res, '%#NONE#')
67+
end
68+
end
69+
end
70+
71+
local pad = math.max(0, max_pad - res_len)
72+
return table.concat(res) .. string.rep(' ', pad)
73+
end
74+
2975
--- @param bufnr integer
3076
--- @param signs Gitsigns.Signs
3177
--- @param hunks Gitsigns.Hunk.Hunk[]
@@ -77,6 +123,9 @@ local function apply_win_signs(bufnr, top, bot, clear)
77123
if signs_staged then
78124
apply_win_signs0(bufnr, signs_staged, bcache.hunks_staged, top, bot, clear, false)
79125
end
126+
if clear then
127+
redraw_statuscol(bufnr, top, bot)
128+
end
80129
end
81130

82131
--- @param blame table<integer,Gitsigns.BlameInfo?>?
@@ -349,7 +398,7 @@ function M.show_deleted_in_float(bufnr, nsd, hunk, staged)
349398

350399
-- Navigate to hunk
351400
vim.cmd('normal ' .. tostring(hunk.removed.start) .. 'gg')
352-
vim.cmd('normal ' .. vim.api.nvim_replace_termcodes('z<CR>', true, false, true))
401+
vim.cmd('normal ' .. api.nvim_replace_termcodes('z<CR>', true, false, true))
353402
end)
354403

355404
local last_lnum = api.nvim_buf_line_count(bufnr)
@@ -531,6 +580,7 @@ function M.detach(bufnr, keep_signs)
531580
if signs_staged then
532581
signs_staged:remove(bufnr)
533582
end
583+
redraw_statuscol(bufnr)
534584
end
535585
end
536586

@@ -542,6 +592,7 @@ function M.reset_signs()
542592
if signs_staged then
543593
signs_staged:reset()
544594
end
595+
redraw_statuscol()
545596
end
546597

547598
--- @param _cb 'win'

lua/gitsigns/signs.lua

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ local config = require('gitsigns.config').config
1111
--- @field hls table<Gitsigns.SignType,Gitsigns.SignConfig>
1212
--- @field name string
1313
--- @field group string
14+
--- @field signs table<integer,[string,string]>
1415
--- @field config table<string,Gitsigns.SignConfig>
1516
--- @field ns integer
1617
local M = {}
@@ -32,24 +33,23 @@ end
3233
function M:remove(bufnr, start_lnum, end_lnum)
3334
if start_lnum then
3435
api.nvim_buf_clear_namespace(bufnr, self.ns, start_lnum - 1, end_lnum or start_lnum)
36+
for i = start_lnum - 1, (end_lnum or start_lnum) - 1 do
37+
self.signs[i] = nil
38+
end
3539
else
40+
self.signs = {}
3641
api.nvim_buf_clear_namespace(bufnr, self.ns, 0, -1)
3742
end
3843
end
3944

4045
---@param bufnr integer
4146
---@param signs Gitsigns.Sign[]
4247
function M:add(bufnr, signs)
43-
if not config.signcolumn and not config.numhl and not config.linehl then
44-
-- Don't place signs if it won't show anything
45-
return
46-
end
47-
4848
for _, s in ipairs(signs) do
4949
if not self:contains(bufnr, s.lnum) then
5050
local cs = self.config[s.type]
5151
local text = cs.text
52-
if config.signcolumn and cs.show_count and s.count then
52+
if cs.show_count and s.count then
5353
local count = s.count
5454
local cc = config.count_chars
5555
local count_char = cc[count] or cc['+'] or ''
@@ -58,20 +58,21 @@ function M:add(bufnr, signs)
5858

5959
local hls = self.hls[s.type]
6060

61-
local ok, err = pcall(api.nvim_buf_set_extmark, bufnr, self.ns, s.lnum - 1, -1, {
62-
id = s.lnum,
61+
local ok, id_or_err = pcall(api.nvim_buf_set_extmark, bufnr, self.ns, s.lnum - 1, -1, {
6362
sign_text = config.signcolumn and text or '',
6463
priority = config.sign_priority,
6564
sign_hl_group = hls.hl,
6665
number_hl_group = config.numhl and hls.numhl or nil,
6766
line_hl_group = config.linehl and hls.linehl or nil,
6867
})
6968

70-
if not ok and config.debug_mode then
69+
if ok then
70+
self.signs[id_or_err] = { text, hls.hl }
71+
elseif config.debug_mode then
7172
vim.schedule(function()
7273
error(table.concat({
7374
string.format('Error placing extmark on line %d', s.lnum),
74-
err,
75+
id_or_err,
7576
}, '\n'))
7677
end)
7778
end
@@ -129,6 +130,7 @@ function M.new(cfg, name)
129130
self.hls = name == 'staged' and config._signs_staged or config.signs
130131
self.group = 'gitsigns_signs_' .. (name or '')
131132
self.ns = api.nvim_create_namespace(self.group)
133+
self.signs = {}
132134
return self
133135
end
134136

0 commit comments

Comments
 (0)