Skip to content

Commit

Permalink
docs: document functions/objects
Browse files Browse the repository at this point in the history
  • Loading branch information
dcampos committed Dec 27, 2024
1 parent becb4b9 commit 3bb2d09
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 24 deletions.
5 changes: 5 additions & 0 deletions lua/snippy.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ setmetatable(M, {
end,
})

--- Set configuration
--- @param o snippy.Config Global configuration parameters
function M.setup(o)
shared.set_config(o)
require('snippy.mapping').init()
end

--- Set buffer configuration
--- @param bufnr integer Buffer number
--- @param o snippy.BufferConfig Configuration parameters for the current buffer
function M.setup_buffer(bufnr, o)
shared.set_buffer_config(bufnr, o)
end
Expand Down
70 changes: 51 additions & 19 deletions lua/snippy/builder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local shared = require('snippy.shared')
local parser = require('snippy.parser')
local fn = vim.fn

---@type table<string, fun(): string?>
local varmap = {
TM_SELECTED_TEXT = function()
return shared.selected_text
Expand Down Expand Up @@ -99,21 +100,39 @@ local varmap = {
end,
}

local Builder = {}
---@class snippy.Builder Snippet renderer/builder
---@field row integer Current row
---@field col integer Current row
---@field indent string Current indent level
---@field extra_indent string
---@field stops table Tabstops/variables being built
---@field result string Snippet being rendered
local Builder = {
row = 0,
col = 0,
word = '',
indent = '',
extra_indent = '',
}

---@param o table?
---@return snippy.Builder
function Builder.new(o)
local builder = setmetatable(o, { __index = Builder })
local builder = setmetatable(o or {}, { __index = Builder })
builder.stops = {}
builder.result = ''
builder.indent = o.indent or ''
builder.extra_indent = ''
return builder
end

---Adds content to the final result
---@param content string
function Builder:add(content)
self.result = self.result .. content
end

---Evaluates Vimscript code
---@param code string
---@return string # Evaluation result
function Builder:eval_vim(code)
local ok, result = pcall(fn.eval, code)
if ok then
Expand All @@ -126,9 +145,13 @@ function Builder:eval_vim(code)
return result
else
util.print_error(string.format('Invalid eval code `%s` at %d:%d: %s', code, self.row, self.col, result))
return ''
end
end

---Evaluates Lua code
---@param code string
---@return string # Evaluation result
function Builder:eval_lua(code)
local ok, result = pcall(fn.luaeval, code)
if ok then
Expand All @@ -138,17 +161,18 @@ function Builder:eval_lua(code)
elseif tp ~= 'table' and tp ~= 'string' then
result = ''
end
---@cast result string
return result
else
util.print_error(string.format('Invalid eval code `%s` at %d:%d: %s', code, self.row, self.col, result))
return ''
end
end

--- Indents a list of lines.
---
--@param lines table: unindented lines
--@param is_expansion boolean: true during eval/variable expansion
--@returns table: indented lines
---Indents a list of lines
---@param lines string[] Unindented lines
---@param is_expansion boolean True during eval/variable expansion, false otherwise
---@return string[] lines List of indented lines
function Builder:indent_lines(lines, is_expansion)
local new_level
for i, line in ipairs(lines) do
Expand All @@ -168,13 +192,13 @@ function Builder:indent_lines(lines, is_expansion)
return lines
end

--- Appends a sequence of characters to the result.
---
--@param is_expansion boolean: true during eval/variable expansion
--@param text any: text to be appended
---Appends a sequence of characters to the result
---@param text string|string[] Text to be appended
---@param is_expansion? boolean True during eval/variable expansion
function Builder:append_text(text, is_expansion)
local lines = type(text) == 'string' and vim.split(text, '\n', true) or text
lines = self:indent_lines(lines, is_expansion)
---@cast lines string[]
lines = self:indent_lines(lines, is_expansion or false)
self.row = self.row + #lines - 1
if #lines > 1 then
self.col = #lines[#lines] -- fn.strchars(lines[#lines])
Expand All @@ -184,22 +208,24 @@ function Builder:append_text(text, is_expansion)
self:add(table.concat(lines, '\n'))
end

--- Evaluates a variable and possibly its children.
---
--@param variable (string) Variable name.
---Evaluates a variable and possibly its children
---@param variable table Variable node
function Builder:evaluate_variable(variable)
if not varmap[variable.name] then
self:append_text(string.format('$%s', variable.name))
self:append_text(string.format('$%s', variable.name), false)
return
end
local result = varmap[variable.name] and varmap[variable.name](variable.children)
local result = varmap[variable.name] and varmap[variable.name]()
if not result then
self:process_structure(variable.children)
else
self:append_text(result, true)
end
end

---Processes the snippet structure
---@param structure table|string The structure or string to process
---@param parent any Parent node
function Builder:process_structure(structure, parent)
if type(structure) == 'table' then
for _, value in ipairs(structure) do
Expand Down Expand Up @@ -262,6 +288,7 @@ function Builder:process_structure(structure, parent)
end
end

---Adds a final ($0) tabstop if none is found
function Builder:fix_ending()
for _, stop in ipairs(self.stops) do
if stop.id == 0 then
Expand All @@ -274,6 +301,11 @@ function Builder:fix_ending()
)
end

---Renders the snippet to a string
---@param structure table
---@param preview boolean? Whether it is a preview rendering
---@return string result Rendered snippet
---@return table stops List of tabstops
function Builder:build_snip(structure, preview)
self:process_structure(structure)
self:fix_ending()
Expand Down
47 changes: 44 additions & 3 deletions lua/snippy/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ end

