{"id":13413505,"url":"https://github.com/ddddddO/gtree","last_synced_at":"2025-03-14T19:32:37.929Z","repository":{"id":38095744,"uuid":"372102795","full_name":"ddddddO/gtree","owner":"ddddddO","description":"Using either Markdown or Programmatically to generate trees🌳 and directories📁, and to verify directories🔍. Provide CLI, Go package and Web.","archived":false,"fork":false,"pushed_at":"2025-02-13T14:55:41.000Z","size":23212,"stargazers_count":262,"open_issues_count":38,"forks_count":8,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-05T22:11:19.805Z","etag":null,"topics":["cli","directory","go","go-package","golang","markdown","tree","tree-structure","trees","wasm"],"latest_commit_sha":null,"homepage":"https://ddddddo.github.io/gtree/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ddddddO.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2021-05-30T01:51:22.000Z","updated_at":"2025-02-25T06:00:37.000Z","dependencies_parsed_at":"2023-12-29T11:28:44.707Z","dependency_job_id":"e67fdb57-ece5-4cfb-a789-c00f8ad33fd6","html_url":"https://github.com/ddddddO/gtree","commit_stats":{"total_commits":1089,"total_committers":4,"mean_commits":272.25,"dds":0.06519742883379243,"last_synced_commit":"c326d44a9e17fb927802d973eee72b56e4ab2aa8"},"previous_names":["ddddddo/gentree"],"tags_count":112,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ddddddO%2Fgtree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ddddddO%2Fgtree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ddddddO%2Fgtree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ddddddO%2Fgtree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ddddddO","download_url":"https://codeload.github.com/ddddddO/gtree/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243635549,"owners_count":20322958,"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":["cli","directory","go","go-package","golang","markdown","tree","tree-structure","trees","wasm"],"created_at":"2024-07-30T20:01:41.896Z","updated_at":"2025-03-14T19:32:37.921Z","avatar_url":"https://github.com/ddddddO.png","language":"Go","readme":"\u003cimg src=\"assets/heart-balloon.svg\" width=\"77\"\u003e[^1]\u003cbr\u003e\n[![GitHub Pages](https://img.shields.io/badge/-GitHub_Pages-00A98F.svg?logo=github\u0026style=flat)](https://ddddddo.github.io/gtree/)\u003cbr\u003e\n[![GitHub release](https://img.shields.io/github/release/ddddddO/gtree.svg?label=Release\u0026color=darkcyan)](https://github.com/ddddddO/gtree/releases) [![Go Reference](https://pkg.go.dev/badge/github.com/ddddddO/gtree)](https://pkg.go.dev/github.com/ddddddO/gtree)\u003cbr\u003e\n[![License](https://img.shields.io/badge/License-BSD_2--Clause-orange.svg?color=darkcyan)](https://github.com/ddddddO/gtree/blob/master/LICENSE) [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go#uncategorized)\u003cbr\u003e\n[![codecov](https://codecov.io/gh/ddddddO/gtree/branch/master/graph/badge.svg?token=JLGSLF33RH)](https://codecov.io/gh/ddddddO/gtree) [![Go Report Card](https://goreportcard.com/badge/github.com/ddddddO/gtree)](https://goreportcard.com/report/github.com/ddddddO/gtree) [![ci](https://github.com/ddddddO/gtree/actions/workflows/ci.yaml/badge.svg)](https://github.com/ddddddO/gtree/actions/workflows/ci.yaml)\n\n\n\u003cimg src=\"assets/demo.gif\"\u003e\u003cbr\u003e\n\nUsing either Markdown or Programmatically to generate directory trees🌳 and directories🗂, and to verify directories🔍.\nProvide CLI, Golang library and Web.\n\n# Table of Contents\n- **[Acknowledgments](https://github.com/ddddddO/gtree?tab=readme-ov-file#acknowledgments)**\n- Features\n\t- **[Web](https://github.com/ddddddO/gtree?tab=readme-ov-file#web)**\n\t- **[CLI](https://github.com/ddddddO/gtree?tab=readme-ov-file#cli)**\n\t- Library - **[Markdown to tree structure](https://github.com/ddddddO/gtree?tab=readme-ov-file#library---markdown-to-tree-structure)**\n\t- Library - **[Programmable tree structure](https://github.com/ddddddO/gtree?tab=readme-ov-file#library---programmable-tree-structure)**\n\t\t- Recommended for developers!👍\n- [Documents](https://github.com/ddddddO/gtree?tab=readme-ov-file#documents)\n- [Process](https://github.com/ddddddO/gtree?tab=readme-ov-file#process)\n- [Performance](https://github.com/ddddddO/gtree?tab=readme-ov-file#performance)\n- [Test coverage](https://github.com/ddddddO/gtree?tab=readme-ov-file#test-coverage)\n\n# Acknowledgments\n\n## Thanks for providing very useful CLI for cloud storage tree output🤩🎉\n\nEveryone is encouraged to use them!\n\n### ⭐[_orangekame3/stree_](https://github.com/orangekame3/stree)\nCLI for **Amazon S3** tree output.\u003c/br\u003e\n[_aws s3_](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/index.html) command does not do what `tree` command does, but [**_stree_**](https://github.com/orangekame3/stree) command can display tree!\n\n### ⭐[_owlinux1000/gcstree_](https://github.com/owlinux1000/gcstree)\nCLI for **Google Cloud Storage** tree output.\u003c/br\u003e\n[_gcloud storage_](https://cloud.google.com/sdk/gcloud/reference/storage) command does not do what `tree` command does, but [**_gcstree_**](https://github.com/owlinux1000/gcstree) command can display tree!\n\n## gtree packeage has been utilized for other tools as well🚀\nI hope you will use these tools as well!\n\n- [Tools](https://github.com/ddddddO/gtree/network/dependents)\n\n# Web\n\nhttps://ddddddo.github.io/gtree/\n\nThis page is that converts from Markdown to tree!\u003cbr\u003e\nThis page calls a function that outputs tree. This function is a Go package compiled as WebAssembly.\u003cbr\u003e\nThe symbols that can be used in Markdown are `*`, `-`, `+`, and `#`.\u003cbr\u003e\nIndentation represents hierarchy. The indentation can be whatever you specify, but use the same pattern.\u003cbr\u003e\nYou can change the branches like in the image below.\u003cbr\u003e\nAlso, once loaded, you can enjoy offline!\u003cbr\u003e\n\n![](assets/web_example.gif)\n\nYou can open it in your browser with\n```console\n$ gtree web\n```\n\n[source code](cmd/gtree-wasm/)\n\n\n# CLI\n\n## Installation\n\n\u003cpre\u003e\n\u003cb\u003eGo (requires 1.18 or later)\u003c/b\u003e\n$ go install github.com/ddddddO/gtree/cmd/gtree@latest\n\n\u003cb\u003eHomebrew\u003c/b\u003e\n$ brew install ddddddO/tap/gtree\n\n\u003cb\u003eScoop\u003c/b\u003e\n$ scoop bucket add ddddddO https://github.com/ddddddO/scoop-bucket.git\n$ scoop install ddddddO/gtree\n\n\u003cb\u003edeb\u003c/b\u003e\n$ export GTREE_VERSION=X.X.X\n$ curl -o gtree.deb -L https://github.com/ddddddO/gtree/releases/download/v$GTREE_VERSION/gtree_$GTREE_VERSION-1_amd64.deb\n$ dpkg -i gtree.deb\n\n\u003cb\u003erpm\u003c/b\u003e\n$ export GTREE_VERSION=X.X.X\n$ yum install https://github.com/ddddddO/gtree/releases/download/v$GTREE_VERSION/gtree_$GTREE_VERSION-1_amd64.rpm\n\n\u003cb\u003eapk\u003c/b\u003e\n$ export GTREE_VERSION=X.X.X\n$ curl -o gtree.apk -L https://github.com/ddddddO/gtree/releases/download/v$GTREE_VERSION/gtree_$GTREE_VERSION-1_amd64.apk\n$ apk add --allow-untrusted gtree.apk\n\n\u003cs\u003e\u003ca href=\"https://aur.archlinux.org/packages/gtree\"\u003e\u003cb\u003eAUR\u003c/b\u003e\u003c/a\u003e\u003c/s\u003e\n$ wip...\n\n\u003ca href=\"https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/text/gtree/default.nix\"\u003e\u003cb\u003eNix\u003c/b\u003e\u003c/a\u003e\n$ nix-env -i gtree\nor\n$ nix-shell -p gtree\n\n\u003ca href=\"https://github.com/macports/macports-ports/blob/master/sysutils/gtree/Portfile\"\u003e\u003cb\u003eMacPorts\u003c/b\u003e\u003c/a\u003e\n$ port install gtree\n\n\u003ca href=\"https://github.com/aquaproj/aqua-registry/blob/main/pkgs/ddddddO/gtree/pkg.yaml\"\u003e\u003cb\u003eaqua\u003c/b\u003e\u003c/a\u003e\n$ aqua g -i ddddddO/gtree\n\n\u003ca href=\"https://github.com/ddddddO/gtree/pkgs/container/gtree\"\u003e\u003cb\u003eDocker\u003c/b\u003e\u003c/a\u003e\n$ docker pull ghcr.io/ddddddo/gtree:latest\n$ docker run ghcr.io/ddddddo/gtree:latest template | docker run -i ghcr.io/ddddddo/gtree:latest output\ngtree\n├── cmd\n│   └── gtree\n│       └── main.go\n├── testdata\n│   ├── sample1.md\n│   └── sample2.md\n├── Makefile\n└── tree.go\n\u003c/pre\u003e\n\n### etc\n\n**download binary from [here](https://github.com/ddddddO/gtree/releases).**\n\n## Usage\n\n```console\n$ gtree --help\nNAME:\n   gtree - This CLI uses Markdown to generate directory trees and directories itself, and also verifies directories.\n           The symbols that can be used in Markdown are '-', '+', '*', and '#'.\n           Within Markdown, indentation represents hierarchy. The indentation can be whatever you specify, but use the same pattern.\n\nUSAGE:\n   gtree [global options] command [command options] [arguments...]\n\nVERSION:\n   1.10.2 / revision 85520a1\n\nCOMMANDS:\n   output, o, out     Outputs tree from markdown.\n                      Let's try 'gtree template | gtree output'.\n   mkdir, m           Makes directories and files from markdown. It is possible to dry run.\n                      Let's try 'gtree template | gtree mkdir -e .go -e .md -e Makefile'.\n   verify, vf         Verifies tree structure represented in markdown by comparing it with existing directories.\n                      Let's try 'gtree template | gtree verify'.\n   template, t, tmpl  Outputs markdown template. Use it to try out gtree CLI.\n   web, w, www        Opens \"Tree Maker\" in your browser and shows the URL in terminal.\n   version, v         Prints the version.\n   help, h            Shows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n   --help, -h     show help\n   --version, -v  print the version\n```\n\n### *Output* subcommand\n```console\n$ gtree output --help\nNAME:\n   gtree output - Outputs tree from markdown.\n                  Let's try 'gtree template | gtree output'.\n\nUSAGE:\n   gtree output [command options] [arguments...]\n\nOPTIONS:\n   --file value, -f value               specify the path to markdown file. (default: stdin)\n   --massive, -m                        set this option when there are very many blocks of markdown. (default: false)\n   --massive-timeout value, --mt value  set this option if you want to set a timeout. (default: 0s)\n   --format value                       set this option when specifying output format. \"json\", \"yaml\", \"toml\"\n   --watch, -w                          follow changes in markdown file. (default: false)\n   --help, -h                           show help\n```\n\n#### Try it!\n\n```console\n$ gtree template\n- gtree\n        - cmd\n                - gtree\n                        - main.go\n        - testdata\n                - sample1.md\n                - sample2.md\n        - Makefile\n        - tree.go\n$ gtree template | gtree output\ngtree\n├── cmd\n│   └── gtree\n│       └── main.go\n├── testdata\n│   ├── sample1.md\n│   └── sample2.md\n├── Makefile\n└── tree.go\n```\n\nOther pattern.\n\n```\n├── gtree output -f testdata/sample1.md\n├── cat testdata/sample1.md | gtree output -f -\n└── cat testdata/sample1.md | gtree output\n```\n\n\n#### Usage other than representing a directory.\n\n```console\n$ cat testdata/sample2.md | gtree output\nk8s_resources\n├── (Tier3)\n│   └── (Tier2)\n│       └── (Tier1)\n│           └── (Tier0)\n├── Deployment\n│   └── ReplicaSet\n│       └── Pod\n│           └── container(s)\n├── CronJob\n│   └── Job\n│       └── Pod\n│           └── container(s)\n└── (empty)\n    ├── DaemonSet\n    │   └── Pod\n    │       └── container(s)\n    └── StatefulSet\n        └── Pod\n            └── container(s)\n```\n\n\n#### Multiple roots\n\n```console\n$ cat testdata/sample6.md | gtree output\nArtiodactyla\n├── Artiofabula\n│   ├── Cetruminantia\n│   │   ├── Whippomorpha\n│   │   │   ├── Hippopotamidae\n│   │   │   └── Cetacea\n│   │   └── Ruminantia\n│   └── Suina\n└── Tylopoda\nCarnivora\n├── Feliformia\n└── Caniformia\n    ├── Canidae\n    └── Arctoidea\n        ├── Ursidae\n        └── x\n            ├── Pinnipedia\n            └── Musteloidea\n                ├── Ailuridae\n                └── x\n                    ├── Mephitidae\n                    └── x\n                        ├── Procyonidae\n                        └── Mustelidae\n```\n\n#### Output JSON\n\n```console\n$ cat testdata/sample5.md | gtree output --format json | jq\n{\n  \"value\": \"a\",\n  \"children\": [\n    {\n      \"value\": \"i\",\n      \"children\": [\n        {\n          \"value\": \"u\",\n          \"children\": [\n            {\n              \"value\": \"k\",\n              \"children\": null\n            },\n            {\n              \"value\": \"kk\",\n              \"children\": null\n            }\n          ]\n        },\n        {\n          \"value\": \"t\",\n          \"children\": null\n        }\n      ]\n    },\n    {\n      \"value\": \"e\",\n      \"children\": [\n        {\n          \"value\": \"o\",\n          \"children\": null\n        }\n      ]\n    },\n    {\n      \"value\": \"g\",\n      \"children\": null\n    }\n  ]\n}\n```\n\n#### Output YAML\n\n```console\n$ cat testdata/sample5.md | gtree output --format yaml\nvalue: a\nchildren:\n- value: i\n  children:\n  - value: u\n    children:\n    - value: k\n      children: []\n    - value: kk\n      children: []\n  - value: t\n    children: []\n- value: e\n  children:\n  - value: o\n    children: []\n- value: g\n  children: []\n```\n\n#### Output TOML\n\n```console\n$ cat testdata/sample5.md | gtree output --format toml\nvalue = 'a'\n[[children]]\nvalue = 'i'\n[[children.children]]\nvalue = 'u'\n[[children.children.children]]\nvalue = 'k'\nchildren = []\n[[children.children.children]]\nvalue = 'kk'\nchildren = []\n\n[[children.children]]\nvalue = 't'\nchildren = []\n\n[[children]]\nvalue = 'e'\n[[children.children]]\nvalue = 'o'\nchildren = []\n\n[[children]]\nvalue = 'g'\nchildren = []\n\n```\n\n\n### *Mkdir* subcommand\n\n```console\n$ gtree mkdir --help\nNAME:\n   gtree mkdir - Makes directories and files from markdown. It is possible to dry run.\n                 Let's try 'gtree template | gtree mkdir -e .go -e .md -e Makefile'.\n\nUSAGE:\n   gtree mkdir [command options] [arguments...]\n\nOPTIONS:\n   --file value, -f value                                       specify the path to markdown file. (default: stdin)\n   --dry-run, -d                                                dry run. detects node that is invalid for directory generation. the order of the output and made directories does not always match. (default: false)\n   --extension value, -e value [ --extension value, -e value ]  set this option if you want to create file instead of directory. for example, if you want to generate files with \".go\" extension: \"-e .go\"\n   --target-dir value                                           set this option if you want to specify the directory you want to make directory. (default: current directory)\n   --help, -h                                                   show help\n```\n\n#### Try it!\n\n```console\n$ gtree template\n- gtree\n        - cmd\n                - gtree\n                        - main.go\n        - testdata\n                - sample1.md\n                - sample2.md\n        - Makefile\n        - tree.go\n$ gtree template | gtree mkdir\n$ tree gtree/\ngtree/\n├── cmd\n│   └── gtree\n│       └── main.go\n├── Makefile\n├── testdata\n│   ├── sample1.md\n│   └── sample2.md\n└── tree.go\n\n8 directories, 0 files\n```\n\n#### *make directories and files*\n```console\n$ gtree template\n- gtree\n        - cmd\n                - gtree\n                        - main.go\n        - testdata\n                - sample1.md\n                - sample2.md\n        - Makefile\n        - tree.go\n$ gtree template | gtree mkdir -e .go -e .md -e Makefile\n$ tree gtree/\ngtree/\n├── cmd\n│   └── gtree\n│       └── main.go\n├── Makefile\n├── testdata\n│   ├── sample1.md\n│   └── sample2.md\n└── tree.go\n\n3 directories, 5 files\n```\n\n#### *dry run*\nDoes not create a file and directory.\n\n```console\n$ gtree template | gtree mkdir --dry-run -e .go -e .md -e Makefile\ngtree\n├── cmd\n│   └── gtree\n│       └── main.go\n├── testdata\n│   ├── sample1.md\n│   └── sample2.md\n├── Makefile\n└── tree.go\n\n4 directories, 5 files\n```\n\n![](assets/cli_mkdir_dryrun.png)\n\n\nAny invalid file or directory name will result in an error.\n\n```console\n$ gtree mkdir --dry-run \u003c\u003cEOS\n- root\n  - aa\n  - bb\n    - b/b\nEOS\ninvalid node name: b/b\n```\n\n```console\n$ gtree mkdir --dry-run \u003c\u003cEOS\n- /root\n  - aa\n  - bb\n    - bb\nEOS\ninvalid node name: /root\n```\n\n### *Verify* subcommand\n```console\n$ gtree verify --help\nNAME:\n   gtree verify - Verifies tree structure represented in markdown by comparing it with existing directories.\n                  Let's try 'gtree template | gtree verify'.\n\nUSAGE:\n   gtree verify [command options] [arguments...]\n\nOPTIONS:\n   --file value, -f value  specify the path to markdown file. (default: stdin)\n   --target-dir value      set this option if you want to specify the directory you want to verify. (default: current directory)\n   --strict                set this option if you want strict directory match validation. (default: non strict)\n   --help, -h              show help\n```\n\n#### Try it!\n\n```console\n$ tree example\nexample\n├── README.md\n├── find_pipe_programmable-gtree\n│   ├── README.md\n│   ├── go.mod\n│   ├── go.sum\n│   └── main.go\n├── go-list_pipe_programmable-gtree\n│   ├── README.md\n│   ├── go.mod\n│   ├── go.sum\n│   └── main.go\n├── like_cli\n│   ├── adapter\n│   │   ├── executor.go\n│   │   └── indentation.go\n│   └── main.go\n├── noexist\n│   └── xxx\n└── programmable\n    └── main.go\n\n6 directories, 14 files\n$ cat testdata/sample9.md\n- example\n        - README.md\n        - find_pipe_programmable-gtree\n                - README.md\n                - go.mod\n                - go.sum\n                - main.go\n        - go-list_pipe_programmable-gtree\n                - README.md\n                - go.mod\n                - go.sum\n                - main.go\n        - like_cli\n                - adapter\n                        - executor.go\n                        - indentation.go\n                - main.go\n                - kkk\n        - programmable\n                - main.go\n$ cat testdata/sample9.md | gtree verify --strict\nExtra paths exist:\n        example/noexist\n        example/noexist/xxx\nRequired paths does not exist:\n        example/like_cli/kkk\n```\n\ninspired by [mactat/framed](https://github.com/mactat/framed) !\n\n# Library - Markdown to tree structure\n\n## Installation\n\nGo version requires 1.18 or later.\n\n```console\n$ go get github.com/ddddddO/gtree\n```\n\n## Usage\n\nThe symbols that can be used in Markdown are `*`, `-`, `+`, and `#`.\n\n|Function|Description|Available optional functions|\n|--|--|--|\n|*[Output](https://github.com/ddddddO/gtree#output-func)*|can output trees|WithBranchFormatIntermedialNode\u003cbr\u003eWithBranchFormatLastNode\u003cbr\u003eWithEncodeJSON\u003cbr\u003eWithEncodeTOML\u003cbr\u003eWithEncodeYAML\u003cbr\u003eWithMassive|\n|*[Mkdir](https://github.com/ddddddO/gtree#mkdir-func)*|can create directories|WithTargetDir\u003cbr\u003eWithFileExtensions\u003cbr\u003eWithDryRun\u003cbr\u003eWithMassive|\n|*[Verify](https://github.com/ddddddO/gtree#verify-func)*|can output the difference between markdown and directories|WithTargetDir\u003cbr\u003eWithStrictVerify\u003cbr\u003eWithMassive|\n|*[Walk](https://github.com/ddddddO/gtree#walk-func)*|can execute user-defined function while traversing tree structure recursively|WithBranchFormatIntermedialNode\u003cbr\u003eWithBranchFormatLastNode\u003cbr\u003eWithMassive|\n\n\n### *Output* func\n\n```go\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/ddddddO/gtree\"\n)\n\nfunc main() {\n\tr1 := bytes.NewBufferString(strings.TrimSpace(`\n- root\n\t- dddd\n\t\t- kkkkkkk\n\t\t\t- lllll\n\t\t\t\t- ffff\n\t\t\t\t- LLL\n\t\t\t\t\t- WWWWW\n\t\t\t\t\t\t- ZZZZZ\n\t\t\t\t- ppppp\n\t\t\t\t\t- KKK\n\t\t\t\t\t\t- 1111111\n\t\t\t\t\t\t\t- AAAAAAA\n\t- eee`))\n\tif err := gtree.Output(os.Stdout, r1); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output:\n\t// root\n\t// ├── dddd\n\t// │   └── kkkkkkk\n\t// │       └── lllll\n\t// │           ├── ffff\n\t// │           ├── LLL\n\t// │           │   └── WWWWW\n\t// │           │       └── ZZZZZ\n\t// │           └── ppppp\n\t// │               └── KKK\n\t// │                   └── 1111111\n\t// │                       └── AAAAAAA\n\t// └── eee\n\n\tr2 := bytes.NewBufferString(strings.TrimSpace(`\n- a\n  - i\n    - u\n      - k\n      - kk\n    - t\n  - e\n    - o\n  - g`))\n\n\t// You can customize branch format.\n\tif err := gtree.Output(os.Stdout, r2,\n\t\tgtree.WithBranchFormatIntermedialNode(\"+-\u003e\", \":   \"),\n\t\tgtree.WithBranchFormatLastNode(\"+-\u003e\", \"    \"),\n\t); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output:\n\t// a\n\t// +-\u003e i\n\t// :   +-\u003e u\n\t// :   :   +-\u003e k\n\t// :   :   +-\u003e kk\n\t// :   +-\u003e t\n\t// +-\u003e e\n\t// :   +-\u003e o\n\t// +-\u003e g\n}\n\n```\n\n#### You can also output JSON/YAML/TOML.\n- `gtree.WithEncodeJSON()`\n- `gtree.WithEncodeTOML()`\n- `gtree.WithEncodeYAML()`\n\n\n### *Mkdir* func\n\n#### `gtree.Mkdir` func makes directories.\n\nYou can use `gtree.WithFileExtensions` func to make specified extensions as file.\n\n\n### *Verify* func\n\n#### `gtree.Verify` func verifies directories.\n\nYou can use `gtree.WithTargetDir` func / `gtree.WithStrictVerify` func.\n\n### *Walk* func\n\n\u003cdetails\u003e\n\u003csummary\u003eSee sample program\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/ddddddO/gtree\"\n)\n\nfunc main() {\n\tsrc := strings.TrimSpace(`\n- a\n  - i\n    - u\n      - k\n  - kk\n    - t\n- e\n  - o\n    - g`)\n\n\tcallback := func(wn *gtree.WalkerNode) error {\n\t\tfmt.Println(wn.Row())\n\t\treturn nil\n\t}\n\n\tif err := gtree.Walk(strings.NewReader(src), callback); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output:\n\t// a\n\t// ├── i\n\t// │   └── u\n\t// │       └── k\n\t// └── kk\n\t//     └── t\n\t// e\n\t// └── o\n\t//     └── g\n\n\tcallback2 := func(wn *gtree.WalkerNode) error {\n\t\tfmt.Println(\"WalkerNode's methods called...\")\n\t\tfmt.Printf(\"\\tName     : %s\\n\", wn.Name())\n\t\tfmt.Printf(\"\\tBranch   : %s\\n\", wn.Branch())\n\t\tfmt.Printf(\"\\tRow      : %s\\n\", wn.Row())\n\t\tfmt.Printf(\"\\tLevel    : %d\\n\", wn.Level())\n\t\tfmt.Printf(\"\\tPath     : %s\\n\", wn.Path())\n\t\tfmt.Printf(\"\\tHasChild : %t\\n\", wn.HasChild())\n\t\treturn nil\n\t}\n\n\tif err := gtree.Walk(strings.NewReader(src), callback2); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output:\n\t// WalkerNode's methods called...\n\t// \tName     : a\n\t// \tBranch   : \n\t// \tRow      : a\n\t// \tLevel    : 1\n\t// \tPath     : a\n\t// \tHasChild : true\n\t// WalkerNode's methods called...\n\t// \tName     : i\n\t// \tBranch   : ├──\n\t// \tRow      : ├── i\n\t// \tLevel    : 2\n\t// \tPath     : a/i\n\t// \tHasChild : true\n\t// WalkerNode's methods called...\n\t// \tName     : u\n\t// \tBranch   : │   └──\n\t// \tRow      : │   └── u\n\t// \tLevel    : 3\n\t// \tPath     : a/i/u\n\t// \tHasChild : true\n\t// WalkerNode's methods called...\n\t// \tName     : k\n\t// \tBranch   : │       └──\n\t// \tRow      : │       └── k\n\t// \tLevel    : 4\n\t// \tPath     : a/i/u/k\n\t// \tHasChild : false\n\t// WalkerNode's methods called...\n\t// \tName     : kk\n\t// \tBranch   : └──\n\t// \tRow      : └── kk\n\t// \tLevel    : 2\n\t// \tPath     : a/kk\n\t// \tHasChild : true\n\t// WalkerNode's methods called...\n\t// \tName     : t\n\t// \tBranch   :     └──\n\t// \tRow      :     └── t\n\t// \tLevel    : 3\n\t// \tPath     : a/kk/t\n\t// \tHasChild : false\n\t// WalkerNode's methods called...\n\t// \tName     : e\n\t// \tBranch   : \n\t// \tRow      : e\n\t// \tLevel    : 1\n\t// \tPath     : e\n\t// \tHasChild : true\n\t// WalkerNode's methods called...\n\t// \tName     : o\n\t// \tBranch   : └──\n\t// \tRow      : └── o\n\t// \tLevel    : 2\n\t// \tPath     : e/o\n\t// \tHasChild : true\n\t// WalkerNode's methods called...\n\t// \tName     : g\n\t// \tBranch   :     └──\n\t// \tRow      :     └── g\n\t// \tLevel    : 3\n\t// \tPath     : e/o/g\n\t// \tHasChild : false\n}\n```\n\n\u003c/details\u003e\n\ninspired by [xlab/treeprint](https://github.com/xlab/treeprint#iterating-over-the-tree-nodes) !\n\n\n# Library - Programmable tree structure\n\n\u003e [!NOTE]\n\u003e The `gonew` command can be used to set up sample project using gtree library.\u003cbr\u003e\n\u003e See [here](https://github.com/ddddddO/gtree/blob/master/example/README.md) for details.\n\n## Installation\n\nGo version requires 1.18 or later.\n\n```console\n$ go get github.com/ddddddO/gtree\n```\n\n## Usage\n\n|Function|Description|Available optional functions|\n|--|--|--|\n|*[OutputProgrammably](https://github.com/ddddddO/gtree#outputprogrammably-func)*|can output tree|WithBranchFormatIntermedialNode\u003cbr\u003eWithBranchFormatLastNode\u003cbr\u003eWithEncodeJSON\u003cbr\u003eWithEncodeTOML\u003cbr\u003eWithEncodeYAML|\n|*[MkdirProgrammably](https://github.com/ddddddO/gtree#mkdirprogrammably-func)*|can create directories|WithTargetDir\u003cbr\u003eWithFileExtensions\u003cbr\u003eWithDryRun|\n|*[VerifyProgrammably](https://github.com/ddddddO/gtree#verifyprogrammably-func)*|can output the difference between tree you composed and directories|WithTargetDir\u003cbr\u003eWithStrictVerify|\n|*[WalkProgrammably](https://github.com/ddddddO/gtree#walkprogrammably-func)*|can execute user-defined function while traversing tree structure recursively|WithBranchFormatIntermedialNode\u003cbr\u003eWithBranchFormatLastNode|\n\n### *OutputProgrammably* func\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/ddddddO/gtree\"\n)\n\nfunc main() {\n\tvar root *gtree.Node = gtree.NewRoot(\"root\")\n\troot.Add(\"child 1\").Add(\"child 2\").Add(\"child 3\")\n\tvar child4 *gtree.Node = root.Add(\"child 1\").Add(\"child 2\").Add(\"child 4\")\n\tchild4.Add(\"child 5\")\n\tchild4.Add(\"child 6\").Add(\"child 7\")\n\troot.Add(\"child 8\")\n\t// you can customize branch format.\n\tif err := gtree.OutputProgrammably(os.Stdout, root,\n\t\tgtree.WithBranchFormatIntermedialNode(\"+--\", \":   \"),\n\t\tgtree.WithBranchFormatLastNode(\"+--\", \"    \"),\n\t); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output:\n\t// root\n\t// +-- child 1\n\t// :   +-- child 2\n\t// :       +-- child 3\n\t// :       +-- child 4\n\t// :           +-- child 5\n\t// :           +-- child 6\n\t// :               +-- child 7\n\t// +-- child 8\n\n\tprimate := preparePrimate()\n\t// default branch format.\n\tif err := gtree.OutputProgrammably(os.Stdout, primate); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output:\n\t// Primate\n\t// ├── Strepsirrhini\n\t// │   ├── Lemuriformes\n\t// │   │   ├── Lemuroidea\n\t// │   │   │   ├── Cheirogaleidae\n\t// │   │   │   ├── Indriidae\n\t// │   │   │   ├── Lemuridae\n\t// │   │   │   └── Lepilemuridae\n\t// │   │   └── Daubentonioidea\n\t// │   │       └── Daubentoniidae\n\t// │   └── Lorisiformes\n\t// │       ├── Galagidae\n\t// │       └── Lorisidae\n\t// └── Haplorrhini\n\t//     ├── Tarsiiformes\n\t//     │   └── Tarsiidae\n\t//     └── Simiiformes\n\t//         ├── Platyrrhini\n\t//         │   ├── Ceboidea\n\t//         │   │   ├── Atelidae\n\t//         │   │   └── Cebidae\n\t//         │   └── Pithecioidea\n\t//         │       └── Pitheciidae\n\t//         └── Catarrhini\n\t//             ├── Cercopithecoidea\n\t//             │   └── Cercopithecidae\n\t//             └── Hominoidea\n\t//                 ├── Hylobatidae\n\t//                 └── Hominidae\n}\n\nfunc preparePrimate() *gtree.Node {\n\tprimate := gtree.NewRoot(\"Primate\")\n\tstrepsirrhini := primate.Add(\"Strepsirrhini\")\n\thaplorrhini := primate.Add(\"Haplorrhini\")\n\tlemuriformes := strepsirrhini.Add(\"Lemuriformes\")\n\tlorisiformes := strepsirrhini.Add(\"Lorisiformes\")\n\n\tlemuroidea := lemuriformes.Add(\"Lemuroidea\")\n\tlemuroidea.Add(\"Cheirogaleidae\")\n\tlemuroidea.Add(\"Indriidae\")\n\tlemuroidea.Add(\"Lemuridae\")\n\tlemuroidea.Add(\"Lepilemuridae\")\n\n\tlemuriformes.Add(\"Daubentonioidea\").Add(\"Daubentoniidae\")\n\n\tlorisiformes.Add(\"Galagidae\")\n\tlorisiformes.Add(\"Lorisidae\")\n\n\thaplorrhini.Add(\"Tarsiiformes\").Add(\"Tarsiidae\")\n\tsimiiformes := haplorrhini.Add(\"Simiiformes\")\n\n\tplatyrrhini := haplorrhini.Add(\"Platyrrhini\")\n\tceboidea := platyrrhini.Add(\"Ceboidea\")\n\tceboidea.Add(\"Atelidae\")\n\tceboidea.Add(\"Cebidae\")\n\tplatyrrhini.Add(\"Pithecioidea\").Add(\"Pitheciidae\")\n\n\tcatarrhini := simiiformes.Add(\"Catarrhini\")\n\tcatarrhini.Add(\"Cercopithecoidea\").Add(\"Cercopithecidae\")\n\thominoidea := catarrhini.Add(\"Hominoidea\")\n\thominoidea.Add(\"Hylobatidae\")\n\thominoidea.Add(\"Hominidae\")\n\n\treturn primate\n}\n\n```\n\n#### The program below converts the result of `find` into a tree.\n\n```go\npackage main\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/ddddddO/gtree\"\n)\n\n// Example:\n// $ cd github.com/ddddddO/gtree\n// $ find . -type d -name .git -prune -o -type f -print\n// ./config.go\n// ./node_generator_test.go\n// ./example/like_cli/adapter/indentation.go\n// ./example/like_cli/adapter/executor.go\n// ./example/like_cli/main.go\n// ./example/find_pipe_programmable-gtree/main.go\n// ...\n// $ find . -type d -name .git -prune -o -type f -print | go run example/find_pipe_programmable-gtree/main.go\n// \u003c\u003c See \"Output:\" below. \u003e\u003e\nfunc main() {\n\tvar (\n\t\troot *gtree.Node\n\t\tnode *gtree.Node\n\t)\n\tscanner := bufio.NewScanner(os.Stdin)\n\tfor scanner.Scan() {\n\t\tline := scanner.Text()              // e.g.) \"./example/find_pipe_programmable-gtree/main.go\"\n\t\tsplited := strings.Split(line, \"/\") // e.g.) [. example find_pipe_programmable-gtree main.go]\n\n\t\tfor i, s := range splited {\n\t\t\tif root == nil {\n\t\t\t\troot = gtree.NewRoot(s) // s := \".\"\n\t\t\t\tnode = root\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif i == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttmp := node.Add(s)\n\t\t\tnode = tmp\n\t\t}\n\t\tnode = root\n\t}\n\n\tif err := gtree.OutputProgrammably(os.Stdout, root); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output:\n\t// .\n\t// ├── config.go\n\t// ├── node_generator_test.go\n\t// ├── example\n\t// │   ├── like_cli\n\t// │   │   ├── adapter\n\t// │   │   │   ├── indentation.go\n\t// │   │   │   └── executor.go\n\t// │   │   └── main.go\n\t// │   ├── find_pipe_programmable-gtree\n\t// │   │   └── main.go\n\t// │   ├── go-list_pipe_programmable-gtree\n\t// │   │   └── main.go\n\t// │   └── programmable\n\t// │       └── main.go\n\t// ├── file_considerer.go\n\t// ├── node.go\n\t// ├── node_generator.go\n\t// ├── .gitignore\n\t// ...\n}\n```\n\n### *MkdirProgrammably* func\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/ddddddO/gtree\"\n)\n\nfunc main() {\n\tprimate := preparePrimate()\n\tif err := gtree.MkdirProgrammably(primate); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output(using Linux 'tree' command):\n\t// 22:20:43 \u003e tree Primate/\n\t// Primate/\n\t// ├── Haplorrhini\n\t// │   ├── Simiiformes\n\t// │   │   ├── Catarrhini\n\t// │   │   │   ├── Cercopithecoidea\n\t// │   │   │   │   └── Cercopithecidae\n\t// │   │   │   └── Hominoidea\n\t// │   │   │       ├── Hominidae\n\t// │   │   │       └── Hylobatidae\n\t// │   │   └── Platyrrhini\n\t// │   │       ├── Ceboidea\n\t// │   │       │   ├── Atelidae\n\t// │   │       │   └── Cebidae\n\t// │   │       └── Pithecioidea\n\t// │   │           └── Pitheciidae\n\t// │   └── Tarsiiformes\n\t// │       └── Tarsiidae\n\t// └── Strepsirrhini\n\t// \t├── Lemuriformes\n\t// \t│   ├── Daubentonioidea\n\t// \t│   │   └── Daubentoniidae\n\t// \t│   └── Lemuroidea\n\t// \t│       ├── Cheirogaleidae\n\t// \t│       ├── Indriidae\n\t// \t│       ├── Lemuridae\n\t// \t│       └── Lepilemuridae\n\t// \t└── Lorisiformes\n\t// \t\t├── Galagidae\n\t// \t\t└── Lorisidae\n\t//\n\t// 28 directories, 0 files\n}\n```\n\n[details](https://github.com/ddddddO/gtree/blob/master/example/programmable/main.go#L354)\n\n\n#### Make directories and files with specific extensions.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/ddddddO/gtree\"\n)\n\nfunc main() {\n\tgtreeDir := gtree.NewRoot(\"gtree\")\n\tgtreeDir.Add(\"cmd\").Add(\"gtree\").Add(\"main.go\")\n\tgtreeDir.Add(\"Makefile\")\n\ttestdataDir := gtreeDir.Add(\"testdata\")\n\ttestdataDir.Add(\"sample1.md\")\n\ttestdataDir.Add(\"sample2.md\")\n\tgtreeDir.Add(\"tree.go\")\n\n\t// make directories and files with specific extensions.\n\tif err := gtree.MkdirProgrammably(\n\t\tgtreeDir,\n\t\tgtree.WithFileExtensions([]string{\".go\", \".md\", \"Makefile\"}),\n\t); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output(using Linux 'tree' command):\n\t// 09:44:50 \u003e tree gtree/\n\t// gtree/\n\t// ├── cmd\n\t// │   └── gtree\n\t// │       └── main.go\n\t// ├── Makefile\n\t// ├── testdata\n\t// │   ├── sample1.md\n\t// │   └── sample2.md\n\t// └── tree.go\n\t//\n\t// 3 directories, 5 files\n}\n```\n\n### *VerifyProgrammably* func\n\nYou can use `gtree.WithTargetDir` func / `gtree.WithStrictVerify` func.\n\n### *WalkProgrammably* func\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/ddddddO/gtree\"\n)\n\nfunc main() {\n\troot := gtree.NewRoot(\"root\")\n\troot.Add(\"child 1\").Add(\"child 2\").Add(\"child 3\")\n\troot.Add(\"child 5\")\n\troot.Add(\"child 1\").Add(\"child 2\").Add(\"child 4\")\n\n\tcallback := func(wn *gtree.WalkerNode) error {\n\t\tfmt.Println(wn.Row())\n\t\treturn nil\n\t}\n\n\tif err := gtree.WalkProgrammably(root, callback); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output:\n\t// root\n\t// ├── child 1\n\t// │   └── child 2\n\t// │       ├── child 3\n\t// │       └── child 4\n\t// └── child 5\n\n\tcallback2 := func(wn *gtree.WalkerNode) error {\n\t\tfmt.Println(\"WalkerNode's methods called...\")\n\t\tfmt.Printf(\"\\tName     : %s\\n\", wn.Name())\n\t\tfmt.Printf(\"\\tBranch   : %s\\n\", wn.Branch())\n\t\tfmt.Printf(\"\\tRow      : %s\\n\", wn.Row())\n\t\tfmt.Printf(\"\\tLevel    : %d\\n\", wn.Level())\n\t\tfmt.Printf(\"\\tPath     : %s\\n\", wn.Path())\n\t\tfmt.Printf(\"\\tHasChild : %t\\n\", wn.HasChild())\n\t\treturn nil\n\t}\n\n\tif err := gtree.WalkProgrammably(root, callback2); err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(1)\n\t}\n\t// Output:\n\t// WalkerNode's methods called...\n\t//         Name     : root\n\t//         Branch   : \n\t//         Row      : root\n\t//         Level    : 1\n\t//         Path     : root\n\t//         HasChild : true\n\t// WalkerNode's methods called...\n\t//         Name     : child 1\n\t//         Branch   : ├──\n\t//         Row      : ├── child 1\n\t//         Level    : 2\n\t//         Path     : root/child 1\n\t//         HasChild : true\n\t// WalkerNode's methods called...\n\t//         Name     : child 2\n\t//         Branch   : │   └──\n\t//         Row      : │   └── child 2\n\t//         Level    : 3\n\t//         Path     : root/child 1/child 2\n\t//         HasChild : true\n\t// WalkerNode's methods called...\n\t//         Name     : child 3\n\t//         Branch   : │       ├──\n\t//         Row      : │       ├── child 3\n\t//         Level    : 4\n\t//         Path     : root/child 1/child 2/child 3\n\t//         HasChild : false\n\t// WalkerNode's methods called...\n\t//         Name     : child 4\n\t//         Branch   : │       └──\n\t//         Row      : │       └── child 4\n\t//         Level    : 4\n\t//         Path     : root/child 1/child 2/child 4\n\t//         HasChild : false\n\t// WalkerNode's methods called...\n\t//         Name     : child 5\n\t//         Branch   : └──\n\t//         Row      : └── child 5\n\t//         Level    : 2\n\t//         Path     : root/child 5\n\t//         HasChild : false\n}\n```\n\n# Process\n\n\u003e [!NOTE]\n\u003e This process is for the Massive Roots mode.\n\n## e.g. [*gtree/pipeline_tree.go*](https://github.com/ddddddO/gtree/blob/master/pipeline_tree.go)\n\n\u003cimage src=\"assets/process.svg\" width=100%\u003e\n\n\n# Performance\n\n\u003e [!WARNING]\n\u003e Depends on the environment.\n\n- Comparison simple implementation and pipeline implementation.\n- In the case of few Roots, simple implementation is faster in execution!\n\t- Use this one by default.\n- However, for multiple Roots, pipeline implementation execution speed tends to be faster💪✨\n\t- In the CLI, it is available by specifying `--massive`.\n\t- In the Go program, it is available by specifying `WithMassive` func.\n\n\u003cimage src=\"assets/performance.svg\" width=100%\u003e\n\n\u003cdetails\u003e\u003csummary\u003eBenchmark log\u003c/summary\u003e\n\n## Simple implementation\n```console\n11:19:22 \u003e go test -benchmem -bench Benchmark -benchtime 100x benchmark_simple_test.go\ngoos: linux\ngoarch: amd64\ncpu: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz\nBenchmarkOutput_singleRoot-4                 100             35375 ns/op           13856 B/op        171 allocs/op\nBenchmarkOutput_tenRoots-4                   100            200540 ns/op           72920 B/op       1597 allocs/op\nBenchmarkOutput_fiftyRoots-4                 100            730156 ns/op          569851 B/op       7919 allocs/op\nBenchmarkOutput_hundredRoots-4               100           1706493 ns/op         1714260 B/op      15820 allocs/op\nBenchmarkOutput_fiveHundredsRoots-4          100          16412090 ns/op        32245140 B/op      79022 allocs/op\nBenchmarkOutput_thousandRoots-4              100          55142492 ns/op        120929674 B/op    158025 allocs/op\nBenchmarkOutput_3000Roots-4                  100         489121246 ns/op        1035617527 B/op   474029 allocs/op\nBenchmarkOutput_6000Roots-4                  100        1613641261 ns/op        4087694372 B/op   948033 allocs/op\nBenchmarkOutput_10000Roots-4                 100        3913090646 ns/op        11293191221 B/op         1580035 allocs/op\nPASS\nok      command-line-arguments  614.944s\n```\n\n## Pipeline implementation\n```console\n11:29:43 \u003e go test -benchmem -bench Benchmark -benchtime 100x benchmark_pipeline_test.go\ngoos: linux\ngoarch: amd64\ncpu: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz\nBenchmarkOutput_pipeline_singleRoot-4                100            188706 ns/op           24236 B/op        300 allocs/op\nBenchmarkOutput_pipeline_tenRoots-4                  100            367758 ns/op          115970 B/op       2186 allocs/op\nBenchmarkOutput_pipeline_fiftyRoots-4                100            947879 ns/op          542188 B/op      10592 allocs/op\nBenchmarkOutput_pipeline_hundredRoots-4              100           1711537 ns/op         1099636 B/op      21094 allocs/op\nBenchmarkOutput_pipeline_fiveHundredsRoots-4         100           6892261 ns/op         5524905 B/op     105107 allocs/op\nBenchmarkOutput_pipeline_thousandRoots-4             100          13100335 ns/op        11225942 B/op     210115 allocs/op\nBenchmarkOutput_pipeline_3000Roots-4                 100          40694497 ns/op        33399766 B/op     630142 allocs/op\nBenchmarkOutput_pipeline_6000Roots-4                 100          85807944 ns/op        66974524 B/op    1260171 allocs/op\nBenchmarkOutput_pipeline_10000Roots-4                100         151486713 ns/op        113908462 B/op   2100208 allocs/op\nPASS\nok      command-line-arguments  30.670s\n```\n\n\u003c/details\u003e\n\n\n# Documents\n- [GoDoc](https://pkg.go.dev/github.com/ddddddO/gtree)\n\n## English\n- [Want to output a tree in Go?](https://medium.com/@allowing_whip_guineapig_430/want-to-output-a-tree-in-go-1851f9fc9900)\n- [Generate directory trees🌳 and the directories itself📁 using Markdown or Programmatically.](https://www.reddit.com/r/commandline/comments/146nk54/generate_directory_trees_and_the_directories/)\n\n## Japanese\n- [Goでtreeを表現する](https://zenn.dev/ddddddo/articles/8cd85c68763f2e)\n- [Markdown形式の入力からtreeを出力するCLI/Web](https://zenn.dev/ddddddo/articles/ad97623a004496)\n- [Markdown形式の入力からファイル/ディレクトリを生成するCLI/Goパッケージ](https://zenn.dev/ddddddo/articles/460d12e8c07763)\n- [盆栽 (節目の記事)](https://zenn.dev/openlogi/articles/f6cc91ac413c8f)\n- [感想](https://scrapbox.io/ddddddo/useful_tools)\n\n# Test coverage\n![treemap](/assets/test_treemap.svg)\n\n...generated by [nikolaydubina/go-cover-treemap](https://github.com/nikolaydubina/go-cover-treemap) !\n\n# Stargazers over time\n[![Stargazers over time](https://starchart.cc/ddddddO/gtree.svg?variant=adaptive)](https://starchart.cc/ddddddO/gtree)\n\n[^1]: Gopher retrieved from [egonelbre/gophers](https://github.com/egonelbre/gophers) !","funding_links":[],"categories":["Utilities","Miscellaneous","Go","Microsoft Office","cli","杂项","\u003ca name=\"text-processing\"\u003e\u003c/a\u003eText processing","Uncategorized"],"sub_categories":["Markdown","Uncategorized","未分类的"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FddddddO%2Fgtree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FddddddO%2Fgtree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FddddddO%2Fgtree/lists"}