Begin prompt implementation

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

@ -1,4 +1,14 @@
let s:winOpenOpts = {
let libmodal#_replacements = [
\ '.', ':', '&', '@', ',', '\\/', '?',
\ '(', ')',
\ '{', '}',
\ '[', ']',
\ '+', '\\*', '\\!', '\\^', '\\>', '\\<', '%', '=',
\ '\\$',
\ '\\'
\]
let libmodal#_winOpenOpts = {
\ 'anchor' : 'SW',
\ 'col' : &columns - 1,
\ 'focusable': v:false,
@ -9,11 +19,56 @@ let s:winOpenOpts = {
\ 'width' : 25,
\}
" SUMMARY:
" * Provide completions for a `libmodal.prompt`.
" PARAMS:
" * `completions` => the list of completions.
" RETURNS:
" * A function that accepts:
" * `argLead` => the current line being edited, stops at the cursor.
" * `cmdLine` => the current line being edited
" * `cursorPos` => the position of the cursor
function! libmodal#CreateCompletionsProvider(completions)
function! l:completionsProvider(argLead, cmdLine, cursorPos) abort closure
" replace conjoining characters with spaces.
let l:spacedArgLead = a:argLead
for l:replacement in s:replacements
let l:spacedArgLead = substitute(l:spacedArgLead, l:replacement, ' ', 'g')
endfor
" split the spaced version of `argLead`.
let l:splitArgLead = split(splitArgLead, ' ')
" make sure the user is in a position were this function
" will provide accurate completions.
if len(splitArgLead) > 1 | return v:none | end
" get the word selected by the user.
let l:word = l:splitArgLead[1]
" get all matches from the completions list.
let l:completions = []
for l:completion in s:completions
if stridx(l:completion, l:word) > -1
let l:completions = add(l:completions, l:completion)
endif
endfor
return l:completions
endfunction
return funcref('l:completionsProvider')
endfunction
" PLACEHOLDER.
function! libmodal#Enter(...) abort
echo ''
endfunction
" PLACEHOLDER.
function! libmodal#Prompt(...) abort
echo ''
endfunction
" SUMMARY:
" * Open a floating window using native vimscript.
" REMARKS:
@ -24,10 +79,5 @@ endfunction
" 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 ''
return nvim_open_win(a:bufHandle, 0, libmodal#_winOpenOpts)
endfunction

@ -6,6 +6,7 @@
local api = vim.api
local globals = require('libmodal/src/base/globals')
local strings = require('libmodal/src/utils/strings')
--[[
/*
@ -21,23 +22,6 @@ local ParseTable = {}
*/
--]]
-----------------------------------------
--[[ SUMMARY:
* Split some `str` using a regex `pattern`.
]]
--[[ PARAMS:
* `str` => the string to split.
* `pattern` => the regex pattern to split `str` with.
]]
-----------------------------------------
local function _stringSplit(str, pattern)
local split = {}
for char in string.gmatch(str, pattern) do
table.insert(split, char)
end
return split
end
---------------------------------
--[[ SUMMARY:
* Reverse the elements of some table.
@ -90,7 +74,7 @@ function ParseTable.new(userTable)
]]
--------------------------------
function parseTable:get(keyDict)
local function _parseGet(dict, splitKey)
local function parseGet(dict, splitKey)
--[[ Get the next character in the combo string. ]]
local k = ''
@ -111,7 +95,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
@ -125,7 +109,7 @@ function ParseTable.new(userTable)
--[[ Get return value. ]]
-- run the inner recursive function in order to return the desired result
return _parseGet(self, reversed)
return parseGet(self, reversed)
end
----------------------------------------
@ -139,7 +123,7 @@ 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 = string.byte(table.remove(splitKey))
@ -148,13 +132,13 @@ function ParseTable.new(userTable)
if not dict[k] then
dict[k] = {}
-- If there is a previous command mapping in place
elseif type(dict[k]) == 'string' then
elseif type(dict[k]) == globals.TYPE_STR then
-- Swap the mapping to a `CR`
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
@ -165,7 +149,7 @@ function ParseTable.new(userTable)
end -- ‡
-- Run the recursive function.
_update(self, _stringSplit(
update(self, strings.split(
string.reverse(key), '.'
))
end

@ -203,7 +203,6 @@ local function _modeLoop(handleExitEvents, indicator, modeInstruction, modeName)
vars.nvim_get(vars.exit, modeName)
) then return false end
-- Echo the indicator.
api.nvim_lecho(indicator)
@ -246,7 +245,7 @@ function mode.enter(...)
--[[ SETUP. ]]
-- Create the indicator for the mode.
local indicator = utils.Indicator.new(args[1])
local indicator = utils.Indicator.mode(args[1])
-- Grab the state of the window.
local winState = utils.WindowState.new()

@ -1,3 +1,15 @@
--[[
/*
* IMPORTS
*/
--]]
local globals = require('libmodal/src/base/globals')
local utils = require('libmodal/src/utils')
local api = utils.api
local vars = utils.vars
--[[
/*
* MODULE
@ -12,6 +24,7 @@ local prompt = {}
*/
--]]
--------------------------
--[[ SUMMARY:
* Enter a prompt.
@ -19,10 +32,75 @@ local prompt = {}
--[[ PARAMS:
* `args[1]` => the prompt name.
* `args[2]` => the prompt callback, or mode command table.
* `args[3]` => a completions table.
]]
--------------------------
function prompt.enter(...)
-- get the arguments
local args = {...}
-- create an indicator
local indicator = utils.Indicator.prompt(args[1])
local modeName = string.lower(args[1])
-- get the completion list.
local completions = nil
if type(args[2]) == globals.TYPE_TBL then
-- unload the keys of the mode command table.
completions = {}
local i = 1
for k, _ in pairs(args[2]) do
completions[i] = k
i = i + 1
end
-- assign completions as the custom completions table provided.
elseif #args > 2 then completions = args[3] end
-- make the completions dict vim-compatable
if completions then completions =
'[' .. table.concat(completions, ',') .. ']'
end
local continueMode = true
while continueMode == true do
local noErrors, err = pcall(function()
-- echo the indicator
api.nvim_redraw()
-- compose prompt command
local cmd = "input('" .. indicator .. "', ''"
if completions then cmd =
cmd .. ", 'customlist,funcref(\"libmodal#CreateCompletionsProvider\", ["
.. completions ..
"])'"
end
-- get input from prompt
local uinput = api.nvim_eval(cmd .. ')') -- closing bracket ends beginning 'input('
-- if a:2 is a function then call it.
if string.len(uinput) > 0 then
vars.nvim_set(vars.input, modeName, uinput)
if completions then
if args[2][uinput] then
api.nvim_command(args[2][uinput])
else
api.nvim_show_err('Unknown command.')
end
else
args[2]()
end
else
continueMode = false
end
end)
if noErrors == false then
utils.showError(err)
continueMode = false
end
end
end
--[[
@ -30,5 +108,5 @@ end
* PUBLICIZE MODULE
*/
--]]
return prompt
return prompt

@ -14,28 +14,53 @@ local Entry = require('libmodal/src/utils/Indicator/Entry')
local Indicator = {}
-- highlight group names
local _HL_GROUP_PROMPT = 'LibmodalPrompt'
local _HL_GROUP_STAR = 'LibmodalStar'
local _HL_GROUP_NONE = 'None'
-- `libmodal.mode` `Entry`s.
local _ENTRY_MODE_START = Entry.new(_HL_GROUP_PROMPT, '-- ')
local _ENTRY_MODE_END = Entry.new(_HL_GROUP_PROMPT, ' --')
-- `libmodal.prompt` `Entry`s.
local _ENTRY_PROMPT_START = Entry.new(_HL_GROUP_STAR, '* ')
local _ENTRY_PROMPT_END = Entry.new(_HL_GROUP_PROMPT, ' > ')
--[[
/*
* CLASS `Indicator`
*/
--]]
--------------------------------
---------------------------------
--[[ SUMMARY:
* Create a new `Indicator`.
* Create a new `Indicator` for a mode.
]]
--[[ PARAMS:
* `modeName` => the name of the mode that this `Indicator` is for.
]]
--------------------------------
function Indicator.new(modeName)
---------------------------------
function Indicator.mode(modeName)
return {
Entry.new('LibmodalPrompt', '-- '),
Entry.new( 'LibmodalPrompt', tostring(modeName) ),
Entry.new('LibmodalPrompt', ' --'),
_ENTRY_MODE_START,
Entry.new(_HL_GROUP_PROMPT, tostring(modeName)),
_ENTRY_MODE_END
}
end
-----------------------------------
--[[ SUMMARY:
* Create a new `Indicator` for a prompt.
]]
--[[ PARAMS:
* `modeName` => the name of the mode that this `Indicator` is for.
]]
-----------------------------------
function Indicator.prompt(modeName)
return '* ' .. tostring(modeName) .. ' > '
end
--[[
/*
* PUBLICIZE MODULE

@ -8,8 +8,9 @@ local utils = {}
utils.api = require('libmodal/src/utils/api')
utils.DateTime = require('libmodal/src/utils/DateTime')
utils.Indicator = require('libmodal/src/utils/Indicator')
utils.WindowState = require('libmodal/src/utils/WindowState')
utils.strings = require('libmodal/src/utils/strings')
utils.vars = require('libmodal/src/utils/vars')
utils.WindowState = require('libmodal/src/utils/WindowState')
--[[
/*

@ -0,0 +1,22 @@
local strings = {}
------------------------------------
--[[ SUMMARY:
* Split some `str` using a regex `pattern`.
]]
--[[ PARAMS:
* `str` => the string to split.
* `pattern` => the regex pattern to split `str` with.
]]
------------------------------------
function strings.split(str, pattern)
local split = {}
local i = 1
for char in string.gmatch(str, pattern) do
split[i] = char
i = i + 1
end
return split
end
return strings
Loading…
Cancel
Save