panvimdoc icon indicating copy to clipboard operation
panvimdoc copied to clipboard

Is it possible to support function documentation?

Open nanozuki opened this issue 3 years ago • 8 comments

I want to write a vim doc with many (lua) functions for neovim. Is it possible to generate a doc like this?

In https://neovim.io/doc/user/api.html

  • a simple example
nvim_win_get_tabpage({window})                        *nvim_win_get_tabpage()*
                Gets the window tabpage

                Parameters:  
                    {window}  Window handle, or 0 for current window

                Return:  
                    Tabpage that contains the window
  • a complex example
nvim_create_autocmd({event}, {*opts})                  *nvim_create_autocmd()*
                Create an |autocommand|

                The API allows for two (mutually exclusive) types of actions
                to be executed when the autocommand triggers: a callback
                function (Lua or Vimscript), or a command (like regular
                autocommands).

                Example using callback:  
                    -- Lua function
                    local myluafun = function() print("This buffer enters") end

                    -- Vimscript function name (as a string)
                    local myvimfun = "g:MyVimFunction"

                    vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
                      pattern = {"*.c", "*.h"},
                      callback = myluafun,  -- Or myvimfun
                    })
 

                Example using command:  
                    vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
                      pattern = {"*.c", "*.h"},
                      command = "echo 'Entering a C or C++ file'",
                    })
 

                Example values for pattern:  
                  pattern = "*.py"
                  pattern = { "*.py", "*.pyi" }
 

                Example values for event:  
                  "BufWritePre"
                  {"CursorHold", "BufWritePre", "BufWritePost"}
 

                Parameters:  
                    {event}  (string|array) The event or events to register
                             this autocommand
                    {opts}   Dictionary of autocommand options:
                             • group (string|integer) optional: the
                               autocommand group name or id to match against.
                             • pattern (string|array) optional: pattern or
                               patterns to match against |autocmd-pattern|.
                             • buffer (integer) optional: buffer number for
                               buffer local autocommands |autocmd-buflocal|.
                               Cannot be used with {pattern}.
                             • desc (string) optional: description of the
                               autocommand.
                             • callback (function|string) optional: if a
                               string, the name of a Vimscript function to
                               call when this autocommand is triggered.
                               Otherwise, a Lua function which is called when
                               this autocommand is triggered. Cannot be used
                               with {command}. Lua callbacks can return true
                               to delete the autocommand; in addition, they
                               accept a single table argument with the
                               following keys:
                               • id: (number) the autocommand id
                               • event: (string) the name of the event that
                                 triggered the autocommand |autocmd-events|
                               • group: (number|nil) the autocommand group id,
                                 if it exists
                               • match: (string) the expanded value of
                                 |<amatch>|
                               • buf: (number) the expanded value of |<abuf>|
                               • file: (string) the expanded value of
                                 |<afile>|

                             • command (string) optional: Vim command to
                               execute on event. Cannot be used with
                               {callback}
                             • once (boolean) optional: defaults to false. Run
                               the autocommand only once |autocmd-once|.
                             • nested (boolean) optional: defaults to false.
                               Run nested autocommands |autocmd-nested|.

                Return:  
                    Integer id of the created autocommand.

                See also:  
                    |autocommand|
                    |nvim_del_autocmd()|

For legacy viml function, there are also a example, in https://neovim.io/doc/user/builtin.html

getbufvar({buf}, {varname} [, {def}])				*getbufvar()*
		The result is the value of option or local buffer variable
		{varname} in buffer {buf}.  Note that the name without "b:"
		must be used.
		The {varname} argument is a string.
		When {varname} is empty returns a |Dictionary| with all the
		buffer-local variables.
		When {varname} is equal to "&" returns a |Dictionary| with all
		the buffer-local options.
		Otherwise, when {varname} starts with "&" returns the value of
		a buffer-local option.
		This also works for a global or buffer-local option, but it
		doesn't work for a global variable, window-local variable or
		window-local option.
		For the use of {buf}, see |bufname()| above.
		When the buffer or variable doesn't exist {def} or an empty
		string is returned, there is no error message.
		Examples:  
			:let bufmodified = getbufvar(1, "&mod")
			:echo "todo myvar = " .. getbufvar("todo", "myvar")

 		Can also be used as a |method|:  
			GetBufnr()->getbufvar(varname)

nanozuki avatar Sep 02 '22 15:09 nanozuki

It seems like:

functionname({params})                                 *functionname()*
|<--    16 space   -->|Content
|<--    16 space   -->||<-8 spaces-->|Sub content
|<--    16 space   -->||<-4 ->|{param1}    description

nanozuki avatar Sep 02 '22 15:09 nanozuki

It'd be great to add this! I'm currently on a break and will keep this issue in mind when I return to working on open source!

kdheepak avatar Oct 24 '22 13:10 kdheepak

I'm just getting back to tackling a number of issues in this project, and I've made a new release that uses Pandoc v3 with a number of improvements. As part of that, I wanted to revisit this issue.

Do you have in mind what you'd like the markdown file to look like? Right now, I see in your README.md, you have a vimdoc block like so:

```vimdoc
api.get_tabs()                                            *tabby.api.get_tabs()*
    Get all tab ids

api.get_tab_wins({tabid})                             *tabby.api.get_tab_wins()*
    Get an winid array in specified tabid.

api.get_current_tab()                              *tabby.api.get_current_tab()*
    Get current tab's id.

api.get_tab_current_win({tabid})               *tabby.api.get_tab_current_win()*
    Get tab's current win's id.

api.get_tab_number({tabid})                         *tabby.api.get_tab_number()*
    Get tab's number.

api.get_wins()                                            *tabby.api.get_wins()*
    Get all windows, except floating window.

api.get_win_tab({winid})                               *tabby.api.get_win_tab()*
    Get tab id of specified window.

api.is_float_win({winid})                             *tabby.api.is_float_win()*
    Return true if this window is floating.

api.is_not_float_win({winid})                     *tabby.api.is_not_float_win()*
    Return true if this window is not floating.
```

