{"id":20126162,"url":"https://github.com/emacs-vs/ts-docstr","last_synced_at":"2025-05-06T17:35:07.658Z","repository":{"id":60110297,"uuid":"539872606","full_name":"emacs-vs/ts-docstr","owner":"emacs-vs","description":"A document string minor mode using tree-sitter","archived":false,"fork":false,"pushed_at":"2025-04-22T23:26:23.000Z","size":5148,"stargazers_count":43,"open_issues_count":5,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-23T00:27:40.131Z","etag":null,"topics":["docstr","docstring","emacs"],"latest_commit_sha":null,"homepage":"https://emacs-vs.github.io/ts-docstr/","language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emacs-vs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["emacs-vs","jcs090218"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2022-09-22T08:18:42.000Z","updated_at":"2025-04-22T23:26:27.000Z","dependencies_parsed_at":"2023-12-11T12:56:58.367Z","dependency_job_id":"7a0e53c0-b0f9-49fd-9403-da998fb9e587","html_url":"https://github.com/emacs-vs/ts-docstr","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emacs-vs%2Fts-docstr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emacs-vs%2Fts-docstr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emacs-vs%2Fts-docstr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emacs-vs%2Fts-docstr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emacs-vs","download_url":"https://codeload.github.com/emacs-vs/ts-docstr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252734471,"owners_count":21796023,"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":["docstr","docstring","emacs"],"created_at":"2024-11-13T20:14:02.180Z","updated_at":"2025-05-06T17:35:07.632Z","avatar_url":"https://github.com/emacs-vs.png","language":"Emacs Lisp","funding_links":["https://github.com/sponsors/emacs-vs","https://github.com/sponsors/jcs090218","https://www.paypal.me/jcs090218","https://www.patreon.com/jcs090218"],"categories":[],"sub_categories":[],"readme":"[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n[![JCS-ELPA](https://raw.githubusercontent.com/jcs-emacs/badges/master/elpa/v/ts-docstr.svg)](https://jcs-emacs.github.io/jcs-elpa/#/ts-docstr)\n\n# ts-docstr\n\u003e A document string minor mode using tree-sitter\n\n[![CI](https://github.com/emacs-vs/ts-docstr/actions/workflows/test.yml/badge.svg)](https://github.com/emacs-vs/ts-docstr/actions/workflows/test.yml)\n[![Docs](https://github.com/emacs-vs/ts-docstr/actions/workflows/docs.yml/badge.svg)](https://github.com/emacs-vs/ts-docstr/actions/workflows/docs.yml)\n\n\u003c!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc --\u003e\n**Table of Contents**\n\n- [ts-docstr](#ts-docstr)\n  - [💾 Installation](#💾-installation)\n    - [🔍 Method 1. with `straight.el` and `use-package`:](#🔍-method-1-with-straightel-and-use-package)\n    - [🔍 Method 2. Manual](#🔍-method-2-manual)\n  - [📇 Commands](#📇-commands)\n  - [🔧 Customization](#🔧-customization)\n    - [🎨 Styles](#🎨-styles)\n    - [⌨️ Keys](#️-keys)\n    - [💬 Ask to select the style](#💬-ask-to-select-the-style)\n    - [🎣 Hooks](#🎣-hooks)\n  - [🔨 Supported languages](#🔨-supported-languages)\n  - [🛠️ Contribute](#🛠️-contribute)\n    - [🔬 Development](#🔬-development)\n    - [❓ How to support my favorite language?](#❓-how-to-support-my-favorite-language)\n      - [🔍 The `activate` function](#🔍-the-activate-function)\n      - [🔍 The `parse` function](#🔍-the-parse-function)\n      - [🔍 The `insert` function](#🔍-the-insert-function)\n    - [❓ How to add a document string style?](#❓-how-to-add-a-document-string-style)\n    - [❓ How to trigger by a key?](#❓-how-to-trigger-by-a-key)\n  - [⚜️ License](#⚜️-license)\n\n\u003c!-- markdown-toc end --\u003e\n\n## 💾 Installation\n\n### 🔍 Method 1. with `straight.el` and `use-package`:\n\n```elisp\n(use-package ts-docstr \n  :straight (ts-docstr :type git :host github :repo \"emacs-vs/ts-docstr\"\n                       :files (:defaults \"langs/*.el\")))\n```\n\n### 🔍 Method 2. Manual\n\n```sh\ngit clone https://github.com/emacs-vs/ts-docstr /path/to/lib\n```\n\nthen in Emacs:\n\n```elisp\n(add-to-list 'load-path \"/path/to/lib\")\n(require ts-docstr)\n```\n\nor\n\n```elisp\n(use-package ts-docstr\n  :load-path \"/path/to/lib\")\n```\n\n## 📇 Commands\n\n| Commands             | Description                                     |\n|:---------------------|:------------------------------------------------|\n| `ts-docstr-at-point` | Add document string at current point.           |\n| `ts-docstr-mode`     | Use nature key bindings.                        |\n| `ts-docstr-ask`      | Ask and update document string style (locally). |\n\n## 🔧 Customization\n\n### 🎨 Styles\n\nThe style can be customized by setting the variable with this pattern\n`ts-docstr-[lang]-style`. Here is an example to set `Java` docstring style\nto `Javadoc`.\n\n```elisp\n(setq ts-docstr-java-style 'javadoc)\n```\n\n### ⌨️ Keys\n\nBetter editing experience,\n\n```elisp\n(setq ts-docstr-key-support t)\n```\n\nThen do `M-x ts-docstr-mode`.\n\n### 💬 Ask to select the style\n\n```elisp\n(setq ts-docstr-ask-on-enable t)\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./etc/ask.png\" width=\"60%\"/\u003e\n\u003c/p\u003e\n\n### 🎣 Hooks\n\nHook patterns are:\n\n* `ts-docstr-[module]-before-[activate/parse/insert]-hook`\n* `ts-docstr-[module]-after-[activate/parse/insert]-hook`\n\nFor example,\n\n* `ts-docstr-c++-before-activate-hook`\n\nor just a general one, (without the language name)\n\n* `ts-docstr-before-activate-hook`\n\n## 🔨 Supported languages\n\u003e ⚠️ Please sort these two lists alphabetically!\n\nThese languages are fairly complete:\n\n* C / C++ / C#\n* Go\n* Java / JavaScript\n* Lua\n* PHP / Python\n* Ruby / Rust\n* Scala\n* Swift\n* TypeScript\n\nThese languages are in development:\n\n* Elixir\n* Haskell\n* Shellscript\n\n## 🛠️ Contribute\n\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)\n[![Elisp styleguide](https://img.shields.io/badge/elisp-style%20guide-purple)](https://github.com/bbatsov/emacs-lisp-style-guide)\n[![Donate on paypal](https://img.shields.io/badge/paypal-donate-1?logo=paypal\u0026color=blue)](https://www.paypal.me/jcs090218)\n[![Become a patron](https://img.shields.io/badge/patreon-become%20a%20patron-orange.svg?logo=patreon)](https://www.patreon.com/jcs090218)\n\nIf you would like to contribute to this project, you may either clone and make\npull requests to this repository. Or you can clone the project and establish\nyour own branch of this tool. Any methods are welcome!\n\n### 🔬 Development\n\nTo run the test locally, you will need the following tools:\n\n- [Eask](https://emacs-eask.github.io/)\n- [Make](https://www.gnu.org/software/make/) (optional)\n\nInstall all dependencies and development dependencies:\n\n```sh\neask install-deps --dev\n```\n\nTo test the package's installation:\n\n```sh\neask package\neask install\n```\n\nTo test compilation:\n\n```sh\neask compile\n```\n\n**🪧 The following steps are optional, but we recommend you follow these lint results!**\n\nThe built-in `checkdoc` linter:\n\n```sh\neask lint checkdoc\n```\n\nThe standard `package` linter:\n\n```sh\neask lint package\n```\n\n*📝 P.S. For more information, find the Eask manual at https://emacs-eask.github.io/.*\n\n### ❓ How to support my favorite language?\n\n\u003e ⚠ Before you start, make sure [tree-sitter-langs](https://github.com/emacs-tree-sitter/tree-sitter-langs)\n\u003e supports the language you want to add!\n\n\u003e ⚠ The best way to learn how the entire process works is to look into other\n\u003e files in the `/langs` folder from the project root. Find a similar language\n\u003e and see through code, all languages' implementation are very similar to one\n\u003e another.\n\nAll parsers are defined in the `/langs` folder from the project root. The file\nis named with the prefix `ts-docstr-` followed by the `language name`. For\nexample, if you want to create a parser for the `C` programming languge; the\nfile should be named `ts-docstr-c.el`.\n\nThe parser file is consist in three part:\n\n* ts-docstr-[lang]-activate `()`\n* ts-docstr-[lang]-parse `(node)`\n* ts-docstr-[lang]-insert `(node data)`\n\n#### 🔍 The `activate` function\n\nThe `activate` function is used to search for a node and confirm weather it\nshould insert a document string. This function will eventually return a captured\nnode, or return `nil` if we shouldn't insert a document string here.\n\nHere is the simplified version of `Java` activate function:\n\n```elisp\n;;;###autoload\n(defun ts-docstr-java-activate ()\n  \"...\"\n  ;; Narrow region to next line, this defines the valid region to insert a\n  ;; document string.\n  (ts-docstr-c-like-narrow-region\n    ;; We grab a list of node from the narrowed region, here we try to capture\n    ;; a `class' or `method' declaration. If this returns 2 or more nodes,\n    ;; report an error since we don't expect these declarations happened on the\n    ;; same line (region).\n    (nth 0 (ts-docstr-grab-nodes-in-range '(class_declaration\n                                            method_declaration)))))\n```\n\nUse `ts-docstr-activatable-p` function to check to see if you are able to insert\na document string at point, this function returns a node.\n\n```elisp\n(defun print-activate-node ()\n  (interactive)  ; make interactive, so you could M-x\n  (message \"node: %s\" (ts-docstr-activatable-p)))\n```\n\nEvaluate, then `M-x print-activate-node` to see if it return something or `nil`.\n\n#### 🔍 The `parse` function\n\nThe `parse` function takes one argument `node` from the `activate` function.\nIn this stage, we collect all necessary data (`paramters`, `class`/`enum` name,\netc) and put into a property list.\n\nHere is a simplest `parse` function for example:\n\n```elisp\n;;;###autoload\n(defun ts-docstr-java-parse (node)\n  \"...\"\n  (if (equal (tsc-node-type node) 'method_declaration)\n      ;; `types' and `variables' are lists. Each store typenames and variables\n      ;; name. We simply parse the tree/node in this steps.\n      (list :type types :variable variables\n            :return (ts-docstr-java--parse-return params)  ; return `t' or `nil'\n            :name (ts-docstr-java--get-name node))         ; return `function' name\n    ;; For `class', we don't need to parse parameters.\n    (list :name (ts-docstr-java--get-name node))))         ; return `class' name\n```\n\n#### 🔍 The `insert` function\n\nThe `insert` function takes two arguments `node` and `data` from previous\nstages. We will need to define a config variable and function.\n\nThe config variable:\n\n```elisp\n\n(defcustom ts-docstr-java-style 'javadoc\n  \"...\"\n  :type '(choice (const :tag \"No specify\" nil)\n                 (const :tag \"Javadoc Style\" javadoc)))\n```\n\nThe config function:\n\n```elisp\n;; This is later called and exposed in the insertion function.\n(defun ts-docstr-java-config ()\n  \"...\"\n  (cl-case ts-docstr-java-style  ; define the style by each style guide\n    (javadoc (list :start \"/**\"  ; this plist is later used in insertion function\n                   :prefix \"* \"\n                   :end \"*/\"\n                   :summary \"{d}\"\n                   :param \"@param {v} {d}\"\n                   :return \"@return {d}\"))\n    (t ...)))\n```\n\nLastly, you can create the `insert` function. In this stage you will write data\nto the current file.\n\n```elisp\n(defun ts-docstr-java-insert (node data)\n  \"Insert document string upon NODE and DATA.\"\n  (ts-docstr-inserting\n    (ts-docstr-insert c-start \"\\n\")                              ; /**\n    (ts-docstr-insert c-prefix \" \" (plist-get data :name) \"\\n\")  ;  * NAME\n    (ts-docstr-insert c-end)))                                   ;  */\n```\n\n```java\n/**\n * Example\n */\nclass Example {}\n```\n\n### ❓ How to add a document string style?\n\nFind the language file in the `/langs` folder from the project root, if you\ncouldn't find it, see [❓ How to support my favorite language?](https://github.com/emacs-vs/ts-docstr#-how-to-support-my-favorite-language).\n\nFirst look into the variable with the name similar to `ts-docstr-[lang]-style`.\nSee the following example,\n\n```elisp\n;; langs/ts-docstr-java.el\n(defcustom ts-docstr-java-style 'javadoc\n  \"...\"\n  :type '(choice (const :tag \"No specify\" nil)\n                 (const :tag \"Javadoc Style\" javadoc)))\n```\n\nSee if the style is already supported. Continue reading if it does **NOT**, \nthere are two parts you need to change in order to support your favorite style!\n\nFirst, you need to add an option to the style variable so other people would\nnotice the changes.\n\n```elisp\n...\n  :type '(choice (const :tag \"No specify\" nil)\n                 (const :tag \"New Doc Style\" new-doc-style)\n...\n```\n\nThen next (last) step is to do the implementation in the insertion function.\nThe implementation is isolated and complex depends on the style you targeted.\nHere we show the core logic of the implementation, but we prefer to look right\ninto the code:\n\n```elisp\n...\n(ts-docstr-with-style-case\n  (new-doc-style  ; listen to new-doc-style\n   (insert \"My new docstring style! :)\"))\n...\n```\n\n### ❓ How to trigger by a key?\n\nTo insert document string with key is to use `ts-docstr-mode`. The entire key\nrelated logic is placed in `ts-docstr-key.el` file from the project root. \nTo implement one, you first need to design the method to insert the entire\ndocument string (I called it triggeration function, or trigger). For example,\nin `C#`, you can trigger the document string insertion function by hittting\nthe third slash in a line.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./etc/langs/csharp/csharp-vs-doc-demo.gif\" width=\"60%\"/\u003e\n\u003c/p\u003e\n\nOnce you have an idea, write the function to do the action. Here is the example\nfor C# slash triggeration function.\n\n\u003e ⚠ Check before you do, may be the triggeration is already there, and make\n\u003e sure your design doesn't conflict with other keys!\n\n```elisp\n(defun ts-docstr-key-csharp-/ (\u0026rest _)\n  \"...\"\n  (ts-docstr-key--with-env '(csharp-mode)         ; Make sure it doesn't pollute other file\n    (when (and (ts-docstr--line-is \"///\")         ; Make sure the line consist of ///\n               (ts-docstr--looking-back \"///\" 3)  ; Make sure cursor is at the end of ///\n               (ts-docstr-activatable-p))         ; Check valid docstring insertion point\n      (backward-delete-char 3)                    ; Delete all slashes, ready to do docstrnig insertion\n      (ts-docstr-at-point))))                     ; Do docstring insertion\n```\n\nThen you would just need to register the function to variable `ts-docstr-key-alist.\n\n```elisp\n(defcustom ts-docstr-key-alist\n  `((\"RET\" . ts-docstr-key-doxygen-like-return)\n    (\"/\"   . ts-docstr-key-csharp-/)             ; Add this line!\n    (\"/\"   . ts-docstr-key-go-/)\n...\n```\n\n## ⚜️ License\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see \u003chttps://www.gnu.org/licenses/\u003e.\n\nSee [`LICENSE`](./LICENSE.txt) for details.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femacs-vs%2Fts-docstr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femacs-vs%2Fts-docstr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femacs-vs%2Fts-docstr/lists"}