< Summary - SonghayCore

Line coverage
86%
Covered lines: 112
Uncovered lines: 18
Coverable lines: 130
Total lines: 291
Line coverage: 86.1%
Branch coverage
74%
Covered branches: 43
Total branches: 58
Branch coverage: 74.1%
Method coverage

Method coverage is only available for sponsors.

Upgrade to PRO version

Metrics

File(s)

/home/rasx/sourceRoot/SonghayCore/SonghayCore/Extensions/ProgramArgsExtensions._.cs

#LineLine coverage
 1namespace Songhay.Extensions;
 2
 3/// <summary>
 4/// Extensions of <see cref="ProgramArgs"/>
 5/// </summary>
 6public static partial class ProgramArgsExtensions
 7{
 8    /// <summary>
 9    /// Gets the argument value.
 10    /// </summary>
 11    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 12    /// <param name="arg">The argument.</param>
 13    public static string? GetArgValue(this ProgramArgs? args, string? arg)
 1514    {
 1515        if (args?.Args == null) return null;
 16
 1517        var index = Array.IndexOf(args.Args, arg);
 1518        var value = args.Args.ElementAtOrDefault(index + 1);
 1519        if (string.IsNullOrWhiteSpace(@value)) throw new ArgumentException($"Argument {arg} is not here.");
 20
 1521        return value;
 1522    }
 23
 24    /// <summary>
 25    /// Determines whether the specified <see cref="ProgramArgs"/> has argument.
 26    /// </summary>
 27    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 28    /// <param name="arg">The argument.</param>
 29    /// <param name="requiresValue">if set to <c>true</c> [requires value].</param>
 30    /// <returns>
 31    ///   <c>true</c> if the specified argument has argument; otherwise, <c>false</c>.
 32    /// </returns>
 33    public static bool HasArg(this ProgramArgs? args, string? arg, bool requiresValue)
 2234    {
 2235        if (args?.Args == null) return false;
 36
 2237        var index = Array.IndexOf(args.Args, arg);
 2738        if (index == -1) return false;
 39
 1740        var lastIndex = Array.LastIndexOf(args.Args, arg);
 1741        if (index != lastIndex) throw new ArgumentException($"Argument {arg} used more than once.");
 42
 2743        if (!requiresValue) return true;
 44
 745        if (args.Args.Length < (index + 1)) throw new ArgumentException($"Argument {arg} requires a value.");
 46
 747        return true;
 2248    }
 49
 50    /// <summary>
 51    /// Converts the <c>args</c> key any help text.
 52    /// </summary>
 53    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 254    public static string? ToHelpDisplayText(this ProgramArgs? args) => args.ToHelpDisplayText(padding: 4);
 55
 56    /// <summary>
 57    /// Converts the <c>args</c> key any help text.
 58    /// </summary>
 59    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 60    /// <param name="padding">the padding between <see cref="ProgramArgs.HelpSet"/> keys and values</param>
 61    public static string? ToHelpDisplayText(this ProgramArgs? args, int padding)
 262    {
 263        if (args == null) return null;
 64
 1365        var maxLength = args.HelpSet.Select(pair => pair.Key.Length).Max();
 66
 267        return args.HelpSet
 268            .Where(pair =>
 1169                !string.IsNullOrWhiteSpace(pair.Key) &&
 1170                !string.IsNullOrWhiteSpace(pair.Value))
 271            .Select(pair =>
 1172            {
 1173                var count = (maxLength - pair.Key.Length) + padding;
 1174                var spaces = Enumerable.Repeat(" ", count).ToArray();
 1175                return
 1176                    $"{pair.Key}{string.Join(string.Empty, spaces)}{pair.Value}{Environment.NewLine}{Environment.NewLine
 1177            })
 1178            .Aggregate((a, i) => $"{a}{i}");
 279    }
 80}

/home/rasx/sourceRoot/SonghayCore/SonghayCore/Extensions/ProgramArgsExtensions.Conventions.cs

