{"id":13538847,"url":"https://github.com/nvim-treesitter/nvim-tree-docs","last_synced_at":"2025-04-10T01:09:33.083Z","repository":{"id":39777245,"uuid":"277915547","full_name":"nvim-treesitter/nvim-tree-docs","owner":"nvim-treesitter","description":"Code documentation built with treesitter","archived":false,"fork":false,"pushed_at":"2023-08-16T13:27:26.000Z","size":342,"stargazers_count":226,"open_issues_count":11,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-10T01:09:26.977Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nvim-treesitter.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-07-07T20:28:36.000Z","updated_at":"2025-03-13T17:39:51.000Z","dependencies_parsed_at":"2022-07-09T05:30:27.871Z","dependency_job_id":"60772d55-acbe-49e3-b7c8-e60ea0a658e9","html_url":"https://github.com/nvim-treesitter/nvim-tree-docs","commit_stats":{"total_commits":64,"total_committers":6,"mean_commits":"10.666666666666666","dds":0.421875,"last_synced_commit":"5db023d783da1e55339e5e25caaf72a59597e626"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvim-treesitter%2Fnvim-tree-docs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvim-treesitter%2Fnvim-tree-docs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvim-treesitter%2Fnvim-tree-docs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvim-treesitter%2Fnvim-tree-docs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nvim-treesitter","download_url":"https://codeload.github.com/nvim-treesitter/nvim-tree-docs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248137886,"owners_count":21053775,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T09:01:16.861Z","updated_at":"2025-04-10T01:09:33.054Z","avatar_url":"https://github.com/nvim-treesitter.png","language":"Lua","readme":"nvim-tree-docs\n==============\n\nHighly configurable documentation generator using treesitter.\n\nThis plugin is experimental!\n\n## Setup\n\nnvim-tree-docs is a module for the `nvim-treesitter` plugin. You can install both by doing (vim-plug):\n\n```vim\nPlug 'nvim-treesitter/nvim-treesitter'\nPlug 'nvim-treesitter/nvim-tree-docs'\n```\n\nYou can configure `nvim-tree-docs` as part of your `nvim-treesitter` configuration.\n\n```lua\nrequire \"nvim-treesitter.configs\".setup {\n  tree_docs = {enable = true}\n}\n```\n\n## Usage\n\nThere are two key bindings provided by default:\n\n- `doc_node_at_cursor`: `gdd`\n- `doc_all_in_range`: `gdd` (Visual)\n\nThese can be configured through the `keymap` option in the config.\n\n## Advanced configuration\n\nThis plugin is extremely configurable. Most documentation is standardized, but our\nprojects and personal preferences for documentation vary. This plugin aims to add total\ncustomization to the user.\n\n### Core concepts\n\nThere three key components to how this plugin operates.\n\n- `processors` -\u003e Processors generate lines of content within a template.\n- `slots` -\u003e Slots are positions where a processor can output it's content.\n- `templates` -\u003e Templates are a list of slots, basically the ordering of processors.\n                 These are by `kind` (Ex: function).\n- `specs` -\u003e Specs are a collection of templates and processors (Ex: jsdoc).\n\n### Basic example\n\nHere is a basic example of how this works (psuedo code).\n\n```lua\nlocal processors = {\n  my_processor = function() -- The processor\n    return \"Output!!!\"\n  end\n}\n\nlocal template = { -- template\n  \"my_processor\", -- slot\n  \"my_processor\"  -- slot\n}\n```\n\nThis example would generate the lines\n\n```\nOutput!!!\nOutput!!!\n```\n\nYou get the idea... The above code doesn't actually do anything, but is just to illustrate the point.\n\n### Configuring slots\n\nThe key advantage is they can be toggled on and off.\nFor example, lets say you like to include an `@author` tag on all your jsdoc classes.\nYou can enable the `author` slot to generate an author tag.\nThis is done in the configuration for the spec.\n\n```lua\nrequire \"nvim-treesitter.configs\".setup {\n  tree_docs = {\n    enable = true,\n    spec_config = {\n      jsdoc = {\n        slots = {\n          class = {author = true}\n        }\n      }\n    }\n  }\n}\n```\n\nThis will generate the following output.\n\n```javascript\n/**\n * The person class\n * @author\n */\nclass Person {}\n```\n\nPretty cool... but this is using the default processor for the spec, which in the case\nof jsdoc, just generates a tag. What if we could modify the behavior of that processor?\nWe can configure author processor in the same config.\n\n```lua\nrequire \"nvim-treesitter.configs\".setup {\n  tree_docs = {\n    enable = true,\n    spec_config = {\n      jsdoc = {\n        slots = {\n          class = {author = true}\n        },\n        processors = {\n          author = function()\n            return \" * @author Steven Sojka\"\n          end\n        }\n      }\n    }\n  }\n}\n```\n\nThis will generate.\n\n```javascript\n/**\n * The person class\n * @author Steven Sojka\n */\nclass Person {}\n```\n\nProcessors can return a single line or multiple lines.\nHere's an advanced sample that will prompt the user for\nan issue ticket number. If the user doesn't enter anything\nthe tag won't get generated.\n\n```lua\nrequire \"nvim-treesitter.configs\".setup {\n  tree_docs = {\n    enable = true,\n    spec_config = {\n      jsdoc = {\n        slots = {\n          class = {see = true, author = true}\n        },\n        processors = {\n          author = function() return \" * @author Steven Sojka\" end\n          see = function()\n            local ticket = vim.fn.input(\"Ticket: \")\n            return ticket ~= \"\" and (\" * @see \" .. ticket) or []\n          end\n        }\n      }\n    }\n  }\n}\n```\n\nThis will result in the following (assuming PROJ-X-123456 was inputted).\n\n```javascript\n/**\n * The person class\n * @author Steven Sojka\n * @see PROJ-X-123456\n */\nclass Person {}\n```\n\n### Configuring templates\n\nTemplates aren't traditional templates. It's basically just a set of slots in a specific order.\nYou can configure the template in the config.\n\n```lua\nrequire \"nvim-treesitter.configs\".setup {\n  tree_docs = {\n    enable = true,\n    spec_config = {\n      jsdoc = {\n        slots = {\n          class = {custom = true, author = true}\n        },\n        templates = {\n          class = {\n            \"doc-start\" -- Note, these are implicit slots and can't be turned off and vary between specs.\n            \"custom\"\n            \"author\"\n            \"doc-end\"\n            \"%content%\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nThis will generate.\n\n```javascript\n/**\n * The person class\n * @custom\n * @author\n */\nclass Person {}\n```\n\nNote, in the above example, if we would have left out the `custom` slot in the template, it would not have output anything.\n\n\n#### Builtin processors\n\nThere are some builtin processors that work across all specs (unless overridden, which is possible).\n\n- `%content%` -\u003e This will output the content line, in our case above it would be the class declaration line.\n                 This makes it possible to wrap or put the documentation below the content line.\n- `%rest%` -\u003e This will output all slots that are enabled, but do not have an explicit slot in the template.\n\n### Template context\n\nThis still needs to be documented...\n\n## Writing language queries\n\nQueries contain a couple conventions that are shared amongst all languages.\n\nQuery tag syntax is `@\u003ckind\u003e.\u003cproperty\u003e`\n\nThe `\u003ckind\u003e` tag corresponds with a template in the language specific template file.\nProperties can be accessed within a processor as the first argument.\n\nFor example, a simple processor that gets the name of a nod\n\n```lua\nfunction(ctx) return ctx.get_text(ctx.name.node) end\n```\n\nThis would correspond to a tag `@\u003ckind\u003e.name`.\n\nProperties are not predefined and can differ from language to language, but there a couple\nthat have special behavior.\n\n### `@\u003ckind\u003e.definition`\n\nThis is the most important one and is required for each `\u003ckind\u003e`.\nThis defines the node that defines the `\u003ckind\u003e`. If multiple queries\nmatch the same definition node, those entries will be merged together.\nThis is very important for function parameters where multiple matches\nneed to be grouped under the same function definition.\n\nFor example, that this javascript query.\n\n```scheme\n(function_declaration\n  name: (identifier) @function.name\n  body: (statement_block\n    (return_statement)? @function.return)) @function.definition\n\n(export_statement\n  (function_declaration) @function.definition) @function.export\n```\n\nThis will match both these functions.\n\n```javascript\nfunction test() {}\n\nexport function test() {}\n```\n\nThe key difference is one will have an `export` node associated with it. Both queries\nmatch the function that is exported but they get merged into a single data model\nbecause both `@function.definition` tags match the same node at the same position.\n\n### `@\u003ckind\u003e.\u003ckind\u003e.definition`\n\nKind queries can be nested to define multiple different node merge points. This can be done\nby providing multiple, nested definition tags. For example in function parameters. A nested `\u003ckind\u003e`\ncan be thought of as a list of similiar items.\n\n### `@\u003ckind\u003e.start_point`\n\nWhen docs are inserted into the document, it will insert the docs at the indentation and position\nof the definition node (`@\u003ckind\u003e.definition`). This can be changed, if you need to keep the same definition\nnode, but need a different start point to insert.\n\nFor example, that this javascript query.\n\n```scheme\n(function_declaration\n  name: (identifier) @function.name\n  body: (statement_block\n    (return_statement)? @function.return_statement)) @function.definition\n\n(export_statement\n  (function_declaration) @function.definition) @function.start_point @function.export\n```\n\nIf we doc'ed the following functions WITHOUT the root tag, we would get this:\n\n```javascript\n/**\n * test\n */\nfunction test() {}\n\n       /**\n        * test\n        */\nexport function test() {}\n```\n\nIncluding the start_point tag flags the export_statement node as the root node INSTEAD of the definition node.\n\n### `@\u003ckind\u003e.end_point`\n\nThis flags the end node that document can be triggered from. For example, the end of a function signature.\nThis is important, because it allows us to trigger docs on a multiline signature.\n\nFor example, that this javascript query.\n\n```scheme\n(\n  (comment)+? @function.doc\n  (function_declaration\n    name: (identifier) @function.name\n    parameters: (formal_parameters) @function.end_point\n    body: (statement_block\n      (return_statement)? @function.return)) @function.definition\n)\n```\n\nThis flags the parameters node as the end node for the signature. This allows us\nto doc signatures that look like this.\n\n```javascript\nfunction test(\n  someVeryLongNameThatRequiresUsToWrap,\n  blorg, // \u003c- We can trigger here to generate docs with no problem\n  boom\n) {\n  return;\n}\n```\n\nThe furtherest end node will be used if there are overlapping end_points.\nYou should always have an end_point defined in order to avoid unwanted document triggers.\n\n### `@\u003ckind\u003e.doc`\n\nThe doc references the current doc that is preceding the definition node. This gives access to existing\ndocumentation to either parse, update, or remove with updated information.\n\n# Roadmap\n\n- Filetype aliases\n- Template marks\n- More doc specs\n- Doc commands that don't require a treesitter node (jsdoc modules)\n- Predifined processors that can be swapped in... (think promptable descriptions?)\n","funding_links":[],"categories":["Lua"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnvim-treesitter%2Fnvim-tree-docs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnvim-treesitter%2Fnvim-tree-docs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnvim-treesitter%2Fnvim-tree-docs/lists"}