-- Public functions

---Complete snippets at the current cursor position
function M.complete()
local col = api.nvim_win_get_cursor(0)[2]
local current_line = api.nvim_get_current_line()
Expand All @@ -261,6 +262,7 @@ function M.complete()
fn.complete(col - #word + 1, choices)
end

---Call this on CompleteDone to expand completed snippets
function M.complete_done()
local completed_item = vim.v.completed_item
log.debug('complete_done', completed_item)
Expand All @@ -286,6 +288,8 @@ function M.complete_done()
end
end

---Returns a list of completion items in the current context
---@return table items
function M.get_completion_items()
local items = {}
local scopes = shared.get_scopes()
Expand All @@ -311,6 +315,9 @@ function M.get_completion_items()
return items
end

---For cutting curently selected text
---@param mode string Currenct selection mode
---@param visual boolean Whether it is a visual selection
function M.cut_text(mode, visual)
local tmpval, tmptype = fn.getreg('x'), fn.getregtype('x')
local keys
Expand Down Expand Up @@ -338,6 +345,8 @@ function M._mirror_stops()
end
end

---Jumps to the previous valid snippet stop
---@return boolean
function M.previous()
local stops = buf.stops
local stop = (buf.current_stop or 0) - 1
Expand All @@ -347,6 +356,8 @@ function M.previous()
return M._jump(stop)
end

---Jumps to the next valid snippet stop
---@return boolean
function M.next()
local stops = buf.stops
local stop = (buf.current_stop or 0) + 1
Expand Down Expand Up @@ -405,7 +416,7 @@ function M._jump(stop)
return true
end

-- Check if the cursor is inside any stop
-- Check if the cursor is inside any stop. Otherwise, clears the current snippet.
function M._check_position()
local stops = buf.stops
local row, col = unpack(api.nvim_win_get_cursor(0))
Expand Down Expand Up @@ -438,6 +449,9 @@ function M._check_position()
buf.clear_state()
end

---Parses a snippet into an internal representation
---@param snippet string|table The snippet to parse (either text or structured)
---@return table parsed The parsed snippet representation
function M.parse_snippet(snippet)
local ok, parsed, pos
local text
Expand All @@ -457,11 +471,15 @@ function M.parse_snippet(snippet)
end
if not ok or pos <= #text then
error("> Error while parsing snippet: didn't parse till the end")
return ''
end
assert(parsed, '> Snippet could not be parsed')
return parsed
end

---Expands a snippet at the current cursor position
---@param snippet string|table The snippet to expand
---@param word string|nil The trigger word that was matched
---@return boolean # True on success, false on failure
function M.expand_snippet(snippet, word)
log.debug('expand_snippet', word, snippet)
local current_line = api.nvim_get_current_line()
Expand Down Expand Up @@ -489,20 +507,28 @@ function M.expand_snippet(snippet, word)
place_stops(stops)
api.nvim_exec_autocmds('User', { pattern = 'SnippyExpanded' })
M.next()
return ''
return true
end

---Returns a string representation of a snippet
---@param snippet string|table The snippet to represent
---@return string # The string representation
function M.get_repr(snippet)
local parsed = M.parse_snippet(snippet)
local builder = Builder.new({ row = 0, col = 0, indent = '', word = '' })
local content, _ = builder:build_snip(parsed, true)
return content
end

---Tries to expand a snippet or advance to the next stop
---@return boolean
function M.expand_or_advance()
return M.expand() or M.next()
end

---Expands a snippet at the current cursor position if possible
---@param auto boolean|nil Whether this is an automatic expansion
---@return boolean
function M.expand(auto)
local word, snippet = get_snippet_at_cursor(auto)
shared.last_char = nil
Expand All @@ -512,6 +538,9 @@ function M.expand(auto)
return false
end

---Checks if a snippet can be expanded at the current position
---@param auto boolean|nil Whether this is an automatic expansion check
---@return boolean
function M.can_expand(auto)
local word, snip = get_snippet_at_cursor(auto)
if word and snip then
Expand All @@ -521,6 +550,9 @@ function M.can_expand(auto)
end
end

---Checks if it's possible to jump in the specified direction
---@param dir integer The direction to check (positive for forward, negative for backward)
---@return boolean
function M.can_jump(dir)
local stops = buf.state().stops
if dir >= 0 then
Expand All @@ -530,10 +562,14 @@ function M.can_jump(dir)
end
end

---Checks if expansion or advancement is possible
---@return boolean
function M.can_expand_or_advance()
return M.can_expand() or M.can_jump(1)
end

---Checks if there is any snippet active
---@return boolean
function M.is_active()
return buf.state().active
end
Expand All @@ -546,6 +582,7 @@ M.readers = {
snipmate_reader,
}

---Loads snippets for the current scopes
function M.read_snippets()
local scopes = shared.get_scopes()
for _, scope in ipairs(scopes) do
Expand All @@ -559,11 +596,15 @@ function M.read_snippets()
end
end

---Clears currently cached snippets
function M.clear_cache()
shared.cache = {}
M._snippets = {}
end

---For completion of snippet file names
---@param prefix string Prefix to find
---@return table results Snippet file names
function M.complete_snippet_files(prefix)
local files = {}
for _, reader in ipairs(M.readers) do
Expand Down
Loading

0 comments on commit 3bb2d09

Please sign in to comment.