Finish translating examples and fix all mode bugs

pull/3/head
Iron-E 4 years ago
parent d6056571d2
commit 88371b5ff0
No known key found for this signature in database
GPG Key ID: 19B71B7B7B021D22

@ -1,8 +1,32 @@
let s:winOpenOpts = {
\ 'anchor' : 'SW',
\ 'col' : &columns - 1,
\ 'focusable': v:false,
\ 'height' : 1,
\ 'relative' : 'editor',
\ 'row' : &lines - &cmdheight - 1,
\ 'style' : 'minimal',
\ 'width' : 25,
\}
" PLACEHOLDER.
function! libmodal#Enter(...) abort
echo ''
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
" PLACEHOLDER.
function! libmodal#Prompt(...) abort
echo ''

@ -1,6 +1,5 @@
local api = vim.api
local libmodal = require('libmodal')
local barModeInputHistory = {}
local function clearHistory(indexToCheck)
@ -9,11 +8,10 @@ local function clearHistory(indexToCheck)
end
end
barMode = function()
table.insert(
barModeInputHistory,
api.nvim_eval('nr2char(g:barModeInput)')
)
function barMode()
table.insert(barModeInputHistory, string.char(
api.nvim_get_var('barModeInput')
))
local index = 1
if barModeInputHistory[1] == 'z' then

@ -1,9 +1,7 @@
local libmodal = require('libmodal')
local barModeRecurse = 0
local barModeCombos = {
['z'] = 'BarModeEnter',
['z'] = 'lua barMode()'
}
function barMode()
@ -12,5 +10,4 @@ function barMode()
barModeRecurse = barModeRecurse - 1
end
vim.api.nvim_command('command! BarModeEnter lua barMode()')
barMode()

@ -1,6 +1,8 @@
let s:barModeCombos = {
\ '': 'echom "You cant exit using escape."',
\ 'q': 'let g:barModeExit = 1'
\}
local libmodal = require('libmodal')
local barModeCombos = {
[''] = 'echom "You cant exit using escape."',
['q'] = 'let g:barModeExit = 1'
}
call libmodal#Enter('BAR', s:barModeCombos, 1)
vim.api.nvim_set_var('barModeExit', 0)
libmodal.mode.enter('BAR', barModeCombos, true)

@ -1,7 +1,8 @@
let s:barModeCombos = {
\ 'zf': 'split',
\ 'zfo': 'vsplit',
\ 'zfc': 'tabnew'
\}
local libmodal = require('libmodal')
local barModeCombos = {
['zf'] = 'split',
['zfo'] = 'vsplit',
['zfc'] = 'tabnew'
}
call libmodal#Enter('BAR', s:barModeCombos)
libmodal.mode.enter('BAR', barModeCombos)

@ -1,13 +1,15 @@
let s:commandList = ['new', 'close', 'last']
local libmodal = require('libmodal')
local commandList = {'new', 'close', 'last'}
function! s:BarMode() abort
if g:tabModeInput ==# 'new'
function barMode()
local uinput = vim.api.nvim_get_var('tabModeInput')
if uinput == 'new' then
execute 'tabnew'
elseif g:tabModeInput ==# 'close'
elseif uinput == 'close' then
execute 'tabclose'
elseif g:tabModeInput ==# 'last'
elseif uinput == 'last' then
execute 'tablast'
endif
endfunction
end
end
call libmodal#Prompt('TAB', funcref('s:BarMode'), s:commandList)
libmodal.prompt.enter('BAR', barMode, commandList)

@ -1,7 +1,8 @@
let s:commands = {
\ 'new': 'tabnew',
\ 'close': 'tabclose',
\ 'last': 'tablast'
\}
local libmodal = require('libmodal')
local commands = {
['new'] = 'tabnew',
['close'] = 'tabclose',
['last'] = 'tablast'
}
call libmodal#Prompt('TAB', s:commands)
libmodal.prompt.enter('BAR', commands)

@ -1,12 +1,20 @@
let s:barModeRecurse = 0
function! s:BarMode()
if g:bar{s:barModeRecurse}ModeInput ==# 'z'
let s:barModeRecurse += 1
execute 'BarModeEnter'
let s:barModeRecurse -= 1
endif
endfunction
command! BarModeEnter call libmodal#Enter('BAR' . s:barModeRecurse, funcref('s:BarMode'))
execute 'BarModeEnter'
local libmodal = require('libmodal')
local barModeRecurse = 0
function barMode()
local uinput = string.char(vim.api.nvim_get_var(
'bar' .. tostring(barModeRecurse) .. 'ModeInput'
))
if uinput == 'z' then
barModeRecurse = barModeRecurse + 1
enter()
barModeRecurse = barModeRecurse - 1
end
end
function enter()
libmodal.mode.enter('BAR' .. barModeRecurse, barMode)
end
enter()

