Skip to content

Commit

Permalink
[git] Colored completions for git checkout ... with Clink v1.1.12 p…
Browse files Browse the repository at this point in the history
…opup list (vladimir-kotikov#135)

* [git] Optionally color the `*` in checkout completions.

In Clink v1.1.9 and higher a match display filter can provide colored
text.  The `git checkout` match display filter now applies a color to
the `*` next to preferred branch names.

This change is written to be compatible with all versions of Clink.

* [git] `git stash ...` works with `clink-popup-complete`.

In Clink v1.1.12 and higher `clink.ondisplaymatches` lets a match
generator supply descriptions associated with matches.  This makes it
possible for the `clink-popup-complete` command to show stash
descriptions next to the stash IDs.

This change is written to be compatible with all versions of Clink.

* Add a version module and color helper.

* Busted runs the modules scripts outside of Clink.

The version module is meant to encapsulate Clink versioning, but it must
do so without relying on Clink being present.

* Restructure code to satisfy code coverage.

It uses the short circuiting `and` operator to try to trick code
coverage analysis into considering the line to have been executed even
though it's impossible to execute.

I could invest in building a mock infrastructure for this repo, but
that's more cost than I'm willing to invest for this scenario.

* Address additional PR feedback:
- Rename the version module.
- Compute all version checks during script exec and cache the results.
- Add comment about Clink's color setting format being SGR params.

* Exclude the renamed version module from codecov.

* Address additional PR feedback:
- Factor the colored star construction differently.

* Fix typo.
Somehow I renamed version module name in the require(), but accidentally
undid the change in this copy of the file.
  • Loading branch information
chrisant996 authored and vladimir-kotikov committed Jan 6, 2021
1 parent a9b3134 commit dc590e8
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .luacheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ return {
files = {
spec = { std = "+busted" },
},
globals = { "clink", "rl_state" }
globals = { "clink", "rl_state", "rl", "settings", "log", "path" }
}
2 changes: 1 addition & 1 deletion .luacov
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
return {
include = { "modules/*" },
exclude = { "lua_modules/*", ".lua/*" },
exclude = { "lua_modules/*", ".lua/*", "modules/clink_version.lua" },
deletestats = false,
runreport = true
}
34 changes: 30 additions & 4 deletions git.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ local path = require('path')
local git = require('gitutil')
local matchers = require('matchers')
local w = require('tables').wrap
local clink_version = require('clink_version')
local color = require('color')
local parser = clink.arg.new_parser

if clink_version.supports_color_settings then
settings.add('color.git.star', 'bright green', 'Color for preferred branch completions')
end

---
-- Lists remote branches based on packed-refs file from git directory
-- @param string [dir] Directory where to search file for
Expand Down Expand Up @@ -156,11 +162,15 @@ local function checkout_spec_generator(token)
-- since it is not added automatically by readline (see previous point)
clink.matches_are_files(0)
clink.match_display_filter = function ()
local star = '*'
if clink_version.supports_query_rl_var and rl.isvariabletrue('colored-stats') then
star = color.get_clink_color('color.git.star')..star..color.get_clink_color('color.filtered')
end
return files:map(function(file)
return clink.is_dir(file) and file..'\\' or file
end)
:concat(local_branches)
:concat(predicted_branches:map(function(branch) return '*'..branch end))
:concat(predicted_branches:map(function(branch) return star..branch end))
:concat(remote_branches)
end

Expand Down Expand Up @@ -259,14 +269,30 @@ local stashes = function(token) -- luacheck: no unused args
local ret = {}
local ret_filter = {}
for i,v in ipairs(stash_times) do
table.insert(ret, "stash@{"..(i-1).."}")
table.insert(ret_filter, "stash@{"..(i-1).."} "..stashes[v])
local match = "stash@{"..(i-1).."}"
table.insert(ret, match)
if clink_version.supports_display_filter_description then
-- Clink now has a richer match interface. By returning a table,
-- the script is able to provide the stash name separately from the
-- description. If the script does so, then the popup completion
-- window is able to show the stash name plus a dimmed description,
-- but only insert the stash name.
table.insert(ret_filter, { match=match, type="word", description=stashes[v] })
else
table.insert(ret_filter, match.." "..stashes[v])
end
end

clink.match_display_filter = function ()
local function filter()
return ret_filter
end

if clink_version.supports_display_filter_description then
clink.ondisplaymatches(filter)
else
clink.match_display_filter = filter
end

return ret
end

Expand Down
13 changes: 13 additions & 0 deletions modules/clink_version.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
local exports = {}

-- Busted runs these modules scripts *outside* of Clink.
-- So these Clink scripts have to work without any Clink APIs being available.
clink = clink or {}

local clink_version_encoded = clink.version_encoded or 0

exports.supports_display_filter_description = (clink_version_encoded >= 10010012)
exports.supports_color_settings = (clink_version_encoded >= 10010009)
exports.supports_query_rl_var = (clink_version_encoded >= 10010009)

return exports
11 changes: 11 additions & 0 deletions modules/color.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
local clink_version = require('clink_version')

local exports = {}

exports.BLACK = 0
Expand All @@ -23,6 +25,15 @@ exports.set_color = function (fore, back, bold)
return "\x1b[3"..fore..";"..bold..";".."4"..back.."m"
end

exports.get_clink_color = function (setting_name)
-- Clink's settings.get() returns SGR parameters for a CSI SGR escape code.
local sgr = clink_version.supports_color_settings and settings.get(setting_name) or ""
if sgr ~= "" then
sgr = "\x1b["..sgr.."m"
end
return sgr
end

exports.color_text = function (text, fore, back, bold)
return exports.set_color(fore, back, bold)..text..exports.set_color()
end
Expand Down
8 changes: 8 additions & 0 deletions spec/color_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe("color module", function()

it("should export methods", function()
assert.are.equal(type(color.set_color), 'function')
assert.are.equal(type(color.get_clink_color), 'function')
assert.are.equal(type(color.color_text), 'function')
end)

Expand Down Expand Up @@ -56,6 +57,13 @@ describe("color module", function()
end)
end)

describe("'get_clink_color' method", function ()

it("should do nothing since Clink support is only available in actual Clink", function ()
assert.are.equals(color.get_clink_color('color.git.star'), "")
end)
end)

describe("'color_text' method", function ()

local TEST_STRING = "abc"
Expand Down

0 comments on commit dc590e8

Please sign in to comment.