Do you have thoughts on what you'd like to write in Markdown instead?

Pandoc supports something called definition lists that we can co-opt for this purpose. I can make this:

api.get_tabs() 

:   Return true if this window is floating.

generate this:

api.get_tabs()                                            *tabby.api.get_tabs()*
    Get all tab ids

Thoughts?

kdheepak avatar Feb 23 '23 08:02 kdheepak

Hi, I tried this, but get:

                                                            *api.get_tabs()*


api.get_tabs()                         Get all tab ids


                                                        *api.get_tab_wins()*


api.get_tab_wins({tabid})              Get an winid array in specified tabid.


                                                     *api.get_current_tab()*


api.get_current_tab()                  Get current tab’s id.


                                                 *api.get_tab_current_win()*


api.get_tab_current_win({tabid})       Get tab’s current win’s id.


                                                      *api.get_tab_number()*


api.get_tab_number({tabid})            Get tab’s number.


                                                            *api.get_wins()*


api.get_wins()                         Get all windows, except floating window.


                                                         *api.get_win_tab()*


api.get_win_tab({winid})               Get tab id of specified window.


                                                        *api.is_float_win()*


api.is_float_win({winid})              Return true if this window is floating.


                                                    *api.is_not_float_win()*


api.is_not_float_win({winid})          Return true if this window is not floating.

And furthermore, if I write these in README:

buf.type()
:   Get buftype option.

    Return:
        buftype, normal buffer is an empty string. check |buftype| or
        <https://neovim.io/doc/user/options.html#'buftype'> for details.

will generate:

                                                                *buf.type()*


buf.type()                             Get buftype option.
                                       Return:
                                       buftype, normal buffer is an empty string. check |buftype| or
                                       |https://neovim.io/doc/user/options.html#'buftype'| for details.

The command I used:

	./panvimdoc.sh --project-name 'tabby' --input-file README.md \
		--vim-version 0.5 --toc 'true' --dedup-subheadings 'true' \
		--description 'A declarative, highly configurable tabline plugin' \
		--demojify 'false' --treesitter 'true' --ignore-rawblocks 'true' \
		--doc-mapping 'true' --doc-mapping-project-name 'false' \
		--shift-heading-level-by 0 --increment-heading-level-by 0

nanozuki avatar Feb 27 '23 08:02 nanozuki

That’s the expected output I’m seeing in your comment. What are you expecting?

kdheepak avatar Feb 27 '23 11:02 kdheepak

That’s the expected output I’m seeing in your comment. What are you expecting?

The generated text differs from your explained in before.

I expect to generate what I wrote in the vim doc code block you mentioned. These codes follow a pattern that is used to neovim lua function documents.

This situation might not be easy to display nicely in both README and VimHelp; I just asking for help. If it cannot be made, it's also ok.

nanozuki avatar Feb 28 '23 02:02 nanozuki

My bad! I completely zoned out while typing that comment and was incorrect.

Definition Lists at the moment generate a two column layout, i.e.

buf.type()
:   Get buftype option.

    Return:
        buftype, normal buffer is an empty string. check |buftype| or
        <https://neovim.io/doc/user/options.html#'buftype'> for details.

generates

                                                                *buf.type()*


buf.type()                             Get buftype option.
                                       Return:
                                       buftype, normal buffer is an empty string. check |buftype| or
                                       |https://neovim.io/doc/user/options.html#'buftype'| for details.

However, level 4 markdown headers with the docmapping: true option added to the github action or in the command line, will generate something similar to what you are looking for. For example, this:

#### :FnlCompile[!] {doc=:FnlCompile}

Diff compiles all indexed fennel files

#### :FnlCompile[!]

Diff compiles all indexed fennel files

#### :[range]CommandName {doc=CommandName}

#### :[range]CommandName

will generate this:

:FnlCompile[!]                                                   *:FnlCompile*

Diff compiles all indexed fennel files


:FnlCompile[!]                                              *test-:FnlCompile*

Diff compiles all indexed fennel files


:[range]CommandName                                              *CommandName*


:[range]CommandName                                        *test-:CommandName*

It's not super pretty yet.

I'm open to suggestions for markdown syntax that would look good in a Markdown file. I can figure out a way to generate the appropriate vimdoc text from that if we can decide on what the markdown file should look like.

Right now both options I have currently implemented are not ideal. The definition lists are not rendered by GitHub and the level 4 headers have to have a {doc = name} if you want to change what the tag name should be, which again renders on GitHub in a not readable manner.

Ideally it would be in a comment like so <!-- doc = tagname --> but that makes it much harder to parse.

I'll leave this issue open till I come up with a better solution.

kdheepak avatar Feb 28 '23 02:02 kdheepak

Is this still work? I use this, but no anchor/tag is created, and the header will be in full uppercase.

I have a new thought for the tag. Can you support <a id="tag-name">content</a> ? It will display a link in GitHub README; if Vimpandoc renders this to Vim tag, it will be very nice.

And I found a workaround today:

<!-- panvimdoc-include-comment ```vimdoc
                                             *programName-line.cwd()*
``` -->

line.cwd()<a id="line-cwd"></a>

And we can use this anchor by:

The document of `line.cwd()` is in here: [line.cwd()](#line-cwd)

nanozuki avatar Jun 03 '24 05:06 nanozuki