neogen icon indicating copy to clipboard operation
neogen copied to clipboard

Added snippet_engine parameter

Open ColinKennedy opened this issue 1 year ago • 0 comments

A (sort of) continuation of https://github.com/danymat/neogen/pull/201

I integrate Neogen + LuaSnip into one with this snippet:

Click to expand
--- Create LuaSnip snippets that can auto-expand Neogen's snippet engine.
---
--- @module 'my_custom.snippets._python_docstring'
---

local snippet_helper = require("my_custom.utilities.snippet_helper")
local luasnip = require("luasnip")
local snippet = luasnip.s
local dynamicNode = require("luasnip.nodes.dynamicNode").D
local snippetNode = require("luasnip.nodes.snippet").SN

--- Create a dynamic LuaSnip snippet-node whose contents are created by Neogen.
---
--- @param section string The Neogen section name to create a LuaSnip snippet.
--- @return LuaSnip.DynamicNode # The created node.
---
local function _make_section_snippet_node(section)
    return dynamicNode(
        1,
        function(args)
            local neogen = require("neogen")

            local lines = neogen.generate(
                -- TODO: Provide an explicit snippet engine (once there's an
                -- argument for it).
                {return_snippet = true, sections = {section}, snippet_engine = "luasnip"}
            )

            local nodes = luasnip.parser.parse_snippet(
                nil,
                table.concat(lines, "\n"),
                { trim_empty = false, dedent = true }
            )

            return snippetNode(nil, nodes)
        end
    )
end

--- Create a LuaSnip snippet for some `section`. Run it when `trigger` is found.
---
--- @param trigger string
---     A word that LuaSnip uses to decide when the snippet should run. e.g. `"Args:"`.
--- @param section string
---     The parts of a docstring that Neogen needs to generate.
--- @return LuaSnip.Snippet
---     The generated auto-complete snippet.
---
local function _make_section_snippet(trigger, section)
    return snippet(
        {
            trig=trigger,
            docstring=string.format(
                'Auto-fill a docstring\'s "%s" section, using Neogen',
                trigger
            ),
        },
        {
            _make_section_snippet_node(section)
        },
        {
            show_condition = function()
                return (
                    snippet_helper.in_docstring()
                    and snippet_helper.is_source_beginning(trigger)
                )
            end
        }
    )
end

return {
    _make_section_snippet("Args:", "parameter"),
    _make_section_snippet("Raises:", "throw"),
    _make_section_snippet("Returns:", "return"),
    _make_section_snippet("Yields:", "yield"),
}

(This later gets included to `luasnip.add_snippets("python", those_snippets_above)

With this, I can just write docstrings naturally like Args: and Neogen auto-expands the arguments for me.

The end result looks like this:

https://github.com/user-attachments/assets/3e44d2a7-54dd-4509-abec-a0f556467c85

https://github.com/user-attachments/assets/6b762a80-193c-474a-bec5-2079c3ff208a

(Sorry the recordings are a bit messed up)

Anyway being able to explicitly ask for the snippet engine means that a user can default to a different snippet engine in their configuration but run a different engine on-demand. This is useful as someone who wants to move to native LSP snippets someday.

ColinKennedy avatar Sep 02 '24 23:09 ColinKennedy