@ -1,11 +1,16 @@
let s:barModeInputHistory = ''
local libmodal = require('libmodal')
function! s:BarMode()
if g:barModeInput ==# ''
echom 'You cant leave using <Esc>.'
elseif g:barModeInput ==# 'q'
let g:barModeExit = 1
endif
endfunction
function barMode()
local uinput = string.char(
vim.api.nvim_get_var('barModeInput')
)
call libmodal#Enter('BAR', funcref('s:BarMode'), 1)
if uinput == '' then
vim.api.nvim_command("echo 'You cant leave using <Esc>.'")
elseif uinput == 'q' then
vim.api.nvim_set_var('barModeExit', true)
end
end
vim.api.nvim_set_var('barModeExit', 0)
libmodal.mode.enter('BAR', barMode, true)

@ -20,6 +20,13 @@ globals.TYPE_TBL = 'table'
globals.VIM_FALSE = 0
globals.VIM_TRUE = 1
function globals.isFalse(val)
return val == false or val == globals.VIM_FALSE
end
function globals.isTrue(val)
return val == true or val == globals.VIM_TRUE
end
--[[
/*

@ -21,7 +21,7 @@ local ParseTable = {}
*/
--]]
----------------------------------------
-----------------------------------------
--[[ SUMMARY:
* Split some `str` using a regex `pattern`.
]]
@ -29,8 +29,8 @@ local ParseTable = {}
* `str` => the string to split.
* `pattern` => the regex pattern to split `str` with.
]]
----------------------------------------
local function stringSplit(str, pattern)
-----------------------------------------
local function _stringSplit(str, pattern)
local split = {}
for char in string.gmatch(str, pattern) do
table.insert(split, char)
@ -38,28 +38,22 @@ local function stringSplit(str, pattern)
return split
end
--------------------------------
---------------------------------
--[[ SUMMARY:
* Reverse the elements of some table.
]]
--[[ PARAMS:
* `tbl` => the table to reverse.
]]
--------------------------------
local function tableReverse(tbl)
local i = 1
local halfway = math.floor(#tbl / 2)
while i <= halfway do
-- get the other end of the dict
local j = #tbl + 1 - i
-- copy the value to a placeholder
local placeholder = tbl[j]
-- swap the values
tbl[j] = tbl[i]
tbl[i] = placeholder
-- increment
i = i + 1
---------------------------------
local function _tableReverse(tbl)
local reversed = {}
local i = #tbl
while i > 0 do
table.insert(reversed, tbl[i])
i = i - 1
end
return reversed
end
--[[
@ -82,7 +76,7 @@ ParseTable.CR = 13
function ParseTable.new(userTable)
local parseTable = {}
----------------------------
--------------------------------
--[[ SUMMARY:
* Get a value from this `ParseTable`.
]]
@ -94,9 +88,9 @@ function ParseTable.new(userTable)
* `table` => when the `key` partially mathes.
* `false` => when `key` is not ANYWHERE.
]]
----------------------------
--------------------------------
function parseTable:get(keyDict)
local function parseGet(dict, splitKey)
local function _parseGet(dict, splitKey)
--[[ Get the next character in the combo string. ]]
local k = ''
@ -117,7 +111,7 @@ function ParseTable.new(userTable)
if val[ParseTable.CR] and #splitKey < 1 then
return val
else
return parseGet(val, splitKey)
return _parseGet(val, splitKey)
end
elseif valType == globals.TYPE_STR and #splitKey < 1 then
return val
@ -127,11 +121,11 @@ function ParseTable.new(userTable)
end
--[[ Reverse the dict. ]]
tableReverse(keyDict)
local reversed = _tableReverse(keyDict)
--[[ Get return value. ]]
-- run the inner recursive function in order to return the desired result
return parseGet(self, keyDict)
return _parseGet(self, reversed)
end
----------------------------------------
@ -145,9 +139,9 @@ function ParseTable.new(userTable)
----------------------------------------
function parseTable:parsePut(key, value)
-- Internal recursion function.
local function update(dict, splitKey) -- †
local function _update(dict, splitKey) -- †
-- Get the next character in the table.
local k = api.nvim_eval("char2nr('" .. table.remove(splitKey) .. "')")
local k = string.byte(table.remove(splitKey))
-- If there are still kacters left in the key.
if #splitKey > 0 then
@ -159,8 +153,8 @@ function ParseTable.new(userTable)
dict[k] = {[ParseTable.CR] = dict[k]}
end
-- run update() again
update(dict[k], splitKey)
-- run _update() again
_update(dict[k], splitKey)
-- If dict[k] is a pre-existing table, don't clobber the table— clobber the `CR` value.
elseif type(dict[k]) == globals.TYPE_TBL then
dict[k][ParseTable.CR] = value
@ -171,7 +165,7 @@ function ParseTable.new(userTable)
end -- ‡
-- Run the recursive function.
update(self, stringSplit(
_update(self, _stringSplit(
string.reverse(key), '.'
))
end

@ -25,19 +25,38 @@ mode.ParseTable = require('libmodal/src/mode/ParseTable')
*/
--]]
local TIMEOUT_CHAR = 'ø'
local TIMEOUT_NR = api.nvim_eval("char2nr('" .. TIMEOUT_CHAR .. "')")
local TIMEOUT_LEN = api.nvim_get_option('TIMEOUT_LEN')
local _TIMEOUT_CHAR = 'ø'
local _TIMEOUT_NR = string.byte(_TIMEOUT_CHAR)
local _TIMEOUT_LEN = api.nvim_get_option('timeoutlen')
----------------------------------------
--[[ SUMMARY:
* Reset libmodal's internal counter of user input to default.
]]
----------------------------------------
local function clearLocalInput(modeName)
local function _clearLocalInput(modeName)
vars.input.instances[modeName] = {}
end
----------------------------------------------
--[[ SUMMARY:
* Update the floating window with the latest user input.
]]
--[[ PARAMS:
* `modeName` => the name of the mode.
]]
----------------------------------------------
local function _updateFloatingWindow(modeName)
local uinput = {}
for _, v in ipairs(vars.input.instances[modeName]) do
table.insert(uinput, string.char(v))
end
api.nvim_buf_set_lines(
vars.buffers.instances[modeName],
0, 1, true, {table.concat(uinput)}
)
end
------------------------------------
--[[ SUMMARY:
* Parse the `comboDict` and see if there is any command to execute.
@ -46,7 +65,7 @@ end
* `modeName` => the name of the mode that is currently active.
]]
------------------------------------
local function comboSelect(modeName)
local function _comboSelect(modeName)
-- Stop any running timers
if vars.timer.instances[modeName] then
vars.timer.instances[modeName]:stop()
@ -72,23 +91,24 @@ local function comboSelect(modeName)
local clearInput = false
-- if there was no matching command
if commandType == false then clearInput = true
if cmd == false then clearInput = true
-- The command was a table, meaning that it MIGHT match.
elseif commandType == globals.TYPE_TBL then
-- Create a new timer
vars.timer.instances[modeName] = vim.loop.new_timer()
-- start the timer
vars.timer.instances[modeName]:start(TIMEOUT_LEN, 0,
vim.schedule_wrap(function()
vars.timer.instances[modeName]:start(
_TIMEOUT_LEN, 0, vim.schedule_wrap(function()
-- Send input to interrupt a blocking `getchar`
api.nvim_feedkeys(TIMEOUT_CHAR, '', false)
api.nvim_feedkeys(_TIMEOUT_CHAR, '', false)
-- if there is a command, execute it.
if cmd[mode.ParseTable.CR] then
api.nvim_command(cmd[mode.ParseTable.CR])
end
-- clear input
clearLocalInput(modeName)
_clearLocalInput(modeName)
_updateFloatingWindow(modeName)
end)
)
-- The command was an actual vim command.
@ -98,11 +118,12 @@ local function comboSelect(modeName)
end
if clearInput then
clearLocalInput(modeName)
_clearLocalInput(modeName)
end
_updateFloatingWindow(modeName)
end
-------------------------------------------------
------------------------------------------------
--[[ SUMMARY:
* Set the initial values used for parsing user input as combos.
]]
@ -110,24 +131,103 @@ end
* `modeName` => the name of the mode being initialized.
* `comboTable` => the table of combos being initialized.
]]
-------------------------------------------------
local function initCombos(modeName, comboTable)
------------------------------------------------
local function _initCombos(modeName, comboTable)
-- Placeholder for timeout value.
local doTimeout = nil
-- Read the correct timeout variable.
if api.nvim_exists('g', vars.timeout.name(modeName)) then
if api.nvim_exists('g', vars.timeout:name(modeName)) then
doTimeout = vars.nvim_get(vars.timeout, modeName)
else
doTimeout = vars.libmodalTimeout
end
else doTimeout = vars.libmodalTimeout end
-- Assign the timeout variable according to `doTimeout`
vars.timeout.instances[modeName] = doTimeout
-- create a floating window
local buf = api.nvim_create_buf(false, true)
vars.buffers.instances[modeName] = buf
vars.windows.instances[modeName] = api.nvim_eval(
'libmodal#WinOpen(' .. buf .. ')'
)
-- Build the parse tree.
vars.combos.instances[modeName] = mode.ParseTable.new(comboTable)
-- Initialize the input history variable.
clearLocalInput(modeName)
_clearLocalInput(modeName)
end
-----------------------------------------------------
--[[ SUMMARY:
* Remove variables used for a mode.
]]
--[[ PARAMS:
* `modeName` => the name of the mode.
* `winState` => the window state prior to mode activation.
]]
-----------------------------------------------------
local function _modeEnterTeardown(modeName, winState)
if vars.windows.instances[modeName] then
api.nvim_win_close(
vars.windows.instances[modeName], false
)
end
for _, v in pairs(vars) do
if type(v) == globals.TYPE_TBL and v.instances[modeName] then
v.instances[modeName] = nil
end
end
api.nvim_command("mode | echo '' | call garbagecollect()")
winState:restore()
end
--------------------------------------------------------------------------------
--[[ SUMMARY:
* Loop an initialized `mode`.
]]
--[[ PARAMS:
* `handleExitEvents` => whether or not to automatically exit on `<Esc>` press.
* `indicator` => the indicator for the mode.
* `modeInstruction` => the instructions for the mode.
* `modeName` => the name of the `mode`.
]]
--[[ RETURNS:
* `boolean` => whether or not the mode should continue
]]
--------------------------------------------------------------------------------
local function _modeLoop(handleExitEvents, indicator, modeInstruction, modeName)
-- If the mode is not handling exit events automatically and the global exit var is true.
if not handleExitEvents and globals.isTrue(
vars.nvim_get(vars.exit, modeName)
) then return false end
-- Echo the indicator.
api.nvim_lecho(indicator)
-- Capture input.
local uinput = api.nvim_input()
-- Return if there was a timeout event.
if uinput == _TIMEOUT_NR then
return true
end
-- Set the global input variable to the new input.
vars.nvim_set(vars.input, modeName, uinput)
-- Make sure that the user doesn't want to exit.
if handleExitEvents and uinput == globals.ESC_NR then
return false
-- If the second argument was a dict, parse it.
elseif type(modeInstruction) == globals.TYPE_TBL then
_comboSelect(modeName)
-- If the second argument was a function, execute it.
else modeInstruction() end
return true
end
------------------------
@ -157,61 +257,32 @@ function mode.enter(...)
-- Determine whether or not this function should handle exiting automatically.
local handleExitEvents = true
if #args > 2 then
handleExitEvents = args[3] == true
handleExitEvents = globals.isFalse(args[3])
end
-- Determine whether a callback was specified, or a combo table.
if type(args[2]) == globals.TYPE_TBL then
initCombos(modeName, args[2])
_initCombos(modeName, args[2])
end
--[[ MODE LOOP. ]]
local continueMode = true
while continueMode do
while continueMode == true do
-- Try (using pcall) to use the mode.
local noErrors = pcall(function()
-- If the mode is not handling exit events automatically and the global exit var is true.
if not handleExitEvents and vars.nvim_get(vars.exit, modeName) then
continueMode = false
return
end
-- Echo the indicator.
api.nvim_lecho(indicator)
-- Capture input.
local uinput = api.nvim_input()
-- Return if there was a timeout event.
if uinput == TIMEOUT_NR then return end
-- Set the global input variable to the new input.
vars.nvim_set(vars.input, modeName, uinput)
-- Make sure that the user doesn't want to exit.
if handleExitEvents and uinput == globals.ESC_NR then
continueMode = false
return
-- If the second argument was a dict, parse it.
elseif type(args[2]) == globals.TYPE_TBL then
comboSelect(modeName)
-- If the second argument was a function, execute it.
else args[2]() end
end)
local noErrors = true
noErrors, continueMode = pcall(_modeLoop,
handleExitEvents, indicator, args[2], modeName
)
-- If there were errors, handle them.
if not noErrors then
utils.showError()
if noErrors == false then
utils.showError(continueMode)
continueMode = false
end
end
--[[ TEARDOWN. ]]
api.nvim_redraw()
api.nvim_echo('')
api.nvim_command('call garbagecollect()')
winState:restore()
_modeEnterTeardown(modeName, winState)
end
--[[

@ -30,10 +30,9 @@ local Indicator = {}
--------------------------------
function Indicator.new(modeName)
return {
Entry.new('LibmodalStar', '*'),
Entry.new( 'None', ' ' ),
Entry.new('LibmodalPrompt', '-- '),
Entry.new( 'LibmodalPrompt', tostring(modeName) ),
Entry.new('None', ' > '),
Entry.new('LibmodalPrompt', ' --'),
}
end

@ -21,8 +21,7 @@ local api = vim.api
]]
------------------------
function api.nvim_bell()
local escape = api.nvim_eval("nr2char('" .. 27 .. "')")
api.nvim_command('normal ' .. escape)
api.nvim_command('normal ' .. string.char(27)) -- escape char
end
---------------------------
@ -47,13 +46,34 @@ end
]]
-----------------------------------
function api.nvim_exists(scope, var)
return api.nvim_eval("exists('" .. scope .. ":" .. var .. "')") ~= globals.VIM_FALSE
return api.nvim_eval("exists('" .. scope .. ":" .. var .. "')") == globals.VIM_TRUE
end
-------------------------
--[[ SUMMARY:
* Gets one character of user input, as a number.
]]
--[[ REMARKS:
* This could also be:
```lua
local cmd = {
'"while 1"',
'"let c = getchar(0)"',
'"if empty(c)"',
'"sleep 20m"',
'"else"',
'"echo c"',
'"break"',
'"endif"',
'"endwhile"'
}
return tonumber(vim.api.nvim_eval(
"execute([" .. table.concat(cmd, ',') .. "])"
))
```
However, I'm not sure if it would accidentally affect text.
]]
-------------------------
function api.nvim_input()
return api.nvim_eval('getchar()')
@ -68,15 +88,16 @@ end
* `hlTables` => the tables to echo with highlights.
]]
---------------------------------
local resetHighlight = Entry.new('None', '')
function api.nvim_lecho(hlTables)
api.nvim_redraw()
table.insert(hlTables, resetHighlight)
for _, hlTable in ipairs(hlTables) do
api.nvim_command(
-- `:echohl` the hlgroup and then `:echon` the string.
"echohl " .. hlTable.hl .. " | echon '" .. hlTable.str .. "'"
)
end
-- api.nvim_command('echohl None')
end
--------------------------
@ -104,6 +125,7 @@ function api.nvim_show_err(title, msg)
Entry.new('Error', msg),
Entry.new('Question', '\n[Press any key to return]')
})
api.nvim_command('call getchar()')
end
--[[

@ -17,12 +17,14 @@ utils.vars = require('libmodal/src/utils/vars')
*/
--]]
function utils.showError()
function utils.showError(pcallErr)
utils.api.nvim_bell()
utils.api.nvim_show_err( 'vim-libmodal error',
utils.api.nvim_get_vvar('throwpoint')
.. '\n' ..
utils.api.nvim_get_vvar('exception')
.. '\n' ..
pcallErr
)
end

