Nuke.Cola
Loading...
Searching...
No Matches
TextExtensions.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text.RegularExpressions;
5using System.Threading.Tasks;
6using Nuke.Common;
7using Nuke.Common.Utilities;
8using Nuke.Common.Utilities.Collections;
9
10namespace Nuke.Cola;
11
12public static class TextExtensions
13{
14 public static IEnumerable<string> DoubleQuoteIfNeeded(this IEnumerable<object> self)
15 => self?.Select(s => s.ToString().DoubleQuoteIfNeeded()) ?? Enumerable.Empty<string>();
16
17 /// <summary>
18 /// Shorthand for one-liner regex parsing from named captures.
19 /// </summary>
20 /// <example>
21 /// "Hello World".Parse(@"Hello (?&lt;SUBJECT&gt;\w+)")("SUBJECT")
22 /// </example>
23 /// <returns>A function to be called with the desired capture name</returns>
24 public static Func<string, string?> Parse(
25 this string? input,
26 string pattern,
27 RegexOptions options = RegexOptions.None,
28 bool forceNullOnEmpty = false,
29 bool forceNullOnWhitespce = false
30 ) => Parse(input, new Regex(pattern, options), forceNullOnEmpty, forceNullOnWhitespce);
31
32 /// <summary>
33 /// Shorthand for one-liner regex parsing from named captures. Allows to use precompiled pattern.
34 /// </summary>
35 /// <example>
36 /// "Hello World".Parse(new Regex(@"Hello (?&lt;SUBJECT&gt;\w+)"))("SUBJECT")
37 /// </example>
38 /// <returns>A function to be called with the desired capture name</returns>
39 public static Func<string, string?> Parse(
40 this string? input,
41 Regex pattern,
42 bool forceNullOnEmpty = false,
43 bool forceNullOnWhitespce = false
44 ) {
45 if (input == null) return i => null;
46
47 var groups = pattern.Matches(input)?.FirstOrDefault()?.Groups;
48 return i => forceNullOnEmpty || forceNullOnWhitespce
49 ? groups?[i]?.Value.Else(ignoreWhitespace: forceNullOnWhitespce)
50 : groups?[i]?.Value;
51 }
52
53 /// <summary>
54 /// Simple convenience function for replacing new lines with other string (space by default)
55 /// </summary>
56 public static string AsSingleLine(this string input, string replaceWith = " ")
57 => input.Replace(Environment.NewLine, replaceWith).Replace("\n", replaceWith);
58
59 /// <summary>
60 /// Converts a glob expression into a Regex expression with captures
61 /// </summary>
62 /// <param name="glob"></param>
63 /// <returns></returns>
64 public static string GlobToRegex(this string glob) => Regex.Escape(glob)
65 // Escape /
66 .Replace("/", @"\/")
67 // preprocess wildcards directly after backslash (edge case)
68 .Replace(@"\*", "*")
69 // Singular * wildcard is converted to capturing ([^\/]*) pattern with surroundings (match everything within current level)
70 .ReplaceRegex(@"(?<PRE>[^\*]|^)\*(?<POST>[^\*])", m => $@"{m.Groups["PRE"]}([^\/]*){m.Groups["POST"]}")
71 // Singular * wildcard at the end of the glob is converted to capturing ([^\/]*) pattern with its prefix surroundings (match everything within current level)
72 .ReplaceRegex(@"(?<PRE>[^\*]|^)\*$", m => $@"{m.Groups["PRE"]}([^\/]*)")
73 // Recursive ** wildcard at the beginning of the expression is simply converted to capturing (.*) pattern
74 .ReplaceRegex(@"^\*\*", m => @"^(.*)")
75 // Recursive ** wildcard at the beginning of path components converted into capturing [\\\/]?(.*) pattern
76 .ReplaceRegex(@"(?:\\\\|\\\/)\*\*", m => @"[\\\/]?(.*)");
77
78 /// <summary>
79 /// Convenience, append a piece of string to an input string only if input string is non-null and non-empty
80 /// </summary>
81 public static string AppendNonEmpty(this string? self, string other)
82 => string.IsNullOrWhiteSpace(self) ? "" : self + other;
83
84 /// <summary>
85 /// Convenience, prepend a piece of string to an input string only if input string is non-null and non-empty
86 /// </summary>
87 public static string PrependNonEmpty(this string? self, string other)
88 => string.IsNullOrWhiteSpace(self) ? "" : other + self;
89
90 /// <summary>
91 /// Defer to a default value if string is null or empty or whitespace only
92 /// </summary>
93 /// <param name="self"></param>
94 /// <param name="def">
95 /// Default value to substitute null/empty/whitespace with (null by default)
96 /// </param>
97 /// <param name="ignoreWhitespace">
98 /// If set to true treat whitespace-only string as empty as well. (true by default)
99 /// </param>
100 /// <returns></returns>
101 public static string? Else(this string? self, string? def = null, bool ignoreWhitespace = true)
102 => (string.IsNullOrWhiteSpace(self) && ignoreWhitespace) || string.IsNullOrEmpty(self)
103 ? def : self;
104}
static Func< string, string?> Parse(this string? input, Regex pattern, bool forceNullOnEmpty=false, bool forceNullOnWhitespce=false)
Shorthand for one-liner regex parsing from named captures. Allows to use precompiled pattern.
static string PrependNonEmpty(this string? self, string other)
Convenience, prepend a piece of string to an input string only if input string is non-null and non-em...
static Func< string, string?> Parse(this string? input, string pattern, RegexOptions options=RegexOptions.None, bool forceNullOnEmpty=false, bool forceNullOnWhitespce=false)
Shorthand for one-liner regex parsing from named captures.
static ? string Else(this string? self, string? def=null, bool ignoreWhitespace=true)
Defer to a default value if string is null or empty or whitespace only.
static string AppendNonEmpty(this string? self, string other)
Convenience, append a piece of string to an input string only if input string is non-null and non-emp...
static string AsSingleLine(this string input, string replaceWith=" ")
Simple convenience function for replacing new lines with other string (space by default)
static string GlobToRegex(this string glob)
Converts a glob expression into a Regex expression with captures.