FormatMore 1.0.0

dotnet add package FormatMore --version 1.0.0                
NuGet\Install-Package FormatMore -Version 1.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FormatMore" Version="1.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add FormatMore --version 1.0.0                
#r "nuget: FormatMore, 1.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install FormatMore as a Cake Addin
#addin nuget:?package=FormatMore&version=1.0.0

// Install FormatMore as a Cake Tool
#tool nuget:?package=FormatMore&version=1.0.0                

FormatMore

A library that offers an alternative to the String.Format method from .NET with added support for formatting lists of items.

Quick Start

Download and reference FormatMore.dll. You can also find it on NuGet.

Add

using FormatMoreUtilities;

(or the appropriate equivalent command in your language of choice) to your file.

Then, invoke FormatMore.Format to format strings. Have a look at the examples further down in this file for some samples of the extended format string features, as well as the full syntax specification in the next section. The FormatMore.Sample and FormatMore.Test` projects can also provide some insight.

Any format strings usable with string.Format can also be passed to FormatMore.Format.

Full Syntax Specification

The String.Format method of .NET defines a format item as

{index[,alignment][:formatString]}

The FormatMore library provides an alternative FormatMore.Format method that accepts extended format items:

{index[listFormat][,alignment][:formatString]}

The additional listFormat element applies to arguments that can be converted to System.Collections.IEnumerable. It is defined as follows:

  • It starts with an opening square bracket [.
  • It may contain any number of arguments that are separated with the pipe character |.
  • The first argument specifies the item count. It is a positive number (e.g. 15) or a number range of the form 2..5. This argument is optional.
  • Any further arguments start with a single identifying character that may be followed by any number of characters.
  • Closing square brackets ] and pipe symbols | within these arguments can be escaped by duplicating them.
  • It ends with a closing square bracket ].
  • It may be followed by an optional question mark ? to indicate that list formatting is optional. In this case, non-enumerable argument values will be formatted as specified while ignoring the list formatting options. (Without the optional marker, applying list formatting options to non-enumerable argument values will cause a FormatException.)

Multiple list format elements may be used to format nested enumerables.

Item Count

If the item count is specified as a single integer number, it indicates the maximum number of items to output. If the enumerable contains more items, a more items marker will be appended.

If the item count is specified as an integer range (e.g. 8..10), the upper bound of the range indicates the maximum number of items to output. If the enumerable contains more items, only the number of items specified as the lower bound of the range will be output. Also, a more items marker will be appended.

If no item count is specified, all items from the enumeration will be output.

Further Arguments

The following table lists additionally supported arguments along with their identifying characters.

Identifying Character Meaning
a Specifies a string that is inserted after each item.
b Specifies a string that is inserted before each item.
d Specifies the delimiter to use between items of the enumerable.
D Specifies an individual delimiter between items. Use indexed values (see below) to indicate which delimiter you would like to define, with the index referring to the delimiters between actually output items.<br />You may specify several D arguments to assign delimiters for different indexes.
e If the enumerable contains no items, the alternative text from this argument will be used instead.
m If the enumerable contains more items than can be displayed as per Item Count, this string will be appended after the items.
p Replaces the list format with settings from a preset.
r If the enumerable contains more items than can be displayed as per Item Count, this string will be appended as an additional item representing the remainder of the items.

If any of these arguments appears multiple times, they will be considered in their order of occurrence.

Indexed Values

An indexed value is specified in the form

index[/condition]=value

In there:

  • index is an integer number. Count the index from zero upwards to reference indexes from the start of the collection, and from -1 downwards to start from the end.
  • condition is an optional condition that checks the total number of items available in the source enumerable. The condition consists of one of the operators <, >, or = (if no operator is specified, = will be assumed), followed by an integer number that is compared to the total number of items.
  • value is the resulting value for the specified index if the condition is met.

Presets

It is possible to store certain frequently occurring list formatting instructions as reusable presets. For this purpose, invoke the static RegisterListFormatPreset method:

FormatMore.RegisterListFormatPreset("CommaList", "[d, |D0/2= and |D-1=, and ]");

You can then reference this preset in your list formatting settings:

FormatMore.Format(
  "The proposal was supported by {0[pCommaList]}, while it was rejected by {1[pCommaList]}.",
  proNames, conNames);

As the specifics of how different types of lists are formatted considerably depend on the display language, the preset formatting can be stored in localization data. Individual localized format strings can then be written in a fairly simple manner, by referring to the named preset.

Examples

Sum

All items from the enumerable are output and joined with the specified delimiter.

var format = "{0[d + ]}";

Console.WriteLine(FormatMore.Format(format,
  new object[] { new[] { 1, 2 } }));
// 1 + 2
Console.WriteLine(FormatMore.Format(format,
  new object[] { new[] { 1, 2, 4 } }));
// 1 + 2 + 4
Console.WriteLine(FormatMore.Format(format,
  new object[] { new[] { 1, 2, 4, 8, 16 } }));
// 1 + 2 + 4 + 8 + 16

Shortened List

The output list is shortened once it exceeds three items.

var format = "{0[3|d;|m...]}";

Console.WriteLine(FormatMore.Format(format,
  new object[] { new[] { 1, 2 } }));
// 1;2
Console.WriteLine(FormatMore.Format(format,
  new object[] { new[] { 1, 2, 4 } }));
// 1;2;4
Console.WriteLine(FormatMore.Format(format,
  new object[] { new[] { 1, 2, 4, 8, 16 } }));
// 1;2;4...

Text Enumeration

The enumeration is properly formatted for a natural language text (depending on which styleguide is used, but that question is out of scope here). Note how the case of two items is treated separately.

var format = "My pizza topping consists of {0[2|d, |rothers|D0/2= and |D-1=, and ]}.";
var ingredients = new[] { "tomatoes", "mushrooms", "onions", "sliced sausages", "spinach leaves" };

Console.WriteLine(FormatMore.Format(format, new object[] { ingredients.Take(1) }));
// My pizza topping consists of tomatoes.
Console.WriteLine(FormatMore.Format(format, new object[] { ingredients.Take(2) }));
// My pizza topping consists of tomatoes and mushrooms.
Console.WriteLine(FormatMore.Format(format, new object[] { ingredients.Take(3) }));
// My pizza topping consists of tomatoes, mushrooms, and others.
Console.WriteLine(FormatMore.Format(format, new object[] { ingredients.Take(5) }));
// My pizza topping consists of tomatoes, mushrooms, and others.

Authors List

Author names are formatted according to the conventions of some widespread styleguides for scientific publications. Up to three authors are spelt out, but for anything above, only the first author and the remark "et al." are output.

var format = "{0[1..3|d, |D0/2= and |D-1=, and |m et al.]}";
(string GivenName, string Surname)[] authors =
{
    ("Eddie", "Example"),
    ("Sue", "Sample"),
    ("Bert", "Beispiel"),
    ("Eduardo", "Ejemplo")
};
var formattedAuthors = authors.Select(a => $"{a.GivenName[0]}. {a.Surname}");

Console.WriteLine(FormatMore.Format(format, new object[] { formattedAuthors.Take(1) }));
// E. Example
Console.WriteLine(FormatMore.Format(format, new object[] { formattedAuthors.Take(2) }));
// E. Example and S. Sample
Console.WriteLine(FormatMore.Format(format, new object[] { formattedAuthors.Take(3) }));
// E. Example, S. Sample, and B. Beispiel
Console.WriteLine(FormatMore.Format(format, new object[] { formattedAuthors.Take(4) }));
// E. Example et al.

This example also demonstrates that the list formatting focuses on formatting of the actual list rather than its items. If you wish to perform further formatting on the individual items, it is adviseable to do this before passing them to the Format method, as done here by means of some LINQ-based processing.

Logical Formula in DNF

The b and a options are used to insert brackets around subterms. The format string makes use of two list format specifications to format the two nested levels of enumerables.

var format = "{0[d or |b(|a)][d and ]}";
var terms = new[] { new[] { "A", "not B", "C" }, new[] { "not A", "B", "not C", "D" } };

Console.WriteLine(FormatMore.Format(format, new object[] { terms }));
// (A and not B and C) or (not A and B and not C and D)

License

The FormatMore library is published under the terms of the MIT license.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 267 1/3/2022