Code/Dependencies/Pixie/Pixie/Options/ValueOption.cs
using System;
using System.Collections.Generic;
namespace WasmBox.Pixie.Options {
/// <summary>
/// Describes a value option: an option takes exactly one argument.
/// </summary>
public sealed class ValueOption<T> : Option {
/// <summary>
/// Creates a value option from an option form,
/// a function that parses an argument and a
/// default value.
/// </summary>
/// <param name="form">
/// The option's form.
/// </param>
/// <param name="parseArgument">
/// A function that parses a string argument.
/// </param>
/// <param name="defaultValue">
/// A default value for the value option.
/// </param>
public ValueOption(
OptionForm form,
Func<OptionForm, string, ILog, T> parseArgument,
T defaultValue)
: this(
new OptionForm[] { form },
parseArgument,
defaultValue) { }
/// <summary>
/// Creates a value option from a list of forms,
/// a function that parses an argument and a
/// default value.
/// </summary>
/// <param name="forms">
/// The list of forms that the value option accepts.
/// </param>
/// <param name="parseArgument">
/// A function that parses a string argument.
/// </param>
/// <param name="defaultValue">
/// A default value for the value option.
/// </param>
public ValueOption(
IReadOnlyList<OptionForm> forms,
Func<OptionForm, string, ILog, T> parseArgument,
T defaultValue)
: this(
forms,
parseArgument,
defaultValue,
OptionDocs.DefaultCategory,
"",
new SymbolicOptionParameter("arg", false)) { }
private ValueOption(
IReadOnlyList<OptionForm> forms,
Func<OptionForm, string, ILog, T> parseArgument,
T defaultValue,
string category,
MarkupNode description,
OptionParameter parameter) {
this.forms = forms;
this.parseArgument = parseArgument;
this.defaultValue = defaultValue;
this.category = category;
this.description = description;
this.parameter = parameter;
}
private ValueOption(ValueOption<T> other)
: this(
other.forms,
other.parseArgument,
other.defaultValue,
other.category,
other.description,
other.parameter) { }
private IReadOnlyList<OptionForm> forms;
private Func<OptionForm, string, ILog, T> parseArgument;
private T defaultValue;
private string category;
private MarkupNode description;
private OptionParameter parameter;
/// <summary>
/// Creates a copy of this option that is classified under a
/// particular category.
/// </summary>
/// <param name="category">The new option's category.</param>
/// <returns>An option.</returns>
public ValueOption<T> WithCategory(string category) {
var result = new ValueOption<T>(this);
result.category = category;
return result;
}
/// <summary>
/// Creates a copy of this option that has a particular description.
/// </summary>
/// <param name="description">The new option's description.</param>
/// <returns>An option.</returns>
public ValueOption<T> WithDescription(MarkupNode description) {
var result = new ValueOption<T>(this);
result.description = description;
return result;
}
/// <summary>
/// Creates a copy of this option that has a particular parameter.
/// </summary>
/// <param name="parameter">The new option's sole parameter.</param>
/// <returns>An option.</returns>
public ValueOption<T> WithParameter(OptionParameter parameter) {
var result = new ValueOption<T>(this);
result.parameter = parameter;
return result;
}
/// <inheritdoc/>
public override IReadOnlyList<OptionForm> Forms => forms;
/// <inheritdoc/>
public override object DefaultValue => defaultValue;
/// <inheritdoc/>
public override OptionDocs Documentation =>
new OptionDocs(
category,
description,
forms,
new OptionParameter[] { parameter });
/// <inheritdoc/>
public override OptionParser CreateParser(OptionForm form) {
return new ValueOptionParser<T>(form, parseArgument);
}
/// <inheritdoc/>
public override ParsedOption MergeValues(ParsedOption first, ParsedOption second) {
return second;
}
}
/// <summary>
/// Helps build value options.
/// </summary>
public static class ValueOption {
/// <summary>
/// Creates a string option that takes a single form.
/// </summary>
/// <param name="form">The string option's form.</param>
/// <param name="defaultValue">The default value for the option.</param>
/// <returns>A string option.</returns>
public static ValueOption<string> CreateStringOption(
OptionForm form,
string defaultValue) {
return new ValueOption<string>(
form,
SequenceOption.parseStringArgument,
defaultValue);
}
/// <summary>
/// Creates a string option that takes a list of forms.
/// </summary>
/// <param name="forms">The string option's forms.</param>
/// <param name="defaultValue">The default value for the option.</param>
/// <returns>A string option.</returns>
public static ValueOption<string> CreateStringOption(
IReadOnlyList<OptionForm> forms,
string defaultValue) {
return new ValueOption<string>(
forms,
SequenceOption.parseStringArgument,
defaultValue);
}
/// <summary>
/// Creates a 32-bit signed integer option that takes a single form.
/// </summary>
/// <param name="form">The 32-bit signed integer option's form.</param>
/// <param name="defaultValue">The default value for the option.</param>
/// <returns>A 32-bit signed integer option.</returns>
public static ValueOption<int> CreateInt32Option(
OptionForm form,
int defaultValue) {
return new ValueOption<int>(
form,
SequenceOption.parseInt32Argument,
defaultValue);
}
/// <summary>
/// Creates a 32-bit signed integer option that takes a list of forms.
/// </summary>
/// <param name="forms">The 32-bit signed integer option's forms.</param>
/// <param name="defaultValue">The default value for the option.</param>
/// <returns>A 32-bit signed integer option.</returns>
public static ValueOption<int> CreateInt32Option(
IReadOnlyList<OptionForm> forms,
int defaultValue) {
return new ValueOption<int>(
forms,
SequenceOption.parseInt32Argument,
defaultValue);
}
}
internal sealed class ValueOptionParser<T> : OptionParser {
public ValueOptionParser(
OptionForm form,
Func<OptionForm, string, ILog, T> parseArgument) {
this.form = form;
this.parseArgument = parseArgument;
this.argument = null;
}
private OptionForm form;
private Func<OptionForm, string, ILog, T> parseArgument;
private string argument;
public override object GetValue(ILog log) {
return parseArgument(form, argument, log);
}
public override bool Parse(string argument) {
// Accept exactly one argument.
if (this.argument == null) {
this.argument = argument;
return true;
}
else {
return false;
}
}
}
}