-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAttributeGroup.cs
99 lines (83 loc) · 4.33 KB
/
AttributeGroup.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2021-2024 Collabora, Ltd
//
// SPDX-License-Identifier: MIT
#nullable enable
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using static MoreLinq.Extensions.PartitionExtension;
namespace PrettyRegistryXml.GroupedAlignment
{
/// <summary>
/// A list of attribute names, usually combined in a <see cref="GroupChoice"/>.
/// They will all be aligned together.
/// </summary>
public class AttributeGroup : AttributeSequenceItemBase
{
/// <value>The attribute names in the desired order</value>
public string[] AttributeNames { get; init; }
/// <value>A <see cref="HashSet{T}"/> of the elements of <see cref="AttributeNames"/> </value>
public HashSet<string> AttributeNameSet { get; private init; }
/// <summary>
/// Extra space to add to this attribute group's width.
/// </summary>
public int ExtraSpace { get; private init; }
/// <summary>
/// Create a group of attributes that will all be aligned (or replaced with placeholder spaces)
/// </summary>
/// <param name="attributeNames">Attribute names in the desired order</param>
public AttributeGroup(params string[] attributeNames)
{
AttributeNames = attributeNames.ToArray();
AttributeNameSet = AttributeNames.ToHashSet();
ExtraSpace = 0;
}
/// <summary>
/// Create a group of attributes that will all be aligned (or replaced with placeholder spaces)
/// </summary>
/// <param name="extraSpace">Extra space</param>
/// <param name="attributeNames">Attribute names in the desired order</param>
public AttributeGroup(int extraSpace, params string[] attributeNames)
{
AttributeNames = attributeNames.ToArray();
AttributeNameSet = AttributeNames.ToHashSet();
ExtraSpace = extraSpace;
}
/// <inheritdoc />
public override int CountHandledAttributes(IEnumerable<string> elementAttrNames) => (from attrName in elementAttrNames
where AttributeNameSet.Contains(attrName)
select true).Count();
/// <summary>
/// Convert to string
/// </summary>
/// <returns>Representation mostly for debugging</returns>
public override string? ToString() => string.Format(CultureInfo.InvariantCulture,
"AttributeGroup( {0} )",
string.Join(", ", from name in AttributeNames
select $"\"{name}\""));
private class WidthComputer : IAttributeSequenceItemWidthComputer
{
private readonly AttributeGroup attrGroup;
public WidthComputer(AttributeGroup attrGroup) => this.attrGroup = attrGroup;
private readonly List<NameLengthPair> observedLengths = new();
public IEnumerable<NameLengthPair> TakeAndHandleAttributes(IEnumerable<NameLengthPair> attributes)
{
var (selected, notSelected) = attributes.Partition(attr => attrGroup.AttributeNameSet.Contains(attr.Name));
observedLengths.AddRange(selected);
return notSelected;
}
public IAttributeSequenceItemAligner Finish()
{
Dictionary<string, int> lengthDictionary = new(from pair in observedLengths
group pair.Length by pair.Name into g
select KeyValuePair.Create(g.Key, g.Max() + attrGroup.ExtraSpace));
var alignments = (from name in attrGroup.AttributeNames
let length = lengthDictionary.GetValueOrDefault(name, 0)
select new Core.AttributeAlignment(name, length)).ToArray();
return new BaseAligner(alignments);
}
}
/// <inheritdoc />
public override IAttributeSequenceItemWidthComputer CreateWidthComputer() => new WidthComputer(this);
}
}