diff --git a/appveyor.yml b/appveyor.yml
index 827ded7f..ff6d4476 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,6 +1,6 @@
#version should be only changed with RELEASE eminent, see RELEASE.md
-version: 2.7.83-beta-{build}
+version: 2.8.0-beta-{build}
image: Visual Studio 2019
@@ -15,8 +15,23 @@ init:
if ($env:APPVEYOR_REPO_TAG -eq "true") {
$ver = $env:APPVEYOR_REPO_TAG_NAME
if($ver.StartsWith("v") -eq $true) { $ver = $ver.Substring(1) }
- Update-AppveyorBuild -Version $ver
+ $env:PACKAGE_VERSION = $ver
+ } else {
+ $env:PACKAGE_VERSION = $env:APPVEYOR_BUILD_VERSION
}
+ - ps: |
+ Write-Host "PACKAGE_VERSION:$env:PACKAGE_VERSION | APPVEYOR_BUILD_VERSION='$env:APPVEYOR_BUILD_VERSION'" -ForegroundColor Yellow
+ Write-Host "APPVEYOR_REPO_TAG_NAME:$env:APPVEYOR_REPO_TAG_NAME'" -ForegroundColor Yellow
+
+skip_commits:
+ files:
+ - docs/*
+ - art/*
+ - '**/*.md'
+ #- .travis.yml
+ - .gitignore
+ - .editorconfig
+ message: /updated readme.*|update readme.*s|update docs.*|update version.*|update changelog.*/
environment:
matrix:
@@ -24,13 +39,13 @@ environment:
- BUILD_TARGET: fsharp
build_script:
-- cmd: dotnet build src/CommandLine/ -c Release --version-suffix %APPVEYOR_BUILD_VERSION% /p:BuildTarget=%BUILD_TARGET%
+- cmd: dotnet build src/CommandLine/ -c Release --version-suffix %PACKAGE_VERSION% /p:BuildTarget=%BUILD_TARGET%
test_script:
- cmd: dotnet test tests/CommandLine.Tests/ /p:BuildTarget=%BUILD_TARGET%
after_test:
-- cmd: dotnet pack src/CommandLine/ -c Release --version-suffix %APPVEYOR_BUILD_VERSION% /p:BuildTarget=%BUILD_TARGET%
+- cmd: dotnet pack src/CommandLine/ -c Release --version-suffix %PACKAGE_VERSION% /p:BuildTarget=%BUILD_TARGET%
artifacts:
- path: 'src/CommandLine/bin/Release/*.nupkg'
@@ -57,3 +72,4 @@ deploy:
artifact: 'NuGetPackages'
on:
APPVEYOR_REPO_TAG: true
+
diff --git a/demo/ReadText.Demo/Options.cs b/demo/ReadText.Demo/Options.cs
index ed4db350..3b14014a 100644
--- a/demo/ReadText.Demo/Options.cs
+++ b/demo/ReadText.Demo/Options.cs
@@ -27,7 +27,7 @@ interface IOptions
string FileName { get; set; }
}
- [Verb("head", HelpText = "Displays first lines of a file.")]
+ [Verb("head", true, HelpText = "Displays first lines of a file.")]
class HeadOptions : IOptions
{
public uint? Lines { get; set; }
@@ -62,4 +62,4 @@ class TailOptions : IOptions
public string FileName { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/src/CommandLine/CommandLine.csproj b/src/CommandLine/CommandLine.csproj
index b05cbb04..4dac1db1 100644
--- a/src/CommandLine/CommandLine.csproj
+++ b/src/CommandLine/CommandLine.csproj
@@ -4,20 +4,20 @@
CommandLine
Library
netstandard2.0;net40;net45;net461
- $(DefineConstants);CSX_EITHER_INTERNAL;CSX_REM_EITHER_BEYOND_2;CSX_ENUM_INTERNAL;ERRH_INTERNAL;ERRH_DISABLE_INLINE_METHODS;CSX_MAYBE_INTERNAL;CSX_REM_EITHER_FUNC;CSX_REM_CRYPTORAND
+ $(DefineConstants);CSX_EITHER_INTERNAL;CSX_REM_EITHER_BEYOND_2;CSX_ENUM_INTERNAL;ERRH_INTERNAL;CSX_MAYBE_INTERNAL;CSX_REM_EITHER_FUNC;CSX_REM_CRYPTORAND;ERRH_ADD_MAYBE_METHODS
$(DefineConstants);SKIP_FSHARP
true
..\..\CommandLine.snk
true
CommandLineParser
CommandLineParser.FSharp
- gsscoder;nemec;ericnewton76
+ gsscoder;nemec;ericnewton76;moh-hassan
Command Line Parser Library
$(VersionSuffix)
0.0.0
Terse syntax C# command line parser for .NET. For FSharp support see CommandLineParser.FSharp. The Command Line Parser Library offers to CLR applications a clean and concise API for manipulating command line arguments and related tasks.
Terse syntax C# command line parser for .NET with F# support. The Command Line Parser Library offers to CLR applications a clean and concise API for manipulating command line arguments and related tasks.
- Copyright (c) 2005 - 2018 Giacomo Stelluti Scala & Contributors
+ Copyright (c) 2005 - 2020 Giacomo Stelluti Scala & Contributors
License.md
CommandLine20.png
https://github.com/commandlineparser/commandline
diff --git a/src/CommandLine/Core/InstanceBuilder.cs b/src/CommandLine/Core/InstanceBuilder.cs
index 4aff4080..0ae564b5 100644
--- a/src/CommandLine/Core/InstanceBuilder.cs
+++ b/src/CommandLine/Core/InstanceBuilder.cs
@@ -98,10 +98,10 @@ public static ParserResult Build(
var validationErrors = specPropsWithValue.Validate(SpecificationPropertyRules.Lookup(tokens));
var allErrors =
- tokenizerResult.SuccessfulMessages()
+ tokenizerResult.SuccessMessages()
.Concat(missingValueErrors)
- .Concat(optionSpecPropsResult.SuccessfulMessages())
- .Concat(valueSpecPropsResult.SuccessfulMessages())
+ .Concat(optionSpecPropsResult.SuccessMessages())
+ .Concat(valueSpecPropsResult.SuccessMessages())
.Concat(validationErrors)
.Concat(setPropertyErrors)
.Memoize();
diff --git a/src/CommandLine/Core/InstanceChooser.cs b/src/CommandLine/Core/InstanceChooser.cs
index 86917233..f3ab9b99 100644
--- a/src/CommandLine/Core/InstanceChooser.cs
+++ b/src/CommandLine/Core/InstanceChooser.cs
@@ -23,6 +23,15 @@ public static ParserResult Choose(
bool autoVersion,
IEnumerable nonFatalErrors)
{
+ var verbs = Verb.SelectFromTypes(types);
+ var defaultVerbs = verbs.Where(t => t.Item1.IsDefault);
+
+ int defaultVerbCount = defaultVerbs.Count();
+ if (defaultVerbCount > 1)
+ return MakeNotParsed(types, new MultipleDefaultVerbsError());
+
+ var defaultVerb = defaultVerbCount == 1 ? defaultVerbs.First() : null;
+
Func> choose = () =>
{
var firstArg = arguments.First();
@@ -31,25 +40,52 @@ public static ParserResult Choose(
nameComparer.Equals(command, firstArg) ||
nameComparer.Equals(string.Concat("--", command), firstArg);
- var verbs = Verb.SelectFromTypes(types);
-
return (autoHelp && preprocCompare("help"))
? MakeNotParsed(types,
MakeHelpVerbRequestedError(verbs,
arguments.Skip(1).FirstOrDefault() ?? string.Empty, nameComparer))
: (autoVersion && preprocCompare("version"))
? MakeNotParsed(types, new VersionRequestedError())
- : MatchVerb(tokenizer, verbs, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, nonFatalErrors);
+ : MatchVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, nonFatalErrors);
};
return arguments.Any()
? choose()
- : MakeNotParsed(types, new NoVerbSelectedError());
+ : (defaultVerbCount == 1
+ ? MatchDefaultVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, nonFatalErrors)
+ : MakeNotParsed(types, new NoVerbSelectedError()));
+ }
+
+ private static ParserResult MatchDefaultVerb(
+ Func, IEnumerable, Result, Error>> tokenizer,
+ IEnumerable> verbs,
+ Tuple defaultVerb,
+ IEnumerable arguments,
+ StringComparer nameComparer,
+ bool ignoreValueCase,
+ CultureInfo parsingCulture,
+ bool autoHelp,
+ bool autoVersion,
+ IEnumerable nonFatalErrors)
+ {
+ return !(defaultVerb is null)
+ ? InstanceBuilder.Build(
+ Maybe.Just>(() => defaultVerb.Item2.AutoDefault()),
+ tokenizer,
+ arguments,
+ nameComparer,
+ ignoreValueCase,
+ parsingCulture,
+ autoHelp,
+ autoVersion,
+ nonFatalErrors)
+ : MakeNotParsed(verbs.Select(v => v.Item2), new BadVerbSelectedError(arguments.First()));
}
private static ParserResult MatchVerb(
Func, IEnumerable, Result, Error>> tokenizer,
IEnumerable> verbs,
+ Tuple defaultVerb,
IEnumerable arguments,
StringComparer nameComparer,
bool ignoreValueCase,
@@ -71,7 +107,7 @@ private static ParserResult MatchVerb(
autoHelp,
autoVersion,
nonFatalErrors)
- : MakeNotParsed(verbs.Select(v => v.Item2), new BadVerbSelectedError(arguments.First()));
+ : MatchDefaultVerb(tokenizer, verbs, defaultVerb, arguments, nameComparer, ignoreValueCase, parsingCulture, autoHelp, autoVersion, nonFatalErrors);
}
private static HelpVerbRequestedError MakeHelpVerbRequestedError(
diff --git a/src/CommandLine/Core/SpecificationPropertyRules.cs b/src/CommandLine/Core/SpecificationPropertyRules.cs
index 9122ee3a..5dc1a406 100644
--- a/src/CommandLine/Core/SpecificationPropertyRules.cs
+++ b/src/CommandLine/Core/SpecificationPropertyRules.cs
@@ -18,12 +18,35 @@ public static IEnumerable, IEnumerable, IEnumerable> EnforceMutuallyExclusiveSetAndGroupAreNotUsedTogether()
+ {
+ return specProps =>
+ {
+ var options =
+ from sp in specProps
+ where sp.Specification.IsOption()
+ let o = (OptionSpecification)sp.Specification
+ where o.SetName.Length > 0
+ where o.Group.Length > 0
+ select o;
+
+ if (options.Any())
+ {
+ return from o in options
+ select new GroupOptionAmbiguityError(new NameInfo(o.ShortName, o.LongName));
+ }
+
+ return Enumerable.Empty();
+ };
+ }
+
private static Func, IEnumerable> EnforceGroup()
{
return specProps =>
@@ -36,14 +59,15 @@ where o.Group.Length > 0
select new
{
Option = o,
- Value = sp.Value
+ Value = sp.Value,
+ DefaultValue = sp.Specification.DefaultValue
};
var groups = from o in optionsValues
group o by o.Option.Group into g
select g;
- var errorGroups = groups.Where(gr => gr.All(g => g.Value.IsNothing()));
+ var errorGroups = groups.Where(gr => gr.All(g => g.Value.IsNothing() && g.DefaultValue.IsNothing()));
if (errorGroups.Any())
{
diff --git a/src/CommandLine/Core/Tokenizer.cs b/src/CommandLine/Core/Tokenizer.cs
index 9fd8863c..ba6f1ef5 100644
--- a/src/CommandLine/Core/Tokenizer.cs
+++ b/src/CommandLine/Core/Tokenizer.cs
@@ -74,7 +74,7 @@ public static Result, Error> ExplodeOptionList(
var flattened = exploded.SelectMany(x => x);
- return Result.Succeed(flattened, tokenizerResult.SuccessfulMessages());
+ return Result.Succeed(flattened, tokenizerResult.SuccessMessages());
}
public static IEnumerable Normalize(
diff --git a/src/CommandLine/Core/Verb.cs b/src/CommandLine/Core/Verb.cs
index 2fb6674d..3a7f12a3 100644
--- a/src/CommandLine/Core/Verb.cs
+++ b/src/CommandLine/Core/Verb.cs
@@ -12,12 +12,17 @@ sealed class Verb
private readonly string name;
private readonly string helpText;
private readonly bool hidden;
+ private readonly bool isDefault;
- public Verb(string name, string helpText, bool hidden = false)
+ public Verb(string name, string helpText, bool hidden = false, bool isDefault = false)
{
- this.name = name ?? throw new ArgumentNullException(nameof(name));
+ if ( string.IsNullOrWhiteSpace(name))
+ throw new ArgumentNullException(nameof(name));
+ this.name = name;
+
this.helpText = helpText ?? throw new ArgumentNullException(nameof(helpText));
this.hidden = hidden;
+ this.isDefault = isDefault;
}
public string Name
@@ -35,12 +40,18 @@ public bool Hidden
get { return hidden; }
}
+ public bool IsDefault
+ {
+ get => isDefault;
+ }
+
public static Verb FromAttribute(VerbAttribute attribute)
{
return new Verb(
attribute.Name,
attribute.HelpText,
- attribute.Hidden
+ attribute.Hidden,
+ attribute.IsDefault
);
}
@@ -54,4 +65,4 @@ select Tuple.Create(
type);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/CommandLine/Error.cs b/src/CommandLine/Error.cs
index e54dbf6a..9359bc91 100644
--- a/src/CommandLine/Error.cs
+++ b/src/CommandLine/Error.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
namespace CommandLine
{
@@ -74,7 +75,16 @@ public enum ErrorType
///
/// Value of type.
///
- MissingGroupOptionError
+ MissingGroupOptionError,
+ ///
+
+ /// Value of type.
+ ///
+ MultipleDefaultVerbsError
+
+ /// Value of type.
+ ///
+ GroupOptionAmbiguityError
}
@@ -532,7 +542,7 @@ internal InvalidAttributeConfigurationError()
}
}
- public sealed class MissingGroupOptionError : Error
+ public sealed class MissingGroupOptionError : Error, IEquatable, IEquatable
{
public const string ErrorMessage = "At least one option in a group must have value.";
@@ -555,5 +565,49 @@ public IEnumerable Names
{
get { return names; }
}
+
+ public new bool Equals(Error obj)
+ {
+ var other = obj as MissingGroupOptionError;
+ if (other != null)
+ {
+ return Equals(other);
+ }
+
+ return base.Equals(obj);
+ }
+
+ public bool Equals(MissingGroupOptionError other)
+ {
+ if (other == null)
+ {
+ return false;
+ }
+
+ return Group.Equals(other.Group) && Names.SequenceEqual(other.Names);
+ }
+ }
+
+ public sealed class GroupOptionAmbiguityError : NamedError
+ {
+ public NameInfo Option;
+
+ internal GroupOptionAmbiguityError(NameInfo option)
+ : base(ErrorType.GroupOptionAmbiguityError, option)
+ {
+ Option = option;
+ }
+ }
+
+ ///
+ /// Models an error generated when multiple default verbs are defined.
+ ///
+ public sealed class MultipleDefaultVerbsError : Error
+ {
+ public const string ErrorMessage = "More than one default verb is not allowed.";
+
+ internal MultipleDefaultVerbsError()
+ : base(ErrorType.MultipleDefaultVerbsError)
+ { }
}
}
diff --git a/src/CommandLine/Infrastructure/ErrorHandling.cs b/src/CommandLine/Infrastructure/ErrorHandling.cs
index 142e1461..8aee4bac 100644
--- a/src/CommandLine/Infrastructure/ErrorHandling.cs
+++ b/src/CommandLine/Infrastructure/ErrorHandling.cs
@@ -1,62 +1,17 @@
//Use project level define(s) when referencing with Paket.
-//#define ERRH_INTERNAL // Uncomment this to set visibility to internal.
-//#define ERRH_DISABLE_INLINE_METHODS // Uncomment this to enable method inlining when compiling for >= NET 4.5.
-//#define ERRH_BUILTIN_TYPES // Uncomment this to use built-in Unit type, instead of extenral identical CSharpx.Unit.
+//#define ERRH_INTERNAL // Uncomment or define at build time to set accessibility to internal.
+//#define ERRH_ENABLE_INLINE_METHODS // Uncomment or define at build time to enable method inlining when compiling for >= NET 4.5.
+//#define ERRH_ADD_MAYBE_METHODS // Uncomment or define at build time to add methods that use Maybe type
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.CompilerServices;
-#if !ERRH_BUILTIN_TYPES
+#if ERRH_ADD_MAYBE_METHODS
using CSharpx;
#endif
namespace RailwaySharp.ErrorHandling
{
- #region Unit Type
-#if ERRH_BUILTIN_TYPES
-#if !ERRH_INTERNAL
- public
-#endif
- struct Unit : IEquatable
- {
- private static readonly Unit @default = new Unit();
-
- public bool Equals(Unit other)
- {
- return true;
- }
-
- public override bool Equals(object obj)
- {
- return obj is Unit;
- }
-
- public override int GetHashCode()
- {
- return 0;
- }
-
- public override string ToString()
- {
- return "()";
- }
-
- public static bool operator ==(Unit first, Unit second)
- {
- return true;
- }
-
- public static bool operator !=(Unit first, Unit second)
- {
- return false;
- }
-
- public static Unit Default { get { return @default; } }
- }
-#endif
- #endregion
-
#if !ERRH_INTERNAL
public
#endif
@@ -76,29 +31,28 @@ enum ResultType
#endif
abstract class Result
{
- private readonly ResultType tag;
+ private readonly ResultType _tag;
protected Result(ResultType tag)
{
- this.tag = tag;
+ _tag = tag;
}
public ResultType Tag
{
- get { return tag; }
+ get { return _tag; }
}
public override string ToString()
{
- switch (Tag)
- {
- case ResultType.Ok:
+ switch (Tag) {
+ default:
var ok = (Ok)this;
return string.Format(
"OK: {0} - {1}",
ok.Success,
string.Join(Environment.NewLine, ok.Messages.Select(v => v.ToString())));
- default:
+ case ResultType.Bad:
var bad = (Bad)this;
return string.Format(
"Error: {0}",
@@ -117,22 +71,24 @@ public override string ToString()
#endif
sealed class Ok : Result
{
- private readonly Tuple> value;
+ private readonly Tuple> _value;
public Ok(TSuccess success, IEnumerable messages)
: base(ResultType.Ok)
{
- this.value = Tuple.Create(success, messages);
+ if (messages == null) throw new ArgumentNullException(nameof(messages));
+
+ _value = Tuple.Create(success, messages);
}
public TSuccess Success
{
- get { return value.Item1; }
+ get { return _value.Item1; }
}
public IEnumerable Messages
{
- get { return value.Item2; }
+ get { return _value.Item2; }
}
}
@@ -146,17 +102,19 @@ public IEnumerable Messages
#endif
sealed class Bad : Result
{
- private readonly IEnumerable messages;
+ private readonly IEnumerable _messages;
public Bad(IEnumerable messages)
: base(ResultType.Bad)
{
- this.messages = messages;
+ if (messages == null) throw new ArgumentException(nameof(messages));
+
+ _messages = messages;
}
public IEnumerable Messages
{
- get { return messages; }
+ get { return _messages; }
}
}
@@ -170,6 +128,8 @@ static class Result
///
public static Result FailWith(IEnumerable messages)
{
+ if (messages == null) throw new ArgumentException(nameof(messages));
+
return new Bad(messages);
}
@@ -178,6 +138,8 @@ public static Result FailWith(IEnumerabl
///
public static Result FailWith(TMessage message)
{
+ if (message == null) throw new ArgumentException(nameof(message));
+
return new Bad(new[] { message });
}
@@ -194,6 +156,8 @@ public static Result Succeed(TSuccess va
///
public static Result Succeed(TSuccess value, TMessage message)
{
+ if (message == null) throw new ArgumentException(nameof(message));
+
return new Ok(value, new[] { message });
}
@@ -202,6 +166,8 @@ public static Result Succeed(TSuccess va
///
public static Result Succeed(TSuccess value, IEnumerable messages)
{
+ if (messages == null) throw new ArgumentException(nameof(messages));
+
return new Ok(value, messages);
}
@@ -210,13 +176,13 @@ public static Result Succeed(TSuccess va
///
public static Result Try(Func func)
{
- try
- {
+ if (func == null) throw new ArgumentException(nameof(func));
+
+ try {
return new Ok(
func(), Enumerable.Empty());
}
- catch (Exception ex)
- {
+ catch (Exception ex) {
return new Bad(
new[] { ex });
}
@@ -231,7 +197,7 @@ static class Trial
///
/// Wraps a value in a Success.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Ok(TSuccess value)
@@ -242,7 +208,7 @@ public static Result Ok(TSuccess value)
///
/// Wraps a value in a Success.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Pass(TSuccess value)
@@ -253,29 +219,33 @@ public static Result Pass(TSuccess value
///
/// Wraps a value in a Success and adds a message.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Warn(TMessage message, TSuccess value)
{
+ if (message == null) throw new ArgumentException(nameof(message));
+
return new Ok(value, new[] { message });
}
///
/// Wraps a message in a Failure.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Fail(TMessage message)
{
+ if (message == null) throw new ArgumentException(nameof(message));
+
return new Bad(new[] { message });
}
///
/// Returns true if the result was not successful.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static bool Failed(Result result)
@@ -286,7 +256,7 @@ public static bool Failed(Result result)
///
/// Takes a Result and maps it with successFunc if it is a Success otherwise it maps it with failureFunc.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static TResult Either(
@@ -294,9 +264,11 @@ public static TResult Either(
Func, TResult> failureFunc,
Result trialResult)
{
+ if (successFunc == null) throw new ArgumentException(nameof(successFunc));
+ if (failureFunc == null) throw new ArgumentException(nameof(failureFunc));
+
var ok = trialResult as Ok;
- if (ok != null)
- {
+ if (ok != null) {
return successFunc(ok.Success, ok.Messages);
}
var bad = (Bad)trialResult;
@@ -307,7 +279,7 @@ public static TResult Either(
/// If the given result is a Success the wrapped value will be returned.
/// Otherwise the function throws an exception with Failure message of the result.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static TSuccess ReturnOrFail(Result result)
@@ -325,13 +297,15 @@ public static TSuccess ReturnOrFail(Result
/// Appends the given messages with the messages in the given result.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result MergeMessages(
IEnumerable messages,
Result result)
{
+ if (messages == null) throw new ArgumentException(nameof(messages));
+
Func, Result> successFunc =
(succ, msgs) =>
new Ok(
@@ -347,13 +321,15 @@ public static Result MergeMessages(
/// If the result is a Success it executes the given function on the value.
/// Otherwise the exisiting failure is propagated.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Bind(
Func> func,
Result result)
{
+ if (func == null) throw new ArgumentException(nameof(func));
+
Func, Result> successFunc =
(succ, msgs) => MergeMessages(msgs, func(succ));
@@ -366,7 +342,7 @@ public static Result Bind(
///
/// Flattens a nested result given the Failure types are equal.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Flatten(
@@ -374,46 +350,44 @@ public static Result Flatten(
{
return Bind(x => x, result);
}
-
+
///
/// If the wrapped function is a success and the given result is a success the function is applied on the value.
/// Otherwise the exisiting error messages are propagated.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Apply(
Result, TMessage> wrappedFunction,
Result result)
{
- if (wrappedFunction.Tag == ResultType.Ok && result.Tag == ResultType.Ok)
- {
+ if (wrappedFunction == null) throw new ArgumentException(nameof(wrappedFunction));
+
+ if (wrappedFunction.Tag == ResultType.Ok && result.Tag == ResultType.Ok) {
var ok1 = (Ok, TMessage>)wrappedFunction;
var ok2 = (Ok)result;
return new Ok(
ok1.Success(ok2.Success), ok1.Messages.Concat(ok2.Messages));
}
- if (wrappedFunction.Tag == ResultType.Bad && result.Tag == ResultType.Ok)
- {
+ if (wrappedFunction.Tag == ResultType.Bad && result.Tag == ResultType.Ok) {
return new Bad(((Bad)result).Messages);
}
- if (wrappedFunction.Tag == ResultType.Ok && result.Tag == ResultType.Bad)
- {
+ if (wrappedFunction.Tag == ResultType.Ok && result.Tag == ResultType.Bad) {
return new Bad(
((Bad)result).Messages);
}
var bad1 = (Bad, TMessage>)wrappedFunction;
var bad2 = (Bad)result;
-
return new Bad(bad1.Messages.Concat(bad2.Messages));
}
///
/// Lifts a function into a Result container and applies it on the given result.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Lift(
@@ -426,22 +400,22 @@ public static Result Lift(
///
/// Promote a function to a monad/applicative, scanning the monadic/applicative arguments from left to right.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Lift2(
Func> func,
- Result a,
- Result b)
+ Result first,
+ Result second)
{
- return Apply(Lift(func, a), b);
+ return Apply(Lift(func, first), second);
}
///
/// Collects a sequence of Results and accumulates their values.
/// If the sequence contains an error the error will be propagated.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result, TMessage> Collect(
@@ -449,21 +423,18 @@ public static Result, TMessage> Collect, Result, TMessage>, Result, TMessage>>(
- null,
- (result, next) =>
- {
- if (result.Tag == ResultType.Ok && next.Tag == ResultType.Ok)
- {
+ null,
+ (result, next) => {
+ if (result.Tag == ResultType.Ok && next.Tag == ResultType.Ok) {
var ok1 = (Ok, TMessage>)result;
var ok2 = (Ok)next;
return
new Ok, TMessage>(
- Enumerable.Empty().Concat(new[] { ok2.Success }).Concat(ok1.Success),
+ Enumerable.Empty().Concat(new [] { ok2.Success }).Concat(ok1.Success),
ok1.Messages.Concat(ok2.Messages));
}
if ((result.Tag == ResultType.Ok && next.Tag == ResultType.Bad)
- || (result.Tag == ResultType.Bad && next.Tag == ResultType.Ok))
- {
+ || (result.Tag == ResultType.Bad && next.Tag == ResultType.Ok)) {
var m1 = result.Tag == ResultType.Ok
? ((Ok, TMessage>)result).Messages
: ((Bad)next).Messages;
@@ -472,8 +443,9 @@ public static Result, TMessage> Collect)next).Messages;
return new Bad, TMessage>(m1.Concat(m2));
}
+
var bad1 = (Bad, TMessage>)result;
- var bad2 = (Bad)next;
+ var bad2 = (Bad)next;
return new Bad, TMessage>(bad1.Messages.Concat(bad2.Messages));
}, x => x));
}
@@ -490,19 +462,22 @@ static class ResultExtensions
///
/// Allows pattern matching on Results.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static void Match(this Result result,
Action> ifSuccess,
Action> ifFailure)
{
+ if (ifSuccess == null) throw new ArgumentException(nameof(ifSuccess));
+ if (ifFailure == null) throw new ArgumentException(nameof(ifFailure));
+
var ok = result as Ok;
- if (ok != null)
- {
+ if (ok != null) {
ifSuccess(ok.Success, ok.Messages);
return;
}
+
var bad = (Bad)result;
ifFailure(bad.Messages);
}
@@ -510,26 +485,20 @@ public static void Match(this Result res
///
/// Allows pattern matching on Results.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static TResult Either(this Result result,
Func, TResult> ifSuccess,
Func, TResult> ifFailure)
{
- var ok = result as Ok;
- if (ok != null)
- {
- return ifSuccess(ok.Success, ok.Messages);
- }
- var bad = (Bad)result;
- return ifFailure(bad.Messages);
+ return Trial.Either(ifSuccess, ifFailure, result);
}
///
/// Lifts a Func into a Result and applies it on the given result.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Map(this Result result,
@@ -542,7 +511,7 @@ public static Result Map(this Re
/// Collects a sequence of Results and accumulates their values.
/// If the sequence contains an error the error will be propagated.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result, TMessage> Collect(
@@ -555,18 +524,16 @@ public static Result, TMessage> Collect
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result, TMessage> Flatten(this Result>, TMessage> result)
{
- if (result.Tag == ResultType.Ok)
- {
+ if (result.Tag == ResultType.Ok) {
var ok = (Ok>, TMessage>)result;
var values = ok.Success;
var result1 = Collect(values);
- if (result1.Tag == ResultType.Ok)
- {
+ if (result1.Tag == ResultType.Ok) {
var ok1 = (Ok, TMessage>)result1;
return new Ok, TMessage>(ok1.Success, ok1.Messages);
}
@@ -581,7 +548,7 @@ public static Result, TMessage> Flatten
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result SelectMany(this Result result,
@@ -595,7 +562,7 @@ public static Result SelectMany(
/// If the result of the Func is a Success it maps it using the given Func.
/// Otherwise the exisiting failure is propagated.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result SelectMany(
@@ -603,6 +570,9 @@ public static Result SelectMany> func,
Func mapperFunc)
{
+ if (func == null) throw new ArgumentException(nameof(func));
+ if (mapperFunc == null) throw new ArgumentException(nameof(mapperFunc));
+
Func> curriedMapper = suc => val => mapperFunc(suc, val);
Func<
Result,
@@ -616,7 +586,7 @@ public static Result SelectMany
/// Lifts a Func into a Result and applies it on the given result.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static Result Select(this Result result,
@@ -628,13 +598,12 @@ public static Result Select(this
///
/// Returns the error messages or fails if the result was a success.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static IEnumerable FailedWith(this Result result)
{
- if (result.Tag == ResultType.Ok)
- {
+ if (result.Tag == ResultType.Ok) {
var ok = (Ok)result;
throw new Exception(
string.Format("Result was a success: {0} - {1}",
@@ -648,13 +617,12 @@ public static IEnumerable FailedWith(this Result
/// Returns the result or fails if the result was an error.
///
-#if !ERRH_DISABLE_INLINE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static TSuccess SucceededWith(this Result result)
{
- if (result.Tag == ResultType.Ok)
- {
+ if (result.Tag == ResultType.Ok) {
var ok = (Ok)result;
return ok.Success;
}
@@ -663,5 +631,34 @@ public static TSuccess SucceededWith(this Result m.ToString()))));
}
+
+ ///
+ /// Returns messages in case of success, otherwise an empty sequence.
+ ///
+ public static IEnumerable SuccessMessages(this Result result)
+ {
+ if (result.Tag == ResultType.Ok) {
+ var ok = (Ok)result;
+ return ok.Messages;
+ }
+ return Enumerable.Empty();
+ }
+
+#if ERRH_ADD_MAYBE_METHODS
+#if ERRH_ENABLE_INLINE_METHODS
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ ///
+ /// Builds a Maybe type instance from a Result one.
+ ///
+ public static Maybe ToMaybe(this Result result)
+ {
+ if (result.Tag == ResultType.Ok) {
+ var ok = (Ok)result;
+ return Maybe.Just(ok.Success);
+ }
+ return Maybe.Nothing();
+ }
+#endif
}
}
\ No newline at end of file
diff --git a/src/CommandLine/Infrastructure/ResultExtensions.cs b/src/CommandLine/Infrastructure/ResultExtensions.cs
deleted file mode 100644
index bdc2a480..00000000
--- a/src/CommandLine/Infrastructure/ResultExtensions.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
-
-using System.Collections.Generic;
-using System.Linq;
-
-using CSharpx;
-using RailwaySharp.ErrorHandling;
-
-namespace CommandLine.Infrastructure
-{
- static class ResultExtensions
- {
- public static IEnumerable SuccessfulMessages(this Result result)
- {
- if (result.Tag == ResultType.Ok)
- {
- var ok = (Ok)result;
- return ok.Messages;
- }
- return Enumerable.Empty();
- }
-
- public static Maybe ToMaybe(this Result