#LineLine coverage
 1namespace Songhay.Extensions;
 2
 3public static partial class ProgramArgsExtensions
 4{
 5    /// <summary>
 6    /// Gets the conventional base-path value.
 7    /// </summary>
 8    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 9    public static string? GetBasePathValue(this ProgramArgs? args)
 510    {
 511        var isBasePathRequired = args.HasArg(ProgramArgs.BasePathRequired, requiresValue: false);
 512        if (!args.HasArg(ProgramArgs.BasePath, isBasePathRequired)) return null;
 13
 514        var basePath = args.GetArgValue(ProgramArgs.BasePath);
 515        if (!Directory.Exists(basePath)) throw new ArgumentException($"{basePath} does not exist.");
 16
 517        return basePath;
 518    }
 19
 20    /// <summary>
 21    /// Gets the path to the output file specified by conventional arguments.
 22    /// </summary>
 23    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 24    /// <remarks>
 25    /// This member will generate a file when it does not exist.
 26    /// </remarks>
 27    public static string? GetOutputPath(this ProgramArgs? args)
 428    {
 429        var outputFile = args.GetArgValue(ProgramArgs.OutputFile);
 30
 431        if (args.HasArg(ProgramArgs.OutputUnderBasePath, requiresValue: false))
 232        {
 233            var basePath = args.GetBasePathValue();
 34
 235            outputFile = ProgramFileUtility.GetCombinedPath(basePath, outputFile);
 236        }
 37
 438        if (!File.Exists(outputFile)) File.WriteAllText(outputFile!, string.Empty);
 39
 440        return outputFile;
 441    }
 42
 43    /// <summary>
 44    /// Gets the conventional settings file <see cref="string"/> content.
 45    /// </summary>
 46    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 47    public static string GetSettings(this ProgramArgs? args)
 148    {
 149        var path = args.GetSettingsFilePath();
 50
 151        if (File.Exists(path)) return File.ReadAllText(path);
 52
 153        var basePath = args.GetBasePathValue();
 54
 155        path = ProgramFileUtility.GetCombinedPath(basePath, path, fileIsExpected: true);
 56
 157        return File.ReadAllText(path);
 158    }
 59
 60    /// <summary>
 61    /// Gets the conventional settings file path.
 62    /// </summary>
 63    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 64    public static string? GetSettingsFilePath(this ProgramArgs? args)
 265    {
 266        var settingsFileName = args.GetArgValue(ProgramArgs.SettingsFile);
 67
 268        return settingsFileName;
 269    }
 70
 71    /// <summary>
 72    /// Gets <see cref="string"/> input
 73    /// from either <see cref="ProgramArgs.InputString"/>
 74    /// or <see cref="ProgramArgs.InputFile"/>.
 75    /// </summary>
 76    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 77    public static string GetStringInput(this ProgramArgs? args)
 378    {
 379        string? input = null;
 80
 381        if (args.HasArg(ProgramArgs.InputString, requiresValue: false))
 182        {
 183            input = args.GetArgValue(ProgramArgs.InputString);
 184        }
 285        else if (args.HasArg(ProgramArgs.InputFile, requiresValue: true))
 286        {
 287            var path = args.GetArgValue(ProgramArgs.InputFile);
 88
 289            if (!File.Exists(path))
 190            {
 191                var basePath = args.GetBasePathValue();
 92
 193                path = ProgramFileUtility
 194                    .GetCombinedPath(basePath, path, fileIsExpected: true);
 95
 196                if (!File.Exists(path))
 097                    throw new FileNotFoundException($"The expected input file, `{path}`, is not here.");
 198            }
 99
 2100            input = File.ReadAllText(path);
 2101        }
 102
 3103        return input.ToReferenceTypeValueOrThrow();
 3104    }
 105
 106    /// <summary>
 107    /// Determines whether args contain the <see cref="ProgramArgs.Help"/> flag.
 108    /// </summary>
 109    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 3110    public static bool IsHelpRequest(this ProgramArgs? args) => args.HasArg(ProgramArgs.Help, requiresValue: false);
 111
 112    /// <summary>
 113    /// Converts the <c>args</c> key to a conventional Configuration key.
 114    /// </summary>
 115    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 116    /// <param name="argKey">The arguments key.</param>
 117    public static string ToConfigurationKey(this ProgramArgs? args, string argKey)
 0118    {
 0119        argKey.ThrowWhenNullOrWhiteSpace();
 120
 0121        return argKey
 0122            .TrimStart('-')
 0123            .Replace("/", string.Empty)
 0124            .Replace("=", string.Empty);
 0125    }
 126
 127    /// <summary>
 128    /// Returns <see cref="ProgramArgs"/>
 129    /// </summary>
 130    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 131    public static ProgramArgs? WithDefaultHelpText(this ProgramArgs? args)
 1132    {
 1133        if (args == null) return null;
 134
 1135        if (!args.HelpSet.ContainsKey(ProgramArgs.BasePath))
 1136            args.HelpSet.Add(ProgramArgs.BasePath,
 1137                "The path to the Directory where the Activity will set its context.");
 138
 1139        if (!args.HelpSet.ContainsKey(ProgramArgs.BasePathRequired))
 1140            args.HelpSet.Add(ProgramArgs.BasePathRequired, $"Indicates that {ProgramArgs.BasePath} is required.");
 141
 1142        if (!args.HelpSet.ContainsKey(ProgramArgs.Help))
 1143            args.HelpSet.Add(ProgramArgs.Help, "Displays this help text.");
 144
 1145        if (!args.HelpSet.ContainsKey(ProgramArgs.InputFile))
 1146            args.HelpSet.Add(ProgramArgs.InputFile,
 1147                $"The path to the file to load as Activity input. {ProgramArgs.InputString} can be used alternatively.")
 148
 1149        if (!args.HelpSet.ContainsKey(ProgramArgs.InputString))
 1150            args.HelpSet.Add(ProgramArgs.InputString,
 1151                $"The string literal used as Activity input. {ProgramArgs.InputFile} can be used alternatively.");
 152
 1153        if (!args.HelpSet.ContainsKey(ProgramArgs.OutputFile))
 1154            args.HelpSet.Add(ProgramArgs.OutputFile,
 1155                $"The path to the file to write as Activity output. This can be an absolute path or relative to {Program
 156
 1157        if (!args.HelpSet.ContainsKey(ProgramArgs.OutputUnderBasePath))
 1158            args.HelpSet.Add(ProgramArgs.OutputUnderBasePath, $"See {ProgramArgs.OutputFile}.");
 159
 1160        if (!args.HelpSet.ContainsKey(ProgramArgs.SettingsFile))
 1161            args.HelpSet.Add(ProgramArgs.SettingsFile,
 1162                $"The path to the file to load as Activity Settings input. This can be an absolute path or relative to {
 163
 1164        return args;
 1165    }
 166
 167    /// <summary>
 168    /// Writes the <see cref="string"/> output
 169    /// to the file specified by <see cref="ProgramArgs.OutputFile"/>.
 170    /// </summary>
 171    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 172    /// <param name="output">the output to write</param>
 173    public static void WriteOutputToFile(this ProgramArgs? args, string output)
 2174    {
 2175        var outputFile = args.GetOutputPath();
 176
 2177        File.WriteAllText(outputFile!, output);
 2178    }
 179
 180    /// <summary>
 181    /// Writes the <see cref="byte"/> array output
 182    /// to the file specified by <see cref="ProgramArgs.OutputFile"/>.
 183    /// </summary>
 184    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 185    /// <param name="output">the output to write</param>
 186    public static void WriteOutputToFile(this ProgramArgs? args, byte[] output)
 0187    {
 0188        var outputFile = args.GetOutputPath().ToReferenceTypeValueOrThrow();
 189
 0190        File.WriteAllBytes(outputFile, output);
 0191    }
 192
 193    /// <summary>
 194    /// Writes the <see cref="Stream"/> output
 195    /// to the file specified by <see cref="ProgramArgs.OutputFile"/>.
 196    /// </summary>
 197    /// <param name="args">The <see cref="ProgramArgs"/>.</param>
 198    /// <param name="stream">the <see cref="Stream"/> to write</param>
 199    /// <remarks>
 200    /// [ see https://stackoverflow.com/a/5515894/22944 ]
 201    /// </remarks>
 202    public static void WriteOutputToFile(this ProgramArgs? args, Stream stream)
 0203    {
 0204        var outputFile = args.GetOutputPath().ToReferenceTypeValueOrThrow();
 205
 0206        using var fileStream = File.Create(outputFile);
 207
 0208        stream.Seek(0, SeekOrigin.Begin);
 0209        stream.CopyTo(fileStream);
 0210    }
 211}