{"id":18323657,"url":"https://github.com/mortalflesh/console-style","last_synced_at":"2025-06-26T10:02:46.525Z","repository":{"id":62530119,"uuid":"155347297","full_name":"MortalFlesh/console-style","owner":"MortalFlesh","description":"Library to help with basic Console I/O","archived":false,"fork":false,"pushed_at":"2025-03-05T08:20:07.000Z","size":386,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-09T15:12:49.141Z","etag":null,"topics":["console","console-visualization","verbosity-level"],"latest_commit_sha":null,"homepage":"","language":"F#","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/MortalFlesh.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":"2018-10-30T08:07:21.000Z","updated_at":"2025-03-05T08:20:10.000Z","dependencies_parsed_at":"2025-04-09T15:12:59.307Z","dependency_job_id":"95bfcc51-9769-4220-918f-e8f8fcefa06b","html_url":"https://github.com/MortalFlesh/console-style","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/MortalFlesh/console-style","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MortalFlesh%2Fconsole-style","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MortalFlesh%2Fconsole-style/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MortalFlesh%2Fconsole-style/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MortalFlesh%2Fconsole-style/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MortalFlesh","download_url":"https://codeload.github.com/MortalFlesh/console-style/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MortalFlesh%2Fconsole-style/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262044401,"owners_count":23249745,"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":["console","console-visualization","verbosity-level"],"created_at":"2024-11-05T18:29:01.983Z","updated_at":"2025-06-26T10:02:46.507Z","avatar_url":"https://github.com/MortalFlesh.png","language":"F#","readme":"Console style\n=============\n\n[![NuGet Version and Downloads count](https://buildstats.info/nuget/ConsoleStyle)](https://www.nuget.org/packages/ConsoleStyle)\n[![Check](https://github.com/MortalFlesh/console-style/actions/workflows/checks.yaml/badge.svg)](https://github.com/MortalFlesh/console-style/actions/workflows/checks.yaml)\n\n\u003e One of the most boring tasks when creating console commands is to deal with the styling of the command's input and output. Displaying titles and tables or asking questions to the user involves a lot of repetitive code.\n\n\u003e This library is inspired by [SymfonyStyle](https://symfony.com/doc/current/console/style.html).\n\n## Installation\n```sh\ndotnet add package ConsoleStyle\n```\n\n## Basic Usage\n```fs\nopen MF.ConsoleStyle\n\nlet console = ConsoleStyle()\n\nconsole.Title \"Hello World!\"\n```\nfor output:\n\n    Hello world!\n    ============\n\n---\n\n### Input\n\n#### Ask\n```fs\nlet name = console.Ask \"What's your name?\"\nlet name = console.Ask(\"What's your %s?\", \"name\")\n```\n\nExample:\n```\nWhat's your name? {stdin}\n```\n\n### Output - single\n\n| Function | example | color | note |\n| ---      | ---     | ---   | ---      |\n| `mainTitle` | `console.MainTitle \"ConsoleStyle\"` | cyan | _see output_ 👇 |\n\n```\n  _____                        __        ____  __           __\n / ___/ ___   ___   ___ ___   / / ___   / __/ / /_  __ __  / / ___\n/ /__  / _ \\ / _ \\ (_-\u003c/ _ \\ / / / -_) _\\ \\  / __/ / // / / / / -_)\n\\___/  \\___//_//_//___/\\___//_/  \\__/ /___/  \\__/  \\_, / /_/  \\__/\n                                                  /___/\n\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n```\n| Function | example | color | note |\n| ---      | ---     | ---   | ---      |\n| `title` | `console.Title \"Title of foo\"` | cyan | _see output_ 👇 |\n```\nTitle of foo\n============\n```\n| Function | example | color | note |\n| ---      | ---     | ---   | ---      |\n| `section` | `console.Secion \"Section of foo\"` | dark-yellow | _see output_ 👇 |\n```\nSection of foo\n--------------\n```\n| Function | example | color | note |\n| ---      | ---     | ---   | ---      |\n| `message` | `console.Message \"a simple message\"` | _default_ | |\n| `newLine` | `console.NewLine()` | _default_ | |\n| `subTitle` | `console.SubTitle \"Sub title\"` | yellow | _Text is natively underlined_ |\n| `error` | `console.Error \"Something went wrong!\"` | red | This output goes to the `stderr` |\n| `success` | `console.Success \"Done\"` | green | |\n| `indent` | `console.Indent \"Something indented\"` | _default_ | _adds spaces at the beginning_ |\n\n**NOTE**: most of the functions allows formatted variant with up to 5 args - see [Formatting](#formatting)\n\n### Output - many\n\n| Function | example | color | note |\n| ---      | ---     | ---   | ---      |\n| `messages` | `console.Messages \"-prefix-\" [\"line 1\"; \"line 2\"]` | _default_ | _see output_ 👇 |\n```\n-prefix-line 1\n-prefix-line 2\n```\n| Function | example | color | note |\n| ---      | ---     | ---   | ---      |\n| `options` | `console.Options \"Foo options\" [ [\"first\"; \"desc 1\"]; [\"second\"; \"desc 2\"] ]` | _default_ with yellow title | _see output_ 👇 |\n```\nFoo options\n    - first   desc 1\n    - second  desc 2\n```\n| Function | example | color | note |\n| ---      | ---     | ---   | ---      |\n| `simpleOptions` | `console.SimpleOptions \"Foo options\" [ [\"first\"; \"desc 1\"]; [\"second\", \"desc 2\"] ]` | Same as `options`, but without line prefix. _default_ with yellow title | _see output_ 👇 |\n```\nFoo options\n    first   desc 1\n    second  desc 2\n```\n| Function | example | color | note |\n| ---      | ---     | ---   | ---      |\n| `groupedOptions` | `console.GroupedOptions \":\" \"Grouped options\" [ [\"first\"; \"desc 1\"]; [\"group:first\"; \"desc\"; \"group 1\"]; [\"group:second\"; \"desc\"; \"group 2\"]; [\"second\"; \"desc 2\"] ]` | Grouped options by their prefix, if there is any. _default_ with yellow title | _see output_ 👇 |\n```\nGrouped options\n    first         desc 1\n    second        desc 2\n group\n    group:first   desc    group 1\n    group:second  desc    group 2\n```\n| Function | example | color | note |\n| ---      | ---     | ---   | ---      |\n| `list` | `console.List [\"line 1\"; \"line 2\"]` | _default_ | _see output_ 👇 |\n```\n - line 1\n - line 2\n```\n\n### Formatting\nSince string formatting with `sprintf` is handled by compiler and is not easy to reproduce, there are explicit functions for formatting up to 5 parameters.\nIt is still **type safe** and **compiler friendly** (_only limitation is for number of parameters, but you can still simply use `sprintf` directly_).\n```fs\nconsole.Message(\"Format %s parameter\", \"one\")\nconsole.Message(\"Format %s, %s parameter\", \"one\", \"two\")\nconsole.Message(\"Format %s, %d and %d parameter\", \"one\", 2, 3)\nconsole.Message(sprintf \"Format %s, %s, %s and %s parameter\" \"one\" \"two\" \"three\" \"more ...\")\n```\n**NOTE**: Other functions allowing formatting works the same way.\n\n### Markup in text\nThere is a special _tag_ for formatting a part of text (`\u003cc:COLOR\u003etext\u003c/c\u003e`).\n\nFormatting -\u003e Usage\n- Bold           `\u003cc:|b\u003eBold\u003c/c\u003e`\n- Dim            `\u003cc:|d\u003eDim\u003c/c\u003e`\n- Italic         `\u003cc:|i\u003eItalic\u003c/c\u003e`\n- Underline      `\u003cc:|u\u003eUnderline\u003c/c\u003e`\n- Reverse        `\u003cc:|r\u003eReverse\u003c/c\u003e`\n- StrikeThrough  `\u003cc:|s\u003eStrikeThrough\u003c/c\u003e`\n- Foreground     `\u003cc:COLOR\u003eColored\u003c/c\u003e`\n- Background     `\u003cc:|bg:COLOR\u003eColored\u003c/c\u003e`\n\nCombining formatting:\n- minimal markup is `\u003cc:\u003etext\u003c/c\u003e`\n- colors `\u003cc:black|bg:red\u003etext with black foreground and red background\u003c/c\u003e`\n- bold and underlined `\u003cc:|bu\u003eBold and underlined\u003c/c\u003e`\n- all formatting options `\u003cc:#D20000|bg:blue|bdiurs\u003eOver formatted\u003c/c\u003e`\n\n#### Available colors:\nNamed colors\n\n![Colors](example/rendered/color-groups.png?raw=true \"Colors\")\n\n_TIP_: Given color is normalized, so you can use `-` or `_` as separator or even use different case for colors.\n(_Example: `darkblue` is same as `dark_blue`, `DARK--Blue`, `dark-blue`, ..._)\n\nYou can also use RGB and RGBA color codes\n\n![More Colors](example/rendered/colors.png?raw=true \"More Colors\")\n\n**NOTE**: You can use colors as both foreground and background for a text.\n\n#### Usage\n```fs\nconsole.Message \"Hello \u003cc:green\u003eworld\u003c/c\u003e!\" // `Hello` and `!` will be in default color, and `world` will be green.\nconsole.Message \"\u003cc:red\u003eHello\u003c/c\u003e \u003cc:green\u003eworld\u003c/c\u003e!\"  // Different color for every word.\n\nconsole.SimpleOptions \"Options:\" [\n    [ \"option1\"; \"This is the \u003cc:magenta\u003efirst\u003c/c\u003e option\"; \"\u003cc:yellow\u003e[default: \\\"foo\\\"]\u003c/c\u003e\" ]\n    [ \"option2\"; \"This is the \u003cc:magenta\u003esecond\u003c/c\u003e option\" ]\n]\n```\n\n### Output complex components\n\n#### Table\n```fs\nconsole.Table [ \"FirstName\"; \"Surname\" ] [\n    [ \"Jon\"; \"Snow\" ]\n    [ \"Peter\"; \"Parker\" ]\n]\n```\nOutput:\n```\n----------- ---------\n FirstName   Surname\n----------- ---------\n Jon         Snow\n Peter       Parker\n----------- ---------\n```\n\n#### Tabs\n\u003e See in the [example](/example/) dir\n\n![Tabs](example/rendered/tabs.png?raw=true \"Tabs\")\n\n```fs\n// First line\n[ \"red\"; \"green\"; \"yellow\"; \"blue\"; \"purple\"; \"orange\"; \"gray\" ]\n|\u003e List.map (fun color -\u003e { Tab.parseColor color \"Sample\" with Value = Some color })\n|\u003e console.Tabs\n\n// Second line\n[ \"#ed1017\"; \"#67c355\"; \"#f3d22b\"; \"#1996f0\"; \"#9064cb\"; \"#ff9603\"; \"#babab8\" ]\n|\u003e List.map (fun color -\u003e { Tab.parseColor color \"Sample\" with Value = Some color })\n|\u003e fun tabs -\u003e console.Tabs(tabs, 10)\n\n// Third line\n[\n    \"#ed1017\", \"#9e2e22\"\n    \"#67c355\", \"#087a3f\"\n    \"#f3d22b\", \"#faa727\"\n    \"#1996f0\", \"#0278be\"\n    \"#9064cb\", \"#6a3390\"\n    \"#ff9603\", \"#faa727\"\n    \"#babab8\", \"#333333\"\n]\n|\u003e List.mapi (fun i (color, darker) -\u003e {\n    Tab.parseColor color (sprintf \"\u003cc:dark-gray|bg:%s|ub\u003eMetric\u003c/c\u003e\" color)\n        with Value = Some \u003c| sprintf \"\u003cc:magenta|bg:%s\u003e %02d \u003c/c\u003e\u003cc:|bg:%s\u003e%% \u003c/c\u003e\" darker (i * 10) darker\n    }\n)\n|\u003e fun tabs -\u003e console.Tabs(tabs, 10)\n```\n\n### Progress bar\n\u003e For more info see https://github.com/Mpdreamz/shellprogressbar\n\n```fs\nlet total = 10\nlet progressBar = console.ProgressStart \"Starting...\" total\n\nfor _ in 1 .. total do\n    console.ProgressAdvance progressBar\n\nconsole.ProgressFinish progressBar\n```\n\n**TIP**: For more examples (_async, with children, etc_) see the `example/Program.fs`\n\n## Styling\nThere is a `Style` settings where you can set up some attributes\n```fs\ntype Style = {\n    /// Whether and how to show a date time\n    ShowDateTime: ShowDateTime\n\n    /// Underline used for main title\n    MainTitleUnderline: Underline\n\n    /// Underline used for title\n    TitleUnderline: Underline\n\n    /// Underline used for section\n    SectionUnderline: Underline\n\n    /// Indentation used in many places (options, date time, ...)\n    Indentation: Indentation\n\n    /// Block length is shared for all blocks (success, warning, ...)\n    BlockLength: int\n\n    /// Custom tags, available in the markup\n    CustomTags: CustomTag list\n}\n\nlet console = ConsoleStyle(style)\n```\n\n**NOTE**: There is also a default styles which you can just override\n```fs\nlet enhancedStyle = { Style.defaults with Indentation = Indentation \"  \" }\n```\n\n### Custom tags\n\u003e See more in the [example](/example/) dir\n\n![Custom Tags](example/rendered/custom-tags.png?raw=true \"Custom Tags\")\n\n```fs\nlet style = {\n    Style.defaults with\n        CustomTags = [\n            CustomTag.createWithMarkup (TagName \"customTag\") {\n                Bold = true\n                Dim = true\n                Italic = true\n                Underline = true\n                Reverse = true\n                StrikeThrough = true\n                Foreground = Some \"black\"\n                Background = Some \"red\"\n            }\n            CustomTag.createAndParseMarkup (TagName \"service\") \":#0b6695|bg:#f79333|u\" |\u003e orFail\n            {\n                Tag = TagName \"name\"\n                Markup = MarkupString.create \"#23ae91\"\n            }\n        ]\n}\n\nlet console = ConsoleStyle(style)\n\nconsole.Section \"Custom tags\"\nconsole.Message (\"Now the \u003ccustomTag\u003ecustom tags\u003c/customTag\u003e example\")\nconsole.Table [ \"Tag\"; \"Value\" ] [\n    [ \"service\"; \"\u003cservice\u003edomain-context\u003c/service\u003e\" ]\n    [ \"name\"; \"\u003cname\u003eJon Snow\u003c/name\u003e\" ]\n]\n```\n\n**NOTE**: There are default custom tags for a simplification of some basic formatting\n    - `number` to style numbers (`\u003cc:magenta\u003e`)\n    - `u` for underline (`\u003cc:|u\u003e`)\n    - `b` for bold (`\u003cc:|b\u003e`)\n    - `i` for italic (`\u003cc:|i\u003e`)\n\n## Output\nThere are multiple outputs available\n- Console - prints output with `Console.Write` functions (**Default**)\n- Print - prints output with `printf` and `eprintf` functions\n- Buffered - buffer every write into string and offers it on `Fetch` method\n- Stream - writes to the given `System.IO.Stream`\n- NoMarkup - writes to the given `IOutput` and remove markup by given `Style`\n- _Combined_ - combination of other outputs\n\n### Usage\n```fs\nuse bufferedOutput = Output.BufferOutput(Verbosity.Normal)\nlet console = ConsoleStyle(bufferedOutput)\n\nconsole.Message(\"Hello\")\n\nlet content: string = bufferedOutput.Fetch()\n```\n\n## Verbosity\nThere are 5 levels of verbosity and every higher (_more verbose_) level will just add more information to previous - meaning, that `VeryVerbose` = `Normal` + `Verbose` + _More_ and so on (_except of `Quiet` which is oposite_)\n\n    Level =\n        | Quiet\n        | Normal\n        | Verbose\n        | VeryVerbose\n        | Debug\n\nDefault level is `Normal`\n\nSome functions have a different output based on current verbosity level\n\nOn `Quiet` only input functions will show an output, no other output is shown (_some components are not even inicialized_)\n- `ask` function will show a _question_\n\nFrom `VeryVerbose` it shows time (and date on `Debug`) on the start of each line (_not for multiline outputs_)\n\n**Note**: not every level adds information to output\n\n### Usage\nYou can set a level of verbosity by\n```fs\nlet console = ConsoleStyle(Verbosity.Verbose)\n\n// or change it on the fly\nconsole.Verbosity \u003c- Verbosity.Verbose\n```\n\nYou can use a verbosity level in your application directly by\n```fs\nconsole.IsQuiet()\nconsole.IsNormal()\nconsole.IsVerbose()\nconsole.IsVeryVerbose()\nconsole.IsDebug()\n```\n\n### Example\nAs it was mentioned before, each level is addition to previous, so we have (except of `Quiet`)\n\n| ⬇️ _function_ AND _level_ ➡️ | `Quiet`  | `Normal` | `Verbose` | `VeryVerbose` | `Debug` |\n| ---                         | ---      | ---      | ---       | ---           | ---     |\n| `IsQuiet()`                 | **true** | false    | false     | false         | false   |\n| `IsNormal()`                | false    | **true** | **true**  | **true**      | **true**|\n| `IsVerbose()`               | false    | false    | **true**  | **true**      | **true**|\n| `IsVeryVerbose()`           | false    | false    | false     | **true**      | **true**|\n| `IsDebug()`                 | false    | false    | false     | false         | **true**|\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmortalflesh%2Fconsole-style","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmortalflesh%2Fconsole-style","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmortalflesh%2Fconsole-style/lists"}