lemmy-help is a emmylua parser as well as a CLI which takes that parsed tree and converts it into vim help docs.

Overview

🤝 lemmy-help

Everyone needs help, so lemmy-help you

lemmy-help

What?

lemmy-help is a emmylua parser as well as a CLI which takes that parsed tree and converts it into vim help docs.

Installation

  • Using cargo
cargo install lemmy-help --features=cli
  • Arch Linux
# Using yay
yay -S lemmy-help

# Using paru
paru -S lemmy-help
  • Using releases

Check out the release page for prebuild binaries available for different operating systems.

Emmylua

To properly generate docs you should follow emmylua spec. The parser is capable of parsing most (not all) of the emmylua syntax. You can read the following doc which can give you the idea on how to properly write emmylua comments.

Usage

Using the CLI is simple just give it the path to the lua files; it will parse them and prints the help doc to stdout

NOTE: The order of parsing + rendering is same as in which they are defined

doc.txt">
lemmy-help \
    "/path/to/first/file" \
    "/path/to/second/file" \
    "/path/to/third/file" > doc.txt

Credits

Comments
  • Private field makes a field a public function

    Private field makes a field a public function

    I'm trying to switch to 0.8.0, but I have the following issue, I have a class with the following:

    ---@class registers
    ---@field options options
    ---@field private _mode string
    

    When I generate the documentation, I get this:

    registers._mode()                                              *registers._mode*
    
    opened by tversteeg 12
  • Module identifier replacement

    Module identifier replacement

    Context: I set up modules like so:

    local M = {}
    
    -- add stuff to M
    -- like:
    function M.something()
        print('something')
    end
    
    return M
    

    So when I run the CLI on it, it outputs like:

    M.something()                                          *M.something*
    

    Would there be a way to replace the text M in this case with require('module.path') for clarity? Could be a simple regex replace or something?

    I guess my question is, what's the best way to generate full API docs spread across multiple modules? For context, I'm trying to generate API docs for my legendary.nvim plugin (issue here: https://github.com/mrjones2014/legendary.nvim/issues/106)

    feature 
    opened by mrjones2014 11
  • feat: language support in `---@usage`

    feat: language support in `---@usage`

    ~~tl;dr: vimdoc syntax for language support in code-block is experimental and also not backward compatible. So, this might get delayed until nvim 0.9 is released.~~ https://github.com/numToStr/lemmy-help/pull/65#issuecomment-1364501136


    This adds support for associating a language for ---@usage tag which defaults to lua for every code block unless explicitly defined using the syntax below.

    Emmylua

    • Single line
    ---@usage [lang] `<code>`
    
    • Multiline
    ---@usage [lang] [[
    ---
    ---@usage ]]
    

    Help (vimdoc)

    >{lang}
    
    code...
    
    <
    

    Screenshot

    image

    opened by numToStr 5
  • Optional `---@field`

    Optional `---@field`

    Sorry for bothering you with all the issues, but I found another one, the fields of the class above a function definition get added to the description of the function below:

    ---`require("registers").apply_register({...})`
    ---@class apply_register_options
    ---@field mode? register_mode How the register should be applied. If `nil` then the mode in which the window is opened is used.
    ---@field keep_open_until_keypress? boolean If `true`, keep the window open until another key is pressed, only applicable when the mode is `"motion"`.
    
    ---Apply the specified register.
    ---@param options? callback_options|apply_register_options Options for firing the callback.
    ---@return function callback Function that can be used to pass to configuration options with callbacks.
    ---@usage [[
    ---require("registers").setup({
    ---    bind_keys = {
    ---        -- Always paste the register when selecting with Enter
    ---        return_key = require("registers").apply_register({ mode = "paste" }),
    ---    }
    ---})
    ---
    ---require("registers").setup({
    ---    bind_keys = {
    ---        -- When pressing a key of the register, wait for another key press before closing the window
    ---        registers = require("registers").apply_register({ keep_open_until_keypress = true }),
    ---    }
    ---})
    ---@usage ]]
    function registers.apply_register(options)
    

    Gets rendered as:

    apply_register_options                                  *apply_register_options*
        `require("registers").apply_register({...})`
    
    
    registers.apply_register({options?})                  *registers.apply_register*
        @field mode? register_mode How the register should be applied. If `nil` then the mode in which the window is opened is used.
        @field keep_open_until_keypress? boolean If `true`, keep the window open until another key is pressed, only applicable when the mode is `"motion"`.
        Apply the specified register.
    
        Parameters: ~
            {options?}  (callback_options|apply_register_options)  Options for firing the callback.
    
        Returns: ~
            {function}  Function that can be used to pass to configuration options with callbacks.
    
        Usage: ~
            >
                require("registers").setup({
                    bind_keys = {
                        -- Always paste the register when selecting with Enter
                        return_key = require("registers").apply_register({ mode = "paste" }),
                    }
                })
    
                require("registers").setup({
                    bind_keys = {
                        -- When pressing a key of the register, wait for another key press before closing the window
                        registers = require("registers").apply_register({ keep_open_until_keypress = true }),
                    }
                })
            <
    

    This has probably something to do with the parsing of linebreaks?

    feature 
    opened by tversteeg 5
  • Annotations not detected for wrapped function

    Annotations not detected for wrapped function

    Not sure if this is a missing feature or if I'm doing something wrong, but I have some functions that I create using a higher order function. For example:

    local function wrap(arg1, arg2)
      return function(...)
        -- Do work
      end
    end
    
    ---@param foo string
    ---@param bar integer
    M.exported_fn = wrap('a', 'b')
    

    In this example, I can't get exported_fn to be picked up by lemmy-help. Is there something else I should be doing to get it to detect properly?

    enhancement 
    opened by stevearc 5
  • Add support for private fields (by not emitting them)

    Add support for private fields (by not emitting them)

    If a field is marked private I think it'd be nice if they weren't emitted at all.

    Right now it seems marking them as such via e.g.:

    --- An individual pin.
    ---@class Pin
    ---@field id string @a label to identify the pin
    ---@field private __data_element Element
    ---@field private __element Element
    ---@field private __extmark number
    ---@field private __extmark_buf number
    

    is misparsed as the field name:

    Pin                                                                        *Pin*
    
    
        Fields: ~
            {id}       (string)                @a label to identify the pin
            {private}  (__data_element)        Element
            {private}  (__element)             Element
            {private}  (__extmark)             number
            {private}  (__extmark_buf)         number
    
    feature good first issue 
    opened by Julian 5
  • @field in @class stops working in 0.7

    @field in @class stops working in 0.7

    When I migrate from 0.6 to 0.7 the @field lines don't show up in the generated help anymore. Here is an example of a migration commit from 0.6 to 0.7, as you can see a lot disappears without me changing the annotations. I can also reproduce this locally.

    opened by tversteeg 4
  • Regression on parsing vararg param (...)

    Regression on parsing vararg param (...)

    Hi 👋

    There seems to be a regression I'm not sure is intentional or not when parsing a vararg parameter.

    Example:

    ---DeleteSessionByName deletes sessions given a provided list of paths
    ---@param ... string[]
    function AutoSession.DeleteSessionByName(...)
      local session_paths = {}
    
      for _, name in ipairs { ... } do
        local escaped_session = Lib.escape_dir(name)
        maybe_disable_autosave(escaped_session)
        local session_path = string.format("%s/%s.vim", AutoSession.get_root_dir(), escaped_session)
        Lib.logger.debug("Deleting session", session_path)
        table.insert(session_paths, session_path)
      end
      AutoSession.DeleteSession(unpack(session_paths))
    end
    

    Found in: https://github.com/rmagatti/auto-session/blob/609c952a50ff1d415d79323364e934eba607fce0/lua/auto-session.lua#L613

    Parses to: https://github.com/rmagatti/auto-session/pull/182/files#diff-27d42bba8f6f0166fc94265a6b8117318675825157368bc590c0da01ba3cba94R145

    Instead of: https://github.com/rmagatti/auto-session/pull/182/files#diff-27d42bba8f6f0166fc94265a6b8117318675825157368bc590c0da01ba3cba94L153

    Screenshot 2022-11-16 at 9 46 22 PM enhancement 
    opened by rmagatti 3
  • Walk directories recursively for files

    Walk directories recursively for files

    (Hello! Thanks a ton for investing in writing this kind of thing, it's sorely needed. Hope you don't mind me filing a few minor issues as I try to use it, feel free to close any that aren't planned or helpful obviously, just documenting what I find!)

    When running lemmy-help myplugin/lua/, expecting it to recurse and generate docs for everything it finds, instead one gets a panic:

    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 21, kind: IsADirectory, message: "Is a directory" }', src/cli.rs:26:48
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    zsh: abort      ~/Desktop/lemmy-help lua/
    
    wontfix 
    opened by Julian 3
  • Literal values in the type definition lead to empty docs

    Literal values in the type definition lead to empty docs

    lua-language-server supports defining literals/an sum type inline in the type definition. An example: @param x "foo"|"bar"

    But this seems to break lemmy-help:

    local M = {}
    
    --- Foobar
    ---@param t? "foo"|"bar"
    function M.foo(t)
      print(t)
    end
    
    return M
    

    Results in:

    ❮ lemmy-help -f foo.lua
    M.foo()                                                                  *M.foo*
    
    
    vim:tw=78:ts=8:noet:ft=help:norl:
    

    image

    Compared with a regular type definition:

    local M = {}
    
    --- Foobar
    ---@param t? string
    function M.foo(t)
      print(t)
    end
    
    return M
    

    Which works as expected:

    ❮ lemmy-help -f foo.lua
    M.foo({t?})                                                              *M.foo*
         Foobar
    
        Parameters: ~
            {t?}  (string)
    
    
    vim:tw=78:ts=8:noet:ft=help:norl:
    

    The long form also works:

    local M = {}
    
    --- Foobar
    ---@param t? string
    ---|"foo"
    ---|"bar"
    function M.foo(t)
      print(t)
    end
    
    return M
    
    ❮ lemmy-help -f foo.lua
    M.foo({t?})                                                              *M.foo*
         Foobar
    
        Parameters: ~
            {t?}  (string)  |"foo"
                            |"bar"
    
    
    vim:tw=78:ts=8:noet:ft=help:norl:
    
    opened by mfussenegger 2
  • lemmy-help v0.8.0 breaking  `Returns` annotation

    lemmy-help v0.8.0 breaking `Returns` annotation

    ---Completion Pandoc CLI arguments
    ---@return table<string>
    ---@usage [[
    ---vim.api.nvim_create_user_command('PandocBuild', function()
    ---  require('pandoc.render').init()
    ---end, {
    ---   nargs = "*",
    ---   complete = require('pandoc.utils').complete,
    ---})
    ---@usage ]]
    M.complete = function(lead, _, _)
      local results = vim.tbl_filter(function(arg)
        return vim.startswith(arg:gsub("^%-+", ""), lead)
      end, vim.tbl_keys(config.types))
    
      return vim.tbl_map(function(arg)
        local format = arg:gsub("^-+", "")
        return config.types[arg] == "flag" and format or format .. "="
      end, results)
    end
    

    Before, generate:

    ================================================================================
    Pandoc Utils                                                      *pandoc.utils*
    
    M.complete()                                             *pandoc.utils.complete*
        Completion Pandoc CLI arguments
    
        Returns: ~
            {table<string>}
    
        Usage: ~
            >
                vim.api.nvim_create_user_command('PandocBuild', function()
                  require('pandoc.render').init()
                end, {
                   nargs = "*",
                   complete = require('pandoc.utils').complete,
                })
            <
    

    Now, v0.8.0:

    ================================================================================
    Pandoc Utils                                                      *pandoc.utils*
    
    M.complete()                                             *pandoc.utils.complete*
        Completion Pandoc CLI arguments
        @return table<string>
    
        Usage: ~
            >
                vim.api.nvim_create_user_command('PandocBuild', function()
                  require('pandoc.render').init()
                end, {
                   nargs = "*",
                   complete = require('pandoc.utils').complete,
                })
            <
    
    
    opened by aspeddro 2
  • Prepend `•` for list items for `---@param` and `---@field`

    Prepend `•` for list items for `---@param` and `---@field`

    This, I believe, is also supported by vimdoc grammar https://github.com/neovim/tree-sitter-vimdoc/blob/61c75058299f3d1cf565697e4073d7b2cc6a6d6c/grammar.js#L146.

    enhancement 
    opened by numToStr 0
  • Local classes are recognized by lemmy-help but their methods aren't

    Local classes are recognized by lemmy-help but their methods aren't

    I've created this file:

    $ cat my_module.lua 
    ---@mod my_module
    local M = {}
    
    ---@class Foo
    M.Foo = {}
    
    function M.Foo:bar()
    end
    
    ---@class Baz
    local Baz = {}
    
    function Baz:qux()
    end
    
    return M
    

    The I ran lemmy-help version 0.10.0 on it:

    $ lemmy-help my_module.lua 
    ================================================================================
                                                                         *my_module*
    
    Foo                                                                        *Foo*
    
    
    M.Foo()                                                                  *M.Foo*
    
    
    Baz                                                                        *Baz*
    
    
    vim:tw=78:ts=8:noet:ft=help:norl:
    

    The Foo class was exported and its method bar was recognized by lemmy-help, but qux did not get an entry even though its class Baz did. Is it because Baz is declared local? But these classes' methods should still get into the docs because users can still get them via functions.

    help wanted 
    opened by idanarye 12
  • Surround types with backticks

    Surround types with backticks

    This will highlight all the types, without taking space of two characters as neovim will hide that via treesitter conceal.

    • Currently
    CommentConfig                                     *comment.config.CommentConfig*
        Plugin's configuration
    
        Fields: ~
            {padding}    (boolean|fun():boolean)  Controls space between the comment
                                                  and the line (default: 'true')
            {sticky}     (boolean)                Whether cursor should stay at the
    
    • Proposed
    CommentConfig                                     *comment.config.CommentConfig*
        Plugin's configuration
    
        Fields: ~
            {padding}    `(boolean|fun():boolean)`  Controls space between the comment
                                                    and the line (default: 'true')
            {sticky}     `(boolean)`                Whether cursor should stay at the
    
    enhancement 
    opened by numToStr 1
  • Support `---@enum`

    Support `---@enum`

    This is very useful in the actual code as we don't have to create separate ---@alias for describing enums but the problem is that we have to parse tables to get all the enum variants

    Reference

    • https://github.com/sumneko/lua-language-server/wiki/Annotations#enum
    • https://github.com/sumneko/lua-language-server/issues/1255#issuecomment-1170870858
    feature 
    opened by numToStr 0
  • JSON

    JSON

    This might be cool. Instead of printing vimdoc we can instead print the whole AST as json so that other tools can walk the AST and do cool stuff with it.

    FLOW

    1. lemmy-help outputs json (flag: --to-json)
    2. User modifies the content (not the structure/AST)
    3. lemmy-help takes that json (flag: --from-json) via stdin and prints vimdoc.

    IDK

    • In case of --from-json, file inputs should be discarded or appended after json?
    feature 
    opened by numToStr 0
Releases(v0.11.0)
Owner
Vikas Raj
I code and eat memes.
Vikas Raj
STKLR is a tool to help you automatically link up named stuff in your rust docs!

_____ _______ _ ___ _____ / ____|__ __| |/ / | | __ \ | (___ | | | ' /| | | |__) | \___ \ | | | < | | | _ / ___

Jer 3 Oct 25, 2022
A fediverse compatible forum and link aggregator. Downstream from Lemmy.

Pangora A fediverse compatible forum and link aggregator. Downstream from Lemmy. About The Project Pangora is a forum and link aggregator. You can pos

Pangora 7 Sep 11, 2023
a terminal user interface for lemmy

Lemmy-Terminal-Viewer Terminal User Interface for lemmy for Linux Terminals (should work in MacOs but i can't test) Install and Usage Linux Download l

Luna 21 Oct 29, 2022
An enhanced search engine just for Lemmy/Fediverse

Please Read If anyone wants to help contribute to this, please feel free to reach out to me. You can obviously find me on Lemmy, mainly https://lemmy.

null 51 Jul 4, 2023
A utility for exporting administrative/moderation statistics from your Lemmy instance's PostgreSQL database to InfluxDB!

Lemmy (Stats) Data Exporter About This Project This project aims to act as a bridge between Lemmy's PostgreSQL database and InfluxDB, primarily to tra

Russell 3 Jul 5, 2023
Vim plugin to quickly parse strings into arrays.

butcher Vim plugin to quickly parse strings into arrays. It is painful to write arrays in any programming language, so butcher makes it easy for you.

null 5 Dec 31, 2021
A CLI tool which can help you automatically kill process of your choice. Useful for freeing up memory and CPU usage!

Quickiller There are always programs such as chrome that keep eating up your resources even when closed! The only way to prevent this is to kill all o

Codingsquirrel 1 Dec 8, 2021
Command-Line program that takes images and produces the copy of the image with a thin frame and palette made of the 10 most frequent colors.

paleatra v.0.0.1 Command-Line program that takes an image and produces the copy of the image with a thin frame and palette made of the 10 most frequen

Beka Modebadze 24 Dec 29, 2022
A CLI tool that converts images to ASCII art.

Rust ASCII Art Converter This Rust tool converts images into ASCII art. It takes an image file as input, resizes it according to specified width and h

TheD24 133 Dec 3, 2023
ddi is a wrapper for dd. It takes all the same arguments, and all it really does is call dd in the background

ddi A safer dd Introduction If you ever used dd, the GNU coreutil that lets you copy data from one file to another, then you may have encountered a ty

Tomás Ralph 80 Sep 8, 2022
`rusty_regex` takes an input string and produces a `regex` string representing what was provided.

rusty_regex This project provides a binary that takes an input string, and preps it for regex usage, effectively replacing known generics and producin

Chris Speakes 2 Dec 31, 2022
Is the GIL seeing someone else? How's about repetitively calling and seeing how long it takes to answer?

GIL Knocker pip install gilknocker When you thought the GIL was available, and you find yourself suspecting it might be spending time with another. Yo

Miles Granger 4 Jan 18, 2023
Count your code by tokens, types of syntax tree nodes, and patterns in the syntax tree. A tokei/scc/cloc alternative.

tcount (pronounced "tee-count") Count your code by tokens, types of syntax tree nodes, and patterns in the syntax tree. Quick Start Simply run tcount

Adam P. Regasz-Rethy 48 Dec 7, 2022
Traversal of tree-sitter Trees and any arbitrary tree with a TreeCursor-like interface

tree-sitter-traversal Traversal of tree-sitter Trees and any arbitrary tree with a TreeCursor-like interface. Using cursors, iteration over the tree c

Sebastian Mendez 12 Jan 8, 2023
As-tree - Print a list of paths as a tree of paths 🌳

as-tree Print a list of paths as a tree of paths. For example, given: dir1/foo.txt dir1/bar.txt dir2/qux.txt it will print: . ├── dir1 │ ├── foo.tx

Jake Zimmerman 396 Dec 10, 2022
A device-tree source parser, analyzer and language server.

Ginko A device-tree source parser, analyzer and language server. The main goal of this project is to make working with device-trees easy. For example,

Lukas Scheller 4 Feb 28, 2024
A CLI tool to get help with CLI tools 🐙

A CLI tool to get help with CLI tools ?? halp aims to help find the correct arguments for command-line tools by checking the predefined list of common

Orhun Parmaksız 566 Apr 16, 2023
A user-friendly TUI for secure file transfers, with arrow-key and VIM-style navigation

gsftp SFTP with an interactive text-based user interface (TUI). Transfer files through an encrypted connection with a visual interface, so you can see

Ben Jiron 3 Jul 7, 2022
A structure editor for a simple functional programming language, with Vim-like shortcuts and commands.

dilim A structure editor for a simple functional programming language, with Vim-like shortcuts and commands. Written in Rust, using the Yew framework,

Joomy Korkut 6 Nov 18, 2022