@ -25,31 +25,33 @@ local vars = {
*/
--]]
-------------------------------
------------------------------------
--[[ SUMMARY:
* Create a new entry in `vars`
]]
--[[ PARAMS:
* `keyName` => the name of the key used to refer to this variable in `vars`.
* `varName` => the name of the variable as it is stored in vim.
]]
-------------------------------
local function new(keyName, varName)
------------------------------------
local function new(keyName)
vars[keyName] = {
-- Instances of variables pertaining to a certain mode.
instances = {},
_varName = 'Mode'
.. string.upper(string.sub(keyName, 0, 1))
.. string.sub(keyName, 2),
-------------------------
---------------------------------
--[[ SUMMARY:
* Get the name of `modeName`s global setting.
]]
--[[ PARAMS:
* `modeName` => the name of the mode.
]]
-------------------------
name = function(modeName)
return modeName .. varName
---------------------------------
name = function(__self, modeName)
return modeName .. __self._varName
end,
}
end
@ -64,11 +66,11 @@ end
]]
------------------------------------
function vars.nvim_get(var, modeName)
return api.nvim_get_var(var.name(modeName))
return api.nvim_get_var(var:name(modeName))
end
function vars.nvim_set(var, modeName, val)
api.nvim_set_var(var.name(modeName), val)
api.nvim_set_var(var:name(modeName), val)
end
--[[
@ -77,11 +79,13 @@ end
*/
--]]
new('combos' , 'ModeCombos' )
new('exit' , 'ModeExit' )
new('input' , 'ModeInput' )
new('timeout' , 'ModeTimeout')
new('timer' , 'ModeTimer' )
new('buffers')
new('combos' )
new('exit' )
new('input' )
new('timeout')
new('timer' )
new('windows')
--[[
/*

Loading…
Cancel
Save