Bug fixes

pull/3/head
Iron-E 4 years ago
parent 1e72ac4c00
commit 481ce853ca
No known key found for this signature in database
GPG Key ID: 19B71B7B7B021D22

@ -17,8 +17,6 @@ let s:winOpenOpts = {
" RETURNS:
" * Input from `input()`.
function! libmodal#_inputWith(indicator, completions)
" TODO: 0.5 — return input(a:indicator, '', 'customlist,v:lua.require("libmodal/src/prompt")…')
" return the closure that was generated using the completions from lua.
function! LibmodalCompletionsProvider(argLead, cmdLine, cursorPos) abort closure
return luaeval(
\ 'require("libmodal/src/Prompt/").createCompletionsProvider(_A[1])(_A[2], _A[3], _A[4])',
@ -30,19 +28,6 @@ function! libmodal#_inputWith(indicator, completions)
return input(a:indicator, '', 'customlist,LibmodalCompletionsProvider')
endfunction
" SUMMARY:
" * Open a floating window using native vimscript.
" REMARKS:
" * There are bugs with creating floating windows using Lua (mostly they are
" always focused), so it was necessary to create a vimscript method.
" PARAMS:
" * `bufHandle` => the buffer to spawn the window for.
" RETURNS:
" * A window handle.
function! libmodal#_winOpen(bufHandle) abort
return nvim_open_win(a:bufHandle, 0, s:winOpenOpts)
endfunction
" SUMMARY:
" * Runs the nvim-libmodal command prompt loop. The function takes an optional
" argument specifying how many times to run (runs until exiting by default).
@ -74,7 +59,7 @@ endfunction
" * `args` => the arguments to pass to `lib`.enter()
function! libmodal#_lua(lib, args)
call luaeval(
\ 'require("libmodal/src/' . a:lib . '").enter(_A[1], _A[2], _A[3])',
\ 'require("libmodal").' . a:lib . '.enter(_A[1], _A[2], _A[3])',
\ [
\ a:args[0],
\ a:args[1],

@ -660,25 +660,29 @@ When submitting an issue, please describe the following:
0.5.0 ~
Additions: ~
* New class `libmodal.Mode`
* New class `libmodal.Mode.Popup`
* New class `libmodal.Prompt`
* New class `libmodal.Vars`
* New class `libmodal.collections.Stack`.
* New class `libmodal.Mode`.
* New class `libmodal.Mode.Popup`.
* New class `libmodal.Prompt`.
* New class `libmodal.Vars`.
Breaking Changes: ~
* Removed `libmodal.utils.vars`
* Moved `libmodal.utils.Indicator` to `libmodal.Indicator`
* Moved `libmodal.mode.ParseTable` to `libmodal.collections.ParseTable`.
* Removed `libmodal.utils.vars`.
* Moved `libmodal.utils.Indicator` to `libmodal.Indicator`.
* Moved `libmodal.utils.Indicator.Entry` to
`libmodal.Indicator.HighlightSegment`
`libmodal.Indicator.HighlightSegment`.
Changes: ~
*Error deprecated `libmodal.mode.enter()`
* Use `libmodal.Mode.new(…):enter()` instead.
*Error deprecated `libmodal.prompt.enter()`
* Use `libmodal.Prompt.new(…):enter()` instead.
* Allowed creation of |libmodal-mode| and |libmodal-prompt| table-objects.
* Call `{mode}:enter()` to enter the mode.
* More efficient recursion.
* Allow creation of |libmodal-mode| and |libmodal-prompt| table-objects.
* Call `libmodal.Mode.new()` or `libmodal.Prompt.new()` to create one.
* Call `{mode}:enter()` to enter the mode.
* More consistent mode recursion with `libmodal.collections.Stack`.
* Removed program logic from `libmodal.mode.enter()`.
* Now internally calls `libmodal.Mode.new(…):enter()` instead.
* Removed program logic from `libmodal.prompt.enter()`.
* Now internally calls `libmodal.Prompt.new(…):enter()` instead.
0.4.1 ~

@ -1,5 +1,5 @@
local libmodal = require('libmodal')
local fooModeRecurse = 0
local fooModeRecurse = 1
function fooMode()
local userInput = string.char(vim.api.nvim_get_var(

@ -9,17 +9,13 @@ local Indicator = {}
Indicator.HighlightSegment = require('libmodal/src/Indicator/HighlightSegment')
-- highlight group names
local _HL_GROUP_PROMPT = 'LibmodalPrompt'
local _HL_GROUP_STAR = 'LibmodalStar'
local _HL_GROUP_NONE = 'None'
local _HL_GROUP_MODE = 'LibmodalPrompt'
local _HL_GROUP_PROMPT = 'LibmodalStar'
-- `libmodal.mode` `HighlightSegment`s.
local _ENTRY_MODE_START = Indicator.HighlightSegment.new(_HL_GROUP_PROMPT, '-- ')
local _ENTRY_MODE_END = Indicator.HighlightSegment.new(_HL_GROUP_PROMPT, ' --')
-- `libmodal.prompt` `HighlightSegment`s.
local _ENTRY_PROMPT_START = Indicator.HighlightSegment.new(_HL_GROUP_STAR, '* ')
local _ENTRY_PROMPT_END = Indicator.HighlightSegment.new(_HL_GROUP_PROMPT, ' > ')
-- predefined segments
local _SEGMENT_MODE_BEGIN = Indicator.HighlightSegment.new(_HL_GROUP_MODE, '-- ')
local _SEGMENT_MODE_END = Indicator.HighlightSegment.new(_HL_GROUP_MODE, ' --')
local _PROMPT_TEMPLATE = {'* ', ' > '}
--[[
/*
@ -27,15 +23,6 @@ local _ENTRY_PROMPT_END = Indicator.HighlightSegment.new(_HL_GROUP_PROMPT, ' >
*/
--]]
local _metaIndicator = {
_ENTRY_MODE_START, nil, _ENTRY_MODE_END
}
_metaIndicator.__index = _metaIndicator
local _PROMPT_TEMPLATE = {
'* ', ' > '
}
--[[
/*
* CLASS `Indicator`
@ -51,14 +38,13 @@ local _PROMPT_TEMPLATE = {
]]
---------------------------------
function Indicator.mode(modeName)
local self = {}
setmetatable(self, _metaIndicator)
self[2] = Indicator.HighlightSegment.new(
_HL_GROUP_PROMPT, tostring(modeName)
)
return self
return {
[1] = _SEGMENT_MODE_BEGIN,
[2] = Indicator.HighlightSegment.new(
_HL_GROUP_MODE, tostring(modeName)
),
[3] = _SEGMENT_MODE_END,
}
end
-----------------------------------
@ -70,7 +56,10 @@ end
]]
-----------------------------------
function Indicator.prompt(modeName)
return table.concat(_PROMPT_TEMPLATE, modeName)
return Indicator.HighlightSegment.new(
_HL_GROUP_PROMPT,
table.concat(_PROMPT_TEMPLATE, modeName)
)
end
--[[

@ -14,62 +14,93 @@ local api = vim.api
local Popup = {}
local _winOpenOpts = {
['anchor'] = 'SW',
['col'] = api.nvim_get_option('columns') - 1,
['focusable'] = false,
['height'] = 1,
['relative'] = 'editor',
['row'] = api.nvim_get_option('lines')
- api.nvim_get_option('cmdheight')
- 1,
['style'] = 'minimal',
['width'] = 25,
}
--[[
/*
* CLASS `Popup`
* META `Popup`
*/
--]]
function Popup.new()
local self = {}
local buffer = api.nvim_create_buf(false, true)
local inputChars = {}
self.window = api.nvim_call_function('libmodal#_winOpen', {buf})
---------------------------
--[[ SUMMARY:
* Close `self.window`
* The `self` is inert after calling this.
]]
---------------------------
function self.close()
api.nvim_win_close(__self.window, false)
buffer = nil
inputChars = nil
self.window = nil
end
local _metaPopup = {}
_metaPopup.__index = _metaPopup
---------------------------------
--[[ SUMMARY:
* Update `buffer` with the latest user `inputBytes`.
]]
---------------------------------
function self.refresh(inputBytes)
-- The user simply typed one more character onto the last one.
if #inputBytes == #inputChars + 1 then
local len = #inputBytes
inputChars[len] = string.char(inputBytes[len])
elseif #inputBytes == 1 then -- the input was cleared.
inputChars = {
[1] = string.char(inputBytes[1])
}
else -- other tries to optimize this procedure fellthrough,
-- so do it the hard way.
inputChars = {}
for i, byte in ipairs(inputBytes) do
inputChars[i] = string.char(byte)
end
end
_metaPopup._buffer = nil
_metaPopup._inputChars = nil
_metaPopup.window = nil
api.nvim_buf_set_lines(
buffer, 0, 1, true,
{table.concat(inputChars)}
)
---------------------------
--[[ SUMMARY:
* Close `self.window`
* The `self` is inert after calling this.
]]
---------------------------
function _metaPopup:close()
api.nvim_win_close(self.window, false)
self._buffer = nil
self._inputChars = nil
self.window = nil
end
---------------------------------
--[[ SUMMARY:
* Update `buffer` with the latest user `inputBytes`.
]]
---------------------------------
function _metaPopup:refresh(inputBytes)
local inputBytesLen = #inputBytes
local inputChars = self._inputChars
-- The user simply typed one more character onto the last one.
if inputBytesLen == #inputChars + 1 then
inputChars[inputBytesLen] = string.char(inputBytes[inputBytesLen])
elseif inputBytesLen == 1 then
inputChars = {string.char(inputBytes[1])}
else -- other tries to optimize this procedure fellthrough, so do it the hard way.
local chars = {}
for i, byte in ipairs(inputBytes) do
chars[i] = string.char(byte)
end
self._inputChars = chars
end
return self
api.nvim_buf_set_lines(
self._buffer, 0, 1, true,
{table.concat(self._inputChars)}
)
end
--[[
/*
* CLASS `Popup`
*/
--]]
function Popup.new()
local buf = api.nvim_create_buf(false, true)
return setmetatable(
{
['_buffer'] = buf,
['_inputChars'] = {},
['window'] = api.nvim_call_function(
'nvim_open_win', {buf, false, _winOpenOpts}
)
},
_metaPopup
)
end
--[[

@ -4,11 +4,11 @@
*/
--]]
local globals = require('libmodal/src/globals')
local Indicator = require('libmodal/src/Indicator')
local Stack = require('libmodal/src/collections/Stack')
local utils = require('libmodal/src/utils')
local Vars = require('libmodal/src/Vars')
local globals = require('libmodal/src/globals')
local Indicator = require('libmodal/src/Indicator')
local collections = require('libmodal/src/collections')
local utils = require('libmodal/src/utils')
local Vars = require('libmodal/src/Vars')
local api = utils.api
@ -20,7 +20,6 @@ local api = utils.api
local Mode = {}
Mode.ParseTable = require('libmodal/src/Mode/ParseTable')
Mode.Popup = require('libmodal/src/Mode/Popup')
local _HELP = '?'
@ -42,11 +41,15 @@ _TIMEOUT.NR = string.byte(_TIMEOUT.CHAR)
local _metaMode = {}
_metaMode.__index = _metaMode
_metaMode._exit = Vars.new('exit')
_metaMode._indicator = nil
_metaMode._instruction = nil
_metaMode._name = nil
_metaMode._winState = nil
local _metaInputBytes = {
['clear'] = function(__self)
for i, _ in ipairs(__self) do
__self[i] = nil
end
end
}
_metaInputBytes.__index = _metaInputBytes
-----------------------------------------------
--[[ SUMMARY:
@ -55,15 +58,15 @@ _metaMode._winState = nil
-----------------------------------------------
function _metaMode:_checkInputForMapping()
-- Stop any running timers
self._modeEnterData:peek().flushInputTimer:stop()
self._flushInputTimer:stop()
-- Append the latest input to the locally stored input history.
local input = self._modeEnterData:peek().input
local inputBytes = self._modeEnterData:peek().inputBytes
input.bytes[#input.bytes + 1] = input:nvimGet(self._name)
inputBytes[#inputBytes + 1] = self._input:nvimGet()
-- Get the command based on the users input.
local cmd = self._mappings:get(input.bytes)
local cmd = self._mappings:get(inputBytes)
-- Get the type of the command.
local commandType = type(cmd)
@ -71,10 +74,10 @@ function _metaMode:_checkInputForMapping()
-- if there was no matching command
if cmd == false then
if #input.bytes < 2 and input.bytes[1] == string.byte(_HELP) then
if #inputBytes < 2 and inputBytes[1] == string.byte(_HELP) then
self._help:show()
end
input:clear()
inputBytes:clear()
-- The command was a table, meaning that it MIGHT match.
elseif commandType == globals.TYPE_TBL
and globals.isTrue(self._timeouts.enabled)
@ -82,27 +85,27 @@ function _metaMode:_checkInputForMapping()
-- Create a new timer
-- start the timer
self._modeEnterData:peek().flushInputTimer:start(
self._flushInputTimer:start(
_TIMEOUT.LEN, 0, vim.schedule_wrap(function()
-- Send input to interrupt a blocking `getchar`
_TIMEOUT:SEND()
-- if there is a command, execute it.
if cmd[Mode.ParseTable.CR] then
api.nvim_command(cmd[Mode.ParseTable.CR])
if cmd[collections.ParseTable.CR] then
api.nvim_command(cmd[collections.ParseTable.CR])
end
-- clear input
input:clear()
self._modeEnterData:peek().popup:refresh(input.bytes)
inputBytes:clear()
self._modeEnterData:peek().popup:refresh(inputBytes)
end)
)
-- The command was an actual vim command.
else
api.nvim_command(cmd)
input:clear()
inputBytes:clear()
end
self._modeEnterData:peek().popup:refresh(input.bytes)
self._modeEnterData:peek().popup:refresh(inputBytes)
end
--------------------------
@ -112,34 +115,26 @@ end
--------------------------
function _metaMode:enter()
-- intialize variables that are needed for each recurse of a function
if self._instruction == globals.TYPE_TBL then
if type(self._instruction) == globals.TYPE_TBL then
-- Initialize the input history variable.
local input = Vars.new('input')
input.bytes = {}
function input:clear()
self.bytes = {}
end
self._modeEnterData:push({
-- Create a timer
['flushInputTimer'] = vim.loop.new_timer(),
-- assign input
['input'] = input,
['inputBytes'] = setmetatable({}, _metaInputBytes),
-- create a floating window
['popup'] = Mode.Popup.new()
})
end
--[[ MODE LOOP. ]]
local continueMode = true
while continueMode == true do
while continueMode do
-- Try (using pcall) to use the mode.
local noErrors, modeResult = pcall(self._inputLoop, self)
-- If there were errors, handle them.
if noErrors == false then
if not noErrors then
utils.showError(modeResult)
continueMode = false
else
@ -156,26 +151,30 @@ end
]]
----------------------------------
function _metaMode:_initMappings()
-- Create a variable for whether or not timeouts are enabled.
self._timeouts = Vars.new('timeouts')
-- Read the correct timeout variable.
if api.nvim_exists('g', self._timeouts:name(modeName)) then self._timeouts.enabled =
self._timeouts:nvimGet(self._name)
else self._timeouts.enabled =
Vars.libmodalTimeouts
end
-- Create a timer to perform actions with.
self._flushInputTimer = vim.loop.new_timer()
-- Determine if a default `Help` should be created.
if not self._instruction[_HELP] then
self._help = utils.Help.new(self._instruction, 'KEY MAP')
end
-- Build the parse tree.
self._mappings = collections.ParseTable.new(self._instruction)
-- Create a table for mode-specific data.
self._modeEnterData = Stack.new()
self._modeEnterData = collections.Stack.new()
-- Build the parse tree.
self._mappings = Mode.ParseTable.new(self._instruction)
-- Create a variable for whether or not timeouts are enabled.
self._timeouts = Vars.new('timeouts', self._name)
-- Read the correct timeout variable.
if api.nvim_exists('g', self._timeouts:name())
then self._timeouts.enabled =
self._timeouts:nvimGet()
else self._timeouts.enabled =
Vars.libmodalTimeouts
end
end
-------------------------------
@ -189,7 +188,7 @@ end
function _metaMode:_inputLoop()
-- If the mode is not handling exit events automatically and the global exit var is true.
if self._exit.supress
and globals.isTrue(self._exit:nvimGet(self._name))
and globals.isTrue(self._exit:nvimGet())
then
return false
end
@ -206,7 +205,7 @@ function _metaMode:_inputLoop()
end
-- Set the global input variable to the new input.
self._modeEnterData:peek().input:nvimSet(self._name, userInput)
self._input:nvimSet(userInput)
-- Make sure that the user doesn't want to exit.
if not self._exit.supress
@ -221,28 +220,28 @@ function _metaMode:_inputLoop()
return true
end
---------------------------------
------------------------------
--[[ SUMMARY:
* Remove variables used for a mode.
]]
---------------------------------
------------------------------
function _metaMode:_tearDown()
if self._instruction == globals.TYPE_TBL then
local modeEnterData = self._modeEnterData:pop()
if type(self._instruction) == globals.TYPE_TBL then
self._flushInputTimer:stop()
modeEnterData.flushInputTimer:stop()
modeEnterData.flushInputTimer = nil
local modeEnterData = self._modeEnterData:pop()
for k, _ in pairs(modeEnterData.input) do
modeEnterData.input[k] = nil
for k, _ in pairs(modeEnterData.inputBytes) do
modeEnterData.inputBytes[k] = nil
end
modeEnterData.input = nil
modeEnterData.inputBytes = nil
modeEnterData.popup:close()
modeEnterData.popup = nil
end
self._winState:restore()
api.nvim_redraw()
end
--[[
@ -263,12 +262,21 @@ end
-----------------------------------------
function Mode.new(name, instruction, ...)
-- Inherit the metatable.
self = setmetatable({}, _metaMode)
local self = setmetatable(
{
['_exit'] = Vars.new('exit', name),
['_indicator'] = Indicator.mode(name),
['_input'] = Vars.new('input', name),
['_instruction'] = instruction,
['_name'] = name,
['_winState'] = utils.WindowState.new(),
},
_metaMode
)
-- Define the exit flag
self._exit = setmetatable({}, _metaMode._exit)
self._exit.supress = (function(optionalValue)
if #optionalValue > 0 then
if optionalValue then
return globals.isTrue(optionalValue)
else
return false
@ -276,10 +284,6 @@ function Mode.new(name, instruction, ...)
end)(unpack({...}))
-- Define other "session" variables.
self._indicator = Indicator.mode(name)
self._instruction = instruction
self._name = name
self._winState = utils.WindowState.new()
-- Determine whether a callback was specified, or a combo table.
if type(instruction) == globals.TYPE_TBL then
@ -290,7 +294,7 @@ function Mode.new(name, instruction, ...)
end
--[[
/*
/
* PUBLICIZE MODULE
*/
--]]

@ -6,7 +6,6 @@
local globals = require('libmodal/src/globals')
local Indicator = require('libmodal/src/Indicator')
local Stack = require('libmodal/src/collections/Stack')
local utils = require('libmodal/src/utils')
local Vars = require('libmodal/src/Vars')
@ -21,11 +20,14 @@ local api = utils.api
local Prompt = {}
local _HELP = 'help'
local _replacements = {
local _REPLACEMENTS = {
'(', ')', '[', ']', '{', '}',
'=', '+', '<', '>', '^',
',', '/', ':', '?', '@', '!', '$', '*', '.', '%', '&', '\\',
}
for i, replacement in ipairs(_REPLACEMENTS) do
_REPLACEMENTS[i] = vim.pesc(replacement)
end
--[[
/*
@ -36,58 +38,72 @@ local _replacements = {
local _metaPrompt = {}
_metaPrompt.__index = _metaPrompt
_metaPrompt._indicator = nil
_metaPrompt._input = nil
_metaPrompt._instruction = nil
_metaPrompt._name = nil
---------------------------------
--[[ SUMMARY:
* Loop to get user input with `input()`.
]]
---------------------------------
function _metaPrompt:_inputLoop()
-- clear previous `echo`s.
api.nvim_redraw()
-- get user input based on `instruction`.
-- define a placeholder for user input
local userInput = ''
if self._completions then userInput =
-- echo the highlighting
api.nvim_command('echohl ' .. self._indicator.hl)
-- set the user input variable
if self._completions
then userInput =
api.nvim_call_function('libmodal#_inputWith', {
self._indicator, self._completions
self._indicator.str, self._completions
})
else userInput =
api.nvim_call_function('input', {
self._indicator
})
api.nvim_call_function('input', {self._indicator})
end
-- if a:2 is a function then call it.
if string.len(userInput) > 0 then
self._input:nvimSet(self._name, userInput)
if type(self._instruction) == globals.TYPE_TBL then
if self._instruction[userInput] then -- there is a defined command for the input.
-- get the instruction for the mode.
local instruction = self._instruction
-- determine what to do with the input
if string.len(userInput) > 0 then -- the user actually entered something
self._input:nvimSet(userInput)
if type(instruction) == globals.TYPE_TBL then -- the instruction is a command table.
if instruction[userInput] then -- there is a defined command for the input.
api.nvim_command(instruction[userInput])
elseif userInput == _HELP then -- the user did not define a 'help' command, so use the default.
self._help:show()
else -- show an error.
api.nvim_show_err(globals.DEFAULT_ERROR_TITLE, 'Unknown command')
end
else instruction()
else -- attempt to call the instruction.
instruction()
end
else return false
else -- indicate we want to leave the prompt
return false
end
return true
end
----------------------------
--[[ SUMMARY:
* Enter a prompt 'mode'.
]]
----------------------------
function _metaPrompt:enter()
-- enter the mode using a loop.
local continueMode = true
while continueMode == true do
local noErrors, result = pcall(self._inputLoop, self)
local continueMode = true
while continueMode do
local noErrors, promptResult = pcall(self._inputLoop, self)
-- if there were errors.
if not noErrors then
utils.showError(err)
utils.showError(promptResult)
continueMode = false
else
continueMode = result
continueMode = promptResult
end
end
end
@ -121,13 +137,15 @@ function Prompt.createCompletionsProvider(completions)
-- replace conjoining characters with spaces.
local spacedArgLead = argLead
for _, v in ipairs(_replacements) do
spacedArgLead, _ = string.gsub(spacedArgLead, vim.pesc(v), ' ')
for _, replacement in ipairs(_REPLACEMENTS) do
spacedArgLead, _ = string.gsub(spacedArgLead, replacement, ' ')
end
-- split the spaced version of `argLead`.
local splitArgLead = vim.split(spacedArgLead, ' ', true)
print(spacedArgLead)
-- make sure the user is in a position were this function
-- will provide accurate completions.
if #splitArgLead > 1 then
@ -139,10 +157,14 @@ function Prompt.createCompletionsProvider(completions)
-- get all matches from the completions list.
local matches = {}
for _, v in ipairs(completions) do
for _, completion in ipairs(completions) do
print('testing ' .. word .. ' against ' .. string.upper(completion))
-- test if `word` is inside of `completions`:`v`, ignoring case.
if string.match(vim.pesc(string.upper(v)), word) then
matches[#matches + 1] = v -- preserve case when providing completions.
if string.match(vim.pesc(string.upper(completion)), word) then
print('>>match')
matches[#matches + 1] = completion -- preserve case when providing completions.
else
print('>>nomatch')
end
end
return matches
@ -160,12 +182,15 @@ end
]]
-------------------------------------------
function Prompt.new(name, instruction, ...)
self = setmetatable({}, _metaPrompt)
self._indicator = Indicator.prompt(name)
self._input = vars.new('input')
self._instruction = instruction
self._name = name
local self = setmetatable(
{
['_indicator'] = Indicator.prompt(name),
['_input'] = Vars.new('input', name),
['_instruction'] = instruction,
['_name'] = name
},
_metaPrompt
)
-- get the arguments
local userCompletions = unpack({...})
@ -176,15 +201,15 @@ function Prompt.new(name, instruction, ...)
local completions = {}
local containedHelp = false
for k, _ in pairs(instruction) do
completions[#completions + 1] = k
if k == _HELP then containedHelp = true
for command, _ in pairs(instruction) do
completions[#completions + 1] = command
if command == _HELP then containedHelp = true
end
end
if not containedHelp then -- assign it.
completions[#completions + 1] = _HELP
vars.help.instances[modeName] = utils.Help.new(instruction, 'COMMAND')
self._help = utils.Help.new(instruction, 'COMMAND')
end
self._completions = completions
@ -192,6 +217,8 @@ function Prompt.new(name, instruction, ...)
-- Use the table that the user gave.
self._completions = userCompletions
end
return self
end

@ -29,18 +29,19 @@ local _metaVars = {}
_metaVars.__index = _metaVars
-- Instances of variables pertaining to a certain mode.
_metaVars.varName = nil
_metaVars._varName = nil
_metaVars._modeName = nil
-------------------------
---------------------------------
--[[ SUMMARY:
* Get the name of `modeName`s global setting.
]]
--[[ PARAMS:
* `modeName` => the name of the mode.
]]
-------------------------
function _metaVars:name(modeName)
return string.lower(modeName) .. self._varName
---------------------------------
function _metaVars:name()
return string.lower(self._modeName) .. self._varName
end
------------------------------------
@ -51,8 +52,8 @@ end
* `modeName` => the mode name this value is being retrieved for.
]]
------------------------------------
function _metaVars:nvimGet(modeName)
return api.nvim_get_var(self:name(modeName))
function _metaVars:nvimGet()
return api.nvim_get_var(self:name())
end
-----------------------------------------
@ -64,8 +65,8 @@ end
* `val` => the value to set `self`'s Vimscript var to.
]]
-----------------------------------------
function _metaVars:nvimSet(modeName, val)
api.nvim_set_var(self:name(modeName), val)
function _metaVars:nvimSet(val)
api.nvim_set_var(self:name(), val)
end
--[[
@ -82,11 +83,11 @@ end
* `keyName` => the name of the key used to refer to this variable in `Vars`.
]]
--------------------------
function Vars.new(keyName)
self = {}
setmetatable(self, _metaVars)
function Vars.new(keyName, modeName)
local self = setmetatable({}, _metaVars)
self._varName = 'Mode' .. string.upper(
self._modeName = modeName
self._varName = 'Mode' .. string.upper(
string.sub(keyName, 0, 1)
) .. string.sub(keyName, 2)

@ -27,7 +27,7 @@ _metaStack._top = nil
]]
--------------------------------
function _metaStack:peek()
return top
return self._top
end
-------------------------
@ -39,18 +39,28 @@ end
]]
-------------------------
function _metaStack:pop()
if len < 1 then return nil
local previousLen = self._len
if previousLen < 1 then return nil
end
-- Store the previous top of the stack.
local previousTop = self._top
-- Remove the previous top of the stack.
self[_len] = nil
self[previousLen] = nil
-- Get the new length of the stack
local newLen = previousLen - 1
-- Update the values of the stack.
self._len = self._len - 1
self._top = self[_len]
if newLen < 1 then -- the stack is empty
self._len = nil
self._top = nil
else -- there is still something in the stack
self._len = newLen
self._top = self[newLen]
end
-- Return the previous top of the stack.
return previousTop
@ -65,8 +75,15 @@ end
]]
-------------------------------
function _metaStack:push(value)
self._len = self._len + 1
self[_len] = value
-- create placeholder so new values are not put into the table until operations have succeeded.
local newLen = self._len + 1
-- Push to the stack
self[newLen] = value
-- update stack values
self._len = newLen
self._top = value
end
--[[
@ -76,8 +93,13 @@ end
--]]
function Stack.new()
local self = {}
setmetatable(self, _metaStack)
return self
return setmetatable({}, _metaStack)
end
--[[
/*
* PUBLICIZE `Stack`
*/
--]]
return Stack

@ -1,3 +1,6 @@
local collections = {}
collections.Stack = require('libmodal/src/collections/Stack')
collections.ParseTable = require('libmodal/src/collections/ParseTable')
collections.Stack = require('libmodal/src/collections/Stack')
return collections

@ -1,46 +0,0 @@
--[[
/*
* IMPORTS
*/
--]]
local Mode = require('libmodal/src/Mode')
--[[
/*
* MODULE
*/
--]]
local mode = {}
mode.ParseTable = Mode.ParseTable
--[[
/*
* LIBRARY `mode`
*/
--]]
------------------------
--[[ DEPRECATED. ]]
--[[ SUMMARY:
* Enter a mode.
]]
--[[ PARAMS:
* `args[1]` => the mode name.
* `args[2]` => the mode callback, or mode combo table.
* `args[3]` => optional exit supresion flag.
]]
------------------------
function mode.enter(name, instruction, ...)
Mode.new(name, instruction, ...):enter()
end
--[[
/*
* PUBLICIZE MODULE
*/
--]]
return mode

@ -6,12 +6,26 @@
local libmodal = {}
libmodal.globals = require('libmodal/src/globals')
libmodal.mode = require('libmodal/src/deprecated/mode')
libmodal.Mode = require('libmodal/src/Mode')
libmodal.prompt = require('libmodal/src/deprecated/prompt')
libmodal.Prompt = require('libmodal/src/Prompt')
libmodal.utils = require('libmodal/src/utils')
libmodal.collection = require('libmodal/src/collections')
libmodal.globals = require('libmodal/src/globals')
libmodal.Indicator = require('libmodal/src/Indicator')
libmodal.Mode = require('libmodal/src/Mode')
libmodal.Prompt = require('libmodal/src/Prompt')
libmodal.utils = require('libmodal/src/utils')
--[[
/*
* MIRRORS
*/
--]]
libmodal.mode = {['enter'] = function(name, instruction, ...)
libmodal.Mode.new(name, instruction, ...):enter()
end}
libmodal.prompt = {['enter'] = function(name, instruction, ...)
libmodal.Prompt.new(name, instruction, ...):enter()
end}
--[[
/*

@ -1,3 +1,24 @@
--[[
/*
* META `Help`
*/
--]]
local _metaHelp = {}
_metaHelp.__index = _metaHelp
-------------------------
--[[ SUMMARY:
* Show the contents of this `Help`.
]]
-------------------------
function _metaHelp:show()
for _, helpText in ipairs(self) do
print(helpText)
end
vim.api.nvim_call_function('getchar', {})
end
--[[
/*
* CLASS `Help`
@ -68,27 +89,19 @@ function Help.new(commandsOrMaps, title)
helpSeparator = table.concat(helpSeparator)
-- Create a new `Help`.
return {
[1] = ' ',
[2] = table.concat(tabAlign({
[title] = 'VIM EXPRESSION',
})),
[3] = table.concat(tabAlign({
[helpSeparator] = '--------------'
})),
[4] = table.concat(tabAlign(commandsOrMaps)),
-----------------------
--[[ SUMMARY:
* Show the contents of this `Help`.
]]
-----------------------
show = function(__self)
for _, v in ipairs(__self) do
print(v)
end
vim.api.nvim_call_function('getchar', {})
end
}
return setmetatable(
{
[1] = ' ',
[2] = table.concat(tabAlign({
[title] = 'VIM EXPRESSION',
})),
[3] = table.concat(tabAlign({
[helpSeparator] = '--------------'
})),
[4] = table.concat(tabAlign(commandsOrMaps)),
},
_metaHelp
)
end
--[[

@ -4,7 +4,7 @@
*/
--]]
local api = vim.api
local api = require('libmodal/src/utils/api')
--[[
/*
@ -17,6 +17,26 @@ local WindowState = {}
local height = 'winheight'
local width = 'winwidth'
--[[
/*
* META `WindowState`
*/
--]]
local _metaWindowState = {}
_metaWindowState.__index = _metaWindowState
-----------------------------------
--[[ SUMMARY
* Restore the state of `self`.
]]
-----------------------------------
function _metaWindowState:restore()
api.nvim_set_option(height, self.height)
api.nvim_set_option(width, self.width)
api.nvim_redraw()
end
--[[
/*
* CLASS `WindowState`
@ -32,22 +52,13 @@ local width = 'winwidth'
]]
--------------------------
function WindowState.new()
local winState = {
['height'] = api.nvim_get_option(height),
['width'] = api.nvim_get_option(width),
}
---------------------------
--[[ SUMMARY
* Restore the state of `self`.
]]
---------------------------
function winState:restore()
api.nvim_set_option(height, self['height'])
api.nvim_set_option(width, self['width'])
end
return winState
return setmetatable(
{
['height'] = api.nvim_get_option(height),
['width'] = api.nvim_get_option(width),
},
_metaWindowState
)
end
--[[

@ -74,14 +74,21 @@ end
* `hlTables` => the tables to echo with highlights.
]]
---------------------------------
local lecho_template = {
[1] = "echohl ",
[2] = nil,
[3] = " | echon '",
[4] = nil,
[5] = "'"
}
function api.nvim_lecho(hlTables)
api.nvim_redraw()
for _, hlTable in ipairs(hlTables) do
-- `:echohl` the hlgroup and then `:echon` the string
api.nvim_command(
"echohl " .. tostring(hlTable['hl'])
.. " | echon '" .. tostring(hlTable['str']) .. "'"
)
lecho_template[2] = tostring(hlTable.hl)
lecho_template[4] = tostring(hlTable.str)
api.nvim_command(table.concat(lecho_template))
end
api.nvim_command('echohl None')
end

Loading…
Cancel
Save