-
-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(functions): Mode aware functions #415
Changes from all commits
243372e
a2363e3
5d3a59f
cf3a2a9
29513d1
f0caf2e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,8 +2,24 @@ local class = require('legendary.vendor.middleclass') | |||||||||||||||||||||||||||||||||||||||||||||||
local util = require('legendary.util') | ||||||||||||||||||||||||||||||||||||||||||||||||
local Filters = require('legendary.data.filters') | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
---Check if modes is an array of strings or itself a string | ||||||||||||||||||||||||||||||||||||||||||||||||
---@param modes table | ||||||||||||||||||||||||||||||||||||||||||||||||
---@return boolean | ||||||||||||||||||||||||||||||||||||||||||||||||
local is_list_of_strings_or_string = function(modes) | ||||||||||||||||||||||||||||||||||||||||||||||||
if modes == nil or type(modes) == 'string' then | ||||||||||||||||||||||||||||||||||||||||||||||||
return true | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
for _, mode in ipairs(modes) do | ||||||||||||||||||||||||||||||||||||||||||||||||
if type(mode) ~= 'string' then | ||||||||||||||||||||||||||||||||||||||||||||||||
return false | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
return true | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
---@class Function | ||||||||||||||||||||||||||||||||||||||||||||||||
---@field implementation function | ||||||||||||||||||||||||||||||||||||||||||||||||
---@field mode_mappings string[] | ||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We shouldn't have the Take a look at how There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Quite a lot for an overnight PR which I made without a prior knowledge of this project, isn't it? I didn't intend to implement fully
Ambiguities
Only to make things more complicated: validation (see below) requires that item's I suggest you take care of map enhancement further after merging this PR. legendary.nvim/lua/legendary/data/function.lua Lines 15 to 20 in 6ea46c2
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean. There's no deadline on the PR. Regarding your 3 bullets, addressing in-order:
It's not really more complicated. You can copy the validator from It we're going to introduce There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
As I said, this PR is about functions, not keymaps; if you want to unify mode-map apis for both, I would suggest you to take care of further mode-map improvement yourself taking the laid groundwork as basis; for me, it's more than enough to have And as I said, I see no reason to introduce that complicated approach, cause there are going to be ambiguities you will have to resolve as project owner |
||||||||||||||||||||||||||||||||||||||||||||||||
---@field description string | ||||||||||||||||||||||||||||||||||||||||||||||||
---@field opts table | ||||||||||||||||||||||||||||||||||||||||||||||||
---@field filters (function[])|nil | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -15,6 +31,11 @@ Function:include(Filters) ---@diagnostic disable-line | |||||||||||||||||||||||||||||||||||||||||||||||
function Function:parse(tbl) -- luacheck: no unused | ||||||||||||||||||||||||||||||||||||||||||||||||
vim.validate({ | ||||||||||||||||||||||||||||||||||||||||||||||||
['1'] = { tbl[1], { 'function' } }, | ||||||||||||||||||||||||||||||||||||||||||||||||
mode = { | ||||||||||||||||||||||||||||||||||||||||||||||||
tbl.mode, | ||||||||||||||||||||||||||||||||||||||||||||||||
is_list_of_strings_or_string, | ||||||||||||||||||||||||||||||||||||||||||||||||
'item.mode should contain only strings of modes: n, i, v etc.', | ||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||
description = { util.get_desc(tbl), { 'string' } }, | ||||||||||||||||||||||||||||||||||||||||||||||||
opts = { tbl.opts, { 'table' }, true }, | ||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -26,6 +47,29 @@ function Function:parse(tbl) -- luacheck: no unused | |||||||||||||||||||||||||||||||||||||||||||||||
instance.opts = tbl.opts or {} | ||||||||||||||||||||||||||||||||||||||||||||||||
instance:parse_filters(tbl.filters) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
-- By default, function can be run in all modes, so mode_mapping is empty | ||||||||||||||||||||||||||||||||||||||||||||||||
instance.mode_mappings = vim.tbl_islist(tbl.mode) and tbl.mode or {} | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
-- If tbl = { fn, mode = "n" } | ||||||||||||||||||||||||||||||||||||||||||||||||
if type(tbl.mode) == 'string' then | ||||||||||||||||||||||||||||||||||||||||||||||||
table.insert(instance.mode_mappings, tbl.mode) | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
-- only tbl = { fn, mode = { 'n' } } | ||||||||||||||||||||||||||||||||||||||||||||||||
-- Reassing implementation with a current-mode hanlder | ||||||||||||||||||||||||||||||||||||||||||||||||
if not vim.tbl_isempty(instance.mode_mappings) then | ||||||||||||||||||||||||||||||||||||||||||||||||
local impl = instance.implementation | ||||||||||||||||||||||||||||||||||||||||||||||||
instance.implementation = function() | ||||||||||||||||||||||||||||||||||||||||||||||||
local modeCurrent = vim.fn.mode() | ||||||||||||||||||||||||||||||||||||||||||||||||
for _, modeInstance in ipairs(instance.mode_mappings) do | ||||||||||||||||||||||||||||||||||||||||||||||||
if modeCurrent == modeInstance then | ||||||||||||||||||||||||||||||||||||||||||||||||
impl() | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+62
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
-- mode_mapping is going to remain static during legendary runtime | ||||||||||||||||||||||||||||||||||||||||||||||||
-- so we can cache current mapping state | ||||||||||||||||||||||||||||||||||||||||||||||||
instance._mode_switched = vim.tbl_islist(instance.mode_mappings) and not vim.tbl_isempty(instance.mode_mappings) | ||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+70
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't feel necessary to me to cache this.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's used for displaying: 29513d1#r1366849251 ; It's essential for both performance reason and readability There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really don't think it will have a noticeable impact on performance, and I don't see how it affects readability either, personally. If you can show some benchmarks proving otherwise I'm all ears. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mrjones2014 It's cheap to check once and leave, then checking whether the list is empty all the time when the list doesn't change. This is obvious. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It’s an extremely inexpensive check. It doesn’t need to be cached. |
||||||||||||||||||||||||||||||||||||||||||||||||
return instance | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -43,4 +87,19 @@ function Function:frecency_id() | |||||||||||||||||||||||||||||||||||||||||||||||
return string.format('<function> %s', self.description) | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
--- Intended to be used by UI filters | ||||||||||||||||||||||||||||||||||||||||||||||||
function Function:modeSwitched() | ||||||||||||||||||||||||||||||||||||||||||||||||
return self._mode_switched | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+90
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on the diff it looks like this function isn't needed either.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's used for displaying: 29513d1#r1366849251 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, you don't have to do it that way though -- see the other comments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feel free to refactor it after a merge |
||||||||||||||||||||||||||||||||||||||||||||||||
function Function:modes() | ||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
if self:modeSwitched() then | ||||||||||||||||||||||||||||||||||||||||||||||||
return self.mode_mappings | ||||||||||||||||||||||||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||||||||||||||||||||||||
-- Just use all modes for UI filtering | ||||||||||||||||||||||||||||||||||||||||||||||||
-- it's half-assed because UI filtering is ugly ¯\_(ツ)_/¯ | ||||||||||||||||||||||||||||||||||||||||||||||||
return { 'n', 'V', 'v', 'x', 's', 'o', '' } | ||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+96
to
+102
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's keep it consistent with how the
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will require a lot of changes in Function's constructor where
Well, mode-map is not consistent across keymaps, commands, autocommands, and functions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Disagree. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not an intent of this PR; I'm fine if you refactor it further after merging it; there is a lof of space for improvement in this project |
||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
return Function |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -38,11 +38,15 @@ function M.default_format(item) | |||||||||
item.description, | ||||||||||
} | ||||||||||
elseif Toolbox.is_function(item) then | ||||||||||
-- stylua: ignore start | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Stylua makes lines in-between ugly otherwise There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather just have the formatter format it than stray from the style of everything else in the entire codebase. |
||||||||||
return { | ||||||||||
Config.icons.fn, | ||||||||||
item--[[@as keymap ]]:modeSwitched() | ||||||||||
and table.concat(item--[[@as Keymap]]:modes(), ', ') | ||||||||||
or Config.icons.fn, | ||||||||||
Comment on lines
+43
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, look carefully what you suggest; this introduces a bug; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't introduce a bug if you also tweak the implementation of |
||||||||||
'<function>', | ||||||||||
item.description, | ||||||||||
} | ||||||||||
-- stylua: ignore end | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We shouldn't be ignoring formatting unless there's a good reason. |
||||||||||
elseif Toolbox.is_itemgroup(item) then | ||||||||||
return { | ||||||||||
item.icon or Config.icons.itemgroup, | ||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.