-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: precede opened or related buffers (#274)
* refactor: separate sorting logic to expand * feat: precede relational buffers * test: add tests for sorters * fix: check if the buffer is really opened in sorters (#276) * fix: check if the buffer is really opened in sorters The check whether the buffer is loaded is added in the enumeration of all the buffers in the list in sorters to ensure the proper sorting. * test: try to fix sorter tests according to changes * test: deal with non-loaded buffers in tests * refactor: use more effective logic to filter bufs * docs: add note for `preceding` option * feat: deal with the case config changed after init * refactor: reduce ambiguity between sorter/matcher --------- Co-authored-by: Alexey Chernov <[email protected]>
- Loading branch information
Showing
11 changed files
with
247 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
---@class FrecencySorterDefault: FrecencySorter | ||
local Default = {} | ||
|
||
---@return FrecencySorterDefault | ||
Default.new = function() | ||
return setmetatable({}, { __index = Default }) | ||
end | ||
|
||
---@param files FrecencyDatabaseEntry[] | ||
---@return FrecencyDatabaseEntry[] | ||
function Default.sort(_, files) | ||
table.sort(files, function(a, b) | ||
return a.score > b.score or (a.score == b.score and a.path > b.path) | ||
end) | ||
return files | ||
end | ||
|
||
return Default |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
local config = require "frecency.config" | ||
local Default = require "frecency.sorter.default" | ||
local Opened = require "frecency.sorter.opened" | ||
local SameRepo = require "frecency.sorter.same_repo" | ||
|
||
---@class FrecencySorter | ||
---@field new fun(): FrecencySorter | ||
---@field sort fun(self: FrecencySorter, files: FrecencyDatabaseEntry[]): FrecencyDatabaseEntry[] | ||
|
||
return { | ||
---@return FrecencySorter | ||
new = function() | ||
local Klass = config.preceding == "opened" and Opened or config.preceding == "same_repo" and SameRepo or Default | ||
return Klass.new() | ||
end, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
local Default = require "frecency.sorter.default" | ||
|
||
---@class FrecencySorterOpened: FrecencySorterDefault | ||
---@field protected buffers string[] | ||
---@field protected buffers_map table<string, boolean> | ||
local Opened = setmetatable({}, { __index = Default }) | ||
|
||
---@return FrecencySorterOpened | ||
Opened.new = function() | ||
local self = setmetatable(Default.new(), { __index = Opened }) --[[@as FrecencySorterOpened]] | ||
local bufnrs = vim.api.nvim_list_bufs() | ||
self.buffers = {} | ||
self.buffers_map = {} | ||
for _, bufnr in ipairs(bufnrs) do | ||
local is_loaded = vim.api.nvim_buf_is_loaded(bufnr) | ||
if is_loaded then | ||
local buffer = vim.api.nvim_buf_get_name(bufnr) | ||
table.insert(self.buffers, buffer) | ||
self.buffers_map[buffer] = true | ||
end | ||
end | ||
return self | ||
end | ||
|
||
function Opened:sort(files) | ||
local sorted = Default.sort(self, files) | ||
---@type FrecencyDatabaseEntry[], FrecencyDatabaseEntry[] | ||
local result, others = {}, {} | ||
for _, entry in ipairs(sorted) do | ||
table.insert(self.buffers_map[entry.path] and result or others, entry) | ||
end | ||
for _, entry in ipairs(others) do | ||
table.insert(result, entry) | ||
end | ||
return result | ||
end | ||
|
||
return Opened |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
local Default = require "frecency.sorter.default" | ||
local Opened = require "frecency.sorter.opened" | ||
|
||
---@class FrecencySorterSameRepo: FrecencySorterOpened | ||
---@field private repos string[] | ||
local SameRepo = setmetatable({}, { __index = Opened }) | ||
|
||
---@return FrecencySorterSameRepo | ||
SameRepo.new = function() | ||
local self = setmetatable(Opened.new(), { __index = SameRepo }) --[[@as FrecencySorterSameRepo]] | ||
self.repos = {} | ||
for _, buffer in ipairs(self.buffers) do | ||
local repo = vim.fs.root(buffer, ".git") | ||
if repo then | ||
table.insert(self.repos, repo) | ||
end | ||
end | ||
return self | ||
end | ||
|
||
function SameRepo:sort(files) | ||
local sorted = Default.sort(self, files) | ||
if #self.repos == 0 then | ||
return sorted | ||
end | ||
---@type FrecencyDatabaseEntry[], FrecencyDatabaseEntry[] | ||
local result, others = {}, {} | ||
for _, entry in ipairs(sorted) do | ||
local matched | ||
for _, repo in ipairs(self.repos) do | ||
matched = not not entry.path:find(repo, 1, true) | ||
if matched then | ||
break | ||
end | ||
end | ||
table.insert(matched and result or others, entry) | ||
end | ||
for _, entry in ipairs(others) do | ||
table.insert(result, entry) | ||
end | ||
return result | ||
end | ||
|
||
return SameRepo |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
local Default = require "frecency.sorter.default" | ||
local Opened = require "frecency.sorter.opened" | ||
local SameRepo = require "frecency.sorter.same_repo" | ||
|
||
---@param text string | ||
local function parse_text(text) | ||
local entries = {} | ||
for line in vim.gsplit(text, "\n", { plain = true, trimempty = true }) do | ||
local part = vim.split(line, "%s+", { trimempty = true }) | ||
if #part == 2 then | ||
table.insert(entries, { score = tonumber(part[1]), path = part[2] }) | ||
end | ||
end | ||
assert(#entries > 0) | ||
return entries | ||
end | ||
|
||
local entries = [[ | ||
10 /path/to/project_A/style.css | ||
20 /path/to/project_B/main.c | ||
40 /path/to/project_C/lib/main.ts | ||
60 /path/to/project_A/image.jpg | ||
80 /path/to/project_B/Makefile | ||
100 /path/to/project_A/index.html | ||
]] | ||
|
||
describe("frecency.sorter", function() | ||
for _, c in ipairs { | ||
{ | ||
M = Default, | ||
name = "Default", | ||
entries = [[ | ||
100 /path/to/project_A/index.html | ||
80 /path/to/project_B/Makefile | ||
60 /path/to/project_A/image.jpg | ||
40 /path/to/project_C/lib/main.ts | ||
20 /path/to/project_B/main.c | ||
10 /path/to/project_A/style.css | ||
]], | ||
}, | ||
{ | ||
M = Opened, | ||
name = "Opened", | ||
entries = [[ | ||
80 /path/to/project_B/Makefile | ||
60 /path/to/project_A/image.jpg | ||
100 /path/to/project_A/index.html | ||
40 /path/to/project_C/lib/main.ts | ||
20 /path/to/project_B/main.c | ||
10 /path/to/project_A/style.css | ||
]], | ||
}, | ||
{ | ||
M = SameRepo, | ||
name = "SameRepo", | ||
entries = [[ | ||
100 /path/to/project_A/index.html | ||
80 /path/to/project_B/Makefile | ||
60 /path/to/project_A/image.jpg | ||
20 /path/to/project_B/main.c | ||
10 /path/to/project_A/style.css | ||
40 /path/to/project_C/lib/main.ts | ||
]], | ||
}, | ||
} do | ||
it(("%s sorter returns valid entries"):format(c.name), function() | ||
local originals = { | ||
nvim_list_bufs = vim.api.nvim_list_bufs, | ||
nvim_buf_get_name = vim.api.nvim_buf_get_name, | ||
nvim_buf_is_loaded = vim.api.nvim_buf_is_loaded, | ||
root = vim.fs.root, | ||
} | ||
---@diagnostic disable-next-line: duplicate-set-field | ||
vim.api.nvim_list_bufs = function() | ||
return { 1, 2 } | ||
end | ||
---@diagnostic disable-next-line: duplicate-set-field | ||
vim.api.nvim_buf_get_name = function(bufnr) | ||
return ({ "/path/to/project_A/image.jpg", "/path/to/project_B/Makefile", "/path/to/project_A/index.html" })[bufnr] | ||
end | ||
---@diagnostic disable-next-line: duplicate-set-field | ||
vim.api.nvim_buf_is_loaded = function(bufnr) | ||
return ({ true, true, false })[bufnr] | ||
end | ||
---@diagnostic disable-next-line: duplicate-set-field | ||
vim.fs.root = function(path, _) | ||
return (path:match "(.*project_.)") | ||
end | ||
local sorter = c.M.new() | ||
assert.are.same(parse_text(c.entries), sorter:sort(parse_text(entries))) | ||
vim.api.nvim_list_bufs = originals.nvim_list_bufs | ||
vim.api.nvim_buf_get_name = originals.nvim_buf_get_name | ||
vim.api.nvim_buf_is_loaded = originals.nvim_buf_is_loaded | ||
vim.fs.root = originals.root | ||
end) | ||
end | ||
end) |