mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-16 21:24:58 +00:00
fix: Fixed a bug where table width calculations were not considering unprintable characters
This commit is contained in:
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||||||
- Console uses unicode for table drawing on Net Standard
|
- Console uses unicode for table drawing on Net Standard
|
||||||
- Using UTC for tracking scheduled events, fixes issues with DST
|
- Using UTC for tracking scheduled events, fixes issues with DST
|
||||||
- Using UTC for tracking durations
|
- Using UTC for tracking durations
|
||||||
|
- Fixed a bug where table width calculations were not considering unprintable characters
|
||||||
|
|
||||||
## [10.3.0] - 2020-01-20
|
## [10.3.0] - 2020-01-20
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace ICD.Common.Utils
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Matches ANSI escape codes, e.g. \x1b[31m and \x1b[30;1m
|
/// Matches ANSI escape codes, e.g. \x1b[31m and \x1b[30;1m
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const string ANSI_PATTERN = "(?'match'\x01b\\[(?'code'[\\d;]+)m)";
|
public const string ANSI_REGEX = "(?'match'\x01b\\[(?'code'[\\d;]+)m)";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Matches ANSI escape codes to HTML styles.
|
/// Matches ANSI escape codes to HTML styles.
|
||||||
@@ -105,7 +105,7 @@ namespace ICD.Common.Utils
|
|||||||
if (string.IsNullOrEmpty(data))
|
if (string.IsNullOrEmpty(data))
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
Regex regex = new Regex(ANSI_PATTERN);
|
Regex regex = new Regex(ANSI_REGEX);
|
||||||
Match match = regex.Match(data);
|
Match match = regex.Match(data);
|
||||||
|
|
||||||
// No matches
|
// No matches
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using ICD.Common.Properties;
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
namespace ICD.Common.Utils.Extensions
|
namespace ICD.Common.Utils.Extensions
|
||||||
@@ -256,5 +257,55 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
return hash1 + (hash2 * 1566083941);
|
return hash1 + (hash2 * 1566083941);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Strips all of the non-printable characters and control codes from the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string ToPrintableCharacters([NotNull] this string extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
// Strip ANSI escape sequences
|
||||||
|
extends = Regex.Replace(extends, AnsiUtils.ANSI_REGEX, string.Empty);
|
||||||
|
|
||||||
|
// Strip control characters
|
||||||
|
extends = Regex.Replace(extends, @"\p{C}+", string.Empty);
|
||||||
|
|
||||||
|
return extends;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the printable length of the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int GetPrintableLength([NotNull] this string extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.ToPrintableCharacters().Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pads the string to the number of printable characters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="length"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string PadRightPrintable([NotNull] this string extends, int length)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
int printableLength = extends.GetPrintableLength();
|
||||||
|
int actualLength = extends.Length;
|
||||||
|
int delta = actualLength - printableLength;
|
||||||
|
|
||||||
|
return extends.PadRight(length + delta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,14 +169,14 @@ namespace ICD.Common.Utils
|
|||||||
|
|
||||||
private int GetColumnWidth(int index)
|
private int GetColumnWidth(int index)
|
||||||
{
|
{
|
||||||
int titleLength = m_Columns[index].Length + 1;
|
int titleLength = m_Columns[index].GetPrintableLength() + 1;
|
||||||
if (m_Rows.Count == 0)
|
if (m_Rows.Count == 0)
|
||||||
return titleLength;
|
return titleLength;
|
||||||
|
|
||||||
int maxColumnWidth = m_Rows.Except((string[])null)
|
int maxColumnWidth = m_Rows.Except((string[])null)
|
||||||
.Max(x => x[index] != null ? x[index].Length : 0) + 1;
|
.Max(x => x[index] != null ? x[index].GetPrintableLength() : 0) + 1;
|
||||||
|
|
||||||
return (titleLength > maxColumnWidth) ? titleLength : maxColumnWidth;
|
return titleLength > maxColumnWidth ? titleLength : maxColumnWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AppendTopSeparator(StringBuilder builder, IList<int> columnWidths)
|
private void AppendTopSeparator(StringBuilder builder, IList<int> columnWidths)
|
||||||
@@ -245,7 +245,7 @@ namespace ICD.Common.Utils
|
|||||||
builder.Append(' ');
|
builder.Append(' ');
|
||||||
|
|
||||||
string value = row[index] ?? string.Empty;
|
string value = row[index] ?? string.Empty;
|
||||||
builder.Append(value.PadRight(columnWidths[index]));
|
builder.Append(value.PadRightPrintable(columnWidths[index]));
|
||||||
|
|
||||||
if (index < row.Count - 1)
|
if (index < row.Count - 1)
|
||||||
builder.Append(VERTICAL);
|
builder.Append(VERTICAL);
|
||||||
|
|||||||
Reference in New Issue
Block a user