{"id":23112942,"url":"https://github.com/vbfox/masteroffoo","last_synced_at":"2025-08-16T19:31:33.929Z","repository":{"id":51805744,"uuid":"69166139","full_name":"vbfox/MasterOfFoo","owner":"vbfox","description":"An F# library to allow using printf style strings in more places.","archived":false,"fork":false,"pushed_at":"2024-09-06T08:40:51.000Z","size":576,"stargazers_count":11,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-06T18:23:46.937Z","etag":null,"topics":["fsharp","printf"],"latest_commit_sha":null,"homepage":"","language":"F#","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/vbfox.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":".github/CODEOWNERS","security":null,"support":null}},"created_at":"2016-09-25T13:31:23.000Z","updated_at":"2024-09-08T15:46:10.000Z","dependencies_parsed_at":"2022-08-23T08:40:23.224Z","dependency_job_id":null,"html_url":"https://github.com/vbfox/MasterOfFoo","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbfox%2FMasterOfFoo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbfox%2FMasterOfFoo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbfox%2FMasterOfFoo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbfox%2FMasterOfFoo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vbfox","download_url":"https://codeload.github.com/vbfox/MasterOfFoo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230051539,"owners_count":18165251,"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":["fsharp","printf"],"created_at":"2024-12-17T02:21:09.832Z","updated_at":"2024-12-17T02:21:10.373Z","avatar_url":"https://github.com/vbfox.png","language":"F#","readme":"﻿# MasterOfFoo\n\n![\"f\" Logo](https://raw.githubusercontent.com/vbfox/MasterOfFoo/master/src/BlackFox.MasterOfFoo/Icon.png)\n\n\n[![Github Actions Status](https://github.com/vbfox/MasterOfFoo/actions/workflows/main.yml/badge.svg)](https://github.com/vbfox/MasterOfFoo/actions/workflows/main.yml?query=branch%3Amaster)\n[![Nuget Package](https://img.shields.io/nuget/v/BlackFox.MasterOfFoo.svg)](https://www.nuget.org/packages/BlackFox.MasterOfFoo)\n\nA library to allow using `printf` style strings in more places.\n\nThe code is essentially an extracted version of [`printf.fs`][printf_fs] where the environement can not only decide\nwhat to do with the final blocks that compose the string (printf put them on the console, sprintf in a buffer, ...)\nbut also what to do with the parameters passed for each format specifier.\n\n## Sample usage\n\n```fsharp\nmodule MyModule =\n    open System.Text\n    open BlackFox.MasterOfFoo\n    type private MySprintfEnv() =\n        inherit PrintfEnv\u003cunit, string, string\u003e()\n        let buf = StringBuilder()\n        override this.Finalize() = buf.ToString ()\n        override this.Write(s : PrintableElement) = ignore(buf.Append(s.FormatAsPrintF()))\n        override this.WriteT(s : string) = ignore(buf.Append(s))\n\n    let mysprintf (format: Format\u003c'T, unit, string, string\u003e) =\n        doPrintfFromEnv format (MySprintfEnv())\n\nMyModule.mysprintf \"Hello %s.\" \"World\"\n```\n\n## Mini-Doc\n\n### PrintableElement\n\n`PrintableElement` represent an element in a string, for example `sprintf \"Foo %s bar\" \"x\"` produce 3\n`PrintableElement`, the first contains the string `\"Foo \"` the second is a format specifier `'s'` with an associated\nstring value `\"x\"` and then there is the string  the string `\" Bar\"`.\n\nMembers :\n\n* `ElementType`: Tell your if this is a string or a format specifier.\n* `Value`: give the value if it was a format specifier.\n* `ValueType`: give the type of value expected by the format specifier.\n* `StarWidth`: The width if specified via another parameter as in \"%*i\".\n* `StarPrecision`: The precision if specified via another parameter as in \"%.*f\".\n* `FormatAsPrintF()`: Get the string representation that printf would have normally generated.\n* `Specifier`: The format specification for format specifiers.\n\n### PrintfEnv\n\n`PrintfEnv` is the type to implement to create a printf variant it has 3 type parameters:\n\n* `'State`: The state of the printer, passed as argument when using '%t'.\n* `'Residue`: The type that methods passed to '%t' must return.\n* `'Result`: The final result type for the printer.\n\nMembers:\n* `Finalize`: Create the final result for this printer\n* `Write`: Write an element from the format string to the printer\n* `WriteT`: Write the result of the method provided by %t to the printer.\n\n### Functions\n\n* `doPrintfFromEnv`: Take a format and a `PrintfEnv` to create a printf-like function\n* `doPrintf`: Same as `doPrintfFromEnv` but allow to know the number of elements when the `PrintfEnv` is created.\n\n## FAQ\n\n### What does it allow exactly that can't be done with the original set of functions ?\n\n* Generating complex object that aren't only a string like an `SqlCommand` or structured logging.\n* Escaping parts in strings, like an `xmlprintf` that would escape `\u003c` to `\u0026lt` in parameters but not in the format\n  string.\n\n### What are the limitations ?\n\nThe main limitation is that the F# compiler allow a strict set of things an you can't go differently.\nThe function signature that is the first argument to `Format\u003c_,_,_,_,\u003e` is generated from rules in the compiler and no\nlibrary can change them.\n\nThe consequence is that we're limited to what is present in the F# compiler, can't add a `%Z` or allow `%0s` to work.\n\n### Aren't you just replicating `ksprintf` ?\n\n`ksprintf` allow you to run code on the final generated result, essentially allowing you to run code during\n`PrintfEnv.Finalize` but you can't manipualte the format specifiers or their parameters.\n\n### What this `Star` syntax\n\nWhen `*` is specified for either the width or the precision an additional parameter is taken by the format to get the\nvalue.\n\n````\n\u003e sprintf \"%*.*f\";;\nval it : (int -\u003e int -\u003e float -\u003e string) = \u003cfun:it@1\u003e\n````\n\n### How are interpolated strings represented ?\n\nThe details of string interpolation internals are specified in [F# RFC FS-1001 - String Interpolation][fs-1001].\n\nThey appear as follow in this library:\n* Type-checked \"printf-style\" fills behave exactly as they do in `sprintf` and friends.\n* Unchecked \".NET-style\" fills appear with a `Specifier.TypeChar` of `'P'` and the .NET format string\n  in `Specifier.InteropHoleDotNetFormat`.\n\n[fs-1001]: https://github.com/fsharp/fslang-design/blob/aca88da13cdb95f4f337d4f7d44cbf9d343704ae/FSharp-5.0/FS-1001-StringInterpolation.md#f-rfc-fs-1001---string-interpolation\n\n## Projects using it\n\n* [ColoredPrintf][colorprintf]: A small library that I created to add colored parts to printf strings.\n\n*If you use it somewhere, ping me on the fediverse [@vbfox@hachyderm.io][fedi] so I can add you.*\n\nMore fun ?\n----------\n\n```fsharp\nmodule ColorPrintf =\n    open System\n    open System.Text\n    open BlackFox.MasterOfFoo\n\n    type private Colorize\u003c'Result\u003e(k) =\n        inherit PrintfEnv\u003cunit, string, 'Result\u003e()\n        override this.Finalize() : 'Result = k()\n        override this.Write(s : PrintableElement) =\n            match s.ElementType with\n            | PrintableElementType.FromFormatSpecifier -\u003e\n                let color = Console.ForegroundColor\n                Console.ForegroundColor \u003c- ConsoleColor.Blue\n                Console.Write(s.FormatAsPrintF())\n                Console.ForegroundColor \u003c- color\n            | _ -\u003e Console.Write(s.FormatAsPrintF())\n        override this.WriteT(s : string) =\n            let color = Console.ForegroundColor\n            Console.ForegroundColor \u003c- ConsoleColor.Red\n            Console.Write(s)\n            Console.ForegroundColor \u003c- color\n\n    let colorprintf (format: Format\u003c'T, unit, string, unit\u003e) =\n        doPrintfFromEnv format (Colorize id)\n\nColorPrintf.colorprintf \"%s est %t\" \"La vie\" (fun _ -\u003e \"belle !\")\n```\n\n[printf_fs]: https://github.com/dotnet/fsharp/blob/main/src/FSharp.Core/printf.fs\n[fedi]: https://hachyderm.io/@vbfox\n[colorprintf]: https://github.com/vbfox/ColoredPrintf\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbfox%2Fmasteroffoo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvbfox%2Fmasteroffoo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbfox%2Fmasteroffoo/lists"}