--============================================================================= -- prompt.lua --- prompt api for spacevim -- Copyright (c) 2016-2023 Wang Shidong & Contributors -- Author: Wang Shidong < wsdjeg@outlook.com > -- URL: https://spacevim.org -- License: GPLv3 --============================================================================= local Key = require('spacevim.api').import('vim.keys') local M = {} M.__cmp = require('spacevim.api').import('vim.compatible') M.__vim = require('spacevim.api').import('vim') M._keys = { close = Key.t(''), } M._prompt = { mpt = '==>', cursor_begin = '', cursor_char = '', cursor_end = '', } M._function_key = {} M._quit = true M._handle_fly = '' M._onclose = '' M._oninputpro = '' function M.open() local srl = vim.o.ruler vim.o.ruler = false M._quit = false M._build_prompt() if M.__cmp.fn.empty(M._prompt.cursor_begin) == 0 then M._handle_input(M._prompt.cursor_begin) else M._handle_input() end vim.o.ruler = srl end function M._c_r_mode_off(timer) M._c_r_mode = false end function M._handle_input(...) local argv = { ... } local begin = argv[1] or '' if begin ~= '' then if type(M._oninputpro) == 'function' then M._oninputpro() end if type(M._handle_fly) == 'function' then M._handle_fly(M._prompt.cursor_begin .. M._prompt.cursor_char .. M._prompt.cursor_end) end M._build_prompt() end M._c_r_mode = false while not M._quit do local char = M.__vim.getchar() if M._function_key[char] ~= nil then local ok, rst = pcall(M._function_key[char]) if not ok then print(rst) end goto continue end if M._c_r_mode then if char:match('^[%w":+/]$') then local reg = '@' .. char local paste = vim.fn.get(vim.fn.split(vim.fn.eval(reg), '\n'), 0, '') M._prompt.cursor_begin = M._prompt.cursor_begin .. paste M._prompt.cursor_char = vim.fn.matchstr(M._prompt.cursor_end, '.$') M._c_r_mode = false M._build_prompt() else M._c_r_mode = false goto continue end elseif char == Key.t('') then M._c_r_mode = true vim.fn.timer_start(2000, M._c_r_mode_off) M._build_prompt() goto continue elseif char == Key.t('') then M._prompt.cursor_begin = M._prompt.cursor_begin .. M._prompt.cursor_char M._prompt.cursor_char = M.__cmp.fn.matchstr(M._prompt.cursor_end, '^.') M._prompt.cursor_end = M.__cmp.fn.substitute(M._prompt.cursor_end, '^.', '', 'g') M._build_prompt() goto continue elseif char == Key.t('') then if M._prompt.cursor_begin ~= '' then M._prompt.cursor_end = M._prompt.cursor_char .. M._prompt.cursor_end M._prompt.cursor_char = vim.fn.matchstr(M._prompt.cursor_begin, '.$') M._prompt.cursor_begin = vim.fn.substitute(M._prompt.cursor_begin, '.$', '', 'g') M._build_prompt() end goto continue elseif char == Key.t('') then M._prompt.cursor_begin = M.__cmp.fn.substitute(M._prompt.cursor_begin, [[[^\ .*]\+\s*$]], '', 'g') M._build_prompt() elseif char == Key.t('') or char == Key.t('') then M._prompt.cursor_end = M.__cmp.fn.substitute( M._prompt.cursor_begin .. M._prompt.cursor_char .. M._prompt.cursor_end, '^.', '', 'g' ) M._prompt.cursor_char = M.__cmp.matchstr(M._prompt.cursor_begin, '^.') M._prompt.cursor_begin = '' M._build_prompt() goto continue elseif char == Key.t('') or char == Key.t('') then M._prompt.cursor_begin = M._prompt.cursor_begin .. M._prompt.cursor_char .. M._prompt.cursor_end M._prompt.cursor_char = '' M._prompt.cursor_end = '' M._build_prompt() goto continue elseif char == Key.t('') then M._prompt.cursor_begin = '' M._build_prompt() elseif char == Key.t('') then M._prompt.cursor_char = '' M._prompt.cursor_end = '' M._build_prompt() elseif char == Key.t('') then M._prompt.cursor_begin = vim.fn.substitute(M._prompt.cursor_begin, '.$', '', 'g') M._build_prompt() elseif (type(M._keys.close) == 'string' and char == M._keys.close) or (type(M._keys.close) == 'table' and vim.fn.index(M._keys.close, char) > -1) then M.close() break elseif char == Key.t('') or char == Key.t('') or vim.fn.char2nr(char) == 128 then goto continue else M._prompt.cursor_begin = M._prompt.cursor_begin .. char M._build_prompt() end if type(M._oninputpro) == 'function' then M._oninputpro() end if type(M._handle_fly) == 'function' then M._handle_fly(M._prompt.cursor_begin .. M._prompt.cursor_char .. M._prompt.cursor_end) end ::continue:: end end function M._build_prompt() local ident = M.__cmp.fn['repeat'](' ', M.__cmp.win_screenpos(0)[2] - 1) vim.cmd('redraw') vim.api.nvim_echo({ { ident .. M._prompt.mpt, 'Comment' }, { M._prompt.cursor_begin, 'None' }, { M._prompt.cursor_char, 'Wildmenu' }, { M._prompt.cursor_end, 'None' }, { '_', 'Comment' }, }, false, {}) end function M._clear_prompt() M._prompt = { mpt = M._prompt.mpt, cursor_begin = '', cursor_char = '', cursor_end = '', } end function M.close() if type(M._onclose) == 'function' then M._onclose() end M._clear_prompt() M._quit = true end return M