{"id":21343910,"url":"https://github.com/benjamin-hodgson/gutenberg","last_synced_at":"2025-07-12T15:31:50.865Z","repository":{"id":39703952,"uuid":"507136772","full_name":"benjamin-hodgson/Gutenberg","owner":"benjamin-hodgson","description":"A fast text layout library","archived":false,"fork":false,"pushed_at":"2023-11-28T20:41:15.000Z","size":479,"stargazers_count":4,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-05-02T01:21:28.091Z","etag":null,"topics":["layout","pretty-print","pretty-printer","text"],"latest_commit_sha":null,"homepage":"https://www.benjamin.pizza/Gutenberg","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/benjamin-hodgson.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}},"created_at":"2022-06-24T20:30:47.000Z","updated_at":"2024-07-05T16:57:32.975Z","dependencies_parsed_at":"2023-11-16T18:26:55.566Z","dependency_job_id":"3d81673b-fd1c-483d-a230-93731a1c50d0","html_url":"https://github.com/benjamin-hodgson/Gutenberg","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benjamin-hodgson%2FGutenberg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benjamin-hodgson%2FGutenberg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benjamin-hodgson%2FGutenberg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benjamin-hodgson%2FGutenberg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benjamin-hodgson","download_url":"https://codeload.github.com/benjamin-hodgson/Gutenberg/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225824607,"owners_count":17529906,"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":["layout","pretty-print","pretty-printer","text"],"created_at":"2024-11-22T01:16:19.177Z","updated_at":"2024-11-22T01:16:19.568Z","avatar_url":"https://github.com/benjamin-hodgson.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"Gutenberg\n=========\n\nA library for laying out text, based on [Phil Wadler's pretty printing algorithm](https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf).\n\n\nInstalling\n----------\n\nGutenberg is [available on Nuget](https://www.nuget.org/packages/Gutenberg). API docs are hosted [on my website](https://www.benjamin.pizza/Gutenberg).\n\n\nTutorial\n--------\n\nGutenberg's core object is called `Document\u003cT\u003e`. It represents a textual document which can be laid out in a variety of ways.\n\nYou can create a document from a string,\n\n```csharp\n// Document\u003cT\u003e is intended to be imported under an alias.\n// If you're not using annotations (an advanced feature),\n// you can set `T` to `object`.\nusing Doc = Gutenberg.Document\u003cobject\u003e;\n\nvar doc = Doc.FromString(\"Hello world!\");\n```\n\nconcatenate documents,\n\n```csharp\nvar doc2 = doc + \" My name is Johannes Gutenberg.\";  // strings can be implicitly cast to documents\n```\n\ninsert line breaks,\n\n```csharp\nvar doc3 = doc2 + Doc.LineBreak + \"Pleased to meet you!\";\n```\n\nand render the document as a string.\n\n```csharp\nConsole.WriteLine(doc3.ToString());\n// Output:\n// Hello world! My name is Johannes Gutenberg.\n// Pleased to meet you!\n```\n\nYou can instruct Gutenberg to try alternative layouts for a document using the `Grouped` method. `Grouped` tells Gutenberg to attempt to _flatten_ the document, collapsing any `LineBreak`s into a single space.\n\n```csharp\nConsole.WriteLine(doc3.Grouped());\n// Output:\n// Hello world! My name is Johannes Gutenberg. Pleased to meet you!\n```\n\nGutenberg tries to use its available horizontal space (a default of 80 characters) efficiently. It tries to flatten the groups within a document as long as there is enough horizontal space to do so. If there's an overflow, it falls back on the un-flattened version.\n\n```csharp\n// set the page width to 60 characters - too narrow to flatten the LineBreak\nConsole.WriteLine(doc3.Grouped().ToString(60));\n// Output:\n// Hello world! My name is Johannes Gutenberg.\n// Pleased to meet you!\n```\n\nThe `Nested` operator controls indentation. If a document gets rendered with line breaks, the line breaks are indented to the document's nesting level.\n\n```csharp\nConsole.WriteLine(doc3.Nested(4).Grouped().ToString(60));\n// Output:\n// Hello world! My name is Johannes Gutenberg.\n//     Pleased to meet you!\n```\n\nYou can place groups inside each other, to give Gutenberg multiple options to layout a document as efficiently as possible. Here's an example of a recursive function to pretty-print a tree which uses nested groups to produce a flexible layout.\n\n```csharp\nrecord Tree(string Name, params Tree[] Children) : IPrettyPrintable\u003cobject\u003e\n{\n    public Doc PrettyPrint()\n    {\n        var children = Children.Length == 0\n            ? Doc.Empty\n            : Doc.ZeroWidthLineBreak\n                .Append(Doc.Concat(\n                    Children\n                        .Select(c =\u003e c.PrettyPrint())\n                        .Separated(\",\" + Doc.LineBreak)\n                ))\n                .Nested(2)\n                .Between(\"[\", Doc.ZeroWidthLineBreak + \"]\");\n        return Doc.Concat(Name).Append(children).Grouped();\n    }\n}\nConsole.WriteLine(exampleTree.PrettyPrint().ToString(20))\n// Output:\n// aaa[\n//   bbbbb[ccc, dd],\n//   eee,\n//   ffff[gg, hhh, ii]\n// ]\n```\n\nYou can read about Gutenberg's internals [on my website](https://www.benjamin.pizza/posts/2024-08-15-prettier-happier-more-imperative.html).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenjamin-hodgson%2Fgutenberg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenjamin-hodgson%2Fgutenberg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenjamin-hodgson%2Fgutenberg/lists"}