{"id":37028218,"url":"https://github.com/davidsusu/tree-printer","last_synced_at":"2026-01-14T03:21:56.781Z","repository":{"id":50561728,"uuid":"77209790","full_name":"davidsusu/tree-printer","owner":"davidsusu","description":"Java library for visualizing tree structures in the command line","archived":false,"fork":false,"pushed_at":"2024-06-29T10:30:43.000Z","size":453,"stargazers_count":37,"open_issues_count":4,"forks_count":8,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-29T11:37:23.043Z","etag":null,"topics":["ascii-art","command-line","java","library","tree","tree-viewer","unicode-art"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidsusu.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":"2016-12-23T08:14:36.000Z","updated_at":"2024-06-29T10:30:46.000Z","dependencies_parsed_at":"2024-06-29T11:35:55.265Z","dependency_job_id":"fdd0fe4d-5c01-4365-a259-c04171ab8c6d","html_url":"https://github.com/davidsusu/tree-printer","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/davidsusu/tree-printer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsusu%2Ftree-printer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsusu%2Ftree-printer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsusu%2Ftree-printer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsusu%2Ftree-printer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidsusu","download_url":"https://codeload.github.com/davidsusu/tree-printer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidsusu%2Ftree-printer/sbom","scorecard":{"id":327666,"data":{"date":"2025-08-11","repo":{"name":"github.com/davidsusu/tree-printer","commit":"b69b1d5938f697e40ff84bdcd0a16c3e5f08c97a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T02:52:02.213Z","repository_id":50561728,"created_at":"2025-08-18T02:52:02.213Z","updated_at":"2025-08-18T02:52:02.213Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408828,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["ascii-art","command-line","java","library","tree","tree-viewer","unicode-art"],"created_at":"2026-01-14T03:21:56.250Z","updated_at":"2026-01-14T03:21:56.775Z","avatar_url":"https://github.com/davidsusu.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tree Printer \u0026#x1F538; *now with colors (ANSI support)*\n\n\u003e [!IMPORTANT]\n\u003e Declarative construction of trees is coming.\n\u003e \n\u003e **[Please leave a comment on the related issue, if you have an idea about better declaring a tree!](https://github.com/davidsusu/tree-printer/issues/15)**\n\nSimple Java library for visualizing tree structures in the command line.\n\n```\nnatural foods\n ├─ fruits\n │  ├─ apple\n │  ├─ banana\n │  ├─ mango\n │  ├─ lorem and\n │  │  ipsum\n │  │ ┌──────────────────────────────────┐\n │  │ │            citroideae            │\n │  ├─│    ┌─────┬─────┴─┬─────────┐     │\n │  │ │ orange lemon grapefruit mandarin │\n │  │ └──────────────────────────────────┘\n │  │ ┌────────────────────────────────┐\n │  │ │         berries                │\n │  │ │     ┌──────┴───────┐           │\n │  └─│   grape          other         │\n │    │  ┌──┴─┐       ┌────┴─────┐     │\n │    │ red white strawberry raspberry │\n │    └────────────────────────────────┘\n ├─ vegetables\n │  ├─ tomato\n │  ├─ carrot\n │  │ A──────────B\n │  └─│ broccoli │\n │    D──────────C\n └─ seeds\n    ├─ walnut\n    └─ peanut\n```\n\n## Migration from 2.x to 3.x\n\nNow coloring and other ANSI escapes are supported.\n[See below for more information.](#coloring-and-other-ansi-formatters)\n\nThe following breaking changes was made:\n\n- `TreeNode.content()` returns with `ConsoleText` (instead of `String`)\n\n## Migration from 1.x to 2.x\n\nThe following breaking changes was made:\n\n- Package/class structure was reorganized\n- Method naming convention was changed (e. g. `getChildren()` \u0026rarr; `children()`)\n- Most of the telescoping constructors was removed (use builders instead)\n- Decorator inheritance was simplified, `forceInherit` option was removed\n\nFurthermore, many little changes, extensions and fixes was added.\n\n## Using in projects\n\nThis library is open source, and available under the Apache License V2.\n\nThe library is compatible with java versions 1.8+.\nSee the `1.x` branch for using the legacy version (compatible with 1.6+).\n\nBuilt packages are available from the Maven Central Repository.\n\nIn gradle projects:\n\n```groovy\n\ndependencies {\n    implementation \"hu.webarticum:tree-printer:${treePrinterVersion}\"\n}\n\n```\n\nIn maven projects:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ehu.webarticum\u003c/groupId\u003e\n  \u003cartifactId\u003etree-printer\u003c/artifactId\u003e\n  \u003cversion\u003e${treePrinterVersion}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Constructing trees\n\nA *tree* is a hierarchical structure built from *nodes*.\nAny tree is given by its root node.\n\nNodes implement the `TreeNode` interface.\nIt contains default implementations for the majority of its methods,\nyou must implement only the `content()` and `children()` methods.\n\nYou can use `SimpleTreeNode` out-of-the-box as a default string-based implementation:\n\n```java\nSimpleTreeNode rootNode = new SimpleTreeNode(\"I'm the root!\");\nrootNode.addChild(new SimpleTreeNode(\"I'm a child...\"));\nrootNode.addChild(new SimpleTreeNode(\"I'm an other child...\"));\n```\n\nHowever, you are free to implement your custom nodes.\n\n## Printing a tree\n\nThere are multiple built-in implementations of the `TreePrinter` interface\nfor printing tree structures via the `print()` method.\nThis method accepts a `TreeNode` (the root node of the printed hierarchy),\nand, optionally, an `Appendable` object, to where the output will be flushed\n(by default, output will be printed to `System.out`).\n\nAlternatively, you can get the visualization as `String` via `stringify()`.\nIn some cases this is inefficient (especially when you print large data with `ListingTreePrinter`).\n\nIt is very easy to visualize the above structure:\n\n```java\nnew ListingTreePrinter().print(rootNode);\n```\n\nAnd the result:\n\n```\nI'm the root!\n ├─I'm a child...\n └─I'm an other child...\n```\n\nOr use a `TraditionalTreePrinter`:\n\n```java\nnew TraditionalTreePrinter().print(rootNode);\n```\n\nWhich results:\n\n```\n           I'm the root!\n       ┌─────────┴───────┐\n       │                 │\nI'm a child... I'm an other child...\n```\n\nFor more available printers see the `hu.webarticum.treeprinter.printer.*` packages.\n\nOf course, `TreePrinter` implementations have many options for controlling the output.\nYou can change the lining characters, the aligning, and so on.\n\nMost classes have builders and some basic constructors for easy change of settings.\nFor example, if we want to align everything to left:\n\n```java\nnew TraditionalTreePrinter(\n        DefaultAligner.builder()\n                .align(DefaultAligner.Alignment.LEFT)\n        .build(),\n        TraditionalTreePrinter.DEFAULT_LINER\n).print(rootNode);\n```\n\nResult:\n\n```\nI'm the root!\n├──────────────┐\n│              │\nI'm a child... I'm an other child...\n```\n\n## Using decorators\n\nYou can easily write node decorators by extending `AbstractTreeNodeDecorator`.\nThere are built-in implementations for adding\npadding, border, shadow and other basic decorations.\n\nIn the previous example the child nodes are confused, because only a single space separates them.\nIt will be much cleaner if we added a border:\n\n```java\nnew TraditionalTreePrinter().print(new BorderTreeNodeDecorator(rootNode));\n```\n\nResult:\n\n```\n            ┌─────────────┐\n            │I'm the root!│\n            └─────────────┘\n        ┌──────────┴────────┐\n        │                   │\n┌──────────────┐ ┌─────────────────────┐\n│I'm a child...│ │I'm an other child...│\n└──────────────┘ └─────────────────────┘\n```\n\nOf course, you can compose as many decorators as you want:\n\n```java\nTreeNode decoratedTreeNode = new ShadowTreeNodeDecorator(\n        BorderTreeNodeDecorator.builder()\n                .wideUnicode()\n                .buildFor(\n                        new PadTreeNodeDecorator(rootNode, new Insets(0, 2))));\n\nnew TraditionalTreePrinter().print(decoratedTreeNode);\n```\n\nResult:\n\n\u003c!--\n```\n               ▛▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▜\n               ▏  I'm the root!  ▕▒\n               ▙▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▟▒\n                ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒\n          ┌──────────────┴──────────┐\n          │                         │\n▛▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▜  ▛▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▜\n▏  I'm a child...  ▕▒ ▏  I'm an other child...  ▕▒\n▙▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▟▒ ▙▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▟▒\n ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒  ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒\n```\n--\u003e\n\n![Decorated tree example](img/decorated-tree.png)\n\nDecorators inherit by default, but you can change this behavior.\n\n## Placeholders\n\nYou can put placeholder nodes into the tree.\nThese nodes are hidden by default in the general printers.\nPlaceholders are useful in n-ary trees, where missing nodes matter.\n\n```java\nboolean displayPlaceholders = true;\n\nSimpleTreeNode alignedTree = new SimpleTreeNode(\"ROOT\");\nalignedTree.addChild(new PlaceholderNode());\nalignedTree.addChild(new SimpleTreeNode(\"RIGHT\"));\n\nnew TraditionalTreePrinter(displayPlaceholders).print(\n        PadTreeNodeDecorator.builder()\n                .horizontalPad(3)\n                .buildFor(new BorderTreeNodeDecorator(alignedTree)));\n```\n\n```\n       ┌────┐\n       │ROOT│\n       └────┘\n   ┌──────┴──┐\n   │         │\n          ┌─────┐\n          │RIGHT│\n          └─────┘\n```\n\nAny node whose `isPlaceholder()` method returns `true` is considered a placeholder.\n`hu.webarticum.treeprinter.PlaceholderNode` is a built-in placeholder,\nit's empty and undecorable too.\n\n## ASCII vs Unicode mode\n\nBuilt-in objects that print lines or borders have a built-in set of characters, both for ASCII and Unicode mode.\nAffected classes have a constructor/builder parameter `useUnicode`.\nYou can globally change the default mode with `UnicodeMode.setUnicodeAsDefault()`.\n(Initial global default is Unicode.)\n\nThe first example with ASCII rendering:\n\n```java\nListingTreePrinter.builder().ascii().build().print(rootNode);\n```\n\nResult:\n\n```\nI'm the root!\n |-I'm a child...\n '-I'm an other child...\n ```\n\n## Coloring and other ANSI formatters\n\nColoring and other ANSI escapes are supported with the following features:\n\n- ANSI formatting support was added to built-in decorators and printers (e. g. colored lining)\n- `ConsoleText` and its implementations was added for better handling of texts\n- `AnsiFormat` and its basic constant instances was added, it's composable\n- global `AnsiMode` added (similar to `UnicodeMode`), ANSI can be disabled globally\n- width of custom ANSI formatted texts is handled properly\n\nInterface `ConsoleText` represents textual content intended for display in the command line.\n`ConsoleText.of(String)` (or `new PlainConsoleText(String)`) represents some plain text (without formatting).\n`ConsoleText.ofAnsi(String)` (or `new AnsiConsoleText(String)`) holds text possibly with format escapes.\nBoth normalizes newlines and unicode codepoints.\nBoth clears non-printable characters, expect that the latter keeps ANSI format escapes.\n\nIt's not necessary to write ANSI escapes by hand.\nThe `AnsiFormat` class represents a formatting, and can be applied to any `ConsoleText`.\nAlso, it's composable.\nLet's see a simple example:\n\n```java\nConsoleText.of(\"Hello ANSI\").format(AnsiFormat.GREEN);\n```\n\nThis will make the text \"Hello ANSI\", in green.\n\nHere is a little bit more complex use case:\n\n```java\nConsoleText.of(\"Hello \").concat(ConsoleText.of(\"ANSI\").format(AnsiFormat.GREEN)).format(AnsiFormat.BOLD);\n```\n\nNow only the word \"ANSI\" is green, but the whole text is in bold.\n\nWe can create a colorful tree:\n\n```java\nSimpleTreeNode rootNode = new SimpleTreeNode(ConsoleText.of(\"Root\").format(\n        AnsiFormat.UNDERLINE.compose(AnsiFormat.BOLD).compose(AnsiFormat.RED)));\n\nSimpleTreeNode childNode1 = new SimpleTreeNode(\n        ConsoleText.of(\"Child 1\").format(AnsiFormat.GREEN.compose(AnsiFormat.BOLD)));\nrootNode.addChild(new BorderTreeNodeDecorator(childNode1, AnsiFormat.RED));\n\nSimpleTreeNode childNode2 = new SimpleTreeNode(\"Child 2\");\nrootNode.addChild(childNode2);\n\nSimpleTreeNode grandChildNode22 = new SimpleTreeNode(\n        ConsoleText.of(\"Grandchild \")\n                .concat(ConsoleText.of(\"2-2\").format(AnsiFormat.CYAN)).breakLine()\n                .concat(ConsoleText.of(\"Line 2\").format(AnsiFormat.RED)).breakLine()\n                .concat(ConsoleText.of(\"Line line 3\").format(AnsiFormat.MAGENTA))\n                .format(AnsiFormat.BOLD));\nchildNode2.addChild(new ShadowTreeNodeDecorator(\n        JustifyTreeNodeDecorator.builder()\n                .minimumHeight(5).minimumWidth(20)\n                .verticalAlign(VerticalAlign.MIDDLE).horizontalAlign(HorizontalAlign.CENTER)\n                .background('~').backgroundFormat(AnsiFormat.CYAN)\n                .buildFor(grandChildNode22), AnsiFormat.BLUE));\n```\n\nThe built-in printers and decorators are formattable too.\nLet's print the above nodes connected with some blue lines:\n\n```java\nnew TraditionalTreePrinter(AnsiFormat.BLUE).print(rootNode);\n```\n\nDepending on the terminal, the result will be something like this:\n\n\u003c!--\n```\n                           Root\n    ┌────────────────────────┴───┐\n    │                            │\n┌───────┐                     Child 2\n│Child 1│              ┌─────────┴─────────────┐\n└───────┘              │                       │\n                Grandchild 2-1       ~~~~~~~~~~~~~~~~~~~~\n                       │             ~~~Grandchild 2-2~~~▒\n                       │             ~~~~~~~Line 2~~~~~~~▒\n                                     ~~~~Line line 3~~~~~▒\n            Grand-grandchild 2-1-1   ~~~~~~~~~~~~~~~~~~~~▒\n                                      ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒\n\n```\n--\u003e\n\n![ANSI formatted tree example](img/ansi-formatted-tree.png)\n\nFor more examples see the `AnsiExamplesMain` demo.\nStudy the API to find more possibilities.\n\n## Future plans\n\nThere are various ideas in the backlog that are planned to be implemented in the next versions, such as:\n\n- More `TreePrinter` implementations\n- More flexible alignment settings\n- Improved `TraditionalTreePrinter`\n- and more\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidsusu%2Ftree-printer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidsusu%2Ftree-printer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidsusu%2Ftree-printer/lists"}